src/cpu/sparc/vm/vtableStubs_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 3037
3d42f82cd811
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 /*
stefank@2314 2 * Copyright (c) 1997, 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 "asm/assembler.hpp"
stefank@2314 27 #include "assembler_sparc.inline.hpp"
stefank@2314 28 #include "code/vtableStubs.hpp"
stefank@2314 29 #include "interp_masm_sparc.hpp"
stefank@2314 30 #include "memory/resourceArea.hpp"
stefank@2314 31 #include "oops/instanceKlass.hpp"
stefank@2314 32 #include "oops/klassVtable.hpp"
stefank@2314 33 #include "runtime/sharedRuntime.hpp"
stefank@2314 34 #include "vmreg_sparc.inline.hpp"
stefank@2314 35 #ifdef COMPILER2
stefank@2314 36 #include "opto/runtime.hpp"
stefank@2314 37 #endif
duke@435 38
duke@435 39 // machine-dependent part of VtableStubs: create vtableStub of correct size and
duke@435 40 // initialize its code
duke@435 41
duke@435 42 #define __ masm->
duke@435 43
duke@435 44
duke@435 45 #ifndef PRODUCT
duke@435 46 extern "C" void bad_compiled_vtable_index(JavaThread* thread, oopDesc* receiver, int index);
duke@435 47 #endif
duke@435 48
duke@435 49
duke@435 50 // Used by compiler only; may use only caller saved, non-argument registers
duke@435 51 // NOTE: %%%% if any change is made to this stub make sure that the function
duke@435 52 // pd_code_size_limit is changed to ensure the correct size for VtableStub
duke@435 53 VtableStub* VtableStubs::create_vtable_stub(int vtable_index) {
duke@435 54 const int sparc_code_length = VtableStub::pd_code_size_limit(true);
duke@435 55 VtableStub* s = new(sparc_code_length) VtableStub(true, vtable_index);
duke@435 56 ResourceMark rm;
duke@435 57 CodeBuffer cb(s->entry_point(), sparc_code_length);
duke@435 58 MacroAssembler* masm = new MacroAssembler(&cb);
duke@435 59
duke@435 60 #ifndef PRODUCT
duke@435 61 if (CountCompiledCalls) {
twisti@1162 62 __ inc_counter(SharedRuntime::nof_megamorphic_calls_addr(), G5, G3_scratch);
duke@435 63 }
duke@435 64 #endif /* PRODUCT */
duke@435 65
duke@435 66 assert(VtableStub::receiver_location() == O0->as_VMReg(), "receiver expected in O0");
duke@435 67
duke@435 68 // get receiver klass
duke@435 69 address npe_addr = __ pc();
coleenp@548 70 __ load_klass(O0, G3_scratch);
duke@435 71
duke@435 72 // set methodOop (in case of interpreted method), and destination address
duke@435 73 int entry_offset = instanceKlass::vtable_start_offset() + vtable_index*vtableEntry::size();
duke@435 74 #ifndef PRODUCT
duke@435 75 if (DebugVtables) {
duke@435 76 Label L;
duke@435 77 // check offset vs vtable length
duke@435 78 __ ld(G3_scratch, instanceKlass::vtable_length_offset()*wordSize, G5);
duke@435 79 __ cmp(G5, vtable_index*vtableEntry::size());
duke@435 80 __ br(Assembler::greaterUnsigned, false, Assembler::pt, L);
duke@435 81 __ delayed()->nop();
duke@435 82 __ set(vtable_index, O2);
duke@435 83 __ call_VM(noreg, CAST_FROM_FN_PTR(address, bad_compiled_vtable_index), O0, O2);
duke@435 84 __ bind(L);
duke@435 85 }
duke@435 86 #endif
duke@435 87 int v_off = entry_offset*wordSize + vtableEntry::method_offset_in_bytes();
duke@435 88 if( __ is_simm13(v_off) ) {
duke@435 89 __ ld_ptr(G3, v_off, G5_method);
duke@435 90 } else {
duke@435 91 __ set(v_off,G5);
duke@435 92 __ ld_ptr(G3, G5, G5_method);
duke@435 93 }
duke@435 94
duke@435 95 #ifndef PRODUCT
duke@435 96 if (DebugVtables) {
duke@435 97 Label L;
duke@435 98 __ br_notnull(G5_method, false, Assembler::pt, L);
duke@435 99 __ delayed()->nop();
duke@435 100 __ stop("Vtable entry is ZERO");
duke@435 101 __ bind(L);
duke@435 102 }
duke@435 103 #endif
duke@435 104
duke@435 105 address ame_addr = __ pc(); // if the vtable entry is null, the method is abstract
duke@435 106 // NOTE: for vtable dispatches, the vtable entry will never be null.
duke@435 107
duke@435 108 __ ld_ptr(G5_method, in_bytes(methodOopDesc::from_compiled_offset()), G3_scratch);
duke@435 109
duke@435 110 // jump to target (either compiled code or c2iadapter)
duke@435 111 __ JMP(G3_scratch, 0);
duke@435 112 // load methodOop (in case we call c2iadapter)
duke@435 113 __ delayed()->nop();
duke@435 114
duke@435 115 masm->flush();
jrose@1058 116
jrose@1058 117 if (PrintMiscellaneous && (WizardMode || Verbose)) {
jrose@1058 118 tty->print_cr("vtable #%d at "PTR_FORMAT"[%d] left over: %d",
jrose@1058 119 vtable_index, s->entry_point(),
jrose@1058 120 (int)(s->code_end() - s->entry_point()),
jrose@1058 121 (int)(s->code_end() - __ pc()));
jrose@1058 122 }
jrose@1058 123 guarantee(__ pc() <= s->code_end(), "overflowed buffer");
jrose@1144 124 // shut the door on sizing bugs
jrose@1144 125 int slop = 2*BytesPerInstWord; // 32-bit offset is this much larger than a 13-bit one
jrose@1144 126 assert(vtable_index > 10 || __ pc() + slop <= s->code_end(), "room for sethi;add");
jrose@1058 127
duke@435 128 s->set_exception_points(npe_addr, ame_addr);
duke@435 129 return s;
duke@435 130 }
duke@435 131
duke@435 132
duke@435 133 // NOTE: %%%% if any change is made to this stub make sure that the function
duke@435 134 // pd_code_size_limit is changed to ensure the correct size for VtableStub
jrose@1058 135 VtableStub* VtableStubs::create_itable_stub(int itable_index) {
duke@435 136 const int sparc_code_length = VtableStub::pd_code_size_limit(false);
jrose@1058 137 VtableStub* s = new(sparc_code_length) VtableStub(false, itable_index);
duke@435 138 ResourceMark rm;
duke@435 139 CodeBuffer cb(s->entry_point(), sparc_code_length);
duke@435 140 MacroAssembler* masm = new MacroAssembler(&cb);
duke@435 141
duke@435 142 Register G3_klassOop = G3_scratch;
duke@435 143 Register G5_interface = G5; // Passed in as an argument
duke@435 144 Label search;
duke@435 145
duke@435 146 // Entry arguments:
duke@435 147 // G5_interface: Interface
duke@435 148 // O0: Receiver
duke@435 149 assert(VtableStub::receiver_location() == O0->as_VMReg(), "receiver expected in O0");
duke@435 150
duke@435 151 // get receiver klass (also an implicit null-check)
duke@435 152 address npe_addr = __ pc();
coleenp@548 153 __ load_klass(O0, G3_klassOop);
duke@435 154 __ verify_oop(G3_klassOop);
duke@435 155
duke@435 156 // Push a new window to get some temp registers. This chops the head of all
duke@435 157 // my 64-bit %o registers in the LION build, but this is OK because no longs
duke@435 158 // are passed in the %o registers. Instead, longs are passed in G1 and G4
duke@435 159 // and so those registers are not available here.
duke@435 160 __ save(SP,-frame::register_save_words*wordSize,SP);
duke@435 161
duke@435 162 #ifndef PRODUCT
duke@435 163 if (CountCompiledCalls) {
twisti@1162 164 __ inc_counter(SharedRuntime::nof_megamorphic_calls_addr(), L0, L1);
duke@435 165 }
duke@435 166 #endif /* PRODUCT */
duke@435 167
jrose@1058 168 Label throw_icce;
duke@435 169
jrose@1058 170 Register L5_method = L5;
jrose@1058 171 __ lookup_interface_method(// inputs: rec. class, interface, itable index
jrose@1058 172 G3_klassOop, G5_interface, itable_index,
jrose@1058 173 // outputs: method, scan temp. reg
jrose@1058 174 L5_method, L2, L3,
jrose@1058 175 throw_icce);
duke@435 176
duke@435 177 #ifndef PRODUCT
duke@435 178 if (DebugVtables) {
duke@435 179 Label L01;
jrose@1058 180 __ bpr(Assembler::rc_nz, false, Assembler::pt, L5_method, L01);
duke@435 181 __ delayed()->nop();
duke@435 182 __ stop("methodOop is null");
duke@435 183 __ bind(L01);
jrose@1058 184 __ verify_oop(L5_method);
duke@435 185 }
duke@435 186 #endif
duke@435 187
duke@435 188 // If the following load is through a NULL pointer, we'll take an OS
duke@435 189 // exception that should translate into an AbstractMethodError. We need the
duke@435 190 // window count to be correct at that time.
jrose@1058 191 __ restore(L5_method, 0, G5_method);
jrose@1058 192 // Restore registers *before* the AME point.
duke@435 193
duke@435 194 address ame_addr = __ pc(); // if the vtable entry is null, the method is abstract
duke@435 195 __ ld_ptr(G5_method, in_bytes(methodOopDesc::from_compiled_offset()), G3_scratch);
duke@435 196
duke@435 197 // G5_method: methodOop
duke@435 198 // O0: Receiver
duke@435 199 // G3_scratch: entry point
duke@435 200 __ JMP(G3_scratch, 0);
duke@435 201 __ delayed()->nop();
duke@435 202
dcubed@451 203 __ bind(throw_icce);
twisti@1162 204 AddressLiteral icce(StubRoutines::throw_IncompatibleClassChangeError_entry());
twisti@1162 205 __ jump_to(icce, G3_scratch);
dcubed@451 206 __ delayed()->restore();
dcubed@451 207
duke@435 208 masm->flush();
dcubed@451 209
jrose@1058 210 if (PrintMiscellaneous && (WizardMode || Verbose)) {
jrose@1058 211 tty->print_cr("itable #%d at "PTR_FORMAT"[%d] left over: %d",
jrose@1058 212 itable_index, s->entry_point(),
jrose@1058 213 (int)(s->code_end() - s->entry_point()),
jrose@1058 214 (int)(s->code_end() - __ pc()));
jrose@1058 215 }
dcubed@451 216 guarantee(__ pc() <= s->code_end(), "overflowed buffer");
jrose@1144 217 // shut the door on sizing bugs
jrose@1144 218 int slop = 2*BytesPerInstWord; // 32-bit offset is this much larger than a 13-bit one
jrose@1144 219 assert(itable_index > 10 || __ pc() + slop <= s->code_end(), "room for sethi;add");
dcubed@451 220
duke@435 221 s->set_exception_points(npe_addr, ame_addr);
duke@435 222 return s;
duke@435 223 }
duke@435 224
duke@435 225
duke@435 226 int VtableStub::pd_code_size_limit(bool is_vtable_stub) {
dcubed@451 227 if (TraceJumps || DebugVtables || CountCompiledCalls || VerifyOops) return 1000;
duke@435 228 else {
duke@435 229 const int slop = 2*BytesPerInstWord; // sethi;add (needed for long offsets)
duke@435 230 if (is_vtable_stub) {
coleenp@548 231 // ld;ld;ld,jmp,nop
coleenp@548 232 const int basic = 5*BytesPerInstWord +
kvn@1077 233 // shift;add for load_klass (only shift with zero heap based)
kvn@1077 234 (UseCompressedOops ?
kvn@1077 235 ((Universe::narrow_oop_base() == NULL) ? BytesPerInstWord : 2*BytesPerInstWord) : 0);
duke@435 236 return basic + slop;
duke@435 237 } else {
jrose@1058 238 const int basic = (28 LP64_ONLY(+ 6)) * BytesPerInstWord +
kvn@1077 239 // shift;add for load_klass (only shift with zero heap based)
kvn@1077 240 (UseCompressedOops ?
kvn@1077 241 ((Universe::narrow_oop_base() == NULL) ? BytesPerInstWord : 2*BytesPerInstWord) : 0);
duke@435 242 return (basic + slop);
duke@435 243 }
duke@435 244 }
jrose@1144 245
jrose@1144 246 // In order to tune these parameters, run the JVM with VM options
jrose@1144 247 // +PrintMiscellaneous and +WizardMode to see information about
jrose@1144 248 // actual itable stubs. Look for lines like this:
jrose@1144 249 // itable #1 at 0x5551212[116] left over: 8
jrose@1144 250 // Reduce the constants so that the "left over" number is 8
jrose@1144 251 // Do not aim at a left-over number of zero, because a very
jrose@1144 252 // large vtable or itable offset (> 4K) will require an extra
jrose@1144 253 // sethi/or pair of instructions.
jrose@1144 254 //
jrose@1144 255 // The JVM98 app. _202_jess has a megamorphic interface call.
jrose@1144 256 // The itable code looks like this:
jrose@1144 257 // Decoding VtableStub itbl[1]@16
jrose@1144 258 // ld [ %o0 + 4 ], %g3
jrose@1144 259 // save %sp, -64, %sp
jrose@1144 260 // ld [ %g3 + 0xe8 ], %l2
jrose@1144 261 // sll %l2, 2, %l2
jrose@1144 262 // add %l2, 0x134, %l2
jrose@1144 263 // and %l2, -8, %l2 ! NOT_LP64 only
jrose@1144 264 // add %g3, %l2, %l2
jrose@1144 265 // add %g3, 4, %g3
jrose@1144 266 // ld [ %l2 ], %l5
jrose@1144 267 // brz,pn %l5, throw_icce
jrose@1144 268 // cmp %l5, %g5
jrose@1144 269 // be %icc, success
jrose@1144 270 // add %l2, 8, %l2
jrose@1144 271 // loop:
jrose@1144 272 // ld [ %l2 ], %l5
jrose@1144 273 // brz,pn %l5, throw_icce
jrose@1144 274 // cmp %l5, %g5
jrose@1144 275 // bne,pn %icc, loop
jrose@1144 276 // add %l2, 8, %l2
jrose@1144 277 // success:
jrose@1144 278 // ld [ %l2 + -4 ], %l2
jrose@1144 279 // ld [ %g3 + %l2 ], %l5
jrose@1144 280 // restore %l5, 0, %g5
jrose@1144 281 // ld [ %g5 + 0x44 ], %g3
jrose@1144 282 // jmp %g3
jrose@1144 283 // nop
jrose@1144 284 // throw_icce:
jrose@1144 285 // sethi %hi(throw_ICCE_entry), %g3
jrose@1144 286 // ! 5 more instructions here, LP64_ONLY
jrose@1144 287 // jmp %g3 + %lo(throw_ICCE_entry)
jrose@1144 288 // restore
duke@435 289 }
duke@435 290
duke@435 291
duke@435 292 int VtableStub::pd_code_alignment() {
duke@435 293 // UltraSPARC cache line size is 8 instructions:
duke@435 294 const unsigned int icache_line_size = 32;
duke@435 295 return icache_line_size;
duke@435 296 }

mercurial