Removed compiled resolution trampoline.

Created assembly versions of resolution trampoline for portable and
quick. Removed compiled version from the image.

Change-Id: I183e110c4e102fb45ce6e7f4e855f8bed7986251
diff --git a/src/check_jni.cc b/src/check_jni.cc
index f97e0b3..19f8abf 100644
--- a/src/check_jni.cc
+++ b/src/check_jni.cc
@@ -31,9 +31,9 @@
 #include "mirror/object_array-inl.h"
 #include "mirror/throwable.h"
 #include "object_utils.h"
+#include "runtime.h"
 #include "scoped_thread_state_change.h"
 #include "thread.h"
-#include "runtime.h"
 
 #define LIBCORE_CPP_JNI_HELPERS
 #include <JNIHelp.h> // from libcore
diff --git a/src/class_linker.cc b/src/class_linker.cc
index cee1881..9dee36a 100644
--- a/src/class_linker.cc
+++ b/src/class_linker.cc
@@ -1034,12 +1034,11 @@
     return;
   }
 
-  // Check if object is an uncompiled method and point the to the interpreter entry point.
+  // Check if object is a method without its code set and point it to the resolution trampoline.
   if (obj->IsMethod()) {
     mirror::AbstractMethod* method = obj->AsMethod();
     if (method->GetCode() == NULL) {
-      const void* interpreter_entry = GetInterpreterEntryPoint();
-      method->SetCode(interpreter_entry);
+      method->SetCode(GetResolutionTrampoline());
     }
   }
 }
@@ -1607,7 +1606,7 @@
 
   if (method->IsStatic() && !method->IsConstructor()) {
     // For static methods excluding the class initializer, install the trampoline.
-    method->SetCode(runtime->GetResolutionStubArray(Runtime::kStaticMethod)->GetData());
+    method->SetCode(GetResolutionTrampoline());
   }
 
   if (method->IsNative()) {
diff --git a/src/common_test.h b/src/common_test.h
index 68b0cf6..05b0e05 100644
--- a/src/common_test.h
+++ b/src/common_test.h
@@ -36,6 +36,7 @@
 #include "object_utils.h"
 #include "os.h"
 #include "runtime.h"
+#include "runtime_support.h"
 #include "scoped_thread_state_change.h"
 #include "ScopedLocalRef.h"
 #include "thread.h"
@@ -354,13 +355,6 @@
 
     runtime_->SetJniDlsymLookupStub(CompilerDriver::CreateJniDlsymLookupStub(instruction_set));
     runtime_->SetAbstractMethodErrorStubArray(CompilerDriver::CreateAbstractMethodErrorStub(instruction_set));
-    for (int i = 0; i < Runtime::kLastTrampolineMethodType; i++) {
-      Runtime::TrampolineType type = Runtime::TrampolineType(i);
-      if (!runtime_->HasResolutionStubArray(type)) {
-        runtime_->SetResolutionStubArray(
-            CompilerDriver::CreateResolutionStub(instruction_set, type), type);
-      }
-    }
     if (!runtime_->HasResolutionMethod()) {
       runtime_->SetResolutionMethod(runtime_->CreateResolutionMethod());
     }
diff --git a/src/compiler/driver/compiler_driver.cc b/src/compiler/driver/compiler_driver.cc
index d464b42..e6f4b67 100644
--- a/src/compiler/driver/compiler_driver.cc
+++ b/src/compiler/driver/compiler_driver.cc
@@ -409,22 +409,6 @@
   return res;
 }
 
