Add DexInstructionIterator and use it a few places

Motivation:
Want to start abstracting away dex specific functionality to enable
CompactDex. Adding an iterator will enable CompactDex iteration to
work differently than normal dex iteration.

Will eventually replace CodeItemIterator.

Bug: 63756964
Test: test-art-host

Change-Id: I90e67c1a994b7698aaac0523a82816b0a003fbdc
diff --git a/compiler/dex/dex_to_dex_compiler.cc b/compiler/dex/dex_to_dex_compiler.cc
index e49f83f..7581962 100644
--- a/compiler/dex/dex_to_dex_compiler.cc
+++ b/compiler/dex/dex_to_dex_compiler.cc
@@ -374,8 +374,8 @@
       // Dex pc is not serialized, only used for checking the instructions. Since we access the
       // array based on the index of the quickened instruction, the indexes must line up perfectly.
       // The reader side uses the NeedsIndexForInstruction function too.
-      const Instruction* inst = Instruction::At(code_item->insns_ + info.dex_pc);
-      CHECK(QuickenInfoTable::NeedsIndexForInstruction(inst)) << inst->Opcode();
+      const Instruction& inst = code_item->InstructionAt(info.dex_pc);
+      CHECK(QuickenInfoTable::NeedsIndexForInstruction(&inst)) << inst.Opcode();
       // Add the index.
       quicken_data.push_back(static_cast<uint8_t>(info.dex_member_index >> 0));
       quicken_data.push_back(static_cast<uint8_t>(info.dex_member_index >> 8));
diff --git a/compiler/dex/inline_method_analyser.cc b/compiler/dex/inline_method_analyser.cc
index c8e3d5e..925863e 100644
--- a/compiler/dex/inline_method_analyser.cc
+++ b/compiler/dex/inline_method_analyser.cc
@@ -64,14 +64,14 @@
  private:
   explicit Matcher(const DexFile::CodeItem* code_item)
       : code_item_(code_item),
-        instruction_(Instruction::At(code_item->insns_)),
+        instruction_(code_item->Instructions().begin()),
         pos_(0u),
         mark_(0u) { }
 
   static bool DoMatch(const DexFile::CodeItem* code_item, MatchFn* const* pattern, size_t size);
 
   const DexFile::CodeItem* const code_item_;
-  const Instruction* instruction_;
+  DexInstructionIterator instruction_;
   size_t pos_;
   size_t mark_;
 };
@@ -93,7 +93,7 @@
     return false;
   }
   matcher->pos_ += 1u;
-  matcher->instruction_ = matcher->instruction_->Next();
+  ++matcher->instruction_;
   return true;
 }
 
@@ -105,7 +105,7 @@
     return true;
   }
   matcher->pos_ = matcher->mark_;
-  matcher->instruction_ = matcher->instruction_->Next();
+  ++matcher->instruction_;
   return true;
 }
 
@@ -301,26 +301,27 @@
   // Verify the invoke, prevent a few odd cases and collect IPUTs.
   uint16_t this_vreg = code_item->registers_size_ - code_item->ins_size_;
   uint16_t zero_vreg_mask = 0u;
