Add GC map to oat file

Change-Id: Ied0462c711a09e2542f231c3b2fa31239958bd28
diff --git a/src/compiler.cc b/src/compiler.cc
index 88e156d..d700adb 100644
--- a/src/compiler.cc
+++ b/src/compiler.cc
@@ -8,6 +8,7 @@
 #include "class_linker.h"
 #include "class_loader.h"
 #include "dex_cache.h"
+#include "dex_verifier.h"
 #include "jni_compiler.h"
 #include "jni_internal.h"
 #include "oat_file.h"
@@ -136,6 +137,7 @@
 
 void Compiler::PostCompile(const ClassLoader* class_loader,
                            const std::vector<const DexFile*>& dex_files) {
+  SetGcMaps(class_loader, dex_files);
   SetCodeAndDirectMethods(dex_files);
 }
 
@@ -481,6 +483,70 @@
   return it->second;
 }
 
+void Compiler::SetGcMaps(const ClassLoader* class_loader, const std::vector<const DexFile*>& dex_files) {
+  for (size_t i = 0; i != dex_files.size(); ++i) {
+    const DexFile* dex_file = dex_files[i];
+    CHECK(dex_file != NULL);
+    SetGcMapsDexFile(class_loader, *dex_file);
+  }
+}
+
+void Compiler::SetGcMapsDexFile(const ClassLoader* class_loader, const DexFile& dex_file) {
+  ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
+  DexCache* dex_cache = class_linker->FindDexCache(dex_file);
+  for (size_t class_def_index = 0; class_def_index < dex_file.NumClassDefs(); class_def_index++) {
+    const DexFile::ClassDef& class_def = dex_file.GetClassDef(class_def_index);
+    const char* descriptor = dex_file.GetClassDescriptor(class_def);
+    Class* klass = class_linker->FindClass(descriptor, class_loader);
+    if (klass == NULL || !klass->IsVerified()) {
+      Thread::Current()->ClearException();
+      continue;
+    }
+    const byte* class_data = dex_file.GetClassData(class_def);
+    if (class_data == NULL) {
+      // empty class such as a marker interface
+      continue;
+    }
+    ClassDataItemIterator it(dex_file, class_data);
+    while (it.HasNextStaticField()) {
+      it.Next();
+    }
+    while (it.HasNextInstanceField()) {
+      it.Next();
+    }
+    while (it.HasNextDirectMethod()) {
+      Method* method = class_linker->ResolveMethod(dex_file, it.GetMemberIndex(), dex_cache,
+                                                   class_loader, true);
+      SetGcMapsMethod(dex_file, method);
+      it.Next();
+    }
+    while (it.HasNextVirtualMethod()) {
+      Method* method = class_linker->ResolveMethod(dex_file, it.GetMemberIndex(), dex_cache,
+                                                   class_loader, false);
+      SetGcMapsMethod(dex_file, method);
+      it.Next();
+    }
+  }
+}
+
+void Compiler::SetGcMapsMethod(const DexFile& dex_file, Method* method) {
+  if (method == NULL) {
+    Thread::Current()->ClearException();
+    return;
+  }
+  uint16_t method_idx = method->GetDexMethodIndex();
+  MethodReference ref(&dex_file, method_idx);
+  CompiledMethod* compiled_method = GetCompiledMethod(ref);
+  if (compiled_method == NULL) {
+    return;
+  }
+  const std::vector<uint8_t>* gc_map = verifier::DexVerifier::GetGcMap(ref);
+  if (gc_map == NULL) {
+    return;
+  }
+  compiled_method->SetGcMap(*gc_map);
+}
+
 void Compiler::SetCodeAndDirectMethods(const std::vector<const DexFile*>& dex_files) {
   for (size_t i = 0; i != dex_files.size(); ++i) {
     const DexFile* dex_file = dex_files[i];