%def op_aget(load="ldr" , shift=2 , data_offset="MIRROR_INT_ARRAY_DATA_OFFSET" , wide=False, is_object=False):
/*
* Array get . vAA < - vBB [ vCC ] .
*
* for : aget , aget - boolean , aget - byte , aget - char , aget - short , aget - wide , aget - object
*
*/
FETCH_B r2, 1 , 0 @ r2<- BB
% if wide:
lsrs r4, rINST, #8 @ r4<- AA; set flags to use 16 -bit encoding
% else:
lsr r4, rINST, #8 @ r4<- AA
FETCH_B r3, 1 , 1 @ r3<- CC
GET_VREG r0, r2 @ r0<- vBB (array object)
GET_VREG r1, r3 @ r1<- vCC (requested index)
// Note: if r0 is null, this will be handled by our SIGSEGV handler.
ldr r3, [r0, #MIRROR_ARRAY_LENGTH_OFFSET] @ r3<- arrayObj->length
add r0, r0, r1, lsl #$shift @ r0<- arrayObj + index*width
cmp r1, r3 @ compare unsigned index, length
bcs common_errArrayIndex @ index >= length, bail
FETCH_ADVANCE_INST 2 @ advance rPC, load rINST
% if wide:
CLEAR_SHADOW_PAIR r4, lr, ip @ Zero out the shadow regs
ldrd r2, [r0, #$data_offset] @ r2/r3<- vBB[vCC]
VREG_INDEX_TO_ADDR r4, r4 @ r4<- &fp[AA]
PREPARE_OPCODE_DISPATCH @ insert opcode to rIBASE
SET_VREG_WIDE_BY_ADDR r2, r3, r4 @ vAA/vAA+1 <- r2/r3
GOTO_OPCODE @ jump to next instruction
% elif is_object:
$load r2, [r0, #$data_offset] @ w2<- vBB[vCC]
UNPOISON_HEAP_REF r2, s="s"
TEST_IF_MARKING 2 f
1 :
PREPARE_OPCODE_DISPATCH @ insert opcode to rIBASE
#ifdef USE_HEAP_POISONING
PRESCALE_VREG r4, r4, s="s" @ set flags to use 16 -bit encoding
SET_VREG_OBJECT_PRESCALED r2, r4 @ vAA<- w2
#else // USE_HEAP_POISONING
SET_VREG_OBJECT r2, r4 @ vAA<- w2
#endif // USE_HEAP_POISONING
GOTO_OPCODE @ jump to next instruction
2 :
bl art_quick_read_barrier_mark_reg02
b 1 b
% else:
PREPARE_OPCODE_DISPATCH @ insert opcode to rIBASE
$load r2, [r0, #$data_offset] @ r2<- vBB[vCC]
SET_VREG r2, r4 @ vAA<- r2
GOTO_OPCODE @ jump to next instruction
%def op_aget_boolean():
% op_aget(load="ldrb" , shift=0 , data_offset="MIRROR_BOOLEAN_ARRAY_DATA_OFFSET" )
%def op_aget_byte():
% op_aget(load="ldrsb" , shift=0 , data_offset="MIRROR_BYTE_ARRAY_DATA_OFFSET" )
%def op_aget_char():
% op_aget(load="ldrh" , shift=1 , data_offset="MIRROR_CHAR_ARRAY_DATA_OFFSET" )
%def op_aget_object():
% op_aget(load="ldr" , shift=2 , data_offset="MIRROR_OBJECT_ARRAY_DATA_OFFSET" , is_object=True)
%def op_aget_short():
% op_aget(load="ldrsh" , shift=1 , data_offset="MIRROR_SHORT_ARRAY_DATA_OFFSET" )
%def op_aget_wide():
% op_aget(load="ldrd" , shift=3 , data_offset="MIRROR_WIDE_ARRAY_DATA_OFFSET" , wide=True)
%def op_aput(store="str" , shift=2 , data_offset="MIRROR_INT_ARRAY_DATA_OFFSET" , wide=False, is_object=False):
/*
* Array put . vBB [ vCC ] < - vAA .
*
* for : aput , aput - boolean , aput - byte , aput - char , aput - short , aput - wide , aput - object
*
*/
FETCH_B r2, 1 , 0 @ r2<- BB
mov r4, rINST, lsr #8 @ r4<- AA
FETCH_B r3, 1 , 1 @ r3<- CC
GET_VREG r0, r2 @ r0<- vBB (array object)
GET_VREG r1, r3 @ r1<- vCC (requested index)
// Note: if r0 is null, this will be handled by our SIGSEGV handler.
ldr r3, [r0, #MIRROR_ARRAY_LENGTH_OFFSET] @ r3<- arrayObj->length
cmp r1, r3 @ compare unsigned index, length
bcs common_errArrayIndex @ index >= length, bail
% if is_object:
EXPORT_PC // Export PC before overwriting it.
FETCH_ADVANCE_INST 2 @ advance rPC, load rINST
GET_VREG r2, r4 @ r2<- vAA
bl art_quick_aput_obj
PREPARE_OPCODE_DISPATCH @ insert opcode to rIBASE
% elif wide:
add r0, r0, r1, lsl #$shift @ r0<- arrayObj + index*width
VREG_INDEX_TO_ADDR r4, r4 @ r4<- &fp[AA]
FETCH_ADVANCE_INST 2 @ advance rPC, load rINST
GET_VREG_WIDE_BY_ADDR r2, r3, r4 @ r2/r3<- vAA/vAA+1
PREPARE_OPCODE_DISPATCH @ insert opcode to rIBASE
strd r2, [r0, #$data_offset] @ r2/r3<- vBB[vCC]
% else:
add r0, r0, r1, lsl #$shift @ r0<- arrayObj + index*width
FETCH_ADVANCE_INST 2 @ advance rPC, load rINST
GET_VREG r2, r4 @ r2<- vAA
PREPARE_OPCODE_DISPATCH @ insert opcode to rIBASE
$store r2, [r0, #$data_offset] @ vBB[vCC]<- r2
GOTO_OPCODE @ jump to next instruction
%def op_aput_boolean():
% op_aput(store="strb" , shift=0 , data_offset="MIRROR_BOOLEAN_ARRAY_DATA_OFFSET" )
%def op_aput_byte():
% op_aput(store="strb" , shift=0 , data_offset="MIRROR_BYTE_ARRAY_DATA_OFFSET" )
%def op_aput_char():
% op_aput(store="strh" , shift=1 , data_offset="MIRROR_CHAR_ARRAY_DATA_OFFSET" )
%def op_aput_short():
% op_aput(store="strh" , shift=1 , data_offset="MIRROR_SHORT_ARRAY_DATA_OFFSET" )
%def op_aput_wide():
% op_aput(store="str" , shift=3 , data_offset="MIRROR_WIDE_ARRAY_DATA_OFFSET" , wide=True)
%def op_aput_object():
% op_aput(store="str" , shift=2 , data_offset="MIRROR_OBJECT_ARRAY_DATA_OFFSET" , is_object=True)
%def op_array_length():
/*
* Return the length of an array .
*/
mov r1, rINST, lsr #12 @ r1<- B
ubfx r2, rINST, #8 , #4 @ r2<- A
GET_VREG r0, r1 @ r0<- vB (object ref)
cmp r0, #0 @ is object null?
beq common_errNullObject @ yup, fail
FETCH_ADVANCE_INST 1 @ advance rPC, load rINST
ldr r3, [r0, #MIRROR_ARRAY_LENGTH_OFFSET] @ r3<- array length
PREPARE_OPCODE_DISPATCH @ insert opcode to rIBASE
SET_VREG r3, r2 @ vB<- length
GOTO_OPCODE @ jump to next instruction
%def op_fill_array_data():
/* fill-array-data vAA, +BBBBBBBB */
EXPORT_PC
FETCH r0, 1 @ r0<- bbbb (lo )
FETCH r1, 2 @ r1<- BBBB (hi )
mov r3, rINST, lsr #8 @ r3<- AA
orr r0, r0, r1, lsl #16 @ r0<- BBBBbbbb
GET_VREG r1, r3 @ r1<- vAA (array object)
add r0, rPC, r0, lsl #1 @ r1<- PC + BBBBbbbb*2 (array data off.)
bl art_quick_handle_fill_data @ (payload, object)
FETCH_ADVANCE_INST 3 @ advance rPC, load rINST
PREPARE_OPCODE_DISPATCH @ insert opcode to rIBASE
GOTO_OPCODE @ jump to next instruction
%def op_filled_new_array(helper="nterp_filled_new_array" ):
/*
* Create a new array with elements filled from registers .
*
* for : filled - new - array , filled - new - array / range
*/
/* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
/* op {vCCCC..v(CCCC+AA-1)}, type@BBBB */
EXPORT_PC
mov r0, rSELF
ldr r1, [sp]
mov r2, rFP
mov r3, rPC
bl $helper
FETCH_ADVANCE_INST 3 // advance rPC, load rINST
PREPARE_OPCODE_DISPATCH // insert opcode to rIBASE
GOTO_OPCODE // jump to next instruction
%def op_filled_new_array_range():
% op_filled_new_array(helper="nterp_filled_new_array_range" )
%def op_new_array():
/* new-array vA, vB, class@CCCC */
EXPORT_PC
% slow_path = add_slow_path(op_new_array_slow_path)
// Fast-path which gets the class from thread-local cache.
% fetch_from_thread_cache("r0" , miss_label=slow_path)
TEST_IF_MARKING 1 f
.L${opcode}_resume:
lsr r1, rINST, #12 // r1<- B
GET_VREG r1, r1 // r1<- vB (array length)
ldr lr, [rSELF, #THREAD_ALLOC_ARRAY_ENTRYPOINT_OFFSET]
blx lr
dmb ishst // need fence for making array's class visible
ubfx r1, rINST, #(8 -2 ), #(4 +2 ) // r1<- A << 2 ; opcode 23 has highest two bits clear
// Shorten the handler by using the dispatch from the `op_new_instance` handler.
% new_instance_opcode = re.sub (r"new_array" , r"new_instance" , opcode);
b .L${new_instance_opcode}_store_r0_to_prescaled_r1_fetch_advance_2_dispatch
1 :
bl art_quick_read_barrier_mark_reg00
b .L${opcode}_resume
%def op_new_array_slow_path():
mov r0, rSELF
ldr r1, [sp]
mov r2, rPC
bl nterp_get_class
b .L${opcode}_resume
Messung V0.5 in Prozent C=88 H=95 G=91
¤ Dauer der Verarbeitung: 0.10 Sekunden
(vorverarbeitet am 2026-06-29)
¤
*© Formatika GbR, Deutschland