Cleanup of redefinition testing

Move redefine logic into a single common function and perform some
other cleanup.

Test: mma -j40 test-art-host
Change-Id: I8618bda4f392b683ce198374066e356b87578e7b
diff --git a/runtime/openjdkjvmti/OpenjdkJvmTi.cc b/runtime/openjdkjvmti/OpenjdkJvmTi.cc
index d1c2293..1ad3f08 100644
--- a/runtime/openjdkjvmti/OpenjdkJvmTi.cc
+++ b/runtime/openjdkjvmti/OpenjdkJvmTi.cc
@@ -1142,6 +1142,34 @@
     return RetransformClassesWithHook(reinterpret_cast<ArtJvmTiEnv*>(env), classes, hook);
   }
 
+  static jvmtiError RedefineClassDirect(ArtJvmTiEnv* env,
+                                        jclass klass,
+                                        jint dex_size,
+                                        unsigned char* dex_file) {
+    if (!IsValidEnv(env)) {
+      return ERR(INVALID_ENVIRONMENT);
+    }
+    jvmtiError ret = OK;
+    std::string location;
+    if ((ret = GetClassLocation(env, klass, &location)) != OK) {
+      // TODO Do something more here? Maybe give log statements?
+      return ret;
+    }
+    std::string error;
+    ret = Redefiner::RedefineClass(env,
+                                    art::Runtime::Current(),
+                                    art::Thread::Current(),
+                                    klass,
+                                    location,
+                                    dex_size,
+                                    reinterpret_cast<uint8_t*>(dex_file),
+                                    &error);
+    if (ret != OK) {
+      LOG(ERROR) << "FAILURE TO REDEFINE " << error;
+    }
+    return ret;
+  }
+
   // TODO This will be called by the event handler for the art::ti Event Load Event
   static jvmtiError RetransformClassesWithHook(ArtJvmTiEnv* env,
                                                const std::vector<jclass>& classes,
@@ -1252,7 +1280,10 @@
   reinterpret_cast<void*>(JvmtiFunctions::RetransformClassWithHook),
   // nullptr,  // reserved1
   JvmtiFunctions::SetEventNotificationMode,
-  nullptr,  // reserved3
+  // SPECIAL FUNCTION: RedefineClassDirect Is normally reserved3
+  // TODO Remove once we have events working.
+  reinterpret_cast<void*>(JvmtiFunctions::RedefineClassDirect),
+  // nullptr,  // reserved3
   JvmtiFunctions::GetAllThreads,
   JvmtiFunctions::SuspendThread,
   JvmtiFunctions::ResumeThread,
diff --git a/runtime/openjdkjvmti/transform.cc b/runtime/openjdkjvmti/transform.cc
index f7b8b92..f545125 100644
--- a/runtime/openjdkjvmti/transform.cc
+++ b/runtime/openjdkjvmti/transform.cc
@@ -58,6 +58,21 @@
 
 namespace openjdkjvmti {
 
+jvmtiError GetClassLocation(ArtJvmTiEnv* env, jclass klass, /*out*/std::string* location) {
+  JNIEnv* jni_env = nullptr;
+  jint ret = env->art_vm->GetEnv(reinterpret_cast<void**>(&jni_env), JNI_VERSION_1_1);
+  if (ret != JNI_OK) {
+    // TODO Different error might be better?
+    return ERR(INTERNAL);
+  }
+  art::ScopedObjectAccess soa(jni_env);
+  art::StackHandleScope<1> hs(art::Thread::Current());
+  art::Handle<art::mirror::Class> hs_klass(hs.NewHandle(soa.Decode<art::mirror::Class>(klass)));
+  const art::DexFile& dex = hs_klass->GetDexFile();
+  *location = dex.GetLocation();
+  return OK;
+}
+
 // TODO Move this function somewhere more appropriate.
 // Gets the data surrounding the given class.
 jvmtiError GetTransformationData(ArtJvmTiEnv* env,
diff --git a/runtime/openjdkjvmti/transform.h b/runtime/openjdkjvmti/transform.h
index 35b990b..0ad5099 100644
--- a/runtime/openjdkjvmti/transform.h
+++ b/runtime/openjdkjvmti/transform.h
@@ -41,6 +41,8 @@
 
 namespace openjdkjvmti {
 
+jvmtiError GetClassLocation(ArtJvmTiEnv* env, jclass klass, /*out*/std::string* location);
+
 // Gets the data surrounding the given class.
 jvmtiError GetTransformationData(ArtJvmTiEnv* env,
                                  jclass klass,