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