-  for (const Instruction* instruction = Instruction::At(code_item->insns_);
-      instruction->Opcode() != Instruction::RETURN_VOID;
-      instruction = instruction->Next()) {
-    if (instruction->Opcode() == Instruction::INVOKE_DIRECT) {
-      ArtMethod* target_method = GetTargetConstructor(method, instruction);
+
+  for (const Instruction& instruction : code_item->Instructions()) {
+    if (instruction.Opcode() == Instruction::RETURN_VOID) {
+      break;
+    } else if (instruction.Opcode() == Instruction::INVOKE_DIRECT) {
+      ArtMethod* target_method = GetTargetConstructor(method, &instruction);
       if (target_method == nullptr) {
         return false;
       }
       // We allow forwarding constructors only if they pass more arguments
       // to prevent infinite recursion.
       if (target_method->GetDeclaringClass() == method->GetDeclaringClass() &&
-          instruction->VRegA_35c() <= code_item->ins_size_) {
+          instruction.VRegA_35c() <= code_item->ins_size_) {
         return false;
       }
-      size_t forwarded = CountForwardedConstructorArguments(code_item, instruction, zero_vreg_mask);
+      size_t forwarded = CountForwardedConstructorArguments(code_item, &instruction, zero_vreg_mask);
       if (forwarded == static_cast<size_t>(-1)) {
         return false;
       }
       if (target_method->GetDeclaringClass()->IsObjectClass()) {
-        DCHECK_EQ(Instruction::At(target_method->GetCodeItem()->insns_)->Opcode(),
+        DCHECK_EQ(target_method->GetCodeItem()->Instructions().begin()->Opcode(),
                   Instruction::RETURN_VOID);
       } else {
         const DexFile::CodeItem* target_code_item = target_method->GetCodeItem();
@@ -345,15 +346,15 @@
           return false;
         }
       }
-    } else if (IsInstructionDirectConst(instruction->Opcode())) {
-      zero_vreg_mask |= GetZeroVRegMask(instruction);
+    } else if (IsInstructionDirectConst(instruction.Opcode())) {
+      zero_vreg_mask |= GetZeroVRegMask(&instruction);
       if ((zero_vreg_mask & (1u << this_vreg)) != 0u) {
         return false;  // Overwriting `this` is unsupported.
       }
     } else {
-      DCHECK(IsInstructionIPut(instruction->Opcode()));
-      DCHECK_EQ(instruction->VRegB_22c(), this_vreg);
-      if (!RecordConstructorIPut(method, instruction, this_vreg, zero_vreg_mask, iputs)) {
+      DCHECK(IsInstructionIPut(instruction.Opcode()));
+      DCHECK_EQ(instruction.VRegB_22c(), this_vreg);
+      if (!RecordConstructorIPut(method, &instruction, this_vreg, zero_vreg_mask, iputs)) {
         return false;
       }
     }
@@ -447,8 +448,7 @@
   // We currently support only plain return or 2-instruction methods.
 
   DCHECK_NE(code_item->insns_size_in_code_units_, 0u);
-  const Instruction* instruction = Instruction::At(code_item->insns_);
-  Instruction::Code opcode = instruction->Opcode();
+  Instruction::Code opcode = code_item->Instructions().begin()->Opcode();
 
   switch (opcode) {
     case Instruction::RETURN_VOID:
@@ -519,7 +519,7 @@
 
 bool InlineMethodAnalyser::AnalyseReturnMethod(const DexFile::CodeItem* code_item,
                                                InlineMethod* result) {
-  const Instruction* return_instruction = Instruction::At(code_item->insns_);
+  DexInstructionIterator return_instruction = code_item->Instructions().begin();
   Instruction::Code return_opcode = return_instruction->Opcode();
   uint32_t reg = return_instruction->VRegA_11x();
   uint32_t arg_start = code_item->registers_size_ - code_item->ins_size_;
@@ -541,7 +541,7 @@
 
 bool InlineMethodAnalyser::AnalyseConstMethod(const DexFile::CodeItem* code_item,
                                               InlineMethod* result) {
-  const Instruction* instruction = Instruction::At(code_item->insns_);
+  DexInstructionIterator instruction = code_item->Instructions().begin();
   const Instruction* return_instruction = instruction->Next();
   Instruction::Code return_opcode = return_instruction->Opcode();
   if (return_opcode != Instruction::RETURN &&
@@ -575,7 +575,7 @@
                                              bool is_static,
                                              ArtMethod* method,
                                              InlineMethod* result) {
-  const Instruction* instruction = Instruction::At(code_item->insns_);
+  DexInstructionIterator instruction = code_item->Instructions().begin();
   Instruction::Code opcode = instruction->Opcode();
   DCHECK(IsInstructionIGet(opcode));
 
@@ -639,7 +639,7 @@
                                              bool is_static,
                                              ArtMethod* method,
                                              InlineMethod* result) {
-  const Instruction* instruction = Instruction::At(code_item->insns_);
+  DexInstructionIterator instruction = code_item->Instructions().begin();
   Instruction::Code opcode = instruction->Opcode();
   DCHECK(IsInstructionIPut(opcode));
 
diff --git a/compiler/dex/verified_method.cc b/compiler/dex/verified_method.cc
index e46dc59..9c5b632 100644
--- a/compiler/dex/verified_method.cc
+++ b/compiler/dex/verified_method.cc
@@ -64,24 +64,21 @@
   if (method_verifier->HasFailures()) {
     return;
   }
-  const DexFile::CodeItem* code_item = method_verifier->CodeItem();
-  const Instruction* inst = Instruction::At(code_item->insns_);
-  const Instruction* end = Instruction::At(code_item->insns_ +
-                                           code_item->insns_size_in_code_units_);
-
-  for (; inst < end; inst = inst->Next()) {
-    Instruction::Code code = inst->Opcode();
+  IterationRange<DexInstructionIterator> instructions = method_verifier->CodeItem()->Instructions();
+  for (auto it = instructions.begin(); it != instructions.end(); ++it) {
+    const Instruction& inst = *it;
+    const Instruction::Code code = inst.Opcode();
     if (code == Instruction::CHECK_CAST) {
-      uint32_t dex_pc = inst->GetDexPc(code_item->insns_);
+      const uint32_t dex_pc = it.GetDexPC(instructions.begin());
       if (!method_verifier->GetInstructionFlags(dex_pc).IsVisited()) {
         // Do not attempt to quicken this instruction, it's unreachable anyway.
         continue;
       }
       const verifier::RegisterLine* line = method_verifier->GetRegLine(dex_pc);
       const verifier::RegType& reg_type(line->GetRegisterType(method_verifier,
-                                                              inst->VRegA_21c()));
+                                                              inst.VRegA_21c()));
       const verifier::RegType& cast_type =
-          method_verifier->ResolveCheckedClass(dex::TypeIndex(inst->VRegB_21c()));
+          method_verifier->ResolveCheckedClass(dex::TypeIndex(inst.VRegB_21c()));
       // Pass null for the method verifier to not record the VerifierDeps dependency
       // if the types are not assignable.
       if (cast_type.IsStrictlyAssignableFrom(reg_type, /* method_verifier */ nullptr)) {