Refactor compact dex writing
Refactor compact dex writing into compact_dex_writer.cc, change
dexlayout writing logic to use the header structs instead of having
an array with indicies.
Bug: 63756964
Test: test-art-host
Change-Id: I58879aefc1672c965789ee539450986c9d830c82
diff --git a/dexlayout/Android.bp b/dexlayout/Android.bp
index 3c71770..fabe6e7 100644
--- a/dexlayout/Android.bp
+++ b/dexlayout/Android.bp
@@ -17,6 +17,7 @@
defaults: ["art_defaults"],
host_supported: true,
srcs: [
+ "compact_dex_writer.cc",
"dexlayout.cc",
"dex_ir.cc",
"dex_ir_builder.cc",
diff --git a/dexlayout/compact_dex_writer.cc b/dexlayout/compact_dex_writer.cc
new file mode 100644
index 0000000..b089c1d
--- /dev/null
+++ b/dexlayout/compact_dex_writer.cc
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "compact_dex_writer.h"
+
+#include "cdex/compact_dex_file.h"
+
+namespace art {
+
+void CompactDexWriter::WriteHeader() {
+ CompactDexFile::Header header;
+ CompactDexFile::WriteMagic(&header.magic_[0]);
+ CompactDexFile::WriteCurrentVersion(&header.magic_[0]);
+ header.checksum_ = header_->Checksum();
+ std::copy_n(header_->Signature(), DexFile::kSha1DigestSize, header.signature_);
+ header.file_size_ = header_->FileSize();
+ header.header_size_ = header_->GetSize();
+ header.endian_tag_ = header_->EndianTag();
+ header.link_size_ = header_->LinkSize();
+ header.link_off_ = header_->LinkOffset();
+ const dex_ir::Collections& collections = header_->GetCollections();
+ header.map_off_ = collections.MapListOffset();
+ header.string_ids_size_ = collections.StringIdsSize();
+ header.string_ids_off_ = collections.StringIdsOffset();
+ header.type_ids_size_ = collections.TypeIdsSize();
+ header.type_ids_off_ = collections.TypeIdsOffset();
+ header.proto_ids_size_ = collections.ProtoIdsSize();
+ header.proto_ids_off_ = collections.ProtoIdsOffset();
+ header.field_ids_size_ = collections.FieldIdsSize();
+ header.field_ids_off_ = collections.FieldIdsOffset();
+ header.method_ids_size_ = collections.MethodIdsSize();
+ header.method_ids_off_ = collections.MethodIdsOffset();
+ header.class_defs_size_ = collections.ClassDefsSize();
+ header.class_defs_off_ = collections.ClassDefsOffset();
+ header.data_size_ = header_->DataSize();
+ header.data_off_ = header_->DataOffset();
+ Write(reinterpret_cast<uint8_t*>(&header), sizeof(header), 0u);
+}
+
+} // namespace art
diff --git a/dexlayout/compact_dex_writer.h b/dexlayout/compact_dex_writer.h
new file mode 100644
index 0000000..1c77202
--- /dev/null
+++ b/dexlayout/compact_dex_writer.h
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Header file of an in-memory representation of DEX files.
+ */
+
+#ifndef ART_DEXLAYOUT_COMPACT_DEX_WRITER_H_
+#define ART_DEXLAYOUT_COMPACT_DEX_WRITER_H_
+
+#include "dex_writer.h"
+
+namespace art {
+
+class CompactDexWriter : public DexWriter {
+ public:
+ CompactDexWriter(dex_ir::Header* header, MemMap* mem_map, CompactDexLevel compact_dex_level)
+ : DexWriter(header, mem_map),
+ compact_dex_level_(compact_dex_level) { }
+
+ protected:
+ void WriteHeader() OVERRIDE;
+
+ const CompactDexLevel compact_dex_level_;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(CompactDexWriter);
+};
+
+} // namespace art
+
+#endif // ART_DEXLAYOUT_COMPACT_DEX_WRITER_H_
diff --git a/dexlayout/dex_writer.cc b/dexlayout/dex_writer.cc
index 8c82106..4895ab6 100644
--- a/dexlayout/dex_writer.cc
+++ b/dexlayout/dex_writer.cc
@@ -12,8 +12,6 @@
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
- *
- * Header file of an in-memory representation of DEX files.
*/
#include "dex_writer.h"
@@ -24,6 +22,7 @@
#include <vector>
#include "cdex/compact_dex_file.h"
+#include "compact_dex_writer.h"
#include "dex_file_types.h"
#include "standard_dex_file.h"
#include "utf.h"
@@ -629,48 +628,36 @@
}
void DexWriter::WriteHeader() {
- uint32_t buffer[20];
- dex_ir::Collections& collections = header_->GetCollections();
- size_t offset = 0;
- if (compact_dex_level_ != CompactDexLevel::kCompactDexLevelNone) {
- static constexpr size_t kMagicAndVersionLen =
- CompactDexFile::kDexMagicSize + CompactDexFile::kDexVersionLen;
- uint8_t magic_and_version[kMagicAndVersionLen] = {};
- CompactDexFile::WriteMagic(&magic_and_version[0]);
- CompactDexFile::WriteCurrentVersion(&magic_and_version[0]);
- offset += Write(magic_and_version, kMagicAndVersionLen * sizeof(uint8_t), offset);
- } else {
- static constexpr size_t kMagicAndVersionLen =
- StandardDexFile::kDexMagicSize + StandardDexFile::kDexVersionLen;
- offset += Write(header_->Magic(), kMagicAndVersionLen * sizeof(uint8_t), offset);
- }
- buffer[0] = header_->Checksum();
- offset += Write(buffer, sizeof(uint32_t), offset);
- offset += Write(header_->Signature(), 20 * sizeof(uint8_t), offset);
- uint32_t file_size = header_->FileSize();
- buffer[0] = file_size;
- buffer[1] = header_->GetSize();
- buffer[2] = header_->EndianTag();
- buffer[3] = header_->LinkSize();
- buffer[4] = header_->LinkOffset();
- buffer[5] = collections.MapListOffset();
- buffer[6] = collections.StringIdsSize();
- buffer[7] = collections.StringIdsOffset();
- buffer[8] = collections.TypeIdsSize();
- buffer[9] = collections.TypeIdsOffset();
- buffer[10] = collections.ProtoIdsSize();
- buffer[11] = collections.ProtoIdsOffset();
- buffer[12] = collections.FieldIdsSize();
- buffer[13] = collections.FieldIdsOffset();
- buffer[14] = collections.MethodIdsSize();
- buffer[15] = collections.MethodIdsOffset();
- uint32_t class_defs_size = collections.ClassDefsSize();
- uint32_t class_defs_off = collections.ClassDefsOffset();
- buffer[16] = class_defs_size;
- buffer[17] = class_defs_off;
- buffer[18] = header_->DataSize();
- buffer[19] = header_->DataOffset();
- Write(buffer, 20 * sizeof(uint32_t), offset);
+ StandardDexFile::Header header;
+ static constexpr size_t kMagicAndVersionLen =
+ StandardDexFile::kDexMagicSize + StandardDexFile::kDexVersionLen;
+ std::copy_n(header_->Magic(), kMagicAndVersionLen, header.magic_);
+ header.checksum_ = header_->Checksum();
+ std::copy_n(header_->Signature(), DexFile::kSha1DigestSize, header.signature_);
+ header.file_size_ = header_->FileSize();
+ header.header_size_ = header_->GetSize();
+ header.endian_tag_ = header_->EndianTag();
+ header.link_size_ = header_->LinkSize();
+ header.link_off_ = header_->LinkOffset();
+ const dex_ir::Collections& collections = header_->GetCollections();
+ header.map_off_ = collections.MapListOffset();
+ header.string_ids_size_ = collections.StringIdsSize();
+ header.string_ids_off_ = collections.StringIdsOffset();
+ header.type_ids_size_ = collections.TypeIdsSize();
+ header.type_ids_off_ = collections.TypeIdsOffset();
+ header.proto_ids_size_ = collections.ProtoIdsSize();
+ header.proto_ids_off_ = collections.ProtoIdsOffset();
+ header.field_ids_size_ = collections.FieldIdsSize();
+ header.field_ids_off_ = collections.FieldIdsOffset();
+ header.method_ids_size_ = collections.MethodIdsSize();
+ header.method_ids_off_ = collections.MethodIdsOffset();
+ header.class_defs_size_ = collections.ClassDefsSize();
+ header.class_defs_off_ = collections.ClassDefsOffset();
+ header.data_size_ = header_->DataSize();
+ header.data_off_ = header_->DataOffset();
+
+ static_assert(sizeof(header) == 0x70, "Size doesn't match dex spec");
+ Write(reinterpret_cast<uint8_t*>(&header), sizeof(header), 0u);
}
void DexWriter::WriteMemMap() {
@@ -695,8 +682,13 @@
}
void DexWriter::Output(dex_ir::Header* header, MemMap* mem_map, CompactDexLevel compact_dex_level) {
- DexWriter dex_writer(header, mem_map, compact_dex_level);
- dex_writer.WriteMemMap();
+ std::unique_ptr<DexWriter> writer;
+ if (compact_dex_level != CompactDexLevel::kCompactDexLevelNone) {
+ writer.reset(new CompactDexWriter(header, mem_map, compact_dex_level));
+ } else {
+ writer.reset(new DexWriter(header, mem_map));
+ }
+ writer->WriteMemMap();
}
} // namespace art
diff --git a/dexlayout/dex_writer.h b/dexlayout/dex_writer.h
index d932b9f..85d3e7e 100644
--- a/dexlayout/dex_writer.h
+++ b/dexlayout/dex_writer.h
@@ -29,16 +29,13 @@
class DexWriter {
public:
- DexWriter(dex_ir::Header* header,
- MemMap* mem_map,
- CompactDexLevel compact_dex_level)
- : header_(header),
- mem_map_(mem_map),
- compact_dex_level_(compact_dex_level) { }
+ DexWriter(dex_ir::Header* header, MemMap* mem_map) : header_(header), mem_map_(mem_map) {}
static void Output(dex_ir::Header* header, MemMap* mem_map, CompactDexLevel compact_dex_level);
- private:
+ virtual ~DexWriter() {}
+
+ protected:
void WriteMemMap();
size_t Write(const void* buffer, size_t length, size_t offset);
@@ -68,12 +65,12 @@
void WriteCallSites();
void WriteMethodHandles();
void WriteMapItem();
- void WriteHeader();
+ virtual void WriteHeader();
dex_ir::Header* const header_;
MemMap* const mem_map_;
- const CompactDexLevel compact_dex_level_;
+ private:
DISALLOW_COPY_AND_ASSIGN(DexWriter);
};
diff --git a/runtime/cdex/compact_dex_file.h b/runtime/cdex/compact_dex_file.h
index 3c1b638..8ab9247 100644
--- a/runtime/cdex/compact_dex_file.h
+++ b/runtime/cdex/compact_dex_file.h
@@ -24,6 +24,9 @@
// CompactDex is a currently ART internal dex file format that aims to reduce storage/RAM usage.
class CompactDexFile : public DexFile {
public:
+ class Header : public DexFile::Header {
+ // Same for now.
+ };
static constexpr uint8_t kDexMagic[kDexMagicSize] = { 'c', 'd', 'e', 'x' };
static constexpr uint8_t kDexMagicVersion[] = {'0', '0', '1', '\0'};
diff --git a/runtime/dex_file.h b/runtime/dex_file.h
index c0e0fbc..f239edc 100644
--- a/runtime/dex_file.h
+++ b/runtime/dex_file.h
@@ -78,35 +78,32 @@
// Raw header_item.
struct Header {
- uint8_t magic_[8];
- uint32_t checksum_; // See also location_checksum_
- uint8_t signature_[kSha1DigestSize];
- uint32_t file_size_; // size of entire file
- uint32_t header_size_; // offset to start of next section
- uint32_t endian_tag_;
- uint32_t link_size_; // unused
- uint32_t link_off_; // unused
- uint32_t map_off_; // unused
- uint32_t string_ids_size_; // number of StringIds
- uint32_t string_ids_off_; // file offset of StringIds array
- uint32_t type_ids_size_; // number of TypeIds, we don't support more than 65535
- uint32_t type_ids_off_; // file offset of TypeIds array
- uint32_t proto_ids_size_; // number of ProtoIds, we don't support more than 65535
- uint32_t proto_ids_off_; // file offset of ProtoIds array
- uint32_t field_ids_size_; // number of FieldIds
- uint32_t field_ids_off_; // file offset of FieldIds array
- uint32_t method_ids_size_; // number of MethodIds
- uint32_t method_ids_off_; // file offset of MethodIds array
- uint32_t class_defs_size_; // number of ClassDefs
- uint32_t class_defs_off_; // file offset of ClassDef array
- uint32_t data_size_; // size of data section
- uint32_t data_off_; // file offset of data section
+ uint8_t magic_[8] = {};
+ uint32_t checksum_ = 0; // See also location_checksum_
+ uint8_t signature_[kSha1DigestSize] = {};
+ uint32_t file_size_ = 0; // size of entire file
+ uint32_t header_size_ = 0; // offset to start of next section
+ uint32_t endian_tag_ = 0;
+ uint32_t link_size_ = 0; // unused
+ uint32_t link_off_ = 0; // unused
+ uint32_t map_off_ = 0; // unused
+ uint32_t string_ids_size_ = 0; // number of StringIds
+ uint32_t string_ids_off_ = 0; // file offset of StringIds array
+ uint32_t type_ids_size_ = 0; // number of TypeIds, we don't support more than 65535
+ uint32_t type_ids_off_ = 0; // file offset of TypeIds array
+ uint32_t proto_ids_size_ = 0; // number of ProtoIds, we don't support more than 65535
+ uint32_t proto_ids_off_ = 0; // file offset of ProtoIds array
+ uint32_t field_ids_size_ = 0; // number of FieldIds
+ uint32_t field_ids_off_ = 0; // file offset of FieldIds array
+ uint32_t method_ids_size_ = 0; // number of MethodIds
+ uint32_t method_ids_off_ = 0; // file offset of MethodIds array
+ uint32_t class_defs_size_ = 0; // number of ClassDefs
+ uint32_t class_defs_off_ = 0; // file offset of ClassDef array
+ uint32_t data_size_ = 0; // size of data section
+ uint32_t data_off_ = 0; // file offset of data section
// Decode the dex magic version
uint32_t GetVersion() const;
-
- private:
- DISALLOW_COPY_AND_ASSIGN(Header);
};
// Map item type codes.
diff --git a/runtime/standard_dex_file.h b/runtime/standard_dex_file.h
index 906b0b7..784ab31 100644
--- a/runtime/standard_dex_file.h
+++ b/runtime/standard_dex_file.h
@@ -28,6 +28,10 @@
// Standard dex file. This is the format that is packaged in APKs and produced by tools.
class StandardDexFile : public DexFile {
public:
+ class Header : public DexFile::Header {
+ // Same for now.
+ };
+
static const uint8_t kDexMagic[kDexMagicSize];
static constexpr size_t kNumDexVersions = 4;
static const uint8_t kDexMagicVersions[kNumDexVersions][kDexVersionLen];