src/cpu/sparc/vm/runtime_sparc.cpp

Thu, 07 Apr 2011 09:53:20 -0700

author
johnc
date
Thu, 07 Apr 2011 09:53:20 -0700
changeset 2781
e1162778c1c8
parent 2314
f95d63e2154a
child 2950
cba7b5c2d53f
permissions
-rw-r--r--

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

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

mercurial