diff options
author | 2018-02-15 10:41:07 +0000 | |
---|---|---|
committer | 2018-02-15 15:36:21 +0000 | |
commit | 7287c4d75e38e7a01c7ea3fdebb47d9cfe128a56 (patch) | |
tree | 2b43d1b334e05e1c5719fee3f2a16bebaff059d9 | |
parent | 1efa7cb8c415f4df8a248242cd773a1fc671878e (diff) |
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
-rw-r--r-- | runtime/Android.bp | 1 | ||||
-rw-r--r-- | runtime/interpreter/unstarted_runtime.cc | 20 | ||||
-rw-r--r-- | runtime/interpreter/unstarted_runtime_list.h | 2 | ||||
-rw-r--r-- | runtime/mirror/class.cc | 36 | ||||
-rw-r--r-- | runtime/mirror/class.h | 4 | ||||
-rw-r--r-- | runtime/native/java_lang_Class.cc | 7 | ||||
-rw-r--r-- | runtime/native/java_lang_Void.cc | 43 | ||||
-rw-r--r-- | runtime/native/java_lang_Void.h | 28 | ||||
-rw-r--r-- | runtime/runtime.cc | 2 |
9 files changed, 62 insertions, 81 deletions
diff --git a/runtime/Android.bp b/runtime/Android.bp index 832d50e691..4c706c3dcd 100644 --- a/runtime/Android.bp +++ b/runtime/Android.bp @@ -244,7 +244,6 @@ cc_defaults { "native/java_lang_Thread.cc", "native/java_lang_Throwable.cc", "native/java_lang_VMClassLoader.cc", - "native/java_lang_Void.cc", "native/java_lang_invoke_MethodHandleImpl.cc", "native/java_lang_ref_FinalizerReference.cc", "native/java_lang_ref_Reference.cc", diff --git a/runtime/interpreter/unstarted_runtime.cc b/runtime/interpreter/unstarted_runtime.cc index 85acc71377..f8dd8293ca 100644 --- a/runtime/interpreter/unstarted_runtime.cc +++ b/runtime/interpreter/unstarted_runtime.cc @@ -235,6 +235,20 @@ void UnstartedRuntime::UnstartedClassForNameLong( UnstartedClassForNameCommon(self, shadow_frame, result, arg_offset, true, "Class.forName"); } +void UnstartedRuntime::UnstartedClassGetPrimitiveClass( + Thread* self, ShadowFrame* shadow_frame, JValue* result, size_t arg_offset) { + ObjPtr<mirror::String> class_name = GetClassName(self, shadow_frame, arg_offset); + ObjPtr<mirror::Class> klass = mirror::Class::GetPrimitiveClass(class_name); + if (UNLIKELY(klass == nullptr)) { + DCHECK(self->IsExceptionPending()); + AbortTransactionOrFail(self, + "Class.getPrimitiveClass() failed: %s", + self->GetException()->GetDetailMessage()->ToModifiedUtf8().c_str()); + return; + } + result->SetL(klass); +} + void UnstartedRuntime::UnstartedClassClassForName( Thread* self, ShadowFrame* shadow_frame, JValue* result, size_t arg_offset) { UnstartedClassForNameCommon(self, shadow_frame, result, arg_offset, true, "Class.classForName"); @@ -738,12 +752,6 @@ void UnstartedRuntime::UnstartedVmClassLoaderFindLoadedClass( } } -void UnstartedRuntime::UnstartedVoidLookupType( - Thread* self ATTRIBUTE_UNUSED, ShadowFrame* shadow_frame ATTRIBUTE_UNUSED, JValue* result, - size_t arg_offset ATTRIBUTE_UNUSED) { - result->SetL(Runtime::Current()->GetClassLinker()->FindPrimitiveClass('V')); -} - // Arraycopy emulation. // Note: we can't use any fast copy functions, as they are not available under transaction. diff --git a/runtime/interpreter/unstarted_runtime_list.h b/runtime/interpreter/unstarted_runtime_list.h index c029e07432..3cc598aed7 100644 --- a/runtime/interpreter/unstarted_runtime_list.h +++ b/runtime/interpreter/unstarted_runtime_list.h @@ -23,6 +23,7 @@ V(CharacterToUpperCase, "int java.lang.Character.toUpperCase(int)") \ V(ClassForName, "java.lang.Class java.lang.Class.forName(java.lang.String)") \ V(ClassForNameLong, "java.lang.Class java.lang.Class.forName(java.lang.String, boolean, java.lang.ClassLoader)") \ + V(ClassGetPrimitiveClass, "java.lang.Class java.lang.Class.getPrimitiveClass(java.lang.String)") \ V(ClassClassForName, "java.lang.Class java.lang.Class.classForName(java.lang.String, boolean, java.lang.ClassLoader)") \ V(ClassNewInstance, "java.lang.Object java.lang.Class.newInstance()") \ V(ClassGetDeclaredField, "java.lang.reflect.Field java.lang.Class.getDeclaredField(java.lang.String)") \ @@ -36,7 +37,6 @@ V(ClassLoaderGetResourceAsStream, "java.io.InputStream java.lang.ClassLoader.getResourceAsStream(java.lang.String)") \ V(ConstructorNewInstance0, "java.lang.Object java.lang.reflect.Constructor.newInstance0(java.lang.Object[])") \ V(VmClassLoaderFindLoadedClass, "java.lang.Class java.lang.VMClassLoader.findLoadedClass(java.lang.ClassLoader, java.lang.String)") \ - V(VoidLookupType, "java.lang.Class java.lang.Void.lookupType()") \ V(SystemArraycopy, "void java.lang.System.arraycopy(java.lang.Object, int, java.lang.Object, int, int)") \ V(SystemArraycopyByte, "void java.lang.System.arraycopy(byte[], int, byte[], int, int)") \ V(SystemArraycopyChar, "void java.lang.System.arraycopy(char[], int, char[], int, int)") \ diff --git a/runtime/mirror/class.cc b/runtime/mirror/class.cc index 9246bae4a6..5d730ce0b0 100644 --- a/runtime/mirror/class.cc +++ b/runtime/mirror/class.cc @@ -72,6 +72,42 @@ void Class::VisitRoots(RootVisitor* visitor) { 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()) { diff --git a/runtime/mirror/class.h b/runtime/mirror/class.h index b5deffb77b..b9a31e54b7 100644 --- a/runtime/mirror/class.h +++ b/runtime/mirror/class.h @@ -1134,6 +1134,10 @@ class MANAGED Class FINAL : public Object { void VisitNativeRoots(Visitor& visitor, PointerSize pointer_size) REQUIRES_SHARED(Locks::mutator_lock_); + // Get one of the primitive classes. + static ObjPtr<mirror::Class> GetPrimitiveClass(ObjPtr<mirror::String> name) + REQUIRES_SHARED(Locks::mutator_lock_); + // When class is verified, set the kAccSkipAccessChecks flag on each method. void SetSkipAccessChecksFlagOnAllMethods(PointerSize pointer_size) REQUIRES_SHARED(Locks::mutator_lock_); diff --git a/runtime/native/java_lang_Class.cc b/runtime/native/java_lang_Class.cc index 4597f68f54..e518553292 100644 --- a/runtime/native/java_lang_Class.cc +++ b/runtime/native/java_lang_Class.cc @@ -176,6 +176,12 @@ static jclass Class_classForName(JNIEnv* env, jclass, jstring javaName, jboolean return soa.AddLocalReference<jclass>(c.Get()); } +static jclass Class_getPrimitiveClass(JNIEnv* env, jclass, jstring name) { + ScopedFastNativeObjectAccess soa(env); + ObjPtr<mirror::Class> klass = mirror::Class::GetPrimitiveClass(soa.Decode<mirror::String>(name)); + return soa.AddLocalReference<jclass>(klass); +} + static jstring Class_getNameNative(JNIEnv* env, jobject javaThis) { ScopedFastNativeObjectAccess soa(env); StackHandleScope<1> hs(soa.Self()); @@ -869,6 +875,7 @@ static JNINativeMethod gMethods[] = { FAST_NATIVE_METHOD(Class, getInnerClassFlags, "(I)I"), FAST_NATIVE_METHOD(Class, getInnerClassName, "()Ljava/lang/String;"), FAST_NATIVE_METHOD(Class, getInterfacesInternal, "()[Ljava/lang/Class;"), + FAST_NATIVE_METHOD(Class, getPrimitiveClass, "(Ljava/lang/String;)Ljava/lang/Class;"), FAST_NATIVE_METHOD(Class, getNameNative, "()Ljava/lang/String;"), FAST_NATIVE_METHOD(Class, getPublicDeclaredFields, "()[Ljava/lang/reflect/Field;"), FAST_NATIVE_METHOD(Class, getSignatureAnnotation, "()[Ljava/lang/String;"), diff --git a/runtime/native/java_lang_Void.cc b/runtime/native/java_lang_Void.cc deleted file mode 100644 index af83dd1a79..0000000000 --- a/runtime/native/java_lang_Void.cc +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Copyright (C) 2017 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "java_lang_Void.h" - -#include "nativehelper/jni_macros.h" - -#include "class_linker-inl.h" -#include "jni_internal.h" -#include "native_util.h" -#include "runtime.h" -#include "scoped_fast_native_object_access-inl.h" - -namespace art { - -static jclass Void_lookupType(JNIEnv* env, jclass) { - ScopedFastNativeObjectAccess soa(env); - return soa.AddLocalReference<jclass>( - Runtime::Current()->GetClassLinker()->GetClassRoot(ClassLinker::kPrimitiveVoid)); -} - -static JNINativeMethod gMethods[] = { - FAST_NATIVE_METHOD(Void, lookupType, "()Ljava/lang/Class;"), -}; - -void register_java_lang_Void(JNIEnv* env) { - REGISTER_NATIVE_METHODS("java/lang/Void"); -} - -} // namespace art diff --git a/runtime/native/java_lang_Void.h b/runtime/native/java_lang_Void.h deleted file mode 100644 index 8777d8068c..0000000000 --- a/runtime/native/java_lang_Void.h +++ /dev/null @@ -1,28 +0,0 @@ -/* - * Copyright (C) 2017 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef ART_RUNTIME_NATIVE_JAVA_LANG_VOID_H_ -#define ART_RUNTIME_NATIVE_JAVA_LANG_VOID_H_ - -#include <jni.h> - -namespace art { - -void register_java_lang_Void(JNIEnv* env); - -} // namespace art - -#endif // ART_RUNTIME_NATIVE_JAVA_LANG_VOID_H_ diff --git a/runtime/runtime.cc b/runtime/runtime.cc index 7aca12e56b..d0aec116a4 100644 --- a/runtime/runtime.cc +++ b/runtime/runtime.cc @@ -120,7 +120,6 @@ #include "native/java_lang_Thread.h" #include "native/java_lang_Throwable.h" #include "native/java_lang_VMClassLoader.h" -#include "native/java_lang_Void.h" #include "native/java_lang_invoke_MethodHandleImpl.h" #include "native/java_lang_ref_FinalizerReference.h" #include "native/java_lang_ref_Reference.h" @@ -1746,7 +1745,6 @@ void Runtime::RegisterRuntimeNativeMethods(JNIEnv* env) { register_java_lang_Thread(env); register_java_lang_Throwable(env); register_java_lang_VMClassLoader(env); - register_java_lang_Void(env); register_java_util_concurrent_atomic_AtomicLong(env); register_libcore_util_CharsetUtils(env); register_org_apache_harmony_dalvik_ddmc_DdmServer(env); |