Change MethodHelper to use a Handle.
Added ConstHandle to help prevent errors where you modify the value
stored in the handle of the caller. Also fixed compaction bugs
related to not knowing MethodHelper::GetReturnType can resolve types.
This bug was present in interpreter RETURN_OBJECT.
Bug: 13077697
Change-Id: I71f964d4d810ab4debda1a09bc968af8f3c874a3
diff --git a/runtime/entrypoints/quick/quick_trampoline_entrypoints.cc b/runtime/entrypoints/quick/quick_trampoline_entrypoints.cc
index 5374f22..05033fc 100644
--- a/runtime/entrypoints/quick/quick_trampoline_entrypoints.cc
+++ b/runtime/entrypoints/quick/quick_trampoline_entrypoints.cc
@@ -474,16 +474,16 @@
} else {
DCHECK(!method->IsNative()) << PrettyMethod(method);
const char* old_cause = self->StartAssertNoThreadSuspension("Building interpreter shadow frame");
- MethodHelper mh(method);
- const DexFile::CodeItem* code_item = mh.GetCodeItem();
+ const DexFile::CodeItem* code_item = method->GetCodeItem();
DCHECK(code_item != nullptr) << PrettyMethod(method);
uint16_t num_regs = code_item->registers_size_;
void* memory = alloca(ShadowFrame::ComputeSize(num_regs));
ShadowFrame* shadow_frame(ShadowFrame::Create(num_regs, NULL, // No last shadow coming from quick.
method, 0, memory));
size_t first_arg_reg = code_item->registers_size_ - code_item->ins_size_;
- BuildQuickShadowFrameVisitor shadow_frame_builder(sp, mh.IsStatic(), mh.GetShorty(),
- mh.GetShortyLength(),
+ uint32_t shorty_len = 0;
+ const char* shorty = method->GetShorty(&shorty_len);
+ BuildQuickShadowFrameVisitor shadow_frame_builder(sp, method->IsStatic(), shorty, shorty_len,
shadow_frame, first_arg_reg);
shadow_frame_builder.VisitArguments();
// Push a transition back into managed code onto the linked list in thread.
@@ -503,6 +503,8 @@
}
}
+ StackHandleScope<1> hs(self);
+ MethodHelper mh(hs.NewHandle(method));
JValue result = interpreter::EnterInterpreterFromStub(self, mh, code_item, *shadow_frame);
// Pop transition.
self->PopManagedStackFragment(fragment);
@@ -604,11 +606,13 @@
jobject rcvr_jobj = soa.AddLocalReference<jobject>(receiver);
// Placing arguments into args vector and remove the receiver.
- MethodHelper proxy_mh(proxy_method);
- DCHECK(!proxy_mh.IsStatic()) << PrettyMethod(proxy_method);
+ mirror::ArtMethod* non_proxy_method = proxy_method->GetInterfaceMethodIfProxy();
+ CHECK(!non_proxy_method->IsStatic()) << PrettyMethod(proxy_method) << " "
+ << PrettyMethod(non_proxy_method);
std::vector<jvalue> args;
- BuildQuickArgumentVisitor local_ref_visitor(sp, proxy_mh.IsStatic(), proxy_mh.GetShorty(),
- proxy_mh.GetShortyLength(), &soa, &args);
+ uint32_t shorty_len = 0;
+ const char* shorty = proxy_method->GetShorty(&shorty_len);
+ BuildQuickArgumentVisitor local_ref_visitor(sp, false, shorty, shorty_len, &soa, &args);
local_ref_visitor.VisitArguments();
DCHECK_GT(args.size(), 0U) << PrettyMethod(proxy_method);
@@ -623,8 +627,7 @@
// All naked Object*s should now be in jobjects, so its safe to go into the main invoke code
// that performs allocations.
self->EndAssertNoThreadSuspension(old_cause);
- JValue result = InvokeProxyInvocationHandler(soa, proxy_mh.GetShorty(),
- rcvr_jobj, interface_method_jobj, args);
+ JValue result = InvokeProxyInvocationHandler(soa, shorty, rcvr_jobj, interface_method_jobj, args);
// Restore references which might have moved.
local_ref_visitor.FixupReferences();
return result.GetJ();
@@ -691,11 +694,8 @@
if (called->IsRuntimeMethod()) {
uint32_t dex_pc = caller->ToDexPc(QuickArgumentVisitor::GetCallingPc(sp));
const DexFile::CodeItem* code;
- {
- MethodHelper mh(caller);
- dex_file = &mh.GetDexFile();
- code = mh.GetCodeItem();
- }
+ dex_file = caller->GetDexFile();
+ code = caller->GetCodeItem();
CHECK_LT(dex_pc, code->insns_size_in_code_units_);
const Instruction* instr = Instruction::At(&code->insns_[dex_pc]);
Instruction::Code instr_code = instr->Opcode();
@@ -751,7 +751,7 @@
} else {
invoke_type = kStatic;
- dex_file = &MethodHelper(called).GetDexFile();
+ dex_file = called->GetDexFile();
dex_method_idx = called->GetDexMethodIndex();
}
uint32_t shorty_len;
@@ -797,9 +797,10 @@
// Calling from one dex file to another, need to compute the method index appropriate to
// the caller's dex file. Since we get here only if the original called was a runtime
// method, we've got the correct dex_file and a dex_method_idx from above.
- DCHECK(&MethodHelper(caller).GetDexFile() == dex_file);
- uint32_t method_index =
- MethodHelper(called).FindDexMethodIndexInOtherDexFile(*dex_file, dex_method_idx);
+ DCHECK_EQ(caller->GetDexFile(), dex_file);
+ StackHandleScope<1> hs(self);
+ MethodHelper mh(hs.NewHandle(called));
+ uint32_t method_index = mh.FindDexMethodIndexInOtherDexFile(*dex_file, dex_method_idx);
if (method_index != DexFile::kDexNoIndex) {
caller->GetDexCacheResolvedMethods()->Set<false>(method_index, called);
}
@@ -1511,10 +1512,9 @@
DCHECK(called->IsNative()) << PrettyMethod(called, true);
// run the visitor
- MethodHelper mh(called);
-
- BuildGenericJniFrameVisitor visitor(&sp, called->IsStatic(), mh.GetShorty(), mh.GetShortyLength(),
- self);
+ uint32_t shorty_len = 0;
+ const char* shorty = called->GetShorty(&shorty_len);
+ BuildGenericJniFrameVisitor visitor(&sp, called->IsStatic(), shorty, shorty_len, self);
visitor.VisitArguments();
visitor.FinalizeHandleScope(self);
@@ -1555,7 +1555,7 @@
// End JNI, as the assembly will move to deliver the exception.
jobject lock = called->IsSynchronized() ? visitor.GetFirstHandleScopeJObject() : nullptr;
- if (mh.GetShorty()[0] == 'L') {
+ if (shorty[0] == 'L') {
artQuickGenericJniEndJNIRef(self, cookie, nullptr, lock);
} else {
artQuickGenericJniEndJNINonRef(self, cookie, lock);
@@ -1594,8 +1594,7 @@
lock = table->GetHandle(0).ToJObject();
}
- MethodHelper mh(called);
- char return_shorty_char = mh.GetShorty()[0];
+ char return_shorty_char = called->GetShorty()[0];
if (return_shorty_char == 'L') {
return artQuickGenericJniEndJNIRef(self, cookie, result.l, lock);
@@ -1721,7 +1720,7 @@
// When we return, the caller will branch to this address, so it had better not be 0!
DCHECK(code != nullptr) << "Code was NULL in method: " << PrettyMethod(method) << " location: "
- << MethodHelper(method).GetDexFile().GetLocation();
+ << method->GetDexFile()->GetLocation();
return GetSuccessValue(code, method);
}
@@ -1870,7 +1869,7 @@
uintptr_t caller_pc = 0;
#endif
uint32_t dex_pc = caller_method->ToDexPc(caller_pc);
- const DexFile::CodeItem* code = MethodHelper(caller_method).GetCodeItem();
+ const DexFile::CodeItem* code = caller_method->GetCodeItem();
CHECK_LT(dex_pc, code->insns_size_in_code_units_);
const Instruction* instr = Instruction::At(&code->insns_[dex_pc]);
Instruction::Code instr_code = instr->Opcode();
@@ -1908,7 +1907,7 @@
// When we return, the caller will branch to this address, so it had better not be 0!
DCHECK(code != nullptr) << "Code was NULL in method: " << PrettyMethod(method) << " location: "
- << MethodHelper(method).GetDexFile().GetLocation();
+ << method->GetDexFile()->GetLocation();
return GetSuccessValue(code, method);
}