Add Class.getPrimitiveClass().
Implement the native part in ART and remove the native parts
of the previously needed workaround for java.lang.Void.TYPE.
Companion libcore/ change:
https://android-review.googlesource.com/619326
Test: m test-art-host-gtest
Test: testrunner.py --host --optimizing
Test: Pixel 2 XL boots.
Bug: 73346078
Change-Id: Icfb201a1f08d8ff2a65c58f7c0ec25aa2296db29
diff --git a/runtime/mirror/class.cc b/runtime/mirror/class.cc
index 9246bae..5d730ce 100644
--- a/runtime/mirror/class.cc
+++ b/runtime/mirror/class.cc
@@ -72,6 +72,42 @@
java_lang_Class_.VisitRootIfNonNull(visitor, RootInfo(kRootStickyClass));
}
+ObjPtr<mirror::Class> Class::GetPrimitiveClass(ObjPtr<mirror::String> name) {
+ const char* expected_name = nullptr;
+ ClassLinker::ClassRoot class_root = ClassLinker::kJavaLangObject; // Invalid.
+ if (name != nullptr && name->GetLength() >= 2) {
+ // Perfect hash for the expected values: from the second letters of the primitive types,
+ // only 'y' has the bit 0x10 set, so use it to change 'b' to 'B'.
+ char hash = name->CharAt(0) ^ ((name->CharAt(1) & 0x10) << 1);
+ switch (hash) {
+ case 'b': expected_name = "boolean"; class_root = ClassLinker::kPrimitiveBoolean; break;
+ case 'B': expected_name = "byte"; class_root = ClassLinker::kPrimitiveByte; break;
+ case 'c': expected_name = "char"; class_root = ClassLinker::kPrimitiveChar; break;
+ case 'd': expected_name = "double"; class_root = ClassLinker::kPrimitiveDouble; break;
+ case 'f': expected_name = "float"; class_root = ClassLinker::kPrimitiveFloat; break;
+ case 'i': expected_name = "int"; class_root = ClassLinker::kPrimitiveInt; break;
+ case 'l': expected_name = "long"; class_root = ClassLinker::kPrimitiveLong; break;
+ case 's': expected_name = "short"; class_root = ClassLinker::kPrimitiveShort; break;
+ case 'v': expected_name = "void"; class_root = ClassLinker::kPrimitiveVoid; break;
+ default: break;
+ }
+ }
+ if (expected_name != nullptr && name->Equals(expected_name)) {
+ ObjPtr<mirror::Class> klass = Runtime::Current()->GetClassLinker()->GetClassRoot(class_root);
+ DCHECK(klass != nullptr);
+ return klass;
+ } else {
+ Thread* self = Thread::Current();
+ if (name == nullptr) {
+ // Note: ThrowNullPointerException() requires a message which we deliberately want to omit.
+ self->ThrowNewException("Ljava/lang/NullPointerException;", /* msg */ nullptr);
+ } else {
+ self->ThrowNewException("Ljava/lang/ClassNotFoundException;", name->ToModifiedUtf8().c_str());
+ }
+ return nullptr;
+ }
+}
+
ClassExt* Class::EnsureExtDataPresent(Thread* self) {
ObjPtr<ClassExt> existing(GetExtData());
if (!existing.IsNull()) {