< prev index next >

src/hotspot/cpu/x86/gc/g1/g1BarrierSetAssembler_x86.cpp

Print this page

108     assert_different_registers(c_rarg0, count);
109     __ mov(c_rarg0, addr);
110     __ mov(c_rarg1, count);
111   }
112   __ call_VM_leaf(CAST_FROM_FN_PTR(address, G1BarrierSetRuntime::write_ref_array_post_entry), 2);
113 #else
114   __ call_VM_leaf(CAST_FROM_FN_PTR(address, G1BarrierSetRuntime::write_ref_array_post_entry),
115                   addr, count);
116 #endif
117   __ popa();
118 }
119 
120 void G1BarrierSetAssembler::load_at(MacroAssembler* masm, DecoratorSet decorators, BasicType type,
121                                     Register dst, Address src, Register tmp1, Register tmp_thread) {
122   bool on_oop = is_reference_type(type);
123   bool on_weak = (decorators & ON_WEAK_OOP_REF) != 0;
124   bool on_phantom = (decorators & ON_PHANTOM_OOP_REF) != 0;
125   bool on_reference = on_weak || on_phantom;
126   ModRefBarrierSetAssembler::load_at(masm, decorators, type, dst, src, tmp1, tmp_thread);
127   if (on_oop && on_reference) {
128     const Register thread = NOT_LP64(tmp_thread) LP64_ONLY(r15_thread);
129     NOT_LP64(__ get_thread(thread));
















130 
131     // Generate the G1 pre-barrier code to log the value of
132     // the referent field in an SATB buffer.
133     g1_write_barrier_pre(masm /* masm */,
134                          noreg /* obj */,
135                          dst /* pre_val */,
136                          thread /* thread */,
137                          tmp1 /* tmp */,
138                          true /* tosca_live */,
139                          true /* expand_call */);




140   }
141 }
142 
143 void G1BarrierSetAssembler::g1_write_barrier_pre(MacroAssembler* masm,
144                                                  Register obj,
145                                                  Register pre_val,
146                                                  Register thread,
147                                                  Register tmp,
148                                                  bool tosca_live,
149                                                  bool expand_call) {
150   // If expand_call is true then we expand the call_VM_leaf macro
151   // directly to skip generating the check by
152   // InterpreterMacroAssembler::call_VM_leaf_base that checks _last_sp.
153 
154 #ifdef _LP64
155   assert(thread == r15_thread, "must be");
156 #endif // _LP64
157 
158   Label done;
159   Label runtime;

187   __ cmpptr(pre_val, (int32_t) NULL_WORD);
188   __ jcc(Assembler::equal, done);
189 
190   // Can we store original value in the thread's buffer?
191   // Is index == 0?
192   // (The index field is typed as size_t.)
193 
194   __ movptr(tmp, index);                   // tmp := *index_adr
195   __ cmpptr(tmp, 0);                       // tmp == 0?
196   __ jcc(Assembler::equal, runtime);       // If yes, goto runtime
197 
198   __ subptr(tmp, wordSize);                // tmp := tmp - wordSize
199   __ movptr(index, tmp);                   // *index_adr := tmp
200   __ addptr(tmp, buffer);                  // tmp := tmp + *buffer_adr
201 
202   // Record the previous value
203   __ movptr(Address(tmp, 0), pre_val);
204   __ jmp(done);
205 
206   __ bind(runtime);
207   // save the live input values
208   if(tosca_live) __ push(rax);
209 
210   if (obj != noreg && obj != rax)
211     __ push(obj);
212 
213   if (pre_val != rax)
214     __ push(pre_val);
215 
216   // Calling the runtime using the regular call_VM_leaf mechanism generates
217   // code (generated by InterpreterMacroAssember::call_VM_leaf_base)
218   // that checks that the *(ebp+frame::interpreter_frame_last_sp) == NULL.
219   //
220   // If we care generating the pre-barrier without a frame (e.g. in the
221   // intrinsified Reference.get() routine) then ebp might be pointing to
222   // the caller frame and so this check will most likely fail at runtime.
223   //
224   // Expanding the call directly bypasses the generation of the check.
225   // So when we do not have have a full interpreter frame on the stack
226   // expand_call should be passed true.
227 
228   NOT_LP64( __ push(thread); )
229 
230   if (expand_call) {
231     LP64_ONLY( assert(pre_val != c_rarg1, "smashed arg"); )
232 #ifdef _LP64
233     if (c_rarg1 != thread) {
234       __ mov(c_rarg1, thread);
235     }
236     if (c_rarg0 != pre_val) {
237       __ mov(c_rarg0, pre_val);
238     }
239 #else
240     __ push(thread);
241     __ push(pre_val);
242 #endif
243     __ MacroAssembler::call_VM_leaf_base(CAST_FROM_FN_PTR(address, G1BarrierSetRuntime::write_ref_field_pre_entry), 2);
244   } else {
245     __ call_VM_leaf(CAST_FROM_FN_PTR(address, G1BarrierSetRuntime::write_ref_field_pre_entry), pre_val, thread);
246   }
247 
248   NOT_LP64( __ pop(thread); )
249 
250   // save the live input values
251   if (pre_val != rax)
252     __ pop(pre_val);
253 
254   if (obj != noreg && obj != rax)
255     __ pop(obj);
256 
257   if(tosca_live) __ pop(rax);
258 
259   __ bind(done);
260 }
261 
262 void G1BarrierSetAssembler::g1_write_barrier_post(MacroAssembler* masm,
263                                                   Register store_addr,
264                                                   Register new_val,
265                                                   Register thread,
266                                                   Register tmp,
267                                                   Register tmp2) {
268   // Generated code assumes that buffer index is pointer sized.
269   STATIC_ASSERT(in_bytes(SATBMarkQueue::byte_width_of_index()) == sizeof(intptr_t));
270 #ifdef _LP64
271   assert(thread == r15_thread, "must be");
272 #endif // _LP64
273 
274   Address queue_index(thread, in_bytes(G1ThreadLocalData::dirty_card_queue_index_offset()));
275   Address buffer(thread, in_bytes(G1ThreadLocalData::dirty_card_queue_buffer_offset()));
276 
277   CardTableBarrierSet* ct =

328 
329   __ bind(runtime);
330   // save the live input values
331   __ push(store_addr);
332 #ifdef _LP64
333   __ call_VM_leaf(CAST_FROM_FN_PTR(address, G1BarrierSetRuntime::write_ref_field_post_entry), card_addr, r15_thread);
334 #else
335   __ push(thread);
336   __ call_VM_leaf(CAST_FROM_FN_PTR(address, G1BarrierSetRuntime::write_ref_field_post_entry), card_addr, thread);
337   __ pop(thread);
338 #endif
339   __ pop(store_addr);
340 
341   __ bind(done);
342 }
343 
344 void G1BarrierSetAssembler::oop_store_at(MacroAssembler* masm, DecoratorSet decorators, BasicType type,
345                                          Address dst, Register val, Register tmp1, Register tmp2) {
346   bool in_heap = (decorators & IN_HEAP) != 0;
347   bool as_normal = (decorators & AS_NORMAL) != 0;
348   assert((decorators & IS_DEST_UNINITIALIZED) == 0, "unsupported");
349 
350   bool needs_pre_barrier = as_normal;
351   bool needs_post_barrier = val != noreg && in_heap;
352 
353   Register tmp3 = LP64_ONLY(r8) NOT_LP64(rsi);
354   Register rthread = LP64_ONLY(r15_thread) NOT_LP64(rcx);
355   // flatten object address if needed
356   // We do it regardless of precise because we need the registers
357   if (dst.index() == noreg && dst.disp() == 0) {
358     if (dst.base() != tmp1) {
359       __ movptr(tmp1, dst.base());
360     }
361   } else {
362     __ lea(tmp1, dst);
363   }
364 
365 #ifndef _LP64
366   InterpreterMacroAssembler *imasm = static_cast<InterpreterMacroAssembler*>(masm);
367 #endif
368 
369   NOT_LP64(__ get_thread(rcx));
370   NOT_LP64(imasm->save_bcp());

108     assert_different_registers(c_rarg0, count);
109     __ mov(c_rarg0, addr);
110     __ mov(c_rarg1, count);
111   }
112   __ call_VM_leaf(CAST_FROM_FN_PTR(address, G1BarrierSetRuntime::write_ref_array_post_entry), 2);
113 #else
114   __ call_VM_leaf(CAST_FROM_FN_PTR(address, G1BarrierSetRuntime::write_ref_array_post_entry),
115                   addr, count);
116 #endif
117   __ popa();
118 }
119 
120 void G1BarrierSetAssembler::load_at(MacroAssembler* masm, DecoratorSet decorators, BasicType type,
121                                     Register dst, Address src, Register tmp1, Register tmp_thread) {
122   bool on_oop = is_reference_type(type);
123   bool on_weak = (decorators & ON_WEAK_OOP_REF) != 0;
124   bool on_phantom = (decorators & ON_PHANTOM_OOP_REF) != 0;
125   bool on_reference = on_weak || on_phantom;
126   ModRefBarrierSetAssembler::load_at(masm, decorators, type, dst, src, tmp1, tmp_thread);
127   if (on_oop && on_reference) {
128     Register thread = NOT_LP64(tmp_thread) LP64_ONLY(r15_thread);
129 
130 #ifndef _LP64
131     // Work around the x86_32 bug that only manifests with Loom for some reason.
132     // MacroAssembler::resolve_weak_handle calls this barrier with tmp_thread == noreg.
133     if (thread == noreg) {
134       if (dst != rcx && tmp1 != rcx) {
135         thread = rcx;
136       } else if (dst != rdx && tmp1 != rdx) {
137         thread = rdx;
138       } else if (dst != rdi && tmp1 != rdi) {
139         thread = rdi;
140       }
141     }
142     assert_different_registers(dst, tmp1, thread);
143     __ push(thread);
144     __ get_thread(thread);
145 #endif
146 
147     // Generate the G1 pre-barrier code to log the value of
148     // the referent field in an SATB buffer.
149     g1_write_barrier_pre(masm /* masm */,
150                          noreg /* obj */,
151                          dst /* pre_val */,
152                          thread /* thread */,
153                          tmp1 /* tmp */,
154                          true /* tosca_live */,
155                          true /* expand_call */);
156 
157 #ifndef _LP64
158     __ pop(thread);
159 #endif
160   }
161 }
162 
163 void G1BarrierSetAssembler::g1_write_barrier_pre(MacroAssembler* masm,
164                                                  Register obj,
165                                                  Register pre_val,
166                                                  Register thread,
167                                                  Register tmp,
168                                                  bool tosca_live,
169                                                  bool expand_call) {
170   // If expand_call is true then we expand the call_VM_leaf macro
171   // directly to skip generating the check by
172   // InterpreterMacroAssembler::call_VM_leaf_base that checks _last_sp.
173 
174 #ifdef _LP64
175   assert(thread == r15_thread, "must be");
176 #endif // _LP64
177 
178   Label done;
179   Label runtime;

207   __ cmpptr(pre_val, (int32_t) NULL_WORD);
208   __ jcc(Assembler::equal, done);
209 
210   // Can we store original value in the thread's buffer?
211   // Is index == 0?
212   // (The index field is typed as size_t.)
213 
214   __ movptr(tmp, index);                   // tmp := *index_adr
215   __ cmpptr(tmp, 0);                       // tmp == 0?
216   __ jcc(Assembler::equal, runtime);       // If yes, goto runtime
217 
218   __ subptr(tmp, wordSize);                // tmp := tmp - wordSize
219   __ movptr(index, tmp);                   // *index_adr := tmp
220   __ addptr(tmp, buffer);                  // tmp := tmp + *buffer_adr
221 
222   // Record the previous value
223   __ movptr(Address(tmp, 0), pre_val);
224   __ jmp(done);
225 
226   __ bind(runtime);








227 
228   // Calling the runtime using the regular call_VM_leaf mechanism generates
229   // code (generated by InterpreterMacroAssember::call_VM_leaf_base)
230   // that checks that the *(ebp+frame::interpreter_frame_last_sp) == NULL.
231   //
232   // If we care generating the pre-barrier without a frame (e.g. in the
233   // intrinsified Reference.get() routine) then ebp might be pointing to
234   // the caller frame and so this check will most likely fail at runtime.
235   //
236   // Expanding the call directly bypasses the generation of the check.
237   // So when we do not have have a full interpreter frame on the stack
238   // expand_call should be passed true.
239 
240   __ pusha();
241 
242   if (expand_call) {
243     LP64_ONLY( assert(pre_val != c_rarg1, "smashed arg"); )
244 #ifdef _LP64
245     if (c_rarg1 != thread) {
246       __ mov(c_rarg1, thread);
247     }
248     if (c_rarg0 != pre_val) {
249       __ mov(c_rarg0, pre_val);
250     }
251 #else
252     __ push(thread);
253     __ push(pre_val);
254 #endif
255     __ MacroAssembler::call_VM_leaf_base(CAST_FROM_FN_PTR(address, G1BarrierSetRuntime::write_ref_field_pre_entry), 2);
256   } else {
257     __ call_VM_leaf(CAST_FROM_FN_PTR(address, G1BarrierSetRuntime::write_ref_field_pre_entry), pre_val, thread);
258   }
259 
260   __ popa();









261 
262   __ bind(done);
263 }
264 
265 void G1BarrierSetAssembler::g1_write_barrier_post(MacroAssembler* masm,
266                                                   Register store_addr,
267                                                   Register new_val,
268                                                   Register thread,
269                                                   Register tmp,
270                                                   Register tmp2) {
271   // Generated code assumes that buffer index is pointer sized.
272   STATIC_ASSERT(in_bytes(SATBMarkQueue::byte_width_of_index()) == sizeof(intptr_t));
273 #ifdef _LP64
274   assert(thread == r15_thread, "must be");
275 #endif // _LP64
276 
277   Address queue_index(thread, in_bytes(G1ThreadLocalData::dirty_card_queue_index_offset()));
278   Address buffer(thread, in_bytes(G1ThreadLocalData::dirty_card_queue_buffer_offset()));
279 
280   CardTableBarrierSet* ct =

331 
332   __ bind(runtime);
333   // save the live input values
334   __ push(store_addr);
335 #ifdef _LP64
336   __ call_VM_leaf(CAST_FROM_FN_PTR(address, G1BarrierSetRuntime::write_ref_field_post_entry), card_addr, r15_thread);
337 #else
338   __ push(thread);
339   __ call_VM_leaf(CAST_FROM_FN_PTR(address, G1BarrierSetRuntime::write_ref_field_post_entry), card_addr, thread);
340   __ pop(thread);
341 #endif
342   __ pop(store_addr);
343 
344   __ bind(done);
345 }
346 
347 void G1BarrierSetAssembler::oop_store_at(MacroAssembler* masm, DecoratorSet decorators, BasicType type,
348                                          Address dst, Register val, Register tmp1, Register tmp2) {
349   bool in_heap = (decorators & IN_HEAP) != 0;
350   bool as_normal = (decorators & AS_NORMAL) != 0;
351   //assert((decorators & IS_DEST_UNINITIALIZED) == 0, "unsupported");
352 
353   bool needs_pre_barrier = as_normal && (! (decorators & IS_DEST_UNINITIALIZED) );
354   bool needs_post_barrier = val != noreg && in_heap;
355 
356   Register tmp3 = LP64_ONLY(r8) NOT_LP64(rsi);
357   Register rthread = LP64_ONLY(r15_thread) NOT_LP64(rcx);
358   // flatten object address if needed
359   // We do it regardless of precise because we need the registers
360   if (dst.index() == noreg && dst.disp() == 0) {
361     if (dst.base() != tmp1) {
362       __ movptr(tmp1, dst.base());
363     }
364   } else {
365     __ lea(tmp1, dst);
366   }
367 
368 #ifndef _LP64
369   InterpreterMacroAssembler *imasm = static_cast<InterpreterMacroAssembler*>(masm);
370 #endif
371 
372   NOT_LP64(__ get_thread(rcx));
373   NOT_LP64(imasm->save_bcp());
< prev index next >