Mercurial > hg > graal-jvmci-8
comparison src/cpu/x86/vm/templateInterpreter_x86_32.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 | 638119ce7cfd |
children | 92add02409c9 |
comparison
equal
deleted
inserted
replaced
3248:e6beb62de02d | 3249:e1162778c1c8 |
---|---|
774 } | 774 } |
775 return NULL; | 775 return NULL; |
776 | 776 |
777 } | 777 } |
778 | 778 |
779 // Method entry for java.lang.ref.Reference.get. | |
780 address InterpreterGenerator::generate_Reference_get_entry(void) { | |
781 #ifndef SERIALGC | |
782 // Code: _aload_0, _getfield, _areturn | |
783 // parameter size = 1 | |
784 // | |
785 // The code that gets generated by this routine is split into 2 parts: | |
786 // 1. The "intrinsified" code for G1 (or any SATB based GC), | |
787 // 2. The slow path - which is an expansion of the regular method entry. | |
788 // | |
789 // Notes:- | |
790 // * In the G1 code we do not check whether we need to block for | |
791 // a safepoint. If G1 is enabled then we must execute the specialized | |
792 // code for Reference.get (except when the Reference object is null) | |
793 // so that we can log the value in the referent field with an SATB | |
794 // update buffer. | |
795 // If the code for the getfield template is modified so that the | |
796 // G1 pre-barrier code is executed when the current method is | |
797 // Reference.get() then going through the normal method entry | |
798 // will be fine. | |
799 // * The G1 code below can, however, check the receiver object (the instance | |
800 // of java.lang.Reference) and jump to the slow path if null. If the | |
801 // Reference object is null then we obviously cannot fetch the referent | |
802 // and so we don't need to call the G1 pre-barrier. Thus we can use the | |
803 // regular method entry code to generate the NPE. | |
804 // | |
805 // This code is based on generate_accessor_enty. | |
806 | |
807 // rbx,: methodOop | |
808 // rcx: receiver (preserve for slow entry into asm interpreter) | |
809 | |
810 // rsi: senderSP must preserved for slow path, set SP to it on fast path | |
811 | |
812 address entry = __ pc(); | |
813 | |
814 const int referent_offset = java_lang_ref_Reference::referent_offset; | |
815 guarantee(referent_offset > 0, "referent offset not initialized"); | |
816 | |
817 if (UseG1GC) { | |
818 Label slow_path; | |
819 | |
820 // Check if local 0 != NULL | |
821 // If the receiver is null then it is OK to jump to the slow path. | |
822 __ movptr(rax, Address(rsp, wordSize)); | |
823 __ testptr(rax, rax); | |
824 __ jcc(Assembler::zero, slow_path); | |
825 | |
826 // rax: local 0 (must be preserved across the G1 barrier call) | |
827 // | |
828 // rbx: method (at this point it's scratch) | |
829 // rcx: receiver (at this point it's scratch) | |
830 // rdx: scratch | |
831 // rdi: scratch | |
832 // | |
833 // rsi: sender sp | |
834 | |
835 // Preserve the sender sp in case the pre-barrier | |
836 // calls the runtime | |
837 __ push(rsi); | |
838 | |
839 // Load the value of the referent field. | |
840 const Address field_address(rax, referent_offset); | |
841 __ movptr(rax, field_address); | |
842 | |
843 // Generate the G1 pre-barrier code to log the value of | |
844 // the referent field in an SATB buffer. | |
845 __ get_thread(rcx); | |
846 __ g1_write_barrier_pre(noreg /* obj */, | |
847 rax /* pre_val */, | |
848 rcx /* thread */, | |
849 rbx /* tmp */, | |
850 true /* tosca_save */, | |
851 true /* expand_call */); | |
852 | |
853 // _areturn | |
854 __ pop(rsi); // get sender sp | |
855 __ pop(rdi); // get return address | |
856 __ mov(rsp, rsi); // set sp to sender sp | |
857 __ jmp(rdi); | |
858 | |
859 __ bind(slow_path); | |
860 (void) generate_normal_entry(false); | |
861 | |
862 return entry; | |
863 } | |
864 #endif // SERIALGC | |
865 | |
866 // If G1 is not enabled then attempt to go through the accessor entry point | |
867 // Reference.get is an accessor | |
868 return generate_accessor_entry(); | |
869 } | |
870 | |
779 // | 871 // |
780 // Interpreter stub for calling a native method. (asm interpreter) | 872 // Interpreter stub for calling a native method. (asm interpreter) |
781 // This sets up a somewhat different looking stack for calling the native method | 873 // This sets up a somewhat different looking stack for calling the native method |
782 // than the typical interpreter frame setup. | 874 // than the typical interpreter frame setup. |
783 // | 875 // |
1442 case Interpreter::java_lang_math_tan : // fall thru | 1534 case Interpreter::java_lang_math_tan : // fall thru |
1443 case Interpreter::java_lang_math_abs : // fall thru | 1535 case Interpreter::java_lang_math_abs : // fall thru |
1444 case Interpreter::java_lang_math_log : // fall thru | 1536 case Interpreter::java_lang_math_log : // fall thru |
1445 case Interpreter::java_lang_math_log10 : // fall thru | 1537 case Interpreter::java_lang_math_log10 : // fall thru |
1446 case Interpreter::java_lang_math_sqrt : entry_point = ((InterpreterGenerator*)this)->generate_math_entry(kind); break; | 1538 case Interpreter::java_lang_math_sqrt : entry_point = ((InterpreterGenerator*)this)->generate_math_entry(kind); break; |
1539 case Interpreter::java_lang_ref_reference_get | |
1540 : entry_point = ((InterpreterGenerator*)this)->generate_Reference_get_entry(); break; | |
1447 default : ShouldNotReachHere(); break; | 1541 default : ShouldNotReachHere(); break; |
1448 } | 1542 } |
1449 | 1543 |
1450 if (entry_point) return entry_point; | 1544 if (entry_point) return entry_point; |
1451 | 1545 |