Merge "Revert "Remove interpreter entrypoint in ArtMethod.""
diff --git a/compiler/image_writer.cc b/compiler/image_writer.cc
index 93dd29d..73e121f 100644
--- a/compiler/image_writer.cc
+++ b/compiler/image_writer.cc
@@ -1417,6 +1417,9 @@
     if (UNLIKELY(orig->IsAbstract())) {
       copy->SetEntryPointFromQuickCompiledCodePtrSize(
           GetOatAddress(quick_to_interpreter_bridge_offset_), target_ptr_size_);
+      copy->SetEntryPointFromInterpreterPtrSize(
+          reinterpret_cast<EntryPointFromInterpreter*>(const_cast<uint8_t*>(
+                  GetOatAddress(interpreter_to_interpreter_bridge_offset_))), target_ptr_size_);
     } else {
       bool quick_is_interpreted;
       const uint8_t* quick_code = GetQuickCode(orig, &quick_is_interpreted);
@@ -1429,6 +1432,16 @@
         copy->SetEntryPointFromJniPtrSize(
             GetOatAddress(jni_dlsym_lookup_offset_), target_ptr_size_);
       }
+
+      // Interpreter entrypoint:
+      // Set the interpreter entrypoint depending on whether there is compiled code or not.
+      uint32_t interpreter_code = (quick_is_interpreted)
+          ? interpreter_to_interpreter_bridge_offset_
+          : interpreter_to_compiled_code_bridge_offset_;
+      EntryPointFromInterpreter* interpreter_entrypoint =
+          reinterpret_cast<EntryPointFromInterpreter*>(
+              const_cast<uint8_t*>(GetOatAddress(interpreter_code)));
+      copy->SetEntryPointFromInterpreterPtrSize(interpreter_entrypoint, target_ptr_size_);
     }
   }
 }
diff --git a/imgdiag/imgdiag.cc b/imgdiag/imgdiag.cc
index dce5206..f324881 100644
--- a/imgdiag/imgdiag.cc
+++ b/imgdiag/imgdiag.cc
@@ -548,6 +548,10 @@
           os << "  entryPointFromJni: "
              << reinterpret_cast<const void*>(
                     art_method->GetEntryPointFromJniPtrSize(pointer_size)) << ", ";
+          os << "  entryPointFromInterpreter: "
+             << reinterpret_cast<const void*>(
+                    art_method->GetEntryPointFromInterpreterPtrSize(pointer_size))
+             << ", ";
           os << "  entryPointFromQuickCompiledCode: "
              << reinterpret_cast<const void*>(
                     art_method->GetEntryPointFromQuickCompiledCodePtrSize(pointer_size))
@@ -627,6 +631,10 @@
           os << "  entryPointFromJni: "
              << reinterpret_cast<const void*>(
                     art_method->GetEntryPointFromJniPtrSize(pointer_size)) << ", ";
+          os << "  entryPointFromInterpreter: "
+             << reinterpret_cast<const void*>(
+                    art_method->GetEntryPointFromInterpreterPtrSize(pointer_size))
+             << ", ";
           os << "  entryPointFromQuickCompiledCode: "
              << reinterpret_cast<const void*>(
                     art_method->GetEntryPointFromQuickCompiledCodePtrSize(pointer_size))
diff --git a/patchoat/patchoat.cc b/patchoat/patchoat.cc
index dbd1d23..3a155be 100644
--- a/patchoat/patchoat.cc
+++ b/patchoat/patchoat.cc
@@ -651,6 +651,8 @@
   copy->SetDexCacheResolvedTypes(RelocatedAddressOfPointer(object->GetDexCacheResolvedTypes()));
   copy->SetEntryPointFromQuickCompiledCodePtrSize(RelocatedAddressOfPointer(
       object->GetEntryPointFromQuickCompiledCodePtrSize(pointer_size)), pointer_size);
