Enter interpreter stub.

Untested code that when set as the code for a AbstractMethod* will force the
next invocation of the Method to transition into the interpreter.

Change-Id: I557bca3a2caf4a78551b39aa5ac4ffb4c486105b
diff --git a/build/Android.common.mk b/build/Android.common.mk
index d7d8365..eb95285 100644
--- a/build/Android.common.mk
+++ b/build/Android.common.mk
@@ -260,6 +260,7 @@
 	src/oat/runtime/support_field.cc \
 	src/oat/runtime/support_fillarray.cc \
 	src/oat/runtime/support_instrumentation.cc \
+        src/oat/runtime/support_interpreter.cc \
 	src/oat/runtime/support_invoke.cc \
 	src/oat/runtime/support_jni.cc \
 	src/oat/runtime/support_locks.cc \
diff --git a/src/interpreter/interpreter.cc b/src/interpreter/interpreter.cc
index 3b041c8..d816830 100644
--- a/src/interpreter/interpreter.cc
+++ b/src/interpreter/interpreter.cc
@@ -1811,7 +1811,7 @@
   // Set up shadow frame with matching number of reference slots to vregs.
   ShadowFrame* last_shadow_frame = self->GetManagedStack()->GetTopShadowFrame();
   UniquePtr<ShadowFrame> shadow_frame(ShadowFrame::Create(num_regs,
-                                                          (last_shadow_frame == NULL) ? NULL : last_shadow_frame->GetLink(),
+                                                          last_shadow_frame,
                                                           method, 0));
   self->PushShadowFrame(shadow_frame.get());
   size_t cur_reg = num_regs - num_ins;
@@ -1870,5 +1870,11 @@
   return Execute(self, mh, code_item, shadow_frame, ret_val);
 }
 
+JValue EnterInterpreterFromStub(Thread* self, MethodHelper& mh, const DexFile::CodeItem* code_item,
+                                ShadowFrame& shadow_frame)
+    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+  return Execute(self, mh, code_item, shadow_frame, JValue());
+}
+
 }  // namespace interpreter
 }  // namespace art
diff --git a/src/interpreter/interpreter.h b/src/interpreter/interpreter.h
index ec6832d..6990458 100644
--- a/src/interpreter/interpreter.h
+++ b/src/interpreter/interpreter.h
@@ -17,12 +17,14 @@
 #ifndef ART_SRC_INTERPRETER_INTERPRETER_H_
 #define ART_SRC_INTERPRETER_INTERPRETER_H_
 
+#include "dex_file.h"
 #include "locks.h"
 
 namespace art {
 
 class AbstractMethod;
 union JValue;
+class MethodHelper;
 class Object;
 class ShadowFrame;
 class Thread;
@@ -37,6 +39,11 @@
                                              JValue ret_val)
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
+extern JValue EnterInterpreterFromStub(Thread* self, MethodHelper& mh,
+                                       const DexFile::CodeItem* code_item,
+                                       ShadowFrame& shadow_frame)
+    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+
 }  // namespace interpreter
 }  // namespace art
 
diff --git a/src/oat/runtime/arm/oat_support_entrypoints_arm.cc b/src/oat/runtime/arm/oat_support_entrypoints_arm.cc
index 041e12b..146eee4 100644
--- a/src/oat/runtime/arm/oat_support_entrypoints_arm.cc
+++ b/src/oat/runtime/arm/oat_support_entrypoints_arm.cc
@@ -138,6 +138,7 @@
 // Instrumentation entrypoints.
 extern "C" void art_instrumentation_entry_from_code(void*);
 extern "C" void art_instrumentation_exit_from_code();
+extern "C" void art_interpreter_entry(void*);
 extern "C" void art_deoptimize();
 
 void InitEntryPoints(EntryPoints* points) {
@@ -264,4 +265,8 @@
   return reinterpret_cast<void*>(art_instrumentation_entry_from_code);
 }
 
