Thu, 07 Apr 2011 09:53:20 -0700
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
1 /*
2 * Copyright (c) 1998, 2010, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation.
8 *
9 * This code is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12 * version 2 for more details (a copy is included in the LICENSE file that
13 * accompanied this code).
14 *
15 * You should have received a copy of the GNU General Public License version
16 * 2 along with this work; if not, write to the Free Software Foundation,
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18 *
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20 * or visit www.oracle.com if you need additional information or have any
21 * questions.
22 *
23 */
25 #include "precompiled.hpp"
26 #ifdef COMPILER2
27 #include "asm/assembler.hpp"
28 #include "assembler_sparc.inline.hpp"
29 #include "classfile/systemDictionary.hpp"
30 #include "code/vmreg.hpp"
31 #include "interpreter/interpreter.hpp"
32 #include "nativeInst_sparc.hpp"
33 #include "opto/runtime.hpp"
34 #include "runtime/interfaceSupport.hpp"
35 #include "runtime/sharedRuntime.hpp"
36 #include "runtime/stubRoutines.hpp"
37 #include "runtime/vframeArray.hpp"
38 #include "utilities/globalDefinitions.hpp"
39 #include "vmreg_sparc.inline.hpp"
40 #endif
43 #define __ masm->
45 ExceptionBlob *OptoRuntime::_exception_blob;
47 //------------------------------ generate_exception_blob ---------------------------
48 // creates exception blob at the end
49 // Using exception blob, this code is jumped from a compiled method.
50 // (see emit_exception_handler in sparc.ad file)
51 //
52 // Given an exception pc at a call we call into the runtime for the
53 // handler in this method. This handler might merely restore state
54 // (i.e. callee save registers) unwind the frame and jump to the
55 // exception handler for the nmethod if there is no Java level handler
56 // for the nmethod.
57 //
58 // This code is entered with a jmp.
59 //
60 // Arguments:
61 // O0: exception oop
62 // O1: exception pc
63 //
64 // Results:
65 // O0: exception oop
66 // O1: exception pc in caller or ???
67 // destination: exception handler of caller
68 //
69 // Note: the exception pc MUST be at a call (precise debug information)
70 //
71 void OptoRuntime::generate_exception_blob() {
72 // allocate space for code
73 ResourceMark rm;
74 int pad = VerifyThread ? 256 : 0;// Extra slop space for more verify code
76 // setup code generation tools
77 // Measured 8/7/03 at 256 in 32bit debug build (no VerifyThread)
78 // Measured 8/7/03 at 528 in 32bit debug build (VerifyThread)
79 CodeBuffer buffer("exception_blob", 600+pad, 512);
80 MacroAssembler* masm = new MacroAssembler(&buffer);
82 int framesize_in_bytes = __ total_frame_size_in_bytes(0);
83 int framesize_in_words = framesize_in_bytes / wordSize;
84 int framesize_in_slots = framesize_in_bytes / sizeof(jint);
86 Label L;
88 int start = __ offset();
90 __ verify_thread();
91 __ st_ptr(Oexception, G2_thread, JavaThread::exception_oop_offset());
92 __ st_ptr(Oissuing_pc, G2_thread, JavaThread::exception_pc_offset());
94 // This call does all the hard work. It checks if an exception catch
95 // exists in the method.
96 // If so, it returns the handler address.
97 // If the nmethod has been deoptimized and it had a handler the handler
98 // address is the deopt blob unpack_with_exception entry.
99 //
100 // If no handler exists it prepares for stack-unwinding, restoring the callee-save
101 // registers of the frame being removed.
102 //
103 __ save_frame(0);
105 __ mov(G2_thread, O0);
106 __ set_last_Java_frame(SP, noreg);
107 __ save_thread(L7_thread_cache);
109 // This call can block at exit and nmethod can be deoptimized at that
110 // point. If the nmethod had a catch point we would jump to the
111 // now deoptimized catch point and fall thru the vanilla deopt
112 // path and lose the exception
113 // Sure would be simpler if this call didn't block!
114 __ call(CAST_FROM_FN_PTR(address, OptoRuntime::handle_exception_C), relocInfo::runtime_call_type);
115 __ delayed()->mov(L7_thread_cache, O0);
117 // Set an oopmap for the call site. This oopmap will only be used if we
118 // are unwinding the stack. Hence, all locations will be dead.
119 // Callee-saved registers will be the same as the frame above (i.e.,
120 // handle_exception_stub), since they were restored when we got the
121 // exception.
123 OopMapSet *oop_maps = new OopMapSet();
124 oop_maps->add_gc_map( __ offset()-start, new OopMap(framesize_in_slots, 0));
126 __ bind(L);
127 __ restore_thread(L7_thread_cache);
128 __ reset_last_Java_frame();
130 __ mov(O0, G3_scratch); // Move handler address to temp
131 __ restore();
133 // Restore SP from L7 if the exception PC is a MethodHandle call site.
134 __ lduw(Address(G2_thread, JavaThread::is_method_handle_return_offset()), O7);
135 __ tst(O7);
136 __ movcc(Assembler::notZero, false, Assembler::icc, L7_mh_SP_save, SP);
138 // G3_scratch contains handler address
139 // Since this may be the deopt blob we must set O7 to look like we returned
140 // from the original pc that threw the exception
142 __ ld_ptr(G2_thread, JavaThread::exception_pc_offset(), O7);
143 __ sub(O7, frame::pc_return_offset, O7);
146 assert(Assembler::is_simm13(in_bytes(JavaThread::exception_oop_offset())), "exception offset overflows simm13, following ld instruction cannot be in delay slot");
147 __ ld_ptr(G2_thread, JavaThread::exception_oop_offset(), Oexception); // O0
148 #ifdef ASSERT
149 __ st_ptr(G0, G2_thread, JavaThread::exception_handler_pc_offset());
150 __ st_ptr(G0, G2_thread, JavaThread::exception_pc_offset());
151 #endif
152 __ JMP(G3_scratch, 0);
153 // Clear the exception oop so GC no longer processes it as a root.
154 __ delayed()->st_ptr(G0, G2_thread, JavaThread::exception_oop_offset());
156 // -------------
157 // make sure all code is generated
158 masm->flush();
160 _exception_blob = ExceptionBlob::create(&buffer, oop_maps, framesize_in_words);
161 }