diff options
author | 2018-06-11 14:06:23 -0700 | |
---|---|---|
committer | 2018-06-13 11:08:05 -0700 | |
commit | d83437cba0eaac9797def3c09f7812e25fdcd6ac (patch) | |
tree | e29156febe965efb57099b232d9b85342db39a41 | |
parent | a316f9129a698ccb995b035f8781f93c58981893 (diff) |
Use factory pattern for dex_ir objects
In preparation for memory improvements, make dex_ir API more friendly to
pre-allocated or in-place type allocation.
Bug: 33017139
Test: make -j 50 test-art-host
Change-Id: I09b67e279a04535b175433287ce98ecbdc37f7a3
-rw-r--r-- | dexlayout/compact_dex_writer.cc | 12 | ||||
-rw-r--r-- | dexlayout/dex_ir.cc | 180 | ||||
-rw-r--r-- | dexlayout/dex_ir.h | 193 | ||||
-rw-r--r-- | dexlayout/dex_ir_builder.cc | 9 | ||||
-rw-r--r-- | dexlayout/dex_verify.cc | 8 | ||||
-rw-r--r-- | dexlayout/dex_visualize.cc | 8 | ||||
-rw-r--r-- | dexlayout/dex_writer.cc | 14 | ||||
-rw-r--r-- | dexlayout/dexlayout.cc | 36 |
8 files changed, 303 insertions, 157 deletions
diff --git a/dexlayout/compact_dex_writer.cc b/dexlayout/compact_dex_writer.cc index 2b4144c611..3f5dbcfce5 100644 --- a/dexlayout/compact_dex_writer.cc +++ b/dexlayout/compact_dex_writer.cc @@ -59,8 +59,8 @@ uint32_t CompactDexWriter::WriteDebugInfoOffsetTable(Stream* stream) { for (auto& method : *(invoke_type == InvokeType::kDirect ? class_data->DirectMethods() : class_data->VirtualMethods())) { - const dex_ir::MethodId* method_id = method->GetMethodId(); - dex_ir::CodeItem* code_item = method->GetCodeItem(); + const dex_ir::MethodId* method_id = method.GetMethodId(); + dex_ir::CodeItem* code_item = method.GetCodeItem(); if (code_item != nullptr && code_item->DebugInfo() != nullptr) { const uint32_t debug_info_offset = code_item->DebugInfo()->GetOffset(); const uint32_t method_idx = method_id->GetIndex(); @@ -248,8 +248,8 @@ void CompactDexWriter::SortDebugInfosByMethodIndex() { for (auto& method : *(invoke_type == InvokeType::kDirect ? class_data->DirectMethods() : class_data->VirtualMethods())) { - const dex_ir::MethodId* method_id = method->GetMethodId(); - dex_ir::CodeItem* code_item = method->GetCodeItem(); + const dex_ir::MethodId* method_id = method.GetMethodId(); + dex_ir::CodeItem* code_item = method.GetCodeItem(); if (code_item != nullptr && code_item->DebugInfo() != nullptr) { const dex_ir::DebugInfoItem* debug_item = code_item->DebugInfo(); method_idx_map.insert(std::make_pair(debug_item, method_id->GetIndex())); @@ -350,8 +350,8 @@ bool CompactDexWriter::CanGenerateCompactDex(std::string* error_msg) { for (auto& method : *(invoke_type == InvokeType::kDirect ? class_data->DirectMethods() : class_data->VirtualMethods())) { - const uint32_t idx = method->GetMethodId()->GetIndex(); - dex_ir::CodeItem* code_item = method->GetCodeItem(); + const uint32_t idx = method.GetMethodId()->GetIndex(); + dex_ir::CodeItem* code_item = method.GetCodeItem(); dex_ir:: DebugInfoItem* debug_info_item = nullptr; if (code_item != nullptr) { debug_info_item = code_item->DebugInfo(); diff --git a/dexlayout/dex_ir.cc b/dexlayout/dex_ir.cc index b7d9db6da5..15e3baf18a 100644 --- a/dexlayout/dex_ir.cc +++ b/dexlayout/dex_ir.cc @@ -318,17 +318,22 @@ void Collections::ReadEncodedValue(const DexFile& dex_file, void Collections::CreateStringId(const DexFile& dex_file, uint32_t i) { const DexFile::StringId& disk_string_id = dex_file.GetStringId(dex::StringIndex(i)); - StringData* string_data = new StringData(dex_file.GetStringData(disk_string_id)); - AddItem(string_datas_map_, string_datas_, string_data, disk_string_id.string_data_off_); - - StringId* string_id = new StringId(string_data); - AddIndexedItem(string_ids_, string_id, StringIdsOffset() + i * StringId::ItemSize(), i); + StringData* string_data = CreateAndAddItem(string_datas_map_, + string_datas_, + disk_string_id.string_data_off_, + dex_file.GetStringData(disk_string_id)); + CreateAndAddIndexedItem(string_ids_, + StringIdsOffset() + i * StringId::ItemSize(), + i, + string_data); } void Collections::CreateTypeId(const DexFile& dex_file, uint32_t i) { const DexFile::TypeId& disk_type_id = dex_file.GetTypeId(dex::TypeIndex(i)); - TypeId* type_id = new TypeId(GetStringId(disk_type_id.descriptor_idx_.index_)); - AddIndexedItem(type_ids_, type_id, TypeIdsOffset() + i * TypeId::ItemSize(), i); + CreateAndAddIndexedItem(type_ids_, + TypeIdsOffset() + i * TypeId::ItemSize(), + i, + GetStringId(disk_type_id.descriptor_idx_.index_)); } void Collections::CreateProtoId(const DexFile& dex_file, uint32_t i) { @@ -336,26 +341,32 @@ void Collections::CreateProtoId(const DexFile& dex_file, uint32_t i) { const DexFile::TypeList* type_list = dex_file.GetProtoParameters(disk_proto_id); TypeList* parameter_type_list = CreateTypeList(type_list, disk_proto_id.parameters_off_); - ProtoId* proto_id = new ProtoId(GetStringId(disk_proto_id.shorty_idx_.index_), - GetTypeId(disk_proto_id.return_type_idx_.index_), - parameter_type_list); - AddIndexedItem(proto_ids_, proto_id, ProtoIdsOffset() + i * ProtoId::ItemSize(), i); + CreateAndAddIndexedItem(proto_ids_, + ProtoIdsOffset() + i * ProtoId::ItemSize(), + i, + GetStringId(disk_proto_id.shorty_idx_.index_), + GetTypeId(disk_proto_id.return_type_idx_.index_), + parameter_type_list); } void Collections::CreateFieldId(const DexFile& dex_file, uint32_t i) { const DexFile::FieldId& disk_field_id = dex_file.GetFieldId(i); - FieldId* field_id = new FieldId(GetTypeId(disk_field_id.class_idx_.index_), - GetTypeId(disk_field_id.type_idx_.index_), - GetStringId(disk_field_id.name_idx_.index_)); - AddIndexedItem(field_ids_, field_id, FieldIdsOffset() + i * FieldId::ItemSize(), i); + CreateAndAddIndexedItem(field_ids_, + FieldIdsOffset() + i * FieldId::ItemSize(), + i, + GetTypeId(disk_field_id.class_idx_.index_), + GetTypeId(disk_field_id.type_idx_.index_), + GetStringId(disk_field_id.name_idx_.index_)); } void Collections::CreateMethodId(const DexFile& dex_file, uint32_t i) { const DexFile::MethodId& disk_method_id = dex_file.GetMethodId(i); - MethodId* method_id = new MethodId(GetTypeId(disk_method_id.class_idx_.index_), - GetProtoId(disk_method_id.proto_idx_.index_), - GetStringId(disk_method_id.name_idx_.index_)); - AddIndexedItem(method_ids_, method_id, MethodIdsOffset() + i * MethodId::ItemSize(), i); + CreateAndAddIndexedItem(method_ids_, + MethodIdsOffset() + i * MethodId::ItemSize(), + i, + GetTypeId(disk_method_id.class_idx_.index_), + GetProtoId(disk_method_id.proto_idx_.index_), + GetStringId(disk_method_id.name_idx_.index_)); } void Collections::CreateClassDef(const DexFile& dex_file, uint32_t i) { @@ -382,9 +393,17 @@ void Collections::CreateClassDef(const DexFile& dex_file, uint32_t i) { CreateEncodedArrayItem(dex_file, static_data, disk_class_def.static_values_off_); ClassData* class_data = CreateClassData( dex_file, dex_file.GetClassData(disk_class_def), disk_class_def.class_data_off_); - ClassDef* class_def = new ClassDef(class_type, access_flags, superclass, interfaces_type_list, - source_file, annotations, static_values, class_data); - AddIndexedItem(class_defs_, class_def, ClassDefsOffset() + i * ClassDef::ItemSize(), i); + CreateAndAddIndexedItem(class_defs_, + ClassDefsOffset() + i * ClassDef::ItemSize(), + i, + class_type, + access_flags, + superclass, + interfaces_type_list, + source_file, + annotations, + static_values, + class_data); } TypeList* Collections::CreateTypeList(const DexFile::TypeList* dex_type_list, uint32_t offset) { @@ -398,8 +417,7 @@ TypeList* Collections::CreateTypeList(const DexFile::TypeList* dex_type_list, ui for (uint32_t index = 0; index < size; ++index) { type_vector->push_back(GetTypeId(dex_type_list->GetTypeItem(index).type_idx_.index_)); } - type_list = new TypeList(type_vector); - AddItem(type_lists_map_, type_lists_, type_list, offset); + type_list = CreateAndAddItem(type_lists_map_, type_lists_, offset, type_vector); } return type_list; } @@ -418,8 +436,10 @@ EncodedArrayItem* Collections::CreateEncodedArrayItem(const DexFile& dex_file, values->push_back(std::unique_ptr<EncodedValue>(ReadEncodedValue(dex_file, &static_data))); } // TODO: Calculate the size of the encoded array. - encoded_array_item = new EncodedArrayItem(values); - AddItem(encoded_array_items_map_, encoded_array_items_, encoded_array_item, offset); + encoded_array_item = CreateAndAddItem(encoded_array_items_map_, + encoded_array_items_, + offset, + values); } return encoded_array_item; } @@ -447,9 +467,12 @@ AnnotationItem* Collections::CreateAnnotationItem(const DexFile& dex_file, const uint8_t* annotation_data = annotation->annotation_; std::unique_ptr<EncodedValue> encoded_value( ReadEncodedValue(dex_file, &annotation_data, DexFile::kDexAnnotationAnnotation, 0)); - annotation_item = new AnnotationItem(visibility, encoded_value->ReleaseEncodedAnnotation()); + annotation_item = CreateAndAddItem(annotation_items_map_, + annotation_items_, + offset, + visibility, + encoded_value->ReleaseEncodedAnnotation()); annotation_item->SetSize(annotation_data - start_data); - AddItem(annotation_items_map_, annotation_items_, annotation_item, offset); } return annotation_item; } @@ -472,8 +495,10 @@ AnnotationSetItem* Collections::CreateAnnotationSetItem(const DexFile& dex_file, AnnotationItem* annotation_item = CreateAnnotationItem(dex_file, annotation); items->push_back(annotation_item); } - annotation_set_item = new AnnotationSetItem(items); - AddItem(annotation_set_items_map_, annotation_set_items_, annotation_set_item, offset); + annotation_set_item = CreateAndAddItem(annotation_set_items_map_, + annotation_set_items_, + offset, + items); } return annotation_set_item; } @@ -538,13 +563,13 @@ AnnotationsDirectoryItem* Collections::CreateAnnotationsDirectoryItem(const DexF } } // TODO: Calculate the size of the annotations directory. -annotations_directory_item = new AnnotationsDirectoryItem( - class_annotation, field_annotations, method_annotations, parameter_annotations); - AddItem(annotations_directory_items_map_, - annotations_directory_items_, - annotations_directory_item, - offset); - return annotations_directory_item; + return CreateAndAddItem(annotations_directory_items_map_, + annotations_directory_items_, + offset, + class_annotation, + field_annotations, + method_annotations, + parameter_annotations); } ParameterAnnotation* Collections::GenerateParameterAnnotation( @@ -559,8 +584,10 @@ ParameterAnnotation* Collections::GenerateParameterAnnotation( uint32_t set_offset = annotation_set_ref_list->list_[i].annotations_off_; annotations->push_back(CreateAnnotationSetItem(dex_file, annotation_set_item, set_offset)); } - set_ref_list = new AnnotationSetRefList(annotations); - AddItem(annotation_set_ref_lists_map_, annotation_set_ref_lists_, set_ref_list, offset); + set_ref_list = CreateAndAddItem(annotation_set_ref_lists_map_, + annotation_set_ref_lists_, + offset, + annotations); } return new ParameterAnnotation(method_id, set_ref_list); } @@ -590,8 +617,11 @@ CodeItem* Collections::DedupeOrCreateCodeItem(const DexFile& dex_file, uint32_t debug_info_size = GetDebugInfoStreamSize(debug_info_stream); uint8_t* debug_info_buffer = new uint8_t[debug_info_size]; memcpy(debug_info_buffer, debug_info_stream, debug_info_size); - debug_info = new DebugInfoItem(debug_info_size, debug_info_buffer); - AddItem(debug_info_items_map_, debug_info_items_, debug_info, debug_info_offset); + debug_info = CreateAndAddItem(debug_info_items_map_, + debug_info_items_, + debug_info_offset, + debug_info_size, + debug_info_buffer); } } @@ -677,14 +707,14 @@ CodeItem* Collections::DedupeOrCreateCodeItem(const DexFile& dex_file, } uint32_t size = dex_file.GetCodeItemSize(*disk_code_item); - CodeItem* code_item = new CodeItem(accessor.RegistersSize(), - accessor.InsSize(), - accessor.OutsSize(), - debug_info, - insns_size, - insns, - tries, - handler_list); + CodeItem* code_item = code_items_.CreateAndAddItem(accessor.RegistersSize(), + accessor.InsSize(), + accessor.OutsSize(), + debug_info, + insns_size, + insns, + tries, + handler_list); code_item->SetSize(size); // Add the code item to the map. @@ -693,7 +723,6 @@ CodeItem* Collections::DedupeOrCreateCodeItem(const DexFile& dex_file, code_item->SetOffset(offset); } code_items_map_.emplace(offsets_pair, code_item); - code_items_.AddItem(code_item); // Add "fixup" references to types, strings, methods, and fields. // This is temporary, as we will probably want more detailed parsing of the @@ -718,7 +747,7 @@ CodeItem* Collections::DedupeOrCreateCodeItem(const DexFile& dex_file, return code_item; } -MethodItem* Collections::GenerateMethodItem(const DexFile& dex_file, ClassDataItemIterator& cdii) { +MethodItem Collections::GenerateMethodItem(const DexFile& dex_file, ClassDataItemIterator& cdii) { MethodId* method_id = GetMethodId(cdii.GetMemberIndex()); uint32_t access_flags = cdii.GetRawMemberAccessFlags(); const DexFile::CodeItem* disk_code_item = cdii.GetMethodCodeItem(); @@ -728,7 +757,7 @@ MethodItem* Collections::GenerateMethodItem(const DexFile& dex_file, ClassDataIt disk_code_item, cdii.GetMethodCodeItemOffset(), cdii.GetMemberIndex()); - return new MethodItem(access_flags, method_id, code_item); + return MethodItem(access_flags, method_id, code_item); } ClassData* Collections::CreateClassData( @@ -743,29 +772,33 @@ ClassData* Collections::CreateClassData( for (; cdii.HasNextStaticField(); cdii.Next()) { FieldId* field_item = GetFieldId(cdii.GetMemberIndex()); uint32_t access_flags = cdii.GetRawMemberAccessFlags(); - static_fields->push_back(std::unique_ptr<FieldItem>(new FieldItem(access_flags, field_item))); + static_fields->emplace_back(access_flags, field_item); } // Instance fields. FieldItemVector* instance_fields = new FieldItemVector(); for (; cdii.HasNextInstanceField(); cdii.Next()) { FieldId* field_item = GetFieldId(cdii.GetMemberIndex()); uint32_t access_flags = cdii.GetRawMemberAccessFlags(); - instance_fields->push_back( - std::unique_ptr<FieldItem>(new FieldItem(access_flags, field_item))); + instance_fields->emplace_back(access_flags, field_item); } // Direct methods. MethodItemVector* direct_methods = new MethodItemVector(); for (; cdii.HasNextDirectMethod(); cdii.Next()) { - direct_methods->push_back(std::unique_ptr<MethodItem>(GenerateMethodItem(dex_file, cdii))); + direct_methods->push_back(GenerateMethodItem(dex_file, cdii)); } // Virtual methods. MethodItemVector* virtual_methods = new MethodItemVector(); for (; cdii.HasNextVirtualMethod(); cdii.Next()) { - virtual_methods->push_back(std::unique_ptr<MethodItem>(GenerateMethodItem(dex_file, cdii))); + virtual_methods->push_back(GenerateMethodItem(dex_file, cdii)); } - class_data = new ClassData(static_fields, instance_fields, direct_methods, virtual_methods); + class_data = CreateAndAddItem(class_datas_map_, + class_datas_, + offset, + static_fields, + instance_fields, + direct_methods, + virtual_methods); class_data->SetSize(cdii.EndDataPointer() - encoded_data); - AddItem(class_datas_map_, class_datas_, class_data, offset); } return class_data; } @@ -802,8 +835,10 @@ void Collections::CreateCallSiteId(const DexFile& dex_file, uint32_t i) { EncodedArrayItem* call_site_item = CreateEncodedArrayItem(dex_file, disk_call_item_ptr, disk_call_site_id.data_off_); - CallSiteId* call_site_id = new CallSiteId(call_site_item); - AddIndexedItem(call_site_ids_, call_site_id, CallSiteIdsOffset() + i * CallSiteId::ItemSize(), i); + CreateAndAddIndexedItem(call_site_ids_, + CallSiteIdsOffset() + i * CallSiteId::ItemSize(), + i, + call_site_item); } void Collections::CreateMethodHandleItem(const DexFile& dex_file, uint32_t i) { @@ -824,11 +859,11 @@ void Collections::CreateMethodHandleItem(const DexFile& dex_file, uint32_t i) { } else { field_or_method_id = GetFieldId(index); } - MethodHandleItem* method_handle = new MethodHandleItem(type, field_or_method_id); - AddIndexedItem(method_handle_items_, - method_handle, - MethodHandleItemsOffset() + i * MethodHandleItem::ItemSize(), - i); + CreateAndAddIndexedItem(method_handle_items_, + MethodHandleItemsOffset() + i * MethodHandleItem::ItemSize(), + i, + type, + field_or_method_id); } void Collections::SortVectorsByMapOrder() { @@ -844,6 +879,19 @@ void Collections::SortVectorsByMapOrder() { class_datas_.SortByMapOrder(class_datas_map_.Collection()); } +void Collections::ClearMaps() { + string_datas_map_.Collection().clear(); + type_lists_map_.Collection().clear(); + encoded_array_items_map_.Collection().clear(); + annotation_items_map_.Collection().clear(); + annotation_set_items_map_.Collection().clear(); + annotation_set_ref_lists_map_.Collection().clear(); + annotations_directory_items_map_.Collection().clear(); + debug_info_items_map_.Collection().clear(); + code_items_map_.clear(); + class_datas_map_.Collection().clear(); +} + static uint32_t HeaderOffset(const dex_ir::Collections& collections ATTRIBUTE_UNUSED) { return 0; } diff --git a/dexlayout/dex_ir.h b/dexlayout/dex_ir.h index 5ecad2bf87..54ff105820 100644 --- a/dexlayout/dex_ir.h +++ b/dexlayout/dex_ir.h @@ -129,7 +129,11 @@ template<class T> class CollectionBase { template<class T> class CollectionVector : public CollectionBase<T> { public: using Vector = std::vector<std::unique_ptr<T>>; - CollectionVector() = default; + CollectionVector() { } + explicit CollectionVector(size_t size) { + // Preallocate so that assignment does not invalidate pointers into the vector. + collection_.reserve(size); + } uint32_t Size() const { return collection_.size(); } Vector& Collection() { return collection_; } @@ -152,8 +156,11 @@ template<class T> class CollectionVector : public CollectionBase<T> { protected: Vector collection_; - void AddItem(T* object) { + template<class... Args> + T* CreateAndAddItem(Args&&... args) { + T* object = new T(std::forward<Args>(args)...); collection_.push_back(std::unique_ptr<T>(object)); + return object; } private: @@ -165,11 +172,20 @@ template<class T> class IndexedCollectionVector : public CollectionVector<T> { public: using Vector = std::vector<std::unique_ptr<T>>; IndexedCollectionVector() = default; + explicit IndexedCollectionVector(size_t size) : CollectionVector<T>(size) { } private: - void AddIndexedItem(T* object, uint32_t index) { + template <class... Args> + T* CreateAndAddIndexedItem(uint32_t index, Args&&... args) { + T* object = CollectionVector<T>::CreateAndAddItem(std::forward<Args>(args)...); object->SetIndex(index); - CollectionVector<T>::collection_.push_back(std::unique_ptr<T>(object)); + return object; + } + + T* GetElement(uint32_t index) { + DCHECK_LT(index, CollectionVector<T>::Size()); + DCHECK_NE(CollectionVector<T>::collection_[index].get(), static_cast<T*>(nullptr)); + return CollectionVector<T>::collection_[index].get(); } friend class Collections; @@ -193,6 +209,8 @@ template<class T> class CollectionMap : public CollectionBase<T> { private: std::map<uint32_t, T*> collection_; + // CollectionMaps do not own the objects they contain, therefore AddItem is supported + // rather than CreateAndAddItem. void AddItem(T* object, uint32_t offset) { auto it = collection_.emplace(offset, object); CHECK(it.second) << "CollectionMap already has an object with offset " << offset << " " @@ -206,13 +224,25 @@ template<class T> class CollectionMap : public CollectionBase<T> { class Collections { public: Collections() = default; - - CollectionVector<StringId>::Vector& StringIds() { return string_ids_.Collection(); } - CollectionVector<TypeId>::Vector& TypeIds() { return type_ids_.Collection(); } - CollectionVector<ProtoId>::Vector& ProtoIds() { return proto_ids_.Collection(); } - CollectionVector<FieldId>::Vector& FieldIds() { return field_ids_.Collection(); } - CollectionVector<MethodId>::Vector& MethodIds() { return method_ids_.Collection(); } - CollectionVector<ClassDef>::Vector& ClassDefs() { return class_defs_.Collection(); } + Collections(uint32_t num_string_ids, + uint32_t num_type_ids, + uint32_t num_proto_ids, + uint32_t num_field_ids, + uint32_t num_method_ids, + uint32_t num_class_defs) + : string_ids_(num_string_ids), + type_ids_(num_type_ids), + proto_ids_(num_proto_ids), + field_ids_(num_field_ids), + method_ids_(num_method_ids), + class_defs_(num_class_defs) { } + + IndexedCollectionVector<StringId>::Vector& StringIds() { return string_ids_.Collection(); } + IndexedCollectionVector<TypeId>::Vector& TypeIds() { return type_ids_.Collection(); } + IndexedCollectionVector<ProtoId>::Vector& ProtoIds() { return proto_ids_.Collection(); } + IndexedCollectionVector<FieldId>::Vector& FieldIds() { return field_ids_.Collection(); } + IndexedCollectionVector<MethodId>::Vector& MethodIds() { return method_ids_.Collection(); } + IndexedCollectionVector<ClassDef>::Vector& ClassDefs() { return class_defs_.Collection(); } CollectionVector<CallSiteId>::Vector& CallSiteIds() { return call_site_ids_.Collection(); } CollectionVector<MethodHandleItem>::Vector& MethodHandleItems() { return method_handle_items_.Collection(); } @@ -266,28 +296,22 @@ class Collections { uint32_t count); StringId* GetStringId(uint32_t index) { - CHECK_LT(index, StringIdsSize()); - return StringIds()[index].get(); + return string_ids_.GetElement(index); } TypeId* GetTypeId(uint32_t index) { - CHECK_LT(index, TypeIdsSize()); - return TypeIds()[index].get(); + return type_ids_.GetElement(index); } ProtoId* GetProtoId(uint32_t index) { - CHECK_LT(index, ProtoIdsSize()); - return ProtoIds()[index].get(); + return proto_ids_.GetElement(index); } FieldId* GetFieldId(uint32_t index) { - CHECK_LT(index, FieldIdsSize()); - return FieldIds()[index].get(); + return field_ids_.GetElement(index); } MethodId* GetMethodId(uint32_t index) { - CHECK_LT(index, MethodIdsSize()); - return MethodIds()[index].get(); + return method_ids_.GetElement(index); } ClassDef* GetClassDef(uint32_t index) { - CHECK_LT(index, ClassDefsSize()); - return ClassDefs()[index].get(); + return class_defs_.GetElement(index); } CallSiteId* GetCallSiteId(uint32_t index) { CHECK_LT(index, CallSiteIdsSize()); @@ -372,31 +396,35 @@ class Collections { // Sort the vectors buy map order (same order that was used in the input file). void SortVectorsByMapOrder(); - - template <typename Type> - void AddItem(CollectionMap<Type>& map, - CollectionVector<Type>& vector, - Type* item, - uint32_t offset) { + // Empty the maps, which are only used for IR construction. + void ClearMaps(); + + template <typename Type, class... Args> + Type* CreateAndAddItem(CollectionMap<Type>& map, + CollectionVector<Type>& vector, + uint32_t offset, + Args&&... args) { + Type* item = vector.CreateAndAddItem(std::forward<Args>(args)...); DCHECK(!map.GetExistingObject(offset)); DCHECK(!item->OffsetAssigned()); if (eagerly_assign_offsets_) { item->SetOffset(offset); } map.AddItem(item, offset); - vector.AddItem(item); + return item; } - template <typename Type> - void AddIndexedItem(IndexedCollectionVector<Type>& vector, - Type* item, - uint32_t offset, - uint32_t index) { + template <typename Type, class... Args> + Type* CreateAndAddIndexedItem(IndexedCollectionVector<Type>& vector, + uint32_t offset, + uint32_t index, + Args&&... args) { + Type* item = vector.CreateAndAddIndexedItem(index, std::forward<Args>(args)...); DCHECK(!item->OffsetAssigned()); if (eagerly_assign_offsets_) { item->SetOffset(offset); } - vector.AddIndexedItem(item, index); + return item; } void SetEagerlyAssignOffsets(bool eagerly_assign_offsets) { @@ -425,7 +453,7 @@ class Collections { ParameterAnnotation* GenerateParameterAnnotation(const DexFile& dex_file, MethodId* method_id, const DexFile::AnnotationSetRefList* annotation_set_ref_list, uint32_t offset); - MethodItem* GenerateMethodItem(const DexFile& dex_file, ClassDataItemIterator& cdii); + MethodItem GenerateMethodItem(const DexFile& dex_file, ClassDataItemIterator& cdii); // Collection vectors own the IR data. IndexedCollectionVector<StringId> string_ids_; @@ -433,6 +461,7 @@ class Collections { IndexedCollectionVector<ProtoId> proto_ids_; IndexedCollectionVector<FieldId> field_ids_; IndexedCollectionVector<MethodId> method_ids_; + IndexedCollectionVector<ClassDef> class_defs_; IndexedCollectionVector<CallSiteId> call_site_ids_; IndexedCollectionVector<MethodHandleItem> method_handle_items_; IndexedCollectionVector<StringData> string_datas_; @@ -442,7 +471,6 @@ class Collections { IndexedCollectionVector<AnnotationSetItem> annotation_set_items_; IndexedCollectionVector<AnnotationSetRefList> annotation_set_ref_lists_; IndexedCollectionVector<AnnotationsDirectoryItem> annotations_directory_items_; - IndexedCollectionVector<ClassDef> class_defs_; // The order of the vectors controls the layout of the output file by index order, to change the // layout just sort the vector. Note that you may only change the order of the non indexed vectors // below. Indexed vectors are accessed by indices in other places, changing the sorting order will @@ -485,6 +513,8 @@ class Item { Item() { } virtual ~Item() { } + Item(Item&&) = default; + // Return the assigned offset. uint32_t GetOffset() const WARN_UNUSED { CHECK(OffsetAssigned()); @@ -536,18 +566,54 @@ class Header : public Item { uint32_t data_size, uint32_t data_offset, bool support_default_methods) + : Item(0, kHeaderItemSize), support_default_methods_(support_default_methods) { + ConstructorHelper(magic, + checksum, + signature, + endian_tag, + file_size, + header_size, + link_size, + link_offset, + data_size, + data_offset); + } + + Header(const uint8_t* magic, + uint32_t checksum, + const uint8_t* signature, + uint32_t endian_tag, + uint32_t file_size, + uint32_t header_size, + uint32_t link_size, + uint32_t link_offset, + uint32_t data_size, + uint32_t data_offset, + bool support_default_methods, + uint32_t num_string_ids, + uint32_t num_type_ids, + uint32_t num_proto_ids, + uint32_t num_field_ids, + uint32_t num_method_ids, + uint32_t num_class_defs) : Item(0, kHeaderItemSize), - checksum_(checksum), - endian_tag_(endian_tag), - file_size_(file_size), - header_size_(header_size), - link_size_(link_size), - link_offset_(link_offset), - data_size_(data_size), - data_offset_(data_offset), - support_default_methods_(support_default_methods) { - memcpy(magic_, magic, sizeof(magic_)); - memcpy(signature_, signature, sizeof(signature_)); + support_default_methods_(support_default_methods), + collections_(num_string_ids, + num_type_ids, + num_proto_ids, + num_field_ids, + num_method_ids, + num_class_defs) { + ConstructorHelper(magic, + checksum, + signature, + endian_tag, + file_size, + header_size, + link_size, + link_offset, + data_size, + data_offset); } ~Header() OVERRIDE { } @@ -596,6 +662,27 @@ class Header : public Item { uint32_t data_offset_; const bool support_default_methods_; + void ConstructorHelper(const uint8_t* magic, + uint32_t checksum, + const uint8_t* signature, + uint32_t endian_tag, + uint32_t file_size, + uint32_t header_size, + uint32_t link_size, + uint32_t link_offset, + uint32_t data_size, + uint32_t data_offset) { + checksum_ = checksum; + endian_tag_ = endian_tag; + file_size_ = file_size; + header_size_ = header_size; + link_size_ = link_size; + link_offset_ = link_offset; + data_size_ = data_size; + data_offset_ = data_offset; + memcpy(magic_, magic, sizeof(magic_)); + memcpy(signature_, signature, sizeof(signature_)); + } Collections collections_; DISALLOW_COPY_AND_ASSIGN(Header); @@ -744,6 +831,8 @@ class FieldItem : public Item { : access_flags_(access_flags), field_id_(field_id) { } ~FieldItem() OVERRIDE { } + FieldItem(FieldItem&&) = default; + uint32_t GetAccessFlags() const { return access_flags_; } const FieldId* GetFieldId() const { return field_id_; } @@ -756,7 +845,7 @@ class FieldItem : public Item { DISALLOW_COPY_AND_ASSIGN(FieldItem); }; -using FieldItemVector = std::vector<std::unique_ptr<FieldItem>>; +using FieldItemVector = std::vector<FieldItem>; class MethodItem : public Item { public: @@ -764,6 +853,8 @@ class MethodItem : public Item { : access_flags_(access_flags), method_id_(method_id), code_(code) { } ~MethodItem() OVERRIDE { } + MethodItem(MethodItem&&) = default; + uint32_t GetAccessFlags() const { return access_flags_; } const MethodId* GetMethodId() const { return method_id_; } CodeItem* GetCodeItem() { return code_; } @@ -778,7 +869,7 @@ class MethodItem : public Item { DISALLOW_COPY_AND_ASSIGN(MethodItem); }; -using MethodItemVector = std::vector<std::unique_ptr<MethodItem>>; +using MethodItemVector = std::vector<MethodItem>; class EncodedValue { public: diff --git a/dexlayout/dex_ir_builder.cc b/dexlayout/dex_ir_builder.cc index 4f9bcdd742..9468f763d6 100644 --- a/dexlayout/dex_ir_builder.cc +++ b/dexlayout/dex_ir_builder.cc @@ -43,7 +43,13 @@ Header* DexIrBuilder(const DexFile& dex_file, disk_header.link_off_, disk_header.data_size_, disk_header.data_off_, - dex_file.SupportsDefaultMethods()); + dex_file.SupportsDefaultMethods(), + dex_file.NumStringIds(), + dex_file.NumTypeIds(), + dex_file.NumProtoIds(), + dex_file.NumFieldIds(), + dex_file.NumMethodIds(), + dex_file.NumClassDefs()); Collections& collections = header->GetCollections(); collections.SetEagerlyAssignOffsets(eagerly_assign_offsets); // Walk the rest of the header fields. @@ -94,6 +100,7 @@ Header* DexIrBuilder(const DexFile& dex_file, // Sort the vectors by the map order (same order as the file). collections.SortVectorsByMapOrder(); + collections.ClearMaps(); // Load the link data if it exists. collections.SetLinkData(std::vector<uint8_t>( diff --git a/dexlayout/dex_verify.cc b/dexlayout/dex_verify.cc index 18ddc86e0c..2e4756b482 100644 --- a/dexlayout/dex_verify.cc +++ b/dexlayout/dex_verify.cc @@ -769,8 +769,8 @@ bool VerifyFields(dex_ir::FieldItemVector* orig, return false; } for (size_t i = 0; i < orig->size(); ++i) { - dex_ir::FieldItem* orig_field = (*orig)[i].get(); - dex_ir::FieldItem* output_field = (*output)[i].get(); + dex_ir::FieldItem* orig_field = &(*orig)[i]; + dex_ir::FieldItem* output_field = &(*output)[i]; if (orig_field->GetFieldId()->GetIndex() != output_field->GetFieldId()->GetIndex()) { *error_msg = StringPrintf("Mismatched field index for class data at offset %x: %u vs %u.", orig_offset, @@ -802,8 +802,8 @@ bool VerifyMethods(dex_ir::MethodItemVector* orig, return false; } for (size_t i = 0; i < orig->size(); ++i) { - dex_ir::MethodItem* orig_method = (*orig)[i].get(); - dex_ir::MethodItem* output_method = (*output)[i].get(); + dex_ir::MethodItem* orig_method = &(*orig)[i]; + dex_ir::MethodItem* output_method = &(*output)[i]; if (orig_method->GetMethodId()->GetIndex() != output_method->GetMethodId()->GetIndex()) { *error_msg = StringPrintf("Mismatched method index for class data at offset %x: %u vs %u.", orig_offset, diff --git a/dexlayout/dex_visualize.cc b/dexlayout/dex_visualize.cc index c8aac941ff..0e04c587e7 100644 --- a/dexlayout/dex_visualize.cc +++ b/dexlayout/dex_visualize.cc @@ -279,22 +279,22 @@ void VisualizeDexLayout(dex_ir::Header* header, dumper->DumpAddressRange(class_data, class_index); if (class_data->StaticFields()) { for (auto& field_item : *class_data->StaticFields()) { - dumper->DumpFieldItem(field_item.get(), class_index); + dumper->DumpFieldItem(&field_item, class_index); } } if (class_data->InstanceFields()) { for (auto& field_item : *class_data->InstanceFields()) { - dumper->DumpFieldItem(field_item.get(), class_index); + dumper->DumpFieldItem(&field_item, class_index); } } if (class_data->DirectMethods()) { for (auto& method_item : *class_data->DirectMethods()) { - dumper->DumpMethodItem(method_item.get(), dex_file, class_index, profile_info); + dumper->DumpMethodItem(&method_item, dex_file, class_index, profile_info); } } if (class_data->VirtualMethods()) { for (auto& method_item : *class_data->VirtualMethods()) { - dumper->DumpMethodItem(method_item.get(), dex_file, class_index, profile_info); + dumper->DumpMethodItem(&method_item, dex_file, class_index, profile_info); } } } diff --git a/dexlayout/dex_writer.cc b/dexlayout/dex_writer.cc index eead13f69a..9ed1312983 100644 --- a/dexlayout/dex_writer.cc +++ b/dexlayout/dex_writer.cc @@ -207,21 +207,21 @@ void DexWriter::WriteEncodedAnnotation(Stream* stream, dex_ir::EncodedAnnotation void DexWriter::WriteEncodedFields(Stream* stream, dex_ir::FieldItemVector* fields) { uint32_t prev_index = 0; - for (std::unique_ptr<dex_ir::FieldItem>& field : *fields) { - uint32_t index = field->GetFieldId()->GetIndex(); + for (auto& field : *fields) { + uint32_t index = field.GetFieldId()->GetIndex(); stream->WriteUleb128(index - prev_index); - stream->WriteUleb128(field->GetAccessFlags()); + stream->WriteUleb128(field.GetAccessFlags()); prev_index = index; } } void DexWriter::WriteEncodedMethods(Stream* stream, dex_ir::MethodItemVector* methods) { uint32_t prev_index = 0; - for (std::unique_ptr<dex_ir::MethodItem>& method : *methods) { - uint32_t index = method->GetMethodId()->GetIndex(); - uint32_t code_off = method->GetCodeItem() == nullptr ? 0 : method->GetCodeItem()->GetOffset(); + for (auto& method : *methods) { + uint32_t index = method.GetMethodId()->GetIndex(); + uint32_t code_off = method.GetCodeItem() == nullptr ? 0 : method.GetCodeItem()->GetOffset(); stream->WriteUleb128(index - prev_index); - stream->WriteUleb128(method->GetAccessFlags()); + stream->WriteUleb128(method.GetAccessFlags()); stream->WriteUleb128(code_off); prev_index = index; } diff --git a/dexlayout/dexlayout.cc b/dexlayout/dexlayout.cc index 62dd1a9554..39d93bfc77 100644 --- a/dexlayout/dexlayout.cc +++ b/dexlayout/dexlayout.cc @@ -1459,8 +1459,8 @@ void DexLayout::DumpClass(int idx, char** last_package) { dex_ir::FieldItemVector* static_fields = class_data->StaticFields(); if (static_fields != nullptr) { for (uint32_t i = 0; i < static_fields->size(); i++) { - DumpSField((*static_fields)[i]->GetFieldId()->GetIndex(), - (*static_fields)[i]->GetAccessFlags(), + DumpSField((*static_fields)[i].GetFieldId()->GetIndex(), + (*static_fields)[i].GetAccessFlags(), i, i < encoded_values_size ? (*encoded_values)[i].get() : nullptr); } // for @@ -1475,8 +1475,8 @@ void DexLayout::DumpClass(int idx, char** last_package) { dex_ir::FieldItemVector* instance_fields = class_data->InstanceFields(); if (instance_fields != nullptr) { for (uint32_t i = 0; i < instance_fields->size(); i++) { - DumpIField((*instance_fields)[i]->GetFieldId()->GetIndex(), - (*instance_fields)[i]->GetAccessFlags(), + DumpIField((*instance_fields)[i].GetFieldId()->GetIndex(), + (*instance_fields)[i].GetAccessFlags(), i); } // for } @@ -1490,9 +1490,9 @@ void DexLayout::DumpClass(int idx, char** last_package) { dex_ir::MethodItemVector* direct_methods = class_data->DirectMethods(); if (direct_methods != nullptr) { for (uint32_t i = 0; i < direct_methods->size(); i++) { - DumpMethod((*direct_methods)[i]->GetMethodId()->GetIndex(), - (*direct_methods)[i]->GetAccessFlags(), - (*direct_methods)[i]->GetCodeItem(), + DumpMethod((*direct_methods)[i].GetMethodId()->GetIndex(), + (*direct_methods)[i].GetAccessFlags(), + (*direct_methods)[i].GetCodeItem(), i); } // for } @@ -1506,9 +1506,9 @@ void DexLayout::DumpClass(int idx, char** last_package) { dex_ir::MethodItemVector* virtual_methods = class_data->VirtualMethods(); if (virtual_methods != nullptr) { for (uint32_t i = 0; i < virtual_methods->size(); i++) { - DumpMethod((*virtual_methods)[i]->GetMethodId()->GetIndex(), - (*virtual_methods)[i]->GetAccessFlags(), - (*virtual_methods)[i]->GetCodeItem(), + DumpMethod((*virtual_methods)[i].GetMethodId()->GetIndex(), + (*virtual_methods)[i].GetAccessFlags(), + (*virtual_methods)[i].GetCodeItem(), i); } // for } @@ -1636,14 +1636,14 @@ void DexLayout::LayoutStringData(const DexFile* dex_file) { } for (size_t i = 0; i < 2; ++i) { for (auto& method : *(i == 0 ? data->DirectMethods() : data->VirtualMethods())) { - const dex_ir::MethodId* method_id = method->GetMethodId(); - dex_ir::CodeItem* code_item = method->GetCodeItem(); + const dex_ir::MethodId* method_id = method.GetMethodId(); + dex_ir::CodeItem* code_item = method.GetCodeItem(); if (code_item == nullptr) { continue; } const bool is_clinit = is_profile_class && - (method->GetAccessFlags() & kAccConstructor) != 0 && - (method->GetAccessFlags() & kAccStatic) != 0; + (method.GetAccessFlags() & kAccConstructor) != 0 && + (method.GetAccessFlags() & kAccStatic) != 0; const bool method_executed = is_clinit || info_->GetMethodHotness(MethodReference(dex_file, method_id->GetIndex())).IsInProfile(); if (!method_executed) { @@ -1744,14 +1744,14 @@ void DexLayout::LayoutCodeItems(const DexFile* dex_file) { for (auto& method : *(invoke_type == InvokeType::kDirect ? class_data->DirectMethods() : class_data->VirtualMethods())) { - const dex_ir::MethodId *method_id = method->GetMethodId(); - dex_ir::CodeItem *code_item = method->GetCodeItem(); + const dex_ir::MethodId *method_id = method.GetMethodId(); + dex_ir::CodeItem *code_item = method.GetCodeItem(); if (code_item == nullptr) { continue; } // Separate executed methods (clinits and profiled methods) from unexecuted methods. - const bool is_clinit = (method->GetAccessFlags() & kAccConstructor) != 0 && - (method->GetAccessFlags() & kAccStatic) != 0; + const bool is_clinit = (method.GetAccessFlags() & kAccConstructor) != 0 && + (method.GetAccessFlags() & kAccStatic) != 0; const bool is_startup_clinit = is_profile_class && is_clinit; using Hotness = ProfileCompilationInfo::MethodHotness; Hotness hotness = info_->GetMethodHotness(MethodReference(dex_file, method_id->GetIndex())); |