+void* GetInterpreterEntryPoint() {
+  return reinterpret_cast<void*>(art_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 dda1222..75039cf 100644
--- a/src/oat/runtime/arm/runtime_support_arm.S
+++ b/src/oat/runtime/arm/runtime_support_arm.S
@@ -771,6 +771,22 @@
     bxeq    lr                     @ return on success
     DELIVER_PENDING_EXCEPTION
 
+    .global art_interpreter_entry
+    .extern artInterpreterEntry
+    ALIGN_FUNCTION_ENTRY
+art_interpreter_entry:
+    SETUP_REF_AND_ARGS_CALLEE_SAVE_FRAME
+    str     r0, [sp, #0]           @ place proxy method at bottom of frame
+    mov     r1, r9                 @ pass Thread::Current
+    mov     r2, sp                 @ pass SP
+    blx     artInterpreterEntry    @ (Method* method, Thread*, SP)
+    ldr     r12, [r9, #THREAD_EXCEPTION_OFFSET]  @ load Thread::Current()->exception_
+    ldr     lr,  [sp, #44]         @ restore lr
+    add     sp,  #48               @ pop frame
+    cmp     r12, #0                @ success if no exception is pending
+    bxeq    lr                     @ return on success
+    DELIVER_PENDING_EXCEPTION
+
     .global art_instrumentation_entry_from_code
     .global art_instrumentation_exit_from_code
     .extern artInstrumentationMethodEntryFromCode
diff --git a/src/oat/runtime/mips/oat_support_entrypoints_mips.cc b/src/oat/runtime/mips/oat_support_entrypoints_mips.cc
index 0b8dc0c..ddff280 100644
--- a/src/oat/runtime/mips/oat_support_entrypoints_mips.cc
+++ b/src/oat/runtime/mips/oat_support_entrypoints_mips.cc
@@ -140,6 +140,7 @@
 // Instrumentation entrypoints.
 extern "C" void art_instrumentation_entry_from_code(void*);
 extern "C" void art_instrumentation_exit_from_code();
+extern "C" void art_interpreter_entry(void*);
 extern "C" void art_deoptimize();
 
 void InitEntryPoints(EntryPoints* points) {
@@ -266,4 +267,8 @@
   return reinterpret_cast<void*>(art_instrumentation_entry_from_code);
 }
 
+void* GetInterpreterEntryPoint() {
+  return reinterpret_cast<void*>(art_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 efd3ede..b49d5a5 100644
--- a/src/oat/runtime/mips/runtime_support_mips.S
+++ b/src/oat/runtime/mips/runtime_support_mips.S
@@ -852,7 +852,7 @@
     SETUP_REF_AND_ARGS_CALLEE_SAVE_FRAME
     sw      $a0, 0($sp)            # place proxy method at bottom of frame
     move    $a2, rSELF             # pass Thread::Current
-    jal     artProxyInvokeHandler  # (Method* proxy method, receiver, Thread*, args...)
+    jal     artProxyInvokeHandler  # (Method* proxy method, receiver, Thread*, SP)
     move    $a3, $sp               # pass $sp
     lw      $t0, THREAD_EXCEPTION_OFFSET(rSELF) # load Thread::Current()->exception_
     lw      $ra, 44($sp)           # restore $ra
@@ -863,6 +863,25 @@
 1:
     DELIVER_PENDING_EXCEPTION
 
+    .global art_interpreter_entry
+    .extern artInterpreterEntry
+    ALIGN_FUNCTION_ENTRY
+art_interpreter_entry:
+    GENERATE_GLOBAL_POINTER
+    SETUP_REF_AND_ARGS_CALLEE_SAVE_FRAME
+    sw      $a0, 0($sp)            # place proxy method at bottom of frame
+    move    $a1, rSELF             # pass Thread::Current
+    jal     artInterpreterEntry    # (Method* method, Thread*, SP)
+    move    $a2, $sp               # pass $sp
+    lw      $t0, THREAD_EXCEPTION_OFFSET(rSELF) # load Thread::Current()->exception_
+    lw      $ra, 44($sp)           # restore $ra
+    bnez    $t0, 1f
+    addiu   $sp, $sp, 48           # pop frame
+    jr      $ra
+    nop
+1:
+    DELIVER_PENDING_EXCEPTION
+
     .global art_instrumentation_entry_from_code
     .global art_instrumentation_exit_from_code
     .extern artInstrumentationMethodEntryFromCode
diff --git a/src/oat/runtime/oat_support_entrypoints.h b/src/oat/runtime/oat_support_entrypoints.h
index 285105d..1c7fa1b 100644
--- a/src/oat/runtime/oat_support_entrypoints.h
+++ b/src/oat/runtime/oat_support_entrypoints.h
@@ -155,6 +155,9 @@
 // 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/support_interpreter.cc b/src/oat/runtime/support_interpreter.cc
new file mode 100644
index 0000000..98751cc
--- /dev/null
+++ b/src/oat/runtime/support_interpreter.cc
@@ -0,0 +1,94 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "argument_visitor.h"
+#include "callee_save_frame.h"
+#include "interpreter/interpreter.h"
+#include "object.h"
+#include "object_utils.h"
+
+namespace art {
+
+// Visits arguments on the stack placing them into the shadow frame.
+class BuildShadowFrameVisitor : public ArgumentVisitor {
+ public:
+  BuildShadowFrameVisitor(MethodHelper& caller_mh, AbstractMethod** sp,
+                          ShadowFrame& sf, size_t first_arg_reg) :
+    ArgumentVisitor(caller_mh, sp), sf_(sf), cur_reg_(first_arg_reg) {}
+
+  virtual void Visit() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+    Primitive::Type type = GetParamPrimitiveType();
+    switch (type) {
+      case Primitive::kPrimLong:  // Fall-through.
+      case Primitive::kPrimDouble:
+        if (IsSplitLongOrDouble()) {
+          sf_.SetVRegLong(cur_reg_, ReadSplitLongParam());
+        } else {
+          sf_.SetVRegLong(cur_reg_, *reinterpret_cast<jlong*>(GetParamAddress()));
+        }
+        break;
+      case Primitive::kPrimNot:
+        sf_.SetVRegReference(cur_reg_, *reinterpret_cast<Object**>(GetParamAddress()));
+        break;
+      case Primitive::kPrimBoolean:  // Fall-through.
+      case Primitive::kPrimByte:     // Fall-through.
+      case Primitive::kPrimChar:     // Fall-through.
+      case Primitive::kPrimShort:    // Fall-through.
+      case Primitive::kPrimInt:      // Fall-through.
+      case Primitive::kPrimFloat:
+        sf_.SetVReg(cur_reg_, *reinterpret_cast<jint*>(GetParamAddress()));
+        break;
+      case Primitive::kPrimVoid:
+        LOG(FATAL) << "UNREACHABLE";
+        break;
+    }
+    ++cur_reg_;
+  }
+
+ private:
+  ShadowFrame& sf_;
+  size_t cur_reg_;
+
+  DISALLOW_COPY_AND_ASSIGN(BuildShadowFrameVisitor);
+};
+
+extern "C" uint64_t artInterpreterEntry(AbstractMethod* method, Thread* self, AbstractMethod** sp)
+    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+  // Ensure we don't get thread suspension until the object arguments are safely in the shadow
+  // frame.
+  const char* old_cause = self->StartAssertNoThreadSuspension("Building interpreter shadow frame");
+  FinishCalleeSaveFrameSetup(self, sp, Runtime::kRefsAndArgs);
+
+  MethodHelper mh(method);
+  const DexFile::CodeItem* code_item = mh.GetCodeItem();
+  UniquePtr<ShadowFrame> shadow_frame(ShadowFrame::Create(code_item->registers_size_,
+                                                          NULL, // No last shadow coming from quick.
+                                                          method, 0));
+  size_t first_arg_reg = code_item->registers_size_ - code_item->ins_size_;
+  BuildShadowFrameVisitor shadow_frame_builder(mh, sp, *shadow_frame.get(), first_arg_reg);
+  shadow_frame_builder.VisitArguments();
+  // Push a transition back into managed code onto the linked list in thread.
+  ManagedStack fragment;
+  self->PushManagedStackFragment(&fragment);
+  self->PushShadowFrame(shadow_frame.get());
+  self->EndAssertNoThreadSuspension(old_cause);
+  JValue result = interpreter::EnterInterpreterFromStub(self, mh, code_item, *shadow_frame.get());
+  // Pop transition.
+  self->PopManagedStackFragment(fragment);
+  return result.GetJ();
+}
+
+}  // namespace art
diff --git a/src/oat/runtime/support_proxy.cc b/src/oat/runtime/support_proxy.cc
index 5bf3cde..f0f07a1 100644
--- a/src/oat/runtime/support_proxy.cc
+++ b/src/oat/runtime/support_proxy.cc
@@ -52,11 +52,11 @@
           val.j = *reinterpret_cast<jlong*>(GetParamAddress());
         }
         break;
-      case Primitive::kPrimBoolean:
-      case Primitive::kPrimByte:
-      case Primitive::kPrimChar:
-      case Primitive::kPrimShort:
-      case Primitive::kPrimInt:
+      case Primitive::kPrimBoolean:  // Fall-through.
+      case Primitive::kPrimByte:     // Fall-through.
+      case Primitive::kPrimChar:     // Fall-through.
+      case Primitive::kPrimShort:    // Fall-through.
+      case Primitive::kPrimInt:      // Fall-through.
       case Primitive::kPrimFloat:
         val.i =  *reinterpret_cast<jint*>(GetParamAddress());
         break;
@@ -71,6 +71,8 @@
  private:
   ScopedObjectAccessUnchecked& soa_;
   std::vector<jvalue>& args_;
+
+  DISALLOW_COPY_AND_ASSIGN(BuildArgumentVisitor);
 };
 
 // Handler for invocation on proxy methods. On entry a frame will exist for the proxy object method
diff --git a/src/oat/runtime/x86/oat_support_entrypoints_x86.cc b/src/oat/runtime/x86/oat_support_entrypoints_x86.cc
index 81cbdd5..c4c2798 100644
--- a/src/oat/runtime/x86/oat_support_entrypoints_x86.cc
+++ b/src/oat/runtime/x86/oat_support_entrypoints_x86.cc
@@ -126,6 +126,7 @@
 // Instrumentation entrypoints.
 extern "C" void art_instrumentation_entry_from_code(void*);
 extern "C" void art_instrumentation_exit_from_code();
+extern "C" void art_interpreter_entry(void*);
 extern "C" void art_deoptimize();
 
 void InitEntryPoints(EntryPoints* points) {
@@ -251,4 +252,8 @@
   return reinterpret_cast<void*>(art_instrumentation_entry_from_code);
 }
 
+void* GetInterpreterEntryPoint() {
+  return reinterpret_cast<void*>(art_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 f2f9fa4..cdb8167 100644
--- a/src/oat/runtime/x86/runtime_support_x86.S
+++ b/src/oat/runtime/x86/runtime_support_x86.S
@@ -737,7 +737,7 @@
     RETURN_OR_DELIVER_PENDING_EXCEPTION    // return or deliver exception
 
 DEFINE_FUNCTION art_proxy_invoke_handler
-    SETUP_REF_AND_ARGS_CALLEE_SAVE_FRAME   // save frame
+    SETUP_REF_AND_ARGS_CALLEE_SAVE_FRAME   // save frame and Method*
     pushl %esp                    // pass SP
     pushl %fs:THREAD_SELF_OFFSET  // pass Thread::Current()
     pushl %ecx                    // pass receiver
@@ -749,6 +749,19 @@
     addl LITERAL(44), %esp        // pop arguments
     RETURN_OR_DELIVER_PENDING_EXCEPTION    // return or deliver exception
 
+DEFINE_FUNCTION art_interpreter_entry
+    SETUP_REF_AND_ARGS_CALLEE_SAVE_FRAME   // save frame and Method*
+    pushl %eax                    // alignment padding
+    pushl %esp                    // pass SP
+    pushl %fs:THREAD_SELF_OFFSET  // pass Thread::Current()
+    pushl %eax                    // pass  method
+    call SYMBOL(artInterpreterEntry)  // (method, Thread*, SP)
+    movd %eax, %xmm0              // place return value also into floating point return value
+    movd %edx, %xmm1
+    punpckldq %xmm1, %xmm0
+    addl LITERAL(44), %esp        // pop arguments
+    RETURN_OR_DELIVER_PENDING_EXCEPTION    // return or deliver exception
+
     /*
      * Routine that intercepts method calls and returns.
      */