Merge "Disable kEnableJavaStackTraceHandler"
diff --git a/compiler/dex/mir_graph.h b/compiler/dex/mir_graph.h
index f14b187..fe6fb75 100644
--- a/compiler/dex/mir_graph.h
+++ b/compiler/dex/mir_graph.h
@@ -338,7 +338,7 @@
     uint32_t method_lowering_info;
   } meta;
 
-  explicit MIR():offset(0), optimization_flags(0), m_unit_index(0), bb(NullBasicBlockId),
+  explicit MIR() : offset(0), optimization_flags(0), m_unit_index(0), bb(NullBasicBlockId),
                  next(nullptr), ssa_rep(nullptr) {
     memset(&meta, 0, sizeof(meta));
   }
@@ -572,7 +572,7 @@
    * @return Returns the raw table pointer.
    */
   const uint16_t* GetTable(MIR* mir, uint32_t table_offset) const {
-    return GetInsns(mir->m_unit_index) + mir->offset + table_offset;
+    return GetInsns(mir->m_unit_index) + mir->offset + static_cast<int32_t>(table_offset);
   }
 
   unsigned int GetNumBlocks() const {
diff --git a/compiler/dex/quick/arm/call_arm.cc b/compiler/dex/quick/arm/call_arm.cc
index b721e02..13b9bf0 100644
--- a/compiler/dex/quick/arm/call_arm.cc
+++ b/compiler/dex/quick/arm/call_arm.cc
@@ -140,41 +140,6 @@
 }
 
 /*
- * Array data table format:
- *  ushort ident = 0x0300   magic value
- *  ushort width            width of each element in the table
- *  uint   size             number of elements in the table
- *  ubyte  data[size*width] table of data values (may contain a single-byte
- *                          padding at the end)
- *
- * Total size is 4+(width * size + 1)/2 16-bit code units.
- */
-void ArmMir2Lir::GenFillArrayData(MIR* mir, DexOffset table_offset, RegLocation rl_src) {
-  const uint16_t* table = mir_graph_->GetTable(mir, table_offset);
-  // Add the table to the list - we'll process it later
-  FillArrayData *tab_rec =
-      static_cast<FillArrayData*>(arena_->Alloc(sizeof(FillArrayData), kArenaAllocData));
-  tab_rec->table = table;
-  tab_rec->vaddr = current_dalvik_offset_;
-  uint16_t width = tab_rec->table[1];
-  uint32_t size = tab_rec->table[2] | ((static_cast<uint32_t>(tab_rec->table[3])) << 16);
-  tab_rec->size = (size * width) + 8;
-
-  fill_array_data_.push_back(tab_rec);
-
-  // Making a call - use explicit registers
-  FlushAllRegs();   /* Everything to home location */
-  LoadValueDirectFixed(rl_src, rs_r0);
-  LoadWordDisp(rs_rARM_SELF, QUICK_ENTRYPOINT_OFFSET(4, pHandleFillArrayData).Int32Value(),
-               rs_rARM_LR);
-  // Materialize a pointer to the fill data image
-  NewLIR3(kThumb2Adr, rs_r1.GetReg(), 0, WrapPointer(tab_rec));
-  ClobberCallerSave();
-  LIR* call_inst = OpReg(kOpBlx, rs_rARM_LR);
-  MarkSafepointPC(call_inst);
-}
-
-/*
  * Handle unlocked -> thin locked transition inline or else call out to quick entrypoint. For more
  * details see monitor.cc.
  */
diff --git a/compiler/dex/quick/arm/codegen_arm.h b/compiler/dex/quick/arm/codegen_arm.h
index 932dd87..1c87a03 100644
--- a/compiler/dex/quick/arm/codegen_arm.h
+++ b/compiler/dex/quick/arm/codegen_arm.h
@@ -118,7 +118,6 @@
     void GenEntrySequence(RegLocation* ArgLocs, RegLocation rl_method);
     void GenExitSequence();
     void GenSpecialExitSequence();
-    void GenFillArrayData(MIR* mir, DexOffset table_offset, RegLocation rl_src);
     void GenFusedFPCmpBranch(BasicBlock* bb, MIR* mir, bool gt_bias, bool is_double);
     void GenFusedLongCmpBranch(BasicBlock* bb, MIR* mir);
     void GenSelect(BasicBlock* bb, MIR* mir);
