Setting klass_ fields of heap allocated objects
Change-Id: Ib1ab43254430497cce0660156394eebddd2cc445
diff --git a/src/class_linker.cc b/src/class_linker.cc
index 15c2e40..19f2f93 100644
--- a/src/class_linker.cc
+++ b/src/class_linker.cc
@@ -27,12 +27,23 @@
}
void ClassLinker::Init() {
- // Allocate and partially initialize the Object and Class classes.
+ // Allocate and partially initialize the Class, Object, Field, Method classes.
// Initialization will be completed when the definitions are loaded.
- java_lang_Object_ = Heap::AllocClass(NULL);
- java_lang_Object_->descriptor_ = "Ljava/lang/Object;";
- java_lang_Class_ = Heap::AllocClass(NULL);
+ java_lang_Class_ = reinterpret_cast<Class*>(Heap::AllocRaw(sizeof(Class), NULL));
java_lang_Class_->descriptor_ = "Ljava/lang/Class;";
+ java_lang_Class_->object_size_ = sizeof(Class);
+ java_lang_Class_->klass_ = java_lang_Class_;
+
+ java_lang_Object_ = AllocClass(NULL);
+ java_lang_Object_->descriptor_ = "Ljava/lang/Object;";
+
+ java_lang_Class_->super_class_ = java_lang_Object_;
+
+ java_lang_ref_Field_ = AllocClass(NULL);
+ java_lang_ref_Field_->descriptor_ = "Ljava/lang/ref/Field;";
+
+ java_lang_ref_Method_ = AllocClass(NULL);
+ java_lang_ref_Method_->descriptor_ = "Ljava/lang/Method;";
// Allocate and initialize the primitive type classes.
primitive_byte_ = CreatePrimitiveClass(kTypeByte, "B");
@@ -44,6 +55,32 @@
primitive_short_ = CreatePrimitiveClass(kTypeShort, "S");
primitive_boolean_ = CreatePrimitiveClass(kTypeBoolean, "Z");
primitive_void_ = CreatePrimitiveClass(kTypeVoid, "V");
+
+ char_array_class_ = AllocClass(NULL);
+ char_array_class_->descriptor_ = "[C";
+ char_array_class_->status_ = Class::kStatusInitialized;
+ char_array_class_->component_type_ = primitive_char_;
+ char_array_class_->array_rank_ = 1;
+ char_array_class_->primitive_type_ = Class::kPrimNot;
+ char_array_class_->super_class_ = java_lang_Object_;
+}
+
+Class* ClassLinker::AllocClass(DexFile* dex_file) {
+ Class* klass = reinterpret_cast<Class*>(Heap::AllocObject(java_lang_Class_));
+ klass->dex_file_ = dex_file;
+ return klass;
+}
+
+StaticField* ClassLinker::AllocStaticField() {
+ return reinterpret_cast<StaticField*>(Heap::AllocRaw(sizeof(StaticField), java_lang_ref_Field_));
+}
+
+InstanceField* ClassLinker::AllocInstanceField() {
+ return reinterpret_cast<InstanceField*>(Heap::AllocRaw(sizeof(InstanceField), java_lang_ref_Field_));
+}
+
+Method* ClassLinker::AllocMethod() {
+ return reinterpret_cast<Method*>(Heap::AllocRaw(sizeof(Method), java_lang_ref_Method_));
}
Class* ClassLinker::FindClass(const char* descriptor,
@@ -55,25 +92,52 @@
Class* klass = LookupClass(descriptor, class_loader);
if (klass == NULL) {
// Class is not yet loaded.
+ const RawDexFile::ClassDef* class_def;
if (dex_file == NULL) {
// No .dex file specified, search the class path.
- dex_file = FindInClassPath(descriptor);
- if (dex_file == NULL) {
+ ClassPathEntry pair = FindInClassPath(descriptor);
+ if (pair.first == NULL) {
LG << "Class " << descriptor << " really not found";
return NULL;
}
+ dex_file = pair.first;
+ class_def = pair.second;
+ } else {
+ class_def = dex_file->GetRaw()->FindClassDef(descriptor);
}
// Load the class from the dex file.
if (!strcmp(descriptor, "Ljava/lang/Object;")) {
klass = java_lang_Object_;
klass->dex_file_ = dex_file;
+ klass->object_size_ = sizeof(Object);
+ if (class_def != NULL) {
+ char_array_class_->super_class_idx_ = class_def->class_idx_;
+ }
} else if (!strcmp(descriptor, "Ljava/lang/Class;")) {
klass = java_lang_Class_;
klass->dex_file_ = dex_file;
+ klass->object_size_ = sizeof(Class);
+ } else if (!strcmp(descriptor, "Ljava/lang/ref/Field;")) {
+ klass = java_lang_ref_Field_;
+ klass->dex_file_ = dex_file;
+ klass->object_size_ = sizeof(Field);
+ } else if (!strcmp(descriptor, "Ljava/lang/ref/Method;")) {
+ klass = java_lang_ref_Method_;
+ klass->dex_file_ = dex_file;
+ klass->object_size_ = sizeof(Method);
+ } else if (!strcmp(descriptor, "Ljava/lang/String;")) {
+ klass = java_lang_String_;
+ klass->dex_file_ = dex_file;
+ klass->object_size_ = sizeof(String);
} else {
- klass = Heap::AllocClass(dex_file);
+ klass = AllocClass(dex_file);
}
- bool is_loaded = LoadClass(descriptor, klass);
+ bool is_loaded;
+ if (class_def == NULL) {
+ is_loaded = false;
+ } else {
+ is_loaded = LoadClass(*class_def, klass);
+ }
if (!is_loaded) {
// TODO: this occurs only when a dex file is provided.
LG << "Class not found"; // TODO: NoClassDefFoundError
@@ -177,7 +241,7 @@
for (size_t i = 0; i < klass->num_sfields_; ++i) {
RawDexFile::Field raw_field;
raw->dexReadClassDataField(&class_data, &raw_field, &last_idx);
- StaticField* sfield = Heap::AllocStaticField();
+ StaticField* sfield = AllocStaticField();
klass->sfields_[i] = sfield;
LoadField(klass, raw_field, sfield);
}
@@ -191,7 +255,7 @@
for (size_t i = 0; i < klass->NumInstanceFields(); ++i) {
RawDexFile::Field raw_field;
raw->dexReadClassDataField(&class_data, &raw_field, &last_idx);
- InstanceField* ifield = Heap::AllocInstanceField();
+ InstanceField* ifield = AllocInstanceField();
klass->ifields_[i] = ifield;
LoadField(klass, raw_field, ifield);
}
@@ -205,7 +269,7 @@
for (size_t i = 0; i < klass->NumDirectMethods(); ++i) {
RawDexFile::Method raw_method;
raw->dexReadClassDataMethod(&class_data, &raw_method, &last_idx);
- Method* meth = Heap::AllocMethod();
+ Method* meth = AllocMethod();
klass->direct_methods_[i] = meth;
LoadMethod(klass, raw_method, meth);
// TODO: register maps
@@ -220,14 +284,13 @@
for (size_t i = 0; i < klass->NumVirtualMethods(); ++i) {
RawDexFile::Method raw_method;
raw->dexReadClassDataMethod(&class_data, &raw_method, &last_idx);
- Method* meth = Heap::AllocMethod();
+ Method* meth = AllocMethod();
klass->virtual_methods_[i] = meth;
LoadMethod(klass, raw_method, meth);
// TODO: register maps
}
}
-
- return klass;
+ return true;
}
void ClassLinker::LoadInterfaces(const RawDexFile::ClassDef& class_def,
@@ -283,14 +346,15 @@
}
}
-DexFile* ClassLinker::FindInClassPath(const char* descriptor) {
+ClassLinker::ClassPathEntry ClassLinker::FindInClassPath(const char* descriptor) {
for (size_t i = 0; i != class_path_.size(); ++i) {
DexFile* dex_file = class_path_[i];
- if (dex_file->HasClass(descriptor)) {
- return dex_file;
+ const RawDexFile::ClassDef* class_def = dex_file->GetRaw()->FindClassDef(descriptor);
+ if (class_def != NULL) {
+ return ClassPathEntry(dex_file, class_def);
}
}
- return NULL;
+ return ClassPathEntry(NULL, NULL);
}
void ClassLinker::AppendToClassPath(DexFile* dex_file) {
@@ -298,9 +362,9 @@
}
Class* ClassLinker::CreatePrimitiveClass(JType type, const char* descriptor) {
- Class* klass = Heap::AllocClass(NULL);
+ Class* klass = AllocClass(NULL);
CHECK(klass != NULL);
- klass->super_class_ = java_lang_Class_;
+ klass->super_class_ = NULL;
klass->access_flags_ = kAccPublic | kAccFinal | kAccAbstract;
klass->descriptor_ = descriptor;
klass->status_ = Class::kStatusInitialized;
@@ -946,7 +1010,7 @@
klass->vtable_count_ += miranda_count;
for (int i = 0; i < miranda_count; i++) {
- Method* meth = Heap::AllocMethod();
+ Method* meth = AllocMethod();
memcpy(meth, miranda_list[i], sizeof(Method));
meth->klass_ = klass;
meth->access_flags_ |= kAccMiranda;
@@ -968,11 +1032,11 @@
}
bool ClassLinker::LinkInstanceFields(Class* klass) {
- int fieldOffset;
+ int field_offset;
if (klass->GetSuperClass() != NULL) {
- fieldOffset = klass->GetSuperClass()->object_size_;
+ field_offset = klass->GetSuperClass()->object_size_;
} else {
- fieldOffset = OFFSETOF_MEMBER(DataObject, fields_);
+ field_offset = OFFSETOF_MEMBER(DataObject, fields_);
}
// Move references to the front.
klass->num_reference_ifields_ = 0;
@@ -1000,22 +1064,22 @@
if (c != '[' && c != 'L') {
break;
}
- pField->SetOffset(fieldOffset);
- fieldOffset += sizeof(uint32_t);
+ pField->SetOffset(field_offset);
+ field_offset += sizeof(uint32_t);
}
// Now we want to pack all of the double-wide fields together. If
// we're not aligned, though, we want to shuffle one 32-bit field
// into place. If we can't find one, we'll have to pad it.
- if (i != klass->NumInstanceFields() && (fieldOffset & 0x04) != 0) {
+ if (i != klass->NumInstanceFields() && (field_offset & 0x04) != 0) {
InstanceField* pField = klass->GetInstanceField(i);
char c = pField->GetType();
if (c != 'J' && c != 'D') {
// The field that comes next is 32-bit, so just advance past it.
assert(c != '[' && c != 'L');
- pField->SetOffset(fieldOffset);
- fieldOffset += sizeof(uint32_t);
+ pField->SetOffset(field_offset);
+ field_offset += sizeof(uint32_t);
i++;
} else {
// Next field is 64-bit, so search for a 32-bit field we can
@@ -1028,22 +1092,22 @@
klass->SetInstanceField(i, singleField);
klass->SetInstanceField(j, pField);
pField = singleField;
- pField->SetOffset(fieldOffset);
- fieldOffset += sizeof(uint32_t);
+ pField->SetOffset(field_offset);
+ field_offset += sizeof(uint32_t);
found = true;
i++;
break;
}
}
if (!found) {
- fieldOffset += sizeof(uint32_t);
+ field_offset += sizeof(uint32_t);
}
}
}
// Alignment is good, shuffle any double-wide fields forward, and
// finish assigning field offsets to all fields.
- assert(i == klass->NumInstanceFields() || (fieldOffset & 0x04) == 0);
+ assert(i == klass->NumInstanceFields() || (field_offset & 0x04) == 0);
for ( ; i < klass->NumInstanceFields(); i++) {
InstanceField* pField = klass->GetInstanceField(i);
char c = pField->GetType();
@@ -1063,10 +1127,10 @@
// This is a double-wide field, leave it be.
}
- pField->SetOffset(fieldOffset);
- fieldOffset += sizeof(uint32_t);
+ pField->SetOffset(field_offset);
+ field_offset += sizeof(uint32_t);
if (c == 'J' || c == 'D')
- fieldOffset += sizeof(uint32_t);
+ field_offset += sizeof(uint32_t);
}
#ifndef NDEBUG
@@ -1096,7 +1160,7 @@
}
#endif
- klass->object_size_ = fieldOffset;
+ klass->object_size_ = field_offset;
return true;
}
@@ -1170,7 +1234,7 @@
const RawDexFile* raw = referring->GetDexFile()->GetRaw();
const RawDexFile::StringId& string_id = raw->GetStringId(string_idx);
const char* string_data = raw->GetStringData(string_id);
- String* new_string = Heap::AllocStringFromModifiedUtf8(string_data);
+ String* new_string = Heap::AllocStringFromModifiedUtf8(java_lang_String_, char_array_class_, string_data);
// TODO: intern the new string
referring->GetDexFile()->SetResolvedString(new_string, string_idx);
return new_string;
diff --git a/src/class_linker.h b/src/class_linker.h
index 00271a5..e4c5ff9 100644
--- a/src/class_linker.h
+++ b/src/class_linker.h
@@ -20,6 +20,11 @@
~ClassLinker() {}
+ Class* AllocClass(DexFile* dex_file);
+ StaticField* AllocStaticField();
+ InstanceField* AllocInstanceField();
+ Method* AllocMethod();
+
// Finds a class by its descriptor name.
Class* FindClass(const char* descriptor,
Object* class_loader,
@@ -43,7 +48,9 @@
String* ResolveString(const Class* referring, uint32_t string_idx);
- DexFile* FindInClassPath(const char* descriptor);
+ typedef std::pair<DexFile*, const RawDexFile::ClassDef*> ClassPathEntry;
+
+ ClassPathEntry FindInClassPath(const char* descriptor);
void AppendToClassPath(DexFile* dex_file);
@@ -117,8 +124,12 @@
Class* primitive_long_;
Class* primitive_void_;
- Class* java_lang_Object_;
Class* java_lang_Class_;
+ Class* java_lang_Object_;
+ Class* java_lang_ref_Field_;
+ Class* java_lang_ref_Method_;
+ Class* java_lang_String_;
+ Class* char_array_class_;
DISALLOW_COPY_AND_ASSIGN(ClassLinker);
};
diff --git a/src/class_linker_test.cc b/src/class_linker_test.cc
index d755e3e..bbe6ebc 100644
--- a/src/class_linker_test.cc
+++ b/src/class_linker_test.cc
@@ -15,7 +15,7 @@
scoped_ptr<ClassLinker> linker(ClassLinker::Create());
linker->AppendToClassPath(dex.get());
- scoped_ptr<Class> klass(Heap::AllocClass(dex.get()));
+ scoped_ptr<Class> klass(linker.get()->AllocClass(dex.get()));
bool result1 = linker->LoadClass("NoSuchClass", klass.get());
EXPECT_FALSE(result1);
bool result2 = linker->LoadClass("LNoSuchClass;", klass.get());
@@ -29,7 +29,7 @@
scoped_ptr<ClassLinker> linker(ClassLinker::Create());
linker->AppendToClassPath(dex.get());
- scoped_ptr<Class> klass(Heap::AllocClass(dex.get()));
+ scoped_ptr<Class> klass(linker.get()->AllocClass(dex.get()));
bool result = linker->LoadClass("LNested;", klass.get());
ASSERT_TRUE(result);
@@ -52,7 +52,9 @@
Class* JavaLangObject = linker->FindClass("Ljava/lang/Object;", NULL, dex.get());
ASSERT_TRUE(JavaLangObject != NULL);
- EXPECT_TRUE(JavaLangObject->GetClass() != NULL);
+ ASSERT_TRUE(JavaLangObject->GetClass() != NULL);
+ ASSERT_EQ(JavaLangObject->GetClass(), JavaLangObject->GetClass()->GetClass());
+ EXPECT_EQ(JavaLangObject->GetClass()->GetSuperClass(), JavaLangObject);
ASSERT_TRUE(JavaLangObject->GetDescriptor() == "Ljava/lang/Object;");
EXPECT_TRUE(JavaLangObject->GetSuperClass() == NULL);
EXPECT_FALSE(JavaLangObject->HasSuperClass());
@@ -72,7 +74,9 @@
Class* MyClass = linker->FindClass("LMyClass;", NULL, dex.get());
ASSERT_TRUE(MyClass != NULL);
- EXPECT_TRUE(MyClass->GetClass() != NULL);
+ ASSERT_TRUE(MyClass->GetClass() != NULL);
+ ASSERT_EQ(MyClass->GetClass(), MyClass->GetClass()->GetClass());
+ EXPECT_EQ(MyClass->GetClass()->GetSuperClass(), JavaLangObject);
ASSERT_TRUE(MyClass->GetDescriptor() == "LMyClass;");
EXPECT_TRUE(MyClass->GetSuperClass() == JavaLangObject);
EXPECT_TRUE(MyClass->HasSuperClass());
@@ -90,6 +94,9 @@
EXPECT_EQ(0U, MyClass->NumVirtualMethods());
EXPECT_EQ(0U, MyClass->NumInstanceFields());
EXPECT_EQ(0U, MyClass->NumStaticFields());
+
+ EXPECT_EQ(JavaLangObject->GetClass()->GetClass(), MyClass->GetClass()->GetClass());
+
}
} // namespace art
diff --git a/src/heap.h b/src/heap.h
index b9f7937..f7ae5a5 100644
--- a/src/heap.h
+++ b/src/heap.h
@@ -19,47 +19,30 @@
~Heap() {}
- static Class* AllocClass(DexFile* dex_file) {
- byte* raw = new byte[sizeof(Class)]();
- Class* klass = reinterpret_cast<Class*>(raw);
- klass->dex_file_ = dex_file;
- return klass;
- }
-
- static StaticField* AllocStaticField() {
- size_t size = sizeof(StaticField);
+ static Object* AllocRaw(size_t size, Class* klass) {
byte* raw = new byte[size]();
- return reinterpret_cast<StaticField*>(raw);
+ Object* object = reinterpret_cast<Object*>(raw);
+ object->klass_ = klass;
+ return object;
}
- static InstanceField* AllocInstanceField() {
- size_t size = sizeof(InstanceField);
- byte* raw = new byte[size]();
- return reinterpret_cast<InstanceField*>(raw);
+ static Object* AllocObject(Class* klass) {
+ return AllocRaw(klass->object_size_, klass);
}
- static Method* AllocMethod() {
- size_t size = sizeof(Method);
- byte* raw = new byte[size]();
- return reinterpret_cast<Method*>(raw);
- }
-
- static CharArray* AllocCharArray(size_t length) {
+ static CharArray* AllocCharArray(Class* char_array, size_t length) {
size_t size = sizeof(Array) + length * sizeof(uint16_t);
- byte* raw = new byte[size]();
- return reinterpret_cast<CharArray*>(raw);
+ return reinterpret_cast<CharArray*>(AllocRaw(size, char_array));
}
- static String* AllocString() {
- size_t size = sizeof(String);
- byte* raw = new byte[size]();
- return reinterpret_cast<String*>(raw);
+ static String* AllocString(Class* java_lang_String) {
+ return reinterpret_cast<String*>(AllocObject(java_lang_String));
}
- static String* AllocStringFromModifiedUtf8(const char* data) {
- String* string = AllocString();
+ static String* AllocStringFromModifiedUtf8(Class* java_lang_String, Class* char_array, const char* data) {
+ String* string = AllocString(java_lang_String);
uint32_t count = strlen(data); // TODO
- CharArray* array = AllocCharArray(count);
+ CharArray* array = AllocCharArray(char_array, count);
string->array_ = array;
string->count_ = count;
return string;
diff --git a/src/object.h b/src/object.h
index d7df9dc..cd57460 100644
--- a/src/object.h
+++ b/src/object.h
@@ -190,8 +190,8 @@
class Field : public Object {
public:
- Class* GetClass() const {
- return klass_;
+ Class* GetDeclaringClass() const {
+ return declaring_class_;
}
const char* GetName() const {
@@ -219,7 +219,7 @@
#undef FIELD_FIELD_SLOTS
// The class in which this field is declared.
- Class* klass_;
+ Class* declaring_class_;
const char* name_;
@@ -315,12 +315,12 @@
return name_;
}
- Class* GetClass() const {
- return klass_;
+ Class* GetDeclaringClass() const {
+ return declaring_class_;
}
// const char* GetReturnTypeDescriptor() const {
- // return klass_->GetDexFile_->GetRaw()->dexStringByTypeIdx(proto_id_.return_type_id_);
+ // return declaring_class_->GetDexFile_->GetRaw()->dexStringByTypeIdx(proto_id_.return_type_id_);
// }
// Returns true if the method is declared public.
@@ -400,7 +400,7 @@
#undef METHOD_FIELD_SLOTS
// the class we are a part of
- Class* klass_;
+ Class* declaring_class_;
// access flags; low 16 bits are defined by spec (could be uint16_t?)
uint32_t access_flags_;
diff --git a/src/object_test.cc b/src/object_test.cc
index c49c4fd..b00e123 100644
--- a/src/object_test.cc
+++ b/src/object_test.cc
@@ -36,7 +36,7 @@
scoped_ptr<ClassLinker> linker(ClassLinker::Create());
linker->AppendToClassPath(dex_file.get());
- scoped_ptr<Class> klass(Heap::AllocClass(dex_file.get()));
+ scoped_ptr<Class> klass(linker.get()->AllocClass(dex_file.get()));
bool result = linker->LoadClass("LProtoCompare;", klass.get());
ASSERT_TRUE(result);
@@ -95,10 +95,10 @@
scoped_ptr<ClassLinker> linker2(ClassLinker::Create());
linker2->AppendToClassPath(dex_file2.get());
- scoped_ptr<Class> klass1(Heap::AllocClass(dex_file1.get()));
+ scoped_ptr<Class> klass1(linker1.get()->AllocClass(dex_file1.get()));
bool result1 = linker1->LoadClass("LProtoCompare;", klass1.get());
ASSERT_TRUE(result1);
- scoped_ptr<Class> klass2(Heap::AllocClass(dex_file2.get()));
+ scoped_ptr<Class> klass2(linker2.get()->AllocClass(dex_file2.get()));
bool result2 = linker2->LoadClass("LProtoCompare2;", klass2.get());
ASSERT_TRUE(result2);