Remove use of MemMap for code allocation.

In preparation of moving to an executable code space.

Change-Id: I6cb6fec93c66005f8020d718fe3c1c5aa1c85356
diff --git a/src/class_linker_test.cc b/src/class_linker_test.cc
index 6f894e3..583c280 100644
--- a/src/class_linker_test.cc
+++ b/src/class_linker_test.cc
@@ -272,8 +272,7 @@
 }
 
 TEST_F(ClassLinkerTest, FindClassNested) {
-  UniquePtr<const DexFile> dex(OpenTestDexFile("Nested"));
-  const PathClassLoader* class_loader = AllocPathClassLoader(dex.get());
+  const ClassLoader* class_loader = LoadDex("Nested");
 
   Class* outer = class_linker_->FindClass("LNested;", class_loader);
   ASSERT_TRUE(outer != NULL);
@@ -326,8 +325,7 @@
   EXPECT_EQ(0U, JavaLangObject->NumStaticFields());
   EXPECT_EQ(0U, JavaLangObject->NumInterfaces());
 
-  UniquePtr<const DexFile> dex(OpenTestDexFile("MyClass"));
-  const PathClassLoader* class_loader = AllocPathClassLoader(dex.get());
+  const ClassLoader* class_loader = LoadDex("MyClass");
   AssertNonExistentClass("LMyClass;");
   Class* MyClass = class_linker_->FindClass("LMyClass;", class_loader);
   ASSERT_TRUE(MyClass != NULL);
@@ -456,10 +454,8 @@
 }
 
 TEST_F(ClassLinkerTest, TwoClassLoadersOneClass) {
-  UniquePtr<const DexFile> dex_1(OpenTestDexFile("MyClass"));
-  UniquePtr<const DexFile> dex_2(OpenTestDexFile("MyClass"));
-  const PathClassLoader* class_loader_1 = AllocPathClassLoader(dex_1.get());
-  const PathClassLoader* class_loader_2 = AllocPathClassLoader(dex_2.get());
+  const ClassLoader* class_loader_1 = LoadDex("MyClass");
+  const ClassLoader* class_loader_2 = LoadDex("MyClass");
   Class* MyClass_1 = class_linker_->FindClass("LMyClass;", class_loader_1);
   Class* MyClass_2 = class_linker_->FindClass("LMyClass;", class_loader_2);
   EXPECT_TRUE(MyClass_1 != NULL);
@@ -469,8 +465,7 @@
 
 TEST_F(ClassLinkerTest, StaticFields) {
   // TODO: uncomment expectations of initial values when InitializeClass works
-  UniquePtr<const DexFile> dex(OpenTestDexFile("Statics"));
-  const PathClassLoader* class_loader = AllocPathClassLoader(dex.get());
+  const ClassLoader* class_loader = LoadDex("Statics");
   Class* statics = class_linker_->FindClass("LStatics;", class_loader);
   class_linker_->EnsureInitialized(statics);
 
@@ -539,8 +534,7 @@
 }
 
 TEST_F(ClassLinkerTest, Interfaces) {
-  UniquePtr<const DexFile> dex(OpenTestDexFile("Interfaces"));
-  const PathClassLoader* class_loader = AllocPathClassLoader(dex.get());
+  const ClassLoader* class_loader = LoadDex("Interfaces");
   Class* I = class_linker_->FindClass("LInterfaces$I;", class_loader);
   Class* J = class_linker_->FindClass("LInterfaces$J;", class_loader);
   Class* A = class_linker_->FindClass("LInterfaces$A;", class_loader);
diff --git a/src/common_test.h b/src/common_test.h
index 5318008..b4c1529 100644
--- a/src/common_test.h
+++ b/src/common_test.h
@@ -9,6 +9,7 @@
 #include "base64.h"
 #include "class_linker.h"
 #include "class_loader.h"
+#include "compiler.h"
 #include "dex_file.h"
 #include "gtest/gtest.h"
 #include "heap.h"
@@ -61,6 +62,29 @@
 };
 
 class CommonTest : public testing::Test {
+ public:
+  static void LogMaps() {
+    const char* maps_file = "/proc/self/maps";
+    std::string contents;
+    CHECK(ReadFileToString(maps_file, &contents));
+    // logcat can't handle it all at once
+    std::vector<std::string> lines;
+    Split(contents, '\n', lines);
+    LOG(INFO) << maps_file << ":";
+    for (size_t i = 0; i < lines.size(); i++) {
+      LOG(INFO) << "    " << lines[i];
+    }
+  }
+
+  static void MakeExecutable(const ByteArray* byte_array) {
+    uintptr_t data = reinterpret_cast<uintptr_t>(byte_array->GetData());
+    uintptr_t base = RoundDown(data, kPageSize);
+    uintptr_t limit = RoundUp(data + byte_array->GetLength(), kPageSize);
+    uintptr_t len = limit - base;
+    int result = mprotect(reinterpret_cast<void*>(base), len, PROT_READ | PROT_WRITE | PROT_EXEC);
+    CHECK_EQ(result, 0);
+  }
+
  protected:
   virtual void SetUp() {
     is_host_ = getenv("ANDROID_BUILD_TOP") != NULL;
@@ -170,6 +194,60 @@
     return dex_file;
   }
 
+  const ClassLoader* LoadDex(const char* dex_name) {
+    const DexFile* dex_file = OpenTestDexFile(dex_name);
+    CHECK(dex_file != NULL);
+    loaded_dex_files_.push_back(dex_file);
+    class_linker_->RegisterDexFile(*dex_file);
+    std::vector<const DexFile*> class_path;
+    class_path.push_back(dex_file);
+    const ClassLoader* class_loader = PathClassLoader::Alloc(class_path);
+    CHECK(class_loader != NULL);
+    Thread::Current()->SetClassLoaderOverride(class_loader);
+    return class_loader;
+  }
+
+  std::string ConvertClassNameToClassDescriptor(const char* class_name) {
+    std::string desc;
+    desc += "L";
+    desc += class_name;
+    desc += ";";
+    std::replace(desc.begin(), desc.end(), '.', '/');
+    return desc;
+  }
+
+  void CompileMethod(Method* method) {
+    CHECK(method != NULL);
+    Compiler compiler;
+    compiler.CompileOne(method);
+    MakeExecutable(method->GetCodeArray());
+    MakeExecutable(method->GetInvokeStubArray());
+  }
+
+  void CompileDirectMethod(const ClassLoader* class_loader,
+                           const char* class_name,
+                           const char* method_name,
+                           const char* signature) {
+    std::string class_descriptor = ConvertClassNameToClassDescriptor(class_name);
+    Class* klass = class_linker_->FindClass(class_descriptor, class_loader);
+    CHECK(klass != NULL) << "Class not found " << class_name;
+    Method* method = klass->FindDirectMethod(method_name, signature);
+    CHECK(method != NULL) << "Method not found " << method_name;
+    CompileMethod(method);
+  }
+
+  void CompileVirtualMethod(const ClassLoader* class_loader,
+                            const char* class_name,
+                            const char* method_name,
+                            const char* signature) {
+    std::string class_descriptor = ConvertClassNameToClassDescriptor(class_name);
+    Class* klass = class_linker_->FindClass(class_descriptor, class_loader);
+    CHECK(klass != NULL) << "Class not found " << class_name;
+    Method* method = klass->FindVirtualMethod(method_name, signature);
+    CHECK(method != NULL) << "Method not found " << method_name;
+    CompileMethod(method);
+  }
+
   bool is_host_;
   std::string android_data_;
   std::string art_cache_;
@@ -177,6 +255,9 @@
   std::vector<const DexFile*> boot_class_path_;
   UniquePtr<Runtime> runtime_;
   ClassLinker* class_linker_;
+
+ private:
+  std::vector<const DexFile*> loaded_dex_files_;
 };
 
 }  // namespace art
