Mercurial > hg > truffle
comparison src/cpu/sparc/vm/c1_CodeStubs_sparc.cpp @ 3249:e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
Summary: A referent object that is only weakly reachable at the start of concurrent marking but is re-attached to the strongly reachable object graph during marking may not be marked as live. This can cause the reference object to be processed prematurely and leave dangling pointers to the referent object. Implement a read barrier for the java.lang.ref.Reference::referent field by intrinsifying the Reference.get() method, and intercepting accesses though JNI, reflection, and Unsafe, so that when a non-null referent object is read it is also logged in an SATB buffer.
Reviewed-by: kvn, iveresov, never, tonyp, dholmes
author | johnc |
---|---|
date | Thu, 07 Apr 2011 09:53:20 -0700 |
parents | 32f7097f9d8f |
children | 59766fd005ff |
comparison
equal
deleted
inserted
replaced
3248:e6beb62de02d | 3249:e1162778c1c8 |
---|---|
406 | 406 |
407 /////////////////////////////////////////////////////////////////////////////////// | 407 /////////////////////////////////////////////////////////////////////////////////// |
408 #ifndef SERIALGC | 408 #ifndef SERIALGC |
409 | 409 |
410 void G1PreBarrierStub::emit_code(LIR_Assembler* ce) { | 410 void G1PreBarrierStub::emit_code(LIR_Assembler* ce) { |
411 // At this point we know that marking is in progress. | |
412 // If do_load() is true then we have to emit the | |
413 // load of the previous value; otherwise it has already | |
414 // been loaded into _pre_val. | |
415 | |
411 __ bind(_entry); | 416 __ bind(_entry); |
412 | 417 |
413 assert(pre_val()->is_register(), "Precondition."); | 418 assert(pre_val()->is_register(), "Precondition."); |
414 | |
415 Register pre_val_reg = pre_val()->as_register(); | 419 Register pre_val_reg = pre_val()->as_register(); |
416 | 420 |
417 ce->mem2reg(addr(), pre_val(), T_OBJECT, patch_code(), info(), false /*wide*/, false /*unaligned*/); | 421 if (do_load()) { |
422 ce->mem2reg(addr(), pre_val(), T_OBJECT, patch_code(), info(), false /*wide*/, false /*unaligned*/); | |
423 } | |
424 | |
418 if (__ is_in_wdisp16_range(_continuation)) { | 425 if (__ is_in_wdisp16_range(_continuation)) { |
419 __ br_on_reg_cond(Assembler::rc_z, /*annul*/false, Assembler::pt, | 426 __ br_on_reg_cond(Assembler::rc_z, /*annul*/false, Assembler::pt, |
420 pre_val_reg, _continuation); | 427 pre_val_reg, _continuation); |
421 } else { | 428 } else { |
422 __ cmp(pre_val_reg, G0); | 429 __ cmp(pre_val_reg, G0); |
427 __ call(Runtime1::entry_for(Runtime1::Runtime1::g1_pre_barrier_slow_id)); | 434 __ call(Runtime1::entry_for(Runtime1::Runtime1::g1_pre_barrier_slow_id)); |
428 __ delayed()->mov(pre_val_reg, G4); | 435 __ delayed()->mov(pre_val_reg, G4); |
429 __ br(Assembler::always, false, Assembler::pt, _continuation); | 436 __ br(Assembler::always, false, Assembler::pt, _continuation); |
430 __ delayed()->nop(); | 437 __ delayed()->nop(); |
431 | 438 |
439 } | |
440 | |
441 void G1UnsafeGetObjSATBBarrierStub::emit_code(LIR_Assembler* ce) { | |
442 // At this point we know that offset == referent_offset. | |
443 // | |
444 // So we might have to emit: | |
445 // if (src == null) goto continuation. | |
446 // | |
447 // and we definitely have to emit: | |
448 // if (klass(src).reference_type == REF_NONE) goto continuation | |
449 // if (!marking_active) goto continuation | |
450 // if (pre_val == null) goto continuation | |
451 // call pre_barrier(pre_val) | |
452 // goto continuation | |
453 // | |
454 __ bind(_entry); | |
455 | |
456 assert(src()->is_register(), "sanity"); | |
457 Register src_reg = src()->as_register(); | |
458 | |
459 if (gen_src_check()) { | |
460 // The original src operand was not a constant. | |
461 // Generate src == null? | |
462 if (__ is_in_wdisp16_range(_continuation)) { | |
463 __ br_on_reg_cond(Assembler::rc_z, /*annul*/false, Assembler::pt, | |
464 src_reg, _continuation); | |
465 } else { | |
466 __ cmp(src_reg, G0); | |
467 __ brx(Assembler::equal, false, Assembler::pt, _continuation); | |
468 } | |
469 __ delayed()->nop(); | |
470 } | |
471 | |
472 // Generate src->_klass->_reference_type() == REF_NONE)? | |
473 assert(tmp()->is_register(), "sanity"); | |
474 Register tmp_reg = tmp()->as_register(); | |
475 | |
476 __ load_klass(src_reg, tmp_reg); | |
477 | |
478 Address ref_type_adr(tmp_reg, instanceKlass::reference_type_offset_in_bytes() + sizeof(oopDesc)); | |
479 __ ld(ref_type_adr, tmp_reg); | |
480 | |
481 if (__ is_in_wdisp16_range(_continuation)) { | |
482 __ br_on_reg_cond(Assembler::rc_z, /*annul*/false, Assembler::pt, | |
483 tmp_reg, _continuation); | |
484 } else { | |
485 __ cmp(tmp_reg, G0); | |
486 __ brx(Assembler::equal, false, Assembler::pt, _continuation); | |
487 } | |
488 __ delayed()->nop(); | |
489 | |
490 // Is marking active? | |
491 assert(thread()->is_register(), "precondition"); | |
492 Register thread_reg = thread()->as_register(); | |
493 | |
494 Address in_progress(thread_reg, in_bytes(JavaThread::satb_mark_queue_offset() + | |
495 PtrQueue::byte_offset_of_active())); | |
496 | |
497 if (in_bytes(PtrQueue::byte_width_of_active()) == 4) { | |
498 __ ld(in_progress, tmp_reg); | |
499 } else { | |
500 assert(in_bytes(PtrQueue::byte_width_of_active()) == 1, "Assumption"); | |
501 __ ldsb(in_progress, tmp_reg); | |
502 } | |
503 if (__ is_in_wdisp16_range(_continuation)) { | |
504 __ br_on_reg_cond(Assembler::rc_z, /*annul*/false, Assembler::pt, | |
505 tmp_reg, _continuation); | |
506 } else { | |
507 __ cmp(tmp_reg, G0); | |
508 __ brx(Assembler::equal, false, Assembler::pt, _continuation); | |
509 } | |
510 __ delayed()->nop(); | |
511 | |
512 // val == null? | |
513 assert(val()->is_register(), "Precondition."); | |
514 Register val_reg = val()->as_register(); | |
515 | |
516 if (__ is_in_wdisp16_range(_continuation)) { | |
517 __ br_on_reg_cond(Assembler::rc_z, /*annul*/false, Assembler::pt, | |
518 val_reg, _continuation); | |
519 } else { | |
520 __ cmp(val_reg, G0); | |
521 __ brx(Assembler::equal, false, Assembler::pt, _continuation); | |
522 } | |
523 __ delayed()->nop(); | |
524 | |
525 __ call(Runtime1::entry_for(Runtime1::Runtime1::g1_pre_barrier_slow_id)); | |
526 __ delayed()->mov(val_reg, G4); | |
527 __ br(Assembler::always, false, Assembler::pt, _continuation); | |
528 __ delayed()->nop(); | |
432 } | 529 } |
433 | 530 |
434 jbyte* G1PostBarrierStub::_byte_map_base = NULL; | 531 jbyte* G1PostBarrierStub::_byte_map_base = NULL; |
435 | 532 |
436 jbyte* G1PostBarrierStub::byte_map_base_slow() { | 533 jbyte* G1PostBarrierStub::byte_map_base_slow() { |