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.inline.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 void ShenandoahBarrierSet::interpreter_read_barrier(MacroAssembler* masm, Register dst) {
 169   if (ShenandoahReadBarrier) {
 170 
 171     Label is_null;
 172     __ testptr(dst, dst);
 173     __ jcc(Assembler::zero, is_null);
 174     interpreter_read_barrier_not_null(masm, dst);
 175     __ bind(is_null);
 176   }
 177 }
 178 
 179 void ShenandoahBarrierSet::interpreter_read_barrier_not_null(MacroAssembler* masm, Register dst) {
 180   if (ShenandoahReadBarrier) {
 181     if (ShenandoahVerifyReadsToFromSpace) {
 182       compile_resolve_oop_runtime(masm, dst);
 183       return;
 184     }
 185     __ movptr(dst, Address(dst, BrooksPointer::byte_offset()));
 186   }
 187 }
 188 
 189 void ShenandoahBarrierSet::interpreter_write_barrier(MacroAssembler* masm, Register dst) {
 190 
 191   if (! ShenandoahWriteBarrier) {
 192     return interpreter_read_barrier(masm, dst);
 193   }
 194 
 195   __ shenandoah_write_barrier(dst);
 196 }
 197 
 198 void ShenandoahBarrierSet::asm_acmp_barrier(MacroAssembler* masm, Register op1, Register op2) {
 199   Label done;
 200   __ jccb(Assembler::equal, done);
 201   interpreter_read_barrier(masm, op1);
 202   interpreter_read_barrier(masm, op2);
 203   __ cmpptr(op1, op2);
 204   __ bind(done);
 205 }
 206 
 207 void ShenandoahHeap::compile_prepare_oop(MacroAssembler* masm, Register obj) {
 208   __ incrementq(obj, BrooksPointer::byte_size());
 209   __ movptr(Address(obj, BrooksPointer::byte_offset()), obj);
 210 }
 211 #endif