Mercurial > hg > graal-jvmci-8
comparison src/cpu/x86/vm/c1_CodeStubs_x86.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 |
---|---|
462 | 462 |
463 ///////////////////////////////////////////////////////////////////////////// | 463 ///////////////////////////////////////////////////////////////////////////// |
464 #ifndef SERIALGC | 464 #ifndef SERIALGC |
465 | 465 |
466 void G1PreBarrierStub::emit_code(LIR_Assembler* ce) { | 466 void G1PreBarrierStub::emit_code(LIR_Assembler* ce) { |
467 | 467 // At this point we know that marking is in progress. |
468 // At this point we know that marking is in progress | 468 // If do_load() is true then we have to emit the |
469 // load of the previous value; otherwise it has already | |
470 // been loaded into _pre_val. | |
469 | 471 |
470 __ bind(_entry); | 472 __ bind(_entry); |
471 assert(pre_val()->is_register(), "Precondition."); | 473 assert(pre_val()->is_register(), "Precondition."); |
472 | 474 |
473 Register pre_val_reg = pre_val()->as_register(); | 475 Register pre_val_reg = pre_val()->as_register(); |
474 | 476 |
475 ce->mem2reg(addr(), pre_val(), T_OBJECT, patch_code(), info(), false /*wide*/, false /*unaligned*/); | 477 if (do_load()) { |
478 ce->mem2reg(addr(), pre_val(), T_OBJECT, patch_code(), info(), false /*wide*/, false /*unaligned*/); | |
479 } | |
476 | 480 |
477 __ cmpptr(pre_val_reg, (int32_t) NULL_WORD); | 481 __ cmpptr(pre_val_reg, (int32_t) NULL_WORD); |
478 __ jcc(Assembler::equal, _continuation); | 482 __ jcc(Assembler::equal, _continuation); |
479 ce->store_parameter(pre_val()->as_register(), 0); | 483 ce->store_parameter(pre_val()->as_register(), 0); |
480 __ call(RuntimeAddress(Runtime1::entry_for(Runtime1::g1_pre_barrier_slow_id))); | 484 __ call(RuntimeAddress(Runtime1::entry_for(Runtime1::g1_pre_barrier_slow_id))); |
481 __ jmp(_continuation); | 485 __ jmp(_continuation); |
482 | 486 |
487 } | |
488 | |
489 void G1UnsafeGetObjSATBBarrierStub::emit_code(LIR_Assembler* ce) { | |
490 // At this point we know that offset == referent_offset. | |
491 // | |
492 // So we might have to emit: | |
493 // if (src == null) goto continuation. | |
494 // | |
495 // and we definitely have to emit: | |
496 // if (klass(src).reference_type == REF_NONE) goto continuation | |
497 // if (!marking_active) goto continuation | |
498 // if (pre_val == null) goto continuation | |
499 // call pre_barrier(pre_val) | |
500 // goto continuation | |
501 // | |
502 __ bind(_entry); | |
503 | |
504 assert(src()->is_register(), "sanity"); | |
505 Register src_reg = src()->as_register(); | |
506 | |
507 if (gen_src_check()) { | |
508 // The original src operand was not a constant. | |
509 // Generate src == null? | |
510 __ cmpptr(src_reg, (int32_t) NULL_WORD); | |
511 __ jcc(Assembler::equal, _continuation); | |
512 } | |
513 | |
514 // Generate src->_klass->_reference_type == REF_NONE)? | |
515 assert(tmp()->is_register(), "sanity"); | |
516 Register tmp_reg = tmp()->as_register(); | |
517 | |
518 __ load_klass(tmp_reg, src_reg); | |
519 | |
520 Address ref_type_adr(tmp_reg, instanceKlass::reference_type_offset_in_bytes() + sizeof(oopDesc)); | |
521 __ cmpl(ref_type_adr, REF_NONE); | |
522 __ jcc(Assembler::equal, _continuation); | |
523 | |
524 // Is marking active? | |
525 assert(thread()->is_register(), "precondition"); | |
526 Register thread_reg = thread()->as_register(); | |
527 | |
528 Address in_progress(thread_reg, in_bytes(JavaThread::satb_mark_queue_offset() + | |
529 PtrQueue::byte_offset_of_active())); | |
530 | |
531 if (in_bytes(PtrQueue::byte_width_of_active()) == 4) { | |
532 __ cmpl(in_progress, 0); | |
533 } else { | |
534 assert(in_bytes(PtrQueue::byte_width_of_active()) == 1, "Assumption"); | |
535 __ cmpb(in_progress, 0); | |
536 } | |
537 __ jcc(Assembler::equal, _continuation); | |
538 | |
539 // val == null? | |
540 assert(val()->is_register(), "Precondition."); | |
541 Register val_reg = val()->as_register(); | |
542 | |
543 __ cmpptr(val_reg, (int32_t) NULL_WORD); | |
544 __ jcc(Assembler::equal, _continuation); | |
545 | |
546 ce->store_parameter(val()->as_register(), 0); | |
547 __ call(RuntimeAddress(Runtime1::entry_for(Runtime1::g1_pre_barrier_slow_id))); | |
548 __ jmp(_continuation); | |
483 } | 549 } |
484 | 550 |
485 jbyte* G1PostBarrierStub::_byte_map_base = NULL; | 551 jbyte* G1PostBarrierStub::_byte_map_base = NULL; |
486 | 552 |
487 jbyte* G1PostBarrierStub::byte_map_base_slow() { | 553 jbyte* G1PostBarrierStub::byte_map_base_slow() { |