+  copy->SetEntryPointFromInterpreterPtrSize(RelocatedAddressOfPointer(
+      object->GetEntryPointFromInterpreterPtrSize(pointer_size)), pointer_size);
   copy->SetEntryPointFromJniPtrSize(RelocatedAddressOfPointer(
       object->GetEntryPointFromJniPtrSize(pointer_size)), pointer_size);
 }
diff --git a/runtime/art_method.h b/runtime/art_method.h
index e8c47d9..4a1e2c4 100644
--- a/runtime/art_method.h
+++ b/runtime/art_method.h
@@ -43,6 +43,9 @@
 class PointerArray;
 }  // namespace mirror
 
+typedef void (EntryPointFromInterpreter)(Thread* self, const DexFile::CodeItem* code_item,
+                                         ShadowFrame* shadow_frame, JValue* result);
+
 class ArtMethod FINAL {
  public:
   ArtMethod() : access_flags_(0), dex_code_item_offset_(0), dex_method_index_(0),
@@ -269,6 +272,23 @@
   void Invoke(Thread* self, uint32_t* args, uint32_t args_size, JValue* result, const char* shorty)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
+  EntryPointFromInterpreter* GetEntryPointFromInterpreter() {
+    return GetEntryPointFromInterpreterPtrSize(sizeof(void*));
+  }
+  EntryPointFromInterpreter* GetEntryPointFromInterpreterPtrSize(size_t pointer_size) {
+    return GetEntryPoint<EntryPointFromInterpreter*>(
+        EntryPointFromInterpreterOffset(pointer_size), pointer_size);
+  }
+
+  void SetEntryPointFromInterpreter(EntryPointFromInterpreter* entry_point_from_interpreter) {
+    SetEntryPointFromInterpreterPtrSize(entry_point_from_interpreter, sizeof(void*));
+  }
+  void SetEntryPointFromInterpreterPtrSize(EntryPointFromInterpreter* entry_point_from_interpreter,
+                                           size_t pointer_size) {
+    SetEntryPoint(EntryPointFromInterpreterOffset(pointer_size), entry_point_from_interpreter,
+                  pointer_size);
+  }
+
   const void* GetEntryPointFromQuickCompiledCode() {
     return GetEntryPointFromQuickCompiledCodePtrSize(sizeof(void*));
   }
@@ -378,6 +398,11 @@
 
   void UnregisterNative() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
+  static MemberOffset EntryPointFromInterpreterOffset(size_t pointer_size) {
+    return MemberOffset(PtrSizedFieldsOffset(pointer_size) + OFFSETOF_MEMBER(
+        PtrSizedFields, entry_point_from_interpreter_) / sizeof(void*) * pointer_size);
+  }
+
   static MemberOffset EntryPointFromJniOffset(size_t pointer_size) {
     return MemberOffset(PtrSizedFieldsOffset(pointer_size) + OFFSETOF_MEMBER(
         PtrSizedFields, entry_point_from_jni_) / sizeof(void*) * pointer_size);
@@ -548,6 +573,10 @@
   // PACKED(4) is necessary for the correctness of
   // RoundUp(OFFSETOF_MEMBER(ArtMethod, ptr_sized_fields_), pointer_size).
   struct PACKED(4) PtrSizedFields {
+    // Method dispatch from the interpreter invokes this pointer which may cause a bridge into
+    // compiled code.
+    void* entry_point_from_interpreter_;
+
     // Pointer to JNI function registered to this method, or a function to resolve the JNI function.
     void* entry_point_from_jni_;
 
diff --git a/runtime/asm_support.h b/runtime/asm_support.h
index 20d75f3..10ed0f4 100644
--- a/runtime/asm_support.h
+++ b/runtime/asm_support.h
@@ -189,11 +189,11 @@
 ADD_TEST_EQ(ART_METHOD_DEX_CACHE_TYPES_OFFSET,
             art::ArtMethod::DexCacheResolvedTypesOffset().Int32Value())
 
-#define ART_METHOD_QUICK_CODE_OFFSET_32 32
+#define ART_METHOD_QUICK_CODE_OFFSET_32 36
 ADD_TEST_EQ(ART_METHOD_QUICK_CODE_OFFSET_32,
             art::ArtMethod::EntryPointFromQuickCompiledCodeOffset(4).Int32Value())
 
-#define ART_METHOD_QUICK_CODE_OFFSET_64 40
+#define ART_METHOD_QUICK_CODE_OFFSET_64 48
 ADD_TEST_EQ(ART_METHOD_QUICK_CODE_OFFSET_64,
             art::ArtMethod::EntryPointFromQuickCompiledCodeOffset(8).Int32Value())
 
diff --git a/runtime/base/bit_utils.h b/runtime/base/bit_utils.h
index 6f45dc8..7972158 100644
--- a/runtime/base/bit_utils.h
+++ b/runtime/base/bit_utils.h
@@ -137,7 +137,7 @@
 }
 
 template<int n, typename T>
-static constexpr bool IsAligned(T x) {
+static inline bool IsAligned(T x) {
   static_assert((n & (n - 1)) == 0, "n is not a power of two");
   return (x & (n - 1)) == 0;
 }
diff --git a/runtime/class_linker.cc b/runtime/class_linker.cc
index 0694227..23c5942 100644
--- a/runtime/class_linker.cc
+++ b/runtime/class_linker.cc
@@ -1195,9 +1195,13 @@
       if (kIsDebugBuild && !method->IsRuntimeMethod()) {
         CHECK(method->GetDeclaringClass() != nullptr);
       }
-      if (!method->IsNative() && !method->IsRuntimeMethod() && !method->IsResolutionMethod()) {
-        method->SetEntryPointFromQuickCompiledCodePtrSize(GetQuickToInterpreterBridge(),
-                                                          image_pointer_size_);
+      if (!method->IsNative()) {
+        method->SetEntryPointFromInterpreterPtrSize(
+            artInterpreterToInterpreterBridge, image_pointer_size_);
+        if (!method->IsRuntimeMethod() && method != runtime->GetResolutionMethod()) {
+          method->SetEntryPointFromQuickCompiledCodePtrSize(GetQuickToInterpreterBridge(),
+                                                            image_pointer_size_);
+        }
       }
     }
   }
@@ -2202,6 +2206,11 @@
 
   // Install entry point from interpreter.
   bool enter_interpreter = NeedsInterpreter(method, method->GetEntryPointFromQuickCompiledCode());
+  if (enter_interpreter && !method->IsNative()) {
+    method->SetEntryPointFromInterpreter(artInterpreterToInterpreterBridge);
+  } else {
+    method->SetEntryPointFromInterpreter(artInterpreterToCompiledCodeBridge);
+  }
 
   if (method->IsAbstract()) {
     method->SetEntryPointFromQuickCompiledCode(GetQuickToInterpreterBridge());
@@ -3507,6 +3516,7 @@
   // At runtime the method looks like a reference and argument saving method, clone the code
   // related parameters from this method.
   out->SetEntryPointFromQuickCompiledCode(GetQuickProxyInvokeHandler());
+  out->SetEntryPointFromInterpreter(artInterpreterToCompiledCodeBridge);
 }
 
 void ClassLinker::CheckProxyMethod(ArtMethod* method, ArtMethod* prototype) const {
@@ -5637,15 +5647,18 @@
                                                const void* method_code) const {
   OatFile::OatMethod oat_method = CreateOatMethod(method_code);
   oat_method.LinkMethod(method);
+  method->SetEntryPointFromInterpreter(artInterpreterToCompiledCodeBridge);
 }
 
 void ClassLinker::SetEntryPointsToInterpreter(ArtMethod* method) const {
   if (!method->IsNative()) {
+    method->SetEntryPointFromInterpreter(artInterpreterToInterpreterBridge);
     method->SetEntryPointFromQuickCompiledCode(GetQuickToInterpreterBridge());
   } else {
     const void* quick_method_code = GetQuickGenericJniStub();
     OatFile::OatMethod oat_method = CreateOatMethod(quick_method_code);
     oat_method.LinkMethod(method);
+    method->SetEntryPointFromInterpreter(artInterpreterToCompiledCodeBridge);
   }
 }
 
diff --git a/runtime/fault_handler.cc b/runtime/fault_handler.cc
index 5f91566..762f061 100644
--- a/runtime/fault_handler.cc
+++ b/runtime/fault_handler.cc
@@ -320,7 +320,7 @@
     return false;
   }
 
-  ArtMethod* method_obj = nullptr;
+  ArtMethod* method_obj = 0;
   uintptr_t return_pc = 0;
   uintptr_t sp = 0;
 
@@ -331,9 +331,7 @@
   // If we don't have a potential method, we're outta here.
   VLOG(signals) << "potential method: " << method_obj;
   // TODO: Check linear alloc and image.
-  DCHECK(IsAligned<sizeof(void*)>(ArtMethod::ObjectSize(sizeof(void*))))
-      << "ArtMethod is not pointer aligned";
-  if (method_obj == nullptr || !IsAligned<sizeof(void*)>(method_obj)) {
+  if (method_obj == 0 || !IsAligned<kObjectAlignment>(method_obj)) {
     VLOG(signals) << "no method";
     return false;
   }
diff --git a/runtime/instrumentation.cc b/runtime/instrumentation.cc
index abe9dc2..d37ddcb 100644
--- a/runtime/instrumentation.cc
+++ b/runtime/instrumentation.cc
@@ -99,6 +99,19 @@
     }
   }
   method->SetEntryPointFromQuickCompiledCode(quick_code);
