diff options
author | 2014-05-21 17:43:44 -0700 | |
---|---|---|
committer | 2014-06-09 12:46:32 -0700 | |
commit | bfd9a4378eacaf2dc2bbe05ad48c5164fc93c9fe (patch) | |
tree | 3d3f667c8232a9c1bb6fe9daea0d364f9ae01d8c | |
parent | 2e1ca953c7fb165da36cc26ea74d3045d7e272c8 (diff) |
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
41 files changed, 711 insertions, 621 deletions
diff --git a/compiler/driver/compiler_driver.cc b/compiler/driver/compiler_driver.cc index 1cfd19461a..16c1e00c83 100644 --- a/compiler/driver/compiler_driver.cc +++ b/compiler/driver/compiler_driver.cc @@ -560,9 +560,8 @@ void CompilerDriver::CompileOne(mirror::ArtMethod* method, TimingLogger* timings soa.AddLocalReference<jobject>(method->GetDeclaringClass()->GetClassLoader())); jclass_loader = soa.Env()->NewGlobalRef(local_class_loader.get()); // Find the dex_file - MethodHelper mh(method); - dex_file = &mh.GetDexFile(); - class_def_idx = mh.GetClassDefIndex(); + dex_file = method->GetDexFile(); + class_def_idx = method->GetClassDefIndex(); } const DexFile::CodeItem* code_item = dex_file->GetCodeItem(method->GetCodeItemOffset()); self->TransitionFromRunnableToSuspended(kNative); @@ -630,7 +629,7 @@ bool CompilerDriver::IsImageClass(const char* descriptor) const { static void ResolveExceptionsForMethod(MethodHelper* mh, std::set<std::pair<uint16_t, const DexFile*>>& exceptions_to_resolve) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - const DexFile::CodeItem* code_item = mh->GetCodeItem(); + const DexFile::CodeItem* code_item = mh->GetMethod()->GetCodeItem(); if (code_item == NULL) { return; // native or abstract method } @@ -650,10 +649,10 @@ static void ResolveExceptionsForMethod(MethodHelper* mh, uint16_t encoded_catch_handler_handlers_type_idx = DecodeUnsignedLeb128(&encoded_catch_handler_list); // Add to set of types to resolve if not already in the dex cache resolved types - if (!mh->IsResolvedTypeIdx(encoded_catch_handler_handlers_type_idx)) { + if (!mh->GetMethod()->IsResolvedTypeIdx(encoded_catch_handler_handlers_type_idx)) { exceptions_to_resolve.insert( std::pair<uint16_t, const DexFile*>(encoded_catch_handler_handlers_type_idx, - &mh->GetDexFile())); + mh->GetMethod()->GetDexFile())); } // ignore address associated with catch handler DecodeUnsignedLeb128(&encoded_catch_handler_list); @@ -669,15 +668,14 @@ static bool ResolveCatchBlockExceptionsClassVisitor(mirror::Class* c, void* arg) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { std::set<std::pair<uint16_t, const DexFile*>>* exceptions_to_resolve = reinterpret_cast<std::set<std::pair<uint16_t, const DexFile*>>*>(arg); - MethodHelper mh; + StackHandleScope<1> hs(Thread::Current()); + MethodHelper mh(hs.NewHandle<mirror::ArtMethod>(nullptr)); for (size_t i = 0; i < c->NumVirtualMethods(); ++i) { - mirror::ArtMethod* m = c->GetVirtualMethod(i); - mh.ChangeMethod(m); + mh.ChangeMethod(c->GetVirtualMethod(i)); ResolveExceptionsForMethod(&mh, *exceptions_to_resolve); } for (size_t i = 0; i < c->NumDirectMethods(); ++i) { - mirror::ArtMethod* m = c->GetDirectMethod(i); - mh.ChangeMethod(m); + mh.ChangeMethod(c->GetDirectMethod(i)); ResolveExceptionsForMethod(&mh, *exceptions_to_resolve); } return true; @@ -1117,8 +1115,7 @@ void CompilerDriver::GetCodeAndMethodForDirectCall(InvokeType* type, InvokeType *stats_flags |= kFlagDirectCallToBoot | kFlagDirectMethodToBoot; } if (!use_dex_cache && compiling_boot) { - MethodHelper mh(method); - if (!IsImageClass(mh.GetDeclaringClassDescriptor())) { + if (!IsImageClass(method->GetDeclaringClassDescriptor())) { // We can only branch directly to Methods that are resolved in the DexCache. // Otherwise we won't invoke the resolution trampoline. use_dex_cache = true; @@ -1131,8 +1128,10 @@ void CompilerDriver::GetCodeAndMethodForDirectCall(InvokeType* type, InvokeType target_method->dex_method_index = method->GetDexMethodIndex(); } else { if (no_guarantee_of_dex_cache_entry) { + StackHandleScope<1> hs(Thread::Current()); + MethodHelper mh(hs.NewHandle(method)); // See if the method is also declared in this dex cache. - uint32_t dex_method_idx = MethodHelper(method).FindDexMethodIndexInOtherDexFile( + uint32_t dex_method_idx = mh.FindDexMethodIndexInOtherDexFile( *target_method->dex_file, target_method->dex_method_index); if (dex_method_idx != DexFile::kDexNoIndex) { target_method->dex_method_index = dex_method_idx; diff --git a/oatdump/oatdump.cc b/oatdump/oatdump.cc index d51179e25a..12970fcaab 100644 --- a/oatdump/oatdump.cc +++ b/oatdump/oatdump.cc @@ -209,7 +209,6 @@ class OatDumper { } const void* GetQuickOatCode(mirror::ArtMethod* m) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - MethodHelper mh(m); for (size_t i = 0; i < oat_dex_files_.size(); i++) { const OatFile::OatDexFile* oat_dex_file = oat_dex_files_[i]; CHECK(oat_dex_file != nullptr); @@ -220,7 +219,7 @@ class OatDumper { << "': " << error_msg; } else { const DexFile::ClassDef* class_def = - dex_file->FindClassDef(mh.GetDeclaringClassDescriptor()); + dex_file->FindClassDef(m->GetDeclaringClassDescriptor()); if (class_def != NULL) { uint16_t class_def_index = dex_file->GetIndexForClassDef(*class_def); const OatFile::OatClass oat_class = oat_dex_file->GetOatClass(class_def_index); @@ -1094,11 +1093,11 @@ class ImageDumper { } } else if (method->IsAbstract() || method->IsCalleeSaveMethod() || method->IsResolutionMethod() || method->IsImtConflictMethod() || - MethodHelper(method).IsClassInitializer()) { + method->IsClassInitializer()) { DCHECK(method->GetNativeGcMap() == NULL) << PrettyMethod(method); DCHECK(method->GetMappingTable() == NULL) << PrettyMethod(method); } else { - const DexFile::CodeItem* code_item = MethodHelper(method).GetCodeItem(); + const DexFile::CodeItem* code_item = method->GetCodeItem(); size_t dex_instruction_bytes = code_item->insns_size_in_code_units_ * 2; state->stats_.dex_instruction_bytes += dex_instruction_bytes; diff --git a/runtime/check_jni.cc b/runtime/check_jni.cc index 46c4389d1d..a81648958b 100644 --- a/runtime/check_jni.cc +++ b/runtime/check_jni.cc @@ -129,7 +129,7 @@ static bool ShouldTrace(JavaVMExt* vm, mirror::ArtMethod* method) // such as NewByteArray. // If -verbose:third-party-jni is on, we want to log any JNI function calls // made by a third-party native method. - std::string class_name(MethodHelper(method).GetDeclaringClassDescriptor()); + std::string class_name(method->GetDeclaringClassDescriptor()); if (!vm->trace.empty() && class_name.find(vm->trace) != std::string::npos) { return true; } @@ -284,7 +284,7 @@ class ScopedCheck { if (m == nullptr) { return; } - if (*expectedType != MethodHelper(m).GetShorty()[0]) { + if (*expectedType != m->GetShorty()[0]) { JniAbortF(function_name_, "the return type of %s does not match %s", function_name_, PrettyMethod(m).c_str()); } diff --git a/runtime/class_linker.cc b/runtime/class_linker.cc index 330b110e90..a43fda1135 100644 --- a/runtime/class_linker.cc +++ b/runtime/class_linker.cc @@ -2807,7 +2807,7 @@ void ClassLinker::ResolveMethodExceptionHandlerTypes(const DexFile& dex_file, } static void CheckProxyConstructor(mirror::ArtMethod* constructor); -static void CheckProxyMethod(mirror::ArtMethod* method, +static void CheckProxyMethod(Handle<mirror::ArtMethod> method, Handle<mirror::ArtMethod> prototype); mirror::Class* ClassLinker::CreateProxyClass(ScopedObjectAccessAlreadyRunnable& soa, jstring name, @@ -2929,11 +2929,12 @@ mirror::Class* ClassLinker::CreateProxyClass(ScopedObjectAccessAlreadyRunnable& CHECK(klass->GetIFields() == nullptr); CheckProxyConstructor(klass->GetDirectMethod(0)); for (size_t i = 0; i < num_virtual_methods; ++i) { - StackHandleScope<1> hs(self); + StackHandleScope<2> hs(self); mirror::ObjectArray<mirror::ArtMethod>* decoded_methods = soa.Decode<mirror::ObjectArray<mirror::ArtMethod>*>(methods); Handle<mirror::ArtMethod> prototype(hs.NewHandle(decoded_methods->Get(i))); - CheckProxyMethod(klass->GetVirtualMethod(i), prototype); + Handle<mirror::ArtMethod> virtual_method(hs.NewHandle(klass->GetVirtualMethod(i))); + CheckProxyMethod(virtual_method, prototype); } mirror::String* decoded_name = soa.Decode<mirror::String*>(name); @@ -3014,9 +3015,9 @@ mirror::ArtMethod* ClassLinker::CreateProxyConstructor(Thread* self, static void CheckProxyConstructor(mirror::ArtMethod* constructor) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { CHECK(constructor->IsConstructor()); - MethodHelper mh(constructor); - CHECK_STREQ(mh.GetName(), "<init>"); - CHECK_STREQ(mh.GetSignature().ToString().c_str(), "(Ljava/lang/reflect/InvocationHandler;)V"); + CHECK_STREQ(constructor->GetName(), "<init>"); + CHECK_STREQ(constructor->GetSignature().ToString().c_str(), + "(Ljava/lang/reflect/InvocationHandler;)V"); DCHECK(constructor->IsPublic()); } @@ -3049,7 +3050,7 @@ mirror::ArtMethod* ClassLinker::CreateProxyMethod(Thread* self, return method; } -static void CheckProxyMethod(mirror::ArtMethod* method, Handle<mirror::ArtMethod> prototype) +static void CheckProxyMethod(Handle<mirror::ArtMethod> method, Handle<mirror::ArtMethod> prototype) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { // Basic sanity CHECK(!prototype->IsFinal()); @@ -3064,9 +3065,9 @@ static void CheckProxyMethod(mirror::ArtMethod* method, Handle<mirror::ArtMethod CHECK_EQ(prototype->GetDexMethodIndex(), method->GetDexMethodIndex()); MethodHelper mh(method); - MethodHelper mh2(prototype.Get()); - CHECK_STREQ(mh.GetName(), mh2.GetName()); - CHECK_STREQ(mh.GetShorty(), mh2.GetShorty()); + MethodHelper mh2(prototype); + CHECK_STREQ(method->GetName(), prototype->GetName()); + CHECK_STREQ(method->GetShorty(), prototype->GetShorty()); // More complex sanity - via dex cache CHECK_EQ(mh.GetReturnType(), mh2.GetReturnType()); } @@ -3321,16 +3322,18 @@ bool ClassLinker::ValidateSuperClassDescriptors(Handle<mirror::Class> klass) { return true; } // Begin with the methods local to the superclass. - MethodHelper mh; - MethodHelper super_mh; + StackHandleScope<2> hs(Thread::Current()); + MethodHelper mh(hs.NewHandle<mirror::ArtMethod>(nullptr)); + MethodHelper super_mh(hs.NewHandle<mirror::ArtMethod>(nullptr)); if (klass->HasSuperClass() && klass->GetClassLoader() != klass->GetSuperClass()->GetClassLoader()) { for (int i = klass->GetSuperClass()->GetVTable()->GetLength() - 1; i >= 0; --i) { mh.ChangeMethod(klass->GetVTable()->GetWithoutChecks(i)); super_mh.ChangeMethod(klass->GetSuperClass()->GetVTable()->GetWithoutChecks(i)); - bool is_override = mh.GetMethod() != super_mh.GetMethod(); - if (is_override && !mh.HasSameSignatureWithDifferentClassLoaders(&super_mh)) { - ThrowLinkageError(klass.Get(), "Class %s method %s resolves differently in superclass %s", + if (mh.GetMethod() != super_mh.GetMethod() && + !mh.HasSameSignatureWithDifferentClassLoaders(&super_mh)) { + ThrowLinkageError(klass.Get(), + "Class %s method %s resolves differently in superclass %s", PrettyDescriptor(klass.Get()).c_str(), PrettyMethod(mh.GetMethod()).c_str(), PrettyDescriptor(klass->GetSuperClass()).c_str()); @@ -3344,9 +3347,10 @@ bool ClassLinker::ValidateSuperClassDescriptors(Handle<mirror::Class> klass) { for (uint32_t j = 0; j < num_methods; ++j) { mh.ChangeMethod(klass->GetIfTable()->GetMethodArray(i)->GetWithoutChecks(j)); super_mh.ChangeMethod(klass->GetIfTable()->GetInterface(i)->GetVirtualMethod(j)); - bool is_override = mh.GetMethod() != super_mh.GetMethod(); - if (is_override && !mh.HasSameSignatureWithDifferentClassLoaders(&super_mh)) { - ThrowLinkageError(klass.Get(), "Class %s method %s resolves differently in interface %s", + if (mh.GetMethod() != super_mh.GetMethod() && + !mh.HasSameSignatureWithDifferentClassLoaders(&super_mh)) { + ThrowLinkageError(klass.Get(), + "Class %s method %s resolves differently in interface %s", PrettyDescriptor(klass.Get()).c_str(), PrettyMethod(mh.GetMethod()).c_str(), PrettyDescriptor(klass->GetIfTable()->GetInterface(i)).c_str()); @@ -3388,7 +3392,7 @@ bool ClassLinker::LinkClass(Thread* self, Handle<mirror::Class> klass, if (!LinkSuperClass(klass)) { return false; } - if (!LinkMethods(klass, interfaces)) { + if (!LinkMethods(self, klass, interfaces)) { return false; } if (!LinkInstanceFields(klass)) { @@ -3507,7 +3511,7 @@ bool ClassLinker::LinkSuperClass(Handle<mirror::Class> klass) { } // Populate the class vtable and itable. Compute return type indices. -bool ClassLinker::LinkMethods(Handle<mirror::Class> klass, +bool ClassLinker::LinkMethods(Thread* self, Handle<mirror::Class> klass, Handle<mirror::ObjectArray<mirror::Class>> interfaces) { if (klass->IsInterface()) { // No vtable. @@ -3523,20 +3527,19 @@ bool ClassLinker::LinkMethods(Handle<mirror::Class> klass, return LinkInterfaceMethods(klass, interfaces); } else { // Link virtual and interface method tables - return LinkVirtualMethods(klass) && LinkInterfaceMethods(klass, interfaces); + return LinkVirtualMethods(self, klass) && LinkInterfaceMethods(klass, interfaces); } return true; } -bool ClassLinker::LinkVirtualMethods(Handle<mirror::Class> klass) { - Thread* self = Thread::Current(); +bool ClassLinker::LinkVirtualMethods(Thread* self, Handle<mirror::Class> klass) { if (klass->HasSuperClass()) { - uint32_t max_count = (klass->NumVirtualMethods() + - klass->GetSuperClass()->GetVTable()->GetLength()); + uint32_t max_count = klass->NumVirtualMethods() + + klass->GetSuperClass()->GetVTable()->GetLength(); size_t actual_count = klass->GetSuperClass()->GetVTable()->GetLength(); CHECK_LE(actual_count, max_count); // TODO: do not assign to the vtable field until it is fully constructed. - StackHandleScope<1> hs(self); + StackHandleScope<3> hs(self); Handle<mirror::ObjectArray<mirror::ArtMethod>> vtable( hs.NewHandle(klass->GetSuperClass()->GetVTable()->CopyOf(self, max_count))); if (UNLIKELY(vtable.Get() == NULL)) { @@ -3544,20 +3547,22 @@ bool ClassLinker::LinkVirtualMethods(Handle<mirror::Class> klass) { return false; } // See if any of our virtual methods override the superclass. + MethodHelper local_mh(hs.NewHandle<mirror::ArtMethod>(nullptr)); + MethodHelper super_mh(hs.NewHandle<mirror::ArtMethod>(nullptr)); for (size_t i = 0; i < klass->NumVirtualMethods(); ++i) { mirror::ArtMethod* local_method = klass->GetVirtualMethodDuringLinking(i); - MethodHelper local_mh(local_method); + local_mh.ChangeMethod(local_method); size_t j = 0; for (; j < actual_count; ++j) { mirror::ArtMethod* super_method = vtable->Get(j); - MethodHelper super_mh(super_method); + super_mh.ChangeMethod(super_method); if (local_mh.HasSameNameAndSignature(&super_mh)) { if (klass->CanAccessMember(super_method->GetDeclaringClass(), super_method->GetAccessFlags())) { if (super_method->IsFinal()) { ThrowLinkageError(klass.Get(), "Method %s overrides final method in class %s", PrettyMethod(local_method).c_str(), - super_mh.GetDeclaringClassDescriptor()); + super_method->GetDeclaringClassDescriptor()); return false; } vtable->Set<false>(j, local_method); @@ -3566,7 +3571,7 @@ bool ClassLinker::LinkVirtualMethods(Handle<mirror::Class> klass) { } else { LOG(WARNING) << "Before Android 4.1, method " << PrettyMethod(local_method) << " would have incorrectly overridden the package-private method in " - << PrettyDescriptor(super_mh.GetDeclaringClassDescriptor()); + << PrettyDescriptor(super_method->GetDeclaringClassDescriptor()); } } } @@ -3592,7 +3597,7 @@ bool ClassLinker::LinkVirtualMethods(Handle<mirror::Class> klass) { } klass->SetVTable(vtable.Get()); } else { - CHECK(klass.Get() == GetClassRoot(kJavaLangObject)); + CHECK_EQ(klass.Get(), GetClassRoot(kJavaLangObject)); uint32_t num_virtual_methods = klass->NumVirtualMethods(); if (!IsUint(16, num_virtual_methods)) { ThrowClassFormatError(klass.Get(), "Too many methods: %d", num_virtual_methods); @@ -3618,8 +3623,9 @@ bool ClassLinker::LinkVirtualMethods(Handle<mirror::Class> klass) { bool ClassLinker::LinkInterfaceMethods(Handle<mirror::Class> klass, Handle<mirror::ObjectArray<mirror::Class>> interfaces) { Thread* const self = Thread::Current(); + Runtime* const runtime = Runtime::Current(); // Set the imt table to be all conflicts by default. - klass->SetImTable(Runtime::Current()->GetDefaultImt()); + klass->SetImTable(runtime->GetDefaultImt()); size_t super_ifcount; if (klass->HasSuperClass()) { super_ifcount = klass->GetSuperClass()->GetIfTableCount(); @@ -3657,7 +3663,7 @@ bool ClassLinker::LinkInterfaceMethods(Handle<mirror::Class> klass, return true; } } - StackHandleScope<2> hs(self); + StackHandleScope<4> hs(self); Handle<mirror::IfTable> iftable(hs.NewHandle(AllocIfTable(self, ifcount))); if (UNLIKELY(iftable.Get() == NULL)) { CHECK(self->IsExceptionPending()); // OOME. @@ -3737,6 +3743,8 @@ bool ClassLinker::LinkInterfaceMethods(Handle<mirror::Class> klass, CHECK(self->IsExceptionPending()); // OOME. return false; } + MethodHelper interface_mh(hs.NewHandle<mirror::ArtMethod>(nullptr)); + MethodHelper vtable_mh(hs.NewHandle<mirror::ArtMethod>(nullptr)); std::vector<mirror::ArtMethod*> miranda_list; for (size_t i = 0; i < ifcount; ++i) { size_t num_methods = iftable->GetInterface(i)->NumVirtualMethods(); @@ -3753,7 +3761,7 @@ bool ClassLinker::LinkInterfaceMethods(Handle<mirror::Class> klass, hs.NewHandle(klass->GetVTableDuringLinking())); for (size_t j = 0; j < num_methods; ++j) { mirror::ArtMethod* interface_method = iftable->GetInterface(i)->GetVirtualMethod(j); - MethodHelper interface_mh(interface_method); + interface_mh.ChangeMethod(interface_method); int32_t k; // For each method listed in the interface's method list, find the // matching method in our class's method list. We want to favor the @@ -3765,7 +3773,7 @@ bool ClassLinker::LinkInterfaceMethods(Handle<mirror::Class> klass, // matter which direction we go. We walk it backward anyway.) for (k = vtable->GetLength() - 1; k >= 0; --k) { mirror::ArtMethod* vtable_method = vtable->Get(k); - MethodHelper vtable_mh(vtable_method); + vtable_mh.ChangeMethod(vtable_method); if (interface_mh.HasSameNameAndSignature(&vtable_mh)) { if (!vtable_method->IsAbstract() && !vtable_method->IsPublic()) { ThrowIllegalAccessError( @@ -3782,7 +3790,7 @@ bool ClassLinker::LinkInterfaceMethods(Handle<mirror::Class> klass, imtable->Set<false>(imt_index, vtable_method); imtable_changed = true; } else { - imtable->Set<false>(imt_index, Runtime::Current()->GetImtConflictMethod()); + imtable->Set<false>(imt_index, runtime->GetImtConflictMethod()); } break; } @@ -3790,11 +3798,10 @@ bool ClassLinker::LinkInterfaceMethods(Handle<mirror::Class> klass, if (k < 0) { StackHandleScope<1> hs(self); auto miranda_method = hs.NewHandle<mirror::ArtMethod>(nullptr); - for (size_t mir = 0; mir < miranda_list.size(); mir++) { - mirror::ArtMethod* mir_method = miranda_list[mir]; - MethodHelper vtable_mh(mir_method); + for (mirror::ArtMethod* mir_method : miranda_list) { + vtable_mh.ChangeMethod(mir_method); if (interface_mh.HasSameNameAndSignature(&vtable_mh)) { - miranda_method.Assign(miranda_list[mir]); + miranda_method.Assign(mir_method); break; } } @@ -3815,7 +3822,7 @@ bool ClassLinker::LinkInterfaceMethods(Handle<mirror::Class> klass, } if (imtable_changed) { // Fill in empty entries in interface method table with conflict. - mirror::ArtMethod* imt_conflict_method = Runtime::Current()->GetImtConflictMethod(); + mirror::ArtMethod* imt_conflict_method = runtime->GetImtConflictMethod(); for (size_t i = 0; i < kImtSize; i++) { if (imtable->Get(i) == NULL) { imtable->Set<false>(i, imt_conflict_method); diff --git a/runtime/class_linker.h b/runtime/class_linker.h index ccf0558689..a1d7bc6bd5 100644 --- a/runtime/class_linker.h +++ b/runtime/class_linker.h @@ -499,11 +499,11 @@ class ClassLinker { bool LoadSuperAndInterfaces(Handle<mirror::Class> klass, const DexFile& dex_file) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); - bool LinkMethods(Handle<mirror::Class> klass, + bool LinkMethods(Thread* self, Handle<mirror::Class> klass, Handle<mirror::ObjectArray<mirror::Class>> interfaces) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); - bool LinkVirtualMethods(Handle<mirror::Class> klass) + bool LinkVirtualMethods(Thread* self, Handle<mirror::Class> klass) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); bool LinkInterfaceMethods(Handle<mirror::Class> klass, diff --git a/runtime/class_linker_test.cc b/runtime/class_linker_test.cc index 45ab33a7f3..04f6946aa8 100644 --- a/runtime/class_linker_test.cc +++ b/runtime/class_linker_test.cc @@ -152,11 +152,10 @@ class ClassLinkerTest : public CommonRuntimeTest { } void AssertMethod(mirror::ArtMethod* method) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - MethodHelper mh(method); EXPECT_TRUE(method != NULL); EXPECT_TRUE(method->GetClass() != NULL); - EXPECT_TRUE(mh.GetName() != NULL); - EXPECT_TRUE(mh.GetSignature() != Signature::NoSignature()); + EXPECT_TRUE(method->GetName() != NULL); + EXPECT_TRUE(method->GetSignature() != Signature::NoSignature()); EXPECT_TRUE(method->GetDexCacheStrings() != NULL); EXPECT_TRUE(method->GetDexCacheResolvedMethods() != NULL); @@ -203,8 +202,7 @@ class ClassLinkerTest : public CommonRuntimeTest { if (klass->IsInterface()) { EXPECT_TRUE(klass->IsAbstract()); if (klass->NumDirectMethods() == 1) { - MethodHelper mh(klass->GetDirectMethod(0)); - EXPECT_TRUE(mh.IsClassInitializer()); + EXPECT_TRUE(klass->GetDirectMethod(0)->IsClassInitializer()); EXPECT_TRUE(klass->GetDirectMethod(0)->IsDirect()); } else { EXPECT_EQ(0U, klass->NumDirectMethods()); diff --git a/runtime/common_throws.cc b/runtime/common_throws.cc index a3e3cfad7e..8de3068dca 100644 --- a/runtime/common_throws.cc +++ b/runtime/common_throws.cc @@ -363,7 +363,7 @@ void ThrowNullPointerExceptionForMethodAccess(const ThrowLocation& throw_locatio } void ThrowNullPointerExceptionFromDexPC(const ThrowLocation& throw_location) { - const DexFile::CodeItem* code = MethodHelper(throw_location.GetMethod()).GetCodeItem(); + const DexFile::CodeItem* code = throw_location.GetMethod()->GetCodeItem(); uint32_t throw_dex_pc = throw_location.GetDexPc(); CHECK_LT(throw_dex_pc, code->insns_size_in_code_units_); const Instruction* instr = Instruction::At(&code->insns_[throw_dex_pc]); diff --git a/runtime/debugger.cc b/runtime/debugger.cc index 8e2340c7a3..73ed59025a 100644 --- a/runtime/debugger.cc +++ b/runtime/debugger.cc @@ -70,7 +70,7 @@ struct AllocRecordStackTraceElement { } int32_t LineNumber() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - return MethodHelper(method).GetLineNumFromDexPC(dex_pc); + return method->GetLineNumFromDexPC(dex_pc); } }; @@ -1373,7 +1373,7 @@ static void SetLocation(JDWP::JdwpLocation& location, mirror::ArtMethod* m, uint std::string Dbg::GetMethodName(JDWP::MethodId method_id) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { mirror::ArtMethod* m = FromMethodId(method_id); - return MethodHelper(m).GetName(); + return m->GetName(); } std::string Dbg::GetFieldName(JDWP::FieldId field_id) @@ -1401,7 +1401,7 @@ static uint32_t MangleAccessFlags(uint32_t accessFlags) { */ static uint16_t MangleSlot(uint16_t slot, mirror::ArtMethod* m) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - const DexFile::CodeItem* code_item = MethodHelper(m).GetCodeItem(); + const DexFile::CodeItem* code_item = m->GetCodeItem(); if (code_item == nullptr) { // We should not get here for a method without code (native, proxy or abstract). Log it and // return the slot as is since all registers are arguments. @@ -1423,7 +1423,7 @@ static uint16_t MangleSlot(uint16_t slot, mirror::ArtMethod* m) */ static uint16_t DemangleSlot(uint16_t slot, mirror::ArtMethod* m) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - const DexFile::CodeItem* code_item = MethodHelper(m).GetCodeItem(); + const DexFile::CodeItem* code_item = m->GetCodeItem(); if (code_item == nullptr) { // We should not get here for a method without code (native, proxy or abstract). Log it and // return the slot as is since all registers are arguments. @@ -1480,10 +1480,9 @@ JDWP::JdwpError Dbg::OutputDeclaredMethods(JDWP::RefTypeId class_id, bool with_g for (size_t i = 0; i < direct_method_count + virtual_method_count; ++i) { mirror::ArtMethod* m = (i < direct_method_count) ? c->GetDirectMethod(i) : c->GetVirtualMethod(i - direct_method_count); - MethodHelper mh(m); expandBufAddMethodId(pReply, ToMethodId(m)); - expandBufAddUtf8String(pReply, mh.GetName()); - expandBufAddUtf8String(pReply, mh.GetSignature().ToString()); + expandBufAddUtf8String(pReply, m->GetName()); + expandBufAddUtf8String(pReply, m->GetSignature().ToString()); if (with_generic) { static const char genericSignature[1] = ""; expandBufAddUtf8String(pReply, genericSignature); @@ -1525,8 +1524,7 @@ void Dbg::OutputLineTable(JDWP::RefTypeId, JDWP::MethodId method_id, JDWP::Expan } }; mirror::ArtMethod* m = FromMethodId(method_id); - MethodHelper mh(m); - const DexFile::CodeItem* code_item = mh.GetCodeItem(); + const DexFile::CodeItem* code_item = m->GetCodeItem(); uint64_t start, end; if (code_item == nullptr) { DCHECK(m->IsNative() || m->IsProxyMethod()); @@ -1550,25 +1548,30 @@ void Dbg::OutputLineTable(JDWP::RefTypeId, JDWP::MethodId method_id, JDWP::Expan context.pReply = pReply; if (code_item != nullptr) { - mh.GetDexFile().DecodeDebugInfo(code_item, m->IsStatic(), m->GetDexMethodIndex(), - DebugCallbackContext::Callback, NULL, &context); + m->GetDexFile()->DecodeDebugInfo(code_item, m->IsStatic(), m->GetDexMethodIndex(), + DebugCallbackContext::Callback, NULL, &context); } JDWP::Set4BE(expandBufGetBuffer(pReply) + numLinesOffset, context.numItems); } -void Dbg::OutputVariableTable(JDWP::RefTypeId, JDWP::MethodId method_id, bool with_generic, JDWP::ExpandBuf* pReply) { +void Dbg::OutputVariableTable(JDWP::RefTypeId, JDWP::MethodId method_id, bool with_generic, + JDWP::ExpandBuf* pReply) { struct DebugCallbackContext { mirror::ArtMethod* method; JDWP::ExpandBuf* pReply; size_t variable_count; bool with_generic; - static void Callback(void* context, uint16_t slot, uint32_t startAddress, uint32_t endAddress, const char* name, const char* descriptor, const char* signature) + static void Callback(void* context, uint16_t slot, uint32_t startAddress, uint32_t endAddress, + const char* name, const char* descriptor, const char* signature) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { DebugCallbackContext* pContext = reinterpret_cast<DebugCallbackContext*>(context); - VLOG(jdwp) << StringPrintf(" %2zd: %d(%d) '%s' '%s' '%s' actual slot=%d mangled slot=%d", pContext->variable_count, startAddress, endAddress - startAddress, name, descriptor, signature, slot, MangleSlot(slot, pContext->method)); + VLOG(jdwp) << StringPrintf(" %2zd: %d(%d) '%s' '%s' '%s' actual slot=%d mangled slot=%d", + pContext->variable_count, startAddress, endAddress - startAddress, + name, descriptor, signature, slot, + MangleSlot(slot, pContext->method)); slot = MangleSlot(slot, pContext->method); @@ -1585,11 +1588,10 @@ void Dbg::OutputVariableTable(JDWP::RefTypeId, JDWP::MethodId method_id, bool wi } }; mirror::ArtMethod* m = FromMethodId(method_id); - MethodHelper mh(m); // arg_count considers doubles and longs to take 2 units. // variable_count considers everything to take 1 unit. - std::string shorty(mh.GetShorty()); + std::string shorty(m->GetShorty()); expandBufAdd4BE(pReply, mirror::ArtMethod::NumArgRegisters(shorty)); // We don't know the total number of variables yet, so leave a blank and update it later. @@ -1602,10 +1604,11 @@ void Dbg::OutputVariableTable(JDWP::RefTypeId, JDWP::MethodId method_id, bool wi context.variable_count = 0; context.with_generic = with_generic; - const DexFile::CodeItem* code_item = mh.GetCodeItem(); + const DexFile::CodeItem* code_item = m->GetCodeItem(); if (code_item != nullptr) { - mh.GetDexFile().DecodeDebugInfo(code_item, m->IsStatic(), m->GetDexMethodIndex(), NULL, - DebugCallbackContext::Callback, &context); + m->GetDexFile()->DecodeDebugInfo( + code_item, m->IsStatic(), m->GetDexMethodIndex(), NULL, DebugCallbackContext::Callback, + &context); } JDWP::Set4BE(expandBufGetBuffer(pReply) + variable_count_offset, context.variable_count); @@ -1614,7 +1617,7 @@ void Dbg::OutputVariableTable(JDWP::RefTypeId, JDWP::MethodId method_id, bool wi void Dbg::OutputMethodReturnValue(JDWP::MethodId method_id, const JValue* return_value, JDWP::ExpandBuf* pReply) { mirror::ArtMethod* m = FromMethodId(method_id); - JDWP::JdwpTag tag = BasicTagFromDescriptor(MethodHelper(m).GetShorty()); + JDWP::JdwpTag tag = BasicTagFromDescriptor(m->GetShorty()); OutputJValue(tag, return_value, pReply); } @@ -1632,8 +1635,7 @@ JDWP::JdwpError Dbg::GetBytecodes(JDWP::RefTypeId, JDWP::MethodId method_id, if (m == NULL) { return JDWP::ERR_INVALID_METHODID; } - MethodHelper mh(m); - const DexFile::CodeItem* code_item = mh.GetCodeItem(); + const DexFile::CodeItem* code_item = m->GetCodeItem(); size_t byte_count = code_item->insns_size_in_code_units_ * 2; const uint8_t* begin = reinterpret_cast<const uint8_t*>(code_item->insns_); const uint8_t* end = begin + byte_count; @@ -2875,18 +2877,18 @@ void Dbg::ManageDeoptimization() { static bool IsMethodPossiblyInlined(Thread* self, mirror::ArtMethod* m) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - MethodHelper mh(m); - const DexFile::CodeItem* code_item = mh.GetCodeItem(); + const DexFile::CodeItem* code_item = m->GetCodeItem(); if (code_item == nullptr) { // TODO We should not be asked to watch location in a native or abstract method so the code item // should never be null. We could just check we never encounter this case. return false; } StackHandleScope<2> hs(self); - Handle<mirror::DexCache> dex_cache(hs.NewHandle(mh.GetDexCache())); - Handle<mirror::ClassLoader> class_loader(hs.NewHandle(mh.GetClassLoader())); - verifier::MethodVerifier verifier(&mh.GetDexFile(), &dex_cache, &class_loader, - &mh.GetClassDef(), code_item, m->GetDexMethodIndex(), m, + mirror::Class* declaring_class = m->GetDeclaringClass(); + Handle<mirror::DexCache> dex_cache(hs.NewHandle(declaring_class->GetDexCache())); + Handle<mirror::ClassLoader> class_loader(hs.NewHandle(declaring_class->GetClassLoader())); + verifier::MethodVerifier verifier(dex_cache->GetDexFile(), &dex_cache, &class_loader, + &m->GetClassDef(), code_item, m->GetDexMethodIndex(), m, m->GetAccessFlags(), false, true, false); // Note: we don't need to verify the method. return InlineMethodAnalyser::AnalyseMethodCode(&verifier, nullptr); @@ -3156,11 +3158,10 @@ JDWP::JdwpError Dbg::ConfigureStep(JDWP::ObjectId thread_id, JDWP::JdwpStepSize single_step_control->dex_pcs.clear(); mirror::ArtMethod* m = single_step_control->method; if (!m->IsNative()) { - MethodHelper mh(m); - const DexFile::CodeItem* const code_item = mh.GetCodeItem(); + const DexFile::CodeItem* const code_item = m->GetCodeItem(); DebugCallbackContext context(single_step_control, line_number, code_item); - mh.GetDexFile().DecodeDebugInfo(code_item, m->IsStatic(), m->GetDexMethodIndex(), - DebugCallbackContext::Callback, NULL, &context); + m->GetDexFile()->DecodeDebugInfo(code_item, m->IsStatic(), m->GetDexMethodIndex(), + DebugCallbackContext::Callback, NULL, &context); } // @@ -3308,32 +3309,41 @@ JDWP::JdwpError Dbg::InvokeMethod(JDWP::ObjectId thread_id, JDWP::ObjectId objec } // Check the argument list matches the method. - MethodHelper mh(m); - if (mh.GetShortyLength() - 1 != arg_count) { + uint32_t shorty_len = 0; + const char* shorty = m->GetShorty(&shorty_len); + if (shorty_len - 1 != arg_count) { return JDWP::ERR_ILLEGAL_ARGUMENT; } - const char* shorty = mh.GetShorty(); - const DexFile::TypeList* types = mh.GetParameterTypeList(); - for (size_t i = 0; i < arg_count; ++i) { - if (shorty[i + 1] != JdwpTagToShortyChar(arg_types[i])) { - return JDWP::ERR_ILLEGAL_ARGUMENT; - } - if (shorty[i + 1] == 'L') { - // Did we really get an argument of an appropriate reference type? - mirror::Class* parameter_type = mh.GetClassFromTypeIdx(types->GetTypeItem(i).type_idx_); - mirror::Object* argument = gRegistry->Get<mirror::Object*>(arg_values[i]); - if (argument == ObjectRegistry::kInvalidObject) { - return JDWP::ERR_INVALID_OBJECT; - } - if (argument != NULL && !argument->InstanceOf(parameter_type)) { + { + StackHandleScope<3> hs(soa.Self()); + MethodHelper mh(hs.NewHandle(m)); + HandleWrapper<mirror::Object> h_obj(hs.NewHandleWrapper(&receiver)); + HandleWrapper<mirror::Class> h_klass(hs.NewHandleWrapper(&c)); + const DexFile::TypeList* types = m->GetParameterTypeList(); + for (size_t i = 0; i < arg_count; ++i) { + if (shorty[i + 1] != JdwpTagToShortyChar(arg_types[i])) { return JDWP::ERR_ILLEGAL_ARGUMENT; } - // Turn the on-the-wire ObjectId into a jobject. - jvalue& v = reinterpret_cast<jvalue&>(arg_values[i]); - v.l = gRegistry->GetJObject(arg_values[i]); + if (shorty[i + 1] == 'L') { + // Did we really get an argument of an appropriate reference type? + mirror::Class* parameter_type = mh.GetClassFromTypeIdx(types->GetTypeItem(i).type_idx_); + mirror::Object* argument = gRegistry->Get<mirror::Object*>(arg_values[i]); + if (argument == ObjectRegistry::kInvalidObject) { + return JDWP::ERR_INVALID_OBJECT; + } + if (argument != NULL && !argument->InstanceOf(parameter_type)) { + return JDWP::ERR_ILLEGAL_ARGUMENT; + } + + // Turn the on-the-wire ObjectId into a jobject. + jvalue& v = reinterpret_cast<jvalue&>(arg_values[i]); + v.l = gRegistry->GetJObject(arg_values[i]); + } } + // Update in case it moved. + m = mh.GetMethod(); } req->receiver = receiver; @@ -3452,7 +3462,7 @@ void Dbg::ExecuteMethod(DebugInvokeReq* pReq) { mirror::Throwable* exception = soa.Self()->GetException(NULL); soa.Self()->ClearException(); pReq->exception = gRegistry->Add(exception); - pReq->result_tag = BasicTagFromDescriptor(MethodHelper(m.Get()).GetShorty()); + pReq->result_tag = BasicTagFromDescriptor(m.Get()->GetShorty()); if (pReq->exception != 0) { VLOG(jdwp) << " JDWP invocation returning with exception=" << exception << " " << exception->Dump(); @@ -4296,10 +4306,10 @@ class StringTable { DISALLOW_COPY_AND_ASSIGN(StringTable); }; -static const char* GetMethodSourceFile(MethodHelper* mh) +static const char* GetMethodSourceFile(mirror::ArtMethod* method) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - DCHECK(mh != nullptr); - const char* source_file = mh->GetDeclaringClassSourceFile(); + DCHECK(method != nullptr); + const char* source_file = method->GetDeclaringClassSourceFile(); return (source_file != nullptr) ? source_file : ""; } @@ -4368,14 +4378,12 @@ jbyteArray Dbg::GetRecentAllocations() { class_names.Add(record->type->GetDescriptor().c_str()); - MethodHelper mh; for (size_t i = 0; i < kMaxAllocRecordStackDepth; i++) { mirror::ArtMethod* m = record->stack[i].method; if (m != NULL) { - mh.ChangeMethod(m); - class_names.Add(mh.GetDeclaringClassDescriptor()); - method_names.Add(mh.GetName()); - filenames.Add(GetMethodSourceFile(&mh)); + class_names.Add(m->GetDeclaringClassDescriptor()); + method_names.Add(m->GetName()); + filenames.Add(GetMethodSourceFile(m)); } } @@ -4427,17 +4435,16 @@ jbyteArray Dbg::GetRecentAllocations() { JDWP::Append2BE(bytes, allocated_object_class_name_index); JDWP::Append1BE(bytes, stack_depth); - MethodHelper mh; for (size_t stack_frame = 0; stack_frame < stack_depth; ++stack_frame) { // For each stack frame: // (2b) method's class name // (2b) method name // (2b) method source file // (2b) line number, clipped to 32767; -2 if native; -1 if no source - mh.ChangeMethod(record->stack[stack_frame].method); - size_t class_name_index = class_names.IndexOf(mh.GetDeclaringClassDescriptor()); - size_t method_name_index = method_names.IndexOf(mh.GetName()); - size_t file_name_index = filenames.IndexOf(GetMethodSourceFile(&mh)); + mirror::ArtMethod* m = record->stack[stack_frame].method; + size_t class_name_index = class_names.IndexOf(m->GetDeclaringClassDescriptor()); + size_t method_name_index = method_names.IndexOf(m->GetName()); + size_t file_name_index = filenames.IndexOf(GetMethodSourceFile(m)); JDWP::Append2BE(bytes, class_name_index); JDWP::Append2BE(bytes, method_name_index); JDWP::Append2BE(bytes, file_name_index); diff --git a/runtime/entrypoints/entrypoint_utils.cc b/runtime/entrypoints/entrypoint_utils.cc index 320273d176..a0e32f520d 100644 --- a/runtime/entrypoints/entrypoint_utils.cc +++ b/runtime/entrypoints/entrypoint_utils.cc @@ -189,18 +189,21 @@ JValue InvokeProxyInvocationHandler(ScopedObjectAccessAlreadyRunnable& soa, cons // Do nothing. return zero; } else { + StackHandleScope<1> hs(soa.Self()); + MethodHelper mh_interface_method( + hs.NewHandle(soa.Decode<mirror::ArtMethod*>(interface_method_jobj))); + // This can cause thread suspension. + mirror::Class* result_type = mh_interface_method.GetReturnType(); mirror::Object* result_ref = soa.Decode<mirror::Object*>(result); mirror::Object* rcvr = soa.Decode<mirror::Object*>(rcvr_jobj); - mirror::ArtMethod* interface_method = - soa.Decode<mirror::ArtMethod*>(interface_method_jobj); - mirror::Class* result_type = MethodHelper(interface_method).GetReturnType(); mirror::ArtMethod* proxy_method; - if (interface_method->GetDeclaringClass()->IsInterface()) { - proxy_method = rcvr->GetClass()->FindVirtualMethodForInterface(interface_method); + if (mh_interface_method.GetMethod()->GetDeclaringClass()->IsInterface()) { + proxy_method = rcvr->GetClass()->FindVirtualMethodForInterface( + mh_interface_method.GetMethod()); } else { // Proxy dispatch to a method defined in Object. - DCHECK(interface_method->GetDeclaringClass()->IsObjectClass()); - proxy_method = interface_method; + DCHECK(mh_interface_method.GetMethod()->GetDeclaringClass()->IsObjectClass()); + proxy_method = mh_interface_method.GetMethod(); } ThrowLocation throw_location(rcvr, proxy_method, -1); JValue result_unboxed; diff --git a/runtime/entrypoints/entrypoint_utils.h b/runtime/entrypoints/entrypoint_utils.h index d0ae746b20..09899c05bd 100644 --- a/runtime/entrypoints/entrypoint_utils.h +++ b/runtime/entrypoints/entrypoint_utils.h @@ -433,9 +433,8 @@ static inline mirror::ArtMethod* FindMethodFromCode(uint32_t method_idx, if (access_check && (vtable == nullptr || vtable_index >= static_cast<uint32_t>(vtable->GetLength()))) { // Behavior to agree with that of the verifier. - MethodHelper mh(resolved_method); - ThrowNoSuchMethodError(type, resolved_method->GetDeclaringClass(), mh.GetName(), - mh.GetSignature()); + ThrowNoSuchMethodError(type, resolved_method->GetDeclaringClass(), + resolved_method->GetName(), resolved_method->GetSignature()); return nullptr; // Failure. } DCHECK(vtable != nullptr); @@ -450,9 +449,8 @@ static inline mirror::ArtMethod* FindMethodFromCode(uint32_t method_idx, vtable = (super_class != nullptr) ? super_class->GetVTable() : nullptr; if (vtable == nullptr || vtable_index >= static_cast<uint32_t>(vtable->GetLength())) { // Behavior to agree with that of the verifier. - MethodHelper mh(resolved_method); - ThrowNoSuchMethodError(type, resolved_method->GetDeclaringClass(), mh.GetName(), - mh.GetSignature()); + ThrowNoSuchMethodError(type, resolved_method->GetDeclaringClass(), + resolved_method->GetName(), resolved_method->GetSignature()); return nullptr; // Failure. } } else { @@ -682,11 +680,13 @@ static inline void CheckReferenceResult(mirror::Object* o, Thread* self) JniAbortF(NULL, "invalid reference returned from %s", PrettyMethod(m).c_str()); } // Make sure that the result is an instance of the type this method was expected to return. - mirror::Class* return_type = MethodHelper(m).GetReturnType(); + StackHandleScope<1> hs(self); + Handle<mirror::ArtMethod> h_m(hs.NewHandle(m)); + mirror::Class* return_type = MethodHelper(h_m).GetReturnType(); if (!o->InstanceOf(return_type)) { - JniAbortF(NULL, "attempt to return an instance of %s from %s", - PrettyTypeOf(o).c_str(), PrettyMethod(m).c_str()); + JniAbortF(NULL, "attempt to return an instance of %s from %s", PrettyTypeOf(o).c_str(), + PrettyMethod(h_m.Get()).c_str()); } } diff --git a/runtime/entrypoints/portable/portable_fillarray_entrypoints.cc b/runtime/entrypoints/portable/portable_fillarray_entrypoints.cc index 1005d0e6fb..335a61770c 100644 --- a/runtime/entrypoints/portable/portable_fillarray_entrypoints.cc +++ b/runtime/entrypoints/portable/portable_fillarray_entrypoints.cc @@ -26,7 +26,7 @@ extern "C" void art_portable_fill_array_data_from_code(mirror::ArtMethod* method mirror::Array* array, uint32_t payload_offset) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - const DexFile::CodeItem* code_item = MethodHelper(method).GetCodeItem(); + const DexFile::CodeItem* code_item = method->GetCodeItem(); const Instruction::ArrayDataPayload* payload = reinterpret_cast<const Instruction::ArrayDataPayload*>(code_item->insns_ + payload_offset); DCHECK_EQ(payload->ident, static_cast<uint16_t>(Instruction::kArrayDataSignature)); diff --git a/runtime/entrypoints/portable/portable_invoke_entrypoints.cc b/runtime/entrypoints/portable/portable_invoke_entrypoints.cc index 3a898e8ed5..eb50ec3272 100644 --- a/runtime/entrypoints/portable/portable_invoke_entrypoints.cc +++ b/runtime/entrypoints/portable/portable_invoke_entrypoints.cc @@ -41,9 +41,8 @@ mirror::ArtMethod* FindMethodHelper(uint32_t method_idx, mirror::Object* this_ob // When we return, the caller will branch to this address, so it had better not be 0! if (UNLIKELY(code == NULL)) { - MethodHelper mh(method); LOG(FATAL) << "Code was NULL in method: " << PrettyMethod(method) - << " location: " << mh.GetDexFile().GetLocation(); + << " location: " << method->GetDexFile()->GetLocation(); } return method; } diff --git a/runtime/entrypoints/portable/portable_throw_entrypoints.cc b/runtime/entrypoints/portable/portable_throw_entrypoints.cc index 1fdb8327cc..189e6b5903 100644 --- a/runtime/entrypoints/portable/portable_throw_entrypoints.cc +++ b/runtime/entrypoints/portable/portable_throw_entrypoints.cc @@ -79,8 +79,9 @@ extern "C" int32_t art_portable_find_catch_block_from_code(mirror::ArtMethod* cu return -1; } mirror::Class* exception_type = exception->GetClass(); - MethodHelper mh(current_method); - const DexFile::CodeItem* code_item = mh.GetCodeItem(); + StackHandleScope<1> hs(self); + MethodHelper mh(hs.NewHandle(current_method)); + const DexFile::CodeItem* code_item = current_method->GetCodeItem(); DCHECK_LT(ti_offset, code_item->tries_size_); const DexFile::TryItem* try_item = DexFile::GetTryItems(*code_item, ti_offset); @@ -102,7 +103,7 @@ extern "C" int32_t art_portable_find_catch_block_from_code(mirror::ArtMethod* cu // TODO: check, the verifier (class linker?) should take care of resolving all exception // classes early. LOG(WARNING) << "Unresolved exception class when finding catch block: " - << mh.GetTypeDescriptorFromTypeIdx(iter_type_idx); + << current_method->GetTypeDescriptorFromTypeIdx(iter_type_idx); } else if (iter_exception_type->IsAssignableFrom(exception_type)) { catch_dex_pc = it.GetHandlerAddress(); result = iter_index; @@ -112,13 +113,11 @@ extern "C" int32_t art_portable_find_catch_block_from_code(mirror::ArtMethod* cu } if (result != -1) { // Handler found. - Runtime::Current()->GetInstrumentation()->ExceptionCaughtEvent(self, - throw_location, - current_method, - catch_dex_pc, - exception); + Runtime::Current()->GetInstrumentation()->ExceptionCaughtEvent( + self, throw_location, current_method, catch_dex_pc, exception); // If the catch block has no move-exception then clear the exception for it. - const Instruction* first_catch_instr = Instruction::At(&mh.GetCodeItem()->insns_[catch_dex_pc]); + const Instruction* first_catch_instr = Instruction::At( + ¤t_method->GetCodeItem()->insns_[catch_dex_pc]); if (first_catch_instr->Opcode() != Instruction::MOVE_EXCEPTION) { self->ClearException(); } diff --git a/runtime/entrypoints/portable/portable_trampoline_entrypoints.cc b/runtime/entrypoints/portable/portable_trampoline_entrypoints.cc index 3756f47311..6825e783a7 100644 --- a/runtime/entrypoints/portable/portable_trampoline_entrypoints.cc +++ b/runtime/entrypoints/portable/portable_trampoline_entrypoints.cc @@ -196,8 +196,9 @@ extern "C" uint64_t artPortableToInterpreterBridge(mirror::ArtMethod* method, Th return 0; } else { const char* old_cause = self->StartAssertNoThreadSuspension("Building interpreter shadow frame"); - MethodHelper mh(method); - const DexFile::CodeItem* code_item = mh.GetCodeItem(); + StackHandleScope<2> hs(self); + MethodHelper mh(hs.NewHandle(method)); + const DexFile::CodeItem* code_item = method->GetCodeItem(); 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. @@ -214,7 +215,6 @@ extern "C" uint64_t artPortableToInterpreterBridge(mirror::ArtMethod* method, Th if (method->IsStatic() && !method->GetDeclaringClass()->IsInitializing()) { // Ensure static method's class is initialized. - StackHandleScope<1> hs(self); Handle<mirror::Class> h_class(hs.NewHandle(method->GetDeclaringClass())); if (!Runtime::Current()->GetClassLinker()->EnsureInitialized(h_class, true, true)) { DCHECK(Thread::Current()->IsExceptionPending()); @@ -294,7 +294,8 @@ extern "C" uint64_t artPortableProxyInvokeHandler(mirror::ArtMethod* proxy_metho jobject rcvr_jobj = soa.AddLocalReference<jobject>(receiver); // Placing arguments into args vector and remove the receiver. - MethodHelper proxy_mh(proxy_method); + StackHandleScope<1> hs(self); + MethodHelper proxy_mh(hs.NewHandle(proxy_method)); std::vector<jvalue> args; BuildPortableArgumentVisitor local_ref_visitor(proxy_mh, sp, soa, args); local_ref_visitor.VisitArguments(); @@ -327,7 +328,7 @@ extern "C" const void* artPortableResolutionTrampoline(mirror::ArtMethod* called InvokeType invoke_type; bool is_range; if (called->IsRuntimeMethod()) { - const DexFile::CodeItem* code = MethodHelper(caller).GetCodeItem(); + const DexFile::CodeItem* 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(); diff --git a/runtime/entrypoints/quick/quick_trampoline_entrypoints.cc b/runtime/entrypoints/quick/quick_trampoline_entrypoints.cc index 5374f22cfc..05033fc058 100644 --- a/runtime/entrypoints/quick/quick_trampoline_entrypoints.cc +++ b/runtime/entrypoints/quick/quick_trampoline_entrypoints.cc @@ -474,16 +474,16 @@ extern "C" uint64_t artQuickToInterpreterBridge(mirror::ArtMethod* method, Threa } 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 @@ extern "C" uint64_t artQuickToInterpreterBridge(mirror::ArtMethod* method, Threa } } + 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 @@ extern "C" uint64_t artQuickProxyInvokeHandler(mirror::ArtMethod* proxy_method, 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 @@ extern "C" uint64_t artQuickProxyInvokeHandler(mirror::ArtMethod* proxy_method, // 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 @@ extern "C" const void* artQuickResolutionTrampoline(mirror::ArtMethod* called, 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 @@ extern "C" const void* artQuickResolutionTrampoline(mirror::ArtMethod* called, } 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 @@ extern "C" const void* artQuickResolutionTrampoline(mirror::ArtMethod* called, // 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 @@ extern "C" ssize_t artQuickGenericJniTrampoline(Thread* self, StackReference<mir 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 @@ extern "C" ssize_t artQuickGenericJniTrampoline(Thread* self, StackReference<mir // 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 @@ extern "C" uint64_t artQuickGenericJniEndTrampoline(Thread* self, 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 @@ static MethodAndCode artInvokeCommon(uint32_t method_idx, mirror::Object* this_o // 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 @@ extern "C" MethodAndCode artInvokeInterfaceTrampoline(mirror::ArtMethod* interfa 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 @@ extern "C" MethodAndCode artInvokeInterfaceTrampoline(mirror::ArtMethod* interfa // 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); } diff --git a/runtime/handle.h b/runtime/handle.h index b70f6510a4..7e13601af9 100644 --- a/runtime/handle.h +++ b/runtime/handle.h @@ -26,18 +26,20 @@ namespace art { class Thread; +template<class T> class Handle; + template<class T> -class Handle { +class ConstHandle { public: - Handle() : reference_(nullptr) { + ConstHandle() : reference_(nullptr) { } - Handle(const Handle<T>& handle) ALWAYS_INLINE : reference_(handle.reference_) { + ConstHandle(const ConstHandle<T>& handle) ALWAYS_INLINE : reference_(handle.reference_) { } - Handle<T>& operator=(const Handle<T>& handle) ALWAYS_INLINE { + ConstHandle<T>& operator=(const ConstHandle<T>& handle) ALWAYS_INLINE { reference_ = handle.reference_; return *this; } - explicit Handle(StackReference<T>* reference) ALWAYS_INLINE : reference_(reference) { + explicit ConstHandle(StackReference<T>* reference) ALWAYS_INLINE : reference_(reference) { } T& operator*() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) ALWAYS_INLINE { return *Get(); @@ -48,11 +50,6 @@ class Handle { T* Get() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) ALWAYS_INLINE { return reference_->AsMirrorPtr(); } - T* Assign(T* reference) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) ALWAYS_INLINE { - T* old = reference_->AsMirrorPtr(); - reference_->Assign(reference); - return old; - } jobject ToJObject() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) ALWAYS_INLINE { if (UNLIKELY(reference_->AsMirrorPtr() == nullptr)) { // Special case so that we work with NullHandles. @@ -65,17 +62,62 @@ class Handle { StackReference<T>* reference_; template<typename S> - explicit Handle(StackReference<S>* reference) + explicit ConstHandle(StackReference<S>* reference) : reference_(reinterpret_cast<StackReference<T>*>(reference)) { } template<typename S> - explicit Handle(const Handle<S>& handle) + explicit ConstHandle(const ConstHandle<S>& handle) : reference_(reinterpret_cast<StackReference<T>*>(handle.reference_)) { } StackReference<T>* GetReference() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) ALWAYS_INLINE { return reference_; } + const StackReference<T>* GetReference() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) + ALWAYS_INLINE { + return reference_; + } + + private: + friend class BuildGenericJniFrameVisitor; + template<class S> friend class ConstHandle; + friend class HandleScope; + template<class S> friend class HandleWrapper; + template<size_t kNumReferences> friend class StackHandleScope; +}; + +template<class T> +class Handle : public ConstHandle<T> { + public: + Handle() { + } + Handle(const Handle<T>& handle) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) ALWAYS_INLINE + : ConstHandle<T>(handle.reference_) { + } + Handle<T>& operator=(const Handle<T>& handle) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) + ALWAYS_INLINE { + ConstHandle<T>::operator=(handle); + return *this; + } + explicit Handle(StackReference<T>* reference) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) + ALWAYS_INLINE : ConstHandle<T>(reference) { + } + T* Assign(T* reference) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) ALWAYS_INLINE { + StackReference<T>* ref = ConstHandle<T>::GetReference(); + T* const old = ref->AsMirrorPtr(); + ref->Assign(reference); + return old; + } + + protected: + template<typename S> + explicit Handle(StackReference<S>* reference) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) + : ConstHandle<T>(reference) { + } + template<typename S> + explicit Handle(const Handle<S>& handle) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) + : ConstHandle<T>(handle) { + } private: friend class BuildGenericJniFrameVisitor; diff --git a/runtime/instrumentation.cc b/runtime/instrumentation.cc index 194cb18078..8e23d1b827 100644 --- a/runtime/instrumentation.cc +++ b/runtime/instrumentation.cc @@ -859,7 +859,8 @@ uint64_t Instrumentation::PopInstrumentationStackFrame(Thread* self, uintptr_t* CheckStackDepth(self, instrumentation_frame, 0); mirror::ArtMethod* method = instrumentation_frame.method_; - char return_shorty = MethodHelper(method).GetShorty()[0]; + uint32_t length; + char return_shorty = method->GetShorty(&length)[0]; JValue return_value; if (return_shorty == 'V') { return_value.SetJ(0); diff --git a/runtime/interpreter/interpreter.cc b/runtime/interpreter/interpreter.cc index 9cfba8d5d7..6dbc6a05ea 100644 --- a/runtime/interpreter/interpreter.cc +++ b/runtime/interpreter/interpreter.cc @@ -400,8 +400,7 @@ void EnterInterpreterFromInvoke(Thread* self, ArtMethod* method, Object* receive } const char* old_cause = self->StartAssertNoThreadSuspension("EnterInterpreterFromInvoke"); - MethodHelper mh(method); - const DexFile::CodeItem* code_item = mh.GetCodeItem(); + const DexFile::CodeItem* code_item = method->GetCodeItem(); uint16_t num_regs; uint16_t num_ins; if (code_item != NULL) { @@ -413,7 +412,7 @@ void EnterInterpreterFromInvoke(Thread* self, ArtMethod* method, Object* receive return; } else { DCHECK(method->IsNative()); - num_regs = num_ins = ArtMethod::NumArgRegisters(mh.GetShorty()); + num_regs = num_ins = ArtMethod::NumArgRegisters(method->GetShorty()); if (!method->IsStatic()) { num_regs++; num_ins++; @@ -431,9 +430,10 @@ void EnterInterpreterFromInvoke(Thread* self, ArtMethod* method, Object* receive shadow_frame->SetVRegReference(cur_reg, receiver); ++cur_reg; } - const char* shorty = mh.GetShorty(); + uint32_t shorty_len = 0; + const char* shorty = method->GetShorty(&shorty_len); for (size_t shorty_pos = 0, arg_pos = 0; cur_reg < num_regs; ++shorty_pos, ++arg_pos, cur_reg++) { - DCHECK_LT(shorty_pos + 1, mh.GetShortyLength()); + DCHECK_LT(shorty_pos + 1, shorty_len); switch (shorty[shorty_pos + 1]) { case 'L': { Object* o = reinterpret_cast<StackReference<Object>*>(&args[arg_pos])->AsMirrorPtr(); @@ -465,6 +465,8 @@ void EnterInterpreterFromInvoke(Thread* self, ArtMethod* method, Object* receive } } if (LIKELY(!method->IsNative())) { + StackHandleScope<1> hs(self); + MethodHelper mh(hs.NewHandle(method)); JValue r = Execute(self, mh, code_item, *shadow_frame, JValue()); if (result != NULL) { *result = r; @@ -488,11 +490,11 @@ void EnterInterpreterFromDeoptimize(Thread* self, ShadowFrame* shadow_frame, JVa SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { JValue value; value.SetJ(ret_val->GetJ()); // Set value to last known result in case the shadow frame chain is empty. - MethodHelper mh; while (shadow_frame != NULL) { self->SetTopOfShadowStack(shadow_frame); - mh.ChangeMethod(shadow_frame->GetMethod()); - const DexFile::CodeItem* code_item = mh.GetCodeItem(); + StackHandleScope<1> hs(self); + MethodHelper mh(hs.NewHandle(shadow_frame->GetMethod())); + const DexFile::CodeItem* code_item = mh.GetMethod()->GetCodeItem(); value = Execute(self, mh, code_item, *shadow_frame, value); ShadowFrame* old_frame = shadow_frame; shadow_frame = shadow_frame->GetLink(); diff --git a/runtime/interpreter/interpreter_common.cc b/runtime/interpreter/interpreter_common.cc index a66bd94ede..c6e05ae020 100644 --- a/runtime/interpreter/interpreter_common.cc +++ b/runtime/interpreter/interpreter_common.cc @@ -54,8 +54,7 @@ template<bool is_range, bool do_assignability_check> bool DoCall(ArtMethod* method, 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 DexFile::CodeItem* code_item = method->GetCodeItem(); const uint16_t num_ins = (is_range) ? inst->VRegA_3rc(inst_data) : inst->VRegA_35c(inst_data); uint16_t num_regs; if (LIKELY(code_item != NULL)) { @@ -73,6 +72,8 @@ bool DoCall(ArtMethod* method, Thread* self, ShadowFrame& shadow_frame, // Initialize new shadow frame. const size_t first_dest_reg = num_regs - num_ins; + StackHandleScope<1> hs(self); + MethodHelper mh(hs.NewHandle(method)); if (do_assignability_check) { // Slow path. // We might need to do class loading, which incurs a thread state change to kNative. So @@ -82,8 +83,9 @@ bool DoCall(ArtMethod* method, Thread* self, ShadowFrame& shadow_frame, // We need to do runtime check on reference assignment. We need to load the shorty // to get the exact type of each reference argument. - const DexFile::TypeList* params = mh.GetParameterTypeList(); - const char* shorty = mh.GetShorty(); + const DexFile::TypeList* params = method->GetParameterTypeList(); + uint32_t shorty_len = 0; + const char* shorty = method->GetShorty(&shorty_len); // TODO: find a cleaner way to separate non-range and range information without duplicating code. uint32_t arg[5]; // only used in invoke-XXX. @@ -98,13 +100,13 @@ bool DoCall(ArtMethod* method, Thread* self, ShadowFrame& shadow_frame, size_t dest_reg = first_dest_reg; size_t arg_offset = 0; if (!method->IsStatic()) { - size_t receiver_reg = (is_range) ? vregC : arg[0]; + size_t receiver_reg = is_range ? vregC : arg[0]; new_shadow_frame->SetVRegReference(dest_reg, shadow_frame.GetVRegReference(receiver_reg)); ++dest_reg; ++arg_offset; } for (uint32_t shorty_pos = 0; dest_reg < num_regs; ++shorty_pos, ++dest_reg, ++arg_offset) { - DCHECK_LT(shorty_pos + 1, mh.GetShortyLength()); + DCHECK_LT(shorty_pos + 1, shorty_len); const size_t src_reg = (is_range) ? vregC + arg_offset : arg[arg_offset]; switch (shorty[shorty_pos + 1]) { case 'L': { @@ -120,7 +122,7 @@ bool DoCall(ArtMethod* method, Thread* self, ShadowFrame& shadow_frame, self->ThrowNewExceptionF(self->GetCurrentLocationForThrow(), "Ljava/lang/VirtualMachineError;", "Invoking %s with bad arg %d, type '%s' not instance of '%s'", - mh.GetName(), shorty_pos, + method->GetName(), shorty_pos, o->GetClass()->GetDescriptor().c_str(), arg_type->GetDescriptor().c_str()); return false; @@ -368,8 +370,9 @@ static void UnstartedRuntimeInvoke(Thread* self, MethodHelper& mh, Object* obj = shadow_frame->GetVRegReference(arg_offset); result->SetI(obj->IdentityHashCode()); } else if (name == "java.lang.String java.lang.reflect.ArtMethod.getMethodName(java.lang.reflect.ArtMethod)") { - ArtMethod* method = shadow_frame->GetVRegReference(arg_offset)->AsArtMethod(); - result->SetL(MethodHelper(method).GetNameAsString()); + StackHandleScope<1> hs(self); + MethodHelper mh(hs.NewHandle(shadow_frame->GetVRegReference(arg_offset)->AsArtMethod())); + result->SetL(mh.GetNameAsString(self)); } else if (name == "void java.lang.System.arraycopy(java.lang.Object, int, java.lang.Object, int, int)" || name == "void java.lang.System.arraycopy(char[], int, char[], int, int)") { // Special case array copying without initializing System. diff --git a/runtime/interpreter/interpreter_common.h b/runtime/interpreter/interpreter_common.h index 6e136d62c3..88a84689b5 100644 --- a/runtime/interpreter/interpreter_common.h +++ b/runtime/interpreter/interpreter_common.h @@ -604,10 +604,15 @@ static inline uint32_t FindNextInstructionFollowingException(Thread* self, ThrowLocation throw_location; mirror::Throwable* exception = self->GetException(&throw_location); bool clear_exception = false; - StackHandleScope<3> hs(self); - Handle<mirror::Class> exception_class(hs.NewHandle(exception->GetClass())); - uint32_t found_dex_pc = shadow_frame.GetMethod()->FindCatchBlock(exception_class, dex_pc, - &clear_exception); + uint32_t found_dex_pc; + { + StackHandleScope<3> hs(self); + Handle<mirror::Class> exception_class(hs.NewHandle(exception->GetClass())); + Handle<mirror::ArtMethod> h_method(hs.NewHandle(shadow_frame.GetMethod())); + HandleWrapper<mirror::Object> h(hs.NewHandleWrapper(&this_object)); + found_dex_pc = mirror::ArtMethod::FindCatchBlock(h_method, exception_class, dex_pc, + &clear_exception); + } if (found_dex_pc == DexFile::kDexNoIndex) { instrumentation->MethodUnwindEvent(self, this_object, shadow_frame.GetMethod(), dex_pc); @@ -627,7 +632,7 @@ static inline void UnexpectedOpcode(const Instruction* inst, MethodHelper& mh) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); static inline void UnexpectedOpcode(const Instruction* inst, MethodHelper& mh) { - LOG(FATAL) << "Unexpected instruction: " << inst->DumpString(&mh.GetDexFile()); + LOG(FATAL) << "Unexpected instruction: " << inst->DumpString(mh.GetMethod()->GetDexFile()); exit(0); // Unreachable, keep GCC happy. } @@ -640,7 +645,7 @@ static inline void TraceExecution(const ShadowFrame& shadow_frame, const Instruc std::ostringstream oss; oss << PrettyMethod(shadow_frame.GetMethod()) << StringPrintf("\n0x%x: ", dex_pc) - << inst->DumpString(&mh.GetDexFile()) << "\n"; + << inst->DumpString(mh.GetMethod()->GetDexFile()) << "\n"; for (uint32_t i = 0; i < shadow_frame.NumberOfVRegs(); ++i) { uint32_t raw_value = shadow_frame.GetVReg(i); Object* ref_value = shadow_frame.GetVRegReference(i); diff --git a/runtime/interpreter/interpreter_goto_table_impl.cc b/runtime/interpreter/interpreter_goto_table_impl.cc index 623d9c34a0..19673ac178 100644 --- a/runtime/interpreter/interpreter_goto_table_impl.cc +++ b/runtime/interpreter/interpreter_goto_table_impl.cc @@ -328,11 +328,13 @@ JValue ExecuteGotoImpl(Thread* self, MethodHelper& mh, const DexFile::CodeItem* if (UNLIKELY(self->TestAllFlags())) { CheckSuspend(self); } - Object* obj_result = shadow_frame.GetVRegReference(inst->VRegA_11x(inst_data)); - result.SetJ(0); - result.SetL(obj_result); + const uint8_t vreg_index = inst->VRegA_11x(inst_data); + Object* obj_result = shadow_frame.GetVRegReference(vreg_index); if (do_assignability_check && obj_result != NULL) { - Class* return_type = MethodHelper(shadow_frame.GetMethod()).GetReturnType(); + StackHandleScope<1> hs(self); + MethodHelper mh(hs.NewHandle(shadow_frame.GetMethod())); + Class* return_type = mh.GetReturnType(); + obj_result = shadow_frame.GetVRegReference(vreg_index); if (return_type == NULL) { // Return the pending exception. HANDLE_PENDING_EXCEPTION(); @@ -347,6 +349,7 @@ JValue ExecuteGotoImpl(Thread* self, MethodHelper& mh, const DexFile::CodeItem* HANDLE_PENDING_EXCEPTION(); } } + result.SetL(obj_result); instrumentation::Instrumentation* instrumentation = Runtime::Current()->GetInstrumentation(); if (UNLIKELY(instrumentation->HasMethodExitListeners())) { instrumentation->MethodExitEvent(self, shadow_frame.GetThisObject(code_item->ins_size_), diff --git a/runtime/interpreter/interpreter_switch_impl.cc b/runtime/interpreter/interpreter_switch_impl.cc index d592a53e1d..a43fad365e 100644 --- a/runtime/interpreter/interpreter_switch_impl.cc +++ b/runtime/interpreter/interpreter_switch_impl.cc @@ -244,11 +244,14 @@ JValue ExecuteSwitchImpl(Thread* self, MethodHelper& mh, const DexFile::CodeItem if (UNLIKELY(self->TestAllFlags())) { CheckSuspend(self); } - Object* obj_result = shadow_frame.GetVRegReference(inst->VRegA_11x(inst_data)); - result.SetJ(0); - result.SetL(obj_result); + const size_t ref_idx = inst->VRegA_11x(inst_data); + Object* obj_result = shadow_frame.GetVRegReference(ref_idx); if (do_assignability_check && obj_result != NULL) { - Class* return_type = MethodHelper(shadow_frame.GetMethod()).GetReturnType(); + StackHandleScope<1> hs(self); + MethodHelper mhs(hs.NewHandle(shadow_frame.GetMethod())); + Class* return_type = mhs.GetReturnType(); + // Re-load since it might have moved. + obj_result = shadow_frame.GetVRegReference(ref_idx); if (return_type == NULL) { // Return the pending exception. HANDLE_PENDING_EXCEPTION(); @@ -263,6 +266,7 @@ JValue ExecuteSwitchImpl(Thread* self, MethodHelper& mh, const DexFile::CodeItem HANDLE_PENDING_EXCEPTION(); } } + result.SetL(obj_result); if (UNLIKELY(instrumentation->HasMethodExitListeners())) { instrumentation->MethodExitEvent(self, shadow_frame.GetThisObject(code_item->ins_size_), shadow_frame.GetMethod(), inst->GetDexPc(insns), diff --git a/runtime/mirror/art_method-inl.h b/runtime/mirror/art_method-inl.h index 5f4619b394..8fcacc2a15 100644 --- a/runtime/mirror/art_method-inl.h +++ b/runtime/mirror/art_method-inl.h @@ -295,7 +295,9 @@ inline QuickMethodFrameInfo ArtMethod::GetQuickFrameInfo() { if (UNLIKELY(entry_point == runtime->GetClassLinker()->GetQuickGenericJniTrampoline())) { // Generic JNI frame. DCHECK(IsNative()); - uint32_t handle_refs = MethodHelper(this).GetNumberOfReferenceArgsWithoutReceiver() + 1; + StackHandleScope<1> hs(Thread::Current()); + uint32_t handle_refs = + MethodHelper(hs.NewHandle(this)).GetNumberOfReferenceArgsWithoutReceiver() + 1; size_t scope_size = HandleScope::SizeOf(handle_refs); QuickMethodFrameInfo callee_info = runtime->GetCalleeSaveMethodFrameInfo(Runtime::kRefsAndArgs); @@ -314,10 +316,143 @@ inline QuickMethodFrameInfo ArtMethod::GetQuickFrameInfo() { inline QuickMethodFrameInfo ArtMethod::GetQuickFrameInfo(const void* code_pointer) { DCHECK(code_pointer != nullptr); - DCHECK(code_pointer == GetQuickOatCodePointer()); + DCHECK_EQ(code_pointer, GetQuickOatCodePointer()); return reinterpret_cast<const OatQuickMethodHeader*>(code_pointer)[-1].frame_info_; } +inline const DexFile* ArtMethod::GetDexFile() { + return GetInterfaceMethodIfProxy()->GetDeclaringClass()->GetDexCache()->GetDexFile(); +} + +inline const char* ArtMethod::GetDeclaringClassDescriptor() { + mirror::ArtMethod* method = GetInterfaceMethodIfProxy(); + uint32_t dex_method_idx = method->GetDexMethodIndex(); + if (UNLIKELY(dex_method_idx == DexFile::kDexNoIndex)) { + return "<runtime method>"; + } + const DexFile* dex_file = method->GetDexFile(); + return dex_file->GetMethodDeclaringClassDescriptor(dex_file->GetMethodId(dex_method_idx)); +} + +inline const char* ArtMethod::GetShorty(uint32_t* out_length) { + mirror::ArtMethod* method = GetInterfaceMethodIfProxy(); + const DexFile* dex_file = method->GetDexFile(); + return dex_file->GetMethodShorty(dex_file->GetMethodId(method->GetDexMethodIndex()), out_length); +} + +inline const Signature ArtMethod::GetSignature() { + mirror::ArtMethod* method = GetInterfaceMethodIfProxy(); + uint32_t dex_method_idx = method->GetDexMethodIndex(); + if (dex_method_idx != DexFile::kDexNoIndex) { + const DexFile* dex_file = method->GetDexFile(); + return dex_file->GetMethodSignature(dex_file->GetMethodId(dex_method_idx)); + } + return Signature::NoSignature(); +} + +inline const char* ArtMethod::GetName() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { + mirror::ArtMethod* method = GetInterfaceMethodIfProxy(); + uint32_t dex_method_idx = method->GetDexMethodIndex(); + if (LIKELY(dex_method_idx != DexFile::kDexNoIndex)) { + const DexFile* dex_file = method->GetDexFile(); + return dex_file->GetMethodName(dex_file->GetMethodId(dex_method_idx)); + } + Runtime* runtime = Runtime::Current(); + if (method == runtime->GetResolutionMethod()) { + return "<runtime internal resolution method>"; + } else if (method == runtime->GetImtConflictMethod()) { + return "<runtime internal imt conflict method>"; + } else if (method == runtime->GetCalleeSaveMethod(Runtime::kSaveAll)) { + return "<runtime internal callee-save all registers method>"; + } else if (method == runtime->GetCalleeSaveMethod(Runtime::kRefsOnly)) { + return "<runtime internal callee-save reference registers method>"; + } else if (method == runtime->GetCalleeSaveMethod(Runtime::kRefsAndArgs)) { + return "<runtime internal callee-save reference and argument registers method>"; + } else { + return "<unknown runtime internal method>"; + } +} + +inline const DexFile::CodeItem* ArtMethod::GetCodeItem() { + mirror::ArtMethod* method = GetInterfaceMethodIfProxy(); + return method->GetDexFile()->GetCodeItem(method->GetCodeItemOffset()); +} + +inline bool ArtMethod::IsResolvedTypeIdx(uint16_t type_idx) { + mirror::ArtMethod* method = GetInterfaceMethodIfProxy(); + return method->GetDexCacheResolvedTypes()->Get(type_idx) != nullptr; +} + +inline int32_t ArtMethod::GetLineNumFromDexPC(uint32_t dex_pc) { + mirror::ArtMethod* method = GetInterfaceMethodIfProxy(); + if (dex_pc == DexFile::kDexNoIndex) { + return method->IsNative() ? -2 : -1; + } + return method->GetDexFile()->GetLineNumFromPC(method, dex_pc); +} + +inline const DexFile::ProtoId& ArtMethod::GetPrototype() { + mirror::ArtMethod* method = GetInterfaceMethodIfProxy(); + const DexFile* dex_file = method->GetDexFile(); + return dex_file->GetMethodPrototype(dex_file->GetMethodId(method->GetDexMethodIndex())); +} + +inline const DexFile::TypeList* ArtMethod::GetParameterTypeList() { + mirror::ArtMethod* method = GetInterfaceMethodIfProxy(); + const DexFile* dex_file = method->GetDexFile(); + const DexFile::ProtoId& proto = dex_file->GetMethodPrototype( + dex_file->GetMethodId(method->GetDexMethodIndex())); + return dex_file->GetProtoParameters(proto); +} + +inline const char* ArtMethod::GetDeclaringClassSourceFile() { + return GetInterfaceMethodIfProxy()->GetDeclaringClass()->GetSourceFile(); +} + +inline uint16_t ArtMethod::GetClassDefIndex() { + return GetInterfaceMethodIfProxy()->GetDeclaringClass()->GetDexClassDefIndex(); +} + +inline const DexFile::ClassDef& ArtMethod::GetClassDef() { + mirror::ArtMethod* method = GetInterfaceMethodIfProxy(); + return method->GetDexFile()->GetClassDef(GetClassDefIndex()); +} + +inline const char* ArtMethod::GetReturnTypeDescriptor() { + mirror::ArtMethod* method = GetInterfaceMethodIfProxy(); + const DexFile* dex_file = method->GetDexFile(); + const DexFile::MethodId& method_id = dex_file->GetMethodId(method->GetDexMethodIndex()); + const DexFile::ProtoId& proto_id = dex_file->GetMethodPrototype(method_id); + uint16_t return_type_idx = proto_id.return_type_idx_; + return dex_file->GetTypeDescriptor(dex_file->GetTypeId(return_type_idx)); +} + +inline const char* ArtMethod::GetTypeDescriptorFromTypeIdx(uint16_t type_idx) { + mirror::ArtMethod* method = GetInterfaceMethodIfProxy(); + const DexFile* dex_file = method->GetDexFile(); + return dex_file->GetTypeDescriptor(dex_file->GetTypeId(type_idx)); +} + +inline mirror::ClassLoader* ArtMethod::GetClassLoader() { + return GetInterfaceMethodIfProxy()->GetDeclaringClass()->GetClassLoader(); +} + +inline mirror::DexCache* ArtMethod::GetDexCache() { + return GetInterfaceMethodIfProxy()->GetDeclaringClass()->GetDexCache(); +} + +inline ArtMethod* ArtMethod::GetInterfaceMethodIfProxy() { + mirror::Class* klass = GetDeclaringClass(); + if (LIKELY(!klass->IsProxyClass())) { + return this; + } + mirror::ArtMethod* interface_method = GetDexCacheResolvedMethods()->Get(GetDexMethodIndex()); + DCHECK(interface_method != nullptr); + DCHECK_EQ(interface_method, + Runtime::Current()->GetClassLinker()->FindMethodForProxy(klass, this)); + return interface_method; +} + } // namespace mirror } // namespace art diff --git a/runtime/mirror/art_method.cc b/runtime/mirror/art_method.cc index c01fc72d3d..3db4be3645 100644 --- a/runtime/mirror/art_method.cc +++ b/runtime/mirror/art_method.cc @@ -142,16 +142,16 @@ ArtMethod* ArtMethod::FindOverriddenMethod() { CHECK_EQ(result, Runtime::Current()->GetClassLinker()->FindMethodForProxy(GetDeclaringClass(), this)); } else { - MethodHelper mh(this); - MethodHelper interface_mh; + StackHandleScope<2> hs(Thread::Current()); + MethodHelper mh(hs.NewHandle(this)); + MethodHelper interface_mh(hs.NewHandle<mirror::ArtMethod>(nullptr)); IfTable* iftable = GetDeclaringClass()->GetIfTable(); for (size_t i = 0; i < iftable->Count() && result == NULL; i++) { Class* interface = iftable->GetInterface(i); for (size_t j = 0; j < interface->NumVirtualMethods(); ++j) { - ArtMethod* interface_method = interface->GetVirtualMethod(j); - interface_mh.ChangeMethod(interface_method); + interface_mh.ChangeMethod(interface->GetVirtualMethod(j)); if (mh.HasSameNameAndSignature(&interface_mh)) { - result = interface_method; + result = interface_mh.GetMethod(); break; } } @@ -159,8 +159,10 @@ ArtMethod* ArtMethod::FindOverriddenMethod() { } } #ifndef NDEBUG - MethodHelper result_mh(result); - DCHECK(result == NULL || MethodHelper(this).HasSameNameAndSignature(&result_mh)); + StackHandleScope<2> hs(Thread::Current()); + MethodHelper result_mh(hs.NewHandle(result)); + MethodHelper this_mh(hs.NewHandle(this)); + DCHECK(result == NULL || this_mh.HasSameNameAndSignature(&result_mh)); #endif return result; } @@ -229,10 +231,10 @@ uintptr_t ArtMethod::ToNativePc(const uint32_t dex_pc) { return 0; } -uint32_t ArtMethod::FindCatchBlock(Handle<Class> exception_type, uint32_t dex_pc, - bool* has_no_move_exception) { - MethodHelper mh(this); - const DexFile::CodeItem* code_item = mh.GetCodeItem(); +uint32_t ArtMethod::FindCatchBlock(Handle<ArtMethod> h_this, Handle<Class> exception_type, + uint32_t dex_pc, bool* has_no_move_exception) { + MethodHelper mh(h_this); + const DexFile::CodeItem* code_item = h_this->GetCodeItem(); // Set aside the exception while we resolve its type. Thread* self = Thread::Current(); ThrowLocation throw_location; @@ -260,7 +262,7 @@ uint32_t ArtMethod::FindCatchBlock(Handle<Class> exception_type, uint32_t dex_pc // release its in use context at the end. delete self->GetLongJumpContext(); LOG(WARNING) << "Unresolved exception class when finding catch block: " - << DescriptorToDot(mh.GetTypeDescriptorFromTypeIdx(iter_type_idx)); + << DescriptorToDot(h_this->GetTypeDescriptorFromTypeIdx(iter_type_idx)); } else if (iter_exception_type->IsAssignableFrom(exception_type.Get())) { found_dex_pc = it.GetHandlerAddress(); break; @@ -283,7 +285,7 @@ void ArtMethod::Invoke(Thread* self, uint32_t* args, uint32_t args_size, JValue* if (kIsDebugBuild) { self->AssertThreadSuspensionIsAllowable(); CHECK_EQ(kRunnable, self->GetState()); - CHECK_STREQ(MethodHelper(this).GetShorty(), shorty); + CHECK_STREQ(GetShorty(), shorty); } // Push a transition back into managed code onto the linked list in thread. diff --git a/runtime/mirror/art_method.h b/runtime/mirror/art_method.h index f901512e47..1c21b81f28 100644 --- a/runtime/mirror/art_method.h +++ b/runtime/mirror/art_method.h @@ -88,6 +88,11 @@ class MANAGED ArtMethod : public Object { return (GetAccessFlags() & kAccConstructor) != 0; } + // Returns true if the method is a class initializer. + bool IsClassInitializer() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { + return IsConstructor() && IsStatic(); + } + // Returns true if the method is static, private, or a constructor. bool IsDirect() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { return IsDirect(GetAccessFlags()); @@ -216,14 +221,14 @@ class MANAGED ArtMethod : public Object { // Find the method that this method overrides ArtMethod* FindOverriddenMethod() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); - void Invoke(Thread* self, uint32_t* args, uint32_t args_size, JValue* result, - const char* shorty) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); + void Invoke(Thread* self, uint32_t* args, uint32_t args_size, JValue* result, const char* shorty) + SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags> EntryPointFromInterpreter* GetEntryPointFromInterpreter() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { return GetFieldPtr<EntryPointFromInterpreter*, kVerifyFlags>( - OFFSET_OF_OBJECT_MEMBER(ArtMethod, entry_point_from_interpreter_)); + OFFSET_OF_OBJECT_MEMBER(ArtMethod, entry_point_from_interpreter_)); } template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags> @@ -281,7 +286,7 @@ class MANAGED ArtMethod : public Object { * * NOTE: For Thumb both pc and code are offset by 1 indicating the Thumb state. */ - return (code <= pc && pc <= code + GetCodeSize()); + return code <= pc && pc <= code + GetCodeSize(); } void AssertPcIsWithinQuickCode(uintptr_t pc) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); @@ -398,8 +403,8 @@ class MANAGED ArtMethod : public Object { // Find the catch block for the given exception type and dex_pc. When a catch block is found, // indicates whether the found catch block is responsible for clearing the exception or whether // a move-exception instruction is present. - uint32_t FindCatchBlock(Handle<Class> exception_type, uint32_t dex_pc, - bool* has_no_move_exception) + static uint32_t FindCatchBlock(Handle<ArtMethod> h_this, Handle<Class> exception_type, + uint32_t dex_pc, bool* has_no_move_exception) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); static void SetClass(Class* java_lang_reflect_ArtMethod); @@ -414,6 +419,30 @@ class MANAGED ArtMethod : public Object { static void VisitRoots(RootCallback* callback, void* arg) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); + const DexFile* GetDexFile() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); + const char* GetDeclaringClassDescriptor() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); + const char* GetShorty() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { + uint32_t unused_length; + return GetShorty(&unused_length); + } + const char* GetShorty(uint32_t* out_length) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); + const Signature GetSignature() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); + const char* GetName() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); + const DexFile::CodeItem* GetCodeItem() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); + bool IsResolvedTypeIdx(uint16_t type_idx) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); + int32_t GetLineNumFromDexPC(uint32_t dex_pc) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); + const DexFile::ProtoId& GetPrototype() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); + const DexFile::TypeList* GetParameterTypeList() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); + const char* GetDeclaringClassSourceFile() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); + uint16_t GetClassDefIndex() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); + const DexFile::ClassDef& GetClassDef() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); + const char* GetReturnTypeDescriptor() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); + const char* GetTypeDescriptorFromTypeIdx(uint16_t type_idx) + SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); + mirror::ClassLoader* GetClassLoader() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); + mirror::DexCache* GetDexCache() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); + ArtMethod* GetInterfaceMethodIfProxy() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); + protected: // Field order required by test "ValidateFieldOrderOfJavaCppUnionClasses". // The class we are a part of. diff --git a/runtime/mirror/class.cc b/runtime/mirror/class.cc index a4090932fd..7b31a8270f 100644 --- a/runtime/mirror/class.cc +++ b/runtime/mirror/class.cc @@ -366,11 +366,9 @@ ArtMethod* Class::FindInterfaceMethod(const DexCache* dex_cache, uint32_t dex_me } ArtMethod* Class::FindDeclaredDirectMethod(const StringPiece& name, const StringPiece& signature) { - MethodHelper mh; for (size_t i = 0; i < NumDirectMethods(); ++i) { ArtMethod* method = GetDirectMethod(i); - mh.ChangeMethod(method); - if (name == mh.GetName() && mh.GetSignature() == signature) { + if (name == method->GetName() && method->GetSignature() == signature) { return method; } } @@ -378,11 +376,9 @@ ArtMethod* Class::FindDeclaredDirectMethod(const StringPiece& name, const String } ArtMethod* Class::FindDeclaredDirectMethod(const StringPiece& name, const Signature& signature) { - MethodHelper mh; for (size_t i = 0; i < NumDirectMethods(); ++i) { ArtMethod* method = GetDirectMethod(i); - mh.ChangeMethod(method); - if (name == mh.GetName() && signature == mh.GetSignature()) { + if (name == method->GetName() && signature == method->GetSignature()) { return method; } } @@ -432,24 +428,19 @@ ArtMethod* Class::FindDirectMethod(const DexCache* dex_cache, uint32_t dex_metho } ArtMethod* Class::FindDeclaredVirtualMethod(const StringPiece& name, const StringPiece& signature) { - MethodHelper mh; for (size_t i = 0; i < NumVirtualMethods(); ++i) { ArtMethod* method = GetVirtualMethod(i); - mh.ChangeMethod(method); - if (name == mh.GetName() && mh.GetSignature() == signature) { + if (name == method->GetName() && method->GetSignature() == signature) { return method; } } return NULL; } -ArtMethod* Class::FindDeclaredVirtualMethod(const StringPiece& name, - const Signature& signature) { - MethodHelper mh; +ArtMethod* Class::FindDeclaredVirtualMethod(const StringPiece& name, const Signature& signature) { for (size_t i = 0; i < NumVirtualMethods(); ++i) { ArtMethod* method = GetVirtualMethod(i); - mh.ChangeMethod(method); - if (name == mh.GetName() && signature == mh.GetSignature()) { + if (name == method->GetName() && signature == method->GetSignature()) { return method; } } @@ -501,13 +492,9 @@ ArtMethod* Class::FindVirtualMethod(const DexCache* dex_cache, uint32_t dex_meth ArtMethod* Class::FindClassInitializer() { for (size_t i = 0; i < NumDirectMethods(); ++i) { ArtMethod* method = GetDirectMethod(i); - if (method->IsConstructor() && method->IsStatic()) { - if (kIsDebugBuild) { - MethodHelper mh(method); - CHECK(mh.IsClassInitializer()); - CHECK_STREQ(mh.GetName(), "<clinit>"); - CHECK_STREQ(mh.GetSignature().ToString().c_str(), "()V"); - } + if (method->IsClassInitializer()) { + DCHECK_STREQ(method->GetName(), "<clinit>"); + DCHECK_STREQ(method->GetSignature().ToString().c_str(), "()V"); return method; } } diff --git a/runtime/mirror/object_test.cc b/runtime/mirror/object_test.cc index 18e50ce013..f85fb2748b 100644 --- a/runtime/mirror/object_test.cc +++ b/runtime/mirror/object_test.cc @@ -451,7 +451,7 @@ TEST_F(ObjectTest, DescriptorCompare) { jobject jclass_loader_1 = LoadDex("ProtoCompare"); jobject jclass_loader_2 = LoadDex("ProtoCompare2"); - StackHandleScope<2> hs(soa.Self()); + StackHandleScope<4> hs(soa.Self()); Handle<ClassLoader> class_loader_1(hs.NewHandle(soa.Decode<ClassLoader*>(jclass_loader_1))); Handle<ClassLoader> class_loader_2(hs.NewHandle(soa.Decode<ClassLoader*>(jclass_loader_2))); @@ -461,33 +461,25 @@ TEST_F(ObjectTest, DescriptorCompare) { ASSERT_TRUE(klass2 != NULL); ArtMethod* m1_1 = klass1->GetVirtualMethod(0); - MethodHelper mh(m1_1); - EXPECT_STREQ(mh.GetName(), "m1"); + EXPECT_STREQ(m1_1->GetName(), "m1"); ArtMethod* m2_1 = klass1->GetVirtualMethod(1); - mh.ChangeMethod(m2_1); - EXPECT_STREQ(mh.GetName(), "m2"); + EXPECT_STREQ(m2_1->GetName(), "m2"); ArtMethod* m3_1 = klass1->GetVirtualMethod(2); - mh.ChangeMethod(m3_1); - EXPECT_STREQ(mh.GetName(), "m3"); + EXPECT_STREQ(m3_1->GetName(), "m3"); ArtMethod* m4_1 = klass1->GetVirtualMethod(3); - mh.ChangeMethod(m4_1); - EXPECT_STREQ(mh.GetName(), "m4"); + EXPECT_STREQ(m4_1->GetName(), "m4"); ArtMethod* m1_2 = klass2->GetVirtualMethod(0); - mh.ChangeMethod(m1_2); - EXPECT_STREQ(mh.GetName(), "m1"); + EXPECT_STREQ(m1_2->GetName(), "m1"); ArtMethod* m2_2 = klass2->GetVirtualMethod(1); - mh.ChangeMethod(m2_2); - EXPECT_STREQ(mh.GetName(), "m2"); + EXPECT_STREQ(m2_2->GetName(), "m2"); ArtMethod* m3_2 = klass2->GetVirtualMethod(2); - mh.ChangeMethod(m3_2); - EXPECT_STREQ(mh.GetName(), "m3"); + EXPECT_STREQ(m3_2->GetName(), "m3"); ArtMethod* m4_2 = klass2->GetVirtualMethod(3); - mh.ChangeMethod(m4_2); - EXPECT_STREQ(mh.GetName(), "m4"); + EXPECT_STREQ(m4_2->GetName(), "m4"); - mh.ChangeMethod(m1_1); - MethodHelper mh2(m1_2); + MethodHelper mh(hs.NewHandle(m1_1)); + MethodHelper mh2(hs.NewHandle(m1_2)); EXPECT_TRUE(mh.HasSameNameAndSignature(&mh2)); EXPECT_TRUE(mh2.HasSameNameAndSignature(&mh)); diff --git a/runtime/mirror/throwable.cc b/runtime/mirror/throwable.cc index 6874fe567b..6efc9e2f54 100644 --- a/runtime/mirror/throwable.cc +++ b/runtime/mirror/throwable.cc @@ -85,16 +85,14 @@ std::string Throwable::Dump() { ObjectArray<Object>* method_trace = down_cast<ObjectArray<Object>*>(stack_state); int32_t depth = method_trace->GetLength() - 1; IntArray* pc_trace = down_cast<IntArray*>(method_trace->Get(depth)); - MethodHelper mh; if (depth == 0) { result += "(Throwable with empty stack trace)"; } else { for (int32_t i = 0; i < depth; ++i) { - ArtMethod* method = down_cast<ArtMethod*>(method_trace->Get(i)); - mh.ChangeMethod(method); + mirror::ArtMethod* method = down_cast<ArtMethod*>(method_trace->Get(i)); uint32_t dex_pc = pc_trace->Get(i); - int32_t line_number = mh.GetLineNumFromDexPC(dex_pc); - const char* source_file = mh.GetDeclaringClassSourceFile(); + int32_t line_number = method->GetLineNumFromDexPC(dex_pc); + const char* source_file = method->GetDeclaringClassSourceFile(); result += StringPrintf(" at %s (%s:%d)\n", PrettyMethod(method, true).c_str(), source_file, line_number); } diff --git a/runtime/monitor.cc b/runtime/monitor.cc index f73ef1e3de..a19445b189 100644 --- a/runtime/monitor.cc +++ b/runtime/monitor.cc @@ -967,14 +967,13 @@ void Monitor::VisitLocks(StackVisitor* stack_visitor, void (*callback)(mirror::O } // <clinit> is another special case. The runtime holds the class lock while calling <clinit>. - MethodHelper mh(m); - if (mh.IsClassInitializer()) { + if (m->IsClassInitializer()) { callback(m->GetDeclaringClass(), callback_context); // Fall through because there might be synchronization in the user code too. } // Is there any reason to believe there's any synchronization in this method? - const DexFile::CodeItem* code_item = mh.GetCodeItem(); + const DexFile::CodeItem* code_item = m->GetCodeItem(); CHECK(code_item != NULL) << PrettyMethod(m); if (code_item->tries_size_ == 0) { return; // No "tries" implies no synchronization, so no held locks to report. @@ -1048,12 +1047,11 @@ void Monitor::TranslateLocation(mirror::ArtMethod* method, uint32_t dex_pc, *line_number = 0; return; } - MethodHelper mh(method); - *source_file = mh.GetDeclaringClassSourceFile(); + *source_file = method->GetDeclaringClassSourceFile(); if (*source_file == NULL) { *source_file = ""; } - *line_number = mh.GetLineNumFromDexPC(dex_pc); + *line_number = method->GetLineNumFromDexPC(dex_pc); } uint32_t Monitor::GetOwnerThreadId() { diff --git a/runtime/object_utils.h b/runtime/object_utils.h index a05ebe6df3..28ce8f34ac 100644 --- a/runtime/object_utils.h +++ b/runtime/object_utils.h @@ -121,12 +121,9 @@ class FieldHelper { class MethodHelper { public: - MethodHelper() : method_(nullptr), shorty_(nullptr), shorty_len_(0) {} - - explicit MethodHelper(mirror::ArtMethod* m) - SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) - : method_(nullptr), shorty_(nullptr), shorty_len_(0) { - SetMethod(m); + explicit MethodHelper(Handle<mirror::ArtMethod> m) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) + : method_(m), shorty_(nullptr), shorty_len_(0) { + SetMethod(m.Get()); } void ChangeMethod(mirror::ArtMethod* new_m) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { @@ -135,48 +132,25 @@ class MethodHelper { shorty_ = nullptr; } - mirror::ArtMethod* GetMethod() const { - return method_; + mirror::ArtMethod* GetMethod() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { + return method_->GetInterfaceMethodIfProxy(); } - const char* GetName() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - const DexFile& dex_file = GetDexFile(); - uint32_t dex_method_idx = method_->GetDexMethodIndex(); - if (LIKELY(dex_method_idx != DexFile::kDexNoIndex)) { - return dex_file.GetMethodName(dex_file.GetMethodId(dex_method_idx)); - } else { - Runtime* runtime = Runtime::Current(); - if (method_ == runtime->GetResolutionMethod()) { - return "<runtime internal resolution method>"; - } else if (method_ == runtime->GetImtConflictMethod()) { - return "<runtime internal imt conflict method>"; - } else if (method_ == runtime->GetCalleeSaveMethod(Runtime::kSaveAll)) { - return "<runtime internal callee-save all registers method>"; - } else if (method_ == runtime->GetCalleeSaveMethod(Runtime::kRefsOnly)) { - return "<runtime internal callee-save reference registers method>"; - } else if (method_ == runtime->GetCalleeSaveMethod(Runtime::kRefsAndArgs)) { - return "<runtime internal callee-save reference and argument registers method>"; - } else { - return "<unknown runtime internal method>"; - } - } - } - - mirror::String* GetNameAsString() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - const DexFile& dex_file = GetDexFile(); - uint32_t dex_method_idx = method_->GetDexMethodIndex(); - const DexFile::MethodId& method_id = dex_file.GetMethodId(dex_method_idx); - StackHandleScope<1> hs(Thread::Current()); - Handle<mirror::DexCache> dex_cache(hs.NewHandle(GetDexCache())); - return GetClassLinker()->ResolveString(dex_file, method_id.name_idx_, dex_cache); + mirror::String* GetNameAsString(Thread* self) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { + const DexFile* dex_file = method_->GetDexFile(); + mirror::ArtMethod* method = method_->GetInterfaceMethodIfProxy(); + uint32_t dex_method_idx = method->GetDexMethodIndex(); + const DexFile::MethodId& method_id = dex_file->GetMethodId(dex_method_idx); + StackHandleScope<1> hs(self); + Handle<mirror::DexCache> dex_cache(hs.NewHandle(method->GetDexCache())); + return Runtime::Current()->GetClassLinker()->ResolveString(*dex_file, method_id.name_idx_, + dex_cache); } const char* GetShorty() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { const char* result = shorty_; if (result == nullptr) { - const DexFile& dex_file = GetDexFile(); - result = dex_file.GetMethodShorty(dex_file.GetMethodId(method_->GetDexMethodIndex()), - &shorty_len_); + result = method_->GetShorty(&shorty_len_); shorty_ = result; } return result; @@ -203,94 +177,27 @@ class MethodHelper { return refs; } - const Signature GetSignature() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - const DexFile& dex_file = GetDexFile(); - uint32_t dex_method_idx = method_->GetDexMethodIndex(); - if (dex_method_idx != DexFile::kDexNoIndex) { - return dex_file.GetMethodSignature(dex_file.GetMethodId(dex_method_idx)); - } else { - return Signature::NoSignature(); - } - } - - const DexFile::ProtoId& GetPrototype() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - const DexFile& dex_file = GetDexFile(); - return dex_file.GetMethodPrototype(dex_file.GetMethodId(method_->GetDexMethodIndex())); - } - - const DexFile::TypeList* GetParameterTypeList() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - const DexFile::ProtoId& proto = GetPrototype(); - return GetDexFile().GetProtoParameters(proto); - } - + // May cause thread suspension due to GetClassFromTypeIdx calling ResolveType this caused a large + // number of bugs at call sites. mirror::Class* GetReturnType(bool resolve = true) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - const DexFile& dex_file = GetDexFile(); - const DexFile::MethodId& method_id = dex_file.GetMethodId(method_->GetDexMethodIndex()); - const DexFile::ProtoId& proto_id = dex_file.GetMethodPrototype(method_id); + mirror::ArtMethod* method = GetMethod(); + const DexFile* dex_file = method->GetDexFile(); + const DexFile::MethodId& method_id = dex_file->GetMethodId(method->GetDexMethodIndex()); + const DexFile::ProtoId& proto_id = dex_file->GetMethodPrototype(method_id); uint16_t return_type_idx = proto_id.return_type_idx_; return GetClassFromTypeIdx(return_type_idx, resolve); } - const char* GetReturnTypeDescriptor() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - const DexFile& dex_file = GetDexFile(); - const DexFile::MethodId& method_id = dex_file.GetMethodId(method_->GetDexMethodIndex()); - const DexFile::ProtoId& proto_id = dex_file.GetMethodPrototype(method_id); - uint16_t return_type_idx = proto_id.return_type_idx_; - return dex_file.GetTypeDescriptor(dex_file.GetTypeId(return_type_idx)); - } - - int32_t GetLineNumFromDexPC(uint32_t dex_pc) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - if (dex_pc == DexFile::kDexNoIndex) { - return method_->IsNative() ? -2 : -1; - } else { - const DexFile& dex_file = GetDexFile(); - return dex_file.GetLineNumFromPC(method_, dex_pc); - } - } - - const char* GetDeclaringClassDescriptor() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - const DexFile& dex_file = GetDexFile(); - uint32_t dex_method_idx = method_->GetDexMethodIndex(); - if (UNLIKELY(dex_method_idx == DexFile::kDexNoIndex)) { - return "<runtime method>"; - } - return dex_file.GetMethodDeclaringClassDescriptor(dex_file.GetMethodId(dex_method_idx)); - } - - const char* GetDeclaringClassSourceFile() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - return method_->GetDeclaringClass()->GetSourceFile(); - } - - uint16_t GetClassDefIndex() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - return method_->GetDeclaringClass()->GetDexClassDefIndex(); - } - - const DexFile::ClassDef& GetClassDef() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - return GetDexFile().GetClassDef(GetClassDefIndex()); - } - - mirror::ClassLoader* GetClassLoader() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - return method_->GetDeclaringClass()->GetClassLoader(); - } - - bool IsStatic() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - return method_->IsStatic(); - } - - bool IsClassInitializer() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - return method_->IsConstructor() && IsStatic(); - } - size_t NumArgs() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { // "1 +" because the first in Args is the receiver. // "- 1" because we don't count the return type. - return (IsStatic() ? 0 : 1) + GetShortyLength() - 1; + return (method_->IsStatic() ? 0 : 1) + GetShortyLength() - 1; } // Get the primitive type associated with the given parameter. Primitive::Type GetParamPrimitiveType(size_t param) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { CHECK_LT(param, NumArgs()); - if (IsStatic()) { + if (GetMethod()->IsStatic()) { param++; // 0th argument must skip return value at start of the shorty } else if (param == 0) { return Primitive::kPrimNot; @@ -310,21 +217,20 @@ class MethodHelper { } bool HasSameNameAndSignature(MethodHelper* other) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - const DexFile& dex_file = GetDexFile(); - const DexFile::MethodId& mid = dex_file.GetMethodId(method_->GetDexMethodIndex()); - if (GetDexCache() == other->GetDexCache()) { + const DexFile* dex_file = method_->GetDexFile(); + const DexFile::MethodId& mid = dex_file->GetMethodId(GetMethod()->GetDexMethodIndex()); + if (method_->GetDexCache() == other->method_->GetDexCache()) { const DexFile::MethodId& other_mid = - dex_file.GetMethodId(other->method_->GetDexMethodIndex()); + dex_file->GetMethodId(other->GetMethod()->GetDexMethodIndex()); return mid.name_idx_ == other_mid.name_idx_ && mid.proto_idx_ == other_mid.proto_idx_; } - const DexFile& other_dex_file = other->GetDexFile(); + const DexFile* other_dex_file = other->method_->GetDexFile(); const DexFile::MethodId& other_mid = - other_dex_file.GetMethodId(other->method_->GetDexMethodIndex()); - if (!DexFileStringEquals(&dex_file, mid.name_idx_, - &other_dex_file, other_mid.name_idx_)) { + other_dex_file->GetMethodId(other->GetMethod()->GetDexMethodIndex()); + if (!DexFileStringEquals(dex_file, mid.name_idx_, other_dex_file, other_mid.name_idx_)) { return false; // Name mismatch. } - return dex_file.GetMethodSignature(mid) == other_dex_file.GetMethodSignature(other_mid); + return dex_file->GetMethodSignature(mid) == other_dex_file->GetMethodSignature(other_mid); } bool HasSameSignatureWithDifferentClassLoaders(MethodHelper* other) @@ -332,8 +238,8 @@ class MethodHelper { if (UNLIKELY(GetReturnType() != other->GetReturnType())) { return false; } - const DexFile::TypeList* types = GetParameterTypeList(); - const DexFile::TypeList* other_types = other->GetParameterTypeList(); + const DexFile::TypeList* types = method_->GetParameterTypeList(); + const DexFile::TypeList* other_types = other->method_->GetParameterTypeList(); if (types == nullptr) { return (other_types == nullptr) || (other_types->Size() == 0); } else if (UNLIKELY(other_types == nullptr)) { @@ -354,84 +260,63 @@ class MethodHelper { return true; } - const DexFile::CodeItem* GetCodeItem() - SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - return GetDexFile().GetCodeItem(method_->GetCodeItemOffset()); - } - - bool IsResolvedTypeIdx(uint16_t type_idx) const - SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - return method_->GetDexCacheResolvedTypes()->Get(type_idx) != nullptr; - } - mirror::Class* GetClassFromTypeIdx(uint16_t type_idx, bool resolve = true) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - mirror::Class* type = method_->GetDexCacheResolvedTypes()->Get(type_idx); + mirror::ArtMethod* method = GetMethod(); + mirror::Class* type = method->GetDexCacheResolvedTypes()->Get(type_idx); if (type == nullptr && resolve) { - type = GetClassLinker()->ResolveType(type_idx, method_); + type = Runtime::Current()->GetClassLinker()->ResolveType(type_idx, method); CHECK(type != nullptr || Thread::Current()->IsExceptionPending()); } return type; } - const char* GetTypeDescriptorFromTypeIdx(uint16_t type_idx) - SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - const DexFile& dex_file = GetDexFile(); - return dex_file.GetTypeDescriptor(dex_file.GetTypeId(type_idx)); - } - mirror::Class* GetDexCacheResolvedType(uint16_t type_idx) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - return method_->GetDexCacheResolvedTypes()->Get(type_idx); - } - - const DexFile& GetDexFile() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - return *GetDexCache()->GetDexFile(); - } - - mirror::DexCache* GetDexCache() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - return method_->GetDeclaringClass()->GetDexCache(); + return GetMethod()->GetDexCacheResolvedTypes()->Get(type_idx); } mirror::String* ResolveString(uint32_t string_idx) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - mirror::String* s = method_->GetDexCacheStrings()->Get(string_idx); + mirror::ArtMethod* method = GetMethod(); + mirror::String* s = method->GetDexCacheStrings()->Get(string_idx); if (UNLIKELY(s == nullptr)) { StackHandleScope<1> hs(Thread::Current()); - Handle<mirror::DexCache> dex_cache(hs.NewHandle(GetDexCache())); - s = GetClassLinker()->ResolveString(GetDexFile(), string_idx, dex_cache); + Handle<mirror::DexCache> dex_cache(hs.NewHandle(method->GetDexCache())); + s = Runtime::Current()->GetClassLinker()->ResolveString(*method->GetDexFile(), string_idx, + dex_cache); } return s; } uint32_t FindDexMethodIndexInOtherDexFile(const DexFile& other_dexfile) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - const DexFile& dexfile = GetDexFile(); - if (&dexfile == &other_dexfile) { - return method_->GetDexMethodIndex(); + mirror::ArtMethod* method = GetMethod(); + const DexFile* dexfile = method->GetDexFile(); + if (dexfile == &other_dexfile) { + return method->GetDexMethodIndex(); } - const DexFile::MethodId& mid = dexfile.GetMethodId(method_->GetDexMethodIndex()); - const char* mid_declaring_class_descriptor = dexfile.StringByTypeIdx(mid.class_idx_); + const DexFile::MethodId& mid = dexfile->GetMethodId(method->GetDexMethodIndex()); + const char* mid_declaring_class_descriptor = dexfile->StringByTypeIdx(mid.class_idx_); const DexFile::StringId* other_descriptor = other_dexfile.FindStringId(mid_declaring_class_descriptor); if (other_descriptor != nullptr) { const DexFile::TypeId* other_type_id = other_dexfile.FindTypeId(other_dexfile.GetIndexForStringId(*other_descriptor)); if (other_type_id != nullptr) { - const char* mid_name = dexfile.GetMethodName(mid); + const char* mid_name = dexfile->GetMethodName(mid); const DexFile::StringId* other_name = other_dexfile.FindStringId(mid_name); if (other_name != nullptr) { uint16_t other_return_type_idx; std::vector<uint16_t> other_param_type_idxs; - bool success = other_dexfile.CreateTypeList(dexfile.GetMethodSignature(mid).ToString(), - &other_return_type_idx, - &other_param_type_idxs); + bool success = other_dexfile.CreateTypeList( + dexfile->GetMethodSignature(mid).ToString(), &other_return_type_idx, + &other_param_type_idxs); if (success) { const DexFile::ProtoId* other_sig = other_dexfile.FindProtoId(other_return_type_idx, other_param_type_idxs); if (other_sig != nullptr) { - const DexFile::MethodId* other_mid = other_dexfile.FindMethodId(*other_type_id, - *other_name, - *other_sig); + const DexFile::MethodId* other_mid = other_dexfile.FindMethodId( + *other_type_id, *other_name, *other_sig); if (other_mid != nullptr) { return other_dexfile.GetIndexForMethodId(*other_mid); } @@ -448,15 +333,17 @@ class MethodHelper { uint32_t FindDexMethodIndexInOtherDexFile(const DexFile& other_dexfile, uint32_t name_and_signature_idx) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - const DexFile& dexfile = GetDexFile(); - const DexFile::MethodId& mid = dexfile.GetMethodId(method_->GetDexMethodIndex()); + mirror::ArtMethod* method = GetMethod(); + const DexFile* dexfile = method->GetDexFile(); + const uint32_t dex_method_idx = method->GetDexMethodIndex(); + const DexFile::MethodId& mid = dexfile->GetMethodId(dex_method_idx); const DexFile::MethodId& name_and_sig_mid = other_dexfile.GetMethodId(name_and_signature_idx); - DCHECK_STREQ(dexfile.GetMethodName(mid), other_dexfile.GetMethodName(name_and_sig_mid)); - DCHECK_EQ(dexfile.GetMethodSignature(mid), other_dexfile.GetMethodSignature(name_and_sig_mid)); - if (&dexfile == &other_dexfile) { - return method_->GetDexMethodIndex(); + DCHECK_STREQ(dexfile->GetMethodName(mid), other_dexfile.GetMethodName(name_and_sig_mid)); + DCHECK_EQ(dexfile->GetMethodSignature(mid), other_dexfile.GetMethodSignature(name_and_sig_mid)); + if (dexfile == &other_dexfile) { + return dex_method_idx; } - const char* mid_declaring_class_descriptor = dexfile.StringByTypeIdx(mid.class_idx_); + const char* mid_declaring_class_descriptor = dexfile->StringByTypeIdx(mid.class_idx_); const DexFile::StringId* other_descriptor = other_dexfile.FindStringId(mid_declaring_class_descriptor); if (other_descriptor != nullptr) { @@ -478,24 +365,10 @@ class MethodHelper { // Set the method_ field, for proxy methods looking up the interface method via the resolved // methods table. void SetMethod(mirror::ArtMethod* method) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - if (method != nullptr) { - mirror::Class* klass = method->GetDeclaringClass(); - if (UNLIKELY(klass->IsProxyClass())) { - mirror::ArtMethod* interface_method = - method->GetDexCacheResolvedMethods()->Get(method->GetDexMethodIndex()); - DCHECK(interface_method != nullptr); - DCHECK(interface_method == GetClassLinker()->FindMethodForProxy(klass, method)); - method = interface_method; - } - } - method_ = method; - } - - ClassLinker* GetClassLinker() ALWAYS_INLINE { - return Runtime::Current()->GetClassLinker(); + method_.Assign(method); } - mirror::ArtMethod* method_; + Handle<mirror::ArtMethod> method_; const char* shorty_; uint32_t shorty_len_; diff --git a/runtime/profiler.cc b/runtime/profiler.cc index bad79b3a3b..00bb50179a 100644 --- a/runtime/profiler.cc +++ b/runtime/profiler.cc @@ -378,8 +378,7 @@ void BackgroundMethodSamplingProfiler::RecordMethod(mirror::ArtMethod* method) { bool is_filtered = false; - MethodHelper mh(method); - if (strcmp(mh.GetName(), "<clinit>") == 0) { + if (strcmp(method->GetName(), "<clinit>") == 0) { // always filter out class init is_filtered = true; } @@ -460,8 +459,7 @@ uint32_t ProfileSampleResults::Write(std::ostream &os) { mirror::ArtMethod *method = meth_iter.first; std::string method_name = PrettyMethod(method); - MethodHelper mh(method); - const DexFile::CodeItem* codeitem = mh.GetCodeItem(); + const DexFile::CodeItem* codeitem = method->GetCodeItem(); uint32_t method_size = 0; if (codeitem != nullptr) { method_size = codeitem->insns_size_in_code_units_; diff --git a/runtime/quick_exception_handler.cc b/runtime/quick_exception_handler.cc index b9cec40ebf..e3f9afc787 100644 --- a/runtime/quick_exception_handler.cc +++ b/runtime/quick_exception_handler.cc @@ -71,11 +71,13 @@ class CatchBlockStackVisitor FINAL : public StackVisitor { DCHECK(method->IsCalleeSaveMethod()); return true; } - return HandleTryItems(method); + StackHandleScope<1> hs(self_); + return HandleTryItems(hs.NewHandle(method)); } private: - bool HandleTryItems(mirror::ArtMethod* method) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { + bool HandleTryItems(Handle<mirror::ArtMethod> method) + SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { uint32_t dex_pc = DexFile::kDexNoIndex; if (!method->IsNative()) { dex_pc = GetDexPc(); @@ -84,10 +86,11 @@ class CatchBlockStackVisitor FINAL : public StackVisitor { bool clear_exception = false; StackHandleScope<1> hs(Thread::Current()); Handle<mirror::Class> to_find(hs.NewHandle((*exception_)->GetClass())); - uint32_t found_dex_pc = method->FindCatchBlock(to_find, dex_pc, &clear_exception); + uint32_t found_dex_pc = mirror::ArtMethod::FindCatchBlock(method, to_find, dex_pc, + &clear_exception); exception_handler_->SetClearException(clear_exception); if (found_dex_pc != DexFile::kDexNoIndex) { - exception_handler_->SetHandlerMethod(method); + exception_handler_->SetHandlerMethod(method.Get()); exception_handler_->SetHandlerDexPc(found_dex_pc); exception_handler_->SetHandlerQuickFramePc(method->ToNativePc(found_dex_pc)); exception_handler_->SetHandlerQuickFrame(GetCurrentQuickFrame()); @@ -175,8 +178,7 @@ class DeoptimizeStackVisitor FINAL : public StackVisitor { private: bool HandleDeoptimization(mirror::ArtMethod* m) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - MethodHelper mh(m); - const DexFile::CodeItem* code_item = mh.GetCodeItem(); + const DexFile::CodeItem* code_item = m->GetCodeItem(); CHECK(code_item != nullptr); uint16_t num_regs = code_item->registers_size_; uint32_t dex_pc = GetDexPc(); @@ -184,10 +186,11 @@ class DeoptimizeStackVisitor FINAL : public StackVisitor { uint32_t new_dex_pc = dex_pc + inst->SizeInCodeUnits(); ShadowFrame* new_frame = ShadowFrame::Create(num_regs, nullptr, m, new_dex_pc); StackHandleScope<2> hs(self_); - Handle<mirror::DexCache> dex_cache(hs.NewHandle(mh.GetDexCache())); - Handle<mirror::ClassLoader> class_loader(hs.NewHandle(mh.GetClassLoader())); - verifier::MethodVerifier verifier(&mh.GetDexFile(), &dex_cache, &class_loader, - &mh.GetClassDef(), code_item, m->GetDexMethodIndex(), m, + mirror::Class* declaring_class = m->GetDeclaringClass(); + Handle<mirror::DexCache> h_dex_cache(hs.NewHandle(declaring_class->GetDexCache())); + Handle<mirror::ClassLoader> h_class_loader(hs.NewHandle(declaring_class->GetClassLoader())); + verifier::MethodVerifier verifier(h_dex_cache->GetDexFile(), &h_dex_cache, &h_class_loader, + &m->GetClassDef(), code_item, m->GetDexMethodIndex(), m, m->GetAccessFlags(), false, true, true); verifier.Verify(); std::vector<int32_t> kinds = verifier.DescribeVRegs(dex_pc); diff --git a/runtime/reflection.cc b/runtime/reflection.cc index c08cc30c68..89cdb4dc7e 100644 --- a/runtime/reflection.cc +++ b/runtime/reflection.cc @@ -222,7 +222,7 @@ class ArgArray { mirror::Object* receiver, mirror::ObjectArray<mirror::Object>* args, MethodHelper& mh) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - const DexFile::TypeList* classes = mh.GetParameterTypeList(); + const DexFile::TypeList* classes = mh.GetMethod()->GetParameterTypeList(); // Set receiver if non-null (method is not static) if (receiver != nullptr) { Append(receiver); @@ -349,7 +349,7 @@ class ArgArray { static void CheckMethodArguments(mirror::ArtMethod* m, uint32_t* args) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - const DexFile::TypeList* params = MethodHelper(m).GetParameterTypeList(); + const DexFile::TypeList* params = m->GetParameterTypeList(); if (params == nullptr) { return; // No arguments so nothing to check. } @@ -359,24 +359,31 @@ static void CheckMethodArguments(mirror::ArtMethod* m, uint32_t* args) if (!m->IsStatic()) { offset = 1; } + // TODO: If args contain object references, it may cause problems + Thread* self = Thread::Current(); + StackHandleScope<1> hs(self); + Handle<mirror::ArtMethod> h_m(hs.NewHandle(m)); + MethodHelper mh(h_m); for (uint32_t i = 0; i < num_params; i++) { uint16_t type_idx = params->GetTypeItem(i).type_idx_; - mirror::Class* param_type = MethodHelper(m).GetClassFromTypeIdx(type_idx); + mirror::Class* param_type = mh.GetClassFromTypeIdx(type_idx); if (param_type == nullptr) { - Thread* self = Thread::Current(); CHECK(self->IsExceptionPending()); LOG(ERROR) << "Internal error: unresolvable type for argument type in JNI invoke: " - << MethodHelper(m).GetTypeDescriptorFromTypeIdx(type_idx) << "\n" + << h_m->GetTypeDescriptorFromTypeIdx(type_idx) << "\n" << self->GetException(nullptr)->Dump(); self->ClearException(); ++error_count; } else if (!param_type->IsPrimitive()) { // TODO: check primitives are in range. + // TODO: There is a compaction bug here since GetClassFromTypeIdx can cause thread suspension, + // this is a hard to fix problem since the args can contain Object*, we need to save and + // restore them by using a visitor similar to the ones used in the trampoline entrypoints. mirror::Object* argument = reinterpret_cast<mirror::Object*>(args[i + offset]); if (argument != nullptr && !argument->InstanceOf(param_type)) { LOG(ERROR) << "JNI ERROR (app bug): attempt to pass an instance of " << PrettyTypeOf(argument) << " as argument " << (i + 1) - << " to " << PrettyMethod(m); + << " to " << PrettyMethod(h_m.Get()); ++error_count; } } else if (param_type->IsPrimitiveLong() || param_type->IsPrimitiveDouble()) { @@ -387,7 +394,7 @@ static void CheckMethodArguments(mirror::ArtMethod* m, uint32_t* args) // TODO: pass the JNI function name (such as "CallVoidMethodV") through so we can call JniAbort // with an argument. JniAbortF(nullptr, "bad arguments passed to %s (see above for details)", - PrettyMethod(m).c_str()); + PrettyMethod(h_m.Get()).c_str()); } } @@ -414,33 +421,36 @@ JValue InvokeWithVarArgs(const ScopedObjectAccessAlreadyRunnable& soa, jobject o SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { mirror::ArtMethod* method = soa.DecodeMethod(mid); mirror::Object* receiver = method->IsStatic() ? nullptr : soa.Decode<mirror::Object*>(obj); - MethodHelper mh(method); + uint32_t shorty_len = 0; + const char* shorty = method->GetShorty(&shorty_len); JValue result; - ArgArray arg_array(mh.GetShorty(), mh.GetShortyLength()); + ArgArray arg_array(shorty, shorty_len); arg_array.BuildArgArrayFromVarArgs(soa, receiver, args); - InvokeWithArgArray(soa, method, &arg_array, &result, mh.GetShorty()); + InvokeWithArgArray(soa, method, &arg_array, &result, shorty); return result; } JValue InvokeWithJValues(const ScopedObjectAccessAlreadyRunnable& soa, mirror::Object* receiver, jmethodID mid, jvalue* args) { mirror::ArtMethod* method = soa.DecodeMethod(mid); - MethodHelper mh(method); + uint32_t shorty_len = 0; + const char* shorty = method->GetShorty(&shorty_len); JValue result; - ArgArray arg_array(mh.GetShorty(), mh.GetShortyLength()); + ArgArray arg_array(shorty, shorty_len); arg_array.BuildArgArrayFromJValues(soa, receiver, args); - InvokeWithArgArray(soa, method, &arg_array, &result, mh.GetShorty()); + InvokeWithArgArray(soa, method, &arg_array, &result, shorty); return result; } JValue InvokeVirtualOrInterfaceWithJValues(const ScopedObjectAccessAlreadyRunnable& soa, mirror::Object* receiver, jmethodID mid, jvalue* args) { mirror::ArtMethod* method = FindVirtualMethod(receiver, soa.DecodeMethod(mid)); - MethodHelper mh(method); + uint32_t shorty_len = 0; + const char* shorty = method->GetShorty(&shorty_len); JValue result; - ArgArray arg_array(mh.GetShorty(), mh.GetShortyLength()); + ArgArray arg_array(shorty, shorty_len); arg_array.BuildArgArrayFromJValues(soa, receiver, args); - InvokeWithArgArray(soa, method, &arg_array, &result, mh.GetShorty()); + InvokeWithArgArray(soa, method, &arg_array, &result, shorty); return result; } @@ -448,11 +458,12 @@ JValue InvokeVirtualOrInterfaceWithVarArgs(const ScopedObjectAccessAlreadyRunnab jobject obj, jmethodID mid, va_list args) { mirror::Object* receiver = soa.Decode<mirror::Object*>(obj); mirror::ArtMethod* method = FindVirtualMethod(receiver, soa.DecodeMethod(mid)); - MethodHelper mh(method); + uint32_t shorty_len = 0; + const char* shorty = method->GetShorty(&shorty_len); JValue result; - ArgArray arg_array(mh.GetShorty(), mh.GetShortyLength()); + ArgArray arg_array(shorty, shorty_len); arg_array.BuildArgArrayFromVarArgs(soa, receiver, args); - InvokeWithArgArray(soa, method, &arg_array, &result, mh.GetShorty()); + InvokeWithArgArray(soa, method, &arg_array, &result, shorty); return result; } @@ -493,8 +504,7 @@ jobject InvokeMethod(const ScopedObjectAccessAlreadyRunnable& soa, jobject javaM // Get our arrays of arguments and their types, and check they're the same size. mirror::ObjectArray<mirror::Object>* objects = soa.Decode<mirror::ObjectArray<mirror::Object>*>(javaArgs); - MethodHelper mh(m); - const DexFile::TypeList* classes = mh.GetParameterTypeList(); + const DexFile::TypeList* classes = m->GetParameterTypeList(); uint32_t classes_size = (classes == nullptr) ? 0 : classes->Size(); uint32_t arg_count = (objects != nullptr) ? objects->GetLength() : 0; if (arg_count != classes_size) { @@ -513,13 +523,17 @@ jobject InvokeMethod(const ScopedObjectAccessAlreadyRunnable& soa, jobject javaM // Invoke the method. JValue result; - ArgArray arg_array(mh.GetShorty(), mh.GetShortyLength()); + uint32_t shorty_len = 0; + const char* shorty = m->GetShorty(&shorty_len); + ArgArray arg_array(shorty, shorty_len); + StackHandleScope<1> hs(soa.Self()); + MethodHelper mh(hs.NewHandle(m)); if (!arg_array.BuildArgArrayFromObjectArray(soa, receiver, objects, mh)) { CHECK(soa.Self()->IsExceptionPending()); return nullptr; } - InvokeWithArgArray(soa, m, &arg_array, &result, mh.GetShorty()); + InvokeWithArgArray(soa, m, &arg_array, &result, shorty); // Wrap any exception with "Ljava/lang/reflect/InvocationTargetException;" and return early. if (soa.Self()->IsExceptionPending()) { diff --git a/runtime/stack.cc b/runtime/stack.cc index ef09816981..7e922c59f0 100644 --- a/runtime/stack.cc +++ b/runtime/stack.cc @@ -40,7 +40,7 @@ mirror::Object* ShadowFrame::GetThisObject() const { } else if (m->IsNative()) { return GetVRegReference(0); } else { - const DexFile::CodeItem* code_item = MethodHelper(m).GetCodeItem(); + const DexFile::CodeItem* code_item = m->GetCodeItem(); CHECK(code_item != NULL) << PrettyMethod(m); uint16_t reg = code_item->registers_size_ - code_item->ins_size_; return GetVRegReference(reg); @@ -125,7 +125,7 @@ mirror::Object* StackVisitor::GetThisObject() const { return cur_shadow_frame_->GetVRegReference(0); } } else { - const DexFile::CodeItem* code_item = MethodHelper(m).GetCodeItem(); + const DexFile::CodeItem* code_item = m->GetCodeItem(); if (code_item == NULL) { UNIMPLEMENTED(ERROR) << "Failed to determine this object of abstract or proxy method: " << PrettyMethod(m); @@ -157,7 +157,7 @@ uint32_t StackVisitor::GetVReg(mirror::ArtMethod* m, uint16_t vreg, VRegKind kin uint32_t spill_mask = is_float ? frame_info.FpSpillMask() : frame_info.CoreSpillMask(); return GetGPR(vmap_table.ComputeRegister(spill_mask, vmap_offset, kind)); } else { - const DexFile::CodeItem* code_item = MethodHelper(m).GetCodeItem(); + const DexFile::CodeItem* code_item = m->GetCodeItem(); DCHECK(code_item != NULL) << PrettyMethod(m); // Can't be NULL or how would we compile its instructions? return *GetVRegAddr(cur_quick_frame_, code_item, frame_info.CoreSpillMask(), frame_info.FpSpillMask(), frame_info.FrameSizeInBytes(), vreg); @@ -184,7 +184,7 @@ void StackVisitor::SetVReg(mirror::ArtMethod* m, uint16_t vreg, uint32_t new_val const uint32_t reg = vmap_table.ComputeRegister(spill_mask, vmap_offset, kReferenceVReg); SetGPR(reg, new_value); } else { - const DexFile::CodeItem* code_item = MethodHelper(m).GetCodeItem(); + const DexFile::CodeItem* code_item = m->GetCodeItem(); DCHECK(code_item != NULL) << PrettyMethod(m); // Can't be NULL or how would we compile its instructions? int offset = GetVRegOffset(code_item, frame_info.CoreSpillMask(), frame_info.FpSpillMask(), frame_info.FrameSizeInBytes(), vreg, kRuntimeISA); diff --git a/runtime/thread.cc b/runtime/thread.cc index 3bfdc3f774..22f0e8097b 100644 --- a/runtime/thread.cc +++ b/runtime/thread.cc @@ -892,8 +892,7 @@ struct StackDumpVisitor : public StackVisitor { if (m->IsNative()) { os << "(Native method)"; } else { - mh.ChangeMethod(m); - const char* source_file(mh.GetDeclaringClassSourceFile()); + const char* source_file(m->GetDeclaringClassSourceFile()); os << "(" << (source_file != nullptr ? source_file : "unavailable") << ":" << line_number << ")"; } @@ -933,7 +932,7 @@ struct StackDumpVisitor : public StackVisitor { std::ostream& os; const Thread* thread; const bool can_allocate; - MethodHelper mh; + mirror::ArtMethod* method; mirror::ArtMethod* last_method; int last_line_number; int repetition_count; @@ -1530,7 +1529,6 @@ jobjectArray Thread::InternalStackTraceToStackTraceElementArray( soa.Decode<mirror::ObjectArray<mirror::Object>*>(internal); // Prepare parameters for StackTraceElement(String cls, String method, String file, int line) mirror::ArtMethod* method = down_cast<mirror::ArtMethod*>(method_trace->Get(i)); - MethodHelper mh(method); int32_t line_number; StackHandleScope<3> hs(soa.Self()); auto class_name_object(hs.NewHandle<mirror::String>(nullptr)); @@ -1542,17 +1540,17 @@ jobjectArray Thread::InternalStackTraceToStackTraceElementArray( } else { mirror::IntArray* pc_trace = down_cast<mirror::IntArray*>(method_trace->Get(depth)); uint32_t dex_pc = pc_trace->Get(i); - line_number = mh.GetLineNumFromDexPC(dex_pc); + line_number = method->GetLineNumFromDexPC(dex_pc); // Allocate element, potentially triggering GC // TODO: reuse class_name_object via Class::name_? - const char* descriptor = mh.GetDeclaringClassDescriptor(); + const char* descriptor = method->GetDeclaringClassDescriptor(); CHECK(descriptor != nullptr); std::string class_name(PrettyDescriptor(descriptor)); class_name_object.Assign(mirror::String::AllocFromModifiedUtf8(soa.Self(), class_name.c_str())); if (class_name_object.Get() == nullptr) { return nullptr; } - const char* source_file = mh.GetDeclaringClassSourceFile(); + const char* source_file = method->GetDeclaringClassSourceFile(); if (source_file != nullptr) { source_name_object.Assign(mirror::String::AllocFromModifiedUtf8(soa.Self(), source_file)); if (source_name_object.Get() == nullptr) { @@ -1560,7 +1558,7 @@ jobjectArray Thread::InternalStackTraceToStackTraceElementArray( } } } - const char* method_name = mh.GetName(); + const char* method_name = method->GetName(); CHECK(method_name != nullptr); Handle<mirror::String> method_name_object( hs.NewHandle(mirror::String::AllocFromModifiedUtf8(soa.Self(), method_name))); @@ -2044,8 +2042,7 @@ class ReferenceMapVisitor : public StackVisitor { if (!m->IsNative() && !m->IsRuntimeMethod() && !m->IsProxyMethod()) { const uint8_t* native_gc_map = m->GetNativeGcMap(); CHECK(native_gc_map != nullptr) << PrettyMethod(m); - mh_.ChangeMethod(m); - const DexFile::CodeItem* code_item = mh_.GetCodeItem(); + const DexFile::CodeItem* code_item = m->GetCodeItem(); DCHECK(code_item != nullptr) << PrettyMethod(m); // Can't be nullptr or how would we compile its instructions? NativePcOffsetToReferenceMap map(native_gc_map); size_t num_regs = std::min(map.RegWidth() * 8, @@ -2100,9 +2097,6 @@ class ReferenceMapVisitor : public StackVisitor { // Visitor for when we visit a root. const RootVisitor& visitor_; - - // A method helper we keep around to avoid dex file/cache re-computations. - MethodHelper mh_; }; class RootCallbackVisitor { diff --git a/runtime/throw_location.cc b/runtime/throw_location.cc index 06b6e8d277..a1347a49bb 100644 --- a/runtime/throw_location.cc +++ b/runtime/throw_location.cc @@ -27,7 +27,7 @@ namespace art { std::string ThrowLocation::Dump() const { if (method_ != nullptr) { return StringPrintf("%s:%d", PrettyMethod(method_).c_str(), - MethodHelper(method_).GetLineNumFromDexPC(dex_pc_)); + method_->GetLineNumFromDexPC(dex_pc_)); } else { return "unknown throw location"; } diff --git a/runtime/trace.cc b/runtime/trace.cc index d53b369ed8..032a566b9b 100644 --- a/runtime/trace.cc +++ b/runtime/trace.cc @@ -677,12 +677,10 @@ void Trace::GetVisitedMethods(size_t buf_size, } void Trace::DumpMethodList(std::ostream& os, const std::set<mirror::ArtMethod*>& visited_methods) { - MethodHelper mh; for (const auto& method : visited_methods) { - mh.ChangeMethod(method); os << StringPrintf("%p\t%s\t%s\t%s\t%s\n", method, - PrettyDescriptor(mh.GetDeclaringClassDescriptor()).c_str(), mh.GetName(), - mh.GetSignature().ToString().c_str(), mh.GetDeclaringClassSourceFile()); + PrettyDescriptor(method->GetDeclaringClassDescriptor()).c_str(), method->GetName(), + method->GetSignature().ToString().c_str(), method->GetDeclaringClassSourceFile()); } } diff --git a/runtime/utils.cc b/runtime/utils.cc index ef2047b8c5..7700658fea 100644 --- a/runtime/utils.cc +++ b/runtime/utils.cc @@ -365,15 +365,14 @@ std::string PrettyMethod(mirror::ArtMethod* m, bool with_signature) { if (m == nullptr) { return "null"; } - MethodHelper mh(m); - std::string result(PrettyDescriptor(mh.GetDeclaringClassDescriptor())); + std::string result(PrettyDescriptor(m->GetDeclaringClassDescriptor())); result += '.'; - result += mh.GetName(); + result += m->GetName(); if (UNLIKELY(m->IsFastNative())) { result += "!"; } if (with_signature) { - const Signature signature = mh.GetSignature(); + const Signature signature = m->GetSignature(); std::string sig_as_string(signature.ToString()); if (signature == Signature::NoSignature()) { return result + sig_as_string; @@ -642,15 +641,14 @@ std::string DescriptorToName(const char* descriptor) { } std::string JniShortName(mirror::ArtMethod* m) { - MethodHelper mh(m); - std::string class_name(mh.GetDeclaringClassDescriptor()); + std::string class_name(m->GetDeclaringClassDescriptor()); // Remove the leading 'L' and trailing ';'... CHECK_EQ(class_name[0], 'L') << class_name; CHECK_EQ(class_name[class_name.size() - 1], ';') << class_name; class_name.erase(0, 1); class_name.erase(class_name.size() - 1, 1); - std::string method_name(mh.GetName()); + std::string method_name(m->GetName()); std::string short_name; short_name += "Java_"; @@ -665,7 +663,7 @@ std::string JniLongName(mirror::ArtMethod* m) { long_name += JniShortName(m); long_name += "__"; - std::string signature(MethodHelper(m).GetSignature().ToString()); + std::string signature(m->GetSignature().ToString()); signature.erase(0, 1); signature.erase(signature.begin() + signature.find(')'), signature.end()); diff --git a/runtime/verifier/method_verifier.cc b/runtime/verifier/method_verifier.cc index c7bb20c950..e5dcbb0ac4 100644 --- a/runtime/verifier/method_verifier.cc +++ b/runtime/verifier/method_verifier.cc @@ -338,12 +338,11 @@ MethodVerifier::~MethodVerifier() { void MethodVerifier::FindLocksAtDexPc(mirror::ArtMethod* m, uint32_t dex_pc, std::vector<uint32_t>* monitor_enter_dex_pcs) { - MethodHelper mh(m); StackHandleScope<2> hs(Thread::Current()); - Handle<mirror::DexCache> dex_cache(hs.NewHandle(mh.GetDexCache())); - Handle<mirror::ClassLoader> class_loader(hs.NewHandle(mh.GetClassLoader())); - MethodVerifier verifier(&mh.GetDexFile(), &dex_cache, &class_loader, &mh.GetClassDef(), - mh.GetCodeItem(), m->GetDexMethodIndex(), m, m->GetAccessFlags(), false, + Handle<mirror::DexCache> dex_cache(hs.NewHandle(m->GetDexCache())); + Handle<mirror::ClassLoader> class_loader(hs.NewHandle(m->GetClassLoader())); + MethodVerifier verifier(m->GetDexFile(), &dex_cache, &class_loader, &m->GetClassDef(), + m->GetCodeItem(), m->GetDexMethodIndex(), m, m->GetAccessFlags(), false, true, false); verifier.interesting_dex_pc_ = dex_pc; verifier.monitor_enter_dex_pcs_ = monitor_enter_dex_pcs; @@ -363,12 +362,11 @@ void MethodVerifier::FindLocksAtDexPc() { mirror::ArtField* MethodVerifier::FindAccessedFieldAtDexPc(mirror::ArtMethod* m, uint32_t dex_pc) { - MethodHelper mh(m); StackHandleScope<2> hs(Thread::Current()); - Handle<mirror::DexCache> dex_cache(hs.NewHandle(mh.GetDexCache())); - Handle<mirror::ClassLoader> class_loader(hs.NewHandle(mh.GetClassLoader())); - MethodVerifier verifier(&mh.GetDexFile(), &dex_cache, &class_loader, &mh.GetClassDef(), - mh.GetCodeItem(), m->GetDexMethodIndex(), m, m->GetAccessFlags(), true, + Handle<mirror::DexCache> dex_cache(hs.NewHandle(m->GetDexCache())); + Handle<mirror::ClassLoader> class_loader(hs.NewHandle(m->GetClassLoader())); + MethodVerifier verifier(m->GetDexFile(), &dex_cache, &class_loader, &m->GetClassDef(), + m->GetCodeItem(), m->GetDexMethodIndex(), m, m->GetAccessFlags(), true, true, false); return verifier.FindAccessedFieldAtDexPc(dex_pc); } @@ -394,12 +392,11 @@ mirror::ArtField* MethodVerifier::FindAccessedFieldAtDexPc(uint32_t dex_pc) { mirror::ArtMethod* MethodVerifier::FindInvokedMethodAtDexPc(mirror::ArtMethod* m, uint32_t dex_pc) { - MethodHelper mh(m); StackHandleScope<2> hs(Thread::Current()); - Handle<mirror::DexCache> dex_cache(hs.NewHandle(mh.GetDexCache())); - Handle<mirror::ClassLoader> class_loader(hs.NewHandle(mh.GetClassLoader())); - MethodVerifier verifier(&mh.GetDexFile(), &dex_cache, &class_loader, &mh.GetClassDef(), - mh.GetCodeItem(), m->GetDexMethodIndex(), m, m->GetAccessFlags(), true, + Handle<mirror::DexCache> dex_cache(hs.NewHandle(m->GetDexCache())); + Handle<mirror::ClassLoader> class_loader(hs.NewHandle(m->GetClassLoader())); + MethodVerifier verifier(m->GetDexFile(), &dex_cache, &class_loader, &m->GetClassDef(), + m->GetCodeItem(), m->GetDexMethodIndex(), m, m->GetAccessFlags(), true, true, false); return verifier.FindInvokedMethodAtDexPc(dex_pc); } @@ -2136,19 +2133,22 @@ bool MethodVerifier::CodeFlowVerifyInstruction(uint32_t* start_guess) { case Instruction::INVOKE_SUPER_RANGE: { bool is_range = (inst->Opcode() == Instruction::INVOKE_VIRTUAL_RANGE || inst->Opcode() == Instruction::INVOKE_SUPER_RANGE); - bool is_super = (inst->Opcode() == Instruction::INVOKE_SUPER || - inst->Opcode() == Instruction::INVOKE_SUPER_RANGE); + bool is_super = (inst->Opcode() == Instruction::INVOKE_SUPER || + inst->Opcode() == Instruction::INVOKE_SUPER_RANGE); mirror::ArtMethod* called_method = VerifyInvocationArgs(inst, METHOD_VIRTUAL, is_range, is_super); const RegType* return_type = nullptr; if (called_method != nullptr) { - MethodHelper mh(called_method); + Thread* self = Thread::Current(); + StackHandleScope<1> hs(self); + Handle<mirror::ArtMethod> h_called_method(hs.NewHandle(called_method)); + MethodHelper mh(h_called_method); mirror::Class* return_type_class = mh.GetReturnType(can_load_classes_); if (return_type_class != nullptr) { - return_type = ®_types_.FromClass(mh.GetReturnTypeDescriptor(), return_type_class, + return_type = ®_types_.FromClass(h_called_method->GetReturnTypeDescriptor(), + return_type_class, return_type_class->CannotBeAssignedFromOtherTypes()); } else { - Thread* self = Thread::Current(); DCHECK(!can_load_classes_ || self->IsExceptionPending()); self->ClearException(); } @@ -2183,7 +2183,7 @@ bool MethodVerifier::CodeFlowVerifyInstruction(uint32_t* start_guess) { return_type_descriptor = dex_file_->StringByTypeIdx(return_type_idx); } else { is_constructor = called_method->IsConstructor(); - return_type_descriptor = MethodHelper(called_method).GetReturnTypeDescriptor(); + return_type_descriptor = called_method->GetReturnTypeDescriptor(); } if (is_constructor) { /* @@ -2249,10 +2249,10 @@ bool MethodVerifier::CodeFlowVerifyInstruction(uint32_t* start_guess) { uint32_t return_type_idx = dex_file_->GetProtoId(method_id.proto_idx_).return_type_idx_; descriptor = dex_file_->StringByTypeIdx(return_type_idx); } else { - descriptor = MethodHelper(called_method).GetReturnTypeDescriptor(); + descriptor = called_method->GetReturnTypeDescriptor(); } - const RegType& return_type = reg_types_.FromDescriptor(class_loader_->Get(), descriptor, - false); + const RegType& return_type = reg_types_.FromDescriptor(class_loader_->Get(), descriptor, + false); if (!return_type.IsLowHalf()) { work_line_->SetResultRegisterType(return_type); } else { @@ -2307,7 +2307,7 @@ bool MethodVerifier::CodeFlowVerifyInstruction(uint32_t* start_guess) { uint32_t return_type_idx = dex_file_->GetProtoId(method_id.proto_idx_).return_type_idx_; descriptor = dex_file_->StringByTypeIdx(return_type_idx); } else { - descriptor = MethodHelper(abs_method).GetReturnTypeDescriptor(); + descriptor = abs_method->GetReturnTypeDescriptor(); } const RegType& return_type = reg_types_.FromDescriptor(class_loader_->Get(), descriptor, false); @@ -2574,7 +2574,7 @@ bool MethodVerifier::CodeFlowVerifyInstruction(uint32_t* start_guess) { bool is_range = (inst->Opcode() == Instruction::INVOKE_VIRTUAL_RANGE_QUICK); mirror::ArtMethod* called_method = VerifyInvokeVirtualQuickArgs(inst, is_range); if (called_method != NULL) { - const char* descriptor = MethodHelper(called_method).GetReturnTypeDescriptor(); + const char* descriptor = called_method->GetReturnTypeDescriptor(); const RegType& return_type = reg_types_.FromDescriptor(class_loader_->Get(), descriptor, false); if (!return_type.IsLowHalf()) { @@ -2962,7 +2962,7 @@ mirror::ArtMethod* MethodVerifier::ResolveMethodAndCheckAccess(uint32_t dex_meth return NULL; } // Disallow any calls to class initializers. - if (MethodHelper(res_method).IsClassInitializer()) { + if (res_method->IsClassInitializer()) { Fail(VERIFY_ERROR_BAD_CLASS_HARD) << "rejecting call to class initializer " << PrettyMethod(res_method); return NULL; @@ -3027,12 +3027,11 @@ mirror::ArtMethod* MethodVerifier::VerifyInvocationArgs(const Instruction* inst, } mirror::Class* super_klass = super.GetClass(); if (res_method->GetMethodIndex() >= super_klass->GetVTable()->GetLength()) { - MethodHelper mh(res_method); Fail(VERIFY_ERROR_NO_METHOD) << "invalid invoke-super from " << PrettyMethod(dex_method_idx_, *dex_file_) << " to super " << super - << "." << mh.GetName() - << mh.GetSignature(); + << "." << res_method->GetName() + << res_method->GetSignature(); return NULL; } } @@ -3081,8 +3080,7 @@ mirror::ArtMethod* MethodVerifier::VerifyInvocationArgs(const Instruction* inst, * Process the target method's signature. This signature may or may not * have been verified, so we can't assume it's properly formed. */ - MethodHelper mh(res_method); - const DexFile::TypeList* params = mh.GetParameterTypeList(); + const DexFile::TypeList* params = res_method->GetParameterTypeList(); size_t params_size = params == NULL ? 0 : params->Size(); uint32_t arg[5]; if (!is_range) { @@ -3096,7 +3094,7 @@ mirror::ArtMethod* MethodVerifier::VerifyInvocationArgs(const Instruction* inst, return NULL; } const char* descriptor = - mh.GetTypeDescriptorFromTypeIdx(params->GetTypeItem(param_index).type_idx_); + res_method->GetTypeDescriptorFromTypeIdx(params->GetTypeItem(param_index).type_idx_); if (descriptor == NULL) { Fail(VERIFY_ERROR_BAD_CLASS_HARD) << "Rejecting invocation of " << PrettyMethod(res_method) << " missing signature component"; @@ -3204,8 +3202,7 @@ mirror::ArtMethod* MethodVerifier::VerifyInvokeVirtualQuickArgs(const Instructio * Process the target method's signature. This signature may or may not * have been verified, so we can't assume it's properly formed. */ - MethodHelper mh(res_method); - const DexFile::TypeList* params = mh.GetParameterTypeList(); + const DexFile::TypeList* params = res_method->GetParameterTypeList(); size_t params_size = params == NULL ? 0 : params->Size(); uint32_t arg[5]; if (!is_range) { @@ -3221,7 +3218,7 @@ mirror::ArtMethod* MethodVerifier::VerifyInvokeVirtualQuickArgs(const Instructio return NULL; } const char* descriptor = - mh.GetTypeDescriptorFromTypeIdx(params->GetTypeItem(param_index).type_idx_); + res_method->GetTypeDescriptorFromTypeIdx(params->GetTypeItem(param_index).type_idx_); if (descriptor == NULL) { Fail(VERIFY_ERROR_BAD_CLASS_HARD) << "Rejecting invocation of " << PrettyMethod(res_method) << " missing signature component"; @@ -3849,13 +3846,18 @@ InstructionFlags* MethodVerifier::CurrentInsnFlags() { const RegType& MethodVerifier::GetMethodReturnType() { if (return_type_ == nullptr) { if (mirror_method_ != NULL) { - MethodHelper mh(mirror_method_); - mirror::Class* return_type_class = mh.GetReturnType(can_load_classes_); + Thread* self = Thread::Current(); + StackHandleScope<1> hs(self); + mirror::Class* return_type_class; + { + HandleWrapper<mirror::ArtMethod> h_mirror_method(hs.NewHandleWrapper(&mirror_method_)); + return_type_class = MethodHelper(h_mirror_method).GetReturnType(can_load_classes_); + } if (return_type_class != nullptr) { - return_type_ = ®_types_.FromClass(mh.GetReturnTypeDescriptor(), return_type_class, + return_type_ = ®_types_.FromClass(mirror_method_->GetReturnTypeDescriptor(), + return_type_class, return_type_class->CannotBeAssignedFromOtherTypes()); } else { - Thread* self = Thread::Current(); DCHECK(!can_load_classes_ || self->IsExceptionPending()); self->ClearException(); } diff --git a/test/ReferenceMap/stack_walk_refmap_jni.cc b/test/ReferenceMap/stack_walk_refmap_jni.cc index 48a6c61fb0..87187ed19d 100644 --- a/test/ReferenceMap/stack_walk_refmap_jni.cc +++ b/test/ReferenceMap/stack_walk_refmap_jni.cc @@ -33,8 +33,8 @@ namespace art { -#define IS_IN_REF_BITMAP(mh, ref_bitmap, reg) \ - (((reg) < mh.GetCodeItem()->registers_size_) && \ +#define IS_IN_REF_BITMAP(ref_bitmap, reg) \ + (((reg) < m->GetCodeItem()->registers_size_) && \ ((*((ref_bitmap) + (reg)/8) >> ((reg) % 8) ) & 0x01)) #define CHECK_REGS_CONTAIN_REFS(...) \ @@ -42,7 +42,7 @@ namespace art { int t[] = {__VA_ARGS__}; \ int t_size = sizeof(t) / sizeof(*t); \ for (int i = 0; i < t_size; ++i) \ - CHECK(IS_IN_REF_BITMAP(mh, ref_bitmap, t[i])) \ + CHECK(IS_IN_REF_BITMAP(ref_bitmap, t[i])) \ << "Error: Reg @ " << i << "-th argument is not in GC map"; \ } while (false) @@ -67,8 +67,7 @@ struct ReferenceMap2Visitor : public StackVisitor { } const uint8_t* ref_bitmap = NULL; - MethodHelper mh(m); - std::string m_name(mh.GetName()); + std::string m_name(m->GetName()); // Given the method name and the number of times the method has been called, // we know the Dex registers with live reference values. Assert that what we diff --git a/test/StackWalk/stack_walk_jni.cc b/test/StackWalk/stack_walk_jni.cc index 3cf2d0ba34..c849c54bbe 100644 --- a/test/StackWalk/stack_walk_jni.cc +++ b/test/StackWalk/stack_walk_jni.cc @@ -30,15 +30,15 @@ namespace art { -#define REG(mh, reg_bitmap, reg) \ - (((reg) < mh.GetCodeItem()->registers_size_) && \ +#define REG(reg_bitmap, reg) \ + (((reg) < m->GetCodeItem()->registers_size_) && \ ((*((reg_bitmap) + (reg)/8) >> ((reg) % 8) ) & 0x01)) #define CHECK_REGS(...) if (!IsShadowFrame()) { \ int t[] = {__VA_ARGS__}; \ int t_size = sizeof(t) / sizeof(*t); \ for (int i = 0; i < t_size; ++i) \ - CHECK(REG(mh, reg_bitmap, t[i])) << "Error: Reg " << i << " is not in RegisterMap"; \ + CHECK(REG(reg_bitmap, t[i])) << "Error: Reg " << i << " is not in RegisterMap"; \ } static int gJava_StackWalk_refmap_calls = 0; @@ -64,8 +64,7 @@ struct TestReferenceMapVisitor : public StackVisitor { NativePcOffsetToReferenceMap map(m->GetNativeGcMap()); reg_bitmap = map.FindBitMap(GetNativePcOffset()); } - MethodHelper mh(m); - StringPiece m_name(mh.GetName()); + StringPiece m_name(m->GetName()); // Given the method name and the number of times the method has been called, // we know the Dex registers with live reference values. Assert that what we |