Some more interpreter cleanup.

- Pass method helper and code item to entry point so they don't
  have to be regenerated.
- Removed interpreter only check from invoke, changing entry
  points instead.

Change-Id: Ib0ea83dcffcdb295d3a48d92ad8a93ac59f9932e
diff --git a/src/class_linker.cc b/src/class_linker.cc
index 52ce964..46c2ade 100644
--- a/src/class_linker.cc
+++ b/src/class_linker.cc
@@ -74,7 +74,8 @@
 
 namespace art {
 
-void artInterpreterToQuickEntry(Thread* self, ShadowFrame* shadow_frame, JValue* result);
+void artInterpreterToQuickEntry(Thread* self, MethodHelper& mh, const DexFile::CodeItem* code_item,
+                                ShadowFrame* shadow_frame, JValue* result);
 
 static void ThrowNoClassDefFoundError(const char* fmt, ...)
     __attribute__((__format__(__printf__, 1, 2)))
@@ -1041,7 +1042,9 @@
   if (obj->IsMethod()) {
     mirror::AbstractMethod* method = obj->AsMethod();
     // Install entry point from interpreter.
-    if (method->GetEntryPointFromCompiledCode() == NULL && !method->IsNative() && !method->IsProxyMethod()) {
+    if (!method->IsNative() && !method->IsProxyMethod() &&
+        (method->GetEntryPointFromCompiledCode() == NULL ||
+         Runtime::Current()->GetInstrumentation()->InterpretOnly())) {
       method->SetEntryPointFromInterpreter(interpreter::EnterInterpreterFromInterpreter);
     } else {
       method->SetEntryPointFromInterpreter(artInterpreterToQuickEntry);
@@ -1608,14 +1611,15 @@
   oat_method.LinkMethod(method.get());
 
   // Install entry point from interpreter.
-  if (method->GetEntryPointFromCompiledCode() == NULL && !method->IsNative() &&
-      !method->IsProxyMethod()) {
+  Runtime* runtime = Runtime::Current();
+  if (!method->IsNative() && !method->IsProxyMethod() &&
+      (method->GetEntryPointFromCompiledCode() == NULL ||
+       runtime->GetInstrumentation()->InterpretOnly())) {
     method->SetEntryPointFromInterpreter(interpreter::EnterInterpreterFromInterpreter);
   } else {
     method->SetEntryPointFromInterpreter(artInterpreterToQuickEntry);
   }
 
-  Runtime* runtime = Runtime::Current();
   if (method->IsAbstract()) {
     method->SetEntryPointFromCompiledCode(GetAbstractMethodErrorStub());
     return;
@@ -1631,7 +1635,9 @@
     method->UnregisterNative(Thread::Current());
   }
 
-  if (method->GetEntryPointFromCompiledCode() == NULL) {
+  if (method->GetEntryPointFromCompiledCode() == NULL ||
+      (runtime->GetInstrumentation()->InterpretOnly() && !method->IsNative() &&
+       !method->IsProxyMethod())) {
     // No code? You must mean to go into the interpreter.
     method->SetEntryPointFromCompiledCode(GetInterpreterEntryPoint());
   }
diff --git a/src/interpreter/interpreter.cc b/src/interpreter/interpreter.cc
index 0997438..124c0ee 100644
--- a/src/interpreter/interpreter.cc
+++ b/src/interpreter/interpreter.cc
@@ -50,12 +50,13 @@
 static const int64_t kMaxLong = std::numeric_limits<int64_t>::max();
 static const int64_t kMinLong = std::numeric_limits<int64_t>::min();
 
-static void UnstartedRuntimeInvoke(Thread* self, AbstractMethod* target_method,
-                                   ShadowFrame* shadow_frame, JValue* result, size_t arg_offset)
+static void UnstartedRuntimeInvoke(Thread* self, MethodHelper& mh,
+                                   const DexFile::CodeItem* code_item, ShadowFrame* shadow_frame,
+                                   JValue* result, size_t arg_offset)
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
   // In a runtime that's not started we intercept certain methods to avoid complicated dependency
   // problems in core libraries.
-  std::string name(PrettyMethod(target_method));
+  std::string name(PrettyMethod(shadow_frame->GetMethod()));
   if (name == "java.lang.Class java.lang.Class.forName(java.lang.String)") {
     std::string descriptor(DotToDescriptor(shadow_frame->GetVRegReference(arg_offset)->AsString()->ToModifiedUtf8().c_str()));
     ClassLoader* class_loader = NULL; // shadow_frame.GetMethod()->GetDeclaringClass()->GetClassLoader();
@@ -132,7 +133,7 @@
     }
   } else {
     // Not special, continue with regular interpreter execution.
-    EnterInterpreterFromInterpreter(self, shadow_frame, result);
+    EnterInterpreterFromInterpreter(self, mh, code_item, shadow_frame, result);
   }
 }
 
@@ -387,47 +388,40 @@
 static void DoInvoke(Thread* self, ShadowFrame& shadow_frame,
                      const Instruction* inst, JValue* result)
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
-  uint32_t vregC = (is_range) ? inst->VRegC_3rc() : inst->VRegC_35c();
-  Object* receiver;
-  if (type == kStatic) {
-    receiver = NULL;
-  } else {
-    receiver = shadow_frame.GetVRegReference(vregC);
-  }
   uint32_t method_idx = (is_range) ? inst->VRegB_3rc() : inst->VRegB_35c();
-  AbstractMethod* target_method = FindMethodFromCode(method_idx, receiver,
-                                                     shadow_frame.GetMethod(),
-                                                     self, true, type);
-  if (UNLIKELY(target_method == NULL)) {
+  uint32_t vregC = (is_range) ? inst->VRegC_3rc() : inst->VRegC_35c();
+  Object* receiver = (type == kStatic) ? NULL : shadow_frame.GetVRegReference(vregC);
+  AbstractMethod* method = FindMethodFromCode(method_idx, receiver, shadow_frame.GetMethod(), self,
+                                              true, type);
+  if (UNLIKELY(method == NULL)) {
     CHECK(self->IsExceptionPending());
     result->SetJ(0);
     return;
   }
-  MethodHelper target_mh(target_method);
 
-  const DexFile::CodeItem* code_item = target_mh.GetCodeItem();
+  MethodHelper mh(method);
+  const DexFile::CodeItem* code_item = mh.GetCodeItem();
   uint16_t num_regs;
   uint16_t num_ins;
-  if (code_item != NULL) {
+  if (LIKELY(code_item != NULL)) {
     num_regs = code_item->registers_size_;
     num_ins = code_item->ins_size_;
-  } else if (target_method->IsAbstract()) {
+  } else if (method->IsAbstract()) {
     ThrowLocation throw_location = self->GetCurrentLocationForThrow();
     self->ThrowNewExceptionF(throw_location, "Ljava/lang/AbstractMethodError;",
-                             "abstract method \"%s\"", PrettyMethod(target_method).c_str());
+                             "abstract method \"%s\"", PrettyMethod(method).c_str());
     return;
   } else {
-    DCHECK(target_method->IsNative() || target_method->IsProxyMethod());
-    num_regs = num_ins = AbstractMethod::NumArgRegisters(target_mh.GetShorty());
-    if (!target_method->IsStatic()) {
+    DCHECK(method->IsNative() || method->IsProxyMethod());
+    num_regs = num_ins = AbstractMethod::NumArgRegisters(mh.GetShorty());
+    if (!method->IsStatic()) {
       num_regs++;
       num_ins++;
     }
   }
 
   void* memory = alloca(ShadowFrame::ComputeSize(num_regs));
-  ShadowFrame* new_shadow_frame(ShadowFrame::Create(num_regs, &shadow_frame,
-                                                    target_method, 0, memory));
+  ShadowFrame* new_shadow_frame(ShadowFrame::Create(num_regs, &shadow_frame, method, 0, memory));
   size_t cur_reg = num_regs - num_ins;
   if (receiver != NULL) {
     new_shadow_frame->SetVRegReference(cur_reg, receiver);
@@ -435,13 +429,13 @@
   }
 
   size_t arg_offset = (receiver == NULL) ? 0 : 1;
-  const char* shorty = target_mh.GetShorty();
+  const char* shorty = mh.GetShorty();
   uint32_t arg[5];
   if (!is_range) {
     inst->GetArgs(arg);
   }
   for (size_t shorty_pos = 0; cur_reg < num_regs; ++shorty_pos, cur_reg++, arg_offset++) {
-    DCHECK_LT(shorty_pos + 1, target_mh.GetShortyLength());
+    DCHECK_LT(shorty_pos + 1, mh.GetShortyLength());
     size_t arg_pos = is_range ? vregC + arg_offset : arg[arg_offset];
     switch (shorty[shorty_pos + 1]) {
       case 'L': {
@@ -464,9 +458,9 @@
   }
 
   if (LIKELY(Runtime::Current()->IsStarted())) {
-    (target_method->GetEntryPointFromInterpreter())(self, new_shadow_frame, result);
+    (method->GetEntryPointFromInterpreter())(self, mh, code_item, new_shadow_frame, result);
   } else {
-    UnstartedRuntimeInvoke(self, target_method, new_shadow_frame, result, num_regs - num_ins);
+    UnstartedRuntimeInvoke(self, mh, code_item, new_shadow_frame, result, num_regs - num_ins);
   }
 }
 
@@ -2701,7 +2695,7 @@
 void EnterInterpreterFromInvoke(Thread* self, AbstractMethod* method, Object* receiver,
                                 uint32_t* args, JValue* result) {
   DCHECK_EQ(self, Thread::Current());
-  if (__builtin_frame_address(0) < self->GetStackEnd()) {
+  if (UNLIKELY(__builtin_frame_address(0) < self->GetStackEnd())) {
     ThrowStackOverflowError(self);
     return;
   }
@@ -2805,7 +2799,7 @@
                                 ShadowFrame& shadow_frame)
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
   DCHECK_EQ(self, Thread::Current());
-  if (__builtin_frame_address(0) < self->GetStackEnd()) {
+  if (UNLIKELY(__builtin_frame_address(0) < self->GetStackEnd())) {
     ThrowStackOverflowError(self);
     return JValue();
   }
@@ -2813,9 +2807,11 @@
   return Execute(self, mh, code_item, shadow_frame, JValue());
 }
 
-void EnterInterpreterFromInterpreter(Thread* self, ShadowFrame* shadow_frame, JValue* result)
+void EnterInterpreterFromInterpreter(Thread* self, MethodHelper& mh,
+                                     const DexFile::CodeItem* code_item, ShadowFrame* shadow_frame,
+                                     JValue* result)
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
-  if (__builtin_frame_address(0) < self->GetStackEnd()) {
+  if (UNLIKELY(__builtin_frame_address(0) < self->GetStackEnd())) {
     ThrowStackOverflowError(self);
     return;
   }
@@ -2832,8 +2828,6 @@
 
   self->PushShadowFrame(shadow_frame);
 
-  MethodHelper mh(method);
-  const DexFile::CodeItem* code_item = mh.GetCodeItem();
   if (LIKELY(!method->IsNative())) {
     result->SetJ(Execute(self, mh, code_item, *shadow_frame, JValue()).GetJ());
   } else {
diff --git a/src/interpreter/interpreter.h b/src/interpreter/interpreter.h
index 96fa050..bae3b65 100644
--- a/src/interpreter/interpreter.h
+++ b/src/interpreter/interpreter.h
@@ -47,7 +47,9 @@
                                        ShadowFrame& shadow_frame)
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
-extern void EnterInterpreterFromInterpreter(Thread* self, ShadowFrame* shadow_frame, JValue* result)
+extern void EnterInterpreterFromInterpreter(Thread* self, MethodHelper& mh,
+                                            const DexFile::CodeItem* code_item,
+                                            ShadowFrame* shadow_frame, JValue* result)
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
 }  // namespace interpreter
diff --git a/src/mirror/abstract_method.cc b/src/mirror/abstract_method.cc
index 5258795..c2ab29e 100644
--- a/src/mirror/abstract_method.cc
+++ b/src/mirror/abstract_method.cc
@@ -268,45 +268,28 @@
       result->SetJ(0);
     }
   } else {
-    bool interpret = runtime->GetInstrumentation()->InterpretOnly() && !IsNative() &&
-        !IsProxyMethod();
     const bool kLogInvocationStartAndReturn = false;
     if (GetEntryPointFromCompiledCode() != NULL) {
-      if (!interpret) {
-        if (kLogInvocationStartAndReturn) {
-          LOG(INFO) << StringPrintf("Invoking '%s' code=%p", PrettyMethod(this).c_str(), GetEntryPointFromCompiledCode());
-        }
+      if (kLogInvocationStartAndReturn) {
+        LOG(INFO) << StringPrintf("Invoking '%s' code=%p", PrettyMethod(this).c_str(), GetEntryPointFromCompiledCode());
+      }
 #ifdef ART_USE_PORTABLE_COMPILER
-        (*art_portable_invoke_stub)(this, args, args_size, self, result, result_type);
+      (*art_portable_invoke_stub)(this, args, args_size, self, result, result_type);
 #else
-        (*art_quick_invoke_stub)(this, args, args_size, self, result, result_type);
+      (*art_quick_invoke_stub)(this, args, args_size, self, result, result_type);
 #endif
-        if (UNLIKELY(reinterpret_cast<int32_t>(self->GetException(NULL)) == -1)) {
-          // Unusual case where we were running LLVM generated code and an
-          // exception was thrown to force the activations to be removed from the
-          // stack. Continue execution in the interpreter.
-          self->ClearException();
-          ShadowFrame* shadow_frame = self->GetAndClearDeoptimizationShadowFrame(result);
-          self->SetTopOfStack(NULL, 0);
-          self->SetTopOfShadowStack(shadow_frame);
-          interpreter::EnterInterpreterFromDeoptimize(self, shadow_frame, result);
-        }
-        if (kLogInvocationStartAndReturn) {
-          LOG(INFO) << StringPrintf("Returned '%s' code=%p", PrettyMethod(this).c_str(), GetEntryPointFromCompiledCode());
-        }
-      } else {
-        if (kLogInvocationStartAndReturn) {
-          LOG(INFO) << "Interpreting " << PrettyMethod(this) << "'";
-        }
-        if (this->IsStatic()) {
-          art::interpreter::EnterInterpreterFromInvoke(self, this, NULL, args, result);
-        } else {
-          Object* receiver = reinterpret_cast<Object*>(args[0]);
-          art::interpreter::EnterInterpreterFromInvoke(self, this, receiver, args + 1, result);
-        }
-        if (kLogInvocationStartAndReturn) {
-          LOG(INFO) << "Returned '" << PrettyMethod(this) << "'";
-        }
+      if (UNLIKELY(reinterpret_cast<int32_t>(self->GetException(NULL)) == -1)) {
+        // Unusual case where we were running LLVM generated code and an
+        // exception was thrown to force the activations to be removed from the
+        // stack. Continue execution in the interpreter.
+        self->ClearException();
+        ShadowFrame* shadow_frame = self->GetAndClearDeoptimizationShadowFrame(result);
+        self->SetTopOfStack(NULL, 0);
+        self->SetTopOfShadowStack(shadow_frame);
+        interpreter::EnterInterpreterFromDeoptimize(self, shadow_frame, result);
+      }
+      if (kLogInvocationStartAndReturn) {
+        LOG(INFO) << StringPrintf("Returned '%s' code=%p", PrettyMethod(this).c_str(), GetEntryPointFromCompiledCode());
       }
     } else {
       LOG(INFO) << "Not invoking '" << PrettyMethod(this)
diff --git a/src/mirror/abstract_method.h b/src/mirror/abstract_method.h
index c8aa11e..59dfdd57 100644
--- a/src/mirror/abstract_method.h
+++ b/src/mirror/abstract_method.h
@@ -18,6 +18,7 @@
 #define ART_SRC_MIRROR_METHOD_H_
 
 #include "class.h"
+#include "dex_file.h"
 #include "invoke_type.h"
 #include "locks.h"
 #include "modifiers.h"
@@ -29,6 +30,7 @@
 struct ConstructorMethodOffsets;
 union JValue;
 struct MethodClassOffsets;
+class MethodHelper;
 struct MethodOffsets;
 class StringPiece;
 class ShadowFrame;
@@ -37,7 +39,8 @@
 
 class StaticStorageBase;
 
-typedef void (EntryPointFromInterpreter)(Thread* self, ShadowFrame* shadow_frame, JValue* result);
+typedef void (EntryPointFromInterpreter)(Thread* self, MethodHelper& mh,
+    const DexFile::CodeItem* code_item, ShadowFrame* shadow_frame, JValue* result);
 
 // C++ mirror of java.lang.reflect.Method and java.lang.reflect.Constructor
 class MANAGED AbstractMethod : public Object {
diff --git a/src/oat/runtime/support_interpreter.cc b/src/oat/runtime/support_interpreter.cc
index a5d6fa3..7060a41 100644
--- a/src/oat/runtime/support_interpreter.cc
+++ b/src/oat/runtime/support_interpreter.cc
@@ -110,12 +110,10 @@
   return result.GetJ();
 }
 
-void artInterpreterToQuickEntry(Thread* self, ShadowFrame* shadow_frame, JValue* result)
+void artInterpreterToQuickEntry(Thread* self, MethodHelper& mh, const DexFile::CodeItem* code_item,
+                                ShadowFrame* shadow_frame, JValue* result)
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
   mirror::AbstractMethod* method = shadow_frame->GetMethod();
-  MethodHelper mh(method);
-  const DexFile::CodeItem* code_item = mh.GetCodeItem();
-
   uint16_t arg_offset = (code_item == NULL) ? 0 : code_item->registers_size_ - code_item->ins_size_;
   ArgArray arg_array(mh.GetShorty(), mh.GetShortyLength());
   arg_array.BuildArgArray(shadow_frame, arg_offset);