diff --git a/compiler/dex/quick/arm64/call_arm64.cc b/compiler/dex/quick/arm64/call_arm64.cc
index e8de876..c898e2d 100644
--- a/compiler/dex/quick/arm64/call_arm64.cc
+++ b/compiler/dex/quick/arm64/call_arm64.cc
@@ -149,41 +149,6 @@
 }
 
 /*
- * Array data table format:
- *  ushort ident = 0x0300   magic value
- *  ushort width            width of each element in the table
- *  uint   size             number of elements in the table
- *  ubyte  data[size*width] table of data values (may contain a single-byte
- *                          padding at the end)
- *
- * Total size is 4+(width * size + 1)/2 16-bit code units.
- */
-void Arm64Mir2Lir::GenFillArrayData(MIR* mir, DexOffset table_offset, RegLocation rl_src) {
-  const uint16_t* table = mir_graph_->GetTable(mir, table_offset);
-  // Add the table to the list - we'll process it later
-  FillArrayData *tab_rec =
-      static_cast<FillArrayData*>(arena_->Alloc(sizeof(FillArrayData), kArenaAllocData));
-  tab_rec->table = table;
-  tab_rec->vaddr = current_dalvik_offset_;
-  uint16_t width = tab_rec->table[1];
-  uint32_t size = tab_rec->table[2] | ((static_cast<uint32_t>(tab_rec->table[3])) << 16);
-  tab_rec->size = (size * width) + 8;
-
-  fill_array_data_.push_back(tab_rec);
-
-  // Making a call - use explicit registers
-  FlushAllRegs();   /* Everything to home location */
-  LoadValueDirectFixed(rl_src, rs_x0);
-  LoadWordDisp(rs_xSELF, QUICK_ENTRYPOINT_OFFSET(8, pHandleFillArrayData).Int32Value(),
-               rs_xLR);
-  // Materialize a pointer to the fill data image
-  NewLIR3(kA64Adr2xd, rx1, 0, WrapPointer(tab_rec));
-  ClobberCallerSave();
-  LIR* call_inst = OpReg(kOpBlx, rs_xLR);
-  MarkSafepointPC(call_inst);
-}
-
-/*
  * Handle unlocked -> thin locked transition inline or else call out to quick entrypoint. For more
  * details see monitor.cc.
  */
diff --git a/compiler/dex/quick/arm64/codegen_arm64.h b/compiler/dex/quick/arm64/codegen_arm64.h
index 93d9b34..510bd4c 100644
--- a/compiler/dex/quick/arm64/codegen_arm64.h
+++ b/compiler/dex/quick/arm64/codegen_arm64.h
@@ -183,7 +183,6 @@
   void GenEntrySequence(RegLocation* ArgLocs, RegLocation rl_method) OVERRIDE;
   void GenExitSequence() OVERRIDE;
   void GenSpecialExitSequence() OVERRIDE;
-  void GenFillArrayData(MIR* mir, DexOffset table_offset, RegLocation rl_src) OVERRIDE;
   void GenFusedFPCmpBranch(BasicBlock* bb, MIR* mir, bool gt_bias, bool is_double) OVERRIDE;
   void GenFusedLongCmpBranch(BasicBlock* bb, MIR* mir) OVERRIDE;
   void GenSelect(BasicBlock* bb, MIR* mir) OVERRIDE;
diff --git a/compiler/dex/quick/gen_common.cc b/compiler/dex/quick/gen_common.cc
index 3f7ecfe..3a3821f 100644
--- a/compiler/dex/quick/gen_common.cc
+++ b/compiler/dex/quick/gen_common.cc
@@ -496,6 +496,27 @@
   }
 }
 
+/*
+ * Array data table format:
+ *  ushort ident = 0x0300   magic value
+ *  ushort width            width of each element in the table
+ *  uint   size             number of elements in the table
+ *  ubyte  data[size*width] table of data values (may contain a single-byte
+ *                          padding at the end)
+ *
+ * Total size is 4+(width * size + 1)/2 16-bit code units.
+ */
+void Mir2Lir::GenFillArrayData(MIR* mir, DexOffset table_offset, RegLocation rl_src) {
+  if (kIsDebugBuild) {
+    const uint16_t* table = mir_graph_->GetTable(mir, table_offset);
+    const Instruction::ArrayDataPayload* payload =
+        reinterpret_cast<const Instruction::ArrayDataPayload*>(table);
+    CHECK_EQ(payload->ident, static_cast<uint16_t>(Instruction::kArrayDataSignature));
+  }
+  uint32_t table_offset_from_start = mir->offset + static_cast<int32_t>(table_offset);
+  CallRuntimeHelperImmRegLocation(kQuickHandleFillArrayData, table_offset_from_start, rl_src, true);
+}
+
 //
 // Slow path to ensure a class is initialized for sget/sput.
 //
diff --git a/compiler/dex/quick/mips/call_mips.cc b/compiler/dex/quick/mips/call_mips.cc
index 6536c41..8b5bc45 100644
--- a/compiler/dex/quick/mips/call_mips.cc
+++ b/compiler/dex/quick/mips/call_mips.cc
@@ -210,54 +210,6 @@
   branch_over->target = target;
 }
 
