diff options
Diffstat (limited to 'compiler')
| -rw-r--r-- | compiler/dex/quick/codegen_util.cc | 189 | ||||
| -rw-r--r-- | compiler/dex/quick/mir_to_lir.h | 16 | ||||
| -rw-r--r-- | compiler/leb128_encoder.h | 25 | ||||
| -rw-r--r-- | compiler/leb128_encoder_test.cc | 114 |
4 files changed, 229 insertions, 115 deletions
diff --git a/compiler/dex/quick/codegen_util.cc b/compiler/dex/quick/codegen_util.cc index 92b24e140a..a682d58646 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 @@ void Mir2Lir::DumpPromotionMap() { } } -/* 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 @@ void Mir2Lir::CodegenDump() { 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 @@ static int AssignLiteralPointerOffsetCommon(LIR* lir, CodeOffset offset) { // 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; - } - } - if (!found) { - LOG(INFO) << "Missing native PC for catch entry @ 0x" << std::hex << dex_pc; + 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; } - } - // 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; + if (it == end || *it > dex_pc) { + LOG(INFO) << "Missing native PC for catch entry @ 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 @@ void Mir2Lir::CreateMappingTables() { 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 @@ void Mir2Lir::CreateMappingTables() { 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]; - } - 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]; + 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() == 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()); - } - 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()); + 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()); CHECK(it2 == table.DexToPcEnd()); } } @@ -724,10 +736,11 @@ class NativePcToReferenceMapBuilder { }; 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 @@ void Mir2Lir::CreateNativeGcMap() { 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* Mir2Lir::GetCompiledMethod() { } 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 92e21ffdf7..fae6c4c9a8 100644 --- a/compiler/dex/quick/mir_to_lir.h +++ b/compiler/dex/quick/mir_to_lir.h @@ -341,9 +341,6 @@ class Mir2Lir : public Backend { 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 @@ class Mir2Lir : public Backend { 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 @@ class Mir2Lir : public Backend { 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 fe38c2f5cd..67666831f0 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 3162ca5f46..c63dfa2497 100644 --- a/compiler/leb128_encoder_test.cc +++ b/compiler/leb128_encoder_test.cc @@ -92,11 +92,12 @@ static DecodeSignedLeb128TestCase sleb128_tests[] = { {(-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, UnsignedSingles) { } } -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 @@ TEST_F(Leb128Test, UnsignedStream) { 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, SignedSingles) { } } -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 @@ TEST_F(Leb128Test, SignedStream) { 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) { |