21 * questions.
22 *
23 */
24
25 #include "precompiled.hpp"
26 #include "asm/assembler.hpp"
27 #include "c1/c1_Defs.hpp"
28 #include "c1/c1_MacroAssembler.hpp"
29 #include "c1/c1_Runtime1.hpp"
30 #include "interpreter/interpreter.hpp"
31 #include "nativeInst_x86.hpp"
32 #include "oops/compiledICHolder.hpp"
33 #include "oops/oop.inline.hpp"
34 #include "prims/jvmtiExport.hpp"
35 #include "register_x86.hpp"
36 #include "runtime/sharedRuntime.hpp"
37 #include "runtime/signature.hpp"
38 #include "runtime/vframeArray.hpp"
39 #include "utilities/macros.hpp"
40 #include "vmreg_x86.inline.hpp"
41 #if INCLUDE_ALL_GCS
42 #include "gc/g1/g1SATBCardTableModRefBS.hpp"
43 #endif
44
45
46 // Implementation of StubAssembler
47
48 int StubAssembler::call_RT(Register oop_result1, Register metadata_result, address entry, int args_size) {
49 // setup registers
50 const Register thread = NOT_LP64(rdi) LP64_ONLY(r15_thread); // is callee-saved register (Visual C++ calling conventions)
51 assert(!(oop_result1->is_valid() || metadata_result->is_valid()) || oop_result1 != metadata_result, "registers must be different");
52 assert(oop_result1 != thread && metadata_result != thread, "registers must be different");
53 assert(args_size >= 0, "illegal args_size");
54 bool align_stack = false;
55 #ifdef _LP64
56 // At a method handle call, the stack may not be properly aligned
57 // when returning with an exception.
58 align_stack = (stub_id() == Runtime1::handle_exception_from_callee_id);
59 #endif
60
61 #ifdef _LP64
62 mov(c_rarg0, thread);
63 set_num_rt_args(0); // Nothing on stack
64 #else
190 push(arg2);
191 push(arg1);
192 #endif // _LP64
193 return call_RT(oop_result1, metadata_result, entry, 3);
194 }
195
196
197 // Implementation of StubFrame
198
199 class StubFrame: public StackObj {
200 private:
201 StubAssembler* _sasm;
202
203 public:
204 StubFrame(StubAssembler* sasm, const char* name, bool must_gc_arguments);
205 void load_argument(int offset_in_words, Register reg);
206
207 ~StubFrame();
208 };
209
210
211 #define __ _sasm->
212
213 StubFrame::StubFrame(StubAssembler* sasm, const char* name, bool must_gc_arguments) {
214 _sasm = sasm;
215 __ set_info(name, must_gc_arguments);
216 __ enter();
217 }
218
219 // load parameters that were stored with LIR_Assembler::store_parameter
220 // Note: offsets for store_parameter and load_argument must match
221 void StubFrame::load_argument(int offset_in_words, Register reg) {
222 // rbp, + 0: link
223 // + 1: return address
224 // + 2: argument with offset 0
225 // + 3: argument with offset 1
226 // + 4: ...
227
228 __ movptr(reg, Address(rbp, (offset_in_words + 2) * BytesPerWord));
229 }
230
231
232 StubFrame::~StubFrame() {
233 __ leave();
234 __ ret(0);
235 }
236
237 #undef __
238
239
240 // Implementation of Runtime1
241
242 #define __ sasm->
243
244 const int float_regs_as_doubles_size_in_slots = pd_nof_fpu_regs_frame_map * 2;
245 const int xmm_regs_as_doubles_size_in_slots = FrameMap::nof_xmm_regs * 2;
246
247 // Stack layout for saving/restoring all the registers needed during a runtime
248 // call (this includes deoptimization)
249 // Note: note that users of this frame may well have arguments to some runtime
250 // while these values are on the stack. These positions neglect those arguments
251 // but the code in save_live_registers will take the argument count into
252 // account.
253 //
254 #ifdef _LP64
255 #define SLOT2(x) x,
256 #define SLOT_PER_WORD 2
257 #else
258 #define SLOT2(x)
259 #define SLOT_PER_WORD 1
260 #endif // _LP64
261
262 enum reg_save_layout {
263 // 64bit needs to keep stack 16 byte aligned. So we add some alignment dummies to make that
288 r11_off, r11H_off, // 392, 396
289 r10_off, r10H_off, // 400, 404
290 r9_off, r9H_off, // 408, 412
291 r8_off, r8H_off, // 416, 420
292 rdi_off, rdiH_off, // 424, 428
293 #else
294 rdi_off = extra_space_offset,
295 #endif // _LP64
296 rsi_off, SLOT2(rsiH_off) // 432, 436
297 rbp_off, SLOT2(rbpH_off) // 440, 444
298 rsp_off, SLOT2(rspH_off) // 448, 452
299 rbx_off, SLOT2(rbxH_off) // 456, 460
300 rdx_off, SLOT2(rdxH_off) // 464, 468
301 rcx_off, SLOT2(rcxH_off) // 472, 476
302 rax_off, SLOT2(raxH_off) // 480, 484
303 saved_rbp_off, SLOT2(saved_rbpH_off) // 488, 492
304 return_off, SLOT2(returnH_off) // 496, 500
305 reg_save_frame_size // As noted: neglects any parameters to runtime // 504
306 };
307
308
309
310 // Save off registers which might be killed by calls into the runtime.
311 // Tries to smart of about FP registers. In particular we separate
312 // saving and describing the FPU registers for deoptimization since we
313 // have to save the FPU registers twice if we describe them and on P4
314 // saving FPU registers which don't contain anything appears
315 // expensive. The deopt blob is the only thing which needs to
316 // describe FPU registers. In all other cases it should be sufficient
317 // to simply save their current value.
318
319 static OopMap* generate_oop_map(StubAssembler* sasm, int num_rt_args,
320 bool save_fpu_registers = true) {
321
322 // In 64bit all the args are in regs so there are no additional stack slots
323 LP64_ONLY(num_rt_args = 0);
324 LP64_ONLY(assert((reg_save_frame_size * VMRegImpl::stack_slot_size) % 16 == 0, "must be 16 byte aligned");)
325 int frame_size_in_slots = reg_save_frame_size + num_rt_args; // args + thread
326 sasm->set_frame_size(frame_size_in_slots / VMRegImpl::slots_per_word);
327
328 // record saved value locations in an OopMap
329 // locations are offsets from sp after runtime call; num_rt_args is number of arguments in call, including thread
396 }
397 }
398 xmm_off += 2;
399 }
400 assert(xmm_off == float_regs_as_doubles_off, "incorrect number of xmm registers");
401
402 } else if (UseSSE == 1) {
403 int xmm_off = xmm_regs_as_doubles_off;
404 for (int n = 0; n < FrameMap::nof_fpu_regs; n++) {
405 VMReg xmm_name_0 = as_XMMRegister(n)->as_VMReg();
406 map->set_callee_saved(VMRegImpl::stack2reg(xmm_off + num_rt_args), xmm_name_0);
407 xmm_off += 2;
408 }
409 assert(xmm_off == float_regs_as_doubles_off, "incorrect number of xmm registers");
410 }
411 }
412
413 return map;
414 }
415
416 static OopMap* save_live_registers(StubAssembler* sasm, int num_rt_args,
417 bool save_fpu_registers = true) {
418 __ block_comment("save_live_registers");
419
420 __ pusha(); // integer registers
421
422 // assert(float_regs_as_doubles_off % 2 == 0, "misaligned offset");
423 // assert(xmm_regs_as_doubles_off % 2 == 0, "misaligned offset");
424
425 __ subptr(rsp, extra_space_offset * VMRegImpl::stack_slot_size);
426
427 #ifdef ASSERT
428 __ movptr(Address(rsp, marker * VMRegImpl::stack_slot_size), (int32_t)0xfeedbeef);
429 #endif
430
431 if (save_fpu_registers) {
432 if (UseSSE < 2) {
433 // save FPU stack
434 __ fnsave(Address(rsp, fpu_state_off * VMRegImpl::stack_slot_size));
435 __ fwait();
436
437 #ifdef ASSERT
471 }
472 #endif
473 for (int n = 0; n < xmm_bypass_limit; n++) {
474 XMMRegister xmm_name = as_XMMRegister(n);
475 __ movdbl(Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + offset), xmm_name);
476 offset += 8;
477 }
478 } else if (UseSSE == 1) {
479 // save XMM registers as float because double not supported without SSE2(num MMX == num fpu)
480 int offset = 0;
481 for (int n = 0; n < FrameMap::nof_fpu_regs; n++) {
482 XMMRegister xmm_name = as_XMMRegister(n);
483 __ movflt(Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + offset), xmm_name);
484 offset += 8;
485 }
486 }
487 }
488
489 // FPU stack must be empty now
490 __ verify_FPU(0, "save_live_registers");
491
492 return generate_oop_map(sasm, num_rt_args, save_fpu_registers);
493 }
494
495
496 static void restore_fpu(StubAssembler* sasm, bool restore_fpu_registers = true) {
497 if (restore_fpu_registers) {
498 if (UseSSE >= 2) {
499 // restore XMM registers
500 int xmm_bypass_limit = FrameMap::nof_xmm_regs;
501 #ifdef _LP64
502 if (UseAVX < 3) {
503 xmm_bypass_limit = xmm_bypass_limit / 2;
504 }
505 #endif
506 int offset = 0;
507 for (int n = 0; n < xmm_bypass_limit; n++) {
508 XMMRegister xmm_name = as_XMMRegister(n);
509 __ movdbl(xmm_name, Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + offset));
510 offset += 8;
511 }
512 } else if (UseSSE == 1) {
513 // restore XMM registers(num MMX == num fpu)
514 int offset = 0;
515 for (int n = 0; n < FrameMap::nof_fpu_regs; n++) {
516 XMMRegister xmm_name = as_XMMRegister(n);
527 }
528
529 } else {
530 // check that FPU stack is really empty
531 __ verify_FPU(0, "restore_live_registers");
532 }
533
534 #ifdef ASSERT
535 {
536 Label ok;
537 __ cmpptr(Address(rsp, marker * VMRegImpl::stack_slot_size), (int32_t)0xfeedbeef);
538 __ jcc(Assembler::equal, ok);
539 __ stop("bad offsets in frame");
540 __ bind(ok);
541 }
542 #endif // ASSERT
543
544 __ addptr(rsp, extra_space_offset * VMRegImpl::stack_slot_size);
545 }
546
547
548 static void restore_live_registers(StubAssembler* sasm, bool restore_fpu_registers = true) {
549 __ block_comment("restore_live_registers");
550
551 restore_fpu(sasm, restore_fpu_registers);
552 __ popa();
553 }
554
555
556 static void restore_live_registers_except_rax(StubAssembler* sasm, bool restore_fpu_registers = true) {
557 __ block_comment("restore_live_registers_except_rax");
558
559 restore_fpu(sasm, restore_fpu_registers);
560
561 #ifdef _LP64
562 __ movptr(r15, Address(rsp, 0));
563 __ movptr(r14, Address(rsp, wordSize));
564 __ movptr(r13, Address(rsp, 2 * wordSize));
565 __ movptr(r12, Address(rsp, 3 * wordSize));
566 __ movptr(r11, Address(rsp, 4 * wordSize));
567 __ movptr(r10, Address(rsp, 5 * wordSize));
568 __ movptr(r9, Address(rsp, 6 * wordSize));
569 __ movptr(r8, Address(rsp, 7 * wordSize));
570 __ movptr(rdi, Address(rsp, 8 * wordSize));
571 __ movptr(rsi, Address(rsp, 9 * wordSize));
572 __ movptr(rbp, Address(rsp, 10 * wordSize));
573 // skip rsp
574 __ movptr(rbx, Address(rsp, 12 * wordSize));
1583 #endif // _LP64
1584 __ jmp(do_return);
1585
1586 __ bind(return0);
1587 __ fpop();
1588 #ifndef _LP64
1589 __ xorptr(rdx,rdx);
1590 __ xorptr(rax,rax);
1591 #else
1592 __ xorptr(rax, rax);
1593 #endif // _LP64
1594
1595 __ bind(do_return);
1596 __ addptr(rsp, 32);
1597 LP64_ONLY(__ pop(rdx);)
1598 __ pop(rcx);
1599 __ pop(rsi);
1600 __ ret(0);
1601 }
1602 break;
1603
1604 #if INCLUDE_ALL_GCS
1605 case g1_pre_barrier_slow_id:
1606 {
1607 StubFrame f(sasm, "g1_pre_barrier", dont_gc_arguments);
1608 // arg0 : previous value of memory
1609
1610 BarrierSet* bs = Universe::heap()->barrier_set();
1611 if (bs->kind() != BarrierSet::G1SATBCTLogging) {
1612 __ movptr(rax, (int)id);
1613 __ call_RT(noreg, noreg, CAST_FROM_FN_PTR(address, unimplemented_entry), rax);
1614 __ should_not_reach_here();
1615 break;
1616 }
1617 __ push(rax);
1618 __ push(rdx);
1619
1620 const Register pre_val = rax;
1621 const Register thread = NOT_LP64(rax) LP64_ONLY(r15_thread);
1622 const Register tmp = rdx;
1623
1624 NOT_LP64(__ get_thread(thread);)
1625
1626 Address queue_active(thread, in_bytes(JavaThread::satb_mark_queue_offset() +
1627 SATBMarkQueue::byte_offset_of_active()));
1628 Address queue_index(thread, in_bytes(JavaThread::satb_mark_queue_offset() +
1629 SATBMarkQueue::byte_offset_of_index()));
1630 Address buffer(thread, in_bytes(JavaThread::satb_mark_queue_offset() +
1631 SATBMarkQueue::byte_offset_of_buf()));
1632
1633 Label done;
1634 Label runtime;
1635
1636 // Is marking still active?
1637 if (in_bytes(SATBMarkQueue::byte_width_of_active()) == 4) {
1638 __ cmpl(queue_active, 0);
1639 } else {
1640 assert(in_bytes(SATBMarkQueue::byte_width_of_active()) == 1, "Assumption");
1641 __ cmpb(queue_active, 0);
1642 }
1643 __ jcc(Assembler::equal, done);
1644
1645 // Can we store original value in the thread's buffer?
1646
1647 __ movptr(tmp, queue_index);
1648 __ testptr(tmp, tmp);
1649 __ jcc(Assembler::zero, runtime);
1650 __ subptr(tmp, wordSize);
1651 __ movptr(queue_index, tmp);
1652 __ addptr(tmp, buffer);
1653
1654 // prev_val (rax)
1655 f.load_argument(0, pre_val);
1656 __ movptr(Address(tmp, 0), pre_val);
1657 __ jmp(done);
1658
1659 __ bind(runtime);
1660
1661 save_live_registers(sasm, 3);
1662
1663 // load the pre-value
1664 f.load_argument(0, rcx);
1665 __ call_VM_leaf(CAST_FROM_FN_PTR(address, SharedRuntime::g1_wb_pre), rcx, thread);
1666
1667 restore_live_registers(sasm);
1668
1669 __ bind(done);
1670
1671 __ pop(rdx);
1672 __ pop(rax);
1673 }
1674 break;
1675
1676 case g1_post_barrier_slow_id:
1677 {
1678 StubFrame f(sasm, "g1_post_barrier", dont_gc_arguments);
1679
1680
1681 // arg0: store_address
1682 Address store_addr(rbp, 2*BytesPerWord);
1683
1684 CardTableModRefBS* ct =
1685 barrier_set_cast<CardTableModRefBS>(Universe::heap()->barrier_set());
1686 assert(sizeof(*ct->byte_map_base) == sizeof(jbyte), "adjust this code");
1687
1688 Label done;
1689 Label enqueued;
1690 Label runtime;
1691
1692 // At this point we know new_value is non-NULL and the new_value crosses regions.
1693 // Must check to see if card is already dirty
1694
1695 const Register thread = NOT_LP64(rax) LP64_ONLY(r15_thread);
1696
1697 Address queue_index(thread, in_bytes(JavaThread::dirty_card_queue_offset() +
1698 DirtyCardQueue::byte_offset_of_index()));
1699 Address buffer(thread, in_bytes(JavaThread::dirty_card_queue_offset() +
1700 DirtyCardQueue::byte_offset_of_buf()));
1701
1702 __ push(rax);
1703 __ push(rcx);
1704
1705 const Register cardtable = rax;
1706 const Register card_addr = rcx;
1707
1708 f.load_argument(0, card_addr);
1709 __ shrptr(card_addr, CardTableModRefBS::card_shift);
1710 // Do not use ExternalAddress to load 'byte_map_base', since 'byte_map_base' is NOT
1711 // a valid address and therefore is not properly handled by the relocation code.
1712 __ movptr(cardtable, (intptr_t)ct->byte_map_base);
1713 __ addptr(card_addr, cardtable);
1714
1715 NOT_LP64(__ get_thread(thread);)
1716
1717 __ cmpb(Address(card_addr, 0), (int)G1SATBCardTableModRefBS::g1_young_card_val());
1718 __ jcc(Assembler::equal, done);
1719
1720 __ membar(Assembler::Membar_mask_bits(Assembler::StoreLoad));
1721 __ cmpb(Address(card_addr, 0), (int)CardTableModRefBS::dirty_card_val());
1722 __ jcc(Assembler::equal, done);
1723
1724 // storing region crossing non-NULL, card is clean.
1725 // dirty card and log.
1726
1727 __ movb(Address(card_addr, 0), (int)CardTableModRefBS::dirty_card_val());
1728
1729 const Register tmp = rdx;
1730 __ push(rdx);
1731
1732 __ movptr(tmp, queue_index);
1733 __ testptr(tmp, tmp);
1734 __ jcc(Assembler::zero, runtime);
1735 __ subptr(tmp, wordSize);
1736 __ movptr(queue_index, tmp);
1737 __ addptr(tmp, buffer);
1738 __ movptr(Address(tmp, 0), card_addr);
1739 __ jmp(enqueued);
1740
1741 __ bind(runtime);
1742
1743 save_live_registers(sasm, 3);
1744
1745 __ call_VM_leaf(CAST_FROM_FN_PTR(address, SharedRuntime::g1_wb_post), card_addr, thread);
1746
1747 restore_live_registers(sasm);
1748
1749 __ bind(enqueued);
1750 __ pop(rdx);
1751
1752 __ bind(done);
1753 __ pop(rcx);
1754 __ pop(rax);
1755 }
1756 break;
1757 #endif // INCLUDE_ALL_GCS
1758
1759 case predicate_failed_trap_id:
1760 {
1761 StubFrame f(sasm, "predicate_failed_trap", dont_gc_arguments);
1762
1763 OopMap* map = save_live_registers(sasm, 1);
1764
1765 int call_offset = __ call_RT(noreg, noreg, CAST_FROM_FN_PTR(address, predicate_failed_trap));
1766 oop_maps = new OopMapSet();
1767 oop_maps->add_gc_map(call_offset, map);
1768 restore_live_registers(sasm);
1769 __ leave();
1770 DeoptimizationBlob* deopt_blob = SharedRuntime::deopt_blob();
1771 assert(deopt_blob != NULL, "deoptimization blob must have been created");
1772
1773 __ jump(RuntimeAddress(deopt_blob->unpack_with_reexecution()));
1774 }
1775 break;
1776
1777 default:
|
21 * questions.
22 *
23 */
24
25 #include "precompiled.hpp"
26 #include "asm/assembler.hpp"
27 #include "c1/c1_Defs.hpp"
28 #include "c1/c1_MacroAssembler.hpp"
29 #include "c1/c1_Runtime1.hpp"
30 #include "interpreter/interpreter.hpp"
31 #include "nativeInst_x86.hpp"
32 #include "oops/compiledICHolder.hpp"
33 #include "oops/oop.inline.hpp"
34 #include "prims/jvmtiExport.hpp"
35 #include "register_x86.hpp"
36 #include "runtime/sharedRuntime.hpp"
37 #include "runtime/signature.hpp"
38 #include "runtime/vframeArray.hpp"
39 #include "utilities/macros.hpp"
40 #include "vmreg_x86.inline.hpp"
41
42 // Implementation of StubAssembler
43
44 int StubAssembler::call_RT(Register oop_result1, Register metadata_result, address entry, int args_size) {
45 // setup registers
46 const Register thread = NOT_LP64(rdi) LP64_ONLY(r15_thread); // is callee-saved register (Visual C++ calling conventions)
47 assert(!(oop_result1->is_valid() || metadata_result->is_valid()) || oop_result1 != metadata_result, "registers must be different");
48 assert(oop_result1 != thread && metadata_result != thread, "registers must be different");
49 assert(args_size >= 0, "illegal args_size");
50 bool align_stack = false;
51 #ifdef _LP64
52 // At a method handle call, the stack may not be properly aligned
53 // when returning with an exception.
54 align_stack = (stub_id() == Runtime1::handle_exception_from_callee_id);
55 #endif
56
57 #ifdef _LP64
58 mov(c_rarg0, thread);
59 set_num_rt_args(0); // Nothing on stack
60 #else
186 push(arg2);
187 push(arg1);
188 #endif // _LP64
189 return call_RT(oop_result1, metadata_result, entry, 3);
190 }
191
192
193 // Implementation of StubFrame
194
195 class StubFrame: public StackObj {
196 private:
197 StubAssembler* _sasm;
198
199 public:
200 StubFrame(StubAssembler* sasm, const char* name, bool must_gc_arguments);
201 void load_argument(int offset_in_words, Register reg);
202
203 ~StubFrame();
204 };
205
206 void StubAssembler::prologue(const char* name, bool must_gc_arguments) {
207 set_info(name, must_gc_arguments);
208 enter();
209 }
210
211 void StubAssembler::epilogue() {
212 leave();
213 ret(0);
214 }
215
216 #define __ _sasm->
217
218 StubFrame::StubFrame(StubAssembler* sasm, const char* name, bool must_gc_arguments) {
219 _sasm = sasm;
220 __ prologue(name, must_gc_arguments);
221 }
222
223 // load parameters that were stored with LIR_Assembler::store_parameter
224 // Note: offsets for store_parameter and load_argument must match
225 void StubFrame::load_argument(int offset_in_words, Register reg) {
226 __ load_parameter(offset_in_words, reg);
227 }
228
229
230 StubFrame::~StubFrame() {
231 __ epilogue();
232 }
233
234 #undef __
235
236
237 // Implementation of Runtime1
238
239 const int float_regs_as_doubles_size_in_slots = pd_nof_fpu_regs_frame_map * 2;
240 const int xmm_regs_as_doubles_size_in_slots = FrameMap::nof_xmm_regs * 2;
241
242 // Stack layout for saving/restoring all the registers needed during a runtime
243 // call (this includes deoptimization)
244 // Note: note that users of this frame may well have arguments to some runtime
245 // while these values are on the stack. These positions neglect those arguments
246 // but the code in save_live_registers will take the argument count into
247 // account.
248 //
249 #ifdef _LP64
250 #define SLOT2(x) x,
251 #define SLOT_PER_WORD 2
252 #else
253 #define SLOT2(x)
254 #define SLOT_PER_WORD 1
255 #endif // _LP64
256
257 enum reg_save_layout {
258 // 64bit needs to keep stack 16 byte aligned. So we add some alignment dummies to make that
283 r11_off, r11H_off, // 392, 396
284 r10_off, r10H_off, // 400, 404
285 r9_off, r9H_off, // 408, 412
286 r8_off, r8H_off, // 416, 420
287 rdi_off, rdiH_off, // 424, 428
288 #else
289 rdi_off = extra_space_offset,
290 #endif // _LP64
291 rsi_off, SLOT2(rsiH_off) // 432, 436
292 rbp_off, SLOT2(rbpH_off) // 440, 444
293 rsp_off, SLOT2(rspH_off) // 448, 452
294 rbx_off, SLOT2(rbxH_off) // 456, 460
295 rdx_off, SLOT2(rdxH_off) // 464, 468
296 rcx_off, SLOT2(rcxH_off) // 472, 476
297 rax_off, SLOT2(raxH_off) // 480, 484
298 saved_rbp_off, SLOT2(saved_rbpH_off) // 488, 492
299 return_off, SLOT2(returnH_off) // 496, 500
300 reg_save_frame_size // As noted: neglects any parameters to runtime // 504
301 };
302
303 // Save off registers which might be killed by calls into the runtime.
304 // Tries to smart of about FP registers. In particular we separate
305 // saving and describing the FPU registers for deoptimization since we
306 // have to save the FPU registers twice if we describe them and on P4
307 // saving FPU registers which don't contain anything appears
308 // expensive. The deopt blob is the only thing which needs to
309 // describe FPU registers. In all other cases it should be sufficient
310 // to simply save their current value.
311
312 static OopMap* generate_oop_map(StubAssembler* sasm, int num_rt_args,
313 bool save_fpu_registers = true) {
314
315 // In 64bit all the args are in regs so there are no additional stack slots
316 LP64_ONLY(num_rt_args = 0);
317 LP64_ONLY(assert((reg_save_frame_size * VMRegImpl::stack_slot_size) % 16 == 0, "must be 16 byte aligned");)
318 int frame_size_in_slots = reg_save_frame_size + num_rt_args; // args + thread
319 sasm->set_frame_size(frame_size_in_slots / VMRegImpl::slots_per_word);
320
321 // record saved value locations in an OopMap
322 // locations are offsets from sp after runtime call; num_rt_args is number of arguments in call, including thread
389 }
390 }
391 xmm_off += 2;
392 }
393 assert(xmm_off == float_regs_as_doubles_off, "incorrect number of xmm registers");
394
395 } else if (UseSSE == 1) {
396 int xmm_off = xmm_regs_as_doubles_off;
397 for (int n = 0; n < FrameMap::nof_fpu_regs; n++) {
398 VMReg xmm_name_0 = as_XMMRegister(n)->as_VMReg();
399 map->set_callee_saved(VMRegImpl::stack2reg(xmm_off + num_rt_args), xmm_name_0);
400 xmm_off += 2;
401 }
402 assert(xmm_off == float_regs_as_doubles_off, "incorrect number of xmm registers");
403 }
404 }
405
406 return map;
407 }
408
409 #define __ this->
410
411 void C1_MacroAssembler::save_live_registers_no_oop_map(int num_rt_args, bool save_fpu_registers) {
412 __ block_comment("save_live_registers");
413
414 __ pusha(); // integer registers
415
416 // assert(float_regs_as_doubles_off % 2 == 0, "misaligned offset");
417 // assert(xmm_regs_as_doubles_off % 2 == 0, "misaligned offset");
418
419 __ subptr(rsp, extra_space_offset * VMRegImpl::stack_slot_size);
420
421 #ifdef ASSERT
422 __ movptr(Address(rsp, marker * VMRegImpl::stack_slot_size), (int32_t)0xfeedbeef);
423 #endif
424
425 if (save_fpu_registers) {
426 if (UseSSE < 2) {
427 // save FPU stack
428 __ fnsave(Address(rsp, fpu_state_off * VMRegImpl::stack_slot_size));
429 __ fwait();
430
431 #ifdef ASSERT
465 }
466 #endif
467 for (int n = 0; n < xmm_bypass_limit; n++) {
468 XMMRegister xmm_name = as_XMMRegister(n);
469 __ movdbl(Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + offset), xmm_name);
470 offset += 8;
471 }
472 } else if (UseSSE == 1) {
473 // save XMM registers as float because double not supported without SSE2(num MMX == num fpu)
474 int offset = 0;
475 for (int n = 0; n < FrameMap::nof_fpu_regs; n++) {
476 XMMRegister xmm_name = as_XMMRegister(n);
477 __ movflt(Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + offset), xmm_name);
478 offset += 8;
479 }
480 }
481 }
482
483 // FPU stack must be empty now
484 __ verify_FPU(0, "save_live_registers");
485 }
486
487 #undef __
488 #define __ sasm->
489
490 static void restore_fpu(C1_MacroAssembler* sasm, bool restore_fpu_registers) {
491 if (restore_fpu_registers) {
492 if (UseSSE >= 2) {
493 // restore XMM registers
494 int xmm_bypass_limit = FrameMap::nof_xmm_regs;
495 #ifdef _LP64
496 if (UseAVX < 3) {
497 xmm_bypass_limit = xmm_bypass_limit / 2;
498 }
499 #endif
500 int offset = 0;
501 for (int n = 0; n < xmm_bypass_limit; n++) {
502 XMMRegister xmm_name = as_XMMRegister(n);
503 __ movdbl(xmm_name, Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + offset));
504 offset += 8;
505 }
506 } else if (UseSSE == 1) {
507 // restore XMM registers(num MMX == num fpu)
508 int offset = 0;
509 for (int n = 0; n < FrameMap::nof_fpu_regs; n++) {
510 XMMRegister xmm_name = as_XMMRegister(n);
521 }
522
523 } else {
524 // check that FPU stack is really empty
525 __ verify_FPU(0, "restore_live_registers");
526 }
527
528 #ifdef ASSERT
529 {
530 Label ok;
531 __ cmpptr(Address(rsp, marker * VMRegImpl::stack_slot_size), (int32_t)0xfeedbeef);
532 __ jcc(Assembler::equal, ok);
533 __ stop("bad offsets in frame");
534 __ bind(ok);
535 }
536 #endif // ASSERT
537
538 __ addptr(rsp, extra_space_offset * VMRegImpl::stack_slot_size);
539 }
540
541 #undef __
542 #define __ this->
543
544 void C1_MacroAssembler::restore_live_registers(bool restore_fpu_registers) {
545 __ block_comment("restore_live_registers");
546
547 restore_fpu(this, restore_fpu_registers);
548 __ popa();
549 }
550
551 #undef __
552 #define __ sasm->
553
554 static OopMap* save_live_registers(StubAssembler* sasm, int num_rt_args,
555 bool save_fpu_registers = true) {
556 sasm->save_live_registers_no_oop_map(num_rt_args, save_fpu_registers);
557 return generate_oop_map(sasm, num_rt_args, save_fpu_registers);
558 }
559
560 static void restore_live_registers(StubAssembler* sasm, bool restore_fpu_registers = true) {
561 sasm->restore_live_registers(restore_fpu_registers);
562 }
563
564 static void restore_live_registers_except_rax(StubAssembler* sasm, bool restore_fpu_registers = true) {
565 __ block_comment("restore_live_registers_except_rax");
566
567 restore_fpu(sasm, restore_fpu_registers);
568
569 #ifdef _LP64
570 __ movptr(r15, Address(rsp, 0));
571 __ movptr(r14, Address(rsp, wordSize));
572 __ movptr(r13, Address(rsp, 2 * wordSize));
573 __ movptr(r12, Address(rsp, 3 * wordSize));
574 __ movptr(r11, Address(rsp, 4 * wordSize));
575 __ movptr(r10, Address(rsp, 5 * wordSize));
576 __ movptr(r9, Address(rsp, 6 * wordSize));
577 __ movptr(r8, Address(rsp, 7 * wordSize));
578 __ movptr(rdi, Address(rsp, 8 * wordSize));
579 __ movptr(rsi, Address(rsp, 9 * wordSize));
580 __ movptr(rbp, Address(rsp, 10 * wordSize));
581 // skip rsp
582 __ movptr(rbx, Address(rsp, 12 * wordSize));
1591 #endif // _LP64
1592 __ jmp(do_return);
1593
1594 __ bind(return0);
1595 __ fpop();
1596 #ifndef _LP64
1597 __ xorptr(rdx,rdx);
1598 __ xorptr(rax,rax);
1599 #else
1600 __ xorptr(rax, rax);
1601 #endif // _LP64
1602
1603 __ bind(do_return);
1604 __ addptr(rsp, 32);
1605 LP64_ONLY(__ pop(rdx);)
1606 __ pop(rcx);
1607 __ pop(rsi);
1608 __ ret(0);
1609 }
1610 break;
1611
1612 case predicate_failed_trap_id:
1613 {
1614 StubFrame f(sasm, "predicate_failed_trap", dont_gc_arguments);
1615
1616 OopMap* map = save_live_registers(sasm, 1);
1617
1618 int call_offset = __ call_RT(noreg, noreg, CAST_FROM_FN_PTR(address, predicate_failed_trap));
1619 oop_maps = new OopMapSet();
1620 oop_maps->add_gc_map(call_offset, map);
1621 restore_live_registers(sasm);
1622 __ leave();
1623 DeoptimizationBlob* deopt_blob = SharedRuntime::deopt_blob();
1624 assert(deopt_blob != NULL, "deoptimization blob must have been created");
1625
1626 __ jump(RuntimeAddress(deopt_blob->unpack_with_reexecution()));
1627 }
1628 break;
1629
1630 default:
|