comparison src/share/vm/c1/c1_CodeStubs.hpp @ 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 e4fee0bdaa85
children 09aad8452938
comparison
equal deleted inserted replaced
3248:e6beb62de02d 3249:e1162778c1c8
517 #ifndef SERIALGC 517 #ifndef SERIALGC
518 518
519 // Code stubs for Garbage-First barriers. 519 // Code stubs for Garbage-First barriers.
520 class G1PreBarrierStub: public CodeStub { 520 class G1PreBarrierStub: public CodeStub {
521 private: 521 private:
522 bool _do_load;
522 LIR_Opr _addr; 523 LIR_Opr _addr;
523 LIR_Opr _pre_val; 524 LIR_Opr _pre_val;
524 LIR_PatchCode _patch_code; 525 LIR_PatchCode _patch_code;
525 CodeEmitInfo* _info; 526 CodeEmitInfo* _info;
526 527
527 public: 528 public:
529 // Version that _does_ generate a load of the previous value from addr.
530 // addr (the address of the field to be read) must be a LIR_Address
528 // pre_val (a temporary register) must be a register; 531 // pre_val (a temporary register) must be a register;
529 // addr (the address of the field to be read) must be a LIR_Address
530 G1PreBarrierStub(LIR_Opr addr, LIR_Opr pre_val, LIR_PatchCode patch_code, CodeEmitInfo* info) : 532 G1PreBarrierStub(LIR_Opr addr, LIR_Opr pre_val, LIR_PatchCode patch_code, CodeEmitInfo* info) :
531 _addr(addr), _pre_val(pre_val), _patch_code(patch_code), _info(info) 533 _addr(addr), _pre_val(pre_val), _do_load(true),
534 _patch_code(patch_code), _info(info)
532 { 535 {
533 assert(_pre_val->is_register(), "should be temporary register"); 536 assert(_pre_val->is_register(), "should be temporary register");
534 assert(_addr->is_address(), "should be the address of the field"); 537 assert(_addr->is_address(), "should be the address of the field");
538 }
539
540 // Version that _does not_ generate load of the previous value; the
541 // previous value is assumed to have already been loaded into pre_val.
542 G1PreBarrierStub(LIR_Opr pre_val) :
543 _addr(LIR_OprFact::illegalOpr), _pre_val(pre_val), _do_load(false),
544 _patch_code(lir_patch_none), _info(NULL)
545 {
546 assert(_pre_val->is_register(), "should be a register");
535 } 547 }
536 548
537 LIR_Opr addr() const { return _addr; } 549 LIR_Opr addr() const { return _addr; }
538 LIR_Opr pre_val() const { return _pre_val; } 550 LIR_Opr pre_val() const { return _pre_val; }
539 LIR_PatchCode patch_code() const { return _patch_code; } 551 LIR_PatchCode patch_code() const { return _patch_code; }
540 CodeEmitInfo* info() const { return _info; } 552 CodeEmitInfo* info() const { return _info; }
541 553 bool do_load() const { return _do_load; }
542 virtual void emit_code(LIR_Assembler* e); 554
543 virtual void visit(LIR_OpVisitState* visitor) { 555 virtual void emit_code(LIR_Assembler* e);
544 // don't pass in the code emit info since it's processed in the fast 556 virtual void visit(LIR_OpVisitState* visitor) {
545 // path 557 if (_do_load) {
546 if (_info != NULL) 558 // don't pass in the code emit info since it's processed in the fast
547 visitor->do_slow_case(_info); 559 // path
548 else 560 if (_info != NULL)
561 visitor->do_slow_case(_info);
562 else
563 visitor->do_slow_case();
564
565 visitor->do_input(_addr);
566 visitor->do_temp(_pre_val);
567 } else {
549 visitor->do_slow_case(); 568 visitor->do_slow_case();
550 visitor->do_input(_addr); 569 visitor->do_input(_pre_val);
551 visitor->do_temp(_pre_val); 570 }
552 } 571 }
553 #ifndef PRODUCT 572 #ifndef PRODUCT
554 virtual void print_name(outputStream* out) const { out->print("G1PreBarrierStub"); } 573 virtual void print_name(outputStream* out) const { out->print("G1PreBarrierStub"); }
574 #endif // PRODUCT
575 };
576
577 // This G1 barrier code stub is used in Unsafe.getObject.
578 // It generates a sequence of guards around the SATB
579 // barrier code that are used to detect when we have
580 // the referent field of a Reference object.
581 // The first check is assumed to have been generated
582 // in the code generated for Unsafe.getObject().
583
584 class G1UnsafeGetObjSATBBarrierStub: public CodeStub {
585 private:
586 LIR_Opr _val;
587 LIR_Opr _src;
588
589 LIR_Opr _tmp;
590 LIR_Opr _thread;
591
592 bool _gen_src_check;
593
594 public:
595 // A G1 barrier that is guarded by generated guards that determine whether
596 // val (which is the result of Unsafe.getObject() should be recorded in an
597 // SATB log buffer. We could be reading the referent field of a Reference object
598 // using Unsafe.getObject() and we need to record the referent.
599 //
600 // * val is the operand returned by the unsafe.getObject routine.
601 // * src is the base object
602 // * tmp is a temp used to load the klass of src, and then reference type
603 // * thread is the thread object.
604
605 G1UnsafeGetObjSATBBarrierStub(LIR_Opr val, LIR_Opr src,
606 LIR_Opr tmp, LIR_Opr thread,
607 bool gen_src_check) :
608 _val(val), _src(src),
609 _tmp(tmp), _thread(thread),
610 _gen_src_check(gen_src_check)
611 {
612 assert(_val->is_register(), "should have already been loaded");
613 assert(_src->is_register(), "should have already been loaded");
614
615 assert(_tmp->is_register(), "should be a temporary register");
616 }
617
618 LIR_Opr val() const { return _val; }
619 LIR_Opr src() const { return _src; }
620
621 LIR_Opr tmp() const { return _tmp; }
622 LIR_Opr thread() const { return _thread; }
623
624 bool gen_src_check() const { return _gen_src_check; }
625
626 virtual void emit_code(LIR_Assembler* e);
627
628 virtual void visit(LIR_OpVisitState* visitor) {
629 visitor->do_slow_case();
630 visitor->do_input(_val);
631 visitor->do_input(_src);
632 visitor->do_input(_thread);
633
634 visitor->do_temp(_tmp);
635 }
636
637 #ifndef PRODUCT
638 virtual void print_name(outputStream* out) const { out->print("G1UnsafeGetObjSATBBarrierStub"); }
555 #endif // PRODUCT 639 #endif // PRODUCT
556 }; 640 };
557 641
558 class G1PostBarrierStub: public CodeStub { 642 class G1PostBarrierStub: public CodeStub {
559 private: 643 private: