1 /* 2 * Copyright (c) 2015, Red Hat, Inc. and/or its affiliates. 3 * 4 * This code is free software; you can redistribute it and/or modify it 5 * under the terms of the GNU General Public License version 2 only, as 6 * published by the Free Software Foundation. 7 * 8 * This code is distributed in the hope that it will be useful, but WITHOUT 9 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 10 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 11 * version 2 for more details (a copy is included in the LICENSE file that 12 * accompanied this code). 13 * 14 * You should have received a copy of the GNU General Public License version 15 * 2 along with this work; if not, write to the Free Software Foundation, 16 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 17 * 18 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 19 * or visit www.oracle.com if you need additional information or have any 20 * questions. 21 * 22 */ 23 24 #include "gc/shenandoah/brooksPointer.hpp" 25 #include "gc/shenandoah/shenandoahBarrierSet.hpp" 26 27 #include "asm/macroAssembler.hpp" 28 #include "interpreter/interpreter.hpp" 29 30 #define __ masm-> 31 32 #ifndef CC_INTERP 33 void ShenandoahBarrierSet::compile_resolve_oop_runtime(MacroAssembler* masm, Register dst) { 34 35 __ push(rscratch1); 36 37 if (dst != rax) { 38 __ push(rax); 39 } 40 if (dst != rbx) { 41 __ push(rbx); 42 } 43 if (dst != rcx) { 44 __ push(rcx); 45 } 46 if (dst != rdx) { 47 __ push(rdx); 48 } 49 if (dst != rdi) { 50 __ push(rdi); 51 } 52 if (dst != rsi) { 53 __ push(rsi); 54 } 55 if (dst != rbp) { 56 __ push(rbp); 57 } 58 if (dst != r8) { 59 __ push(r8); 60 } 61 if (dst != r9) { 62 __ push(r9); 63 } 64 if (dst != r11) { 65 __ push(r11); 66 } 67 if (dst != r12) { 68 __ push(r12); 69 } 70 if (dst != r13) { 71 __ push(r13); 72 } 73 if (dst != r14) { 74 __ push(r14); 75 } 76 if (dst != r15) { 77 __ push(r15); 78 } 79 80 __ subptr(rsp, 128); 81 __ movdbl(Address(rsp, 0), xmm0); 82 __ movdbl(Address(rsp, 8), xmm1); 83 __ movdbl(Address(rsp, 16), xmm2); 84 __ movdbl(Address(rsp, 24), xmm3); 85 __ movdbl(Address(rsp, 32), xmm4); 86 __ movdbl(Address(rsp, 40), xmm5); 87 __ movdbl(Address(rsp, 48), xmm6); 88 __ movdbl(Address(rsp, 56), xmm7); 89 __ movdbl(Address(rsp, 64), xmm8); 90 __ movdbl(Address(rsp, 72), xmm9); 91 __ movdbl(Address(rsp, 80), xmm10); 92 __ movdbl(Address(rsp, 88), xmm11); 93 __ movdbl(Address(rsp, 96), xmm12); 94 __ movdbl(Address(rsp, 104), xmm13); 95 __ movdbl(Address(rsp, 112), xmm14); 96 __ movdbl(Address(rsp, 120), xmm15); 97 98 __ mov(c_rarg1, dst); 99 __ super_call_VM_leaf(CAST_FROM_FN_PTR(address, ShenandoahBarrierSet::resolve_oop_static), c_rarg1); 100 __ mov(rscratch1, rax); 101 102 __ movdbl(xmm0, Address(rsp, 0)); 103 __ movdbl(xmm1, Address(rsp, 8)); 104 __ movdbl(xmm2, Address(rsp, 16)); 105 __ movdbl(xmm3, Address(rsp, 24)); 106 __ movdbl(xmm4, Address(rsp, 32)); 107 __ movdbl(xmm5, Address(rsp, 40)); 108 __ movdbl(xmm6, Address(rsp, 48)); 109 __ movdbl(xmm7, Address(rsp, 56)); 110 __ movdbl(xmm8, Address(rsp, 64)); 111 __ movdbl(xmm9, Address(rsp, 72)); 112 __ movdbl(xmm10, Address(rsp, 80)); 113 __ movdbl(xmm11, Address(rsp, 88)); 114 __ movdbl(xmm12, Address(rsp, 96)); 115 __ movdbl(xmm13, Address(rsp, 104)); 116 __ movdbl(xmm14, Address(rsp, 112)); 117 __ movdbl(xmm15, Address(rsp, 120)); 118 __ addptr(rsp, 128); 119 120 if (dst != r15) { 121 __ pop(r15); 122 } 123 if (dst != r14) { 124 __ pop(r14); 125 } 126 if (dst != r13) { 127 __ pop(r13); 128 } 129 if (dst != r12) { 130 __ pop(r12); 131 } 132 if (dst != r11) { 133 __ pop(r11); 134 } 135 if (dst != r9) { 136 __ pop(r9); 137 } 138 if (dst != r8) { 139 __ pop(r8); 140 } 141 if (dst != rbp) { 142 __ pop(rbp); 143 } 144 if (dst != rsi) { 145 __ pop(rsi); 146 } 147 if (dst != rdi) { 148 __ pop(rdi); 149 } 150 if (dst != rdx) { 151 __ pop(rdx); 152 } 153 if (dst != rcx) { 154 __ pop(rcx); 155 } 156 if (dst != rbx) { 157 __ pop(rbx); 158 } 159 if (dst != rax) { 160 __ pop(rax); 161 } 162 163 __ mov(dst, rscratch1); 164 165 __ pop(rscratch1); 166 } 167 168 // TODO: The following should really live in an X86 specific subclass. 169 void ShenandoahBarrierSet::interpreter_read_barrier(MacroAssembler* masm, Register dst) { 170 if (ShenandoahReadBarrier) { 171 172 Label is_null; 173 __ testptr(dst, dst); 174 __ jcc(Assembler::zero, is_null); 175 interpreter_read_barrier_not_null(masm, dst); 176 __ bind(is_null); 177 } 178 } 179 180 void ShenandoahBarrierSet::interpreter_read_barrier_not_null(MacroAssembler* masm, Register dst) { 181 if (ShenandoahReadBarrier) { 182 if (ShenandoahVerifyReadsToFromSpace) { 183 compile_resolve_oop_runtime(masm, dst); 184 return; 185 } 186 __ movptr(dst, Address(dst, -8)); 187 } 188 } 189 190 void ShenandoahBarrierSet::interpreter_write_barrier(MacroAssembler* masm, Register dst) { 191 192 if (! ShenandoahWriteBarrier) { 193 assert(! ShenandoahConcurrentEvacuation, "Can only do this without concurrent evacuation"); 194 return interpreter_read_barrier(masm, dst); 195 } 196 197 assert(dst != rscratch1, "different regs"); 198 //assert(dst != rscratch2, "Need rscratch2"); 199 200 Label done; 201 202 Address evacuation_in_progress = Address(r15_thread, in_bytes(JavaThread::evacuation_in_progress_offset())); 203 204 __ cmpb(evacuation_in_progress, 0); 205 206 // Now check if evacuation is in progress. 207 interpreter_read_barrier_not_null(masm, dst); 208 209 __ jcc(Assembler::equal, done); 210 __ push(rscratch1); 211 __ push(rscratch2); 212 213 __ movptr(rscratch1, dst); 214 __ shrptr(rscratch1, ShenandoahHeapRegion::RegionSizeShift); 215 __ movptr(rscratch2, (intptr_t) ShenandoahHeap::in_cset_fast_test_addr()); 216 __ movbool(rscratch2, Address(rscratch2, rscratch1, Address::times_1)); 217 __ testb(rscratch2, 0x1); 218 219 __ pop(rscratch2); 220 __ pop(rscratch1); 221 222 __ jcc(Assembler::zero, done); 223 224 __ push(rscratch1); 225 226 // Save possibly live regs. 227 if (dst != rax) { 228 __ push(rax); 229 } 230 if (dst != rbx) { 231 __ push(rbx); 232 } 233 if (dst != rcx) { 234 __ push(rcx); 235 } 236 if (dst != rdx) { 237 __ push(rdx); 238 } 239 if (dst != c_rarg1) { 240 __ push(c_rarg1); 241 } 242 243 __ subptr(rsp, 2 * wordSize); 244 __ movdbl(Address(rsp, 0), xmm0); 245 246 // Call into runtime 247 __ super_call_VM_leaf(CAST_FROM_FN_PTR(address, ShenandoahBarrierSet::resolve_and_maybe_copy_oop_interp), dst); 248 __ mov(rscratch1, rax); 249 250 // Restore possibly live regs. 251 __ movdbl(xmm0, Address(rsp, 0)); 252 __ addptr(rsp, 2 * Interpreter::stackElementSize); 253 254 if (dst != c_rarg1) { 255 __ pop(c_rarg1); 256 } 257 if (dst != rdx) { 258 __ pop(rdx); 259 } 260 if (dst != rcx) { 261 __ pop(rcx); 262 } 263 if (dst != rbx) { 264 __ pop(rbx); 265 } 266 if (dst != rax) { 267 __ pop(rax); 268 } 269 270 // Move result into dst reg. 271 __ mov(dst, rscratch1); 272 273 __ pop(rscratch1); 274 275 __ bind(done); 276 } 277 278 void ShenandoahHeap::compile_prepare_oop(MacroAssembler* masm, Register obj) { 279 __ incrementq(obj, BrooksPointer::BROOKS_POINTER_OBJ_SIZE * HeapWordSize); 280 __ movptr(Address(obj, -1 * HeapWordSize), obj); 281 } 282 #endif 283