Move ti-stress to use slicer directly

Now that slicer is in the AOSP tree we can use it directly for ti
stress tests.

Test: ./test/run-test --host --jvmti-redefine-stress 001-HelloWorld

Change-Id: I89a9f532458b24466b453f493ab63c9c4af6de6d
diff --git a/test/ti-stress/stress.cc b/test/ti-stress/stress.cc
index 5d7c2f3..4e0f48d 100644
--- a/test/ti-stress/stress.cc
+++ b/test/ti-stress/stress.cc
@@ -28,15 +28,20 @@
 #include "jvmti.h"
 #include "utils.h"
 
+#include "code_ir.h"
+#include "control_flow_graph.h"
+#include "dex_ir.h"
+#include "dex_ir_builder.h"
+#include "instrumentation.h"
+#include "reader.h"
+#include "writer.h"
+
 namespace art {
 
 // Should we do a 'full_rewrite' with this test?
 static constexpr bool kDoFullRewrite = true;
 
 struct StressData {
-  std::string dexter_cmd;
-  std::string out_temp_dex;
-  std::string in_temp_dex;
   bool vm_class_loader_initialized;
   bool trace_stress;
   bool redefine_stress;
@@ -44,51 +49,60 @@
   bool step_stress;
 };
 
-static void WriteToFile(const std::string& fname, jint data_len, const unsigned char* data) {
-  std::ofstream file(fname, std::ios::binary | std::ios::out | std::ios::trunc);
-  file.write(reinterpret_cast<const char*>(data), data_len);
-  file.flush();
-}
-
-static bool ReadIntoBuffer(const std::string& fname, /*out*/std::vector<unsigned char>* data) {
-  std::ifstream file(fname, std::ios::binary | std::ios::in);
-  file.seekg(0, std::ios::end);
-  size_t len = file.tellg();
-  data->resize(len);
-  file.seekg(0);
-  file.read(reinterpret_cast<char*>(data->data()), len);
-  return len != 0;
-}
-
-// TODO rewrite later.
-static bool DoExtractClassFromData(StressData* data,
-                                   const std::string& class_name,
+static bool DoExtractClassFromData(jvmtiEnv* env,
+                                   const std::string& descriptor,
                                    jint in_len,
                                    const unsigned char* in_data,
-                                   /*out*/std::vector<unsigned char>* dex) {
-  // Write the dex file into a temporary file.
-  WriteToFile(data->in_temp_dex, in_len, in_data);
-  // Clear out file so even if something suppresses the exit value we will still detect dexter
-  // failure.
-  WriteToFile(data->out_temp_dex, 0, nullptr);
-  // Have dexter do the extraction.
-  std::vector<std::string> args;
-  args.push_back(data->dexter_cmd);
-  if (kDoFullRewrite) {
-    args.push_back("-x");
-    args.push_back("full_rewrite");
-  }
-  args.push_back("-e");
-  args.push_back(class_name);
-  args.push_back("-o");
-  args.push_back(data->out_temp_dex);
-  args.push_back(data->in_temp_dex);
-  std::string error;
-  if (ExecAndReturnCode(args, &error) != 0) {
-    LOG(ERROR) << "unable to execute dexter: " << error;
+                                   /*out*/jint* out_len,
+                                   /*out*/unsigned char** out_data) {
+  dex::Reader reader(in_data, in_len);
+  dex::u4 class_idx = reader.FindClassIndex(descriptor.c_str());
+  if (class_idx != dex::kNoIndex) {
+    reader.CreateClassIr(class_idx);
+  } else {
+    LOG(ERROR) << "ERROR: Can't find class " << descriptor;
     return false;
   }
-  return ReadIntoBuffer(data->out_temp_dex, dex);
+  auto dex_ir = reader.GetIr();
+
+  if (kDoFullRewrite) {
+    for (auto& ir_method : dex_ir->encoded_methods) {
+      if (ir_method->code != nullptr) {
+        lir::CodeIr code_ir(ir_method.get(), dex_ir);
+        lir::ControlFlowGraph cfg_compact(&code_ir, false);
+        lir::ControlFlowGraph cfg_verbose(&code_ir, true);
+        code_ir.Assemble();
+      }
+    }
+  }
+  dex::Writer writer(dex_ir);
+
+  struct Allocator : public dex::Writer::Allocator {
+    explicit Allocator(jvmtiEnv* jvmti_env) : jvmti_env_(jvmti_env) {}
+    virtual void* Allocate(size_t size) {
+      unsigned char* out = nullptr;
+      if (JVMTI_ERROR_NONE != jvmti_env_->Allocate(size, &out)) {
+        return nullptr;
+      } else {
+        return out;
+      }
+    }
+    virtual void Free(void* ptr) {
+      jvmti_env_->Deallocate(reinterpret_cast<unsigned char*>(ptr));
+    }
+   private:
+    jvmtiEnv* jvmti_env_;
+  };
+  Allocator alloc(env);
+  size_t res_len;
+  unsigned char* res = writer.CreateImage(&alloc, &res_len);
+  if (res != nullptr) {
+    *out_data = res;
+    *out_len = res_len;
+    return true;
+  } else {
+    return false;
+  }
 }
 
 class ScopedThreadInfo {
@@ -615,10 +629,10 @@
                                          jint* new_class_data_len,
                                          unsigned char** new_class_data) {
   std::vector<unsigned char> out;
-  std::string name_str(name);
-  // Make the jvmti semi-descriptor into the java style descriptor (though with $ for inner
-  // classes).
-  std::replace(name_str.begin(), name_str.end(), '/', '.');
+  // Make the jvmti semi-descriptor into the full descriptor.
+  std::string name_str("L");
+  name_str += name;
+  name_str += ";";
   StressData* data = nullptr;
   CHECK_EQ(jvmti->GetEnvironmentLocalStorage(reinterpret_cast<void**>(&data)),
            JVMTI_ERROR_NONE);
@@ -626,15 +640,11 @@
     LOG(WARNING) << "Ignoring load of class " << name << " because VMClassLoader is not yet "
                  << "initialized. Transforming this class could cause spurious test failures.";
     return;
-  } else if (DoExtractClassFromData(data, name_str, class_data_len, class_data, /*out*/ &out)) {
+  } else if (DoExtractClassFromData(jvmti, name_str, class_data_len, class_data,
+                                    /*out*/ new_class_data_len, /*out*/ new_class_data)) {
     LOG(INFO) << "Extracted class: " << name;
-    unsigned char* new_data;
-    CHECK_EQ(JVMTI_ERROR_NONE, jvmti->Allocate(out.size(), &new_data));
-    memcpy(new_data, out.data(), out.size());
-    *new_class_data_len = static_cast<jint>(out.size());
-    *new_class_data = new_data;
   } else {
-    std::cerr << "Unable to extract class " << name_str << std::endl;
+    std::cerr << "Unable to extract class " << name << std::endl;
     *new_class_data_len = 0;
     *new_class_data = nullptr;
   }
@@ -653,7 +663,7 @@
 }
 
 // Options are
-// jvmti-stress,[redefine,${DEXTER_BINARY},${TEMP_FILE_1},${TEMP_FILE_2},][trace,][field]
+// jvmti-stress,[redefine,][trace,][field]
 static void ReadOptions(StressData* data, char* options) {
   std::string ops(options);
   CHECK_EQ(GetOption(ops), "jvmti-stress") << "Options should start with jvmti-stress";
@@ -668,12 +678,6 @@
       data->field_stress = true;
     } else if (cur == "redefine") {
       data->redefine_stress = true;
-      ops = AdvanceOption(ops);
-      data->dexter_cmd = GetOption(ops);
-      ops = AdvanceOption(ops);
-      data->in_temp_dex = GetOption(ops);
-      ops = AdvanceOption(ops);
-      data->out_temp_dex = GetOption(ops);
     } else {
       LOG(FATAL) << "Unknown option: " << GetOption(ops);
     }