blob: a5c75f5958be26890a050c5f4f0d741db2f1a9d0 [file] [log] [blame]
Doug Simon3ef35612016-12-11 12:05:57 -08001/*
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 */
23package org.graalvm.compiler.hotspot.amd64;
24
25import static org.graalvm.compiler.core.common.GraalOptions.GeneratePIC;
26import static org.graalvm.compiler.lir.LIRInstruction.OperandFlag.HINT;
27import static org.graalvm.compiler.lir.LIRInstruction.OperandFlag.ILLEGAL;
28import static org.graalvm.compiler.lir.LIRInstruction.OperandFlag.REG;
29import static org.graalvm.compiler.lir.LIRInstruction.OperandFlag.STACK;
30import static jdk.vm.ci.code.ValueUtil.asRegister;
31import static jdk.vm.ci.code.ValueUtil.isRegister;
32import static jdk.vm.ci.code.ValueUtil.isStackSlot;
33
34import org.graalvm.compiler.asm.Label;
35import org.graalvm.compiler.asm.amd64.AMD64Address;
36import org.graalvm.compiler.asm.amd64.AMD64Assembler.ConditionFlag;
Igor Veresovd405f162017-03-22 13:42:45 -070037import org.graalvm.compiler.core.common.CompressEncoding;
Doug Simon3ef35612016-12-11 12:05:57 -080038import org.graalvm.compiler.asm.amd64.AMD64MacroAssembler;
39import org.graalvm.compiler.debug.GraalError;
Doug Simon3ef35612016-12-11 12:05:57 -080040import org.graalvm.compiler.hotspot.GraalHotSpotVMConfig;
41import org.graalvm.compiler.lir.LIRInstructionClass;
42import org.graalvm.compiler.lir.StandardOp.LoadConstantOp;
43import org.graalvm.compiler.lir.amd64.AMD64LIRInstruction;
44import org.graalvm.compiler.lir.amd64.AMD64Move;
45import org.graalvm.compiler.lir.asm.CompilationResultBuilder;
46
47import jdk.vm.ci.amd64.AMD64Kind;
48import jdk.vm.ci.code.Register;
49import jdk.vm.ci.hotspot.HotSpotMetaspaceConstant;
50import jdk.vm.ci.hotspot.HotSpotObjectConstant;
51import jdk.vm.ci.meta.AllocatableValue;
52import jdk.vm.ci.meta.Constant;
53
54public 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 Veresovd405f162017-03-22 13:42:45 -070070 if (GeneratePIC.getValue(crb.getOptions())) {
Doug Simon3ef35612016-12-11 12:05:57 -080071 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 Veresovd405f162017-03-22 13:42:45 -0700149 if (GeneratePIC.getValue(crb.getOptions())) {
Doug Simon3ef35612016-12-11 12:05:57 -0800150 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 Veresovd405f162017-03-22 13:42:45 -0700207 if (encoding.hasBase() || GeneratePIC.getValue(crb.getOptions())) {
Doug Simon3ef35612016-12-11 12:05:57 -0800208 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 Veresovd405f162017-03-22 13:42:45 -0700216 if (encoding.hasShift()) {
217 masm.shrq(resReg, encoding.getShift());
Doug Simon3ef35612016-12-11 12:05:57 -0800218 }
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 Veresovd405f162017-03-22 13:42:45 -0700246 if (encoding.getShift() != 0) {
247 masm.shlq(resReg, encoding.getShift());
Doug Simon3ef35612016-12-11 12:05:57 -0800248 }
249
Igor Veresovd405f162017-03-22 13:42:45 -0700250 if (encoding.hasBase() || GeneratePIC.getValue(crb.getOptions())) {
Doug Simon3ef35612016-12-11 12:05:57 -0800251 if (nonNull) {
252 masm.addq(resReg, asRegister(baseRegister));
253 } else {
Igor Veresovd405f162017-03-22 13:42:45 -0700254 if (!encoding.hasShift()) {
Doug Simon3ef35612016-12-11 12:05:57 -0800255 // 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 Veresov5b9a2a72017-01-10 21:39:20 +0300268 public static void decodeKlassPointer(CompilationResultBuilder crb, AMD64MacroAssembler masm, Register register, Register scratch, AMD64Address address, GraalHotSpotVMConfig config) {
269 CompressEncoding encoding = config.getKlassEncoding();
Doug Simon3ef35612016-12-11 12:05:57 -0800270 masm.movl(register, address);
Igor Veresovd405f162017-03-22 13:42:45 -0700271 if (encoding.getShift() != 0) {
272 masm.shlq(register, encoding.getShift());
Doug Simon3ef35612016-12-11 12:05:57 -0800273 }
Igor Veresovd405f162017-03-22 13:42:45 -0700274 boolean pic = GeneratePIC.getValue(crb.getOptions());
275 if (pic || encoding.hasBase()) {
276 if (pic) {
Igor Veresov5b9a2a72017-01-10 21:39:20 +0300277 masm.movq(scratch, masm.getPlaceholder(-1));
278 crb.recordMark(config.MARKID_NARROW_KLASS_BASE_ADDRESS);
279 } else {
Igor Veresovd405f162017-03-22 13:42:45 -0700280 assert encoding.getBase() != 0;
281 masm.movq(scratch, encoding.getBase());
Igor Veresov5b9a2a72017-01-10 21:39:20 +0300282 }
Doug Simon3ef35612016-12-11 12:05:57 -0800283 masm.addq(register, scratch);
284 }
285 }
286}