diff options
author | Vladimir Marko <vmarko@google.com> | 2018-05-24 11:09:38 +0100 |
---|---|---|
committer | Vladimir Marko <vmarko@google.com> | 2018-05-25 11:32:31 +0100 |
commit | b4eb1b19e1dd35d12a408358656c1421f507d231 (patch) | |
tree | 03ba65d206b5e6222dcca0f62a973bcbb1bf8a50 | |
parent | ff7ff426e136aa8fd6e33d873f6259311982f6bb (diff) | |
download | android_art-b4eb1b19e1dd35d12a408358656c1421f507d231.tar.gz android_art-b4eb1b19e1dd35d12a408358656c1421f507d231.tar.bz2 android_art-b4eb1b19e1dd35d12a408358656c1421f507d231.zip |
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
25 files changed, 460 insertions, 341 deletions
diff --git a/compiler/optimizing/inliner.cc b/compiler/optimizing/inliner.cc index ffa000e34e..6900cd883a 100644 --- a/compiler/optimizing/inliner.cc +++ b/compiler/optimizing/inliner.cc @@ -20,6 +20,7 @@ #include "base/enums.h" #include "builder.h" #include "class_linker.h" +#include "class_root.h" #include "constant_folding.h" #include "data_type-inl.h" #include "dead_code_elimination.h" @@ -537,7 +538,7 @@ static Handle<mirror::ObjectArray<mirror::Class>> AllocateInlineCacheHolder( Handle<mirror::ObjectArray<mirror::Class>> inline_cache = hs->NewHandle( mirror::ObjectArray<mirror::Class>::Alloc( self, - class_linker->GetClassRoot(ClassLinker::kClassArrayClass), + GetClassRoot<mirror::ObjectArray<mirror::Class>>(class_linker), InlineCache::kIndividualCacheSize)); if (inline_cache == nullptr) { // We got an OOME. Just clear the exception, and don't inline. @@ -777,7 +778,7 @@ HInliner::InlineCacheType HInliner::ExtractClassesFromOfflineProfile( HInstanceFieldGet* HInliner::BuildGetReceiverClass(ClassLinker* class_linker, HInstruction* receiver, uint32_t dex_pc) const { - ArtField* field = class_linker->GetClassRoot(ClassLinker::kJavaLangObject)->GetInstanceField(0); + ArtField* field = GetClassRoot<mirror::Object>(class_linker)->GetInstanceField(0); DCHECK_EQ(std::string(field->GetName()), "shadow$_klass_"); HInstanceFieldGet* result = new (graph_->GetAllocator()) HInstanceFieldGet( receiver, @@ -2120,9 +2121,8 @@ bool HInliner::ReturnTypeMoreSpecific(HInvoke* invoke_instruction, return true; } else if (return_replacement->IsInstanceFieldGet()) { HInstanceFieldGet* field_get = return_replacement->AsInstanceFieldGet(); - ClassLinker* class_linker = Runtime::Current()->GetClassLinker(); if (field_get->GetFieldInfo().GetField() == - class_linker->GetClassRoot(ClassLinker::kJavaLangObject)->GetInstanceField(0)) { + GetClassRoot<mirror::Object>()->GetInstanceField(0)) { return true; } } diff --git a/compiler/optimizing/instruction_simplifier.cc b/compiler/optimizing/instruction_simplifier.cc index ca84d421a7..63704a470e 100644 --- a/compiler/optimizing/instruction_simplifier.cc +++ b/compiler/optimizing/instruction_simplifier.cc @@ -18,6 +18,7 @@ #include "art_method-inl.h" #include "class_linker-inl.h" +#include "class_root.h" #include "data_type-inl.h" #include "escape.h" #include "intrinsics.h" @@ -1563,8 +1564,7 @@ static bool RecognizeAndSimplifyClassCheck(HCondition* condition) { { ScopedObjectAccess soa(Thread::Current()); - ClassLinker* class_linker = Runtime::Current()->GetClassLinker(); - ArtField* field = class_linker->GetClassRoot(ClassLinker::kJavaLangObject)->GetInstanceField(0); + ArtField* field = GetClassRoot<mirror::Object>()->GetInstanceField(0); DCHECK_EQ(std::string(field->GetName()), "shadow$_klass_"); if (field_get->GetFieldInfo().GetField() != field) { return false; diff --git a/compiler/optimizing/nodes.cc b/compiler/optimizing/nodes.cc index 7f78dc257e..99b0b186d4 100644 --- a/compiler/optimizing/nodes.cc +++ b/compiler/optimizing/nodes.cc @@ -22,6 +22,7 @@ #include "base/bit_vector-inl.h" #include "base/stl_util.h" #include "class_linker-inl.h" +#include "class_root.h" #include "code_generator.h" #include "common_dominator.h" #include "intrinsics.h" @@ -40,9 +41,8 @@ static constexpr bool kEnableFloatingPointStaticEvaluation = (FLT_EVAL_METHOD == void HGraph::InitializeInexactObjectRTI(VariableSizedHandleScope* handles) { ScopedObjectAccess soa(Thread::Current()); // Create the inexact Object reference type and store it in the HGraph. - ClassLinker* linker = Runtime::Current()->GetClassLinker(); inexact_object_rti_ = ReferenceTypeInfo::Create( - handles->NewHandle(linker->GetClassRoot(ClassLinker::kJavaLangObject)), + handles->NewHandle(GetClassRoot<mirror::Object>()), /* is_exact */ false); } diff --git a/compiler/optimizing/optimizing_compiler.cc b/compiler/optimizing/optimizing_compiler.cc index c4977decd9..79ac6b9b9d 100644 --- a/compiler/optimizing/optimizing_compiler.cc +++ b/compiler/optimizing/optimizing_compiler.cc @@ -31,6 +31,7 @@ #include "base/scoped_arena_allocator.h" #include "base/timing_logger.h" #include "builder.h" +#include "class_root.h" #include "code_generator.h" #include "compiled_method.h" #include "compiler.h" @@ -1309,13 +1310,12 @@ bool OptimizingCompiler::JitCompile(Thread* self, size_t method_info_size = 0; codegen->ComputeStackMapAndMethodInfoSize(&stack_map_size, &method_info_size); size_t number_of_roots = codegen->GetNumberOfJitRoots(); - ClassLinker* class_linker = Runtime::Current()->GetClassLinker(); // We allocate an object array to ensure the JIT roots that we will collect in EmitJitRoots // will be visible by the GC between EmitLiterals and CommitCode. Once CommitCode is // executed, this array is not needed. Handle<mirror::ObjectArray<mirror::Object>> roots( hs.NewHandle(mirror::ObjectArray<mirror::Object>::Alloc( - self, class_linker->GetClassRoot(ClassLinker::kObjectArrayClass), number_of_roots))); + self, GetClassRoot<mirror::ObjectArray<mirror::Object>>(), number_of_roots))); if (roots == nullptr) { // Out of memory, just clear the exception to avoid any Java exception uncaught problems. MaybeRecordStat(compilation_stats_.get(), MethodCompilationStat::kJitOutOfMemoryForCommit); diff --git a/compiler/optimizing/reference_type_propagation.cc b/compiler/optimizing/reference_type_propagation.cc index ecfa790b91..f3fe62561f 100644 --- a/compiler/optimizing/reference_type_propagation.cc +++ b/compiler/optimizing/reference_type_propagation.cc @@ -22,6 +22,7 @@ #include "base/scoped_arena_containers.h" #include "base/enums.h" #include "class_linker-inl.h" +#include "class_root.h" #include "handle_scope-inl.h" #include "mirror/class-inl.h" #include "mirror/dex_cache.h" @@ -40,43 +41,40 @@ static inline ObjPtr<mirror::DexCache> FindDexCacheWithHint( } static inline ReferenceTypeInfo::TypeHandle GetRootHandle(VariableSizedHandleScope* handles, - ClassLinker::ClassRoot class_root, + ClassRoot class_root, ReferenceTypeInfo::TypeHandle* cache) { if (!ReferenceTypeInfo::IsValidHandle(*cache)) { // Mutator lock is required for NewHandle. - ClassLinker* linker = Runtime::Current()->GetClassLinker(); ScopedObjectAccess soa(Thread::Current()); - *cache = handles->NewHandle(linker->GetClassRoot(class_root)); + *cache = handles->NewHandle(GetClassRoot(class_root)); } return *cache; } ReferenceTypeInfo::TypeHandle ReferenceTypePropagation::HandleCache::GetObjectClassHandle() { - return GetRootHandle(handles_, ClassLinker::kJavaLangObject, &object_class_handle_); + return GetRootHandle(handles_, ClassRoot::kJavaLangObject, &object_class_handle_); } ReferenceTypeInfo::TypeHandle ReferenceTypePropagation::HandleCache::GetClassClassHandle() { - return GetRootHandle(handles_, ClassLinker::kJavaLangClass, &class_class_handle_); + return GetRootHandle(handles_, ClassRoot::kJavaLangClass, &class_class_handle_); } ReferenceTypeInfo::TypeHandle ReferenceTypePropagation::HandleCache::GetMethodHandleClassHandle() { return GetRootHandle(handles_, - ClassLinker::kJavaLangInvokeMethodHandleImpl, + ClassRoot::kJavaLangInvokeMethodHandleImpl, &method_handle_class_handle_); } ReferenceTypeInfo::TypeHandle ReferenceTypePropagation::HandleCache::GetMethodTypeClassHandle() { - return GetRootHandle(handles_, - ClassLinker::kJavaLangInvokeMethodType, - &method_type_class_handle_); + return GetRootHandle(handles_, ClassRoot::kJavaLangInvokeMethodType, &method_type_class_handle_); } ReferenceTypeInfo::TypeHandle ReferenceTypePropagation::HandleCache::GetStringClassHandle() { - return GetRootHandle(handles_, ClassLinker::kJavaLangString, &string_class_handle_); + return GetRootHandle(handles_, ClassRoot::kJavaLangString, &string_class_handle_); } ReferenceTypeInfo::TypeHandle ReferenceTypePropagation::HandleCache::GetThrowableClassHandle() { - return GetRootHandle(handles_, ClassLinker::kJavaLangThrowable, &throwable_class_handle_); + return GetRootHandle(handles_, ClassRoot::kJavaLangThrowable, &throwable_class_handle_); } class ReferenceTypePropagation::RTPVisitor : public HGraphDelegateVisitor { @@ -341,8 +339,7 @@ static void BoundTypeForClassCheck(HInstruction* check) { { ScopedObjectAccess soa(Thread::Current()); - ClassLinker* class_linker = Runtime::Current()->GetClassLinker(); - ArtField* field = class_linker->GetClassRoot(ClassLinker::kJavaLangObject)->GetInstanceField(0); + ArtField* field = GetClassRoot<mirror::Object>()->GetInstanceField(0); DCHECK_EQ(std::string(field->GetName()), "shadow$_klass_"); if (field_get->GetFieldInfo().GetField() != field) { return; diff --git a/dex2oat/linker/image_writer.cc b/dex2oat/linker/image_writer.cc index 01726af1d6..058724570d 100644 --- a/dex2oat/linker/image_writer.cc +++ b/dex2oat/linker/image_writer.cc @@ -33,6 +33,7 @@ #include "base/logging.h" // For VLOG. #include "base/unix_file/fd_file.h" #include "class_linker-inl.h" +#include "class_root.h" #include "compiled_method.h" #include "dex/dex_file-inl.h" #include "dex/dex_file_types.h" @@ -618,8 +619,7 @@ void ImageWriter::AssignImageBinSlot(mirror::Object* object, size_t oat_index) { } } else if (object->GetClass<kVerifyNone>()->IsStringClass()) { bin = Bin::kString; // Strings are almost always immutable (except for object header). - } else if (object->GetClass<kVerifyNone>() == - Runtime::Current()->GetClassLinker()->GetClassRoot(ClassLinker::kJavaLangObject)) { + } else if (object->GetClass<kVerifyNone>() == GetClassRoot<mirror::Object>()) { // Instance of java lang object, probably a lock object. This means it will be dirty when we // synchronize on it. bin = Bin::kMiscDirty; @@ -2409,8 +2409,7 @@ void ImageWriter::FixupObject(Object* orig, Object* copy) { ArtMethod* src_method = src->GetArtMethod(); dest->SetArtMethod(GetImageMethodAddress(src_method)); } else if (!klass->IsArrayClass()) { - ClassLinker* class_linker = Runtime::Current()->GetClassLinker(); - if (klass == class_linker->GetClassRoot(ClassLinker::kJavaLangDexCache)) { + if (klass == GetClassRoot<mirror::DexCache>()) { FixupDexCache(down_cast<mirror::DexCache*>(orig), down_cast<mirror::DexCache*>(copy)); } else if (klass->IsClassLoaderClass()) { mirror::ClassLoader* copy_loader = down_cast<mirror::ClassLoader*>(copy); diff --git a/openjdkjvmti/ti_class_definition.cc b/openjdkjvmti/ti_class_definition.cc index 1b641cd905..dce2733e7e 100644 --- a/openjdkjvmti/ti_class_definition.cc +++ b/openjdkjvmti/ti_class_definition.cc @@ -33,6 +33,7 @@ #include "base/array_slice.h" #include "class_linker-inl.h" +#include "class_root.h" #include "dex/dex_file.h" #include "fixed_up_dex_file.h" #include "handle.h" @@ -162,8 +163,7 @@ static void GetDexDataForRetransformation(art::Handle<art::mirror::Class> klass, << "Expected java/lang/Long but found object of type " << orig_dex->GetClass()->PrettyClass(); art::ObjPtr<art::mirror::Class> prim_long_class( - art::Runtime::Current()->GetClassLinker()->GetClassRoot( - art::ClassLinker::kPrimitiveLong)); + art::GetClassRoot(art::ClassRoot::kPrimitiveLong)); art::JValue val; if (!art::UnboxPrimitiveForResult(orig_dex.Get(), prim_long_class, &val)) { // This should never happen. @@ -226,8 +226,7 @@ static const art::DexFile* GetQuickenedDexFile(art::Handle<art::mirror::Class> k << "Expected java/lang/Long but found object of type " << orig_dex->GetClass()->PrettyClass(); art::ObjPtr<art::mirror::Class> prim_long_class( - art::Runtime::Current()->GetClassLinker()->GetClassRoot( - art::ClassLinker::kPrimitiveLong)); + art::GetClassRoot(art::ClassRoot::kPrimitiveLong)); art::JValue val; if (!art::UnboxPrimitiveForResult(orig_dex.Ptr(), prim_long_class, &val)) { LOG(FATAL) << "Unable to unwrap a long value!"; diff --git a/openjdkjvmti/ti_redefine.cc b/openjdkjvmti/ti_redefine.cc index 8a726bca14..48e2958773 100644 --- a/openjdkjvmti/ti_redefine.cc +++ b/openjdkjvmti/ti_redefine.cc @@ -42,6 +42,7 @@ #include "base/array_ref.h" #include "base/stringpiece.h" #include "class_linker-inl.h" +#include "class_root.h" #include "debugger.h" #include "dex/art_dex_file_loader.h" #include "dex/dex_file.h" @@ -485,7 +486,7 @@ art::mirror::DexCache* Redefiner::ClassRedefinition::CreateNewDexCache( art::ClassLinker* cl = driver_->runtime_->GetClassLinker(); art::Handle<art::mirror::DexCache> cache(hs.NewHandle( art::ObjPtr<art::mirror::DexCache>::DownCast( - cl->GetClassRoot(art::ClassLinker::kJavaLangDexCache)->AllocObject(driver_->self_)))); + art::GetClassRoot<art::mirror::DexCache>(cl)->AllocObject(driver_->self_)))); if (cache.IsNull()) { driver_->self_->AssertPendingOOMException(); return nullptr; @@ -859,12 +860,10 @@ class RedefinitionDataHolder { art::Thread* self, std::vector<Redefiner::ClassRedefinition>* redefinitions) REQUIRES_SHARED(art::Locks::mutator_lock_) : - arr_( - hs->NewHandle( - art::mirror::ObjectArray<art::mirror::Object>::Alloc( - self, - runtime->GetClassLinker()->GetClassRoot(art::ClassLinker::kObjectArrayClass), - redefinitions->size() * kNumSlots))), + arr_(hs->NewHandle(art::mirror::ObjectArray<art::mirror::Object>::Alloc( + self, + art::GetClassRoot<art::mirror::ObjectArray<art::mirror::Object>>(runtime->GetClassLinker()), + redefinitions->size() * kNumSlots))), redefinitions_(redefinitions) {} bool IsNull() const REQUIRES_SHARED(art::Locks::mutator_lock_) { diff --git a/runtime/Android.bp b/runtime/Android.bp index 92607f51a0..9043866e73 100644 --- a/runtime/Android.bp +++ b/runtime/Android.bp @@ -40,6 +40,7 @@ libart_cc_defaults { "check_jni.cc", "class_linker.cc", "class_loader_context.cc", + "class_root.cc", "class_table.cc", "common_throws.cc", "compiler_filter.cc", diff --git a/runtime/class_linker-inl.h b/runtime/class_linker-inl.h index ae06f8f9bc..7a99d3dc5e 100644 --- a/runtime/class_linker-inl.h +++ b/runtime/class_linker-inl.h @@ -365,14 +365,6 @@ inline ArtField* ClassLinker::ResolveField(uint32_t field_idx, return resolved_field; } -inline mirror::Class* ClassLinker::GetClassRoot(ClassRoot class_root) { - DCHECK(!class_roots_.IsNull()); - mirror::ObjectArray<mirror::Class>* class_roots = class_roots_.Read(); - ObjPtr<mirror::Class> klass = class_roots->Get(class_root); - DCHECK(klass != nullptr); - return klass.Ptr(); -} - template <class Visitor> inline void ClassLinker::VisitClassTables(const Visitor& visitor) { Thread* const self = Thread::Current(); diff --git a/runtime/class_linker.cc b/runtime/class_linker.cc index b88aa5e07a..e2449f941c 100644 --- a/runtime/class_linker.cc +++ b/runtime/class_linker.cc @@ -51,6 +51,7 @@ #include "cha.h" #include "class_linker-inl.h" #include "class_loader_utils.h" +#include "class_root.h" #include "class_table-inl.h" #include "compiler_callbacks.h" #include "debug_print.h" @@ -516,29 +517,30 @@ bool ClassLinker::InitWithoutImage(std::vector<std::unique_ptr<const DexFile>> b // Create storage for root classes, save away our work so far (requires descriptors). class_roots_ = GcRoot<mirror::ObjectArray<mirror::Class>>( - mirror::ObjectArray<mirror::Class>::Alloc(self, object_array_class.Get(), - kClassRootsMax)); + mirror::ObjectArray<mirror::Class>::Alloc(self, + object_array_class.Get(), + static_cast<int32_t>(ClassRoot::kMax))); CHECK(!class_roots_.IsNull()); - SetClassRoot(kJavaLangClass, java_lang_Class.Get()); - SetClassRoot(kJavaLangObject, java_lang_Object.Get()); - SetClassRoot(kClassArrayClass, class_array_class.Get()); - SetClassRoot(kObjectArrayClass, object_array_class.Get()); - SetClassRoot(kCharArrayClass, char_array_class.Get()); - SetClassRoot(kJavaLangString, java_lang_String.Get()); - SetClassRoot(kJavaLangRefReference, java_lang_ref_Reference.Get()); + SetClassRoot(ClassRoot::kJavaLangClass, java_lang_Class.Get()); + SetClassRoot(ClassRoot::kJavaLangObject, java_lang_Object.Get()); + SetClassRoot(ClassRoot::kClassArrayClass, class_array_class.Get()); + SetClassRoot(ClassRoot::kObjectArrayClass, object_array_class.Get()); + SetClassRoot(ClassRoot::kCharArrayClass, char_array_class.Get()); + SetClassRoot(ClassRoot::kJavaLangString, java_lang_String.Get()); + SetClassRoot(ClassRoot::kJavaLangRefReference, java_lang_ref_Reference.Get()); // Fill in the empty iftable. Needs to be done after the kObjectArrayClass root is set. java_lang_Object->SetIfTable(AllocIfTable(self, 0)); // Setup the primitive type classes. - SetClassRoot(kPrimitiveBoolean, CreatePrimitiveClass(self, Primitive::kPrimBoolean)); - SetClassRoot(kPrimitiveByte, CreatePrimitiveClass(self, Primitive::kPrimByte)); - SetClassRoot(kPrimitiveShort, CreatePrimitiveClass(self, Primitive::kPrimShort)); - SetClassRoot(kPrimitiveInt, CreatePrimitiveClass(self, Primitive::kPrimInt)); - SetClassRoot(kPrimitiveLong, CreatePrimitiveClass(self, Primitive::kPrimLong)); - SetClassRoot(kPrimitiveFloat, CreatePrimitiveClass(self, Primitive::kPrimFloat)); - SetClassRoot(kPrimitiveDouble, CreatePrimitiveClass(self, Primitive::kPrimDouble)); - SetClassRoot(kPrimitiveVoid, CreatePrimitiveClass(self, Primitive::kPrimVoid)); + SetClassRoot(ClassRoot::kPrimitiveBoolean, CreatePrimitiveClass(self, Primitive::kPrimBoolean)); + SetClassRoot(ClassRoot::kPrimitiveByte, CreatePrimitiveClass(self, Primitive::kPrimByte)); + SetClassRoot(ClassRoot::kPrimitiveShort, CreatePrimitiveClass(self, Primitive::kPrimShort)); + SetClassRoot(ClassRoot::kPrimitiveInt, CreatePrimitiveClass(self, Primitive::kPrimInt)); + SetClassRoot(ClassRoot::kPrimitiveLong, CreatePrimitiveClass(self, Primitive::kPrimLong)); + SetClassRoot(ClassRoot::kPrimitiveFloat, CreatePrimitiveClass(self, Primitive::kPrimFloat)); + SetClassRoot(ClassRoot::kPrimitiveDouble, CreatePrimitiveClass(self, Primitive::kPrimDouble)); + SetClassRoot(ClassRoot::kPrimitiveVoid, CreatePrimitiveClass(self, Primitive::kPrimVoid)); // Create array interface entries to populate once we can load system classes. array_iftable_ = GcRoot<mirror::IfTable>(AllocIfTable(self, 2)); @@ -546,23 +548,23 @@ bool ClassLinker::InitWithoutImage(std::vector<std::unique_ptr<const DexFile>> b // Create int array type for AllocDexCache (done in AppendToBootClassPath). Handle<mirror::Class> int_array_class(hs.NewHandle( AllocClass(self, java_lang_Class.Get(), mirror::Array::ClassSize(image_pointer_size_)))); - int_array_class->SetComponentType(GetClassRoot(kPrimitiveInt)); + int_array_class->SetComponentType(GetClassRoot(ClassRoot::kPrimitiveInt, this)); mirror::IntArray::SetArrayClass(int_array_class.Get()); - SetClassRoot(kIntArrayClass, int_array_class.Get()); + SetClassRoot(ClassRoot::kIntArrayClass, int_array_class.Get()); // Create long array type for AllocDexCache (done in AppendToBootClassPath). Handle<mirror::Class> long_array_class(hs.NewHandle( AllocClass(self, java_lang_Class.Get(), mirror::Array::ClassSize(image_pointer_size_)))); - long_array_class->SetComponentType(GetClassRoot(kPrimitiveLong)); + long_array_class->SetComponentType(GetClassRoot(ClassRoot::kPrimitiveLong, this)); mirror::LongArray::SetArrayClass(long_array_class.Get()); - SetClassRoot(kLongArrayClass, long_array_class.Get()); + SetClassRoot(ClassRoot::kLongArrayClass, long_array_class.Get()); // now that these are registered, we can use AllocClass() and AllocObjectArray // Set up DexCache. This cannot be done later since AppendToBootClassPath calls AllocDexCache. Handle<mirror::Class> java_lang_DexCache(hs.NewHandle( AllocClass(self, java_lang_Class.Get(), mirror::DexCache::ClassSize(image_pointer_size_)))); - SetClassRoot(kJavaLangDexCache, java_lang_DexCache.Get()); + SetClassRoot(ClassRoot::kJavaLangDexCache, java_lang_DexCache.Get()); java_lang_DexCache->SetDexCacheClass(); java_lang_DexCache->SetObjectSize(mirror::DexCache::InstanceSize()); mirror::Class::SetStatus(java_lang_DexCache, ClassStatus::kResolved, self); @@ -571,7 +573,7 @@ bool ClassLinker::InitWithoutImage(std::vector<std::unique_ptr<const DexFile>> b // Setup dalvik.system.ClassExt Handle<mirror::Class> dalvik_system_ClassExt(hs.NewHandle( AllocClass(self, java_lang_Class.Get(), mirror::ClassExt::ClassSize(image_pointer_size_)))); - SetClassRoot(kDalvikSystemClassExt, dalvik_system_ClassExt.Get()); + SetClassRoot(ClassRoot::kDalvikSystemClassExt, dalvik_system_ClassExt.Get()); mirror::ClassExt::SetClass(dalvik_system_ClassExt.Get()); mirror::Class::SetStatus(dalvik_system_ClassExt, ClassStatus::kResolved, self); @@ -580,7 +582,7 @@ bool ClassLinker::InitWithoutImage(std::vector<std::unique_ptr<const DexFile>> b AllocClass(self, java_lang_Class.Get(), mirror::ObjectArray<mirror::String>::ClassSize(image_pointer_size_)))); object_array_string->SetComponentType(java_lang_String.Get()); - SetClassRoot(kJavaLangStringArrayClass, object_array_string.Get()); + SetClassRoot(ClassRoot::kJavaLangStringArrayClass, object_array_string.Get()); LinearAlloc* linear_alloc = runtime->GetLinearAlloc(); // Create runtime resolution and imt conflict methods. @@ -608,7 +610,7 @@ bool ClassLinker::InitWithoutImage(std::vector<std::unique_ptr<const DexFile>> b // run char class through InitializePrimitiveClass to finish init InitializePrimitiveClass(char_class.Get(), Primitive::kPrimChar); - SetClassRoot(kPrimitiveChar, char_class.Get()); // needs descriptor + SetClassRoot(ClassRoot::kPrimitiveChar, char_class.Get()); // needs descriptor // Set up GenericJNI entrypoint. That is mainly a hack for common_compiler_test.h so that // we do not need friend classes or a publicly exposed setter. @@ -634,25 +636,25 @@ bool ClassLinker::InitWithoutImage(std::vector<std::unique_ptr<const DexFile>> b CHECK_EQ(dalvik_system_ClassExt->GetObjectSize(), mirror::ClassExt::InstanceSize()); // Setup the primitive array type classes - can't be done until Object has a vtable. - SetClassRoot(kBooleanArrayClass, FindSystemClass(self, "[Z")); - mirror::BooleanArray::SetArrayClass(GetClassRoot(kBooleanArrayClass)); + SetClassRoot(ClassRoot::kBooleanArrayClass, FindSystemClass(self, "[Z")); + mirror::BooleanArray::SetArrayClass(GetClassRoot(ClassRoot::kBooleanArrayClass, this)); - SetClassRoot(kByteArrayClass, FindSystemClass(self, "[B")); - mirror::ByteArray::SetArrayClass(GetClassRoot(kByteArrayClass)); + SetClassRoot(ClassRoot::kByteArrayClass, FindSystemClass(self, "[B")); + mirror::ByteArray::SetArrayClass(GetClassRoot(ClassRoot::kByteArrayClass, this)); CheckSystemClass(self, char_array_class, "[C"); - SetClassRoot(kShortArrayClass, FindSystemClass(self, "[S")); - mirror::ShortArray::SetArrayClass(GetClassRoot(kShortArrayClass)); + SetClassRoot(ClassRoot::kShortArrayClass, FindSystemClass(self, "[S")); + mirror::ShortArray::SetArrayClass(GetClassRoot(ClassRoot::kShortArrayClass, this)); CheckSystemClass(self, int_array_class, "[I"); CheckSystemClass(self, long_array_class, "[J"); - SetClassRoot(kFloatArrayClass, FindSystemClass(self, "[F")); - mirror::FloatArray::SetArrayClass(GetClassRoot(kFloatArrayClass)); + SetClassRoot(ClassRoot::kFloatArrayClass, FindSystemClass(self, "[F")); + mirror::FloatArray::SetArrayClass(GetClassRoot(ClassRoot::kFloatArrayClass, this)); - SetClassRoot(kDoubleArrayClass, FindSystemClass(self, "[D")); - mirror::DoubleArray::SetArrayClass(GetClassRoot(kDoubleArrayClass)); + SetClassRoot(ClassRoot::kDoubleArrayClass, FindSystemClass(self, "[D")); + mirror::DoubleArray::SetArrayClass(GetClassRoot(ClassRoot::kDoubleArrayClass, this)); // Run Class through FindSystemClass. This initializes the dex_cache_ fields and register it // in class_table_. @@ -683,102 +685,103 @@ bool ClassLinker::InitWithoutImage(std::vector<std::unique_ptr<const DexFile>> b mirror::Class::GetDirectInterface(self, object_array_class.Get(), 1)); CHECK_EQ(object_array_string.Get(), - FindSystemClass(self, GetClassRootDescriptor(kJavaLangStringArrayClass))); + FindSystemClass(self, GetClassRootDescriptor(ClassRoot::kJavaLangStringArrayClass))); // End of special init trickery, all subsequent classes may be loaded via FindSystemClass. // Create java.lang.reflect.Proxy root. - SetClassRoot(kJavaLangReflectProxy, FindSystemClass(self, "Ljava/lang/reflect/Proxy;")); + SetClassRoot(ClassRoot::kJavaLangReflectProxy, + FindSystemClass(self, "Ljava/lang/reflect/Proxy;")); // Create java.lang.reflect.Field.class root. auto* class_root = FindSystemClass(self, "Ljava/lang/reflect/Field;"); CHECK(class_root != nullptr); - SetClassRoot(kJavaLangReflectField, class_root); + SetClassRoot(ClassRoot::kJavaLangReflectField, class_root); mirror::Field::SetClass(class_root); // Create java.lang.reflect.Field array root. class_root = FindSystemClass(self, "[Ljava/lang/reflect/Field;"); CHECK(class_root != nullptr); - SetClassRoot(kJavaLangReflectFieldArrayClass, class_root); + SetClassRoot(ClassRoot::kJavaLangReflectFieldArrayClass, class_root); mirror::Field::SetArrayClass(class_root); // Create java.lang.reflect.Constructor.class root and array root. class_root = FindSystemClass(self, "Ljava/lang/reflect/Constructor;"); CHECK(class_root != nullptr); - SetClassRoot(kJavaLangReflectConstructor, class_root); + SetClassRoot(ClassRoot::kJavaLangReflectConstructor, class_root); mirror::Constructor::SetClass(class_root); class_root = FindSystemClass(self, "[Ljava/lang/reflect/Constructor;"); CHECK(class_root != nullptr); - SetClassRoot(kJavaLangReflectConstructorArrayClass, class_root); + SetClassRoot(ClassRoot::kJavaLangReflectConstructorArrayClass, class_root); mirror::Constructor::SetArrayClass(class_root); // Create java.lang.reflect.Method.class root and array root. class_root = FindSystemClass(self, "Ljava/lang/reflect/Method;"); CHECK(class_root != nullptr); - SetClassRoot(kJavaLangReflectMethod, class_root); + SetClassRoot(ClassRoot::kJavaLangReflectMethod, class_root); mirror::Method::SetClass(class_root); class_root = FindSystemClass(self, "[Ljava/lang/reflect/Method;"); CHECK(class_root != nullptr); - SetClassRoot(kJavaLangReflectMethodArrayClass, class_root); + SetClassRoot(ClassRoot::kJavaLangReflectMethodArrayClass, class_root); mirror::Method::SetArrayClass(class_root); // Create java.lang.invoke.CallSite.class root class_root = FindSystemClass(self, "Ljava/lang/invoke/CallSite;"); CHECK(class_root != nullptr); - SetClassRoot(kJavaLangInvokeCallSite, class_root); + SetClassRoot(ClassRoot::kJavaLangInvokeCallSite, class_root); mirror::CallSite::SetClass(class_root); // Create java.lang.invoke.MethodType.class root class_root = FindSystemClass(self, "Ljava/lang/invoke/MethodType;"); CHECK(class_root != nullptr); - SetClassRoot(kJavaLangInvokeMethodType, class_root); + SetClassRoot(ClassRoot::kJavaLangInvokeMethodType, class_root); mirror::MethodType::SetClass(class_root); // Create java.lang.invoke.MethodHandleImpl.class root class_root = FindSystemClass(self, "Ljava/lang/invoke/MethodHandleImpl;"); CHECK(class_root != nullptr); - SetClassRoot(kJavaLangInvokeMethodHandleImpl, class_root); + SetClassRoot(ClassRoot::kJavaLangInvokeMethodHandleImpl, class_root); mirror::MethodHandleImpl::SetClass(class_root); // Create java.lang.invoke.MethodHandles.Lookup.class root class_root = FindSystemClass(self, "Ljava/lang/invoke/MethodHandles$Lookup;"); CHECK(class_root != nullptr); - SetClassRoot(kJavaLangInvokeMethodHandlesLookup, class_root); + SetClassRoot(ClassRoot::kJavaLangInvokeMethodHandlesLookup, class_root); mirror::MethodHandlesLookup::SetClass(class_root); // Create java.lang.invoke.VarHandle.class root class_root = FindSystemClass(self, "Ljava/lang/invoke/VarHandle;"); CHECK(class_root != nullptr); - SetClassRoot(kJavaLangInvokeVarHandle, class_root); + SetClassRoot(ClassRoot::kJavaLangInvokeVarHandle, class_root); mirror::VarHandle::SetClass(class_root); // Create java.lang.invoke.FieldVarHandle.class root class_root = FindSystemClass(self, "Ljava/lang/invoke/FieldVarHandle;"); CHECK(class_root != nullptr); - SetClassRoot(kJavaLangInvokeFieldVarHandle, class_root); + SetClassRoot(ClassRoot::kJavaLangInvokeFieldVarHandle, class_root); mirror::FieldVarHandle::SetClass(class_root); // Create java.lang.invoke.ArrayElementVarHandle.class root class_root = FindSystemClass(self, "Ljava/lang/invoke/ArrayElementVarHandle;"); CHECK(class_root != nullptr); - SetClassRoot(kJavaLangInvokeArrayElementVarHandle, class_root); + SetClassRoot(ClassRoot::kJavaLangInvokeArrayElementVarHandle, class_root); mirror::ArrayElementVarHandle::SetClass(class_root); // Create java.lang.invoke.ByteArrayViewVarHandle.class root class_root = FindSystemClass(self, "Ljava/lang/invoke/ByteArrayViewVarHandle;"); CHECK(class_root != nullptr); - SetClassRoot(kJavaLangInvokeByteArrayViewVarHandle, class_root); + SetClassRoot(ClassRoot::kJavaLangInvokeByteArrayViewVarHandle, class_root); mirror::ByteArrayViewVarHandle::SetClass(class_root); // Create java.lang.invoke.ByteBufferViewVarHandle.class root class_root = FindSystemClass(self, "Ljava/lang/invoke/ByteBufferViewVarHandle;"); CHECK(class_root != nullptr); - SetClassRoot(kJavaLangInvokeByteBufferViewVarHandle, class_root); + SetClassRoot(ClassRoot::kJavaLangInvokeByteBufferViewVarHandle, class_root); mirror::ByteBufferViewVarHandle::SetClass(class_root); class_root = FindSystemClass(self, "Ldalvik/system/EmulatedStackFrame;"); CHECK(class_root != nullptr); - SetClassRoot(kDalvikSystemEmulatedStackFrame, class_root); + SetClassRoot(ClassRoot::kDalvikSystemEmulatedStackFrame, class_root); mirror::EmulatedStackFrame::SetClass(class_root); // java.lang.ref classes need to be specially flagged, but otherwise are normal classes @@ -805,18 +808,19 @@ bool ClassLinker::InitWithoutImage(std::vector<std::unique_ptr<const DexFile>> b class_root = FindSystemClass(self, "Ljava/lang/ClassLoader;"); class_root->SetClassLoaderClass(); CHECK_EQ(class_root->GetObjectSize(), mirror::ClassLoader::InstanceSize()); - SetClassRoot(kJavaLangClassLoader, class_root); + SetClassRoot(ClassRoot::kJavaLangClassLoader, class_root); // Set up java.lang.Throwable, java.lang.ClassNotFoundException, and // java.lang.StackTraceElement as a convenience. - SetClassRoot(kJavaLangThrowable, FindSystemClass(self, "Ljava/lang/Throwable;")); - mirror::Throwable::SetClass(GetClassRoot(kJavaLangThrowable)); - SetClassRoot(kJavaLangClassNotFoundException, + SetClassRoot(ClassRoot::kJavaLangThrowable, FindSystemClass(self, "Ljava/lang/Throwable;")); + mirror::Throwable::SetClass(GetClassRoot(ClassRoot::kJavaLangThrowable, this)); + SetClassRoot(ClassRoot::kJavaLangClassNotFoundException, FindSystemClass(self, "Ljava/lang/ClassNotFoundException;")); - SetClassRoot(kJavaLangStackTraceElement, FindSystemClass(self, "Ljava/lang/StackTraceElement;")); - SetClassRoot(kJavaLangStackTraceElementArrayClass, + SetClassRoot(ClassRoot::kJavaLangStackTraceElement, + FindSystemClass(self, "Ljava/lang/StackTraceElement;")); + SetClassRoot(ClassRoot::kJavaLangStackTraceElementArrayClass, FindSystemClass(self, "[Ljava/lang/StackTraceElement;")); - mirror::StackTraceElement::SetClass(GetClassRoot(kJavaLangStackTraceElement)); + mirror::StackTraceElement::SetClass(GetClassRoot(ClassRoot::kJavaLangStackTraceElement, this)); // Create conflict tables that depend on the class linker. runtime->FixupConflictTables(); @@ -834,8 +838,7 @@ static void CreateStringInitBindings(Thread* self, ClassLinker* class_linker) ObjPtr<mirror::Class> string_factory_class = class_linker->FindSystemClass(self, "Ljava/lang/StringFactory;"); CHECK(string_factory_class != nullptr); - ObjPtr<mirror::Class> string_class = - class_linker->GetClassRoot(ClassLinker::ClassRoot::kJavaLangString); + ObjPtr<mirror::Class> string_class = GetClassRoot<mirror::String>(class_linker); WellKnownClasses::InitStringInit(string_class, string_factory_class); // Update the primordial thread. self->InitStringEntryPoints(); @@ -851,7 +854,8 @@ void ClassLinker::FinishInit(Thread* self) { // as the types of the field can't be resolved prior to the runtime being // fully initialized StackHandleScope<2> hs(self); - Handle<mirror::Class> java_lang_ref_Reference = hs.NewHandle(GetClassRoot(kJavaLangRefReference)); + Handle<mirror::Class> java_lang_ref_Reference = + hs.NewHandle(GetClassRoot<mirror::Reference>(this)); Handle<mirror::Class> java_lang_ref_FinalizerReference = hs.NewHandle(FindSystemClass(self, "Ljava/lang/ref/FinalizerReference;")); @@ -876,7 +880,7 @@ void ClassLinker::FinishInit(Thread* self) { CHECK_STREQ(zombie->GetTypeDescriptor(), "Ljava/lang/Object;"); // ensure all class_roots_ are initialized - for (size_t i = 0; i < kClassRootsMax; i++) { + for (size_t i = 0; i < static_cast<size_t>(ClassRoot::kMax); i++) { ClassRoot class_root = static_cast<ClassRoot>(i); ObjPtr<mirror::Class> klass = GetClassRoot(class_root); CHECK(klass != nullptr); @@ -896,11 +900,11 @@ void ClassLinker::FinishInit(Thread* self) { void ClassLinker::RunRootClinits() { Thread* self = Thread::Current(); - for (size_t i = 0; i < ClassLinker::kClassRootsMax; ++i) { - ObjPtr<mirror::Class> c = GetClassRoot(ClassRoot(i)); + for (size_t i = 0; i < static_cast<size_t>(ClassRoot::kMax); ++i) { + ObjPtr<mirror::Class> c = GetClassRoot(ClassRoot(i), this); if (!c->IsArrayClass() && !c->IsPrimitive()) { StackHandleScope<1> hs(self); - Handle<mirror::Class> h_class(hs.NewHandle(GetClassRoot(ClassRoot(i)))); + Handle<mirror::Class> h_class(hs.NewHandle(c)); EnsureInitialized(self, h_class, true, true); self->AssertNoPendingException(); } @@ -1034,13 +1038,13 @@ bool ClassLinker::InitFromBootImage(std::string* error_msg) { class_roots_ = GcRoot<mirror::ObjectArray<mirror::Class>>( down_cast<mirror::ObjectArray<mirror::Class>*>( spaces[0]->GetImageHeader().GetImageRoot(ImageHeader::kClassRoots))); - mirror::Class::SetClassClass(class_roots_.Read()->Get(kJavaLangClass)); + mirror::Class::SetClassClass(GetClassRoot(ClassRoot::kJavaLangClass, this)); // Special case of setting up the String class early so that we can test arbitrary objects // as being Strings or not - mirror::String::SetClass(GetClassRoot(kJavaLangString)); + mirror::String::SetClass(GetClassRoot<mirror::String>(this)); - ObjPtr<mirror::Class> java_lang_Object = GetClassRoot(kJavaLangObject); + ObjPtr<mirror::Class> java_lang_Object = GetClassRoot<mirror::Object>(this); java_lang_Object->SetObjectSize(sizeof(mirror::Object)); // Allocate in non-movable so that it's possible to check if a JNI weak global ref has been // cleared without triggering the read barrier and unintentionally mark the sentinel alive. @@ -1048,37 +1052,48 @@ bool ClassLinker::InitFromBootImage(std::string* error_msg) { self, java_lang_Object, java_lang_Object->GetObjectSize(), VoidFunctor())); // reinit array_iftable_ from any array class instance, they should be == - array_iftable_ = GcRoot<mirror::IfTable>(GetClassRoot(kObjectArrayClass)->GetIfTable()); - DCHECK_EQ(array_iftable_.Read(), GetClassRoot(kBooleanArrayClass)->GetIfTable()); + array_iftable_ = + GcRoot<mirror::IfTable>(GetClassRoot(ClassRoot::kObjectArrayClass, this)->GetIfTable()); + DCHECK_EQ(array_iftable_.Read(), GetClassRoot(ClassRoot::kBooleanArrayClass, this)->GetIfTable()); // String class root was set above - mirror::Field::SetClass(GetClassRoot(kJavaLangReflectField)); - mirror::Field::SetArrayClass(GetClassRoot(kJavaLangReflectFieldArrayClass)); - mirror::Constructor::SetClass(GetClassRoot(kJavaLangReflectConstructor)); - mirror::Constructor::SetArrayClass(GetClassRoot(kJavaLangReflectConstructorArrayClass)); - mirror::Method::SetClass(GetClassRoot(kJavaLangReflectMethod)); - mirror::Method::SetArrayClass(GetClassRoot(kJavaLangReflectMethodArrayClass)); - mirror::CallSite::SetClass(GetClassRoot(kJavaLangInvokeCallSite)); - mirror::MethodHandleImpl::SetClass(GetClassRoot(kJavaLangInvokeMethodHandleImpl)); - mirror::MethodHandlesLookup::SetClass(GetClassRoot(kJavaLangInvokeMethodHandlesLookup)); - mirror::MethodType::SetClass(GetClassRoot(kJavaLangInvokeMethodType)); - mirror::VarHandle::SetClass(GetClassRoot(kJavaLangInvokeVarHandle)); - mirror::FieldVarHandle::SetClass(GetClassRoot(kJavaLangInvokeFieldVarHandle)); - mirror::ArrayElementVarHandle::SetClass(GetClassRoot(kJavaLangInvokeArrayElementVarHandle)); - mirror::ByteArrayViewVarHandle::SetClass(GetClassRoot(kJavaLangInvokeByteArrayViewVarHandle)); - mirror::ByteBufferViewVarHandle::SetClass(GetClassRoot(kJavaLangInvokeByteBufferViewVarHandle)); - mirror::Reference::SetClass(GetClassRoot(kJavaLangRefReference)); - mirror::BooleanArray::SetArrayClass(GetClassRoot(kBooleanArrayClass)); - mirror::ByteArray::SetArrayClass(GetClassRoot(kByteArrayClass)); - mirror::CharArray::SetArrayClass(GetClassRoot(kCharArrayClass)); - mirror::DoubleArray::SetArrayClass(GetClassRoot(kDoubleArrayClass)); - mirror::FloatArray::SetArrayClass(GetClassRoot(kFloatArrayClass)); - mirror::IntArray::SetArrayClass(GetClassRoot(kIntArrayClass)); - mirror::LongArray::SetArrayClass(GetClassRoot(kLongArrayClass)); - mirror::ShortArray::SetArrayClass(GetClassRoot(kShortArrayClass)); - mirror::Throwable::SetClass(GetClassRoot(kJavaLangThrowable)); - mirror::StackTraceElement::SetClass(GetClassRoot(kJavaLangStackTraceElement)); - mirror::EmulatedStackFrame::SetClass(GetClassRoot(kDalvikSystemEmulatedStackFrame)); - mirror::ClassExt::SetClass(GetClassRoot(kDalvikSystemClassExt)); + mirror::Field::SetClass(GetClassRoot(ClassRoot::kJavaLangReflectField, this)); + mirror::Field::SetArrayClass(GetClassRoot(ClassRoot::kJavaLangReflectFieldArrayClass, this)); + mirror::Constructor::SetClass(GetClassRoot(ClassRoot::kJavaLangReflectConstructor, this).Ptr()); + mirror::Constructor::SetArrayClass( + GetClassRoot(ClassRoot::kJavaLangReflectConstructorArrayClass, this).Ptr()); + mirror::Method::SetClass(GetClassRoot(ClassRoot::kJavaLangReflectMethod, this).Ptr()); + mirror::Method::SetArrayClass( + GetClassRoot(ClassRoot::kJavaLangReflectMethodArrayClass, this).Ptr()); + mirror::CallSite::SetClass(GetClassRoot(ClassRoot::kJavaLangInvokeCallSite, this).Ptr()); + mirror::MethodHandleImpl::SetClass( + GetClassRoot(ClassRoot::kJavaLangInvokeMethodHandleImpl, this).Ptr()); + mirror::MethodHandlesLookup::SetClass( + GetClassRoot(ClassRoot::kJavaLangInvokeMethodHandlesLookup, this).Ptr()); + mirror::MethodType::SetClass( + GetClassRoot(ClassRoot::kJavaLangInvokeMethodType, this).Ptr()); + mirror::VarHandle::SetClass(GetClassRoot(ClassRoot::kJavaLangInvokeVarHandle, this).Ptr()); + mirror::FieldVarHandle::SetClass( + GetClassRoot(ClassRoot::kJavaLangInvokeFieldVarHandle, this).Ptr()); + mirror::ArrayElementVarHandle::SetClass( + GetClassRoot(ClassRoot::kJavaLangInvokeArrayElementVarHandle, this).Ptr()); + mirror::ByteArrayViewVarHandle::SetClass( + GetClassRoot(ClassRoot::kJavaLangInvokeByteArrayViewVarHandle, this).Ptr()); + mirror::ByteBufferViewVarHandle::SetClass( + GetClassRoot(ClassRoot::kJavaLangInvokeByteBufferViewVarHandle, this).Ptr()); + mirror::Reference::SetClass(GetClassRoot(ClassRoot::kJavaLangRefReference, this)); + mirror::BooleanArray::SetArrayClass(GetClassRoot(ClassRoot::kBooleanArrayClass, this)); + mirror::ByteArray::SetArrayClass(GetClassRoot(ClassRoot::kByteArrayClass, this)); + mirror::CharArray::SetArrayClass(GetClassRoot(ClassRoot::kCharArrayClass, this)); + mirror::DoubleArray::SetArrayClass(GetClassRoot(ClassRoot::kDoubleArrayClass, this)); + mirror::FloatArray::SetArrayClass(GetClassRoot(ClassRoot::kFloatArrayClass, this)); + mirror::IntArray::SetArrayClass(GetClassRoot(ClassRoot::kIntArrayClass, this)); + mirror::LongArray::SetArrayClass(GetClassRoot(ClassRoot::kLongArrayClass, this)); + mirror::ShortArray::SetArrayClass(GetClassRoot(ClassRoot::kShortArrayClass, this)); + mirror::Throwable::SetClass(GetClassRoot(ClassRoot::kJavaLangThrowable, this)); + mirror::StackTraceElement::SetClass(GetClassRoot(ClassRoot::kJavaLangStackTraceElement, this)); + mirror::EmulatedStackFrame::SetClass( + GetClassRoot(ClassRoot::kDalvikSystemEmulatedStackFrame, this).Ptr()); + mirror::ClassExt::SetClass(GetClassRoot(ClassRoot::kDalvikSystemClassExt, this)); for (gc::space::ImageSpace* image_space : spaces) { // Boot class loader, use a null handle. @@ -1695,15 +1710,16 @@ bool ClassLinker::AddImageSpace( MutableHandle<mirror::ClassLoader> image_class_loader(hs.NewHandle( app_image ? header.GetImageRoot(ImageHeader::kClassLoader)->AsClassLoader() : nullptr)); DCHECK(class_roots != nullptr); - if (class_roots->GetLength() != static_cast<int32_t>(kClassRootsMax)) { + if (class_roots->GetLength() != static_cast<int32_t>(ClassRoot::kMax)) { *error_msg = StringPrintf("Expected %d class roots but got %d", class_roots->GetLength(), - static_cast<int32_t>(kClassRootsMax)); + static_cast<int32_t>(ClassRoot::kMax)); return false; } // Check against existing class roots to make sure they match the ones in the boot image. - for (size_t i = 0; i < kClassRootsMax; i++) { - if (class_roots->Get(i) != GetClassRoot(static_cast<ClassRoot>(i))) { + ObjPtr<mirror::ObjectArray<mirror::Class>> existing_class_roots = GetClassRoots(); + for (size_t i = 0; i < static_cast<size_t>(ClassRoot::kMax); i++) { + if (class_roots->Get(i) != GetClassRoot(static_cast<ClassRoot>(i), existing_class_roots)) { *error_msg = "App image class roots must have pointer equality with runtime ones."; return false; } @@ -2231,7 +2247,7 @@ mirror::DexCache* ClassLinker::AllocDexCache(ObjPtr<mirror::String>* out_locatio StackHandleScope<1> hs(self); DCHECK(out_location != nullptr); auto dex_cache(hs.NewHandle(ObjPtr<mirror::DexCache>::DownCast( - GetClassRoot(kJavaLangDexCache)->AllocObject(self)))); + GetClassRoot<mirror::DexCache>(this)->AllocObject(self)))); if (dex_cache == nullptr) { self->AssertPendingOOMException(); return nullptr; @@ -2280,14 +2296,14 @@ mirror::Class* ClassLinker::AllocClass(Thread* self, } mirror::Class* ClassLinker::AllocClass(Thread* self, uint32_t class_size) { - return AllocClass(self, GetClassRoot(kJavaLangClass), class_size); + return AllocClass(self, GetClassRoot<mirror::Class>(this), class_size); } mirror::ObjectArray<mirror::StackTraceElement>* ClassLinker::AllocStackTraceElementArray( Thread* self, size_t length) { return mirror::ObjectArray<mirror::StackTraceElement>::Alloc( - self, GetClassRoot(kJavaLangStackTraceElementArrayClass), length); + self, GetClassRoot<mirror::ObjectArray<mirror::StackTraceElement>>(this), length); } mirror::Class* ClassLinker::EnsureResolved(Thread* self, @@ -2684,17 +2700,17 @@ mirror::Class* ClassLinker::DefineClass(Thread* self, if (UNLIKELY(!init_done_)) { // finish up init of hand crafted class_roots_ if (strcmp(descriptor, "Ljava/lang/Object;") == 0) { - klass.Assign(GetClassRoot(kJavaLangObject)); + klass.Assign(GetClassRoot<mirror::Object>(this)); } else if (strcmp(descriptor, "Ljava/lang/Class;") == 0) { - klass.Assign(GetClassRoot(kJavaLangClass)); + klass.Assign(GetClassRoot<mirror::Class>(this)); } else if (strcmp(descriptor, "Ljava/lang/String;") == 0) { - klass.Assign(GetClassRoot(kJavaLangString)); + klass.Assign(GetClassRoot<mirror::String>(this)); } else if (strcmp(descriptor, "Ljava/lang/ref/Reference;") == 0) { - klass.Assign(GetClassRoot(kJavaLangRefReference)); + klass.Assign(GetClassRoot<mirror::Reference>(this)); } else if (strcmp(descriptor, "Ljava/lang/DexCache;") == 0) { - klass.Assign(GetClassRoot(kJavaLangDexCache)); + klass.Assign(GetClassRoot<mirror::DexCache>(this)); } else if (strcmp(descriptor, "Ldalvik/system/ClassExt;") == 0) { - klass.Assign(GetClassRoot(kDalvikSystemClassExt)); + klass.Assign(GetClassRoot<mirror::ClassExt>(this)); } } @@ -2744,7 +2760,7 @@ mirror::Class* ClassLinker::DefineClass(Thread* self, ObjectLock<mirror::Class> lock(self, klass); klass->SetClinitThreadId(self->GetTid()); // Make sure we have a valid empty iftable even if there are errors. - klass->SetIfTable(GetClassRoot(kJavaLangObject)->GetIfTable()); + klass->SetIfTable(GetClassRoot<mirror::Object>(this)->GetIfTable()); // Add the newly loaded class to the loaded classes table. ObjPtr<mirror::Class> existing = InsertClass(descriptor, klass.Get(), hash); @@ -3084,7 +3100,7 @@ void ClassLinker::SetupClass(const DexFile& dex_file, const char* descriptor = dex_file.GetClassDescriptor(dex_class_def); CHECK(descriptor != nullptr); - klass->SetClass(GetClassRoot(kJavaLangClass)); + klass->SetClass(GetClassRoot<mirror::Class>(this)); uint32_t access_flags = dex_class_def.GetJavaAccessFlags(); CHECK_EQ(access_flags & ~kAccJavaFlagsMask, 0U); klass->SetAccessFlags(access_flags); @@ -3654,7 +3670,7 @@ mirror::Class* ClassLinker::InitializePrimitiveClass(ObjPtr<mirror::Class> primi ObjectLock<mirror::Class> lock(self, h_class); h_class->SetAccessFlags(kAccPublic | kAccFinal | kAccAbstract); h_class->SetPrimitiveType(type); - h_class->SetIfTable(GetClassRoot(kJavaLangObject)->GetIfTable()); + h_class->SetIfTable(GetClassRoot<mirror::Object>(this)->GetIfTable()); mirror::Class::SetStatus(h_class, ClassStatus::kInitialized, self); const char* descriptor = Primitive::Descriptor(type); ObjPtr<mirror::Class> existing = InsertClass(descriptor, @@ -3737,17 +3753,17 @@ mirror::Class* ClassLinker::CreateArrayClass(Thread* self, const char* descripto if (UNLIKELY(!init_done_)) { // Classes that were hand created, ie not by FindSystemClass if (strcmp(descriptor, "[Ljava/lang/Class;") == 0) { - new_class.Assign(GetClassRoot(kClassArrayClass)); + new_class.Assign(GetClassRoot<mirror::ObjectArray<mirror::Class>>(this)); } else if (strcmp(descriptor, "[Ljava/lang/Object;") == 0) { - new_class.Assign(GetClassRoot(kObjectArrayClass)); - } else if (strcmp(descriptor, GetClassRootDescriptor(kJavaLangStringArrayClass)) == 0) { - new_class.Assign(GetClassRoot(kJavaLangStringArrayClass)); + new_class.Assign(GetClassRoot<mirror::ObjectArray<mirror::Object>>(this)); + } else if (strcmp(descriptor, "[Ljava/lang/String;") == 0) { + new_class.Assign(GetClassRoot<mirror::ObjectArray<mirror::String>>(this)); } else if (strcmp(descriptor, "[C") == 0) { - new_class.Assign(GetClassRoot(kCharArrayClass)); + new_class.Assign(GetClassRoot<mirror::CharArray>(this)); } else if (strcmp(descriptor, "[I") == 0) { - new_class.Assign(GetClassRoot(kIntArrayClass)); + new_class.Assign(GetClassRoot<mirror::IntArray>(this)); } else if (strcmp(descriptor, "[J") == 0) { - new_class.Assign(GetClassRoot(kLongArrayClass)); + new_class.Assign(GetClassRoot<mirror::LongArray>(this)); } } if (new_class == nullptr) { @@ -3760,7 +3776,7 @@ mirror::Class* ClassLinker::CreateArrayClass(Thread* self, const char* descripto } ObjectLock<mirror::Class> lock(self, new_class); // Must hold lock on object when initializing. DCHECK(new_class->GetComponentType() != nullptr); - ObjPtr<mirror::Class> java_lang_Object = GetClassRoot(kJavaLangObject); + ObjPtr<mirror::Class> java_lang_Object = GetClassRoot<mirror::Object>(this); new_class->SetSuperClass(java_lang_Object); new_class->SetVTable(java_lang_Object->GetVTable()); new_class->SetPrimitiveType(Primitive::kPrimNot); @@ -3828,25 +3844,26 @@ mirror::Class* ClassLinker::CreateArrayClass(Thread* self, const char* descripto } mirror::Class* ClassLinker::FindPrimitiveClass(char type) { + ObjPtr<mirror::ObjectArray<mirror::Class>> class_roots = GetClassRoots(); switch (type) { case 'B': - return GetClassRoot(kPrimitiveByte); + return GetClassRoot(ClassRoot::kPrimitiveByte, class_roots).Ptr(); case 'C': - return GetClassRoot(kPrimitiveChar); + return GetClassRoot(ClassRoot::kPrimitiveChar, class_roots).Ptr(); case 'D': - return GetClassRoot(kPrimitiveDouble); + return GetClassRoot(ClassRoot::kPrimitiveDouble, class_roots).Ptr(); case 'F': - return GetClassRoot(kPrimitiveFloat); + return GetClassRoot(ClassRoot::kPrimitiveFloat, class_roots).Ptr(); case 'I': - return GetClassRoot(kPrimitiveInt); + return GetClassRoot(ClassRoot::kPrimitiveInt, class_roots).Ptr(); case 'J': - return GetClassRoot(kPrimitiveLong); + return GetClassRoot(ClassRoot::kPrimitiveLong, class_roots).Ptr(); case 'S': - return GetClassRoot(kPrimitiveShort); + return GetClassRoot(ClassRoot::kPrimitiveShort, class_roots).Ptr(); case 'Z': - return GetClassRoot(kPrimitiveBoolean); + return GetClassRoot(ClassRoot::kPrimitiveBoolean, class_roots).Ptr(); case 'V': - return GetClassRoot(kPrimitiveVoid); + return GetClassRoot(ClassRoot::kPrimitiveVoid, class_roots).Ptr(); default: break; } @@ -4381,7 +4398,7 @@ mirror::Class* ClassLinker::CreateProxyClass(ScopedObjectAccessAlreadyRunnable& Thread* self = soa.Self(); StackHandleScope<10> hs(self); MutableHandle<mirror::Class> temp_klass(hs.NewHandle( - AllocClass(self, GetClassRoot(kJavaLangClass), sizeof(mirror::Class)))); + AllocClass(self, GetClassRoot<mirror::Class>(this), sizeof(mirror::Class)))); if (temp_klass == nullptr) { CHECK(self->IsExceptionPending()); // OOME. return nullptr; @@ -4394,9 +4411,9 @@ mirror::Class* ClassLinker::CreateProxyClass(ScopedObjectAccessAlreadyRunnable& temp_klass->SetClassLoader(soa.Decode<mirror::ClassLoader>(loader)); DCHECK_EQ(temp_klass->GetPrimitiveType(), Primitive::kPrimNot); temp_klass->SetName(soa.Decode<mirror::String>(name)); - temp_klass->SetDexCache(GetClassRoot(kJavaLangReflectProxy)->GetDexCache()); + temp_klass->SetDexCache(GetClassRoot<mirror::Proxy>(this)->GetDexCache()); // Object has an empty iftable, copy it for that reason. - temp_klass->SetIfTable(GetClassRoot(kJavaLangObject)->GetIfTable()); + temp_klass->SetIfTable(GetClassRoot<mirror::Object>(this)->GetIfTable()); mirror::Class::SetStatus(temp_klass, ClassStatus::kIdx, self); std::string descriptor(GetDescriptorForProxy(temp_klass.Get())); const size_t hash = ComputeModifiedUtf8Hash(descriptor.c_str()); @@ -4463,7 +4480,7 @@ mirror::Class* ClassLinker::CreateProxyClass(ScopedObjectAccessAlreadyRunnable& } // The super class is java.lang.reflect.Proxy - temp_klass->SetSuperClass(GetClassRoot(kJavaLangReflectProxy)); + temp_klass->SetSuperClass(GetClassRoot<mirror::Proxy>(this)); // Now effectively in the loaded state. mirror::Class::SetStatus(temp_klass, ClassStatus::kLoaded, self); self->AssertNoPendingException(); @@ -4551,11 +4568,12 @@ std::string ClassLinker::GetDescriptorForProxy(ObjPtr<mirror::Class> proxy_class void ClassLinker::CreateProxyConstructor(Handle<mirror::Class> klass, ArtMethod* out) { // Create constructor for Proxy that must initialize the method. - CHECK_EQ(GetClassRoot(kJavaLangReflectProxy)->NumDirectMethods(), 21u); + ObjPtr<mirror::Class> proxy_class = GetClassRoot<mirror::Proxy>(this); + CHECK_EQ(proxy_class->NumDirectMethods(), 21u); // Find the <init>(InvocationHandler)V method. The exact method offset varies depending // on which front-end compiler was used to build the libcore DEX files. - ArtMethod* proxy_constructor = GetClassRoot(kJavaLangReflectProxy)->FindConstructor( + ArtMethod* proxy_constructor = proxy_class->FindConstructor( "(Ljava/lang/reflect/InvocationHandler;)V", image_pointer_size_); DCHECK(proxy_constructor != nullptr) << "Could not find <init> method in java.lang.reflect.Proxy"; @@ -5553,7 +5571,8 @@ bool ClassLinker::LoadSuperAndInterfaces(Handle<mirror::Class> klass, const DexF bool ClassLinker::LinkSuperClass(Handle<mirror::Class> klass) { CHECK(!klass->IsPrimitive()); ObjPtr<mirror::Class> super = klass->GetSuperClass(); - if (klass.Get() == GetClassRoot(kJavaLangObject)) { + ObjPtr<mirror::Class> object_class = GetClassRoot<mirror::Object>(this); + if (klass.Get() == object_class) { if (super != nullptr) { ThrowClassFormatError(klass.Get(), "java.lang.Object must not have a superclass"); return false; @@ -5566,7 +5585,7 @@ bool ClassLinker::LinkSuperClass(Handle<mirror::Class> klass) { return false; } // Verify - if (klass->IsInterface() && super != GetClassRoot(kJavaLangObject)) { + if (klass->IsInterface() && super != object_class) { ThrowClassFormatError(klass.Get(), "Interfaces must have java.lang.Object as superclass"); return false; } @@ -5609,7 +5628,7 @@ bool ClassLinker::LinkSuperClass(Handle<mirror::Class> klass) { klass->SetClassFlags(klass->GetClassFlags() | reference_flags); } // Disallow custom direct subclasses of java.lang.ref.Reference. - if (init_done_ && super == GetClassRoot(kJavaLangRefReference)) { + if (init_done_ && super == GetClassRoot<mirror::Reference>(this)) { ThrowLinkageError(klass.Get(), "Class %s attempts to subclass java.lang.ref.Reference, which is not allowed", klass->PrettyDescriptor().c_str()); @@ -5974,7 +5993,7 @@ bool ClassLinker::LinkVirtualMethods( } klass->SetVTable(vtable.Get()); } else { - CHECK_EQ(klass.Get(), GetClassRoot(kJavaLangObject)); + CHECK_EQ(klass.Get(), GetClassRoot<mirror::Object>(this)); if (!IsUint<16>(num_virtual_methods)) { ThrowClassFormatError(klass.Get(), "Too many methods: %d", static_cast<int>(num_virtual_methods)); @@ -7851,7 +7870,7 @@ ObjPtr<mirror::Class> ClassLinker::DoResolveType(dex::TypeIndex type_idx, // Convert a ClassNotFoundException to a NoClassDefFoundError. StackHandleScope<1> hs(self); Handle<mirror::Throwable> cause(hs.NewHandle(self->GetException())); - if (cause->InstanceOf(GetClassRoot(kJavaLangClassNotFoundException))) { + if (cause->InstanceOf(GetClassRoot(ClassRoot::kJavaLangClassNotFoundException, this))) { DCHECK(resolved == nullptr); // No Handle needed to preserve resolved. self->ClearException(); ThrowNoClassDefFoundError("Failed resolution of: %s", descriptor); @@ -8678,67 +8697,10 @@ void ClassLinker::SetClassRoot(ClassRoot class_root, ObjPtr<mirror::Class> klass mirror::ObjectArray<mirror::Class>* class_roots = class_roots_.Read(); DCHECK(class_roots != nullptr); - DCHECK(class_roots->Get(class_root) == nullptr); - class_roots->Set<false>(class_root, klass); -} - -const char* ClassLinker::GetClassRootDescriptor(ClassRoot class_root) { - static const char* class_roots_descriptors[] = { - "Ljava/lang/Class;", - "Ljava/lang/Object;", - "[Ljava/lang/Class;", - "[Ljava/lang/Object;", - "Ljava/lang/String;", - "Ljava/lang/DexCache;", - "Ljava/lang/ref/Reference;", - "Ljava/lang/reflect/Constructor;", - "Ljava/lang/reflect/Field;", - "Ljava/lang/reflect/Method;", - "Ljava/lang/reflect/Proxy;", - "[Ljava/lang/String;", - "[Ljava/lang/reflect/Constructor;", - "[Ljava/lang/reflect/Field;", - "[Ljava/lang/reflect/Method;", - "Ljava/lang/invoke/CallSite;", - "Ljava/lang/invoke/MethodHandleImpl;", - "Ljava/lang/invoke/MethodHandles$Lookup;", - "Ljava/lang/invoke/MethodType;", - "Ljava/lang/invoke/VarHandle;", - "Ljava/lang/invoke/FieldVarHandle;", - "Ljava/lang/invoke/ArrayElementVarHandle;", - "Ljava/lang/invoke/ByteArrayViewVarHandle;", - "Ljava/lang/invoke/ByteBufferViewVarHandle;", - "Ljava/lang/ClassLoader;", - "Ljava/lang/Throwable;", - "Ljava/lang/ClassNotFoundException;", - "Ljava/lang/StackTraceElement;", - "Ldalvik/system/EmulatedStackFrame;", - "Z", - "B", - "C", - "D", - "F", - "I", - "J", - "S", - "V", - "[Z", - "[B", - "[C", - "[D", - "[F", - "[I", - "[J", - "[S", - "[Ljava/lang/StackTraceElement;", - "Ldalvik/system/ClassExt;", - }; - static_assert(arraysize(class_roots_descriptors) == size_t(kClassRootsMax), - "Mismatch between class descriptors and class-root enum"); - - const char* descriptor = class_roots_descriptors[class_root]; - CHECK(descriptor != nullptr); - return descriptor; + DCHECK_LT(static_cast<uint32_t>(class_root), static_cast<uint32_t>(ClassRoot::kMax)); + int32_t index = static_cast<int32_t>(class_root); + DCHECK(class_roots->Get(index) == nullptr); + class_roots->Set<false>(index, klass); } jobject ClassLinker::CreateWellKnownClassLoader(Thread* self, @@ -9071,7 +9033,7 @@ mirror::Class* ClassLinker::GetHoldingClassOfCopiedMethod(ArtMethod* method) { mirror::IfTable* ClassLinker::AllocIfTable(Thread* self, size_t ifcount) { return down_cast<mirror::IfTable*>( mirror::IfTable::Alloc(self, - GetClassRoot(kObjectArrayClass), + GetClassRoot<mirror::ObjectArray<mirror::Object>>(this), ifcount * mirror::IfTable::kMax)); } diff --git a/runtime/class_linker.h b/runtime/class_linker.h index 52ecf82c86..afe5c99990 100644 --- a/runtime/class_linker.h +++ b/runtime/class_linker.h @@ -68,6 +68,7 @@ using MethodDexCacheType = std::atomic<MethodDexCachePair>; } // namespace mirror class ClassHierarchyAnalysis; +enum class ClassRoot : uint32_t; class ClassTable; template<class T> class Handle; class ImtConflictTable; @@ -107,59 +108,6 @@ class AllocatorVisitor { class ClassLinker { public: - // Well known mirror::Class roots accessed via GetClassRoot. - enum ClassRoot { - kJavaLangClass, - kJavaLangObject, - kClassArrayClass, - kObjectArrayClass, - kJavaLangString, - kJavaLangDexCache, - kJavaLangRefReference, - kJavaLangReflectConstructor, - kJavaLangReflectField, - kJavaLangReflectMethod, - kJavaLangReflectProxy, - kJavaLangStringArrayClass, - kJavaLangReflectConstructorArrayClass, - kJavaLangReflectFieldArrayClass, - kJavaLangReflectMethodArrayClass, - kJavaLangInvokeCallSite, - kJavaLangInvokeMethodHandleImpl, - kJavaLangInvokeMethodHandlesLookup, - kJavaLangInvokeMethodType, - kJavaLangInvokeVarHandle, - kJavaLangInvokeFieldVarHandle, - kJavaLangInvokeArrayElementVarHandle, - kJavaLangInvokeByteArrayViewVarHandle, - kJavaLangInvokeByteBufferViewVarHandle, - kJavaLangClassLoader, - kJavaLangThrowable, - kJavaLangClassNotFoundException, - kJavaLangStackTraceElement, - kDalvikSystemEmulatedStackFrame, - kPrimitiveBoolean, - kPrimitiveByte, - kPrimitiveChar, - kPrimitiveDouble, - kPrimitiveFloat, - kPrimitiveInt, - kPrimitiveLong, - kPrimitiveShort, - kPrimitiveVoid, - kBooleanArrayClass, - kByteArrayClass, - kCharArrayClass, - kDoubleArrayClass, - kFloatArrayClass, - kIntArrayClass, - kLongArrayClass, - kShortArrayClass, - kJavaLangStackTraceElementArrayClass, - kDalvikSystemClassExt, - kClassRootsMax, - }; - static constexpr bool kAppImageMayContainStrings = false; explicit ClassLinker(InternTable* intern_table); @@ -552,10 +500,6 @@ class ClassLinker { pid_t GetClassesLockOwner(); // For SignalCatcher. pid_t GetDexLockOwner(); // For SignalCatcher. - mirror::Class* GetClassRoot(ClassRoot class_root) REQUIRES_SHARED(Locks::mutator_lock_); - - static const char* GetClassRootDescriptor(ClassRoot class_root); - // Is the given entry point quick code to run the resolution stub? bool IsQuickResolutionStub(const void* entry_point) const; @@ -597,8 +541,9 @@ class ClassLinker { REQUIRES(!Locks::classlinker_classes_lock_) REQUIRES_SHARED(Locks::mutator_lock_); + template <ReadBarrierOption kReadBarrierOption = kWithReadBarrier> mirror::ObjectArray<mirror::Class>* GetClassRoots() REQUIRES_SHARED(Locks::mutator_lock_) { - mirror::ObjectArray<mirror::Class>* class_roots = class_roots_.Read(); + mirror::ObjectArray<mirror::Class>* class_roots = class_roots_.Read<kReadBarrierOption>(); DCHECK(class_roots != nullptr); return class_roots; } diff --git a/runtime/class_linker_test.cc b/runtime/class_linker_test.cc index 6ed029ceb1..48ec6b6c27 100644 --- a/runtime/class_linker_test.cc +++ b/runtime/class_linker_test.cc @@ -25,6 +25,7 @@ #include "art_method-inl.h" #include "base/enums.h" #include "class_linker-inl.h" +#include "class_root.h" #include "common_runtime_test.h" #include "dex/dex_file_types.h" #include "dex/standard_dex_file.h" @@ -1387,11 +1388,10 @@ TEST_F(ClassLinkerTest, FinalizableBit) { TEST_F(ClassLinkerTest, ClassRootDescriptors) { ScopedObjectAccess soa(Thread::Current()); std::string temp; - for (int i = 0; i < ClassLinker::kClassRootsMax; i++) { - ObjPtr<mirror::Class> klass = class_linker_->GetClassRoot(ClassLinker::ClassRoot(i)); + for (size_t i = 0; i < static_cast<size_t>(ClassRoot::kMax); i++) { + ObjPtr<mirror::Class> klass = GetClassRoot(ClassRoot(i), class_linker_); EXPECT_GT(strlen(klass->GetDescriptor(&temp)), 0U); - EXPECT_STREQ(klass->GetDescriptor(&temp), - class_linker_->GetClassRootDescriptor(ClassLinker::ClassRoot(i))) << " i = " << i; + EXPECT_STREQ(klass->GetDescriptor(&temp), GetClassRootDescriptor(ClassRoot(i))) << " i = " << i; } } diff --git a/runtime/class_root.cc b/runtime/class_root.cc new file mode 100644 index 0000000000..08820b0c61 --- /dev/null +++ b/runtime/class_root.cc @@ -0,0 +1,36 @@ +/* + * 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. + */ + +#include "class_root.h" + +namespace art { + +const char* GetClassRootDescriptor(ClassRoot class_root) { + static const char* class_roots_descriptors[] = { +#define CLASS_ROOT_DESCRIPTOR(name, descriptor, mirror_type) descriptor, + CLASS_ROOT_LIST(CLASS_ROOT_DESCRIPTOR) +#undef CLASS_ROOT_DESCRIPTOR + }; + static_assert(arraysize(class_roots_descriptors) == static_cast<size_t>(ClassRoot::kMax), + "Mismatch between class descriptors and class-root enum"); + + DCHECK_LT(static_cast<uint32_t>(class_root), static_cast<uint32_t>(ClassRoot::kMax)); + const char* descriptor = class_roots_descriptors[static_cast<size_t>(class_root)]; + CHECK(descriptor != nullptr); + return descriptor; +} + +} // namespace art diff --git a/runtime/class_root.h b/runtime/class_root.h new file mode 100644 index 0000000000..f43e2c6920 --- /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_ diff --git a/runtime/entrypoints/quick/callee_save_frame.h b/runtime/entrypoints/quick/callee_save_frame.h index 6f1bbaa093..1e309071f6 100644 --- a/runtime/entrypoints/quick/callee_save_frame.h +++ b/runtime/entrypoints/quick/callee_save_frame.h @@ -68,7 +68,7 @@ class ScopedQuickEntrypointChecks { bool exit_check_; }; -namespace detail_ { +namespace detail { template <InstructionSet> struct CSFSelector; // No definition for unspecialized callee save frame selector. @@ -87,9 +87,9 @@ struct CSFSelector<InstructionSet::kX86> { using type = x86::X86CalleeSaveFrame; template <> struct CSFSelector<InstructionSet::kX86_64> { using type = x86_64::X86_64CalleeSaveFrame; }; -} // namespace detail_ +} // namespace detail -using RuntimeCalleeSaveFrame = detail_::CSFSelector<kRuntimeISA>::type; +using RuntimeCalleeSaveFrame = detail::CSFSelector<kRuntimeISA>::type; } // namespace art diff --git a/runtime/gc/accounting/mod_union_table_test.cc b/runtime/gc/accounting/mod_union_table_test.cc index e5b8ea5609..d59ff71676 100644 --- a/runtime/gc/accounting/mod_union_table_test.cc +++ b/runtime/gc/accounting/mod_union_table_test.cc @@ -17,6 +17,7 @@ #include "mod_union_table-inl.h" #include "class_linker-inl.h" +#include "class_root.h" #include "common_runtime_test.h" #include "gc/space/space-inl.h" #include "mirror/array-inl.h" @@ -70,8 +71,7 @@ class ModUnionTableTest : public CommonRuntimeTest { mirror::Class* GetObjectArrayClass(Thread* self, space::ContinuousMemMapAllocSpace* space) REQUIRES_SHARED(Locks::mutator_lock_) { if (java_lang_object_array_ == nullptr) { - java_lang_object_array_ = - Runtime::Current()->GetClassLinker()->GetClassRoot(ClassLinker::kObjectArrayClass); + java_lang_object_array_ = GetClassRoot<mirror::ObjectArray<mirror::Object>>().Ptr(); // Since the test doesn't have an image, the class of the object array keeps cards live // inside the card cache mod-union table and causes the check // ASSERT_FALSE(table->ContainsCardFor(reinterpret_cast<uintptr_t>(obj3))); diff --git a/runtime/gc/collector/concurrent_copying.cc b/runtime/gc/collector/concurrent_copying.cc index 0747c3c77b..2c2c437365 100644 --- a/runtime/gc/collector/concurrent_copying.cc +++ b/runtime/gc/collector/concurrent_copying.cc @@ -23,6 +23,7 @@ #include "base/quasi_atomic.h" #include "base/stl_util.h" #include "base/systrace.h" +#include "class_root.h" #include "debugger.h" #include "gc/accounting/atomic_stack.h" #include "gc/accounting/heap_bitmap-inl.h" @@ -2244,7 +2245,7 @@ void ConcurrentCopying::FillWithDummyObject(mirror::Object* dummy_obj, size_t by // Avoid going through read barrier for since kDisallowReadBarrierDuringScan may be enabled. // Explicitly mark to make sure to get an object in the to-space. mirror::Class* int_array_class = down_cast<mirror::Class*>( - Mark(mirror::IntArray::GetArrayClass<kWithoutReadBarrier>())); + Mark(GetClassRoot<mirror::IntArray, kWithoutReadBarrier>().Ptr())); CHECK(int_array_class != nullptr); if (ReadBarrier::kEnableToSpaceInvariantChecks) { AssertToSpaceInvariant(nullptr, MemberOffset(0), int_array_class); @@ -2324,7 +2325,7 @@ mirror::Object* ConcurrentCopying::AllocateInSkippedBlock(size_t alloc_size) { CHECK_GE(byte_size - alloc_size, min_object_size); // FillWithDummyObject may mark an object, avoid holding skipped_blocks_lock_ to prevent lock // violation and possible deadlock. The deadlock case is a recursive case: - // FillWithDummyObject -> IntArray::GetArrayClass -> Mark -> Copy -> AllocateInSkippedBlock. + // FillWithDummyObject -> Mark(IntArray.class) -> Copy -> AllocateInSkippedBlock. FillWithDummyObject(reinterpret_cast<mirror::Object*>(addr + alloc_size), byte_size - alloc_size); CHECK(region_space_->IsInToSpace(reinterpret_cast<mirror::Object*>(addr + alloc_size))); diff --git a/runtime/gc/heap_verification_test.cc b/runtime/gc/heap_verification_test.cc index 40ee86ce79..4f06ee6910 100644 --- a/runtime/gc/heap_verification_test.cc +++ b/runtime/gc/heap_verification_test.cc @@ -18,6 +18,7 @@ #include "base/memory_tool.h" #include "class_linker-inl.h" +#include "class_root.h" #include "handle_scope-inl.h" #include "mirror/object-inl.h" #include "mirror/object_array-inl.h" @@ -36,10 +37,9 @@ class VerificationTest : public CommonRuntimeTest { template <class T> mirror::ObjectArray<T>* AllocObjectArray(Thread* self, size_t length) REQUIRES_SHARED(Locks::mutator_lock_) { - ClassLinker* const class_linker = Runtime::Current()->GetClassLinker(); return mirror::ObjectArray<T>::Alloc( self, - class_linker->GetClassRoot(ClassLinker::ClassRoot::kObjectArrayClass), + GetClassRoot<mirror::ObjectArray<mirror::Object>>(), length); } }; diff --git a/runtime/hprof/hprof.cc b/runtime/hprof/hprof.cc index 3b6487449b..7bd5a6a68a 100644 --- a/runtime/hprof/hprof.cc +++ b/runtime/hprof/hprof.cc @@ -50,6 +50,7 @@ #include "base/time_utils.h" #include "base/unix_file/fd_file.h" #include "class_linker.h" +#include "class_root.h" #include "common_throws.h" #include "debugger.h" #include "dex/dex_file-inl.h" @@ -1418,8 +1419,7 @@ void Hprof::DumpFakeObjectArray(mirror::Object* obj, const std::set<mirror::Obje __ AddObjectId(obj); __ AddStackTraceSerialNumber(LookupStackTraceSerialNumber(obj)); __ AddU4(elements.size()); - __ AddClassId(LookupClassId( - Runtime::Current()->GetClassLinker()->GetClassRoot(ClassLinker::kObjectArrayClass))); + __ AddClassId(LookupClassId(GetClassRoot<mirror::ObjectArray<mirror::Object>>().Ptr())); for (mirror::Object* e : elements) { __ AddObjectId(e); } diff --git a/runtime/interpreter/unstarted_runtime_test.cc b/runtime/interpreter/unstarted_runtime_test.cc index 860de2c28b..98fe8b271b 100644 --- a/runtime/interpreter/unstarted_runtime_test.cc +++ b/runtime/interpreter/unstarted_runtime_test.cc @@ -23,6 +23,7 @@ #include "base/enums.h" #include "base/memory_tool.h" #include "class_linker.h" +#include "class_root.h" #include "common_runtime_test.h" #include "dex/descriptors_names.h" #include "dex/dex_instruction.h" @@ -1370,7 +1371,7 @@ TEST_F(UnstartedRuntimeTest, ConstructorNewInstance0) { Handle<mirror::ObjectArray<mirror::Object>> args = hs.NewHandle( mirror::ObjectArray<mirror::Object>::Alloc( - self, class_linker_->GetClassRoot(ClassLinker::ClassRoot::kObjectArrayClass), 1)); + self, GetClassRoot<mirror::ObjectArray<mirror::Object>>(class_linker_), 1)); ASSERT_TRUE(args != nullptr); args->Set(0, input.Get()); diff --git a/runtime/mirror/class.cc b/runtime/mirror/class.cc index 3f4e841f86..ad6b37b86a 100644 --- a/runtime/mirror/class.cc +++ b/runtime/mirror/class.cc @@ -26,6 +26,7 @@ #include "class_ext.h" #include "class_linker-inl.h" #include "class_loader.h" +#include "class_root.h" #include "dex/descriptors_names.h" #include "dex/dex_file-inl.h" #include "dex/dex_file_annotations.h" @@ -75,26 +76,26 @@ void Class::VisitRoots(RootVisitor* visitor) { ObjPtr<mirror::Class> Class::GetPrimitiveClass(ObjPtr<mirror::String> name) { const char* expected_name = nullptr; - ClassLinker::ClassRoot class_root = ClassLinker::kJavaLangObject; // Invalid. + ClassRoot class_root = ClassRoot::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; + case 'b': expected_name = "boolean"; class_root = ClassRoot::kPrimitiveBoolean; break; + case 'B': expected_name = "byte"; class_root = ClassRoot::kPrimitiveByte; break; + case 'c': expected_name = "char"; class_root = ClassRoot::kPrimitiveChar; break; + case 'd': expected_name = "double"; class_root = ClassRoot::kPrimitiveDouble; break; + case 'f': expected_name = "float"; class_root = ClassRoot::kPrimitiveFloat; break; + case 'i': expected_name = "int"; class_root = ClassRoot::kPrimitiveInt; break; + case 'l': expected_name = "long"; class_root = ClassRoot::kPrimitiveLong; break; + case 's': expected_name = "short"; class_root = ClassRoot::kPrimitiveShort; break; + case 'v': expected_name = "void"; class_root = ClassRoot::kPrimitiveVoid; break; default: break; } } if (expected_name != nullptr && name->Equals(expected_name)) { - ObjPtr<mirror::Class> klass = Runtime::Current()->GetClassLinker()->GetClassRoot(class_root); + ObjPtr<mirror::Class> klass = GetClassRoot(class_root); DCHECK(klass != nullptr); return klass; } else { diff --git a/runtime/mirror/emulated_stack_frame.cc b/runtime/mirror/emulated_stack_frame.cc index 5f00c6e9c7..527408b3e5 100644 --- a/runtime/mirror/emulated_stack_frame.cc +++ b/runtime/mirror/emulated_stack_frame.cc @@ -17,6 +17,7 @@ #include "emulated_stack_frame.h" #include "class-inl.h" +#include "class_root.h" #include "gc_root-inl.h" #include "jvalue-inl.h" #include "method_handles-inl.h" @@ -166,8 +167,7 @@ mirror::EmulatedStackFrame* EmulatedStackFrame::CreateFromShadowFrameAndArgs( CalculateFrameAndReferencesSize(to_types.Get(), r_type.Get(), &frame_size, &refs_size); // Step 3 : Allocate the arrays. - ClassLinker* class_linker = Runtime::Current()->GetClassLinker(); - ObjPtr<mirror::Class> array_class(class_linker->GetClassRoot(ClassLinker::kObjectArrayClass)); + ObjPtr<mirror::Class> array_class(GetClassRoot<mirror::ObjectArray<mirror::Object>>()); Handle<mirror::ObjectArray<mirror::Object>> references(hs.NewHandle( mirror::ObjectArray<mirror::Object>::Alloc(self, array_class, refs_size))); diff --git a/runtime/mirror/object_test.cc b/runtime/mirror/object_test.cc index 69ba4b98cf..8b7a1b6876 100644 --- a/runtime/mirror/object_test.cc +++ b/runtime/mirror/object_test.cc @@ -28,6 +28,7 @@ #include "class-inl.h" #include "class_linker-inl.h" #include "class_linker.h" +#include "class_root.h" #include "common_runtime_test.h" #include "dex/dex_file.h" #include "entrypoints/entrypoint_utils-inl.h" @@ -78,7 +79,7 @@ class ObjectTest : public CommonRuntimeTest { mirror::ObjectArray<T>* AllocObjectArray(Thread* self, size_t length) REQUIRES_SHARED(Locks::mutator_lock_) { return mirror::ObjectArray<T>::Alloc( - self, class_linker_->GetClassRoot(ClassLinker::ClassRoot::kObjectArrayClass), length); + self, GetClassRoot(ClassRoot::kObjectArrayClass, class_linker_), length); } }; diff --git a/runtime/thread.cc b/runtime/thread.cc index 5a80929350..129bae6d9a 100644 --- a/runtime/thread.cc +++ b/runtime/thread.cc @@ -47,6 +47,7 @@ #include "base/to_str.h" #include "base/utils.h" #include "class_linker-inl.h" +#include "class_root.h" #include "debugger.h" #include "dex/descriptors_names.h" #include "dex/dex_file-inl.h" @@ -2510,7 +2511,8 @@ class BuildInternalStackTraceVisitor : public StackVisitor { // class of the ArtMethod pointers. ClassLinker* class_linker = Runtime::Current()->GetClassLinker(); StackHandleScope<1> hs(self_); - ObjPtr<mirror::Class> array_class = class_linker->GetClassRoot(ClassLinker::kObjectArrayClass); + ObjPtr<mirror::Class> array_class = + GetClassRoot<mirror::ObjectArray<mirror::Object>>(class_linker); // The first element is the methods and dex pc array, the other elements are declaring classes // for the methods to ensure classes in the stack trace don't get unloaded. Handle<mirror::ObjectArray<mirror::Object>> trace( |