Mercurial > hg > graal-jvmci-8
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: |