210 void load_argument(int offset_in_words, Register reg); |
204 void load_argument(int offset_in_words, Register reg); |
211 |
205 |
212 ~StubFrame(); |
206 ~StubFrame(); |
213 }; |
207 }; |
214 |
208 |
|
209 void StubAssembler::prologue(const char* name, bool must_gc_arguments) { |
|
210 set_info(name, must_gc_arguments); |
|
211 enter(); |
|
212 } |
|
213 |
|
214 void StubAssembler::epilogue() { |
|
215 leave(); |
|
216 ret(0); |
|
217 } |
215 |
218 |
216 #define __ _sasm-> |
219 #define __ _sasm-> |
217 |
220 |
218 StubFrame::StubFrame(StubAssembler* sasm, const char* name, bool must_gc_arguments) { |
221 StubFrame::StubFrame(StubAssembler* sasm, const char* name, bool must_gc_arguments) { |
219 _sasm = sasm; |
222 _sasm = sasm; |
220 __ set_info(name, must_gc_arguments); |
223 __ prologue(name, must_gc_arguments); |
221 __ enter(); |
|
222 } |
224 } |
223 |
225 |
224 // load parameters that were stored with LIR_Assembler::store_parameter |
226 // load parameters that were stored with LIR_Assembler::store_parameter |
225 // Note: offsets for store_parameter and load_argument must match |
227 // Note: offsets for store_parameter and load_argument must match |
226 void StubFrame::load_argument(int offset_in_words, Register reg) { |
228 void StubFrame::load_argument(int offset_in_words, Register reg) { |
227 // rbp, + 0: link |
229 __ load_parameter(offset_in_words, reg); |
228 // + 1: return address |
|
229 // + 2: argument with offset 0 |
|
230 // + 3: argument with offset 1 |
|
231 // + 4: ... |
|
232 |
|
233 __ movptr(reg, Address(rbp, (offset_in_words + 2) * BytesPerWord)); |
|
234 } |
230 } |
235 |
231 |
236 |
232 |
237 StubFrame::~StubFrame() { |
233 StubFrame::~StubFrame() { |
238 __ leave(); |
234 __ epilogue(); |
239 __ ret(0); |
|
240 } |
235 } |
241 |
236 |
242 #undef __ |
237 #undef __ |
243 |
238 |
244 |
239 |
245 // Implementation of Runtime1 |
240 // Implementation of Runtime1 |
246 |
|
247 #define __ sasm-> |
|
248 |
241 |
249 const int float_regs_as_doubles_size_in_slots = pd_nof_fpu_regs_frame_map * 2; |
242 const int float_regs_as_doubles_size_in_slots = pd_nof_fpu_regs_frame_map * 2; |
250 const int xmm_regs_as_doubles_size_in_slots = FrameMap::nof_xmm_regs * 2; |
243 const int xmm_regs_as_doubles_size_in_slots = FrameMap::nof_xmm_regs * 2; |
251 |
244 |
252 // Stack layout for saving/restoring all the registers needed during a runtime |
245 // Stack layout for saving/restoring all the registers needed during a runtime |
547 #endif // ASSERT |
539 #endif // ASSERT |
548 |
540 |
549 __ addptr(rsp, extra_space_offset * VMRegImpl::stack_slot_size); |
541 __ addptr(rsp, extra_space_offset * VMRegImpl::stack_slot_size); |
550 } |
542 } |
551 |
543 |
|
544 #undef __ |
|
545 #define __ this-> |
|
546 |
|
547 void C1_MacroAssembler::restore_live_registers(bool restore_fpu_registers) { |
|
548 __ block_comment("restore_live_registers"); |
|
549 |
|
550 restore_fpu(this, restore_fpu_registers); |
|
551 __ popa(); |
|
552 } |
|
553 |
|
554 #undef __ |
|
555 #define __ sasm-> |
|
556 |
|
557 static OopMap* save_live_registers(StubAssembler* sasm, int num_rt_args, |
|
558 bool save_fpu_registers = true) { |
|
559 sasm->save_live_registers_no_oop_map(num_rt_args, save_fpu_registers); |
|
560 return generate_oop_map(sasm, num_rt_args, save_fpu_registers); |
|
561 } |
552 |
562 |
553 static void restore_live_registers(StubAssembler* sasm, bool restore_fpu_registers = true) { |
563 static void restore_live_registers(StubAssembler* sasm, bool restore_fpu_registers = true) { |
554 __ block_comment("restore_live_registers"); |
564 sasm->restore_live_registers(restore_fpu_registers); |
555 |
565 } |
556 restore_fpu(sasm, restore_fpu_registers); |
|
557 __ popa(); |
|
558 } |
|
559 |
|
560 |
566 |
561 static void restore_live_registers_except_rax(StubAssembler* sasm, bool restore_fpu_registers = true) { |
567 static void restore_live_registers_except_rax(StubAssembler* sasm, bool restore_fpu_registers = true) { |
562 __ block_comment("restore_live_registers_except_rax"); |
568 __ block_comment("restore_live_registers_except_rax"); |
563 |
569 |
564 restore_fpu(sasm, restore_fpu_registers); |
570 restore_fpu(sasm, restore_fpu_registers); |
1555 __ pop(rsi); |
1561 __ pop(rsi); |
1556 __ ret(0); |
1562 __ ret(0); |
1557 } |
1563 } |
1558 break; |
1564 break; |
1559 |
1565 |
1560 #if INCLUDE_ALL_GCS |
|
1561 case g1_pre_barrier_slow_id: |
|
1562 { |
|
1563 StubFrame f(sasm, "g1_pre_barrier", dont_gc_arguments); |
|
1564 // arg0 : previous value of memory |
|
1565 |
|
1566 BarrierSet* bs = BarrierSet::barrier_set(); |
|
1567 if (bs->kind() != BarrierSet::G1BarrierSet) { |
|
1568 __ movptr(rax, (int)id); |
|
1569 __ call_RT(noreg, noreg, CAST_FROM_FN_PTR(address, unimplemented_entry), rax); |
|
1570 __ should_not_reach_here(); |
|
1571 break; |
|
1572 } |
|
1573 __ push(rax); |
|
1574 __ push(rdx); |
|
1575 |
|
1576 const Register pre_val = rax; |
|
1577 const Register thread = NOT_LP64(rax) LP64_ONLY(r15_thread); |
|
1578 const Register tmp = rdx; |
|
1579 |
|
1580 NOT_LP64(__ get_thread(thread);) |
|
1581 |
|
1582 Address queue_active(thread, in_bytes(G1ThreadLocalData::satb_mark_queue_active_offset())); |
|
1583 Address queue_index(thread, in_bytes(G1ThreadLocalData::satb_mark_queue_index_offset())); |
|
1584 Address buffer(thread, in_bytes(G1ThreadLocalData::satb_mark_queue_buffer_offset())); |
|
1585 |
|
1586 Label done; |
|
1587 Label runtime; |
|
1588 |
|
1589 // Is marking still active? |
|
1590 if (in_bytes(SATBMarkQueue::byte_width_of_active()) == 4) { |
|
1591 __ cmpl(queue_active, 0); |
|
1592 } else { |
|
1593 assert(in_bytes(SATBMarkQueue::byte_width_of_active()) == 1, "Assumption"); |
|
1594 __ cmpb(queue_active, 0); |
|
1595 } |
|
1596 __ jcc(Assembler::equal, done); |
|
1597 |
|
1598 // Can we store original value in the thread's buffer? |
|
1599 |
|
1600 __ movptr(tmp, queue_index); |
|
1601 __ testptr(tmp, tmp); |
|
1602 __ jcc(Assembler::zero, runtime); |
|
1603 __ subptr(tmp, wordSize); |
|
1604 __ movptr(queue_index, tmp); |
|
1605 __ addptr(tmp, buffer); |
|
1606 |
|
1607 // prev_val (rax) |
|
1608 f.load_argument(0, pre_val); |
|
1609 __ movptr(Address(tmp, 0), pre_val); |
|
1610 __ jmp(done); |
|
1611 |
|
1612 __ bind(runtime); |
|
1613 |
|
1614 save_live_registers(sasm, 3); |
|
1615 |
|
1616 // load the pre-value |
|
1617 f.load_argument(0, rcx); |
|
1618 __ call_VM_leaf(CAST_FROM_FN_PTR(address, SharedRuntime::g1_wb_pre), rcx, thread); |
|
1619 |
|
1620 restore_live_registers(sasm); |
|
1621 |
|
1622 __ bind(done); |
|
1623 |
|
1624 __ pop(rdx); |
|
1625 __ pop(rax); |
|
1626 } |
|
1627 break; |
|
1628 |
|
1629 case g1_post_barrier_slow_id: |
|
1630 { |
|
1631 StubFrame f(sasm, "g1_post_barrier", dont_gc_arguments); |
|
1632 |
|
1633 BarrierSet* bs = BarrierSet::barrier_set(); |
|
1634 if (bs->kind() != BarrierSet::G1BarrierSet) { |
|
1635 __ movptr(rax, (int)id); |
|
1636 __ call_RT(noreg, noreg, CAST_FROM_FN_PTR(address, unimplemented_entry), rax); |
|
1637 __ should_not_reach_here(); |
|
1638 break; |
|
1639 } |
|
1640 |
|
1641 // arg0: store_address |
|
1642 Address store_addr(rbp, 2*BytesPerWord); |
|
1643 |
|
1644 Label done; |
|
1645 Label enqueued; |
|
1646 Label runtime; |
|
1647 |
|
1648 // At this point we know new_value is non-NULL and the new_value crosses regions. |
|
1649 // Must check to see if card is already dirty |
|
1650 |
|
1651 const Register thread = NOT_LP64(rax) LP64_ONLY(r15_thread); |
|
1652 |
|
1653 Address queue_index(thread, in_bytes(G1ThreadLocalData::dirty_card_queue_index_offset())); |
|
1654 Address buffer(thread, in_bytes(G1ThreadLocalData::dirty_card_queue_buffer_offset())); |
|
1655 |
|
1656 __ push(rax); |
|
1657 __ push(rcx); |
|
1658 |
|
1659 const Register cardtable = rax; |
|
1660 const Register card_addr = rcx; |
|
1661 |
|
1662 f.load_argument(0, card_addr); |
|
1663 __ shrptr(card_addr, CardTable::card_shift); |
|
1664 // Do not use ExternalAddress to load 'byte_map_base', since 'byte_map_base' is NOT |
|
1665 // a valid address and therefore is not properly handled by the relocation code. |
|
1666 __ movptr(cardtable, ci_card_table_address_as<intptr_t>()); |
|
1667 __ addptr(card_addr, cardtable); |
|
1668 |
|
1669 NOT_LP64(__ get_thread(thread);) |
|
1670 |
|
1671 __ cmpb(Address(card_addr, 0), (int)G1CardTable::g1_young_card_val()); |
|
1672 __ jcc(Assembler::equal, done); |
|
1673 |
|
1674 __ membar(Assembler::Membar_mask_bits(Assembler::StoreLoad)); |
|
1675 __ cmpb(Address(card_addr, 0), (int)CardTable::dirty_card_val()); |
|
1676 __ jcc(Assembler::equal, done); |
|
1677 |
|
1678 // storing region crossing non-NULL, card is clean. |
|
1679 // dirty card and log. |
|
1680 |
|
1681 __ movb(Address(card_addr, 0), (int)CardTable::dirty_card_val()); |
|
1682 |
|
1683 const Register tmp = rdx; |
|
1684 __ push(rdx); |
|
1685 |
|
1686 __ movptr(tmp, queue_index); |
|
1687 __ testptr(tmp, tmp); |
|
1688 __ jcc(Assembler::zero, runtime); |
|
1689 __ subptr(tmp, wordSize); |
|
1690 __ movptr(queue_index, tmp); |
|
1691 __ addptr(tmp, buffer); |
|
1692 __ movptr(Address(tmp, 0), card_addr); |
|
1693 __ jmp(enqueued); |
|
1694 |
|
1695 __ bind(runtime); |
|
1696 |
|
1697 save_live_registers(sasm, 3); |
|
1698 |
|
1699 __ call_VM_leaf(CAST_FROM_FN_PTR(address, SharedRuntime::g1_wb_post), card_addr, thread); |
|
1700 |
|
1701 restore_live_registers(sasm); |
|
1702 |
|
1703 __ bind(enqueued); |
|
1704 __ pop(rdx); |
|
1705 |
|
1706 __ bind(done); |
|
1707 __ pop(rcx); |
|
1708 __ pop(rax); |
|
1709 } |
|
1710 break; |
|
1711 #endif // INCLUDE_ALL_GCS |
|
1712 |
|
1713 case predicate_failed_trap_id: |
1566 case predicate_failed_trap_id: |
1714 { |
1567 { |
1715 StubFrame f(sasm, "predicate_failed_trap", dont_gc_arguments); |
1568 StubFrame f(sasm, "predicate_failed_trap", dont_gc_arguments); |
1716 |
1569 |
1717 OopMap* map = save_live_registers(sasm, 1); |
1570 OopMap* map = save_live_registers(sasm, 1); |