diff options
author | Vladimir Marko <vmarko@google.com> | 2024-05-06 14:43:54 +0200 |
---|---|---|
committer | VladimĂr Marko <vmarko@google.com> | 2024-05-09 07:12:59 +0000 |
commit | 8e4b50a62ddb7ecfecb3e0caf3cab9f0e35eee76 (patch) | |
tree | 70bdb03cba6a1ad3b9c0fb0cccba657e0fbbd398 | |
parent | 488413f47e7552d067edf9cfd5ceda321fc12f88 (diff) | |
download | art-8e4b50a62ddb7ecfecb3e0caf3cab9f0e35eee76.tar.gz |
Clean up `RegTypeCache::FromDescriptor()` arguments.
Only tests passed `true` as `precise` and most of them do
not really care about that anyway. For the two that do, we
implement a helper function to get a precise `j.l.Object`
reference type the way we would get it for `new Object()`.
Remove the `precise` argument and change the `ClassLoader`
argument to `Handle<>` (also for other functions) to avoid
unnecessary `Handle<>` decoding and re-encoding.
Also clean up `RegTypeCache:From()` which has only one
non-test caller, namely `RegTypeCache::FromDescriptor()`.
Make it private and similarly remove the `precise` argument.
Change tests to use `FromDescriptor()` instead.
Test: m test-art-host-gtest
Test: testrunner.py --host --optimizing
Change-Id: Iab68aea975ec57899d74c728130ece852a810ae7
-rw-r--r-- | runtime/verifier/method_verifier.cc | 56 | ||||
-rw-r--r-- | runtime/verifier/reg_type_cache.cc | 42 | ||||
-rw-r--r-- | runtime/verifier/reg_type_cache.h | 13 | ||||
-rw-r--r-- | runtime/verifier/reg_type_test.cc | 71 |
4 files changed, 91 insertions, 91 deletions
diff --git a/runtime/verifier/method_verifier.cc b/runtime/verifier/method_verifier.cc index aca2b477fc..a9983fa9bc 100644 --- a/runtime/verifier/method_verifier.cc +++ b/runtime/verifier/method_verifier.cc @@ -670,7 +670,7 @@ class MethodVerifier final : public ::art::verifier::MethodVerifier { const dex::MethodId& method_id = dex_file_->GetMethodId(dex_method_idx_); const char* descriptor = dex_file_->GetTypeDescriptor(dex_file_->GetTypeId(method_id.class_idx_)); - declaring_class_ = ®_types_.FromDescriptor(class_loader_.Get(), descriptor, false); + declaring_class_ = ®_types_.FromDescriptor(class_loader_, descriptor); } return *declaring_class_; } @@ -2534,8 +2534,7 @@ bool MethodVerifier<kVerifierDebug>::CodeFlowVerifyInstruction(uint32_t* start_g Fail(VERIFY_ERROR_BAD_CLASS_HARD) << "invalid fill-array-data for array of type " << array_type; } else { - const RegType& component_type = reg_types_.GetComponentType(array_type, - class_loader_.Get()); + const RegType& component_type = reg_types_.GetComponentType(array_type, class_loader_); DCHECK(!component_type.IsConflict()); if (component_type.IsNonZeroReferenceTypes()) { Fail(VERIFY_ERROR_BAD_CLASS_HARD) << "invalid fill-array-data with component type " @@ -2878,7 +2877,7 @@ bool MethodVerifier<kVerifierDebug>::CodeFlowVerifyInstruction(uint32_t* start_g dex::TypeIndex return_type_idx = dex_file_->GetProtoId(method_id.proto_idx_).return_type_idx_; const char* descriptor = dex_file_->GetTypeDescriptor(return_type_idx); - return_type = ®_types_.FromDescriptor(class_loader_.Get(), descriptor, false); + return_type = ®_types_.FromDescriptor(class_loader_, descriptor); } if (!return_type->IsLowHalf()) { work_line_->SetResultRegisterType(this, *return_type); @@ -2958,9 +2957,7 @@ bool MethodVerifier<kVerifierDebug>::CodeFlowVerifyInstruction(uint32_t* start_g work_line_->MarkRefsAsInitialized(this, this_type); } if (return_type == nullptr) { - return_type = ®_types_.FromDescriptor(class_loader_.Get(), - return_type_descriptor, - false); + return_type = ®_types_.FromDescriptor(class_loader_, return_type_descriptor); } if (!return_type->IsLowHalf()) { work_line_->SetResultRegisterType(this, *return_type); @@ -2984,9 +2981,7 @@ bool MethodVerifier<kVerifierDebug>::CodeFlowVerifyInstruction(uint32_t* start_g } else { descriptor = called_method->GetReturnTypeDescriptor(); } - const RegType& return_type = reg_types_.FromDescriptor(class_loader_.Get(), - descriptor, - false); + const RegType& return_type = reg_types_.FromDescriptor(class_loader_, descriptor); if (!return_type.IsLowHalf()) { work_line_->SetResultRegisterType(this, return_type); } else { @@ -3041,9 +3036,7 @@ bool MethodVerifier<kVerifierDebug>::CodeFlowVerifyInstruction(uint32_t* start_g } else { descriptor = abs_method->GetReturnTypeDescriptor(); } - const RegType& return_type = reg_types_.FromDescriptor(class_loader_.Get(), - descriptor, - false); + const RegType& return_type = reg_types_.FromDescriptor(class_loader_, descriptor); if (!return_type.IsLowHalf()) { work_line_->SetResultRegisterType(this, return_type); } else { @@ -3076,7 +3069,7 @@ bool MethodVerifier<kVerifierDebug>::CodeFlowVerifyInstruction(uint32_t* start_g const char* return_descriptor = dex_file_->GetReturnTypeDescriptor(dex_file_->GetProtoId(proto_idx)); const RegType& return_type = - reg_types_.FromDescriptor(class_loader_.Get(), return_descriptor, false); + reg_types_.FromDescriptor(class_loader_, return_descriptor); if (!return_type.IsLowHalf()) { work_line_->SetResultRegisterType(this, return_type); } else { @@ -3109,7 +3102,7 @@ bool MethodVerifier<kVerifierDebug>::CodeFlowVerifyInstruction(uint32_t* start_g // Step 3. Propagate return type information const RegType& return_type = - reg_types_.FromDescriptor(class_loader_.Get(), return_descriptor, false); + reg_types_.FromDescriptor(class_loader_, return_descriptor); if (!return_type.IsLowHalf()) { work_line_->SetResultRegisterType(this, return_type); } else { @@ -3618,7 +3611,7 @@ const RegType& MethodVerifier<kVerifierDebug>::ResolveClass(dex::TypeIndex class } } else { const char* descriptor = dex_file_->GetTypeDescriptor(class_idx); - result = ®_types_.FromDescriptor(class_loader_.Get(), descriptor, false); + result = ®_types_.FromDescriptor(class_loader_, descriptor); } DCHECK(result != nullptr); if (result->IsConflict()) { @@ -3941,10 +3934,8 @@ ArtMethod* MethodVerifier<kVerifierDebug>::VerifyInvocationArgsFromIterator( } else { const uint32_t method_idx = GetMethodIdxOfInvoke(inst); const dex::TypeIndex class_idx = dex_file_->GetMethodId(method_idx).class_idx_; - res_method_class = ®_types_.FromDescriptor( - class_loader_.Get(), - dex_file_->GetTypeDescriptor(class_idx), - false); + res_method_class = + ®_types_.FromDescriptor(class_loader_, dex_file_->GetTypeDescriptor(class_idx)); } if (!res_method_class->IsAssignableFrom(adjusted_type, this)) { Fail(adjusted_type.IsUnresolvedTypes() @@ -3981,9 +3972,7 @@ ArtMethod* MethodVerifier<kVerifierDebug>::VerifyInvocationArgsFromIterator( return nullptr; } - const RegType& reg_type = reg_types_.FromDescriptor(class_loader_.Get(), - param_descriptor, - false); + const RegType& reg_type = reg_types_.FromDescriptor(class_loader_, param_descriptor); uint32_t get_reg = is_range ? inst->VRegC() + static_cast<uint32_t>(sig_registers) : arg[sig_registers]; if (reg_type.IsIntegralTypes()) { @@ -4139,10 +4128,8 @@ ArtMethod* MethodVerifier<kVerifierDebug>::VerifyInvocationArgs( // has a vtable entry for the target method. Or the target is on a interface. if (method_type == METHOD_SUPER) { dex::TypeIndex class_idx = dex_file_->GetMethodId(method_idx).class_idx_; - const RegType& reference_type = reg_types_.FromDescriptor( - class_loader_.Get(), - dex_file_->GetTypeDescriptor(class_idx), - false); + const RegType& reference_type = + reg_types_.FromDescriptor(class_loader_, dex_file_->GetTypeDescriptor(class_idx)); if (reference_type.IsUnresolvedTypes()) { // We cannot differentiate on whether this is a class change error or just // a missing method. This will be handled at runtime. @@ -4315,7 +4302,7 @@ void MethodVerifier<kVerifierDebug>::VerifyNewArray(const Instruction* inst, DCHECK(!res_type.IsUnresolvedMergedReference()); // 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_.Get()); + const RegType& expected_type = reg_types_.GetComponentType(res_type, class_loader_); uint32_t arg_count = (is_range) ? inst->VRegA_3rc() : inst->VRegA_35c(); uint32_t arg[5]; if (!is_range) { @@ -4376,7 +4363,7 @@ void MethodVerifier<kVerifierDebug>::VerifyAGet(const Instruction* inst, } } else { /* verify the class */ - const RegType& component_type = reg_types_.GetComponentType(array_type, class_loader_.Get()); + const RegType& component_type = reg_types_.GetComponentType(array_type, class_loader_); if (!component_type.IsReferenceTypes() && !is_primitive) { Fail(VERIFY_ERROR_BAD_CLASS_HARD) << "primitive array type " << array_type << " source for aget-object"; @@ -4498,7 +4485,7 @@ void MethodVerifier<kVerifierDebug>::VerifyAPut(const Instruction* inst, << " because of missing class"; } } else { - const RegType& component_type = reg_types_.GetComponentType(array_type, class_loader_.Get()); + const RegType& component_type = reg_types_.GetComponentType(array_type, class_loader_); const uint32_t vregA = inst->VRegA_23x(); if (is_primitive) { VerifyPrimitivePut(component_type, insn_type, vregA); @@ -4738,9 +4725,8 @@ void MethodVerifier<kVerifierDebug>::VerifyISFieldAccess(const Instruction* inst if (kAccType == FieldAccessType::kAccPut) { const dex::FieldId& field_id = dex_file_->GetFieldId(field_idx); const char* field_class_descriptor = dex_file_->GetFieldDeclaringClassDescriptor(field_id); - const RegType* field_class_type = ®_types_.FromDescriptor(class_loader_.Get(), - field_class_descriptor, - false); + const RegType* field_class_type = + ®_types_.FromDescriptor(class_loader_, field_class_descriptor); if (!field_class_type->Equals(GetDeclaringClass())) { Fail(VERIFY_ERROR_ACCESS_FIELD) << "could not check field put for final field modify of " << field_class_descriptor @@ -4754,7 +4740,7 @@ void MethodVerifier<kVerifierDebug>::VerifyISFieldAccess(const Instruction* inst if (field_type == nullptr) { const dex::FieldId& field_id = dex_file_->GetFieldId(field_idx); const char* descriptor = dex_file_->GetFieldTypeDescriptor(field_id); - field_type = ®_types_.FromDescriptor(class_loader_.Get(), descriptor, false); + field_type = ®_types_.FromDescriptor(class_loader_, descriptor); } DCHECK(field_type != nullptr); const uint32_t vregA = (is_static) ? inst->VRegA_21c() : inst->VRegA_22c(); @@ -4874,7 +4860,7 @@ const RegType& MethodVerifier<kVerifierDebug>::GetMethodReturnType() { const dex::ProtoId& proto_id = dex_file_->GetMethodPrototype(method_id); dex::TypeIndex 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_.Get(), descriptor, false); + return_type_ = ®_types_.FromDescriptor(class_loader_, descriptor); } return *return_type_; } diff --git a/runtime/verifier/reg_type_cache.cc b/runtime/verifier/reg_type_cache.cc index 14022d297f..b7aa1715e1 100644 --- a/runtime/verifier/reg_type_cache.cc +++ b/runtime/verifier/reg_type_cache.cc @@ -84,9 +84,8 @@ void RegTypeCache::FillPrimitiveAndSmallConstantTypes() { new (&allocator_) NullType(null_handle_, "", kNullCacheId); } -const RegType& RegTypeCache::FromDescriptor(ObjPtr<mirror::ClassLoader> loader, - const char* descriptor, - bool precise) { +const RegType& RegTypeCache::FromDescriptor(Handle<mirror::ClassLoader> loader, + const char* descriptor) { if (descriptor[1] == '\0') { switch (descriptor[0]) { case 'Z': @@ -110,7 +109,7 @@ const RegType& RegTypeCache::FromDescriptor(ObjPtr<mirror::ClassLoader> loader, return Conflict(); } } else if (descriptor[0] == 'L' || descriptor[0] == '[') { - return From(loader, descriptor, precise); + return From(loader, descriptor); } else { return Conflict(); } @@ -156,17 +155,15 @@ bool RegTypeCache::MatchDescriptor(size_t idx, const std::string_view& descripto } ObjPtr<mirror::Class> RegTypeCache::ResolveClass(const char* descriptor, - ObjPtr<mirror::ClassLoader> loader) { + Handle<mirror::ClassLoader> loader) { // Class was not found, must create new type. // Try resolving class Thread* self = Thread::Current(); - StackHandleScope<1> hs(self); - Handle<mirror::ClassLoader> class_loader(hs.NewHandle(loader)); ObjPtr<mirror::Class> klass = nullptr; if (can_load_classes_) { - klass = class_linker_->FindClass(self, descriptor, class_loader); + klass = class_linker_->FindClass(self, descriptor, loader); } else { - klass = class_linker_->LookupClass(self, descriptor, loader); + klass = class_linker_->LookupClass(self, descriptor, loader.Get()); if (klass != nullptr && !klass->IsResolved()) { // We found the class but without it being loaded its not safe for use. klass = nullptr; @@ -181,14 +178,12 @@ std::string_view RegTypeCache::AddString(const std::string_view& str) { return std::string_view(ptr, str.length()); } -const RegType& RegTypeCache::From(ObjPtr<mirror::ClassLoader> loader, - const char* descriptor, - bool precise) { +const RegType& RegTypeCache::From(Handle<mirror::ClassLoader> loader, const char* descriptor) { std::string_view sv_descriptor(descriptor); // Try looking up the class in the cache first. We use a std::string_view to avoid // repeated strlen operations on the descriptor. for (size_t i = kNumPrimitivesAndSmallConstants; i < entries_.size(); i++) { - if (MatchDescriptor(i, sv_descriptor, precise)) { + if (MatchDescriptor(i, sv_descriptor, /* precise= */ false)) { return *(entries_[i]); } } @@ -196,17 +191,14 @@ const RegType& RegTypeCache::From(ObjPtr<mirror::ClassLoader> loader, // Try resolving class. ObjPtr<mirror::Class> klass = ResolveClass(descriptor, loader); if (klass != nullptr) { - // Class resolved, first look for the class in the list of entries - // Class was not found, must create new type. - // To pass the verification, the type should be imprecise, - // instantiable or an interface with the precise type set to false. - DCHECK_IMPLIES(precise, klass->IsInstantiable()); - // Create a precise type if: - // 1- Class is final and NOT an interface. a precise interface is meaningless !! - // 2- Precise Flag passed as true. + // Create a precise type if the class cannot be assigned from other types + // (final classes, arrays of final classes and primitive arrays, see + // `Class::CannotBeAssignedFromOtherTypes()`; primitive types should not + // reach this code). + DCHECK(!klass->IsPrimitive()); RegType* entry; // Create an imprecise type if we can't tell for a fact that it is precise. - if (klass->CannotBeAssignedFromOtherTypes() || precise) { + if (klass->CannotBeAssignedFromOtherTypes()) { DCHECK_IMPLIES(klass->IsAbstract(), klass->IsArrayClass()); DCHECK(!klass->IsInterface()); entry = new (&allocator_) PreciseReferenceType(handles_.NewHandle(klass), @@ -587,13 +579,13 @@ const ConstantType& RegTypeCache::FromCat2ConstHi(int32_t value, bool precise) { } const RegType& RegTypeCache::GetComponentType(const RegType& array, - ObjPtr<mirror::ClassLoader> loader) { + Handle<mirror::ClassLoader> loader) { if (!array.IsArrayTypes()) { return Conflict(); } else if (array.IsUnresolvedTypes()) { DCHECK(!array.IsUnresolvedMergedReference()); // Caller must make sure not to ask for this. const std::string descriptor(array.GetDescriptor()); - return FromDescriptor(loader, descriptor.c_str() + 1, false); + return FromDescriptor(loader, descriptor.c_str() + 1); } else { ObjPtr<mirror::Class> klass = array.GetClass()->GetComponentType(); std::string temp; @@ -602,7 +594,7 @@ const RegType& RegTypeCache::GetComponentType(const RegType& array, // Arrays may have erroneous component types, use unresolved in that case. // We assume that the primitive classes are not erroneous, so we know it is a // reference type. - return FromDescriptor(loader, descriptor, false); + return FromDescriptor(loader, descriptor); } else { return FromClass(descriptor, klass, klass->CannotBeAssignedFromOtherTypes()); } diff --git a/runtime/verifier/reg_type_cache.h b/runtime/verifier/reg_type_cache.h index ae8b904ecd..897cfb7809 100644 --- a/runtime/verifier/reg_type_cache.h +++ b/runtime/verifier/reg_type_cache.h @@ -72,8 +72,6 @@ class RegTypeCache { VariableSizedHandleScope& handles, bool can_suspend = true); const art::verifier::RegType& GetFromId(uint16_t id) const; - const RegType& From(ObjPtr<mirror::ClassLoader> loader, const char* descriptor, bool precise) - REQUIRES_SHARED(Locks::mutator_lock_); // Find a RegType, returns null if not found. const RegType* FindClass(ObjPtr<mirror::Class> klass, bool precise) const REQUIRES_SHARED(Locks::mutator_lock_); @@ -91,9 +89,7 @@ class RegTypeCache { REQUIRES_SHARED(Locks::mutator_lock_); const ConstantType& FromCat2ConstHi(int32_t value, bool precise) REQUIRES_SHARED(Locks::mutator_lock_); - const RegType& FromDescriptor(ObjPtr<mirror::ClassLoader> loader, - const char* descriptor, - bool precise) + const RegType& FromDescriptor(Handle<mirror::ClassLoader> loader, const char* descriptor) REQUIRES_SHARED(Locks::mutator_lock_); const RegType& FromUnresolvedMerge(const RegType& left, const RegType& right, @@ -148,7 +144,7 @@ class RegTypeCache { const ImpreciseConstType& IntConstant() REQUIRES_SHARED(Locks::mutator_lock_); const ImpreciseConstType& PosByteConstant() REQUIRES_SHARED(Locks::mutator_lock_); const ImpreciseConstType& PosShortConstant() REQUIRES_SHARED(Locks::mutator_lock_); - const RegType& GetComponentType(const RegType& array, ObjPtr<mirror::ClassLoader> loader) + const RegType& GetComponentType(const RegType& array, Handle<mirror::ClassLoader> loader) REQUIRES_SHARED(Locks::mutator_lock_); void Dump(std::ostream& os) REQUIRES_SHARED(Locks::mutator_lock_); const RegType& RegTypeFromPrimitiveType(Primitive::Type) const; @@ -181,13 +177,16 @@ class RegTypeCache { private: void FillPrimitiveAndSmallConstantTypes() REQUIRES_SHARED(Locks::mutator_lock_); - ObjPtr<mirror::Class> ResolveClass(const char* descriptor, ObjPtr<mirror::ClassLoader> loader) + ObjPtr<mirror::Class> ResolveClass(const char* descriptor, Handle<mirror::ClassLoader> loader) REQUIRES_SHARED(Locks::mutator_lock_); bool MatchDescriptor(size_t idx, const std::string_view& descriptor, bool precise) REQUIRES_SHARED(Locks::mutator_lock_); const ConstantType& FromCat1NonSmallConstant(int32_t value, bool precise) REQUIRES_SHARED(Locks::mutator_lock_); + const RegType& From(Handle<mirror::ClassLoader> loader, const char* descriptor) + REQUIRES_SHARED(Locks::mutator_lock_); + // Returns the pass in RegType. template <class RegTypeType> RegTypeType& AddEntry(RegTypeType* new_entry) REQUIRES_SHARED(Locks::mutator_lock_); diff --git a/runtime/verifier/reg_type_test.cc b/runtime/verifier/reg_type_test.cc index ec4c23ee59..052eae76e2 100644 --- a/runtime/verifier/reg_type_test.cc +++ b/runtime/verifier/reg_type_test.cc @@ -36,6 +36,19 @@ class RegTypeTest : public CommonRuntimeTest { RegTypeTest() { use_boot_image_ = true; // Make the Runtime creation cheaper. } + + static const RegType& PreciseJavaLangObjectFromDescriptor(RegTypeCache* cache, + Handle<mirror::ClassLoader> loader) + REQUIRES_SHARED(Locks::mutator_lock_) { + // To create a precise `java.lang.Object` reference from a descriptor, go through + // `Uninitialized()` and `FromUninitialized()` as we would for `new Object()`. + const RegType& imprecise_obj = cache->FromDescriptor(loader, "Ljava/lang/Object;"); + CHECK(!imprecise_obj.IsPreciseReference()); + const RegType& precise_obj = + cache->FromUninitialized(cache->Uninitialized(imprecise_obj, /* allocation_pc= */ 0u)); + CHECK(precise_obj.IsPreciseReference()); + return precise_obj; + } }; TEST_F(RegTypeTest, ConstLoHi) { @@ -368,18 +381,19 @@ TEST_F(RegTypeTest, Primitives) { class RegTypeReferenceTest : public RegTypeTest {}; -TEST_F(RegTypeReferenceTest, JavalangObjectImprecise) { +TEST_F(RegTypeReferenceTest, JavaLangObjectImprecise) { // Tests matching precisions. A reference type that was created precise doesn't // match the one that is imprecise. ArenaStack stack(Runtime::Current()->GetArenaPool()); ScopedArenaAllocator allocator(&stack); ScopedObjectAccess soa(Thread::Current()); VariableSizedHandleScope handles(soa.Self()); + ScopedNullHandle<mirror::ClassLoader> loader; RegTypeCache cache( Runtime::Current()->GetClassLinker(), /* can_load_classes= */ true, allocator, handles); const RegType& imprecise_obj = cache.JavaLangObject(false); const RegType& precise_obj = cache.JavaLangObject(true); - const RegType& precise_obj_2 = cache.FromDescriptor(nullptr, "Ljava/lang/Object;", true); + const RegType& precise_obj_2 = PreciseJavaLangObjectFromDescriptor(&cache, loader); EXPECT_TRUE(precise_obj.Equals(precise_obj_2)); EXPECT_FALSE(imprecise_obj.Equals(precise_obj)); @@ -394,13 +408,14 @@ TEST_F(RegTypeReferenceTest, UnresolvedType) { ScopedArenaAllocator allocator(&stack); ScopedObjectAccess soa(Thread::Current()); VariableSizedHandleScope handles(soa.Self()); + ScopedNullHandle<mirror::ClassLoader> loader; RegTypeCache cache( Runtime::Current()->GetClassLinker(), /* can_load_classes= */ true, allocator, handles); - const RegType& ref_type_0 = cache.FromDescriptor(nullptr, "Ljava/lang/DoesNotExist;", true); + const RegType& ref_type_0 = cache.FromDescriptor(loader, "Ljava/lang/DoesNotExist;"); EXPECT_TRUE(ref_type_0.IsUnresolvedReference()); EXPECT_TRUE(ref_type_0.IsNonZeroReferenceTypes()); - const RegType& ref_type_1 = cache.FromDescriptor(nullptr, "Ljava/lang/DoesNotExist;", true); + const RegType& ref_type_1 = cache.FromDescriptor(loader, "Ljava/lang/DoesNotExist;"); EXPECT_TRUE(ref_type_0.Equals(ref_type_1)); const RegType& unresolved_super_class = cache.FromUnresolvedSuperClass(ref_type_0); @@ -414,11 +429,12 @@ TEST_F(RegTypeReferenceTest, UnresolvedUnintializedType) { ScopedArenaAllocator allocator(&stack); ScopedObjectAccess soa(Thread::Current()); VariableSizedHandleScope handles(soa.Self()); + ScopedNullHandle<mirror::ClassLoader> loader; RegTypeCache cache( Runtime::Current()->GetClassLinker(), /* can_load_classes= */ true, allocator, handles); - const RegType& ref_type_0 = cache.FromDescriptor(nullptr, "Ljava/lang/DoesNotExist;", true); + const RegType& ref_type_0 = cache.FromDescriptor(loader, "Ljava/lang/DoesNotExist;"); EXPECT_TRUE(ref_type_0.IsUnresolvedReference()); - const RegType& ref_type = cache.FromDescriptor(nullptr, "Ljava/lang/DoesNotExist;", true); + const RegType& ref_type = cache.FromDescriptor(loader, "Ljava/lang/DoesNotExist;"); EXPECT_TRUE(ref_type_0.Equals(ref_type)); // Create an uninitialized type of this unresolved type const RegType& unresolved_unintialised = cache.Uninitialized(ref_type, 1101ull); @@ -440,10 +456,12 @@ TEST_F(RegTypeReferenceTest, Dump) { ScopedArenaAllocator allocator(&stack); ScopedObjectAccess soa(Thread::Current()); VariableSizedHandleScope handles(soa.Self()); + ScopedNullHandle<mirror::ClassLoader> loader; RegTypeCache cache( Runtime::Current()->GetClassLinker(), /* can_load_classes= */ true, allocator, handles); - const RegType& unresolved_ref = cache.FromDescriptor(nullptr, "Ljava/lang/DoesNotExist;", true); - const RegType& unresolved_ref_another = cache.FromDescriptor(nullptr, "Ljava/lang/DoesNotExistEither;", true); + const RegType& unresolved_ref = cache.FromDescriptor(loader, "Ljava/lang/DoesNotExist;"); + const RegType& unresolved_ref_another = + cache.FromDescriptor(loader, "Ljava/lang/DoesNotExistEither;"); const RegType& resolved_ref = cache.JavaLangString(); const RegType& resolved_unintialiesd = cache.Uninitialized(resolved_ref, 10); const RegType& unresolved_unintialized = cache.Uninitialized(unresolved_ref, 12); @@ -470,11 +488,12 @@ TEST_F(RegTypeReferenceTest, JavalangString) { ScopedArenaAllocator allocator(&stack); ScopedObjectAccess soa(Thread::Current()); VariableSizedHandleScope handles(soa.Self()); + ScopedNullHandle<mirror::ClassLoader> loader; RegTypeCache cache( Runtime::Current()->GetClassLinker(), /* can_load_classes= */ true, allocator, handles); const RegType& ref_type = cache.JavaLangString(); const RegType& ref_type_2 = cache.JavaLangString(); - const RegType& ref_type_3 = cache.FromDescriptor(nullptr, "Ljava/lang/String;", true); + const RegType& ref_type_3 = cache.FromDescriptor(loader, "Ljava/lang/String;"); EXPECT_TRUE(ref_type.Equals(ref_type_2)); EXPECT_TRUE(ref_type_2.Equals(ref_type_3)); @@ -494,11 +513,12 @@ TEST_F(RegTypeReferenceTest, JavalangObject) { ScopedArenaAllocator allocator(&stack); ScopedObjectAccess soa(Thread::Current()); VariableSizedHandleScope handles(soa.Self()); + ScopedNullHandle<mirror::ClassLoader> loader; RegTypeCache cache( Runtime::Current()->GetClassLinker(), /* can_load_classes= */ true, allocator, handles); const RegType& ref_type = cache.JavaLangObject(true); const RegType& ref_type_2 = cache.JavaLangObject(true); - const RegType& ref_type_3 = cache.FromDescriptor(nullptr, "Ljava/lang/Object;", true); + const RegType& ref_type_3 = PreciseJavaLangObjectFromDescriptor(&cache, loader); EXPECT_TRUE(ref_type.Equals(ref_type_2)); EXPECT_TRUE(ref_type_3.Equals(ref_type_2)); @@ -511,15 +531,16 @@ TEST_F(RegTypeReferenceTest, Merging) { ArenaStack stack(Runtime::Current()->GetArenaPool()); ScopedArenaAllocator allocator(&stack); VariableSizedHandleScope handles(soa.Self()); + ScopedNullHandle<mirror::ClassLoader> loader; RegTypeCache cache_new( Runtime::Current()->GetClassLinker(), /* can_load_classes= */ true, allocator, handles); const RegType& string = cache_new.JavaLangString(); const RegType& Object = cache_new.JavaLangObject(true); EXPECT_TRUE(string.Merge(Object, &cache_new, /* verifier= */ nullptr).IsJavaLangObject()); // Merge two unresolved types. - const RegType& ref_type_0 = cache_new.FromDescriptor(nullptr, "Ljava/lang/DoesNotExist;", true); + const RegType& ref_type_0 = cache_new.FromDescriptor(loader, "Ljava/lang/DoesNotExist;"); EXPECT_TRUE(ref_type_0.IsUnresolvedReference()); - const RegType& ref_type_1 = cache_new.FromDescriptor(nullptr, "Ljava/lang/DoesNotExistToo;", true); + const RegType& ref_type_1 = cache_new.FromDescriptor(loader, "Ljava/lang/DoesNotExistToo;"); EXPECT_FALSE(ref_type_0.Equals(ref_type_1)); const RegType& merged = ref_type_1.Merge(ref_type_0, &cache_new, /* verifier= */ nullptr); @@ -751,6 +772,7 @@ TEST_F(RegTypeTest, MergeSemiLatticeRef) { ScopedDisableMovingGC no_gc(soa.Self()); VariableSizedHandleScope handles(soa.Self()); + ScopedNullHandle<mirror::ClassLoader> loader; RegTypeCache cache( Runtime::Current()->GetClassLinker(), /* can_load_classes= */ true, allocator, handles); @@ -760,12 +782,12 @@ TEST_F(RegTypeTest, MergeSemiLatticeRef) { const RegType& int_type = cache.Integer(); const RegType& obj = cache.JavaLangObject(false); - const RegType& obj_arr = cache.From(nullptr, "[Ljava/lang/Object;", false); + const RegType& obj_arr = cache.FromDescriptor(loader, "[Ljava/lang/Object;"); ASSERT_FALSE(obj_arr.IsUnresolvedReference()); - const RegType& unresolved_a = cache.From(nullptr, "Ldoes/not/resolve/A;", false); + const RegType& unresolved_a = cache.FromDescriptor(loader, "Ldoes/not/resolve/A;"); ASSERT_TRUE(unresolved_a.IsUnresolvedReference()); - const RegType& unresolved_b = cache.From(nullptr, "Ldoes/not/resolve/B;", false); + const RegType& unresolved_b = cache.FromDescriptor(loader, "Ldoes/not/resolve/B;"); ASSERT_TRUE(unresolved_b.IsUnresolvedReference()); const RegType& unresolved_ab = cache.FromUnresolvedMerge(unresolved_a, unresolved_b, nullptr); ASSERT_TRUE(unresolved_ab.IsUnresolvedMergedReference()); @@ -778,25 +800,25 @@ TEST_F(RegTypeTest, MergeSemiLatticeRef) { const RegType& uninit_unres_a_0 = cache.Uninitialized(unresolved_a, 0); const RegType& uninit_unres_b_0 = cache.Uninitialized(unresolved_b, 0); - const RegType& number = cache.From(nullptr, "Ljava/lang/Number;", false); + const RegType& number = cache.FromDescriptor(loader, "Ljava/lang/Number;"); ASSERT_FALSE(number.IsUnresolvedReference()); - const RegType& integer = cache.From(nullptr, "Ljava/lang/Integer;", false); + const RegType& integer = cache.FromDescriptor(loader, "Ljava/lang/Integer;"); ASSERT_FALSE(integer.IsUnresolvedReference()); const RegType& uninit_number_0 = cache.Uninitialized(number, 0u); const RegType& uninit_integer_0 = cache.Uninitialized(integer, 0u); - const RegType& number_arr = cache.From(nullptr, "[Ljava/lang/Number;", false); + const RegType& number_arr = cache.FromDescriptor(loader, "[Ljava/lang/Number;"); ASSERT_FALSE(number_arr.IsUnresolvedReference()); - const RegType& integer_arr = cache.From(nullptr, "[Ljava/lang/Integer;", false); + const RegType& integer_arr = cache.FromDescriptor(loader, "[Ljava/lang/Integer;"); ASSERT_FALSE(integer_arr.IsUnresolvedReference()); - const RegType& number_arr_arr = cache.From(nullptr, "[[Ljava/lang/Number;", false); + const RegType& number_arr_arr = cache.FromDescriptor(loader, "[[Ljava/lang/Number;"); ASSERT_FALSE(number_arr_arr.IsUnresolvedReference()); - const RegType& char_arr = cache.From(nullptr, "[C", false); + const RegType& char_arr = cache.FromDescriptor(loader, "[C"); ASSERT_FALSE(char_arr.IsUnresolvedReference()); - const RegType& byte_arr = cache.From(nullptr, "[B", false); + const RegType& byte_arr = cache.FromDescriptor(loader, "[B"); ASSERT_FALSE(byte_arr.IsUnresolvedReference()); const RegType& unresolved_a_num = cache.FromUnresolvedMerge(unresolved_a, number, nullptr); @@ -1118,11 +1140,12 @@ TEST_F(RegTypeOOMTest, ClassJoinOOM) { constexpr const char* kNumberArrayFive = "[[[[[Ljava/lang/Number;"; VariableSizedHandleScope handles(soa.Self()); + ScopedNullHandle<mirror::ClassLoader> loader; RegTypeCache cache( Runtime::Current()->GetClassLinker(), /* can_load_classes= */ true, allocator, handles); - const RegType& int_array_array = cache.From(nullptr, kIntArrayFive, false); + const RegType& int_array_array = cache.FromDescriptor(loader, kIntArrayFive); ASSERT_TRUE(int_array_array.HasClass()); - const RegType& float_array_array = cache.From(nullptr, kFloatArrayFive, false); + const RegType& float_array_array = cache.FromDescriptor(loader, kFloatArrayFive); ASSERT_TRUE(float_array_array.HasClass()); // Check assumptions: the joined classes don't exist, yet. |