diff options
author | Mathieu Chartier <mathieuc@google.com> | 2013-09-13 13:46:47 -0700 |
---|---|---|
committer | Mathieu Chartier <mathieuc@google.com> | 2013-11-11 15:34:27 -0800 |
commit | 590fee9e8972f872301c2d16a575d579ee564bee (patch) | |
tree | b02db45c72f1911ec896b93379ada0276aea3199 /runtime/verifier | |
parent | 5b70680b8df6d8fa95bb8e1070d0107f3d388940 (diff) | |
download | art-590fee9e8972f872301c2d16a575d579ee564bee.zip art-590fee9e8972f872301c2d16a575d579ee564bee.tar.gz art-590fee9e8972f872301c2d16a575d579ee564bee.tar.bz2 |
Compacting collector.
The compacting collector is currently similar to semispace. It works by
copying objects back and forth between two bump pointer spaces. There
are types of objects which are "non-movable" due to current runtime
limitations. These are Classes, Methods, and Fields.
Bump pointer spaces are a new type of continuous alloc space which have
no lock in the allocation code path. When you allocate from these it uses
atomic operations to increase an index. Traversing the objects in the bump
pointer space relies on Object::SizeOf matching the allocated size exactly.
Runtime changes:
JNI::GetArrayElements returns copies objects if you attempt to get the
backing data of a movable array. For GetArrayElementsCritical, we return
direct backing storage for any types of arrays, but temporarily disable
the GC until the critical region is completed.
Added a new runtime call called VisitObjects, this is used in place of
the old pattern which was flushing the allocation stack and walking
the bitmaps.
Changed image writer to be compaction safe and use object monitor word
for forwarding addresses.
Added a bunch of added SIRTs to ClassLinker, MethodLinker, etc..
TODO: Enable switching allocators, compacting on background, etc..
Bug: 8981901
Change-Id: I3c886fd322a6eef2b99388d19a765042ec26ab99
Diffstat (limited to 'runtime/verifier')
-rw-r--r-- | runtime/verifier/method_verifier.cc | 176 | ||||
-rw-r--r-- | runtime/verifier/method_verifier.h | 27 | ||||
-rw-r--r-- | runtime/verifier/reg_type.cc | 3 | ||||
-rw-r--r-- | runtime/verifier/reg_type_cache.cc | 3 |
4 files changed, 113 insertions, 96 deletions
diff --git a/runtime/verifier/method_verifier.cc b/runtime/verifier/method_verifier.cc index 9f98061..9cd8f73 100644 --- a/runtime/verifier/method_verifier.cc +++ b/runtime/verifier/method_verifier.cc @@ -39,6 +39,7 @@ #include "object_utils.h" #include "register_line-inl.h" #include "runtime.h" +#include "scoped_thread_state_change.h" #include "verifier/dex_gc_map.h" namespace art { @@ -113,17 +114,15 @@ MethodVerifier::FailureKind MethodVerifier::VerifyClass(const mirror::Class* kla *error += dex_file.GetLocation(); return kHardFailure; } - return VerifyClass(&dex_file, - kh.GetDexCache(), - klass->GetClassLoader(), - class_def, - allow_soft_failures, - error); + Thread* self = Thread::Current(); + SirtRef<mirror::DexCache> dex_cache(self, kh.GetDexCache()); + SirtRef<mirror::ClassLoader> class_loader(self, klass->GetClassLoader()); + return VerifyClass(&dex_file, dex_cache, class_loader, class_def, allow_soft_failures, error); } MethodVerifier::FailureKind MethodVerifier::VerifyClass(const DexFile* dex_file, - mirror::DexCache* dex_cache, - mirror::ClassLoader* class_loader, + SirtRef<mirror::DexCache>& dex_cache, + SirtRef<mirror::ClassLoader>& class_loader, const DexFile::ClassDef* class_def, bool allow_soft_failures, std::string* error) { @@ -233,8 +232,8 @@ MethodVerifier::FailureKind MethodVerifier::VerifyClass(const DexFile* dex_file, MethodVerifier::FailureKind MethodVerifier::VerifyMethod(uint32_t method_idx, const DexFile* dex_file, - mirror::DexCache* dex_cache, - mirror::ClassLoader* class_loader, + SirtRef<mirror::DexCache>& dex_cache, + SirtRef<mirror::ClassLoader>& class_loader, const DexFile::ClassDef* class_def, const DexFile::CodeItem* code_item, mirror::ArtMethod* method, @@ -243,8 +242,8 @@ MethodVerifier::FailureKind MethodVerifier::VerifyMethod(uint32_t method_idx, MethodVerifier::FailureKind result = kNoFailure; uint64_t start_ns = NanoTime(); - MethodVerifier verifier_(dex_file, dex_cache, class_loader, class_def, code_item, method_idx, - method, method_access_flags, true, allow_soft_failures); + MethodVerifier verifier_(dex_file, &dex_cache, &class_loader, class_def, code_item, + method_idx, method, method_access_flags, true, allow_soft_failures); if (verifier_.Verify()) { // Verification completed, however failures may be pending that didn't cause the verification // to hard fail. @@ -277,13 +276,14 @@ MethodVerifier::FailureKind MethodVerifier::VerifyMethod(uint32_t method_idx, } void MethodVerifier::VerifyMethodAndDump(std::ostream& os, uint32_t dex_method_idx, - const DexFile* dex_file, mirror::DexCache* dex_cache, - mirror::ClassLoader* class_loader, + const DexFile* dex_file, + SirtRef<mirror::DexCache>& dex_cache, + SirtRef<mirror::ClassLoader>& class_loader, const DexFile::ClassDef* class_def, const DexFile::CodeItem* code_item, mirror::ArtMethod* method, uint32_t method_access_flags) { - MethodVerifier verifier(dex_file, dex_cache, class_loader, class_def, code_item, + MethodVerifier verifier(dex_file, &dex_cache, &class_loader, class_def, code_item, dex_method_idx, method, method_access_flags, true, true); verifier.Verify(); verifier.DumpFailures(os); @@ -291,13 +291,12 @@ void MethodVerifier::VerifyMethodAndDump(std::ostream& os, uint32_t dex_method_i verifier.Dump(os); } -MethodVerifier::MethodVerifier(const DexFile* dex_file, mirror::DexCache* dex_cache, - mirror::ClassLoader* class_loader, +MethodVerifier::MethodVerifier(const DexFile* dex_file, SirtRef<mirror::DexCache>* dex_cache, + SirtRef<mirror::ClassLoader>* class_loader, const DexFile::ClassDef* class_def, - const DexFile::CodeItem* code_item, - uint32_t dex_method_idx, mirror::ArtMethod* method, - uint32_t method_access_flags, bool can_load_classes, - bool allow_soft_failures) + const DexFile::CodeItem* code_item, uint32_t dex_method_idx, + mirror::ArtMethod* method, uint32_t method_access_flags, + bool can_load_classes, bool allow_soft_failures) : reg_types_(can_load_classes), work_insn_idx_(-1), dex_method_idx_(dex_method_idx), @@ -323,12 +322,19 @@ MethodVerifier::MethodVerifier(const DexFile* dex_file, mirror::DexCache* dex_ca DCHECK(class_def != nullptr); } +MethodVerifier::~MethodVerifier() { + STLDeleteElements(&failure_messages_); +} + void MethodVerifier::FindLocksAtDexPc(mirror::ArtMethod* m, uint32_t dex_pc, std::vector<uint32_t>& monitor_enter_dex_pcs) { MethodHelper mh(m); - MethodVerifier verifier(&mh.GetDexFile(), mh.GetDexCache(), mh.GetClassLoader(), - &mh.GetClassDef(), mh.GetCodeItem(), m->GetDexMethodIndex(), - m, m->GetAccessFlags(), false, true); + Thread* self = Thread::Current(); + SirtRef<mirror::DexCache> dex_cache(self, mh.GetDexCache()); + SirtRef<mirror::ClassLoader> class_loader(self, mh.GetClassLoader()); + MethodVerifier verifier(&mh.GetDexFile(), &dex_cache, &class_loader, &mh.GetClassDef(), + mh.GetCodeItem(), m->GetDexMethodIndex(), m, m->GetAccessFlags(), false, + true); verifier.interesting_dex_pc_ = dex_pc; verifier.monitor_enter_dex_pcs_ = &monitor_enter_dex_pcs; verifier.FindLocksAtDexPc(); @@ -348,9 +354,12 @@ void MethodVerifier::FindLocksAtDexPc() { mirror::ArtField* MethodVerifier::FindAccessedFieldAtDexPc(mirror::ArtMethod* m, uint32_t dex_pc) { MethodHelper mh(m); - MethodVerifier verifier(&mh.GetDexFile(), mh.GetDexCache(), mh.GetClassLoader(), - &mh.GetClassDef(), mh.GetCodeItem(), m->GetDexMethodIndex(), - m, m->GetAccessFlags(), false, true); + Thread* self = Thread::Current(); + SirtRef<mirror::DexCache> dex_cache(self, mh.GetDexCache()); + SirtRef<mirror::ClassLoader> class_loader(self, mh.GetClassLoader()); + MethodVerifier verifier(&mh.GetDexFile(), &dex_cache, &class_loader, &mh.GetClassDef(), + mh.GetCodeItem(), m->GetDexMethodIndex(), m, m->GetAccessFlags(), false, + true); return verifier.FindAccessedFieldAtDexPc(dex_pc); } @@ -374,11 +383,14 @@ mirror::ArtField* MethodVerifier::FindAccessedFieldAtDexPc(uint32_t dex_pc) { } mirror::ArtMethod* MethodVerifier::FindInvokedMethodAtDexPc(mirror::ArtMethod* m, - uint32_t dex_pc) { + uint32_t dex_pc) { MethodHelper mh(m); - MethodVerifier verifier(&mh.GetDexFile(), mh.GetDexCache(), mh.GetClassLoader(), - &mh.GetClassDef(), mh.GetCodeItem(), m->GetDexMethodIndex(), - m, m->GetAccessFlags(), false, true); + Thread* self = Thread::Current(); + SirtRef<mirror::DexCache> dex_cache(self, mh.GetDexCache()); + SirtRef<mirror::ClassLoader> class_loader(self, mh.GetClassLoader()); + MethodVerifier verifier(&mh.GetDexFile(), &dex_cache, &class_loader, &mh.GetClassDef(), + mh.GetCodeItem(), m->GetDexMethodIndex(), m, m->GetAccessFlags(), false, + true); return verifier.FindInvokedMethodAtDexPc(dex_pc); } @@ -589,7 +601,7 @@ bool MethodVerifier::ScanTryCatchBlocks() { if (iterator.GetHandlerTypeIndex() != DexFile::kDexNoIndex16) { mirror::Class* exception_type = linker->ResolveType(*dex_file_, iterator.GetHandlerTypeIndex(), - dex_cache_, class_loader_); + *dex_cache_, *class_loader_); if (exception_type == NULL) { DCHECK(Thread::Current()->IsExceptionPending()); Thread::Current()->ClearException(); @@ -1211,7 +1223,8 @@ bool MethodVerifier::SetTypesFromSignature() { // it's effectively considered initialized the instant we reach here (in the sense that we // can return without doing anything or call virtual methods). { - const RegType& reg_type = reg_types_.FromDescriptor(class_loader_, descriptor, false); + const RegType& reg_type = reg_types_.FromDescriptor(class_loader_->get(), descriptor, + false); reg_line->SetRegisterType(arg_start + cur_arg, reg_type); } break; @@ -1853,7 +1866,8 @@ bool MethodVerifier::CodeFlowVerifyInstruction(uint32_t* start_guess) { Fail(VERIFY_ERROR_BAD_CLASS_HARD) << "invalid fill-array-data with array type " << array_type; } else { - const RegType& component_type = reg_types_.GetComponentType(array_type, class_loader_); + const RegType& component_type = reg_types_.GetComponentType(array_type, + class_loader_->get()); DCHECK(!component_type.IsConflict()); if (component_type.IsNonZeroReferenceTypes()) { Fail(VERIFY_ERROR_BAD_CLASS_HARD) << "invalid fill-array-data with component type " @@ -2168,7 +2182,7 @@ bool MethodVerifier::CodeFlowVerifyInstruction(uint32_t* start_guess) { const DexFile::MethodId& method_id = dex_file_->GetMethodId(method_idx); uint32_t return_type_idx = dex_file_->GetProtoId(method_id.proto_idx_).return_type_idx_; const char* descriptor = dex_file_->StringByTypeIdx(return_type_idx); - return_type = ®_types_.FromDescriptor(class_loader_, descriptor, false); + return_type = ®_types_.FromDescriptor(class_loader_->get(), descriptor, false); } if (!return_type->IsLowHalf()) { work_line_->SetResultRegisterType(*return_type); @@ -2235,8 +2249,8 @@ bool MethodVerifier::CodeFlowVerifyInstruction(uint32_t* start_guess) { */ work_line_->MarkRefsAsInitialized(this_type); } - const RegType& return_type = reg_types_.FromDescriptor(class_loader_, return_type_descriptor, - false); + const RegType& return_type = reg_types_.FromDescriptor(class_loader_->get(), + return_type_descriptor, false); if (!return_type.IsLowHalf()) { work_line_->SetResultRegisterType(return_type); } else { @@ -2257,11 +2271,12 @@ bool MethodVerifier::CodeFlowVerifyInstruction(uint32_t* start_guess) { uint32_t method_idx = (is_range) ? inst->VRegB_3rc() : inst->VRegB_35c(); const DexFile::MethodId& method_id = dex_file_->GetMethodId(method_idx); uint32_t return_type_idx = dex_file_->GetProtoId(method_id.proto_idx_).return_type_idx_; - descriptor = dex_file_->StringByTypeIdx(return_type_idx); + descriptor = dex_file_->StringByTypeIdx(return_type_idx); } else { descriptor = MethodHelper(called_method).GetReturnTypeDescriptor(); } - const RegType& return_type = reg_types_.FromDescriptor(class_loader_, descriptor, false); + const RegType& return_type = reg_types_.FromDescriptor(class_loader_->get(), descriptor, + false); if (!return_type.IsLowHalf()) { work_line_->SetResultRegisterType(return_type); } else { @@ -2318,7 +2333,8 @@ bool MethodVerifier::CodeFlowVerifyInstruction(uint32_t* start_guess) { } else { descriptor = MethodHelper(abs_method).GetReturnTypeDescriptor(); } - const RegType& return_type = reg_types_.FromDescriptor(class_loader_, descriptor, false); + const RegType& return_type = reg_types_.FromDescriptor(class_loader_->get(), descriptor, + false); if (!return_type.IsLowHalf()) { work_line_->SetResultRegisterType(return_type); } else { @@ -2584,7 +2600,8 @@ bool MethodVerifier::CodeFlowVerifyInstruction(uint32_t* start_guess) { mirror::ArtMethod* called_method = VerifyInvokeVirtualQuickArgs(inst, is_range); if (called_method != NULL) { const char* descriptor = MethodHelper(called_method).GetReturnTypeDescriptor(); - const RegType& return_type = reg_types_.FromDescriptor(class_loader_, descriptor, false); + const RegType& return_type = reg_types_.FromDescriptor(class_loader_->get(), descriptor, + false); if (!return_type.IsLowHalf()) { work_line_->SetResultRegisterType(return_type); } else { @@ -2850,18 +2867,18 @@ bool MethodVerifier::CodeFlowVerifyInstruction(uint32_t* start_guess) { const RegType& MethodVerifier::ResolveClassAndCheckAccess(uint32_t class_idx) { const char* descriptor = dex_file_->StringByTypeIdx(class_idx); const RegType& referrer = GetDeclaringClass(); - mirror::Class* klass = dex_cache_->GetResolvedType(class_idx); + mirror::Class* klass = (*dex_cache_)->GetResolvedType(class_idx); const RegType& result = klass != NULL ? reg_types_.FromClass(descriptor, klass, klass->CannotBeAssignedFromOtherTypes()) - : reg_types_.FromDescriptor(class_loader_, descriptor, false); + : reg_types_.FromDescriptor(class_loader_->get(), descriptor, false); if (result.IsConflict()) { Fail(VERIFY_ERROR_BAD_CLASS_SOFT) << "accessing broken descriptor '" << descriptor << "' in " << referrer; return result; } if (klass == NULL && !result.IsUnresolvedTypes()) { - dex_cache_->SetResolvedType(class_idx, result.GetClass()); + (*dex_cache_)->SetResolvedType(class_idx, result.GetClass()); } // Check if access is allowed. Unresolved types use xxxWithAccessCheck to // check at runtime if access is allowed and so pass here. If result is @@ -2935,7 +2952,7 @@ mirror::ArtMethod* MethodVerifier::ResolveMethodAndCheckAccess(uint32_t dex_meth } mirror::Class* klass = klass_type.GetClass(); const RegType& referrer = GetDeclaringClass(); - mirror::ArtMethod* res_method = dex_cache_->GetResolvedMethod(dex_method_idx); + mirror::ArtMethod* res_method = (*dex_cache_)->GetResolvedMethod(dex_method_idx); if (res_method == NULL) { const char* name = dex_file_->GetMethodName(method_id); const Signature signature = dex_file_->GetMethodSignature(method_id); @@ -2948,7 +2965,7 @@ mirror::ArtMethod* MethodVerifier::ResolveMethodAndCheckAccess(uint32_t dex_meth res_method = klass->FindVirtualMethod(name, signature); } if (res_method != NULL) { - dex_cache_->SetResolvedMethod(dex_method_idx, res_method); + (*dex_cache_)->SetResolvedMethod(dex_method_idx, res_method); } else { // If a virtual or interface method wasn't found with the expected type, look in // the direct methods. This can happen when the wrong invoke type is used or when @@ -3112,7 +3129,7 @@ mirror::ArtMethod* MethodVerifier::VerifyInvocationArgs(const Instruction* inst, << " missing signature component"; return NULL; } - const RegType& reg_type = reg_types_.FromDescriptor(class_loader_, descriptor, false); + const RegType& reg_type = reg_types_.FromDescriptor(class_loader_->get(), descriptor, false); uint32_t get_reg = is_range ? inst->VRegC_3rc() + actual_args : arg[actual_args]; if (reg_type.IsIntegralTypes()) { const RegType& src_type = work_line_->GetRegisterType(get_reg); @@ -3136,8 +3153,7 @@ mirror::ArtMethod* MethodVerifier::VerifyInvocationArgs(const Instruction* inst, } mirror::ArtMethod* MethodVerifier::GetQuickInvokedMethod(const Instruction* inst, - RegisterLine* reg_line, - bool is_range) { + RegisterLine* reg_line, bool is_range) { DCHECK(inst->Opcode() == Instruction::INVOKE_VIRTUAL_QUICK || inst->Opcode() == Instruction::INVOKE_VIRTUAL_RANGE_QUICK); const RegType& actual_arg_type = reg_line->GetInvocationThis(inst, is_range); @@ -3152,11 +3168,13 @@ mirror::ArtMethod* MethodVerifier::GetQuickInvokedMethod(const Instruction* inst } else { const std::string& descriptor(actual_arg_type.GetDescriptor()); ClassLinker* class_linker = Runtime::Current()->GetClassLinker(); - this_class = class_linker->FindClass(descriptor.c_str(), class_loader_); + this_class = class_linker->FindClass(descriptor.c_str(), *class_loader_); if (this_class == NULL) { - Thread::Current()->ClearException(); + Thread* self = Thread::Current(); + self->ClearException(); // Look for a system class - this_class = class_linker->FindClass(descriptor.c_str(), NULL); + SirtRef<mirror::ClassLoader> null_class_loader(self, nullptr); + this_class = class_linker->FindClass(descriptor.c_str(), null_class_loader); } } if (this_class == NULL) { @@ -3246,7 +3264,7 @@ mirror::ArtMethod* MethodVerifier::VerifyInvokeVirtualQuickArgs(const Instructio << " missing signature component"; return NULL; } - const RegType& reg_type = reg_types_.FromDescriptor(class_loader_, descriptor, false); + const RegType& reg_type = reg_types_.FromDescriptor(class_loader_->get(), descriptor, false); uint32_t get_reg = is_range ? inst->VRegC_3rc() + actual_args : arg[actual_args]; if (!work_line_->VerifyRegisterType(get_reg, reg_type)) { return res_method; @@ -3290,7 +3308,7 @@ void MethodVerifier::VerifyNewArray(const Instruction* inst, bool is_filled, boo } else { // Verify each register. If "arg_count" is bad, VerifyRegisterType() will run off the end of // the list and fail. It's legal, if silly, for arg_count to be zero. - const RegType& expected_type = reg_types_.GetComponentType(res_type, class_loader_); + const RegType& expected_type = reg_types_.GetComponentType(res_type, class_loader_->get()); uint32_t arg_count = (is_range) ? inst->VRegA_3rc() : inst->VRegA_35c(); uint32_t arg[5]; if (!is_range) { @@ -3332,7 +3350,7 @@ void MethodVerifier::VerifyAGet(const Instruction* inst, Fail(VERIFY_ERROR_BAD_CLASS_HARD) << "not array type " << array_type << " with aget"; } else { /* verify the class */ - const RegType& component_type = reg_types_.GetComponentType(array_type, class_loader_); + const RegType& component_type = reg_types_.GetComponentType(array_type, class_loader_->get()); if (!component_type.IsReferenceTypes() && !is_primitive) { Fail(VERIFY_ERROR_BAD_CLASS_HARD) << "primitive array type " << array_type << " source for aget-object"; @@ -3409,7 +3427,7 @@ void MethodVerifier::VerifyAPut(const Instruction* inst, } else if (!array_type.IsArrayTypes()) { Fail(VERIFY_ERROR_BAD_CLASS_HARD) << "not array type " << array_type << " with aput"; } else { - const RegType& component_type = reg_types_.GetComponentType(array_type, class_loader_); + const RegType& component_type = reg_types_.GetComponentType(array_type, class_loader_->get()); const uint32_t vregA = inst->VRegA_23x(); if (is_primitive) { VerifyPrimitivePut(component_type, insn_type, vregA); @@ -3441,10 +3459,9 @@ mirror::ArtField* MethodVerifier::GetStaticField(int field_idx) { if (klass_type.IsUnresolvedTypes()) { return NULL; // Can't resolve Class so no more to do here, will do checking at runtime. } - mirror::ArtField* field = Runtime::Current()->GetClassLinker()->ResolveFieldJLS(*dex_file_, - field_idx, - dex_cache_, - class_loader_); + ClassLinker* class_linker = Runtime::Current()->GetClassLinker(); + mirror::ArtField* field = class_linker->ResolveFieldJLS(*dex_file_, field_idx, *dex_cache_, + *class_loader_); if (field == NULL) { VLOG(verifier) << "Unable to resolve static field " << field_idx << " (" << dex_file_->GetFieldName(field_id) << ") in " @@ -3460,9 +3477,8 @@ mirror::ArtField* MethodVerifier::GetStaticField(int field_idx) { } else if (!field->IsStatic()) { Fail(VERIFY_ERROR_CLASS_CHANGE) << "expected field " << PrettyField(field) << " to be static"; return NULL; - } else { - return field; } + return field; } mirror::ArtField* MethodVerifier::GetInstanceField(const RegType& obj_type, int field_idx) { @@ -3478,10 +3494,9 @@ mirror::ArtField* MethodVerifier::GetInstanceField(const RegType& obj_type, int if (klass_type.IsUnresolvedTypes()) { return NULL; // Can't resolve Class so no more to do here } - mirror::ArtField* field = Runtime::Current()->GetClassLinker()->ResolveFieldJLS(*dex_file_, - field_idx, - dex_cache_, - class_loader_); + ClassLinker* class_linker = Runtime::Current()->GetClassLinker(); + mirror::ArtField* field = class_linker->ResolveFieldJLS(*dex_file_, field_idx, *dex_cache_, + *class_loader_); if (field == NULL) { VLOG(verifier) << "Unable to resolve instance field " << field_idx << " (" << dex_file_->GetFieldName(field_id) << ") in " @@ -3550,8 +3565,7 @@ void MethodVerifier::VerifyISGet(const Instruction* inst, const RegType& insn_ty if (field_type == nullptr) { const DexFile::FieldId& field_id = dex_file_->GetFieldId(field_idx); const char* descriptor = dex_file_->GetFieldTypeDescriptor(field_id); - mirror::ClassLoader* loader = class_loader_; - field_type = ®_types_.FromDescriptor(loader, descriptor, false); + field_type = ®_types_.FromDescriptor(class_loader_->get(), descriptor, false); } const uint32_t vregA = (is_static) ? inst->VRegA_21c() : inst->VRegA_22c(); if (is_primitive) { @@ -3613,8 +3627,7 @@ void MethodVerifier::VerifyISPut(const Instruction* inst, const RegType& insn_ty if (field_type == nullptr) { const DexFile::FieldId& field_id = dex_file_->GetFieldId(field_idx); const char* descriptor = dex_file_->GetFieldTypeDescriptor(field_id); - mirror::ClassLoader* loader = class_loader_; - field_type = ®_types_.FromDescriptor(loader, descriptor, false); + field_type = ®_types_.FromDescriptor(class_loader_->get(), descriptor, false); } const uint32_t vregA = (is_static) ? inst->VRegA_21c() : inst->VRegA_22c(); if (is_primitive) { @@ -3671,11 +3684,13 @@ mirror::ArtField* MethodVerifier::GetQuickFieldAccess(const Instruction* inst, // We need to resolve the class from its descriptor. const std::string& descriptor(object_type.GetDescriptor()); ClassLinker* class_linker = Runtime::Current()->GetClassLinker(); - object_class = class_linker->FindClass(descriptor.c_str(), class_loader_); + Thread* self = Thread::Current(); + object_class = class_linker->FindClass(descriptor.c_str(), *class_loader_); if (object_class == NULL) { - Thread::Current()->ClearException(); + self->ClearException(); // Look for a system class - object_class = class_linker->FindClass(descriptor.c_str(), NULL); + SirtRef<mirror::ClassLoader> null_class_loader(self, nullptr); + object_class = class_linker->FindClass(descriptor.c_str(), null_class_loader); } } if (object_class == NULL) { @@ -3881,8 +3896,8 @@ const RegType& MethodVerifier::GetMethodReturnType() { MethodHelper mh(mirror_method_); mirror::Class* return_type_class = mh.GetReturnType(); if (return_type_class != nullptr) { - return_type_ =®_types_.FromClass(mh.GetReturnTypeDescriptor(), return_type_class, - return_type_class->CannotBeAssignedFromOtherTypes()); + return_type_ = ®_types_.FromClass(mh.GetReturnTypeDescriptor(), return_type_class, + return_type_class->CannotBeAssignedFromOtherTypes()); } else { Thread* self = Thread::Current(); DCHECK(self->IsExceptionPending()); @@ -3894,7 +3909,7 @@ const RegType& MethodVerifier::GetMethodReturnType() { const DexFile::ProtoId& proto_id = dex_file_->GetMethodPrototype(method_id); uint16_t return_type_idx = proto_id.return_type_idx_; const char* descriptor = dex_file_->GetTypeDescriptor(dex_file_->GetTypeId(return_type_idx)); - return_type_ = ®_types_.FromDescriptor(class_loader_, descriptor, false); + return_type_ = ®_types_.FromDescriptor(class_loader_->get(), descriptor, false); } } return *return_type_; @@ -3910,7 +3925,7 @@ const RegType& MethodVerifier::GetDeclaringClass() { declaring_class_ = ®_types_.FromClass(descriptor, klass, klass->CannotBeAssignedFromOtherTypes()); } else { - declaring_class_ = ®_types_.FromDescriptor(class_loader_, descriptor, false); + declaring_class_ = ®_types_.FromDescriptor(class_loader_->get(), descriptor, false); } } return *declaring_class_; @@ -3969,7 +3984,8 @@ MethodVerifier::MethodSafeCastSet* MethodVerifier::GenerateSafeCastSet() { // String[] in which case the stores need to be of Strings. if (array_type.IsPreciseReference()) { const RegType& value_type(line->GetRegisterType(inst->VRegA_23x())); - const RegType& component_type(reg_types_.GetComponentType(array_type, class_loader_)); + const RegType& component_type(reg_types_.GetComponentType(array_type, + class_loader_->get())); is_safe_cast = component_type.IsStrictlyAssignableFrom(value_type); } } @@ -4026,8 +4042,8 @@ MethodVerifier::PcToConcreteMethodMap* MethodVerifier::GenerateDevirtMap() { // We can't devirtualize abstract classes except on arrays of abstract classes. continue; } - mirror::ArtMethod* abstract_method = - dex_cache_->GetResolvedMethod(is_range ? inst->VRegB_3rc() : inst->VRegB_35c()); + mirror::ArtMethod* abstract_method = (*dex_cache_)->GetResolvedMethod( + is_range ? inst->VRegB_3rc() : inst->VRegB_35c()); if (abstract_method == NULL) { // If the method is not found in the cache this means that it was never found // by ResolveMethodAndCheckAccess() called when verifying invoke_*. diff --git a/runtime/verifier/method_verifier.h b/runtime/verifier/method_verifier.h index 57fde1d..8a663f9 100644 --- a/runtime/verifier/method_verifier.h +++ b/runtime/verifier/method_verifier.h @@ -33,6 +33,7 @@ #include "reg_type_cache-inl.h" #include "register_line.h" #include "safe_map.h" +#include "sirt_ref.h" #include "UniquePtr.h" namespace art { @@ -142,14 +143,15 @@ class MethodVerifier { static FailureKind VerifyClass(const mirror::Class* klass, bool allow_soft_failures, std::string* error) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); - static FailureKind VerifyClass(const DexFile* dex_file, mirror::DexCache* dex_cache, - mirror::ClassLoader* class_loader, + static FailureKind VerifyClass(const DexFile* dex_file, SirtRef<mirror::DexCache>& dex_cache, + SirtRef<mirror::ClassLoader>& class_loader, const DexFile::ClassDef* class_def, bool allow_soft_failures, std::string* error) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); static void VerifyMethodAndDump(std::ostream& os, uint32_t method_idx, const DexFile* dex_file, - mirror::DexCache* dex_cache, mirror::ClassLoader* class_loader, + SirtRef<mirror::DexCache>& dex_cache, + SirtRef<mirror::ClassLoader>& class_loader, const DexFile::ClassDef* class_def, const DexFile::CodeItem* code_item, mirror::ArtMethod* method, uint32_t method_access_flags) @@ -217,16 +219,13 @@ class MethodVerifier { return can_load_classes_; } - MethodVerifier(const DexFile* dex_file, mirror::DexCache* dex_cache, - mirror::ClassLoader* class_loader, const DexFile::ClassDef* class_def, - const DexFile::CodeItem* code_item, - uint32_t method_idx, mirror::ArtMethod* method, + MethodVerifier(const DexFile* dex_file, SirtRef<mirror::DexCache>* dex_cache, + SirtRef<mirror::ClassLoader>* class_loader, const DexFile::ClassDef* class_def, + const DexFile::CodeItem* code_item, uint32_t method_idx, mirror::ArtMethod* method, uint32_t access_flags, bool can_load_classes, bool allow_soft_failures) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); - ~MethodVerifier() { - STLDeleteElements(&failure_messages_); - } + ~MethodVerifier(); // Run verification on the method. Returns true if verification completes and false if the input // has an irrecoverable corruption. @@ -257,8 +256,8 @@ class MethodVerifier { * for code flow problems. */ static FailureKind VerifyMethod(uint32_t method_idx, const DexFile* dex_file, - mirror::DexCache* dex_cache, - mirror::ClassLoader* class_loader, + SirtRef<mirror::DexCache>& dex_cache, + SirtRef<mirror::ClassLoader>& class_loader, const DexFile::ClassDef* class_def_idx, const DexFile::CodeItem* code_item, mirror::ArtMethod* method, uint32_t method_access_flags, @@ -685,9 +684,9 @@ class MethodVerifier { const RegType* return_type_; // Lazily computed return type of the method. const DexFile* const dex_file_; // The dex file containing the method. // The dex_cache for the declaring class of the method. - mirror::DexCache* dex_cache_ GUARDED_BY(Locks::mutator_lock_); + SirtRef<mirror::DexCache>* dex_cache_ GUARDED_BY(Locks::mutator_lock_); // The class loader for the declaring class of the method. - mirror::ClassLoader* class_loader_ GUARDED_BY(Locks::mutator_lock_); + SirtRef<mirror::ClassLoader>* class_loader_ GUARDED_BY(Locks::mutator_lock_); const DexFile::ClassDef* const class_def_; // The class def of the declaring class of the method. const DexFile::CodeItem* const code_item_; // The code item containing the code for the method. const RegType* declaring_class_; // Lazily computed reg type of the method's declaring class. diff --git a/runtime/verifier/reg_type.cc b/runtime/verifier/reg_type.cc index 50d1583..d82e75d 100644 --- a/runtime/verifier/reg_type.cc +++ b/runtime/verifier/reg_type.cc @@ -928,7 +928,8 @@ mirror::Class* RegType::ClassJoin(mirror::Class* s, mirror::Class* t) { } mirror::Class* common_elem = ClassJoin(s_ct, t_ct); ClassLinker* class_linker = Runtime::Current()->GetClassLinker(); - mirror::ClassLoader* class_loader = s->GetClassLoader(); + Thread* self = Thread::Current(); + SirtRef<mirror::ClassLoader> class_loader(self, s->GetClassLoader()); std::string descriptor("["); descriptor += ClassHelper(common_elem).GetDescriptor(); mirror::Class* array_class = class_linker->FindClass(descriptor.c_str(), class_loader); diff --git a/runtime/verifier/reg_type_cache.cc b/runtime/verifier/reg_type_cache.cc index 446dd00..a62e835 100644 --- a/runtime/verifier/reg_type_cache.cc +++ b/runtime/verifier/reg_type_cache.cc @@ -140,9 +140,10 @@ mirror::Class* RegTypeCache::ResolveClass(const char* descriptor, mirror::ClassL // Class was not found, must create new type. // Try resolving class ClassLinker* class_linker = Runtime::Current()->GetClassLinker(); + SirtRef<mirror::ClassLoader> class_loader(Thread::Current(), loader); mirror::Class* klass = NULL; if (can_load_classes_) { - klass = class_linker->FindClass(descriptor, loader); + klass = class_linker->FindClass(descriptor, class_loader); } else { klass = class_linker->LookupClass(descriptor, loader); if (klass != NULL && !klass->IsLoaded()) { |