Mercurial > hg > graal-jvmci-8
comparison src/cpu/sparc/vm/templateInterpreter_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 | dd031b2226de |
children | 2e038ad0c1d0 |
comparison
equal
deleted
inserted
replaced
3248:e6beb62de02d | 3249:e1162778c1c8 |
---|---|
759 __ bind(slow_path); | 759 __ bind(slow_path); |
760 (void) generate_normal_entry(false); | 760 (void) generate_normal_entry(false); |
761 return entry; | 761 return entry; |
762 } | 762 } |
763 return NULL; | 763 return NULL; |
764 } | |
765 | |
766 // Method entry for java.lang.ref.Reference.get. | |
767 address InterpreterGenerator::generate_Reference_get_entry(void) { | |
768 #ifndef SERIALGC | |
769 // Code: _aload_0, _getfield, _areturn | |
770 // parameter size = 1 | |
771 // | |
772 // The code that gets generated by this routine is split into 2 parts: | |
773 // 1. The "intrinsified" code for G1 (or any SATB based GC), | |
774 // 2. The slow path - which is an expansion of the regular method entry. | |
775 // | |
776 // Notes:- | |
777 // * In the G1 code we do not check whether we need to block for | |
778 // a safepoint. If G1 is enabled then we must execute the specialized | |
779 // code for Reference.get (except when the Reference object is null) | |
780 // so that we can log the value in the referent field with an SATB | |
781 // update buffer. | |
782 // If the code for the getfield template is modified so that the | |
783 // G1 pre-barrier code is executed when the current method is | |
784 // Reference.get() then going through the normal method entry | |
785 // will be fine. | |
786 // * The G1 code can, however, check the receiver object (the instance | |
787 // of java.lang.Reference) and jump to the slow path if null. If the | |
788 // Reference object is null then we obviously cannot fetch the referent | |
789 // and so we don't need to call the G1 pre-barrier. Thus we can use the | |
790 // regular method entry code to generate the NPE. | |
791 // | |
792 // This code is based on generate_accessor_enty. | |
793 | |
794 address entry = __ pc(); | |
795 | |
796 const int referent_offset = java_lang_ref_Reference::referent_offset; | |
797 guarantee(referent_offset > 0, "referent offset not initialized"); | |
798 | |
799 if (UseG1GC) { | |
800 Label slow_path; | |
801 | |
802 // In the G1 code we don't check if we need to reach a safepoint. We | |
803 // continue and the thread will safepoint at the next bytecode dispatch. | |
804 | |
805 // Check if local 0 != NULL | |
806 // If the receiver is null then it is OK to jump to the slow path. | |
807 __ ld_ptr(Gargs, G0, Otos_i ); // get local 0 | |
808 __ tst(Otos_i); // check if local 0 == NULL and go the slow path | |
809 __ brx(Assembler::zero, false, Assembler::pn, slow_path); | |
810 __ delayed()->nop(); | |
811 | |
812 | |
813 // Load the value of the referent field. | |
814 if (Assembler::is_simm13(referent_offset)) { | |
815 __ load_heap_oop(Otos_i, referent_offset, Otos_i); | |
816 } else { | |
817 __ set(referent_offset, G3_scratch); | |
818 __ load_heap_oop(Otos_i, G3_scratch, Otos_i); | |
819 } | |
820 | |
821 // Generate the G1 pre-barrier code to log the value of | |
822 // the referent field in an SATB buffer. Note with | |
823 // these parameters the pre-barrier does not generate | |
824 // the load of the previous value | |
825 | |
826 __ g1_write_barrier_pre(noreg /* obj */, noreg /* index */, 0 /* offset */, | |
827 Otos_i /* pre_val */, | |
828 G3_scratch /* tmp */, | |
829 true /* preserve_o_regs */); | |
830 | |
831 // _areturn | |
832 __ retl(); // return from leaf routine | |
833 __ delayed()->mov(O5_savedSP, SP); | |
834 | |
835 // Generate regular method entry | |
836 __ bind(slow_path); | |
837 (void) generate_normal_entry(false); | |
838 return entry; | |
839 } | |
840 #endif // SERIALGC | |
841 | |
842 // If G1 is not enabled then attempt to go through the accessor entry point | |
843 // Reference.get is an accessor | |
844 return generate_accessor_entry(); | |
764 } | 845 } |
765 | 846 |
766 // | 847 // |
767 // Interpreter stub for calling a native method. (asm interpreter) | 848 // Interpreter stub for calling a native method. (asm interpreter) |
768 // This sets up a somewhat different looking stack for calling the native method | 849 // This sets up a somewhat different looking stack for calling the native method |