src/cpu/sparc/vm/jniFastGetField_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 4323
f0c2369fda5a
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 /*
twisti@2103 2 * Copyright (c) 2004, 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 #include "assembler_sparc.inline.hpp"
stefank@2314 27 #include "memory/resourceArea.hpp"
stefank@2314 28 #include "prims/jniFastGetField.hpp"
stefank@2314 29 #include "prims/jvm_misc.hpp"
stefank@2314 30 #include "runtime/safepoint.hpp"
duke@435 31
duke@435 32 // TSO ensures that loads are blocking and ordered with respect to
duke@435 33 // to earlier loads, so we don't need LoadLoad membars.
duke@435 34
duke@435 35 #define __ masm->
duke@435 36
duke@435 37 #define BUFFER_SIZE 30*sizeof(jint)
duke@435 38
duke@435 39 // Common register usage:
duke@435 40 // O0: env
duke@435 41 // O1: obj
duke@435 42 // O2: jfieldID
duke@435 43 // O4: offset (O2 >> 2)
duke@435 44 // G4: old safepoint counter
duke@435 45
duke@435 46 address JNI_FastGetField::generate_fast_get_int_field0(BasicType type) {
duke@435 47 const char *name;
duke@435 48 switch (type) {
duke@435 49 case T_BOOLEAN: name = "jni_fast_GetBooleanField"; break;
duke@435 50 case T_BYTE: name = "jni_fast_GetByteField"; break;
duke@435 51 case T_CHAR: name = "jni_fast_GetCharField"; break;
duke@435 52 case T_SHORT: name = "jni_fast_GetShortField"; break;
duke@435 53 case T_INT: name = "jni_fast_GetIntField"; break;
duke@435 54 default: ShouldNotReachHere();
duke@435 55 }
duke@435 56 ResourceMark rm;
twisti@2103 57 BufferBlob* blob = BufferBlob::create(name, BUFFER_SIZE*wordSize);
twisti@2103 58 CodeBuffer cbuf(blob);
duke@435 59 MacroAssembler* masm = new MacroAssembler(&cbuf);
twisti@2103 60 address fast_entry = __ pc();
duke@435 61
duke@435 62 Label label1, label2;
duke@435 63
twisti@1162 64 AddressLiteral cnt_addrlit(SafepointSynchronize::safepoint_counter_addr());
twisti@1162 65 __ sethi (cnt_addrlit, O3);
twisti@1162 66 Address cnt_addr(O3, cnt_addrlit.low10());
twisti@1162 67 __ ld (cnt_addr, G4);
duke@435 68 __ andcc (G4, 1, G0);
duke@435 69 __ br (Assembler::notZero, false, Assembler::pn, label1);
duke@435 70 __ delayed()->srl (O2, 2, O4);
duke@435 71 __ ld_ptr (O1, 0, O5);
duke@435 72
duke@435 73 assert(count < LIST_CAPACITY, "LIST_CAPACITY too small");
duke@435 74 speculative_load_pclist[count] = __ pc();
duke@435 75 switch (type) {
duke@435 76 case T_BOOLEAN: __ ldub (O5, O4, G3); break;
duke@435 77 case T_BYTE: __ ldsb (O5, O4, G3); break;
duke@435 78 case T_CHAR: __ lduh (O5, O4, G3); break;
duke@435 79 case T_SHORT: __ ldsh (O5, O4, G3); break;
duke@435 80 case T_INT: __ ld (O5, O4, G3); break;
duke@435 81 default: ShouldNotReachHere();
duke@435 82 }
duke@435 83
twisti@1162 84 __ ld (cnt_addr, O5);
duke@435 85 __ cmp (O5, G4);
duke@435 86 __ br (Assembler::notEqual, false, Assembler::pn, label2);
duke@435 87 __ delayed()->mov (O7, G1);
duke@435 88 __ retl ();
duke@435 89 __ delayed()->mov (G3, O0);
duke@435 90
duke@435 91 slowcase_entry_pclist[count++] = __ pc();
duke@435 92 __ bind (label1);
duke@435 93 __ mov (O7, G1);
duke@435 94
duke@435 95 address slow_case_addr;
duke@435 96 switch (type) {
duke@435 97 case T_BOOLEAN: slow_case_addr = jni_GetBooleanField_addr(); break;
duke@435 98 case T_BYTE: slow_case_addr = jni_GetByteField_addr(); break;
duke@435 99 case T_CHAR: slow_case_addr = jni_GetCharField_addr(); break;
duke@435 100 case T_SHORT: slow_case_addr = jni_GetShortField_addr(); break;
duke@435 101 case T_INT: slow_case_addr = jni_GetIntField_addr(); break;
duke@435 102 default: ShouldNotReachHere();
duke@435 103 }
duke@435 104 __ bind (label2);
duke@435 105 __ call (slow_case_addr, relocInfo::none);
duke@435 106 __ delayed()->mov (G1, O7);
duke@435 107
duke@435 108 __ flush ();
duke@435 109
duke@435 110 return fast_entry;
duke@435 111 }
duke@435 112
duke@435 113 address JNI_FastGetField::generate_fast_get_boolean_field() {
duke@435 114 return generate_fast_get_int_field0(T_BOOLEAN);
duke@435 115 }
duke@435 116
duke@435 117 address JNI_FastGetField::generate_fast_get_byte_field() {
duke@435 118 return generate_fast_get_int_field0(T_BYTE);
duke@435 119 }
duke@435 120
duke@435 121 address JNI_FastGetField::generate_fast_get_char_field() {
duke@435 122 return generate_fast_get_int_field0(T_CHAR);
duke@435 123 }
duke@435 124
duke@435 125 address JNI_FastGetField::generate_fast_get_short_field() {
duke@435 126 return generate_fast_get_int_field0(T_SHORT);
duke@435 127 }
duke@435 128
duke@435 129 address JNI_FastGetField::generate_fast_get_int_field() {
duke@435 130 return generate_fast_get_int_field0(T_INT);
duke@435 131 }
duke@435 132
duke@435 133 address JNI_FastGetField::generate_fast_get_long_field() {
duke@435 134 const char *name = "jni_fast_GetLongField";
duke@435 135 ResourceMark rm;
twisti@2103 136 BufferBlob* blob = BufferBlob::create(name, BUFFER_SIZE*wordSize);
twisti@2103 137 CodeBuffer cbuf(blob);
duke@435 138 MacroAssembler* masm = new MacroAssembler(&cbuf);
twisti@2103 139 address fast_entry = __ pc();
duke@435 140
duke@435 141 Label label1, label2;
duke@435 142
twisti@1162 143 AddressLiteral cnt_addrlit(SafepointSynchronize::safepoint_counter_addr());
twisti@1162 144 __ sethi (cnt_addrlit, G3);
twisti@1162 145 Address cnt_addr(G3, cnt_addrlit.low10());
twisti@1162 146 __ ld (cnt_addr, G4);
duke@435 147 __ andcc (G4, 1, G0);
duke@435 148 __ br (Assembler::notZero, false, Assembler::pn, label1);
duke@435 149 __ delayed()->srl (O2, 2, O4);
duke@435 150 __ ld_ptr (O1, 0, O5);
duke@435 151 __ add (O5, O4, O5);
duke@435 152
duke@435 153 #ifndef _LP64
duke@435 154 assert(count < LIST_CAPACITY-1, "LIST_CAPACITY too small");
duke@435 155 speculative_load_pclist[count++] = __ pc();
duke@435 156 __ ld (O5, 0, G2);
duke@435 157
duke@435 158 speculative_load_pclist[count] = __ pc();
duke@435 159 __ ld (O5, 4, O3);
duke@435 160 #else
duke@435 161 assert(count < LIST_CAPACITY, "LIST_CAPACITY too small");
duke@435 162 speculative_load_pclist[count] = __ pc();
duke@435 163 __ ldx (O5, 0, O3);
duke@435 164 #endif
duke@435 165
twisti@1162 166 __ ld (cnt_addr, G1);
duke@435 167 __ cmp (G1, G4);
duke@435 168 __ br (Assembler::notEqual, false, Assembler::pn, label2);
duke@435 169 __ delayed()->mov (O7, G1);
duke@435 170
duke@435 171 #ifndef _LP64
duke@435 172 __ mov (G2, O0);
duke@435 173 __ retl ();
duke@435 174 __ delayed()->mov (O3, O1);
duke@435 175 #else
duke@435 176 __ retl ();
duke@435 177 __ delayed()->mov (O3, O0);
duke@435 178 #endif
duke@435 179
duke@435 180 #ifndef _LP64
duke@435 181 slowcase_entry_pclist[count-1] = __ pc();
duke@435 182 slowcase_entry_pclist[count++] = __ pc() ;
duke@435 183 #else
duke@435 184 slowcase_entry_pclist[count++] = __ pc();
duke@435 185 #endif
duke@435 186
duke@435 187 __ bind (label1);
duke@435 188 __ mov (O7, G1);
duke@435 189
duke@435 190 address slow_case_addr = jni_GetLongField_addr();
duke@435 191 __ bind (label2);
duke@435 192 __ call (slow_case_addr, relocInfo::none);
duke@435 193 __ delayed()->mov (G1, O7);
duke@435 194
duke@435 195 __ flush ();
duke@435 196
duke@435 197 return fast_entry;
duke@435 198 }
duke@435 199
duke@435 200 address JNI_FastGetField::generate_fast_get_float_field0(BasicType type) {
duke@435 201 const char *name;
duke@435 202 switch (type) {
duke@435 203 case T_FLOAT: name = "jni_fast_GetFloatField"; break;
duke@435 204 case T_DOUBLE: name = "jni_fast_GetDoubleField"; break;
duke@435 205 default: ShouldNotReachHere();
duke@435 206 }
duke@435 207 ResourceMark rm;
twisti@2103 208 BufferBlob* blob = BufferBlob::create(name, BUFFER_SIZE*wordSize);
twisti@2103 209 CodeBuffer cbuf(blob);
duke@435 210 MacroAssembler* masm = new MacroAssembler(&cbuf);
twisti@2103 211 address fast_entry = __ pc();
duke@435 212
duke@435 213 Label label1, label2;
duke@435 214
twisti@1162 215 AddressLiteral cnt_addrlit(SafepointSynchronize::safepoint_counter_addr());
twisti@1162 216 __ sethi (cnt_addrlit, O3);
twisti@1162 217 Address cnt_addr(O3, cnt_addrlit.low10());
twisti@1162 218 __ ld (cnt_addr, G4);
duke@435 219 __ andcc (G4, 1, G0);
duke@435 220 __ br (Assembler::notZero, false, Assembler::pn, label1);
duke@435 221 __ delayed()->srl (O2, 2, O4);
duke@435 222 __ ld_ptr (O1, 0, O5);
duke@435 223
duke@435 224 assert(count < LIST_CAPACITY, "LIST_CAPACITY too small");
duke@435 225 speculative_load_pclist[count] = __ pc();
duke@435 226 switch (type) {
duke@435 227 case T_FLOAT: __ ldf (FloatRegisterImpl::S, O5, O4, F0); break;
duke@435 228 case T_DOUBLE: __ ldf (FloatRegisterImpl::D, O5, O4, F0); break;
duke@435 229 default: ShouldNotReachHere();
duke@435 230 }
duke@435 231
twisti@1162 232 __ ld (cnt_addr, O5);
duke@435 233 __ cmp (O5, G4);
duke@435 234 __ br (Assembler::notEqual, false, Assembler::pn, label2);
duke@435 235 __ delayed()->mov (O7, G1);
duke@435 236
duke@435 237 __ retl ();
duke@435 238 __ delayed()-> nop ();
duke@435 239
duke@435 240 slowcase_entry_pclist[count++] = __ pc();
duke@435 241 __ bind (label1);
duke@435 242 __ mov (O7, G1);
duke@435 243
duke@435 244 address slow_case_addr;
duke@435 245 switch (type) {
duke@435 246 case T_FLOAT: slow_case_addr = jni_GetFloatField_addr(); break;
duke@435 247 case T_DOUBLE: slow_case_addr = jni_GetDoubleField_addr(); break;
duke@435 248 default: ShouldNotReachHere();
duke@435 249 }
duke@435 250 __ bind (label2);
duke@435 251 __ call (slow_case_addr, relocInfo::none);
duke@435 252 __ delayed()->mov (G1, O7);
duke@435 253
duke@435 254 __ flush ();
duke@435 255
duke@435 256 return fast_entry;
duke@435 257 }
duke@435 258
duke@435 259 address JNI_FastGetField::generate_fast_get_float_field() {
duke@435 260 return generate_fast_get_float_field0(T_FLOAT);
duke@435 261 }
duke@435 262
duke@435 263 address JNI_FastGetField::generate_fast_get_double_field() {
duke@435 264 return generate_fast_get_float_field0(T_DOUBLE);
duke@435 265 }

mercurial