+  if (!method->IsResolutionMethod()) {
+    ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
+    if (class_linker->IsQuickToInterpreterBridge(quick_code) ||
+        (class_linker->IsQuickResolutionStub(quick_code) &&
+         Runtime::Current()->GetInstrumentation()->IsForcedInterpretOnly() &&
+         !method->IsNative() && !method->IsProxyMethod())) {
+      DCHECK(!method->IsNative()) << PrettyMethod(method);
+      DCHECK(!method->IsProxyMethod()) << PrettyMethod(method);
+      method->SetEntryPointFromInterpreter(art::artInterpreterToInterpreterBridge);
+    } else {
+      method->SetEntryPointFromInterpreter(art::artInterpreterToCompiledCodeBridge);
+    }
+  }
 }
 
 void Instrumentation::InstallStubsForMethod(ArtMethod* method) {
diff --git a/runtime/interpreter/interpreter_common.cc b/runtime/interpreter/interpreter_common.cc
index 0980ea1..fa103b1 100644
--- a/runtime/interpreter/interpreter_common.cc
+++ b/runtime/interpreter/interpreter_common.cc
@@ -19,7 +19,6 @@
 #include <cmath>
 
 #include "debugger.h"
-#include "entrypoints/runtime_asm_entrypoints.h"
 #include "mirror/array-inl.h"
 #include "unstarted_runtime.h"
 #include "verifier/method_verifier.h"
@@ -491,23 +490,6 @@
                                 uint32_t arg[Instruction::kMaxVarArgRegs],
                                 uint32_t vregC) ALWAYS_INLINE;
 
