Refactor ClassLinker::FindPrimitiveClass().
Introduce ClassLinker::LookupPrimitiveClass() that never
throws an exception and use it to clean up callers that
are not supposed to cause thread suspension.
Test: m test-art-host-gtest
Bug: 118909457
Change-Id: Ibfee8b7991c4a0d1fa636c85f14437c9865d1658
diff --git a/runtime/class_linker.cc b/runtime/class_linker.cc
index 9ba52c4..7ccfff1 100644
--- a/runtime/class_linker.cc
+++ b/runtime/class_linker.cc
@@ -4011,33 +4011,31 @@
return existing;
}
-ObjPtr<mirror::Class> ClassLinker::FindPrimitiveClass(char type) {
- ObjPtr<mirror::ObjectArray<mirror::Class>> class_roots = GetClassRoots();
+ObjPtr<mirror::Class> ClassLinker::LookupPrimitiveClass(char type) {
+ ClassRoot class_root;
switch (type) {
- case 'B':
- return GetClassRoot(ClassRoot::kPrimitiveByte, class_roots);
- case 'C':
- return GetClassRoot(ClassRoot::kPrimitiveChar, class_roots);
- case 'D':
- return GetClassRoot(ClassRoot::kPrimitiveDouble, class_roots);
- case 'F':
- return GetClassRoot(ClassRoot::kPrimitiveFloat, class_roots);
- case 'I':
- return GetClassRoot(ClassRoot::kPrimitiveInt, class_roots);
- case 'J':
- return GetClassRoot(ClassRoot::kPrimitiveLong, class_roots);
- case 'S':
- return GetClassRoot(ClassRoot::kPrimitiveShort, class_roots);
- case 'Z':
- return GetClassRoot(ClassRoot::kPrimitiveBoolean, class_roots);
- case 'V':
- return GetClassRoot(ClassRoot::kPrimitiveVoid, class_roots);
+ case 'B': class_root = ClassRoot::kPrimitiveByte; break;
+ case 'C': class_root = ClassRoot::kPrimitiveChar; break;
+ case 'D': class_root = ClassRoot::kPrimitiveDouble; break;
+ case 'F': class_root = ClassRoot::kPrimitiveFloat; break;
+ case 'I': class_root = ClassRoot::kPrimitiveInt; break;
+ case 'J': class_root = ClassRoot::kPrimitiveLong; break;
+ case 'S': class_root = ClassRoot::kPrimitiveShort; break;
+ case 'Z': class_root = ClassRoot::kPrimitiveBoolean; break;
+ case 'V': class_root = ClassRoot::kPrimitiveVoid; break;
default:
- break;
+ return nullptr;
}
- std::string printable_type(PrintableChar(type));
- ThrowNoClassDefFoundError("Not a primitive type: %s", printable_type.c_str());
- return nullptr;
+ return GetClassRoot(class_root, this);
+}
+
+ObjPtr<mirror::Class> ClassLinker::FindPrimitiveClass(char type) {
+ ObjPtr<mirror::Class> result = LookupPrimitiveClass(type);
+ if (UNLIKELY(result == nullptr)) {
+ std::string printable_type(PrintableChar(type));
+ ThrowNoClassDefFoundError("Not a primitive type: %s", printable_type.c_str());
+ }
+ return result;
}
ObjPtr<mirror::Class> ClassLinker::InsertClass(const char* descriptor,
@@ -8033,7 +8031,7 @@
if (descriptor[1] == '\0') {
// only the descriptors of primitive types should be 1 character long, also avoid class lookup
// for primitive classes that aren't backed by dex files.
- type = FindPrimitiveClass(descriptor[0]);
+ type = LookupPrimitiveClass(descriptor[0]);
} else {
Thread* const self = Thread::Current();
DCHECK(self != nullptr);
@@ -8562,7 +8560,7 @@
switch (handle_type) {
case DexFile::MethodHandleType::kStaticPut: {
method_params->Set(0, target_field->ResolveType());
- return_type = hs.NewHandle(FindPrimitiveClass('V'));
+ return_type = hs.NewHandle(GetClassRoot(ClassRoot::kPrimitiveVoid, this));
break;
}
case DexFile::MethodHandleType::kStaticGet: {
@@ -8572,7 +8570,7 @@
case DexFile::MethodHandleType::kInstancePut: {
method_params->Set(0, target_field->GetDeclaringClass());
method_params->Set(1, target_field->ResolveType());
- return_type = hs.NewHandle(FindPrimitiveClass('V'));
+ return_type = hs.NewHandle(GetClassRoot(ClassRoot::kPrimitiveVoid, this));
break;
}
case DexFile::MethodHandleType::kInstanceGet: {
diff --git a/runtime/class_linker.h b/runtime/class_linker.h
index 7afd575..60e68d5 100644
--- a/runtime/class_linker.h
+++ b/runtime/class_linker.h
@@ -196,6 +196,7 @@
REQUIRES(!Locks::classlinker_classes_lock_)
REQUIRES_SHARED(Locks::mutator_lock_);
+ ObjPtr<mirror::Class> LookupPrimitiveClass(char type) REQUIRES_SHARED(Locks::mutator_lock_);
ObjPtr<mirror::Class> FindPrimitiveClass(char type) REQUIRES_SHARED(Locks::mutator_lock_);
void DumpForSigQuit(std::ostream& os) REQUIRES(!Locks::classlinker_classes_lock_);
diff --git a/runtime/native/dalvik_system_VMRuntime.cc b/runtime/native/dalvik_system_VMRuntime.cc
index 32b88e6..49b71cd 100644
--- a/runtime/native/dalvik_system_VMRuntime.cc
+++ b/runtime/native/dalvik_system_VMRuntime.cc
@@ -371,7 +371,7 @@
const char* class_name = dex_file->StringByTypeIdx(type_idx);
ClassLinker* linker = Runtime::Current()->GetClassLinker();
ObjPtr<mirror::Class> klass = (class_name[1] == '\0')
- ? linker->FindPrimitiveClass(class_name[0])
+ ? linker->LookupPrimitiveClass(class_name[0])
: linker->LookupClass(self, class_name, nullptr);
if (klass == nullptr) {
return;
diff --git a/runtime/native/java_lang_reflect_Field.cc b/runtime/native/java_lang_reflect_Field.cc
index b9ac88d..f21ded9 100644
--- a/runtime/native/java_lang_reflect_Field.cc
+++ b/runtime/native/java_lang_reflect_Field.cc
@@ -334,14 +334,15 @@
return;
}
ObjPtr<mirror::Class> field_type;
- const char* field_type_desciptor = f->GetArtField()->GetTypeDescriptor();
- Primitive::Type field_prim_type = Primitive::GetType(field_type_desciptor[0]);
+ const char* field_type_descriptor = f->GetArtField()->GetTypeDescriptor();
+ Primitive::Type field_prim_type = Primitive::GetType(field_type_descriptor[0]);
if (field_prim_type == Primitive::kPrimNot) {
field_type = f->GetType();
- DCHECK(field_type != nullptr);
} else {
- field_type = Runtime::Current()->GetClassLinker()->FindPrimitiveClass(field_type_desciptor[0]);
+ field_type =
+ Runtime::Current()->GetClassLinker()->LookupPrimitiveClass(field_type_descriptor[0]);
}
+ DCHECK(field_type != nullptr) << field_type_descriptor;
// We now don't expect suspension unless an exception is thrown.
// Unbox the value, if necessary.
ObjPtr<mirror::Object> boxed_value = soa.Decode<mirror::Object>(javaValue);
diff --git a/runtime/reflection.cc b/runtime/reflection.cc
index 646de75..8011836 100644
--- a/runtime/reflection.cc
+++ b/runtime/reflection.cc
@@ -886,32 +886,31 @@
JValue boxed_value;
ObjPtr<mirror::Class> klass = o->GetClass();
- ObjPtr<mirror::Class> src_class = nullptr;
- ClassLinker* const class_linker = Runtime::Current()->GetClassLinker();
+ Primitive::Type primitive_type;
ArtField* primitive_field = &klass->GetIFieldsPtr()->At(0);
if (klass->DescriptorEquals("Ljava/lang/Boolean;")) {
- src_class = class_linker->FindPrimitiveClass('Z');
+ primitive_type = Primitive::kPrimBoolean;
boxed_value.SetZ(primitive_field->GetBoolean(o));
} else if (klass->DescriptorEquals("Ljava/lang/Byte;")) {
- src_class = class_linker->FindPrimitiveClass('B');
+ primitive_type = Primitive::kPrimByte;
boxed_value.SetB(primitive_field->GetByte(o));
} else if (klass->DescriptorEquals("Ljava/lang/Character;")) {
- src_class = class_linker->FindPrimitiveClass('C');
+ primitive_type = Primitive::kPrimChar;
boxed_value.SetC(primitive_field->GetChar(o));
} else if (klass->DescriptorEquals("Ljava/lang/Float;")) {
- src_class = class_linker->FindPrimitiveClass('F');
+ primitive_type = Primitive::kPrimFloat;
boxed_value.SetF(primitive_field->GetFloat(o));
} else if (klass->DescriptorEquals("Ljava/lang/Double;")) {
- src_class = class_linker->FindPrimitiveClass('D');
+ primitive_type = Primitive::kPrimDouble;
boxed_value.SetD(primitive_field->GetDouble(o));
} else if (klass->DescriptorEquals("Ljava/lang/Integer;")) {
- src_class = class_linker->FindPrimitiveClass('I');
+ primitive_type = Primitive::kPrimInt;
boxed_value.SetI(primitive_field->GetInt(o));
} else if (klass->DescriptorEquals("Ljava/lang/Long;")) {
- src_class = class_linker->FindPrimitiveClass('J');
+ primitive_type = Primitive::kPrimLong;
boxed_value.SetJ(primitive_field->GetLong(o));
} else if (klass->DescriptorEquals("Ljava/lang/Short;")) {
- src_class = class_linker->FindPrimitiveClass('S');
+ primitive_type = Primitive::kPrimShort;
boxed_value.SetS(primitive_field->GetShort(o));
} else {
std::string temp;
@@ -923,7 +922,8 @@
}
return ConvertPrimitiveValue(unbox_for_result,
- src_class->GetPrimitiveType(), dst_class->GetPrimitiveType(),
+ primitive_type,
+ dst_class->GetPrimitiveType(),
boxed_value, unboxed_value);
}