diff --git a/src/compiler.cc b/src/compiler.cc
index 8396bdf..e2d72f5 100644
--- a/src/compiler.cc
+++ b/src/compiler.cc
@@ -7,6 +7,7 @@
 #include "class_loader.h"
 #include "dex_cache.h"
 #include "jni_compiler.h"
+#include "jni_internal.h"
 #include "runtime.h"
 
 extern bool oatCompileMethod(art::Method*, art::InstructionSet);
@@ -96,9 +97,31 @@
   }
 }
 
+// This is private API, but with two different implementations: ARM and x86.
+void CreateInvokeStub(Assembler* assembler, Method* method);
+
+namespace {
+
+void CompileInvokeStub(Method* method) {
+  if (method->GetInvokeStub() != NULL) {
+    return;
+  }
+  // TODO: use signature to find a matching stub
+  // TODO: failed, acquire a lock on the stub table
+  Assembler assembler;
+  art::CreateInvokeStub(&assembler, method);
+  // TODO: store native_entry in the stub table
+  ByteArray* code = ByteArray::Alloc(assembler.CodeSize());
+  MemoryRegion region(code->GetData(), code->GetLength());
+  assembler.FinalizeInstructions(region);
+  method->SetInvokeStub(code);
+  CHECK(method->GetInvokeStub() != NULL);
+}
+
+} // namespace
+
 void Compiler::CompileMethod(Method* method) {
   if (method->IsNative()) {
-    // TODO note code will be unmapped when JniCompiler goes out of scope
     Assembler jni_asm;
     JniCompiler jni_compiler;
     jni_compiler.Compile(&jni_asm, method);
@@ -110,6 +133,9 @@
     oatCompileMethod(method, kThumb2);
   }
   // CHECK(method->HasCode());  // TODO: enable this check ASAP
+
+  CompileInvokeStub(method);
+  CHECK(method->GetInvokeStub() != NULL);
 }
 
 void Compiler::SetCodeAndDirectMethods(const ClassLoader* class_loader) {
diff --git a/src/compiler/Frontend.cc b/src/compiler/Frontend.cc
index dbd06ab..d6f891b 100644
--- a/src/compiler/Frontend.cc
+++ b/src/compiler/Frontend.cc
@@ -18,6 +18,7 @@
 #include "CompilerInternals.h"
 #include "Dataflow.h"
 #include "constants.h"
+#include "object.h"
 #include "runtime.h"
 
 static inline bool contentIsInsn(const u2* codePtr) {
@@ -716,8 +717,7 @@
         if (PrettyMethod(method).find("java.lang.Object.<init>") != std::string::npos) {
             compiling = true;
         }
-    } else if ( (method->GetName()->ToModifiedUtf8().find("foo") != std::string::npos) ||
-        (method->GetName()->ToModifiedUtf8().find("main") != std::string::npos)) {
+    } else if (method->GetName()->ToModifiedUtf8().find("foo") != std::string::npos) {
         compiling = false;
     }
 
@@ -916,8 +916,11 @@
         }
     }
 
-    method->SetCode((const art::byte*)&cUnit.codeBuffer[0],
-                    cUnit.codeBuffer.size() * 2, art::kThumb2);
+    art::ByteArray* managed_code = art::ByteArray::Alloc(cUnit.codeBuffer.size() * 2);
+    memcpy(managed_code->GetData(),
+           reinterpret_cast<const int8_t*>(&cUnit.codeBuffer[0]),
+           managed_code->GetLength());
+    method->SetCode(managed_code, art::kThumb2);
     method->SetFrameSizeInBytes(cUnit.frameSize);
     method->SetCoreSpillMask(cUnit.coreSpillMask);
     method->SetFpSpillMask(cUnit.fpSpillMask);
diff --git a/src/compiler_test.cc b/src/compiler_test.cc
index b4e43cc..c144f7c 100644
--- a/src/compiler_test.cc
+++ b/src/compiler_test.cc
@@ -18,66 +18,6 @@
 class CompilerTest : public CommonTest {
  protected:
 
-  const ClassLoader* LoadDex(const char* dex_name) {
-    dex_file_.reset(OpenTestDexFile(dex_name));
-    class_linker_->RegisterDexFile(*dex_file_.get());
-    std::vector<const DexFile*> class_path;
-    class_path.push_back(dex_file_.get());
-    const ClassLoader* class_loader = PathClassLoader::Alloc(class_path);
-    Thread::Current()->SetClassLoaderOverride(class_loader);
-    return class_loader;
-  }
-
-
-  void CompileDex(const char* dex_name) {
-    Compile(LoadDex(dex_name));
-  }
-
-  void CompileSystem() {
-    Compile(NULL);
-  }
-
-  void Compile(const ClassLoader* class_loader) {
-    Compiler compiler;
-    compiler.CompileAll(NULL);
-  }
-
-  std::string ConvertClassNameToClassDescriptor(const char* class_name) {
-    std::string desc;
-    desc += "L";
-    desc += class_name;
-    desc += ";";
-    std::replace(desc.begin(), desc.end(), '.', '/');
-    return desc;
-  }
-
-
-  void CompileDirectMethod(const ClassLoader* class_loader,
-                           const char* class_name,
-                           const char* method_name,
-                           const char* signature) {
-    std::string class_descriptor = ConvertClassNameToClassDescriptor(class_name);
-    Class* klass = class_linker_->FindClass(class_descriptor, class_loader);
-    CHECK(klass != NULL) << "Class not found " << class_name;
-    Method* method = klass->FindDirectMethod(method_name, signature);
-    CHECK(method != NULL) << "Method not found " << method_name;
-    Compiler compiler;
-    compiler.CompileOne(method);
-  }
-
-  void CompileVirtualMethod(const ClassLoader* class_loader,
-                            const char* class_name,
-                            const char* method_name,
-                            const char* signature) {
-    std::string class_descriptor = ConvertClassNameToClassDescriptor(class_name);
-    Class* klass = class_linker_->FindClass(class_descriptor, class_loader);
-    CHECK(klass != NULL) << "Class not found " << class_name;
-    Method* method = klass->FindVirtualMethod(method_name, signature);
-    CHECK(method != NULL) << "Method not found " << method_name;
-    Compiler compiler;
-    compiler.CompileOne(method);
-  }
-
   void AssertStaticIntMethod(const ClassLoader* class_loader,
                              const char* klass, const char* method, const char* signature,
                              jint expected, ...) {
@@ -114,8 +54,6 @@
     EXPECT_EQ(expected, result);
 #endif // __arm__
   }
- private:
-  UniquePtr<const DexFile> dex_file_;
 };
 
 // TODO renenable when compiler can handle libcore
