1 /* 2 * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. 8 * 9 * This code is distributed in the hope that it will be useful, but WITHOUT 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12 * version 2 for more details (a copy is included in the LICENSE file that 13 * accompanied this code). 14 * 15 * You should have received a copy of the GNU General Public License version 16 * 2 along with this work; if not, write to the Free Software Foundation, 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18 * 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20 * or visit www.oracle.com if you need additional information or have any 21 * questions. 22 */ 23 package org.graalvm.compiler.hotspot.amd64; 24 25 import static org.graalvm.compiler.core.common.GraalOptions.GeneratePIC; 26 import static org.graalvm.compiler.lir.LIRInstruction.OperandFlag.HINT; 27 import static org.graalvm.compiler.lir.LIRInstruction.OperandFlag.ILLEGAL; 28 import static org.graalvm.compiler.lir.LIRInstruction.OperandFlag.REG; 29 import static org.graalvm.compiler.lir.LIRInstruction.OperandFlag.STACK; 30 import static jdk.vm.ci.code.ValueUtil.asRegister; 31 import static jdk.vm.ci.code.ValueUtil.isRegister; 32 import static jdk.vm.ci.code.ValueUtil.isStackSlot; 33 34 import org.graalvm.compiler.asm.Label; 35 import org.graalvm.compiler.asm.amd64.AMD64Address; 36 import org.graalvm.compiler.asm.amd64.AMD64Assembler.ConditionFlag; 37 import org.graalvm.compiler.asm.amd64.AMD64MacroAssembler; 38 import org.graalvm.compiler.debug.GraalError; 39 import org.graalvm.compiler.hotspot.CompressEncoding; 40 import org.graalvm.compiler.hotspot.GraalHotSpotVMConfig; 41 import org.graalvm.compiler.lir.LIRInstructionClass; 42 import org.graalvm.compiler.lir.StandardOp.LoadConstantOp; 43 import org.graalvm.compiler.lir.amd64.AMD64LIRInstruction; 44 import org.graalvm.compiler.lir.amd64.AMD64Move; 45 import org.graalvm.compiler.lir.asm.CompilationResultBuilder; 46 47 import jdk.vm.ci.amd64.AMD64Kind; 48 import jdk.vm.ci.code.Register; 49 import jdk.vm.ci.hotspot.HotSpotMetaspaceConstant; 50 import jdk.vm.ci.hotspot.HotSpotObjectConstant; 51 import jdk.vm.ci.meta.AllocatableValue; 52 import jdk.vm.ci.meta.Constant; 53 54 public class AMD64HotSpotMove { 55 56 public static final class HotSpotLoadObjectConstantOp extends AMD64LIRInstruction implements LoadConstantOp { 57 public static final LIRInstructionClass<HotSpotLoadObjectConstantOp> TYPE = LIRInstructionClass.create(HotSpotLoadObjectConstantOp.class); 58 59 @Def({REG, STACK}) private AllocatableValue result; 60 private final HotSpotObjectConstant input; 61 62 public HotSpotLoadObjectConstantOp(AllocatableValue result, HotSpotObjectConstant input) { 63 super(TYPE); 64 this.result = result; 65 this.input = input; 66 } 67 68 @Override 69 public void emitCode(CompilationResultBuilder crb, AMD64MacroAssembler masm) { 70 if (GeneratePIC.getValue()) { 71 throw GraalError.shouldNotReachHere("Object constant load should not be happening directly"); 72 } 73 boolean compressed = input.isCompressed(); 74 if (crb.target.inlineObjects) { 75 crb.recordInlineDataInCode(input); 76 if (isRegister(result)) { 77 if (compressed) { 78 masm.movl(asRegister(result), 0xDEADDEAD); 79 } else { 80 masm.movq(asRegister(result), 0xDEADDEADDEADDEADL); 81 } 82 } else { 83 assert isStackSlot(result); 84 if (compressed) { 85 masm.movl((AMD64Address) crb.asAddress(result), 0xDEADDEAD); 86 } else { 87 throw GraalError.shouldNotReachHere("Cannot store 64-bit constants to memory"); 88 } 89 } 90 } else { 91 if (isRegister(result)) { 92 AMD64Address address = (AMD64Address) crb.recordDataReferenceInCode(input, compressed ? 4 : 8); 93 if (compressed) { 94 masm.movl(asRegister(result), address); 95 } else { 96 masm.movq(asRegister(result), address); 97 } 98 } else { 99 throw GraalError.shouldNotReachHere("Cannot directly store data patch to memory"); 100 } 101 } 102 } 103 104 @Override 105 public Constant getConstant() { 106 return input; 107 } 108 109 @Override 110 public AllocatableValue getResult() { 111 return result; 112 } 113 } 114 115 public static final class BaseMove extends AMD64LIRInstruction { 116 public static final LIRInstructionClass<BaseMove> TYPE = LIRInstructionClass.create(BaseMove.class); 117 118 @Def({REG, HINT}) protected AllocatableValue result; 119 private final GraalHotSpotVMConfig config; 120 121 public BaseMove(AllocatableValue result, GraalHotSpotVMConfig config) { 122 super(TYPE); 123 this.result = result; 124 this.config = config; 125 } 126 127 @Override 128 public void emitCode(CompilationResultBuilder crb, AMD64MacroAssembler masm) { 129 masm.movq(asRegister(result), masm.getPlaceholder(-1)); 130 crb.recordMark(config.MARKID_NARROW_KLASS_BASE_ADDRESS); 131 } 132 133 } 134 135 public static final class HotSpotLoadMetaspaceConstantOp extends AMD64LIRInstruction implements LoadConstantOp { 136 public static final LIRInstructionClass<HotSpotLoadMetaspaceConstantOp> TYPE = LIRInstructionClass.create(HotSpotLoadMetaspaceConstantOp.class); 137 138 @Def({REG, STACK}) private AllocatableValue result; 139 private final HotSpotMetaspaceConstant input; 140 141 public HotSpotLoadMetaspaceConstantOp(AllocatableValue result, HotSpotMetaspaceConstant input) { 142 super(TYPE); 143 this.result = result; 144 this.input = input; 145 } 146 147 @Override 148 public void emitCode(CompilationResultBuilder crb, AMD64MacroAssembler masm) { 149 if (GeneratePIC.getValue()) { 150 throw GraalError.shouldNotReachHere("Metaspace constant load should not be happening directly"); 151 } 152 boolean compressed = input.isCompressed(); 153 if (isRegister(result)) { 154 if (compressed) { 155 crb.recordInlineDataInCode(input); 156 masm.movl(asRegister(result), 0xDEADDEAD); 157 } else { 158 crb.recordInlineDataInCode(input); 159 masm.movq(asRegister(result), 0xDEADDEADDEADDEADL); 160 } 161 } else { 162 assert isStackSlot(result); 163 if (compressed) { 164 crb.recordInlineDataInCode(input); 165 masm.movl((AMD64Address) crb.asAddress(result), 0xDEADDEAD); 166 } else { 167 throw GraalError.shouldNotReachHere("Cannot store 64-bit constants to memory"); 168 } 169 } 170 } 171 172 @Override 173 public Constant getConstant() { 174 return input; 175 } 176 177 @Override 178 public AllocatableValue getResult() { 179 return result; 180 } 181 } 182 183 public static final class CompressPointer extends AMD64LIRInstruction { 184 public static final LIRInstructionClass<CompressPointer> TYPE = LIRInstructionClass.create(CompressPointer.class); 185 186 private final CompressEncoding encoding; 187 private final boolean nonNull; 188 189 @Def({REG, HINT}) protected AllocatableValue result; 190 @Use({REG}) protected AllocatableValue input; 191 @Alive({REG, ILLEGAL}) protected AllocatableValue baseRegister; 192 193 public CompressPointer(AllocatableValue result, AllocatableValue input, AllocatableValue baseRegister, CompressEncoding encoding, boolean nonNull) { 194 super(TYPE); 195 this.result = result; 196 this.input = input; 197 this.baseRegister = baseRegister; 198 this.encoding = encoding; 199 this.nonNull = nonNull; 200 } 201 202 @Override 203 public void emitCode(CompilationResultBuilder crb, AMD64MacroAssembler masm) { 204 AMD64Move.move(AMD64Kind.QWORD, crb, masm, result, input); 205 206 Register resReg = asRegister(result); 207 if (encoding.base != 0 || GeneratePIC.getValue()) { 208 Register baseReg = asRegister(baseRegister); 209 if (!nonNull) { 210 masm.testq(resReg, resReg); 211 masm.cmovq(ConditionFlag.Equal, resReg, baseReg); 212 } 213 masm.subq(resReg, baseReg); 214 } 215 216 if (encoding.shift != 0) { 217 masm.shrq(resReg, encoding.shift); 218 } 219 } 220 } 221 222 public static final class UncompressPointer extends AMD64LIRInstruction { 223 public static final LIRInstructionClass<UncompressPointer> TYPE = LIRInstructionClass.create(UncompressPointer.class); 224 225 private final CompressEncoding encoding; 226 private final boolean nonNull; 227 228 @Def({REG, HINT}) protected AllocatableValue result; 229 @Use({REG}) protected AllocatableValue input; 230 @Alive({REG, ILLEGAL}) protected AllocatableValue baseRegister; 231 232 public UncompressPointer(AllocatableValue result, AllocatableValue input, AllocatableValue baseRegister, CompressEncoding encoding, boolean nonNull) { 233 super(TYPE); 234 this.result = result; 235 this.input = input; 236 this.baseRegister = baseRegister; 237 this.encoding = encoding; 238 this.nonNull = nonNull; 239 } 240 241 @Override 242 public void emitCode(CompilationResultBuilder crb, AMD64MacroAssembler masm) { 243 AMD64Move.move(AMD64Kind.DWORD, crb, masm, result, input); 244 245 Register resReg = asRegister(result); 246 if (encoding.shift != 0) { 247 masm.shlq(resReg, encoding.shift); 248 } 249 250 if (encoding.base != 0 || GeneratePIC.getValue()) { 251 if (nonNull) { 252 masm.addq(resReg, asRegister(baseRegister)); 253 } else { 254 if (encoding.shift == 0) { 255 // if encoding.shift != 0, the flags are already set by the shlq 256 masm.testq(resReg, resReg); 257 } 258 259 Label done = new Label(); 260 masm.jccb(ConditionFlag.Equal, done); 261 masm.addq(resReg, asRegister(baseRegister)); 262 masm.bind(done); 263 } 264 } 265 } 266 } 267 268 public static void decodeKlassPointer(CompilationResultBuilder crb, AMD64MacroAssembler masm, Register register, Register scratch, AMD64Address address, GraalHotSpotVMConfig config) { 269 CompressEncoding encoding = config.getKlassEncoding(); 270 masm.movl(register, address); 271 if (encoding.shift != 0) { 272 assert encoding.alignment == encoding.shift : "Decode algorithm is wrong"; 273 masm.shlq(register, encoding.alignment); 274 } 275 if (GeneratePIC.getValue() || encoding.base != 0) { 276 if (GeneratePIC.getValue()) { 277 masm.movq(scratch, masm.getPlaceholder(-1)); 278 crb.recordMark(config.MARKID_NARROW_KLASS_BASE_ADDRESS); 279 } else { 280 assert encoding.base != 0; 281 masm.movq(scratch, encoding.base); 282 } 283 masm.addq(register, scratch); 284 } 285 } 286 }