-/*
- * Array data table format:
- *  ushort ident = 0x0300   magic value
- *  ushort width            width of each element in the table
- *  uint   size             number of elements in the table
- *  ubyte  data[size*width] table of data values (may contain a single-byte
- *                          padding at the end)
- *
- * Total size is 4+(width * size + 1)/2 16-bit code units.
- */
-void MipsMir2Lir::GenFillArrayData(MIR* mir, DexOffset table_offset, RegLocation rl_src) {
-  const uint16_t* table = mir_graph_->GetTable(mir, table_offset);
-  // Add the table to the list - we'll process it later
-  FillArrayData* tab_rec =
-      reinterpret_cast<FillArrayData*>(arena_->Alloc(sizeof(FillArrayData),
-                                                     kArenaAllocData));
-  tab_rec->table = table;
-  tab_rec->vaddr = current_dalvik_offset_;
-  uint16_t width = tab_rec->table[1];
-  uint32_t size = tab_rec->table[2] | ((static_cast<uint32_t>(tab_rec->table[3])) << 16);
-  tab_rec->size = (size * width) + 8;
-
-  fill_array_data_.push_back(tab_rec);
-
-  // Making a call - use explicit registers
-  FlushAllRegs();   /* Everything to home location */
-  LockCallTemps();
-  LoadValueDirectFixed(rl_src, rs_rMIPS_ARG0);
-
-  // Must prevent code motion for the curr pc pair
-  GenBarrier();
-  NewLIR0(kMipsCurrPC);  // Really a jal to .+8
-  // Now, fill the branch delay slot with the helper load
-  RegStorage r_tgt = LoadHelper(kQuickHandleFillArrayData);
-  GenBarrier();  // Scheduling barrier
-
-  // Construct BaseLabel and set up table base register
-  LIR* base_label = NewLIR0(kPseudoTargetLabel);
-
-  // Materialize a pointer to the fill data image
-  NewLIR4(kMipsDelta, rMIPS_ARG1, 0, WrapPointer(base_label), WrapPointer(tab_rec));
-
-  // And go...
-  ClobberCallerSave();
-  LIR* call_inst = OpReg(kOpBlx, r_tgt);  // ( array*, fill_data* )
-  MarkSafepointPC(call_inst);
-}
-
 void MipsMir2Lir::GenMoveException(RegLocation rl_dest) {
   int ex_offset = Thread::ExceptionOffset<4>().Int32Value();
   RegLocation rl_result = EvalLoc(rl_dest, kRefReg, true);
diff --git a/compiler/dex/quick/mips/codegen_mips.h b/compiler/dex/quick/mips/codegen_mips.h
index be94019..bd709f3 100644
--- a/compiler/dex/quick/mips/codegen_mips.h
+++ b/compiler/dex/quick/mips/codegen_mips.h
@@ -116,7 +116,6 @@
     void GenEntrySequence(RegLocation* ArgLocs, RegLocation rl_method);
     void GenExitSequence();
     void GenSpecialExitSequence();
-    void GenFillArrayData(MIR* mir, DexOffset table_offset, RegLocation rl_src);
     void GenFusedFPCmpBranch(BasicBlock* bb, MIR* mir, bool gt_bias, bool is_double);
     void GenFusedLongCmpBranch(BasicBlock* bb, MIR* mir);
     void GenSelect(BasicBlock* bb, MIR* mir);
diff --git a/compiler/dex/quick/mir_to_lir.h b/compiler/dex/quick/mir_to_lir.h
index 3de4c56..858fb1c 100644
--- a/compiler/dex/quick/mir_to_lir.h
+++ b/compiler/dex/quick/mir_to_lir.h
@@ -832,6 +832,7 @@
     void GenNewArray(uint32_t type_idx, RegLocation rl_dest,
                      RegLocation rl_src);
     void GenFilledNewArray(CallInfo* info);
+    void GenFillArrayData(MIR* mir, DexOffset table_offset, RegLocation rl_src);
     void GenSput(MIR* mir, RegLocation rl_src, OpSize size);
     // Get entrypoints are specific for types, size alone is not sufficient to safely infer
     // entrypoint.
@@ -1321,7 +1322,6 @@
 
     virtual void GenEntrySequence(RegLocation* ArgLocs, RegLocation rl_method) = 0;
     virtual void GenExitSequence() = 0;
-    virtual void GenFillArrayData(MIR* mir, DexOffset table_offset, RegLocation rl_src) = 0;
     virtual void GenFusedFPCmpBranch(BasicBlock* bb, MIR* mir, bool gt_bias, bool is_double) = 0;
     virtual void GenFusedLongCmpBranch(BasicBlock* bb, MIR* mir) = 0;
 
diff --git a/compiler/dex/quick/x86/call_x86.cc b/compiler/dex/quick/x86/call_x86.cc
index 441ec9e..86efc1e 100644
--- a/compiler/dex/quick/x86/call_x86.cc
+++ b/compiler/dex/quick/x86/call_x86.cc
@@ -126,54 +126,6 @@
   branch_over->target = target;
 }
 
