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..59dfdd5 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);