Refactor DexInstructionIterator

Add a way to get the dex PC for the "for each" use case.

Bug: 67104794
Test: test-art-host
Change-Id: I144c459c9a2a03ec8d56842280338d1f7ce1caf0
diff --git a/compiler/dex/inline_method_analyser.cc b/compiler/dex/inline_method_analyser.cc
index 925863e..518b0ec 100644
--- a/compiler/dex/inline_method_analyser.cc
+++ b/compiler/dex/inline_method_analyser.cc
@@ -302,7 +302,8 @@
   uint16_t this_vreg = code_item->registers_size_ - code_item->ins_size_;
   uint16_t zero_vreg_mask = 0u;
 
-  for (const Instruction& instruction : code_item->Instructions()) {
+  for (const DexInstructionPcPair& pair : code_item->Instructions()) {
+    const Instruction& instruction = pair.Inst();
     if (instruction.Opcode() == Instruction::RETURN_VOID) {
       break;
     } else if (instruction.Opcode() == Instruction::INVOKE_DIRECT) {
diff --git a/compiler/dex/verified_method.cc b/compiler/dex/verified_method.cc
index 9c5b632..df75e07 100644
--- a/compiler/dex/verified_method.cc
+++ b/compiler/dex/verified_method.cc
@@ -64,12 +64,11 @@
   if (method_verifier->HasFailures()) {
     return;
   }
-  IterationRange<DexInstructionIterator> instructions = method_verifier->CodeItem()->Instructions();
-  for (auto it = instructions.begin(); it != instructions.end(); ++it) {
-    const Instruction& inst = *it;
+  for (const DexInstructionPcPair& pair : method_verifier->CodeItem()->Instructions()) {
+    const Instruction& inst = pair.Inst();
     const Instruction::Code code = inst.Opcode();
     if (code == Instruction::CHECK_CAST) {
-      const uint32_t dex_pc = it.GetDexPC(instructions.begin());
+      const uint32_t dex_pc = pair.DexPc();
       if (!method_verifier->GetInstructionFlags(dex_pc).IsVisited()) {
         // Do not attempt to quicken this instruction, it's unreachable anyway.
         continue;
diff --git a/compiler/driver/compiler_driver.cc b/compiler/driver/compiler_driver.cc
index 135f9c7..ed3f0d2 100644
--- a/compiler/driver/compiler_driver.cc
+++ b/compiler/driver/compiler_driver.cc
@@ -736,13 +736,13 @@
   }
 
   ClassLinker* const class_linker = Runtime::Current()->GetClassLinker();
-  for (const Instruction& inst : code_item->Instructions()) {
-    switch (inst.Opcode()) {
+  for (const DexInstructionPcPair& inst : code_item->Instructions()) {
+    switch (inst->Opcode()) {
       case Instruction::CONST_STRING:
       case Instruction::CONST_STRING_JUMBO: {
-        dex::StringIndex string_index((inst.Opcode() == Instruction::CONST_STRING)
-            ? inst.VRegB_21c()
-            : inst.VRegB_31c());
+        dex::StringIndex string_index((inst->Opcode() == Instruction::CONST_STRING)
+            ? inst->VRegB_21c()
+            : inst->VRegB_31c());
         mirror::String* string = class_linker->ResolveString(dex_file, string_index, dex_cache);
         CHECK(string != nullptr) << "Could not allocate a string when forcing determinism";
         break;
@@ -2416,14 +2416,14 @@
     if (clinit != nullptr) {
       const DexFile::CodeItem* code_item = clinit->GetCodeItem();
       DCHECK(code_item != nullptr);
-      for (const Instruction& inst : code_item->Instructions()) {
-        if (inst.Opcode() == Instruction::CONST_STRING) {
+      for (const DexInstructionPcPair& inst : code_item->Instructions()) {
+        if (inst->Opcode() == Instruction::CONST_STRING) {
           ObjPtr<mirror::String> s = class_linker->ResolveString(
-              *dex_file, dex::StringIndex(inst.VRegB_21c()), h_dex_cache);
+              *dex_file, dex::StringIndex(inst->VRegB_21c()), h_dex_cache);
           CHECK(s != nullptr);
-        } else if (inst.Opcode() == Instruction::CONST_STRING_JUMBO) {
+        } else if (inst->Opcode() == Instruction::CONST_STRING_JUMBO) {
           ObjPtr<mirror::String> s = class_linker->ResolveString(
-              *dex_file, dex::StringIndex(inst.VRegB_31c()), h_dex_cache);
+              *dex_file, dex::StringIndex(inst->VRegB_31c()), h_dex_cache);
           CHECK(s != nullptr);
         }
       }
diff --git a/compiler/optimizing/code_generator.cc b/compiler/optimizing/code_generator.cc
index b8d1f52..2314251 100644
--- a/compiler/optimizing/code_generator.cc
+++ b/compiler/optimizing/code_generator.cc
@@ -919,10 +919,9 @@
   }
   ArenaVector<size_t> covered(
       loop_headers.size(), 0, graph.GetAllocator()->Adapter(kArenaAllocMisc));
-  IterationRange<DexInstructionIterator> instructions = code_item.Instructions();
-  for (auto it = instructions.begin(); it != instructions.end(); ++it) {
-    const uint32_t dex_pc = it.GetDexPC(instructions.begin());
-    const Instruction& instruction = *it;
+  for (const DexInstructionPcPair& pair : code_item.Instructions()) {
+    const uint32_t dex_pc = pair.DexPc();
+    const Instruction& instruction = pair.Inst();
     if (instruction.IsBranch()) {
       uint32_t target = dex_pc + instruction.GetTargetOffset();
       CheckCovers(target, graph, code_info, loop_headers, &covered);
diff --git a/compiler/optimizing/instruction_builder.cc b/compiler/optimizing/instruction_builder.cc
index 902985e..0f0be20 100644
--- a/compiler/optimizing/instruction_builder.cc
+++ b/compiler/optimizing/instruction_builder.cc
@@ -382,16 +382,18 @@
   dex_file_->DecodeDebugPositionInfo(&code_item_, Callback::Position, locations);
   // Instruction-specific tweaks.
   IterationRange<DexInstructionIterator> instructions = code_item_.Instructions();
-  for (const Instruction& inst : instructions) {
-    switch (inst.Opcode()) {
+  for (DexInstructionIterator it = instructions.begin(); it != instructions.end(); ++it) {
+    switch (it->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(inst.GetDexPc(code_item_.insns_));
-        const Instruction* next = inst.Next();
-        if (DexInstructionIterator(next) != instructions.end()) {
-          locations->SetBit(next->GetDexPc(code_item_.insns_));
+        locations->ClearBit(it.DexPc());
+        DexInstructionIterator next = it;
+        ++next;
+        DCHECK(next != it);
+        if (next != instructions.end()) {
+          locations->SetBit(next.DexPc());
         }
         break;
       }