Performance improvement for mapping table creation.
Avoid the raw mapping tables altogether.
Change-Id: I6d1c786325d369e899a75f15701edbafdd14363f
diff --git a/compiler/dex/quick/codegen_util.cc b/compiler/dex/quick/codegen_util.cc
index 92b24e1..a682d58 100644
--- a/compiler/dex/quick/codegen_util.cc
+++ b/compiler/dex/quick/codegen_util.cc
@@ -24,6 +24,28 @@
namespace art {
+namespace {
+
+/* Dump a mapping table */
+template <typename It>
+void DumpMappingTable(const char* table_name, const char* descriptor, const char* name,
+ const Signature& signature, uint32_t size, It first) {
+ if (size != 0) {
+ std::string line(StringPrintf("\n %s %s%s_%s_table[%zu] = {", table_name,
+ descriptor, name, signature.ToString().c_str(), size));
+ std::replace(line.begin(), line.end(), ';', '_');
+ LOG(INFO) << line;
+ for (uint32_t i = 0; i != size; ++i) {
+ line = StringPrintf(" {0x%05x, 0x%04x},", first.NativePcOffset(), first.DexPc());
+ ++first;
+ LOG(INFO) << line;
+ }
+ LOG(INFO) <<" };\n\n";
+ }
+}
+
+} // anonymous namespace
+
bool Mir2Lir::IsInexpensiveConstant(RegLocation rl_src) {
bool res = false;
if (rl_src.is_const) {
@@ -251,23 +273,6 @@
}
}
-/* Dump a mapping table */
-void Mir2Lir::DumpMappingTable(const char* table_name, const char* descriptor,
- const char* name, const Signature& signature,
- const std::vector<uint32_t>& v) {
- if (v.size() > 0) {
- std::string line(StringPrintf("\n %s %s%s_%s_table[%zu] = {", table_name,
- descriptor, name, signature.ToString().c_str(), v.size()));
- std::replace(line.begin(), line.end(), ';', '_');
- LOG(INFO) << line;
- for (uint32_t i = 0; i < v.size(); i+=2) {
- line = StringPrintf(" {0x%05x, 0x%04x},", v[i], v[i+1]);
- LOG(INFO) << line;
- }
- LOG(INFO) <<" };\n\n";
- }
-}
-
/* Dump instructions and constant pool contents */
void Mir2Lir::CodegenDump() {
LOG(INFO) << "Dumping LIR insns for "
@@ -302,8 +307,13 @@
const char* descriptor(cu_->dex_file->GetMethodDeclaringClassDescriptor(method_id));
// Dump mapping tables
- DumpMappingTable("PC2Dex_MappingTable", descriptor, name, signature, pc2dex_mapping_table_);
- DumpMappingTable("Dex2PC_MappingTable", descriptor, name, signature, dex2pc_mapping_table_);
+ if (!encoded_mapping_table_.empty()) {
+ MappingTable table(&encoded_mapping_table_[0]);
+ DumpMappingTable("PC2Dex_MappingTable", descriptor, name, signature,
+ table.PcToDexSize(), table.PcToDexBegin());
+ DumpMappingTable("Dex2PC_MappingTable", descriptor, name, signature,
+ table.DexToPcSize(), table.DexToPcBegin());
+ }
}
/*
@@ -522,34 +532,34 @@
// Make sure we have a code address for every declared catch entry
bool Mir2Lir::VerifyCatchEntries() {
+ MappingTable table(&encoded_mapping_table_[0]);
+ std::vector<uint32_t> dex_pcs;
+ dex_pcs.reserve(table.DexToPcSize());
+ for (auto it = table.DexToPcBegin(), end = table.DexToPcEnd(); it != end; ++it) {
+ dex_pcs.push_back(it.DexPc());
+ }
+ // Sort dex_pcs, so that we can quickly check it against the ordered mir_graph_->catches_.
+ std::sort(dex_pcs.begin(), dex_pcs.end());
+
bool success = true;
- for (std::set<uint32_t>::const_iterator it = mir_graph_->catches_.begin();
- it != mir_graph_->catches_.end(); ++it) {
- uint32_t dex_pc = *it;
- bool found = false;
- for (size_t i = 0; i < dex2pc_mapping_table_.size(); i += 2) {
- if (dex_pc == dex2pc_mapping_table_[i+1]) {
- found = true;
- break;
- }
+ auto it = dex_pcs.begin(), end = dex_pcs.end();
+ for (uint32_t dex_pc : mir_graph_->catches_) {
+ while (it != end && *it < dex_pc) {
+ LOG(INFO) << "Unexpected catch entry @ dex pc 0x" << std::hex << *it;
+ ++it;
+ success = false;
}
- if (!found) {
+ if (it == end || *it > dex_pc) {
LOG(INFO) << "Missing native PC for catch entry @ 0x" << std::hex << dex_pc;
success = false;
- }
- }
- // Now, try in the other direction
- for (size_t i = 0; i < dex2pc_mapping_table_.size(); i += 2) {
- uint32_t dex_pc = dex2pc_mapping_table_[i+1];
- if (mir_graph_->catches_.find(dex_pc) == mir_graph_->catches_.end()) {
- LOG(INFO) << "Unexpected catch entry @ dex pc 0x" << std::hex << dex_pc;
- success = false;
+ } else {
+ ++it;
}
}
if (!success) {
LOG(INFO) << "Bad dex2pcMapping table in " << PrettyMethod(cu_->method_idx, *cu_->dex_file);
LOG(INFO) << "Entries @ decode: " << mir_graph_->catches_.size() << ", Entries in table: "
- << dex2pc_mapping_table_.size()/2;
+ << table.DexToPcSize();
}
return success;
}
@@ -573,8 +583,6 @@
static_cast<int32_t>(pc2dex_dalvik_offset));
pc2dex_offset = tgt_lir->offset;
pc2dex_dalvik_offset = tgt_lir->dalvik_offset;
- pc2dex_mapping_table_.push_back(tgt_lir->offset);
- pc2dex_mapping_table_.push_back(tgt_lir->dalvik_offset);
}
if (!tgt_lir->flags.is_nop && (tgt_lir->opcode == kPseudoExportedPC)) {
dex2pc_entries += 1;
@@ -584,63 +592,67 @@
static_cast<int32_t>(dex2pc_dalvik_offset));
dex2pc_offset = tgt_lir->offset;
dex2pc_dalvik_offset = tgt_lir->dalvik_offset;
- dex2pc_mapping_table_.push_back(tgt_lir->offset);
- dex2pc_mapping_table_.push_back(tgt_lir->dalvik_offset);
}
}
- if (kIsDebugBuild) {
- CHECK(VerifyCatchEntries());
- }
- DCHECK_EQ(pc2dex_mapping_table_.size(), 2u * pc2dex_entries);
- DCHECK_EQ(dex2pc_mapping_table_.size(), 2u * dex2pc_entries);
uint32_t total_entries = pc2dex_entries + dex2pc_entries;
uint32_t hdr_data_size = UnsignedLeb128Size(total_entries) + UnsignedLeb128Size(pc2dex_entries);
uint32_t data_size = hdr_data_size + pc2dex_data_size + dex2pc_data_size;
- encoded_mapping_table_.Reserve(data_size);
- encoded_mapping_table_.PushBackUnsigned(total_entries);
- encoded_mapping_table_.PushBackUnsigned(pc2dex_entries);
+ encoded_mapping_table_.resize(data_size);
+ uint8_t* write_pos = &encoded_mapping_table_[0];
+ write_pos = EncodeUnsignedLeb128(write_pos, total_entries);
+ write_pos = EncodeUnsignedLeb128(write_pos, pc2dex_entries);
+ DCHECK_EQ(static_cast<size_t>(write_pos - &encoded_mapping_table_[0]), hdr_data_size);
+ uint8_t* write_pos2 = write_pos + pc2dex_data_size;
- dex2pc_offset = 0u;
- dex2pc_dalvik_offset = 0u;
pc2dex_offset = 0u;
pc2dex_dalvik_offset = 0u;
- for (uint32_t i = 0; i != pc2dex_entries; ++i) {
- encoded_mapping_table_.PushBackUnsigned(pc2dex_mapping_table_[2 * i] - pc2dex_offset);
- encoded_mapping_table_.PushBackSigned(static_cast<int32_t>(pc2dex_mapping_table_[2 * i + 1]) -
- static_cast<int32_t>(pc2dex_dalvik_offset));
- pc2dex_offset = pc2dex_mapping_table_[2 * i];
- pc2dex_dalvik_offset = pc2dex_mapping_table_[2 * i + 1];
+ dex2pc_offset = 0u;
+ dex2pc_dalvik_offset = 0u;
+ for (LIR* tgt_lir = first_lir_insn_; tgt_lir != NULL; tgt_lir = NEXT_LIR(tgt_lir)) {
+ if (!tgt_lir->flags.is_nop && (tgt_lir->opcode == kPseudoSafepointPC)) {
+ DCHECK(pc2dex_offset <= tgt_lir->offset);
+ write_pos = EncodeUnsignedLeb128(write_pos, tgt_lir->offset - pc2dex_offset);
+ write_pos = EncodeSignedLeb128(write_pos, static_cast<int32_t>(tgt_lir->dalvik_offset) -
+ static_cast<int32_t>(pc2dex_dalvik_offset));
+ pc2dex_offset = tgt_lir->offset;
+ pc2dex_dalvik_offset = tgt_lir->dalvik_offset;
+ }
+ if (!tgt_lir->flags.is_nop && (tgt_lir->opcode == kPseudoExportedPC)) {
+ DCHECK(dex2pc_offset <= tgt_lir->offset);
+ write_pos2 = EncodeUnsignedLeb128(write_pos2, tgt_lir->offset - dex2pc_offset);
+ write_pos2 = EncodeSignedLeb128(write_pos2, static_cast<int32_t>(tgt_lir->dalvik_offset) -
+ static_cast<int32_t>(dex2pc_dalvik_offset));
+ dex2pc_offset = tgt_lir->offset;
+ dex2pc_dalvik_offset = tgt_lir->dalvik_offset;
+ }
}
- DCHECK(encoded_mapping_table_.GetData().size() == hdr_data_size + pc2dex_data_size);
- for (uint32_t i = 0; i != dex2pc_entries; ++i) {
- encoded_mapping_table_.PushBackUnsigned(dex2pc_mapping_table_[2 * i] - dex2pc_offset);
- encoded_mapping_table_.PushBackSigned(static_cast<int32_t>(dex2pc_mapping_table_[2 * i + 1]) -
- static_cast<int32_t>(dex2pc_dalvik_offset));
- dex2pc_offset = dex2pc_mapping_table_[2 * i];
- dex2pc_dalvik_offset = dex2pc_mapping_table_[2 * i + 1];
- }
- DCHECK(encoded_mapping_table_.GetData().size() == data_size);
+ DCHECK_EQ(static_cast<size_t>(write_pos - &encoded_mapping_table_[0]),
+ hdr_data_size + pc2dex_data_size);
+ DCHECK_EQ(static_cast<size_t>(write_pos2 - &encoded_mapping_table_[0]), data_size);
if (kIsDebugBuild) {
+ CHECK(VerifyCatchEntries());
+
// Verify the encoded table holds the expected data.
- MappingTable table(&encoded_mapping_table_.GetData()[0]);
+ MappingTable table(&encoded_mapping_table_[0]);
CHECK_EQ(table.TotalSize(), total_entries);
CHECK_EQ(table.PcToDexSize(), pc2dex_entries);
- CHECK_EQ(table.DexToPcSize(), dex2pc_mapping_table_.size() / 2);
auto 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());
+ auto it2 = table.DexToPcBegin();
+ for (LIR* tgt_lir = first_lir_insn_; tgt_lir != NULL; tgt_lir = NEXT_LIR(tgt_lir)) {
+ if (!tgt_lir->flags.is_nop && (tgt_lir->opcode == kPseudoSafepointPC)) {
+ CHECK_EQ(tgt_lir->offset, it.NativePcOffset());
+ CHECK_EQ(tgt_lir->dalvik_offset, it.DexPc());
+ ++it;
+ }
+ if (!tgt_lir->flags.is_nop && (tgt_lir->opcode == kPseudoExportedPC)) {
+ CHECK_EQ(tgt_lir->offset, it2.NativePcOffset());
+ CHECK_EQ(tgt_lir->dalvik_offset, it2.DexPc());
+ ++it2;
+ }
}
CHECK(it == table.PcToDexEnd());
- auto 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());
- }
CHECK(it2 == table.DexToPcEnd());
}
}
@@ -724,10 +736,11 @@
};
void Mir2Lir::CreateNativeGcMap() {
- const std::vector<uint32_t>& mapping_table = pc2dex_mapping_table_;
+ DCHECK(!encoded_mapping_table_.empty());
+ MappingTable mapping_table(&encoded_mapping_table_[0]);
uint32_t max_native_offset = 0;
- for (size_t i = 0; i < mapping_table.size(); i += 2) {
- uint32_t native_offset = mapping_table[i + 0];
+ for (auto it = mapping_table.PcToDexBegin(), end = mapping_table.PcToDexEnd(); it != end; ++it) {
+ uint32_t native_offset = it.NativePcOffset();
if (native_offset > max_native_offset) {
max_native_offset = native_offset;
}
@@ -737,12 +750,12 @@
verifier::DexPcToReferenceMap dex_gc_map(&(*gc_map_raw)[4], gc_map_raw->size() - 4);
// Compute native offset to references size.
NativePcToReferenceMapBuilder native_gc_map_builder(&native_gc_map_,
- mapping_table.size() / 2, max_native_offset,
- dex_gc_map.RegWidth());
+ mapping_table.PcToDexSize(),
+ max_native_offset, dex_gc_map.RegWidth());
- for (size_t i = 0; i < mapping_table.size(); i += 2) {
- uint32_t native_offset = mapping_table[i + 0];
- uint32_t dex_pc = mapping_table[i + 1];
+ for (auto it = mapping_table.PcToDexBegin(), end = mapping_table.PcToDexEnd(); it != end; ++it) {
+ uint32_t native_offset = it.NativePcOffset();
+ uint32_t dex_pc = it.DexPc();
const uint8_t* references = dex_gc_map.FindBitMap(dex_pc, false);
CHECK(references != NULL) << "Missing ref for dex pc 0x" << std::hex << dex_pc;
native_gc_map_builder.AddEntry(native_offset, references);
@@ -1041,7 +1054,7 @@
}
CompiledMethod* result =
new CompiledMethod(*cu_->compiler_driver, cu_->instruction_set, code_buffer_, frame_size_,
- core_spill_mask_, fp_spill_mask_, encoded_mapping_table_.GetData(),
+ core_spill_mask_, fp_spill_mask_, encoded_mapping_table_,
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 92e21ff..fae6c4c 100644
--- a/compiler/dex/quick/mir_to_lir.h
+++ b/compiler/dex/quick/mir_to_lir.h
@@ -341,9 +341,6 @@
bool EvaluateBranch(Instruction::Code opcode, int src1, int src2);
bool IsInexpensiveConstant(RegLocation rl_src);
ConditionCode FlipComparisonOrder(ConditionCode before);
- void DumpMappingTable(const char* table_name, const char* descriptor,
- const char* name, const Signature& signature,
- const std::vector<uint32_t>& v);
void InstallLiteralPools();
void InstallSwitchTables();
void InstallFillArrayData();
@@ -792,17 +789,6 @@
GrowableArray<RegisterInfo*> tempreg_info_;
GrowableArray<RegisterInfo*> reginfo_map_;
GrowableArray<void*> pointer_storage_;
- /*
- * Holds mapping from native PC to dex PC for safepoints where we may deoptimize.
- * Native PC is on the return address of the safepointed operation. Dex PC is for
- * the instruction being executed at the safepoint.
- */
- std::vector<uint32_t> pc2dex_mapping_table_;
- /*
- * Holds mapping from Dex PC to native PC for catch entry points. Native PC and Dex PC
- * immediately preceed the instruction.
- */
- std::vector<uint32_t> dex2pc_mapping_table_;
CodeOffset current_code_offset_; // Working byte offset of machine instructons.
CodeOffset data_offset_; // starting offset of literal pool.
size_t total_size_; // header + code size.
@@ -828,7 +814,7 @@
int live_sreg_;
CodeBuffer code_buffer_;
// The encoding mapping table data (dex -> pc offset and pc offset -> dex) with a size prefix.
- Leb128EncodingVector encoded_mapping_table_;
+ std::vector<uint8_t> 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/leb128_encoder.h b/compiler/leb128_encoder.h
index fe38c2f..6766683 100644
--- a/compiler/leb128_encoder.h
+++ b/compiler/leb128_encoder.h
@@ -22,6 +22,31 @@
namespace art {
+static inline uint8_t* EncodeUnsignedLeb128(uint8_t* dest, uint32_t value) {
+ uint8_t out = value & 0x7f;
+ value >>= 7;
+ while (value != 0) {
+ *dest++ = out | 0x80;
+ out = value & 0x7f;
+ value >>= 7;
+ }
+ *dest++ = out;
+ return dest;
+}
+
+static inline uint8_t* EncodeSignedLeb128(uint8_t* dest, int32_t value) {
+ uint32_t extra_bits = static_cast<uint32_t>(value ^ (value >> 31)) >> 6;
+ uint8_t out = value & 0x7f;
+ while (extra_bits != 0u) {
+ *dest++ = out | 0x80;
+ value >>= 7;
+ out = value & 0x7f;
+ extra_bits >>= 7;
+ }
+ *dest++ = out;
+ return dest;
+}
+
// An encoder with an API similar to vector<uint32_t> where the data is captured in ULEB128 format.
class Leb128EncodingVector {
public:
diff --git a/compiler/leb128_encoder_test.cc b/compiler/leb128_encoder_test.cc
index 3162ca5..c63dfa2 100644
--- a/compiler/leb128_encoder_test.cc
+++ b/compiler/leb128_encoder_test.cc
@@ -92,11 +92,12 @@
{(-1) << 31, {0x80, 0x80, 0x80, 0x80, 0x78}},
};
-TEST_F(Leb128Test, UnsignedSingles) {
+TEST_F(Leb128Test, UnsignedSinglesVector) {
// Test individual encodings.
for (size_t i = 0; i < arraysize(uleb128_tests); ++i) {
Leb128EncodingVector builder;
builder.PushBackUnsigned(uleb128_tests[i].decoded);
+ EXPECT_EQ(UnsignedLeb128Size(uleb128_tests[i].decoded), builder.GetData().size());
const uint8_t* data_ptr = &uleb128_tests[i].leb128_data[0];
const uint8_t* encoded_data_ptr = &builder.GetData()[0];
for (size_t j = 0; j < 5; ++j) {
@@ -110,7 +111,26 @@
}
}
-TEST_F(Leb128Test, UnsignedStream) {
+TEST_F(Leb128Test, UnsignedSingles) {
+ // Test individual encodings.
+ for (size_t i = 0; i < arraysize(uleb128_tests); ++i) {
+ uint8_t encoded_data[5];
+ uint8_t* end = EncodeUnsignedLeb128(encoded_data, uleb128_tests[i].decoded);
+ size_t data_size = static_cast<size_t>(end - encoded_data);
+ EXPECT_EQ(UnsignedLeb128Size(uleb128_tests[i].decoded), data_size);
+ const uint8_t* data_ptr = &uleb128_tests[i].leb128_data[0];
+ for (size_t j = 0; j < 5; ++j) {
+ if (j < data_size) {
+ EXPECT_EQ(data_ptr[j], encoded_data[j]) << " i = " << i << " j = " << j;
+ } else {
+ EXPECT_EQ(data_ptr[j], 0U) << " i = " << i << " j = " << j;
+ }
+ }
+ EXPECT_EQ(DecodeUnsignedLeb128(&data_ptr), uleb128_tests[i].decoded) << " i = " << i;
+ }
+}
+
+TEST_F(Leb128Test, UnsignedStreamVector) {
// Encode a number of entries.
Leb128EncodingVector builder;
for (size_t i = 0; i < arraysize(uleb128_tests); ++i) {
@@ -119,20 +139,46 @@
const uint8_t* encoded_data_ptr = &builder.GetData()[0];
for (size_t i = 0; i < arraysize(uleb128_tests); ++i) {
const uint8_t* data_ptr = &uleb128_tests[i].leb128_data[0];
- for (size_t j = 0; j < 5; ++j) {
- if (data_ptr[j] != 0) {
- EXPECT_EQ(data_ptr[j], encoded_data_ptr[j]) << " i = " << i << " j = " << j;
- }
+ for (size_t j = 0; j < UnsignedLeb128Size(uleb128_tests[i].decoded); ++j) {
+ EXPECT_EQ(data_ptr[j], encoded_data_ptr[j]) << " i = " << i << " j = " << j;
+ }
+ for (size_t j = UnsignedLeb128Size(uleb128_tests[i].decoded); j < 5; ++j) {
+ EXPECT_EQ(data_ptr[j], 0) << " i = " << i << " j = " << j;
}
EXPECT_EQ(DecodeUnsignedLeb128(&encoded_data_ptr), uleb128_tests[i].decoded) << " i = " << i;
}
+ EXPECT_EQ(builder.GetData().size(),
+ static_cast<size_t>(encoded_data_ptr - &builder.GetData()[0]));
}
-TEST_F(Leb128Test, SignedSingles) {
+TEST_F(Leb128Test, UnsignedStream) {
+ // Encode a number of entries.
+ uint8_t encoded_data[5 * arraysize(uleb128_tests)];
+ uint8_t* end = encoded_data;
+ for (size_t i = 0; i < arraysize(uleb128_tests); ++i) {
+ end = EncodeUnsignedLeb128(end, uleb128_tests[i].decoded);
+ }
+ size_t data_size = static_cast<size_t>(end - encoded_data);
+ const uint8_t* encoded_data_ptr = encoded_data;
+ for (size_t i = 0; i < arraysize(uleb128_tests); ++i) {
+ const uint8_t* data_ptr = &uleb128_tests[i].leb128_data[0];
+ for (size_t j = 0; j < UnsignedLeb128Size(uleb128_tests[i].decoded); ++j) {
+ EXPECT_EQ(data_ptr[j], encoded_data_ptr[j]) << " i = " << i << " j = " << j;
+ }
+ for (size_t j = UnsignedLeb128Size(uleb128_tests[i].decoded); j < 5; ++j) {
+ EXPECT_EQ(data_ptr[j], 0) << " i = " << i << " j = " << j;
+ }
+ EXPECT_EQ(DecodeUnsignedLeb128(&encoded_data_ptr), uleb128_tests[i].decoded) << " i = " << i;
+ }
+ EXPECT_EQ(data_size, static_cast<size_t>(encoded_data_ptr - encoded_data));
+}
+
+TEST_F(Leb128Test, SignedSinglesVector) {
// Test individual encodings.
for (size_t i = 0; i < arraysize(sleb128_tests); ++i) {
Leb128EncodingVector builder;
builder.PushBackSigned(sleb128_tests[i].decoded);
+ EXPECT_EQ(SignedLeb128Size(sleb128_tests[i].decoded), builder.GetData().size());
const uint8_t* data_ptr = &sleb128_tests[i].leb128_data[0];
const uint8_t* encoded_data_ptr = &builder.GetData()[0];
for (size_t j = 0; j < 5; ++j) {
@@ -146,7 +192,26 @@
}
}
-TEST_F(Leb128Test, SignedStream) {
+TEST_F(Leb128Test, SignedSingles) {
+ // Test individual encodings.
+ for (size_t i = 0; i < arraysize(sleb128_tests); ++i) {
+ uint8_t encoded_data[5];
+ uint8_t* end = EncodeSignedLeb128(encoded_data, sleb128_tests[i].decoded);
+ size_t data_size = static_cast<size_t>(end - encoded_data);
+ EXPECT_EQ(SignedLeb128Size(sleb128_tests[i].decoded), data_size);
+ const uint8_t* data_ptr = &sleb128_tests[i].leb128_data[0];
+ for (size_t j = 0; j < 5; ++j) {
+ if (j < data_size) {
+ EXPECT_EQ(data_ptr[j], encoded_data[j]) << " i = " << i << " j = " << j;
+ } else {
+ EXPECT_EQ(data_ptr[j], 0U) << " i = " << i << " j = " << j;
+ }
+ }
+ EXPECT_EQ(DecodeSignedLeb128(&data_ptr), sleb128_tests[i].decoded) << " i = " << i;
+ }
+}
+
+TEST_F(Leb128Test, SignedStreamVector) {
// Encode a number of entries.
Leb128EncodingVector builder;
for (size_t i = 0; i < arraysize(sleb128_tests); ++i) {
@@ -155,13 +220,38 @@
const uint8_t* encoded_data_ptr = &builder.GetData()[0];
for (size_t i = 0; i < arraysize(sleb128_tests); ++i) {
const uint8_t* data_ptr = &sleb128_tests[i].leb128_data[0];
- for (size_t j = 0; j < 5; ++j) {
- if (data_ptr[j] != 0) {
- EXPECT_EQ(data_ptr[j], encoded_data_ptr[j]) << " i = " << i << " j = " << j;
- }
+ for (size_t j = 0; j < SignedLeb128Size(sleb128_tests[i].decoded); ++j) {
+ EXPECT_EQ(data_ptr[j], encoded_data_ptr[j]) << " i = " << i << " j = " << j;
+ }
+ for (size_t j = SignedLeb128Size(sleb128_tests[i].decoded); j < 5; ++j) {
+ EXPECT_EQ(data_ptr[j], 0) << " i = " << i << " j = " << j;
}
EXPECT_EQ(DecodeSignedLeb128(&encoded_data_ptr), sleb128_tests[i].decoded) << " i = " << i;
}
+ EXPECT_EQ(builder.GetData().size(),
+ static_cast<size_t>(encoded_data_ptr - &builder.GetData()[0]));
+}
+
+TEST_F(Leb128Test, SignedStream) {
+ // Encode a number of entries.
+ uint8_t encoded_data[5 * arraysize(sleb128_tests)];
+ uint8_t* end = encoded_data;
+ for (size_t i = 0; i < arraysize(sleb128_tests); ++i) {
+ end = EncodeSignedLeb128(end, sleb128_tests[i].decoded);
+ }
+ size_t data_size = static_cast<size_t>(end - encoded_data);
+ const uint8_t* encoded_data_ptr = encoded_data;
+ for (size_t i = 0; i < arraysize(sleb128_tests); ++i) {
+ const uint8_t* data_ptr = &sleb128_tests[i].leb128_data[0];
+ for (size_t j = 0; j < SignedLeb128Size(sleb128_tests[i].decoded); ++j) {
+ EXPECT_EQ(data_ptr[j], encoded_data_ptr[j]) << " i = " << i << " j = " << j;
+ }
+ for (size_t j = SignedLeb128Size(sleb128_tests[i].decoded); j < 5; ++j) {
+ EXPECT_EQ(data_ptr[j], 0) << " i = " << i << " j = " << j;
+ }
+ EXPECT_EQ(DecodeSignedLeb128(&encoded_data_ptr), sleb128_tests[i].decoded) << " i = " << i;
+ }
+ EXPECT_EQ(data_size, static_cast<size_t>(encoded_data_ptr - encoded_data));
}
TEST_F(Leb128Test, Speed) {