1.1 --- a/src/cpu/sparc/vm/c1_Runtime1_sparc.cpp Wed Jun 04 13:51:09 2008 -0700 1.2 +++ b/src/cpu/sparc/vm/c1_Runtime1_sparc.cpp Thu Jun 05 15:57:56 2008 -0700 1.3 @@ -832,6 +832,163 @@ 1.4 } 1.5 break; 1.6 1.7 +#ifndef SERIALGC 1.8 + case g1_pre_barrier_slow_id: 1.9 + { // G4: previous value of memory 1.10 + BarrierSet* bs = Universe::heap()->barrier_set(); 1.11 + if (bs->kind() != BarrierSet::G1SATBCTLogging) { 1.12 + __ save_frame(0); 1.13 + __ set((int)id, O1); 1.14 + __ call_RT(noreg, noreg, CAST_FROM_FN_PTR(address, unimplemented_entry), I0); 1.15 + __ should_not_reach_here(); 1.16 + break; 1.17 + } 1.18 + 1.19 + __ set_info("g1_pre_barrier_slow_id", dont_gc_arguments); 1.20 + 1.21 + Register pre_val = G4; 1.22 + Register tmp = G1_scratch; 1.23 + Register tmp2 = G3_scratch; 1.24 + 1.25 + Label refill, restart; 1.26 + bool with_frame = false; // I don't know if we can do with-frame. 1.27 + int satb_q_index_byte_offset = 1.28 + in_bytes(JavaThread::satb_mark_queue_offset() + 1.29 + PtrQueue::byte_offset_of_index()); 1.30 + int satb_q_buf_byte_offset = 1.31 + in_bytes(JavaThread::satb_mark_queue_offset() + 1.32 + PtrQueue::byte_offset_of_buf()); 1.33 + __ bind(restart); 1.34 + __ ld_ptr(G2_thread, satb_q_index_byte_offset, tmp); 1.35 + 1.36 + __ br_on_reg_cond(Assembler::rc_z, /*annul*/false, 1.37 + Assembler::pn, tmp, refill); 1.38 + 1.39 + // If the branch is taken, no harm in executing this in the delay slot. 1.40 + __ delayed()->ld_ptr(G2_thread, satb_q_buf_byte_offset, tmp2); 1.41 + __ sub(tmp, oopSize, tmp); 1.42 + 1.43 + __ st_ptr(pre_val, tmp2, tmp); // [_buf + index] := <address_of_card> 1.44 + // Use return-from-leaf 1.45 + __ retl(); 1.46 + __ delayed()->st_ptr(tmp, G2_thread, satb_q_index_byte_offset); 1.47 + 1.48 + __ bind(refill); 1.49 + __ save_frame(0); 1.50 + 1.51 + __ mov(pre_val, L0); 1.52 + __ mov(tmp, L1); 1.53 + __ mov(tmp2, L2); 1.54 + 1.55 + __ call_VM_leaf(L7_thread_cache, 1.56 + CAST_FROM_FN_PTR(address, 1.57 + SATBMarkQueueSet::handle_zero_index_for_thread), 1.58 + G2_thread); 1.59 + 1.60 + __ mov(L0, pre_val); 1.61 + __ mov(L1, tmp); 1.62 + __ mov(L2, tmp2); 1.63 + 1.64 + __ br(Assembler::always, /*annul*/false, Assembler::pt, restart); 1.65 + __ delayed()->restore(); 1.66 + } 1.67 + break; 1.68 + 1.69 + case g1_post_barrier_slow_id: 1.70 + { 1.71 + BarrierSet* bs = Universe::heap()->barrier_set(); 1.72 + if (bs->kind() != BarrierSet::G1SATBCTLogging) { 1.73 + __ save_frame(0); 1.74 + __ set((int)id, O1); 1.75 + __ call_RT(noreg, noreg, CAST_FROM_FN_PTR(address, unimplemented_entry), I0); 1.76 + __ should_not_reach_here(); 1.77 + break; 1.78 + } 1.79 + 1.80 + __ set_info("g1_post_barrier_slow_id", dont_gc_arguments); 1.81 + 1.82 + Register addr = G4; 1.83 + Register cardtable = G5; 1.84 + Register tmp = G1_scratch; 1.85 + Register tmp2 = G3_scratch; 1.86 + jbyte* byte_map_base = ((CardTableModRefBS*)bs)->byte_map_base; 1.87 + 1.88 + Label not_already_dirty, restart, refill; 1.89 + 1.90 +#ifdef _LP64 1.91 + __ srlx(addr, CardTableModRefBS::card_shift, addr); 1.92 +#else 1.93 + __ srl(addr, CardTableModRefBS::card_shift, addr); 1.94 +#endif 1.95 + 1.96 + Address rs(cardtable, (address)byte_map_base); 1.97 + __ load_address(rs); // cardtable := <card table base> 1.98 + __ ldub(addr, cardtable, tmp); // tmp := [addr + cardtable] 1.99 + 1.100 + __ br_on_reg_cond(Assembler::rc_nz, /*annul*/false, Assembler::pt, 1.101 + tmp, not_already_dirty); 1.102 + // Get cardtable + tmp into a reg by itself -- useful in the take-the-branch 1.103 + // case, harmless if not. 1.104 + __ delayed()->add(addr, cardtable, tmp2); 1.105 + 1.106 + // We didn't take the branch, so we're already dirty: return. 1.107 + // Use return-from-leaf 1.108 + __ retl(); 1.109 + __ delayed()->nop(); 1.110 + 1.111 + // Not dirty. 1.112 + __ bind(not_already_dirty); 1.113 + // First, dirty it. 1.114 + __ stb(G0, tmp2, 0); // [cardPtr] := 0 (i.e., dirty). 1.115 + 1.116 + Register tmp3 = cardtable; 1.117 + Register tmp4 = tmp; 1.118 + 1.119 + // these registers are now dead 1.120 + addr = cardtable = tmp = noreg; 1.121 + 1.122 + int dirty_card_q_index_byte_offset = 1.123 + in_bytes(JavaThread::dirty_card_queue_offset() + 1.124 + PtrQueue::byte_offset_of_index()); 1.125 + int dirty_card_q_buf_byte_offset = 1.126 + in_bytes(JavaThread::dirty_card_queue_offset() + 1.127 + PtrQueue::byte_offset_of_buf()); 1.128 + __ bind(restart); 1.129 + __ ld_ptr(G2_thread, dirty_card_q_index_byte_offset, tmp3); 1.130 + 1.131 + __ br_on_reg_cond(Assembler::rc_z, /*annul*/false, Assembler::pn, 1.132 + tmp3, refill); 1.133 + // If the branch is taken, no harm in executing this in the delay slot. 1.134 + __ delayed()->ld_ptr(G2_thread, dirty_card_q_buf_byte_offset, tmp4); 1.135 + __ sub(tmp3, oopSize, tmp3); 1.136 + 1.137 + __ st_ptr(tmp2, tmp4, tmp3); // [_buf + index] := <address_of_card> 1.138 + // Use return-from-leaf 1.139 + __ retl(); 1.140 + __ delayed()->st_ptr(tmp3, G2_thread, dirty_card_q_index_byte_offset); 1.141 + 1.142 + __ bind(refill); 1.143 + __ save_frame(0); 1.144 + 1.145 + __ mov(tmp2, L0); 1.146 + __ mov(tmp3, L1); 1.147 + __ mov(tmp4, L2); 1.148 + 1.149 + __ call_VM_leaf(L7_thread_cache, 1.150 + CAST_FROM_FN_PTR(address, 1.151 + DirtyCardQueueSet::handle_zero_index_for_thread), 1.152 + G2_thread); 1.153 + 1.154 + __ mov(L0, tmp2); 1.155 + __ mov(L1, tmp3); 1.156 + __ mov(L2, tmp4); 1.157 + 1.158 + __ br(Assembler::always, /*annul*/false, Assembler::pt, restart); 1.159 + __ delayed()->restore(); 1.160 + } 1.161 + break; 1.162 +#endif // !SERIALGC 1.163 + 1.164 default: 1.165 { __ set_info("unimplemented entry", dont_gc_arguments); 1.166 __ save_frame(0);