src/cpu/sparc/vm/c1_MacroAssembler_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 2447
5577848f5923
child 2708
1d1603768966
child 2746
d86923d96dca
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 /*
trims@1907 2 * Copyright (c) 1999, 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 "c1/c1_MacroAssembler.hpp"
stefank@2314 27 #include "c1/c1_Runtime1.hpp"
stefank@2314 28 #include "classfile/systemDictionary.hpp"
stefank@2314 29 #include "gc_interface/collectedHeap.hpp"
stefank@2314 30 #include "interpreter/interpreter.hpp"
stefank@2314 31 #include "oops/arrayOop.hpp"
stefank@2314 32 #include "oops/markOop.hpp"
stefank@2314 33 #include "runtime/basicLock.hpp"
stefank@2314 34 #include "runtime/biasedLocking.hpp"
stefank@2314 35 #include "runtime/os.hpp"
stefank@2314 36 #include "runtime/stubRoutines.hpp"
duke@435 37
duke@435 38 void C1_MacroAssembler::inline_cache_check(Register receiver, Register iCache) {
duke@435 39 Label L;
duke@435 40 const Register temp_reg = G3_scratch;
duke@435 41 // Note: needs more testing of out-of-line vs. inline slow case
duke@435 42 verify_oop(receiver);
iveresov@2344 43 load_klass(receiver, temp_reg);
duke@435 44 cmp(temp_reg, iCache);
duke@435 45 brx(Assembler::equal, true, Assembler::pt, L);
duke@435 46 delayed()->nop();
twisti@1162 47 AddressLiteral ic_miss(SharedRuntime::get_ic_miss_stub());
twisti@1162 48 jump_to(ic_miss, temp_reg);
duke@435 49 delayed()->nop();
duke@435 50 align(CodeEntryAlignment);
duke@435 51 bind(L);
duke@435 52 }
duke@435 53
duke@435 54
duke@435 55 void C1_MacroAssembler::explicit_null_check(Register base) {
duke@435 56 Unimplemented();
duke@435 57 }
duke@435 58
duke@435 59
duke@435 60 void C1_MacroAssembler::build_frame(int frame_size_in_bytes) {
duke@435 61
duke@435 62 generate_stack_overflow_check(frame_size_in_bytes);
duke@435 63 // Create the frame.
duke@435 64 save_frame_c1(frame_size_in_bytes);
duke@435 65 }
duke@435 66
duke@435 67
duke@435 68 void C1_MacroAssembler::unverified_entry(Register receiver, Register ic_klass) {
duke@435 69 if (C1Breakpoint) breakpoint_trap();
duke@435 70 inline_cache_check(receiver, ic_klass);
duke@435 71 }
duke@435 72
duke@435 73
duke@435 74 void C1_MacroAssembler::verified_entry() {
duke@435 75 if (C1Breakpoint) breakpoint_trap();
duke@435 76 // build frame
duke@435 77 verify_FPU(0, "method_entry");
duke@435 78 }
duke@435 79
duke@435 80
duke@435 81 void C1_MacroAssembler::lock_object(Register Rmark, Register Roop, Register Rbox, Register Rscratch, Label& slow_case) {
duke@435 82 assert_different_registers(Rmark, Roop, Rbox, Rscratch);
duke@435 83
duke@435 84 Label done;
duke@435 85
twisti@1162 86 Address mark_addr(Roop, oopDesc::mark_offset_in_bytes());
duke@435 87
duke@435 88 // The following move must be the first instruction of emitted since debug
duke@435 89 // information may be generated for it.
duke@435 90 // Load object header
duke@435 91 ld_ptr(mark_addr, Rmark);
duke@435 92
duke@435 93 verify_oop(Roop);
duke@435 94
duke@435 95 // save object being locked into the BasicObjectLock
duke@435 96 st_ptr(Roop, Rbox, BasicObjectLock::obj_offset_in_bytes());
duke@435 97
duke@435 98 if (UseBiasedLocking) {
duke@435 99 biased_locking_enter(Roop, Rmark, Rscratch, done, &slow_case);
duke@435 100 }
duke@435 101
duke@435 102 // Save Rbox in Rscratch to be used for the cas operation
duke@435 103 mov(Rbox, Rscratch);
duke@435 104
duke@435 105 // and mark it unlocked
duke@435 106 or3(Rmark, markOopDesc::unlocked_value, Rmark);
duke@435 107
duke@435 108 // save unlocked object header into the displaced header location on the stack
duke@435 109 st_ptr(Rmark, Rbox, BasicLock::displaced_header_offset_in_bytes());
duke@435 110
duke@435 111 // compare object markOop with Rmark and if equal exchange Rscratch with object markOop
duke@435 112 assert(mark_addr.disp() == 0, "cas must take a zero displacement");
duke@435 113 casx_under_lock(mark_addr.base(), Rmark, Rscratch, (address)StubRoutines::Sparc::atomic_memory_operation_lock_addr());
duke@435 114 // if compare/exchange succeeded we found an unlocked object and we now have locked it
duke@435 115 // hence we are done
duke@435 116 cmp(Rmark, Rscratch);
duke@435 117 brx(Assembler::equal, false, Assembler::pt, done);
duke@435 118 delayed()->sub(Rscratch, SP, Rscratch); //pull next instruction into delay slot
duke@435 119 // we did not find an unlocked object so see if this is a recursive case
duke@435 120 // sub(Rscratch, SP, Rscratch);
duke@435 121 assert(os::vm_page_size() > 0xfff, "page size too small - change the constant");
duke@435 122 andcc(Rscratch, 0xfffff003, Rscratch);
duke@435 123 brx(Assembler::notZero, false, Assembler::pn, slow_case);
duke@435 124 delayed()->st_ptr(Rscratch, Rbox, BasicLock::displaced_header_offset_in_bytes());
duke@435 125 bind(done);
duke@435 126 }
duke@435 127
duke@435 128
duke@435 129 void C1_MacroAssembler::unlock_object(Register Rmark, Register Roop, Register Rbox, Label& slow_case) {
duke@435 130 assert_different_registers(Rmark, Roop, Rbox);
duke@435 131
duke@435 132 Label done;
duke@435 133
twisti@1162 134 Address mark_addr(Roop, oopDesc::mark_offset_in_bytes());
duke@435 135 assert(mark_addr.disp() == 0, "cas must take a zero displacement");
duke@435 136
duke@435 137 if (UseBiasedLocking) {
duke@435 138 // load the object out of the BasicObjectLock
duke@435 139 ld_ptr(Rbox, BasicObjectLock::obj_offset_in_bytes(), Roop);
duke@435 140 verify_oop(Roop);
duke@435 141 biased_locking_exit(mark_addr, Rmark, done);
duke@435 142 }
duke@435 143 // Test first it it is a fast recursive unlock
duke@435 144 ld_ptr(Rbox, BasicLock::displaced_header_offset_in_bytes(), Rmark);
duke@435 145 br_null(Rmark, false, Assembler::pt, done);
duke@435 146 delayed()->nop();
duke@435 147 if (!UseBiasedLocking) {
duke@435 148 // load object
duke@435 149 ld_ptr(Rbox, BasicObjectLock::obj_offset_in_bytes(), Roop);
duke@435 150 verify_oop(Roop);
duke@435 151 }
duke@435 152
duke@435 153 // Check if it is still a light weight lock, this is is true if we see
duke@435 154 // the stack address of the basicLock in the markOop of the object
duke@435 155 casx_under_lock(mark_addr.base(), Rbox, Rmark, (address)StubRoutines::Sparc::atomic_memory_operation_lock_addr());
duke@435 156 cmp(Rbox, Rmark);
duke@435 157
duke@435 158 brx(Assembler::notEqual, false, Assembler::pn, slow_case);
duke@435 159 delayed()->nop();
duke@435 160 // Done
duke@435 161 bind(done);
duke@435 162 }
duke@435 163
duke@435 164
duke@435 165 void C1_MacroAssembler::try_allocate(
duke@435 166 Register obj, // result: pointer to object after successful allocation
duke@435 167 Register var_size_in_bytes, // object size in bytes if unknown at compile time; invalid otherwise
duke@435 168 int con_size_in_bytes, // object size in bytes if known at compile time
phh@2423 169 Register t1, // temp register, must be global register for incr_allocated_bytes
duke@435 170 Register t2, // temp register
duke@435 171 Label& slow_case // continuation point if fast allocation fails
duke@435 172 ) {
phh@2447 173 RegisterOrConstant size_in_bytes = var_size_in_bytes->is_valid()
phh@2447 174 ? RegisterOrConstant(var_size_in_bytes) : RegisterOrConstant(con_size_in_bytes);
duke@435 175 if (UseTLAB) {
duke@435 176 tlab_allocate(obj, var_size_in_bytes, con_size_in_bytes, t1, slow_case);
duke@435 177 } else {
duke@435 178 eden_allocate(obj, var_size_in_bytes, con_size_in_bytes, t1, t2, slow_case);
phh@2447 179 incr_allocated_bytes(size_in_bytes, t1, t2);
duke@435 180 }
duke@435 181 }
duke@435 182
duke@435 183
duke@435 184 void C1_MacroAssembler::initialize_header(Register obj, Register klass, Register len, Register t1, Register t2) {
duke@435 185 assert_different_registers(obj, klass, len, t1, t2);
duke@435 186 if (UseBiasedLocking && !len->is_valid()) {
duke@435 187 ld_ptr(klass, Klass::prototype_header_offset_in_bytes() + klassOopDesc::klass_part_offset_in_bytes(), t1);
duke@435 188 } else {
duke@435 189 set((intx)markOopDesc::prototype(), t1);
duke@435 190 }
iveresov@2344 191 st_ptr(t1, obj, oopDesc::mark_offset_in_bytes());
iveresov@2344 192 if (UseCompressedOops) {
iveresov@2344 193 // Save klass
iveresov@2344 194 mov(klass, t1);
iveresov@2344 195 encode_heap_oop_not_null(t1);
iveresov@2344 196 stw(t1, obj, oopDesc::klass_offset_in_bytes());
iveresov@2344 197 } else {
iveresov@2344 198 st_ptr(klass, obj, oopDesc::klass_offset_in_bytes());
iveresov@2344 199 }
iveresov@2344 200 if (len->is_valid()) st(len, obj, arrayOopDesc::length_offset_in_bytes());
iveresov@2344 201 else if (UseCompressedOops) {
iveresov@2344 202 store_klass_gap(G0, obj);
iveresov@2344 203 }
duke@435 204 }
duke@435 205
duke@435 206
duke@435 207 void C1_MacroAssembler::initialize_body(Register base, Register index) {
duke@435 208 assert_different_registers(base, index);
duke@435 209 Label loop;
duke@435 210 bind(loop);
duke@435 211 subcc(index, HeapWordSize, index);
duke@435 212 brx(Assembler::greaterEqual, true, Assembler::pt, loop);
duke@435 213 delayed()->st_ptr(G0, base, index);
duke@435 214 }
duke@435 215
duke@435 216
duke@435 217 void C1_MacroAssembler::allocate_object(
duke@435 218 Register obj, // result: pointer to object after successful allocation
duke@435 219 Register t1, // temp register
phh@2423 220 Register t2, // temp register, must be a global register for try_allocate
duke@435 221 Register t3, // temp register
duke@435 222 int hdr_size, // object header size in words
duke@435 223 int obj_size, // object size in words
duke@435 224 Register klass, // object klass
duke@435 225 Label& slow_case // continuation point if fast allocation fails
duke@435 226 ) {
duke@435 227 assert_different_registers(obj, t1, t2, t3, klass);
duke@435 228 assert(klass == G5, "must be G5");
duke@435 229
duke@435 230 // allocate space & initialize header
duke@435 231 if (!is_simm13(obj_size * wordSize)) {
duke@435 232 // would need to use extra register to load
duke@435 233 // object size => go the slow case for now
duke@435 234 br(Assembler::always, false, Assembler::pt, slow_case);
duke@435 235 delayed()->nop();
duke@435 236 return;
duke@435 237 }
duke@435 238 try_allocate(obj, noreg, obj_size * wordSize, t2, t3, slow_case);
duke@435 239
duke@435 240 initialize_object(obj, klass, noreg, obj_size * HeapWordSize, t1, t2);
duke@435 241 }
duke@435 242
duke@435 243 void C1_MacroAssembler::initialize_object(
duke@435 244 Register obj, // result: pointer to object after successful allocation
duke@435 245 Register klass, // object klass
duke@435 246 Register var_size_in_bytes, // object size in bytes if unknown at compile time; invalid otherwise
duke@435 247 int con_size_in_bytes, // object size in bytes if known at compile time
duke@435 248 Register t1, // temp register
duke@435 249 Register t2 // temp register
duke@435 250 ) {
iveresov@2344 251 const int hdr_size_in_bytes = instanceOopDesc::header_size() * HeapWordSize;
duke@435 252
duke@435 253 initialize_header(obj, klass, noreg, t1, t2);
duke@435 254
duke@435 255 #ifdef ASSERT
duke@435 256 {
duke@435 257 Label ok;
duke@435 258 ld(klass, klassOopDesc::header_size() * HeapWordSize + Klass::layout_helper_offset_in_bytes(), t1);
duke@435 259 if (var_size_in_bytes != noreg) {
duke@435 260 cmp(t1, var_size_in_bytes);
duke@435 261 } else {
duke@435 262 cmp(t1, con_size_in_bytes);
duke@435 263 }
duke@435 264 brx(Assembler::equal, false, Assembler::pt, ok);
duke@435 265 delayed()->nop();
duke@435 266 stop("bad size in initialize_object");
duke@435 267 should_not_reach_here();
duke@435 268
duke@435 269 bind(ok);
duke@435 270 }
duke@435 271
duke@435 272 #endif
duke@435 273
duke@435 274 // initialize body
duke@435 275 const int threshold = 5 * HeapWordSize; // approximate break even point for code size
duke@435 276 if (var_size_in_bytes != noreg) {
duke@435 277 // use a loop
duke@435 278 add(obj, hdr_size_in_bytes, t1); // compute address of first element
duke@435 279 sub(var_size_in_bytes, hdr_size_in_bytes, t2); // compute size of body
duke@435 280 initialize_body(t1, t2);
duke@435 281 #ifndef _LP64
duke@435 282 } else if (VM_Version::v9_instructions_work() && con_size_in_bytes < threshold * 2) {
duke@435 283 // on v9 we can do double word stores to fill twice as much space.
duke@435 284 assert(hdr_size_in_bytes % 8 == 0, "double word aligned");
duke@435 285 assert(con_size_in_bytes % 8 == 0, "double word aligned");
duke@435 286 for (int i = hdr_size_in_bytes; i < con_size_in_bytes; i += 2 * HeapWordSize) stx(G0, obj, i);
duke@435 287 #endif
duke@435 288 } else if (con_size_in_bytes <= threshold) {
duke@435 289 // use explicit NULL stores
duke@435 290 for (int i = hdr_size_in_bytes; i < con_size_in_bytes; i += HeapWordSize) st_ptr(G0, obj, i);
duke@435 291 } else if (con_size_in_bytes > hdr_size_in_bytes) {
duke@435 292 // use a loop
duke@435 293 const Register base = t1;
duke@435 294 const Register index = t2;
duke@435 295 add(obj, hdr_size_in_bytes, base); // compute address of first element
duke@435 296 // compute index = number of words to clear
duke@435 297 set(con_size_in_bytes - hdr_size_in_bytes, index);
duke@435 298 initialize_body(base, index);
duke@435 299 }
duke@435 300
kvn@1215 301 if (CURRENT_ENV->dtrace_alloc_probes()) {
duke@435 302 assert(obj == O0, "must be");
duke@435 303 call(CAST_FROM_FN_PTR(address, Runtime1::entry_for(Runtime1::dtrace_object_alloc_id)),
duke@435 304 relocInfo::runtime_call_type);
duke@435 305 delayed()->nop();
duke@435 306 }
duke@435 307
duke@435 308 verify_oop(obj);
duke@435 309 }
duke@435 310
duke@435 311
duke@435 312 void C1_MacroAssembler::allocate_array(
duke@435 313 Register obj, // result: pointer to array after successful allocation
duke@435 314 Register len, // array length
duke@435 315 Register t1, // temp register
duke@435 316 Register t2, // temp register
duke@435 317 Register t3, // temp register
duke@435 318 int hdr_size, // object header size in words
duke@435 319 int elt_size, // element size in bytes
duke@435 320 Register klass, // object klass
duke@435 321 Label& slow_case // continuation point if fast allocation fails
duke@435 322 ) {
duke@435 323 assert_different_registers(obj, len, t1, t2, t3, klass);
duke@435 324 assert(klass == G5, "must be G5");
duke@435 325 assert(t1 == G1, "must be G1");
duke@435 326
duke@435 327 // determine alignment mask
duke@435 328 assert(!(BytesPerWord & 1), "must be a multiple of 2 for masking code to work");
duke@435 329
duke@435 330 // check for negative or excessive length
duke@435 331 // note: the maximum length allowed is chosen so that arrays of any
duke@435 332 // element size with this length are always smaller or equal
duke@435 333 // to the largest integer (i.e., array size computation will
duke@435 334 // not overflow)
duke@435 335 set(max_array_allocation_length, t1);
duke@435 336 cmp(len, t1);
duke@435 337 br(Assembler::greaterUnsigned, false, Assembler::pn, slow_case);
duke@435 338
duke@435 339 // compute array size
duke@435 340 // note: if 0 <= len <= max_length, len*elt_size + header + alignment is
duke@435 341 // smaller or equal to the largest integer; also, since top is always
duke@435 342 // aligned, we can do the alignment here instead of at the end address
duke@435 343 // computation
duke@435 344 const Register arr_size = t1;
duke@435 345 switch (elt_size) {
duke@435 346 case 1: delayed()->mov(len, arr_size); break;
duke@435 347 case 2: delayed()->sll(len, 1, arr_size); break;
duke@435 348 case 4: delayed()->sll(len, 2, arr_size); break;
duke@435 349 case 8: delayed()->sll(len, 3, arr_size); break;
duke@435 350 default: ShouldNotReachHere();
duke@435 351 }
duke@435 352 add(arr_size, hdr_size * wordSize + MinObjAlignmentInBytesMask, arr_size); // add space for header & alignment
duke@435 353 and3(arr_size, ~MinObjAlignmentInBytesMask, arr_size); // align array size
duke@435 354
duke@435 355 // allocate space & initialize header
duke@435 356 if (UseTLAB) {
duke@435 357 tlab_allocate(obj, arr_size, 0, t2, slow_case);
duke@435 358 } else {
duke@435 359 eden_allocate(obj, arr_size, 0, t2, t3, slow_case);
duke@435 360 }
duke@435 361 initialize_header(obj, klass, len, t2, t3);
duke@435 362
duke@435 363 // initialize body
duke@435 364 const Register base = t2;
duke@435 365 const Register index = t3;
duke@435 366 add(obj, hdr_size * wordSize, base); // compute address of first element
duke@435 367 sub(arr_size, hdr_size * wordSize, index); // compute index = number of words to clear
duke@435 368 initialize_body(base, index);
duke@435 369
kvn@1215 370 if (CURRENT_ENV->dtrace_alloc_probes()) {
duke@435 371 assert(obj == O0, "must be");
duke@435 372 call(CAST_FROM_FN_PTR(address, Runtime1::entry_for(Runtime1::dtrace_object_alloc_id)),
duke@435 373 relocInfo::runtime_call_type);
duke@435 374 delayed()->nop();
duke@435 375 }
duke@435 376
duke@435 377 verify_oop(obj);
duke@435 378 }
duke@435 379
duke@435 380
duke@435 381 #ifndef PRODUCT
duke@435 382
duke@435 383 void C1_MacroAssembler::verify_stack_oop(int stack_offset) {
duke@435 384 if (!VerifyOops) return;
twisti@1162 385 verify_oop_addr(Address(SP, stack_offset + STACK_BIAS));
duke@435 386 }
duke@435 387
duke@435 388 void C1_MacroAssembler::verify_not_null_oop(Register r) {
duke@435 389 Label not_null;
duke@435 390 br_zero(Assembler::notEqual, false, Assembler::pt, r, not_null);
duke@435 391 delayed()->nop();
duke@435 392 stop("non-null oop required");
duke@435 393 bind(not_null);
duke@435 394 if (!VerifyOops) return;
duke@435 395 verify_oop(r);
duke@435 396 }
duke@435 397
duke@435 398 void C1_MacroAssembler::invalidate_registers(bool iregisters, bool lregisters, bool oregisters,
duke@435 399 Register preserve1, Register preserve2) {
duke@435 400 if (iregisters) {
duke@435 401 for (int i = 0; i < 6; i++) {
duke@435 402 Register r = as_iRegister(i);
duke@435 403 if (r != preserve1 && r != preserve2) set(0xdead, r);
duke@435 404 }
duke@435 405 }
duke@435 406 if (oregisters) {
duke@435 407 for (int i = 0; i < 6; i++) {
duke@435 408 Register r = as_oRegister(i);
duke@435 409 if (r != preserve1 && r != preserve2) set(0xdead, r);
duke@435 410 }
duke@435 411 }
duke@435 412 if (lregisters) {
duke@435 413 for (int i = 0; i < 8; i++) {
duke@435 414 Register r = as_lRegister(i);
duke@435 415 if (r != preserve1 && r != preserve2) set(0xdead, r);
duke@435 416 }
duke@435 417 }
duke@435 418 }
duke@435 419
duke@435 420
duke@435 421 #endif

mercurial