Convert Class::descriptor_ from StringPiece to String (as part of image loading)
Change-Id: Iab5ffa353661a7c06ee79af1f40d399a53777174
diff --git a/src/class_linker.cc b/src/class_linker.cc
index 448a542..55aaff4 100644
--- a/src/class_linker.cc
+++ b/src/class_linker.cc
@@ -32,7 +32,7 @@
// java_lang_Class comes first, its needed for AllocClass
Class* java_lang_Class = down_cast<Class*>(Heap::AllocObject(NULL, sizeof(Class)));
CHECK(java_lang_Class != NULL);
- java_lang_Class->descriptor_ = "Ljava/lang/Class;";
+ // java_lang_Class->descriptor_ = "Ljava/lang/Class;"; // XXX bdc can these be created later?
java_lang_Class->object_size_ = sizeof(Class);
java_lang_Class->klass_ = java_lang_Class;
// AllocClass(Class*) can now be used
@@ -40,7 +40,7 @@
// java_lang_Object comes next so that object_array_class can be created
Class* java_lang_Object = AllocClass(java_lang_Class);
CHECK(java_lang_Object != NULL);
- java_lang_Object->descriptor_ = "Ljava/lang/Object;";
+ // java_lang_Object->descriptor_ = "Ljava/lang/Object;"; // XXX bdc can these be created later?
// backfill Object as the super class of Class
java_lang_Class->super_class_ = java_lang_Object;
// mark as non-primitive for object_array_class
@@ -49,38 +49,47 @@
// object_array_class is for root_classes to provide the storage for these classes
Class* object_array_class = AllocClass(java_lang_Class);
CHECK(object_array_class != NULL);
- object_array_class->descriptor_ = "[Ljava/lang/Object;";
+ // object_array_class->descriptor_ = "[Ljava/lang/Object;"; // XXX bdc can these be created later?
object_array_class->component_type_ = java_lang_Object;
// String and char[] are necessary so that FindClass can assign names to members
Class* java_lang_String = AllocClass(java_lang_Class);
CHECK(java_lang_String != NULL);
- java_lang_String->descriptor_ = "Ljava/lang/String;";
+ // java_lang_String->descriptor_ = "Ljava/lang/String;"; // XXX can these be created later?
CHECK_LT(java_lang_String->object_size_, sizeof(String));
java_lang_String->object_size_ = sizeof(String);
+ String::InitClass(java_lang_String);
Class* char_array_class = AllocClass(java_lang_Class);
CHECK(char_array_class != NULL);
- char_array_class->descriptor_ = "[C";
+ // char_array_class->descriptor_ = "[C"; // XXX can these be created later?
CharArray::SetArrayClass(char_array_class);
+ // Now String::Alloc* can be used
+
+ // backfill Class descriptors missing until this point
+ java_lang_Class->descriptor_ = String::AllocFromModifiedUtf8("Ljava/lang/Class;");
+ java_lang_Object->descriptor_ = String::AllocFromModifiedUtf8("Ljava/lang/Object;");
+ object_array_class->descriptor_ = String::AllocFromModifiedUtf8("[Ljava/lang/Object;");
+ java_lang_String->descriptor_ = String::AllocFromModifiedUtf8("Ljava/lang/String;");
+ char_array_class->descriptor_ = String::AllocFromModifiedUtf8("[C");
// int[] and long[] are used for static field storage
Class* int_array_class = AllocClass(java_lang_Class);
CHECK(int_array_class != NULL);
- int_array_class->descriptor_ = "[I";
+ int_array_class->descriptor_ = String::AllocFromModifiedUtf8("[I");
IntArray::SetArrayClass(int_array_class);
Class* long_array_class = AllocClass(java_lang_Class);
CHECK(long_array_class != NULL);
- long_array_class->descriptor_ = "[J";
+ long_array_class->descriptor_ = String::AllocFromModifiedUtf8("[J");
LongArray::SetArrayClass(long_array_class);
// Field and Method are necessary so that FindClass can link members
Class* java_lang_reflect_Field = AllocClass(java_lang_Class);
CHECK(java_lang_reflect_Field != NULL);
- java_lang_reflect_Field->descriptor_ = "Ljava/lang/reflect/Field;";
+ java_lang_reflect_Field->descriptor_ = String::AllocFromModifiedUtf8("Ljava/lang/reflect/Field;");
CHECK_LT(java_lang_reflect_Field->object_size_, sizeof(Field));
java_lang_reflect_Field->object_size_ = sizeof(Field);
Class* java_lang_reflect_Method = AllocClass(java_lang_Class);
- java_lang_reflect_Method->descriptor_ = "Ljava/lang/reflect/Method;";
+ java_lang_reflect_Method->descriptor_ = String::AllocFromModifiedUtf8("Ljava/lang/reflect/Method;");
CHECK(java_lang_reflect_Method != NULL);
CHECK_LT(java_lang_reflect_Method->object_size_, sizeof(Method));
java_lang_reflect_Method->object_size_ = sizeof(Method);
@@ -98,9 +107,6 @@
class_roots_->Set(kJavaLangReflectMethod, java_lang_reflect_Method);
// now that these are registered, we can use AllocClass() and AllocObjectArray
- String::InitClasses(java_lang_String);
- // Now AllocString* can be used
-
// setup boot_class_path_ now that we can use AllocObjectArray to
// create DexCache instances
for (size_t i = 0; i != boot_class_path.size(); ++i) {
@@ -111,24 +117,24 @@
// run Class, Field, and Method through FindSystemClass.
// this initializes their dex_cache_ fields and register them in classes_.
// we also override their object_size_ values to accommodate the extra C++ fields.
- Class* Class_class = FindSystemClass(java_lang_Class->GetDescriptor());
+ Class* Class_class = FindSystemClass("Ljava/lang/Class;");
CHECK_EQ(java_lang_Class, Class_class);
CHECK_LT(java_lang_Class->object_size_, sizeof(Class));
java_lang_Class->object_size_ = sizeof(Class);
- Class* Field_class = FindSystemClass(java_lang_reflect_Field->GetDescriptor());
+ Class* Field_class = FindSystemClass("Ljava/lang/reflect/Field;");
CHECK_EQ(java_lang_reflect_Field, Field_class);
CHECK_LT(java_lang_reflect_Field->object_size_, sizeof(Field));
java_lang_reflect_Field->object_size_ = sizeof(Field);
- Class* Method_class = FindSystemClass(java_lang_reflect_Method->GetDescriptor());
+ Class* Method_class = FindSystemClass("Ljava/lang/reflect/Method;");
CHECK_EQ(java_lang_reflect_Method, Method_class);
CHECK_LT(java_lang_reflect_Method->object_size_, sizeof(Method));
java_lang_reflect_Method->object_size_ = sizeof(Method);
// Object and String just need more minimal setup, since they do not have extra C++ fields.
- Class* Object_class = FindSystemClass(java_lang_Object->GetDescriptor());
+ Class* Object_class = FindSystemClass("Ljava/lang/Object;");
CHECK_EQ(java_lang_Object, Object_class);
CHECK_EQ(java_lang_Object->object_size_, sizeof(Object));
- Class* String_class = FindSystemClass(java_lang_String->GetDescriptor());
+ Class* String_class = FindSystemClass("Ljava/lang/String;");
CHECK_EQ(java_lang_String, String_class);
CHECK_EQ(java_lang_String->object_size_, sizeof(String));
@@ -323,7 +329,7 @@
ObjectLock lock(klass);
klass->clinit_thread_id_ = self->GetId();
// Add the newly loaded class to the loaded classes table.
- bool success = InsertClass(klass); // TODO: just return collision
+ bool success = InsertClass(descriptor, klass); // TODO: just return collision
if (!success) {
// We may fail to insert if we raced with another thread.
klass->clinit_thread_id_ = 0;
@@ -387,8 +393,7 @@
CHECK(descriptor != NULL);
klass->klass_ = GetClassRoot(kJavaLangClass);
- klass->descriptor_.set(descriptor);
- klass->descriptor_alloc_ = NULL;
+ klass->descriptor_ = String::AllocFromModifiedUtf8(descriptor);
klass->access_flags_ = dex_class_def.access_flags_;
klass->class_loader_ = class_loader;
klass->primitive_type_ = Class::kPrimNot;
@@ -508,7 +513,7 @@
int32_t utf16_length;
scoped_array<char> utf8(dex_file.CreateMethodDescriptor(method_id.proto_idx_,
&utf16_length));
- dst->descriptor_ = String::AllocFromModifiedUtf8(utf16_length, utf8.get());
+ dst->signature_ = String::AllocFromModifiedUtf8(utf16_length, utf8.get());
}
dst->proto_idx_ = method_id.proto_idx_;
dst->code_off_ = src.code_off_;
@@ -570,15 +575,14 @@
return NULL;
}
-Class* ClassLinker::CreatePrimitiveClass(const StringPiece& descriptor) {
+Class* ClassLinker::CreatePrimitiveClass(const char* descriptor) {
Class* klass = AllocClass();
CHECK(klass != NULL);
klass->super_class_ = NULL;
klass->access_flags_ = kAccPublic | kAccFinal | kAccAbstract;
- klass->descriptor_ = descriptor;
- klass->descriptor_alloc_ = NULL;
+ klass->descriptor_ = String::AllocFromModifiedUtf8(descriptor);
klass->status_ = Class::kStatusInitialized;
- bool success = InsertClass(klass);
+ bool success = InsertClass(descriptor, klass);
CHECK(success) << "CreatePrimitiveClass(" << descriptor << ") failed";
return klass;
}
@@ -683,10 +687,7 @@
return NULL;
}
}
- new_class->descriptor_alloc_ = new std::string(descriptor.data(),
- descriptor.size());
- new_class->descriptor_.set(new_class->descriptor_alloc_->data(),
- new_class->descriptor_alloc_->size());
+ new_class->descriptor_ = String::AllocFromModifiedUtf8(descriptor.ToString().c_str());
Class* java_lang_Object = GetClassRoot(kJavaLangObject);
new_class->super_class_ = java_lang_Object;
new_class->vtable_ = java_lang_Object->vtable_;
@@ -696,6 +697,7 @@
new_class->array_rank_ = array_rank;
new_class->status_ = Class::kStatusInitialized;
// don't need to set new_class->object_size_
+ // because Object::SizeOf delegates to Array::SizeOf
// All arrays have java/lang/Cloneable and java/io/Serializable as
@@ -726,7 +728,7 @@
new_class->access_flags_ = ((new_class->component_type_->access_flags_ &
~kAccInterface) | kAccFinal) & kAccJavaFlagsMask;
- if (InsertClass(new_class)) {
+ if (InsertClass(descriptor, new_class)) {
return new_class;
}
// Another thread must have loaded the class after we
@@ -770,19 +772,20 @@
return NULL; // Not reachable.
}
-bool ClassLinker::InsertClass(Class* klass) {
+bool ClassLinker::InsertClass(const StringPiece& descriptor, Class* klass) {
+ size_t hash = StringPieceHash()(descriptor);
MutexLock mu(classes_lock_);
- const StringPiece& key = klass->GetDescriptor();
- Table::iterator it = classes_.insert(std::make_pair(key, klass));
+ Table::iterator it = classes_.insert(std::make_pair(hash, klass));
return ((*it).second == klass);
}
Class* ClassLinker::LookupClass(const StringPiece& descriptor, ClassLoader* class_loader) {
+ size_t hash = StringPieceHash()(descriptor);
MutexLock mu(classes_lock_);
typedef Table::const_iterator It; // TODO: C++0x auto
- for (It it = classes_.find(descriptor), end = classes_.end(); it != end; ++it) {
+ for (It it = classes_.find(hash), end = classes_.end(); it != end; ++it) {
Class* klass = it->second;
- if (klass->descriptor_ == descriptor && klass->class_loader_ == class_loader) {
+ if (klass->descriptor_->Equals(descriptor) && klass->class_loader_ == class_loader) {
return klass;
}
}
@@ -974,7 +977,6 @@
CHECK(descriptor != NULL);
CHECK(klass1 != NULL);
CHECK(klass2 != NULL);
-#if 0
Class* found1 = FindClass(descriptor, klass1->GetClassLoader());
// TODO: found1 == NULL
Class* found2 = FindClass(descriptor, klass2->GetClassLoader());
@@ -988,7 +990,6 @@
return false;
}
}
-#endif
return true;
}
@@ -1033,7 +1034,7 @@
if (dex_cache == NULL) {
return;
}
- const StringPiece& descriptor = klass->GetDescriptor();
+ const std::string descriptor(klass->GetDescriptor()->ToModifiedUtf8());
const DexFile& dex_file = FindDexFile(dex_cache);
const DexFile::ClassDef* dex_class_def = dex_file.FindClassDef(descriptor);
CHECK(dex_class_def != NULL);
@@ -1140,7 +1141,7 @@
bool ClassLinker::LinkSuperClass(Class* klass) {
CHECK(!klass->IsPrimitive());
const Class* super = klass->GetSuperClass();
- if (klass->GetDescriptor() == "Ljava/lang/Object;") {
+ if (klass->GetDescriptor()->Equals("Ljava/lang/Object;")) {
if (super != NULL) {
LG << "Superclass must not be defined"; // TODO: ClassFormatError
return false;
@@ -1154,15 +1155,15 @@
}
// Verify
if (super->IsFinal()) {
- LG << "Superclass " << super->descriptor_ << " is declared final"; // TODO: IncompatibleClassChangeError
+ LG << "Superclass " << super->descriptor_->ToModifiedUtf8() << " is declared final"; // TODO: IncompatibleClassChangeError
return false;
}
if (super->IsInterface()) {
- LG << "Superclass " << super->descriptor_ << " is an interface"; // TODO: IncompatibleClassChangeError
+ LG << "Superclass " << super->descriptor_->ToModifiedUtf8() << " is an interface"; // TODO: IncompatibleClassChangeError
return false;
}
if (!klass->CanAccess(super)) {
- LG << "Superclass " << super->descriptor_ << " is inaccessible"; // TODO: IllegalAccessError
+ LG << "Superclass " << super->descriptor_->ToModifiedUtf8() << " is inaccessible"; // TODO: IllegalAccessError
return false;
}
return true;
@@ -1234,9 +1235,8 @@
klass->vtable_ = klass->vtable_->CopyOf(actual_count);
}
} else {
- CHECK(klass->GetDescriptor() == "Ljava/lang/Object;");
+ CHECK(klass->GetDescriptor()->Equals("Ljava/lang/Object;"));
uint32_t num_virtual_methods = klass->NumVirtualMethods();
- CHECK(klass->GetDescriptor() == "Ljava/lang/Object;");
if (!IsUint(16, num_virtual_methods)) {
LG << "Too many methods"; // TODO: VirtualMachineError
return false;