diff options
Diffstat (limited to 'runtime')
52 files changed, 651 insertions, 899 deletions
diff --git a/runtime/Android.mk b/runtime/Android.mk index 087c0ea990..7dfdb75529 100644 --- a/runtime/Android.mk +++ b/runtime/Android.mk @@ -42,7 +42,6 @@ LIBART_COMMON_SRC_FILES := \ dex_file_verifier.cc \ dex_instruction.cc \ elf_file.cc \ - field_helper.cc \ gc/allocator/dlmalloc.cc \ gc/allocator/rosalloc.cc \ gc/accounting/card_table.cc \ @@ -91,7 +90,6 @@ LIBART_COMMON_SRC_FILES := \ jobject_comparator.cc \ mem_map.cc \ memory_region.cc \ - method_helper.cc \ mirror/art_field.cc \ mirror/art_method.cc \ mirror/array.cc \ diff --git a/runtime/check_jni.cc b/runtime/check_jni.cc index fe5b765a3a..e45d3a3831 100644 --- a/runtime/check_jni.cc +++ b/runtime/check_jni.cc @@ -24,7 +24,6 @@ #include "class_linker.h" #include "class_linker-inl.h" #include "dex_file-inl.h" -#include "field_helper.h" #include "gc/space/space.h" #include "java_vm_ext.h" #include "jni_internal.h" diff --git a/runtime/class_linker.cc b/runtime/class_linker.cc index 7a8e4a3d92..ee13e0389a 100644 --- a/runtime/class_linker.cc +++ b/runtime/class_linker.cc @@ -43,7 +43,6 @@ #include "intern_table.h" #include "interpreter/interpreter.h" #include "leb128.h" -#include "method_helper-inl.h" #include "oat.h" #include "oat_file.h" #include "object_lock.h" @@ -1671,6 +1670,7 @@ void ClassLinker::InitFromImage() { LOG(FATAL) << "Failed to open dex file " << dex_file_location << " from within oat file " << oat_file.GetLocation() << " error '" << error_msg << "'"; + UNREACHABLE(); } CHECK_EQ(dex_file->GetLocationChecksum(), oat_dex_file->GetDexFileLocationChecksum()); @@ -2393,6 +2393,7 @@ uint32_t ClassLinker::SizeOfClassWithoutEmbeddedTables(const DexFile& dex_file, break; default: LOG(FATAL) << "Unknown descriptor: " << c; + UNREACHABLE(); } } } @@ -2442,7 +2443,7 @@ static uint32_t GetOatMethodIndexFromMethodIndex(const DexFile& dex_file, uint16 } DCHECK(!it.HasNext()); LOG(FATAL) << "Failed to find method index " << method_idx << " in " << dex_file.GetLocation(); - return 0; + UNREACHABLE(); } const OatFile::OatMethod ClassLinker::FindOatMethodFor(mirror::ArtMethod* method, bool* found) { @@ -2780,7 +2781,7 @@ void ClassLinker::LoadClass(Thread* self, const DexFile& dex_file, klass->SetDexClassDefIndex(dex_file.GetIndexForClassDef(dex_class_def)); klass->SetDexTypeIndex(dex_class_def.class_idx_); - klass->SetDexCacheStrings(klass->GetDexCache()->GetStrings()); + CHECK(klass->GetDexCacheStrings() != nullptr); const uint8_t* class_data = dex_file.GetClassData(dex_class_def); if (class_data == nullptr) { @@ -3078,7 +3079,7 @@ mirror::DexCache* ClassLinker::FindDexCache(const DexFile& dex_file) { LOG(ERROR) << "Registered dex file " << i << " = " << dex_cache->GetDexFile()->GetLocation(); } LOG(FATAL) << "Failed to find DexCache for DexFile " << location; - return nullptr; + UNREACHABLE(); } void ClassLinker::FixupDexCaches(mirror::ArtMethod* resolution_method) { @@ -3749,8 +3750,7 @@ bool ClassLinker::VerifyClassUsingOatFile(const DexFile& dex_file, mirror::Class LOG(FATAL) << "Unexpected class status: " << oat_file_class_status << " " << dex_file.GetLocation() << " " << PrettyClass(klass) << " " << klass->GetDescriptor(&temp); - - return false; + UNREACHABLE(); } void ClassLinker::ResolveClassExceptionHandlerTypes(const DexFile& dex_file, @@ -4345,6 +4345,41 @@ bool ClassLinker::WaitForInitializeClass(Handle<mirror::Class> klass, Thread* se UNREACHABLE(); } +static bool HasSameSignatureWithDifferentClassLoaders(Thread* self, + Handle<mirror::ArtMethod> method1, + Handle<mirror::ArtMethod> method2) + SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { + { + StackHandleScope<1> hs(self); + Handle<mirror::Class> return_type(hs.NewHandle(method1->GetReturnType())); + if (UNLIKELY(method2->GetReturnType() != return_type.Get())) { + return false; + } + } + const DexFile::TypeList* types1 = method1->GetParameterTypeList(); + const DexFile::TypeList* types2 = method2->GetParameterTypeList(); + if (types1 == nullptr) { + return (types2 == nullptr) || (types2->Size() == 0); + } else if (UNLIKELY(types2 == nullptr)) { + return types1->Size() == 0; + } + uint32_t num_types = types1->Size(); + if (UNLIKELY(num_types != types2->Size())) { + return false; + } + for (uint32_t i = 0; i < num_types; ++i) { + mirror::Class* param_type = + method1->GetClassFromTypeIndex(types1->GetTypeItem(i).type_idx_, true); + mirror::Class* other_param_type = + method2->GetClassFromTypeIndex(types2->GetTypeItem(i).type_idx_, true); + if (UNLIKELY(param_type != other_param_type)) { + return false; + } + } + return true; +} + + bool ClassLinker::ValidateSuperClassDescriptors(Handle<mirror::Class> klass) { if (klass->IsInterface()) { return true; @@ -4352,19 +4387,19 @@ bool ClassLinker::ValidateSuperClassDescriptors(Handle<mirror::Class> klass) { // Begin with the methods local to the superclass. Thread* self = Thread::Current(); StackHandleScope<2> hs(self); - MutableMethodHelper mh(hs.NewHandle<mirror::ArtMethod>(nullptr)); - MutableMethodHelper super_mh(hs.NewHandle<mirror::ArtMethod>(nullptr)); + MutableHandle<mirror::ArtMethod> h_m(hs.NewHandle<mirror::ArtMethod>(nullptr)); + MutableHandle<mirror::ArtMethod> super_h_m(hs.NewHandle<mirror::ArtMethod>(nullptr)); if (klass->HasSuperClass() && klass->GetClassLoader() != klass->GetSuperClass()->GetClassLoader()) { for (int i = klass->GetSuperClass()->GetVTableLength() - 1; i >= 0; --i) { - mh.ChangeMethod(klass->GetVTableEntry(i)); - super_mh.ChangeMethod(klass->GetSuperClass()->GetVTableEntry(i)); - if (mh.GetMethod() != super_mh.GetMethod() && - !mh.HasSameSignatureWithDifferentClassLoaders(self, &super_mh)) { + h_m.Assign(klass->GetVTableEntry(i)); + super_h_m.Assign(klass->GetSuperClass()->GetVTableEntry(i)); + if (h_m.Get() != super_h_m.Get() && + !HasSameSignatureWithDifferentClassLoaders(self, h_m, super_h_m)) { ThrowLinkageError(klass.Get(), "Class %s method %s resolves differently in superclass %s", PrettyDescriptor(klass.Get()).c_str(), - PrettyMethod(mh.GetMethod()).c_str(), + PrettyMethod(h_m.Get()).c_str(), PrettyDescriptor(klass->GetSuperClass()).c_str()); return false; } @@ -4374,14 +4409,14 @@ bool ClassLinker::ValidateSuperClassDescriptors(Handle<mirror::Class> klass) { if (klass->GetClassLoader() != klass->GetIfTable()->GetInterface(i)->GetClassLoader()) { uint32_t num_methods = klass->GetIfTable()->GetInterface(i)->NumVirtualMethods(); 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)); - if (mh.GetMethod() != super_mh.GetMethod() && - !mh.HasSameSignatureWithDifferentClassLoaders(self, &super_mh)) { + h_m.Assign(klass->GetIfTable()->GetMethodArray(i)->GetWithoutChecks(j)); + super_h_m.Assign(klass->GetIfTable()->GetInterface(i)->GetVirtualMethod(j)); + if (h_m.Get() != super_h_m.Get() && + !HasSameSignatureWithDifferentClassLoaders(self, h_m, super_h_m)) { ThrowLinkageError(klass.Get(), "Class %s method %s resolves differently in interface %s", PrettyDescriptor(klass.Get()).c_str(), - PrettyMethod(mh.GetMethod()).c_str(), + PrettyMethod(h_m.Get()).c_str(), PrettyDescriptor(klass->GetIfTable()->GetInterface(i)).c_str()); return false; } @@ -5566,71 +5601,73 @@ mirror::ArtMethod* ClassLinker::ResolveMethod(const DexFile& dex_file, uint32_t } // If we found something, check that it can be accessed by the referrer. + bool exception_generated = false; if (resolved != nullptr && referrer.Get() != nullptr) { mirror::Class* methods_class = resolved->GetDeclaringClass(); mirror::Class* referring_class = referrer->GetDeclaringClass(); if (!referring_class->CanAccess(methods_class)) { ThrowIllegalAccessErrorClassForMethodDispatch(referring_class, methods_class, resolved, type); - return nullptr; + exception_generated = true; } else if (!referring_class->CanAccessMember(methods_class, resolved->GetAccessFlags())) { ThrowIllegalAccessErrorMethod(referring_class, resolved); - return nullptr; + exception_generated = true; } } - - // Otherwise, throw an IncompatibleClassChangeError if we found something, and check interface - // methods and throw if we find the method there. If we find nothing, throw a - // NoSuchMethodError. - switch (type) { - case kDirect: - case kStatic: - if (resolved != nullptr) { - ThrowIncompatibleClassChangeError(type, kVirtual, resolved, referrer.Get()); - } else { - resolved = klass->FindInterfaceMethod(name, signature); + if (!exception_generated) { + // Otherwise, throw an IncompatibleClassChangeError if we found something, and check + // interface methods and throw if we find the method there. If we find nothing, throw a + // NoSuchMethodError. + switch (type) { + case kDirect: + case kStatic: if (resolved != nullptr) { - ThrowIncompatibleClassChangeError(type, kInterface, resolved, referrer.Get()); + ThrowIncompatibleClassChangeError(type, kVirtual, resolved, referrer.Get()); } else { - ThrowNoSuchMethodError(type, klass, name, signature); + resolved = klass->FindInterfaceMethod(name, signature); + if (resolved != nullptr) { + ThrowIncompatibleClassChangeError(type, kInterface, resolved, referrer.Get()); + } else { + ThrowNoSuchMethodError(type, klass, name, signature); + } } - } - break; - case kInterface: - if (resolved != nullptr) { - ThrowIncompatibleClassChangeError(type, kDirect, resolved, referrer.Get()); - } else { - resolved = klass->FindVirtualMethod(name, signature); + break; + case kInterface: if (resolved != nullptr) { - ThrowIncompatibleClassChangeError(type, kVirtual, resolved, referrer.Get()); + ThrowIncompatibleClassChangeError(type, kDirect, resolved, referrer.Get()); } else { - ThrowNoSuchMethodError(type, klass, name, signature); + resolved = klass->FindVirtualMethod(name, signature); + if (resolved != nullptr) { + ThrowIncompatibleClassChangeError(type, kVirtual, resolved, referrer.Get()); + } else { + ThrowNoSuchMethodError(type, klass, name, signature); + } } - } - break; - case kSuper: - if (resolved != nullptr) { - ThrowIncompatibleClassChangeError(type, kDirect, resolved, referrer.Get()); - } else { - ThrowNoSuchMethodError(type, klass, name, signature); - } - break; - case kVirtual: - if (resolved != nullptr) { - ThrowIncompatibleClassChangeError(type, kDirect, resolved, referrer.Get()); - } else { - resolved = klass->FindInterfaceMethod(name, signature); + break; + case kSuper: if (resolved != nullptr) { - ThrowIncompatibleClassChangeError(type, kInterface, resolved, referrer.Get()); + ThrowIncompatibleClassChangeError(type, kDirect, resolved, referrer.Get()); } else { ThrowNoSuchMethodError(type, klass, name, signature); } - } - break; + break; + case kVirtual: + if (resolved != nullptr) { + ThrowIncompatibleClassChangeError(type, kDirect, resolved, referrer.Get()); + } else { + resolved = klass->FindInterfaceMethod(name, signature); + if (resolved != nullptr) { + ThrowIncompatibleClassChangeError(type, kInterface, resolved, referrer.Get()); + } else { + ThrowNoSuchMethodError(type, klass, name, signature); + } + } + break; + } } } - DCHECK(Thread::Current()->IsExceptionPending()); + Thread::Current()->AssertPendingException(); return nullptr; } } diff --git a/runtime/class_linker_test.cc b/runtime/class_linker_test.cc index c22c51e525..4f09460197 100644 --- a/runtime/class_linker_test.cc +++ b/runtime/class_linker_test.cc @@ -23,7 +23,6 @@ #include "common_runtime_test.h" #include "dex_file.h" #include "entrypoints/entrypoint_utils-inl.h" -#include "field_helper.h" #include "gc/heap.h" #include "mirror/art_field-inl.h" #include "mirror/art_method.h" @@ -178,9 +177,7 @@ class ClassLinkerTest : public CommonRuntimeTest { EXPECT_TRUE(field->GetClass() != nullptr); EXPECT_EQ(klass, field->GetDeclaringClass()); EXPECT_TRUE(field->GetName() != nullptr); - StackHandleScope<1> hs(Thread::Current()); - FieldHelper fh(hs.NewHandle(field)); - EXPECT_TRUE(fh.GetType() != nullptr); + EXPECT_TRUE(field->GetType(true) != nullptr); } void AssertClass(const std::string& descriptor, Handle<mirror::Class> klass) @@ -286,8 +283,7 @@ class ClassLinkerTest : public CommonRuntimeTest { for (size_t i = 0; i < klass->NumInstanceFields(); i++) { mirror::ArtField* field = klass->GetInstanceField(i); fhandle.Assign(field); - FieldHelper fh(fhandle); - mirror::Class* field_type = fh.GetType(); + mirror::Class* field_type = fhandle->GetType(true); ASSERT_TRUE(field_type != nullptr); if (!field->IsPrimitiveType()) { ASSERT_TRUE(!field_type->IsPrimitive()); @@ -295,7 +291,7 @@ class ClassLinkerTest : public CommonRuntimeTest { if (current_ref_offset.Uint32Value() == end_ref_offset.Uint32Value()) { // While Reference.referent is not primitive, the ClassLinker // treats it as such so that the garbage collector won't scan it. - EXPECT_EQ(PrettyField(fh.GetField()), + EXPECT_EQ(PrettyField(fhandle.Get()), "java.lang.Object java.lang.ref.Reference.referent"); } else { current_ref_offset = MemberOffset(current_ref_offset.Uint32Value() + diff --git a/runtime/debugger.cc b/runtime/debugger.cc index 86d027b8ab..a9b70cbaa1 100644 --- a/runtime/debugger.cc +++ b/runtime/debugger.cc @@ -25,13 +25,11 @@ #include "class_linker-inl.h" #include "dex_file-inl.h" #include "dex_instruction.h" -#include "field_helper.h" #include "gc/accounting/card_table-inl.h" #include "gc/space/large_object_space.h" #include "gc/space/space-inl.h" #include "handle_scope.h" #include "jdwp/object_registry.h" -#include "method_helper-inl.h" #include "mirror/art_field-inl.h" #include "mirror/art_method-inl.h" #include "mirror/class.h" @@ -1924,7 +1922,7 @@ static JDWP::JdwpError SetFieldValueImpl(JDWP::ObjectId object_id, JDWP::FieldId HandleWrapper<mirror::Object> h_v(hs.NewHandleWrapper(&v)); HandleWrapper<mirror::ArtField> h_f(hs.NewHandleWrapper(&f)); HandleWrapper<mirror::Object> h_o(hs.NewHandleWrapper(&o)); - field_type = FieldHelper(h_f).GetType(); + field_type = h_f->GetType(true); } if (!field_type->IsAssignableFrom(v->GetClass())) { return JDWP::ERR_INVALID_OBJECT; @@ -3687,7 +3685,7 @@ JDWP::JdwpError Dbg::InvokeMethod(JDWP::ObjectId thread_id, JDWP::ObjectId objec { StackHandleScope<3> hs(soa.Self()); - MethodHelper mh(hs.NewHandle(m)); + HandleWrapper<mirror::ArtMethod> h_m(hs.NewHandleWrapper(&m)); HandleWrapper<mirror::Object> h_obj(hs.NewHandleWrapper(&receiver)); HandleWrapper<mirror::Class> h_klass(hs.NewHandleWrapper(&c)); const DexFile::TypeList* types = m->GetParameterTypeList(); @@ -3698,7 +3696,8 @@ JDWP::JdwpError Dbg::InvokeMethod(JDWP::ObjectId thread_id, JDWP::ObjectId objec 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::Class* parameter_type = + h_m->GetClassFromTypeIndex(types->GetTypeItem(i).type_idx_, true); mirror::Object* argument = gRegistry->Get<mirror::Object*>(arg_values[i], &error); if (error != JDWP::ERR_NONE) { return JDWP::ERR_INVALID_OBJECT; @@ -3712,8 +3711,6 @@ JDWP::JdwpError Dbg::InvokeMethod(JDWP::ObjectId thread_id, JDWP::ObjectId objec v.l = gRegistry->GetJObject(arg_values[i]); } } - // Update in case it moved. - m = mh.GetMethod(); } req->receiver = receiver; diff --git a/runtime/entrypoints/entrypoint_utils.cc b/runtime/entrypoints/entrypoint_utils.cc index da2dfe11d0..c329fe6920 100644 --- a/runtime/entrypoints/entrypoint_utils.cc +++ b/runtime/entrypoints/entrypoint_utils.cc @@ -20,7 +20,6 @@ #include "class_linker-inl.h" #include "dex_file-inl.h" #include "gc/accounting/card_table-inl.h" -#include "method_helper-inl.h" #include "mirror/art_field-inl.h" #include "mirror/art_method-inl.h" #include "mirror/class-inl.h" diff --git a/runtime/entrypoints/interpreter/interpreter_entrypoints.cc b/runtime/entrypoints/interpreter/interpreter_entrypoints.cc index 908d3cd43c..3b47f245f7 100644 --- a/runtime/entrypoints/interpreter/interpreter_entrypoints.cc +++ b/runtime/entrypoints/interpreter/interpreter_entrypoints.cc @@ -24,9 +24,7 @@ namespace art { -// TODO: Make the MethodHelper here be compaction safe. -extern "C" void artInterpreterToCompiledCodeBridge(Thread* self, MethodHelper* mh, - const DexFile::CodeItem* code_item, +extern "C" void artInterpreterToCompiledCodeBridge(Thread* self, const DexFile::CodeItem* code_item, ShadowFrame* shadow_frame, JValue* result) { mirror::ArtMethod* method = shadow_frame->GetMethod(); // Ensure static methods are initialized. @@ -50,11 +48,11 @@ extern "C" void artInterpreterToCompiledCodeBridge(Thread* self, MethodHelper* m } uint16_t arg_offset = (code_item == NULL) ? 0 : code_item->registers_size_ - code_item->ins_size_; if (kUsePortableCompiler) { - InvokeWithShadowFrame(self, shadow_frame, arg_offset, mh, result); + InvokeWithShadowFrame(self, shadow_frame, arg_offset, result); } else { method->Invoke(self, shadow_frame->GetVRegArgs(arg_offset), (shadow_frame->NumberOfVRegs() - arg_offset) * sizeof(uint32_t), - result, mh->GetShorty()); + result, method->GetShorty()); } } diff --git a/runtime/entrypoints/interpreter/interpreter_entrypoints.h b/runtime/entrypoints/interpreter/interpreter_entrypoints.h index 5d646e905f..09522149a7 100644 --- a/runtime/entrypoints/interpreter/interpreter_entrypoints.h +++ b/runtime/entrypoints/interpreter/interpreter_entrypoints.h @@ -27,17 +27,14 @@ namespace art { union JValue; -class MethodHelper; class ShadowFrame; class Thread; // Pointers to functions that are called by interpreter trampolines via thread-local storage. struct PACKED(4) InterpreterEntryPoints { - void (*pInterpreterToInterpreterBridge)(Thread* self, MethodHelper* mh, - const DexFile::CodeItem* code_item, + void (*pInterpreterToInterpreterBridge)(Thread* self, const DexFile::CodeItem* code_item, ShadowFrame* shadow_frame, JValue* result); - void (*pInterpreterToCompiledCodeBridge)(Thread* self, MethodHelper* mh, - const DexFile::CodeItem* code_item, + void (*pInterpreterToCompiledCodeBridge)(Thread* self, const DexFile::CodeItem* code_item, ShadowFrame* shadow_frame, JValue* result); }; diff --git a/runtime/entrypoints/portable/portable_trampoline_entrypoints.cc b/runtime/entrypoints/portable/portable_trampoline_entrypoints.cc index e7975f8923..2a2771f31c 100644 --- a/runtime/entrypoints/portable/portable_trampoline_entrypoints.cc +++ b/runtime/entrypoints/portable/portable_trampoline_entrypoints.cc @@ -27,6 +27,56 @@ namespace art { +class ShortyHelper { + public: + ShortyHelper(const char* shorty, uint32_t shorty_len, bool is_static) + : shorty_(shorty), shorty_len_(shorty_len), is_static_(is_static) { + } + + const char* GetShorty() const { + return shorty_; + } + + uint32_t GetShortyLength() const { + return shorty_len_; + } + + size_t NumArgs() const { + // "1 +" because the first in Args is the receiver. + // "- 1" because we don't count the return type. + return (is_static_ ? 0 : 1) + GetShortyLength() - 1; + } + + // Get the primitive type associated with the given parameter. + Primitive::Type GetParamPrimitiveType(size_t param) const { + CHECK_LT(param, NumArgs()); + if (is_static_) { + param++; // 0th argument must skip return value at start of the shorty. + } else if (param == 0) { + return Primitive::kPrimNot; + } + return Primitive::GetType(shorty_[param]); + } + + // Is the specified parameter a long or double, where parameter 0 is 'this' for instance methods. + bool IsParamALongOrDouble(size_t param) const { + Primitive::Type type = GetParamPrimitiveType(param); + return type == Primitive::kPrimLong || type == Primitive::kPrimDouble; + } + + // Is the specified parameter a reference, where parameter 0 is 'this' for instance methods. + bool IsParamAReference(size_t param) const { + return GetParamPrimitiveType(param) == Primitive::kPrimNot; + } + + private: + const char* const shorty_; + const uint32_t shorty_len_; + const bool is_static_; + + DISALLOW_COPY_AND_ASSIGN(ShortyHelper); +}; + // Visits the arguments as saved to the stack by a Runtime::kRefAndArgs callee save frame. class PortableArgumentVisitor { public: @@ -60,7 +110,7 @@ class PortableArgumentVisitor { #define PORTABLE_STACK_ARG_SKIP 0 #endif - PortableArgumentVisitor(MethodHelper& caller_mh, mirror::ArtMethod** sp) + PortableArgumentVisitor(ShortyHelper& caller_mh, mirror::ArtMethod** sp) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) : caller_mh_(caller_mh), args_in_regs_(ComputeArgsInRegs(caller_mh)), @@ -119,7 +169,7 @@ class PortableArgumentVisitor { } private: - static size_t ComputeArgsInRegs(MethodHelper& mh) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { + static size_t ComputeArgsInRegs(ShortyHelper& mh) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { #if (defined(__i386__)) UNUSED(mh); return 0; @@ -136,7 +186,7 @@ class PortableArgumentVisitor { return args_in_regs; #endif } - MethodHelper& caller_mh_; + ShortyHelper& caller_mh_; const size_t args_in_regs_; const size_t num_params_; uint8_t* const reg_args_; @@ -149,7 +199,7 @@ class PortableArgumentVisitor { // Visits arguments on the stack placing them into the shadow frame. class BuildPortableShadowFrameVisitor : public PortableArgumentVisitor { public: - BuildPortableShadowFrameVisitor(MethodHelper& caller_mh, mirror::ArtMethod** sp, + BuildPortableShadowFrameVisitor(ShortyHelper& caller_mh, mirror::ArtMethod** sp, ShadowFrame& sf, size_t first_arg_reg) : PortableArgumentVisitor(caller_mh, sp), sf_(sf), cur_reg_(first_arg_reg) { } virtual void Visit() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { @@ -198,7 +248,9 @@ extern "C" uint64_t artPortableToInterpreterBridge(mirror::ArtMethod* method, Th } else { const char* old_cause = self->StartAssertNoThreadSuspension("Building interpreter shadow frame"); StackHandleScope<2> hs(self); - MethodHelper mh(hs.NewHandle(method)); + uint32_t shorty_len; + const char* shorty = method->GetShorty(&shorty_len); + ShortyHelper mh(shorty, shorty_len, method->IsStatic()); const DexFile::CodeItem* code_item = method->GetCodeItem(); uint16_t num_regs = code_item->registers_size_; void* memory = alloca(ShadowFrame::ComputeSize(num_regs)); @@ -224,7 +276,7 @@ extern "C" uint64_t artPortableToInterpreterBridge(mirror::ArtMethod* method, Th } } - JValue result = interpreter::EnterInterpreterFromEntryPoint(self, &mh, code_item, shadow_frame); + JValue result = interpreter::EnterInterpreterFromEntryPoint(self, code_item, shadow_frame); // Pop transition. self->PopManagedStackFragment(fragment); return result.GetJ(); @@ -235,7 +287,7 @@ extern "C" uint64_t artPortableToInterpreterBridge(mirror::ArtMethod* method, Th // to jobjects. class BuildPortableArgumentVisitor : public PortableArgumentVisitor { public: - BuildPortableArgumentVisitor(MethodHelper& caller_mh, mirror::ArtMethod** sp, + BuildPortableArgumentVisitor(ShortyHelper& caller_mh, mirror::ArtMethod** sp, ScopedObjectAccessUnchecked& soa, std::vector<jvalue>& args) : PortableArgumentVisitor(caller_mh, sp), soa_(soa), args_(args) {} @@ -294,8 +346,9 @@ 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. - StackHandleScope<1> hs(self); - MethodHelper proxy_mh(hs.NewHandle(proxy_method)); + uint32_t shorty_len; + const char* shorty = proxy_method->GetShorty(&shorty_len); + ShortyHelper proxy_mh(shorty, shorty_len, false); std::vector<jvalue> args; BuildPortableArgumentVisitor local_ref_visitor(proxy_mh, sp, soa, args); local_ref_visitor.VisitArguments(); diff --git a/runtime/entrypoints/quick/quick_trampoline_entrypoints.cc b/runtime/entrypoints/quick/quick_trampoline_entrypoints.cc index 93dc62a094..cb816298ad 100644 --- a/runtime/entrypoints/quick/quick_trampoline_entrypoints.cc +++ b/runtime/entrypoints/quick/quick_trampoline_entrypoints.cc @@ -22,6 +22,7 @@ #include "entrypoints/runtime_asm_entrypoints.h" #include "gc/accounting/card_table-inl.h" #include "interpreter/interpreter.h" +#include "method_reference.h" #include "mirror/art_method-inl.h" #include "mirror/class-inl.h" #include "mirror/dex_cache-inl.h" @@ -510,25 +511,25 @@ extern "C" uint64_t artQuickToInterpreterBridge(mirror::ArtMethod* method, Threa BuildQuickShadowFrameVisitor shadow_frame_builder(sp, method->IsStatic(), shorty, shorty_len, shadow_frame, first_arg_reg); shadow_frame_builder.VisitArguments(); + const bool needs_initialization = + method->IsStatic() && !method->GetDeclaringClass()->IsInitialized(); // Push a transition back into managed code onto the linked list in thread. ManagedStack fragment; self->PushManagedStackFragment(&fragment); self->PushShadowFrame(shadow_frame); self->EndAssertNoThreadSuspension(old_cause); - StackHandleScope<1> hs(self); - MethodHelper mh(hs.NewHandle(method)); - if (mh.Get()->IsStatic() && !mh.Get()->GetDeclaringClass()->IsInitialized()) { + if (needs_initialization) { // Ensure static method's class is initialized. - StackHandleScope<1> hs2(self); - Handle<mirror::Class> h_class(hs2.NewHandle(mh.Get()->GetDeclaringClass())); + StackHandleScope<1> hs(self); + Handle<mirror::Class> h_class(hs.NewHandle(shadow_frame->GetMethod()->GetDeclaringClass())); if (!Runtime::Current()->GetClassLinker()->EnsureInitialized(self, h_class, true, true)) { - DCHECK(Thread::Current()->IsExceptionPending()) << PrettyMethod(mh.Get()); + DCHECK(Thread::Current()->IsExceptionPending()) << PrettyMethod(shadow_frame->GetMethod()); self->PopManagedStackFragment(fragment); return 0; } } - JValue result = interpreter::EnterInterpreterFromEntryPoint(self, &mh, code_item, shadow_frame); + JValue result = interpreter::EnterInterpreterFromEntryPoint(self, code_item, shadow_frame); // Pop transition. self->PopManagedStackFragment(fragment); // No need to restore the args since the method has already been run by the interpreter. @@ -641,7 +642,7 @@ extern "C" uint64_t artQuickProxyInvokeHandler(mirror::ArtMethod* proxy_method, // Convert proxy method into expected interface method. mirror::ArtMethod* interface_method = proxy_method->FindOverriddenMethod(); - DCHECK(interface_method != NULL) << PrettyMethod(proxy_method); + DCHECK(interface_method != nullptr) << PrettyMethod(proxy_method); DCHECK(!interface_method->IsProxyMethod()) << PrettyMethod(interface_method); jobject interface_method_jobj = soa.AddLocalReference<jobject>(interface_method); @@ -710,12 +711,12 @@ extern "C" const void* artQuickResolutionTrampoline(mirror::ArtMethod* called, ClassLinker* linker = Runtime::Current()->GetClassLinker(); mirror::ArtMethod* caller = QuickArgumentVisitor::GetCallingMethod(sp); InvokeType invoke_type; - const DexFile* dex_file; - uint32_t dex_method_idx; - if (called->IsRuntimeMethod()) { + MethodReference called_method(nullptr, 0); + const bool called_method_known_on_entry = !called->IsRuntimeMethod(); + if (!called_method_known_on_entry) { uint32_t dex_pc = caller->ToDexPc(QuickArgumentVisitor::GetCallingPc(sp)); const DexFile::CodeItem* code; - dex_file = caller->GetDexFile(); + called_method.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]); @@ -763,33 +764,33 @@ extern "C" const void* artQuickResolutionTrampoline(mirror::ArtMethod* called, is_range = true; break; default: - LOG(FATAL) << "Unexpected call into trampoline: " << instr->DumpString(NULL); - // Avoid used uninitialized warnings. - invoke_type = kDirect; - is_range = false; + LOG(FATAL) << "Unexpected call into trampoline: " << instr->DumpString(nullptr); + UNREACHABLE(); } - dex_method_idx = (is_range) ? instr->VRegB_3rc() : instr->VRegB_35c(); + called_method.dex_method_index = (is_range) ? instr->VRegB_3rc() : instr->VRegB_35c(); } else { invoke_type = kStatic; - dex_file = called->GetDexFile(); - dex_method_idx = called->GetDexMethodIndex(); + called_method.dex_file = called->GetDexFile(); + called_method.dex_method_index = called->GetDexMethodIndex(); } uint32_t shorty_len; const char* shorty = - dex_file->GetMethodShorty(dex_file->GetMethodId(dex_method_idx), &shorty_len); + called_method.dex_file->GetMethodShorty( + called_method.dex_file->GetMethodId(called_method.dex_method_index), &shorty_len); RememberForGcArgumentVisitor visitor(sp, invoke_type == kStatic, shorty, shorty_len, &soa); visitor.VisitArguments(); self->EndAssertNoThreadSuspension(old_cause); - bool virtual_or_interface = invoke_type == kVirtual || invoke_type == kInterface; + const bool virtual_or_interface = invoke_type == kVirtual || invoke_type == kInterface; // Resolve method filling in dex cache. - if (UNLIKELY(called->IsRuntimeMethod())) { + if (!called_method_known_on_entry) { StackHandleScope<1> hs(self); mirror::Object* dummy = nullptr; HandleWrapper<mirror::Object> h_receiver( hs.NewHandleWrapper(virtual_or_interface ? &receiver : &dummy)); - called = linker->ResolveMethod(self, dex_method_idx, &caller, invoke_type); + DCHECK_EQ(caller->GetDexFile(), called_method.dex_file); + called = linker->ResolveMethod(self, called_method.dex_method_index, &caller, invoke_type); } - const void* code = NULL; + const void* code = nullptr; if (LIKELY(!self->IsExceptionPending())) { // Incompatible class change should have been handled in resolve method. CHECK(!called->CheckIncompatibleClassChange(invoke_type)) @@ -810,20 +811,26 @@ extern "C" const void* artQuickResolutionTrampoline(mirror::ArtMethod* called, << invoke_type << " " << orig_called->GetVtableIndex(); // We came here because of sharpening. Ensure the dex cache is up-to-date on the method index - // of the sharpened method. - if (called->HasSameDexCacheResolvedMethods(caller)) { - caller->SetDexCacheResolvedMethod(called->GetDexMethodIndex(), called); - } else { + // of the sharpened method avoiding dirtying the dex cache if possible. + // Note, called_method.dex_method_index references the dex method before the + // FindVirtualMethodFor... This is ok for FindDexMethodIndexInOtherDexFile that only cares + // about the name and signature. + uint32_t update_dex_cache_method_index = called->GetDexMethodIndex(); + if (!called->HasSameDexCacheResolvedMethods(caller)) { // 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_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->SetDexCacheResolvedMethod(method_index, called); - } + DCHECK(!called_method_known_on_entry); + DCHECK_EQ(caller->GetDexFile(), called_method.dex_file); + const DexFile* caller_dex_file = called_method.dex_file; + uint32_t caller_method_name_and_sig_index = called_method.dex_method_index; + update_dex_cache_method_index = + called->FindDexMethodIndexInOtherDexFile(*caller_dex_file, + caller_method_name_and_sig_index); + } + if ((update_dex_cache_method_index != DexFile::kDexNoIndex) && + (caller->GetDexCacheResolvedMethod(update_dex_cache_method_index) != called)) { + caller->SetDexCacheResolvedMethod(update_dex_cache_method_index, called); } } // Ensure that the called method's class is initialized. @@ -845,7 +852,7 @@ extern "C" const void* artQuickResolutionTrampoline(mirror::ArtMethod* called, DCHECK(called_class->IsErroneous()); } } - CHECK_EQ(code == NULL, self->IsExceptionPending()); + CHECK_EQ(code == nullptr, self->IsExceptionPending()); // Fixup any locally saved objects may have moved during a GC. visitor.FixupReferences(); // Place called method in callee-save frame to be placed as first argument to quick method. @@ -1262,6 +1269,7 @@ class ComputeNativeCallFrameSize { break; default: LOG(FATAL) << "Unexpected type: " << cur_type_ << " in " << shorty; + UNREACHABLE(); } } @@ -1785,7 +1793,7 @@ static TwoWordReturn artInvokeCommon(uint32_t method_idx, mirror::Object* this_o visitor.FixupReferences(); } - if (UNLIKELY(method == NULL)) { + if (UNLIKELY(method == nullptr)) { CHECK(self->IsExceptionPending()); return GetTwoWordFailureValue(); // Failure. } @@ -1794,7 +1802,7 @@ static TwoWordReturn artInvokeCommon(uint32_t method_idx, mirror::Object* this_o const void* code = method->GetEntryPointFromQuickCompiledCode(); // 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) + DCHECK(code != nullptr) << "Code was null in method: " << PrettyMethod(method) << " location: " << method->GetDexFile()->GetLocation(); @@ -1880,7 +1888,7 @@ extern "C" TwoWordReturn artInvokeInterfaceTrampoline(mirror::ArtMethod* interfa mirror::ArtMethod* method; if (LIKELY(interface_method->GetDexMethodIndex() != DexFile::kDexNoIndex)) { method = this_object->GetClass()->FindVirtualMethodForInterface(interface_method); - if (UNLIKELY(method == NULL)) { + if (UNLIKELY(method == nullptr)) { ThrowIncompatibleClassChangeErrorClassForInterfaceDispatch(interface_method, this_object, caller_method); return GetTwoWordFailureValue(); // Failure. @@ -1900,7 +1908,7 @@ extern "C" TwoWordReturn artInvokeInterfaceTrampoline(mirror::ArtMethod* interfa Instruction::Code instr_code = instr->Opcode(); CHECK(instr_code == Instruction::INVOKE_INTERFACE || instr_code == Instruction::INVOKE_INTERFACE_RANGE) - << "Unexpected call into interface trampoline: " << instr->DumpString(NULL); + << "Unexpected call into interface trampoline: " << instr->DumpString(nullptr); uint32_t dex_method_idx; if (instr_code == Instruction::INVOKE_INTERFACE) { dex_method_idx = instr->VRegB_35c(); @@ -1932,7 +1940,7 @@ extern "C" TwoWordReturn artInvokeInterfaceTrampoline(mirror::ArtMethod* interfa const void* code = method->GetEntryPointFromQuickCompiledCode(); // 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) + DCHECK(code != nullptr) << "Code was null in method: " << PrettyMethod(method) << " location: " << method->GetDexFile()->GetLocation(); return GetTwoWordSuccessValue(reinterpret_cast<uintptr_t>(code), diff --git a/runtime/fault_handler.cc b/runtime/fault_handler.cc index 835485c351..94753d4461 100644 --- a/runtime/fault_handler.cc +++ b/runtime/fault_handler.cc @@ -177,6 +177,12 @@ void FaultManager::HandleFault(int sig, siginfo_t* info, void* context) { Thread* self = Thread::Current(); + // If ART is not running, or the thread is not attached to ART pass the + // signal on to the next handler in the chain. + if (self == nullptr || Runtime::Current() == nullptr || !Runtime::Current()->IsStarted()) { + InvokeUserSignalHandler(sig, info, context); + return; + } // Now set up the nested signal handler. // TODO: add SIGSEGV back to the nested signals when we can handle running out stack gracefully. diff --git a/runtime/field_helper.cc b/runtime/field_helper.cc deleted file mode 100644 index 5c85c46096..0000000000 --- a/runtime/field_helper.cc +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Copyright (C) 2011 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "field_helper.h" - -#include "class_linker-inl.h" -#include "dex_file.h" -#include "mirror/dex_cache.h" -#include "runtime.h" -#include "thread-inl.h" - -namespace art { - -mirror::Class* FieldHelper::GetType(bool resolve) { - uint32_t field_index = field_->GetDexFieldIndex(); - if (UNLIKELY(field_->GetDeclaringClass()->IsProxyClass())) { - return Runtime::Current()->GetClassLinker()->FindSystemClass(Thread::Current(), - field_->GetTypeDescriptor()); - } - const DexFile* dex_file = field_->GetDexFile(); - const DexFile::FieldId& field_id = dex_file->GetFieldId(field_index); - mirror::Class* type = field_->GetDexCache()->GetResolvedType(field_id.type_idx_); - if (resolve && (type == nullptr)) { - type = Runtime::Current()->GetClassLinker()->ResolveType(field_id.type_idx_, field_.Get()); - CHECK(type != nullptr || Thread::Current()->IsExceptionPending()); - } - return type; -} - -const char* FieldHelper::GetDeclaringClassDescriptor() { - return field_->GetDeclaringClass()->GetDescriptor(&declaring_class_descriptor_); -} - -} // namespace art diff --git a/runtime/field_helper.h b/runtime/field_helper.h deleted file mode 100644 index 8097025089..0000000000 --- a/runtime/field_helper.h +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Copyright (C) 2011 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef ART_RUNTIME_FIELD_HELPER_H_ -#define ART_RUNTIME_FIELD_HELPER_H_ - -#include "base/macros.h" -#include "handle.h" -#include "mirror/art_field.h" - -namespace art { - -class FieldHelper { - public: - explicit FieldHelper(Handle<mirror::ArtField> f) : field_(f) {} - - mirror::ArtField* GetField() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - return field_.Get(); - } - - mirror::Class* GetType(bool resolve = true) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); - - // The returned const char* is only guaranteed to be valid for the lifetime of the FieldHelper. - // If you need it longer, copy it into a std::string. - const char* GetDeclaringClassDescriptor() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); - - private: - Handle<mirror::ArtField> field_; - std::string declaring_class_descriptor_; - - DISALLOW_COPY_AND_ASSIGN(FieldHelper); -}; - -} // namespace art - -#endif // ART_RUNTIME_FIELD_HELPER_H_ diff --git a/runtime/gc/heap-inl.h b/runtime/gc/heap-inl.h index 3101c68599..9d2f6d1238 100644 --- a/runtime/gc/heap-inl.h +++ b/runtime/gc/heap-inl.h @@ -48,11 +48,20 @@ inline mirror::Object* Heap::AllocObjectWithAllocator(Thread* self, mirror::Clas } // Need to check that we arent the large object allocator since the large object allocation code // path this function. If we didn't check we would have an infinite loop. + mirror::Object* obj; if (kCheckLargeObject && UNLIKELY(ShouldAllocLargeObject(klass, byte_count))) { - return AllocLargeObject<kInstrumented, PreFenceVisitor>(self, klass, byte_count, - pre_fence_visitor); + obj = AllocLargeObject<kInstrumented, PreFenceVisitor>(self, &klass, byte_count, + pre_fence_visitor); + if (obj != nullptr) { + return obj; + } else { + // There should be an OOM exception, since we are retrying, clear it. + self->ClearException(); + } + // If the large object allocation failed, try to use the normal spaces (main space, + // non moving space). This can happen if there is significant virtual address space + // fragmentation. } - mirror::Object* obj; AllocationTimer alloc_timer(this, &obj); size_t bytes_allocated; size_t usable_size; @@ -171,10 +180,13 @@ inline void Heap::PushOnAllocationStack(Thread* self, mirror::Object** obj) { } template <bool kInstrumented, typename PreFenceVisitor> -inline mirror::Object* Heap::AllocLargeObject(Thread* self, mirror::Class* klass, +inline mirror::Object* Heap::AllocLargeObject(Thread* self, mirror::Class** klass, size_t byte_count, const PreFenceVisitor& pre_fence_visitor) { - return AllocObjectWithAllocator<kInstrumented, false, PreFenceVisitor>(self, klass, byte_count, + // Save and restore the class in case it moves. + StackHandleScope<1> hs(self); + auto klass_wrapper = hs.NewHandleWrapper(klass); + return AllocObjectWithAllocator<kInstrumented, false, PreFenceVisitor>(self, *klass, byte_count, kAllocatorTypeLOS, pre_fence_visitor); } diff --git a/runtime/gc/heap.cc b/runtime/gc/heap.cc index 0cceaa4467..0fd0a9ff52 100644 --- a/runtime/gc/heap.cc +++ b/runtime/gc/heap.cc @@ -365,6 +365,7 @@ Heap::Heap(size_t initial_size, size_t growth_limit, size_t min_free, size_t max uint8_t* heap_end = continuous_spaces_.back()->Limit(); size_t heap_capacity = heap_end - heap_begin; // Remove the main backup space since it slows down the GC to have unused extra spaces. + // TODO: Avoid needing to do this. if (main_space_backup_.get() != nullptr) { RemoveSpace(main_space_backup_.get()); } @@ -977,6 +978,22 @@ void Heap::DoPendingTransitionOrTrim() { Trim(); } +class TrimIndirectReferenceTableClosure : public Closure { + public: + explicit TrimIndirectReferenceTableClosure(Barrier* barrier) : barrier_(barrier) { + } + virtual void Run(Thread* thread) OVERRIDE NO_THREAD_SAFETY_ANALYSIS { + ATRACE_BEGIN("Trimming reference table"); + thread->GetJniEnv()->locals.Trim(); + ATRACE_END(); + barrier_->Pass(Thread::Current()); + } + + private: + Barrier* const barrier_; +}; + + void Heap::Trim() { Thread* self = Thread::Current(); { @@ -998,6 +1015,19 @@ void Heap::Trim() { WaitForGcToCompleteLocked(kGcCauseTrim, self); collector_type_running_ = kCollectorTypeHeapTrim; } + // Trim reference tables. + { + ScopedObjectAccess soa(self); + JavaVMExt* vm = soa.Vm(); + // Trim globals indirect reference table. + vm->TrimGlobals(); + // Trim locals indirect reference tables. + Barrier barrier(0); + TrimIndirectReferenceTableClosure closure(&barrier); + ScopedThreadStateChange tsc(self, kWaitingForCheckPointsToRun); + size_t barrier_count = Runtime::Current()->GetThreadList()->RunCheckpoint(&closure); + barrier.Increment(self, barrier_count); + } uint64_t start_ns = NanoTime(); // Trim the managed spaces. uint64_t total_alloc_space_allocated = 0; @@ -1571,6 +1601,8 @@ HomogeneousSpaceCompactResult Heap::PerformHomogeneousSpaceCompact() { to_space->GetMemMap()->Protect(PROT_READ | PROT_WRITE); const uint64_t space_size_before_compaction = from_space->Size(); AddSpace(to_space); + // Make sure that we will have enough room to copy. + CHECK_GE(to_space->GetFootprintLimit(), from_space->GetFootprintLimit()); Compact(to_space, from_space, kGcCauseHomogeneousSpaceCompact); // Leave as prot read so that we can still run ROSAlloc verification on this space. from_space->GetMemMap()->Protect(PROT_READ); @@ -1689,8 +1721,8 @@ void Heap::TransitionCollector(CollectorType collector_type) { RemoveSpace(temp_space_); temp_space_ = nullptr; mem_map->Protect(PROT_READ | PROT_WRITE); - CreateMainMallocSpace(mem_map.get(), kDefaultInitialSize, mem_map->Size(), - mem_map->Size()); + CreateMainMallocSpace(mem_map.get(), kDefaultInitialSize, + std::min(mem_map->Size(), growth_limit_), mem_map->Size()); mem_map.release(); // Compact to the main space from the bump pointer space, don't need to swap semispaces. AddSpace(main_space_); @@ -1703,9 +1735,9 @@ void Heap::TransitionCollector(CollectorType collector_type) { if (kIsDebugBuild && kUseRosAlloc) { mem_map->Protect(PROT_READ | PROT_WRITE); } - main_space_backup_.reset(CreateMallocSpaceFromMemMap(mem_map.get(), kDefaultInitialSize, - mem_map->Size(), mem_map->Size(), - name, true)); + main_space_backup_.reset(CreateMallocSpaceFromMemMap( + mem_map.get(), kDefaultInitialSize, std::min(mem_map->Size(), growth_limit_), + mem_map->Size(), name, true)); if (kIsDebugBuild && kUseRosAlloc) { mem_map->Protect(PROT_NONE); } @@ -1947,7 +1979,8 @@ void Heap::PreZygoteFork() { MemMap* mem_map = main_space_->ReleaseMemMap(); RemoveSpace(main_space_); space::Space* old_main_space = main_space_; - CreateMainMallocSpace(mem_map, kDefaultInitialSize, mem_map->Size(), mem_map->Size()); + CreateMainMallocSpace(mem_map, kDefaultInitialSize, std::min(mem_map->Size(), growth_limit_), + mem_map->Size()); delete old_main_space; AddSpace(main_space_); } else { @@ -2959,7 +2992,18 @@ void Heap::GrowForUtilization(collector::GarbageCollector* collector_ran) { void Heap::ClearGrowthLimit() { growth_limit_ = capacity_; - non_moving_space_->ClearGrowthLimit(); + for (const auto& space : continuous_spaces_) { + if (space->IsMallocSpace()) { + gc::space::MallocSpace* malloc_space = space->AsMallocSpace(); + malloc_space->ClearGrowthLimit(); + malloc_space->SetFootprintLimit(malloc_space->Capacity()); + } + } + // This space isn't added for performance reasons. + if (main_space_backup_.get() != nullptr) { + main_space_backup_->ClearGrowthLimit(); + main_space_backup_->SetFootprintLimit(main_space_backup_->Capacity()); + } } void Heap::AddFinalizerReference(Thread* self, mirror::Object** object) { diff --git a/runtime/gc/heap.h b/runtime/gc/heap.h index 69a573ef98..4e1a0ff242 100644 --- a/runtime/gc/heap.h +++ b/runtime/gc/heap.h @@ -654,7 +654,7 @@ class Heap { // We don't force this to be inlined since it is a slow path. template <bool kInstrumented, typename PreFenceVisitor> - mirror::Object* AllocLargeObject(Thread* self, mirror::Class* klass, size_t byte_count, + mirror::Object* AllocLargeObject(Thread* self, mirror::Class** klass, size_t byte_count, const PreFenceVisitor& pre_fence_visitor) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); diff --git a/runtime/globals.h b/runtime/globals.h index 4d33196c98..3104229b17 100644 --- a/runtime/globals.h +++ b/runtime/globals.h @@ -64,6 +64,12 @@ static constexpr bool kUsePortableCompiler = true; static constexpr bool kUsePortableCompiler = false; #endif +#if defined(ART_USE_OPTIMIZING_COMPILER) +static constexpr bool kUseOptimizingCompiler = true; +#else +static constexpr bool kUseOptimizingCompiler = false; +#endif + // Garbage collector constants. static constexpr bool kMovingCollector = true && !kUsePortableCompiler; static constexpr bool kMarkCompactSupport = false && kMovingCollector; diff --git a/runtime/indirect_reference_table.cc b/runtime/indirect_reference_table.cc index 4d177a32d8..0d84a1ef98 100644 --- a/runtime/indirect_reference_table.cc +++ b/runtime/indirect_reference_table.cc @@ -162,13 +162,12 @@ bool IndirectReferenceTable::Remove(uint32_t cookie, IndirectRef iref) { DCHECK(table_ != NULL); DCHECK_GE(segment_state_.parts.numHoles, prevState.parts.numHoles); - int idx = ExtractIndex(iref); - if (GetIndirectRefKind(iref) == kHandleScopeOrInvalid && Thread::Current()->HandleScopeContains(reinterpret_cast<jobject>(iref))) { LOG(WARNING) << "Attempt to remove local handle scope entry from IRT, ignoring"; return true; } + const int idx = ExtractIndex(iref); if (idx < bottomIndex) { // Wrong segment. LOG(WARNING) << "Attempt to remove index outside index area (" << idx @@ -236,6 +235,13 @@ bool IndirectReferenceTable::Remove(uint32_t cookie, IndirectRef iref) { return true; } +void IndirectReferenceTable::Trim() { + const size_t top_index = Capacity(); + auto* release_start = AlignUp(reinterpret_cast<uint8_t*>(&table_[top_index]), kPageSize); + uint8_t* release_end = table_mem_map_->End(); + madvise(release_start, release_end - release_start, MADV_DONTNEED); +} + void IndirectReferenceTable::VisitRoots(RootCallback* callback, void* arg, uint32_t tid, RootType root_type) { for (auto ref : *this) { diff --git a/runtime/indirect_reference_table.h b/runtime/indirect_reference_table.h index 168f9f2764..fbd5714688 100644 --- a/runtime/indirect_reference_table.h +++ b/runtime/indirect_reference_table.h @@ -331,6 +331,9 @@ class IndirectReferenceTable { return Offset(OFFSETOF_MEMBER(IndirectReferenceTable, segment_state_)); } + // Release pages past the end of the table that may have previously held references. + void Trim() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); + private: // Extract the table index from an indirect reference. static uint32_t ExtractIndex(IndirectRef iref) { diff --git a/runtime/interpreter/interpreter.cc b/runtime/interpreter/interpreter.cc index b17f3039c6..b04a18b934 100644 --- a/runtime/interpreter/interpreter.cc +++ b/runtime/interpreter/interpreter.cc @@ -327,37 +327,31 @@ static constexpr InterpreterImplKind kInterpreterImplKind = kComputedGotoImplKin // Clang 3.4 fails to build the goto interpreter implementation. static constexpr InterpreterImplKind kInterpreterImplKind = kSwitchImpl; template<bool do_access_check, bool transaction_active> -JValue ExecuteGotoImpl(Thread*, MethodHelper&, const DexFile::CodeItem*, ShadowFrame&, JValue) { +JValue ExecuteGotoImpl(Thread*, const DexFile::CodeItem*, ShadowFrame&, JValue) { LOG(FATAL) << "UNREACHABLE"; UNREACHABLE(); } // Explicit definitions of ExecuteGotoImpl. template<> SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) -JValue ExecuteGotoImpl<true, false>(Thread* self, MethodHelper& mh, - const DexFile::CodeItem* code_item, +JValue ExecuteGotoImpl<true, false>(Thread* self, const DexFile::CodeItem* code_item, ShadowFrame& shadow_frame, JValue result_register); template<> SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) -JValue ExecuteGotoImpl<false, false>(Thread* self, MethodHelper& mh, - const DexFile::CodeItem* code_item, +JValue ExecuteGotoImpl<false, false>(Thread* self, const DexFile::CodeItem* code_item, ShadowFrame& shadow_frame, JValue result_register); template<> SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) -JValue ExecuteGotoImpl<true, true>(Thread* self, MethodHelper& mh, - const DexFile::CodeItem* code_item, - ShadowFrame& shadow_frame, JValue result_register); +JValue ExecuteGotoImpl<true, true>(Thread* self, const DexFile::CodeItem* code_item, + ShadowFrame& shadow_frame, JValue result_register); template<> SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) -JValue ExecuteGotoImpl<false, true>(Thread* self, MethodHelper& mh, - const DexFile::CodeItem* code_item, - ShadowFrame& shadow_frame, JValue result_register); +JValue ExecuteGotoImpl<false, true>(Thread* self, const DexFile::CodeItem* code_item, + ShadowFrame& shadow_frame, JValue result_register); #endif -static JValue Execute(Thread* self, MethodHelper& mh, const DexFile::CodeItem* code_item, - ShadowFrame& shadow_frame, JValue result_register) +static JValue Execute(Thread* self, const DexFile::CodeItem* code_item, ShadowFrame& shadow_frame, + JValue result_register) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); -static inline JValue Execute(Thread* self, MethodHelper& mh, const DexFile::CodeItem* code_item, +static inline JValue Execute(Thread* self, const DexFile::CodeItem* code_item, ShadowFrame& shadow_frame, JValue result_register) { - DCHECK(shadow_frame.GetMethod() == mh.GetMethod() || - shadow_frame.GetMethod()->GetDeclaringClass()->IsProxyClass()); DCHECK(!shadow_frame.GetMethod()->IsAbstract()); DCHECK(!shadow_frame.GetMethod()->IsNative()); shadow_frame.GetMethod()->GetDeclaringClass()->AssertInitializedOrInitializingInThread(self); @@ -367,32 +361,32 @@ static inline JValue Execute(Thread* self, MethodHelper& mh, const DexFile::Code // Enter the "without access check" interpreter. if (kInterpreterImplKind == kSwitchImpl) { if (transaction_active) { - return ExecuteSwitchImpl<false, true>(self, mh, code_item, shadow_frame, result_register); + return ExecuteSwitchImpl<false, true>(self, code_item, shadow_frame, result_register); } else { - return ExecuteSwitchImpl<false, false>(self, mh, code_item, shadow_frame, result_register); + return ExecuteSwitchImpl<false, false>(self, code_item, shadow_frame, result_register); } } else { DCHECK_EQ(kInterpreterImplKind, kComputedGotoImplKind); if (transaction_active) { - return ExecuteGotoImpl<false, true>(self, mh, code_item, shadow_frame, result_register); + return ExecuteGotoImpl<false, true>(self, code_item, shadow_frame, result_register); } else { - return ExecuteGotoImpl<false, false>(self, mh, code_item, shadow_frame, result_register); + return ExecuteGotoImpl<false, false>(self, code_item, shadow_frame, result_register); } } } else { // Enter the "with access check" interpreter. if (kInterpreterImplKind == kSwitchImpl) { if (transaction_active) { - return ExecuteSwitchImpl<true, true>(self, mh, code_item, shadow_frame, result_register); + return ExecuteSwitchImpl<true, true>(self, code_item, shadow_frame, result_register); } else { - return ExecuteSwitchImpl<true, false>(self, mh, code_item, shadow_frame, result_register); + return ExecuteSwitchImpl<true, false>(self, code_item, shadow_frame, result_register); } } else { DCHECK_EQ(kInterpreterImplKind, kComputedGotoImplKind); if (transaction_active) { - return ExecuteGotoImpl<true, true>(self, mh, code_item, shadow_frame, result_register); + return ExecuteGotoImpl<true, true>(self, code_item, shadow_frame, result_register); } else { - return ExecuteGotoImpl<true, false>(self, mh, code_item, shadow_frame, result_register); + return ExecuteGotoImpl<true, false>(self, code_item, shadow_frame, result_register); } } } @@ -473,9 +467,7 @@ 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()); + JValue r = Execute(self, code_item, *shadow_frame, JValue()); if (result != NULL) { *result = r; } @@ -500,10 +492,8 @@ void EnterInterpreterFromDeoptimize(Thread* self, ShadowFrame* shadow_frame, JVa value.SetJ(ret_val->GetJ()); // Set value to last known result in case the shadow frame chain is empty. while (shadow_frame != NULL) { self->SetTopOfShadowStack(shadow_frame); - 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); + const DexFile::CodeItem* code_item = shadow_frame->GetMethod()->GetCodeItem(); + value = Execute(self, code_item, *shadow_frame, value); ShadowFrame* old_frame = shadow_frame; shadow_frame = shadow_frame->GetLink(); delete old_frame; @@ -511,8 +501,7 @@ void EnterInterpreterFromDeoptimize(Thread* self, ShadowFrame* shadow_frame, JVa ret_val->SetJ(value.GetJ()); } -JValue EnterInterpreterFromEntryPoint(Thread* self, MethodHelper* mh, - const DexFile::CodeItem* code_item, +JValue EnterInterpreterFromEntryPoint(Thread* self, const DexFile::CodeItem* code_item, ShadowFrame* shadow_frame) { DCHECK_EQ(self, Thread::Current()); bool implicit_check = !Runtime::Current()->ExplicitStackOverflowChecks(); @@ -521,11 +510,10 @@ JValue EnterInterpreterFromEntryPoint(Thread* self, MethodHelper* mh, return JValue(); } - return Execute(self, *mh, code_item, *shadow_frame, JValue()); + return Execute(self, code_item, *shadow_frame, JValue()); } -extern "C" void artInterpreterToInterpreterBridge(Thread* self, MethodHelper* mh, - const DexFile::CodeItem* code_item, +extern "C" void artInterpreterToInterpreterBridge(Thread* self, const DexFile::CodeItem* code_item, ShadowFrame* shadow_frame, JValue* result) { bool implicit_check = !Runtime::Current()->ExplicitStackOverflowChecks(); if (UNLIKELY(__builtin_frame_address(0) < self->GetStackEndForInterpreter(implicit_check))) { @@ -534,10 +522,10 @@ extern "C" void artInterpreterToInterpreterBridge(Thread* self, MethodHelper* mh } self->PushShadowFrame(shadow_frame); - DCHECK_EQ(shadow_frame->GetMethod(), mh->Get()); // Ensure static methods are initialized. - if (mh->Get()->IsStatic()) { - mirror::Class* declaring_class = mh->Get()->GetDeclaringClass(); + const bool is_static = shadow_frame->GetMethod()->IsStatic(); + if (is_static) { + mirror::Class* declaring_class = shadow_frame->GetMethod()->GetDeclaringClass(); if (UNLIKELY(!declaring_class->IsInitialized())) { StackHandleScope<1> hs(self); HandleWrapper<Class> h_declaring_class(hs.NewHandleWrapper(&declaring_class)); @@ -551,15 +539,15 @@ extern "C" void artInterpreterToInterpreterBridge(Thread* self, MethodHelper* mh } } - if (LIKELY(!mh->Get()->IsNative())) { - result->SetJ(Execute(self, *mh, code_item, *shadow_frame, JValue()).GetJ()); + if (LIKELY(!shadow_frame->GetMethod()->IsNative())) { + result->SetJ(Execute(self, code_item, *shadow_frame, JValue()).GetJ()); } else { // We don't expect to be asked to interpret native code (which is entered via a JNI compiler // generated stub) except during testing and image writing. CHECK(!Runtime::Current()->IsStarted()); - Object* receiver = mh->Get()->IsStatic() ? nullptr : shadow_frame->GetVRegReference(0); - uint32_t* args = shadow_frame->GetVRegArgs(mh->Get()->IsStatic() ? 0 : 1); - UnstartedRuntimeJni(self, mh->Get(), receiver, args, result); + Object* receiver = is_static ? nullptr : shadow_frame->GetVRegReference(0); + uint32_t* args = shadow_frame->GetVRegArgs(is_static ? 0 : 1); + UnstartedRuntimeJni(self, shadow_frame->GetMethod(), receiver, args, result); } self->PopShadowFrame(); diff --git a/runtime/interpreter/interpreter.h b/runtime/interpreter/interpreter.h index d327a71a4f..7d634b3d25 100644 --- a/runtime/interpreter/interpreter.h +++ b/runtime/interpreter/interpreter.h @@ -27,7 +27,6 @@ class Object; } // namespace mirror union JValue; -class MethodHelper; class ShadowFrame; class Thread; @@ -42,21 +41,18 @@ extern void EnterInterpreterFromDeoptimize(Thread* self, ShadowFrame* shadow_fra JValue* ret_val) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); -extern JValue EnterInterpreterFromEntryPoint(Thread* self, MethodHelper* mh, - const DexFile::CodeItem* code_item, +extern JValue EnterInterpreterFromEntryPoint(Thread* self, const DexFile::CodeItem* code_item, ShadowFrame* shadow_frame) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); } // namespace interpreter -extern "C" void artInterpreterToInterpreterBridge(Thread* self, MethodHelper* mh, - const DexFile::CodeItem* code_item, +extern "C" void artInterpreterToInterpreterBridge(Thread* self, const DexFile::CodeItem* code_item, ShadowFrame* shadow_frame, JValue* result) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); -extern "C" void artInterpreterToCompiledCodeBridge(Thread* self, MethodHelper* mh, - const DexFile::CodeItem* code_item, +extern "C" void artInterpreterToCompiledCodeBridge(Thread* self, const DexFile::CodeItem* code_item, ShadowFrame* shadow_frame, JValue* result) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); diff --git a/runtime/interpreter/interpreter_common.cc b/runtime/interpreter/interpreter_common.cc index eb80c307f6..3c7db85395 100644 --- a/runtime/interpreter/interpreter_common.cc +++ b/runtime/interpreter/interpreter_common.cc @@ -16,7 +16,6 @@ #include "interpreter_common.h" -#include "field_helper.h" #include "mirror/array-inl.h" namespace art { @@ -267,8 +266,7 @@ bool DoFieldPut(Thread* self, const ShadowFrame& shadow_frame, const Instruction HandleWrapper<mirror::ArtField> h_f(hs.NewHandleWrapper(&f)); HandleWrapper<mirror::Object> h_reg(hs.NewHandleWrapper(®)); HandleWrapper<mirror::Object> h_obj(hs.NewHandleWrapper(&obj)); - FieldHelper fh(h_f); - field_class = fh.GetType(); + field_class = h_f->GetType(true); } if (!reg->VerifierInstanceOf(field_class)) { // This should never happen. @@ -505,14 +503,14 @@ uint32_t FindNextInstructionFollowingException(Thread* self, return found_dex_pc; } -void UnexpectedOpcode(const Instruction* inst, MethodHelper& mh) { - LOG(FATAL) << "Unexpected instruction: " << inst->DumpString(mh.GetMethod()->GetDexFile()); - exit(0); // Unreachable, keep GCC happy. +void UnexpectedOpcode(const Instruction* inst, const ShadowFrame& shadow_frame) { + LOG(FATAL) << "Unexpected instruction: " + << inst->DumpString(shadow_frame.GetMethod()->GetDexFile()); + UNREACHABLE(); } -static void UnstartedRuntimeInvoke(Thread* self, MethodHelper* mh, - const DexFile::CodeItem* code_item, ShadowFrame* shadow_frame, - JValue* result, size_t arg_offset) +static void UnstartedRuntimeInvoke(Thread* self, const DexFile::CodeItem* code_item, + ShadowFrame* shadow_frame, JValue* result, size_t arg_offset) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); // Assign register 'src_reg' from shadow_frame to register 'dest_reg' into new_shadow_frame. @@ -541,29 +539,28 @@ void AbortTransaction(Thread* self, const char* fmt, ...) { } template<bool is_range, bool do_assignability_check> -bool DoCall(ArtMethod* method, Thread* self, ShadowFrame& shadow_frame, +bool DoCall(ArtMethod* called_method, Thread* self, ShadowFrame& shadow_frame, const Instruction* inst, uint16_t inst_data, JValue* result) { // Compute method information. - const DexFile::CodeItem* code_item = method->GetCodeItem(); + const DexFile::CodeItem* code_item = called_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)) { num_regs = code_item->registers_size_; DCHECK_EQ(num_ins, code_item->ins_size_); } else { - DCHECK(method->IsNative() || method->IsProxyMethod()); + DCHECK(called_method->IsNative() || called_method->IsProxyMethod()); num_regs = num_ins; } // Allocate shadow frame on the stack. const char* old_cause = self->StartAssertNoThreadSuspension("DoCall"); void* memory = alloca(ShadowFrame::ComputeSize(num_regs)); - ShadowFrame* new_shadow_frame(ShadowFrame::Create(num_regs, &shadow_frame, method, 0, memory)); + ShadowFrame* new_shadow_frame(ShadowFrame::Create(num_regs, &shadow_frame, called_method, 0, + memory)); // 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 @@ -573,11 +570,12 @@ 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.Get()->GetParameterTypeList(); + const DexFile::TypeList* params = new_shadow_frame->GetMethod()->GetParameterTypeList(); uint32_t shorty_len = 0; - const char* shorty = mh.Get()->GetShorty(&shorty_len); + const char* shorty = new_shadow_frame->GetMethod()->GetShorty(&shorty_len); - // TODO: find a cleaner way to separate non-range and range information without duplicating code. + // TODO: find a cleaner way to separate non-range and range information without duplicating + // code. uint32_t arg[5]; // only used in invoke-XXX. uint32_t vregC; // only used in invoke-XXX-range. if (is_range) { @@ -589,7 +587,7 @@ bool DoCall(ArtMethod* method, Thread* self, ShadowFrame& shadow_frame, // Handle receiver apart since it's not part of the shorty. size_t dest_reg = first_dest_reg; size_t arg_offset = 0; - if (!mh.Get()->IsStatic()) { + if (!new_shadow_frame->GetMethod()->IsStatic()) { size_t receiver_reg = is_range ? vregC : arg[0]; new_shadow_frame->SetVRegReference(dest_reg, shadow_frame.GetVRegReference(receiver_reg)); ++dest_reg; @@ -602,7 +600,9 @@ bool DoCall(ArtMethod* method, Thread* self, ShadowFrame& shadow_frame, case 'L': { Object* o = shadow_frame.GetVRegReference(src_reg); if (do_assignability_check && o != NULL) { - Class* arg_type = mh.GetClassFromTypeIdx(params->GetTypeItem(shorty_pos).type_idx_); + Class* arg_type = + new_shadow_frame->GetMethod()->GetClassFromTypeIndex( + params->GetTypeItem(shorty_pos).type_idx_, true); if (arg_type == NULL) { CHECK(self->IsExceptionPending()); return false; @@ -613,7 +613,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.Get()->GetName(), shorty_pos, + new_shadow_frame->GetMethod()->GetName(), shorty_pos, o->GetClass()->GetDescriptor(&temp1), arg_type->GetDescriptor(&temp2)); return false; @@ -650,7 +650,8 @@ bool DoCall(ArtMethod* method, Thread* self, ShadowFrame& shadow_frame, uint16_t regList = inst->Fetch16(2); uint16_t count = num_ins; if (count == 5) { - AssignRegister(new_shadow_frame, shadow_frame, first_dest_reg + 4U, (inst_data >> 8) & 0x0f); + AssignRegister(new_shadow_frame, shadow_frame, first_dest_reg + 4U, + (inst_data >> 8) & 0x0f); --count; } for (size_t arg_index = 0; arg_index < count; ++arg_index, regList >>= 4) { @@ -662,17 +663,24 @@ bool DoCall(ArtMethod* method, Thread* self, ShadowFrame& shadow_frame, // Do the call now. if (LIKELY(Runtime::Current()->IsStarted())) { - if (kIsDebugBuild && mh.Get()->GetEntryPointFromInterpreter() == nullptr) { - LOG(FATAL) << "Attempt to invoke non-executable method: " << PrettyMethod(mh.Get()); + if (kIsDebugBuild && new_shadow_frame->GetMethod()->GetEntryPointFromInterpreter() == nullptr) { + LOG(FATAL) << "Attempt to invoke non-executable method: " + << PrettyMethod(new_shadow_frame->GetMethod()); + UNREACHABLE(); } if (kIsDebugBuild && Runtime::Current()->GetInstrumentation()->IsForcedInterpretOnly() && - !mh.Get()->IsNative() && !mh.Get()->IsProxyMethod() && - mh.Get()->GetEntryPointFromInterpreter() == artInterpreterToCompiledCodeBridge) { - LOG(FATAL) << "Attempt to call compiled code when -Xint: " << PrettyMethod(mh.Get()); + !new_shadow_frame->GetMethod()->IsNative() && + !new_shadow_frame->GetMethod()->IsProxyMethod() && + new_shadow_frame->GetMethod()->GetEntryPointFromInterpreter() + == artInterpreterToCompiledCodeBridge) { + LOG(FATAL) << "Attempt to call compiled code when -Xint: " + << PrettyMethod(new_shadow_frame->GetMethod()); + UNREACHABLE(); } - (mh.Get()->GetEntryPointFromInterpreter())(self, &mh, code_item, new_shadow_frame, result); + (new_shadow_frame->GetMethod()->GetEntryPointFromInterpreter())(self, code_item, + new_shadow_frame, result); } else { - UnstartedRuntimeInvoke(self, &mh, code_item, new_shadow_frame, result, first_dest_reg); + UnstartedRuntimeInvoke(self, code_item, new_shadow_frame, result, first_dest_reg); } return !self->IsExceptionPending(); } @@ -813,8 +821,8 @@ static void UnstartedRuntimeFindClass(Thread* self, Handle<mirror::String> class result->SetL(found); } -static void UnstartedRuntimeInvoke(Thread* self, MethodHelper* mh, - const DexFile::CodeItem* code_item, ShadowFrame* shadow_frame, +static void UnstartedRuntimeInvoke(Thread* self, const DexFile::CodeItem* code_item, + ShadowFrame* shadow_frame, JValue* result, size_t arg_offset) { // In a runtime that's not started we intercept certain methods to avoid complicated dependency // problems in core libraries. @@ -934,7 +942,7 @@ static void UnstartedRuntimeInvoke(Thread* self, MethodHelper* mh, } } else { // Not special, continue with regular interpreter execution. - artInterpreterToInterpreterBridge(self, mh, code_item, shadow_frame, result); + artInterpreterToInterpreterBridge(self, code_item, shadow_frame, result); } } diff --git a/runtime/interpreter/interpreter_common.h b/runtime/interpreter/interpreter_common.h index f88d56a30a..ce7c1c3817 100644 --- a/runtime/interpreter/interpreter_common.h +++ b/runtime/interpreter/interpreter_common.h @@ -33,7 +33,6 @@ #include "entrypoints/entrypoint_utils-inl.h" #include "gc/accounting/card_table-inl.h" #include "handle_scope-inl.h" -#include "method_helper-inl.h" #include "nth_caller_visitor.h" #include "mirror/art_field-inl.h" #include "mirror/art_method.h" @@ -70,13 +69,11 @@ namespace interpreter { // External references to both interpreter implementations. template<bool do_access_check, bool transaction_active> -extern JValue ExecuteSwitchImpl(Thread* self, MethodHelper& mh, - const DexFile::CodeItem* code_item, +extern JValue ExecuteSwitchImpl(Thread* self, const DexFile::CodeItem* code_item, ShadowFrame& shadow_frame, JValue result_register); template<bool do_access_check, bool transaction_active> -extern JValue ExecuteGotoImpl(Thread* self, MethodHelper& mh, - const DexFile::CodeItem* code_item, +extern JValue ExecuteGotoImpl(Thread* self, const DexFile::CodeItem* code_item, ShadowFrame& shadow_frame, JValue result_register); void ThrowNullPointerExceptionFromInterpreter(const ShadowFrame& shadow_frame) @@ -100,7 +97,7 @@ void RecordArrayElementsInTransaction(mirror::Array* array, int32_t count) // DoInvokeVirtualQuick functions. // Returns true on success, otherwise throws an exception and returns false. template<bool is_range, bool do_assignability_check> -bool DoCall(ArtMethod* method, Thread* self, ShadowFrame& shadow_frame, +bool DoCall(ArtMethod* called_method, Thread* self, ShadowFrame& shadow_frame, const Instruction* inst, uint16_t inst_data, JValue* result); // Handles invoke-XXX/range instructions. @@ -112,19 +109,20 @@ static inline bool DoInvoke(Thread* self, ShadowFrame& shadow_frame, const Instr const uint32_t vregC = (is_range) ? inst->VRegC_3rc() : inst->VRegC_35c(); Object* receiver = (type == kStatic) ? nullptr : shadow_frame.GetVRegReference(vregC); mirror::ArtMethod* sf_method = shadow_frame.GetMethod(); - ArtMethod* const method = FindMethodFromCode<type, do_access_check>( + ArtMethod* const called_method = FindMethodFromCode<type, do_access_check>( method_idx, &receiver, &sf_method, self); // The shadow frame should already be pushed, so we don't need to update it. - if (UNLIKELY(method == nullptr)) { + if (UNLIKELY(called_method == nullptr)) { CHECK(self->IsExceptionPending()); result->SetJ(0); return false; - } else if (UNLIKELY(method->IsAbstract())) { - ThrowAbstractMethodError(method); + } else if (UNLIKELY(called_method->IsAbstract())) { + ThrowAbstractMethodError(called_method); result->SetJ(0); return false; } else { - return DoCall<is_range, do_access_check>(method, self, shadow_frame, inst, inst_data, result); + return DoCall<is_range, do_access_check>(called_method, self, shadow_frame, inst, inst_data, + result); } } @@ -144,18 +142,18 @@ static inline bool DoInvokeVirtualQuick(Thread* self, ShadowFrame& shadow_frame, } const uint32_t vtable_idx = (is_range) ? inst->VRegB_3rc() : inst->VRegB_35c(); CHECK(receiver->GetClass()->ShouldHaveEmbeddedImtAndVTable()); - ArtMethod* const method = receiver->GetClass()->GetEmbeddedVTableEntry(vtable_idx); - if (UNLIKELY(method == nullptr)) { + ArtMethod* const called_method = receiver->GetClass()->GetEmbeddedVTableEntry(vtable_idx); + if (UNLIKELY(called_method == nullptr)) { CHECK(self->IsExceptionPending()); result->SetJ(0); return false; - } else if (UNLIKELY(method->IsAbstract())) { - ThrowAbstractMethodError(method); + } else if (UNLIKELY(called_method->IsAbstract())) { + ThrowAbstractMethodError(called_method); result->SetJ(0); return false; } else { // No need to check since we've been quickened. - return DoCall<is_range, false>(method, self, shadow_frame, inst, inst_data, result); + return DoCall<is_range, false>(called_method, self, shadow_frame, inst, inst_data, result); } } @@ -351,12 +349,12 @@ uint32_t FindNextInstructionFollowingException(Thread* self, ShadowFrame& shadow uint32_t dex_pc, const instrumentation::Instrumentation* instrumentation) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); -void UnexpectedOpcode(const Instruction* inst, MethodHelper& mh) +void UnexpectedOpcode(const Instruction* inst, const ShadowFrame& shadow_frame) __attribute__((cold, noreturn)) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); static inline void TraceExecution(const ShadowFrame& shadow_frame, const Instruction* inst, - const uint32_t dex_pc, MethodHelper& mh) + const uint32_t dex_pc) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { constexpr bool kTracing = false; if (kTracing) { @@ -364,7 +362,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.GetMethod()->GetDexFile()) << "\n"; + << inst->DumpString(shadow_frame.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 6350c56cf9..c332a7b598 100644 --- a/runtime/interpreter/interpreter_goto_table_impl.cc +++ b/runtime/interpreter/interpreter_goto_table_impl.cc @@ -26,7 +26,6 @@ namespace interpreter { // - "inst_data" : the current instruction's first 16 bits. // - "dex_pc": the current pc. // - "shadow_frame": the current shadow frame. -// - "mh": the current MethodHelper. // - "currentHandlersTable": the current table of pointer to each instruction handler. // Advance to the next instruction and updates interpreter state. @@ -36,7 +35,7 @@ namespace interpreter { inst = inst->RelativeAt(disp); \ dex_pc = static_cast<uint32_t>(static_cast<int32_t>(dex_pc) + disp); \ shadow_frame.SetDexPC(dex_pc); \ - TraceExecution(shadow_frame, inst, dex_pc, mh); \ + TraceExecution(shadow_frame, inst, dex_pc); \ inst_data = inst->Fetch16(0); \ goto *currentHandlersTable[inst->Opcode(inst_data)]; \ } while (false) @@ -59,6 +58,7 @@ namespace interpreter { do { \ if (kIsDebugBuild) { \ LOG(FATAL) << "We should not be here !"; \ + UNREACHABLE(); \ } \ } while (false) @@ -111,8 +111,8 @@ namespace interpreter { * */ template<bool do_access_check, bool transaction_active> -JValue ExecuteGotoImpl(Thread* self, MethodHelper& mh, const DexFile::CodeItem* code_item, - ShadowFrame& shadow_frame, JValue result_register) { +JValue ExecuteGotoImpl(Thread* self, const DexFile::CodeItem* code_item, ShadowFrame& shadow_frame, + JValue result_register) { // Define handler tables: // - The main handler table contains execution handlers for each instruction. // - The alternative handler table contains prelude handlers which check for thread suspend and @@ -2279,103 +2279,103 @@ JValue ExecuteGotoImpl(Thread* self, MethodHelper& mh, const DexFile::CodeItem* HANDLE_INSTRUCTION_END(); HANDLE_INSTRUCTION_START(UNUSED_3E) - UnexpectedOpcode(inst, mh); + UnexpectedOpcode(inst, shadow_frame); HANDLE_INSTRUCTION_END(); HANDLE_INSTRUCTION_START(UNUSED_3F) - UnexpectedOpcode(inst, mh); + UnexpectedOpcode(inst, shadow_frame); HANDLE_INSTRUCTION_END(); HANDLE_INSTRUCTION_START(UNUSED_40) - UnexpectedOpcode(inst, mh); + UnexpectedOpcode(inst, shadow_frame); HANDLE_INSTRUCTION_END(); HANDLE_INSTRUCTION_START(UNUSED_41) - UnexpectedOpcode(inst, mh); + UnexpectedOpcode(inst, shadow_frame); HANDLE_INSTRUCTION_END(); HANDLE_INSTRUCTION_START(UNUSED_42) - UnexpectedOpcode(inst, mh); + UnexpectedOpcode(inst, shadow_frame); HANDLE_INSTRUCTION_END(); HANDLE_INSTRUCTION_START(UNUSED_43) - UnexpectedOpcode(inst, mh); + UnexpectedOpcode(inst, shadow_frame); HANDLE_INSTRUCTION_END(); HANDLE_INSTRUCTION_START(UNUSED_79) - UnexpectedOpcode(inst, mh); + UnexpectedOpcode(inst, shadow_frame); HANDLE_INSTRUCTION_END(); HANDLE_INSTRUCTION_START(UNUSED_7A) - UnexpectedOpcode(inst, mh); + UnexpectedOpcode(inst, shadow_frame); HANDLE_INSTRUCTION_END(); HANDLE_INSTRUCTION_START(UNUSED_EF) - UnexpectedOpcode(inst, mh); + UnexpectedOpcode(inst, shadow_frame); HANDLE_INSTRUCTION_END(); HANDLE_INSTRUCTION_START(UNUSED_F0) - UnexpectedOpcode(inst, mh); + UnexpectedOpcode(inst, shadow_frame); HANDLE_INSTRUCTION_END(); HANDLE_INSTRUCTION_START(UNUSED_F1) - UnexpectedOpcode(inst, mh); + UnexpectedOpcode(inst, shadow_frame); HANDLE_INSTRUCTION_END(); HANDLE_INSTRUCTION_START(UNUSED_F2) - UnexpectedOpcode(inst, mh); + UnexpectedOpcode(inst, shadow_frame); HANDLE_INSTRUCTION_END(); HANDLE_INSTRUCTION_START(UNUSED_F3) - UnexpectedOpcode(inst, mh); + UnexpectedOpcode(inst, shadow_frame); HANDLE_INSTRUCTION_END(); HANDLE_INSTRUCTION_START(UNUSED_F4) - UnexpectedOpcode(inst, mh); + UnexpectedOpcode(inst, shadow_frame); HANDLE_INSTRUCTION_END(); HANDLE_INSTRUCTION_START(UNUSED_F5) - UnexpectedOpcode(inst, mh); + UnexpectedOpcode(inst, shadow_frame); HANDLE_INSTRUCTION_END(); HANDLE_INSTRUCTION_START(UNUSED_F6) - UnexpectedOpcode(inst, mh); + UnexpectedOpcode(inst, shadow_frame); HANDLE_INSTRUCTION_END(); HANDLE_INSTRUCTION_START(UNUSED_F7) - UnexpectedOpcode(inst, mh); + UnexpectedOpcode(inst, shadow_frame); HANDLE_INSTRUCTION_END(); HANDLE_INSTRUCTION_START(UNUSED_F8) - UnexpectedOpcode(inst, mh); + UnexpectedOpcode(inst, shadow_frame); HANDLE_INSTRUCTION_END(); HANDLE_INSTRUCTION_START(UNUSED_F9) - UnexpectedOpcode(inst, mh); + UnexpectedOpcode(inst, shadow_frame); HANDLE_INSTRUCTION_END(); HANDLE_INSTRUCTION_START(UNUSED_FA) - UnexpectedOpcode(inst, mh); + UnexpectedOpcode(inst, shadow_frame); HANDLE_INSTRUCTION_END(); HANDLE_INSTRUCTION_START(UNUSED_FB) - UnexpectedOpcode(inst, mh); + UnexpectedOpcode(inst, shadow_frame); HANDLE_INSTRUCTION_END(); HANDLE_INSTRUCTION_START(UNUSED_FC) - UnexpectedOpcode(inst, mh); + UnexpectedOpcode(inst, shadow_frame); HANDLE_INSTRUCTION_END(); HANDLE_INSTRUCTION_START(UNUSED_FD) - UnexpectedOpcode(inst, mh); + UnexpectedOpcode(inst, shadow_frame); HANDLE_INSTRUCTION_END(); HANDLE_INSTRUCTION_START(UNUSED_FE) - UnexpectedOpcode(inst, mh); + UnexpectedOpcode(inst, shadow_frame); HANDLE_INSTRUCTION_END(); HANDLE_INSTRUCTION_START(UNUSED_FF) - UnexpectedOpcode(inst, mh); + UnexpectedOpcode(inst, shadow_frame); HANDLE_INSTRUCTION_END(); exception_pending_label: { @@ -2430,21 +2430,17 @@ JValue ExecuteGotoImpl(Thread* self, MethodHelper& mh, const DexFile::CodeItem* // Explicit definitions of ExecuteGotoImpl. template SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) HOT_ATTR -JValue ExecuteGotoImpl<true, false>(Thread* self, MethodHelper& mh, - const DexFile::CodeItem* code_item, +JValue ExecuteGotoImpl<true, false>(Thread* self, const DexFile::CodeItem* code_item, ShadowFrame& shadow_frame, JValue result_register); template SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) HOT_ATTR -JValue ExecuteGotoImpl<false, false>(Thread* self, MethodHelper& mh, - const DexFile::CodeItem* code_item, +JValue ExecuteGotoImpl<false, false>(Thread* self, const DexFile::CodeItem* code_item, ShadowFrame& shadow_frame, JValue result_register); template SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) -JValue ExecuteGotoImpl<true, true>(Thread* self, MethodHelper& mh, - const DexFile::CodeItem* code_item, - ShadowFrame& shadow_frame, JValue result_register); +JValue ExecuteGotoImpl<true, true>(Thread* self, const DexFile::CodeItem* code_item, + ShadowFrame& shadow_frame, JValue result_register); template SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) -JValue ExecuteGotoImpl<false, true>(Thread* self, MethodHelper& mh, - const DexFile::CodeItem* code_item, - ShadowFrame& shadow_frame, JValue result_register); +JValue ExecuteGotoImpl<false, true>(Thread* self, const DexFile::CodeItem* code_item, + ShadowFrame& shadow_frame, JValue result_register); } // namespace interpreter } // namespace art diff --git a/runtime/interpreter/interpreter_switch_impl.cc b/runtime/interpreter/interpreter_switch_impl.cc index 1b6f53e6c6..f9bbfa17b9 100644 --- a/runtime/interpreter/interpreter_switch_impl.cc +++ b/runtime/interpreter/interpreter_switch_impl.cc @@ -57,7 +57,7 @@ namespace interpreter { } while (false) template<bool do_access_check, bool transaction_active> -JValue ExecuteSwitchImpl(Thread* self, MethodHelper& mh, const DexFile::CodeItem* code_item, +JValue ExecuteSwitchImpl(Thread* self, const DexFile::CodeItem* code_item, ShadowFrame& shadow_frame, JValue result_register) { bool do_assignability_check = do_access_check; if (UNLIKELY(!shadow_frame.HasReferenceArray())) { @@ -82,7 +82,7 @@ JValue ExecuteSwitchImpl(Thread* self, MethodHelper& mh, const DexFile::CodeItem while (true) { dex_pc = inst->GetDexPc(insns); shadow_frame.SetDexPC(dex_pc); - TraceExecution(shadow_frame, inst, dex_pc, mh); + TraceExecution(shadow_frame, inst, dex_pc); inst_data = inst->Fetch16(0); switch (inst->Opcode(inst_data)) { case Instruction::NOP: @@ -2140,27 +2140,23 @@ JValue ExecuteSwitchImpl(Thread* self, MethodHelper& mh, const DexFile::CodeItem case Instruction::UNUSED_EF ... Instruction::UNUSED_FF: case Instruction::UNUSED_79: case Instruction::UNUSED_7A: - UnexpectedOpcode(inst, mh); + UnexpectedOpcode(inst, shadow_frame); } } } // NOLINT(readability/fn_size) // Explicit definitions of ExecuteSwitchImpl. template SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) HOT_ATTR -JValue ExecuteSwitchImpl<true, false>(Thread* self, MethodHelper& mh, - const DexFile::CodeItem* code_item, +JValue ExecuteSwitchImpl<true, false>(Thread* self, const DexFile::CodeItem* code_item, ShadowFrame& shadow_frame, JValue result_register); template SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) HOT_ATTR -JValue ExecuteSwitchImpl<false, false>(Thread* self, MethodHelper& mh, - const DexFile::CodeItem* code_item, +JValue ExecuteSwitchImpl<false, false>(Thread* self, const DexFile::CodeItem* code_item, ShadowFrame& shadow_frame, JValue result_register); template SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) -JValue ExecuteSwitchImpl<true, true>(Thread* self, MethodHelper& mh, - const DexFile::CodeItem* code_item, +JValue ExecuteSwitchImpl<true, true>(Thread* self, const DexFile::CodeItem* code_item, ShadowFrame& shadow_frame, JValue result_register); template SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) -JValue ExecuteSwitchImpl<false, true>(Thread* self, MethodHelper& mh, - const DexFile::CodeItem* code_item, +JValue ExecuteSwitchImpl<false, true>(Thread* self, const DexFile::CodeItem* code_item, ShadowFrame& shadow_frame, JValue result_register); } // namespace interpreter diff --git a/runtime/java_vm_ext.cc b/runtime/java_vm_ext.cc index a5abce6ab1..5d04faccb5 100644 --- a/runtime/java_vm_ext.cc +++ b/runtime/java_vm_ext.cc @@ -756,6 +756,11 @@ void JavaVMExt::SweepJniWeakGlobals(IsMarkedCallback* callback, void* arg) { } } +void JavaVMExt::TrimGlobals() { + WriterMutexLock mu(Thread::Current(), globals_lock_); + globals_.Trim(); +} + void JavaVMExt::VisitRoots(RootCallback* callback, void* arg) { Thread* self = Thread::Current(); { diff --git a/runtime/java_vm_ext.h b/runtime/java_vm_ext.h index 2957ba3fae..749b9fb6c0 100644 --- a/runtime/java_vm_ext.h +++ b/runtime/java_vm_ext.h @@ -131,6 +131,9 @@ class JavaVMExt : public JavaVM { return unchecked_functions_; } + void TrimGlobals() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) + LOCKS_EXCLUDED(globals_lock_); + private: Runtime* const runtime_; diff --git a/runtime/jni_internal.cc b/runtime/jni_internal.cc index 1dcfcabf9d..4797e696d8 100644 --- a/runtime/jni_internal.cc +++ b/runtime/jni_internal.cc @@ -566,7 +566,8 @@ class JNI { return soa.AddLocalReference<jobject>(decoded_obj); } - static void DeleteLocalRef(JNIEnv* env, jobject obj) { + static void DeleteLocalRef(JNIEnv* env, jobject obj) + SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { if (obj == nullptr) { return; } diff --git a/runtime/method_helper-inl.h b/runtime/method_helper-inl.h deleted file mode 100644 index 7a7949e0fa..0000000000 --- a/runtime/method_helper-inl.h +++ /dev/null @@ -1,62 +0,0 @@ -/* - * Copyright (C) 2011 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef ART_RUNTIME_METHOD_HELPER_INL_H_ -#define ART_RUNTIME_METHOD_HELPER_INL_H_ - -#include "method_helper.h" - -#include "class_linker.h" -#include "mirror/object_array.h" -#include "runtime.h" -#include "thread-inl.h" - -namespace art { - -template <template <class T> class HandleKind> -template <template <class T2> class HandleKind2> -inline bool MethodHelperT<HandleKind>::HasSameNameAndSignature(MethodHelperT<HandleKind2>* other) { - 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->GetMethod()->GetDexMethodIndex()); - return mid.name_idx_ == other_mid.name_idx_ && mid.proto_idx_ == other_mid.proto_idx_; - } - const DexFile* other_dex_file = other->method_->GetDexFile(); - const DexFile::MethodId& other_mid = - 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); -} - -template <template <class T> class HandleKind> -inline mirror::Class* MethodHelperT<HandleKind>::GetClassFromTypeIdx(uint16_t type_idx, - bool resolve) { - mirror::ArtMethod* method = GetMethod(); - mirror::Class* type = method->GetDexCacheResolvedType(type_idx); - if (type == nullptr && resolve) { - type = Runtime::Current()->GetClassLinker()->ResolveType(type_idx, method); - CHECK(type != nullptr || Thread::Current()->IsExceptionPending()); - } - return type; -} - -} // namespace art - -#endif // ART_RUNTIME_METHOD_HELPER_INL_H_ diff --git a/runtime/method_helper.cc b/runtime/method_helper.cc deleted file mode 100644 index 81e17943ec..0000000000 --- a/runtime/method_helper.cc +++ /dev/null @@ -1,164 +0,0 @@ -/* - * Copyright (C) 2011 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "method_helper-inl.h" - -#include "class_linker.h" -#include "dex_file-inl.h" -#include "handle_scope-inl.h" -#include "mirror/art_method-inl.h" -#include "mirror/dex_cache.h" -#include "runtime.h" - -namespace art { - -template <template <class T> class HandleKind> -template <template <class T2> class HandleKind2> -bool MethodHelperT<HandleKind>::HasSameSignatureWithDifferentClassLoaders(Thread* self, - MethodHelperT<HandleKind2>* other) { - { - StackHandleScope<1> hs(self); - Handle<mirror::Class> return_type(hs.NewHandle(GetMethod()->GetReturnType())); - if (UNLIKELY(other->GetMethod()->GetReturnType() != return_type.Get())) { - return false; - } - } - 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)) { - return types->Size() == 0; - } - uint32_t num_types = types->Size(); - if (UNLIKELY(num_types != other_types->Size())) { - return false; - } - for (uint32_t i = 0; i < num_types; ++i) { - mirror::Class* param_type = GetClassFromTypeIdx(types->GetTypeItem(i).type_idx_); - mirror::Class* other_param_type = - other->GetClassFromTypeIdx(other_types->GetTypeItem(i).type_idx_); - if (UNLIKELY(param_type != other_param_type)) { - return false; - } - } - return true; -} - -template <template <class T> class HandleKind> -uint32_t MethodHelperT<HandleKind>::FindDexMethodIndexInOtherDexFile(const DexFile& other_dexfile) - SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - 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::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 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); - 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); - if (other_mid != nullptr) { - return other_dexfile.GetIndexForMethodId(*other_mid); - } - } - } - } - } - } - return DexFile::kDexNoIndex; -} - -template <template <typename> class HandleKind> -uint32_t MethodHelperT<HandleKind>::FindDexMethodIndexInOtherDexFile( - const DexFile& other_dexfile, uint32_t name_and_signature_idx) - SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - 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 dex_method_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) { - const DexFile::TypeId* other_type_id = - other_dexfile.FindTypeId(other_dexfile.GetIndexForStringId(*other_descriptor)); - if (other_type_id != nullptr) { - const DexFile::MethodId* other_mid = other_dexfile.FindMethodId( - *other_type_id, other_dexfile.GetStringId(name_and_sig_mid.name_idx_), - other_dexfile.GetProtoId(name_and_sig_mid.proto_idx_)); - if (other_mid != nullptr) { - return other_dexfile.GetIndexForMethodId(*other_mid); - } - } - } - return DexFile::kDexNoIndex; -} - -// Instantiate methods. -template -uint32_t MethodHelperT<Handle>::FindDexMethodIndexInOtherDexFile(const DexFile& other_dexfile); -template -uint32_t MethodHelperT<MutableHandle>::FindDexMethodIndexInOtherDexFile( - const DexFile& other_dexfile); - -template -uint32_t MethodHelperT<Handle>::FindDexMethodIndexInOtherDexFile(const DexFile& other_dexfile, - uint32_t name_and_signature_idx); -template -uint32_t MethodHelperT<MutableHandle>::FindDexMethodIndexInOtherDexFile( - const DexFile& other_dexfile, uint32_t name_and_signature_idx); - -template -bool MethodHelperT<Handle>::HasSameSignatureWithDifferentClassLoaders<Handle>(Thread* self, - MethodHelperT<Handle>* other); - -template -bool MethodHelperT<Handle>::HasSameSignatureWithDifferentClassLoaders<MutableHandle>(Thread* self, - MethodHelperT<MutableHandle>* other); - -template -bool MethodHelperT<MutableHandle>::HasSameSignatureWithDifferentClassLoaders<Handle>(Thread* self, - MethodHelperT<Handle>* other); - -template -bool MethodHelperT<MutableHandle>::HasSameSignatureWithDifferentClassLoaders<MutableHandle>( - Thread* self, MethodHelperT<MutableHandle>* other); - -} // namespace art diff --git a/runtime/method_helper.h b/runtime/method_helper.h deleted file mode 100644 index dc305d57b7..0000000000 --- a/runtime/method_helper.h +++ /dev/null @@ -1,160 +0,0 @@ -/* - * Copyright (C) 2011 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef ART_RUNTIME_METHOD_HELPER_H_ -#define ART_RUNTIME_METHOD_HELPER_H_ - -#include "base/macros.h" -#include "handle.h" -#include "mirror/art_method.h" -#include "primitive.h" - -namespace art { - -template <template <class T> class HandleKind> -class MethodHelperT { - public: - explicit MethodHelperT(HandleKind<mirror::ArtMethod> m) - SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) : method_(m), shorty_(nullptr), shorty_len_(0) { - } - - mirror::ArtMethod* GetMethod() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - return method_->GetInterfaceMethodIfProxy(); - } - - // GetMethod() != Get() for proxy methods. - mirror::ArtMethod* Get() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - return method_.Get(); - } - - const char* GetShorty() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - const char* result = shorty_; - if (result == nullptr) { - result = method_->GetShorty(&shorty_len_); - shorty_ = result; - } - return result; - } - - uint32_t GetShortyLength() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - if (shorty_ == nullptr) { - GetShorty(); - } - return shorty_len_; - } - - // Counts the number of references in the parameter list of the corresponding method. - // Note: Thus does _not_ include "this" for non-static methods. - uint32_t GetNumberOfReferenceArgsWithoutReceiver() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - const char* shorty = GetShorty(); - uint32_t refs = 0; - for (uint32_t i = 1; i < shorty_len_ ; ++i) { - if (shorty[i] == 'L') { - refs++; - } - } - - return refs; - } - - 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 (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 (GetMethod()->IsStatic()) { - param++; // 0th argument must skip return value at start of the shorty - } else if (param == 0) { - return Primitive::kPrimNot; - } - return Primitive::GetType(GetShorty()[param]); - } - - // Is the specified parameter a long or double, where parameter 0 is 'this' for instance methods. - bool IsParamALongOrDouble(size_t param) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - Primitive::Type type = GetParamPrimitiveType(param); - return type == Primitive::kPrimLong || type == Primitive::kPrimDouble; - } - - // Is the specified parameter a reference, where parameter 0 is 'this' for instance methods. - bool IsParamAReference(size_t param) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - return GetParamPrimitiveType(param) == Primitive::kPrimNot; - } - - template <template <class T> class HandleKind2> - ALWAYS_INLINE bool HasSameNameAndSignature(MethodHelperT<HandleKind2>* other) - SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); - - template <template <class T> class HandleKind2> - bool HasSameSignatureWithDifferentClassLoaders(Thread* self, MethodHelperT<HandleKind2>* other) - SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); - - mirror::Class* GetClassFromTypeIdx(uint16_t type_idx, bool resolve = true) - SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); - - uint32_t FindDexMethodIndexInOtherDexFile(const DexFile& other_dexfile) - SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); - - // The name_and_signature_idx MUST point to a MethodId with the same name and signature in the - // other_dexfile, such as the method index used to resolve this method in the other_dexfile. - uint32_t FindDexMethodIndexInOtherDexFile(const DexFile& other_dexfile, - uint32_t name_and_signature_idx) - SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); - - protected: - HandleKind<mirror::ArtMethod> method_; - - const char* shorty_; - uint32_t shorty_len_; - - private: - template <template <class T2> class HandleKind2> friend class MethodHelperT; - - DISALLOW_COPY_AND_ASSIGN(MethodHelperT); -}; - -class MethodHelper : public MethodHelperT<Handle> { - using MethodHelperT<Handle>::MethodHelperT; - private: - DISALLOW_COPY_AND_ASSIGN(MethodHelper); -}; - -class MutableMethodHelper : public MethodHelperT<MutableHandle> { - using MethodHelperT<MutableHandle>::MethodHelperT; - public: - void ChangeMethod(mirror::ArtMethod* new_m) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - DCHECK(new_m != nullptr); - SetMethod(new_m); - shorty_ = nullptr; - } - - private: - // 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_) { - method_.Assign(method); - } - - DISALLOW_COPY_AND_ASSIGN(MutableMethodHelper); -}; - -} // namespace art - -#endif // ART_RUNTIME_METHOD_HELPER_H_ diff --git a/runtime/mirror/art_field-inl.h b/runtime/mirror/art_field-inl.h index 03425cc300..2b406bdd91 100644 --- a/runtime/mirror/art_field-inl.h +++ b/runtime/mirror/art_field-inl.h @@ -20,6 +20,7 @@ #include "art_field.h" #include "base/logging.h" +#include "class_linker.h" #include "dex_cache.h" #include "gc/accounting/card_table-inl.h" #include "jvalue.h" @@ -289,6 +290,22 @@ inline bool ArtField::IsPrimitiveType() SHARED_LOCKS_REQUIRED(Locks::mutator_loc return GetTypeAsPrimitiveType() != Primitive::kPrimNot; } +inline Class* ArtField::GetType(bool resolve) { + uint32_t field_index = GetDexFieldIndex(); + if (UNLIKELY(GetDeclaringClass()->IsProxyClass())) { + return Runtime::Current()->GetClassLinker()->FindSystemClass(Thread::Current(), + GetTypeDescriptor()); + } + const DexFile* dex_file = GetDexFile(); + const DexFile::FieldId& field_id = dex_file->GetFieldId(field_index); + mirror::Class* type = GetDexCache()->GetResolvedType(field_id.type_idx_); + if (resolve && (type == nullptr)) { + type = Runtime::Current()->GetClassLinker()->ResolveType(field_id.type_idx_, this); + CHECK(type != nullptr || Thread::Current()->IsExceptionPending()); + } + return type; +} + inline size_t ArtField::FieldSize() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { return Primitive::ComponentSize(GetTypeAsPrimitiveType()); } diff --git a/runtime/mirror/art_field.h b/runtime/mirror/art_field.h index 50299b670a..a1d8844664 100644 --- a/runtime/mirror/art_field.h +++ b/runtime/mirror/art_field.h @@ -161,6 +161,8 @@ class MANAGED ArtField FINAL : public Object { bool IsPrimitiveType() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); + Class* GetType(bool resolve) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); + size_t FieldSize() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); mirror::DexCache* GetDexCache() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); diff --git a/runtime/mirror/art_method-inl.h b/runtime/mirror/art_method-inl.h index 22d55e2a39..c29276a238 100644 --- a/runtime/mirror/art_method-inl.h +++ b/runtime/mirror/art_method-inl.h @@ -24,7 +24,6 @@ #include "class_linker.h" #include "dex_cache.h" #include "dex_file.h" -#include "method_helper.h" #include "object-inl.h" #include "object_array.h" #include "oat.h" @@ -141,6 +140,15 @@ inline bool ArtMethod::HasSameDexCacheResolvedTypes(ArtMethod* other) { return GetDexCacheResolvedTypes() == other->GetDexCacheResolvedTypes(); } +inline mirror::Class* ArtMethod::GetClassFromTypeIndex(uint16_t type_idx, bool resolve) { + mirror::Class* type = GetDexCacheResolvedType(type_idx); + if (type == nullptr && resolve) { + type = Runtime::Current()->GetClassLinker()->ResolveType(type_idx, this); + CHECK(type != nullptr || Thread::Current()->IsExceptionPending()); + } + return type; +} + inline uint32_t ArtMethod::GetCodeSize() { DCHECK(!IsRuntimeMethod() && !IsProxyMethod()) << PrettyMethod(this); const void* code = EntryPointToCodePointer(GetEntryPointFromQuickCompiledCode()); diff --git a/runtime/mirror/art_method.cc b/runtime/mirror/art_method.cc index 4f5ca3fe5d..1729686314 100644 --- a/runtime/mirror/art_method.cc +++ b/runtime/mirror/art_method.cc @@ -29,7 +29,6 @@ #include "interpreter/interpreter.h" #include "jni_internal.h" #include "mapping_table.h" -#include "method_helper-inl.h" #include "object_array-inl.h" #include "object_array.h" #include "object-inl.h" @@ -93,7 +92,7 @@ InvokeType ArtMethod::GetInvokeType() { void ArtMethod::SetClass(Class* java_lang_reflect_ArtMethod) { CHECK(java_lang_reflect_ArtMethod_.IsNull()); - CHECK(java_lang_reflect_ArtMethod != NULL); + CHECK(java_lang_reflect_ArtMethod != nullptr); java_lang_reflect_ArtMethod_ = GcRoot<Class>(java_lang_reflect_ArtMethod); } @@ -116,14 +115,31 @@ size_t ArtMethod::NumArgRegisters(const StringPiece& shorty) { return num_registers; } +static bool HasSameNameAndSignature(ArtMethod* method1, ArtMethod* method2) + SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { + ScopedAssertNoThreadSuspension ants(Thread::Current(), "HasSameNameAndSignature"); + const DexFile* dex_file = method1->GetDexFile(); + const DexFile::MethodId& mid = dex_file->GetMethodId(method1->GetDexMethodIndex()); + if (method1->GetDexCache() == method2->GetDexCache()) { + const DexFile::MethodId& mid2 = dex_file->GetMethodId(method2->GetDexMethodIndex()); + return mid.name_idx_ == mid2.name_idx_ && mid.proto_idx_ == mid2.proto_idx_; + } + const DexFile* dex_file2 = method2->GetDexFile(); + const DexFile::MethodId& mid2 = dex_file2->GetMethodId(method2->GetDexMethodIndex()); + if (!DexFileStringEquals(dex_file, mid.name_idx_, dex_file2, mid2.name_idx_)) { + return false; // Name mismatch. + } + return dex_file->GetMethodSignature(mid) == dex_file2->GetMethodSignature(mid2); +} + ArtMethod* ArtMethod::FindOverriddenMethod() { if (IsStatic()) { - return NULL; + return nullptr; } Class* declaring_class = GetDeclaringClass(); Class* super_class = declaring_class->GetSuperClass(); uint16_t method_index = GetMethodIndex(); - ArtMethod* result = NULL; + ArtMethod* result = nullptr; // Did this method override a super class method? If so load the result from the super class' // vtable if (super_class->HasVTable() && method_index < super_class->GetVTableLength()) { @@ -135,16 +151,13 @@ ArtMethod* ArtMethod::FindOverriddenMethod() { CHECK_EQ(result, Runtime::Current()->GetClassLinker()->FindMethodForProxy(GetDeclaringClass(), this)); } else { - StackHandleScope<2> hs(Thread::Current()); - MethodHelper mh(hs.NewHandle(this)); - MutableMethodHelper interface_mh(hs.NewHandle<mirror::ArtMethod>(nullptr)); IfTable* iftable = GetDeclaringClass()->GetIfTable(); - for (size_t i = 0; i < iftable->Count() && result == NULL; i++) { + for (size_t i = 0; i < iftable->Count() && result == nullptr; i++) { Class* interface = iftable->GetInterface(i); for (size_t j = 0; j < interface->NumVirtualMethods(); ++j) { - interface_mh.ChangeMethod(interface->GetVirtualMethod(j)); - if (mh.HasSameNameAndSignature(&interface_mh)) { - result = interface_mh.GetMethod(); + mirror::ArtMethod* interface_method = interface->GetVirtualMethod(j); + if (HasSameNameAndSignature(this, interface_method)) { + result = interface_method; break; } } @@ -152,14 +165,40 @@ ArtMethod* ArtMethod::FindOverriddenMethod() { } } if (kIsDebugBuild) { - StackHandleScope<2> hs(Thread::Current()); - MethodHelper result_mh(hs.NewHandle(result)); - MethodHelper this_mh(hs.NewHandle(this)); - DCHECK(result == nullptr || this_mh.HasSameNameAndSignature(&result_mh)); + DCHECK(result == nullptr || HasSameNameAndSignature(this, result)); } return result; } +uint32_t ArtMethod::FindDexMethodIndexInOtherDexFile(const DexFile& other_dexfile, + uint32_t name_and_signature_idx) { + const DexFile* dexfile = GetDexFile(); + const uint32_t dex_method_idx = 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 dex_method_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) { + const DexFile::TypeId* other_type_id = + other_dexfile.FindTypeId(other_dexfile.GetIndexForStringId(*other_descriptor)); + if (other_type_id != nullptr) { + const DexFile::MethodId* other_mid = other_dexfile.FindMethodId( + *other_type_id, other_dexfile.GetStringId(name_and_sig_mid.name_idx_), + other_dexfile.GetProtoId(name_and_sig_mid.proto_idx_)); + if (other_mid != nullptr) { + return other_dexfile.GetIndexForMethodId(*other_mid); + } + } + } + return DexFile::kDexNoIndex; +} + uint32_t ArtMethod::ToDexPc(const uintptr_t pc, bool abort_on_failure) { if (IsPortableCompiled()) { // Portable doesn't use the machine pc, we just use dex pc instead. @@ -228,7 +267,6 @@ uintptr_t ArtMethod::ToNativeQuickPc(const uint32_t dex_pc, bool abort_on_failur 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(); @@ -248,7 +286,7 @@ uint32_t ArtMethod::FindCatchBlock(Handle<ArtMethod> h_this, Handle<Class> excep break; } // Does this catch exception type apply? - Class* iter_exception_type = mh.GetClassFromTypeIdx(iter_type_idx); + Class* iter_exception_type = h_this->GetClassFromTypeIndex(iter_type_idx, true); if (UNLIKELY(iter_exception_type == nullptr)) { // Now have a NoClassDefFoundError as exception. Ignore in case the exception class was // removed by a pro-guard like tool. @@ -420,7 +458,7 @@ void ArtMethod::Invoke(Thread* self, uint32_t* args, uint32_t args_size, JValue* } } else { LOG(INFO) << "Not invoking '" << PrettyMethod(this) << "' code=null"; - if (result != NULL) { + if (result != nullptr) { result->SetJ(0); } } @@ -430,6 +468,21 @@ void ArtMethod::Invoke(Thread* self, uint32_t* args, uint32_t args_size, JValue* self->PopManagedStackFragment(fragment); } +// Counts the number of references in the parameter list of the corresponding method. +// Note: Thus does _not_ include "this" for non-static methods. +static uint32_t GetNumberOfReferenceArgsWithoutReceiver(ArtMethod* method) + SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { + uint32_t shorty_len; + const char* shorty = method->GetShorty(&shorty_len); + uint32_t refs = 0; + for (uint32_t i = 1; i < shorty_len ; ++i) { + if (shorty[i] == 'L') { + refs++; + } + } + return refs; +} + QuickMethodFrameInfo ArtMethod::GetQuickFrameInfo() { if (UNLIKELY(IsPortableCompiled())) { // Portable compiled dex bytecode or jni stub. @@ -472,8 +525,7 @@ QuickMethodFrameInfo ArtMethod::GetQuickFrameInfo() { // Generic JNI frame. DCHECK(IsNative()); StackHandleScope<1> hs(Thread::Current()); - uint32_t handle_refs = - MethodHelper(hs.NewHandle(this)).GetNumberOfReferenceArgsWithoutReceiver() + 1; + uint32_t handle_refs = GetNumberOfReferenceArgsWithoutReceiver(this) + 1; size_t scope_size = HandleScope::SizeOf(handle_refs); QuickMethodFrameInfo callee_info = runtime->GetCalleeSaveMethodFrameInfo(Runtime::kRefsAndArgs); @@ -493,7 +545,7 @@ QuickMethodFrameInfo ArtMethod::GetQuickFrameInfo() { void ArtMethod::RegisterNative(const void* native_method, bool is_fast) { CHECK(IsNative()) << PrettyMethod(this); CHECK(!IsFastNative()) << PrettyMethod(this); - CHECK(native_method != NULL) << PrettyMethod(this); + CHECK(native_method != nullptr) << PrettyMethod(this); if (is_fast) { SetAccessFlags(GetAccessFlags() | kAccFastNative); } diff --git a/runtime/mirror/art_method.h b/runtime/mirror/art_method.h index da494e0ec9..210794488d 100644 --- a/runtime/mirror/art_method.h +++ b/runtime/mirror/art_method.h @@ -32,15 +32,14 @@ namespace art { struct ArtMethodOffsets; struct ConstructorMethodOffsets; union JValue; -class MethodHelper; class ScopedObjectAccessAlreadyRunnable; class StringPiece; class ShadowFrame; namespace mirror { -typedef void (EntryPointFromInterpreter)(Thread* self, MethodHelper* mh, - const DexFile::CodeItem* code_item, ShadowFrame* shadow_frame, JValue* result); +typedef void (EntryPointFromInterpreter)(Thread* self, const DexFile::CodeItem* code_item, + ShadowFrame* shadow_frame, JValue* result); #define ART_METHOD_HAS_PADDING_FIELD_ON_64_BIT @@ -238,9 +237,21 @@ class MANAGED ArtMethod FINAL : public Object { bool HasSameDexCacheResolvedTypes(ObjectArray<Class>* other_cache) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); - // Find the method that this method overrides + // Get the Class* from the type index into this method's dex cache. + mirror::Class* GetClassFromTypeIndex(uint16_t type_idx, bool resolve) + SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); + + // Find the method that this method overrides. ArtMethod* FindOverriddenMethod() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); + // Find the method index for this method within other_dexfile. If this method isn't present then + // return DexFile::kDexNoIndex. The name_and_signature_idx MUST refer to a MethodId with the same + // name and signature in the other_dexfile, such as the method index used to resolve this method + // in the other_dexfile. + uint32_t FindDexMethodIndexInOtherDexFile(const DexFile& other_dexfile, + uint32_t name_and_signature_idx) + 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_); diff --git a/runtime/mirror/class-inl.h b/runtime/mirror/class-inl.h index 599f178cbf..1662ebfe82 100644 --- a/runtime/mirror/class-inl.h +++ b/runtime/mirror/class-inl.h @@ -575,6 +575,10 @@ inline Object* Class::Alloc(Thread* self, gc::AllocatorType allocator_type) { allocator_type, VoidFunctor()); if (add_finalizer && LIKELY(obj != nullptr)) { heap->AddFinalizerReference(self, &obj); + if (UNLIKELY(self->IsExceptionPending())) { + // Failed to allocate finalizer reference, it means that the whole allocation failed. + obj = nullptr; + } } return obj; } diff --git a/runtime/mirror/class.cc b/runtime/mirror/class.cc index 566505911b..bd3bfbf9fe 100644 --- a/runtime/mirror/class.cc +++ b/runtime/mirror/class.cc @@ -149,6 +149,7 @@ void Class::SetStatus(Status new_status, Thread* self) { void Class::SetDexCache(DexCache* new_dex_cache) { SetFieldObject<false>(OFFSET_OF_OBJECT_MEMBER(Class, dex_cache_), new_dex_cache); + SetDexCacheStrings(new_dex_cache != nullptr ? new_dex_cache->GetStrings() : nullptr); } void Class::SetClassSize(uint32_t new_class_size) { diff --git a/runtime/mirror/class.h b/runtime/mirror/class.h index 2fc5ffb517..bd49754731 100644 --- a/runtime/mirror/class.h +++ b/runtime/mirror/class.h @@ -29,6 +29,10 @@ #include "read_barrier_option.h" #include "utils.h" +#ifndef IMT_SIZE +#error IMT_SIZE not defined +#endif + namespace art { struct ClassOffsets; @@ -58,7 +62,7 @@ class MANAGED Class FINAL : public Object { // Interface method table size. Increasing this value reduces the chance of two interface methods // colliding in the interface method table but increases the size of classes that implement // (non-marker) interfaces. - static constexpr size_t kImtSize = 64; + static constexpr size_t kImtSize = IMT_SIZE; // imtable entry embedded in class object. struct MANAGED ImTableEntry { @@ -654,6 +658,7 @@ class MANAGED Class FINAL : public Object { template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags> DexCache* GetDexCache() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); + // Also updates the dex_cache_strings_ variable from new_dex_cache. void SetDexCache(DexCache* new_dex_cache) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); ALWAYS_INLINE ObjectArray<ArtMethod>* GetDirectMethods() diff --git a/runtime/mirror/object.cc b/runtime/mirror/object.cc index fa1f226dc0..65d6adedcf 100644 --- a/runtime/mirror/object.cc +++ b/runtime/mirror/object.cc @@ -24,7 +24,6 @@ #include "class.h" #include "class-inl.h" #include "class_linker-inl.h" -#include "field_helper.h" #include "gc/accounting/card_table-inl.h" #include "gc/heap.h" #include "iftable-inl.h" @@ -202,12 +201,16 @@ void Object::CheckFieldAssignmentImpl(MemberOffset field_offset, Object* new_val if (fields != NULL) { size_t num_ifields = fields->GetLength(); for (size_t i = 0; i < num_ifields; ++i) { + StackHandleScope<1> hs(Thread::Current()); + Handle<Object> h_object(hs.NewHandle(new_value)); ArtField* field = fields->Get(i); if (field->GetOffset().Int32Value() == field_offset.Int32Value()) { CHECK_NE(field->GetTypeAsPrimitiveType(), Primitive::kPrimNot); - StackHandleScope<1> hs(Thread::Current()); - FieldHelper fh(hs.NewHandle(field)); - CHECK(fh.GetType()->IsAssignableFrom(new_value->GetClass())); + // TODO: resolve the field type for moving GC. + mirror::Class* field_type = field->GetType(!kMovingCollector); + if (field_type != nullptr) { + CHECK(field_type->IsAssignableFrom(new_value->GetClass())); + } return; } } @@ -225,9 +228,11 @@ void Object::CheckFieldAssignmentImpl(MemberOffset field_offset, Object* new_val ArtField* field = fields->Get(i); if (field->GetOffset().Int32Value() == field_offset.Int32Value()) { CHECK_NE(field->GetTypeAsPrimitiveType(), Primitive::kPrimNot); - StackHandleScope<1> hs(Thread::Current()); - FieldHelper fh(hs.NewHandle(field)); - CHECK(fh.GetType()->IsAssignableFrom(new_value->GetClass())); + // TODO: resolve the field type for moving GC. + mirror::Class* field_type = field->GetType(!kMovingCollector); + if (field_type != nullptr) { + CHECK(field_type->IsAssignableFrom(new_value->GetClass())); + } return; } } @@ -235,6 +240,7 @@ void Object::CheckFieldAssignmentImpl(MemberOffset field_offset, Object* new_val } LOG(FATAL) << "Failed to find field for assignment to " << reinterpret_cast<void*>(this) << " of type " << PrettyDescriptor(c) << " at offset " << field_offset; + UNREACHABLE(); } } // namespace mirror diff --git a/runtime/mirror/object_test.cc b/runtime/mirror/object_test.cc index 4402031ef1..9d789cd0cc 100644 --- a/runtime/mirror/object_test.cc +++ b/runtime/mirror/object_test.cc @@ -34,7 +34,6 @@ #include "gc/heap.h" #include "handle_scope-inl.h" #include "iftable-inl.h" -#include "method_helper-inl.h" #include "object-inl.h" #include "object_array-inl.h" #include "scoped_thread_state_change.h" @@ -528,26 +527,6 @@ TEST_F(ObjectTest, DescriptorCompare) { EXPECT_STREQ(m3_2->GetName(), "m3"); ArtMethod* m4_2 = klass2->GetVirtualMethod(3); EXPECT_STREQ(m4_2->GetName(), "m4"); - - MutableMethodHelper mh(hs.NewHandle(m1_1)); - MutableMethodHelper mh2(hs.NewHandle(m1_2)); - EXPECT_TRUE(mh.HasSameNameAndSignature(&mh2)); - EXPECT_TRUE(mh2.HasSameNameAndSignature(&mh)); - - mh.ChangeMethod(m2_1); - mh2.ChangeMethod(m2_2); - EXPECT_TRUE(mh.HasSameNameAndSignature(&mh2)); - EXPECT_TRUE(mh2.HasSameNameAndSignature(&mh)); - - mh.ChangeMethod(m3_1); - mh2.ChangeMethod(m3_2); - EXPECT_TRUE(mh.HasSameNameAndSignature(&mh2)); - EXPECT_TRUE(mh2.HasSameNameAndSignature(&mh)); - - mh.ChangeMethod(m4_1); - mh2.ChangeMethod(m4_2); - EXPECT_TRUE(mh.HasSameNameAndSignature(&mh2)); - EXPECT_TRUE(mh2.HasSameNameAndSignature(&mh)); } TEST_F(ObjectTest, StringHashCode) { diff --git a/runtime/native/java_lang_reflect_Field.cc b/runtime/native/java_lang_reflect_Field.cc index a0426205c2..2cebf02471 100644 --- a/runtime/native/java_lang_reflect_Field.cc +++ b/runtime/native/java_lang_reflect_Field.cc @@ -20,7 +20,6 @@ #include "class_linker-inl.h" #include "common_throws.h" #include "dex_file-inl.h" -#include "field_helper.h" #include "jni_internal.h" #include "mirror/art_field-inl.h" #include "mirror/art_method-inl.h" @@ -294,9 +293,8 @@ static void Field_set(JNIEnv* env, jobject javaField, jobject javaObj, jobject j StackHandleScope<2> hs(soa.Self()); HandleWrapper<mirror::Object> h_o(hs.NewHandleWrapper(&o)); HandleWrapper<mirror::ArtField> h_f(hs.NewHandleWrapper(&f)); - FieldHelper fh(h_f); // May cause resolution. - field_type = fh.GetType(true); + field_type = h_f->GetType(true); if (field_type == nullptr) { DCHECK(soa.Self()->IsExceptionPending()); return; diff --git a/runtime/native_bridge_art_interface.cc b/runtime/native_bridge_art_interface.cc index ffadfc61a7..1775468688 100644 --- a/runtime/native_bridge_art_interface.cc +++ b/runtime/native_bridge_art_interface.cc @@ -28,10 +28,8 @@ namespace art { static const char* GetMethodShorty(JNIEnv* env, jmethodID mid) { ScopedObjectAccess soa(env); - StackHandleScope<1> scope(soa.Self()); mirror::ArtMethod* m = soa.DecodeMethod(mid); - MethodHelper mh(scope.NewHandle(m)); - return mh.GetShorty(); + return m->GetShorty(); } static uint32_t GetNativeMethodCount(JNIEnv* env, jclass clazz) { diff --git a/runtime/proxy_test.cc b/runtime/proxy_test.cc index 1eded628ed..3260992fba 100644 --- a/runtime/proxy_test.cc +++ b/runtime/proxy_test.cc @@ -18,7 +18,6 @@ #include <vector> #include "common_compiler_test.h" -#include "field_helper.h" #include "mirror/art_field-inl.h" #include "scoped_thread_state_change.h" @@ -184,21 +183,20 @@ TEST_F(ProxyTest, ProxyFieldHelper) { // Test "Class[] interfaces" field. MutableHandle<mirror::ArtField> fhandle = hs.NewHandle(static_fields->Get(0)); - FieldHelper fh(fhandle); - EXPECT_EQ("interfaces", std::string(fh.GetField()->GetName())); - EXPECT_EQ("[Ljava/lang/Class;", std::string(fh.GetField()->GetTypeDescriptor())); - EXPECT_EQ(interfacesFieldClass.Get(), fh.GetType()); - EXPECT_EQ("L$Proxy1234;", std::string(fh.GetDeclaringClassDescriptor())); - EXPECT_FALSE(fh.GetField()->IsPrimitiveType()); + EXPECT_EQ("interfaces", std::string(fhandle->GetName())); + EXPECT_EQ("[Ljava/lang/Class;", std::string(fhandle->GetTypeDescriptor())); + EXPECT_EQ(interfacesFieldClass.Get(), fhandle->GetType(true)); + std::string temp; + EXPECT_EQ("L$Proxy1234;", std::string(fhandle->GetDeclaringClass()->GetDescriptor(&temp))); + EXPECT_FALSE(fhandle->IsPrimitiveType()); // Test "Class[][] throws" field. fhandle.Assign(static_fields->Get(1)); - FieldHelper fh2(fhandle); - EXPECT_EQ("throws", std::string(fh2.GetField()->GetName())); - EXPECT_EQ("[[Ljava/lang/Class;", std::string(fh2.GetField()->GetTypeDescriptor())); - EXPECT_EQ(throwsFieldClass.Get(), fh2.GetType()); - EXPECT_EQ("L$Proxy1234;", std::string(fh2.GetDeclaringClassDescriptor())); - EXPECT_FALSE(fh2.GetField()->IsPrimitiveType()); + EXPECT_EQ("throws", std::string(fhandle->GetName())); + EXPECT_EQ("[[Ljava/lang/Class;", std::string(fhandle->GetTypeDescriptor())); + EXPECT_EQ(throwsFieldClass.Get(), fhandle->GetType(true)); + EXPECT_EQ("L$Proxy1234;", std::string(fhandle->GetDeclaringClass()->GetDescriptor(&temp))); + EXPECT_FALSE(fhandle->IsPrimitiveType()); } } // namespace art diff --git a/runtime/reflection.cc b/runtime/reflection.cc index 44d1bc4ad1..85f9938934 100644 --- a/runtime/reflection.cc +++ b/runtime/reflection.cc @@ -21,7 +21,6 @@ #include "dex_file-inl.h" #include "entrypoints/entrypoint_utils.h" #include "jni_internal.h" -#include "method_helper-inl.h" #include "mirror/art_field-inl.h" #include "mirror/art_method-inl.h" #include "mirror/class-inl.h" @@ -220,9 +219,10 @@ class ArgArray { } bool BuildArgArrayFromObjectArray(mirror::Object* receiver, - mirror::ObjectArray<mirror::Object>* args, MethodHelper& mh) + mirror::ObjectArray<mirror::Object>* args, + Handle<mirror::ArtMethod> h_m) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - const DexFile::TypeList* classes = mh.GetMethod()->GetParameterTypeList(); + const DexFile::TypeList* classes = h_m->GetParameterTypeList(); // Set receiver if non-null (method is not static) if (receiver != nullptr) { Append(receiver); @@ -231,11 +231,11 @@ class ArgArray { mirror::Object* arg = args->Get(args_offset); if (((shorty_[i] == 'L') && (arg != nullptr)) || ((arg == nullptr && shorty_[i] != 'L'))) { mirror::Class* dst_class = - mh.GetClassFromTypeIdx(classes->GetTypeItem(args_offset).type_idx_); + h_m->GetClassFromTypeIndex(classes->GetTypeItem(args_offset).type_idx_, true); if (UNLIKELY(arg == nullptr || !arg->InstanceOf(dst_class))) { ThrowIllegalArgumentException(nullptr, StringPrintf("method %s argument %zd has type %s, got %s", - PrettyMethod(mh.GetMethod(), false).c_str(), + PrettyMethod(h_m.Get(), false).c_str(), args_offset + 1, // Humans don't count from 0. PrettyDescriptor(dst_class).c_str(), PrettyTypeOf(arg).c_str()).c_str()); @@ -263,7 +263,7 @@ class ArgArray { } else { \ ThrowIllegalArgumentException(nullptr, \ StringPrintf("method %s argument %zd has type %s, got %s", \ - PrettyMethod(mh.GetMethod(), false).c_str(), \ + PrettyMethod(h_m.Get(), false).c_str(), \ args_offset + 1, \ expected, \ PrettyTypeOf(arg).c_str()).c_str()); \ @@ -329,6 +329,7 @@ class ArgArray { #ifndef NDEBUG default: LOG(FATAL) << "Unexpected shorty character: " << shorty_[i]; + UNREACHABLE(); #endif } #undef DO_FIRST_ARG @@ -360,14 +361,13 @@ static void CheckMethodArguments(JavaVMExt* vm, mirror::ArtMethod* m, uint32_t* if (!m->IsStatic()) { offset = 1; } - // TODO: If args contain object references, it may cause problems + // 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 = mh.GetClassFromTypeIdx(type_idx); + mirror::Class* param_type = h_m->GetClassFromTypeIndex(type_idx, true); if (param_type == nullptr) { CHECK(self->IsExceptionPending()); LOG(ERROR) << "Internal error: unresolvable type for argument type in JNI invoke: " @@ -528,7 +528,7 @@ JValue InvokeVirtualOrInterfaceWithVarArgs(const ScopedObjectAccessAlreadyRunnab } void InvokeWithShadowFrame(Thread* self, ShadowFrame* shadow_frame, uint16_t arg_offset, - MethodHelper* mh, JValue* result) { + JValue* result) { // We want to make sure that the stack is not within a small distance from the // protected region in case we are calling into a leaf function whose stack // check has been elided. @@ -536,11 +536,12 @@ void InvokeWithShadowFrame(Thread* self, ShadowFrame* shadow_frame, uint16_t arg ThrowStackOverflowError(self); return; } - - ArgArray arg_array(mh->GetShorty(), mh->GetShortyLength()); + uint32_t shorty_len; + const char* shorty = shadow_frame->GetMethod()->GetShorty(&shorty_len); + ArgArray arg_array(shorty, shorty_len); arg_array.BuildArgArrayFromFrame(shadow_frame, arg_offset); shadow_frame->GetMethod()->Invoke(self, arg_array.GetArray(), arg_array.GetNumBytes(), result, - mh->GetShorty()); + shorty); } jobject InvokeMethod(const ScopedObjectAccessAlreadyRunnable& soa, jobject javaMethod, @@ -571,7 +572,7 @@ jobject InvokeMethod(const ScopedObjectAccessAlreadyRunnable& soa, jobject javaM // Check that the receiver is non-null and an instance of the field's declaring class. receiver = soa.Decode<mirror::Object*>(javaReceiver); if (!VerifyObjectIsClass(receiver, declaring_class)) { - return NULL; + return nullptr; } // Find the actual implementation of the virtual method. @@ -585,10 +586,10 @@ jobject InvokeMethod(const ScopedObjectAccessAlreadyRunnable& soa, jobject javaM uint32_t classes_size = (classes == nullptr) ? 0 : classes->Size(); uint32_t arg_count = (objects != nullptr) ? objects->GetLength() : 0; if (arg_count != classes_size) { - ThrowIllegalArgumentException(NULL, + ThrowIllegalArgumentException(nullptr, StringPrintf("Wrong number of arguments; expected %d, got %d", classes_size, arg_count).c_str()); - return NULL; + return nullptr; } // If method is not set to be accessible, verify it can be accessed by the caller. @@ -611,8 +612,8 @@ jobject InvokeMethod(const ScopedObjectAccessAlreadyRunnable& soa, jobject javaM 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(receiver, objects, mh)) { + Handle<mirror::ArtMethod> h_m(hs.NewHandle(m)); + if (!arg_array.BuildArgArrayFromObjectArray(receiver, objects, h_m)) { CHECK(soa.Self()->IsExceptionPending()); return nullptr; } @@ -627,22 +628,21 @@ jobject InvokeMethod(const ScopedObjectAccessAlreadyRunnable& soa, jobject javaM jmethodID mid = soa.Env()->GetMethodID(exception_class, "<init>", "(Ljava/lang/Throwable;)V"); jobject exception_instance = soa.Env()->NewObject(exception_class, mid, th); soa.Env()->Throw(reinterpret_cast<jthrowable>(exception_instance)); - return NULL; + return nullptr; } // Box if necessary and return. - return soa.AddLocalReference<jobject>( - BoxPrimitive(Primitive::GetType(mh.GetMethod()->GetReturnTypeDescriptor()[0]), result)); + return soa.AddLocalReference<jobject>(BoxPrimitive(Primitive::GetType(shorty[0]), result)); } bool VerifyObjectIsClass(mirror::Object* o, mirror::Class* c) { - if (o == NULL) { - ThrowNullPointerException(NULL, "null receiver"); + if (o == nullptr) { + ThrowNullPointerException(nullptr, "null receiver"); return false; } else if (!o->InstanceOf(c)) { std::string expected_class_name(PrettyDescriptor(c)); std::string actual_class_name(PrettyTypeOf(o)); - ThrowIllegalArgumentException(NULL, + ThrowIllegalArgumentException(nullptr, StringPrintf("Expected receiver of type %s, but got %s", expected_class_name.c_str(), actual_class_name.c_str()).c_str()); diff --git a/runtime/reflection.h b/runtime/reflection.h index f9a795194d..1a64871e92 100644 --- a/runtime/reflection.h +++ b/runtime/reflection.h @@ -29,7 +29,6 @@ namespace mirror { class Object; } // namespace mirror union JValue; -class MethodHelper; class ScopedObjectAccessAlreadyRunnable; class ShadowFrame; class ThrowLocation; @@ -65,7 +64,7 @@ JValue InvokeVirtualOrInterfaceWithVarArgs(const ScopedObjectAccessAlreadyRunnab SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); void InvokeWithShadowFrame(Thread* self, ShadowFrame* shadow_frame, uint16_t arg_offset, - MethodHelper* mh, JValue* result) + JValue* result) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); jobject InvokeMethod(const ScopedObjectAccessAlreadyRunnable& soa, jobject method, jobject receiver, diff --git a/runtime/thread-inl.h b/runtime/thread-inl.h index e30e745154..7aed8b033c 100644 --- a/runtime/thread-inl.h +++ b/runtime/thread-inl.h @@ -69,7 +69,12 @@ inline ThreadState Thread::SetState(ThreadState new_state) { // Cannot use this code to change into Runnable as changing to Runnable should fail if // old_state_and_flags.suspend_request is true. DCHECK_NE(new_state, kRunnable); - DCHECK_EQ(this, Thread::Current()); + if (kIsDebugBuild && this != Thread::Current()) { + std::string name; + GetThreadName(name); + LOG(FATAL) << "Thread \"" << name << "\"(" << this << " != Thread::Current()=" + << Thread::Current() << ") changing state to " << new_state; + } union StateAndFlags old_state_and_flags; old_state_and_flags.as_int = tls32_.state_and_flags.as_int; tls32_.state_and_flags.as_struct.state = new_state; diff --git a/runtime/thread.h b/runtime/thread.h index b69d2f4a83..5b3e746cc9 100644 --- a/runtime/thread.h +++ b/runtime/thread.h @@ -1189,7 +1189,7 @@ class ScopedAssertNoThreadSuspension { private: Thread* const self_; - const char* old_cause_; + const char* const old_cause_; }; std::ostream& operator<<(std::ostream& os, const Thread& thread); diff --git a/runtime/thread_list.cc b/runtime/thread_list.cc index 5ff90d6392..beafcda8f2 100644 --- a/runtime/thread_list.cc +++ b/runtime/thread_list.cc @@ -168,7 +168,9 @@ class DumpCheckpoint FINAL : public Closure { const uint32_t kWaitTimeoutMs = 10000; bool timed_out = barrier_.Increment(self, threads_running_checkpoint, kWaitTimeoutMs); if (timed_out) { - LOG(kIsDebugBuild ? FATAL : ERROR) << "Unexpected time out during dump checkpoint."; + // Avoid a recursive abort. + LOG((kIsDebugBuild && (gAborting == 0)) ? FATAL : ERROR) + << "Unexpected time out during dump checkpoint."; } } diff --git a/runtime/trace.cc b/runtime/trace.cc index 2cc50b3732..b5108443b0 100644 --- a/runtime/trace.cc +++ b/runtime/trace.cc @@ -735,7 +735,9 @@ void Trace::StoreExitingThreadInfo(Thread* thread) { if (the_trace_ != nullptr) { std::string name; thread->GetThreadName(name); - the_trace_->exited_threads_.Put(thread->GetTid(), name); + // The same thread/tid may be used multiple times. As SafeMap::Put does not allow to override + // a previous mapping, use SafeMap::Overwrite. + the_trace_->exited_threads_.Overwrite(thread->GetTid(), name); } } diff --git a/runtime/utils.cc b/runtime/utils.cc index ad46be644f..1211547a51 100644 --- a/runtime/utils.cc +++ b/runtime/utils.cc @@ -28,7 +28,6 @@ #include "base/stl_util.h" #include "base/unix_file/fd_file.h" #include "dex_file-inl.h" -#include "field_helper.h" #include "mirror/art_field-inl.h" #include "mirror/art_method-inl.h" #include "mirror/class-inl.h" @@ -324,8 +323,8 @@ std::string PrettyField(mirror::ArtField* f, bool with_type) { result += PrettyDescriptor(f->GetTypeDescriptor()); result += ' '; } - StackHandleScope<1> hs(Thread::Current()); - result += PrettyDescriptor(FieldHelper(hs.NewHandle(f)).GetDeclaringClassDescriptor()); + std::string temp; + result += PrettyDescriptor(f->GetDeclaringClass()->GetDescriptor(&temp)); result += '.'; result += f->GetName(); return result; diff --git a/runtime/verifier/method_verifier.cc b/runtime/verifier/method_verifier.cc index a10c7cb895..1b3cc8ff93 100644 --- a/runtime/verifier/method_verifier.cc +++ b/runtime/verifier/method_verifier.cc @@ -25,12 +25,10 @@ #include "dex_file-inl.h" #include "dex_instruction-inl.h" #include "dex_instruction_visitor.h" -#include "field_helper.h" #include "gc/accounting/card_table-inl.h" #include "indenter.h" #include "intern_table.h" #include "leb128.h" -#include "method_helper-inl.h" #include "mirror/art_field-inl.h" #include "mirror/art_method-inl.h" #include "mirror/class.h" @@ -3827,7 +3825,7 @@ void MethodVerifier::VerifyISFieldAccess(const Instruction* inst, const RegType& { StackHandleScope<1> hs(self_); HandleWrapper<mirror::ArtField> h_field(hs.NewHandleWrapper(&field)); - field_type_class = FieldHelper(h_field).GetType(can_load_classes_); + field_type_class = h_field->GetType(can_load_classes_); } if (field_type_class != nullptr) { field_type = ®_types_.FromClass(field->GetTypeDescriptor(), field_type_class, @@ -3951,7 +3949,7 @@ void MethodVerifier::VerifyQuickFieldAccess(const Instruction* inst, const RegTy { StackHandleScope<1> hs(Thread::Current()); HandleWrapper<mirror::ArtField> h_field(hs.NewHandleWrapper(&field)); - field_type_class = FieldHelper(h_field).GetType(can_load_classes_); + field_type_class = h_field->GetType(can_load_classes_); } if (field_type_class != nullptr) { |