-SHARED_LOCKS_REQUIRED(Locks::mutator_lock_)
-static inline bool NeedsInterpreter(Thread* self, ShadowFrame* new_shadow_frame) ALWAYS_INLINE;
-
-static inline bool NeedsInterpreter(Thread* self, ShadowFrame* new_shadow_frame) {
-  ArtMethod* target = new_shadow_frame->GetMethod();
-  if (UNLIKELY(target->IsNative() || target->IsProxyMethod())) {
-    return false;
-  }
-  Runtime* runtime = Runtime::Current();
-  ClassLinker* class_linker = runtime->GetClassLinker();
-  return runtime->GetInstrumentation()->IsForcedInterpretOnly() ||
-        // Doing this check avoids doing compiled/interpreter transitions.
-        class_linker->IsQuickToInterpreterBridge(target->GetEntryPointFromQuickCompiledCode()) ||
-        // Force the use of interpreter when it is required by the debugger.
-        Dbg::IsForcedInterpreterNeededForCalling(self, target);
-}
-
 template<bool is_range, bool do_assignability_check>
 static inline bool DoCallCommon(ArtMethod* called_method,
                                 Thread* self,
@@ -678,11 +660,28 @@
 
   // Do the call now.
   if (LIKELY(Runtime::Current()->IsStarted())) {
-    if (NeedsInterpreter(self, new_shadow_frame)) {
-      artInterpreterToInterpreterBridge(self, code_item, new_shadow_frame, result);
-    } else {
-      artInterpreterToCompiledCodeBridge(self, code_item, new_shadow_frame, result);
+    if (kIsDebugBuild && new_shadow_frame->GetMethod()->GetEntryPointFromInterpreter() == nullptr) {
+      LOG(FATAL) << "Attempt to invoke non-executable method: "
+          << PrettyMethod(new_shadow_frame->GetMethod());
+      UNREACHABLE();
     }
+    if (kIsDebugBuild && Runtime::Current()->GetInstrumentation()->IsForcedInterpretOnly() &&
+        !new_shadow_frame->GetMethod()->IsNative() &&
+        !new_shadow_frame->GetMethod()->IsProxyMethod() &&
+        new_shadow_frame->GetMethod()->GetEntryPointFromInterpreter()
+            == artInterpreterToCompiledCodeBridge) {
+      LOG(FATAL) << "Attempt to call compiled code when -Xint: "
+          << PrettyMethod(new_shadow_frame->GetMethod());
+      UNREACHABLE();
+    }
+    // Force the use of interpreter when it is required by the debugger.
+    EntryPointFromInterpreter* entry;
+    if (UNLIKELY(Dbg::IsForcedInterpreterNeededForCalling(self, new_shadow_frame->GetMethod()))) {
+      entry = &art::artInterpreterToInterpreterBridge;
+    } else {
+      entry = new_shadow_frame->GetMethod()->GetEntryPointFromInterpreter();
+    }
+    entry(self, code_item, new_shadow_frame, result);
   } else {
     UnstartedRuntime::Invoke(self, code_item, new_shadow_frame, result, first_dest_reg);
   }
diff --git a/runtime/jit/jit.cc b/runtime/jit/jit.cc
index fda97db..bc9545b 100644
--- a/runtime/jit/jit.cc
+++ b/runtime/jit/jit.cc
@@ -132,7 +132,11 @@
     VLOG(jit) << "JIT not compiling " << PrettyMethod(method) << " due to breakpoint";
     return false;
   }
-  return jit_compile_method_(jit_compiler_handle_, method, self);
+  const bool result = jit_compile_method_(jit_compiler_handle_, method, self);
+  if (result) {
+    method->SetEntryPointFromInterpreter(artInterpreterToCompiledCodeBridge);
+  }
+  return result;
 }
 
 void Jit::CreateThreadPool() {
diff --git a/runtime/oat.h b/runtime/oat.h
index 5706c4e..000ae8e 100644
--- a/runtime/oat.h
+++ b/runtime/oat.h
@@ -32,7 +32,7 @@
 class PACKED(4) OatHeader {
  public:
   static constexpr uint8_t kOatMagic[] = { 'o', 'a', 't', '\n' };
-  static constexpr uint8_t kOatVersion[] = { '0', '6', '5', '\0' };
+  static constexpr uint8_t kOatVersion[] = { '0', '6', '4', '\0' };
 
   static constexpr const char* kImageLocationKey = "image-location";
   static constexpr const char* kDex2OatCmdLineKey = "dex2oat-cmdline";
diff --git a/runtime/stack.cc b/runtime/stack.cc
index 6f3b0a3..11c94db 100644
--- a/runtime/stack.cc
+++ b/runtime/stack.cc
@@ -857,6 +857,7 @@
               << " native=" << method->IsNative()
               << " entrypoints=" << method->GetEntryPointFromQuickCompiledCode()
               << "," << method->GetEntryPointFromJni()
+              << "," << method->GetEntryPointFromInterpreter()
               << " next=" << *cur_quick_frame_;
         }