summaryrefslogtreecommitdiff
path: root/runtime/class_linker.cc
diff options
context:
space:
mode:
Diffstat (limited to 'runtime/class_linker.cc')
-rw-r--r--runtime/class_linker.cc929
1 files changed, 383 insertions, 546 deletions
diff --git a/runtime/class_linker.cc b/runtime/class_linker.cc
index b88aa5e07a..fd10f3b5e6 100644
--- a/runtime/class_linker.cc
+++ b/runtime/class_linker.cc
@@ -51,10 +51,12 @@
#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"
#include "debugger.h"
+#include "dex/class_accessor-inl.h"
#include "dex/descriptors_names.h"
#include "dex/dex_file-inl.h"
#include "dex/dex_file_exception_helpers.h"
@@ -431,10 +433,10 @@ bool ClassLinker::InitWithoutImage(std::vector<std::unique_ptr<const DexFile>> b
heap->IncrementDisableMovingGC(self);
StackHandleScope<64> hs(self); // 64 is picked arbitrarily.
auto class_class_size = mirror::Class::ClassClassSize(image_pointer_size_);
- Handle<mirror::Class> java_lang_Class(hs.NewHandle(down_cast<mirror::Class*>(
- heap->AllocNonMovableObject<true>(self, nullptr, class_class_size, VoidFunctor()))));
+ Handle<mirror::Class> java_lang_Class(hs.NewHandle(ObjPtr<mirror::Class>::DownCast(MakeObjPtr(
+ heap->AllocNonMovableObject<true>(self, nullptr, class_class_size, VoidFunctor())))));
CHECK(java_lang_Class != nullptr);
- mirror::Class::SetClassClass(java_lang_Class.Get());
+ java_lang_Class->SetClassFlags(mirror::kClassFlagClass);
java_lang_Class->SetClass(java_lang_Class.Get());
if (kUseBakerReadBarrier) {
java_lang_Class->AssertReadBarrierState();
@@ -483,86 +485,66 @@ bool ClassLinker::InitWithoutImage(std::vector<std::unique_ptr<const DexFile>> b
mirror::ObjectArray<mirror::Object>::ClassSize(image_pointer_size_))));
object_array_class->SetComponentType(java_lang_Object.Get());
- // Setup the char (primitive) class to be used for char[].
- Handle<mirror::Class> char_class(hs.NewHandle(
- AllocClass(self, java_lang_Class.Get(),
- mirror::Class::PrimitiveClassSize(image_pointer_size_))));
- // The primitive char class won't be initialized by
- // InitializePrimitiveClass until line 459, but strings (and
- // internal char arrays) will be allocated before that and the
- // component size, which is computed from the primitive type, needs
- // to be set here.
- char_class->SetPrimitiveType(Primitive::kPrimChar);
-
- // Setup the char[] class to be used for String.
- Handle<mirror::Class> char_array_class(hs.NewHandle(
- AllocClass(self, java_lang_Class.Get(), mirror::Array::ClassSize(image_pointer_size_))));
- char_array_class->SetComponentType(char_class.Get());
- mirror::CharArray::SetArrayClass(char_array_class.Get());
-
// Setup String.
Handle<mirror::Class> java_lang_String(hs.NewHandle(
AllocClass(self, java_lang_Class.Get(), mirror::String::ClassSize(image_pointer_size_))));
java_lang_String->SetStringClass();
- mirror::String::SetClass(java_lang_String.Get());
mirror::Class::SetStatus(java_lang_String, ClassStatus::kResolved, self);
// Setup java.lang.ref.Reference.
Handle<mirror::Class> java_lang_ref_Reference(hs.NewHandle(
AllocClass(self, java_lang_Class.Get(), mirror::Reference::ClassSize(image_pointer_size_))));
- mirror::Reference::SetClass(java_lang_ref_Reference.Get());
java_lang_ref_Reference->SetObjectSize(mirror::Reference::InstanceSize());
mirror::Class::SetStatus(java_lang_ref_Reference, ClassStatus::kResolved, self);
// 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::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::kPrimitiveChar, CreatePrimitiveClass(self, Primitive::kPrimChar));
+ 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));
- // Create int array type for AllocDexCache (done in AppendToBootClassPath).
+ // Create int array type for native pointer arrays (for example vtables) on 32-bit archs.
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));
- mirror::IntArray::SetArrayClass(int_array_class.Get());
- SetClassRoot(kIntArrayClass, int_array_class.Get());
+ int_array_class->SetComponentType(GetClassRoot(ClassRoot::kPrimitiveInt, this));
+ SetClassRoot(ClassRoot::kIntArrayClass, int_array_class.Get());
- // Create long array type for AllocDexCache (done in AppendToBootClassPath).
+ // Create long array type for native pointer arrays (for example vtables) on 64-bit archs.
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));
- mirror::LongArray::SetArrayClass(long_array_class.Get());
- SetClassRoot(kLongArrayClass, long_array_class.Get());
+ long_array_class->SetComponentType(GetClassRoot(ClassRoot::kPrimitiveLong, this));
+ 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,8 +553,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());
- mirror::ClassExt::SetClass(dalvik_system_ClassExt.Get());
+ SetClassRoot(ClassRoot::kDalvikSystemClassExt, dalvik_system_ClassExt.Get());
mirror::Class::SetStatus(dalvik_system_ClassExt, ClassStatus::kResolved, self);
// Set up array classes for string, field, method
@@ -580,7 +561,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.
@@ -606,10 +587,6 @@ bool ClassLinker::InitWithoutImage(std::vector<std::unique_ptr<const DexFile>> b
// now we can use FindSystemClass
- // run char class through InitializePrimitiveClass to finish init
- InitializePrimitiveClass(char_class.Get(), Primitive::kPrimChar);
- SetClassRoot(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.
quick_generic_jni_trampoline_ = GetQuickGenericJniStub();
@@ -634,25 +611,20 @@ 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"));
- SetClassRoot(kByteArrayClass, FindSystemClass(self, "[B"));
- mirror::ByteArray::SetArrayClass(GetClassRoot(kByteArrayClass));
+ SetClassRoot(ClassRoot::kByteArrayClass, FindSystemClass(self, "[B"));
- CheckSystemClass(self, char_array_class, "[C");
+ SetClassRoot(ClassRoot::kCharArrayClass, FindSystemClass(self, "[C"));
- SetClassRoot(kShortArrayClass, FindSystemClass(self, "[S"));
- mirror::ShortArray::SetArrayClass(GetClassRoot(kShortArrayClass));
+ SetClassRoot(ClassRoot::kShortArrayClass, FindSystemClass(self, "[S"));
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"));
- SetClassRoot(kDoubleArrayClass, FindSystemClass(self, "[D"));
- mirror::DoubleArray::SetArrayClass(GetClassRoot(kDoubleArrayClass));
+ SetClassRoot(ClassRoot::kDoubleArrayClass, FindSystemClass(self, "[D"));
// Run Class through FindSystemClass. This initializes the dex_cache_ fields and register it
// in class_table_.
@@ -683,103 +655,89 @@ 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;");
+ ObjPtr<mirror::Class> class_root = FindSystemClass(self, "Ljava/lang/reflect/Field;");
CHECK(class_root != nullptr);
- SetClassRoot(kJavaLangReflectField, class_root);
- mirror::Field::SetClass(class_root);
+ SetClassRoot(ClassRoot::kJavaLangReflectField, 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);
- mirror::Field::SetArrayClass(class_root);
+ SetClassRoot(ClassRoot::kJavaLangReflectFieldArrayClass, 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);
- mirror::Constructor::SetClass(class_root);
+ SetClassRoot(ClassRoot::kJavaLangReflectConstructor, class_root);
class_root = FindSystemClass(self, "[Ljava/lang/reflect/Constructor;");
CHECK(class_root != nullptr);
- SetClassRoot(kJavaLangReflectConstructorArrayClass, class_root);
- mirror::Constructor::SetArrayClass(class_root);
+ SetClassRoot(ClassRoot::kJavaLangReflectConstructorArrayClass, 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);
- mirror::Method::SetClass(class_root);
+ SetClassRoot(ClassRoot::kJavaLangReflectMethod, class_root);
class_root = FindSystemClass(self, "[Ljava/lang/reflect/Method;");
CHECK(class_root != nullptr);
- SetClassRoot(kJavaLangReflectMethodArrayClass, class_root);
- mirror::Method::SetArrayClass(class_root);
+ SetClassRoot(ClassRoot::kJavaLangReflectMethodArrayClass, 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);
- mirror::CallSite::SetClass(class_root);
+ SetClassRoot(ClassRoot::kJavaLangInvokeCallSite, 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);
- mirror::MethodType::SetClass(class_root);
+ SetClassRoot(ClassRoot::kJavaLangInvokeMethodType, 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);
- mirror::MethodHandleImpl::SetClass(class_root);
+ SetClassRoot(ClassRoot::kJavaLangInvokeMethodHandleImpl, class_root);
+ SetClassRoot(ClassRoot::kJavaLangInvokeMethodHandle, class_root->GetSuperClass());
// 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);
- mirror::MethodHandlesLookup::SetClass(class_root);
+ SetClassRoot(ClassRoot::kJavaLangInvokeMethodHandlesLookup, 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);
- mirror::VarHandle::SetClass(class_root);
+ SetClassRoot(ClassRoot::kJavaLangInvokeVarHandle, 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);
- mirror::FieldVarHandle::SetClass(class_root);
+ SetClassRoot(ClassRoot::kJavaLangInvokeFieldVarHandle, 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);
- mirror::ArrayElementVarHandle::SetClass(class_root);
+ SetClassRoot(ClassRoot::kJavaLangInvokeArrayElementVarHandle, 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);
- mirror::ByteArrayViewVarHandle::SetClass(class_root);
+ SetClassRoot(ClassRoot::kJavaLangInvokeByteArrayViewVarHandle, 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);
- mirror::ByteBufferViewVarHandle::SetClass(class_root);
+ SetClassRoot(ClassRoot::kJavaLangInvokeByteBufferViewVarHandle, class_root);
class_root = FindSystemClass(self, "Ldalvik/system/EmulatedStackFrame;");
CHECK(class_root != nullptr);
- SetClassRoot(kDalvikSystemEmulatedStackFrame, class_root);
- mirror::EmulatedStackFrame::SetClass(class_root);
+ SetClassRoot(ClassRoot::kDalvikSystemEmulatedStackFrame, class_root);
// java.lang.ref classes need to be specially flagged, but otherwise are normal classes
// finish initializing Reference class
@@ -805,18 +763,17 @@ 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;"));
+ 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));
// Create conflict tables that depend on the class linker.
runtime->FixupConflictTables();
@@ -834,8 +791,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 +807,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 +833,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 +853,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();
}
@@ -1032,15 +989,12 @@ 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));
+ ObjPtr<mirror::ObjectArray<mirror::Class>>::DownCast(MakeObjPtr(
+ spaces[0]->GetImageHeader().GetImageRoot(ImageHeader::kClassRoots))));
+ DCHECK_EQ(GetClassRoot(ClassRoot::kJavaLangClass, this)->GetClassFlags(),
+ mirror::kClassFlagClass);
- // 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));
-
- 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 +1002,9 @@ 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());
- // 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));
+ array_iftable_ =
+ GcRoot<mirror::IfTable>(GetClassRoot(ClassRoot::kObjectArrayClass, this)->GetIfTable());
+ DCHECK_EQ(array_iftable_.Read(), GetClassRoot(ClassRoot::kBooleanArrayClass, this)->GetIfTable());
for (gc::space::ImageSpace* image_space : spaces) {
// Boot class loader, use a null handle.
@@ -1169,7 +1095,7 @@ static bool FlattenPathClassLoader(ObjPtr<mirror::ClassLoader> class_loader,
return false; // Stop the visit.
}
if (name != nullptr) {
- out_dex_file_names->push_front(name.Ptr());
+ out_dex_file_names->push_front(name);
}
return true; // Continue with the next Element.
};
@@ -1695,15 +1621,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;
}
@@ -2131,8 +2058,7 @@ void ClassLinker::VisitClassesWithoutClassesLock(ClassVisitor* visitor) {
// Add 100 in case new classes get loaded when we are filling in the object array.
class_table_size = NumZygoteClasses() + NumNonZygoteClasses() + 100;
}
- ObjPtr<mirror::Class> class_type = mirror::Class::GetJavaLangClass();
- ObjPtr<mirror::Class> array_of_class = FindArrayClass(self, &class_type);
+ ObjPtr<mirror::Class> array_of_class = GetClassRoot<mirror::ObjectArray<mirror::Class>>(this);
classes.Assign(
mirror::ObjectArray<mirror::Class>::Alloc(self, array_of_class, class_table_size));
CHECK(classes != nullptr); // OOME.
@@ -2155,35 +2081,6 @@ void ClassLinker::VisitClassesWithoutClassesLock(ClassVisitor* visitor) {
}
ClassLinker::~ClassLinker() {
- mirror::Class::ResetClass();
- mirror::Constructor::ResetClass();
- mirror::Field::ResetClass();
- mirror::Method::ResetClass();
- mirror::Reference::ResetClass();
- mirror::StackTraceElement::ResetClass();
- mirror::String::ResetClass();
- mirror::Throwable::ResetClass();
- mirror::BooleanArray::ResetArrayClass();
- mirror::ByteArray::ResetArrayClass();
- mirror::CharArray::ResetArrayClass();
- mirror::Constructor::ResetArrayClass();
- mirror::DoubleArray::ResetArrayClass();
- mirror::Field::ResetArrayClass();
- mirror::FloatArray::ResetArrayClass();
- mirror::Method::ResetArrayClass();
- mirror::IntArray::ResetArrayClass();
- mirror::LongArray::ResetArrayClass();
- mirror::ShortArray::ResetArrayClass();
- mirror::CallSite::ResetClass();
- mirror::MethodType::ResetClass();
- mirror::MethodHandleImpl::ResetClass();
- mirror::MethodHandlesLookup::ResetClass();
- mirror::VarHandle::ResetClass();
- mirror::FieldVarHandle::ResetClass();
- mirror::ArrayElementVarHandle::ResetClass();
- mirror::ByteArrayViewVarHandle::ResetClass();
- mirror::ByteBufferViewVarHandle::ResetClass();
- mirror::EmulatedStackFrame::ResetClass();
Thread* const self = Thread::Current();
for (const ClassLoaderData& data : class_loaders_) {
// CHA unloading analysis is not needed. No negative consequences are expected because
@@ -2218,20 +2115,20 @@ void ClassLinker::DeleteClassLoader(Thread* self, const ClassLoaderData& data, b
delete data.class_table;
}
-mirror::PointerArray* ClassLinker::AllocPointerArray(Thread* self, size_t length) {
- return down_cast<mirror::PointerArray*>(
+ObjPtr<mirror::PointerArray> ClassLinker::AllocPointerArray(Thread* self, size_t length) {
+ return ObjPtr<mirror::PointerArray>::DownCast(
image_pointer_size_ == PointerSize::k64
- ? static_cast<mirror::Array*>(mirror::LongArray::Alloc(self, length))
- : static_cast<mirror::Array*>(mirror::IntArray::Alloc(self, length)));
+ ? ObjPtr<mirror::Array>(mirror::LongArray::Alloc(self, length))
+ : ObjPtr<mirror::Array>(mirror::IntArray::Alloc(self, length)));
}
-mirror::DexCache* ClassLinker::AllocDexCache(ObjPtr<mirror::String>* out_location,
- Thread* self,
- const DexFile& dex_file) {
+ObjPtr<mirror::DexCache> ClassLinker::AllocDexCache(/*out*/ ObjPtr<mirror::String>* out_location,
+ Thread* self,
+ const DexFile& dex_file) {
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;
@@ -2245,9 +2142,9 @@ mirror::DexCache* ClassLinker::AllocDexCache(ObjPtr<mirror::String>* out_locatio
return dex_cache.Get();
}
-mirror::DexCache* ClassLinker::AllocAndInitializeDexCache(Thread* self,
- const DexFile& dex_file,
- LinearAlloc* linear_alloc) {
+ObjPtr<mirror::DexCache> ClassLinker::AllocAndInitializeDexCache(Thread* self,
+ const DexFile& dex_file,
+ LinearAlloc* linear_alloc) {
ObjPtr<mirror::String> location = nullptr;
ObjPtr<mirror::DexCache> dex_cache = AllocDexCache(&location, self, dex_file);
if (dex_cache != nullptr) {
@@ -2260,12 +2157,12 @@ mirror::DexCache* ClassLinker::AllocAndInitializeDexCache(Thread* self,
linear_alloc,
image_pointer_size_);
}
- return dex_cache.Ptr();
+ return dex_cache;
}
-mirror::Class* ClassLinker::AllocClass(Thread* self,
- ObjPtr<mirror::Class> java_lang_Class,
- uint32_t class_size) {
+ObjPtr<mirror::Class> ClassLinker::AllocClass(Thread* self,
+ ObjPtr<mirror::Class> java_lang_Class,
+ uint32_t class_size) {
DCHECK_GE(class_size, sizeof(mirror::Class));
gc::Heap* heap = Runtime::Current()->GetHeap();
mirror::Class::InitializeClassVisitor visitor(class_size);
@@ -2279,20 +2176,20 @@ mirror::Class* ClassLinker::AllocClass(Thread* self,
return k->AsClass();
}
-mirror::Class* ClassLinker::AllocClass(Thread* self, uint32_t class_size) {
- return AllocClass(self, GetClassRoot(kJavaLangClass), class_size);
+ObjPtr<mirror::Class> ClassLinker::AllocClass(Thread* self, uint32_t class_size) {
+ return AllocClass(self, GetClassRoot<mirror::Class>(this), class_size);
}
-mirror::ObjectArray<mirror::StackTraceElement>* ClassLinker::AllocStackTraceElementArray(
+ObjPtr<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,
- const char* descriptor,
- ObjPtr<mirror::Class> klass) {
+ObjPtr<mirror::Class> ClassLinker::EnsureResolved(Thread* self,
+ const char* descriptor,
+ ObjPtr<mirror::Class> klass) {
DCHECK(klass != nullptr);
if (kIsDebugBuild) {
StackHandleScope<1> hs(self);
@@ -2364,7 +2261,7 @@ mirror::Class* ClassLinker::EnsureResolved(Thread* self,
// Return the loaded class. No exceptions should be pending.
CHECK(klass->IsResolved()) << klass->PrettyClass();
self->AssertNoPendingException();
- return klass.Ptr();
+ return klass;
}
typedef std::pair<const DexFile*, const DexFile::ClassDef*> ClassPathEntry;
@@ -2386,7 +2283,7 @@ bool ClassLinker::FindClassInBaseDexClassLoader(ScopedObjectAccessAlreadyRunnabl
const char* descriptor,
size_t hash,
Handle<mirror::ClassLoader> class_loader,
- ObjPtr<mirror::Class>* result) {
+ /*out*/ ObjPtr<mirror::Class>* result) {
// Termination case: boot class loader.
if (IsBootClassLoader(soa, class_loader.Get())) {
*result = FindClassInBootClassLoaderClassPath(self, descriptor, hash);
@@ -2500,9 +2397,9 @@ ObjPtr<mirror::Class> ClassLinker::FindClassInBaseDexClassLoaderClassPath(
return ret;
}
-mirror::Class* ClassLinker::FindClass(Thread* self,
- const char* descriptor,
- Handle<mirror::ClassLoader> class_loader) {
+ObjPtr<mirror::Class> ClassLinker::FindClass(Thread* self,
+ const char* descriptor,
+ Handle<mirror::ClassLoader> class_loader) {
DCHECK_NE(*descriptor, '\0') << "descriptor is empty string";
DCHECK(self != nullptr);
self->AssertNoPendingException();
@@ -2639,7 +2536,7 @@ mirror::Class* ClassLinker::FindClass(Thread* self,
if (old == nullptr) {
old = result_ptr; // For the comparison below, after releasing the lock.
if (descriptor_equals) {
- class_table->InsertWithHash(result_ptr.Ptr(), hash);
+ class_table->InsertWithHash(result_ptr, hash);
Runtime::Current()->GetHeap()->WriteBarrierEveryFieldOf(class_loader.Get());
} // else throw below, after releasing the lock.
}
@@ -2667,16 +2564,16 @@ mirror::Class* ClassLinker::FindClass(Thread* self,
DescriptorToDot(descriptor).c_str());
return nullptr;
}
- // success, return mirror::Class*
- return result_ptr.Ptr();
+ // Success.
+ return result_ptr;
}
-mirror::Class* ClassLinker::DefineClass(Thread* self,
- const char* descriptor,
- size_t hash,
- Handle<mirror::ClassLoader> class_loader,
- const DexFile& dex_file,
- const DexFile::ClassDef& dex_class_def) {
+ObjPtr<mirror::Class> ClassLinker::DefineClass(Thread* self,
+ const char* descriptor,
+ size_t hash,
+ Handle<mirror::ClassLoader> class_loader,
+ const DexFile& dex_file,
+ const DexFile::ClassDef& dex_class_def) {
StackHandleScope<3> hs(self);
auto klass = hs.NewHandle<mirror::Class>(nullptr);
@@ -2684,17 +2581,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 +2641,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);
@@ -2834,52 +2731,50 @@ mirror::Class* ClassLinker::DefineClass(Thread* self,
uint32_t ClassLinker::SizeOfClassWithoutEmbeddedTables(const DexFile& dex_file,
const DexFile::ClassDef& dex_class_def) {
- const uint8_t* class_data = dex_file.GetClassData(dex_class_def);
size_t num_ref = 0;
size_t num_8 = 0;
size_t num_16 = 0;
size_t num_32 = 0;
size_t num_64 = 0;
- if (class_data != nullptr) {
- // We allow duplicate definitions of the same field in a class_data_item
- // but ignore the repeated indexes here, b/21868015.
- uint32_t last_field_idx = dex::kDexNoIndex;
- for (ClassDataItemIterator it(dex_file, class_data); it.HasNextStaticField(); it.Next()) {
- uint32_t field_idx = it.GetMemberIndex();
- // Ordering enforced by DexFileVerifier.
- DCHECK(last_field_idx == dex::kDexNoIndex || last_field_idx <= field_idx);
- if (UNLIKELY(field_idx == last_field_idx)) {
- continue;
- }
- last_field_idx = field_idx;
- const DexFile::FieldId& field_id = dex_file.GetFieldId(field_idx);
- const char* descriptor = dex_file.GetFieldTypeDescriptor(field_id);
- char c = descriptor[0];
- switch (c) {
- case 'L':
- case '[':
- num_ref++;
- break;
- case 'J':
- case 'D':
- num_64++;
- break;
- case 'I':
- case 'F':
- num_32++;
- break;
- case 'S':
- case 'C':
- num_16++;
- break;
- case 'B':
- case 'Z':
- num_8++;
- break;
- default:
- LOG(FATAL) << "Unknown descriptor: " << c;
- UNREACHABLE();
- }
+ ClassAccessor accessor(dex_file, dex_class_def);
+ // We allow duplicate definitions of the same field in a class_data_item
+ // but ignore the repeated indexes here, b/21868015.
+ uint32_t last_field_idx = dex::kDexNoIndex;
+ for (const ClassAccessor::Field& field : accessor.GetStaticFields()) {
+ uint32_t field_idx = field.GetIndex();
+ // Ordering enforced by DexFileVerifier.
+ DCHECK(last_field_idx == dex::kDexNoIndex || last_field_idx <= field_idx);
+ if (UNLIKELY(field_idx == last_field_idx)) {
+ continue;
+ }
+ last_field_idx = field_idx;
+ const DexFile::FieldId& field_id = dex_file.GetFieldId(field_idx);
+ const char* descriptor = dex_file.GetFieldTypeDescriptor(field_id);
+ char c = descriptor[0];
+ switch (c) {
+ case 'L':
+ case '[':
+ num_ref++;
+ break;
+ case 'J':
+ case 'D':
+ num_64++;
+ break;
+ case 'I':
+ case 'F':
+ num_32++;
+ break;
+ case 'S':
+ case 'C':
+ num_16++;
+ break;
+ case 'B':
+ case 'Z':
+ num_8++;
+ break;
+ default:
+ LOG(FATAL) << "Unknown descriptor: " << c;
+ UNREACHABLE();
}
}
return mirror::Class::ComputeClassSize(false,
@@ -2977,17 +2872,15 @@ void ClassLinker::FixupStaticTrampolines(ObjPtr<mirror::Class> klass) {
const DexFile& dex_file = klass->GetDexFile();
const DexFile::ClassDef* dex_class_def = klass->GetClassDef();
CHECK(dex_class_def != nullptr);
- const uint8_t* class_data = dex_file.GetClassData(*dex_class_def);
+ ClassAccessor accessor(dex_file, *dex_class_def);
// There should always be class data if there were direct methods.
- CHECK(class_data != nullptr) << klass->PrettyDescriptor();
- ClassDataItemIterator it(dex_file, class_data);
- it.SkipAllFields();
+ CHECK(accessor.HasClassData()) << klass->PrettyDescriptor();
bool has_oat_class;
OatFile::OatClass oat_class = OatFile::FindOatClass(dex_file,
klass->GetDexClassDefIndex(),
&has_oat_class);
// Link the code of methods skipped by LinkCode.
- for (size_t method_index = 0; it.HasNextDirectMethod(); ++method_index, it.Next()) {
+ for (size_t method_index = 0; method_index < accessor.NumDirectMethods(); ++method_index) {
ArtMethod* method = klass->GetDirectMethod(method_index, image_pointer_size_);
if (!method->IsStatic()) {
// Only update static methods.
@@ -3084,7 +2977,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);
@@ -3096,17 +2989,6 @@ void ClassLinker::SetupClass(const DexFile& dex_file,
klass->SetDexTypeIndex(dex_class_def.class_idx_);
}
-void ClassLinker::LoadClass(Thread* self,
- const DexFile& dex_file,
- const DexFile::ClassDef& dex_class_def,
- Handle<mirror::Class> klass) {
- const uint8_t* class_data = dex_file.GetClassData(dex_class_def);
- if (class_data == nullptr) {
- return; // no fields or methods - for example a marker interface
- }
- LoadClassMembers(self, dex_file, class_data, klass);
-}
-
LengthPrefixedArray<ArtField>* ClassLinker::AllocArtFieldArray(Thread* self,
LinearAlloc* allocator,
size_t length) {
@@ -3165,10 +3047,15 @@ LinearAlloc* ClassLinker::GetOrCreateAllocatorForClassLoader(ObjPtr<mirror::Clas
return allocator;
}
-void ClassLinker::LoadClassMembers(Thread* self,
- const DexFile& dex_file,
- const uint8_t* class_data,
- Handle<mirror::Class> klass) {
+void ClassLinker::LoadClass(Thread* self,
+ const DexFile& dex_file,
+ const DexFile::ClassDef& dex_class_def,
+ Handle<mirror::Class> klass) {
+ ClassAccessor accessor(dex_file, dex_class_def);
+ if (!accessor.HasClassData()) {
+ return;
+ }
+ Runtime* const runtime = Runtime::Current();
{
// Note: We cannot have thread suspension until the field and method arrays are setup or else
// Class::VisitFieldRoots may miss some fields or methods.
@@ -3177,45 +3064,79 @@ void ClassLinker::LoadClassMembers(Thread* self,
// We allow duplicate definitions of the same field in a class_data_item
// but ignore the repeated indexes here, b/21868015.
LinearAlloc* const allocator = GetAllocatorForClassLoader(klass->GetClassLoader());
- ClassDataItemIterator it(dex_file, class_data);
LengthPrefixedArray<ArtField>* sfields = AllocArtFieldArray(self,
allocator,
- it.NumStaticFields());
- size_t num_sfields = 0;
- uint32_t last_field_idx = 0u;
- for (; it.HasNextStaticField(); it.Next()) {
- uint32_t field_idx = it.GetMemberIndex();
- DCHECK_GE(field_idx, last_field_idx); // Ordering enforced by DexFileVerifier.
- if (num_sfields == 0 || LIKELY(field_idx > last_field_idx)) {
- DCHECK_LT(num_sfields, it.NumStaticFields());
- LoadField(it, klass, &sfields->At(num_sfields));
- ++num_sfields;
- last_field_idx = field_idx;
- }
- }
-
- // Load instance fields.
+ accessor.NumStaticFields());
LengthPrefixedArray<ArtField>* ifields = AllocArtFieldArray(self,
allocator,
- it.NumInstanceFields());
+ accessor.NumInstanceFields());
+ size_t num_sfields = 0u;
size_t num_ifields = 0u;
- last_field_idx = 0u;
- for (; it.HasNextInstanceField(); it.Next()) {
- uint32_t field_idx = it.GetMemberIndex();
- DCHECK_GE(field_idx, last_field_idx); // Ordering enforced by DexFileVerifier.
- if (num_ifields == 0 || LIKELY(field_idx > last_field_idx)) {
- DCHECK_LT(num_ifields, it.NumInstanceFields());
- LoadField(it, klass, &ifields->At(num_ifields));
- ++num_ifields;
- last_field_idx = field_idx;
- }
- }
+ uint32_t last_static_field_idx = 0u;
+ uint32_t last_instance_field_idx = 0u;
- if (UNLIKELY(num_sfields != it.NumStaticFields()) ||
- UNLIKELY(num_ifields != it.NumInstanceFields())) {
+ // Methods
+ bool has_oat_class = false;
+ const OatFile::OatClass oat_class = (runtime->IsStarted() && !runtime->IsAotCompiler())
+ ? OatFile::FindOatClass(dex_file, klass->GetDexClassDefIndex(), &has_oat_class)
+ : OatFile::OatClass::Invalid();
+ const OatFile::OatClass* oat_class_ptr = has_oat_class ? &oat_class : nullptr;
+ klass->SetMethodsPtr(
+ AllocArtMethodArray(self, allocator, accessor.NumMethods()),
+ accessor.NumDirectMethods(),
+ accessor.NumVirtualMethods());
+ size_t class_def_method_index = 0;
+ uint32_t last_dex_method_index = dex::kDexNoIndex;
+ size_t last_class_def_method_index = 0;
+
+ // Use the visitor since the ranged based loops are bit slower from seeking. Seeking to the
+ // methods needs to decode all of the fields.
+ accessor.VisitFieldsAndMethods([&](
+ const ClassAccessor::Field& field) REQUIRES_SHARED(Locks::mutator_lock_) {
+ uint32_t field_idx = field.GetIndex();
+ DCHECK_GE(field_idx, last_static_field_idx); // Ordering enforced by DexFileVerifier.
+ if (num_sfields == 0 || LIKELY(field_idx > last_static_field_idx)) {
+ LoadField(field, klass, &sfields->At(num_sfields));
+ ++num_sfields;
+ last_static_field_idx = field_idx;
+ }
+ }, [&](const ClassAccessor::Field& field) REQUIRES_SHARED(Locks::mutator_lock_) {
+ uint32_t field_idx = field.GetIndex();
+ DCHECK_GE(field_idx, last_instance_field_idx); // Ordering enforced by DexFileVerifier.
+ if (num_ifields == 0 || LIKELY(field_idx > last_instance_field_idx)) {
+ LoadField(field, klass, &ifields->At(num_ifields));
+ ++num_ifields;
+ last_instance_field_idx = field_idx;
+ }
+ }, [&](const ClassAccessor::Method& method) REQUIRES_SHARED(Locks::mutator_lock_) {
+ ArtMethod* art_method = klass->GetDirectMethodUnchecked(class_def_method_index,
+ image_pointer_size_);
+ LoadMethod(dex_file, method, klass, art_method);
+ LinkCode(this, art_method, oat_class_ptr, class_def_method_index);
+ uint32_t it_method_index = method.GetIndex();
+ if (last_dex_method_index == it_method_index) {
+ // duplicate case
+ art_method->SetMethodIndex(last_class_def_method_index);
+ } else {
+ art_method->SetMethodIndex(class_def_method_index);
+ last_dex_method_index = it_method_index;
+ last_class_def_method_index = class_def_method_index;
+ }
+ ++class_def_method_index;
+ }, [&](const ClassAccessor::Method& method) REQUIRES_SHARED(Locks::mutator_lock_) {
+ ArtMethod* art_method = klass->GetVirtualMethodUnchecked(
+ class_def_method_index - accessor.NumDirectMethods(),
+ image_pointer_size_);
+ LoadMethod(dex_file, method, klass, art_method);
+ LinkCode(this, art_method, oat_class_ptr, class_def_method_index);
+ ++class_def_method_index;
+ });
+
+ if (UNLIKELY(num_ifields + num_sfields != accessor.NumFields())) {
LOG(WARNING) << "Duplicate fields in class " << klass->PrettyDescriptor()
- << " (unique static fields: " << num_sfields << "/" << it.NumStaticFields()
- << ", unique instance fields: " << num_ifields << "/" << it.NumInstanceFields() << ")";
+ << " (unique static fields: " << num_sfields << "/" << accessor.NumStaticFields()
+ << ", unique instance fields: " << num_ifields << "/" << accessor.NumInstanceFields()
+ << ")";
// NOTE: Not shrinking the over-allocated sfields/ifields, just setting size.
if (sfields != nullptr) {
sfields->SetSize(num_sfields);
@@ -3229,87 +3150,49 @@ void ClassLinker::LoadClassMembers(Thread* self,
DCHECK_EQ(klass->NumStaticFields(), num_sfields);
klass->SetIFieldsPtr(ifields);
DCHECK_EQ(klass->NumInstanceFields(), num_ifields);
- // Load methods.
- bool has_oat_class = false;
- const OatFile::OatClass oat_class =
- (Runtime::Current()->IsStarted() && !Runtime::Current()->IsAotCompiler())
- ? OatFile::FindOatClass(dex_file, klass->GetDexClassDefIndex(), &has_oat_class)
- : OatFile::OatClass::Invalid();
- const OatFile::OatClass* oat_class_ptr = has_oat_class ? &oat_class : nullptr;
- klass->SetMethodsPtr(
- AllocArtMethodArray(self, allocator, it.NumDirectMethods() + it.NumVirtualMethods()),
- it.NumDirectMethods(),
- it.NumVirtualMethods());
- size_t class_def_method_index = 0;
- uint32_t last_dex_method_index = dex::kDexNoIndex;
- size_t last_class_def_method_index = 0;
- // TODO These should really use the iterators.
- for (size_t i = 0; it.HasNextDirectMethod(); i++, it.Next()) {
- ArtMethod* method = klass->GetDirectMethodUnchecked(i, image_pointer_size_);
- LoadMethod(dex_file, it, klass, method);
- LinkCode(this, method, oat_class_ptr, class_def_method_index);
- uint32_t it_method_index = it.GetMemberIndex();
- if (last_dex_method_index == it_method_index) {
- // duplicate case
- method->SetMethodIndex(last_class_def_method_index);
- } else {
- method->SetMethodIndex(class_def_method_index);
- last_dex_method_index = it_method_index;
- last_class_def_method_index = class_def_method_index;
- }
- class_def_method_index++;
- }
- for (size_t i = 0; it.HasNextVirtualMethod(); i++, it.Next()) {
- ArtMethod* method = klass->GetVirtualMethodUnchecked(i, image_pointer_size_);
- LoadMethod(dex_file, it, klass, method);
- DCHECK_EQ(class_def_method_index, it.NumDirectMethods() + i);
- LinkCode(this, method, oat_class_ptr, class_def_method_index);
- class_def_method_index++;
- }
- DCHECK(!it.HasNext());
}
// Ensure that the card is marked so that remembered sets pick up native roots.
Runtime::Current()->GetHeap()->WriteBarrierEveryFieldOf(klass.Get());
self->AllowThreadSuspension();
}
-void ClassLinker::LoadField(const ClassDataItemIterator& it,
+void ClassLinker::LoadField(const ClassAccessor::Field& field,
Handle<mirror::Class> klass,
ArtField* dst) {
- const uint32_t field_idx = it.GetMemberIndex();
+ const uint32_t field_idx = field.GetIndex();
dst->SetDexFieldIndex(field_idx);
dst->SetDeclaringClass(klass.Get());
// Get access flags from the DexFile. If this is a boot class path class,
// also set its runtime hidden API access flags.
- uint32_t access_flags = it.GetFieldAccessFlags();
+ uint32_t access_flags = field.GetAccessFlags();
if (klass->IsBootStrapClassLoaded()) {
access_flags =
- HiddenApiAccessFlags::EncodeForRuntime(access_flags, it.DecodeHiddenAccessFlags());
+ HiddenApiAccessFlags::EncodeForRuntime(access_flags, field.DecodeHiddenAccessFlags());
}
dst->SetAccessFlags(access_flags);
}
void ClassLinker::LoadMethod(const DexFile& dex_file,
- const ClassDataItemIterator& it,
+ const ClassAccessor::Method& method,
Handle<mirror::Class> klass,
ArtMethod* dst) {
- uint32_t dex_method_idx = it.GetMemberIndex();
+ const uint32_t dex_method_idx = method.GetIndex();
const DexFile::MethodId& method_id = dex_file.GetMethodId(dex_method_idx);
const char* method_name = dex_file.StringDataByIdx(method_id.name_idx_);
ScopedAssertNoThreadSuspension ants("LoadMethod");
dst->SetDexMethodIndex(dex_method_idx);
dst->SetDeclaringClass(klass.Get());
- dst->SetCodeItemOffset(it.GetMethodCodeItemOffset());
+ dst->SetCodeItemOffset(method.GetCodeItemOffset());
// Get access flags from the DexFile. If this is a boot class path class,
// also set its runtime hidden API access flags.
- uint32_t access_flags = it.GetMethodAccessFlags();
+ uint32_t access_flags = method.GetAccessFlags();
if (klass->IsBootStrapClassLoaded()) {
access_flags =
- HiddenApiAccessFlags::EncodeForRuntime(access_flags, it.DecodeHiddenAccessFlags());
+ HiddenApiAccessFlags::EncodeForRuntime(access_flags, method.DecodeHiddenAccessFlags());
}
if (UNLIKELY(strcmp("finalize", method_name) == 0)) {
@@ -3634,27 +3517,20 @@ ClassLinker::DexCacheData ClassLinker::FindDexCacheDataLocked(const DexFile& dex
return DexCacheData();
}
-mirror::Class* ClassLinker::CreatePrimitiveClass(Thread* self, Primitive::Type type) {
- ObjPtr<mirror::Class> klass =
+ObjPtr<mirror::Class> ClassLinker::CreatePrimitiveClass(Thread* self, Primitive::Type type) {
+ ObjPtr<mirror::Class> primitive_class =
AllocClass(self, mirror::Class::PrimitiveClassSize(image_pointer_size_));
- if (UNLIKELY(klass == nullptr)) {
+ if (UNLIKELY(primitive_class == nullptr)) {
self->AssertPendingOOMException();
return nullptr;
}
- return InitializePrimitiveClass(klass, type);
-}
-
-mirror::Class* ClassLinker::InitializePrimitiveClass(ObjPtr<mirror::Class> primitive_class,
- Primitive::Type type) {
- CHECK(primitive_class != nullptr);
// Must hold lock on object when initializing.
- Thread* self = Thread::Current();
StackHandleScope<1> hs(self);
Handle<mirror::Class> h_class(hs.NewHandle(primitive_class));
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,
@@ -3677,8 +3553,10 @@ mirror::Class* ClassLinker::InitializePrimitiveClass(ObjPtr<mirror::Class> primi
// array class; that always comes from the base element class.
//
// Returns null with an exception raised on failure.
-mirror::Class* ClassLinker::CreateArrayClass(Thread* self, const char* descriptor, size_t hash,
- Handle<mirror::ClassLoader> class_loader) {
+ObjPtr<mirror::Class> ClassLinker::CreateArrayClass(Thread* self,
+ const char* descriptor,
+ size_t hash,
+ Handle<mirror::ClassLoader> class_loader) {
// Identify the underlying component type
CHECK_EQ('[', descriptor[0]);
StackHandleScope<2> hs(self);
@@ -3721,7 +3599,7 @@ mirror::Class* ClassLinker::CreateArrayClass(Thread* self, const char* descripto
ObjPtr<mirror::Class> new_class =
LookupClass(self, descriptor, hash, component_type->GetClassLoader());
if (new_class != nullptr) {
- return new_class.Ptr();
+ return new_class;
}
}
@@ -3737,17 +3615,15 @@ 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));
- } else if (strcmp(descriptor, "[C") == 0) {
- new_class.Assign(GetClassRoot(kCharArrayClass));
+ 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, "[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 +3636,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);
@@ -3824,29 +3700,30 @@ mirror::Class* ClassLinker::CreateArrayClass(Thread* self, const char* descripto
//
// (Yes, this happens.)
- return existing.Ptr();
+ return existing;
}
-mirror::Class* ClassLinker::FindPrimitiveClass(char type) {
+ObjPtr<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);
case 'C':
- return GetClassRoot(kPrimitiveChar);
+ return GetClassRoot(ClassRoot::kPrimitiveChar, class_roots);
case 'D':
- return GetClassRoot(kPrimitiveDouble);
+ return GetClassRoot(ClassRoot::kPrimitiveDouble, class_roots);
case 'F':
- return GetClassRoot(kPrimitiveFloat);
+ return GetClassRoot(ClassRoot::kPrimitiveFloat, class_roots);
case 'I':
- return GetClassRoot(kPrimitiveInt);
+ return GetClassRoot(ClassRoot::kPrimitiveInt, class_roots);
case 'J':
- return GetClassRoot(kPrimitiveLong);
+ return GetClassRoot(ClassRoot::kPrimitiveLong, class_roots);
case 'S':
- return GetClassRoot(kPrimitiveShort);
+ return GetClassRoot(ClassRoot::kPrimitiveShort, class_roots);
case 'Z':
- return GetClassRoot(kPrimitiveBoolean);
+ return GetClassRoot(ClassRoot::kPrimitiveBoolean, class_roots);
case 'V':
- return GetClassRoot(kPrimitiveVoid);
+ return GetClassRoot(ClassRoot::kPrimitiveVoid, class_roots);
default:
break;
}
@@ -3855,7 +3732,9 @@ mirror::Class* ClassLinker::FindPrimitiveClass(char type) {
return nullptr;
}
-mirror::Class* ClassLinker::InsertClass(const char* descriptor, ObjPtr<mirror::Class> klass, size_t hash) {
+ObjPtr<mirror::Class> ClassLinker::InsertClass(const char* descriptor,
+ ObjPtr<mirror::Class> klass,
+ size_t hash) {
if (VLOG_IS_ON(class_linker)) {
ObjPtr<mirror::DexCache> dex_cache = klass->GetDexCache();
std::string source;
@@ -3871,7 +3750,7 @@ mirror::Class* ClassLinker::InsertClass(const char* descriptor, ObjPtr<mirror::C
ClassTable* const class_table = InsertClassTableForClassLoader(class_loader);
ObjPtr<mirror::Class> existing = class_table->Lookup(descriptor, hash);
if (existing != nullptr) {
- return existing.Ptr();
+ return existing;
}
VerifyObject(klass);
class_table->InsertWithHash(klass, hash);
@@ -3910,22 +3789,22 @@ void ClassLinker::UpdateClassMethods(ObjPtr<mirror::Class> klass,
Runtime::Current()->GetHeap()->WriteBarrierEveryFieldOf(klass);
}
-mirror::Class* ClassLinker::LookupClass(Thread* self,
- const char* descriptor,
- ObjPtr<mirror::ClassLoader> class_loader) {
+ObjPtr<mirror::Class> ClassLinker::LookupClass(Thread* self,
+ const char* descriptor,
+ ObjPtr<mirror::ClassLoader> class_loader) {
return LookupClass(self, descriptor, ComputeModifiedUtf8Hash(descriptor), class_loader);
}
-mirror::Class* ClassLinker::LookupClass(Thread* self,
- const char* descriptor,
- size_t hash,
- ObjPtr<mirror::ClassLoader> class_loader) {
+ObjPtr<mirror::Class> ClassLinker::LookupClass(Thread* self,
+ const char* descriptor,
+ size_t hash,
+ ObjPtr<mirror::ClassLoader> class_loader) {
ReaderMutexLock mu(self, *Locks::classlinker_classes_lock_);
ClassTable* const class_table = ClassTableForClassLoader(class_loader);
if (class_table != nullptr) {
ObjPtr<mirror::Class> result = class_table->Lookup(descriptor, hash);
if (result != nullptr) {
- return result.Ptr();
+ return result;
}
}
return nullptr;
@@ -4372,16 +4251,16 @@ void ClassLinker::ResolveMethodExceptionHandlerTypes(ArtMethod* method) {
}
}
-mirror::Class* ClassLinker::CreateProxyClass(ScopedObjectAccessAlreadyRunnable& soa,
- jstring name,
- jobjectArray interfaces,
- jobject loader,
- jobjectArray methods,
- jobjectArray throws) {
+ObjPtr<mirror::Class> ClassLinker::CreateProxyClass(ScopedObjectAccessAlreadyRunnable& soa,
+ jstring name,
+ jobjectArray interfaces,
+ jobject loader,
+ jobjectArray methods,
+ jobjectArray throws) {
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 +4273,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());
@@ -4434,7 +4313,7 @@ mirror::Class* ClassLinker::CreateProxyClass(ScopedObjectAccessAlreadyRunnable&
// They have as many virtual methods as the array
auto h_methods = hs.NewHandle(soa.Decode<mirror::ObjectArray<mirror::Method>>(methods));
- DCHECK_EQ(h_methods->GetClass(), mirror::Method::ArrayClass())
+ DCHECK_EQ(h_methods->GetClass(), GetClassRoot<mirror::ObjectArray<mirror::Method>>())
<< mirror::Class::PrettyClass(h_methods->GetClass());
const size_t num_virtual_methods = h_methods->GetLength();
@@ -4463,7 +4342,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 +4430,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";
@@ -4879,24 +4759,29 @@ bool ClassLinker::InitializeClass(Thread* self, Handle<mirror::Class> klass,
this,
*dex_class_def);
const DexFile& dex_file = *dex_cache->GetDexFile();
- const uint8_t* class_data = dex_file.GetClassData(*dex_class_def);
- ClassDataItemIterator field_it(dex_file, class_data);
+
if (value_it.HasNext()) {
- DCHECK(field_it.HasNextStaticField());
+ ClassAccessor accessor(dex_file, *dex_class_def);
CHECK(can_init_statics);
- for ( ; value_it.HasNext(); value_it.Next(), field_it.Next()) {
- ArtField* field = ResolveField(
- field_it.GetMemberIndex(), dex_cache, class_loader, /* is_static */ true);
+ for (const ClassAccessor::Field& field : accessor.GetStaticFields()) {
+ if (!value_it.HasNext()) {
+ break;
+ }
+ ArtField* art_field = ResolveField(field.GetIndex(),
+ dex_cache,
+ class_loader,
+ /* is_static */ true);
if (Runtime::Current()->IsActiveTransaction()) {
- value_it.ReadValueToField<true>(field);
+ value_it.ReadValueToField<true>(art_field);
} else {
- value_it.ReadValueToField<false>(field);
+ value_it.ReadValueToField<false>(art_field);
}
if (self->IsExceptionPending()) {
break;
}
- DCHECK(!value_it.HasNext() || field_it.HasNextStaticField());
+ value_it.Next();
}
+ DCHECK(self->IsExceptionPending() || !value_it.HasNext());
}
}
@@ -5553,7 +5438,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 +5452,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 +5495,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());
@@ -5829,8 +5715,8 @@ bool ClassLinker::LinkVirtualMethods(
klass->SetVTable(super_vtable);
return true;
}
- vtable = hs.NewHandle(down_cast<mirror::PointerArray*>(
- super_vtable->CopyOf(self, max_count)));
+ vtable = hs.NewHandle(
+ ObjPtr<mirror::PointerArray>::DownCast(super_vtable->CopyOf(self, max_count)));
if (UNLIKELY(vtable == nullptr)) {
self->AssertPendingOOMException();
return false;
@@ -5966,7 +5852,7 @@ bool ClassLinker::LinkVirtualMethods(
// Shrink vtable if possible
CHECK_LE(actual_count, max_count);
if (actual_count < max_count) {
- vtable.Assign(down_cast<mirror::PointerArray*>(vtable->CopyOf(self, actual_count)));
+ vtable.Assign(ObjPtr<mirror::PointerArray>::DownCast(vtable->CopyOf(self, actual_count)));
if (UNLIKELY(vtable == nullptr)) {
self->AssertPendingOOMException();
return false;
@@ -5974,13 +5860,13 @@ 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));
return false;
}
- auto* vtable = AllocPointerArray(self, num_virtual_methods);
+ ObjPtr<mirror::PointerArray> vtable = AllocPointerArray(self, num_virtual_methods);
if (UNLIKELY(vtable == nullptr)) {
self->AssertPendingOOMException();
return false;
@@ -6224,7 +6110,8 @@ bool ClassLinker::AllocateIfTableMethodArrays(Thread* self,
DCHECK(if_table != nullptr);
DCHECK(if_table->GetMethodArray(i) != nullptr);
// If we are working on a super interface, try extending the existing method array.
- method_array = down_cast<mirror::PointerArray*>(if_table->GetMethodArray(i)->Clone(self));
+ method_array = ObjPtr<mirror::PointerArray>::DownCast(MakeObjPtr(
+ if_table->GetMethodArray(i)->Clone(self)));
} else {
method_array = AllocPointerArray(self, num_methods);
}
@@ -6488,7 +6375,7 @@ static bool NotSubinterfaceOfAny(
// iftable must be large enough to hold all interfaces without changing its size.
static size_t FillIfTable(ObjPtr<mirror::IfTable> iftable,
size_t super_ifcount,
- std::vector<mirror::Class*> to_process)
+ std::vector<ObjPtr<mirror::Class>> to_process)
REQUIRES(Roles::uninterruptible_)
REQUIRES_SHARED(Locks::mutator_lock_) {
// This is the set of all class's already in the iftable. Used to make checking if a class has
@@ -6628,11 +6515,11 @@ bool ClassLinker::SetupInterfaceLookupTable(Thread* self, Handle<mirror::Class>
size_t new_ifcount;
{
ScopedAssertNoThreadSuspension nts("Copying mirror::Class*'s for FillIfTable");
- std::vector<mirror::Class*> to_add;
+ std::vector<ObjPtr<mirror::Class>> to_add;
for (size_t i = 0; i < num_interfaces; i++) {
ObjPtr<mirror::Class> interface = have_interfaces ? interfaces->Get(i) :
mirror::Class::GetDirectInterface(self, klass.Get(), i);
- to_add.push_back(interface.Ptr());
+ to_add.push_back(interface);
}
new_ifcount = FillIfTable(iftable.Get(), super_ifcount, std::move(to_add));
@@ -6643,7 +6530,7 @@ bool ClassLinker::SetupInterfaceLookupTable(Thread* self, Handle<mirror::Class>
// Shrink iftable in case duplicates were found
if (new_ifcount < ifcount) {
DCHECK_NE(num_interfaces, 0U);
- iftable.Assign(down_cast<mirror::IfTable*>(
+ iftable.Assign(ObjPtr<mirror::IfTable>::DownCast(
iftable->CopyOf(self, new_ifcount * mirror::IfTable::kMax)));
if (UNLIKELY(iftable == nullptr)) {
self->AssertPendingOOMException();
@@ -7157,7 +7044,7 @@ ObjPtr<mirror::PointerArray> ClassLinker::LinkInterfaceMethodsHelper::UpdateVtab
default_conflict_methods_.size();
ObjPtr<mirror::PointerArray> vtable =
- down_cast<mirror::PointerArray*>(old_vtable->CopyOf(self_, new_vtable_count));
+ ObjPtr<mirror::PointerArray>::DownCast(old_vtable->CopyOf(self_, new_vtable_count));
if (UNLIKELY(vtable == nullptr)) {
self_->AssertPendingOOMException();
return nullptr;
@@ -7770,14 +7657,15 @@ void ClassLinker::CreateReferenceInstanceOffsets(Handle<mirror::Class> klass) {
klass->SetReferenceInstanceOffsets(reference_offsets);
}
-ObjPtr<mirror::String> ClassLinker::ResolveString(dex::StringIndex string_idx,
- Handle<mirror::DexCache> dex_cache) {
- DCHECK(dex_cache != nullptr);
- Thread::PoisonObjectPointersIfDebug();
- ObjPtr<mirror::String> resolved = dex_cache->GetResolvedString(string_idx);
- if (resolved != nullptr) {
- return resolved;
- }
+ObjPtr<mirror::String> ClassLinker::DoResolveString(dex::StringIndex string_idx,
+ ObjPtr<mirror::DexCache> dex_cache) {
+ StackHandleScope<1> hs(Thread::Current());
+ Handle<mirror::DexCache> h_dex_cache(hs.NewHandle(dex_cache));
+ return DoResolveString(string_idx, h_dex_cache);
+}
+
+ObjPtr<mirror::String> ClassLinker::DoResolveString(dex::StringIndex string_idx,
+ Handle<mirror::DexCache> dex_cache) {
const DexFile& dex_file = *dex_cache->GetDexFile();
uint32_t utf16_length;
const char* utf8_data = dex_file.StringDataAndUtf16LengthByIdx(string_idx, &utf16_length);
@@ -7788,13 +7676,9 @@ ObjPtr<mirror::String> ClassLinker::ResolveString(dex::StringIndex string_idx,
return string;
}
-ObjPtr<mirror::String> ClassLinker::LookupString(dex::StringIndex string_idx,
- ObjPtr<mirror::DexCache> dex_cache) {
+ObjPtr<mirror::String> ClassLinker::DoLookupString(dex::StringIndex string_idx,
+ ObjPtr<mirror::DexCache> dex_cache) {
DCHECK(dex_cache != nullptr);
- ObjPtr<mirror::String> resolved = dex_cache->GetResolvedString(string_idx);
- if (resolved != nullptr) {
- return resolved;
- }
const DexFile& dex_file = *dex_cache->GetDexFile();
uint32_t utf16_length;
const char* utf8_data = dex_file.StringDataAndUtf16LengthByIdx(string_idx, &utf16_length);
@@ -7807,6 +7691,11 @@ ObjPtr<mirror::String> ClassLinker::LookupString(dex::StringIndex string_idx,
}
ObjPtr<mirror::Class> ClassLinker::DoLookupResolvedType(dex::TypeIndex type_idx,
+ ObjPtr<mirror::Class> referrer) {
+ return DoLookupResolvedType(type_idx, referrer->GetDexCache(), referrer->GetClassLoader());
+}
+
+ObjPtr<mirror::Class> ClassLinker::DoLookupResolvedType(dex::TypeIndex type_idx,
ObjPtr<mirror::DexCache> dex_cache,
ObjPtr<mirror::ClassLoader> class_loader) {
const DexFile& dex_file = *dex_cache->GetDexFile();
@@ -7822,7 +7711,7 @@ ObjPtr<mirror::Class> ClassLinker::DoLookupResolvedType(dex::TypeIndex type_idx,
DCHECK(self != nullptr);
const size_t hash = ComputeModifiedUtf8Hash(descriptor);
// Find the class in the loaded classes table.
- type = LookupClass(self, descriptor, hash, class_loader.Ptr());
+ type = LookupClass(self, descriptor, hash, class_loader);
}
if (type != nullptr) {
if (type->IsResolved()) {
@@ -7835,6 +7724,14 @@ ObjPtr<mirror::Class> ClassLinker::DoLookupResolvedType(dex::TypeIndex type_idx,
}
ObjPtr<mirror::Class> ClassLinker::DoResolveType(dex::TypeIndex type_idx,
+ ObjPtr<mirror::Class> referrer) {
+ StackHandleScope<2> hs(Thread::Current());
+ Handle<mirror::DexCache> dex_cache(hs.NewHandle(referrer->GetDexCache()));
+ Handle<mirror::ClassLoader> class_loader(hs.NewHandle(referrer->GetClassLoader()));
+ return DoResolveType(type_idx, dex_cache, class_loader);
+}
+
+ObjPtr<mirror::Class> ClassLinker::DoResolveType(dex::TypeIndex type_idx,
Handle<mirror::DexCache> dex_cache,
Handle<mirror::ClassLoader> class_loader) {
Thread* self = Thread::Current();
@@ -7851,7 +7748,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);
@@ -8197,7 +8094,7 @@ ObjPtr<mirror::MethodType> ClassLinker::ResolveMethodType(
ObjPtr<mirror::MethodType> resolved = dex_cache->GetResolvedMethodType(proto_idx);
if (resolved != nullptr) {
- return resolved.Ptr();
+ return resolved;
}
StackHandleScope<4> hs(self);
@@ -8218,8 +8115,7 @@ ObjPtr<mirror::MethodType> ClassLinker::ResolveMethodType(
// other than by looking at the shorty ?
const size_t num_method_args = strlen(dex_file.StringDataByIdx(proto_id.shorty_idx_)) - 1;
- ObjPtr<mirror::Class> class_type = mirror::Class::GetJavaLangClass();
- ObjPtr<mirror::Class> array_of_class = FindArrayClass(self, &class_type);
+ ObjPtr<mirror::Class> array_of_class = GetClassRoot<mirror::ObjectArray<mirror::Class>>(this);
Handle<mirror::ObjectArray<mirror::Class>> method_params(hs.NewHandle(
mirror::ObjectArray<mirror::Class>::Alloc(self, array_of_class, num_method_args)));
if (method_params == nullptr) {
@@ -8325,11 +8221,10 @@ mirror::MethodHandle* ClassLinker::ResolveMethodHandleForField(
}
StackHandleScope<4> hs(self);
- ObjPtr<mirror::Class> class_type = mirror::Class::GetJavaLangClass();
- ObjPtr<mirror::Class> array_of_class = FindArrayClass(self, &class_type);
+ ObjPtr<mirror::Class> array_of_class = GetClassRoot<mirror::ObjectArray<mirror::Class>>(this);
Handle<mirror::ObjectArray<mirror::Class>> method_params(hs.NewHandle(
mirror::ObjectArray<mirror::Class>::Alloc(self, array_of_class, num_params)));
- if (UNLIKELY(method_params.Get() == nullptr)) {
+ if (UNLIKELY(method_params == nullptr)) {
DCHECK(self->IsExceptionPending());
return nullptr;
}
@@ -8504,8 +8399,7 @@ mirror::MethodHandle* ClassLinker::ResolveMethodHandleForMethod(
int32_t num_params = static_cast<int32_t>(shorty_length + receiver_count - 1);
StackHandleScope<7> hs(self);
- ObjPtr<mirror::Class> class_type = mirror::Class::GetJavaLangClass();
- ObjPtr<mirror::Class> array_of_class = FindArrayClass(self, &class_type);
+ ObjPtr<mirror::Class> array_of_class = GetClassRoot<mirror::ObjectArray<mirror::Class>>(this);
Handle<mirror::ObjectArray<mirror::Class>> method_params(hs.NewHandle(
mirror::ObjectArray<mirror::Class>::Alloc(self, array_of_class, num_params)));
if (method_params.Get() == nullptr) {
@@ -8678,67 +8572,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,
@@ -8913,7 +8750,7 @@ void ClassLinker::InsertDexFileInToClassLoader(ObjPtr<mirror::Object> dex_file,
DCHECK(dex_file != nullptr);
Thread* const self = Thread::Current();
WriterMutexLock mu(self, *Locks::classlinker_classes_lock_);
- ClassTable* const table = ClassTableForClassLoader(class_loader.Ptr());
+ ClassTable* const table = ClassTableForClassLoader(class_loader);
DCHECK(table != nullptr);
if (table->InsertStrongRoot(dex_file) && class_loader != nullptr) {
// It was not already inserted, perform the write barrier to let the GC know the class loader's
@@ -9060,19 +8897,19 @@ class ClassLinker::FindVirtualMethodHolderVisitor : public ClassVisitor {
const PointerSize pointer_size_;
};
-mirror::Class* ClassLinker::GetHoldingClassOfCopiedMethod(ArtMethod* method) {
+ObjPtr<mirror::Class> ClassLinker::GetHoldingClassOfCopiedMethod(ArtMethod* method) {
ScopedTrace trace(__FUNCTION__); // Since this function is slow, have a trace to notify people.
CHECK(method->IsCopied());
FindVirtualMethodHolderVisitor visitor(method, image_pointer_size_);
VisitClasses(&visitor);
- return visitor.holder_.Ptr();
+ return visitor.holder_;
}
-mirror::IfTable* ClassLinker::AllocIfTable(Thread* self, size_t ifcount) {
- return down_cast<mirror::IfTable*>(
+ObjPtr<mirror::IfTable> ClassLinker::AllocIfTable(Thread* self, size_t ifcount) {
+ return ObjPtr<mirror::IfTable>::DownCast(ObjPtr<mirror::ObjectArray<mirror::Object>>(
mirror::IfTable::Alloc(self,
- GetClassRoot(kObjectArrayClass),
- ifcount * mirror::IfTable::kMax));
+ GetClassRoot<mirror::ObjectArray<mirror::Object>>(this),
+ ifcount * mirror::IfTable::kMax)));
}
// Instantiate ResolveMethod.