-/*
- * Array data table format:
- *  ushort ident = 0x0300   magic value
- *  ushort width            width of each element in the table
- *  uint   size             number of elements in the table
- *  ubyte  data[size*width] table of data values (may contain a single-byte
- *                          padding at the end)
- *
- * Total size is 4+(width * size + 1)/2 16-bit code units.
- */
-void X86Mir2Lir::GenFillArrayData(MIR* mir, DexOffset table_offset, RegLocation rl_src) {
-  const uint16_t* table = mir_graph_->GetTable(mir, table_offset);
-  // Add the table to the list - we'll process it later
-  FillArrayData* tab_rec =
-      static_cast<FillArrayData*>(arena_->Alloc(sizeof(FillArrayData), kArenaAllocData));
-  tab_rec->table = table;
-  tab_rec->vaddr = current_dalvik_offset_;
-  uint16_t width = tab_rec->table[1];
-  uint32_t size = tab_rec->table[2] | ((static_cast<uint32_t>(tab_rec->table[3])) << 16);
-  tab_rec->size = (size * width) + 8;
-
-  fill_array_data_.push_back(tab_rec);
-
-  // Making a call - use explicit registers
-  FlushAllRegs();   /* Everything to home location */
-  RegStorage array_ptr = TargetReg(kArg0, kRef);
-  RegStorage payload = TargetPtrReg(kArg1);
-  RegStorage method_start = TargetPtrReg(kArg2);
-
-  LoadValueDirectFixed(rl_src, array_ptr);
-  // Materialize a pointer to the fill data image
-  if (base_of_code_ != nullptr) {
-    // We can use the saved value.
-    RegLocation rl_method = mir_graph_->GetRegLocation(base_of_code_->s_reg_low);
-    if (rl_method.wide) {
-      LoadValueDirectWide(rl_method, method_start);
-    } else {
-      LoadValueDirect(rl_method, method_start);
-    }
-    store_method_addr_used_ = true;
-  } else {
-    NewLIR1(kX86StartOfMethod, method_start.GetReg());
-  }
-  NewLIR2(kX86PcRelAdr, payload.GetReg(), WrapPointer(tab_rec));
-  OpRegReg(kOpAdd, payload, method_start);
-  CallRuntimeHelperRegReg(kQuickHandleFillArrayData, array_ptr, payload, true);
-}
-
 void X86Mir2Lir::GenMoveException(RegLocation rl_dest) {
   int ex_offset = cu_->target64 ?
       Thread::ExceptionOffset<8>().Int32Value() :
diff --git a/compiler/dex/quick/x86/codegen_x86.h b/compiler/dex/quick/x86/codegen_x86.h
index 8edfc01..b3544da 100644
--- a/compiler/dex/quick/x86/codegen_x86.h
+++ b/compiler/dex/quick/x86/codegen_x86.h
@@ -245,7 +245,6 @@
   void GenEntrySequence(RegLocation* ArgLocs, RegLocation rl_method) OVERRIDE;
   void GenExitSequence() OVERRIDE;
   void GenSpecialExitSequence() OVERRIDE;
-  void GenFillArrayData(MIR* mir, DexOffset table_offset, RegLocation rl_src) OVERRIDE;
   void GenFusedFPCmpBranch(BasicBlock* bb, MIR* mir, bool gt_bias, bool is_double) OVERRIDE;
   void GenFusedLongCmpBranch(BasicBlock* bb, MIR* mir) OVERRIDE;
   void GenSelect(BasicBlock* bb, MIR* mir) OVERRIDE;
diff --git a/runtime/arch/arm/quick_entrypoints_arm.S b/runtime/arch/arm/quick_entrypoints_arm.S
index 51bcd3c..466e9eb 100644
--- a/runtime/arch/arm/quick_entrypoints_arm.S
+++ b/runtime/arch/arm/quick_entrypoints_arm.S
@@ -426,16 +426,7 @@
      * Entry from managed code that calls artHandleFillArrayDataFromCode and delivers exception on
      * failure.
      */
-    .extern artHandleFillArrayDataFromCode
-ENTRY art_quick_handle_fill_data
-    SETUP_REF_ONLY_CALLEE_SAVE_FRAME  @ save callee saves in case exception allocation triggers GC
-    mov    r2, r9                          @ pass Thread::Current
-    mov    r3, sp                          @ pass SP
-    bl     artHandleFillArrayDataFromCode  @ (Array*, const DexFile::Payload*, Thread*, SP)
-    RESTORE_REF_ONLY_CALLEE_SAVE_FRAME
-    RETURN_IF_RESULT_IS_ZERO
-    DELIVER_PENDING_EXCEPTION
-END art_quick_handle_fill_data
+TWO_ARG_REF_DOWNCALL art_quick_handle_fill_data, artHandleFillArrayDataFromCode, RETURN_IF_RESULT_IS_ZERO_OR_DELIVER
 
     /*
      * Entry from managed code that calls artLockObjectFromCode, may block for GC. r0 holds the
diff --git a/runtime/arch/arm64/quick_entrypoints_arm64.S b/runtime/arch/arm64/quick_entrypoints_arm64.S
index 606816a..252e89e 100644
--- a/runtime/arch/arm64/quick_entrypoints_arm64.S
+++ b/runtime/arch/arm64/quick_entrypoints_arm64.S
@@ -940,16 +940,7 @@
      * Entry from managed code that calls artHandleFillArrayDataFromCode and delivers exception on
      * failure.
      */
-    .extern artHandleFillArrayDataFromCode
-ENTRY art_quick_handle_fill_data
-    SETUP_REF_ONLY_CALLEE_SAVE_FRAME  // Save callee saves in case exception allocation triggers GC.
-    mov    x2, xSELF                       // Pass Thread::Current.
-    mov    x3, sp                          // Pass SP.
-    bl     artHandleFillArrayDataFromCode  // (Array*, const DexFile::Payload*, Thread*, SP)
-    RESTORE_REF_ONLY_CALLEE_SAVE_FRAME
-    RETURN_IF_RESULT_IS_ZERO
-    DELIVER_PENDING_EXCEPTION
-END art_quick_handle_fill_data
+TWO_ARG_REF_DOWNCALL art_quick_handle_fill_data, artHandleFillArrayDataFromCode, RETURN_IF_W0_IS_ZERO_OR_DELIVER
 
     /*
      * Entry from managed code that calls artLockObjectFromCode, may block for GC. x0 holds the
diff --git a/runtime/arch/mips/quick_entrypoints_mips.S b/runtime/arch/mips/quick_entrypoints_mips.S
index 9e9e523..609c65a 100644
--- a/runtime/arch/mips/quick_entrypoints_mips.S
+++ b/runtime/arch/mips/quick_entrypoints_mips.S
@@ -545,9 +545,10 @@
 ENTRY art_quick_handle_fill_data
     GENERATE_GLOBAL_POINTER
     SETUP_REF_ONLY_CALLEE_SAVE_FRAME  # save callee saves in case exception allocation triggers GC
-    move    $a2, rSELF                         # pass Thread::Current
-    jal     artHandleFillArrayDataFromCode     # (Array*, const DexFile::Payload*, Thread*, $sp)
-    move    $a3, $sp                           # pass $sp
+    lw     $a2, 64($sp)                   # pass referrer's Method*
+    move   $a3, rSELF                     # pass Thread::Current
+    jal    artHandleFillArrayDataFromCode # (payload offset, Array*, method, Thread*, $sp)
+    sw     $sp, 16($sp)                   # pass $sp
     RETURN_IF_ZERO
 END art_quick_handle_fill_data
 
diff --git a/runtime/arch/x86/quick_entrypoints_x86.S b/runtime/arch/x86/quick_entrypoints_x86.S
index 4155b7e..411d273 100644
--- a/runtime/arch/x86/quick_entrypoints_x86.S
+++ b/runtime/arch/x86/quick_entrypoints_x86.S
@@ -560,7 +560,7 @@
 TWO_ARG_DOWNCALL art_quick_initialize_type, artInitializeTypeFromCode, RETURN_IF_RESULT_IS_NON_ZERO
 TWO_ARG_DOWNCALL art_quick_initialize_type_and_verify_access, artInitializeTypeAndVerifyAccessFromCode, RETURN_IF_RESULT_IS_NON_ZERO
 
-TWO_ARG_DOWNCALL art_quick_handle_fill_data, artHandleFillArrayDataFromCode, RETURN_IF_EAX_ZERO
+TWO_ARG_REF_DOWNCALL art_quick_handle_fill_data, artHandleFillArrayDataFromCode, RETURN_IF_EAX_ZERO
 
 DEFINE_FUNCTION art_quick_lock_object
     testl %eax, %eax                      // null check object/eax
diff --git a/runtime/arch/x86_64/quick_entrypoints_x86_64.S b/runtime/arch/x86_64/quick_entrypoints_x86_64.S
index e68cfbc..ca9c0bf 100644
--- a/runtime/arch/x86_64/quick_entrypoints_x86_64.S
+++ b/runtime/arch/x86_64/quick_entrypoints_x86_64.S
@@ -858,7 +858,7 @@
 TWO_ARG_DOWNCALL art_quick_initialize_type, artInitializeTypeFromCode, RETURN_IF_RESULT_IS_NON_ZERO
 TWO_ARG_DOWNCALL art_quick_initialize_type_and_verify_access, artInitializeTypeAndVerifyAccessFromCode, RETURN_IF_RESULT_IS_NON_ZERO
 
-TWO_ARG_DOWNCALL art_quick_handle_fill_data, artHandleFillArrayDataFromCode, RETURN_IF_EAX_ZERO
+TWO_ARG_REF_DOWNCALL art_quick_handle_fill_data, artHandleFillArrayDataFromCode, RETURN_IF_EAX_ZERO
 
 DEFINE_FUNCTION art_quick_lock_object
     testl %edi, %edi                      // Null check object/rdi.
diff --git a/runtime/base/mutex.cc b/runtime/base/mutex.cc
index 4383a7c..cbcd408 100644
--- a/runtime/base/mutex.cc
+++ b/runtime/base/mutex.cc
@@ -648,7 +648,13 @@
 void ReaderWriterMutex::Dump(std::ostream& os) const {
   os << name_
       << " level=" << static_cast<int>(level_)
-      << " owner=" << GetExclusiveOwnerTid() << " ";
+      << " owner=" << GetExclusiveOwnerTid()
+#if ART_USE_FUTEXES
+      << " state=" << state_.LoadSequentiallyConsistent()
+      << " num_pending_writers=" << num_pending_writers_.LoadSequentiallyConsistent()
+      << " num_pending_readers=" << num_pending_readers_.LoadSequentiallyConsistent()
+#endif
+      << " ";
   DumpContention(os);
 }
 
diff --git a/runtime/entrypoints/entrypoint_utils.cc b/runtime/entrypoints/entrypoint_utils.cc
index 835d6e2..7b90339 100644
--- a/runtime/entrypoints/entrypoint_utils.cc
+++ b/runtime/entrypoints/entrypoint_utils.cc
@@ -344,4 +344,28 @@
     return zero;
   }
 }
+
+bool FillArrayData(mirror::Object* obj, const Instruction::ArrayDataPayload* payload) {
+  DCHECK_EQ(payload->ident, static_cast<uint16_t>(Instruction::kArrayDataSignature));
+  if (UNLIKELY(obj == nullptr)) {
+    ThrowNullPointerException(nullptr, "null array in FILL_ARRAY_DATA");
+    return false;
+  }
+  mirror::Array* array = obj->AsArray();
+  DCHECK(!array->IsObjectArray());
+  if (UNLIKELY(static_cast<int32_t>(payload->element_count) > array->GetLength())) {
+    Thread* self = Thread::Current();
+    ThrowLocation throw_location = self->GetCurrentLocationForThrow();
+    self->ThrowNewExceptionF(throw_location,
+                             "Ljava/lang/ArrayIndexOutOfBoundsException;",
+                             "failed FILL_ARRAY_DATA; length=%d, index=%d",
+                             array->GetLength(), payload->element_count);
+    return false;
+  }
+  // Copy data from dex file to memory assuming both are little endian.
+  uint32_t size_in_bytes = payload->element_count * payload->element_width;
+  memcpy(array->GetRawData(payload->element_width, 0), payload->data, size_in_bytes);
+  return true;
+}
+
 }  // namespace art
diff --git a/runtime/entrypoints/entrypoint_utils.h b/runtime/entrypoints/entrypoint_utils.h
index 08edecf..ce34993 100644
--- a/runtime/entrypoints/entrypoint_utils.h
+++ b/runtime/entrypoints/entrypoint_utils.h
@@ -22,6 +22,7 @@
 
 #include "base/macros.h"
 #include "base/mutex.h"
+#include "dex_instruction.h"
 #include "gc/allocator_type.h"
 #include "invoke_type.h"
 #include "jvalue.h"
@@ -179,6 +180,9 @@
                                     std::vector<jvalue>& args)
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
+bool FillArrayData(mirror::Object* obj, const Instruction::ArrayDataPayload* payload)
+    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+
 // Entry point for deoptimization.
 extern "C" void art_quick_deoptimize();
 static inline uintptr_t GetQuickDeoptimizationEntryPoint() {
diff --git a/runtime/entrypoints/portable/portable_fillarray_entrypoints.cc b/runtime/entrypoints/portable/portable_fillarray_entrypoints.cc
index 686954b..f0ad6de 100644
--- a/runtime/entrypoints/portable/portable_fillarray_entrypoints.cc
+++ b/runtime/entrypoints/portable/portable_fillarray_entrypoints.cc
@@ -15,9 +15,8 @@
  */
 
 #include "dex_instruction.h"
-#include "entrypoints/entrypoint_utils-inl.h"
+#include "entrypoints/entrypoint_utils.h"
 #include "mirror/art_method-inl.h"
-#include "mirror/object-inl.h"
 
 namespace art {
 
@@ -29,22 +28,7 @@
   const DexFile::CodeItem* code_item = method->GetCodeItem();
   const Instruction::ArrayDataPayload* payload =
       reinterpret_cast<const Instruction::ArrayDataPayload*>(code_item->insns_ + payload_offset);
-  DCHECK_EQ(payload->ident, static_cast<uint16_t>(Instruction::kArrayDataSignature));
-  if (UNLIKELY(array == NULL)) {
-    ThrowNullPointerException(NULL, "null array in FILL_ARRAY_DATA");
-    return;  // Error
-  }
-  DCHECK(array->IsArrayInstance() && !array->IsObjectArray());
-  if (UNLIKELY(static_cast<int32_t>(payload->element_count) > array->GetLength())) {
-    Thread* self = Thread::Current();
-    ThrowLocation throw_location = self->GetCurrentLocationForThrow();
-    self->ThrowNewExceptionF(throw_location, "Ljava/lang/ArrayIndexOutOfBoundsException;",
-                             "failed FILL_ARRAY_DATA; length=%d, index=%d",
-                             array->GetLength(), payload->element_count - 1);
-    return;  // Error
-  }
-  uint32_t size_in_bytes = payload->element_count * payload->element_width;
-  memcpy(array->GetRawData(payload->element_width, 0), payload->data, size_in_bytes);
+  FillArrayData(array, payload);
 }
 
 }  // namespace art
