summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--runtime/dex_instruction-inl.h13
-rw-r--r--runtime/dex_instruction.h5
-rw-r--r--runtime/entrypoints/interpreter/interpreter_entrypoints.cc12
-rw-r--r--runtime/interpreter/interpreter.cc18
-rw-r--r--runtime/interpreter/interpreter_common.cc195
-rw-r--r--runtime/interpreter/interpreter_common.h79
-rw-r--r--runtime/interpreter/interpreter_goto_table_impl.cc25
-rw-r--r--runtime/interpreter/interpreter_switch_impl.cc24
-rw-r--r--runtime/stack.h3
9 files changed, 165 insertions, 209 deletions
diff --git a/runtime/dex_instruction-inl.h b/runtime/dex_instruction-inl.h
index 4d39024..207b0b6 100644
--- a/runtime/dex_instruction-inl.h
+++ b/runtime/dex_instruction-inl.h
@@ -281,7 +281,7 @@ inline uint16_t Instruction::VRegC_3rc() const {
return Fetch16(2);
}
-inline void Instruction::GetArgs(uint32_t arg[5]) const {
+inline void Instruction::GetArgs(uint32_t arg[5], uint16_t inst_data) const {
DCHECK_EQ(FormatOf(Opcode()), k35c);
/*
@@ -295,7 +295,8 @@ inline void Instruction::GetArgs(uint32_t arg[5]) const {
* method constant (or equivalent) is always in vB.
*/
uint16_t regList = Fetch16(2);
- uint4_t count = InstB(); // This is labeled A in the spec.
+ uint4_t count = InstB(inst_data); // This is labeled A in the spec.
+ DCHECK_LE(count, 5U) << "Invalid arg count in 35c (" << count << ")";
/*
* Copy the argument registers into the arg[] array, and
@@ -305,15 +306,13 @@ inline void Instruction::GetArgs(uint32_t arg[5]) const {
* copies of those.) Note that cases 5..2 fall through.
*/
switch (count) {
- case 5: arg[4] = InstA();
+ case 5: arg[4] = InstA(inst_data);
case 4: arg[3] = (regList >> 12) & 0x0f;
case 3: arg[2] = (regList >> 8) & 0x0f;
case 2: arg[1] = (regList >> 4) & 0x0f;
case 1: arg[0] = regList & 0x0f; break;
- case 0: break; // Valid, but no need to do anything.
- default:
- LOG(ERROR) << "Invalid arg count in 35c (" << count << ")";
- return;
+ default: // case 0
+ break; // Valid, but no need to do anything.
}
}
diff --git a/runtime/dex_instruction.h b/runtime/dex_instruction.h
index e8db3bc..c434cdd 100644
--- a/runtime/dex_instruction.h
+++ b/runtime/dex_instruction.h
@@ -365,7 +365,10 @@ class Instruction {
uint16_t VRegC_3rc() const;
// Fills the given array with the 'arg' array of the instruction.
- void GetArgs(uint32_t args[5]) const;
+ void GetArgs(uint32_t args[5], uint16_t inst_data) const;
+ void GetArgs(uint32_t args[5]) const {
+ return GetArgs(args, Fetch16(0));
+ }
// Returns the opcode field of the instruction. The given "inst_data" parameter must be the first
// 16 bits of instruction.
diff --git a/runtime/entrypoints/interpreter/interpreter_entrypoints.cc b/runtime/entrypoints/interpreter/interpreter_entrypoints.cc
index ecf98bc..05c02f2 100644
--- a/runtime/entrypoints/interpreter/interpreter_entrypoints.cc
+++ b/runtime/entrypoints/interpreter/interpreter_entrypoints.cc
@@ -31,7 +31,15 @@ extern "C" void artInterpreterToCompiledCodeBridge(Thread* self, MethodHelper& m
mirror::ArtMethod* method = shadow_frame->GetMethod();
// Ensure static methods are initialized.
if (method->IsStatic()) {
- Runtime::Current()->GetClassLinker()->EnsureInitialized(method->GetDeclaringClass(), true, true);
+ mirror::Class* declaringClass = method->GetDeclaringClass();
+ if (UNLIKELY(!declaringClass->IsInitializing())) {
+ if (UNLIKELY(!Runtime::Current()->GetClassLinker()->EnsureInitialized(declaringClass,
+ true, true))) {
+ DCHECK(Thread::Current()->IsExceptionPending());
+ return;
+ }
+ CHECK(declaringClass->IsInitializing());
+ }
}
uint16_t arg_offset = (code_item == NULL) ? 0 : code_item->registers_size_ - code_item->ins_size_;
#if defined(ART_USE_PORTABLE_COMPILER)
@@ -40,7 +48,7 @@ extern "C" void artInterpreterToCompiledCodeBridge(Thread* self, MethodHelper& m
method->Invoke(self, arg_array.GetArray(), arg_array.GetNumBytes(), result, mh.GetShorty()[0]);
#else
method->Invoke(self, shadow_frame->GetVRegArgs(arg_offset),
- (shadow_frame->NumberOfVRegs() - arg_offset) * 4,
+ (shadow_frame->NumberOfVRegs() - arg_offset) * sizeof(uint32_t),
result, mh.GetShorty()[0]);
#endif
}
diff --git a/runtime/interpreter/interpreter.cc b/runtime/interpreter/interpreter.cc
index fd92e06..8aa6fa2 100644
--- a/runtime/interpreter/interpreter.cc
+++ b/runtime/interpreter/interpreter.cc
@@ -422,15 +422,18 @@ extern "C" void artInterpreterToInterpreterBridge(Thread* self, MethodHelper& mh
}
ArtMethod* method = shadow_frame->GetMethod();
- if (method->IsStatic() && !method->GetDeclaringClass()->IsInitializing()) {
- if (!Runtime::Current()->GetClassLinker()->EnsureInitialized(method->GetDeclaringClass(),
- true, true)) {
- DCHECK(Thread::Current()->IsExceptionPending());
- return;
+ // Ensure static methods are initialized.
+ if (method->IsStatic()) {
+ Class* declaringClass = method->GetDeclaringClass();
+ if (UNLIKELY(!declaringClass->IsInitializing())) {
+ if (UNLIKELY(!Runtime::Current()->GetClassLinker()->EnsureInitialized(declaringClass,
+ true, true))) {
+ DCHECK(Thread::Current()->IsExceptionPending());
+ return;
+ }
+ CHECK(declaringClass->IsInitializing());
}
- CHECK(method->GetDeclaringClass()->IsInitializing());
}
-
self->PushShadowFrame(shadow_frame);
if (LIKELY(!method->IsNative())) {
@@ -445,7 +448,6 @@ extern "C" void artInterpreterToInterpreterBridge(Thread* self, MethodHelper& mh
}
self->PopShadowFrame();
- return;
}
} // namespace interpreter
diff --git a/runtime/interpreter/interpreter_common.cc b/runtime/interpreter/interpreter_common.cc
index 36b250c..4992031 100644
--- a/runtime/interpreter/interpreter_common.cc
+++ b/runtime/interpreter/interpreter_common.cc
@@ -19,62 +19,59 @@
namespace art {
namespace interpreter {
-template<InvokeType type, bool is_range, bool do_access_check>
-bool DoInvoke(Thread* self, ShadowFrame& shadow_frame,
- const Instruction* inst, JValue* result) {
- bool do_assignability_check = do_access_check;
- uint32_t method_idx = (is_range) ? inst->VRegB_3rc() : inst->VRegB_35c();
- uint32_t vregC = (is_range) ? inst->VRegC_3rc() : inst->VRegC_35c();
- Object* receiver = (type == kStatic) ? NULL : shadow_frame.GetVRegReference(vregC);
- ArtMethod* method = FindMethodFromCode(method_idx, receiver, shadow_frame.GetMethod(), self,
- do_access_check, type);
- if (UNLIKELY(method == NULL)) {
- CHECK(self->IsExceptionPending());
- result->SetJ(0);
- return false;
- } else if (UNLIKELY(method->IsAbstract())) {
- ThrowAbstractMethodError(method);
- result->SetJ(0);
- return false;
- }
+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_);
+template<bool is_range, bool do_assignability_check>
+bool DoCall(ArtMethod* method, Object* receiver, Thread* self, ShadowFrame& shadow_frame,
+ const Instruction* inst, uint16_t inst_data, JValue* result) {
+ // Compute method information.
MethodHelper mh(method);
const DexFile::CodeItem* code_item = mh.GetCodeItem();
+ const uint16_t num_ins = (is_range) ? inst->VRegA_3rc(inst_data) : inst->VRegA_35c(inst_data);
uint16_t num_regs;
- uint16_t num_ins;
if (LIKELY(code_item != NULL)) {
num_regs = code_item->registers_size_;
- num_ins = code_item->ins_size_;
+ DCHECK_EQ(num_ins, code_item->ins_size_);
} else {
DCHECK(method->IsNative() || method->IsProxyMethod());
- num_regs = num_ins = ArtMethod::NumArgRegisters(mh.GetShorty());
- if (!method->IsStatic()) {
- num_regs++;
- num_ins++;
- }
+ num_regs = num_ins;
}
+ // Allocate shadow frame on the stack.
void* memory = alloca(ShadowFrame::ComputeSize(num_regs));
ShadowFrame* new_shadow_frame(ShadowFrame::Create(num_regs, &shadow_frame, method, 0, memory));
+
+ // Initialize new shadow frame.
size_t cur_reg = num_regs - num_ins;
+ size_t arg_offset = 0;
if (receiver != NULL) {
+ DCHECK(!method->IsStatic());
new_shadow_frame->SetVRegReference(cur_reg, receiver);
++cur_reg;
+ ++arg_offset;
+ } else {
+ DCHECK(method->IsStatic());
}
const DexFile::TypeList* params;
if (do_assignability_check) {
params = mh.GetParameterTypeList();
}
- size_t arg_offset = (receiver == NULL) ? 0 : 1;
const char* shorty = mh.GetShorty();
- uint32_t arg[5];
- if (!is_range) {
- inst->GetArgs(arg);
+ // TODO: find a cleaner way to separate non-range and range information.
+ uint32_t arg[5]; // only used in invoke-XXX.
+ uint32_t vregC; // only used in invoke-XXX-range.
+ if (is_range) {
+ vregC = inst->VRegC_3rc();
+ } else {
+ inst->GetArgs(arg, inst_data);
}
- for (size_t shorty_pos = 0; cur_reg < num_regs; ++shorty_pos, cur_reg++, arg_offset++) {
+ for (size_t shorty_pos = 0; cur_reg < num_regs; ++shorty_pos, ++cur_reg, ++arg_offset) {
DCHECK_LT(shorty_pos + 1, mh.GetShortyLength());
- size_t arg_pos = is_range ? vregC + arg_offset : arg[arg_offset];
+ size_t arg_pos = (is_range) ? vregC + arg_offset : arg[arg_offset];
switch (shorty[shorty_pos + 1]) {
case 'L': {
Object* o = shadow_frame.GetVRegReference(arg_pos);
@@ -102,94 +99,8 @@ bool DoInvoke(Thread* self, ShadowFrame& shadow_frame,
uint64_t wide_value = (static_cast<uint64_t>(shadow_frame.GetVReg(arg_pos + 1)) << 32) |
static_cast<uint32_t>(shadow_frame.GetVReg(arg_pos));
new_shadow_frame->SetVRegLong(cur_reg, wide_value);
- cur_reg++;
- arg_offset++;
- break;
- }
- default:
- new_shadow_frame->SetVReg(cur_reg, shadow_frame.GetVReg(arg_pos));
- break;
- }
- }
-
- if (LIKELY(Runtime::Current()->IsStarted())) {
- (method->GetEntryPointFromInterpreter())(self, mh, code_item, new_shadow_frame, result);
- } else {
- UnstartedRuntimeInvoke(self, mh, code_item, new_shadow_frame, result, num_regs - num_ins);
- }
- return !self->IsExceptionPending();
-}
-
-template<bool is_range>
-bool DoInvokeVirtualQuick(Thread* self, ShadowFrame& shadow_frame,
- const Instruction* inst, JValue* result) {
- uint32_t vregC = (is_range) ? inst->VRegC_3rc() : inst->VRegC_35c();
- Object* receiver = shadow_frame.GetVRegReference(vregC);
- if (UNLIKELY(receiver == NULL)) {
- // We lost the reference to the method index so we cannot get a more
- // precised exception message.
- ThrowNullPointerExceptionFromDexPC(shadow_frame.GetCurrentLocationForThrow());
- return false;
- }
- uint32_t vtable_idx = (is_range) ? inst->VRegB_3rc() : inst->VRegB_35c();
- // TODO: use ObjectArray<T>::GetWithoutChecks ?
- ArtMethod* method = receiver->GetClass()->GetVTable()->Get(vtable_idx);
- if (UNLIKELY(method == NULL)) {
- CHECK(self->IsExceptionPending());
- result->SetJ(0);
- return false;
- } else if (UNLIKELY(method->IsAbstract())) {
- ThrowAbstractMethodError(method);
- result->SetJ(0);
- return false;
- }
-
- MethodHelper mh(method);
- const DexFile::CodeItem* code_item = mh.GetCodeItem();
- uint16_t num_regs;
- uint16_t num_ins;
- if (code_item != NULL) {
- num_regs = code_item->registers_size_;
- num_ins = code_item->ins_size_;
- } else {
- DCHECK(method->IsNative() || method->IsProxyMethod());
- num_regs = num_ins = ArtMethod::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,
- method, 0, memory));
- size_t cur_reg = num_regs - num_ins;
- if (receiver != NULL) {
- new_shadow_frame->SetVRegReference(cur_reg, receiver);
- ++cur_reg;
- }
-
- size_t arg_offset = (receiver == NULL) ? 0 : 1;
- 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, mh.GetShortyLength());
- size_t arg_pos = is_range ? vregC + arg_offset : arg[arg_offset];
- switch (shorty[shorty_pos + 1]) {
- case 'L': {
- Object* o = shadow_frame.GetVRegReference(arg_pos);
- new_shadow_frame->SetVRegReference(cur_reg, o);
- break;
- }
- case 'J': case 'D': {
- uint64_t wide_value = (static_cast<uint64_t>(shadow_frame.GetVReg(arg_pos + 1)) << 32) |
- static_cast<uint32_t>(shadow_frame.GetVReg(arg_pos));
- new_shadow_frame->SetVRegLong(cur_reg, wide_value);
- cur_reg++;
- arg_offset++;
+ ++cur_reg;
+ ++arg_offset;
break;
}
default:
@@ -198,6 +109,7 @@ bool DoInvokeVirtualQuick(Thread* self, ShadowFrame& shadow_frame,
}
}
+ // Do the call now.
if (LIKELY(Runtime::Current()->IsStarted())) {
(method->GetEntryPointFromInterpreter())(self, mh, code_item, new_shadow_frame, result);
} else {
@@ -273,9 +185,9 @@ bool DoFilledNewArray(const Instruction* inst, const ShadowFrame& shadow_frame,
return true;
}
-void UnstartedRuntimeInvoke(Thread* self, MethodHelper& mh,
- const DexFile::CodeItem* code_item, 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) {
// In a runtime that's not started we intercept certain methods to avoid complicated dependency
// problems in core libraries.
std::string name(PrettyMethod(shadow_frame->GetMethod()));
@@ -367,34 +279,17 @@ void UnstartedRuntimeInvoke(Thread* self, MethodHelper& mh,
}
}
-// Explicit DoInvoke template function declarations.
-#define EXPLICIT_DO_INVOKE_TEMPLATE_DECL(_type, _is_range_, _check) \
- template bool DoInvoke<_type, _is_range_, _check>(Thread* self, ShadowFrame& shadow_frame, \
- const Instruction* inst, JValue* result)
-
-#define EXPLICIT_DO_INVOKE_TEMPLATE_DECL_VARIANTS(_type) \
- EXPLICIT_DO_INVOKE_TEMPLATE_DECL(_type, false, false); \
- EXPLICIT_DO_INVOKE_TEMPLATE_DECL(_type, false, true); \
- EXPLICIT_DO_INVOKE_TEMPLATE_DECL(_type, true, false); \
- EXPLICIT_DO_INVOKE_TEMPLATE_DECL(_type, true, true)
-
-EXPLICIT_DO_INVOKE_TEMPLATE_DECL_VARIANTS(kStatic);
-EXPLICIT_DO_INVOKE_TEMPLATE_DECL_VARIANTS(kDirect);
-EXPLICIT_DO_INVOKE_TEMPLATE_DECL_VARIANTS(kVirtual);
-EXPLICIT_DO_INVOKE_TEMPLATE_DECL_VARIANTS(kSuper);
-EXPLICIT_DO_INVOKE_TEMPLATE_DECL_VARIANTS(kInterface);
-
-#undef EXPLICIT_DO_INVOKE_TEMPLATE_DECL_VARIANTS
-#undef EXPLICIT_DO_INVOKE_TEMPLATE_DECL
-
-// Explicit DoInvokeVirtualQuick template function declarations.
-#define EXPLICIT_DO_INVOKE_VIRTUAL_QUICK_TEMPLATE_DECL(_is_range) \
-template bool DoInvokeVirtualQuick<_is_range>(Thread* self, ShadowFrame& shadow_frame, \
- const Instruction* inst, JValue* result)
-
-EXPLICIT_DO_INVOKE_VIRTUAL_QUICK_TEMPLATE_DECL(false);
-EXPLICIT_DO_INVOKE_VIRTUAL_QUICK_TEMPLATE_DECL(true);
-#undef EXPLICIT_DO_INVOKE_VIRTUAL_QUICK_TEMPLATE_DECL
+// Explicit DoCall template function declarations.
+#define EXPLICIT_DO_CALL_TEMPLATE_DECL(_is_range, _do_assignability_check) \
+template bool DoCall<_is_range, _do_assignability_check>(ArtMethod* method, Object* receiver, \
+ Thread* self, ShadowFrame& shadow_frame, \
+ const Instruction* inst, \
+ uint16_t inst_data, JValue* result)
+EXPLICIT_DO_CALL_TEMPLATE_DECL(false, false);
+EXPLICIT_DO_CALL_TEMPLATE_DECL(false, true);
+EXPLICIT_DO_CALL_TEMPLATE_DECL(true, false);
+EXPLICIT_DO_CALL_TEMPLATE_DECL(true, true);
+#undef EXPLICIT_DO_CALL_TEMPLATE_DECL
// Explicit DoFilledNewArray template function declarations.
#define EXPLICIT_DO_FILLED_NEW_ARRAY_TEMPLATE_DECL(_is_range_, _check) \
diff --git a/runtime/interpreter/interpreter_common.h b/runtime/interpreter/interpreter_common.h
index 3ad1935..80502b4 100644
--- a/runtime/interpreter/interpreter_common.h
+++ b/runtime/interpreter/interpreter_common.h
@@ -71,7 +71,7 @@ template<bool do_access_check>
extern JValue ExecuteSwitchImpl(Thread* self, MethodHelper& mh,
const DexFile::CodeItem* code_item,
ShadowFrame& shadow_frame, JValue result_register)
- NO_THREAD_SAFETY_ANALYSIS __attribute__((hot));
+ NO_THREAD_SAFETY_ANALYSIS HOT_ATTR;
// TODO: should be SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) which is failing due to template
// specialization.
@@ -79,12 +79,7 @@ template<bool do_access_check>
extern JValue ExecuteGotoImpl(Thread* self, MethodHelper& mh,
const DexFile::CodeItem* code_item,
ShadowFrame& shadow_frame, JValue result_register)
- NO_THREAD_SAFETY_ANALYSIS __attribute__((hot));
-
-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_);
+ NO_THREAD_SAFETY_ANALYSIS HOT_ATTR;
static inline void DoMonitorEnter(Thread* self, Object* ref) NO_THREAD_SAFETY_ANALYSIS {
ref->MonitorEnter(self);
@@ -96,16 +91,72 @@ static inline void DoMonitorExit(Thread* self, Object* ref) NO_THREAD_SAFETY_ANA
// TODO: should be SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) which is failing due to template
// specialization.
+template<bool is_range, bool do_assignability_check>
+bool DoCall(ArtMethod* method, Object* receiver, Thread* self, ShadowFrame& shadow_frame,
+ const Instruction* inst, uint16_t inst_data, JValue* result) NO_THREAD_SAFETY_ANALYSIS;
+
+// TODO: should be SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) which is failing due to template
+// specialization.
template<InvokeType type, bool is_range, bool do_access_check>
-bool DoInvoke(Thread* self, ShadowFrame& shadow_frame,
- const Instruction* inst, JValue* result) NO_THREAD_SAFETY_ANALYSIS;
+static bool DoInvoke(Thread* self, ShadowFrame& shadow_frame, const Instruction* inst,
+ uint16_t inst_data, JValue* result) NO_THREAD_SAFETY_ANALYSIS ALWAYS_INLINE;
+
+template<InvokeType type, bool is_range, bool do_access_check>
+static inline bool DoInvoke(Thread* self, ShadowFrame& shadow_frame, const Instruction* inst,
+ uint16_t inst_data, JValue* result) {
+ const uint32_t method_idx = (is_range) ? inst->VRegB_3rc() : inst->VRegB_35c();
+ const uint32_t vregC = (is_range) ? inst->VRegC_3rc() : inst->VRegC_35c();
+ Object* const receiver = (type == kStatic) ? NULL : shadow_frame.GetVRegReference(vregC);
+ ArtMethod* const method = FindMethodFromCode(method_idx, receiver, shadow_frame.GetMethod(), self,
+ do_access_check, type);
+ if (UNLIKELY(method == NULL)) {
+ CHECK(self->IsExceptionPending());
+ result->SetJ(0);
+ return false;
+ } else if (UNLIKELY(method->IsAbstract())) {
+ ThrowAbstractMethodError(method);
+ result->SetJ(0);
+ return false;
+ } else {
+ return DoCall<is_range, do_access_check>(method, receiver, self, shadow_frame, inst,
+ inst_data, result);
+ }
+}
// TODO: should be SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) which is failing due to template
// specialization.
template<bool is_range>
-bool DoInvokeVirtualQuick(Thread* self, ShadowFrame& shadow_frame,
- const Instruction* inst, JValue* result)
- NO_THREAD_SAFETY_ANALYSIS;
+static bool DoInvokeVirtualQuick(Thread* self, ShadowFrame& shadow_frame, const Instruction* inst,
+ uint16_t inst_data, JValue* result)
+ NO_THREAD_SAFETY_ANALYSIS ALWAYS_INLINE;
+
+template<bool is_range>
+static inline bool DoInvokeVirtualQuick(Thread* self, ShadowFrame& shadow_frame,
+ const Instruction* inst, uint16_t inst_data,
+ JValue* result) {
+ const uint32_t vregC = (is_range) ? inst->VRegC_3rc() : inst->VRegC_35c();
+ Object* const receiver = shadow_frame.GetVRegReference(vregC);
+ if (UNLIKELY(receiver == NULL)) {
+ // We lost the reference to the method index so we cannot get a more
+ // precised exception message.
+ ThrowNullPointerExceptionFromDexPC(shadow_frame.GetCurrentLocationForThrow());
+ return false;
+ }
+ const uint32_t vtable_idx = (is_range) ? inst->VRegB_3rc() : inst->VRegB_35c();
+ ArtMethod* const method = receiver->GetClass()->GetVTable()->GetWithoutChecks(vtable_idx);
+ if (UNLIKELY(method == NULL)) {
+ CHECK(self->IsExceptionPending());
+ result->SetJ(0);
+ return false;
+ } else if (UNLIKELY(method->IsAbstract())) {
+ ThrowAbstractMethodError(method);
+ result->SetJ(0);
+ return false;
+ } else {
+ // No need to check since we've been quickened.
+ return DoCall<is_range, false>(method, receiver, self, shadow_frame, inst, inst_data, result);
+ }
+}
// We use template functions to optimize compiler inlining process. Otherwise,
// some parts of the code (like a switch statement) which depend on a constant
@@ -283,11 +334,11 @@ static inline bool DoFieldPut(Thread* self, const ShadowFrame& shadow_frame,
// TODO: should be SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) which is failing due to template
// specialization.
template<Primitive::Type field_type>
-static bool DoIPutQuick(ShadowFrame& shadow_frame, const Instruction* inst, uint16_t inst_data)
+static bool DoIPutQuick(const ShadowFrame& shadow_frame, const Instruction* inst, uint16_t inst_data)
NO_THREAD_SAFETY_ANALYSIS ALWAYS_INLINE;
template<Primitive::Type field_type>
-static inline bool DoIPutQuick(ShadowFrame& shadow_frame, const Instruction* inst, uint16_t inst_data) {
+static inline bool DoIPutQuick(const ShadowFrame& shadow_frame, const Instruction* inst, uint16_t inst_data) {
Object* obj = shadow_frame.GetVRegReference(inst->VRegB_22c(inst_data));
if (UNLIKELY(obj == NULL)) {
// We lost the reference to the field index so we cannot get a more
diff --git a/runtime/interpreter/interpreter_goto_table_impl.cc b/runtime/interpreter/interpreter_goto_table_impl.cc
index 018add3..5a00831 100644
--- a/runtime/interpreter/interpreter_goto_table_impl.cc
+++ b/runtime/interpreter/interpreter_goto_table_impl.cc
@@ -29,7 +29,6 @@ namespace interpreter {
// - "currentHandlersTable": the current table of pointer to each instruction handler.
// Advance to the next instruction and updates interpreter state.
-// TODO: move check suspend to backward branch, return and exception handling.
#define ADVANCE(_offset) \
do { \
int32_t disp = static_cast<int32_t>(_offset); \
@@ -1339,84 +1338,84 @@ JValue ExecuteGotoImpl(Thread* self, MethodHelper& mh, const DexFile::CodeItem*
HANDLE_INSTRUCTION_END();
HANDLE_INSTRUCTION_START(INVOKE_VIRTUAL) {
- bool success = DoInvoke<kVirtual, false, do_access_check>(self, shadow_frame, inst, &result_register);
+ bool success = DoInvoke<kVirtual, false, do_access_check>(self, shadow_frame, inst, inst_data, &result_register);
UPDATE_HANDLER_TABLE();
POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, 3);
}
HANDLE_INSTRUCTION_END();
HANDLE_INSTRUCTION_START(INVOKE_VIRTUAL_RANGE) {
- bool success = DoInvoke<kVirtual, true, do_access_check>(self, shadow_frame, inst, &result_register);
+ bool success = DoInvoke<kVirtual, true, do_access_check>(self, shadow_frame, inst, inst_data, &result_register);
UPDATE_HANDLER_TABLE();
POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, 3);
}
HANDLE_INSTRUCTION_END();
HANDLE_INSTRUCTION_START(INVOKE_SUPER) {
- bool success = DoInvoke<kSuper, false, do_access_check>(self, shadow_frame, inst, &result_register);
+ bool success = DoInvoke<kSuper, false, do_access_check>(self, shadow_frame, inst, inst_data, &result_register);
UPDATE_HANDLER_TABLE();
POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, 3);
}
HANDLE_INSTRUCTION_END();
HANDLE_INSTRUCTION_START(INVOKE_SUPER_RANGE) {
- bool success = DoInvoke<kSuper, true, do_access_check>(self, shadow_frame, inst, &result_register);
+ bool success = DoInvoke<kSuper, true, do_access_check>(self, shadow_frame, inst, inst_data, &result_register);
UPDATE_HANDLER_TABLE();
POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, 3);
}
HANDLE_INSTRUCTION_END();
HANDLE_INSTRUCTION_START(INVOKE_DIRECT) {
- bool success = DoInvoke<kDirect, false, do_access_check>(self, shadow_frame, inst, &result_register);
+ bool success = DoInvoke<kDirect, false, do_access_check>(self, shadow_frame, inst, inst_data, &result_register);
UPDATE_HANDLER_TABLE();
POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, 3);
}
HANDLE_INSTRUCTION_END();
HANDLE_INSTRUCTION_START(INVOKE_DIRECT_RANGE) {
- bool success = DoInvoke<kDirect, true, do_access_check>(self, shadow_frame, inst, &result_register);
+ bool success = DoInvoke<kDirect, true, do_access_check>(self, shadow_frame, inst, inst_data, &result_register);
UPDATE_HANDLER_TABLE();
POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, 3);
}
HANDLE_INSTRUCTION_END();
HANDLE_INSTRUCTION_START(INVOKE_INTERFACE) {
- bool success = DoInvoke<kInterface, false, do_access_check>(self, shadow_frame, inst, &result_register);
+ bool success = DoInvoke<kInterface, false, do_access_check>(self, shadow_frame, inst, inst_data, &result_register);
UPDATE_HANDLER_TABLE();
POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, 3);
}
HANDLE_INSTRUCTION_END();
HANDLE_INSTRUCTION_START(INVOKE_INTERFACE_RANGE) {
- bool success = DoInvoke<kInterface, true, do_access_check>(self, shadow_frame, inst, &result_register);
+ bool success = DoInvoke<kInterface, true, do_access_check>(self, shadow_frame, inst, inst_data, &result_register);
UPDATE_HANDLER_TABLE();
POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, 3);
}
HANDLE_INSTRUCTION_END();
HANDLE_INSTRUCTION_START(INVOKE_STATIC) {
- bool success = DoInvoke<kStatic, false, do_access_check>(self, shadow_frame, inst, &result_register);
+ bool success = DoInvoke<kStatic, false, do_access_check>(self, shadow_frame, inst, inst_data, &result_register);
UPDATE_HANDLER_TABLE();
POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, 3);
}
HANDLE_INSTRUCTION_END();
HANDLE_INSTRUCTION_START(INVOKE_STATIC_RANGE) {
- bool success = DoInvoke<kStatic, true, do_access_check>(self, shadow_frame, inst, &result_register);
+ bool success = DoInvoke<kStatic, true, do_access_check>(self, shadow_frame, inst, inst_data, &result_register);
UPDATE_HANDLER_TABLE();
POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, 3);
}
HANDLE_INSTRUCTION_END();
HANDLE_INSTRUCTION_START(INVOKE_VIRTUAL_QUICK) {
- bool success = DoInvokeVirtualQuick<false>(self, shadow_frame, inst, &result_register);
+ bool success = DoInvokeVirtualQuick<false>(self, shadow_frame, inst, inst_data, &result_register);
UPDATE_HANDLER_TABLE();
POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, 3);
}
HANDLE_INSTRUCTION_END();
HANDLE_INSTRUCTION_START(INVOKE_VIRTUAL_RANGE_QUICK) {
- bool success = DoInvokeVirtualQuick<true>(self, shadow_frame, inst, &result_register);
+ bool success = DoInvokeVirtualQuick<true>(self, shadow_frame, inst, inst_data, &result_register);
UPDATE_HANDLER_TABLE();
POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, 3);
}
diff --git a/runtime/interpreter/interpreter_switch_impl.cc b/runtime/interpreter/interpreter_switch_impl.cc
index 2d658b3..82f216a 100644
--- a/runtime/interpreter/interpreter_switch_impl.cc
+++ b/runtime/interpreter/interpreter_switch_impl.cc
@@ -1283,73 +1283,73 @@ static JValue ExecuteSwitchImpl(Thread* self, MethodHelper& mh, const DexFile::C
}
case Instruction::INVOKE_VIRTUAL: {
PREAMBLE();
- bool success = DoInvoke<kVirtual, false, do_access_check>(self, shadow_frame, inst, &result_register);
+ bool success = DoInvoke<kVirtual, false, do_access_check>(self, shadow_frame, inst, inst_data, &result_register);
POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_3xx);
break;
}
case Instruction::INVOKE_VIRTUAL_RANGE: {
PREAMBLE();
- bool success = DoInvoke<kVirtual, true, do_access_check>(self, shadow_frame, inst, &result_register);
+ bool success = DoInvoke<kVirtual, true, do_access_check>(self, shadow_frame, inst, inst_data, &result_register);
POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_3xx);
break;
}
case Instruction::INVOKE_SUPER: {
PREAMBLE();
- bool success = DoInvoke<kSuper, false, do_access_check>(self, shadow_frame, inst, &result_register);
+ bool success = DoInvoke<kSuper, false, do_access_check>(self, shadow_frame, inst, inst_data, &result_register);
POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_3xx);
break;
}
case Instruction::INVOKE_SUPER_RANGE: {
PREAMBLE();
- bool success = DoInvoke<kSuper, true, do_access_check>(self, shadow_frame, inst, &result_register);
+ bool success = DoInvoke<kSuper, true, do_access_check>(self, shadow_frame, inst, inst_data, &result_register);
POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_3xx);
break;
}
case Instruction::INVOKE_DIRECT: {
PREAMBLE();
- bool success = DoInvoke<kDirect, false, do_access_check>(self, shadow_frame, inst, &result_register);
+ bool success = DoInvoke<kDirect, false, do_access_check>(self, shadow_frame, inst, inst_data, &result_register);
POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_3xx);
break;
}
case Instruction::INVOKE_DIRECT_RANGE: {
PREAMBLE();
- bool success = DoInvoke<kDirect, true, do_access_check>(self, shadow_frame, inst, &result_register);
+ bool success = DoInvoke<kDirect, true, do_access_check>(self, shadow_frame, inst, inst_data, &result_register);
POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_3xx);
break;
}
case Instruction::INVOKE_INTERFACE: {
PREAMBLE();
- bool success = DoInvoke<kInterface, false, do_access_check>(self, shadow_frame, inst, &result_register);
+ bool success = DoInvoke<kInterface, false, do_access_check>(self, shadow_frame, inst, inst_data, &result_register);
POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_3xx);
break;
}
case Instruction::INVOKE_INTERFACE_RANGE: {
PREAMBLE();
- bool success = DoInvoke<kInterface, true, do_access_check>(self, shadow_frame, inst, &result_register);
+ bool success = DoInvoke<kInterface, true, do_access_check>(self, shadow_frame, inst, inst_data, &result_register);
POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_3xx);
break;
}
case Instruction::INVOKE_STATIC: {
PREAMBLE();
- bool success = DoInvoke<kStatic, false, do_access_check>(self, shadow_frame, inst, &result_register);
+ bool success = DoInvoke<kStatic, false, do_access_check>(self, shadow_frame, inst, inst_data, &result_register);
POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_3xx);
break;
}
case Instruction::INVOKE_STATIC_RANGE: {
PREAMBLE();
- bool success = DoInvoke<kStatic, true, do_access_check>(self, shadow_frame, inst, &result_register);
+ bool success = DoInvoke<kStatic, true, do_access_check>(self, shadow_frame, inst, inst_data, &result_register);
POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_3xx);
break;
}
case Instruction::INVOKE_VIRTUAL_QUICK: {
PREAMBLE();
- bool success = DoInvokeVirtualQuick<false>(self, shadow_frame, inst, &result_register);
+ bool success = DoInvokeVirtualQuick<false>(self, shadow_frame, inst, inst_data, &result_register);
POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_3xx);
break;
}
case Instruction::INVOKE_VIRTUAL_RANGE_QUICK: {
PREAMBLE();
- bool success = DoInvokeVirtualQuick<true>(self, shadow_frame, inst, &result_register);
+ bool success = DoInvokeVirtualQuick<true>(self, shadow_frame, inst, inst_data, &result_register);
POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_3xx);
break;
}
diff --git a/runtime/stack.h b/runtime/stack.h
index 2bf3340..700b7f1 100644
--- a/runtime/stack.h
+++ b/runtime/stack.h
@@ -68,8 +68,7 @@ class ShadowFrame {
static ShadowFrame* Create(uint32_t num_vregs, ShadowFrame* link,
mirror::ArtMethod* method, uint32_t dex_pc) {
uint8_t* memory = new uint8_t[ComputeSize(num_vregs)];
- ShadowFrame* sf = new (memory) ShadowFrame(num_vregs, link, method, dex_pc, true);
- return sf;
+ return Create(num_vregs, link, method, dex_pc, memory);
}
// Create ShadowFrame for interpreter using provided memory.