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