Doug Simon | 3ef3561 | 2016-12-11 12:05:57 -0800 | [diff] [blame] | 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; |
Igor Veresov | d405f16 | 2017-03-22 13:42:45 -0700 | [diff] [blame] | 37 | import org.graalvm.compiler.core.common.CompressEncoding; |
Doug Simon | 3ef3561 | 2016-12-11 12:05:57 -0800 | [diff] [blame] | 38 | import org.graalvm.compiler.asm.amd64.AMD64MacroAssembler; |
| 39 | import org.graalvm.compiler.debug.GraalError; |
Doug Simon | 3ef3561 | 2016-12-11 12:05:57 -0800 | [diff] [blame] | 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) { |
Igor Veresov | d405f16 | 2017-03-22 13:42:45 -0700 | [diff] [blame] | 70 | if (GeneratePIC.getValue(crb.getOptions())) { |
Doug Simon | 3ef3561 | 2016-12-11 12:05:57 -0800 | [diff] [blame] | 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) { |
Igor Veresov | d405f16 | 2017-03-22 13:42:45 -0700 | [diff] [blame] | 149 | if (GeneratePIC.getValue(crb.getOptions())) { |
Doug Simon | 3ef3561 | 2016-12-11 12:05:57 -0800 | [diff] [blame] | 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); |
Igor Veresov | d405f16 | 2017-03-22 13:42:45 -0700 | [diff] [blame] | 207 | if (encoding.hasBase() || GeneratePIC.getValue(crb.getOptions())) { |
Doug Simon | 3ef3561 | 2016-12-11 12:05:57 -0800 | [diff] [blame] | 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 | |
Igor Veresov | d405f16 | 2017-03-22 13:42:45 -0700 | [diff] [blame] | 216 | if (encoding.hasShift()) { |
| 217 | masm.shrq(resReg, encoding.getShift()); |
Doug Simon | 3ef3561 | 2016-12-11 12:05:57 -0800 | [diff] [blame] | 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); |
Igor Veresov | d405f16 | 2017-03-22 13:42:45 -0700 | [diff] [blame] | 246 | if (encoding.getShift() != 0) { |
| 247 | masm.shlq(resReg, encoding.getShift()); |
Doug Simon | 3ef3561 | 2016-12-11 12:05:57 -0800 | [diff] [blame] | 248 | } |
| 249 | |
Igor Veresov | d405f16 | 2017-03-22 13:42:45 -0700 | [diff] [blame] | 250 | if (encoding.hasBase() || GeneratePIC.getValue(crb.getOptions())) { |
Doug Simon | 3ef3561 | 2016-12-11 12:05:57 -0800 | [diff] [blame] | 251 | if (nonNull) { |
| 252 | masm.addq(resReg, asRegister(baseRegister)); |
| 253 | } else { |
Igor Veresov | d405f16 | 2017-03-22 13:42:45 -0700 | [diff] [blame] | 254 | if (!encoding.hasShift()) { |
Doug Simon | 3ef3561 | 2016-12-11 12:05:57 -0800 | [diff] [blame] | 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 | |
Igor Veresov | 5b9a2a7 | 2017-01-10 21:39:20 +0300 | [diff] [blame] | 268 | public static void decodeKlassPointer(CompilationResultBuilder crb, AMD64MacroAssembler masm, Register register, Register scratch, AMD64Address address, GraalHotSpotVMConfig config) { |
| 269 | CompressEncoding encoding = config.getKlassEncoding(); |
Doug Simon | 3ef3561 | 2016-12-11 12:05:57 -0800 | [diff] [blame] | 270 | masm.movl(register, address); |
Igor Veresov | d405f16 | 2017-03-22 13:42:45 -0700 | [diff] [blame] | 271 | if (encoding.getShift() != 0) { |
| 272 | masm.shlq(register, encoding.getShift()); |
Doug Simon | 3ef3561 | 2016-12-11 12:05:57 -0800 | [diff] [blame] | 273 | } |
Igor Veresov | d405f16 | 2017-03-22 13:42:45 -0700 | [diff] [blame] | 274 | boolean pic = GeneratePIC.getValue(crb.getOptions()); |
| 275 | if (pic || encoding.hasBase()) { |
| 276 | if (pic) { |
Igor Veresov | 5b9a2a7 | 2017-01-10 21:39:20 +0300 | [diff] [blame] | 277 | masm.movq(scratch, masm.getPlaceholder(-1)); |
| 278 | crb.recordMark(config.MARKID_NARROW_KLASS_BASE_ADDRESS); |
| 279 | } else { |
Igor Veresov | d405f16 | 2017-03-22 13:42:45 -0700 | [diff] [blame] | 280 | assert encoding.getBase() != 0; |
| 281 | masm.movq(scratch, encoding.getBase()); |
Igor Veresov | 5b9a2a7 | 2017-01-10 21:39:20 +0300 | [diff] [blame] | 282 | } |
Doug Simon | 3ef3561 | 2016-12-11 12:05:57 -0800 | [diff] [blame] | 283 | masm.addq(register, scratch); |
| 284 | } |
| 285 | } |
| 286 | } |