diff --git a/src/dex_verifier_test.cc b/src/dex_verifier_test.cc
index ea419f9..e6d8096 100644
--- a/src/dex_verifier_test.cc
+++ b/src/dex_verifier_test.cc
@@ -39,8 +39,7 @@
 }
 
 TEST_F(DexVerifierTest, IntMath) {
-  UniquePtr<const DexFile> dex(OpenTestDexFile("IntMath"));
-  const PathClassLoader* class_loader = AllocPathClassLoader(dex.get());
+  const ClassLoader* class_loader = LoadDex("IntMath");
   Class* klass = class_linker_->FindClass("LIntMath;", class_loader);
   ASSERT_TRUE(DexVerify::VerifyClass(klass));
 }
diff --git a/src/heap.h b/src/heap.h
index 5168fe7..30133b7 100644
--- a/src/heap.h
+++ b/src/heap.h
@@ -21,9 +21,9 @@
 
 class Heap {
  public:
-  static const size_t kInitialSize = 16 * MB;
+  static const size_t kInitialSize = 64 * MB;  // TODO: lower to 4
 
-  static const size_t kMaximumSize = 64 * MB;
+  static const size_t kMaximumSize = 64 * MB;  // TODO: lower to 16
 
   typedef void (RootVisitor)(const Object* root, void* arg);
 
diff --git a/src/image_test.cc b/src/image_test.cc
index b205fe2..d54c3ce 100644
--- a/src/image_test.cc
+++ b/src/image_test.cc
@@ -73,10 +73,8 @@
 
   // enable to display maps to debug boot_base and boot_limit checking problems below
   if (false) {
-    const char* maps_file = "/proc/self/maps";
-    std::string contents;
-    CHECK(ReadFileToString(maps_file, &contents));
-    LG << maps_file << ":\n" << contents;
+    // TODO: switch to sending kill -3 to self
+    LogMaps();
   }
 
   byte* boot_base = boot_space->GetBase();
diff --git a/src/jni_compiler.cc b/src/jni_compiler.cc
index 1789e1b..0a11268 100644
--- a/src/jni_compiler.cc
+++ b/src/jni_compiler.cc
@@ -311,10 +311,11 @@
   // 17. Finalize code generation
   jni_asm->EmitSlowPaths();
   size_t cs = jni_asm->CodeSize();
-  MemoryRegion code(AllocateCode(cs), cs);
+  ByteArray* managed_code = ByteArray::Alloc(cs);
+  CHECK(managed_code != NULL);
+  MemoryRegion code(managed_code->GetData(), managed_code->GetLength());
   jni_asm->FinalizeInstructions(code);
-  native_method->SetCode(reinterpret_cast<byte*>(code.pointer()), cs,
-      jni_asm->GetInstructionSet());
+  native_method->SetCode(managed_code, jni_asm->GetInstructionSet());
   native_method->SetFrameSizeInBytes(frame_size);
   native_method->SetReturnPcOffsetInBytes(jni_conv.ReturnPcOffset());
 }
@@ -408,20 +409,7 @@
   }
 }
 
-void* JniCompiler::AllocateCode(size_t size) {
-  CHECK_LT(((jni_code_top_ - jni_code_->GetAddress()) + size), jni_code_->GetLength());
-  void *result = jni_code_top_;
-  jni_code_top_ += size;
-  return result;
-}
-
-JniCompiler::JniCompiler() {
-  // TODO: this shouldn't be managed by the JniCompiler, we should have a
-  // code cache.
-  jni_code_.reset(MemMap::Map(kPageSize, PROT_READ | PROT_WRITE | PROT_EXEC));
-  CHECK(jni_code_.get() !=  NULL);
-  jni_code_top_ = jni_code_->GetAddress();
-}
+JniCompiler::JniCompiler() {}
 
 JniCompiler::~JniCompiler() {}
 
diff --git a/src/jni_compiler.h b/src/jni_compiler.h
index 3c0d8b4..ece0dea 100644
--- a/src/jni_compiler.h
+++ b/src/jni_compiler.h
@@ -34,15 +34,6 @@
                           JniCallingConvention *jni_conv,
                           ManagedRegister in_reg);
 
-  // A poor man's code cache
-  void* AllocateCode(size_t size);
-
-  // Allocated code
-  UniquePtr<MemMap> jni_code_;
-
-  // Pointer to the free space
-  byte* jni_code_top_;
-
   DISALLOW_COPY_AND_ASSIGN(JniCompiler);
 };
 
