22 * |
22 * |
23 */ |
23 */ |
24 |
24 |
25 #include "precompiled.hpp" |
25 #include "precompiled.hpp" |
26 #include "gc/shared/barrierSetAssembler.hpp" |
26 #include "gc/shared/barrierSetAssembler.hpp" |
|
27 #include "gc/shared/collectedHeap.hpp" |
27 #include "interpreter/interp_masm.hpp" |
28 #include "interpreter/interp_masm.hpp" |
28 #include "runtime/jniHandles.hpp" |
29 #include "runtime/jniHandles.hpp" |
|
30 #include "runtime/thread.hpp" |
29 |
31 |
30 #define __ masm-> |
32 #define __ masm-> |
31 |
33 |
32 void BarrierSetAssembler::load_at(MacroAssembler* masm, DecoratorSet decorators, BasicType type, |
34 void BarrierSetAssembler::load_at(MacroAssembler* masm, DecoratorSet decorators, BasicType type, |
33 Register dst, Address src, Register tmp1, Register tmp_thread) { |
35 Register dst, Address src, Register tmp1, Register tmp_thread) { |
211 void BarrierSetAssembler::try_resolve_jobject_in_native(MacroAssembler* masm, Register jni_env, |
213 void BarrierSetAssembler::try_resolve_jobject_in_native(MacroAssembler* masm, Register jni_env, |
212 Register obj, Register tmp, Label& slowpath) { |
214 Register obj, Register tmp, Label& slowpath) { |
213 __ clear_jweak_tag(obj); |
215 __ clear_jweak_tag(obj); |
214 __ movptr(obj, Address(obj, 0)); |
216 __ movptr(obj, Address(obj, 0)); |
215 } |
217 } |
|
218 |
|
219 void BarrierSetAssembler::tlab_allocate(MacroAssembler* masm, |
|
220 Register thread, Register obj, |
|
221 Register var_size_in_bytes, |
|
222 int con_size_in_bytes, |
|
223 Register t1, |
|
224 Register t2, |
|
225 Label& slow_case) { |
|
226 assert_different_registers(obj, t1, t2); |
|
227 assert_different_registers(obj, var_size_in_bytes, t1); |
|
228 Register end = t2; |
|
229 if (!thread->is_valid()) { |
|
230 #ifdef _LP64 |
|
231 thread = r15_thread; |
|
232 #else |
|
233 assert(t1->is_valid(), "need temp reg"); |
|
234 thread = t1; |
|
235 __ get_thread(thread); |
|
236 #endif |
|
237 } |
|
238 |
|
239 __ verify_tlab(); |
|
240 |
|
241 __ movptr(obj, Address(thread, JavaThread::tlab_top_offset())); |
|
242 if (var_size_in_bytes == noreg) { |
|
243 __ lea(end, Address(obj, con_size_in_bytes)); |
|
244 } else { |
|
245 __ lea(end, Address(obj, var_size_in_bytes, Address::times_1)); |
|
246 } |
|
247 __ cmpptr(end, Address(thread, JavaThread::tlab_end_offset())); |
|
248 __ jcc(Assembler::above, slow_case); |
|
249 |
|
250 // update the tlab top pointer |
|
251 __ movptr(Address(thread, JavaThread::tlab_top_offset()), end); |
|
252 |
|
253 // recover var_size_in_bytes if necessary |
|
254 if (var_size_in_bytes == end) { |
|
255 __ subptr(var_size_in_bytes, obj); |
|
256 } |
|
257 __ verify_tlab(); |
|
258 } |
|
259 |
|
260 // Defines obj, preserves var_size_in_bytes |
|
261 void BarrierSetAssembler::eden_allocate(MacroAssembler* masm, |
|
262 Register thread, Register obj, |
|
263 Register var_size_in_bytes, |
|
264 int con_size_in_bytes, |
|
265 Register t1, |
|
266 Label& slow_case) { |
|
267 assert(obj == rax, "obj must be in rax, for cmpxchg"); |
|
268 assert_different_registers(obj, var_size_in_bytes, t1); |
|
269 if (!Universe::heap()->supports_inline_contig_alloc()) { |
|
270 __ jmp(slow_case); |
|
271 } else { |
|
272 Register end = t1; |
|
273 Label retry; |
|
274 __ bind(retry); |
|
275 ExternalAddress heap_top((address) Universe::heap()->top_addr()); |
|
276 __ movptr(obj, heap_top); |
|
277 if (var_size_in_bytes == noreg) { |
|
278 __ lea(end, Address(obj, con_size_in_bytes)); |
|
279 } else { |
|
280 __ lea(end, Address(obj, var_size_in_bytes, Address::times_1)); |
|
281 } |
|
282 // if end < obj then we wrapped around => object too long => slow case |
|
283 __ cmpptr(end, obj); |
|
284 __ jcc(Assembler::below, slow_case); |
|
285 __ cmpptr(end, ExternalAddress((address) Universe::heap()->end_addr())); |
|
286 __ jcc(Assembler::above, slow_case); |
|
287 // Compare obj with the top addr, and if still equal, store the new top addr in |
|
288 // end at the address of the top addr pointer. Sets ZF if was equal, and clears |
|
289 // it otherwise. Use lock prefix for atomicity on MPs. |
|
290 __ locked_cmpxchgptr(end, heap_top); |
|
291 __ jcc(Assembler::notEqual, retry); |
|
292 incr_allocated_bytes(masm, thread, var_size_in_bytes, con_size_in_bytes, thread->is_valid() ? noreg : t1); |
|
293 } |
|
294 } |
|
295 |
|
296 void BarrierSetAssembler::incr_allocated_bytes(MacroAssembler* masm, Register thread, |
|
297 Register var_size_in_bytes, |
|
298 int con_size_in_bytes, |
|
299 Register t1) { |
|
300 if (!thread->is_valid()) { |
|
301 #ifdef _LP64 |
|
302 thread = r15_thread; |
|
303 #else |
|
304 assert(t1->is_valid(), "need temp reg"); |
|
305 thread = t1; |
|
306 __ get_thread(thread); |
|
307 #endif |
|
308 } |
|
309 |
|
310 #ifdef _LP64 |
|
311 if (var_size_in_bytes->is_valid()) { |
|
312 __ addq(Address(thread, in_bytes(JavaThread::allocated_bytes_offset())), var_size_in_bytes); |
|
313 } else { |
|
314 __ addq(Address(thread, in_bytes(JavaThread::allocated_bytes_offset())), con_size_in_bytes); |
|
315 } |
|
316 #else |
|
317 if (var_size_in_bytes->is_valid()) { |
|
318 __ addl(Address(thread, in_bytes(JavaThread::allocated_bytes_offset())), var_size_in_bytes); |
|
319 } else { |
|
320 __ addl(Address(thread, in_bytes(JavaThread::allocated_bytes_offset())), con_size_in_bytes); |
|
321 } |
|
322 __ adcl(Address(thread, in_bytes(JavaThread::allocated_bytes_offset())+4), 0); |
|
323 #endif |
|
324 } |