diff --git a/runtime/entrypoints/quick/quick_fillarray_entrypoints.cc b/runtime/entrypoints/quick/quick_fillarray_entrypoints.cc
index 4ec2879..06bbabc 100644
--- a/runtime/entrypoints/quick/quick_fillarray_entrypoints.cc
+++ b/runtime/entrypoints/quick/quick_fillarray_entrypoints.cc
@@ -15,49 +15,25 @@
  */
 
 #include "callee_save_frame.h"
-#include "common_throws.h"
-#include "dex_instruction.h"
 #include "mirror/array.h"
-#include "mirror/object-inl.h"
+#include "mirror/art_method-inl.h"
+#include "entrypoints/entrypoint_utils.h"
 
 namespace art {
 
 /*
- * Fill the array with predefined constant values, throwing exceptions if the array is null or
- * not of sufficient length.
- *
- * NOTE: When dealing with a raw dex file, the data to be copied uses
- * little-endian ordering.  Require that oat2dex do any required swapping
- * so this routine can get by with a memcpy().
- *
- * Format of the data:
- *  ushort ident = 0x0300   magic value
- *  ushort width            width of each element in the table
- *  uint   size             number of elements in the table
- *  ubyte  data[size*width] table of data values (may contain a single-byte
- *                          padding at the end)
+ * Handle fill array data by copying appropriate part of dex file into array.
  */
-extern "C" int artHandleFillArrayDataFromCode(mirror::Array* array,
-                                              const Instruction::ArrayDataPayload* payload,
-                                              Thread* self, StackReference<mirror::ArtMethod>* sp)
+extern "C" int artHandleFillArrayDataFromCode(uint32_t payload_offset, mirror::Array* array,
+                                              mirror::ArtMethod* method, Thread* self,
+                                              StackReference<mirror::ArtMethod>* sp)
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
   FinishCalleeSaveFrameSetup(self, sp, Runtime::kRefsOnly);
-  DCHECK_EQ(payload->ident, static_cast<uint16_t>(Instruction::kArrayDataSignature));
-  if (UNLIKELY(array == NULL)) {
-    ThrowNullPointerException(NULL, "null array in FILL_ARRAY_DATA");
-    return -1;  // Error
-  }
-  DCHECK(array->IsArrayInstance() && !array->IsObjectArray());
-  if (UNLIKELY(static_cast<int32_t>(payload->element_count) > array->GetLength())) {
-    ThrowLocation throw_location = self->GetCurrentLocationForThrow();
-    self->ThrowNewExceptionF(throw_location, "Ljava/lang/ArrayIndexOutOfBoundsException;",
-                             "failed FILL_ARRAY_DATA; length=%d, index=%d",
-                             array->GetLength(), payload->element_count - 1);
-    return -1;  // Error
-  }
-  uint32_t size_in_bytes = payload->element_count * payload->element_width;
-  memcpy(array->GetRawData(payload->element_width, 0), payload->data, size_in_bytes);
-  return 0;  // Success
+  const uint16_t* const insns = method->GetCodeItem()->insns_;
+  const Instruction::ArrayDataPayload* payload =
+      reinterpret_cast<const Instruction::ArrayDataPayload*>(insns + payload_offset);
+  bool success = FillArrayData(array, payload);
+  return success ? 0 : -1;
 }
 
 }  // namespace art
diff --git a/runtime/interpreter/interpreter_goto_table_impl.cc b/runtime/interpreter/interpreter_goto_table_impl.cc
index 5c8a6c6..db7c452 100644
--- a/runtime/interpreter/interpreter_goto_table_impl.cc
+++ b/runtime/interpreter/interpreter_goto_table_impl.cc
@@ -573,30 +573,14 @@
 
   HANDLE_INSTRUCTION_START(FILL_ARRAY_DATA) {
     Object* obj = shadow_frame.GetVRegReference(inst->VRegA_31t(inst_data));
-    if (UNLIKELY(obj == NULL)) {
-      ThrowNullPointerException(NULL, "null array in FILL_ARRAY_DATA");
-      HANDLE_PENDING_EXCEPTION();
-    } else {
-      Array* array = obj->AsArray();
-      DCHECK(array->IsArrayInstance() && !array->IsObjectArray());
-      const uint16_t* payload_addr = reinterpret_cast<const uint16_t*>(inst) + inst->VRegB_31t();
-      const Instruction::ArrayDataPayload* payload =
-          reinterpret_cast<const Instruction::ArrayDataPayload*>(payload_addr);
-      if (UNLIKELY(static_cast<int32_t>(payload->element_count) > array->GetLength())) {
-        self->ThrowNewExceptionF(shadow_frame.GetCurrentLocationForThrow(),
-                                 "Ljava/lang/ArrayIndexOutOfBoundsException;",
-                                 "failed FILL_ARRAY_DATA; length=%d, index=%d",
-                                 array->GetLength(), payload->element_count);
-        HANDLE_PENDING_EXCEPTION();
-      } else {
-        if (transaction_active) {
-          RecordArrayElementsInTransaction(array, payload->element_count);
-        }
-        uint32_t size_in_bytes = payload->element_count * payload->element_width;
-        memcpy(array->GetRawData(payload->element_width, 0), payload->data, size_in_bytes);
-        ADVANCE(3);
-      }
+    const uint16_t* payload_addr = reinterpret_cast<const uint16_t*>(inst) + inst->VRegB_31t();
+    const Instruction::ArrayDataPayload* payload =
+        reinterpret_cast<const Instruction::ArrayDataPayload*>(payload_addr);
+    bool success = FillArrayData(obj, payload);
+    if (transaction_active && success) {
+      RecordArrayElementsInTransaction(obj->AsArray(), payload->element_count);
     }
+    POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, 3);
   }
   HANDLE_INSTRUCTION_END();
 
