Add ClassPreDefine hook.

This hook is called prior to defining a class for the first time. It
allows callbacks to modify the dex-file used to load the class if they
wish. The event handler is responsible for ensuring that the returned
dex-file is set-up correctly.

Bug: 31684920
Test: mma -j40 test-art-host
Change-Id: Iaed79c1597913148ead795e033a0a10a4ebe6b2b
diff --git a/runtime/runtime_callbacks.cc b/runtime/runtime_callbacks.cc
index 7b15a4f..25324b5 100644
--- a/runtime/runtime_callbacks.cc
+++ b/runtime/runtime_callbacks.cc
@@ -67,6 +67,36 @@
   }
 }
 
+void RuntimeCallbacks::ClassPreDefine(const char* descriptor,
+                                      Handle<mirror::Class> temp_class,
+                                      Handle<mirror::ClassLoader> loader,
+                                      const DexFile& initial_dex_file,
+                                      const DexFile::ClassDef& initial_class_def,
+                                      /*out*/DexFile const** final_dex_file,
+                                      /*out*/DexFile::ClassDef const** final_class_def) {
+  DexFile const* current_dex_file = &initial_dex_file;
+  DexFile::ClassDef const* current_class_def = &initial_class_def;
+  for (ClassLoadCallback* cb : class_callbacks_) {
+    DexFile const* new_dex_file = nullptr;
+    DexFile::ClassDef const* new_class_def = nullptr;
+    cb->ClassPreDefine(descriptor,
+                       temp_class,
+                       loader,
+                       *current_dex_file,
+                       *current_class_def,
+                       &new_dex_file,
+                       &new_class_def);
+    if ((new_dex_file != nullptr && new_dex_file != current_dex_file) ||
+        (new_class_def != nullptr && new_class_def != current_class_def)) {
+      DCHECK(new_dex_file != nullptr && new_class_def != nullptr);
+      current_dex_file = new_dex_file;
+      current_class_def = new_class_def;
+    }
+  }
+  *final_dex_file = current_dex_file;
+  *final_class_def = current_class_def;
+}
+
 void RuntimeCallbacks::ClassPrepare(Handle<mirror::Class> temp_klass, Handle<mirror::Class> klass) {
   for (ClassLoadCallback* cb : class_callbacks_) {
     cb->ClassPrepare(temp_klass, klass);