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));
}
* @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 {
}
/*
- * 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.
*/
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);
}
/*
- * 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.
*/
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;
}
}
+/*
+ * 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.
//
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);
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);
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.
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;
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() :
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;
* 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
* 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
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
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
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.
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
#include "base/macros.h"
#include "base/mutex.h"
+#include "dex_instruction.h"
#include "gc/allocator_type.h"
#include "invoke_type.h"
#include "jvalue.h"
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() {
*/
#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 {
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
*/
#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
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();
}
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;
}