summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVladimir Marko <vmarko@google.com>2024-05-06 14:43:54 +0200
committerVladimĂ­r Marko <vmarko@google.com>2024-05-09 07:12:59 +0000
commit8e4b50a62ddb7ecfecb3e0caf3cab9f0e35eee76 (patch)
tree70bdb03cba6a1ad3b9c0fb0cccba657e0fbbd398
parent488413f47e7552d067edf9cfd5ceda321fc12f88 (diff)
downloadart-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.cc56
-rw-r--r--runtime/verifier/reg_type_cache.cc42
-rw-r--r--runtime/verifier/reg_type_cache.h13
-rw-r--r--runtime/verifier/reg_type_test.cc71
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_ = &reg_types_.FromDescriptor(class_loader_.Get(), descriptor, false);
+ declaring_class_ = &reg_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 = &reg_types_.FromDescriptor(class_loader_.Get(), descriptor, false);
+ return_type = &reg_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 = &reg_types_.FromDescriptor(class_loader_.Get(),
- return_type_descriptor,
- false);
+ return_type = &reg_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 = &reg_types_.FromDescriptor(class_loader_.Get(), descriptor, false);
+ result = &reg_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 = &reg_types_.FromDescriptor(
- class_loader_.Get(),
- dex_file_->GetTypeDescriptor(class_idx),
- false);
+ res_method_class =
+ &reg_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 = &reg_types_.FromDescriptor(class_loader_.Get(),
- field_class_descriptor,
- false);
+ const RegType* field_class_type =
+ &reg_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 = &reg_types_.FromDescriptor(class_loader_.Get(), descriptor, false);
+ field_type = &reg_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_ = &reg_types_.FromDescriptor(class_loader_.Get(), descriptor, false);
+ return_type_ = &reg_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.