diff --git a/runtime/interpreter/interpreter_switch_impl.cc b/runtime/interpreter/interpreter_switch_impl.cc
index c6cef6a..fe0af27 100644
--- a/runtime/interpreter/interpreter_switch_impl.cc
+++ b/runtime/interpreter/interpreter_switch_impl.cc
@@ -484,30 +484,18 @@
       }
       case Instruction::FILL_ARRAY_DATA: {
         PREAMBLE();
-        Object* obj = shadow_frame.GetVRegReference(inst->VRegA_31t(inst_data));
-        if (UNLIKELY(obj == NULL)) {
-          ThrowNullPointerException(NULL, "null array in FILL_ARRAY_DATA");
-          HANDLE_PENDING_EXCEPTION();
-          break;
-        }
-        Array* array = obj->AsArray();
-        DCHECK(array->IsArrayInstance() && !array->IsObjectArray());
         const uint16_t* payload_addr = reinterpret_cast<const uint16_t*>(inst) + inst->VRegB_31t();
         const Instruction::ArrayDataPayload* payload =
             reinterpret_cast<const Instruction::ArrayDataPayload*>(payload_addr);
-        if (UNLIKELY(static_cast<int32_t>(payload->element_count) > array->GetLength())) {
-          self->ThrowNewExceptionF(shadow_frame.GetCurrentLocationForThrow(),
-                                   "Ljava/lang/ArrayIndexOutOfBoundsException;",
-                                   "failed FILL_ARRAY_DATA; length=%d, index=%d",
-                                   array->GetLength(), payload->element_count);
+        Object* obj = shadow_frame.GetVRegReference(inst->VRegA_31t(inst_data));
+        bool success = FillArrayData(obj, payload);
+        if (!success) {
           HANDLE_PENDING_EXCEPTION();
           break;
         }
         if (transaction_active) {
-          RecordArrayElementsInTransaction(array, payload->element_count);
+          RecordArrayElementsInTransaction(obj->AsArray(), payload->element_count);
         }
-        uint32_t size_in_bytes = payload->element_count * payload->element_width;
-        memcpy(array->GetRawData(payload->element_width, 0), payload->data, size_in_bytes);
         inst = inst->Next_3xx();
         break;
       }
diff --git a/runtime/thread_list.cc b/runtime/thread_list.cc
index ec5b775..53c2859 100644
--- a/runtime/thread_list.cc
+++ b/runtime/thread_list.cc
@@ -199,6 +199,8 @@
   Runtime* runtime = Runtime::Current();
   std::ostringstream ss;
   ss << "Thread suspend timeout\n";
+  Locks::mutator_lock_->Dump(ss);
+  ss << "\n";
   runtime->GetThreadList()->Dump(ss);
   LOG(FATAL) << ss.str();
   exit(0);