diff options
22 files changed, 84 insertions, 290 deletions
diff --git a/compiler/dex/mir_graph.h b/compiler/dex/mir_graph.h index f14b1876e8..fe6fb75151 100644 --- a/compiler/dex/mir_graph.h +++ b/compiler/dex/mir_graph.h @@ -338,7 +338,7 @@ struct MIR { 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 @@ class MIRGraph { * @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 b721e02e9a..13b9bf09ed 100644 --- a/compiler/dex/quick/arm/call_arm.cc +++ b/compiler/dex/quick/arm/call_arm.cc @@ -140,41 +140,6 @@ void ArmMir2Lir::GenLargePackedSwitch(MIR* mir, uint32_t table_offset, RegLocati } /* - * 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 932dd87923..1c87a0386c 100644 --- a/compiler/dex/quick/arm/codegen_arm.h +++ b/compiler/dex/quick/arm/codegen_arm.h @@ -118,7 +118,6 @@ class ArmMir2Lir FINAL : public Mir2Lir { 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 e8de876d61..c898e2d205 100644 --- a/compiler/dex/quick/arm64/call_arm64.cc +++ b/compiler/dex/quick/arm64/call_arm64.cc @@ -149,41 +149,6 @@ void Arm64Mir2Lir::GenLargePackedSwitch(MIR* mir, uint32_t table_offset, RegLoca } /* - * 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 93d9b34beb..510bd4c5de 100644 --- a/compiler/dex/quick/arm64/codegen_arm64.h +++ b/compiler/dex/quick/arm64/codegen_arm64.h @@ -183,7 +183,6 @@ class Arm64Mir2Lir FINAL : public Mir2Lir { 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 3f7ecfe03b..3a3821f800 100644 --- a/compiler/dex/quick/gen_common.cc +++ b/compiler/dex/quick/gen_common.cc @@ -496,6 +496,27 @@ void Mir2Lir::GenFilledNewArray(CallInfo* info) { } } +/* + * 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 6536c413e8..8b5bc45683 100644 --- a/compiler/dex/quick/mips/call_mips.cc +++ b/compiler/dex/quick/mips/call_mips.cc @@ -210,54 +210,6 @@ void MipsMir2Lir::GenLargePackedSwitch(MIR* mir, DexOffset table_offset, RegLoca 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 be94019ef3..bd709f38ae 100644 --- a/compiler/dex/quick/mips/codegen_mips.h +++ b/compiler/dex/quick/mips/codegen_mips.h @@ -116,7 +116,6 @@ class MipsMir2Lir FINAL : public Mir2Lir { 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 3de4c563dd..858fb1c138 100644 --- a/compiler/dex/quick/mir_to_lir.h +++ b/compiler/dex/quick/mir_to_lir.h @@ -832,6 +832,7 @@ class Mir2Lir : public Backend { 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 @@ class Mir2Lir : public Backend { 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 441ec9e009..86efc1e52c 100644 --- a/compiler/dex/quick/x86/call_x86.cc +++ b/compiler/dex/quick/x86/call_x86.cc @@ -126,54 +126,6 @@ void X86Mir2Lir::GenLargePackedSwitch(MIR* mir, DexOffset table_offset, RegLocat 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 8edfc017d1..b3544dafba 100644 --- a/compiler/dex/quick/x86/codegen_x86.h +++ b/compiler/dex/quick/x86/codegen_x86.h @@ -245,7 +245,6 @@ class X86Mir2Lir : public Mir2Lir { 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 51bcd3c654..466e9eb098 100644 --- a/runtime/arch/arm/quick_entrypoints_arm.S +++ b/runtime/arch/arm/quick_entrypoints_arm.S @@ -426,16 +426,7 @@ END art_quick_do_long_jump * 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 606816a181..252e89e938 100644 --- a/runtime/arch/arm64/quick_entrypoints_arm64.S +++ b/runtime/arch/arm64/quick_entrypoints_arm64.S @@ -940,16 +940,7 @@ END art_quick_do_long_jump * 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 9e9e5236af..609c65a38f 100644 --- a/runtime/arch/mips/quick_entrypoints_mips.S +++ b/runtime/arch/mips/quick_entrypoints_mips.S @@ -545,9 +545,10 @@ END art_quick_invoke_stub 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 4155b7eefe..411d273bca 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_static_storage, artInitializeStaticStorage 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 e68cfbcbc6..ca9c0bf0fa 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_static_storage, artInitializeStaticStorage 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/entrypoints/entrypoint_utils.cc b/runtime/entrypoints/entrypoint_utils.cc index 835d6e2b7e..7b90339b68 100644 --- a/runtime/entrypoints/entrypoint_utils.cc +++ b/runtime/entrypoints/entrypoint_utils.cc @@ -344,4 +344,28 @@ JValue InvokeProxyInvocationHandler(ScopedObjectAccessAlreadyRunnable& soa, cons 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 08edecfb00..ce34993950 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 @@ JValue InvokeProxyInvocationHandler(ScopedObjectAccessAlreadyRunnable& soa, cons 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 686954bc33..f0ad6de3a1 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 @@ extern "C" void art_portable_fill_array_data_from_code(mirror::ArtMethod* method 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 4ec28791fb..06bbabcbe2 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 5c8a6c6f16..db7c452819 100644 --- a/runtime/interpreter/interpreter_goto_table_impl.cc +++ b/runtime/interpreter/interpreter_goto_table_impl.cc @@ -573,30 +573,14 @@ JValue ExecuteGotoImpl(Thread* self, MethodHelper& mh, const DexFile::CodeItem* 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 c6cef6a648..fe0af27f00 100644 --- a/runtime/interpreter/interpreter_switch_impl.cc +++ b/runtime/interpreter/interpreter_switch_impl.cc @@ -484,30 +484,18 @@ JValue ExecuteSwitchImpl(Thread* self, MethodHelper& mh, const DexFile::CodeItem } 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; } |