Merge "Fix potential out of bounds access in 151-OpenFileLimit test."
diff --git a/Android.mk b/Android.mk
index cb0b709..0a90a0b 100644
--- a/Android.mk
+++ b/Android.mk
@@ -135,11 +135,11 @@
 else
 test-art-target-sync: $(TEST_ART_TARGET_SYNC_DEPS)
 	$(TEST_ART_ADB_ROOT_AND_REMOUNT)
-	adb wait-for-device push $(ANDROID_PRODUCT_OUT)/system $(ART_TEST_ANDROID_ROOT)
+	adb wait-for-device push $(PRODUCT_OUT)/system $(ART_TEST_ANDROID_ROOT)
 # Push the contents of the `data` dir into `/data` on the device.  If
 # `/data` already exists on the device, it is not overwritten, but its
 # contents are updated.
-	adb push $(ANDROID_PRODUCT_OUT)/data /
+	adb push $(PRODUCT_OUT)/data /
 endif
 endif
 
diff --git a/compiler/exception_test.cc b/compiler/exception_test.cc
index 4dbef0d..59d20f8 100644
--- a/compiler/exception_test.cc
+++ b/compiler/exception_test.cc
@@ -24,6 +24,7 @@
 #include "common_runtime_test.h"
 #include "dex_file-inl.h"
 #include "dex_file.h"
+#include "dex_file_exception_helpers.h"
 #include "gtest/gtest.h"
 #include "handle_scope-inl.h"
 #include "leb128.h"
@@ -129,20 +130,18 @@
 
 TEST_F(ExceptionTest, FindCatchHandler) {
   ScopedObjectAccess soa(Thread::Current());
-  const DexFile::CodeItem* code_item = dex_->GetCodeItem(method_f_->GetCodeItemOffset());
-  CodeItemDataAccessor accessor(dex_, code_item);
+  CodeItemDataAccessor accessor(dex_, dex_->GetCodeItem(method_f_->GetCodeItemOffset()));
 
-  ASSERT_TRUE(code_item != nullptr);
+  ASSERT_TRUE(accessor.HasCodeItem());
 
   ASSERT_EQ(2u, accessor.TriesSize());
   ASSERT_NE(0u, accessor.InsnsSizeInCodeUnits());
 
-  const DexFile::TryItem *t0, *t1;
-  t0 = dex_->GetTryItems(*code_item, 0);
-  t1 = dex_->GetTryItems(*code_item, 1);
-  EXPECT_LE(t0->start_addr_, t1->start_addr_);
+  const DexFile::TryItem& t0 = accessor.TryItems().begin()[0];
+  const DexFile::TryItem& t1 = accessor.TryItems().begin()[1];
+  EXPECT_LE(t0.start_addr_, t1.start_addr_);
   {
-    CatchHandlerIterator iter(*code_item, 4 /* Dex PC in the first try block */);
+    CatchHandlerIterator iter(accessor, 4 /* Dex PC in the first try block */);
     EXPECT_STREQ("Ljava/io/IOException;", dex_->StringByTypeIdx(iter.GetHandlerTypeIndex()));
     ASSERT_TRUE(iter.HasNext());
     iter.Next();
@@ -152,14 +151,14 @@
     EXPECT_FALSE(iter.HasNext());
   }
   {
-    CatchHandlerIterator iter(*code_item, 8 /* Dex PC in the second try block */);
+    CatchHandlerIterator iter(accessor, 8 /* Dex PC in the second try block */);
     EXPECT_STREQ("Ljava/io/IOException;", dex_->StringByTypeIdx(iter.GetHandlerTypeIndex()));
     ASSERT_TRUE(iter.HasNext());
     iter.Next();
     EXPECT_FALSE(iter.HasNext());
   }
   {
-    CatchHandlerIterator iter(*code_item, 11 /* Dex PC not in any try block */);
+    CatchHandlerIterator iter(accessor, 11 /* Dex PC not in any try block */);
     EXPECT_FALSE(iter.HasNext());
   }
 }
