diff options
| -rw-r--r-- | src/class_linker.cc | 320 | ||||
| -rw-r--r-- | src/class_linker.h | 23 | ||||
| -rw-r--r-- | src/class_linker_test.cc | 84 | ||||
| -rw-r--r-- | src/heap.cc | 1 | ||||
| -rw-r--r-- | src/image_writer.cc | 69 | ||||
| -rw-r--r-- | src/image_writer.h | 18 | ||||
| -rw-r--r-- | src/mark_sweep.cc | 70 | ||||
| -rw-r--r-- | src/mark_sweep.h | 3 | ||||
| -rw-r--r-- | src/object.cc | 140 | ||||
| -rw-r--r-- | src/object.h | 195 | ||||
| -rw-r--r-- | src/object_bitmap.cc | 2 | ||||
| -rw-r--r-- | src/object_bitmap.h | 4 | ||||
| -rw-r--r-- | src/thread.cc | 2 |
13 files changed, 581 insertions, 350 deletions
diff --git a/src/class_linker.cc b/src/class_linker.cc index 63791135c6..92cf4de01c 100644 --- a/src/class_linker.cc +++ b/src/class_linker.cc @@ -65,14 +65,14 @@ void ClassLinker::Init(const std::vector<DexFile*>& boot_class_path) { 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 @@ void ClassLinker::Init(const std::vector<DexFile*>& boot_class_path) { 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 @@ void ClassLinker::Init(const std::vector<DexFile*>& boot_class_path) { 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 @@ void ClassLinker::Init(const std::vector<DexFile*>& boot_class_path) { 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 @@ void ClassLinker::Init(const std::vector<DexFile*>& boot_class_path) { // 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 @@ void ClassLinker::Init(const std::vector<DexFile*>& boot_class_path) { 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 @@ void ClassLinker::Init(const std::vector<DexFile*>& boot_class_path, Space* spac 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 @@ DexCache* ClassLinker::AllocDexCache(const DexFile* dex_file) { 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 @@ Class* ClassLinker::FindClass(const StringPiece& descriptor, } 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 @@ Class* ClassLinker::FindClass(const StringPiece& descriptor, 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 @@ DexCache* ClassLinker::FindDexCache(const DexFile* dex_file) const { } 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 @@ Class* ClassLinker::CreateArrayClass(const StringPiece& descriptor, 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 @@ void ClassLinker::InitializeStaticFields(Class* klass) { 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 @@ void ClassLinker::InitializeStaticFields(Class* klass) { 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 @@ bool ClassLinker::LinkClass(Class* klass, const DexFile& dex_file) { if (!LinkMethods(klass)) { return false; } - if (!LinkStaticFields(klass)) { + if (!LinkInstanceFields(klass)) { return false; } - if (!LinkInstanceFields(klass)) { + if (!LinkStaticFields(klass)) { return false; } - CreateReferenceOffsets(klass); + CreateReferenceInstanceOffsets(klass); + CreateReferenceStaticOffsets(klass); CHECK_EQ(Class::kStatusLoaded, klass->status_); klass->status_ = Class::kStatusResolved; return true; @@ -1557,68 +1593,61 @@ void ClassLinker::LinkAbstractMethods(Class* klass) { } } -// 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 @@ bool ClassLinker::LinkInstanceFields(Class* klass) { // 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 @@ bool ClassLinker::LinkInstanceFields(Class* klass) { // 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 @@ bool ClassLinker::LinkInstanceFields(Class* klass) { // 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 @@ bool ClassLinker::LinkInstanceFields(Class* klass) { 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 @@ bool ClassLinker::LinkInstanceFields(Class* klass) { 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; + } + } + 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; } } - klass->SetReferenceOffsets(reference_offsets); } Class* ClassLinker::ResolveClass(const Class* referrer, diff --git a/src/class_linker.h b/src/class_linker.h index 13754db1de..5b629d5e28 100644 --- a/src/class_linker.h +++ b/src/class_linker.h @@ -75,7 +75,7 @@ class ClassLinker { // 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 @@ class ClassLinker { 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 @@ class ClassLinker { 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 @@ class ClassLinker { void LinkAbstractMethods(Class* klass); bool LinkStaticFields(Class* klass); - bool LinkInstanceFields(Class* klass); - - void CreateReferenceOffsets(Class* klass); + bool LinkFields(size_t field_offset, + size_t& num_reference_fields, + size_t num_fields, + ObjectArray<Field>* fields, + size_t& size); + + 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 ca305f195c..2583fcfc7d 100644 --- a/src/class_linker_test.cc +++ b/src/class_linker_test.cc @@ -198,7 +198,7 @@ class ClassLinkerTest : public CommonTest { 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 @@ TEST_F(ClassLinkerTest, StaticFields) { 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(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(NULL, s9->GetObject(NULL)); // TODO: needs clinit to be run? + s9->SetObject(NULL, NULL); + + 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 7369804541..f86f5562df 100644 --- a/src/heap.cc +++ b/src/heap.cc @@ -103,6 +103,7 @@ void Heap::Destroy() { 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 1c7acffd11..39981404e1 100644 --- a/src/image_writer.cc +++ b/src/image_writer.cc @@ -79,7 +79,7 @@ ObjectArray<Object>* CreateInternedArray() { } // 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 @@ void ImageWriter::CopyAndFixupObjects() { 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 @@ void ImageWriter::CopyAndFixupObjectsCallback(Object *obj, void *arg) { 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::FixupObject(Object* orig, Object* copy) { } } -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 @@ void ImageWriter::FixupClass(Class* orig, Class* copy) { 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 @@ void ImageWriter::FixupMethod(Method* orig, Method* copy) { // 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 @@ void ImageWriter::FixupInstanceFields(Object* orig, Object* copy) { 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 8e9ac103cd..ebd86a57b4 100644 --- a/src/image_writer.h +++ b/src/image_writer.h @@ -46,16 +46,18 @@ class ImageWriter { } 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 8541f76c8b..179d95415e 100644 --- a/src/mark_sweep.cc +++ b/src/mark_sweep.cc @@ -126,8 +126,24 @@ void MarkSweep::Sweep() { // 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 @@ void MarkSweep::ScanInstanceFields(const Object* obj) { 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 @@ void MarkSweep::ScanInstanceFields(const Object* obj) { } } -// 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 @@ void MarkSweep::ScanClass(const Object* obj) { // 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 @@ void MarkSweep::EnqueuePendingReference(Object* ref, Object** list) { 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 @@ Object* MarkSweep::DequeuePendingReference(Object** list) { 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 @@ void MarkSweep::DelayReferenceReferent(Object* obj) { 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 @@ void MarkSweep::ScanObject(const Object* obj) { // 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 @@ void MarkSweep::ClearWhiteReferences(Object** list) { 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 @@ void MarkSweep::EnqueueClearedReferences(Object** cleared) { // 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 47a703a5d1..5f374ae9e4 100644 --- a/src/mark_sweep.h +++ b/src/mark_sweep.h @@ -70,6 +70,9 @@ class MarkSweep { // 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 3200e4d051..93166602d8 100644 --- a/src/object.cc +++ b/src/object.cc @@ -161,128 +161,160 @@ bool Class::IsInSamePackage(const Class* that) const { return IsInSamePackage(klass1->descriptor_, klass2->descriptor_); } -bool Field::GetBoolean() { +uint32_t Field::Get32(const Object* object) const { + CHECK((object == NULL) == IsStatic()); + if (IsStatic()) { + object = declaring_class_; + } + return object->GetField32(GetOffset()); +} + +void Field::Set32(Object* object, uint32_t new_value) const { + CHECK((object == NULL) == IsStatic()); + if (IsStatic()) { + object = declaring_class_; + } + object->SetField32(GetOffset(), new_value); +} + +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'); - CHECK(IsStatic()); - return declaring_class_->static_32bit_primitives_->Get(offset_); + return Get32(object); } -void Field::SetBoolean(bool z) { +void Field::SetBoolean(Object* object, bool z) const { CHECK_EQ(GetType(), 'Z'); - CHECK(IsStatic()); - declaring_class_->static_32bit_primitives_->Set(offset_, z); + Set32(object, z); } -int8_t Field::GetByte() { +int8_t Field::GetByte(const Object* object) const { CHECK_EQ(GetType(), 'B'); - CHECK(IsStatic()); - return declaring_class_->static_32bit_primitives_->Get(offset_); + return Get32(object); } -void Field::SetByte(int8_t b) { +void Field::SetByte(Object* object, int8_t b) const { CHECK_EQ(GetType(), 'B'); CHECK(IsStatic()); - declaring_class_->static_32bit_primitives_->Set(offset_, b); + Set32(object, b); } -uint16_t Field::GetChar() { +uint16_t Field::GetChar(const Object* object) const { CHECK_EQ(GetType(), 'C'); - CHECK(IsStatic()); - return declaring_class_->static_32bit_primitives_->Get(offset_); + return Get32(object); } -void Field::SetChar(uint16_t c) { +void Field::SetChar(Object* object, uint16_t c) const { CHECK_EQ(GetType(), 'C'); CHECK(IsStatic()); - declaring_class_->static_32bit_primitives_->Set(offset_, c); + Set32(object, c); } -uint16_t Field::GetShort() { +uint16_t Field::GetShort(const Object* object) const { CHECK_EQ(GetType(), 'S'); - CHECK(IsStatic()); - return declaring_class_->static_32bit_primitives_->Get(offset_); + return Get32(object); } -void Field::SetShort(uint16_t s) { +void Field::SetShort(Object* object, uint16_t s) const { CHECK_EQ(GetType(), 'S'); CHECK(IsStatic()); - declaring_class_->static_32bit_primitives_->Set(offset_, s); + Set32(object, s); } -int32_t Field::GetInt() { +int32_t Field::GetInt(const Object* object) const { CHECK_EQ(GetType(), 'I'); - CHECK(IsStatic()); - return declaring_class_->static_32bit_primitives_->Get(offset_); + return Get32(object); } -void Field::SetInt(int32_t i) { +void Field::SetInt(Object* object, int32_t i) const { CHECK_EQ(GetType(), 'I'); CHECK(IsStatic()); - declaring_class_->static_32bit_primitives_->Set(offset_, i); + Set32(object, i); } -int64_t Field::GetLong() { +int64_t Field::GetLong(const Object* object) const { CHECK_EQ(GetType(), 'J'); - CHECK(IsStatic()); - return declaring_class_->static_64bit_primitives_->Get(offset_); + return Get64(object); } -void Field::SetLong(int64_t j) { +void Field::SetLong(Object* object, int64_t j) const { CHECK_EQ(GetType(), 'J'); CHECK(IsStatic()); - declaring_class_->static_64bit_primitives_->Set(offset_, j); + Set64(object, 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_); -} - -const Object* Field::GetObject() const { - CHECK(GetType() == 'L' || GetType() == '['); - CHECK(IsStatic()); - return declaring_class_->static_references_->Get(offset_); + return GetObj(object); } -void Field::SetObject(Object* l) { +void Field::SetObject(Object* object, Object* l) const { CHECK(GetType() == 'L' || GetType() == '['); - declaring_class_->static_references_->Set(offset_, l); // TODO: write barrier + SetObj(object, l); } -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 @@ uint32_t Method::NumArgRegisters() { 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 6322b8d9c9..840c9665d9 100644 --- a/src/object.h +++ b/src/object.h @@ -158,15 +158,9 @@ class Object { 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 @@ class Object { // 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 @@ class Object { return down_cast<const Class*>(this); } + bool IsClassClass() const; + bool IsObjectArray() const; template<class T> @@ -252,6 +268,11 @@ class Object { 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 @@ class Object { return down_cast<Field*>(this); } + const Field* AsField() const { + DCHECK(IsField()); + return down_cast<const Field*>(this); + } + public: Class* klass_; @@ -335,28 +361,36 @@ class Field : public AccessibleObject { 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 @@ class Method : public AccessibleObject { } // 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 @@ class Class : public Object { return descriptor_; } + size_t SizeOf() const { + return class_size_; + } + Status GetStatus() const { return status_; } @@ -1046,6 +1084,11 @@ class Class : public Object { 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 @@ class Class : public Object { 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 @@ class Class : public Object { // 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 @@ class Class : public Object { // 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 @@ inline bool Object::IsClass() const { 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 @@ inline size_t Object::SizeOf() const { if (IsArray()) { return AsArray()->SizeOf(); } + if (IsClass()) { + return AsClass()->SizeOf(); + } return klass_->object_size_; } @@ -1292,8 +1350,47 @@ inline size_t Array::SizeOf() const { 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 7de498860d..40dd41d4df 100644 --- a/src/object_bitmap.cc +++ b/src/object_bitmap.cc @@ -89,7 +89,7 @@ void HeapBitmap::Walk(HeapBitmap::Callback* callback, void* arg) { 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 3cc973cea8..3cb1aad8d8 100644 --- a/src/object_bitmap.h +++ b/src/object_bitmap.h @@ -48,9 +48,9 @@ class HeapBitmap { 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 15382b9e9f..d4b700850a 100644 --- a/src/thread.cc +++ b/src/thread.cc @@ -144,7 +144,7 @@ size_t Thread::NumShbHandles() { } 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 |