Uleb128 compression of vmap and mapping table.
Bug 9437697.
Change-Id: I30bcb97d12cd8b46d3b2cdcbdd358f08fbb9947a
(cherry picked from commit 1809a72a66d245ae598582d658b93a24ac3bf01e)
diff --git a/compiler/dex/quick/codegen_util.cc b/compiler/dex/quick/codegen_util.cc
index c9780fa..5f6f3d5 100644
--- a/compiler/dex/quick/codegen_util.cc
+++ b/compiler/dex/quick/codegen_util.cc
@@ -17,6 +17,7 @@
#include "dex/compiler_internals.h"
#include "dex_file-inl.h"
#include "gc_map.h"
+#include "mapping_table.h"
#include "mir_to_lir-inl.h"
#include "verifier/dex_gc_map.h"
#include "verifier/method_verifier.h"
@@ -515,15 +516,35 @@
}
}
if (kIsDebugBuild) {
- DCHECK(VerifyCatchEntries());
+ CHECK(VerifyCatchEntries());
}
- combined_mapping_table_.push_back(pc2dex_mapping_table_.size() +
- dex2pc_mapping_table_.size());
- combined_mapping_table_.push_back(pc2dex_mapping_table_.size());
- combined_mapping_table_.insert(combined_mapping_table_.end(), pc2dex_mapping_table_.begin(),
- pc2dex_mapping_table_.end());
- combined_mapping_table_.insert(combined_mapping_table_.end(), dex2pc_mapping_table_.begin(),
- dex2pc_mapping_table_.end());
+ CHECK_EQ(pc2dex_mapping_table_.size() & 1, 0U);
+ CHECK_EQ(dex2pc_mapping_table_.size() & 1, 0U);
+ uint32_t total_entries = (pc2dex_mapping_table_.size() + dex2pc_mapping_table_.size()) / 2;
+ uint32_t pc2dex_entries = pc2dex_mapping_table_.size() / 2;
+ encoded_mapping_table_.PushBack(total_entries);
+ encoded_mapping_table_.PushBack(pc2dex_entries);
+ encoded_mapping_table_.InsertBack(pc2dex_mapping_table_.begin(), pc2dex_mapping_table_.end());
+ encoded_mapping_table_.InsertBack(dex2pc_mapping_table_.begin(), dex2pc_mapping_table_.end());
+ if (kIsDebugBuild) {
+ // Verify the encoded table holds the expected data.
+ MappingTable table(&encoded_mapping_table_.GetData()[0]);
+ CHECK_EQ(table.TotalSize(), total_entries);
+ CHECK_EQ(table.PcToDexSize(), pc2dex_entries);
+ CHECK_EQ(table.DexToPcSize(), dex2pc_mapping_table_.size() / 2);
+ MappingTable::PcToDexIterator it = table.PcToDexBegin();
+ for (uint32_t i = 0; i < pc2dex_mapping_table_.size(); ++i, ++it) {
+ CHECK_EQ(pc2dex_mapping_table_.at(i), it.NativePcOffset());
+ ++i;
+ CHECK_EQ(pc2dex_mapping_table_.at(i), it.DexPc());
+ }
+ MappingTable::DexToPcIterator it2 = table.DexToPcBegin();
+ for (uint32_t i = 0; i < dex2pc_mapping_table_.size(); ++i, ++it2) {
+ CHECK_EQ(dex2pc_mapping_table_.at(i), it2.NativePcOffset());
+ ++i;
+ CHECK_EQ(dex2pc_mapping_table_.at(i), it2.DexPc());
+ }
+ }
}
class NativePcToReferenceMapBuilder {
@@ -980,28 +1001,35 @@
CompiledMethod* Mir2Lir::GetCompiledMethod() {
// Combine vmap tables - core regs, then fp regs - into vmap_table
- std::vector<uint16_t> vmap_table;
+ std::vector<uint16_t> raw_vmap_table;
// Core regs may have been inserted out of order - sort first
std::sort(core_vmap_table_.begin(), core_vmap_table_.end());
for (size_t i = 0 ; i < core_vmap_table_.size(); i++) {
// Copy, stripping out the phys register sort key
- vmap_table.push_back(~(-1 << VREG_NUM_WIDTH) & core_vmap_table_[i]);
+ raw_vmap_table.push_back(~(-1 << VREG_NUM_WIDTH) & core_vmap_table_[i]);
}
// If we have a frame, push a marker to take place of lr
if (frame_size_ > 0) {
- vmap_table.push_back(INVALID_VREG);
+ raw_vmap_table.push_back(INVALID_VREG);
} else {
DCHECK_EQ(__builtin_popcount(core_spill_mask_), 0);
DCHECK_EQ(__builtin_popcount(fp_spill_mask_), 0);
}
// Combine vmap tables - core regs, then fp regs. fp regs already sorted
for (uint32_t i = 0; i < fp_vmap_table_.size(); i++) {
- vmap_table.push_back(fp_vmap_table_[i]);
+ raw_vmap_table.push_back(fp_vmap_table_[i]);
+ }
+ UnsignedLeb128EncodingVector vmap_encoder;
+ // Prefix the encoded data with its size.
+ vmap_encoder.PushBack(raw_vmap_table.size());
+ typedef std::vector<uint16_t>::const_iterator It;
+ for (It cur = raw_vmap_table.begin(), end = raw_vmap_table.end(); cur != end; ++cur) {
+ vmap_encoder.PushBack(*cur);
}
CompiledMethod* result =
new CompiledMethod(cu_->instruction_set, code_buffer_,
frame_size_, core_spill_mask_, fp_spill_mask_,
- combined_mapping_table_, vmap_table, native_gc_map_);
+ encoded_mapping_table_.GetData(), vmap_encoder.GetData(), native_gc_map_);
return result;
}
diff --git a/compiler/dex/quick/mir_to_lir.h b/compiler/dex/quick/mir_to_lir.h
index 2794bf5..517fc66 100644
--- a/compiler/dex/quick/mir_to_lir.h
+++ b/compiler/dex/quick/mir_to_lir.h
@@ -25,6 +25,7 @@
#include "dex/growable_array.h"
#include "dex/arena_allocator.h"
#include "driver/compiler_driver.h"
+#include "leb128_encoder.h"
#include "safe_map.h"
namespace art {
@@ -760,7 +761,8 @@
*/
int live_sreg_;
CodeBuffer code_buffer_;
- std::vector<uint32_t> combined_mapping_table_;
+ // The encoding mapping table data (dex -> pc offset and pc offset -> dex) with a size prefix.
+ UnsignedLeb128EncodingVector encoded_mapping_table_;
std::vector<uint32_t> core_vmap_table_;
std::vector<uint32_t> fp_vmap_table_;
std::vector<uint8_t> native_gc_map_;
diff --git a/compiler/image_writer.cc b/compiler/image_writer.cc
index 550d642..3432c8c 100644
--- a/compiler/image_writer.cc
+++ b/compiler/image_writer.cc
@@ -547,11 +547,11 @@
// Normal (non-abstract non-native) methods have various tables to relocate.
uint32_t mapping_table_off = orig->GetOatMappingTableOffset();
const byte* mapping_table = GetOatAddress(mapping_table_off);
- copy->SetMappingTable(reinterpret_cast<const uint32_t*>(mapping_table));
+ copy->SetMappingTable(mapping_table);
uint32_t vmap_table_offset = orig->GetOatVmapTableOffset();
const byte* vmap_table = GetOatAddress(vmap_table_offset);
- copy->SetVmapTable(reinterpret_cast<const uint16_t*>(vmap_table));
+ copy->SetVmapTable(vmap_table);
uint32_t native_gc_map_offset = orig->GetOatNativeGcMapOffset();
const byte* native_gc_map = GetOatAddress(native_gc_map_offset);
diff --git a/compiler/leb128_encoder.h b/compiler/leb128_encoder.h
new file mode 100644
index 0000000..e9a1c32
--- /dev/null
+++ b/compiler/leb128_encoder.h
@@ -0,0 +1,63 @@
+/*
+ * Copyright (C) 2011 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.
+ */
+
+#ifndef ART_COMPILER_LEB128_ENCODER_H_
+#define ART_COMPILER_LEB128_ENCODER_H_
+
+#include "base/macros.h"
+
+namespace art {
+
+// An encoder with an API similar to vector<uint32_t> where the data is captured in ULEB128 format.
+class UnsignedLeb128EncodingVector {
+ public:
+ UnsignedLeb128EncodingVector() {
+ }
+
+ void PushBack(uint32_t value) {
+ bool done = false;
+ do {
+ uint8_t out = value & 0x7f;
+ if (out != value) {
+ data_.push_back(out | 0x80);
+ value >>= 7;
+ } else {
+ data_.push_back(out);
+ done = true;
+ }
+ } while (!done);
+ }
+
+ template<typename It>
+ void InsertBack(It cur, It end) {
+ for (; cur != end; ++cur) {
+ PushBack(*cur);
+ }
+ }
+
+ const std::vector<uint8_t>& GetData() const {
+ return data_;
+ }
+
+ private:
+ std::vector<uint8_t> data_;
+
+ DISALLOW_COPY_AND_ASSIGN(UnsignedLeb128EncodingVector);
+};
+
+} // namespace art
+
+#endif // ART_COMPILER_LEB128_ENCODER_H_
diff --git a/compiler/oat_writer.cc b/compiler/oat_writer.cc
index 21c5317..ce88cf6 100644
--- a/compiler/oat_writer.cc
+++ b/compiler/oat_writer.cc
@@ -322,12 +322,12 @@
core_spill_mask = compiled_method->GetCoreSpillMask();
fp_spill_mask = compiled_method->GetFpSpillMask();
- const std::vector<uint32_t>& mapping_table = compiled_method->GetMappingTable();
+ const std::vector<uint8_t>& mapping_table = compiled_method->GetMappingTable();
size_t mapping_table_size = mapping_table.size() * sizeof(mapping_table[0]);
mapping_table_offset = (mapping_table_size == 0) ? 0 : offset;
// Deduplicate mapping tables
- SafeMap<const std::vector<uint32_t>*, uint32_t>::iterator mapping_iter =
+ SafeMap<const std::vector<uint8_t>*, uint32_t>::iterator mapping_iter =
mapping_table_offsets_.find(&mapping_table);
if (mapping_iter != mapping_table_offsets_.end()) {
mapping_table_offset = mapping_iter->second;
@@ -337,12 +337,12 @@
oat_header_->UpdateChecksum(&mapping_table[0], mapping_table_size);
}
- const std::vector<uint16_t>& vmap_table = compiled_method->GetVmapTable();
+ const std::vector<uint8_t>& vmap_table = compiled_method->GetVmapTable();
size_t vmap_table_size = vmap_table.size() * sizeof(vmap_table[0]);
vmap_table_offset = (vmap_table_size == 0) ? 0 : offset;
// Deduplicate vmap tables
- SafeMap<const std::vector<uint16_t>*, uint32_t>::iterator vmap_iter =
+ SafeMap<const std::vector<uint8_t>*, uint32_t>::iterator vmap_iter =
vmap_table_offsets_.find(&vmap_table);
if (vmap_iter != vmap_table_offsets_.end()) {
vmap_table_offset = vmap_iter->second;
@@ -717,11 +717,11 @@
DCHECK_OFFSET();
#endif
- const std::vector<uint32_t>& mapping_table = compiled_method->GetMappingTable();
+ const std::vector<uint8_t>& mapping_table = compiled_method->GetMappingTable();
size_t mapping_table_size = mapping_table.size() * sizeof(mapping_table[0]);
// Deduplicate mapping tables
- SafeMap<const std::vector<uint32_t>*, uint32_t>::iterator mapping_iter =
+ SafeMap<const std::vector<uint8_t>*, uint32_t>::iterator mapping_iter =
mapping_table_offsets_.find(&mapping_table);
if (mapping_iter != mapping_table_offsets_.end() &&
relative_offset != method_offsets.mapping_table_offset_) {
@@ -741,11 +741,11 @@
}
DCHECK_OFFSET();
- const std::vector<uint16_t>& vmap_table = compiled_method->GetVmapTable();
+ const std::vector<uint8_t>& vmap_table = compiled_method->GetVmapTable();
size_t vmap_table_size = vmap_table.size() * sizeof(vmap_table[0]);
// Deduplicate vmap tables
- SafeMap<const std::vector<uint16_t>*, uint32_t>::iterator vmap_iter =
+ SafeMap<const std::vector<uint8_t>*, uint32_t>::iterator vmap_iter =
vmap_table_offsets_.find(&vmap_table);
if (vmap_iter != vmap_table_offsets_.end() &&
relative_offset != method_offsets.vmap_table_offset_) {
diff --git a/compiler/oat_writer.h b/compiler/oat_writer.h
index e6cc0bc..f7801f5 100644
--- a/compiler/oat_writer.h
+++ b/compiler/oat_writer.h
@@ -226,8 +226,8 @@
// code mappings for deduplication
SafeMap<const std::vector<uint8_t>*, uint32_t, MapCompare<std::vector<uint8_t> > > code_offsets_;
- SafeMap<const std::vector<uint16_t>*, uint32_t, MapCompare<std::vector<uint16_t> > > vmap_table_offsets_;
- SafeMap<const std::vector<uint32_t>*, uint32_t, MapCompare<std::vector<uint32_t> > > mapping_table_offsets_;
+ SafeMap<const std::vector<uint8_t>*, uint32_t, MapCompare<std::vector<uint8_t> > > vmap_table_offsets_;
+ SafeMap<const std::vector<uint8_t>*, uint32_t, MapCompare<std::vector<uint8_t> > > mapping_table_offsets_;
SafeMap<const std::vector<uint8_t>*, uint32_t, MapCompare<std::vector<uint8_t> > > gc_map_offsets_;
DISALLOW_COPY_AND_ASSIGN(OatWriter);