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;
         }