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/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.
*/