Refactor ClassRoot/GetClassRoot().
Move it outside the ClassLinker, into its own header file,
and add retrieval based on a mirror class template argument.
Keep the SetClassRoot() as a private member of ClassLinker.
Make the new GetClassRoot()s return ObjPtr<>.
Test: m test-art-host-gtest
Test: testrunner.py --host --optimizing
Bug: 31113334
Change-Id: Icbc6b62b41f6ffd65b437297a21eadbb0454e2b7
diff --git a/runtime/class_root.h b/runtime/class_root.h
new file mode 100644
index 0000000..f43e2c6
--- /dev/null
+++ b/runtime/class_root.h
@@ -0,0 +1,183 @@
+/*
+ * Copyright (C) 2018 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_CLASS_ROOT_H_
+#define ART_RUNTIME_CLASS_ROOT_H_
+
+#include "class_linker.h"
+#include "mirror/class.h"
+#include "mirror/object_array-inl.h"
+#include "obj_ptr-inl.h"
+#include "runtime.h"
+
+namespace art {
+
+namespace mirror {
+class ArrayElementVarHandle;
+class ByteArrayViewVarHandle;
+class ByteBufferViewVarHandle;
+class CallSite;
+class ClassExt;
+class ClassLoader;
+class Constructor;
+class DexCache;
+class EmulatedStackFrame;
+class Field;
+class FieldVarHandle;
+class Method;
+class MethodHandleImpl;
+class MethodHandlesLookup;
+class MethodType;
+class Object;
+class Proxy;
+template<typename T> class PrimitiveArray;
+class Reference;
+class StackTraceElement;
+class String;
+class Throwable;
+class VarHandle;
+} // namespace mirror
+
+#define CLASS_ROOT_LIST(M) \
+ M(kJavaLangClass, "Ljava/lang/Class;", mirror::Class) \
+ M(kJavaLangObject, "Ljava/lang/Object;", mirror::Object) \
+ M(kClassArrayClass, "[Ljava/lang/Class;", mirror::ObjectArray<mirror::Class>) \
+ M(kObjectArrayClass, "[Ljava/lang/Object;", mirror::ObjectArray<mirror::Object>) \
+ M(kJavaLangString, "Ljava/lang/String;", mirror::String) \
+ M(kJavaLangDexCache, "Ljava/lang/DexCache;", mirror::DexCache) \
+ M(kJavaLangRefReference, "Ljava/lang/ref/Reference;", mirror::Reference) \
+ M(kJavaLangReflectConstructor, "Ljava/lang/reflect/Constructor;", mirror::Constructor) \
+ M(kJavaLangReflectField, "Ljava/lang/reflect/Field;", mirror::Field) \
+ M(kJavaLangReflectMethod, "Ljava/lang/reflect/Method;", mirror::Method) \
+ M(kJavaLangReflectProxy, "Ljava/lang/reflect/Proxy;", mirror::Proxy) \
+ M(kJavaLangStringArrayClass, "[Ljava/lang/String;", mirror::ObjectArray<mirror::String>) \
+ M(kJavaLangReflectConstructorArrayClass, "[Ljava/lang/reflect/Constructor;", mirror::ObjectArray<mirror::Constructor>) \
+ M(kJavaLangReflectFieldArrayClass, "[Ljava/lang/reflect/Field;", mirror::ObjectArray<mirror::Field>) \
+ M(kJavaLangReflectMethodArrayClass, "[Ljava/lang/reflect/Method;", mirror::ObjectArray<mirror::Method>) \
+ M(kJavaLangInvokeCallSite, "Ljava/lang/invoke/CallSite;", mirror::CallSite) \
+ M(kJavaLangInvokeMethodHandleImpl, "Ljava/lang/invoke/MethodHandleImpl;", mirror::MethodHandleImpl) \
+ M(kJavaLangInvokeMethodHandlesLookup, "Ljava/lang/invoke/MethodHandles$Lookup;", mirror::MethodHandlesLookup) \
+ M(kJavaLangInvokeMethodType, "Ljava/lang/invoke/MethodType;", mirror::MethodType) \
+ M(kJavaLangInvokeVarHandle, "Ljava/lang/invoke/VarHandle;", mirror::VarHandle) \
+ M(kJavaLangInvokeFieldVarHandle, "Ljava/lang/invoke/FieldVarHandle;", mirror::FieldVarHandle) \
+ M(kJavaLangInvokeArrayElementVarHandle, "Ljava/lang/invoke/ArrayElementVarHandle;", mirror::ArrayElementVarHandle) \
+ M(kJavaLangInvokeByteArrayViewVarHandle, "Ljava/lang/invoke/ByteArrayViewVarHandle;", mirror::ByteArrayViewVarHandle) \
+ M(kJavaLangInvokeByteBufferViewVarHandle, "Ljava/lang/invoke/ByteBufferViewVarHandle;", mirror::ByteBufferViewVarHandle) \
+ M(kJavaLangClassLoader, "Ljava/lang/ClassLoader;", mirror::ClassLoader) \
+ M(kJavaLangThrowable, "Ljava/lang/Throwable;", mirror::Throwable) \
+ M(kJavaLangClassNotFoundException, "Ljava/lang/ClassNotFoundException;", detail::NoMirrorType<detail::ClassNotFoundExceptionTag>) \
+ M(kJavaLangStackTraceElement, "Ljava/lang/StackTraceElement;", mirror::StackTraceElement) \
+ M(kDalvikSystemEmulatedStackFrame, "Ldalvik/system/EmulatedStackFrame;", mirror::EmulatedStackFrame) \
+ M(kPrimitiveBoolean, "Z", detail::NoMirrorType<uint8_t>) \
+ M(kPrimitiveByte, "B", detail::NoMirrorType<int8_t>) \
+ M(kPrimitiveChar, "C", detail::NoMirrorType<uint16_t>) \
+ M(kPrimitiveDouble, "D", detail::NoMirrorType<double>) \
+ M(kPrimitiveFloat, "F", detail::NoMirrorType<float>) \
+ M(kPrimitiveInt, "I", detail::NoMirrorType<int32_t>) \
+ M(kPrimitiveLong, "J", detail::NoMirrorType<int64_t>) \
+ M(kPrimitiveShort, "S", detail::NoMirrorType<int16_t>) \
+ M(kPrimitiveVoid, "V", detail::NoMirrorType<void>) \
+ M(kBooleanArrayClass, "[Z", mirror::PrimitiveArray<uint8_t>) \
+ M(kByteArrayClass, "[B", mirror::PrimitiveArray<int8_t>) \
+ M(kCharArrayClass, "[C", mirror::PrimitiveArray<uint16_t>) \
+ M(kDoubleArrayClass, "[D", mirror::PrimitiveArray<double>) \
+ M(kFloatArrayClass, "[F", mirror::PrimitiveArray<float>) \
+ M(kIntArrayClass, "[I", mirror::PrimitiveArray<int32_t>) \
+ M(kLongArrayClass, "[J", mirror::PrimitiveArray<int64_t>) \
+ M(kShortArrayClass, "[S", mirror::PrimitiveArray<int16_t>) \
+ M(kJavaLangStackTraceElementArrayClass, "[Ljava/lang/StackTraceElement;", mirror::ObjectArray<mirror::StackTraceElement>) \
+ M(kDalvikSystemClassExt, "Ldalvik/system/ClassExt;", mirror::ClassExt)
+
+// Well known mirror::Class roots accessed via ClassLinker::GetClassRoots().
+enum class ClassRoot : uint32_t {
+#define CLASS_ROOT_ENUMERATOR(name, descriptor, mirror_type) name,
+ CLASS_ROOT_LIST(CLASS_ROOT_ENUMERATOR)
+#undef CLASS_ROOT_ENUMERATOR
+ kMax,
+};
+
+const char* GetClassRootDescriptor(ClassRoot class_root);
+
+template <ReadBarrierOption kReadBarrierOption = kWithReadBarrier>
+inline ObjPtr<mirror::Class> GetClassRoot(
+ ClassRoot class_root,
+ ObjPtr<mirror::ObjectArray<mirror::Class>> class_roots) REQUIRES_SHARED(Locks::mutator_lock_) {
+ DCHECK(class_roots != nullptr);
+ if (kReadBarrierOption == kWithReadBarrier) {
+ // With read barrier all references must point to the to-space.
+ // Without read barrier, this check could fail.
+ DCHECK_EQ(class_roots, Runtime::Current()->GetClassLinker()->GetClassRoots());
+ }
+ DCHECK_LT(static_cast<uint32_t>(class_root), static_cast<uint32_t>(ClassRoot::kMax));
+ int32_t index = static_cast<int32_t>(class_root);
+ ObjPtr<mirror::Class> klass =
+ class_roots->GetWithoutChecks<kDefaultVerifyFlags, kReadBarrierOption>(index);
+ DCHECK(klass != nullptr);
+ return klass.Ptr();
+}
+
+template <ReadBarrierOption kReadBarrierOption = kWithReadBarrier>
+inline ObjPtr<mirror::Class> GetClassRoot(ClassRoot class_root, ClassLinker* linker)
+ REQUIRES_SHARED(Locks::mutator_lock_) {
+ return GetClassRoot<kReadBarrierOption>(class_root, linker->GetClassRoots<kReadBarrierOption>());
+}
+
+template <ReadBarrierOption kReadBarrierOption = kWithReadBarrier>
+inline ObjPtr<mirror::Class> GetClassRoot(ClassRoot class_root)
+ REQUIRES_SHARED(Locks::mutator_lock_) {
+ return GetClassRoot<kReadBarrierOption>(class_root, Runtime::Current()->GetClassLinker());
+}
+
+namespace detail {
+
+class ClassNotFoundExceptionTag;
+template <class Tag> struct NoMirrorType;
+
+template <class MirrorType>
+struct ClassRootSelector; // No definition for unspecialized ClassRoot selector.
+
+#define SPECIALIZE_CLASS_ROOT_SELECTOR(name, descriptor, mirror_type) \
+ template <> \
+ struct ClassRootSelector<mirror_type> { \
+ static constexpr ClassRoot value = ClassRoot::name; \
+ };
+
+CLASS_ROOT_LIST(SPECIALIZE_CLASS_ROOT_SELECTOR)
+
+#undef SPECIALIZE_CLASS_ROOT_SELECTOR
+
+} // namespace detail
+
+template <class MirrorType, ReadBarrierOption kReadBarrierOption = kWithReadBarrier>
+inline ObjPtr<mirror::Class> GetClassRoot(ObjPtr<mirror::ObjectArray<mirror::Class>> class_roots)
+ REQUIRES_SHARED(Locks::mutator_lock_) {
+ return GetClassRoot<kWithReadBarrier>(detail::ClassRootSelector<MirrorType>::value, class_roots);
+}
+
+template <class MirrorType, ReadBarrierOption kReadBarrierOption = kWithReadBarrier>
+inline ObjPtr<mirror::Class> GetClassRoot(ClassLinker* linker)
+ REQUIRES_SHARED(Locks::mutator_lock_) {
+ return GetClassRoot<kWithReadBarrier>(detail::ClassRootSelector<MirrorType>::value, linker);
+}
+
+template <class MirrorType, ReadBarrierOption kReadBarrierOption = kWithReadBarrier>
+inline ObjPtr<mirror::Class> GetClassRoot() REQUIRES_SHARED(Locks::mutator_lock_) {
+ return GetClassRoot<kWithReadBarrier>(detail::ClassRootSelector<MirrorType>::value);
+}
+
+} // namespace art
+
+#endif // ART_RUNTIME_CLASS_ROOT_H_