Reduce meta-data object sizes, introduce meta-data helper classes.
Change-Id: Id14ad218f1c74c659701352fdf1a45bf6444daa3
diff --git a/src/class_linker.cc b/src/class_linker.cc
index 9e4a76d..6555070 100644
--- a/src/class_linker.cc
+++ b/src/class_linker.cc
@@ -19,6 +19,7 @@
#include "monitor.h"
#include "oat_file.h"
#include "object.h"
+#include "object_utils.h"
#include "runtime.h"
#include "runtime_support.h"
#include "ScopedLocalRef.h"
@@ -59,13 +60,14 @@
void ThrowNoSuchMethodError(const char* kind,
Class* c, const StringPiece& name, const StringPiece& signature) {
- DexCache* dex_cache = c->GetDexCache();
+ ClassHelper kh(c);
std::ostringstream msg;
msg << "no " << kind << " method " << name << "." << signature
- << " in class " << c->GetDescriptor()->ToModifiedUtf8()
+ << " in class " << kh.GetDescriptor()
<< " or its superclasses";
- if (dex_cache) {
- msg << " (defined in " << dex_cache->GetLocation()->ToModifiedUtf8() << ")";
+ std::string location(kh.GetLocation());
+ if (!location.empty()) {
+ msg << " (defined in " << location << ")";
}
Thread::Current()->ThrowNewException("Ljava/lang/NoSuchMethodError;", msg.str().c_str());
}
@@ -81,11 +83,11 @@
if (c->GetVerifyErrorClass() != NULL) {
// TODO: change the verifier to store an _instance_, with a useful detail message?
- std::string error_descriptor(c->GetVerifyErrorClass()->GetDescriptor()->ToModifiedUtf8());
- Thread::Current()->ThrowNewException(error_descriptor.c_str(),
- PrettyDescriptor(c->GetDescriptor()).c_str());
+ ClassHelper ve_ch(c->GetVerifyErrorClass());
+ std::string error_descriptor(ve_ch.GetDescriptor());
+ Thread::Current()->ThrowNewException(error_descriptor.c_str(), PrettyDescriptor(c).c_str());
} else {
- ThrowNoClassDefFoundError("%s", PrettyDescriptor(c->GetDescriptor()).c_str());
+ ThrowNoClassDefFoundError("%s", PrettyDescriptor(c).c_str());
}
}
@@ -204,7 +206,6 @@
dex_lock_("ClassLinker dex lock"),
classes_lock_("ClassLinker classes lock"),
class_roots_(NULL),
- array_interfaces_(NULL),
array_iftable_(NULL),
init_done_(false),
intern_table_(intern_table) {
@@ -269,14 +270,6 @@
java_lang_String->SetObjectSize(sizeof(String));
java_lang_String->SetStatus(Class::kStatusResolved);
- // Backfill Class descriptors missing until this point
- java_lang_Class->SetDescriptor(intern_table_->InternStrong("Ljava/lang/Class;"));
- java_lang_Object->SetDescriptor(intern_table_->InternStrong("Ljava/lang/Object;"));
- class_array_class->SetDescriptor(intern_table_->InternStrong("[Ljava/lang/Class;"));
- object_array_class->SetDescriptor(intern_table_->InternStrong("[Ljava/lang/Object;"));
- java_lang_String->SetDescriptor(intern_table_->InternStrong("Ljava/lang/String;"));
- char_array_class->SetDescriptor(intern_table_->InternStrong("[C"));
-
// Create storage for root classes, save away our work so far (requires
// descriptors)
class_roots_ = ObjectArray<Class>::Alloc(object_array_class.get(), kClassRootsMax);
@@ -299,12 +292,10 @@
SetClassRoot(kPrimitiveVoid, CreatePrimitiveClass("V", Primitive::kPrimVoid));
// Create array interface entries to populate once we can load system classes
- array_interfaces_ = AllocClassArray(2);
array_iftable_ = AllocObjectArray<InterfaceEntry>(2);
// Create int array type for AllocDexCache (done in AppendToBootClassPath)
SirtRef<Class> int_array_class(AllocClass(java_lang_Class.get(), sizeof(Class)));
- int_array_class->SetDescriptor(intern_table_->InternStrong("[I"));
int_array_class->SetComponentType(GetClassRoot(kPrimitiveInt));
IntArray::SetArrayClass(int_array_class.get());
SetClassRoot(kIntArrayClass, int_array_class.get());
@@ -324,7 +315,6 @@
// Constructor, Field, and Method are necessary so that FindClass can link members
SirtRef<Class> java_lang_reflect_Constructor(AllocClass(java_lang_Class.get(), sizeof(MethodClass)));
- java_lang_reflect_Constructor->SetDescriptor(intern_table_->InternStrong("Ljava/lang/reflect/Constructor;"));
CHECK(java_lang_reflect_Constructor.get() != NULL);
java_lang_reflect_Constructor->SetObjectSize(sizeof(Method));
SetClassRoot(kJavaLangReflectConstructor, java_lang_reflect_Constructor.get());
@@ -332,14 +322,12 @@
SirtRef<Class> java_lang_reflect_Field(AllocClass(java_lang_Class.get(), sizeof(FieldClass)));
CHECK(java_lang_reflect_Field.get() != NULL);
- java_lang_reflect_Field->SetDescriptor(intern_table_->InternStrong("Ljava/lang/reflect/Field;"));
java_lang_reflect_Field->SetObjectSize(sizeof(Field));
SetClassRoot(kJavaLangReflectField, java_lang_reflect_Field.get());
java_lang_reflect_Field->SetStatus(Class::kStatusResolved);
Field::SetClass(java_lang_reflect_Field.get());
SirtRef<Class> java_lang_reflect_Method(AllocClass(java_lang_Class.get(), sizeof(MethodClass)));
- java_lang_reflect_Method->SetDescriptor(intern_table_->InternStrong("Ljava/lang/reflect/Method;"));
CHECK(java_lang_reflect_Method.get() != NULL);
java_lang_reflect_Method->SetObjectSize(sizeof(Method));
SetClassRoot(kJavaLangReflectMethod, java_lang_reflect_Method.get());
@@ -398,21 +386,19 @@
CHECK(java_lang_Cloneable != NULL);
Class* java_io_Serializable = FindSystemClass("Ljava/io/Serializable;");
CHECK(java_io_Serializable != NULL);
- CHECK(array_interfaces_ != NULL);
- array_interfaces_->Set(0, java_lang_Cloneable);
- array_interfaces_->Set(1, java_io_Serializable);
// We assume that Cloneable/Serializable don't have superinterfaces --
// normally we'd have to crawl up and explicitly list all of the
// supers as well.
- array_iftable_->Set(0, AllocInterfaceEntry(array_interfaces_->Get(0)));
- array_iftable_->Set(1, AllocInterfaceEntry(array_interfaces_->Get(1)));
+ array_iftable_->Set(0, AllocInterfaceEntry(java_lang_Cloneable));
+ array_iftable_->Set(1, AllocInterfaceEntry(java_io_Serializable));
// Sanity check Class[] and Object[]'s interfaces
- CHECK_EQ(java_lang_Cloneable, class_array_class->GetInterface(0));
- CHECK_EQ(java_io_Serializable, class_array_class->GetInterface(1));
- CHECK_EQ(java_lang_Cloneable, object_array_class->GetInterface(0));
- CHECK_EQ(java_io_Serializable, object_array_class->GetInterface(1));
-
+ ClassHelper kh(class_array_class.get(), this);
+ CHECK_EQ(java_lang_Cloneable, kh.GetInterface(0));
+ CHECK_EQ(java_io_Serializable, kh.GetInterface(1));
+ kh.ChangeClass(object_array_class.get());
+ CHECK_EQ(java_lang_Cloneable, kh.GetInterface(0));
+ CHECK_EQ(java_io_Serializable, kh.GetInterface(1));
// run Class, Constructor, Field, and Method through FindSystemClass.
// this initializes their dex_cache_ fields and register them in classes_.
Class* Class_class = FindSystemClass("Ljava/lang/Class;");
@@ -497,25 +483,37 @@
Heap::SetWellKnownClasses(java_lang_ref_FinalizerReference, java_lang_ref_ReferenceQueue);
+ const DexFile& java_lang_dex = FindDexFile(java_lang_ref_Reference->GetDexCache());
+
Field* pendingNext = java_lang_ref_Reference->GetInstanceField(0);
- CHECK(pendingNext->GetName()->Equals("pendingNext"));
- CHECK_EQ(ResolveType(pendingNext->GetTypeIdx(), pendingNext), java_lang_ref_Reference);
+ FieldHelper fh(pendingNext, this);
+ CHECK_STREQ(fh.GetName(), "pendingNext");
+ CHECK_EQ(java_lang_dex.GetFieldId(pendingNext->GetDexFieldIndex()).type_idx_,
+ java_lang_ref_Reference->GetDexTypeIndex());
Field* queue = java_lang_ref_Reference->GetInstanceField(1);
- CHECK(queue->GetName()->Equals("queue"));
- CHECK_EQ(ResolveType(queue->GetTypeIdx(), queue), java_lang_ref_ReferenceQueue);
+ fh.ChangeField(queue);
+ CHECK_STREQ(fh.GetName(), "queue");
+ CHECK_EQ(java_lang_dex.GetFieldId(queue->GetDexFieldIndex()).type_idx_,
+ java_lang_ref_ReferenceQueue->GetDexTypeIndex());
Field* queueNext = java_lang_ref_Reference->GetInstanceField(2);
- CHECK(queueNext->GetName()->Equals("queueNext"));
- CHECK_EQ(ResolveType(queueNext->GetTypeIdx(), queueNext), java_lang_ref_Reference);
+ fh.ChangeField(queueNext);
+ CHECK_STREQ(fh.GetName(), "queueNext");
+ CHECK_EQ(java_lang_dex.GetFieldId(queueNext->GetDexFieldIndex()).type_idx_,
+ java_lang_ref_Reference->GetDexTypeIndex());
Field* referent = java_lang_ref_Reference->GetInstanceField(3);
- CHECK(referent->GetName()->Equals("referent"));
- CHECK_EQ(ResolveType(referent->GetTypeIdx(), referent), GetClassRoot(kJavaLangObject));
+ fh.ChangeField(referent);
+ CHECK_STREQ(fh.GetName(), "referent");
+ CHECK_EQ(java_lang_dex.GetFieldId(referent->GetDexFieldIndex()).type_idx_,
+ GetClassRoot(kJavaLangObject)->GetDexTypeIndex());
Field* zombie = java_lang_ref_FinalizerReference->GetInstanceField(2);
- CHECK(zombie->GetName()->Equals("zombie"));
- CHECK_EQ(ResolveType(zombie->GetTypeIdx(), zombie), GetClassRoot(kJavaLangObject));
+ fh.ChangeField(zombie);
+ CHECK_STREQ(fh.GetName(), "zombie");
+ CHECK_EQ(java_lang_dex.GetFieldId(zombie->GetDexFieldIndex()).type_idx_,
+ GetClassRoot(kJavaLangObject)->GetDexTypeIndex());
Heap::SetReferenceOffsets(referent->GetOffset(),
queue->GetOffset(),
@@ -534,7 +532,6 @@
}
CHECK(array_iftable_ != NULL);
- CHECK(array_interfaces_ != NULL);
// disable the slow paths in FindClass and CreatePrimitiveClass now
// that Object, Class, and Object[] are setup
@@ -611,7 +608,9 @@
LOG(INFO) << "ClassLinker::OpenOat entering";
}
const ImageHeader& image_header = space->GetImageHeader();
- String* oat_location = image_header.GetImageRoot(ImageHeader::kOatLocation)->AsString();
+ // Grab location but don't use Object::AsString as we haven't yet initialized the roots to
+ // check the down cast
+ String* oat_location = down_cast<String*>(image_header.GetImageRoot(ImageHeader::kOatLocation));
std::string oat_filename;
oat_filename += runtime->GetHostPrefix();
oat_filename += oat_location->ToModifiedUtf8();
@@ -734,6 +733,14 @@
Object* dex_caches_object = space->GetImageHeader().GetImageRoot(ImageHeader::kDexCaches);
ObjectArray<DexCache>* dex_caches = dex_caches_object->AsObjectArray<DexCache>();
+ if (i == 0) {
+ // Special case of setting up the String class early so that we can test arbitrary objects
+ // as being Strings or not
+ Class* java_lang_String = spaces[0]->GetImageHeader().GetImageRoot(ImageHeader::kClassRoots)
+ ->AsObjectArray<Class>()->Get(kJavaLangString);
+ String::SetClass(java_lang_String);
+ }
+
CHECK_EQ(oat_file->GetOatHeader().GetDexFileCount(),
static_cast<uint32_t>(dex_caches->GetLength()));
for (int i = 0; i < dex_caches->GetLength(); i++) {
@@ -767,13 +774,10 @@
Object* class_roots_object = spaces[0]->GetImageHeader().GetImageRoot(ImageHeader::kClassRoots);
class_roots_ = class_roots_object->AsObjectArray<Class>();
- // reinit array_interfaces_ and array_iftable_ from any array class instance, they should all be ==
- array_interfaces_ = GetClassRoot(kObjectArrayClass)->GetInterfaces();
- DCHECK(array_interfaces_ == GetClassRoot(kBooleanArrayClass)->GetInterfaces());
+ // reinit array_iftable_ from any array class instance, they should be ==
array_iftable_ = GetClassRoot(kObjectArrayClass)->GetIfTable();
DCHECK(array_iftable_ == GetClassRoot(kBooleanArrayClass)->GetIfTable());
-
- String::SetClass(GetClassRoot(kJavaLangString));
+ // String class root was set above
Field::SetClass(GetClassRoot(kJavaLangReflectField));
Method::SetClasses(GetClassRoot(kJavaLangReflectConstructor), GetClassRoot(kJavaLangReflectMethod));
BooleanArray::SetArrayClass(GetClassRoot(kBooleanArrayClass));
@@ -806,7 +810,7 @@
if (obj->IsClass()) {
// restore class to ClassLinker::classes_ table
Class* klass = obj->AsClass();
- std::string descriptor = klass->GetDescriptor()->ToModifiedUtf8();
+ std::string descriptor(ClassHelper(klass, class_linker).GetDescriptor());
bool success = class_linker->InsertClass(descriptor, klass, true);
DCHECK(success);
return;
@@ -832,7 +836,6 @@
// Note. we deliberately ignore the class roots in the image (held in image_classes_)
}
- visitor(array_interfaces_, arg);
visitor(array_iftable_, arg);
}
@@ -960,7 +963,7 @@
// Check for circular dependencies between classes.
if (!klass->IsResolved() && klass->GetClinitThreadId() == self->GetTid()) {
self->ThrowNewException("Ljava/lang/ClassCircularityError;",
- PrettyDescriptor(klass->GetDescriptor()).c_str());
+ PrettyDescriptor(klass).c_str());
return NULL;
}
// Wait for the pending initialization to complete.
@@ -985,15 +988,16 @@
Thread* self = Thread::Current();
DCHECK(self != NULL);
CHECK(!self->IsExceptionPending()) << PrettyTypeOf(self->GetException());
+ if (descriptor.size() == 1) {
+ // only the descriptors of primitive types should be 1 character long, also avoid class lookup
+ // for primitive classes that aren't backed by dex files.
+ return FindPrimitiveClass(descriptor[0]);
+ }
// Find the class in the loaded classes table.
Class* klass = LookupClass(descriptor, class_loader);
if (klass != NULL) {
return EnsureResolved(klass);
}
- if (descriptor.size() == 1) {
- // only the descriptors of primitive types should be 1 character long
- return FindPrimitiveClass(descriptor[0]);
- }
// Class is not yet loaded.
if (descriptor[0] == '[') {
return CreateArrayClass(descriptor, class_loader);
@@ -1179,14 +1183,6 @@
CHECK(descriptor != NULL);
klass->SetClass(GetClassRoot(kJavaLangClass));
- if (klass->GetDescriptor() != NULL) {
- DCHECK(klass->GetDescriptor()->Equals(descriptor));
- } else {
- klass->SetDescriptor(intern_table_->InternStrong(descriptor));
- if (klass->GetDescriptor() == NULL) {
- return;
- }
- }
uint32_t access_flags = dex_class_def.access_flags_;
// Make sure that none of our runtime-only flags are set.
CHECK_EQ(access_flags & ~kAccJavaFlagsMask, 0U);
@@ -1195,21 +1191,7 @@
DCHECK(klass->GetPrimitiveType() == Primitive::kPrimNot);
klass->SetStatus(Class::kStatusIdx);
- klass->SetTypeIdx(dex_class_def.class_idx_);
- klass->SetSuperClassTypeIdx(dex_class_def.superclass_idx_);
- klass->SetAnnotationsOffset(dex_class_def.annotations_off_);
-
- const char* source_file = dex_file.GetSourceFile(dex_class_def);
- if (source_file != NULL) {
- String* source_file_string = intern_table_->InternStrong(source_file);
- if (source_file_string == NULL) {
- return;
- }
- klass->SetSourceFile(source_file_string);
- }
-
- // Load class interfaces.
- LoadInterfaces(dex_file, dex_class_def, klass);
+ klass->SetDexTypeIndex(dex_class_def.class_idx_);
// Load fields fields.
const byte* class_data = dex_file.GetClassData(dex_class_def);
@@ -1279,88 +1261,59 @@
DCHECK(!it.HasNext());
}
-void ClassLinker::LoadInterfaces(const DexFile& dex_file,
- const DexFile::ClassDef& dex_class_def,
- SirtRef<Class>& klass) {
- const DexFile::TypeList* list = dex_file.GetInterfacesList(dex_class_def);
- if (list != NULL) {
- klass->SetInterfaces(AllocClassArray(list->Size()));
- IntArray* interfaces_idx = IntArray::Alloc(list->Size());
- klass->SetInterfacesTypeIdx(interfaces_idx);
- for (size_t i = 0; i < list->Size(); ++i) {
- const DexFile::TypeItem& type_item = list->GetTypeItem(i);
- interfaces_idx->Set(i, type_item.type_idx_);
- }
- }
-}
-
void ClassLinker::LoadField(const DexFile& dex_file, const ClassDataItemIterator& it,
SirtRef<Class>& klass, SirtRef<Field>& dst) {
- const DexFile::FieldId& field_id = dex_file.GetFieldId(it.GetMemberIndex());
+ uint32_t field_idx = it.GetMemberIndex();
+ dst->SetDexFieldIndex(field_idx);
dst->SetDeclaringClass(klass.get());
- dst->SetName(ResolveString(dex_file, field_id.name_idx_, klass->GetDexCache()));
- dst->SetTypeIdx(field_id.type_idx_);
dst->SetAccessFlags(it.GetMemberAccessFlags());
-
- // In order to access primitive types using GetTypeDuringLinking we need to
- // ensure they are resolved into the dex cache
- const char* descriptor = dex_file.GetFieldTypeDescriptor(field_id);
- if (descriptor[1] == '\0') {
- // only the descriptors of primitive types should be 1 character long
- Class* resolved = ResolveType(dex_file, field_id.type_idx_, klass.get());
- DCHECK(resolved->IsPrimitive());
- }
}
void ClassLinker::LoadMethod(const DexFile& dex_file, const ClassDataItemIterator& it,
SirtRef<Class>& klass, SirtRef<Method>& dst) {
- const DexFile::MethodId& method_id = dex_file.GetMethodId(it.GetMemberIndex());
+ uint32_t method_idx = it.GetMemberIndex();
+ dst->SetDexMethodIndex(method_idx);
+ const DexFile::MethodId& method_id = dex_file.GetMethodId(method_idx);
dst->SetDeclaringClass(klass.get());
- String* method_name = ResolveString(dex_file, method_id.name_idx_, klass->GetDexCache());
- if (method_name == NULL) {
- return;
- }
- dst->SetName(method_name);
- if (method_name->Equals("<init>")) {
+
+ StringPiece method_name(dex_file.GetMethodName(method_id));
+ if (method_name == "<init>") {
dst->SetClass(GetClassRoot(kJavaLangReflectConstructor));
}
- int32_t utf16_length;
- std::string signature(dex_file.CreateMethodSignature(method_id.proto_idx_, &utf16_length));
- String* signature_string = intern_table_->InternStrong(utf16_length, signature.c_str());
- if (signature_string == NULL) {
- return;
- }
- dst->SetSignature(signature_string);
-
- if (method_name->Equals("finalize") && signature == "()V") {
- /*
- * The Enum class declares a "final" finalize() method to prevent subclasses from introducing
- * a finalizer. We don't want to set the finalizable flag for Enum or its subclasses, so we
- * exclude it here.
- *
- * We also want to avoid setting the flag on Object, where we know that finalize() is empty.
- */
- if (klass->GetClassLoader() != NULL ||
- (!klass->GetDescriptor()->Equals("Ljava/lang/Object;") &&
- !klass->GetDescriptor()->Equals("Ljava/lang/Enum;"))) {
- klass->SetFinalizable();
+ if (method_name == "finalize") {
+ // Create the prototype for a signature of "()V"
+ const DexFile::StringId* void_string_id = dex_file.FindStringId("V");
+ if (void_string_id != NULL) {
+ const DexFile::TypeId* void_type_id =
+ dex_file.FindTypeId(dex_file.GetIndexForStringId(*void_string_id));
+ if (void_type_id != NULL) {
+ std::vector<uint16_t> no_args;
+ const DexFile::ProtoId* finalizer_proto =
+ dex_file.FindProtoId(dex_file.GetIndexForTypeId(*void_type_id), no_args);
+ if (finalizer_proto != NULL) {
+ // We have the prototype in the dex file
+ if (klass->GetClassLoader() != NULL) { // All non-boot finalizer methods are flagged
+ klass->SetFinalizable();
+ } else {
+ StringPiece klass_descriptor(dex_file.StringByTypeIdx(klass->GetDexTypeIndex()));
+ // The Enum class declares a "final" finalize() method to prevent subclasses from
+ // introducing a finalizer. We don't want to set the finalizable flag for Enum or its
+ // subclasses, so we exclude it here.
+ // We also want to avoid setting the flag on Object, where we know that finalize() is
+ // empty.
+ if (klass_descriptor != "Ljava/lang/Object;" &&
+ klass_descriptor != "Ljava/lang/Enum;") {
+ klass->SetFinalizable();
+ }
+ }
+ }
+ }
}
}
-
- dst->SetProtoIdx(method_id.proto_idx_);
dst->SetCodeItemOffset(it.GetMethodCodeItemOffset());
- const char* shorty = dex_file.GetShorty(method_id.proto_idx_);
- String* shorty_string = intern_table_->InternStrong(shorty);
- dst->SetShorty(shorty_string);
- if (shorty_string == NULL) {
- return;
- }
dst->SetAccessFlags(it.GetMemberAccessFlags());
- uint32_t return_type_idx = dex_file.GetProtoId(method_id.proto_idx_).return_type_idx_;
- DCHECK_LT(return_type_idx, dex_file.NumTypeIds());
- dst->SetReturnTypeIdx(return_type_idx);
dst->SetDexCacheStrings(klass->GetDexCache()->GetStrings());
dst->SetDexCacheResolvedTypes(klass->GetDexCache()->GetResolvedTypes());
@@ -1370,20 +1323,6 @@
dst->SetDexCacheInitializedStaticStorage(klass->GetDexCache()->GetInitializedStaticStorage());
// TODO: check for finalize method
-
- const DexFile::CodeItem* code_item = it.GetMethodCodeItem();
- if (code_item != NULL) {
- dst->SetNumRegisters(code_item->registers_size_);
- dst->SetNumIns(code_item->ins_size_);
- dst->SetNumOuts(code_item->outs_size_);
- } else {
- uint16_t num_args = Method::NumArgRegisters(shorty);
- if ((it.GetMemberAccessFlags() & kAccStatic) == 0) {
- ++num_args;
- }
- dst->SetNumRegisters(num_args);
- // TODO: native methods
- }
}
void ClassLinker::AppendToBootClassPath(const DexFile& dex_file) {
@@ -1474,8 +1413,6 @@
// TODO: deduce one argument from the other
CHECK(primitive_class != NULL);
primitive_class->SetAccessFlags(kAccPublic | kAccFinal | kAccAbstract);
- primitive_class->SetDescriptor(intern_table_->InternStrong(descriptor));
- CHECK(primitive_class->GetDescriptor() != NULL);
primitive_class->SetPrimitiveType(type);
primitive_class->SetStatus(Class::kStatusInitialized);
bool success = InsertClass(descriptor, primitive_class, false);
@@ -1561,14 +1498,6 @@
new_class->SetComponentType(component_type);
}
DCHECK(new_class->GetComponentType() != NULL);
- if (new_class->GetDescriptor() != NULL) {
- DCHECK(new_class->GetDescriptor()->Equals(descriptor));
- } else {
- new_class->SetDescriptor(intern_table_->InternStrong(descriptor.c_str()));
- if (new_class->GetDescriptor() == NULL) {
- return NULL;
- }
- }
Class* java_lang_Object = GetClassRoot(kJavaLangObject);
new_class->SetSuperClass(java_lang_Object);
new_class->SetVTable(java_lang_Object->GetVTable());
@@ -1591,9 +1520,7 @@
// Use the single, global copies of "interfaces" and "iftable"
// (remember not to free them for arrays).
- CHECK(array_interfaces_ != NULL);
CHECK(array_iftable_ != NULL);
- new_class->SetInterfaces(array_interfaces_);
new_class->SetIfTable(array_iftable_);
// Inherit access flags from the component type. Arrays can't be
@@ -1677,16 +1604,19 @@
MutexLock mu(classes_lock_);
typedef Table::const_iterator It; // TODO: C++0x auto
// TODO: determine if its better to search classes_ or image_classes_ first
+ ClassHelper kh;
for (It it = classes_.find(hash), end = classes_.end(); it != end; ++it) {
Class* klass = it->second;
- if (klass->GetDescriptor()->Equals(descriptor) && klass->GetClassLoader() == class_loader) {
+ kh.ChangeClass(klass);
+ if (kh.GetDescriptor() == descriptor && klass->GetClassLoader() == class_loader) {
classes_.erase(it);
return true;
}
}
for (It it = image_classes_.find(hash), end = image_classes_.end(); it != end; ++it) {
Class* klass = it->second;
- if (klass->GetDescriptor()->Equals(descriptor) && klass->GetClassLoader() == class_loader) {
+ kh.ChangeClass(klass);
+ if (kh.GetDescriptor() == descriptor && klass->GetClassLoader() == class_loader) {
image_classes_.erase(it);
return true;
}
@@ -1699,15 +1629,18 @@
MutexLock mu(classes_lock_);
typedef Table::const_iterator It; // TODO: C++0x auto
// TODO: determine if its better to search classes_ or image_classes_ first
+ ClassHelper kh(NULL, this);
for (It it = classes_.find(hash), end = classes_.end(); it != end; ++it) {
Class* klass = it->second;
- if (klass->GetDescriptor()->Equals(descriptor) && klass->GetClassLoader() == class_loader) {
+ kh.ChangeClass(klass);
+ if (descriptor == kh.GetDescriptor() && klass->GetClassLoader() == class_loader) {
return klass;
}
}
for (It it = image_classes_.find(hash), end = image_classes_.end(); it != end; ++it) {
Class* klass = it->second;
- if (klass->GetDescriptor()->Equals(descriptor) && klass->GetClassLoader() == class_loader) {
+ kh.ChangeClass(klass);
+ if (descriptor == kh.GetDescriptor() && klass->GetClassLoader() == class_loader) {
return klass;
}
}
@@ -1720,16 +1653,19 @@
MutexLock mu(classes_lock_);
typedef Table::const_iterator It; // TODO: C++0x auto
// TODO: determine if its better to search classes_ or image_classes_ first
+ ClassHelper kh(NULL, this);
for (It it = classes_.find(hash), end = classes_.end(); it != end; ++it) {
- Class* c = it->second;
- if (c->GetDescriptor()->Equals(descriptor)) {
- classes.push_back(c);
+ Class* klass = it->second;
+ kh.ChangeClass(klass);
+ if (descriptor == kh.GetDescriptor()) {
+ classes.push_back(klass);
}
}
for (It it = image_classes_.find(hash), end = image_classes_.end(); it != end; ++it) {
- Class* c = it->second;
- if (c->GetDescriptor()->Equals(descriptor)) {
- classes.push_back(c);
+ Class* klass = it->second;
+ kh.ChangeClass(klass);
+ if (descriptor == kh.GetDescriptor()) {
+ classes.push_back(klass);
}
}
}
@@ -1749,48 +1685,56 @@
Thread* self = Thread::Current();
CHECK(!self->IsExceptionPending()) << PrettyTypeOf(self->GetException());
self->ThrowNewExceptionF("Ljava/lang/VerifyError;", "Verification of %s failed",
- PrettyDescriptor(klass->GetDescriptor()).c_str());
+ PrettyDescriptor(klass).c_str());
CHECK_EQ(klass->GetStatus(), Class::kStatusVerifying);
klass->SetStatus(Class::kStatusError);
}
}
Class* ClassLinker::CreateProxyClass(String* name, ObjectArray<Class>* interfaces,
- ClassLoader* loader, ObjectArray<Method>* methods, ObjectArray<ObjectArray<Class> >* throws) {
+ ClassLoader* loader, ObjectArray<Method>* methods,
+ ObjectArray<ObjectArray<Class> >* throws) {
SirtRef<Class> klass(AllocClass(GetClassRoot(kJavaLangClass), sizeof(ProxyClass)));
CHECK(klass.get() != NULL);
klass->SetObjectSize(sizeof(Proxy));
- const char* descriptor = DotToDescriptor(name->ToModifiedUtf8().c_str()).c_str();;
- klass->SetDescriptor(intern_table_->InternStrong(descriptor));
- klass->SetAccessFlags(kAccPublic | kAccFinal);
+ klass->SetAccessFlags(kAccClassIsProxy | kAccPublic | kAccFinal);
klass->SetClassLoader(loader);
- klass->SetStatus(Class::kStatusInitialized); // no loading or initializing necessary
+ klass->SetName(name);
Class* proxy_class = GetClassRoot(kJavaLangReflectProxy);
+ klass->SetDexCache(proxy_class->GetDexCache());
+ klass->SetDexTypeIndex(-1);
klass->SetSuperClass(proxy_class); // The super class is java.lang.reflect.Proxy
- klass->SetInterfaces(interfaces); // The interfaces are the array of interfaces specified
+ klass->SetStatus(Class::kStatusInitialized); // no loading or initializing necessary
// Proxies have 1 direct method, the constructor
klass->SetDirectMethods(AllocObjectArray<Method>(1));
- klass->SetDirectMethod(0, CreateProxyConstructor(klass));
+ klass->SetDirectMethod(0, CreateProxyConstructor(klass, proxy_class));
// Create virtual method using specified prototypes
size_t num_virtual_methods = methods->GetLength();
klass->SetVirtualMethods(AllocObjectArray<Method>(num_virtual_methods));
for (size_t i = 0; i < num_virtual_methods; ++i) {
SirtRef<Method> prototype(methods->Get(i));
- klass->SetVirtualMethod(i, CreateProxyMethod(klass, prototype, throws->Get(i)));
+ klass->SetVirtualMethod(i, CreateProxyMethod(klass, prototype));
}
// Link the virtual methods, creating vtable and iftables
- if (!LinkMethods(klass)) {
+ if (!LinkMethods(klass, interfaces)) {
DCHECK(Thread::Current()->IsExceptionPending());
return NULL;
}
return klass.get();
}
-Method* ClassLinker::CreateProxyConstructor(SirtRef<Class>& klass) {
+std::string ClassLinker::GetDescriptorForProxy(const Class* proxy_class) {
+ DCHECK(proxy_class->IsProxyClass());
+ String* name = proxy_class->GetName();
+ DCHECK(name != NULL);
+ return DotToDescriptor(name->ToModifiedUtf8().c_str());
+}
+
+
+Method* ClassLinker::CreateProxyConstructor(SirtRef<Class>& klass, Class* proxy_class) {
// Create constructor for Proxy that must initialize h
- Class* proxy_class = GetClassRoot(kJavaLangReflectProxy);
ObjectArray<Method>* proxy_direct_methods = proxy_class->GetDirectMethods();
CHECK_EQ(proxy_direct_methods->GetLength(), 15);
Method* proxy_constructor = proxy_direct_methods->Get(2);
@@ -1802,15 +1746,18 @@
constructor->SetDeclaringClass(klass.get());
// Sanity checks
CHECK(constructor->IsConstructor());
- CHECK(constructor->GetName()->Equals("<init>"));
- CHECK(constructor->GetSignature()->Equals("(Ljava/lang/reflect/InvocationHandler;)V"));
+ MethodHelper mh(constructor);
+ CHECK_STREQ(mh.GetName(), "<init>");
+ CHECK(mh.GetSignature() == "(Ljava/lang/reflect/InvocationHandler;)V");
DCHECK(constructor->IsPublic());
return constructor;
}
-Method* ClassLinker::CreateProxyMethod(SirtRef<Class>& klass, SirtRef<Method>& prototype,
- ObjectArray<Class>* throws) {
- // We steal everything from the prototype (such as DexCache, invoke stub, etc.) then specialise
+Method* ClassLinker::CreateProxyMethod(SirtRef<Class>& klass, SirtRef<Method>& prototype) {
+ // Ensure prototype is in dex cache so that we can use the dex cache to look up the overridden
+ // prototype method
+ prototype->GetDexCacheResolvedMethods()->Set(prototype->GetDexMethodIndex(), prototype.get());
+ // We steal everything from the prototype (such as DexCache, invoke stub, etc.) then specialize
// as necessary
Method* method = down_cast<Method*>(prototype->Clone());
@@ -1818,7 +1765,6 @@
// the intersection of throw exceptions as defined in Proxy
method->SetDeclaringClass(klass.get());
method->SetAccessFlags((method->GetAccessFlags() & ~kAccAbstract) | kAccFinal);
- method->SetExceptionTypes(throws);
// At runtime the method looks like a reference and argument saving method, clone the code
// related parameters from this method.
@@ -1829,12 +1775,21 @@
method->SetCode(reinterpret_cast<void*>(art_proxy_invoke_handler));
// Basic sanity
- DCHECK(method->GetName()->Equals(prototype->GetName()));
- DCHECK(method->GetSignature()->Equals(prototype->GetSignature()));
- DCHECK(method->GetShorty()->Equals(prototype->GetShorty()));
+ CHECK(!prototype->IsFinal());
+ CHECK(method->IsFinal());
+ CHECK(!method->IsAbstract());
+ MethodHelper mh(method);
+ const char* method_name = mh.GetName();
+ const char* method_shorty = mh.GetShorty();
+ Class* method_return = mh.GetReturnType();
+
+ mh.ChangeMethod(prototype.get());
+
+ CHECK_STREQ(mh.GetName(), method_name);
+ CHECK_STREQ(mh.GetShorty(), method_shorty);
// More complex sanity - via dex cache
- CHECK_EQ(method->GetReturnType(), prototype->GetReturnType());
+ CHECK_EQ(mh.GetReturnType(), method_return);
return method;
}
@@ -1928,8 +1883,8 @@
thread_stats->class_init_time_ns += (t1 - t0);
klass->SetStatus(Class::kStatusInitialized);
if (verbose_) {
- LOG(INFO) << "Initialized class " << klass->GetDescriptor()->ToModifiedUtf8()
- << " from " << klass->GetDexCache()->GetLocation()->ToModifiedUtf8();
+ ClassHelper kh(klass);
+ LOG(INFO) << "Initialized class " << kh.GetDescriptor() << " from " << kh.GetLocation();
}
}
lock.NotifyAll();
@@ -1959,7 +1914,7 @@
// The caller wants an exception, but it was thrown in a
// different thread. Synthesize one here.
ThrowNoClassDefFoundError("<clinit> failed for class %s; see exception in other thread",
- PrettyDescriptor(klass->GetDescriptor()).c_str());
+ PrettyDescriptor(klass).c_str());
return false;
}
if (klass->IsInitialized()) {
@@ -1984,7 +1939,9 @@
!HasSameMethodDescriptorClasses(method, super, klass)) {
klass->DumpClass(std::cerr, Class::kDumpClassFullDetail);
- ThrowLinkageError("Class %s method %s resolves differently in superclass %s", PrettyDescriptor(klass->GetDescriptor()).c_str(), PrettyMethod(method).c_str(), PrettyDescriptor(super->GetDescriptor()).c_str());
+ ThrowLinkageError("Class %s method %s resolves differently in superclass %s",
+ PrettyDescriptor(klass).c_str(), PrettyMethod(method).c_str(),
+ PrettyDescriptor(super).c_str());
return false;
}
}
@@ -1999,7 +1956,10 @@
method->GetDeclaringClass())) {
klass->DumpClass(std::cerr, Class::kDumpClassFullDetail);
- ThrowLinkageError("Class %s method %s resolves differently in interface %s", PrettyDescriptor(method->GetDeclaringClass()->GetDescriptor()).c_str(), PrettyMethod(method).c_str(), PrettyDescriptor(interface->GetDescriptor()).c_str());
+ ThrowLinkageError("Class %s method %s resolves differently in interface %s",
+ PrettyDescriptor(method->GetDeclaringClass()).c_str(),
+ PrettyMethod(method).c_str(),
+ PrettyDescriptor(interface).c_str());
return false;
}
}
@@ -2015,7 +1975,8 @@
return true;
}
const DexFile& dex_file = FindDexFile(method->GetDeclaringClass()->GetDexCache());
- const DexFile::ProtoId& proto_id = dex_file.GetProtoId(method->GetProtoIdx());
+ const DexFile::ProtoId& proto_id =
+ dex_file.GetMethodPrototype(dex_file.GetMethodId(method->GetDexMethodIndex()));
for (DexFileParameterIterator it(dex_file, proto_id); it.HasNext(); it.Next()) {
const char* descriptor = it.GetDescriptor();
if (descriptor == NULL) {
@@ -2121,10 +2082,10 @@
if (dex_cache == NULL) {
return;
}
- const DexFile& dex_file = FindDexFile(dex_cache);
- const std::string descriptor(klass->GetDescriptor()->ToModifiedUtf8());
- const DexFile::ClassDef* dex_class_def = dex_file.FindClassDef(descriptor);
+ ClassHelper kh(klass);
+ const DexFile::ClassDef* dex_class_def = kh.GetClassDef();
CHECK(dex_class_def != NULL);
+ const DexFile& dex_file = kh.GetDexFile();
EncodedStaticFieldValueIterator it(dex_file, dex_cache, this, *dex_class_def);
if (it.HasNext()) {
@@ -2142,7 +2103,7 @@
if (!LinkSuperClass(klass)) {
return false;
}
- if (!LinkMethods(klass)) {
+ if (!LinkMethods(klass, NULL)) {
return false;
}
if (!LinkInstanceFields(klass)) {
@@ -2160,30 +2121,38 @@
bool ClassLinker::LoadSuperAndInterfaces(SirtRef<Class>& klass, const DexFile& dex_file) {
CHECK_EQ(Class::kStatusIdx, klass->GetStatus());
- if (klass->GetSuperClassTypeIdx() != DexFile::kDexNoIndex16) {
- Class* super_class = ResolveType(dex_file, klass->GetSuperClassTypeIdx(), klass.get());
+ StringPiece descriptor(dex_file.StringByTypeIdx(klass->GetDexTypeIndex()));
+ const DexFile::ClassDef* class_def = dex_file.FindClassDef(descriptor);
+ if (class_def == NULL) {
+ return false;
+ }
+ uint16_t super_class_idx = class_def->superclass_idx_;
+ if (super_class_idx != DexFile::kDexNoIndex16) {
+ Class* super_class = ResolveType(dex_file, super_class_idx, klass.get());
if (super_class == NULL) {
DCHECK(Thread::Current()->IsExceptionPending());
return false;
}
klass->SetSuperClass(super_class);
}
- for (size_t i = 0; i < klass->NumInterfaces(); ++i) {
- uint32_t idx = klass->GetInterfacesTypeIdx()->Get(i);
- Class* interface = ResolveType(dex_file, idx, klass.get());
- klass->SetInterface(i, interface);
- if (interface == NULL) {
- DCHECK(Thread::Current()->IsExceptionPending());
- return false;
- }
- // Verify
- if (!klass->CanAccess(interface)) {
- // TODO: the RI seemed to ignore this in my testing.
- Thread::Current()->ThrowNewExceptionF("Ljava/lang/IllegalAccessError;",
- "Interface %s implemented by class %s is inaccessible",
- PrettyDescriptor(interface->GetDescriptor()).c_str(),
- PrettyDescriptor(klass->GetDescriptor()).c_str());
- return false;
+ const DexFile::TypeList* interfaces = dex_file.GetInterfacesList(*class_def);
+ if (interfaces != NULL) {
+ for (size_t i = 0; i < interfaces->Size(); i++) {
+ uint16_t idx = interfaces->GetTypeItem(i).type_idx_;
+ Class* interface = ResolveType(dex_file, idx, klass.get());
+ if (interface == NULL) {
+ DCHECK(Thread::Current()->IsExceptionPending());
+ return false;
+ }
+ // Verify
+ if (!klass->CanAccess(interface)) {
+ // TODO: the RI seemed to ignore this in my testing.
+ Thread::Current()->ThrowNewExceptionF("Ljava/lang/IllegalAccessError;",
+ "Interface %s implemented by class %s is inaccessible",
+ PrettyDescriptor(interface).c_str(),
+ PrettyDescriptor(klass.get()).c_str());
+ return false;
+ }
}
}
// Mark the class as loaded.
@@ -2194,7 +2163,7 @@
bool ClassLinker::LinkSuperClass(SirtRef<Class>& klass) {
CHECK(!klass->IsPrimitive());
Class* super = klass->GetSuperClass();
- if (klass->GetDescriptor()->Equals("Ljava/lang/Object;")) {
+ if (klass.get() == GetClassRoot(kJavaLangObject)) {
if (super != NULL) {
Thread::Current()->ThrowNewExceptionF("Ljava/lang/ClassFormatError;",
"java.lang.Object must not have a superclass");
@@ -2203,24 +2172,23 @@
return true;
}
if (super == NULL) {
- ThrowLinkageError("No superclass defined for class %s",
- PrettyDescriptor(klass->GetDescriptor()).c_str());
+ ThrowLinkageError("No superclass defined for class %s", PrettyDescriptor(klass.get()).c_str());
return false;
}
// Verify
if (super->IsFinal() || super->IsInterface()) {
Thread::Current()->ThrowNewExceptionF("Ljava/lang/IncompatibleClassChangeError;",
"Superclass %s of %s is %s",
- PrettyDescriptor(super->GetDescriptor()).c_str(),
- PrettyDescriptor(klass->GetDescriptor()).c_str(),
+ PrettyDescriptor(super).c_str(),
+ PrettyDescriptor(klass.get()).c_str(),
super->IsFinal() ? "declared final" : "an interface");
return false;
}
if (!klass->CanAccess(super)) {
Thread::Current()->ThrowNewExceptionF("Ljava/lang/IllegalAccessError;",
"Superclass %s is inaccessible by %s",
- PrettyDescriptor(super->GetDescriptor()).c_str(),
- PrettyDescriptor(klass->GetDescriptor()).c_str());
+ PrettyDescriptor(super).c_str(),
+ PrettyDescriptor(klass.get()).c_str());
return false;
}
@@ -2237,7 +2205,7 @@
// Disallow custom direct subclasses of java.lang.ref.Reference.
if (init_done_ && super == GetClassRoot(kJavaLangRefReference)) {
ThrowLinkageError("Class %s attempts to subclass java.lang.ref.Reference, which is not allowed",
- PrettyDescriptor(klass->GetDescriptor()).c_str());
+ PrettyDescriptor(klass.get()).c_str());
return false;
}
@@ -2252,7 +2220,7 @@
}
// Populate the class vtable and itable. Compute return type indices.
-bool ClassLinker::LinkMethods(SirtRef<Class>& klass) {
+bool ClassLinker::LinkMethods(SirtRef<Class>& klass, ObjectArray<Class>* interfaces) {
if (klass->IsInterface()) {
// No vtable.
size_t count = klass->NumVirtualMethods();
@@ -2264,10 +2232,10 @@
klass->GetVirtualMethodDuringLinking(i)->SetMethodIndex(i);
}
// Link interface method tables
- return LinkInterfaceMethods(klass);
+ return LinkInterfaceMethods(klass, interfaces);
} else {
// Link virtual and interface method tables
- return LinkVirtualMethods(klass) && LinkInterfaceMethods(klass);
+ return LinkVirtualMethods(klass) && LinkInterfaceMethods(klass, interfaces);
}
return true;
}
@@ -2280,18 +2248,22 @@
// TODO: do not assign to the vtable field until it is fully constructed.
ObjectArray<Method>* vtable = klass->GetSuperClass()->GetVTable()->CopyOf(max_count);
// See if any of our virtual methods override the superclass.
+ MethodHelper local_mh(NULL, this);
+ MethodHelper super_mh(NULL, this);
for (size_t i = 0; i < klass->NumVirtualMethods(); ++i) {
Method* local_method = klass->GetVirtualMethodDuringLinking(i);
+ local_mh.ChangeMethod(local_method);
size_t j = 0;
for (; j < actual_count; ++j) {
Method* super_method = vtable->Get(j);
- if (local_method->HasSameNameAndSignature(super_method)) {
+ super_mh.ChangeMethod(super_method);
+ if (local_mh.HasSameNameAndSignature(&super_mh)) {
// Verify
if (super_method->IsFinal()) {
+ MethodHelper mh(local_method);
ThrowLinkageError("Method %s.%s overrides final method in class %s",
- PrettyDescriptor(klass->GetDescriptor()).c_str(),
- local_method->GetName()->ToModifiedUtf8().c_str(),
- PrettyDescriptor(super_method->GetDeclaringClass()->GetDescriptor()).c_str());
+ PrettyDescriptor(klass.get()).c_str(),
+ mh.GetName(), mh.GetDeclaringClassDescriptor());
return false;
}
vtable->Set(j, local_method);
@@ -2317,7 +2289,7 @@
}
klass->SetVTable(vtable);
} else {
- CHECK(klass->GetDescriptor()->Equals("Ljava/lang/Object;"));
+ CHECK(klass.get() == GetClassRoot(kJavaLangObject));
uint32_t num_virtual_methods = klass->NumVirtualMethods();
if (!IsUint(16, num_virtual_methods)) {
ThrowClassFormatError("Too many methods: %d", num_virtual_methods);
@@ -2334,7 +2306,7 @@
return true;
}
-bool ClassLinker::LinkInterfaceMethods(SirtRef<Class>& klass) {
+bool ClassLinker::LinkInterfaceMethods(SirtRef<Class>& klass, ObjectArray<Class>* interfaces) {
size_t super_ifcount;
if (klass->HasSuperClass()) {
super_ifcount = klass->GetSuperClass()->GetIfTableCount();
@@ -2342,9 +2314,12 @@
super_ifcount = 0;
}
size_t ifcount = super_ifcount;
- ifcount += klass->NumInterfaces();
- for (size_t i = 0; i < klass->NumInterfaces(); i++) {
- ifcount += klass->GetInterface(i)->GetIfTableCount();
+ ClassHelper kh(klass.get(), this);
+ uint32_t num_interfaces = interfaces == NULL ? kh.NumInterfaces() : interfaces->GetLength();
+ ifcount += num_interfaces;
+ for (size_t i = 0; i < num_interfaces; i++) {
+ Class* interface = interfaces == NULL ? kh.GetInterface(i) : interfaces->Get(i);
+ ifcount += interface->GetIfTableCount();
}
if (ifcount == 0) {
// TODO: enable these asserts with klass status validation
@@ -2361,14 +2336,15 @@
}
// Flatten the interface inheritance hierarchy.
size_t idx = super_ifcount;
- for (size_t i = 0; i < klass->NumInterfaces(); i++) {
- Class* interface = klass->GetInterface(i);
+ for (size_t i = 0; i < num_interfaces; i++) {
+ Class* interface = interfaces == NULL ? kh.GetInterface(i) : interfaces->Get(i);
DCHECK(interface != NULL);
if (!interface->IsInterface()) {
+ ClassHelper ih(interface);
Thread::Current()->ThrowNewExceptionF("Ljava/lang/IncompatibleClassChangeError;",
"Class %s implements non-interface class %s",
- PrettyDescriptor(klass->GetDescriptor()).c_str(),
- PrettyDescriptor(interface->GetDescriptor()).c_str());
+ PrettyDescriptor(klass.get()).c_str(),
+ PrettyDescriptor(ih.GetDescriptor()).c_str());
return false;
}
// Add this interface.
@@ -2386,6 +2362,8 @@
return true;
}
std::vector<Method*> miranda_list;
+ MethodHelper vtable_mh(NULL, this);
+ MethodHelper interface_mh(NULL, this);
for (size_t i = 0; i < ifcount; ++i) {
InterfaceEntry* interface_entry = iftable->Get(i);
Class* interface = interface_entry->GetInterface();
@@ -2394,6 +2372,7 @@
ObjectArray<Method>* vtable = klass->GetVTableDuringLinking();
for (size_t j = 0; j < interface->NumVirtualMethods(); ++j) {
Method* interface_method = interface->GetVirtualMethod(j);
+ interface_mh.ChangeMethod(interface_method);
int32_t k;
// For each method listed in the interface's method list, find the
// matching method in our class's method list. We want to favor the
@@ -2405,7 +2384,8 @@
// matter which direction we go. We walk it backward anyway.)
for (k = vtable->GetLength() - 1; k >= 0; --k) {
Method* vtable_method = vtable->Get(k);
- if (interface_method->HasSameNameAndSignature(vtable_method)) {
+ vtable_mh.ChangeMethod(vtable_method);
+ if (interface_mh.HasSameNameAndSignature(&vtable_mh)) {
if (!vtable_method->IsPublic()) {
Thread::Current()->ThrowNewExceptionF("Ljava/lang/IllegalAccessError;",
"Implementation not public: %s", PrettyMethod(vtable_method).c_str());
@@ -2418,7 +2398,9 @@
if (k < 0) {
SirtRef<Method> miranda_method(NULL);
for (size_t mir = 0; mir < miranda_list.size(); mir++) {
- if (miranda_list[mir]->HasSameNameAndSignature(interface_method)) {
+ Method* mir_method = miranda_list[mir];
+ vtable_mh.ChangeMethod(mir_method);
+ if (interface_mh.HasSameNameAndSignature(&vtable_mh)) {
miranda_method.reset(miranda_list[mir]);
break;
}
@@ -2481,10 +2463,13 @@
}
struct LinkFieldsComparator {
+ LinkFieldsComparator(FieldHelper* fh) : fh_(fh) {}
bool operator()(const Field* field1, const Field* field2) {
// First come reference fields, then 64-bit, and finally 32-bit
- Primitive::Type type1 = field1->GetPrimitiveType();
- Primitive::Type type2 = field2->GetPrimitiveType();
+ fh_->ChangeField(field1);
+ Primitive::Type type1 = fh_->GetTypeAsPrimitiveType();
+ fh_->ChangeField(field2);
+ Primitive::Type type2 = fh_->GetTypeAsPrimitiveType();
bool isPrimitive1 = type1 != Primitive::kPrimNot;
bool isPrimitive2 = type2 != Primitive::kPrimNot;
bool is64bit1 = isPrimitive1 && (type1 == Primitive::kPrimLong || type1 == Primitive::kPrimDouble);
@@ -2496,10 +2481,14 @@
}
// same basic group? then sort by string.
- std::string name1 = field1->GetName()->ToModifiedUtf8();
- std::string name2 = field2->GetName()->ToModifiedUtf8();
+ fh_->ChangeField(field1);
+ StringPiece name1(fh_->GetName());
+ fh_->ChangeField(field2);
+ StringPiece name2(fh_->GetName());
return name1 < name2;
}
+
+ FieldHelper* fh_;
};
bool ClassLinker::LinkFields(SirtRef<Class>& klass, bool is_static) {
@@ -2532,16 +2521,18 @@
for (size_t i = 0; i < num_fields; i++) {
grouped_and_sorted_fields.push_back(fields->Get(i));
}
+ FieldHelper fh(NULL, this);
std::sort(grouped_and_sorted_fields.begin(),
grouped_and_sorted_fields.end(),
- LinkFieldsComparator());
+ LinkFieldsComparator(&fh));
// References should be at the front.
size_t current_field = 0;
size_t num_reference_fields = 0;
for (; current_field < num_fields; current_field++) {
Field* field = grouped_and_sorted_fields.front();
- Primitive::Type type = field->GetPrimitiveType();
+ fh.ChangeField(field);
+ Primitive::Type type = fh.GetTypeAsPrimitiveType();
bool isPrimitive = type != Primitive::kPrimNot;
if (isPrimitive) {
break; // past last reference, move on to the next phase
@@ -2559,7 +2550,8 @@
if (current_field != num_fields && !IsAligned<8>(field_offset.Uint32Value())) {
for (size_t i = 0; i < grouped_and_sorted_fields.size(); i++) {
Field* field = grouped_and_sorted_fields[i];
- Primitive::Type type = field->GetPrimitiveType();
+ fh.ChangeField(field);
+ Primitive::Type type = fh.GetTypeAsPrimitiveType();
CHECK(type != Primitive::kPrimNot); // should only be working on primitive types
if (type == Primitive::kPrimLong || type == Primitive::kPrimDouble) {
continue;
@@ -2580,7 +2572,8 @@
while (!grouped_and_sorted_fields.empty()) {
Field* field = grouped_and_sorted_fields.front();
grouped_and_sorted_fields.pop_front();
- Primitive::Type type = field->GetPrimitiveType();
+ fh.ChangeField(field);
+ Primitive::Type type = fh.GetTypeAsPrimitiveType();
CHECK(type != Primitive::kPrimNot); // should only be working on primitive types
fields->Set(current_field, field);
field->SetOffset(field_offset);
@@ -2592,11 +2585,14 @@
}
// We lie to the GC about the java.lang.ref.Reference.referent field, so it doesn't scan it.
- if (!is_static && klass->GetDescriptor()->Equals("Ljava/lang/ref/Reference;")) {
+ std::string descriptor(ClassHelper(klass.get(), this).GetDescriptor());
+ if (!is_static && descriptor == "Ljava/lang/ref/Reference;") {
// We know there are no non-reference fields in the Reference classes, and we know
// that 'referent' is alphabetically last, so this is easy...
CHECK_EQ(num_reference_fields, num_fields);
- CHECK(fields->Get(num_fields - 1)->GetName()->Equals("referent"));
+ fh.ChangeField(fields->Get(num_fields - 1));
+ StringPiece name(fh.GetName());
+ CHECK(name == "referent");
--num_reference_fields;
}
@@ -2612,9 +2608,10 @@
<< " field=" << PrettyField(field)
<< " offset=" << field->GetField32(MemberOffset(Field::OffsetOffset()), false);
}
- Primitive::Type type = field->GetPrimitiveType();
+ fh.ChangeField(field);
+ Primitive::Type type = fh.GetTypeAsPrimitiveType();
bool is_primitive = type != Primitive::kPrimNot;
- if (klass->GetDescriptor()->Equals("Ljava/lang/ref/Reference;") && field->GetName()->Equals("referent")) {
+ if (descriptor == "Ljava/lang/ref/Reference;" && StringPiece(fh.GetName()) == "referent") {
is_primitive = true; // We lied above, so we have to expect a lie here.
}
if (is_primitive) {
@@ -2711,7 +2708,7 @@
}
Class* ClassLinker::ResolveType(const DexFile& dex_file,
- uint32_t type_idx,
+ uint16_t type_idx,
DexCache* dex_cache,
const ClassLoader* class_loader) {
Class* resolved = dex_cache->GetResolvedType(type_idx);
@@ -2842,4 +2839,15 @@
return dex_lock_.GetOwner();
}
+void ClassLinker::SetClassRoot(ClassRoot class_root, Class* klass) {
+ DCHECK(!init_done_);
+
+ DCHECK(klass != NULL);
+ DCHECK(klass->GetClassLoader() == NULL);
+
+ DCHECK(class_roots_ != NULL);
+ DCHECK(class_roots_->Get(class_root) == NULL);
+ class_roots_->Set(class_root, klass);
+}
+
} // namespace art