diff --git a/compiler/optimizing/block_builder.cc b/compiler/optimizing/block_builder.cc
index c505efa..0c92600 100644
--- a/compiler/optimizing/block_builder.cc
+++ b/compiler/optimizing/block_builder.cc
@@ -19,6 +19,7 @@
 #include "base/logging.h"  // FOR VLOG.
 #include "bytecode_utils.h"
 #include "code_item_accessors-inl.h"
+#include "dex_file_exception_helpers.h"
 #include "quicken_info.h"
 
 namespace art {
diff --git a/dexdump/dexdump.cc b/dexdump/dexdump.cc
index 730d4b9..ba2a922 100644
--- a/dexdump/dexdump.cc
+++ b/dexdump/dexdump.cc
@@ -48,6 +48,7 @@
 #include "dex_file-inl.h"
 #include "dex_file_loader.h"
 #include "dex_file_types.h"
+#include "dex_file_exception_helpers.h"
 #include "dex_instruction-inl.h"
 #include "dexdump_cfg.h"
 
@@ -735,7 +736,8 @@
  * Dumps the catches table associated with the code.
  */
 static void dumpCatches(const DexFile* pDexFile, const DexFile::CodeItem* pCode) {
-  const u4 triesSize = CodeItemDataAccessor(pDexFile, pCode).TriesSize();
+  CodeItemDataAccessor accessor(pDexFile, pCode);
+  const u4 triesSize = accessor.TriesSize();
 
   // No catch table.
   if (triesSize == 0) {
@@ -745,12 +747,11 @@
 
   // Dump all table entries.
   fprintf(gOutFile, "      catches       : %d\n", triesSize);
-  for (u4 i = 0; i < triesSize; i++) {
-    const DexFile::TryItem* pTry = pDexFile->GetTryItems(*pCode, i);
-    const u4 start = pTry->start_addr_;
-    const u4 end = start + pTry->insn_count_;
+  for (const DexFile::TryItem& try_item : accessor.TryItems()) {
+    const u4 start = try_item.start_addr_;
+    const u4 end = start + try_item.insn_count_;
     fprintf(gOutFile, "        0x%04x - 0x%04x\n", start, end);
-    for (CatchHandlerIterator it(*pCode, *pTry); it.HasNext(); it.Next()) {
+    for (CatchHandlerIterator it(accessor, try_item); it.HasNext(); it.Next()) {
       const dex::TypeIndex tidx = it.GetHandlerTypeIndex();
       const char* descriptor = (!tidx.IsValid()) ? "<any>" : pDexFile->StringByTypeIdx(tidx);
       fprintf(gOutFile, "          %s -> 0x%04x\n", descriptor, it.GetHandlerAddress());
diff --git a/dexdump/dexdump_cfg.cc b/dexdump/dexdump_cfg.cc
index dd57a11..7e9f113 100644
--- a/dexdump/dexdump_cfg.cc
+++ b/dexdump/dexdump_cfg.cc
@@ -27,6 +27,7 @@
 
 #include "code_item_accessors-no_art-inl.h"
 #include "dex_file-inl.h"
+#include "dex_file_exception_helpers.h"
 #include "dex_instruction-inl.h"
 
 namespace art {
@@ -38,7 +39,7 @@
   os << "digraph {\n";
   os << "  # /* " << dex_file->PrettyMethod(dex_method_idx, true) << " */\n";
 
-  CodeItemInstructionAccessor accessor(dex_file, code_item);
+  CodeItemDataAccessor accessor(dex_file, code_item);
 
   std::set<uint32_t> dex_pc_is_branch_target;
   {
@@ -195,7 +196,7 @@
           }
 
           // Look at the exceptions of the first entry.
-          CatchHandlerIterator catch_it(*code_item, dex_pc);
+          CatchHandlerIterator catch_it(accessor, dex_pc);
           for (; catch_it.HasNext(); catch_it.Next()) {
             exception_targets.insert(catch_it.GetHandlerAddress());
           }
@@ -254,7 +255,7 @@
         // Exception edges. If this is not the first instruction in the block
         if (block_start_dex_pc != dex_pc) {
           std::set<uint32_t> current_handler_pcs;
-          CatchHandlerIterator catch_it(*code_item, dex_pc);
+          CatchHandlerIterator catch_it(accessor, dex_pc);
           for (; catch_it.HasNext(); catch_it.Next()) {
             current_handler_pcs.insert(catch_it.GetHandlerAddress());
           }
@@ -295,7 +296,7 @@
       const Instruction* inst = &accessor.InstructionAt(dex_pc);
       uint32_t this_node_id = dex_pc_to_incl_id.find(dex_pc)->second;
       while (true) {
-        CatchHandlerIterator catch_it(*code_item, dex_pc);
+        CatchHandlerIterator catch_it(accessor, dex_pc);
         if (catch_it.HasNext()) {
           std::set<uint32_t> handled_targets;
           for (; catch_it.HasNext(); catch_it.Next()) {
diff --git a/dexlayout/dex_ir.cc b/dexlayout/dex_ir.cc
index a163bd9..157d4ef 100644
--- a/dexlayout/dex_ir.cc
+++ b/dexlayout/dex_ir.cc
@@ -23,6 +23,7 @@
 #include "dex_ir.h"
 
 #include "code_item_accessors-inl.h"
+#include "dex_file_exception_helpers.h"
 #include "dex_instruction-inl.h"
 #include "dex_ir_builder.h"
 
@@ -610,7 +611,7 @@
       if (handlers == nullptr) {
         bool catch_all = false;
         TypeAddrPairVector* addr_pairs = new TypeAddrPairVector();
-        for (CatchHandlerIterator it(disk_code_item, disk_try_item); it.HasNext(); it.Next()) {
+        for (CatchHandlerIterator it(accessor, disk_try_item); it.HasNext(); it.Next()) {
           const dex::TypeIndex type_index = it.GetHandlerTypeIndex();
           const TypeId* type_id = GetTypeIdOrNullPtr(type_index.index_);
           catch_all |= type_id == nullptr;
diff --git a/runtime/Android.bp b/runtime/Android.bp
index 1e5fe16..8fe901d 100644
--- a/runtime/Android.bp
+++ b/runtime/Android.bp
@@ -58,8 +58,9 @@
         "compiler_filter.cc",
         "debugger.cc",
         "dex_file.cc",
-        "dex_file_loader.cc",
         "dex_file_annotations.cc",
+        "dex_file_exception_helpers.cc",
+        "dex_file_loader.cc",
         "dex_file_layout.cc",
         "dex_file_tracking_registrar.cc",
         "dex_file_verifier.cc",
diff --git a/runtime/art_method.cc b/runtime/art_method.cc
index 7ddaa7e..d6e4ce5 100644
--- a/runtime/art_method.cc
+++ b/runtime/art_method.cc
@@ -26,6 +26,7 @@
 #include "class_linker-inl.h"
 #include "debugger.h"
 #include "dex_file-inl.h"
+#include "dex_file_exception_helpers.h"
 #include "dex_instruction.h"
 #include "entrypoints/runtime_asm_entrypoints.h"
 #include "gc/accounting/card_table-inl.h"
@@ -263,7 +264,6 @@
 
 uint32_t ArtMethod::FindCatchBlock(Handle<mirror::Class> exception_type,
                                    uint32_t dex_pc, bool* has_no_move_exception) {
-  const DexFile::CodeItem* code_item = GetCodeItem();
   // Set aside the exception while we resolve its type.
   Thread* self = Thread::Current();
   StackHandleScope<1> hs(self);
@@ -272,7 +272,8 @@
   // Default to handler not found.
   uint32_t found_dex_pc = dex::kDexNoIndex;
   // Iterate over the catch handlers associated with dex_pc.
-  for (CatchHandlerIterator it(*code_item, dex_pc); it.HasNext(); it.Next()) {
+  CodeItemDataAccessor accessor(this);
+  for (CatchHandlerIterator it(accessor, dex_pc); it.HasNext(); it.Next()) {
     dex::TypeIndex iter_type_idx = it.GetHandlerTypeIndex();
     // Catch all case
     if (!iter_type_idx.IsValid()) {
@@ -297,7 +298,7 @@
     }
   }
   if (found_dex_pc != dex::kDexNoIndex) {
-    const Instruction& first_catch_instr = DexInstructions().InstructionAt(found_dex_pc);
+    const Instruction& first_catch_instr = accessor.InstructionAt(found_dex_pc);
     *has_no_move_exception = (first_catch_instr.Opcode() != Instruction::MOVE_EXCEPTION);
   }
   // Put the exception back.
diff --git a/runtime/class_linker.cc b/runtime/class_linker.cc
index 24fcce4..192517f 100644
--- a/runtime/class_linker.cc
+++ b/runtime/class_linker.cc
@@ -51,6 +51,7 @@
 #include "compiler_callbacks.h"
 #include "debugger.h"
 #include "dex_file-inl.h"
+#include "dex_file_exception_helpers.h"
 #include "dex_file_loader.h"
 #include "entrypoints/entrypoint_utils.h"
 #include "entrypoints/runtime_asm_entrypoints.h"
diff --git a/runtime/class_linker_test.cc b/runtime/class_linker_test.cc
index 246f89e..3dca2f9 100644
--- a/runtime/class_linker_test.cc
+++ b/runtime/class_linker_test.cc
@@ -795,6 +795,12 @@
   }
 };
 
+struct ArrayElementVarHandleOffsets : public CheckOffsets<mirror::ArrayElementVarHandle> {
+  ArrayElementVarHandleOffsets() : CheckOffsets<mirror::ArrayElementVarHandle>(
+      false, "Ljava/lang/invoke/ArrayElementVarHandle;") {
+  }
+};
+
 struct ByteArrayViewVarHandleOffsets : public CheckOffsets<mirror::ByteArrayViewVarHandle> {
   ByteArrayViewVarHandleOffsets() : CheckOffsets<mirror::ByteArrayViewVarHandle>(
       false, "Ljava/lang/invoke/ByteArrayViewVarHandle;") {
@@ -838,6 +844,7 @@
   EXPECT_TRUE(CallSiteOffsets().Check());
   EXPECT_TRUE(VarHandleOffsets().Check());
   EXPECT_TRUE(FieldVarHandleOffsets().Check());
+  EXPECT_TRUE(ArrayElementVarHandleOffsets().Check());
   EXPECT_TRUE(ByteArrayViewVarHandleOffsets().Check());
   EXPECT_TRUE(ByteBufferViewVarHandleOffsets().Check());
 }
diff --git a/runtime/dex_file.cc b/runtime/dex_file.cc
index 4aed402..d136dc3 100644
--- a/runtime/dex_file.cc
+++ b/runtime/dex_file.cc
@@ -802,85 +802,6 @@
   ptr_ += width;
 }
 
-CatchHandlerIterator::CatchHandlerIterator(const DexFile::CodeItem& code_item, uint32_t address) {
-  handler_.address_ = -1;
-  int32_t offset = -1;
-
-  // Short-circuit the overwhelmingly common cases.
-  switch (code_item.tries_size_) {
-    case 0:
-      break;
-    case 1: {
-      const DexFile::TryItem* tries = DexFile::GetTryItems(code_item, 0);
-      uint32_t start = tries->start_addr_;
-      if (address >= start) {
-        uint32_t end = start + tries->insn_count_;
-        if (address < end) {
-          offset = tries->handler_off_;
-        }
-      }
-      break;
-    }
-    default:
-      offset = DexFile::FindCatchHandlerOffset(code_item, address);
-  }
-  Init(code_item, offset);
-}
-
-CatchHandlerIterator::CatchHandlerIterator(const DexFile::CodeItem& code_item,
-                                           const DexFile::TryItem& try_item) {
-  handler_.address_ = -1;
-  Init(code_item, try_item.handler_off_);
-}
-
-void CatchHandlerIterator::Init(const DexFile::CodeItem& code_item,
-                                int32_t offset) {
-  if (offset >= 0) {
-    Init(DexFile::GetCatchHandlerData(code_item, offset));
-  } else {
-    // Not found, initialize as empty
-    current_data_ = nullptr;
-    remaining_count_ = -1;
-    catch_all_ = false;
-    DCHECK(!HasNext());
-  }
-}
-
-void CatchHandlerIterator::Init(const uint8_t* handler_data) {
-  current_data_ = handler_data;
-  remaining_count_ = DecodeSignedLeb128(&current_data_);
-
-  // If remaining_count_ is non-positive, then it is the negative of
-  // the number of catch types, and the catches are followed by a
-  // catch-all handler.
-  if (remaining_count_ <= 0) {
-    catch_all_ = true;
-    remaining_count_ = -remaining_count_;
-  } else {
-    catch_all_ = false;
-  }
-  Next();
-}
-
-void CatchHandlerIterator::Next() {
-  if (remaining_count_ > 0) {
-    handler_.type_idx_ = dex::TypeIndex(DecodeUnsignedLeb128(&current_data_));
-    handler_.address_  = DecodeUnsignedLeb128(&current_data_);
-    remaining_count_--;
-    return;
-  }
-
-  if (catch_all_) {
-    handler_.type_idx_ = dex::TypeIndex(DexFile::kDexNoIndex16);
-    handler_.address_  = DecodeUnsignedLeb128(&current_data_);
-    catch_all_ = false;
-    return;
-  }
-
-  // no more handler
-  remaining_count_ = -1;
-}
-
 namespace dex {
 
 std::ostream& operator<<(std::ostream& os, const StringIndex& index) {
diff --git a/runtime/dex_file.h b/runtime/dex_file.h
index f3a88f7..e80a13c 100644
--- a/runtime/dex_file.h
+++ b/runtime/dex_file.h
@@ -342,12 +342,10 @@
 
    private:
     ART_FRIEND_TEST(CodeItemAccessorsTest, TestDexInstructionsAccessor);
-    friend class CatchHandlerIterator;
     friend class CodeItemDataAccessor;
     friend class CodeItemDebugInfoAccessor;
     friend class CodeItemInstructionAccessor;
     friend class DexFile;  // TODO: Remove this one when it's cleaned up.
-    friend class DexFileVerifier;
     friend class VdexFile;  // TODO: Remove this one when it's cleaned up.
     DISALLOW_COPY_AND_ASSIGN(CodeItem);
   };
@@ -1466,47 +1464,6 @@
 };
 std::ostream& operator<<(std::ostream& os, const CallSiteArrayValueIterator::ValueType& code);
 
-class CatchHandlerIterator {
- public:
-  CatchHandlerIterator(const DexFile::CodeItem& code_item, uint32_t address);
-
-  CatchHandlerIterator(const DexFile::CodeItem& code_item,
-                       const DexFile::TryItem& try_item);
-
-  explicit CatchHandlerIterator(const uint8_t* handler_data) {
-    Init(handler_data);
-  }
-
-  dex::TypeIndex GetHandlerTypeIndex() const {
-    return handler_.type_idx_;
-  }
-  uint32_t GetHandlerAddress() const {
-    return handler_.address_;
-  }
-  void Next();
-  bool HasNext() const {
-    return remaining_count_ != -1 || catch_all_;
-  }
-  // End of this set of catch blocks, convenience method to locate next set of catch blocks
-  const uint8_t* EndDataPointer() const {
-    CHECK(!HasNext());
-    return current_data_;
-  }
-
- private:
-  void Init(const DexFile::CodeItem& code_item, int32_t offset);
-  void Init(const uint8_t* handler_data);
-
-  struct CatchHandlerItem {
-    dex::TypeIndex type_idx_;  // type index of the caught exception type
-    uint32_t address_;  // handler address
-  } handler_;
-  const uint8_t* current_data_;  // the current handler in dex file.
-  int32_t remaining_count_;   // number of handlers not read.
-  bool catch_all_;            // is there a handler that will catch all exceptions in case
-                              // that all typed handler does not match.
-};
-
 }  // namespace art
 
 #endif  // ART_RUNTIME_DEX_FILE_H_
diff --git a/runtime/dex_file_exception_helpers.cc b/runtime/dex_file_exception_helpers.cc
new file mode 100644
index 0000000..ad56eb0
--- /dev/null
+++ b/runtime/dex_file_exception_helpers.cc
@@ -0,0 +1,104 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "dex_file_exception_helpers.h"
+
+#include "code_item_accessors-no_art-inl.h"
+
+namespace art {
+
+CatchHandlerIterator::CatchHandlerIterator(const CodeItemDataAccessor& accessor, uint32_t address) {
+  handler_.address_ = -1;
+  int32_t offset = -1;
+
+  // Short-circuit the overwhelmingly common cases.
+  switch (accessor.TriesSize()) {
+    case 0:
+      break;
+    case 1: {
+      const DexFile::TryItem* tries = accessor.TryItems().begin();
+      uint32_t start = tries->start_addr_;
+      if (address >= start) {
+        uint32_t end = start + tries->insn_count_;
+        if (address < end) {
+          offset = tries->handler_off_;
+        }
+      }
+      break;
+    }
+    default: {
+      const DexFile::TryItem* try_item = accessor.FindTryItem(address);
+      offset = try_item != nullptr ? try_item->handler_off_ : -1;
+      break;
+    }
+  }
+  Init(accessor, offset);
+}
+
+CatchHandlerIterator::CatchHandlerIterator(const CodeItemDataAccessor& accessor,
+                                           const DexFile::TryItem& try_item) {
+  handler_.address_ = -1;
+  Init(accessor, try_item.handler_off_);
+}
+
+void CatchHandlerIterator::Init(const CodeItemDataAccessor& accessor, int32_t offset) {
+  if (offset >= 0) {
+    Init(accessor.GetCatchHandlerData(offset));
+  } else {
+    // Not found, initialize as empty
+    current_data_ = nullptr;
+    remaining_count_ = -1;
+    catch_all_ = false;
+    DCHECK(!HasNext());
+  }
+}
+
+void CatchHandlerIterator::Init(const uint8_t* handler_data) {
+  current_data_ = handler_data;
+  remaining_count_ = DecodeSignedLeb128(&current_data_);
+
+  // If remaining_count_ is non-positive, then it is the negative of
+  // the number of catch types, and the catches are followed by a
+  // catch-all handler.
+  if (remaining_count_ <= 0) {
+    catch_all_ = true;
+    remaining_count_ = -remaining_count_;
+  } else {
+    catch_all_ = false;
+  }
+  Next();
+}
+
+void CatchHandlerIterator::Next() {
+  if (remaining_count_ > 0) {
+    handler_.type_idx_ = dex::TypeIndex(DecodeUnsignedLeb128(&current_data_));
+    handler_.address_  = DecodeUnsignedLeb128(&current_data_);
+    remaining_count_--;
+    return;
+  }
+
+  if (catch_all_) {
+    handler_.type_idx_ = dex::TypeIndex(DexFile::kDexNoIndex16);
+    handler_.address_  = DecodeUnsignedLeb128(&current_data_);
+    catch_all_ = false;
+    return;
+  }
+
+  // no more handler
+  remaining_count_ = -1;
+}
+
+}  // namespace art
diff --git a/runtime/dex_file_exception_helpers.h b/runtime/dex_file_exception_helpers.h
new file mode 100644
index 0000000..739ed1f
--- /dev/null
+++ b/runtime/dex_file_exception_helpers.h
@@ -0,0 +1,68 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ART_RUNTIME_DEX_FILE_EXCEPTION_HELPERS_H_
+#define ART_RUNTIME_DEX_FILE_EXCEPTION_HELPERS_H_
+
+#include "dex_file.h"
+
+namespace art {
+
+class CodeItemDataAccessor;
+
+class CatchHandlerIterator {
+ public:
+  CatchHandlerIterator(const CodeItemDataAccessor& accessor, uint32_t address);
+
+  CatchHandlerIterator(const CodeItemDataAccessor& accessor, const DexFile::TryItem& try_item);
+
+  explicit CatchHandlerIterator(const uint8_t* handler_data) {
+    Init(handler_data);
+  }
+
+  dex::TypeIndex GetHandlerTypeIndex() const {
+    return handler_.type_idx_;
+  }
+  uint32_t GetHandlerAddress() const {
+    return handler_.address_;
+  }
+  void Next();
+  bool HasNext() const {
+    return remaining_count_ != -1 || catch_all_;
+  }
+  // End of this set of catch blocks, convenience method to locate next set of catch blocks
+  const uint8_t* EndDataPointer() const {
+    CHECK(!HasNext());
+    return current_data_;
+  }
+
+ private:
+  void Init(const CodeItemDataAccessor& accessor, int32_t offset);
+  void Init(const uint8_t* handler_data);
+
+  struct CatchHandlerItem {
+    dex::TypeIndex type_idx_;  // type index of the caught exception type
+    uint32_t address_;  // handler address
+  } handler_;
+  const uint8_t* current_data_;  // the current handler in dex file.
+  int32_t remaining_count_;   // number of handlers not read.
+  bool catch_all_;            // is there a handler that will catch all exceptions in case
+                              // that all typed handler does not match.
+};
+
+}  // namespace art
+
+#endif  // ART_RUNTIME_DEX_FILE_EXCEPTION_HELPERS_H_
diff --git a/runtime/dex_file_verifier.cc b/runtime/dex_file_verifier.cc
index edf5650..8656bcc 100644
--- a/runtime/dex_file_verifier.cc
+++ b/runtime/dex_file_verifier.cc
@@ -23,6 +23,7 @@
 
 #include "android-base/stringprintf.h"
 
+#include "code_item_accessors-no_art-inl.h"
 #include "dex_file-inl.h"
 #include "experimental_flags.h"
 #include "leb128.h"
@@ -572,7 +573,8 @@
 
 bool DexFileVerifier::CheckAndGetHandlerOffsets(const DexFile::CodeItem* code_item,
                                                 uint32_t* handler_offsets, uint32_t handlers_size) {
-  const uint8_t* handlers_base = DexFile::GetCatchHandlerData(*code_item, 0);
+  CodeItemDataAccessor accessor(dex_file_, code_item);
+  const uint8_t* handlers_base = accessor.GetCatchHandlerData();
 
   for (uint32_t i = 0; i < handlers_size; i++) {
     bool catch_all;
@@ -600,7 +602,7 @@
       }
 
       DECODE_UNSIGNED_CHECKED_FROM(ptr_, addr);
-      if (UNLIKELY(addr >= code_item->insns_size_in_code_units_)) {
+      if (UNLIKELY(addr >= accessor.InsnsSizeInCodeUnits())) {
         ErrorStringPrintf("Invalid handler addr: %x", addr);
         return false;
       }
@@ -608,7 +610,7 @@
 
     if (catch_all) {
       DECODE_UNSIGNED_CHECKED_FROM(ptr_, addr);
-      if (UNLIKELY(addr >= code_item->insns_size_in_code_units_)) {
+      if (UNLIKELY(addr >= accessor.InsnsSizeInCodeUnits())) {
         ErrorStringPrintf("Invalid handler catch_all_addr: %x", addr);
         return false;
       }
@@ -1224,14 +1226,14 @@
     return false;
   }
 
-  if (UNLIKELY(code_item->ins_size_ > code_item->registers_size_)) {
+  CodeItemDataAccessor accessor(dex_file_, code_item);
+  if (UNLIKELY(accessor.InsSize() > accessor.RegistersSize())) {
     ErrorStringPrintf("ins_size (%ud) > registers_size (%ud)",
-                      code_item->ins_size_, code_item->registers_size_);
+                      accessor.InsSize(), accessor.RegistersSize());
     return false;
   }
 
-  if (UNLIKELY((code_item->outs_size_ > 5) &&
-               (code_item->outs_size_ > code_item->registers_size_))) {
+  if (UNLIKELY(accessor.OutsSize() > 5 && accessor.OutsSize() > accessor.RegistersSize())) {
     /*
      * outs_size can be up to 5, even if registers_size is smaller, since the
      * short forms of method invocation allow repetitions of a register multiple
@@ -1239,18 +1241,18 @@
      * need to be represented in-order in the register file.
      */
     ErrorStringPrintf("outs_size (%ud) > registers_size (%ud)",
-                      code_item->outs_size_, code_item->registers_size_);
+                      accessor.OutsSize(), accessor.RegistersSize());
     return false;
   }
 
-  const uint16_t* insns = code_item->insns_;
-  uint32_t insns_size = code_item->insns_size_in_code_units_;
+  const uint16_t* insns = accessor.Insns();
+  uint32_t insns_size = accessor.InsnsSizeInCodeUnits();
   if (!CheckListSize(insns, insns_size, sizeof(uint16_t), "insns size")) {
     return false;
   }
 
   // Grab the end of the insns if there are no try_items.
-  uint32_t try_items_size = code_item->tries_size_;
+  uint32_t try_items_size = accessor.TriesSize();
   if (try_items_size == 0) {
     ptr_ = reinterpret_cast<const uint8_t*>(&insns[insns_size]);
     return true;
@@ -1262,12 +1264,12 @@
     return false;
   }
 
-  const DexFile::TryItem* try_items = DexFile::GetTryItems(*code_item, 0);
+  const DexFile::TryItem* try_items = accessor.TryItems().begin();
   if (!CheckListSize(try_items, try_items_size, sizeof(DexFile::TryItem), "try_items size")) {
     return false;
   }
 
-  ptr_ = DexFile::GetCatchHandlerData(*code_item, 0);
+  ptr_ = accessor.GetCatchHandlerData();
   DECODE_UNSIGNED_CHECKED_FROM(ptr_, handlers_size);
 
   if (UNLIKELY((handlers_size == 0) || (handlers_size >= 65536))) {
diff --git a/runtime/mirror/var_handle.h b/runtime/mirror/var_handle.h
index a2a5d8c..54a6d27 100644
--- a/runtime/mirror/var_handle.h
+++ b/runtime/mirror/var_handle.h
@@ -26,6 +26,7 @@
 template<class T> class Handle;
 struct VarHandleOffsets;
 struct FieldVarHandleOffsets;
+struct ArrayElementVarHandleOffsets;
 struct ByteArrayViewVarHandleOffsets;
 struct ByteBufferViewVarHandleOffsets;
 
diff --git a/runtime/verifier/method_verifier.cc b/runtime/verifier/method_verifier.cc
index be6915f..63f21f8 100644
--- a/runtime/verifier/method_verifier.cc
+++ b/runtime/verifier/method_verifier.cc
@@ -32,6 +32,7 @@
 #include "class_linker.h"
 #include "compiler_callbacks.h"
 #include "dex_file-inl.h"
+#include "dex_file_exception_helpers.h"
 #include "dex_instruction-inl.h"
 #include "dex_instruction_utils.h"
 #include "experimental_flags.h"
@@ -3630,7 +3631,7 @@
     bool has_catch_all_handler = false;
     const DexFile::TryItem* try_item = code_item_accessor_.FindTryItem(work_insn_idx_);
     CHECK(try_item != nullptr);
-    CatchHandlerIterator iterator(code_item_accessor_.GetCatchHandlerData(try_item->handler_off_));
+    CatchHandlerIterator iterator(code_item_accessor_, *try_item);
 
     // Need the linker to try and resolve the handled class to check if it's Throwable.
     ClassLinker* linker = Runtime::Current()->GetClassLinker();