diff --git a/src/jni_compiler_test.cc b/src/jni_compiler_test.cc
index 3ef970e..933970b 100644
--- a/src/jni_compiler_test.cc
+++ b/src/jni_compiler_test.cc
@@ -22,9 +22,7 @@
  protected:
   virtual void SetUp() {
     CommonTest::SetUp();
-    dex_.reset(OpenTestDexFile("MyClassNatives"));
-    class_loader_ = AllocPathClassLoader(dex_.get());
-    Thread::Current()->SetClassLoaderOverride(class_loader_);
+    class_loader_ = LoadDex("MyClassNatives");
   }
 
   void SetupForTest(bool direct, const char* method_name,
@@ -44,7 +42,7 @@
     ASSERT_TRUE(method != NULL);
 
     // Compile the native method
-    jni_compiler.Compile(&jni_asm, method);
+    CompileMethod(method);
     ASSERT_TRUE(method->HasCode());
 
     if (direct) {
@@ -66,10 +64,9 @@
   static jclass jklass_;
   static jobject jobj_;
  protected:
-  UniquePtr<const DexFile> dex_;
-  const PathClassLoader* class_loader_;
-  Assembler jni_asm;
-  JniCompiler jni_compiler;
+  const ClassLoader* class_loader_;
+  Assembler jni_asm_;
+  JniCompiler jni_compiler_;
   JNIEnv* env_;
   jmethodID jmethod_;
 };
diff --git a/src/jni_internal.cc b/src/jni_internal.cc
index a7c7dc7..a75a365 100644
--- a/src/jni_internal.cc
+++ b/src/jni_internal.cc
@@ -25,31 +25,6 @@
 
 namespace art {
 
-// This is private API, but with two different implementations: ARM and x86.
-void CreateInvokeStub(Assembler* assembler, Method* method);
-
-// TODO: this should be in our anonymous namespace, but is currently needed
-// for testing in "jni_internal_test.cc".
-void EnsureInvokeStub(Method* method) {
-  if (method->GetInvokeStub() != NULL) {
-    return;
-  }
-  // TODO: use signature to find a matching stub
-  // TODO: failed, acquire a lock on the stub table
-  Assembler assembler;
-  CreateInvokeStub(&assembler, method);
-  // TODO: store native_entry in the stub table
-  int prot = PROT_READ | PROT_WRITE | PROT_EXEC;
-  size_t length = assembler.CodeSize();
-  void* addr = mmap(NULL, length, prot, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
-  if (addr == MAP_FAILED) {
-    PLOG(FATAL) << "mmap failed for " << PrettyMethod(method);
-  }
-  MemoryRegion region(addr, length);
-  assembler.FinalizeInstructions(region);
-  method->SetInvokeStub(reinterpret_cast<Method::InvokeStub*>(region.pointer()));
-}
-
 /*
  * Add a local reference for an object to the current stack frame.  When
  * the native function returns, the reference will be discarded.
@@ -231,10 +206,8 @@
   // Call the invoke stub associated with the method
   // Pass everything as arguments
   const Method::InvokeStub* stub = method->GetInvokeStub();
-  CHECK(stub != NULL);
-
   JValue result;
-  if (method->HasCode()) {
+  if (method->HasCode() && stub != NULL) {
     (*stub)(method, receiver, self, args, &result);
   } else {
     LOG(WARNING) << "Not invoking method with no associated code: "
@@ -334,8 +307,6 @@
     return NULL;
   }
 
-  EnsureInvokeStub(method);
-
   return reinterpret_cast<jmethodID>(AddWeakGlobalReference(ts, method));
 }
 
diff --git a/src/jni_internal_test.cc b/src/jni_internal_test.cc
index 325d1ec..8572e40 100644
--- a/src/jni_internal_test.cc
+++ b/src/jni_internal_test.cc
@@ -647,9 +647,7 @@
 
 
 TEST_F(JniInternalTest, GetPrimitiveField_SetPrimitiveField) {
-  UniquePtr<const DexFile> dex(OpenTestDexFile("AllFields"));
-  const PathClassLoader* class_loader = AllocPathClassLoader(dex.get());
-  Thread::Current()->SetClassLoaderOverride(class_loader);
+  LoadDex("AllFields");
 
   jclass c = env_->FindClass("AllFields");
   ASSERT_TRUE(c != NULL);
@@ -676,9 +674,7 @@
 }
 
 TEST_F(JniInternalTest, GetObjectField_SetObjectField) {
-  UniquePtr<const DexFile> dex(OpenTestDexFile("AllFields"));
-  const PathClassLoader* class_loader = AllocPathClassLoader(dex.get());
-  Thread::Current()->SetClassLoaderOverride(class_loader);
+  LoadDex("AllFields");
 
   jclass c = env_->FindClass("AllFields");
   ASSERT_TRUE(c != NULL);
@@ -823,25 +819,10 @@
   env_->DeleteWeakGlobalRef(o2);
 }
 
-void EnsureInvokeStub(Method* method);
-
-Method::InvokeStub* AllocateStub(Method* method,
-                                 byte* code,
-                                 size_t length) {
-  CHECK(method->GetInvokeStub() == NULL);
-  EnsureInvokeStub(method);
-  Method::InvokeStub* stub = method->GetInvokeStub();
-  CHECK(stub != NULL);
-  method->SetCode(code, length, kThumb2);
-  return stub;
-}
-
 #if defined(__arm__)
 TEST_F(JniInternalTest, StaticMainMethod) {
-  UniquePtr<const DexFile> dex(OpenTestDexFile("Main"));
-
-  const PathClassLoader* class_loader = AllocPathClassLoader(dex.get());
-  ASSERT_TRUE(class_loader != NULL);
+  const ClassLoader* class_loader = LoadDex("Main");
+  CompileDirectMethod(class_loader, "Main", "main", "([Ljava/lang/String;)V");
 
   Class* klass = class_linker_->FindClass("LMain;", class_loader);
   ASSERT_TRUE(klass != NULL);
@@ -849,14 +830,7 @@
   Method* method = klass->FindDirectMethod("main", "([Ljava/lang/String;)V");
   ASSERT_TRUE(method != NULL);
 
-  byte main_LV_code[] = {
-    0x2d, 0xe9, 0x00, 0x40, 0x83, 0xb0, 0xcd, 0xf8, 0x00, 0x00,
-    0xcd, 0xf8, 0x14, 0x10, 0x03, 0xb0, 0xbd, 0xe8, 0x00, 0x80,
-  };
-
-  Method::InvokeStub* stub = AllocateStub(method,
-                                          main_LV_code,
-                                          sizeof(main_LV_code));
+  Method::InvokeStub* stub = method->GetInvokeStub();
 
   Object* arg = NULL;
 
@@ -864,10 +838,8 @@
 }
 
 TEST_F(JniInternalTest, StaticNopMethod) {
-  UniquePtr<const DexFile> dex(OpenTestDexFile("StaticLeafMethods"));
-
-  const PathClassLoader* class_loader = AllocPathClassLoader(dex.get());
-  ASSERT_TRUE(class_loader != NULL);
+  const ClassLoader* class_loader = LoadDex("StaticLeafMethods");
+  CompileDirectMethod(class_loader, "StaticLeafMethods", "nop", "()V");
 
   Class* klass = class_linker_->FindClass("LStaticLeafMethods;", class_loader);
   ASSERT_TRUE(klass != NULL);
@@ -875,24 +847,14 @@
   Method* method = klass->FindDirectMethod("nop", "()V");
   ASSERT_TRUE(method != NULL);
 
-  byte nop_V_code[] = {
-    0x2d, 0xe9, 0x00, 0x40, 0x83, 0xb0, 0xcd, 0xf8,
-    0x00, 0x00, 0x03, 0xb0, 0xbd, 0xe8, 0x00, 0x80,
-  };
-
-  Method::InvokeStub* stub = AllocateStub(method,
-                                          nop_V_code,
-                                          sizeof(nop_V_code));
-  ASSERT_TRUE(stub);
+  Method::InvokeStub* stub = method->GetInvokeStub();
 
   (*stub)(method, NULL, NULL, NULL, NULL);
 }
 
 TEST_F(JniInternalTest, StaticIdentityByteMethod) {
-  UniquePtr<const DexFile> dex(OpenTestDexFile("StaticLeafMethods"));
-
-  const PathClassLoader* class_loader = AllocPathClassLoader(dex.get());
-  ASSERT_TRUE(class_loader != NULL);
+  const ClassLoader* class_loader = LoadDex("StaticLeafMethods");
+  CompileDirectMethod(class_loader, "StaticLeafMethods", "identity", "(B)B");
 
   Class* klass = class_linker_->FindClass("LStaticLeafMethods;", class_loader);
   ASSERT_TRUE(klass != NULL);
@@ -900,15 +862,7 @@
   Method* method = klass->FindDirectMethod("identity", "(B)B");
   ASSERT_TRUE(method != NULL);
 
-  byte identity_BB_code[] = {
-    0x2d, 0xe9, 0x00, 0x40, 0x83, 0xb0, 0xcd, 0xf8,
-    0x00, 0x00, 0xcd, 0xf8, 0x14, 0x10, 0x05, 0x98,
-    0x03, 0xb0, 0xbd, 0xe8, 0x00, 0x80, 0x00, 0x00,
-  };
-
-  Method::InvokeStub* stub = AllocateStub(method,
-                                          identity_BB_code,
-                                          sizeof(identity_BB_code));
+  Method::InvokeStub* stub = method->GetInvokeStub();
 
   int arg;
   JValue result;
@@ -935,10 +889,8 @@
 }
 
 TEST_F(JniInternalTest, StaticIdentityIntMethod) {
-  UniquePtr<const DexFile> dex(OpenTestDexFile("StaticLeafMethods"));
-
-  const PathClassLoader* class_loader = AllocPathClassLoader(dex.get());
-  ASSERT_TRUE(class_loader != NULL);
+  const ClassLoader* class_loader = LoadDex("StaticLeafMethods");
+  CompileDirectMethod(class_loader, "StaticLeafMethods", "identity", "(I)I");
 
   Class* klass = class_linker_->FindClass("LStaticLeafMethods;", class_loader);
   ASSERT_TRUE(klass != NULL);
@@ -946,15 +898,7 @@
   Method* method = klass->FindDirectMethod("identity", "(I)I");
   ASSERT_TRUE(method != NULL);
 
-  byte identity_II_code[] = {
-    0x2d, 0xe9, 0x00, 0x40, 0x83, 0xb0, 0xcd, 0xf8,
-    0x00, 0x00, 0xcd, 0xf8, 0x14, 0x10, 0x05, 0x98,
-    0x03, 0xb0, 0xbd, 0xe8, 0x00, 0x80, 0x00, 0x00,
-  };
-
-  Method::InvokeStub* stub = AllocateStub(method,
-                                          identity_II_code,
-                                          sizeof(identity_II_code));
+  Method::InvokeStub* stub = method->GetInvokeStub();
 
   int arg;
   JValue result;
@@ -981,10 +925,8 @@
 }
 
 TEST_F(JniInternalTest, StaticIdentityDoubleMethod) {
-  UniquePtr<const DexFile> dex(OpenTestDexFile("StaticLeafMethods"));
-
-  const PathClassLoader* class_loader = AllocPathClassLoader(dex.get());
-  ASSERT_TRUE(class_loader != NULL);
+  const ClassLoader* class_loader = LoadDex("StaticLeafMethods");
+  CompileDirectMethod(class_loader, "StaticLeafMethods", "identity", "(D)D");
 
   Class* klass = class_linker_->FindClass("LStaticLeafMethods;", class_loader);
   ASSERT_TRUE(klass != NULL);
@@ -992,16 +934,7 @@
   Method* method = klass->FindDirectMethod("identity", "(D)D");
   ASSERT_TRUE(method != NULL);
 
-  byte identity_DD_code[] = {
-    0x2d, 0xe9, 0x00, 0x40, 0x83, 0xb0, 0xcd, 0xf8,
-    0x00, 0x00, 0xcd, 0xf8, 0x14, 0x10, 0xcd, 0xf8,
-    0x18, 0x20, 0x05, 0x98, 0x06, 0x99, 0x03, 0xb0,
-    0xbd, 0xe8, 0x00, 0x80,
-  };
-
-  Method::InvokeStub* stub = AllocateStub(method,
-                                          identity_DD_code,
-                                          sizeof(identity_DD_code));
+  Method::InvokeStub* stub = method->GetInvokeStub();
 
   double arg;
   JValue result;
@@ -1028,10 +961,8 @@
 }
 
 TEST_F(JniInternalTest, StaticSumIntIntMethod) {
-  UniquePtr<const DexFile> dex(OpenTestDexFile("StaticLeafMethods"));
-
-  const PathClassLoader* class_loader = AllocPathClassLoader(dex.get());
-  ASSERT_TRUE(class_loader != NULL);
+  const ClassLoader* class_loader = LoadDex("StaticLeafMethods");
+  CompileDirectMethod(class_loader, "StaticLeafMethods", "sum", "(II)I");
 
   Class* klass = class_linker_->FindClass("LStaticLeafMethods;", class_loader);
   ASSERT_TRUE(klass != NULL);
@@ -1039,17 +970,7 @@
   Method* method = klass->FindDirectMethod("sum", "(II)I");
   ASSERT_TRUE(method != NULL);
 
-  byte sum_III_code[] = {
-    0x2d, 0xe9, 0x00, 0x40, 0x83, 0xb0, 0xcd, 0xf8,
-    0x00, 0x00, 0xcd, 0xf8, 0x14, 0x10, 0xcd, 0xf8,
-    0x18, 0x20, 0x05, 0x98, 0x06, 0x99, 0x42, 0x18,
-    0xcd, 0xf8, 0x04, 0x20, 0x01, 0x98, 0x03, 0xb0,
-    0xbd, 0xe8, 0x00, 0x80,
-  };
-
-  Method::InvokeStub* stub = AllocateStub(method,
-                                          sum_III_code,
-                                          sizeof(sum_III_code));
+  Method::InvokeStub* stub = method->GetInvokeStub();
 
   int args[2];
   JValue result;
@@ -1086,10 +1007,8 @@
 }
 
 TEST_F(JniInternalTest, StaticSumIntIntIntMethod) {
-  UniquePtr<const DexFile> dex(OpenTestDexFile("StaticLeafMethods"));
-
-  const PathClassLoader* class_loader = AllocPathClassLoader(dex.get());
-  ASSERT_TRUE(class_loader != NULL);
+  const ClassLoader* class_loader = LoadDex("StaticLeafMethods");
+  CompileDirectMethod(class_loader, "StaticLeafMethods", "sum", "(III)I");
 
   Class* klass = class_linker_->FindClass("LStaticLeafMethods;", class_loader);
   ASSERT_TRUE(klass != NULL);
@@ -1097,19 +1016,7 @@
   Method* method = klass->FindDirectMethod("sum", "(III)I");
   ASSERT_TRUE(method != NULL);
 
-  byte sum_IIII_code[] = {
-    0x2d, 0xe9, 0x00, 0x40, 0x83, 0xb0, 0xcd, 0xf8,
-    0x00, 0x00, 0xcd, 0xf8, 0x14, 0x10, 0xcd, 0xf8,
-    0x18, 0x20, 0xcd, 0xf8, 0x1c, 0x30, 0x05, 0x98,
-    0x06, 0x99, 0x42, 0x18, 0xcd, 0xf8, 0x04, 0x20,
-    0x01, 0x9b, 0xdd, 0xf8, 0x1c, 0xc0, 0x13, 0xeb,
-    0x0c, 0x03, 0xcd, 0xf8, 0x04, 0x30, 0x01, 0x98,
-    0x03, 0xb0, 0xbd, 0xe8, 0x00, 0x80, 0x00, 0x00,
-  };
-
-  Method::InvokeStub* stub = AllocateStub(method,
-                                          sum_IIII_code,
-                                          sizeof(sum_IIII_code));
+  Method::InvokeStub* stub = method->GetInvokeStub();
 
   int args[3];
   JValue result;
@@ -1151,10 +1058,8 @@
 }
 
 TEST_F(JniInternalTest, StaticSumIntIntIntIntMethod) {
-  UniquePtr<const DexFile> dex(OpenTestDexFile("StaticLeafMethods"));
-
-  const PathClassLoader* class_loader = AllocPathClassLoader(dex.get());
-  ASSERT_TRUE(class_loader != NULL);
+  const ClassLoader* class_loader = LoadDex("StaticLeafMethods");
+  CompileDirectMethod(class_loader, "StaticLeafMethods", "sum", "(IIII)I");
 
   Class* klass = class_linker_->FindClass("LStaticLeafMethods;", class_loader);
   ASSERT_TRUE(klass != NULL);
@@ -1162,20 +1067,7 @@
   Method* method = klass->FindDirectMethod("sum", "(IIII)I");
   ASSERT_TRUE(method != NULL);
 
-  byte sum_IIIII_code[] = {
-    0x2d, 0xe9, 0x00, 0x40, 0x83, 0xb0, 0xcd, 0xf8,
-    0x00, 0x00, 0xcd, 0xf8, 0x14, 0x10, 0xcd, 0xf8,
-    0x18, 0x20, 0xcd, 0xf8, 0x1c, 0x30, 0x05, 0x98,
-    0x06, 0x99, 0x42, 0x18, 0xcd, 0xf8, 0x04, 0x20,
-    0x01, 0x9b, 0xdd, 0xf8, 0x1c, 0xc0, 0x13, 0xeb,
-    0x0c, 0x03, 0xcd, 0xf8, 0x04, 0x30, 0x01, 0x98,
-    0x08, 0x99, 0x40, 0x18, 0xcd, 0xf8, 0x04, 0x00,
-    0x01, 0x98, 0x03, 0xb0, 0xbd, 0xe8, 0x00, 0x80,
-  };
-
-  Method::InvokeStub* stub = AllocateStub(method,
-                                          sum_IIIII_code,
-                                          sizeof(sum_IIIII_code));
+  Method::InvokeStub* stub = method->GetInvokeStub();
 
   int args[4];
   JValue result;
@@ -1222,10 +1114,8 @@
 }
 
 TEST_F(JniInternalTest, StaticSumIntIntIntIntIntMethod) {
-  UniquePtr<const DexFile> dex(OpenTestDexFile("StaticLeafMethods"));
-
-  const PathClassLoader* class_loader = AllocPathClassLoader(dex.get());
-  ASSERT_TRUE(class_loader != NULL);
+  const ClassLoader* class_loader = LoadDex("StaticLeafMethods");
+  CompileDirectMethod(class_loader, "StaticLeafMethods", "sum", "(IIIII)I");
 
   Class* klass = class_linker_->FindClass("LStaticLeafMethods;", class_loader);
   ASSERT_TRUE(klass != NULL);
@@ -1233,22 +1123,7 @@
   Method* method = klass->FindDirectMethod("sum", "(IIIII)I");
   ASSERT_TRUE(method != NULL);
 
-  byte sum_IIIIII_code[] = {
-    0x2d, 0xe9, 0x00, 0x40, 0x83, 0xb0, 0xcd, 0xf8,
-    0x00, 0x00, 0xcd, 0xf8, 0x14, 0x10, 0xcd, 0xf8,
-    0x18, 0x20, 0xcd, 0xf8, 0x1c, 0x30, 0x05, 0x98,
-    0x06, 0x99, 0x42, 0x18, 0xcd, 0xf8, 0x04, 0x20,
-    0x01, 0x9b, 0xdd, 0xf8, 0x1c, 0xc0, 0x13, 0xeb,
-    0x0c, 0x03, 0xcd, 0xf8, 0x04, 0x30, 0x01, 0x98,
-    0x08, 0x99, 0x40, 0x18, 0xcd, 0xf8, 0x04, 0x00,
-    0x01, 0x9a, 0x09, 0x9b, 0xd2, 0x18, 0xcd, 0xf8,
-    0x04, 0x20, 0x01, 0x98, 0x03, 0xb0, 0xbd, 0xe8,
-    0x00, 0x80, 0x00, 0x00,
-  };
-
-  Method::InvokeStub* stub = AllocateStub(method,
-                                          sum_IIIIII_code,
-                                          sizeof(sum_IIIIII_code));
+  Method::InvokeStub* stub = method->GetInvokeStub();
 
   int args[5];
   JValue result;
@@ -1300,10 +1175,8 @@
 }
 
 TEST_F(JniInternalTest, StaticSumDoubleDoubleMethod) {
-  UniquePtr<const DexFile> dex(OpenTestDexFile("StaticLeafMethods"));
-
-  const PathClassLoader* class_loader = AllocPathClassLoader(dex.get());
-  ASSERT_TRUE(class_loader != NULL);
+  const ClassLoader* class_loader = LoadDex("StaticLeafMethods");
+  CompileDirectMethod(class_loader, "StaticLeafMethods", "sum", "(DD)D");
 
   Class* klass = class_linker_->FindClass("LStaticLeafMethods;", class_loader);
   ASSERT_TRUE(klass != NULL);
@@ -1311,18 +1184,7 @@
   Method* method = klass->FindDirectMethod("sum", "(DD)D");
   ASSERT_TRUE(method != NULL);
 
-  byte sum_DDD_code[] = {
-    0x2d, 0xe9, 0x00, 0x40, 0x87, 0xb0, 0xcd, 0xf8,
-    0x00, 0x00, 0xcd, 0xf8, 0x24, 0x10, 0xcd, 0xf8,
-    0x28, 0x20, 0xcd, 0xf8, 0x2c, 0x30, 0x9d, 0xed,
-    0x09, 0x0b, 0x9d, 0xed, 0x0b, 0x1b, 0x30, 0xee,
-    0x01, 0x2b, 0x8d, 0xed, 0x04, 0x2b, 0x04, 0x98,
-    0x05, 0x99, 0x07, 0xb0, 0xbd, 0xe8, 0x00, 0x80,
-  };
-
-  Method::InvokeStub* stub = AllocateStub(method,
-                                          sum_DDD_code,
-                                          sizeof(sum_DDD_code));
+  Method::InvokeStub* stub = method->GetInvokeStub();
 
   double args[2];
   JValue result;
@@ -1359,10 +1221,8 @@
 }
 
 TEST_F(JniInternalTest, StaticSumDoubleDoubleDoubleMethod) {
-  UniquePtr<const DexFile> dex(OpenTestDexFile("StaticLeafMethods"));
-
-  const PathClassLoader* class_loader = AllocPathClassLoader(dex.get());
-  ASSERT_TRUE(class_loader != NULL);
+  const ClassLoader* class_loader = LoadDex("StaticLeafMethods");
+  CompileDirectMethod(class_loader, "StaticLeafMethods", "sum", "(DDD)D");
 
   Class* klass = class_linker_->FindClass("LStaticLeafMethods;", class_loader);
   ASSERT_TRUE(klass != NULL);
@@ -1370,20 +1230,7 @@
   Method* method = klass->FindDirectMethod("sum", "(DDD)D");
   ASSERT_TRUE(method != NULL);
 
-  byte sum_DDDD_code[] = {
-    0x2d, 0xe9, 0x00, 0x40, 0x87, 0xb0, 0xcd, 0xf8,
-    0x00, 0x00, 0xcd, 0xf8, 0x24, 0x10, 0xcd, 0xf8,
-    0x28, 0x20, 0xcd, 0xf8, 0x2c, 0x30, 0x9d, 0xed,
-    0x09, 0x0b, 0x9d, 0xed, 0x0b, 0x1b, 0x30, 0xee,
-    0x01, 0x2b, 0x8d, 0xed, 0x04, 0x2b, 0x9d, 0xed,
-    0x04, 0x3b, 0x9d, 0xed, 0x0d, 0x4b, 0x33, 0xee,
-    0x04, 0x3b, 0x8d, 0xed, 0x04, 0x3b, 0x04, 0x98,
-    0x05, 0x99, 0x07, 0xb0, 0xbd, 0xe8, 0x00, 0x80,
-  };
-
-  Method::InvokeStub* stub = AllocateStub(method,
-                                          sum_DDDD_code,
-                                          sizeof(sum_DDDD_code));
+  Method::InvokeStub* stub = method->GetInvokeStub();
 
   double args[3];
   JValue result;
@@ -1411,10 +1258,8 @@
 }
 
 TEST_F(JniInternalTest, StaticSumDoubleDoubleDoubleDoubleMethod) {
-  UniquePtr<const DexFile> dex(OpenTestDexFile("StaticLeafMethods"));
-
-  const PathClassLoader* class_loader = AllocPathClassLoader(dex.get());
-  ASSERT_TRUE(class_loader != NULL);
+  const ClassLoader* class_loader = LoadDex("StaticLeafMethods");
+  CompileDirectMethod(class_loader, "StaticLeafMethods", "sum", "(DDDD)D");
 
   Class* klass = class_linker_->FindClass("LStaticLeafMethods;", class_loader);
   ASSERT_TRUE(klass != NULL);
@@ -1422,22 +1267,7 @@
   Method* method = klass->FindDirectMethod("sum", "(DDDD)D");
   ASSERT_TRUE(method != NULL);
 
-  byte sum_DDDDD_code[] = {
-    0x2d, 0xe9, 0x00, 0x40, 0x87, 0xb0, 0xcd, 0xf8,
-    0x00, 0x00, 0xcd, 0xf8, 0x24, 0x10, 0xcd, 0xf8,
-    0x28, 0x20, 0xcd, 0xf8, 0x2c, 0x30, 0x9d, 0xed,
-    0x09, 0x0b, 0x9d, 0xed, 0x0b, 0x1b, 0x30, 0xee,
-    0x01, 0x2b, 0x8d, 0xed, 0x04, 0x2b, 0x9d, 0xed,
-    0x04, 0x3b, 0x9d, 0xed, 0x0d, 0x4b, 0x33, 0xee,
-    0x04, 0x3b, 0x8d, 0xed, 0x04, 0x3b, 0x9d, 0xed,
-    0x04, 0x5b, 0x9d, 0xed, 0x0f, 0x6b, 0x35, 0xee,
-    0x06, 0x5b, 0x8d, 0xed, 0x04, 0x5b, 0x04, 0x98,
-    0x05, 0x99, 0x07, 0xb0, 0xbd, 0xe8, 0x00, 0x80,
-  };
-
-  Method::InvokeStub* stub = AllocateStub(method,
-                                          sum_DDDDD_code,
-                                          sizeof(sum_DDDDD_code));
+  Method::InvokeStub* stub = method->GetInvokeStub();
 
   double args[4];
   JValue result;
@@ -1468,10 +1298,8 @@
 }
 
 TEST_F(JniInternalTest, StaticSumDoubleDoubleDoubleDoubleDoubleMethod) {
-  UniquePtr<const DexFile> dex(OpenTestDexFile("StaticLeafMethods"));
-
-  const PathClassLoader* class_loader = AllocPathClassLoader(dex.get());
-  ASSERT_TRUE(class_loader != NULL);
+  const ClassLoader* class_loader = LoadDex("StaticLeafMethods");
+  CompileDirectMethod(class_loader, "StaticLeafMethods", "sum", "(DDDDD)D");
 
   Class* klass = class_linker_->FindClass("LStaticLeafMethods;", class_loader);
   ASSERT_TRUE(klass != NULL);
@@ -1479,24 +1307,7 @@
   Method* method = klass->FindDirectMethod("sum", "(DDDDD)D");
   ASSERT_TRUE(method != NULL);
 
-  byte sum_DDDDDD_code[] = {
-    0x2d, 0xe9, 0x00, 0x40, 0x87, 0xb0, 0xcd, 0xf8,
-    0x00, 0x00, 0xcd, 0xf8, 0x24, 0x10, 0xcd, 0xf8,
-    0x28, 0x20, 0xcd, 0xf8, 0x2c, 0x30, 0x9d, 0xed,
-    0x09, 0x0b, 0x9d, 0xed, 0x0b, 0x1b, 0x30, 0xee,
-    0x01, 0x2b, 0x8d, 0xed, 0x04, 0x2b, 0x9d, 0xed,
-    0x04, 0x3b, 0x9d, 0xed, 0x0d, 0x4b, 0x33, 0xee,
-    0x04, 0x3b, 0x8d, 0xed, 0x04, 0x3b, 0x9d, 0xed,
-    0x04, 0x5b, 0x9d, 0xed, 0x0f, 0x6b, 0x35, 0xee,
-    0x06, 0x5b, 0x8d, 0xed, 0x04, 0x5b, 0x9d, 0xed,
-    0x04, 0x7b, 0x9d, 0xed, 0x11, 0x0b, 0x37, 0xee,
-    0x00, 0x7b, 0x8d, 0xed, 0x04, 0x7b, 0x04, 0x98,
-    0x05, 0x99, 0x07, 0xb0, 0xbd, 0xe8, 0x00, 0x80,
-  };
-
-  Method::InvokeStub* stub = AllocateStub(method,
-                                          sum_DDDDDD_code,
-                                          sizeof(sum_DDDDDD_code));
+  Method::InvokeStub* stub = method->GetInvokeStub();
 
   double args[5];
   JValue result;
diff --git a/src/object.cc b/src/object.cc
index 3ddfe59..d60b4c8 100644
--- a/src/object.cc
+++ b/src/object.cc
@@ -462,26 +462,27 @@
           this->GetSignature()->Equals(that->GetSignature()));
 }
 
-void Method::SetCode(const byte* compiled_code,
-                     size_t byte_count,
-                     InstructionSet set) {
-  // Copy the code into an executable region.
-  code_instruction_set_ = set;
-  code_area_.reset(MemMap::Map(byte_count,
-                               PROT_READ | PROT_WRITE | PROT_EXEC));
-  CHECK(code_area_.get());
-  byte* code = code_area_->GetAddress();
-  memcpy(code, compiled_code, byte_count);
-  __builtin___clear_cache(code, code + byte_count);
-
+void Method::SetCode(ByteArray* code_array,
+                     InstructionSet instruction_set) {
+  CHECK(!HasCode() || IsNative());
+  SetFieldPtr<ByteArray*>(OFFSET_OF_OBJECT_MEMBER(Method, code_array_), code_array, false);
+  int8_t* code = code_array->GetData();
   uintptr_t address = reinterpret_cast<uintptr_t>(code);
-  if (code_instruction_set_ == kThumb2) {
+  if (instruction_set == kThumb2) {
     // Set the low-order bit so a BLX will switch to Thumb mode
     address |= 0x1;
   }
   SetFieldPtr<uintptr_t>(OFFSET_OF_OBJECT_MEMBER(Method, code_), address, false);
 }
 
+void Method::SetInvokeStub(const ByteArray* invoke_stub_array) {
+  const InvokeStub* invoke_stub = reinterpret_cast<InvokeStub*>(invoke_stub_array->GetData());
+  SetFieldPtr<const ByteArray*>(
+      OFFSET_OF_OBJECT_MEMBER(Method, invoke_stub_array_), invoke_stub_array, false);
+  SetFieldPtr<const InvokeStub*>(
+      OFFSET_OF_OBJECT_MEMBER(Method, invoke_stub_), invoke_stub, false);
+}
+
 void Class::SetStatus(Status new_status) {
   CHECK(new_status > GetStatus() || new_status == kStatusError ||
         Runtime::Current() == NULL);  // no runtime implies we're not initialized
diff --git a/src/object.h b/src/object.h
index 85e7a92..5857571 100644
--- a/src/object.h
+++ b/src/object.h
@@ -828,6 +828,10 @@
   // Size in bytes of the return value
   size_t ReturnSize() const;
 
+  const ByteArray* GetCodeArray() const {
+    return GetFieldPtr<const ByteArray*>(OFFSET_OF_OBJECT_MEMBER(Method, code_array_), false);
+  }
+
   const void* GetCode() const {
     return GetFieldPtr<const void*>(OFFSET_OF_OBJECT_MEMBER(Method, code_), false);
   }
@@ -836,9 +840,7 @@
     return GetCode() != NULL;
   }
 
-  void SetCode(const byte* compiled_code,
-               size_t byte_count,
-               InstructionSet set);
+  void SetCode(ByteArray* code_array, InstructionSet instruction_set);
 
   static MemberOffset GetCodeOffset() {
     return OFFSET_OF_OBJECT_MEMBER(Method, code_);
@@ -873,12 +875,14 @@
   }
 
   void RegisterNative(const void* native_method) {
+    CHECK(IsNative());
     CHECK(native_method != NULL);
     SetFieldPtr<const void*>(OFFSET_OF_OBJECT_MEMBER(Method, native_method_),
                              native_method, false);
   }
 
   void UnregisterNative() {
+    CHECK(IsNative());
     SetFieldPtr<const void*>(OFFSET_OF_OBJECT_MEMBER(Method, native_method_),
                              NULL, false);
   }
@@ -887,6 +891,13 @@
     return OFFSET_OF_OBJECT_MEMBER(Method, native_method_);
   }
 
+  ByteArray* GetInvokeStubArray() const {
+    ByteArray* result = GetFieldPtr<ByteArray*>(
+        OFFSET_OF_OBJECT_MEMBER(Method, invoke_stub_array_), false);
+    // TODO: DCHECK(result != NULL);  should be ahead of time compiled
+    return result;
+  }
+
   // Native to managed invocation stub entry point
   InvokeStub* GetInvokeStub() const {
     InvokeStub* result = GetFieldPtr<InvokeStub*>(
@@ -911,10 +922,7 @@
     return OFFSET_OF_OBJECT_MEMBER(Method, method_index_);
   }
 
-  void SetInvokeStub(const InvokeStub* new_invoke_stub) {
-    SetFieldPtr<const InvokeStub*>(
-        OFFSET_OF_OBJECT_MEMBER(Method, invoke_stub_), new_invoke_stub, false);
-  }
+  void SetInvokeStub(const ByteArray* invoke_stub_array);
 
   void SetFpSpillMask(uint32_t fp_spill_mask) {
     // Computed during compilation
@@ -1030,24 +1038,23 @@
   ObjectArray<StaticStorageBase>* dex_cache_initialized_static_storage_;
 
  private:
-  // Compiled code associated with this method
-  UniquePtr<MemMap> code_area_;
+  // Storage for code_
+  const ByteArray* code_array_;
+
+  // Compiled code associated with this method for callers from managed code.
+  // May be compiled managed code or a bridge for invoking a native method.
   const void* code_;
 
-  // Instruction set of the compiled code
-  InstructionSet code_instruction_set_;
-
-  // Size in bytes of compiled code associated with this method
-  const uint32_t code_size_;
-
   // Offset of return PC within frame for compiled code (in bytes)
-  // Offset of PC within compiled code (in bytes)
   size_t return_pc_offset_in_bytes_;
 
-  // Any native method registered with this method
+  // The target native method registered with this method
   const void* native_method_;
 
-  // Native invocation stub entry point.
+  // Storage for invoke_stub_
+  const ByteArray* invoke_stub_array_;
+
+  // Native invocation stub entry point for calling from native to managed code.
   const InvokeStub* invoke_stub_;
 
   static Class* java_lang_reflect_Method_;
diff --git a/src/object_test.cc b/src/object_test.cc
index d485c2e..79a1f2d 100644
--- a/src/object_test.cc
+++ b/src/object_test.cc
@@ -274,10 +274,8 @@
 TEST_F(ObjectTest, DescriptorCompare) {
   ClassLinker* linker = class_linker_;
 
-  UniquePtr<const DexFile> proto1_dex_file(OpenTestDexFile("ProtoCompare"));
-  const PathClassLoader* class_loader_1 = AllocPathClassLoader(proto1_dex_file.get());
-  UniquePtr<const DexFile> proto2_dex_file(OpenTestDexFile("ProtoCompare2"));
-  const PathClassLoader* class_loader_2 = AllocPathClassLoader(proto2_dex_file.get());
+  const ClassLoader* class_loader_1 = LoadDex("ProtoCompare");
+  const ClassLoader* class_loader_2 = LoadDex("ProtoCompare2");
 
   Class* klass1 = linker->FindClass("LProtoCompare;", class_loader_1);
   ASSERT_TRUE(klass1 != NULL);
@@ -323,8 +321,7 @@
 }
 
 TEST_F(ObjectTest, InstanceOf) {
-  UniquePtr<const DexFile> dex(OpenTestDexFile("XandY"));
-  const PathClassLoader* class_loader = AllocPathClassLoader(dex.get());
+  const ClassLoader* class_loader = LoadDex("XandY");
   Class* X = class_linker_->FindClass("LX;", class_loader);
   Class* Y = class_linker_->FindClass("LY;", class_loader);
   ASSERT_TRUE(X != NULL);
@@ -350,8 +347,7 @@
 }
 
 TEST_F(ObjectTest, IsAssignableFrom) {
-  UniquePtr<const DexFile> dex(OpenTestDexFile("XandY"));
-  const PathClassLoader* class_loader = AllocPathClassLoader(dex.get());
+  const ClassLoader* class_loader = LoadDex("XandY");
   Class* X = class_linker_->FindClass("LX;", class_loader);
   Class* Y = class_linker_->FindClass("LY;", class_loader);
 
@@ -362,8 +358,7 @@
 }
 
 TEST_F(ObjectTest, IsAssignableFromArray) {
-  UniquePtr<const DexFile> dex(OpenTestDexFile("XandY"));
-  const PathClassLoader* class_loader = AllocPathClassLoader(dex.get());
+  const ClassLoader* class_loader = LoadDex("XandY");
   Class* X = class_linker_->FindClass("LX;", class_loader);
   Class* Y = class_linker_->FindClass("LY;", class_loader);
   ASSERT_TRUE(X != NULL);
diff --git a/src/space.h b/src/space.h
index 1715a87..92b017a 100644
--- a/src/space.h
+++ b/src/space.h
@@ -16,7 +16,10 @@
 // A space contains memory allocated for managed objects.
 class Space {
  public:
-  // create a Space with the requested sizes requesting a specific base address.
+  // Create a Space with the requested sizes. The requested
+  // base address is not guaranteed to be granted, if it is required,
+  // the caller should call GetBase on the returned space to confirm
+  // the request was granted.
   static Space* Create(size_t initial_size, size_t maximum_size, byte* requested_base);
 
   // create a Space from an image file. cannot be used for future allocation or collected.