Change enums in ImageWriter to `enum class`.
Test: m test-art-host-gtest
Test: testrunner.py --host --optimizing
Change-Id: I0f6687f6b99b78a2a56064ed96cba4e238bc01cd
diff --git a/dex2oat/linker/image_writer.cc b/dex2oat/linker/image_writer.cc
index 68c9f80..5ade583 100644
--- a/dex2oat/linker/image_writer.cc
+++ b/dex2oat/linker/image_writer.cc
@@ -365,7 +365,7 @@
size_t oat_index = GetOatIndex(object);
ImageInfo& image_info = GetImageInfo(oat_index);
- size_t bin_slot_offset = image_info.bin_slot_offsets_[bin_slot.GetBin()];
+ size_t bin_slot_offset = image_info.GetBinSlotOffset(bin_slot.GetBin());
size_t new_offset = bin_slot_offset + bin_slot.GetIndex();
DCHECK_ALIGNED(new_offset, kObjectAlignment);
@@ -436,9 +436,10 @@
auto it = dex_file_oat_index_map_.find(dex_file);
DCHECK(it != dex_file_oat_index_map_.end()) << dex_file->GetLocation();
ImageInfo& image_info = GetImageInfo(it->second);
- image_info.dex_cache_array_starts_.Put(dex_file, image_info.bin_slot_sizes_[kBinDexCacheArray]);
+ image_info.dex_cache_array_starts_.Put(
+ dex_file, image_info.GetBinSlotSize(Bin::kDexCacheArray));
DexCacheArraysLayout layout(target_ptr_size_, dex_file);
- image_info.bin_slot_sizes_[kBinDexCacheArray] += layout.Size();
+ image_info.IncrementBinSlotSize(Bin::kDexCacheArray, layout.Size());
}
ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
@@ -494,7 +495,7 @@
DCHECK(!IsInBootImage(array));
size_t oat_index = GetOatIndexForDexCache(dex_cache);
native_object_relocations_.emplace(array,
- NativeObjectRelocation { oat_index, offset, kNativeObjectRelocationTypeDexCacheArray });
+ NativeObjectRelocation { oat_index, offset, NativeObjectRelocationType::kDexCacheArray });
}
}
@@ -512,7 +513,7 @@
}
// kBinArtMethodClean picked arbitrarily, just required to differentiate between ArtFields and
// ArtMethods.
- pointer_arrays_.emplace(arr, kBinArtMethodClean);
+ pointer_arrays_.emplace(arr, Bin::kArtMethodClean);
}
void ImageWriter::AssignImageBinSlot(mirror::Object* object, size_t oat_index) {
@@ -528,8 +529,7 @@
//
// This means more pages will stay either clean or shared dirty (with zygote) and
// the app will use less of its own (private) memory.
- Bin bin = kBinRegular;
- size_t current_offset = 0u;
+ Bin bin = Bin::kRegular;
if (kBinObjects) {
//
@@ -563,7 +563,7 @@
// so packing them together will not result in a noticeably tighter dirty-to-clean ratio.
//
if (object->IsClass()) {
- bin = kBinClassVerified;
+ bin = Bin::kClassVerified;
mirror::Class* klass = object->AsClass();
// Add non-embedded vtable to the pointer array table if there is one.
@@ -584,15 +584,15 @@
// - classes with dirty static fields.
if (dirty_image_objects_ != nullptr &&
dirty_image_objects_->find(klass->PrettyDescriptor()) != dirty_image_objects_->end()) {
- bin = kBinKnownDirty;
+ bin = Bin::kKnownDirty;
} else if (klass->GetStatus() == Class::kStatusInitialized) {
- bin = kBinClassInitialized;
+ bin = Bin::kClassInitialized;
// If the class's static fields are all final, put it into a separate bin
// since it's very likely it will stay clean.
uint32_t num_static_fields = klass->NumStaticFields();
if (num_static_fields == 0) {
- bin = kBinClassInitializedFinalStatics;
+ bin = Bin::kClassInitializedFinalStatics;
} else {
// Maybe all the statics are final?
bool all_final = true;
@@ -605,20 +605,20 @@
}
if (all_final) {
- bin = kBinClassInitializedFinalStatics;
+ bin = Bin::kClassInitializedFinalStatics;
}
}
}
} else if (object->GetClass<kVerifyNone>()->IsStringClass()) {
- bin = kBinString; // Strings are almost always immutable (except for object header).
+ bin = Bin::kString; // Strings are almost always immutable (except for object header).
} else if (object->GetClass<kVerifyNone>() ==
Runtime::Current()->GetClassLinker()->GetClassRoot(ClassLinker::kJavaLangObject)) {
// Instance of java lang object, probably a lock object. This means it will be dirty when we
// synchronize on it.
- bin = kBinMiscDirty;
+ bin = Bin::kMiscDirty;
} else if (object->IsDexCache()) {
// Dex file field becomes dirty when the image is loaded.
- bin = kBinMiscDirty;
+ bin = Bin::kMiscDirty;
}
// else bin = kBinRegular
}
@@ -630,14 +630,15 @@
ImageInfo& image_info = GetImageInfo(oat_index);
size_t offset_delta = RoundUp(object_size, kObjectAlignment); // 64-bit alignment
- current_offset = image_info.bin_slot_sizes_[bin]; // How many bytes the current bin is at (aligned).
+ // How many bytes the current bin is at (aligned).
+ size_t current_offset = image_info.GetBinSlotSize(bin);
// Move the current bin size up to accommodate the object we just assigned a bin slot.
- image_info.bin_slot_sizes_[bin] += offset_delta;
+ image_info.IncrementBinSlotSize(bin, offset_delta);
BinSlot new_bin_slot(bin, current_offset);
SetImageBinSlot(object, new_bin_slot);
- ++image_info.bin_slot_count_[bin];
+ image_info.IncrementBinSlotCount(bin, 1u);
// Grow the image closer to the end by the object we just assigned.
image_info.image_end_ += offset_delta;
@@ -665,7 +666,7 @@
BinSlot bin_slot(offset);
size_t oat_index = GetOatIndex(object);
const ImageInfo& image_info = GetImageInfo(oat_index);
- DCHECK_LT(bin_slot.GetIndex(), image_info.bin_slot_sizes_[bin_slot.GetBin()])
+ DCHECK_LT(bin_slot.GetIndex(), image_info.GetBinSlotSize(bin_slot.GetBin()))
<< "bin slot offset should not exceed the size of that bin";
}
return true;
@@ -682,7 +683,7 @@
BinSlot bin_slot(static_cast<uint32_t>(offset));
size_t oat_index = GetOatIndex(object);
const ImageInfo& image_info = GetImageInfo(oat_index);
- DCHECK_LT(bin_slot.GetIndex(), image_info.bin_slot_sizes_[bin_slot.GetBin()]);
+ DCHECK_LT(bin_slot.GetIndex(), image_info.GetBinSlotSize(bin_slot.GetBin()));
return bin_slot;
}
@@ -1402,12 +1403,12 @@
auto it = native_object_relocations_.find(cur_fields);
CHECK(it == native_object_relocations_.end()) << "Field array " << cur_fields
<< " already forwarded";
- size_t& offset = image_info.bin_slot_sizes_[kBinArtField];
+ size_t offset = image_info.GetBinSlotSize(Bin::kArtField);
DCHECK(!IsInBootImage(cur_fields));
native_object_relocations_.emplace(
cur_fields,
NativeObjectRelocation {
- oat_index, offset, kNativeObjectRelocationTypeArtFieldArray
+ oat_index, offset, NativeObjectRelocationType::kArtFieldArray
});
offset += header_size;
// Forward individual fields so that we can quickly find where they belong.
@@ -1420,9 +1421,14 @@
DCHECK(!IsInBootImage(field));
native_object_relocations_.emplace(
field,
- NativeObjectRelocation { oat_index, offset, kNativeObjectRelocationTypeArtField });
+ NativeObjectRelocation { oat_index,
+ offset,
+ NativeObjectRelocationType::kArtField });
offset += sizeof(ArtField);
}
+ image_info.IncrementBinSlotSize(
+ Bin::kArtField, header_size + cur_fields->size() * sizeof(ArtField));
+ DCHECK_EQ(offset, image_info.GetBinSlotSize(Bin::kArtField));
}
}
// Visit and assign offsets for methods.
@@ -1436,8 +1442,8 @@
}
}
NativeObjectRelocationType type = any_dirty
- ? kNativeObjectRelocationTypeArtMethodDirty
- : kNativeObjectRelocationTypeArtMethodClean;
+ ? NativeObjectRelocationType::kArtMethodDirty
+ : NativeObjectRelocationType::kArtMethodClean;
Bin bin_type = BinTypeForNativeRelocationType(type);
// Forward the entire array at once, but header first.
const size_t method_alignment = ArtMethod::Alignment(target_ptr_size_);
@@ -1449,15 +1455,15 @@
auto it = native_object_relocations_.find(array);
CHECK(it == native_object_relocations_.end())
<< "Method array " << array << " already forwarded";
- size_t& offset = image_info.bin_slot_sizes_[bin_type];
+ size_t offset = image_info.GetBinSlotSize(bin_type);
DCHECK(!IsInBootImage(array));
native_object_relocations_.emplace(array,
NativeObjectRelocation {
oat_index,
offset,
- any_dirty ? kNativeObjectRelocationTypeArtMethodArrayDirty
- : kNativeObjectRelocationTypeArtMethodArrayClean });
- offset += header_size;
+ any_dirty ? NativeObjectRelocationType::kArtMethodArrayDirty
+ : NativeObjectRelocationType::kArtMethodArrayClean });
+ image_info.IncrementBinSlotSize(bin_type, header_size);
for (auto& m : as_klass->GetMethods(target_ptr_size_)) {
AssignMethodOffset(&m, type, oat_index);
}
@@ -1476,7 +1482,7 @@
if (imt_method->IsRuntimeMethod() &&
!IsInBootImage(imt_method) &&
!NativeRelocationAssigned(imt_method)) {
- AssignMethodOffset(imt_method, kNativeObjectRelocationTypeRuntimeMethod, oat_index);
+ AssignMethodOffset(imt_method, NativeObjectRelocationType::kRuntimeMethod, oat_index);
}
}
}
@@ -1526,9 +1532,9 @@
imt,
NativeObjectRelocation {
oat_index,
- image_info.bin_slot_sizes_[kBinImTable],
- kNativeObjectRelocationTypeIMTable});
- image_info.bin_slot_sizes_[kBinImTable] += size;
+ image_info.GetBinSlotSize(Bin::kImTable),
+ NativeObjectRelocationType::kIMTable});
+ image_info.IncrementBinSlotSize(Bin::kImTable, size);
return true;
}
@@ -1545,9 +1551,9 @@
table,
NativeObjectRelocation {
oat_index,
- image_info.bin_slot_sizes_[kBinIMTConflictTable],
- kNativeObjectRelocationTypeIMTConflictTable});
- image_info.bin_slot_sizes_[kBinIMTConflictTable] += size;
+ image_info.GetBinSlotSize(Bin::kIMTConflictTable),
+ NativeObjectRelocationType::kIMTConflictTable});
+ image_info.IncrementBinSlotSize(Bin::kIMTConflictTable, size);
}
void ImageWriter::AssignMethodOffset(ArtMethod* method,
@@ -1560,9 +1566,10 @@
TryAssignConflictTableOffset(method->GetImtConflictTable(target_ptr_size_), oat_index);
}
ImageInfo& image_info = GetImageInfo(oat_index);
- size_t& offset = image_info.bin_slot_sizes_[BinTypeForNativeRelocationType(type)];
+ Bin bin_type = BinTypeForNativeRelocationType(type);
+ size_t offset = image_info.GetBinSlotSize(bin_type);
native_object_relocations_.emplace(method, NativeObjectRelocation { oat_index, offset, type });
- offset += ArtMethod::Size(target_ptr_size_);
+ image_info.IncrementBinSlotSize(bin_type, ArtMethod::Size(target_ptr_size_));
}
void ImageWriter::UnbinObjectsIntoOffset(mirror::Object* obj) {
@@ -1697,7 +1704,7 @@
CHECK(m->IsRuntimeMethod());
DCHECK_EQ(compile_app_image_, IsInBootImage(m)) << "Trampolines should be in boot image";
if (!IsInBootImage(m)) {
- AssignMethodOffset(m, kNativeObjectRelocationTypeRuntimeMethod, GetDefaultOatIndex());
+ AssignMethodOffset(m, NativeObjectRelocationType::kRuntimeMethod, GetDefaultOatIndex());
}
}
@@ -1803,18 +1810,18 @@
// Calculate bin slot offsets.
for (ImageInfo& image_info : image_infos_) {
size_t bin_offset = image_objects_offset_begin_;
- for (size_t i = 0; i != kBinSize; ++i) {
- switch (i) {
- case kBinArtMethodClean:
- case kBinArtMethodDirty: {
+ for (size_t i = 0; i != kNumberOfBins; ++i) {
+ switch (static_cast<Bin>(i)) {
+ case Bin::kArtMethodClean:
+ case Bin::kArtMethodDirty: {
bin_offset = RoundUp(bin_offset, method_alignment);
break;
}
- case kBinDexCacheArray:
+ case Bin::kDexCacheArray:
bin_offset = RoundUp(bin_offset, DexCacheArraysLayout::Alignment(target_ptr_size_));
break;
- case kBinImTable:
- case kBinIMTConflictTable: {
+ case Bin::kImTable:
+ case Bin::kIMTConflictTable: {
bin_offset = RoundUp(bin_offset, static_cast<size_t>(target_ptr_size_));
break;
}
@@ -1827,7 +1834,7 @@
}
// NOTE: There may be additional padding between the bin slots and the intern table.
DCHECK_EQ(image_info.image_end_,
- GetBinSizeSum(image_info, kBinMirrorCount) + image_objects_offset_begin_);
+ image_info.GetBinSizeSum(Bin::kMirrorCount) + image_objects_offset_begin_);
}
// Calculate image offsets.
@@ -1864,7 +1871,7 @@
NativeObjectRelocation& relocation = pair.second;
Bin bin_type = BinTypeForNativeRelocationType(relocation.type);
ImageInfo& image_info = GetImageInfo(relocation.oat_index);
- relocation.offset += image_info.bin_slot_offsets_[bin_type];
+ relocation.offset += image_info.GetBinSlotOffset(bin_type);
}
}
@@ -1881,33 +1888,32 @@
// Add field section.
ImageSection* field_section = &out_sections[ImageHeader::kSectionArtFields];
- *field_section = ImageSection(bin_slot_offsets_[kBinArtField], bin_slot_sizes_[kBinArtField]);
- CHECK_EQ(bin_slot_offsets_[kBinArtField], field_section->Offset());
+ *field_section = ImageSection(GetBinSlotOffset(Bin::kArtField), GetBinSlotSize(Bin::kArtField));
// Add method section.
ImageSection* methods_section = &out_sections[ImageHeader::kSectionArtMethods];
*methods_section = ImageSection(
- bin_slot_offsets_[kBinArtMethodClean],
- bin_slot_sizes_[kBinArtMethodClean] + bin_slot_sizes_[kBinArtMethodDirty]);
+ GetBinSlotOffset(Bin::kArtMethodClean),
+ GetBinSlotSize(Bin::kArtMethodClean) + GetBinSlotSize(Bin::kArtMethodDirty));
// IMT section.
ImageSection* imt_section = &out_sections[ImageHeader::kSectionImTables];
- *imt_section = ImageSection(bin_slot_offsets_[kBinImTable], bin_slot_sizes_[kBinImTable]);
+ *imt_section = ImageSection(GetBinSlotOffset(Bin::kImTable), GetBinSlotSize(Bin::kImTable));
// Conflict tables section.
ImageSection* imt_conflict_tables_section = &out_sections[ImageHeader::kSectionIMTConflictTables];
- *imt_conflict_tables_section = ImageSection(bin_slot_offsets_[kBinIMTConflictTable],
- bin_slot_sizes_[kBinIMTConflictTable]);
+ *imt_conflict_tables_section = ImageSection(GetBinSlotOffset(Bin::kIMTConflictTable),
+ GetBinSlotSize(Bin::kIMTConflictTable));
// Runtime methods section.
ImageSection* runtime_methods_section = &out_sections[ImageHeader::kSectionRuntimeMethods];
- *runtime_methods_section = ImageSection(bin_slot_offsets_[kBinRuntimeMethod],
- bin_slot_sizes_[kBinRuntimeMethod]);
+ *runtime_methods_section = ImageSection(GetBinSlotOffset(Bin::kRuntimeMethod),
+ GetBinSlotSize(Bin::kRuntimeMethod));
// Add dex cache arrays section.
ImageSection* dex_cache_arrays_section = &out_sections[ImageHeader::kSectionDexCacheArrays];
- *dex_cache_arrays_section = ImageSection(bin_slot_offsets_[kBinDexCacheArray],
- bin_slot_sizes_[kBinDexCacheArray]);
+ *dex_cache_arrays_section = ImageSection(GetBinSlotOffset(Bin::kDexCacheArray),
+ GetBinSlotSize(Bin::kDexCacheArray));
// For boot image, round up to the page boundary to separate the interned strings and
// class table from the modifiable data. We shall mprotect() these pages read-only when
// we load the boot image. This is more than sufficient for the string table alignment,
@@ -2060,16 +2066,16 @@
DCHECK_GE(dest, image_info.image_->Begin() + image_info.image_end_);
DCHECK(!IsInBootImage(pair.first));
switch (relocation.type) {
- case kNativeObjectRelocationTypeArtField: {
+ case NativeObjectRelocationType::kArtField: {
memcpy(dest, pair.first, sizeof(ArtField));
CopyReference(
reinterpret_cast<ArtField*>(dest)->GetDeclaringClassAddressWithoutBarrier(),
reinterpret_cast<ArtField*>(pair.first)->GetDeclaringClass().Ptr());
break;
}
- case kNativeObjectRelocationTypeRuntimeMethod:
- case kNativeObjectRelocationTypeArtMethodClean:
- case kNativeObjectRelocationTypeArtMethodDirty: {
+ case NativeObjectRelocationType::kRuntimeMethod:
+ case NativeObjectRelocationType::kArtMethodClean:
+ case NativeObjectRelocationType::kArtMethodDirty: {
CopyAndFixupMethod(reinterpret_cast<ArtMethod*>(pair.first),
reinterpret_cast<ArtMethod*>(dest),
image_info);
@@ -2077,12 +2083,12 @@
}
// For arrays, copy just the header since the elements will get copied by their corresponding
// relocations.
- case kNativeObjectRelocationTypeArtFieldArray: {
+ case NativeObjectRelocationType::kArtFieldArray: {
memcpy(dest, pair.first, LengthPrefixedArray<ArtField>::ComputeSize(0));
break;
}
- case kNativeObjectRelocationTypeArtMethodArrayClean:
- case kNativeObjectRelocationTypeArtMethodArrayDirty: {
+ case NativeObjectRelocationType::kArtMethodArrayClean:
+ case NativeObjectRelocationType::kArtMethodArrayDirty: {
size_t size = ArtMethod::Size(target_ptr_size_);
size_t alignment = ArtMethod::Alignment(target_ptr_size_);
memcpy(dest, pair.first, LengthPrefixedArray<ArtMethod>::ComputeSize(0, size, alignment));
@@ -2090,16 +2096,16 @@
reinterpret_cast<LengthPrefixedArray<ArtMethod>*>(dest)->ClearPadding(size, alignment);
break;
}
- case kNativeObjectRelocationTypeDexCacheArray:
+ case NativeObjectRelocationType::kDexCacheArray:
// Nothing to copy here, everything is done in FixupDexCache().
break;
- case kNativeObjectRelocationTypeIMTable: {
+ case NativeObjectRelocationType::kIMTable: {
ImTable* orig_imt = reinterpret_cast<ImTable*>(pair.first);
ImTable* dest_imt = reinterpret_cast<ImTable*>(dest);
CopyAndFixupImTable(orig_imt, dest_imt);
break;
}
- case kNativeObjectRelocationTypeIMTConflictTable: {
+ case NativeObjectRelocationType::kIMTConflictTable: {
auto* orig_table = reinterpret_cast<ImtConflictTable*>(pair.first);
CopyAndFixupImtConflictTable(
orig_table,
@@ -2197,7 +2203,7 @@
<< method << " idx=" << i << "/" << num_elements << " with declaring class "
<< Class::PrettyClass(method->GetDeclaringClass());
} else {
- CHECK_EQ(array_type, kBinArtField);
+ CHECK_EQ(array_type, Bin::kArtField);
auto* field = reinterpret_cast<ArtField*>(elem);
LOG(FATAL) << "No relocation entry for ArtField " << field->PrettyField() << " @ "
<< field << " idx=" << i << "/" << num_elements << " with declaring class "
@@ -2518,8 +2524,8 @@
copy_dex_cache->SetDexFile(nullptr);
}
-const uint8_t* ImageWriter::GetOatAddress(OatAddress type) const {
- DCHECK_LT(type, kOatAddressCount);
+const uint8_t* ImageWriter::GetOatAddress(StubType type) const {
+ DCHECK_LE(type, StubType::kLast);
// If we are compiling an app image, we need to use the stubs of the boot image.
if (compile_app_image_) {
// Use the current image pointers.
@@ -2531,26 +2537,26 @@
const OatHeader& header = oat_file->GetOatHeader();
switch (type) {
// TODO: We could maybe clean this up if we stored them in an array in the oat header.
- case kOatAddressQuickGenericJNITrampoline:
+ case StubType::kQuickGenericJNITrampoline:
return static_cast<const uint8_t*>(header.GetQuickGenericJniTrampoline());
- case kOatAddressInterpreterToInterpreterBridge:
+ case StubType::kInterpreterToInterpreterBridge:
return static_cast<const uint8_t*>(header.GetInterpreterToInterpreterBridge());
- case kOatAddressInterpreterToCompiledCodeBridge:
+ case StubType::kInterpreterToCompiledCodeBridge:
return static_cast<const uint8_t*>(header.GetInterpreterToCompiledCodeBridge());
- case kOatAddressJNIDlsymLookup:
+ case StubType::kJNIDlsymLookup:
return static_cast<const uint8_t*>(header.GetJniDlsymLookup());
- case kOatAddressQuickIMTConflictTrampoline:
+ case StubType::kQuickIMTConflictTrampoline:
return static_cast<const uint8_t*>(header.GetQuickImtConflictTrampoline());
- case kOatAddressQuickResolutionTrampoline:
+ case StubType::kQuickResolutionTrampoline:
return static_cast<const uint8_t*>(header.GetQuickResolutionTrampoline());
- case kOatAddressQuickToInterpreterBridge:
+ case StubType::kQuickToInterpreterBridge:
return static_cast<const uint8_t*>(header.GetQuickToInterpreterBridge());
default:
UNREACHABLE();
}
}
const ImageInfo& primary_image_info = GetImageInfo(0);
- return GetOatAddressForOffset(primary_image_info.oat_address_offsets_[type], primary_image_info);
+ return GetOatAddressForOffset(primary_image_info.GetStubOffset(type), primary_image_info);
}
const uint8_t* ImageWriter::GetQuickCode(ArtMethod* method,
@@ -2586,16 +2592,16 @@
} else if (quick_code == nullptr && method->IsNative() &&
(!method->IsStatic() || method->GetDeclaringClass()->IsInitialized())) {
// Non-static or initialized native method missing compiled code, use generic JNI version.
- quick_code = GetOatAddress(kOatAddressQuickGenericJNITrampoline);
+ quick_code = GetOatAddress(StubType::kQuickGenericJNITrampoline);
} else if (quick_code == nullptr && !method->IsNative()) {
// We don't have code at all for a non-native method, use the interpreter.
- quick_code = GetOatAddress(kOatAddressQuickToInterpreterBridge);
+ quick_code = GetOatAddress(StubType::kQuickToInterpreterBridge);
*quick_is_interpreted = true;
} else {
CHECK(!method->GetDeclaringClass()->IsInitialized());
// We have code for a static method, but need to go through the resolution stub for class
// initialization.
- quick_code = GetOatAddress(kOatAddressQuickResolutionTrampoline);
+ quick_code = GetOatAddress(StubType::kQuickResolutionTrampoline);
}
if (!IsInBootOatFile(quick_code)) {
// DCHECK_GE(quick_code, oat_data_begin_);
@@ -2630,11 +2636,11 @@
if (orig_table != nullptr) {
// Special IMT conflict method, normal IMT conflict method or unimplemented IMT method.
copy->SetEntryPointFromQuickCompiledCodePtrSize(
- GetOatAddress(kOatAddressQuickIMTConflictTrampoline), target_ptr_size_);
+ GetOatAddress(StubType::kQuickIMTConflictTrampoline), target_ptr_size_);
copy->SetImtConflictTable(NativeLocationInImage(orig_table), target_ptr_size_);
} else if (UNLIKELY(orig == runtime->GetResolutionMethod())) {
copy->SetEntryPointFromQuickCompiledCodePtrSize(
- GetOatAddress(kOatAddressQuickResolutionTrampoline), target_ptr_size_);
+ GetOatAddress(StubType::kQuickResolutionTrampoline), target_ptr_size_);
} else {
bool found_one = false;
for (size_t i = 0; i < static_cast<size_t>(CalleeSaveType::kLastCalleeSaveType); ++i) {
@@ -2653,7 +2659,7 @@
// use results in an AbstractMethodError. We use the interpreter to achieve this.
if (UNLIKELY(!orig->IsInvokable())) {
copy->SetEntryPointFromQuickCompiledCodePtrSize(
- GetOatAddress(kOatAddressQuickToInterpreterBridge), target_ptr_size_);
+ GetOatAddress(StubType::kQuickToInterpreterBridge), target_ptr_size_);
} else {
bool quick_is_interpreted;
const uint8_t* quick_code = GetQuickCode(orig, image_info, &quick_is_interpreted);
@@ -2664,17 +2670,17 @@
// The native method's pointer is set to a stub to lookup via dlsym.
// Note this is not the code_ pointer, that is handled above.
copy->SetEntryPointFromJniPtrSize(
- GetOatAddress(kOatAddressJNIDlsymLookup), target_ptr_size_);
+ GetOatAddress(StubType::kJNIDlsymLookup), target_ptr_size_);
}
}
}
}
-size_t ImageWriter::GetBinSizeSum(ImageWriter::ImageInfo& image_info, ImageWriter::Bin up_to) const {
- DCHECK_LE(up_to, kBinSize);
- return std::accumulate(&image_info.bin_slot_sizes_[0],
- &image_info.bin_slot_sizes_[up_to],
- /*init*/0);
+size_t ImageWriter::ImageInfo::GetBinSizeSum(Bin up_to) const {
+ DCHECK_LE(static_cast<size_t>(up_to), kNumberOfBins);
+ return std::accumulate(&bin_slot_sizes_[0],
+ &bin_slot_sizes_[0] + static_cast<size_t>(up_to),
+ /*init*/ static_cast<size_t>(0));
}
ImageWriter::BinSlot::BinSlot(uint32_t lockword) : lockword_(lockword) {
@@ -2683,7 +2689,7 @@
static_assert(kBinShift == 27, "wrong number of shift");
static_assert(sizeof(BinSlot) == sizeof(LockWord), "BinSlot/LockWord must have equal sizes");
- DCHECK_LT(GetBin(), kBinSize);
+ DCHECK_LT(GetBin(), Bin::kMirrorCount);
DCHECK_ALIGNED(GetIndex(), kObjectAlignment);
}
@@ -2702,23 +2708,23 @@
ImageWriter::Bin ImageWriter::BinTypeForNativeRelocationType(NativeObjectRelocationType type) {
switch (type) {
- case kNativeObjectRelocationTypeArtField:
- case kNativeObjectRelocationTypeArtFieldArray:
- return kBinArtField;
- case kNativeObjectRelocationTypeArtMethodClean:
- case kNativeObjectRelocationTypeArtMethodArrayClean:
- return kBinArtMethodClean;
- case kNativeObjectRelocationTypeArtMethodDirty:
- case kNativeObjectRelocationTypeArtMethodArrayDirty:
- return kBinArtMethodDirty;
- case kNativeObjectRelocationTypeDexCacheArray:
- return kBinDexCacheArray;
- case kNativeObjectRelocationTypeRuntimeMethod:
- return kBinRuntimeMethod;
- case kNativeObjectRelocationTypeIMTable:
- return kBinImTable;
- case kNativeObjectRelocationTypeIMTConflictTable:
- return kBinIMTConflictTable;
+ case NativeObjectRelocationType::kArtField:
+ case NativeObjectRelocationType::kArtFieldArray:
+ return Bin::kArtField;
+ case NativeObjectRelocationType::kArtMethodClean:
+ case NativeObjectRelocationType::kArtMethodArrayClean:
+ return Bin::kArtMethodClean;
+ case NativeObjectRelocationType::kArtMethodDirty:
+ case NativeObjectRelocationType::kArtMethodArrayDirty:
+ return Bin::kArtMethodDirty;
+ case NativeObjectRelocationType::kDexCacheArray:
+ return Bin::kDexCacheArray;
+ case NativeObjectRelocationType::kRuntimeMethod:
+ return Bin::kRuntimeMethod;
+ case NativeObjectRelocationType::kIMTable:
+ return Bin::kImTable;
+ case NativeObjectRelocationType::kIMTConflictTable:
+ return Bin::kIMTConflictTable;
}
UNREACHABLE();
}
@@ -2782,20 +2788,20 @@
if (oat_index == GetDefaultOatIndex()) {
// Primary oat file, read the trampolines.
- cur_image_info.oat_address_offsets_[kOatAddressInterpreterToInterpreterBridge] =
- oat_header.GetInterpreterToInterpreterBridgeOffset();
- cur_image_info.oat_address_offsets_[kOatAddressInterpreterToCompiledCodeBridge] =
- oat_header.GetInterpreterToCompiledCodeBridgeOffset();
- cur_image_info.oat_address_offsets_[kOatAddressJNIDlsymLookup] =
- oat_header.GetJniDlsymLookupOffset();
- cur_image_info.oat_address_offsets_[kOatAddressQuickGenericJNITrampoline] =
- oat_header.GetQuickGenericJniTrampolineOffset();
- cur_image_info.oat_address_offsets_[kOatAddressQuickIMTConflictTrampoline] =
- oat_header.GetQuickImtConflictTrampolineOffset();
- cur_image_info.oat_address_offsets_[kOatAddressQuickResolutionTrampoline] =
- oat_header.GetQuickResolutionTrampolineOffset();
- cur_image_info.oat_address_offsets_[kOatAddressQuickToInterpreterBridge] =
- oat_header.GetQuickToInterpreterBridgeOffset();
+ cur_image_info.SetStubOffset(StubType::kInterpreterToInterpreterBridge,
+ oat_header.GetInterpreterToInterpreterBridgeOffset());
+ cur_image_info.SetStubOffset(StubType::kInterpreterToCompiledCodeBridge,
+ oat_header.GetInterpreterToCompiledCodeBridgeOffset());
+ cur_image_info.SetStubOffset(StubType::kJNIDlsymLookup,
+ oat_header.GetJniDlsymLookupOffset());
+ cur_image_info.SetStubOffset(StubType::kQuickGenericJNITrampoline,
+ oat_header.GetQuickGenericJniTrampolineOffset());
+ cur_image_info.SetStubOffset(StubType::kQuickIMTConflictTrampoline,
+ oat_header.GetQuickImtConflictTrampolineOffset());
+ cur_image_info.SetStubOffset(StubType::kQuickResolutionTrampoline,
+ oat_header.GetQuickResolutionTrampolineOffset());
+ cur_image_info.SetStubOffset(StubType::kQuickToInterpreterBridge,
+ oat_header.GetQuickToInterpreterBridgeOffset());
}
}
diff --git a/dex2oat/linker/image_writer.h b/dex2oat/linker/image_writer.h
index 68c7b59..3aceceb 100644
--- a/dex2oat/linker/image_writer.h
+++ b/dex2oat/linker/image_writer.h
@@ -161,70 +161,70 @@
// Classify different kinds of bins that objects end up getting packed into during image writing.
// Ordered from dirtiest to cleanest (until ArtMethods).
- enum Bin {
- kBinKnownDirty, // Known dirty objects from --dirty-image-objects list
- kBinMiscDirty, // Dex caches, object locks, etc...
- kBinClassVerified, // Class verified, but initializers haven't been run
+ enum class Bin {
+ kKnownDirty, // Known dirty objects from --dirty-image-objects list
+ kMiscDirty, // Dex caches, object locks, etc...
+ kClassVerified, // Class verified, but initializers haven't been run
// Unknown mix of clean/dirty:
- kBinRegular,
- kBinClassInitialized, // Class initializers have been run
+ kRegular,
+ kClassInitialized, // Class initializers have been run
// All classes get their own bins since their fields often dirty
- kBinClassInitializedFinalStatics, // Class initializers have been run, no non-final statics
+ kClassInitializedFinalStatics, // Class initializers have been run, no non-final statics
// Likely-clean:
- kBinString, // [String] Almost always immutable (except for obj header).
+ kString, // [String] Almost always immutable (except for obj header).
// Add more bins here if we add more segregation code.
// Non mirror fields must be below.
// ArtFields should be always clean.
- kBinArtField,
+ kArtField,
// If the class is initialized, then the ArtMethods are probably clean.
- kBinArtMethodClean,
+ kArtMethodClean,
// ArtMethods may be dirty if the class has native methods or a declaring class that isn't
// initialized.
- kBinArtMethodDirty,
+ kArtMethodDirty,
// IMT (clean)
- kBinImTable,
+ kImTable,
// Conflict tables (clean).
- kBinIMTConflictTable,
+ kIMTConflictTable,
// Runtime methods (always clean, do not have a length prefix array).
- kBinRuntimeMethod,
+ kRuntimeMethod,
// Dex cache arrays have a special slot for PC-relative addressing. Since they are
// huge, and as such their dirtiness is not important for the clean/dirty separation,
// we arbitrarily keep them at the end of the native data.
- kBinDexCacheArray, // Arrays belonging to dex cache.
- kBinSize,
+ kDexCacheArray, // Arrays belonging to dex cache.
+ kLast = kDexCacheArray,
// Number of bins which are for mirror objects.
- kBinMirrorCount = kBinArtField,
+ kMirrorCount = kArtField,
};
friend std::ostream& operator<<(std::ostream& stream, const Bin& bin);
- enum NativeObjectRelocationType {
- kNativeObjectRelocationTypeArtField,
- kNativeObjectRelocationTypeArtFieldArray,
- kNativeObjectRelocationTypeArtMethodClean,
- kNativeObjectRelocationTypeArtMethodArrayClean,
- kNativeObjectRelocationTypeArtMethodDirty,
- kNativeObjectRelocationTypeArtMethodArrayDirty,
- kNativeObjectRelocationTypeRuntimeMethod,
- kNativeObjectRelocationTypeIMTable,
- kNativeObjectRelocationTypeIMTConflictTable,
- kNativeObjectRelocationTypeDexCacheArray,
+ enum class NativeObjectRelocationType {
+ kArtField,
+ kArtFieldArray,
+ kArtMethodClean,
+ kArtMethodArrayClean,
+ kArtMethodDirty,
+ kArtMethodArrayDirty,
+ kRuntimeMethod,
+ kIMTable,
+ kIMTConflictTable,
+ kDexCacheArray,
};
friend std::ostream& operator<<(std::ostream& stream, const NativeObjectRelocationType& type);
- enum OatAddress {
- kOatAddressInterpreterToInterpreterBridge,
- kOatAddressInterpreterToCompiledCodeBridge,
- kOatAddressJNIDlsymLookup,
- kOatAddressQuickGenericJNITrampoline,
- kOatAddressQuickIMTConflictTrampoline,
- kOatAddressQuickResolutionTrampoline,
- kOatAddressQuickToInterpreterBridge,
- // Number of elements in the enum.
- kOatAddressCount,
+ enum class StubType {
+ kInterpreterToInterpreterBridge,
+ kInterpreterToCompiledCodeBridge,
+ kJNIDlsymLookup,
+ kQuickGenericJNITrampoline,
+ kQuickIMTConflictTrampoline,
+ kQuickResolutionTrampoline,
+ kQuickToInterpreterBridge,
+ kLast = kQuickToInterpreterBridge,
};
- friend std::ostream& operator<<(std::ostream& stream, const OatAddress& oat_address);
+ friend std::ostream& operator<<(std::ostream& stream, const StubType& stub_type);
- static constexpr size_t kBinBits = MinimumBitsToStore<uint32_t>(kBinMirrorCount - 1);
+ static constexpr size_t kBinBits =
+ MinimumBitsToStore<uint32_t>(static_cast<size_t>(Bin::kMirrorCount) - 1);
// uint32 = typeof(lockword_)
// Subtract read barrier bits since we want these to remain 0, or else it may result in DCHECK
// failures due to invalid read barrier bits during object field reads.
@@ -232,6 +232,12 @@
// 111000.....0
static const size_t kBinMask = ((static_cast<size_t>(1) << kBinBits) - 1) << kBinShift;
+ // Number of bins, including non-mirror bins.
+ static constexpr size_t kNumberOfBins = static_cast<size_t>(Bin::kLast) + 1u;
+
+ // Number of stub types.
+ static constexpr size_t kNumberOfStubTypes = static_cast<size_t>(StubType::kLast) + 1u;
+
// We use the lock word to store the bin # and bin index of the object in the image.
//
// The struct size must be exactly sizeof(LockWord), currently 32-bits, since this will end up
@@ -262,6 +268,39 @@
// excluding the bitmap.
size_t CreateImageSections(ImageSection* out_sections, bool app_image) const;
+ size_t GetStubOffset(StubType stub_type) const {
+ DCHECK_LT(static_cast<size_t>(stub_type), kNumberOfStubTypes);
+ return stub_offsets_[static_cast<size_t>(stub_type)];
+ }
+
+ void SetStubOffset(StubType stub_type, size_t offset) {
+ DCHECK_LT(static_cast<size_t>(stub_type), kNumberOfStubTypes);
+ stub_offsets_[static_cast<size_t>(stub_type)] = offset;
+ }
+
+ size_t GetBinSlotOffset(Bin bin) const {
+ DCHECK_LT(static_cast<size_t>(bin), kNumberOfBins);
+ return bin_slot_offsets_[static_cast<size_t>(bin)];
+ }
+
+ void IncrementBinSlotSize(Bin bin, size_t size_to_add) {
+ DCHECK_LT(static_cast<size_t>(bin), kNumberOfBins);
+ bin_slot_sizes_[static_cast<size_t>(bin)] += size_to_add;
+ }
+
+ size_t GetBinSlotSize(Bin bin) const {
+ DCHECK_LT(static_cast<size_t>(bin), kNumberOfBins);
+ return bin_slot_sizes_[static_cast<size_t>(bin)];
+ }
+
+ void IncrementBinSlotCount(Bin bin, size_t count_to_add) {
+ DCHECK_LT(static_cast<size_t>(bin), kNumberOfBins);
+ bin_slot_count_[static_cast<size_t>(bin)] += count_to_add;
+ }
+
+ // Calculate the sum total of the bin slot sizes in [0, up_to). Defaults to all bins.
+ size_t GetBinSizeSum(Bin up_to) const;
+
std::unique_ptr<MemMap> image_; // Memory mapped for generating the image.
// Target begin of this image. Notes: It is not valid to write here, this is the address
@@ -300,12 +339,12 @@
SafeMap<const DexFile*, size_t> dex_cache_array_starts_;
// Offset from oat_data_begin_ to the stubs.
- uint32_t oat_address_offsets_[kOatAddressCount] = {};
+ uint32_t stub_offsets_[kNumberOfStubTypes] = {};
// Bin slot tracking for dirty object packing.
- size_t bin_slot_sizes_[kBinSize] = {}; // Number of bytes in a bin.
- size_t bin_slot_offsets_[kBinSize] = {}; // Number of bytes in previous bins.
- size_t bin_slot_count_[kBinSize] = {}; // Number of objects in a bin.
+ size_t bin_slot_sizes_[kNumberOfBins] = {}; // Number of bytes in a bin.
+ size_t bin_slot_offsets_[kNumberOfBins] = {}; // Number of bytes in previous bins.
+ size_t bin_slot_count_[kNumberOfBins] = {}; // Number of objects in a bin.
// Cached size of the intern table for when we allocate memory.
size_t intern_table_bytes_ = 0;
@@ -367,7 +406,7 @@
}
// Returns the address in the boot image if we are compiling the app image.
- const uint8_t* GetOatAddress(OatAddress type) const;
+ const uint8_t* GetOatAddress(StubType type) const;
const uint8_t* GetOatAddressForOffset(uint32_t offset, const ImageInfo& image_info) const {
// With Quick, code is within the OatFile, as there are all in one
@@ -443,9 +482,6 @@
bool* quick_is_interpreted)
REQUIRES_SHARED(Locks::mutator_lock_);
- // Calculate the sum total of the bin slot sizes in [0, up_to). Defaults to all bins.
- size_t GetBinSizeSum(ImageInfo& image_info, Bin up_to = kBinSize) const;
-
// Return true if a method is likely to be dirtied at runtime.
bool WillMethodBeDirty(ArtMethod* m) const REQUIRES_SHARED(Locks::mutator_lock_);
@@ -572,9 +608,9 @@
NativeObjectRelocationType type;
bool IsArtMethodRelocation() const {
- return type == kNativeObjectRelocationTypeArtMethodClean ||
- type == kNativeObjectRelocationTypeArtMethodDirty ||
- type == kNativeObjectRelocationTypeRuntimeMethod;
+ return type == NativeObjectRelocationType::kArtMethodClean ||
+ type == NativeObjectRelocationType::kArtMethodDirty ||
+ type == NativeObjectRelocationType::kRuntimeMethod;
}
};
std::unordered_map<void*, NativeObjectRelocation> native_object_relocations_;