253
254 void MethodHandles::RicochetFrame::leave_ricochet_frame(MacroAssembler* _masm,
255 Register recv_reg,
256 Register new_sp_reg,
257 Register sender_pc_reg) {
258 assert(new_sp_reg == I5_savedSP, "exact_sender_sp already in place");
259 assert(sender_pc_reg == I7, "in a fixed place");
260 // does not include the __ ret() & __ restore()
261 assert_different_registers(recv_reg, new_sp_reg, sender_pc_reg);
262 // Take down the frame.
263 // Cf. InterpreterMacroAssembler::remove_activation.
264 BLOCK_COMMENT("end_ricochet_frame {");
265 if (recv_reg->is_valid())
266 __ mov(L2_saved_target, recv_reg);
267 BLOCK_COMMENT("} end_ricochet_frame");
268 }
269
270 // Emit code to verify that FP is pointing at a valid ricochet frame.
271 #ifdef ASSERT
272 enum {
273 ARG_LIMIT = 255, SLOP = 35,
274 // use this parameter for checking for garbage stack movements:
275 UNREASONABLE_STACK_MOVE = (ARG_LIMIT + SLOP)
276 // the slop defends against false alarms due to fencepost errors
277 };
278
279 void MethodHandles::RicochetFrame::verify_clean(MacroAssembler* _masm) {
280 // The stack should look like this:
281 // ... keep1 | dest=42 | keep2 | magic | handler | magic | recursive args | [RF]
282 // Check various invariants.
283
284 Register O7_temp = O7, O5_temp = O5;
285
286 Label L_ok_1, L_ok_2, L_ok_3, L_ok_4;
287 BLOCK_COMMENT("verify_clean {");
288 // Magic numbers must check out:
289 __ set((int32_t) MAGIC_NUMBER_1, O7_temp);
290 __ cmp(O7_temp, L0_magic_number_1);
291 __ br(Assembler::equal, false, Assembler::pt, L_ok_1);
292 __ delayed()->nop();
293 __ stop("damaged ricochet frame: MAGIC_NUMBER_1 not found");
1564 // pseudo-code:
1565 // argslot = src_addr - swap_bytes
1566 // destslot = dest_addr
1567 // while (argslot >= destslot) *(argslot + swap_bytes) = *(argslot + 0), argslot--;
1568 move_arg_slots_up(_masm,
1569 O1_destslot,
1570 Address(O0_argslot, 0),
1571 swap_slots,
1572 O0_argslot, O2_scratch);
1573 } else {
1574 // Here is the other direction, rotate < 0:
1575 // (low mem) (high mem)
1576 // | arg: odd_slot | arg+1: more_slots... :dest+1 |
1577 // =>
1578 // | arg: more_slots... | dest: odd_slot :dest+1 |
1579 // work argslot up to destslot, copying contiguous data downwards
1580 // pseudo-code:
1581 // argslot = src_addr + swap_bytes
1582 // destslot = dest_addr
1583 // while (argslot <= destslot) *(argslot - swap_bytes) = *(argslot + 0), argslot++;
1584 __ add(O1_destslot, wordSize, O1_destslot);
1585 move_arg_slots_down(_masm,
1586 Address(O0_argslot, swap_slots * wordSize),
1587 O1_destslot,
1588 -swap_slots,
1589 O0_argslot, O2_scratch);
1590
1591 __ sub(O1_destslot, wordSize, O1_destslot);
1592 }
1593 // pop the original first chunk into the destination slot, now free
1594 switch (swap_slots) {
1595 case 2 : __ st_ptr(O4_scratch, Address(O1_destslot, 1 * wordSize)); // fall-thru
1596 case 1 : __ st_ptr(O3_scratch, Address(O1_destslot, 0 * wordSize)); break;
1597 default: ShouldNotReachHere();
1598 }
1599 }
1600
1601 __ load_heap_oop(G3_mh_vmtarget, G3_method_handle);
1602 __ jump_to_method_handle_entry(G3_method_handle, O1_scratch);
1603 }
1604 break;
1605
1606 case _adapter_dup_args:
1607 {
1608 // 'argslot' is the position of the first argument to duplicate.
1609 load_vmargslot(_masm, G3_amh_vmargslot, O0_argslot);
1610 __ add(__ argument_address(O0_argslot, O0_argslot), O0_argslot);
1611
|
253
254 void MethodHandles::RicochetFrame::leave_ricochet_frame(MacroAssembler* _masm,
255 Register recv_reg,
256 Register new_sp_reg,
257 Register sender_pc_reg) {
258 assert(new_sp_reg == I5_savedSP, "exact_sender_sp already in place");
259 assert(sender_pc_reg == I7, "in a fixed place");
260 // does not include the __ ret() & __ restore()
261 assert_different_registers(recv_reg, new_sp_reg, sender_pc_reg);
262 // Take down the frame.
263 // Cf. InterpreterMacroAssembler::remove_activation.
264 BLOCK_COMMENT("end_ricochet_frame {");
265 if (recv_reg->is_valid())
266 __ mov(L2_saved_target, recv_reg);
267 BLOCK_COMMENT("} end_ricochet_frame");
268 }
269
270 // Emit code to verify that FP is pointing at a valid ricochet frame.
271 #ifdef ASSERT
272 enum {
273 ARG_LIMIT = 255, SLOP = 45,
274 // use this parameter for checking for garbage stack movements:
275 UNREASONABLE_STACK_MOVE = (ARG_LIMIT + SLOP)
276 // the slop defends against false alarms due to fencepost errors
277 };
278
279 void MethodHandles::RicochetFrame::verify_clean(MacroAssembler* _masm) {
280 // The stack should look like this:
281 // ... keep1 | dest=42 | keep2 | magic | handler | magic | recursive args | [RF]
282 // Check various invariants.
283
284 Register O7_temp = O7, O5_temp = O5;
285
286 Label L_ok_1, L_ok_2, L_ok_3, L_ok_4;
287 BLOCK_COMMENT("verify_clean {");
288 // Magic numbers must check out:
289 __ set((int32_t) MAGIC_NUMBER_1, O7_temp);
290 __ cmp(O7_temp, L0_magic_number_1);
291 __ br(Assembler::equal, false, Assembler::pt, L_ok_1);
292 __ delayed()->nop();
293 __ stop("damaged ricochet frame: MAGIC_NUMBER_1 not found");
1564 // pseudo-code:
1565 // argslot = src_addr - swap_bytes
1566 // destslot = dest_addr
1567 // while (argslot >= destslot) *(argslot + swap_bytes) = *(argslot + 0), argslot--;
1568 move_arg_slots_up(_masm,
1569 O1_destslot,
1570 Address(O0_argslot, 0),
1571 swap_slots,
1572 O0_argslot, O2_scratch);
1573 } else {
1574 // Here is the other direction, rotate < 0:
1575 // (low mem) (high mem)
1576 // | arg: odd_slot | arg+1: more_slots... :dest+1 |
1577 // =>
1578 // | arg: more_slots... | dest: odd_slot :dest+1 |
1579 // work argslot up to destslot, copying contiguous data downwards
1580 // pseudo-code:
1581 // argslot = src_addr + swap_bytes
1582 // destslot = dest_addr
1583 // while (argslot <= destslot) *(argslot - swap_bytes) = *(argslot + 0), argslot++;
1584 // dest_slot denotes an exclusive upper limit
1585 int limit_bias = OP_ROT_ARGS_DOWN_LIMIT_BIAS;
1586 if (limit_bias != 0)
1587 __ add(O1_destslot, - limit_bias * wordSize, O1_destslot);
1588 move_arg_slots_down(_masm,
1589 Address(O0_argslot, swap_slots * wordSize),
1590 O1_destslot,
1591 -swap_slots,
1592 O0_argslot, O2_scratch);
1593
1594 __ sub(O1_destslot, swap_slots * wordSize, O1_destslot);
1595 }
1596 // pop the original first chunk into the destination slot, now free
1597 switch (swap_slots) {
1598 case 2 : __ st_ptr(O4_scratch, Address(O1_destslot, 1 * wordSize)); // fall-thru
1599 case 1 : __ st_ptr(O3_scratch, Address(O1_destslot, 0 * wordSize)); break;
1600 default: ShouldNotReachHere();
1601 }
1602 }
1603
1604 __ load_heap_oop(G3_mh_vmtarget, G3_method_handle);
1605 __ jump_to_method_handle_entry(G3_method_handle, O1_scratch);
1606 }
1607 break;
1608
1609 case _adapter_dup_args:
1610 {
1611 // 'argslot' is the position of the first argument to duplicate.
1612 load_vmargslot(_masm, G3_amh_vmargslot, O0_argslot);
1613 __ add(__ argument_address(O0_argslot, O0_argslot), O0_argslot);
1614
|