Move static field storage to end of Class instance
Change-Id: I90061999c9eef9d900e4269508b983a61f48b264
diff --git a/src/class_linker.cc b/src/class_linker.cc
index 6379113..92cf4de 100644
--- a/src/class_linker.cc
+++ b/src/class_linker.cc
@@ -65,14 +65,14 @@
CHECK(!init_done_);
// java_lang_Class comes first, its needed for AllocClass
- Class* java_lang_Class = down_cast<Class*>(Heap::AllocObject(NULL, sizeof(Class)));
+ Class* java_lang_Class = down_cast<Class*>(Heap::AllocObject(NULL, sizeof(ClassClass)));
CHECK(java_lang_Class != NULL);
- java_lang_Class->object_size_ = sizeof(Class);
+ java_lang_Class->class_size_ = sizeof(ClassClass);
java_lang_Class->klass_ = java_lang_Class;
// AllocClass(Class*) can now be used
// java_lang_Object comes next so that object_array_class can be created
- Class* java_lang_Object = AllocClass(java_lang_Class);
+ Class* java_lang_Object = AllocClass(java_lang_Class, sizeof(Class));
CHECK(java_lang_Object != NULL);
// backfill Object as the super class of Class
java_lang_Class->super_class_ = java_lang_Object;
@@ -80,17 +80,17 @@
java_lang_Object->primitive_type_ = Class::kPrimNot;
// object_array_class is for root_classes to provide the storage for these classes
- Class* object_array_class = AllocClass(java_lang_Class);
+ Class* object_array_class = AllocClass(java_lang_Class, sizeof(Class));
CHECK(object_array_class != NULL);
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);
+ Class* java_lang_String = AllocClass(java_lang_Class, sizeof(StringClass));
CHECK(java_lang_String != NULL);
CHECK_LT(java_lang_String->object_size_, sizeof(String));
java_lang_String->object_size_ = sizeof(String);
String::SetClass(java_lang_String);
- Class* char_array_class = AllocClass(java_lang_Class);
+ Class* char_array_class = AllocClass(java_lang_Class, sizeof(Class));
CHECK(char_array_class != NULL);
CharArray::SetArrayClass(char_array_class);
// Now String::Alloc* can be used
@@ -102,23 +102,13 @@
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_ = 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_ = 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);
+ Class* java_lang_reflect_Field = AllocClass(java_lang_Class, sizeof(FieldClass));
CHECK(java_lang_reflect_Field != NULL);
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);
+ Class* java_lang_reflect_Method = AllocClass(java_lang_Class, sizeof(MethodClass));
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));
@@ -131,8 +121,6 @@
SetClassRoot(kObjectArrayClass, object_array_class);
SetClassRoot(kJavaLangString, java_lang_String);
SetClassRoot(kCharArrayClass, char_array_class);
- SetClassRoot(kIntArrayClass, int_array_class);
- SetClassRoot(kLongArrayClass, long_array_class);
SetClassRoot(kJavaLangReflectField, java_lang_reflect_Field);
SetClassRoot(kJavaLangReflectMethod, java_lang_reflect_Method);
// now that these are registered, we can use AllocClass() and AllocObjectArray
@@ -225,10 +213,6 @@
// run char[], int[] and long[] through FindClass to complete initialization
Class* found_char_array_class = FindSystemClass("[C");
CHECK_EQ(char_array_class, found_char_array_class);
- Class* found_int_array_class = FindSystemClass("[I");
- CHECK_EQ(int_array_class, found_int_array_class);
- Class* found_long_array_class = FindSystemClass("[J");
- CHECK_EQ(long_array_class, found_long_array_class);
// Initialize all the other primitive array types for PrimitiveArray::Alloc.
// These are easy because everything we need has already been set up.
@@ -236,11 +220,15 @@
SetClassRoot(kByteArrayClass, FindSystemClass("[B"));
SetClassRoot(kDoubleArrayClass, FindSystemClass("[D"));
SetClassRoot(kFloatArrayClass, FindSystemClass("[F"));
+ SetClassRoot(kIntArrayClass, FindSystemClass("[I"));
+ SetClassRoot(kLongArrayClass, FindSystemClass("[J"));
SetClassRoot(kShortArrayClass, FindSystemClass("[S"));
BooleanArray::SetArrayClass(GetClassRoot(kBooleanArrayClass));
ByteArray::SetArrayClass(GetClassRoot(kByteArrayClass));
DoubleArray::SetArrayClass(GetClassRoot(kDoubleArrayClass));
FloatArray::SetArrayClass(GetClassRoot(kFloatArrayClass));
+ IntArray::SetArrayClass(GetClassRoot(kIntArrayClass));
+ LongArray::SetArrayClass(GetClassRoot(kLongArrayClass));
ShortArray::SetArrayClass(GetClassRoot(kShortArrayClass));
FinishInit();
@@ -343,7 +331,7 @@
FinishInit();
}
-void ClassLinker::InitCallback(Object *obj, void *arg) {
+void ClassLinker::InitCallback(Object* obj, void *arg) {
DCHECK(obj != NULL);
DCHECK(arg != NULL);
InitCallbackState* state = reinterpret_cast<InitCallbackState*>(arg);
@@ -410,12 +398,15 @@
return dex_cache;
}
-Class* ClassLinker::AllocClass(Class* java_lang_Class) {
- return java_lang_Class->NewInstance()->AsClass();
+Class* ClassLinker::AllocClass(Class* java_lang_Class, size_t class_size) {
+ DCHECK_GE(class_size, sizeof(Class));
+ Class* klass = Heap::AllocObject(java_lang_Class, class_size)->AsClass();
+ klass->class_size_ = class_size;
+ return klass;
}
-Class* ClassLinker::AllocClass() {
- return AllocClass(GetClassRoot(kJavaLangClass));
+Class* ClassLinker::AllocClass(size_t class_size) {
+ return AllocClass(GetClassRoot(kJavaLangClass), class_size);
}
Field* ClassLinker::AllocField() {
@@ -476,10 +467,10 @@
} else if (descriptor == "Ljava/lang/reflect/Method;") {
klass = GetClassRoot(kJavaLangReflectMethod);
} else {
- klass = AllocClass();
+ klass = AllocClass(SizeOfClass(dex_file, dex_class_def));
}
} else {
- klass = AllocClass();
+ klass = AllocClass(SizeOfClass(dex_file, dex_class_def));
}
klass->dex_cache_ = dex_cache;
LoadClass(dex_file, dex_class_def, klass, class_loader);
@@ -542,6 +533,53 @@
return klass;
}
+// Precomputes size that will be needed for Class, matching LinkStaticFields
+size_t ClassLinker::SizeOfClass(const DexFile& dex_file,
+ const DexFile::ClassDef& dex_class_def) {
+ const byte* class_data = dex_file.GetClassData(dex_class_def);
+ DexFile::ClassDataHeader header = dex_file.ReadClassDataHeader(&class_data);
+ size_t num_static_fields = header.static_fields_size_;
+ size_t num_ref = 0;
+ size_t num_32 = 0;
+ size_t num_64 = 0;
+ if (num_static_fields != 0) {
+ uint32_t last_idx = 0;
+ for (size_t i = 0; i < num_static_fields; ++i) {
+ DexFile::Field dex_field;
+ dex_file.dexReadClassDataField(&class_data, &dex_field, &last_idx);
+ const DexFile::FieldId& field_id = dex_file.GetFieldId(dex_field.field_idx_);
+ const char* descriptor = dex_file.dexStringByTypeIdx(field_id.type_idx_);
+ char c = descriptor[0];
+ if (c == 'L' || c == '[') {
+ num_ref++;
+ } else if (c == 'J' || c == 'D') {
+ num_64++;
+ } else {
+ num_32++;
+ }
+ }
+ }
+
+ // start with generic class data
+ size_t size = sizeof(Class);
+ // follow with reference fields which must be contiguous at start
+ size += (num_ref * sizeof(uint32_t));
+ // if there are 64-bit fields to add, make sure they are aligned
+ if (num_64 != 0 && size != RoundUp(size, 8)) { // for 64-bit alignment
+ if (num_32 != 0) {
+ // use an available 32-bit field for padding
+ num_32--;
+ }
+ size += sizeof(uint32_t); // either way, we are adding a word
+ DCHECK_EQ(size, RoundUp(size, 8));
+ }
+ // tack on any 64-bit fields now that alignment is assured
+ size += (num_64 * sizeof(uint64_t));
+ // tack on any remaining 32-bit fields
+ size += (num_32 * sizeof(uint32_t));
+ return size;
+}
+
void ClassLinker::LoadClass(const DexFile& dex_file,
const DexFile::ClassDef& dex_class_def,
Class* klass,
@@ -750,7 +788,7 @@
}
Class* ClassLinker::CreatePrimitiveClass(const char* descriptor) {
- Class* klass = AllocClass();
+ Class* klass = AllocClass(sizeof(Class));
CHECK(klass != NULL);
klass->super_class_ = NULL;
klass->access_flags_ = kAccPublic | kAccFinal | kAccAbstract;
@@ -849,14 +887,10 @@
new_class = GetClassRoot(kObjectArrayClass);
} else if (descriptor == "[C") {
new_class = GetClassRoot(kCharArrayClass);
- } else if (descriptor == "[I") {
- new_class = GetClassRoot(kIntArrayClass);
- } else if (descriptor == "[J") {
- new_class = GetClassRoot(kLongArrayClass);
}
}
if (new_class == NULL) {
- new_class = AllocClass();
+ new_class = AllocClass(sizeof(Class));
if (new_class == NULL) {
return NULL;
}
@@ -1205,6 +1239,7 @@
return;
}
DexCache* dex_cache = klass->GetDexCache();
+ // TODO: this seems like the wrong check. do we really want !IsPrimitive && !IsArray?
if (dex_cache == NULL) {
return;
}
@@ -1224,37 +1259,37 @@
DexFile::ValueType type = dex_file.ReadEncodedValue(&addr, &value);
switch (type) {
case DexFile::kByte:
- field->SetByte(value.b);
+ field->SetByte(NULL, value.b);
break;
case DexFile::kShort:
- field->SetShort(value.s);
+ field->SetShort(NULL, value.s);
break;
case DexFile::kChar:
- field->SetChar(value.c);
+ field->SetChar(NULL, value.c);
break;
case DexFile::kInt:
- field->SetInt(value.i);
+ field->SetInt(NULL, value.i);
break;
case DexFile::kLong:
- field->SetLong(value.j);
+ field->SetLong(NULL, value.j);
break;
case DexFile::kFloat:
- field->SetFloat(value.f);
+ field->SetFloat(NULL, value.f);
break;
case DexFile::kDouble:
- field->SetDouble(value.d);
+ field->SetDouble(NULL, value.d);
break;
case DexFile::kString: {
uint32_t string_idx = value.i;
String* resolved = ResolveString(klass, string_idx, dex_file);
- field->SetObject(resolved);
+ field->SetObject(NULL, resolved);
break;
}
case DexFile::kBoolean:
- field->SetBoolean(value.z);
+ field->SetBoolean(NULL, value.z);
break;
case DexFile::kNull:
- field->SetObject(value.l);
+ field->SetObject(NULL, value.l);
break;
default:
LOG(FATAL) << "Unknown type " << static_cast<int>(type);
@@ -1270,13 +1305,14 @@
if (!LinkMethods(klass)) {
return false;
}
- if (!LinkStaticFields(klass)) {
- return false;
- }
if (!LinkInstanceFields(klass)) {
return false;
}
- CreateReferenceOffsets(klass);
+ if (!LinkStaticFields(klass)) {
+ return false;
+ }
+ CreateReferenceInstanceOffsets(klass);
+ CreateReferenceStaticOffsets(klass);
CHECK_EQ(Class::kStatusLoaded, klass->status_);
klass->status_ = Class::kStatusResolved;
return true;
@@ -1557,68 +1593,61 @@
}
}
-// Each static field will be stored in one of three arrays: static_references_,
-// static_32bit_primitives_, or static_64bit_primitives_. This assigns each
-// field a slot in its array and create the arrays.
-bool ClassLinker::LinkStaticFields(Class* klass) {
- size_t next_reference_slot = 0;
- size_t next_32bit_primitive_slot = 0;
- size_t next_64bit_primitive_slot = 0;
-
- for (size_t i = 0; i < klass->NumStaticFields(); i++) {
- Field* field = klass->GetStaticField(i);
- char type = field->GetType();
- if (type == '[' || type == 'L') {
- field->offset_ = next_reference_slot++;
- } else if (type == 'J' || type == 'D') {
- field->offset_ = next_64bit_primitive_slot++;
- } else {
- field->offset_ = next_32bit_primitive_slot++;
- }
- }
-
- if (next_reference_slot > 0) {
- Class* array_class = GetClassRoot(kObjectArrayClass);
- klass->static_references_ = ObjectArray<Object>::Alloc(array_class, next_reference_slot);
- }
- if (next_32bit_primitive_slot > 0) {
- klass->static_32bit_primitives_ = IntArray::Alloc(next_32bit_primitive_slot);
- }
- if (next_64bit_primitive_slot > 0) {
- klass->static_64bit_primitives_ = LongArray::Alloc(next_64bit_primitive_slot);
- }
-
- return true;
-}
-
bool ClassLinker::LinkInstanceFields(Class* klass) {
- int field_offset;
+ CHECK(klass != NULL);
+ size_t field_offset;
if (klass->GetSuperClass() != NULL) {
field_offset = klass->GetSuperClass()->object_size_;
} else {
field_offset = OFFSETOF_MEMBER(DataObject, fields_);
}
+ return LinkFields(field_offset,
+ klass->num_reference_instance_fields_,
+ klass->NumInstanceFields(),
+ klass->ifields_,
+ klass->object_size_);
+}
+
+bool ClassLinker::LinkStaticFields(Class* klass) {
+ CHECK(klass != NULL);
+ size_t allocated_class_size = klass->class_size_;
+ size_t field_offset = OFFSETOF_MEMBER(Class, fields_);
+ bool success = LinkFields(field_offset,
+ klass->num_reference_static_fields_,
+ klass->NumStaticFields(),
+ klass->sfields_,
+ klass->class_size_);
+ CHECK_EQ(allocated_class_size, klass->class_size_);
+ return success;
+}
+
+bool ClassLinker::LinkFields(size_t field_offset,
+ size_t& num_reference_fields,
+ size_t num_fields,
+ ObjectArray<Field>* fields,
+ size_t& size) {
+ CHECK((num_fields == 0) == (fields == NULL));
// Move references to the front.
- klass->num_reference_instance_fields_ = 0;
+ num_reference_fields = 0;
size_t i = 0;
- for ( ; i < klass->NumInstanceFields(); i++) {
- Field* pField = klass->GetInstanceField(i);
+ for ( ; i < num_fields; i++) {
+ Field* pField = fields->Get(i);
char c = pField->GetType();
if (c != '[' && c != 'L') {
- for (size_t j = klass->NumInstanceFields() - 1; j > i; j--) {
- Field* refField = klass->GetInstanceField(j);
+ for (size_t j = num_fields - 1; j > i; j--) {
+ Field* refField = fields->Get(j);
char rc = refField->GetType();
if (rc == '[' || rc == 'L') {
- klass->SetInstanceField(i, refField);
- klass->SetInstanceField(j, pField);
+ fields->Set(i, refField);
+ fields->Set(j, pField);
pField = refField;
c = rc;
- klass->num_reference_instance_fields_++;
+ num_reference_fields++;
break;
}
}
} else {
- klass->num_reference_instance_fields_++;
+ num_reference_fields++;
}
if (c != '[' && c != 'L') {
break;
@@ -1630,8 +1659,8 @@
// 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() && (field_offset & 0x04) != 0) {
- Field* pField = klass->GetInstanceField(i);
+ if (i != num_fields && (field_offset & 0x04) != 0) {
+ Field* pField = fields->Get(i);
char c = pField->GetType();
if (c != 'J' && c != 'D') {
@@ -1645,12 +1674,12 @@
// Next field is 64-bit, so search for a 32-bit field we can
// swap into it.
bool found = false;
- for (size_t j = klass->NumInstanceFields() - 1; j > i; j--) {
- Field* singleField = klass->GetInstanceField(j);
+ for (size_t j = num_fields - 1; j > i; j--) {
+ Field* singleField = fields->Get(j);
char rc = singleField->GetType();
if (rc != 'J' && rc != 'D') {
- klass->SetInstanceField(i, singleField);
- klass->SetInstanceField(j, pField);
+ fields->Set(i, singleField);
+ fields->Set(j, pField);
pField = singleField;
pField->SetOffset(field_offset);
field_offset += sizeof(uint32_t);
@@ -1667,17 +1696,17 @@
// Alignment is good, shuffle any double-wide fields forward, and
// finish assigning field offsets to all fields.
- DCHECK(i == klass->NumInstanceFields() || (field_offset & 0x04) == 0);
- for ( ; i < klass->NumInstanceFields(); i++) {
- Field* pField = klass->GetInstanceField(i);
+ DCHECK(i == num_fields || (field_offset & 0x04) == 0);
+ for ( ; i < num_fields; i++) {
+ Field* pField = fields->Get(i);
char c = pField->GetType();
if (c != 'D' && c != 'J') {
- for (size_t j = klass->NumInstanceFields() - 1; j > i; j--) {
- Field* doubleField = klass->GetInstanceField(j);
+ for (size_t j = num_fields - 1; j > i; j--) {
+ Field* doubleField = fields->Get(j);
char rc = doubleField->GetType();
if (rc == 'D' || rc == 'J') {
- klass->SetInstanceField(i, doubleField);
- klass->SetInstanceField(j, pField);
+ fields->Set(i, doubleField);
+ fields->Set(j, pField);
pField = doubleField;
c = rc;
break;
@@ -1689,16 +1718,17 @@
pField->SetOffset(field_offset);
field_offset += sizeof(uint32_t);
- if (c == 'J' || c == 'D')
+ if (c == 'J' || c == 'D') {
field_offset += sizeof(uint32_t);
+ }
}
#ifndef NDEBUG
// Make sure that all reference fields appear before
// non-reference fields, and all double-wide fields are aligned.
bool seen_non_ref = false;
- for (i = 0; i < klass->NumInstanceFields(); i++) {
- Field *pField = klass->GetInstanceField(i);
+ for (i = 0; i < num_fields; i++) {
+ Field *pField = fields->Get(i);
char c = pField->GetType();
if (c == 'D' || c == 'J') {
@@ -1708,50 +1738,64 @@
if (c != '[' && c != 'L') {
if (!seen_non_ref) {
seen_non_ref = true;
- DCHECK_EQ(klass->NumReferenceInstanceFields(), i);
+ DCHECK_EQ(num_reference_fields, i);
}
} else {
DCHECK(!seen_non_ref);
}
}
if (!seen_non_ref) {
- DCHECK_EQ(klass->NumInstanceFields(), klass->NumReferenceInstanceFields());
+ DCHECK_EQ(num_fields, num_reference_fields);
}
#endif
- klass->object_size_ = field_offset;
+ size = field_offset;
return true;
}
// Set the bitmap of reference offsets, refOffsets, from the ifields
// list.
-void ClassLinker::CreateReferenceOffsets(Class* klass) {
- uint32_t reference_offsets = 0;
+void ClassLinker::CreateReferenceInstanceOffsets(Class* klass) {
+ klass->reference_instance_offsets_ = 0;
if (klass->HasSuperClass()) {
- reference_offsets = klass->GetSuperClass()->GetReferenceOffsets();
- }
- // If our superclass overflowed, we don't stand a chance.
- if (reference_offsets != CLASS_WALK_SUPER) {
- // All of the fields that contain object references are guaranteed
- // to be at the beginning of the ifields list.
- for (size_t i = 0; i < klass->NumReferenceInstanceFields(); ++i) {
- // Note that, per the comment on struct InstField, f->byteOffset
- // is the offset from the beginning of obj, not the offset into
- // obj->instanceData.
- const Field* field = klass->GetInstanceField(i);
- size_t byte_offset = field->GetOffset();
- CHECK_GE(byte_offset, CLASS_SMALLEST_OFFSET);
- CHECK_EQ(byte_offset & (CLASS_OFFSET_ALIGNMENT - 1), 0U);
- if (CLASS_CAN_ENCODE_OFFSET(byte_offset)) {
- uint32_t new_bit = CLASS_BIT_FROM_OFFSET(byte_offset);
- CHECK_NE(new_bit, 0U);
- reference_offsets |= new_bit;
- } else {
- reference_offsets = CLASS_WALK_SUPER;
- break;
- }
+ klass->reference_instance_offsets_ = klass->GetSuperClass()->GetReferenceInstanceOffsets();
+ // If our superclass overflowed, we don't stand a chance.
+ if (klass->reference_instance_offsets_ == CLASS_WALK_SUPER) {
+ return;
}
}
- klass->SetReferenceOffsets(reference_offsets);
+ CreateReferenceOffsets(klass->reference_instance_offsets_,
+ klass->NumReferenceInstanceFields(),
+ klass->ifields_);
+}
+
+void ClassLinker::CreateReferenceStaticOffsets(Class* klass) {
+ klass->reference_static_offsets_ = 0;
+ CreateReferenceOffsets(klass->reference_static_offsets_,
+ klass->NumReferenceStaticFields(),
+ klass->sfields_);
+}
+
+void ClassLinker::CreateReferenceOffsets(uint32_t& reference_offsets,
+ size_t num_reference_fields,
+ const ObjectArray<Field>* fields) {
+ // All of the fields that contain object references are guaranteed
+ // to be at the beginning of the fields list.
+ for (size_t i = 0; i < num_reference_fields; ++i) {
+ // Note that byte_offset is the offset from the beginning of
+ // object, not the offset into instance data
+ const Field* field = fields->Get(i);
+ size_t byte_offset = field->GetOffset();
+ CHECK_GE(byte_offset, CLASS_SMALLEST_OFFSET);
+ CHECK_EQ(byte_offset & (CLASS_OFFSET_ALIGNMENT - 1), 0U);
+ if (CLASS_CAN_ENCODE_OFFSET(byte_offset)) {
+ uint32_t new_bit = CLASS_BIT_FROM_OFFSET(byte_offset);
+ CHECK_NE(new_bit, 0U);
+ reference_offsets |= new_bit;
+ } else {
+ reference_offsets = CLASS_WALK_SUPER;
+ break;
+ }
+ }
}
Class* ClassLinker::ResolveClass(const Class* referrer,
diff --git a/src/class_linker.h b/src/class_linker.h
index 13754db..5b629d5 100644
--- a/src/class_linker.h
+++ b/src/class_linker.h
@@ -75,7 +75,7 @@
// Initialize class linker from pre-initialized space.
void Init(const std::vector<DexFile*>& boot_class_path_, Space* space);
- static void InitCallback(Object *obj, void *arg);
+ static void InitCallback(Object* obj, void *arg);
struct InitCallbackState;
void FinishInit();
@@ -83,12 +83,12 @@
bool InitializeClass(Class* klass);
// For early bootstrapping by Init
- Class* AllocClass(Class* java_lang_Class);
+ Class* AllocClass(Class* java_lang_Class, size_t class_size);
// Alloc* convenience functions to avoid needing to pass in Class*
// values that are known to the ClassLinker such as
// kObjectArrayClass and kJavaLangString etc.
- Class* AllocClass();
+ Class* AllocClass(size_t class_size);
DexCache* AllocDexCache(const DexFile* dex_file);
Field* AllocField();
Method* AllocMethod();
@@ -108,6 +108,9 @@
void AppendToBootClassPath(const DexFile* dex_file);
void AppendToBootClassPath(const DexFile* dex_file, DexCache* dex_cache);
+ size_t SizeOfClass(const DexFile& dex_file,
+ const DexFile::ClassDef& dex_class_def);
+
void LoadClass(const DexFile& dex_file,
const DexFile::ClassDef& dex_class_def,
Class* klass,
@@ -170,10 +173,18 @@
void LinkAbstractMethods(Class* klass);
bool LinkStaticFields(Class* klass);
-
bool LinkInstanceFields(Class* klass);
+ bool LinkFields(size_t field_offset,
+ size_t& num_reference_fields,
+ size_t num_fields,
+ ObjectArray<Field>* fields,
+ size_t& size);
- void CreateReferenceOffsets(Class* klass);
+ void CreateReferenceInstanceOffsets(Class* klass);
+ void CreateReferenceStaticOffsets(Class* klass);
+ void CreateReferenceOffsets(uint32_t& reference_offsets,
+ size_t num_reference_fields,
+ const ObjectArray<Field>* fields);
std::vector<const DexFile*> boot_class_path_;
diff --git a/src/class_linker_test.cc b/src/class_linker_test.cc
index ca305f1..2583fcf 100644
--- a/src/class_linker_test.cc
+++ b/src/class_linker_test.cc
@@ -198,7 +198,7 @@
total_num_reference_instance_fields += k->NumReferenceInstanceFields();
k = k->GetSuperClass();
}
- EXPECT_EQ(klass->GetReferenceOffsets() == 0,
+ EXPECT_EQ(klass->GetReferenceInstanceOffsets() == 0,
total_num_reference_instance_fields == 0);
}
@@ -412,70 +412,70 @@
scoped_ptr<DexFile> dex(OpenDexFileBase64(kStatics, "kStatics"));
PathClassLoader* class_loader = AllocPathClassLoader(dex.get());
Class* statics = class_linker_->FindClass("LStatics;", class_loader);
- // class_linker_->InitializeClass(statics); // TODO: uncomment this
+ class_linker_->EnsureInitialized(statics);
EXPECT_EQ(10U, statics->NumStaticFields());
- Field* s0 = statics->GetStaticField(0);
+ Field* s0 = statics->FindStaticField("s0", "Z");
EXPECT_TRUE(s0->GetClass()->descriptor_->Equals("Ljava/lang/reflect/Field;"));
EXPECT_EQ('Z', s0->GetType());
-// EXPECT_EQ(true, s0->GetBoolean()); // TODO: uncomment this
- s0->SetBoolean(false);
+ // EXPECT_EQ(true, s0->GetBoolean(NULL)); // TODO: needs clinit to be run?
+ s0->SetBoolean(NULL, false);
- Field* s1 = statics->GetStaticField(1);
+ Field* s1 = statics->FindStaticField("s1", "B");
EXPECT_EQ('B', s1->GetType());
-// EXPECT_EQ(5, s1->GetByte()); // TODO: uncomment this
- s1->SetByte(6);
+ // EXPECT_EQ(5, s1->GetByte(NULL)); // TODO: needs clinit to be run?
+ s1->SetByte(NULL, 6);
- Field* s2 = statics->GetStaticField(2);
+ Field* s2 = statics->FindStaticField("s2", "C");
EXPECT_EQ('C', s2->GetType());
-// EXPECT_EQ('a', s2->GetChar()); // TODO: uncomment this
- s2->SetChar('b');
+ // EXPECT_EQ('a', s2->GetChar(NULL)); // TODO: needs clinit to be run?
+ s2->SetChar(NULL, 'b');
- Field* s3 = statics->GetStaticField(3);
+ Field* s3 = statics->FindStaticField("s3", "S");
EXPECT_EQ('S', s3->GetType());
-// EXPECT_EQ(65000, s3->GetShort()); // TODO: uncomment this
- s3->SetShort(65001);
+ // EXPECT_EQ(65000, s3->GetShort(NULL)); // TODO: needs clinit to be run?
+ s3->SetShort(NULL, 65001);
- Field* s4 = statics->GetStaticField(4);
+ Field* s4 = statics->FindStaticField("s4", "I");
EXPECT_EQ('I', s4->GetType());
-// EXPECT_EQ(2000000000, s4->GetInt()); // TODO: uncomment this
- s4->SetInt(2000000001);
+ // EXPECT_EQ(2000000000, s4->GetInt(NULL)); // TODO: needs clinit to be run?
+ s4->SetInt(NULL, 2000000001);
- Field* s5 = statics->GetStaticField(5);
+ Field* s5 = statics->FindStaticField("s5", "J");
EXPECT_EQ('J', s5->GetType());
-// EXPECT_EQ(0x1234567890abcdefLL, s5->GetLong()); // TODO: uncomment this
- s5->SetLong(0x34567890abcdef12LL);
+ // EXPECT_EQ(0x1234567890abcdefLL, s5->GetLong(NULL)); // TODO: needs clinit to be run?
+ s5->SetLong(NULL, 0x34567890abcdef12LL);
- Field* s6 = statics->GetStaticField(6);
+ Field* s6 = statics->FindStaticField("s6", "F");
EXPECT_EQ('F', s6->GetType());
-// EXPECT_EQ(0.5, s6->GetFloat()); // TODO: uncomment this
- s6->SetFloat(0.75);
+ // EXPECT_EQ(0.5, s6->GetFloat(NULL)); // TODO: needs clinit to be run?
+ s6->SetFloat(NULL, 0.75);
- Field* s7 = statics->GetStaticField(7);
+ Field* s7 = statics->FindStaticField("s7", "D");
EXPECT_EQ('D', s7->GetType());
-// EXPECT_EQ(16777217, s7->GetDouble()); // TODO: uncomment this
- s7->SetDouble(16777219);
+ // EXPECT_EQ(16777217, s7->GetDouble(NULL)); // TODO: needs clinit to be run?
+ s7->SetDouble(NULL, 16777219);
- Field* s8 = statics->GetStaticField(8);
+ Field* s8 = statics->FindStaticField("s8", "Ljava/lang/Object;");
EXPECT_EQ('L', s8->GetType());
-// EXPECT_TRUE(s8->GetObject()->AsString()->Equals("android")); // TODO: uncomment this
- s8->SetObject(String::AllocFromModifiedUtf8("robot"));
+ // EXPECT_TRUE(s8->GetObject(NULL)->AsString()->Equals("android")); // TODO: needs clinit to be run?
+ s8->SetObject(NULL, String::AllocFromModifiedUtf8("robot"));
- Field* s9 = statics->GetStaticField(9);
+ Field* s9 = statics->FindStaticField("s9", "[Ljava/lang/Object;");
EXPECT_EQ('[', s9->GetType());
-// EXPECT_EQ(NULL, s9->GetObject()); // TODO: uncomment this
- s9->SetObject(NULL);
+ // EXPECT_EQ(NULL, s9->GetObject(NULL)); // TODO: needs clinit to be run?
+ s9->SetObject(NULL, NULL);
- EXPECT_EQ(false, s0->GetBoolean());
- EXPECT_EQ(6, s1->GetByte());
- EXPECT_EQ('b', s2->GetChar());
- EXPECT_EQ(65001, s3->GetShort());
- EXPECT_EQ(2000000001, s4->GetInt());
- EXPECT_EQ(0x34567890abcdef12LL, s5->GetLong());
- EXPECT_EQ(0.75, s6->GetFloat());
- EXPECT_EQ(16777219, s7->GetDouble());
- EXPECT_TRUE(s8->GetObject()->AsString()->Equals("robot"));
+ EXPECT_EQ(false, s0->GetBoolean(NULL));
+ EXPECT_EQ(6, s1->GetByte(NULL));
+ EXPECT_EQ('b', s2->GetChar(NULL));
+ EXPECT_EQ(65001, s3->GetShort(NULL));
+ EXPECT_EQ(2000000001, s4->GetInt(NULL));
+ EXPECT_EQ(0x34567890abcdef12LL, s5->GetLong(NULL));
+ EXPECT_EQ(0.75, s6->GetFloat(NULL));
+ EXPECT_EQ(16777219, s7->GetDouble(NULL));
+ EXPECT_TRUE(s8->GetObject(NULL)->AsString()->Equals("robot"));
}
} // namespace art
diff --git a/src/heap.cc b/src/heap.cc
index 7369804..f86f556 100644
--- a/src/heap.cc
+++ b/src/heap.cc
@@ -103,6 +103,7 @@
Object* Heap::AllocObject(Class* klass, size_t num_bytes) {
DCHECK(klass == NULL
|| klass->descriptor_ == NULL
+ || (klass->IsClassClass() && num_bytes >= sizeof(Class))
|| (klass->object_size_ == (klass->IsArray() ? 0 : num_bytes)));
Object* obj = Allocate(num_bytes);
if (obj != NULL) {
diff --git a/src/image_writer.cc b/src/image_writer.cc
index 1c7acff..3998140 100644
--- a/src/image_writer.cc
+++ b/src/image_writer.cc
@@ -79,7 +79,7 @@
} // namespace
-void ImageWriter::CalculateNewObjectOffsetsCallback(Object *obj, void *arg) {
+void ImageWriter::CalculateNewObjectOffsetsCallback(Object* obj, void *arg) {
DCHECK(obj != NULL);
DCHECK(arg != NULL);
ImageWriter* image_writer = reinterpret_cast<ImageWriter*>(arg);
@@ -116,14 +116,15 @@
heap_bitmap->Walk(CopyAndFixupObjectsCallback, this);
}
-void ImageWriter::CopyAndFixupObjectsCallback(Object *obj, void *arg) {
- DCHECK(obj != NULL);
+void ImageWriter::CopyAndFixupObjectsCallback(Object* object, void *arg) {
+ DCHECK(object != NULL);
DCHECK(arg != NULL);
+ const Object* obj = object;
ImageWriter* image_writer = reinterpret_cast<ImageWriter*>(arg);
size_t offset = image_writer->GetImageOffset(obj);
byte* dst = image_writer->image_->GetAddress() + offset;
- byte* src = reinterpret_cast<byte*>(obj);
+ const byte* src = reinterpret_cast<const byte*>(obj);
size_t n = obj->SizeOf();
DCHECK_LT(offset + n, image_writer->image_->GetLength());
memcpy(dst, src, n);
@@ -131,7 +132,7 @@
image_writer->FixupObject(obj, copy);
}
-void ImageWriter::FixupObject(Object* orig, Object* copy) {
+void ImageWriter::FixupObject(const Object* orig, Object* copy) {
DCHECK(orig != NULL);
DCHECK(copy != NULL);
copy->klass_ = down_cast<Class*>(GetImageAddress(orig->klass_));
@@ -149,7 +150,7 @@
}
}
-void ImageWriter::FixupClass(Class* orig, Class* copy) {
+void ImageWriter::FixupClass(const Class* orig, Class* copy) {
FixupInstanceFields(orig, copy);
copy->descriptor_ = down_cast<String*>(GetImageAddress(orig->descriptor_));
copy->dex_cache_ = down_cast<DexCache*>(GetImageAddress(orig->dex_cache_));
@@ -163,12 +164,13 @@
copy->vtable_ = down_cast<ObjectArray<Method>*>(GetImageAddress(orig->vtable_));
// TODO: convert iftable_ to heap allocated storage
copy->ifields_ = down_cast<ObjectArray<Field>*>(GetImageAddress(orig->ifields_));
+ // TODO: convert source_file_ to heap allocated storage
copy->sfields_ = down_cast<ObjectArray<Field>*>(GetImageAddress(orig->sfields_));
- copy->static_references_ = down_cast<ObjectArray<Object>*>(GetImageAddress(orig->static_references_));
+ FixupStaticFields(orig, copy);
}
// TODO: remove this slow path
-void ImageWriter::FixupMethod(Method* orig, Method* copy) {
+void ImageWriter::FixupMethod(const Method* orig, Method* copy) {
FixupInstanceFields(orig, copy);
// TODO: remove need for this by adding "signature" to java.lang.reflect.Method
copy->signature_ = down_cast<String*>(GetImageAddress(orig->signature_));
@@ -176,20 +178,42 @@
// TODO: convert shorty_ to heap allocated storage
}
-void ImageWriter::FixupField(Field* orig, Field* copy) {
+void ImageWriter::FixupField(const Field* orig, Field* copy) {
FixupInstanceFields(orig, copy);
// TODO: convert descriptor_ to heap allocated storage
}
-void ImageWriter::FixupObjectArray(ObjectArray<Object>* orig, ObjectArray<Object>* copy) {
+void ImageWriter::FixupObjectArray(const ObjectArray<Object>* orig, ObjectArray<Object>* copy) {
for (int32_t i = 0; i < orig->GetLength(); ++i) {
const Object* element = orig->Get(i);
copy->Set(i, GetImageAddress(element));
}
}
-void ImageWriter::FixupInstanceFields(Object* orig, Object* copy) {
- uint32_t ref_offsets = orig->GetClass()->GetReferenceOffsets();
+void ImageWriter::FixupInstanceFields(const Object* orig, Object* copy) {
+ DCHECK(orig != NULL);
+ DCHECK(copy != NULL);
+ Class* klass = orig->GetClass();
+ DCHECK(klass != NULL);
+ FixupFields(orig,
+ copy,
+ klass->GetReferenceInstanceOffsets(),
+ false);
+}
+
+void ImageWriter::FixupStaticFields(const Class* orig, Class* copy) {
+ DCHECK(orig != NULL);
+ DCHECK(copy != NULL);
+ FixupFields(orig,
+ copy,
+ orig->GetReferenceStaticOffsets(),
+ true);
+}
+
+void ImageWriter::FixupFields(const Object* orig,
+ Object* copy,
+ uint32_t ref_offsets,
+ bool is_static) {
if (ref_offsets != CLASS_WALK_SUPER) {
// Found a reference offset bitmap. Fixup the specified offsets.
while (ref_offsets != 0) {
@@ -200,14 +224,21 @@
ref_offsets &= ~(CLASS_HIGH_BIT >> right_shift);
}
} else {
- // There is no reference offset bitmap for this class. Walk up
- // the class inheritance hierarchy and find reference offsets the
- // hard way.
- for (Class *klass = orig->GetClass();
+ // There is no reference offset bitmap. In the non-static case,
+ // walk up the class inheritance hierarchy and find reference
+ // offsets the hard way. In the static case, just consider this
+ // class.
+ for (const Class *klass = is_static ? orig->AsClass() : orig->GetClass();
klass != NULL;
- klass = klass->GetSuperClass()) {
- for (size_t i = 0; i < klass->NumReferenceInstanceFields(); ++i) {
- size_t field_offset = klass->GetInstanceField(i)->GetOffset();
+ klass = is_static ? NULL : klass->GetSuperClass()) {
+ size_t num_reference_fields = (is_static
+ ? klass->NumReferenceStaticFields()
+ : klass->NumReferenceInstanceFields());
+ for (size_t i = 0; i < num_reference_fields; ++i) {
+ Field* field = (is_static
+ ? klass->GetStaticField(i)
+ : klass->GetInstanceField(i));
+ size_t field_offset = field->GetOffset();
const Object* ref = orig->GetFieldObject(field_offset);
copy->SetFieldObject(field_offset, GetImageAddress(ref));
}
diff --git a/src/image_writer.h b/src/image_writer.h
index 8e9ac10..ebd86a5 100644
--- a/src/image_writer.h
+++ b/src/image_writer.h
@@ -46,16 +46,18 @@
}
void CalculateNewObjectOffsets();
- static void CalculateNewObjectOffsetsCallback(Object *obj, void *arg);
+ static void CalculateNewObjectOffsetsCallback(Object* obj, void *arg);
void CopyAndFixupObjects();
- static void CopyAndFixupObjectsCallback(Object *obj, void *arg);
- void FixupClass(Class* orig, Class* copy);
- void FixupMethod(Method* orig, Method* copy);
- void FixupField(Field* orig, Field* copy);
- void FixupObject(Object* orig, Object* copy);
- void FixupObjectArray(ObjectArray<Object>* orig, ObjectArray<Object>* copy);
- void FixupInstanceFields(Object* orig, Object* copy);
+ static void CopyAndFixupObjectsCallback(Object* obj, void *arg);
+ void FixupClass(const Class* orig, Class* copy);
+ void FixupMethod(const Method* orig, Method* copy);
+ void FixupField(const Field* orig, Field* copy);
+ void FixupObject(const Object* orig, Object* copy);
+ void FixupObjectArray(const ObjectArray<Object>* orig, ObjectArray<Object>* copy);
+ void FixupInstanceFields(const Object* orig, Object* copy);
+ void FixupStaticFields(const Class* orig, Class* copy);
+ void FixupFields(const Object* orig, Object* copy, uint32_t ref_offsets, bool is_static);
// memory mapped for generating the image
scoped_ptr<MemMap> image_;
diff --git a/src/mark_sweep.cc b/src/mark_sweep.cc
index 8541f76..179d954 100644
--- a/src/mark_sweep.cc
+++ b/src/mark_sweep.cc
@@ -126,8 +126,24 @@
// Scans instance fields.
void MarkSweep::ScanInstanceFields(const Object* obj) {
DCHECK(obj != NULL);
- DCHECK(obj->GetClass() != NULL);
- uint32_t ref_offsets = obj->GetClass()->GetReferenceOffsets();
+ Class* klass = obj->GetClass();
+ DCHECK(klass != NULL);
+ ScanFields(obj,
+ klass->GetReferenceInstanceOffsets(),
+ false);
+}
+
+// Scans static storage on a Class.
+void MarkSweep::ScanStaticFields(const Class* klass) {
+ DCHECK(klass != NULL);
+ ScanFields(klass,
+ klass->GetReferenceStaticOffsets(),
+ true);
+}
+
+void MarkSweep::ScanFields(const Object* obj,
+ uint32_t ref_offsets,
+ bool is_static) {
if (ref_offsets != CLASS_WALK_SUPER) {
// Found a reference offset bitmap. Mark the specified offsets.
while (ref_offsets != 0) {
@@ -138,14 +154,21 @@
ref_offsets &= ~(CLASS_HIGH_BIT >> right_shift);
}
} else {
- // There is no reference offset bitmap for this class. Walk up
- // the class inheritance hierarchy and find reference offsets the
- // hard way.
- for (Class *klass = obj->GetClass();
+ // There is no reference offset bitmap. In the non-static case,
+ // walk up the class inheritance hierarchy and find reference
+ // offsets the hard way. In the static case, just consider this
+ // class.
+ for (const Class* klass = is_static ? obj->AsClass() : obj->GetClass();
klass != NULL;
- klass = klass->GetSuperClass()) {
- for (size_t i = 0; i < klass->NumReferenceInstanceFields(); ++i) {
- size_t field_offset = klass->GetInstanceField(i)->GetOffset();
+ klass = is_static ? NULL : klass->GetSuperClass()) {
+ size_t num_reference_fields = (is_static
+ ? klass->NumReferenceStaticFields()
+ : klass->NumReferenceInstanceFields());
+ for (size_t i = 0; i < num_reference_fields; ++i) {
+ Field* field = (is_static
+ ? klass->GetStaticField(i)
+ : klass->GetInstanceField(i));
+ size_t field_offset = field->GetOffset();
const Object* ref = obj->GetFieldObject(field_offset);
MarkObject(ref);
}
@@ -153,19 +176,6 @@
}
}
-// Scans the static fields of a class object.
-void MarkSweep::ScanStaticFields(const Class* klass) {
- DCHECK(klass != NULL);
- for (size_t i = 0; i < klass->NumStaticFields(); ++i) {
- const Field* static_field = klass->GetStaticField(i);
- char ch = static_field->GetType();
- if (ch == '[' || ch == 'L') {
- const Object* obj = static_field->GetObject();
- MarkObject(obj);
- }
- }
-}
-
void MarkSweep::ScanInterfaces(const Class* klass) {
DCHECK(klass != NULL);
for (size_t i = 0; i < klass->NumInterfaces(); ++i) {
@@ -198,7 +208,7 @@
// Scans the header of all array objects. If the array object is
// specialized to a reference type, scans the array data as well.
-void MarkSweep::ScanArray(const Object *obj) {
+void MarkSweep::ScanArray(const Object* obj) {
DCHECK(obj != NULL);
DCHECK(obj->GetClass() != NULL);
MarkObject(obj->GetClass());
@@ -219,7 +229,7 @@
ref->SetFieldObject(offset, ref);
*list = ref;
} else {
- Object *head = (*list)->GetFieldObject(offset);
+ Object* head = (*list)->GetFieldObject(offset);
ref->SetFieldObject(offset, head);
(*list)->SetFieldObject(offset, ref);
}
@@ -235,7 +245,7 @@
ref = *list;
*list = NULL;
} else {
- Object *next = head->GetFieldObject(offset);
+ Object* next = head->GetFieldObject(offset);
(*list)->SetFieldObject(offset, next);
ref = head;
}
@@ -253,7 +263,7 @@
Object* pending = obj->GetFieldObject(reference_pendingNext_offset_);
Object* referent = obj->GetFieldObject(reference_referent_offset_);
if (pending == NULL && referent != NULL && !IsMarked(referent)) {
- Object **list = NULL;
+ Object** list = NULL;
if (obj->IsSoftReference()) {
list = &soft_reference_list_;
} else if (obj->IsWeakReference()) {
@@ -300,7 +310,7 @@
// anymore, so use a finger that points past the end of them.
void MarkSweep::ProcessMarkStack() {
while (!mark_stack_->IsEmpty()) {
- const Object *obj = mark_stack_->Pop();
+ const Object* obj = mark_stack_->Pop();
ScanObject(obj);
}
}
@@ -367,8 +377,8 @@
DCHECK(list != NULL);
size_t offset = reference_referent_offset_;
while (*list != NULL) {
- Object *ref = DequeuePendingReference(list);
- Object *referent = ref->GetFieldObject(offset);
+ Object* ref = DequeuePendingReference(list);
+ Object* referent = ref->GetFieldObject(offset);
if (referent != NULL && !IsMarked(referent)) {
// Referent is white, clear it.
ClearReference(ref);
@@ -456,7 +466,7 @@
// TODO: Method *meth = gDvm.methJavaLangRefReferenceQueueAdd;
// DCHECK(meth != NULL);
// JValue unused;
- // Object *reference = *cleared;
+ // Object* reference = *cleared;
// TODO: dvmCallMethod(self, meth, NULL, &unused, reference);
UNIMPLEMENTED(FATAL);
*cleared = NULL;
diff --git a/src/mark_sweep.h b/src/mark_sweep.h
index 47a703a..5f374ae 100644
--- a/src/mark_sweep.h
+++ b/src/mark_sweep.h
@@ -70,6 +70,9 @@
// Grays references in static fields.
void ScanStaticFields(const Class* klass);
+ // Used by ScanInstanceFields and ScanStaticFields
+ void ScanFields(const Object* obj, uint32_t ref_offsets, bool is_static);
+
// Grays interface class objects.
void ScanInterfaces(const Class* klass);
diff --git a/src/object.cc b/src/object.cc
index 3200e4d..9316660 100644
--- a/src/object.cc
+++ b/src/object.cc
@@ -161,128 +161,160 @@
return IsInSamePackage(klass1->descriptor_, klass2->descriptor_);
}
-bool Field::GetBoolean() {
- CHECK_EQ(GetType(), 'Z');
- CHECK(IsStatic());
- return declaring_class_->static_32bit_primitives_->Get(offset_);
+uint32_t Field::Get32(const Object* object) const {
+ CHECK((object == NULL) == IsStatic());
+ if (IsStatic()) {
+ object = declaring_class_;
+ }
+ return object->GetField32(GetOffset());
}
-void Field::SetBoolean(bool z) {
- CHECK_EQ(GetType(), 'Z');
- CHECK(IsStatic());
- declaring_class_->static_32bit_primitives_->Set(offset_, z);
+void Field::Set32(Object* object, uint32_t new_value) const {
+ CHECK((object == NULL) == IsStatic());
+ if (IsStatic()) {
+ object = declaring_class_;
+ }
+ object->SetField32(GetOffset(), new_value);
}
-int8_t Field::GetByte() {
+uint64_t Field::Get64(const Object* object) const {
+ CHECK((object == NULL) == IsStatic());
+ if (IsStatic()) {
+ object = declaring_class_;
+ }
+ return object->GetField64(GetOffset());
+}
+
+void Field::Set64(Object* object, uint64_t new_value) const {
+ CHECK((object == NULL) == IsStatic());
+ if (IsStatic()) {
+ object = declaring_class_;
+ }
+ object->SetField64(GetOffset(), new_value);
+}
+
+Object* Field::GetObj(const Object* object) const {
+ CHECK((object == NULL) == IsStatic());
+ if (IsStatic()) {
+ object = declaring_class_;
+ }
+ return object->GetFieldObject(GetOffset());
+}
+
+void Field::SetObj(Object* object, Object* new_value) const {
+ CHECK((object == NULL) == IsStatic());
+ if (IsStatic()) {
+ object = declaring_class_;
+ }
+ object->SetFieldObject(GetOffset(), new_value);
+}
+
+bool Field::GetBoolean(const Object* object) const {
+ CHECK_EQ(GetType(), 'Z');
+ return Get32(object);
+}
+
+void Field::SetBoolean(Object* object, bool z) const {
+ CHECK_EQ(GetType(), 'Z');
+ Set32(object, z);
+}
+
+int8_t Field::GetByte(const Object* object) const {
+ CHECK_EQ(GetType(), 'B');
+ return Get32(object);
+}
+
+void Field::SetByte(Object* object, int8_t b) const {
CHECK_EQ(GetType(), 'B');
CHECK(IsStatic());
- return declaring_class_->static_32bit_primitives_->Get(offset_);
+ Set32(object, b);
}
-void Field::SetByte(int8_t b) {
- CHECK_EQ(GetType(), 'B');
- CHECK(IsStatic());
- declaring_class_->static_32bit_primitives_->Set(offset_, b);
+uint16_t Field::GetChar(const Object* object) const {
+ CHECK_EQ(GetType(), 'C');
+ return Get32(object);
}
-uint16_t Field::GetChar() {
+void Field::SetChar(Object* object, uint16_t c) const {
CHECK_EQ(GetType(), 'C');
CHECK(IsStatic());
- return declaring_class_->static_32bit_primitives_->Get(offset_);
+ Set32(object, c);
}
-void Field::SetChar(uint16_t c) {
- CHECK_EQ(GetType(), 'C');
- CHECK(IsStatic());
- declaring_class_->static_32bit_primitives_->Set(offset_, c);
+uint16_t Field::GetShort(const Object* object) const {
+ CHECK_EQ(GetType(), 'S');
+ return Get32(object);
}
-uint16_t Field::GetShort() {
+void Field::SetShort(Object* object, uint16_t s) const {
CHECK_EQ(GetType(), 'S');
CHECK(IsStatic());
- return declaring_class_->static_32bit_primitives_->Get(offset_);
+ Set32(object, s);
}
-void Field::SetShort(uint16_t s) {
- CHECK_EQ(GetType(), 'S');
- CHECK(IsStatic());
- declaring_class_->static_32bit_primitives_->Set(offset_, s);
+int32_t Field::GetInt(const Object* object) const {
+ CHECK_EQ(GetType(), 'I');
+ return Get32(object);
}
-int32_t Field::GetInt() {
+void Field::SetInt(Object* object, int32_t i) const {
CHECK_EQ(GetType(), 'I');
CHECK(IsStatic());
- return declaring_class_->static_32bit_primitives_->Get(offset_);
+ Set32(object, i);
}
-void Field::SetInt(int32_t i) {
- CHECK_EQ(GetType(), 'I');
- CHECK(IsStatic());
- declaring_class_->static_32bit_primitives_->Set(offset_, i);
+int64_t Field::GetLong(const Object* object) const {
+ CHECK_EQ(GetType(), 'J');
+ return Get64(object);
}
-int64_t Field::GetLong() {
+void Field::SetLong(Object* object, int64_t j) const {
CHECK_EQ(GetType(), 'J');
CHECK(IsStatic());
- return declaring_class_->static_64bit_primitives_->Get(offset_);
+ Set64(object, j);
}
-void Field::SetLong(int64_t j) {
- CHECK_EQ(GetType(), 'J');
- CHECK(IsStatic());
- declaring_class_->static_64bit_primitives_->Set(offset_, j);
-}
-
-float Field::GetFloat() {
+float Field::GetFloat(const Object* object) const {
CHECK_EQ(GetType(), 'F');
- CHECK(IsStatic());
JValue float_bits;
- float_bits.i = declaring_class_->static_32bit_primitives_->Get(offset_);
+ float_bits.i = Get32(object);
return float_bits.f;
}
-void Field::SetFloat(float f) {
+void Field::SetFloat(Object* object, float f) const {
CHECK_EQ(GetType(), 'F');
CHECK(IsStatic());
JValue float_bits;
float_bits.f = f;
- declaring_class_->static_32bit_primitives_->Set(offset_, float_bits.i);
+ Set32(object, float_bits.i);
}
-double Field::GetDouble() {
+double Field::GetDouble(const Object* object) const {
CHECK_EQ(GetType(), 'D');
- CHECK(IsStatic());
JValue double_bits;
- double_bits.j = declaring_class_->static_64bit_primitives_->Get(offset_);
+ double_bits.j = Get64(object);
return double_bits.d;
}
-void Field::SetDouble(double d) {
+void Field::SetDouble(Object* object, double d) const {
CHECK_EQ(GetType(), 'D');
CHECK(IsStatic());
JValue double_bits;
double_bits.d = d;
- declaring_class_->static_64bit_primitives_->Set(offset_, double_bits.j);
+ Set64(object, double_bits.j);
}
-Object* Field::GetObject() {
+Object* Field::GetObject(const Object* object) const {
CHECK(GetType() == 'L' || GetType() == '[');
- CHECK(IsStatic());
- return declaring_class_->static_references_->Get(offset_);
+ return GetObj(object);
}
-const Object* Field::GetObject() const {
+void Field::SetObject(Object* object, Object* l) const {
CHECK(GetType() == 'L' || GetType() == '[');
- CHECK(IsStatic());
- return declaring_class_->static_references_->Get(offset_);
+ SetObj(object, l);
}
-void Field::SetObject(Object* l) {
- CHECK(GetType() == 'L' || GetType() == '[');
- declaring_class_->static_references_->Set(offset_, l); // TODO: write barrier
-}
-
-uint32_t Method::NumArgRegisters() {
+uint32_t Method::NumArgRegisters() const {
CHECK(shorty_ != NULL);
uint32_t num_registers = 0;
for (int i = 1; i < shorty_.length(); ++i) {
@@ -296,7 +328,7 @@
return num_registers;
}
-size_t Method::NumArgArrayBytes() {
+size_t Method::NumArgArrayBytes() const {
const StringPiece& shorty = GetShorty();
size_t num_bytes = 0;
for (int i = 1; i < shorty.size(); ++i) {
diff --git a/src/object.h b/src/object.h
index 6322b8d..840c966 100644
--- a/src/object.h
+++ b/src/object.h
@@ -158,15 +158,9 @@
monitor_->Wait(timeout, nanos);
}
- const Object* GetFieldObject(size_t field_offset) const {
- Object* that = const_cast<Object*>(this);
- Object* other = that->GetFieldObject(field_offset);
- return const_cast<const Object*>(other);
- }
-
- Object* GetFieldObject(size_t field_offset) {
- byte* raw_addr = reinterpret_cast<byte*>(this) + field_offset;
- return *reinterpret_cast<Object**>(raw_addr);
+ Object* GetFieldObject(size_t field_offset) const {
+ const byte* raw_addr = reinterpret_cast<const byte*>(this) + field_offset;
+ return *reinterpret_cast<Object* const *>(raw_addr);
}
void SetFieldObject(size_t offset, Object* new_value) {
@@ -175,6 +169,26 @@
// TODO: write barrier
}
+ uint32_t GetField32(size_t field_offset) const {
+ const byte* raw_addr = reinterpret_cast<const byte*>(this) + field_offset;
+ return *reinterpret_cast<const uint32_t*>(raw_addr);
+ }
+
+ void SetField32(size_t offset, uint32_t new_value) {
+ byte* raw_addr = reinterpret_cast<byte*>(this) + offset;
+ *reinterpret_cast<uint32_t*>(raw_addr) = new_value;
+ }
+
+ uint64_t GetField64(size_t field_offset) const {
+ const byte* raw_addr = reinterpret_cast<const byte*>(this) + field_offset;
+ return *reinterpret_cast<const uint64_t*>(raw_addr);
+ }
+
+ void SetField64(size_t offset, uint64_t new_value) {
+ byte* raw_addr = reinterpret_cast<byte*>(this) + offset;
+ *reinterpret_cast<uint64_t*>(raw_addr) = new_value;
+ }
+
bool IsClass() const;
Class* AsClass() {
@@ -187,6 +201,8 @@
return down_cast<const Class*>(this);
}
+ bool IsClassClass() const;
+
bool IsObjectArray() const;
template<class T>
@@ -252,6 +268,11 @@
return down_cast<Method*>(this);
}
+ const Method* AsMethod() const {
+ DCHECK(IsMethod());
+ return down_cast<const Method*>(this);
+ }
+
bool IsField() const;
Field* AsField() {
@@ -259,6 +280,11 @@
return down_cast<Field*>(this);
}
+ const Field* AsField() const {
+ DCHECK(IsField());
+ return down_cast<const Field*>(this);
+ }
+
public:
Class* klass_;
@@ -335,28 +361,36 @@
offset_ = num_bytes;
}
- // static field access
- bool GetBoolean();
- void SetBoolean(bool z);
- int8_t GetByte();
- void SetByte(int8_t b);
- uint16_t GetChar();
- void SetChar(uint16_t c);
- uint16_t GetShort();
- void SetShort(uint16_t s);
- int32_t GetInt();
- void SetInt(int32_t i);
- int64_t GetLong();
- void SetLong(int64_t j);
- float GetFloat();
- void SetFloat(float f);
- double GetDouble();
- void SetDouble(double d);
- Object* GetObject();
- const Object* GetObject() const;
- void SetObject(Object* l);
+ // field access, null object for static fields
+ bool GetBoolean(const Object* object) const;
+ void SetBoolean(Object* object, bool z) const;
+ int8_t GetByte(const Object* object) const;
+ void SetByte(Object* object, int8_t b) const;
+ uint16_t GetChar(const Object* object) const;
+ void SetChar(Object* object, uint16_t c) const;
+ uint16_t GetShort(const Object* object) const;
+ void SetShort(Object* object, uint16_t s) const;
+ int32_t GetInt(const Object* object) const;
+ void SetInt(Object* object, int32_t i) const;
+ int64_t GetLong(const Object* object) const;
+ void SetLong(Object* object, int64_t j) const;
+ float GetFloat(const Object* object) const;
+ void SetFloat(Object* object, float f) const;
+ double GetDouble(const Object* object) const;
+ void SetDouble(Object* object, double d) const;
+ Object* GetObject(const Object* object) const;
+ void SetObject(Object* object, Object* l) const;
public: // TODO: private
+
+ // private implemention of field access using raw data
+ uint32_t Get32(const Object* object) const;
+ void Set32(Object* object, uint32_t new_value) const;
+ uint64_t Get64(const Object* object) const;
+ void Set64(Object* object, uint64_t new_value) const;
+ Object* GetObj(const Object* object) const;
+ void SetObj(Object* object, Object* new_value) const;
+
// Field order required by test "ValidateFieldOrderOfJavaCppUnionClasses".
// The class in which this field is declared.
Class* declaring_class_;
@@ -445,11 +479,11 @@
}
// Number of argument registers required by the prototype.
- uint32_t NumArgRegisters();
+ uint32_t NumArgRegisters() const;
// Number of argument bytes required for densely packing the
// arguments into an array of arguments.
- size_t NumArgArrayBytes();
+ size_t NumArgArrayBytes() const;
public: // TODO: private
// Field order required by test "ValidateFieldOrderOfJavaCppUnionClasses".
@@ -912,6 +946,10 @@
return descriptor_;
}
+ size_t SizeOf() const {
+ return class_size_;
+ }
+
Status GetStatus() const {
return status_;
}
@@ -1046,6 +1084,11 @@
return num_reference_instance_fields_;
}
+ // Returns the number of static fields containing reference types.
+ size_t NumReferenceStaticFields() const {
+ return num_reference_static_fields_;
+ }
+
// Finds the given instance field in this class or a superclass.
Field* FindInstanceField(const StringPiece& name,
const StringPiece& descriptor);
@@ -1084,12 +1127,20 @@
sfields_->Set(i, f);
}
- uint32_t GetReferenceOffsets() const {
- return reference_offsets_;
+ uint32_t GetReferenceInstanceOffsets() const {
+ return reference_instance_offsets_;
}
- void SetReferenceOffsets(uint32_t new_reference_offsets) {
- reference_offsets_ = new_reference_offsets;
+ void SetReferenceInstanceOffsets(uint32_t new_reference_offsets) {
+ reference_instance_offsets_ = new_reference_offsets;
+ }
+
+ uint32_t GetReferenceStaticOffsets() const {
+ return reference_static_offsets_;
+ }
+
+ void SetReferenceStaticOffsets(uint32_t new_reference_offsets) {
+ reference_static_offsets_ = new_reference_offsets;
}
size_t NumInterfaces() const {
@@ -1220,11 +1271,11 @@
// specifies the number of reference fields.
ObjectArray<Field>* ifields_;
- // number of fields that are object refs
+ // number of instance fields that are object refs
size_t num_reference_instance_fields_;
// Bitmap of offsets of ifields.
- uint32_t reference_offsets_;
+ uint32_t reference_instance_offsets_;
// source file name, if known. Otherwise, NULL.
const char* source_file_;
@@ -1232,18 +1283,17 @@
// Static fields
ObjectArray<Field>* sfields_;
- // static field storage
- //
- // Each static field is stored in one of three arrays:
- // o references are stored in static_references_
- // o doubles and longs are stored in static_64bit_primitives_
- // o everything else is in static_32bit_primitives_
- // Static fields select their array using their type and their index using the
- // Field->slot_ member. Storing static fields in arrays avoids the need for a
- // special case in the GC.
- ObjectArray<Object>* static_references_;
- IntArray* static_32bit_primitives_;
- LongArray* static_64bit_primitives_;
+ // number of static fields that are object refs
+ size_t num_reference_static_fields_;
+
+ // Bitmap of offsets of sfields.
+ uint32_t reference_static_offsets_;
+
+ // Total class size; used when allocating storage on gc heap.
+ size_t class_size_;
+
+ // Location of first static field.
+ uint32_t fields_[0];
private:
DISALLOW_IMPLICIT_CONSTRUCTORS(Class);
@@ -1261,6 +1311,11 @@
return klass_ == java_lang_Class;
}
+inline bool Object::IsClassClass() const {
+ Class* java_lang_Class = klass_->klass_;
+ return this == java_lang_Class;
+}
+
inline bool Object::IsObjectArray() const {
return IsArray() && !klass_->component_type_->IsPrimitive();
}
@@ -1285,6 +1340,9 @@
if (IsArray()) {
return AsArray()->SizeOf();
}
+ if (IsClass()) {
+ return AsClass()->SizeOf();
+ }
return klass_->object_size_;
}
@@ -1292,8 +1350,47 @@
return SizeOf(GetLength(), klass_->GetComponentSize());
}
+class ClassClass : public Class {
+ private:
+ // Padding to ensure the 64-bit serialVersionUID_ begins on a 8-byte boundary
+ int32_t padding_;
+ int64_t serialVersionUID_;
+ DISALLOW_IMPLICIT_CONSTRUCTORS(ClassClass);
+};
+
+class StringClass : public Class {
+ private:
+ CharArray* ASCII_;
+ Object* CASE_INSENSITIVE_ORDER_;
+ uint32_t REPLACEMENT_CHAR_;
+ int64_t serialVersionUID;
+ DISALLOW_IMPLICIT_CONSTRUCTORS(StringClass);
+};
+
+class FieldClass : public Class {
+ private:
+ Object* ORDER_BY_NAME_AND_DECLARING_CLASS_;
+ uint32_t TYPE_BOOLEAN_;
+ uint32_t TYPE_BYTE_;
+ uint32_t TYPE_CHAR_;
+ uint32_t TYPE_DOUBLE_;
+ uint32_t TYPE_FLOAT_;
+ uint32_t TYPE_INTEGER_;
+ uint32_t TYPE_LONG_;
+ uint32_t TYPE_SHORT_;
+ DISALLOW_IMPLICIT_CONSTRUCTORS(FieldClass);
+};
+
+class MethodClass : public Class {
+ private:
+ int32_t DECLARED_;
+ int32_t PUBLIC_;
+ DISALLOW_IMPLICIT_CONSTRUCTORS(MethodClass);
+};
+
class DataObject : public Object {
public:
+ // Location of first instance field.
uint32_t fields_[0];
private:
DISALLOW_IMPLICIT_CONSTRUCTORS(DataObject);
diff --git a/src/object_bitmap.cc b/src/object_bitmap.cc
index 7de4988..40dd41d 100644
--- a/src/object_bitmap.cc
+++ b/src/object_bitmap.cc
@@ -89,7 +89,7 @@
uintptr_t ptr_base = HB_INDEX_TO_OFFSET(i) + base_;
while (word != 0) {
const int shift = CLZ(word);
- Object* obj = (Object *)(ptr_base + shift * kAlignment);
+ Object* obj = (Object*) (ptr_base + shift * kAlignment);
(*callback)(obj, arg);
word &= ~(high_bit >> shift);
}
diff --git a/src/object_bitmap.h b/src/object_bitmap.h
index 3cc973c..3cb1aad 100644
--- a/src/object_bitmap.h
+++ b/src/object_bitmap.h
@@ -48,9 +48,9 @@
public:
static const size_t kAlignment = 8;
- typedef void Callback(Object *obj, void *arg);
+ typedef void Callback(Object* obj, void *arg);
- typedef void ScanCallback(Object *obj, void *finger, void *arg);
+ typedef void ScanCallback(Object* obj, void *finger, void *arg);
typedef void SweepCallback(size_t numPtrs, void **ptrs, void *arg);
diff --git a/src/thread.cc b/src/thread.cc
index 15382b9..d4b7008 100644
--- a/src/thread.cc
+++ b/src/thread.cc
@@ -144,7 +144,7 @@
}
bool Thread::ShbContains(jobject obj) {
- Object **shb_entry = reinterpret_cast<Object**>(obj);
+ Object** shb_entry = reinterpret_cast<Object**>(obj);
for (StackHandleBlock* cur = top_shb_; cur; cur = cur->Link()) {
size_t num_refs = cur->NumberOfReferences();
DCHECK_GT(num_refs, 0u); // A SHB should always have a jobject/jclass