-mirror::ByteArray* CompilerDriver::CreateResolutionStub(InstructionSet instruction_set,
-                                                        Runtime::TrampolineType type) {
-  switch (instruction_set) {
-    case kArm:
-    case kThumb2:
-      return arm::ArmCreateResolutionTrampoline(type);
-    case kMips:
-      return mips::MipsCreateResolutionTrampoline(type);
-    case kX86:
-      return x86::X86CreateResolutionTrampoline(type);
-    default:
-      LOG(FATAL) << "Unknown InstructionSet: " << instruction_set;
-      return NULL;
-  }
-}
-
 mirror::ByteArray* CompilerDriver::CreateJniDlsymLookupStub(InstructionSet instruction_set) {
   switch (instruction_set) {
     case kArm:
diff --git a/src/compiler/driver/compiler_driver.h b/src/compiler/driver/compiler_driver.h
index fae6902..3581f5f 100644
--- a/src/compiler/driver/compiler_driver.h
+++ b/src/compiler/driver/compiler_driver.h
@@ -106,12 +106,6 @@
   static mirror::ByteArray* CreateAbstractMethodErrorStub(InstructionSet instruction_set)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
-
-  // Generate the trampoline that's invoked by unresolved direct methods
-  static mirror::ByteArray* CreateResolutionStub(InstructionSet instruction_set,
-                                                 Runtime::TrampolineType type)
-      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
-
   static mirror::ByteArray* CreateJniDlsymLookupStub(InstructionSet instruction_set)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
diff --git a/src/dex2oat.cc b/src/dex2oat.cc
index 97212ce..36b8d26 100644
--- a/src/dex2oat.cc
+++ b/src/dex2oat.cc
@@ -378,12 +378,6 @@
     if (!runtime->HasAbstractMethodErrorStubArray()) {
       runtime->SetAbstractMethodErrorStubArray(CompilerDriver::CreateAbstractMethodErrorStub(instruction_set));
     }
-    for (int i = 0; i < Runtime::kLastTrampolineMethodType; i++) {
-      Runtime::TrampolineType type = Runtime::TrampolineType(i);
-      if (!runtime->HasResolutionStubArray(type)) {
-        runtime->SetResolutionStubArray(CompilerDriver::CreateResolutionStub(instruction_set, type), type);
-      }
-    }
     if (!runtime->HasResolutionMethod()) {
       runtime->SetResolutionMethod(runtime->CreateResolutionMethod());
     }
diff --git a/src/gc/space.cc b/src/gc/space.cc
index e618f07..d7378c3 100644
--- a/src/gc/space.cc
+++ b/src/gc/space.cc
@@ -518,14 +518,6 @@
   mirror::Object* ame_stub_array = image_header.GetImageRoot(ImageHeader::kAbstractMethodErrorStubArray);
   runtime->SetAbstractMethodErrorStubArray(down_cast<mirror::ByteArray*>(ame_stub_array));
 
-  mirror::Object* resolution_stub_array =
-      image_header.GetImageRoot(ImageHeader::kStaticResolutionStubArray);
-  runtime->SetResolutionStubArray(
-      down_cast<mirror::ByteArray*>(resolution_stub_array), Runtime::kStaticMethod);
-  resolution_stub_array = image_header.GetImageRoot(ImageHeader::kUnknownMethodResolutionStubArray);
-  runtime->SetResolutionStubArray(
-      down_cast<mirror::ByteArray*>(resolution_stub_array), Runtime::kUnknownMethod);
-
   mirror::Object* resolution_method = image_header.GetImageRoot(ImageHeader::kResolutionMethod);
   runtime->SetResolutionMethod(down_cast<mirror::AbstractMethod*>(resolution_method));
 
diff --git a/src/image.cc b/src/image.cc
index d6bf635..c746c8e 100644
--- a/src/image.cc
+++ b/src/image.cc
@@ -24,7 +24,7 @@
 namespace art {
 
 const byte ImageHeader::kImageMagic[] = { 'a', 'r', 't', '\n' };
-const byte ImageHeader::kImageVersion[] = { '0', '0', '2', '\0' };
+const byte ImageHeader::kImageVersion[] = { '0', '0', '3', '\0' };
 
 ImageHeader::ImageHeader(uint32_t image_begin,
                          uint32_t image_roots,
diff --git a/src/image.h b/src/image.h
index 6501328..040e3fe 100644
--- a/src/image.h
+++ b/src/image.h
@@ -83,8 +83,6 @@
   enum ImageRoot {
     kJniStubArray,
     kAbstractMethodErrorStubArray,
-    kStaticResolutionStubArray,
-    kUnknownMethodResolutionStubArray,
     kResolutionMethod,
     kCalleeSaveMethod,
     kRefsOnlySaveMethod,
diff --git a/src/image_writer.cc b/src/image_writer.cc
index 5638b5b..16ac385 100644
--- a/src/image_writer.cc
+++ b/src/image_writer.cc
@@ -354,10 +354,6 @@
   image_roots->Set(ImageHeader::kJniStubArray, runtime->GetJniDlsymLookupStub());
   image_roots->Set(ImageHeader::kAbstractMethodErrorStubArray,
                    runtime->GetAbstractMethodErrorStubArray());
-  image_roots->Set(ImageHeader::kStaticResolutionStubArray,
-                   runtime->GetResolutionStubArray(Runtime::kStaticMethod));
-  image_roots->Set(ImageHeader::kUnknownMethodResolutionStubArray,
-                   runtime->GetResolutionStubArray(Runtime::kUnknownMethod));
   image_roots->Set(ImageHeader::kResolutionMethod, runtime->GetResolutionMethod());
   image_roots->Set(ImageHeader::kCalleeSaveMethod,
                    runtime->GetCalleeSaveMethod(Runtime::kSaveAll));
@@ -490,31 +486,13 @@
   }
 
   if (orig == Runtime::Current()->GetResolutionMethod()) {
-    // The resolution stub's code points at the unknown resolution trampoline
-    ByteArray* orig_res_stub_array_ =
-        Runtime::Current()->GetResolutionStubArray(Runtime::kUnknownMethod);
-    CHECK(orig->GetCode() == orig_res_stub_array_->GetData());
-    ByteArray* copy_res_stub_array_ = down_cast<ByteArray*>(GetImageAddress(orig_res_stub_array_));
-    copy->SetCode(copy_res_stub_array_->GetData());
+    // The resolution method's code is set to the resolution trampoline when we load the image.
+    copy->SetCode(NULL);
     return;
   }
 
-  // Non-abstract methods typically have code
-  uint32_t code_offset = orig->GetOatCodeOffset();
-  const byte* code = NULL;
-  if (orig->IsStatic()) {
-    // Static methods may point at the resolution trampoline stub
-    ByteArray* orig_res_stub_array_ =
-        Runtime::Current()->GetResolutionStubArray(Runtime::kStaticMethod);
-    if (reinterpret_cast<int8_t*>(code_offset) == orig_res_stub_array_->GetData()) {
-      ByteArray* copy_res_stub_array_ = down_cast<ByteArray*>(GetImageAddress(orig_res_stub_array_));
-      code = reinterpret_cast<const byte*>(copy_res_stub_array_->GetData());
-    }
-  }
-  if (code == NULL) {
-    code = GetOatAddress(code_offset);
-  }
-  copy->SetCode(code);
+  // Non-abstract methods have code
+  copy->SetCode(GetOatAddress(orig->GetOatCodeOffset()));
 
   if (orig->IsNative()) {
     // The native method's pointer is directed to a stub to lookup via dlsym.
diff --git a/src/instrumentation.cc b/src/instrumentation.cc
index a8c2c73..43bab53 100644
--- a/src/instrumentation.cc
+++ b/src/instrumentation.cc
@@ -62,7 +62,7 @@
         if (is_initialized || !method->IsStatic() || method->IsConstructor()) {
           new_code = class_linker->GetOatCodeFor(method);
         } else {
-          new_code = Runtime::Current()->GetResolutionStubArray(Runtime::kStaticMethod)->GetData();
+          new_code = GetResolutionTrampoline();
         }
       } else {  // !uninstall
         if (!interpreter_stubs_installed_ || method->IsNative()) {
@@ -380,7 +380,7 @@
   if (LIKELY(!instrumentation_stubs_installed_)) {
     const void* code = method->GetCode();
     DCHECK(code != NULL);
-    if (LIKELY(code != runtime->GetResolutionStubArray(Runtime::kStaticMethod)->GetData())) {
+    if (LIKELY(code != GetResolutionTrampoline())) {
       return code;
     }
   }
diff --git a/src/mirror/abstract_method-inl.h b/src/mirror/abstract_method-inl.h
index fd02474..a420714 100644
--- a/src/mirror/abstract_method-inl.h
+++ b/src/mirror/abstract_method-inl.h
@@ -20,9 +20,9 @@
 #include "abstract_method.h"
 
 #include "dex_file.h"
-#include "oat/runtime/oat_support_entrypoints.h"
 #include "object_array.h"
 #include "runtime.h"
+#include "runtime_support.h"
 
 namespace art {
 namespace mirror {
@@ -117,8 +117,7 @@
   if (GetCode() == GetInterpreterEntryPoint()) {
     return;
   }
-  Runtime* runtime = Runtime::Current();
-  if (GetCode() == runtime->GetResolutionStubArray(Runtime::kStaticMethod)->GetData()) {
+  if (GetCode() == GetResolutionTrampoline()) {
       return;
   }
   DCHECK(IsWithinCode(pc))
diff --git a/src/oat/runtime/arm/oat_support_entrypoints_arm.cc b/src/oat/runtime/arm/oat_support_entrypoints_arm.cc
index 1276f78..dcf6bb8 100644
--- a/src/oat/runtime/arm/oat_support_entrypoints_arm.cc
+++ b/src/oat/runtime/arm/oat_support_entrypoints_arm.cc
@@ -14,8 +14,8 @@
  * limitations under the License.
  */
 
-#include "runtime_support.h"
 #include "oat/runtime/oat_support_entrypoints.h"
+#include "runtime_support.h"
 
 namespace art {
 
@@ -97,9 +97,6 @@
 extern "C" int32_t art_quick_string_compareto(void*, void*);
 
 // Invoke entrypoints.
-const void* UnresolvedDirectMethodTrampolineFromCode(mirror::AbstractMethod*,
-                                                     mirror::AbstractMethod**, Thread*,
-                                                     Runtime::TrampolineType);
 extern "C" void art_quick_invoke_direct_trampoline_with_access_check(uint32_t, void*);
 extern "C" void art_quick_invoke_interface_trampoline(uint32_t, void*);
 extern "C" void art_quick_invoke_interface_trampoline_with_access_check(uint32_t, void*);
@@ -121,12 +118,6 @@
 extern "C" void art_quick_throw_null_pointer_exception_from_code();
 extern "C" void art_quick_throw_stack_overflow_from_code(void*);
 
-// Instrumentation entrypoints.
-extern "C" void art_quick_instrumentation_entry_from_code(void*);
-extern "C" void art_quick_instrumentation_exit_from_code();
-extern "C" void art_quick_interpreter_entry(void*);
-extern "C" void art_quick_deoptimize();
-
 void InitEntryPoints(EntryPoints* points) {
   // Alloc
   points->pAllocArrayFromCode = art_quick_alloc_array_from_code;
@@ -206,7 +197,6 @@
   points->pMemcpy = memcpy;
 
   // Invocation
-  points->pUnresolvedDirectMethodTrampolineFromCode = UnresolvedDirectMethodTrampolineFromCode;
   points->pInvokeDirectTrampolineWithAccessCheck = art_quick_invoke_direct_trampoline_with_access_check;
   points->pInvokeInterfaceTrampoline = art_quick_invoke_interface_trampoline;
   points->pInvokeInterfaceTrampolineWithAccessCheck = art_quick_invoke_interface_trampoline_with_access_check;
@@ -228,20 +218,4 @@
   points->pThrowStackOverflowFromCode = art_quick_throw_stack_overflow_from_code;
 };
 
-uintptr_t GetInstrumentationExitPc() {
-  return reinterpret_cast<uintptr_t>(art_quick_instrumentation_exit_from_code);
-}
-
-uintptr_t GetDeoptimizationEntryPoint() {
-  return reinterpret_cast<uintptr_t>(art_quick_deoptimize);
-}
-
-void* GetInstrumentationEntryPoint() {
-  return reinterpret_cast<void*>(art_quick_instrumentation_entry_from_code);
-}
-
-void* GetInterpreterEntryPoint() {
-  return reinterpret_cast<void*>(art_quick_interpreter_entry);
-}
-
 }  // namespace art
diff --git a/src/oat/runtime/arm/runtime_support_arm.S b/src/oat/runtime/arm/runtime_support_arm.S
index 0e34d40..2aa380b 100644
--- a/src/oat/runtime/arm/runtime_support_arm.S
+++ b/src/oat/runtime/arm/runtime_support_arm.S
@@ -246,6 +246,47 @@
 INVOKE_TRAMPOLINE art_quick_invoke_super_trampoline_with_access_check, artInvokeSuperTrampolineWithAccessCheck
 INVOKE_TRAMPOLINE art_quick_invoke_virtual_trampoline_with_access_check, artInvokeVirtualTrampolineWithAccessCheck
 
+     /*
+     * Portable resolution trampoline.
+     */
+     .extern artPortableResolutionTrampoline
+ENTRY art_portable_resolution_trampoline
+    push   {r0, r1, r2, r3, lr}           @ spill regs
+    .save  {r0, r1, r2, r3, lr}
+    .pad #20
+    .cfi_adjust_cfa_offset 20
+    sub    sp, #12                        @ pad stack pointer to align frame
+    .pad #12
+    mov    r2, r9                         @ pass Thread::Current
+    mov    r1, sp                         @ pass stack pointer
+    blx    artPortableResolutionTrampoline   @ (method_idx, sp, Thread*)
+    mov    r12, r0                        @ save method code pointer result
+    add    sp, #12                        @ remove padding from stack pointer
+    .cfi_adjust_cfa_offset -12
+    pop    {r0, r1, r2, r3, lr}           @ restore regs
+    .cfi_adjust_cfa_offset -20
+    cmp    r12, #0                        @ is method code null?
+    bxne   r12                            @ if non-null, tail call to method's code
+    bx     lr                             @ otherwise, return to caller to handle exception
+END art_portable_resolution_trampoline
+
+    /*
+     * Quick resolution trampoline.
+     */
+     .extern artQuickResolutionTrampoline
+ENTRY art_quick_resolution_trampoline
+    SETUP_REF_AND_ARGS_CALLEE_SAVE_FRAME  @ save callee saves in case allocation triggers GC
+    mov    r2, r9                         @ pass Thread::Current
+    mov    r1, sp                         @ pass stack pointer
+    blx    artQuickResolutionTrampoline   @ (method_idx, sp, Thread*)
+    mov    r12, r0                        @ save method code pointer result
+    add    sp, #4                         @ set up stack pointer
+    .cfi_adjust_cfa_offset -4
+    pop    {r0-r3, r5-r8, r10-r11, lr}    @ 11 words, r0 will hold method*
+    .cfi_adjust_cfa_offset -44
+    bx     r12                            @ leaf call to method code
+END art_quick_resolution_trampoline
+
     /*
      * Portable invocation stub.
      * On entry:
diff --git a/src/oat/runtime/arm/stub_arm.cc b/src/oat/runtime/arm/stub_arm.cc
index 33354bd..7c97f4c 100644
--- a/src/oat/runtime/arm/stub_arm.cc
+++ b/src/oat/runtime/arm/stub_arm.cc
@@ -28,70 +28,6 @@
 namespace art {
 namespace arm {
 
-mirror::ByteArray* ArmCreateResolutionTrampoline(Runtime::TrampolineType type) {
-  UniquePtr<ArmAssembler> assembler(static_cast<ArmAssembler*>(Assembler::Create(kArm)));
-#if !defined(ART_USE_PORTABLE_COMPILER)
-  // | Out args |
-  // | Method*  | <- SP on entry
-  // | LR       |    return address into caller
-  // | ...      |    callee saves
-  // | R3       |    possible argument
-  // | R2       |    possible argument
-  // | R1       |    possible argument
-  // | R0       |    junk on call to UnresolvedDirectMethodTrampolineFromCode, holds result Method*
-  // | Method*  |    Callee save Method* set up by UnresolvedDirectMethodTrampolineFromCode
-  // Save callee saves and ready frame for exception delivery
-  RegList save = (1 << R1) | (1 << R2) | (1 << R3) | (1 << R5) | (1 << R6) | (1 << R7) | (1 << R8) |
-                 (1 << R10) | (1 << R11) | (1 << LR);
-  // TODO: enable when GetCalleeSaveMethod is available at stub generation time
-  // DCHECK_EQ(save, Runtime::Current()->GetCalleeSaveMethod(Runtime::kRefsAndArgs)->GetCoreSpillMask());
-  __ PushList(save);
-  __ LoadFromOffset(kLoadWord, R12, TR,
-                    ENTRYPOINT_OFFSET(pUnresolvedDirectMethodTrampolineFromCode));
-  __ mov(R2, ShifterOperand(TR));  // Pass Thread::Current() in R2
-  __ LoadImmediate(R3, type);
-  __ IncreaseFrameSize(8);         // 2 words of space for alignment
-  __ mov(R1, ShifterOperand(SP));  // Pass SP
-  // Call to unresolved direct method trampoline (method_idx, sp, Thread*, is_static)
-  __ blx(R12);
-  __ mov(R12, ShifterOperand(R0));  // Save code address returned into R12
-  // Restore registers which may have been modified by GC, "R0" will hold the Method*
-  __ DecreaseFrameSize(4);
-  __ PopList((1 << R0) | save);
-  __ bx(R12);  // Leaf call to method's code
-
-  __ bkpt(0);
-#else // ART_USE_PORTABLE_COMPILER
-  RegList save = (1 << R0) | (1 << R1) | (1 << R2) | (1 << R3) | (1 << LR);
-  __ PushList(save);
-  __ LoadFromOffset(kLoadWord, R12, TR,
-                    ENTRYPOINT_OFFSET(pUnresolvedDirectMethodTrampolineFromCode));
-  __ mov(R2, ShifterOperand(TR));  // Pass Thread::Current() in R2
-  __ LoadImmediate(R3, type);  // Pass is_static
-  __ mov(R1, ShifterOperand(SP));  // Pass sp for Method** callee_addr
-  __ IncreaseFrameSize(12);         // 3 words of space for alignment
-  // Call to unresolved direct method trampoline (callee, callee_addr, Thread*, is_static)
-  __ blx(R12);
-  __ mov(R12, ShifterOperand(R0));  // Save code address returned into R12
-  __ DecreaseFrameSize(12);
-  __ PopList(save);
-  __ cmp(R12, ShifterOperand(0));
-  __ bx(R12, NE);                   // If R12 != 0 tail call method's code
-
-  __ bx(LR);                        // Return to caller to handle exception
-#endif // ART_USE_PORTABLE_COMPILER
-
-  assembler->EmitSlowPaths();
-  size_t cs = assembler->CodeSize();
-  Thread* self = Thread::Current();
-  SirtRef<mirror::ByteArray> resolution_trampoline(self, mirror::ByteArray::Alloc(self, cs));
-  CHECK(resolution_trampoline.get() != NULL);
-  MemoryRegion code(resolution_trampoline->GetData(), resolution_trampoline->GetLength());
-  assembler->FinalizeInstructions(code);
-
-  return resolution_trampoline.get();
-}
-
 typedef void (*ThrowAme)(mirror::AbstractMethod*, Thread*);
 
 mirror::ByteArray* CreateAbstractMethodErrorStub() {
diff --git a/src/oat/runtime/mips/oat_support_entrypoints_mips.cc b/src/oat/runtime/mips/oat_support_entrypoints_mips.cc
index 599b14c..b201b07 100644
--- a/src/oat/runtime/mips/oat_support_entrypoints_mips.cc
+++ b/src/oat/runtime/mips/oat_support_entrypoints_mips.cc
@@ -99,9 +99,6 @@
 extern "C" int32_t art_quick_string_compareto(void*, void*);
 
 // Invoke entrypoints.
-const void* UnresolvedDirectMethodTrampolineFromCode(mirror::AbstractMethod*,
-                                                     mirror::AbstractMethod**, Thread*,
-                                                     Runtime::TrampolineType);
 extern "C" void art_quick_invoke_direct_trampoline_with_access_check(uint32_t, void*);
 extern "C" void art_quick_invoke_interface_trampoline(uint32_t, void*);
 extern "C" void art_quick_invoke_interface_trampoline_with_access_check(uint32_t, void*);
@@ -123,12 +120,6 @@
 extern "C" void art_quick_throw_null_pointer_exception_from_code();
 extern "C" void art_quick_throw_stack_overflow_from_code(void*);
 
-// Instrumentation entrypoints.
-extern "C" void art_quick_instrumentation_entry_from_code(void*);
-extern "C" void art_quick_instrumentation_exit_from_code();
-extern "C" void art_quick_interpreter_entry(void*);
-extern "C" void art_quick_deoptimize();
-
 void InitEntryPoints(EntryPoints* points) {
   // Alloc
   points->pAllocArrayFromCode = art_quick_alloc_array_from_code;
@@ -207,7 +198,6 @@
   points->pMemcpy = memcpy;
 
   // Invocation
-  points->pUnresolvedDirectMethodTrampolineFromCode = UnresolvedDirectMethodTrampolineFromCode;
   points->pInvokeDirectTrampolineWithAccessCheck = art_quick_invoke_direct_trampoline_with_access_check;
   points->pInvokeInterfaceTrampoline = art_quick_invoke_interface_trampoline;
   points->pInvokeInterfaceTrampolineWithAccessCheck = art_quick_invoke_interface_trampoline_with_access_check;
@@ -229,21 +219,4 @@
   points->pThrowStackOverflowFromCode = art_quick_throw_stack_overflow_from_code;
 };
 
-uintptr_t GetInstrumentationExitPc() {
-  return reinterpret_cast<uintptr_t>(art_quick_instrumentation_exit_from_code);
-}
-
-uintptr_t GetDeoptimizationEntryPoint() {
-  UNIMPLEMENTED(FATAL);
-  return reinterpret_cast<uintptr_t>(art_quick_deoptimize);
-}
-
-void* GetInstrumentationEntryPoint() {
-  return reinterpret_cast<void*>(art_quick_instrumentation_entry_from_code);
-}
-
-void* GetInterpreterEntryPoint() {
-  return reinterpret_cast<void*>(art_quick_interpreter_entry);
-}
-
 }  // namespace art
diff --git a/src/oat/runtime/mips/runtime_support_mips.S b/src/oat/runtime/mips/runtime_support_mips.S
index 31b1846..f5f8d9b 100644
--- a/src/oat/runtime/mips/runtime_support_mips.S
+++ b/src/oat/runtime/mips/runtime_support_mips.S
@@ -378,16 +378,16 @@
     SETUP_REF_AND_ARGS_CALLEE_SAVE_FRAME  # save callee saves in case allocation triggers GC
     lw    $a2, 48($sp)                    # pass caller Method*
     move  $t0, $sp                        # save $sp
-    addiu $sp, $sp, -16                   # make space for extra args
-    .cfi_adjust_cfa_offset 16
+    addiu $sp, $sp, -32                   # make space for extra args
+    .cfi_adjust_cfa_offset 32
     move  $a3, rSELF                      # pass Thread::Current
-    sw    $gp, 12($sp)                    # save $gp
+    sw    $gp, 20($sp)                    # save $gp
     .cfi_rel_offset 28, 12
     jal   \cxx_name                       # (method_idx, this, caller, Thread*, $sp)
     sw    $t0, 16($sp)                    # pass $sp
-    lw    $gp, 12($sp)                    # restore $gp
-    addiu $sp, $sp, 16                    # release out args
-    .cfi_adjust_cfa_offset -16
+    lw    $gp, 20($sp)                    # restore $gp
+    addiu $sp, $sp, 32                    # release out args
+    .cfi_adjust_cfa_offset -32
     move  $a0, $v0                        # save target Method*
     move  $t9, $v1                        # save $v0->code_
     RESTORE_REF_AND_ARGS_CALLEE_SAVE_FRAME
@@ -408,6 +408,70 @@
 INVOKE_TRAMPOLINE art_quick_invoke_super_trampoline_with_access_check, artInvokeSuperTrampolineWithAccessCheck
 INVOKE_TRAMPOLINE art_quick_invoke_virtual_trampoline_with_access_check, artInvokeVirtualTrampolineWithAccessCheck
 
+     /*
+     * Portable resolution trampoline.
+     */
+     .extern artPortableResolutionTrampoline
+ENTRY art_portable_resolution_trampoline
+    GENERATE_GLOBAL_POINTER
+    addiu $sp, $sp, -32          # leave room for $a0, $a1, $a2, $a3, and $ra
+    .cfi_adjust_cfa_offset 32
+    sw     $ra, 16($sp)
+    .cfi_rel_offset 31, 16
+    sw     $a3, 12($sp)
+    .cfi_rel_offset 7, 12
+    sw     $a2, 8($sp)
+    .cfi_rel_offset 6, 8
+    sw     $a1, 4($sp)
+    .cfi_rel_offset 5, 4
+    sw     $a0, 0($sp)
+    .cfi_rel_offset 4, 0
+    move  $a2, $s1              # pass Thread::Current()
+    jal   artPortableResolutionTrampoline  # (method_idx, sp, Thread*)
+    move  $a1, $sp              # pass stack pointer
+    lw    $a0, 0($sp)           # restore registers from stack
+    lw    $a1, 4($sp)
+    lw    $a2, 8($sp)
+    lw    $a3, 12($sp)
+    lw    $ra, 16($sp)
+    beq   $v0, $zero, resolve_fail
+    addiu $sp, $sp, 32          # restore the stack
+    .cfi_adjust_cfa_offset -32
+    jr    $t9                   # leaf call to method's code
+    move  $t9, $v0              # put method code result in $t9
+resolve_fail:
+    jr    $ra
+    nop
+END art_portable_resolution_trampoline
+
+     /*
+     * Quick resolution trampoline.
+     */
+     .extern artQuickResolutionTrampoline
+ENTRY art_quick_resolution_trampoline
+    GENERATE_GLOBAL_POINTER
+    SETUP_REF_AND_ARGS_CALLEE_SAVE_FRAME
+    move  $a2, $s1              # pass Thread::Current()
+    jal   artQuickResolutionTrampoline  # (method_idx, sp, Thread*)
+    move  $a1, $sp              # pass stack pointer
+    move  $t9, $v0              # put method code result in $t9
+    lw    $a0, 0($sp)           # restore registers from stack
+    lw    $a1, 4($sp)
+    lw    $a2, 8($sp)
+    lw    $a3, 12($sp)
+    lw    $s2, 16($sp)
+    lw    $s3, 20($sp)
+    lw    $s4, 24($sp)
+    lw    $s5, 28($sp)
+    lw    $s6, 32($sp)
+    lw    $s7, 36($sp)
+    lw    $fp, 40($sp)
+    lw    $ra, 44($sp)
+    jr    $t9                   # leaf call to method's code
+    addiu $sp, $sp, 48          # restore the stack
+    .cfi_adjust_cfa_offset -48
+END art_quick_resolution_trampoline
+
     /*
      * Common invocation stub for portable and quick.
      * On entry:
diff --git a/src/oat/runtime/mips/stub_mips.cc b/src/oat/runtime/mips/stub_mips.cc
index 60ec9de..a1adf66 100644
--- a/src/oat/runtime/mips/stub_mips.cc
+++ b/src/oat/runtime/mips/stub_mips.cc
@@ -28,100 +28,6 @@
 namespace art {
 namespace mips {
 
-mirror::ByteArray* MipsCreateResolutionTrampoline(Runtime::TrampolineType type) {
-  UniquePtr<MipsAssembler> assembler(static_cast<MipsAssembler*>(Assembler::Create(kMips)));
-#if !defined(ART_USE_PORTABLE_COMPILER)
-  // | Out args   |
-  // | Method*    | <- SP on entry
-  // | RA         |    return address into caller
-  // | ...        |    callee saves
-  // | A3         |    possible argument
-  // | A2         |    possible argument
-  // | A1         |    possible argument
-  // | A0/Method* |    Callee save Method* set up by UnresolvedDirectMethodTrampolineFromCode
-  // Save callee saves and ready frame for exception delivery
-  __ AddConstant(SP, SP, -48);
-  __ StoreToOffset(kStoreWord, RA, SP, 44);
-  __ StoreToOffset(kStoreWord, FP, SP, 40);
-  __ StoreToOffset(kStoreWord, S7, SP, 36);
-  __ StoreToOffset(kStoreWord, S6, SP, 32);
-  __ StoreToOffset(kStoreWord, S5, SP, 28);
-  __ StoreToOffset(kStoreWord, S4, SP, 24);
-  __ StoreToOffset(kStoreWord, S3, SP, 20);
-  __ StoreToOffset(kStoreWord, S2, SP, 16);
-  __ StoreToOffset(kStoreWord, A3, SP, 12);
-  __ StoreToOffset(kStoreWord, A2, SP, 8);
-  __ StoreToOffset(kStoreWord, A1, SP, 4);
-
-  __ LoadFromOffset(kLoadWord, T9, S1,
-                    ENTRYPOINT_OFFSET(pUnresolvedDirectMethodTrampolineFromCode));
-  __ Move(A2, S1);  // Pass Thread::Current() in A2
-  __ LoadImmediate(A3, type); // Pass is_static
-  __ Move(A1, SP);  // Pass SP for Method** callee_addr
-  __ Jalr(T9); // Call to unresolved direct method trampoline (method_idx, sp, Thread*, is_static)
-
-  // Restore registers which may have been modified by GC
-  __ LoadFromOffset(kLoadWord, A0, SP, 0);
-  __ LoadFromOffset(kLoadWord, A1, SP, 4);
-  __ LoadFromOffset(kLoadWord, A2, SP, 8);
-  __ LoadFromOffset(kLoadWord, A3, SP, 12);
-  __ LoadFromOffset(kLoadWord, S2, SP, 16);
-  __ LoadFromOffset(kLoadWord, S3, SP, 20);
-  __ LoadFromOffset(kLoadWord, S4, SP, 24);
-  __ LoadFromOffset(kLoadWord, S5, SP, 28);
-  __ LoadFromOffset(kLoadWord, S6, SP, 32);
-  __ LoadFromOffset(kLoadWord, S7, SP, 36);
-  __ LoadFromOffset(kLoadWord, FP, SP, 40);
-  __ LoadFromOffset(kLoadWord, RA, SP, 44);
-  __ AddConstant(SP, SP, 48);
-
-  __ Move(T9, V0); // Put method's code in T9
-  __ Jr(T9);  // Leaf call to method's code
-
-  __ Break();
-#else // ART_USE_PORTABLE_COMPILER
-  // Build frame and save argument registers and RA.
-  __ AddConstant(SP, SP, -32);
-  __ StoreToOffset(kStoreWord, RA, SP, 28);
-  __ StoreToOffset(kStoreWord, A3, SP, 24);
-  __ StoreToOffset(kStoreWord, A2, SP, 20);
-  __ StoreToOffset(kStoreWord, A1, SP, 16);
-  __ StoreToOffset(kStoreWord, A0, SP, 12);
-
-  __ LoadFromOffset(kLoadWord, T9, S1,
-                    ENTRYPOINT_OFFSET(pUnresolvedDirectMethodTrampolineFromCode));
-  __ Move(A2, S1);  // Pass Thread::Current() in A2
-  __ LoadImmediate(A3, type);  // Pass is_static
-  __ Move(A1, SP);  // Pass SP for Method** callee_addr
-  __ Jalr(T9); // Call to unresolved direct method trampoline (callee, callee_addr, Thread*, is_static)
-
-  // Restore frame, argument registers, and RA.
-  __ LoadFromOffset(kLoadWord, A0, SP, 12);
-  __ LoadFromOffset(kLoadWord, A1, SP, 16);
-  __ LoadFromOffset(kLoadWord, A2, SP, 20);
-  __ LoadFromOffset(kLoadWord, A3, SP, 24);
-  __ LoadFromOffset(kLoadWord, RA, SP, 28);
-  __ AddConstant(SP, SP, 32);
-
-  Label resolve_fail;
-  __ EmitBranch(V0, ZERO, &resolve_fail, true);
-  __ Jr(V0); // If V0 != 0 tail call method's code
-  __ Bind(&resolve_fail, false);
-  __ Jr(RA); // Return to caller to handle exception
-#endif // ART_USE_PORTABLE_COMPILER
-
-  assembler->EmitSlowPaths();
-
-  size_t cs = assembler->CodeSize();
-  Thread* self = Thread::Current();
-  SirtRef<mirror::ByteArray> resolution_trampoline(self, mirror::ByteArray::Alloc(self, cs));
-  CHECK(resolution_trampoline.get() != NULL);
-  MemoryRegion code(resolution_trampoline->GetData(), resolution_trampoline->GetLength());
-  assembler->FinalizeInstructions(code);
-
-  return resolution_trampoline.get();
-}
-
 typedef void (*ThrowAme)(mirror::AbstractMethod*, Thread*);
 
 mirror::ByteArray* CreateAbstractMethodErrorStub() {
diff --git a/src/oat/runtime/oat_support_entrypoints.h b/src/oat/runtime/oat_support_entrypoints.h
index 9cd9cc7..5be1e49 100644
--- a/src/oat/runtime/oat_support_entrypoints.h
+++ b/src/oat/runtime/oat_support_entrypoints.h
@@ -112,9 +112,6 @@
   void* (*pMemcpy)(void*, const void*, size_t);
 
   // Invocation
-  const void* (*pUnresolvedDirectMethodTrampolineFromCode)(mirror::AbstractMethod*,
-                                                           mirror::AbstractMethod**, Thread*,
-                                                           Runtime::TrampolineType);
   void (*pInvokeDirectTrampolineWithAccessCheck)(uint32_t, void*);
   void (*pInvokeInterfaceTrampoline)(uint32_t, void*);
   void (*pInvokeInterfaceTrampolineWithAccessCheck)(uint32_t, void*);
@@ -163,18 +160,6 @@
 // Change the debugger entry point in the data structure.
 void ChangeDebuggerEntryPoint(EntryPoints* points, bool enabled);
 
-// The return_pc of instrumentation exit stub.
-uintptr_t GetInstrumentationExitPc();
-
-// Entry point for deoptimization.
-uintptr_t GetDeoptimizationEntryPoint();
-
-// Return address of instrumentation stub.
-void* GetInstrumentationEntryPoint();
-
-// Return address of interpreter stub.
-void* GetInterpreterEntryPoint();
-
 }  // namespace art
 
 #endif  // ART_SRC_OAT_RUNTIME_OAT_SUPPORT_ENTRYPOINTS_H_
diff --git a/src/oat/runtime/stub.h b/src/oat/runtime/stub.h
index 2679793..ee39273 100644
--- a/src/oat/runtime/stub.h
+++ b/src/oat/runtime/stub.h
@@ -28,8 +28,6 @@
 namespace arm {
   mirror::ByteArray* CreateAbstractMethodErrorStub()
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
-  mirror::ByteArray* ArmCreateResolutionTrampoline(Runtime::TrampolineType type)
-      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
   mirror::ByteArray* CreateJniDlsymLookupStub()
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 }
@@ -37,8 +35,6 @@
 namespace mips {
   mirror::ByteArray* CreateAbstractMethodErrorStub()
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
-  mirror::ByteArray* MipsCreateResolutionTrampoline(Runtime::TrampolineType type)
-      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
   mirror::ByteArray* CreateJniDlsymLookupStub()
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 }
@@ -46,8 +42,6 @@
 namespace x86 {
   mirror::ByteArray* CreateAbstractMethodErrorStub()
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
-  mirror::ByteArray* X86CreateResolutionTrampoline(Runtime::TrampolineType type)
-      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
   mirror::ByteArray* CreateJniDlsymLookupStub()
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 }
diff --git a/src/oat/runtime/support_stubs.cc b/src/oat/runtime/support_stubs.cc
index 56fc07f..230421a 100644
--- a/src/oat/runtime/support_stubs.cc
+++ b/src/oat/runtime/support_stubs.cc
@@ -35,11 +35,94 @@
 
 namespace art {
 
-#if !defined(ART_USE_PORTABLE_COMPILER)
-// Lazily resolve a method. Called by stub code.
-const void* UnresolvedDirectMethodTrampolineFromCode(mirror::AbstractMethod* called,
-                                                     mirror::AbstractMethod** sp, Thread* thread,
-                                                     Runtime::TrampolineType type)
+// Lazily resolve a method for portable. Called by stub code.
+extern "C" const void* artPortableResolutionTrampoline(mirror::AbstractMethod* called,
+                                                       mirror::AbstractMethod** called_addr,
+                                                       Thread* thread)
+    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+  uint32_t dex_pc;
+  mirror::AbstractMethod* caller = thread->GetCurrentMethod(&dex_pc);
+
+  ClassLinker* linker = Runtime::Current()->GetClassLinker();
+  InvokeType invoke_type;
+  uint32_t dex_method_idx;
+  DCHECK(called->IsRuntimeMethod());
+  const DexFile::CodeItem* code_item = MethodHelper(caller).GetCodeItem();
+  CHECK_LT(dex_pc, code_item->insns_size_in_code_units_);
+  const Instruction* instr = Instruction::At(&code_item->insns_[dex_pc]);
+  Instruction::Code instr_code = instr->Opcode();
+  switch (instr_code) {
+    case Instruction::INVOKE_DIRECT:  // Fall-through.
+    case Instruction::INVOKE_DIRECT_RANGE:
+      invoke_type = kDirect;
+      break;
+    case Instruction::INVOKE_STATIC:  // Fall-through.
+    case Instruction::INVOKE_STATIC_RANGE:
+      invoke_type = kStatic;
+      break;
+    case Instruction::INVOKE_SUPER:  // Fall-through.
+    case Instruction::INVOKE_SUPER_RANGE:
+      invoke_type = kSuper;
+      break;
+    case Instruction::INVOKE_VIRTUAL:  // Fall-through.
+    case Instruction::INVOKE_VIRTUAL_RANGE:
+      invoke_type = kVirtual;
+      break;
+    default:
+      LOG(FATAL) << "Unexpected call into trampoline: " << instr->DumpString(NULL);
+      invoke_type = kDirect;  // Avoid used uninitialized warnings.
+  }
+  DecodedInstruction dec_insn(instr);
+  dex_method_idx = dec_insn.vB;
+  called = linker->ResolveMethod(dex_method_idx, caller, invoke_type);
+  const void* code = NULL;
+  if (LIKELY(!thread->IsExceptionPending())) {
+    // Incompatible class change should have been handled in resolve method.
+    CHECK(!called->CheckIncompatibleClassChange(invoke_type));
+    // Ensure that the called method's class is initialized.
+    mirror::Class* called_class = called->GetDeclaringClass();
+    linker->EnsureInitialized(called_class, true, true);
+    if (LIKELY(called_class->IsInitialized())) {
+      code = called->GetCode();
+      // TODO: remove this after we solve the link issue.
+      { // for lazy link.
+        if (code == NULL) {
+          code = linker->GetOatCodeFor(called);
+        }
+      }
+    } else if (called_class->IsInitializing()) {
+      if (invoke_type == kStatic) {
+        // Class is still initializing, go to oat and grab code (trampoline must be left in place
+        // until class is initialized to stop races between threads).
+        code = linker->GetOatCodeFor(called);
+      } else {
+        // No trampoline for non-static methods.
+        code = called->GetCode();
+        // TODO: remove this after we solve the link issue.
+        { // for lazy link.
+          if (code == NULL) {
+            code = linker->GetOatCodeFor(called);
+          }
+        }
+      }
+    } else {
+      DCHECK(called_class->IsErroneous());
+    }
+  }
+  if (LIKELY(code != NULL)) {
+    // Expect class to at least be initializing.
+    DCHECK(called->GetDeclaringClass()->IsInitializing());
+    // Don't want infinite recursion.
+    DCHECK(code != GetResolutionTrampoline());
+    // Set up entry into main method
+    *called_addr = called;
+  }
+  return code;
+}
+
+// Lazily resolve a method for quick. Called by stub code.
+extern "C" const void* artQuickResolutionTrampoline(mirror::AbstractMethod* called,
+                                                    mirror::AbstractMethod** sp, Thread* thread)
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
 #if defined(__arm__)
   // On entry the stack pointed by sp is:
@@ -122,8 +205,7 @@
   const char* shorty;
   uint32_t shorty_len;
 #endif
-  if (type == Runtime::kUnknownMethod) {
-    DCHECK(called->IsRuntimeMethod());
+  if (called->IsRuntimeMethod()) {
     uint32_t dex_pc = caller->ToDexPc(caller_pc);
     const DexFile::CodeItem* code = MethodHelper(caller).GetCodeItem();
     CHECK_LT(dex_pc, code->insns_size_in_code_units_);
@@ -156,8 +238,7 @@
     shorty = linker->MethodShorty(dex_method_idx, caller, &shorty_len);
 #endif
   } else {
-    DCHECK(!called->IsRuntimeMethod());
-    invoke_type = (type == Runtime::kStaticMethod) ? kStatic : kDirect;
+    invoke_type = kStatic;
     dex_method_idx = called->GetDexMethodIndex();
 #if !defined(__i386__)
     MethodHelper mh(called);
@@ -212,7 +293,7 @@
   }
 #endif
   // Resolve method filling in dex cache
-  if (type == Runtime::kUnknownMethod) {
+  if (called->IsRuntimeMethod()) {
     called = linker->ResolveMethod(dex_method_idx, caller, invoke_type);
   }
   const void* code = NULL;
@@ -248,105 +329,12 @@
     // Expect class to at least be initializing.
     DCHECK(called->GetDeclaringClass()->IsInitializing());
     // Don't want infinite recursion.
-    DCHECK(code != Runtime::Current()->GetResolutionStubArray(Runtime::kUnknownMethod)->GetData());
+    DCHECK(code != GetResolutionTrampoline());
     // Set up entry into main method
     regs[0] = reinterpret_cast<uintptr_t>(called);
   }
   return code;
 }
-#else // ART_USE_PORTABLE_COMPILER
-const void* UnresolvedDirectMethodTrampolineFromCode(mirror::AbstractMethod* called,
-                                                     mirror::AbstractMethod** called_addr,
-                                                     Thread* thread, Runtime::TrampolineType type)
-    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
-  uint32_t dex_pc;
-  mirror::AbstractMethod* caller = thread->GetCurrentMethod(&dex_pc);
-
-  ClassLinker* linker = Runtime::Current()->GetClassLinker();
-  InvokeType invoke_type;
-  uint32_t dex_method_idx;
-  if (type == Runtime::kUnknownMethod) {
-    DCHECK(called->IsRuntimeMethod());
-    const DexFile::CodeItem* code = MethodHelper(caller).GetCodeItem();
-    CHECK_LT(dex_pc, code->insns_size_in_code_units_);
-    const Instruction* instr = Instruction::At(&code->insns_[dex_pc]);
-    Instruction::Code instr_code = instr->Opcode();
-    switch (instr_code) {
-      case Instruction::INVOKE_DIRECT:  // Fall-through.
-      case Instruction::INVOKE_DIRECT_RANGE:
-        invoke_type = kDirect;
-        break;
-      case Instruction::INVOKE_STATIC:  // Fall-through.
-      case Instruction::INVOKE_STATIC_RANGE:
-        invoke_type = kStatic;
-        break;
-      case Instruction::INVOKE_SUPER:  // Fall-through.
-      case Instruction::INVOKE_SUPER_RANGE:
-        invoke_type = kSuper;
-        break;
-      case Instruction::INVOKE_VIRTUAL:  // Fall-through.
-      case Instruction::INVOKE_VIRTUAL_RANGE:
-        invoke_type = kVirtual;
-        break;
-      default:
-        LOG(FATAL) << "Unexpected call into trampoline: " << instr->DumpString(NULL);
-        invoke_type = kDirect;  // Avoid used uninitialized warnings.
-    }
-    DecodedInstruction dec_insn(instr);
-    dex_method_idx = dec_insn.vB;
-  } else {
-    DCHECK(!called->IsRuntimeMethod());
-    invoke_type = (type == Runtime::kStaticMethod) ? kStatic : kDirect;
-    dex_method_idx = called->GetDexMethodIndex();
-  }
-  if (type == Runtime::kUnknownMethod) {
-    called = linker->ResolveMethod(dex_method_idx, caller, invoke_type);
-  }
-  const void* code = NULL;
-  if (LIKELY(!thread->IsExceptionPending())) {
-    // Incompatible class change should have been handled in resolve method.
-    CHECK(!called->CheckIncompatibleClassChange(invoke_type));
-    // Ensure that the called method's class is initialized.
-    mirror::Class* called_class = called->GetDeclaringClass();
-    linker->EnsureInitialized(called_class, true, true);
-    if (LIKELY(called_class->IsInitialized())) {
-      code = called->GetCode();
-      // TODO: remove this after we solve the link issue.
-      { // for lazy link.
-        if (code == NULL) {
-          code = linker->GetOatCodeFor(called);
-        }
-      }
-    } else if (called_class->IsInitializing()) {
-      if (invoke_type == kStatic) {
-        // Class is still initializing, go to oat and grab code (trampoline must be left in place
-        // until class is initialized to stop races between threads).
-        code = linker->GetOatCodeFor(called);
-      } else {
-        // No trampoline for non-static methods.
-        code = called->GetCode();
-        // TODO: remove this after we solve the link issue.
-        { // for lazy link.
-          if (code == NULL) {
-            code = linker->GetOatCodeFor(called);
-          }
-        }
-      }
-    } else {
-      DCHECK(called_class->IsErroneous());
-    }
-  }
-  if (LIKELY(code != NULL)) {
-    // Expect class to at least be initializing.
-    DCHECK(called->GetDeclaringClass()->IsInitializing());
-    // Don't want infinite recursion.
-    DCHECK(code != Runtime::Current()->GetResolutionStubArray(Runtime::kUnknownMethod)->GetData());
-    // Set up entry into main method
-    *called_addr = called;
-  }
-  return code;
-}
-#endif // ART_USE_PORTABLE_COMPILER
 
 // Called by the AbstractMethodError. Called by stub code.
 extern void ThrowAbstractMethodErrorFromCode(mirror::AbstractMethod* method, Thread* self,
diff --git a/src/oat/runtime/x86/oat_support_entrypoints_x86.cc b/src/oat/runtime/x86/oat_support_entrypoints_x86.cc
index 708e04e..2e35d78 100644
--- a/src/oat/runtime/x86/oat_support_entrypoints_x86.cc
+++ b/src/oat/runtime/x86/oat_support_entrypoints_x86.cc
@@ -82,9 +82,6 @@
 extern "C" void* art_quick_memcpy(void*, const void*, size_t);
 
 // Invoke entrypoints.
-const void* UnresolvedDirectMethodTrampolineFromCode(mirror::AbstractMethod*,
-                                                     mirror::AbstractMethod**, Thread*,
-                                                     Runtime::TrampolineType);
 extern "C" void art_quick_invoke_direct_trampoline_with_access_check(uint32_t, void*);
 extern "C" void art_quick_invoke_interface_trampoline(uint32_t, void*);
 extern "C" void art_quick_invoke_interface_trampoline_with_access_check(uint32_t, void*);
@@ -106,12 +103,6 @@
 extern "C" void art_quick_throw_null_pointer_exception_from_code();
 extern "C" void art_quick_throw_stack_overflow_from_code(void*);
 
-// Instrumentation entrypoints.
-extern "C" void art_quick_instrumentation_entry_from_code(void*);
-extern "C" void art_quick_instrumentation_exit_from_code();
-extern "C" void art_quick_interpreter_entry(void*);
-extern "C" void art_quick_deoptimize();
-
 void InitEntryPoints(EntryPoints* points) {
   // Alloc
   points->pAllocArrayFromCode = art_quick_alloc_array_from_code;
@@ -190,7 +181,6 @@
   points->pMemcpy = art_quick_memcpy;
 
   // Invocation
-  points->pUnresolvedDirectMethodTrampolineFromCode = UnresolvedDirectMethodTrampolineFromCode;
   points->pInvokeDirectTrampolineWithAccessCheck = art_quick_invoke_direct_trampoline_with_access_check;
   points->pInvokeInterfaceTrampoline = art_quick_invoke_interface_trampoline;
   points->pInvokeInterfaceTrampolineWithAccessCheck = art_quick_invoke_interface_trampoline_with_access_check;
@@ -212,20 +202,4 @@
   points->pThrowStackOverflowFromCode = art_quick_throw_stack_overflow_from_code;
 };
 
-uintptr_t GetInstrumentationExitPc() {
-  return reinterpret_cast<uintptr_t>(art_quick_instrumentation_exit_from_code);
-}
-
-uintptr_t GetDeoptimizationEntryPoint() {
-  return reinterpret_cast<uintptr_t>(art_quick_deoptimize);
-}
-
-void* GetInstrumentationEntryPoint() {
-  return reinterpret_cast<void*>(art_quick_instrumentation_entry_from_code);
-}
-
-void* GetInterpreterEntryPoint() {
-  return reinterpret_cast<void*>(art_quick_interpreter_entry);
-}
-
 }  // namespace art
diff --git a/src/oat/runtime/x86/runtime_support_x86.S b/src/oat/runtime/x86/runtime_support_x86.S
index 3ca42d1..22330c9 100644
--- a/src/oat/runtime/x86/runtime_support_x86.S
+++ b/src/oat/runtime/x86/runtime_support_x86.S
@@ -301,6 +301,50 @@
 INVOKE_TRAMPOLINE art_quick_invoke_super_trampoline_with_access_check, artInvokeSuperTrampolineWithAccessCheck
 INVOKE_TRAMPOLINE art_quick_invoke_virtual_trampoline_with_access_check, artInvokeVirtualTrampolineWithAccessCheck
 
+     /*
+     * Portable resolution trampoline.
+     */
+DEFINE_FUNCTION art_portable_resolution_trampoline
+    PUSH ebp                      // stash %ebp
+    movl %esp, %ebp               // save %esp
+    subl LITERAL(8), %esp         // align stack
+    movl 8(%ebp), %eax            // load the called method* into %eax
+    leal 8(%ebp), %edx            // put the called method* address in %edx
+    pushl %fs:THREAD_SELF_OFFSET  // pass Thread::Current()
+    PUSH edx                      // pass called method* address
+    PUSH eax                      // pass method*
+    call SYMBOL(artPortableResolutionTrampoline)  // (method_idx, sp, Thread*)
+    leave                         // restore the stack
+    cmpl LITERAL(0), %eax         // check if returned method code is null
+    je resolve_fail               // if null, jump to return to handle
+    jmp *%eax                     // otherwise, tail call to intended method
+resolve_fail:
+    ret
+END_FUNCTION art_portable_resolution_trampoline
+
+    /*
+     * Quick resolution trampoline.
+     */
+DEFINE_FUNCTION art_quick_resolution_trampoline
+    SETUP_REF_AND_ARGS_CALLEE_SAVE_FRAME
+    movl %esp, %ecx               // save stack pointer
+    PUSH eax                      // align stack
+    pushl %fs:THREAD_SELF_OFFSET  // pass Thread::Current()
+    PUSH ecx                      // pass stack pointer
+    PUSH eax                      // pass method*
+    call SYMBOL(artQuickResolutionTrampoline)  // (method_idx, sp, Thread*)
+    movl %eax, %edi               // save returned code pointer in %edi
+    addl LITERAL(16), %esp        // pop arguments
+    POP eax                       // restore registers
+    POP ecx
+    POP edx
+    POP ebx
+    POP ebp
+    POP esi
+    xchgl %edi, (%esp)            // swap %edi and code pointer
+    ret                           // tail call to intended method
+END_FUNCTION art_quick_resolution_trampoline
+
     /*
      * Portable invocation stub.
      * On entry:
diff --git a/src/oat/runtime/x86/stub_x86.cc b/src/oat/runtime/x86/stub_x86.cc
index 14c9ce4..3f85b28 100644
--- a/src/oat/runtime/x86/stub_x86.cc
+++ b/src/oat/runtime/x86/stub_x86.cc
@@ -28,80 +28,6 @@
 namespace art {
 namespace x86 {
 
-mirror::ByteArray* X86CreateResolutionTrampoline(Runtime::TrampolineType type) {
-  UniquePtr<X86Assembler> assembler(static_cast<X86Assembler*>(Assembler::Create(kX86)));
-
-#if !defined(ART_USE_PORTABLE_COMPILER)
-  // Set up the callee save frame to conform with Runtime::CreateCalleeSaveMethod(kRefsAndArgs)
-  // return address
-  __ pushl(EDI);
-  __ pushl(ESI);
-  __ pushl(EBP);
-  __ pushl(EBX);
-  __ pushl(EDX);
-  __ pushl(ECX);
-  __ pushl(EAX);  // <-- callee save Method* to go here
-  __ movl(ECX, ESP);          // save ESP
-  __ pushl(Immediate(type));  // pass is_static
-  __ fs()->pushl(Address::Absolute(Thread::SelfOffset()));  // Thread*
-  __ pushl(ECX);              // pass ESP for Method*
-  __ pushl(EAX);              // pass Method*
-
-  // Call to resolve method.
-  __ Call(ThreadOffset(ENTRYPOINT_OFFSET(pUnresolvedDirectMethodTrampolineFromCode)),
-          X86ManagedRegister::FromCpuRegister(ECX));
-
-  __ movl(EDI, EAX);  // save code pointer in EDI
-  __ addl(ESP, Immediate(16));  // Pop arguments
-  __ popl(EAX);  // Restore args.
-  __ popl(ECX);
-  __ popl(EDX);
-  __ popl(EBX);
-  __ popl(EBP);  // Restore callee saves.
-  __ popl(ESI);
-  // Swap EDI callee save with code pointer
-  __ xchgl(EDI, Address(ESP, 0));
-  // Tail call to intended method.
-  __ ret();
-#else // ART_USE_PORTABLE_COMPILER
-  __ pushl(EBP);
-  __ movl(EBP, ESP);          // save ESP
-  __ subl(ESP, Immediate(8));  // Align stack
-  __ movl(EAX, Address(EBP, 8));  // Method* called
-  __ leal(EDX, Address(EBP, 8));  // Method** called_addr
-  __ pushl(Immediate(type));  // pass is_static
-  __ fs()->pushl(Address::Absolute(Thread::SelfOffset()));  // pass thread
-  __ pushl(EDX);  // pass called_addr
-  __ pushl(EAX);  // pass called
-
-  // Call to resolve method.
-  __ Call(ThreadOffset(ENTRYPOINT_OFFSET(pUnresolvedDirectMethodTrampolineFromCode)),
-          X86ManagedRegister::FromCpuRegister(ECX));
-
-  __ leave();
-
-  Label resolve_fail;  // forward declaration
-  __ cmpl(EAX, Immediate(0));
-  __ j(kEqual, &resolve_fail);
-
-  __ jmp(EAX);
-  // Tail call to intended method.
-
-  __ Bind(&resolve_fail);
-  __ ret();
-#endif // ART_USE_PORTABLE_COMPILER
-
-  assembler->EmitSlowPaths();
-  size_t cs = assembler->CodeSize();
-  Thread* self = Thread::Current();
-  SirtRef<mirror::ByteArray> resolution_trampoline(self, mirror::ByteArray::Alloc(self, cs));
-  CHECK(resolution_trampoline.get() != NULL);
-  MemoryRegion code(resolution_trampoline->GetData(), resolution_trampoline->GetLength());
-  assembler->FinalizeInstructions(code);
-
-  return resolution_trampoline.get();
-}
-
 typedef void (*ThrowAme)(mirror::AbstractMethod*, Thread*);
 
 mirror::ByteArray* CreateAbstractMethodErrorStub() {
diff --git a/src/oat_writer.cc b/src/oat_writer.cc
index e586f98..e529654 100644
--- a/src/oat_writer.cc
+++ b/src/oat_writer.cc
@@ -369,7 +369,7 @@
         method->GetDeclaringClass()->IsInitialized()) {
       method->SetOatCodeOffset(code_offset);
     } else {
-      method->SetCode(Runtime::Current()->GetResolutionStubArray(Runtime::kStaticMethod)->GetData());
+      method->SetCode(NULL);
     }
     method->SetOatVmapTableOffset(vmap_table_offset);
     method->SetOatNativeGcMapOffset(gc_map_offset);
diff --git a/src/oatdump.cc b/src/oatdump.cc
index 37a995d..62af7a9 100644
--- a/src/oatdump.cc
+++ b/src/oatdump.cc
@@ -84,8 +84,6 @@
 const char* image_roots_descriptions_[] = {
   "kJniStubArray",
   "kAbstractMethodErrorStubArray",
-  "kStaticResolutionStubArray",
-  "kUnknownMethodResolutionStubArray",
   "kResolutionMethod",
   "kCalleeSaveMethod",
   "kRefsOnlySaveMethod",
@@ -883,9 +881,8 @@
 
   const void* GetOatCodeBegin(mirror::AbstractMethod* m)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
-    Runtime* runtime = Runtime::Current();
     const void* code = m->GetCode();
-    if (code == runtime->GetResolutionStubArray(Runtime::kStaticMethod)->GetData()) {
+    if (code == GetResolutionTrampoline()) {
       code = oat_dumper_->GetOatCode(m);
     }
     if (oat_dumper_->GetInstructionSet() == kThumb2) {
@@ -999,7 +996,7 @@
           indent_os << StringPrintf("OAT CODE: %p\n", oat_code);
         }
       } else if (method->IsAbstract() || method->IsCalleeSaveMethod() ||
-          method->IsResolutionMethod()) {
+          method->IsResolutionMethod() || MethodHelper(method).IsClassInitializer()) {
         DCHECK(method->GetNativeGcMap() == NULL) << PrettyMethod(method);
         DCHECK(method->GetMappingTable() == NULL) << PrettyMethod(method);
       } else {
diff --git a/src/runtime.cc b/src/runtime.cc
index 9661f50..b336156 100644
--- a/src/runtime.cc
+++ b/src/runtime.cc
@@ -102,9 +102,6 @@
       use_compile_time_class_path_(false),
       main_thread_group_(NULL),
       system_thread_group_(NULL) {
-  for (int i = 0; i < Runtime::kLastTrampolineMethodType; i++) {
-    resolution_stub_array_[i] = NULL;
-  }
   for (int i = 0; i < Runtime::kLastCalleeSaveType; i++) {
     callee_save_methods_[i] = NULL;
   }
@@ -1070,9 +1067,6 @@
   }
   visitor(jni_stub_array_, arg);
   visitor(abstract_method_error_stub_array_, arg);
-  for (int i = 0; i < Runtime::kLastTrampolineMethodType; i++) {
-    visitor(resolution_stub_array_[i], arg);
-  }
   visitor(resolution_method_, arg);
   for (int i = 0; i < Runtime::kLastCalleeSaveType; i++) {
     visitor(callee_save_methods_[i], arg);
@@ -1109,12 +1103,6 @@
   abstract_method_error_stub_array_ = abstract_method_error_stub_array;
 }
 
-void Runtime::SetResolutionStubArray(mirror::ByteArray* resolution_stub_array, TrampolineType type) {
-  CHECK(resolution_stub_array != NULL);
-  CHECK(!HasResolutionStubArray(type) || resolution_stub_array_[type] == resolution_stub_array);
-  resolution_stub_array_[type] = resolution_stub_array;
-}
-
 mirror::AbstractMethod* Runtime::CreateResolutionMethod() {
   mirror::Class* method_class = mirror::AbstractMethod::GetMethodClass();
   Thread* self = Thread::Current();
@@ -1123,9 +1111,8 @@
   method->SetDeclaringClass(method_class);
   // TODO: use a special method for resolution method saves
   method->SetDexMethodIndex(DexFile::kDexNoIndex16);
-  mirror::ByteArray* unknown_resolution_stub = GetResolutionStubArray(kUnknownMethod);
-  CHECK(unknown_resolution_stub != NULL);
-  method->SetCode(unknown_resolution_stub->GetData());
+  // When compiling, the code pointer will get set later when the image is loaded.
+  method->SetCode(Runtime::Current()->IsCompiler() ? NULL : GetResolutionTrampoline());
   return method.get();
 }
 
diff --git a/src/runtime.h b/src/runtime.h
index 67c8e36..93cffbe 100644
--- a/src/runtime.h
+++ b/src/runtime.h
@@ -264,24 +264,6 @@
 
   void SetAbstractMethodErrorStubArray(mirror::ByteArray* abstract_method_error_stub_array);
 
-  enum TrampolineType {
-    kStaticMethod,
-    kUnknownMethod,
-    kLastTrampolineMethodType  // Value used for iteration
-  };
-
-  bool HasResolutionStubArray(TrampolineType type) const {
-    return resolution_stub_array_[type] != NULL;
-  }
-
-  mirror::ByteArray* GetResolutionStubArray(TrampolineType type) const {
-    CHECK(HasResolutionStubArray(type));
-    DCHECK_LT(static_cast<int>(type), static_cast<int>(kLastTrampolineMethodType));
-    return resolution_stub_array_[type];
-  }
-
-  void SetResolutionStubArray(mirror::ByteArray* resolution_stub_array, TrampolineType type);
-
   // Returns a special method that calls into a trampoline for runtime method resolution
   mirror::AbstractMethod* GetResolutionMethod() const {
     CHECK(HasResolutionMethod());
@@ -419,8 +401,6 @@
 
   mirror::ByteArray* abstract_method_error_stub_array_;
 
-  mirror::ByteArray* resolution_stub_array_[kLastTrampolineMethodType];
-
   mirror::AbstractMethod* callee_save_methods_[kLastCalleeSaveType];
 
   mirror::AbstractMethod* resolution_method_;
diff --git a/src/runtime_support.h b/src/runtime_support.h
index c7eb957..2bab323 100644
--- a/src/runtime_support.h
+++ b/src/runtime_support.h
@@ -32,7 +32,13 @@
 
 extern "C" void art_interpreter_invoke_handler();
 extern "C" void art_portable_proxy_invoke_handler();
+extern "C" void art_portable_resolution_trampoline();
+extern "C" void art_quick_deoptimize();
+extern "C" void art_quick_instrumentation_entry_from_code(void*);
+extern "C" void art_quick_instrumentation_exit_from_code();
+extern "C" void art_quick_interpreter_entry(void*);
 extern "C" void art_quick_proxy_invoke_handler();
+extern "C" void art_quick_resolution_trampoline();
 extern "C" void art_work_around_app_jni_bugs();
 
 extern "C" double art_l2d(int64_t l);
@@ -313,6 +319,46 @@
                                     std::vector<jvalue>& args)
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) ;
 
+// Entry point for deoptimization.
+static inline uintptr_t GetDeoptimizationEntryPoint() {
+  return reinterpret_cast<uintptr_t>(art_quick_deoptimize);
+}
+
+// Return address of instrumentation stub.
+static inline void* GetInstrumentationEntryPoint() {
+  return reinterpret_cast<void*>(art_quick_instrumentation_entry_from_code);
+}
+
+// The return_pc of instrumentation exit stub.
+static inline uintptr_t GetInstrumentationExitPc() {
+  return reinterpret_cast<uintptr_t>(art_quick_instrumentation_exit_from_code);
+}
+
+// Return address of interpreter stub.
+static inline void* GetInterpreterEntryPoint() {
+  return reinterpret_cast<void*>(art_quick_interpreter_entry);
+}
+
+// Return address of portable resolution trampoline stub.
+static inline void* GetPortableResolutionTrampoline() {
+  return reinterpret_cast<void*>(art_portable_resolution_trampoline);
+}
+
+// Return address of quick resolution trampoline stub.
+static inline void* GetQuickResolutionTrampoline() {
+  return reinterpret_cast<void*>(art_quick_resolution_trampoline);
+}
+
+// Return address of resolution trampoline stub for defined compiler.
+static inline void* GetResolutionTrampoline() {
+#if defined(ART_USE_PORTABLE_COMPILER)
+  return GetPortableResolutionTrampoline();
+#else
+  return GetQuickResolutionTrampoline();
+#endif
+
 }  // namespace art
 
+}
+
 #endif  // ART_SRC_RUNTIME_SUPPORT_H_
diff --git a/src/thread.cc b/src/thread.cc
index 07a3a90..c878a86 100644
--- a/src/thread.cc
+++ b/src/thread.cc
@@ -1646,7 +1646,6 @@
   ENTRY_POINT_INFO(pMemcmp16),
   ENTRY_POINT_INFO(pStringCompareTo),
   ENTRY_POINT_INFO(pMemcpy),
-  ENTRY_POINT_INFO(pUnresolvedDirectMethodTrampolineFromCode),
   ENTRY_POINT_INFO(pInvokeDirectTrampolineWithAccessCheck),
   ENTRY_POINT_INFO(pInvokeInterfaceTrampoline),
   ENTRY_POINT_INFO(pInvokeInterfaceTrampolineWithAccessCheck),