Delete CodeItemIterator
Replace uses with DexInstructionIterator.
Bug: 63756964
Test: test-art-host-gtest
Change-Id: I28c839c372edcb60583867355d46b14f8752d41b
diff --git a/compiler/dex/dex_to_dex_compiler.cc b/compiler/dex/dex_to_dex_compiler.cc
index a94dbe9..cc452fc 100644
--- a/compiler/dex/dex_to_dex_compiler.cc
+++ b/compiler/dex/dex_to_dex_compiler.cc
@@ -112,9 +112,10 @@
void DexCompiler::Compile() {
DCHECK_EQ(dex_to_dex_compilation_level_, DexToDexCompilationLevel::kOptimize);
- for (CodeItemIterator it(*unit_.GetCodeItem()); !it.Done(); it.Advance()) {
- Instruction* inst = const_cast<Instruction*>(&it.CurrentInstruction());
- const uint32_t dex_pc = it.CurrentDexPc();
+ IterationRange<DexInstructionIterator> instructions = unit_.GetCodeItem()->Instructions();
+ for (DexInstructionIterator it = instructions.begin(); it != instructions.end(); ++it) {
+ const uint32_t dex_pc = it.DexPc();
+ Instruction* inst = const_cast<Instruction*>(&it.Inst());
switch (inst->Opcode()) {
case Instruction::RETURN_VOID:
CompileReturnVoid(inst, dex_pc);
@@ -125,7 +126,7 @@
if (inst->Opcode() == Instruction::NOP) {
// We turned the CHECK_CAST into two NOPs, avoid visiting the second NOP twice since this
// would add 2 quickening info entries.
- it.Advance();
+ ++it;
}
break;
@@ -362,8 +363,8 @@
if (kIsDebugBuild) {
// Double check that the counts line up with the size of the quicken info.
size_t quicken_count = 0;
- for (CodeItemIterator it(*code_item); !it.Done(); it.Advance()) {
- if (QuickenInfoTable::NeedsIndexForInstruction(&it.CurrentInstruction())) {
+ for (const DexInstructionPcPair& pair : code_item->Instructions()) {
+ if (QuickenInfoTable::NeedsIndexForInstruction(&pair.Inst())) {
++quicken_count;
}
}
diff --git a/compiler/optimizing/block_builder.cc b/compiler/optimizing/block_builder.cc
index d7def77..595dd4d 100644
--- a/compiler/optimizing/block_builder.cc
+++ b/compiler/optimizing/block_builder.cc
@@ -76,9 +76,10 @@
// Iterate over all instructions and find branching instructions. Create blocks for
// the locations these instructions branch to.
- for (CodeItemIterator it(code_item_); !it.Done(); it.Advance()) {
- uint32_t dex_pc = it.CurrentDexPc();
- const Instruction& instruction = it.CurrentInstruction();
+ IterationRange<DexInstructionIterator> instructions = code_item_.Instructions();
+ for (const DexInstructionPcPair& pair : instructions) {
+ const uint32_t dex_pc = pair.DexPc();
+ const Instruction& instruction = pair.Inst();
if (instruction.IsBranch()) {
number_of_branches_++;
@@ -105,13 +106,13 @@
}
if (instruction.CanFlowThrough()) {
- if (it.IsLast()) {
+ DexInstructionIterator next(std::next(DexInstructionIterator(pair)));
+ if (next == instructions.end()) {
// In the normal case we should never hit this but someone can artificially forge a dex
// file to fall-through out the method code. In this case we bail out compilation.
return false;
- } else {
- MaybeCreateBlockAt(dex_pc + it.CurrentInstruction().SizeInCodeUnits());
}
+ MaybeCreateBlockAt(next.DexPc());
}
}
@@ -126,8 +127,9 @@
bool is_throwing_block = false;
// Calculate the qucikening index here instead of CreateBranchTargets since it's easier to
// calculate in dex_pc order.
- for (CodeItemIterator it(code_item_); !it.Done(); it.Advance()) {
- uint32_t dex_pc = it.CurrentDexPc();
+ for (const DexInstructionPcPair& pair : code_item_.Instructions()) {
+ const uint32_t dex_pc = pair.DexPc();
+ const Instruction& instruction = pair.Inst();
// Check if this dex_pc address starts a new basic block.
HBasicBlock* next_block = GetBlockAt(dex_pc);
@@ -144,7 +146,7 @@
graph_->AddBlock(block);
}
// Make sure to increment this before the continues.
- if (QuickenInfoTable::NeedsIndexForInstruction(&it.CurrentInstruction())) {
+ if (QuickenInfoTable::NeedsIndexForInstruction(&instruction)) {
++quicken_index;
}
@@ -153,8 +155,6 @@
continue;
}
- const Instruction& instruction = it.CurrentInstruction();
-
if (!is_throwing_block && IsThrowingDexInstruction(instruction)) {
DCHECK(!ContainsElement(throwing_blocks_, block));
is_throwing_block = true;
@@ -185,9 +185,9 @@
continue;
}
+ // Go to the next instruction in case we read dex PC below.
if (instruction.CanFlowThrough()) {
- uint32_t next_dex_pc = dex_pc + instruction.SizeInCodeUnits();
- block->AddSuccessor(GetBlockAt(next_dex_pc));
+ block->AddSuccessor(GetBlockAt(std::next(DexInstructionIterator(pair)).DexPc()));
}
// The basic block ends here. Do not add any more instructions.
@@ -229,7 +229,7 @@
}
}
- const Instruction& first = GetDexInstructionAt(code_item_, catch_block->GetDexPc());
+ const Instruction& first = code_item_.InstructionAt(catch_block->GetDexPc());
if (first.Opcode() == Instruction::MOVE_EXCEPTION) {
// Verifier guarantees that if a catch block begins with MOVE_EXCEPTION then
// it has no live normal predecessors.
diff --git a/compiler/optimizing/instruction_builder.cc b/compiler/optimizing/instruction_builder.cc
index 0f0be20..8e9b818 100644
--- a/compiler/optimizing/instruction_builder.cc
+++ b/compiler/optimizing/instruction_builder.cc
@@ -321,19 +321,19 @@
quicken_index = block_builder_->GetQuickenIndex(block_dex_pc);
}
- for (CodeItemIterator it(code_item_, block_dex_pc); !it.Done(); it.Advance()) {
+ for (const DexInstructionPcPair& pair : code_item_.Instructions(block_dex_pc)) {
if (current_block_ == nullptr) {
// The previous instruction ended this block.
break;
}
- uint32_t dex_pc = it.CurrentDexPc();
+ const uint32_t dex_pc = pair.DexPc();
if (dex_pc != block_dex_pc && FindBlockStartingAt(dex_pc) != nullptr) {
// This dex_pc starts a new basic block.
break;
}
- if (current_block_->IsTryBlock() && IsThrowingDexInstruction(it.CurrentInstruction())) {
+ if (current_block_->IsTryBlock() && IsThrowingDexInstruction(pair.Inst())) {
PropagateLocalsToCatchBlocks();
}
@@ -341,11 +341,11 @@
AppendInstruction(new (allocator_) HNativeDebugInfo(dex_pc));
}
- if (!ProcessDexInstruction(it.CurrentInstruction(), dex_pc, quicken_index)) {
+ if (!ProcessDexInstruction(pair.Inst(), dex_pc, quicken_index)) {
return false;
}
- if (QuickenInfoTable::NeedsIndexForInstruction(&it.CurrentInstruction())) {
+ if (QuickenInfoTable::NeedsIndexForInstruction(&pair.Inst())) {
++quicken_index;
}
}
@@ -382,16 +382,15 @@
dex_file_->DecodeDebugPositionInfo(&code_item_, Callback::Position, locations);
// Instruction-specific tweaks.
IterationRange<DexInstructionIterator> instructions = code_item_.Instructions();
- for (DexInstructionIterator it = instructions.begin(); it != instructions.end(); ++it) {
- switch (it->Opcode()) {
+ for (const DexInstructionPcPair& inst : instructions) {
+ switch (inst->Opcode()) {
case Instruction::MOVE_EXCEPTION: {
// Stop in native debugger after the exception has been moved.
// The compiler also expects the move at the start of basic block so
// we do not want to interfere by inserting native-debug-info before it.
- locations->ClearBit(it.DexPc());
- DexInstructionIterator next = it;
- ++next;
- DCHECK(next != it);
+ locations->ClearBit(inst.DexPc());
+ DexInstructionIterator next = std::next(DexInstructionIterator(inst));
+ DCHECK(next.DexPc() != inst.DexPc());
if (next != instructions.end()) {
locations->SetBit(next.DexPc());
}
diff --git a/dex2oat/dex2oat_test.cc b/dex2oat/dex2oat_test.cc
index cb91978..6a2ef1e 100644
--- a/dex2oat/dex2oat_test.cc
+++ b/dex2oat/dex2oat_test.cc
@@ -940,8 +940,8 @@
class_it.HasNext();
class_it.Next()) {
if (class_it.IsAtMethod() && class_it.GetMethodCodeItem() != nullptr) {
- for (CodeItemIterator it(*class_it.GetMethodCodeItem()); !it.Done(); it.Advance()) {
- Instruction* inst = const_cast<Instruction*>(&it.CurrentInstruction());
+ for (const DexInstructionPcPair& inst :
+ class_it.GetMethodCodeItem()->Instructions()) {
ASSERT_FALSE(inst->IsQuickened());
}
}
diff --git a/profman/profman.cc b/profman/profman.cc
index 4c4bb87..ea534f8 100644
--- a/profman/profman.cc
+++ b/profman/profman.cc
@@ -725,15 +725,15 @@
const DexFile::CodeItem* code_item = dex_file->GetCodeItem(offset);
bool found_invoke = false;
- for (CodeItemIterator it(*code_item); !it.Done(); it.Advance()) {
- if (it.CurrentInstruction().Opcode() == Instruction::INVOKE_VIRTUAL) {
+ for (const DexInstructionPcPair& inst : code_item->Instructions()) {
+ if (inst->Opcode() == Instruction::INVOKE_VIRTUAL) {
if (found_invoke) {
LOG(ERROR) << "Multiple invoke INVOKE_VIRTUAL found: "
<< dex_file->PrettyMethod(method_index);
return false;
}
found_invoke = true;
- *dex_pc = it.CurrentDexPc();
+ *dex_pc = inst.DexPc();
}
}
if (!found_invoke) {
diff --git a/runtime/bytecode_utils.h b/runtime/bytecode_utils.h
index b6a3c03..815e0ba 100644
--- a/runtime/bytecode_utils.h
+++ b/runtime/bytecode_utils.h
@@ -24,35 +24,6 @@
namespace art {
-class CodeItemIterator : public ValueObject {
- public:
- explicit CodeItemIterator(const DexFile::CodeItem& code_item) : CodeItemIterator(code_item, 0u) {}
- CodeItemIterator(const DexFile::CodeItem& code_item, uint32_t start_dex_pc)
- : code_ptr_(code_item.insns_ + start_dex_pc),
- code_end_(code_item.insns_ + code_item.insns_size_in_code_units_),
- dex_pc_(start_dex_pc) {}
-
- bool Done() const { return code_ptr_ >= code_end_; }
- bool IsLast() const { return code_ptr_ + CurrentInstruction().SizeInCodeUnits() >= code_end_; }
-
- const Instruction& CurrentInstruction() const { return *Instruction::At(code_ptr_); }
- uint32_t CurrentDexPc() const { return dex_pc_; }
-
- void Advance() {
- DCHECK(!Done());
- size_t instruction_size = CurrentInstruction().SizeInCodeUnits();
- code_ptr_ += instruction_size;
- dex_pc_ += instruction_size;
- }
-
- private:
- const uint16_t* code_ptr_;
- const uint16_t* const code_end_;
- uint32_t dex_pc_;
-
- DISALLOW_COPY_AND_ASSIGN(CodeItemIterator);
-};
-
class DexSwitchTable : public ValueObject {
public:
DexSwitchTable(const Instruction& instruction, uint32_t dex_pc)
@@ -164,10 +135,6 @@
size_t index_;
};
-inline const Instruction& GetDexInstructionAt(const DexFile::CodeItem& code_item, uint32_t dex_pc) {
- return CodeItemIterator(code_item, dex_pc).CurrentInstruction();
-}
-
inline bool IsThrowingDexInstruction(const Instruction& instruction) {
// Special-case MONITOR_EXIT which is a throwing instruction but the verifier
// guarantees that it will never throw. This is necessary to avoid rejecting
diff --git a/runtime/dex_file.h b/runtime/dex_file.h
index f239edc..5c9b258 100644
--- a/runtime/dex_file.h
+++ b/runtime/dex_file.h
@@ -301,8 +301,9 @@
// Raw code_item.
struct CodeItem {
- IterationRange<DexInstructionIterator> Instructions() const {
- return { DexInstructionIterator(insns_, 0u),
+ IterationRange<DexInstructionIterator> Instructions(uint32_t start_dex_pc = 0u) const {
+ DCHECK_LE(start_dex_pc, insns_size_in_code_units_);
+ return { DexInstructionIterator(insns_, start_dex_pc),
DexInstructionIterator(insns_, insns_size_in_code_units_) };
}
diff --git a/runtime/dex_instruction_iterator.h b/runtime/dex_instruction_iterator.h
index f77908c..be583a2 100644
--- a/runtime/dex_instruction_iterator.h
+++ b/runtime/dex_instruction_iterator.h
@@ -123,6 +123,9 @@
explicit DexInstructionIterator(const uint16_t* inst, uint32_t dex_pc)
: DexInstructionIteratorBase(Instruction::At(inst), dex_pc) {}
+ explicit DexInstructionIterator(const DexInstructionPcPair& pair)
+ : DexInstructionIterator(pair.Instructions(), pair.DexPc()) {}
+
// Value after modification.
DexInstructionIterator& operator++() {
data_.dex_pc_ += Inst().SizeInCodeUnits();
diff --git a/runtime/dex_to_dex_decompiler.cc b/runtime/dex_to_dex_decompiler.cc
index 908405b..a5ebade 100644
--- a/runtime/dex_to_dex_decompiler.cc
+++ b/runtime/dex_to_dex_decompiler.cc
@@ -89,8 +89,8 @@
// because the RETURN_VOID quickening is not encoded in the quickening data. Because
// unquickening is a rare need and not performance sensitive, it is not worth the
// added storage to also add the RETURN_VOID quickening in the quickened data.
- for (CodeItemIterator it(code_item_); !it.Done(); it.Advance()) {
- Instruction* inst = const_cast<Instruction*>(&it.CurrentInstruction());
+ for (const DexInstructionPcPair& pair : code_item_.Instructions()) {
+ Instruction* inst = const_cast<Instruction*>(&pair.Inst());
switch (inst->Opcode()) {
case Instruction::RETURN_VOID_NO_BARRIER:
diff --git a/test/983-source-transform-verify/source_transform.cc b/test/983-source-transform-verify/source_transform.cc
index ef67ace..ca3f88b 100644
--- a/test/983-source-transform-verify/source_transform.cc
+++ b/test/983-source-transform-verify/source_transform.cc
@@ -89,13 +89,13 @@
if (!it.IsAtMethod() || it.GetMethodCodeItem() == nullptr) {
continue;
}
- for (CodeItemIterator code_it(*it.GetMethodCodeItem()); !code_it.Done(); code_it.Advance()) {
- const Instruction& inst = code_it.CurrentInstruction();
+ for (const DexInstructionPcPair& pair : it.GetMethodCodeItem()->Instructions()) {
+ const Instruction& inst = pair.Inst();
int forbiden_flags = (Instruction::kVerifyError | Instruction::kVerifyRuntimeOnly);
if (inst.Opcode() == Instruction::RETURN_VOID_NO_BARRIER ||
(inst.GetVerifyExtraFlags() & forbiden_flags) != 0) {
std::cout << "Unexpected instruction found in " << dex->PrettyMethod(it.GetMemberIndex())
- << " [Dex PC: 0x" << std::hex << code_it.CurrentDexPc() << std::dec << "] : "
+ << " [Dex PC: 0x" << std::hex << pair.DexPc() << std::dec << "] : "
<< inst.DumpString(dex.get()) << std::endl;
continue;
}