summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--dexlayout/compact_dex_writer.cc86
-rw-r--r--dexlayout/compact_dex_writer.h23
-rw-r--r--dexlayout/dex_writer.cc38
-rw-r--r--dexlayout/dex_writer.h4
4 files changed, 109 insertions, 42 deletions
diff --git a/dexlayout/compact_dex_writer.cc b/dexlayout/compact_dex_writer.cc
index ef31c3f212..6149e75753 100644
--- a/dexlayout/compact_dex_writer.cc
+++ b/dexlayout/compact_dex_writer.cc
@@ -34,7 +34,8 @@ CompactDexLevel CompactDexWriter::GetCompactDexLevel() const {
}
CompactDexWriter::Container::Container(bool dedupe_code_items)
- : code_item_dedupe_(dedupe_code_items, &data_section_) {}
+ : code_item_dedupe_(dedupe_code_items, &data_section_),
+ data_item_dedupe_(/*dedupe*/ true, &data_section_) {}
uint32_t CompactDexWriter::WriteDebugInfoOffsetTable(Stream* stream) {
const uint32_t start_offset = stream->Tell();
@@ -103,16 +104,45 @@ uint32_t CompactDexWriter::WriteDebugInfoOffsetTable(Stream* stream) {
return stream->Tell() - start_offset;
}
-uint32_t CompactDexWriter::WriteCodeItem(Stream* stream,
- dex_ir::CodeItem* code_item,
- bool reserve_only) {
+CompactDexWriter::ScopedDataSectionItem::ScopedDataSectionItem(Stream* stream,
+ dex_ir::Item* item,
+ size_t alignment,
+ Deduper* deduper)
+ : stream_(stream),
+ item_(item),
+ alignment_(alignment),
+ deduper_(deduper),
+ start_offset_(stream->Tell()) {
+ stream_->AlignTo(alignment_);
+}
+
+CompactDexWriter::ScopedDataSectionItem::~ScopedDataSectionItem() {
+ // After having written, maybe dedupe the whole code item (excluding padding).
+ const uint32_t deduped_offset = deduper_->Dedupe(start_offset_,
+ stream_->Tell(),
+ item_->GetOffset());
+ // In case we dedupe to something with wrong alignment, just say we didn't dedupe.
+ if (deduped_offset != Deduper::kDidNotDedupe && IsAlignedParam(deduped_offset, alignment_)) {
+ item_->SetOffset(deduped_offset);
+ stream_->Clear(start_offset_, stream_->Tell() - start_offset_);
+ // Undo the offset for all that we wrote since we deduped.
+ stream_->Seek(start_offset_);
+ }
+}
+
+size_t CompactDexWriter::ScopedDataSectionItem::Written() const {
+ return stream_->Tell() - start_offset_;
+}
+
+void CompactDexWriter::WriteCodeItem(Stream* stream,
+ dex_ir::CodeItem* code_item,
+ bool reserve_only) {
DCHECK(code_item != nullptr);
DCHECK(!reserve_only) << "Not supported because of deduping.";
- const uint32_t start_offset = stream->Tell();
-
- // Align to minimum requirements, additional alignment requirements are handled below after we
- // know the preheader size.
- stream->AlignTo(CompactDexFile::CodeItem::kAlignment);
+ ScopedDataSectionItem data_item(stream,
+ code_item,
+ CompactDexFile::CodeItem::kAlignment,
+ code_item_dedupe_);
CompactDexFile::CodeItem disk_code_item;
@@ -146,8 +176,6 @@ uint32_t CompactDexWriter::WriteCodeItem(Stream* stream,
}
}
- const uint32_t data_start = stream->Tell();
-
// Write preheader first.
stream->Write(reinterpret_cast<const uint8_t*>(preheader), preheader_bytes);
// Registered offset is after the preheader.
@@ -159,21 +187,15 @@ uint32_t CompactDexWriter::WriteCodeItem(Stream* stream,
stream->Write(code_item->Insns(), code_item->InsnsSize() * sizeof(uint16_t));
// Write the post instruction data.
WriteCodeItemPostInstructionData(stream, code_item, reserve_only);
+}
- if (compute_offsets_) {
- // After having written, maybe dedupe the whole code item (excluding padding).
- const uint32_t deduped_offset = code_item_dedupe_->Dedupe(data_start,
- stream->Tell(),
- code_item->GetOffset());
- if (deduped_offset != Deduper::kDidNotDedupe) {
- code_item->SetOffset(deduped_offset);
- stream->Clear(start_offset, stream->Tell() - start_offset);
- // Undo the offset for all that we wrote since we deduped.
- stream->Seek(start_offset);
- }
- }
-
- return stream->Tell() - start_offset;
+void CompactDexWriter::WriteDebugInfoItem(Stream* stream, dex_ir::DebugInfoItem* debug_info) {
+ ScopedDataSectionItem data_item(stream,
+ debug_info,
+ SectionAlignment(DexFile::kDexTypeDebugInfoItem),
+ data_item_dedupe_);
+ ProcessOffset(stream, debug_info);
+ stream->Write(debug_info->GetDebugInfo(), debug_info->GetDebugInfoSize());
}
@@ -284,11 +306,24 @@ size_t CompactDexWriter::GetHeaderSize() const {
return sizeof(CompactDexFile::Header);
}
+void CompactDexWriter::WriteStringData(Stream* stream, dex_ir::StringData* string_data) {
+ ScopedDataSectionItem data_item(stream,
+ string_data,
+ SectionAlignment(DexFile::kDexTypeStringDataItem),
+ data_item_dedupe_);
+ ProcessOffset(stream, string_data);
+ stream->WriteUleb128(CountModifiedUtf8Chars(string_data->Data()));
+ stream->Write(string_data->Data(), strlen(string_data->Data()));
+ // Skip null terminator (already zeroed out, no need to write).
+ stream->Skip(1);
+}
+
void CompactDexWriter::Write(DexContainer* output) {
CHECK(output->IsCompactDexContainer());
Container* const container = down_cast<Container*>(output);
// For now, use the same stream for both data and metadata.
Stream temp_main_stream(output->GetMainSection());
+ CHECK_EQ(output->GetMainSection()->Size(), 0u);
Stream temp_data_stream(output->GetDataSection());
Stream* main_stream = &temp_main_stream;
Stream* data_stream = &temp_data_stream;
@@ -299,6 +334,7 @@ void CompactDexWriter::Write(DexContainer* output) {
static_cast<uint32_t>(output->GetDataSection()->Size()),
kDataSectionAlignment));
code_item_dedupe_ = &container->code_item_dedupe_;
+ data_item_dedupe_ = &container->data_item_dedupe_;
// Starting offset is right after the header.
main_stream->Seek(GetHeaderSize());
diff --git a/dexlayout/compact_dex_writer.h b/dexlayout/compact_dex_writer.h
index 626b85a86b..4834bfc3af 100644
--- a/dexlayout/compact_dex_writer.h
+++ b/dexlayout/compact_dex_writer.h
@@ -86,6 +86,21 @@ class CompactDexWriter : public DexWriter {
HashedMemoryRange::HashEqual> dedupe_map_;
};
+ // Handles alignment and deduping of a data section item.
+ class ScopedDataSectionItem {
+ public:
+ ScopedDataSectionItem(Stream* stream, dex_ir::Item* item, size_t alignment, Deduper* deduper);
+ ~ScopedDataSectionItem();
+ size_t Written() const;
+
+ private:
+ Stream* const stream_;
+ dex_ir::Item* const item_;
+ const size_t alignment_;
+ Deduper* deduper_;
+ const uint32_t start_offset_;
+ };
+
public:
class Container : public DexContainer {
public:
@@ -107,6 +122,7 @@ class CompactDexWriter : public DexWriter {
VectorSection main_section_;
VectorSection data_section_;
Deduper code_item_dedupe_;
+ Deduper data_item_dedupe_;
friend class CompactDexWriter;
};
@@ -122,7 +138,11 @@ class CompactDexWriter : public DexWriter {
uint32_t WriteDebugInfoOffsetTable(Stream* stream);
- uint32_t WriteCodeItem(Stream* stream, dex_ir::CodeItem* code_item, bool reserve_only) OVERRIDE;
+ void WriteCodeItem(Stream* stream, dex_ir::CodeItem* code_item, bool reserve_only) OVERRIDE;
+
+ void WriteStringData(Stream* stream, dex_ir::StringData* string_data) OVERRIDE;
+
+ void WriteDebugInfoItem(Stream* stream, dex_ir::DebugInfoItem* debug_info) OVERRIDE;
void SortDebugInfosByMethodIndex();
@@ -140,6 +160,7 @@ class CompactDexWriter : public DexWriter {
// State for where we are deduping.
Deduper* code_item_dedupe_ = nullptr;
+ Deduper* data_item_dedupe_ = nullptr;
DISALLOW_COPY_AND_ASSIGN(CompactDexWriter);
};
diff --git a/dexlayout/dex_writer.cc b/dexlayout/dex_writer.cc
index 67d0f9ac68..a9aa97dc80 100644
--- a/dexlayout/dex_writer.cc
+++ b/dexlayout/dex_writer.cc
@@ -254,15 +254,19 @@ uint32_t DexWriter::WriteStringIds(Stream* stream, bool reserve_only) {
return stream->Tell() - start;
}
+void DexWriter::WriteStringData(Stream* stream, dex_ir::StringData* string_data) {
+ ProcessOffset(stream, string_data);
+ stream->AlignTo(SectionAlignment(DexFile::kDexTypeStringDataItem));
+ stream->WriteUleb128(CountModifiedUtf8Chars(string_data->Data()));
+ stream->Write(string_data->Data(), strlen(string_data->Data()));
+ // Skip null terminator (already zeroed out, no need to write).
+ stream->Skip(1);
+}
+
uint32_t DexWriter::WriteStringDatas(Stream* stream) {
const uint32_t start = stream->Tell();
for (std::unique_ptr<dex_ir::StringData>& string_data : header_->GetCollections().StringDatas()) {
- ProcessOffset(stream, string_data.get());
- stream->AlignTo(SectionAlignment(DexFile::kDexTypeStringDataItem));
- stream->WriteUleb128(CountModifiedUtf8Chars(string_data->Data()));
- stream->Write(string_data->Data(), strlen(string_data->Data()));
- // Skip null terminator (already zeroed out, no need to write).
- stream->Skip(1);
+ WriteStringData(stream, string_data.get());
}
if (compute_offsets_ && start != stream->Tell()) {
header_->GetCollections().SetStringDatasOffset(start);
@@ -483,13 +487,17 @@ uint32_t DexWriter::WriteAnnotationsDirectories(Stream* stream) {
return stream->Tell() - start;
}
+void DexWriter::WriteDebugInfoItem(Stream* stream, dex_ir::DebugInfoItem* debug_info) {
+ stream->AlignTo(SectionAlignment(DexFile::kDexTypeDebugInfoItem));
+ ProcessOffset(stream, debug_info);
+ stream->Write(debug_info->GetDebugInfo(), debug_info->GetDebugInfoSize());
+}
+
uint32_t DexWriter::WriteDebugInfoItems(Stream* stream) {
const uint32_t start = stream->Tell();
for (std::unique_ptr<dex_ir::DebugInfoItem>& debug_info :
header_->GetCollections().DebugInfoItems()) {
- stream->AlignTo(SectionAlignment(DexFile::kDexTypeDebugInfoItem));
- ProcessOffset(stream, debug_info.get());
- stream->Write(debug_info->GetDebugInfo(), debug_info->GetDebugInfoSize());
+ WriteDebugInfoItem(stream, debug_info.get());
}
if (compute_offsets_ && start != stream->Tell()) {
header_->GetCollections().SetDebugInfoItemsOffset(start);
@@ -535,9 +543,9 @@ uint32_t DexWriter::WriteCodeItemPostInstructionData(Stream* stream,
return stream->Tell() - start_offset;
}
-uint32_t DexWriter::WriteCodeItem(Stream* stream,
- dex_ir::CodeItem* code_item,
- bool reserve_only) {
+void DexWriter::WriteCodeItem(Stream* stream,
+ dex_ir::CodeItem* code_item,
+ bool reserve_only) {
DCHECK(code_item != nullptr);
const uint32_t start_offset = stream->Tell();
stream->AlignTo(SectionAlignment(DexFile::kDexTypeCodeItem));
@@ -564,7 +572,6 @@ uint32_t DexWriter::WriteCodeItem(Stream* stream,
if (reserve_only) {
stream->Clear(start_offset, stream->Tell() - start_offset);
}
- return stream->Tell() - start_offset;
}
uint32_t DexWriter::WriteCodeItems(Stream* stream, bool reserve_only) {
@@ -575,13 +582,14 @@ uint32_t DexWriter::WriteCodeItems(Stream* stream, bool reserve_only) {
}
const uint32_t start = stream->Tell();
for (auto& code_item : header_->GetCollections().CodeItems()) {
- const size_t code_item_size = WriteCodeItem(stream, code_item.get(), reserve_only);
+ uint32_t start_offset = stream->Tell();
+ WriteCodeItem(stream, code_item.get(), reserve_only);
// Only add the section hotness info once.
if (!reserve_only && code_section != nullptr) {
auto it = dex_layout_->LayoutHotnessInfo().code_item_layout_.find(code_item.get());
if (it != dex_layout_->LayoutHotnessInfo().code_item_layout_.end()) {
code_section->parts_[static_cast<size_t>(it->second)].CombineSection(
- stream->Tell() - code_item_size,
+ start_offset,
stream->Tell());
}
}
diff --git a/dexlayout/dex_writer.h b/dexlayout/dex_writer.h
index e581a8b61b..e6e05334e4 100644
--- a/dexlayout/dex_writer.h
+++ b/dexlayout/dex_writer.h
@@ -260,7 +260,9 @@ class DexWriter {
virtual uint32_t WriteCodeItemPostInstructionData(Stream* stream,
dex_ir::CodeItem* item,
bool reserve_only);
- virtual uint32_t WriteCodeItem(Stream* stream, dex_ir::CodeItem* item, bool reserve_only);
+ virtual void WriteCodeItem(Stream* stream, dex_ir::CodeItem* item, bool reserve_only);
+ virtual void WriteDebugInfoItem(Stream* stream, dex_ir::DebugInfoItem* debug_info);
+ virtual void WriteStringData(Stream* stream, dex_ir::StringData* string_data);
// Process an offset, if compute_offset is set, write into the dex ir item, otherwise read the
// existing offset and use that for writing.