1 /*
2  * Copyright (c) 2012, 2020, 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 
24 
25 package org.graalvm.compiler.hotspot;
26 
27 import static org.graalvm.compiler.hotspot.meta.HotSpotForeignCallDescriptor.Reexecutability.NOT_REEXECUTABLE;
28 import static org.graalvm.compiler.hotspot.meta.HotSpotForeignCallDescriptor.Reexecutability.REEXECUTABLE;
29 import static org.graalvm.compiler.hotspot.meta.HotSpotForeignCallDescriptor.Transition.LEAF;
30 import static org.graalvm.compiler.hotspot.meta.HotSpotForeignCallDescriptor.Transition.LEAF_NO_VZERO;
31 import static org.graalvm.compiler.hotspot.meta.HotSpotForeignCallDescriptor.Transition.SAFEPOINT;
32 import static org.graalvm.compiler.hotspot.meta.HotSpotForeignCallsProviderImpl.NO_LOCATIONS;
33 import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.TLAB_END_LOCATION;
34 import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.TLAB_TOP_LOCATION;
35 import static org.graalvm.compiler.replacements.arraycopy.ArrayCopyForeignCalls.UNSAFE_ARRAYCOPY;
36 import static jdk.internal.vm.compiler.word.LocationIdentity.any;
37 
38 import java.util.EnumSet;
39 
40 import jdk.internal.vm.compiler.collections.EconomicMap;
41 import jdk.internal.vm.compiler.collections.EconomicSet;
42 import jdk.internal.vm.compiler.collections.Equivalence;
43 import jdk.internal.vm.compiler.collections.MapCursor;
44 import org.graalvm.compiler.code.CompilationResult;
45 import org.graalvm.compiler.core.common.CompilationIdentifier;
46 import org.graalvm.compiler.core.common.cfg.AbstractBlockBase;
47 import org.graalvm.compiler.core.common.spi.ForeignCallDescriptor;
48 import org.graalvm.compiler.core.common.spi.ForeignCallLinkage;
49 import org.graalvm.compiler.core.common.spi.ForeignCallSignature;
50 import org.graalvm.compiler.core.target.Backend;
51 import org.graalvm.compiler.graph.Node.ConstantNodeParameter;
52 import org.graalvm.compiler.graph.Node.NodeIntrinsic;
53 import org.graalvm.compiler.hotspot.meta.HotSpotForeignCallDescriptor;
54 import org.graalvm.compiler.hotspot.meta.HotSpotProviders;
55 import org.graalvm.compiler.hotspot.nodes.VMErrorNode;
56 import org.graalvm.compiler.hotspot.nodes.aot.ResolveConstantStubCall;
57 import org.graalvm.compiler.hotspot.replacements.AESCryptSubstitutions;
58 import org.graalvm.compiler.hotspot.replacements.BigIntegerSubstitutions;
59 import org.graalvm.compiler.hotspot.replacements.CipherBlockChainingSubstitutions;
60 import org.graalvm.compiler.hotspot.replacements.DigestBaseSubstitutions;
61 import org.graalvm.compiler.hotspot.replacements.SHA2Substitutions;
62 import org.graalvm.compiler.hotspot.replacements.SHA5Substitutions;
63 import org.graalvm.compiler.hotspot.replacements.SHASubstitutions;
64 import org.graalvm.compiler.hotspot.stubs.ExceptionHandlerStub;
65 import org.graalvm.compiler.hotspot.stubs.Stub;
66 import org.graalvm.compiler.hotspot.stubs.UnwindExceptionToCallerStub;
67 import org.graalvm.compiler.hotspot.word.KlassPointer;
68 import org.graalvm.compiler.hotspot.word.MethodCountersPointer;
69 import org.graalvm.compiler.lir.LIR;
70 import org.graalvm.compiler.lir.LIRFrameState;
71 import org.graalvm.compiler.lir.LIRInstruction;
72 import org.graalvm.compiler.lir.LIRInstruction.OperandFlag;
73 import org.graalvm.compiler.lir.LIRInstruction.OperandMode;
74 import org.graalvm.compiler.lir.StandardOp.LabelOp;
75 import org.graalvm.compiler.lir.StandardOp.RestoreRegistersOp;
76 import org.graalvm.compiler.lir.StandardOp.SaveRegistersOp;
77 import org.graalvm.compiler.lir.ValueConsumer;
78 import org.graalvm.compiler.lir.asm.CompilationResultBuilder;
79 import org.graalvm.compiler.lir.framemap.FrameMap;
80 import org.graalvm.compiler.nodes.NamedLocationIdentity;
81 import org.graalvm.compiler.nodes.UnwindNode;
82 import org.graalvm.compiler.nodes.extended.ForeignCallNode;
83 import org.graalvm.compiler.options.Option;
84 import org.graalvm.compiler.options.OptionKey;
85 import org.graalvm.compiler.options.OptionType;
86 import org.graalvm.compiler.options.OptionValues;
87 import org.graalvm.compiler.phases.tiers.SuitesProvider;
88 import org.graalvm.compiler.serviceprovider.JavaVersionUtil;
89 import org.graalvm.compiler.word.Word;
90 import jdk.internal.vm.compiler.word.LocationIdentity;
91 import jdk.internal.vm.compiler.word.Pointer;
92 
93 import jdk.vm.ci.code.CallingConvention;
94 import jdk.vm.ci.code.CompilationRequest;
95 import jdk.vm.ci.code.CompiledCode;
96 import jdk.vm.ci.code.Register;
97 import jdk.vm.ci.code.StackSlot;
98 import jdk.vm.ci.code.ValueUtil;
99 import jdk.vm.ci.hotspot.HotSpotCompilationRequest;
100 import jdk.vm.ci.hotspot.HotSpotJVMCIRuntime;
101 import jdk.vm.ci.hotspot.HotSpotResolvedJavaMethod;
102 import jdk.vm.ci.meta.AllocatableValue;
103 import jdk.vm.ci.meta.JavaKind;
104 import jdk.vm.ci.meta.ResolvedJavaMethod;
105 import jdk.vm.ci.meta.Value;
106 import jdk.vm.ci.runtime.JVMCICompiler;
107 
108 /**
109  * HotSpot specific backend.
110  */
111 public abstract class HotSpotBackend extends Backend implements FrameMap.ReferenceMapBuilderFactory {
112 
113     public static class Options {
114         // @formatter:off
115         @Option(help = "Use Graal arithmetic stubs instead of HotSpot stubs where possible")
116         public static final OptionKey<Boolean> GraalArithmeticStubs = new OptionKey<>(JavaVersionUtil.JAVA_SPEC >= 9);
117         @Option(help = "Enables instruction profiling on assembler level. Valid values are a comma separated list of supported instructions." +
118                         " Compare with subclasses of Assembler.InstructionCounter.", type = OptionType.Debug)
119         public static final OptionKey<String> ASMInstructionProfiling = new OptionKey<>(null);
120         // @formatter:on
121     }
122 
123     /**
124      * Descriptor for {@link ExceptionHandlerStub}. This stub is called by the
125      * {@linkplain HotSpotMarkId#EXCEPTION_HANDLER_ENTRY exception handler} in a compiled method.
126      */
127     public static final HotSpotForeignCallDescriptor EXCEPTION_HANDLER = new HotSpotForeignCallDescriptor(LEAF_NO_VZERO, NOT_REEXECUTABLE, any(), "exceptionHandler", void.class, Object.class,
128                     Word.class);
129 
130     /**
131      * Descriptor for SharedRuntime::get_ic_miss_stub().
132      */
133     public static final HotSpotForeignCallDescriptor IC_MISS_HANDLER = new HotSpotForeignCallDescriptor(LEAF_NO_VZERO, REEXECUTABLE, NO_LOCATIONS, "icMissHandler", void.class);
134 
135     /**
136      * Descriptor for SharedRuntime::get_handle_wrong_method_stub().
137      */
138     public static final HotSpotForeignCallDescriptor WRONG_METHOD_HANDLER = new HotSpotForeignCallDescriptor(LEAF_NO_VZERO, REEXECUTABLE, NO_LOCATIONS, "wrongMethodHandler", void.class);
139 
140     /**
141      * Descriptor for {@link UnwindExceptionToCallerStub}. This stub is called by code generated
142      * from {@link UnwindNode}.
143      */
144     public static final HotSpotForeignCallDescriptor UNWIND_EXCEPTION_TO_CALLER = new HotSpotForeignCallDescriptor(SAFEPOINT, NOT_REEXECUTABLE, any(), "unwindExceptionToCaller", void.class,
145                     Object.class, Word.class);
146 
147     /**
148      * Descriptor for the arguments when unwinding to an exception handler in a caller.
149      */
150     public static final HotSpotForeignCallDescriptor EXCEPTION_HANDLER_IN_CALLER = new HotSpotForeignCallDescriptor(LEAF_NO_VZERO, NOT_REEXECUTABLE, any(), "exceptionHandlerInCaller",
151                     void.class, Object.class, Word.class);
152 
153     private final HotSpotGraalRuntimeProvider runtime;
154 
155     /**
156      * @see AESCryptSubstitutions#encryptBlockStub(ForeignCallDescriptor, Word, Word, Pointer)
157      */
158     public static final HotSpotForeignCallDescriptor ENCRYPT_BLOCK = new HotSpotForeignCallDescriptor(LEAF, NOT_REEXECUTABLE, NamedLocationIdentity.getArrayLocation(JavaKind.Byte), "encrypt_block",
159                     void.class, Word.class, Word.class, Pointer.class);
160 
161     /**
162      * @see AESCryptSubstitutions#decryptBlockStub(ForeignCallDescriptor, Word, Word, Pointer)
163      */
164     public static final HotSpotForeignCallDescriptor DECRYPT_BLOCK = new HotSpotForeignCallDescriptor(LEAF, NOT_REEXECUTABLE, NamedLocationIdentity.getArrayLocation(JavaKind.Byte), "decrypt_block",
165                     void.class, Word.class, Word.class, Pointer.class);
166 
167     /**
168      * @see AESCryptSubstitutions#decryptBlockStub(ForeignCallDescriptor, Word, Word, Pointer)
169      */
170     public static final HotSpotForeignCallDescriptor DECRYPT_BLOCK_WITH_ORIGINAL_KEY = new HotSpotForeignCallDescriptor(LEAF, NOT_REEXECUTABLE, NamedLocationIdentity.getArrayLocation(JavaKind.Byte),
171                     "decrypt_block_with_original_key", void.class, Word.class, Word.class, Pointer.class,
172                     Pointer.class);
173 
174     /**
175      * @see CipherBlockChainingSubstitutions#crypt
176      */
177     public static final HotSpotForeignCallDescriptor ENCRYPT = new HotSpotForeignCallDescriptor(LEAF, NOT_REEXECUTABLE, NamedLocationIdentity.getArrayLocation(JavaKind.Byte), "encrypt", void.class,
178                     Word.class, Word.class, Pointer.class, Pointer.class, int.class);
179 
180     /**
181      * @see CipherBlockChainingSubstitutions#crypt
182      */
183     public static final HotSpotForeignCallDescriptor DECRYPT = new HotSpotForeignCallDescriptor(LEAF, NOT_REEXECUTABLE, NamedLocationIdentity.getArrayLocation(JavaKind.Byte), "decrypt", void.class,
184                     Word.class, Word.class, Pointer.class, Pointer.class, int.class);
185 
186     /**
187      * @see CipherBlockChainingSubstitutions#crypt
188      */
189     public static final HotSpotForeignCallDescriptor DECRYPT_WITH_ORIGINAL_KEY = new HotSpotForeignCallDescriptor(LEAF, NOT_REEXECUTABLE, NamedLocationIdentity.getArrayLocation(JavaKind.Byte),
190                     "decrypt_with_original_key", void.class, Word.class, Word.class, Pointer.class, Pointer.class,
191                     int.class, Pointer.class);
192 
193     /**
194      * @see BigIntegerSubstitutions#multiplyToLen
195      */
196     public static final HotSpotForeignCallDescriptor MULTIPLY_TO_LEN = new HotSpotForeignCallDescriptor(LEAF_NO_VZERO, NOT_REEXECUTABLE, NamedLocationIdentity.getArrayLocation(JavaKind.Int),
197                     "multiplyToLen",
198                     void.class, Word.class, int.class, Word.class, int.class, Word.class, int.class);
199 
multiplyToLenStub(Word xAddr, int xlen, Word yAddr, int ylen, Word zAddr, int zLen)200     public static void multiplyToLenStub(Word xAddr, int xlen, Word yAddr, int ylen, Word zAddr, int zLen) {
201         multiplyToLenStub(HotSpotBackend.MULTIPLY_TO_LEN, xAddr, xlen, yAddr, ylen, zAddr, zLen);
202     }
203 
204     @NodeIntrinsic(ForeignCallNode.class)
multiplyToLenStub(@onstantNodeParameter ForeignCallDescriptor descriptor, Word xIn, int xLen, Word yIn, int yLen, Word zIn, int zLen)205     private static native void multiplyToLenStub(@ConstantNodeParameter ForeignCallDescriptor descriptor, Word xIn, int xLen, Word yIn, int yLen, Word zIn, int zLen);
206 
207     /**
208      * @see BigIntegerSubstitutions#mulAdd
209      */
210     public static final HotSpotForeignCallDescriptor MUL_ADD = new HotSpotForeignCallDescriptor(LEAF_NO_VZERO, NOT_REEXECUTABLE, NamedLocationIdentity.getArrayLocation(JavaKind.Int), "mulAdd",
211                     int.class,
212                     Word.class, Word.class, int.class, int.class, int.class);
213 
mulAddStub(Word inAddr, Word outAddr, int newOffset, int len, int k)214     public static int mulAddStub(Word inAddr, Word outAddr, int newOffset, int len, int k) {
215         return mulAddStub(HotSpotBackend.MUL_ADD, inAddr, outAddr, newOffset, len, k);
216     }
217 
218     @NodeIntrinsic(ForeignCallNode.class)
mulAddStub(@onstantNodeParameter ForeignCallDescriptor descriptor, Word inAddr, Word outAddr, int newOffset, int len, int k)219     private static native int mulAddStub(@ConstantNodeParameter ForeignCallDescriptor descriptor, Word inAddr, Word outAddr, int newOffset, int len, int k);
220 
221     /**
222      * @see BigIntegerSubstitutions#implMontgomeryMultiply
223      */
224     public static final HotSpotForeignCallDescriptor MONTGOMERY_MULTIPLY = new HotSpotForeignCallDescriptor(LEAF_NO_VZERO, NOT_REEXECUTABLE, NamedLocationIdentity.getArrayLocation(JavaKind.Int),
225                     "implMontgomeryMultiply", void.class, Word.class, Word.class, Word.class, int.class, long.class,
226                     Word.class);
227 
implMontgomeryMultiply(Word aAddr, Word bAddr, Word nAddr, int len, long inv, Word productAddr)228     public static void implMontgomeryMultiply(Word aAddr, Word bAddr, Word nAddr, int len, long inv, Word productAddr) {
229         implMontgomeryMultiply(HotSpotBackend.MONTGOMERY_MULTIPLY, aAddr, bAddr, nAddr, len, inv, productAddr);
230     }
231 
232     @NodeIntrinsic(ForeignCallNode.class)
implMontgomeryMultiply(@onstantNodeParameter ForeignCallDescriptor descriptor, Word aAddr, Word bAddr, Word nAddr, int len, long inv, Word productAddr)233     private static native void implMontgomeryMultiply(@ConstantNodeParameter ForeignCallDescriptor descriptor, Word aAddr, Word bAddr, Word nAddr, int len, long inv, Word productAddr);
234 
235     /**
236      * @see BigIntegerSubstitutions#implMontgomerySquare
237      */
238     public static final HotSpotForeignCallDescriptor MONTGOMERY_SQUARE = new HotSpotForeignCallDescriptor(LEAF_NO_VZERO, NOT_REEXECUTABLE, NamedLocationIdentity.getArrayLocation(JavaKind.Int),
239                     "implMontgomerySquare", void.class, Word.class, Word.class, int.class, long.class, Word.class);
240 
implMontgomerySquare(Word aAddr, Word nAddr, int len, long inv, Word productAddr)241     public static void implMontgomerySquare(Word aAddr, Word nAddr, int len, long inv, Word productAddr) {
242         implMontgomerySquare(HotSpotBackend.MONTGOMERY_SQUARE, aAddr, nAddr, len, inv, productAddr);
243     }
244 
245     @NodeIntrinsic(ForeignCallNode.class)
implMontgomerySquare(@onstantNodeParameter ForeignCallDescriptor descriptor, Word aAddr, Word nAddr, int len, long inv, Word productAddr)246     private static native void implMontgomerySquare(@ConstantNodeParameter ForeignCallDescriptor descriptor, Word aAddr, Word nAddr, int len, long inv, Word productAddr);
247 
248     /**
249      * @see BigIntegerSubstitutions#implSquareToLen
250      */
251     public static final HotSpotForeignCallDescriptor SQUARE_TO_LEN = new HotSpotForeignCallDescriptor(LEAF_NO_VZERO, NOT_REEXECUTABLE, NamedLocationIdentity.getArrayLocation(JavaKind.Int),
252                     "implSquareToLen",
253                     void.class, Word.class, int.class, Word.class, int.class);
254 
implSquareToLen(Word xAddr, int len, Word zAddr, int zLen)255     public static void implSquareToLen(Word xAddr, int len, Word zAddr, int zLen) {
256         implSquareToLen(SQUARE_TO_LEN, xAddr, len, zAddr, zLen);
257     }
258 
259     @NodeIntrinsic(ForeignCallNode.class)
implSquareToLen(@onstantNodeParameter ForeignCallDescriptor descriptor, Word xAddr, int len, Word zAddr, int zLen)260     private static native void implSquareToLen(@ConstantNodeParameter ForeignCallDescriptor descriptor, Word xAddr, int len, Word zAddr, int zLen);
261 
262     /**
263      * @see SHASubstitutions#implCompress0
264      */
265     public static final HotSpotForeignCallDescriptor SHA_IMPL_COMPRESS = new HotSpotForeignCallDescriptor(LEAF, NOT_REEXECUTABLE, any(), "shaImplCompress", void.class, Word.class,
266                     Object.class);
267 
shaImplCompressStub(Word bufAddr, Object state)268     public static void shaImplCompressStub(Word bufAddr, Object state) {
269         shaImplCompressStub(HotSpotBackend.SHA_IMPL_COMPRESS, bufAddr, state);
270     }
271 
272     @NodeIntrinsic(ForeignCallNode.class)
shaImplCompressStub(@onstantNodeParameter ForeignCallDescriptor descriptor, Word bufAddr, Object state)273     private static native void shaImplCompressStub(@ConstantNodeParameter ForeignCallDescriptor descriptor, Word bufAddr, Object state);
274 
275     /**
276      * @see SHA2Substitutions#implCompress0
277      */
278     public static final HotSpotForeignCallDescriptor SHA2_IMPL_COMPRESS = new HotSpotForeignCallDescriptor(LEAF, NOT_REEXECUTABLE, any(), "sha2ImplCompress", void.class, Word.class,
279                     Object.class);
280 
sha2ImplCompressStub(Word bufAddr, Object state)281     public static void sha2ImplCompressStub(Word bufAddr, Object state) {
282         sha2ImplCompressStub(HotSpotBackend.SHA2_IMPL_COMPRESS, bufAddr, state);
283     }
284 
285     @NodeIntrinsic(ForeignCallNode.class)
sha2ImplCompressStub(@onstantNodeParameter ForeignCallDescriptor descriptor, Word bufAddr, Object state)286     private static native void sha2ImplCompressStub(@ConstantNodeParameter ForeignCallDescriptor descriptor, Word bufAddr, Object state);
287 
288     /**
289      * @see SHA5Substitutions#implCompress0
290      */
291     public static final HotSpotForeignCallDescriptor SHA5_IMPL_COMPRESS = new HotSpotForeignCallDescriptor(LEAF, NOT_REEXECUTABLE, any(), "sha5ImplCompress", void.class, Word.class,
292                     Object.class);
293 
sha5ImplCompressStub(Word bufAddr, Object state)294     public static void sha5ImplCompressStub(Word bufAddr, Object state) {
295         sha5ImplCompressStub(HotSpotBackend.SHA5_IMPL_COMPRESS, bufAddr, state);
296     }
297 
298     @NodeIntrinsic(ForeignCallNode.class)
sha5ImplCompressStub(@onstantNodeParameter ForeignCallDescriptor descriptor, Word bufAddr, Object state)299     private static native void sha5ImplCompressStub(@ConstantNodeParameter ForeignCallDescriptor descriptor, Word bufAddr, Object state);
300 
301     /**
302      * @see DigestBaseSubstitutions#implCompressMultiBlock0
303      */
304     public static final HotSpotForeignCallDescriptor SHA_IMPL_COMPRESS_MB = new HotSpotForeignCallDescriptor(LEAF, NOT_REEXECUTABLE, any(), "shaImplCompressMB", int.class, Word.class,
305                     Object.class, int.class, int.class);
306 
shaImplCompressMBStub(Word bufAddr, Object stateAddr, int ofs, int limit)307     public static int shaImplCompressMBStub(Word bufAddr, Object stateAddr, int ofs, int limit) {
308         return shaImplCompressMBStub(HotSpotBackend.SHA_IMPL_COMPRESS_MB, bufAddr, stateAddr, ofs, limit);
309     }
310 
311     @NodeIntrinsic(ForeignCallNode.class)
shaImplCompressMBStub(@onstantNodeParameter ForeignCallDescriptor descriptor, Word bufAddr, Object state, int ofs, int limit)312     private static native int shaImplCompressMBStub(@ConstantNodeParameter ForeignCallDescriptor descriptor, Word bufAddr, Object state, int ofs, int limit);
313 
314     public static final HotSpotForeignCallDescriptor SHA2_IMPL_COMPRESS_MB = new HotSpotForeignCallDescriptor(LEAF, NOT_REEXECUTABLE, any(), "sha2ImplCompressMB", int.class, Word.class,
315                     Object.class, int.class, int.class);
316 
sha2ImplCompressMBStub(Word bufAddr, Object stateAddr, int ofs, int limit)317     public static int sha2ImplCompressMBStub(Word bufAddr, Object stateAddr, int ofs, int limit) {
318         return sha2ImplCompressMBStub(HotSpotBackend.SHA2_IMPL_COMPRESS_MB, bufAddr, stateAddr, ofs, limit);
319     }
320 
321     @NodeIntrinsic(ForeignCallNode.class)
sha2ImplCompressMBStub(@onstantNodeParameter ForeignCallDescriptor descriptor, Word bufAddr, Object state, int ofs, int limit)322     private static native int sha2ImplCompressMBStub(@ConstantNodeParameter ForeignCallDescriptor descriptor, Word bufAddr, Object state, int ofs, int limit);
323 
324     public static final HotSpotForeignCallDescriptor SHA5_IMPL_COMPRESS_MB = new HotSpotForeignCallDescriptor(LEAF, NOT_REEXECUTABLE, any(), "sha5ImplCompressMB", int.class, Word.class,
325                     Object.class, int.class, int.class);
326 
sha5ImplCompressMBStub(Word bufAddr, Object stateAddr, int ofs, int limit)327     public static int sha5ImplCompressMBStub(Word bufAddr, Object stateAddr, int ofs, int limit) {
328         return sha5ImplCompressMBStub(HotSpotBackend.SHA5_IMPL_COMPRESS_MB, bufAddr, stateAddr, ofs, limit);
329     }
330 
331     @NodeIntrinsic(ForeignCallNode.class)
sha5ImplCompressMBStub(@onstantNodeParameter ForeignCallDescriptor descriptor, Word bufAddr, Object state, int ofs, int limit)332     private static native int sha5ImplCompressMBStub(@ConstantNodeParameter ForeignCallDescriptor descriptor, Word bufAddr, Object state, int ofs, int limit);
333 
unsafeArraycopy(Word srcAddr, Word dstAddr, Word size)334     public static void unsafeArraycopy(Word srcAddr, Word dstAddr, Word size) {
335         unsafeArraycopyStub(UNSAFE_ARRAYCOPY, srcAddr, dstAddr, size);
336     }
337 
338     @NodeIntrinsic(ForeignCallNode.class)
unsafeArraycopyStub(@onstantNodeParameter ForeignCallSignature descriptor, Word srcAddr, Word dstAddr, Word size)339     private static native void unsafeArraycopyStub(@ConstantNodeParameter ForeignCallSignature descriptor, Word srcAddr, Word dstAddr, Word size);
340 
341     /**
342      * Descriptor for {@code StubRoutines::_ghash_processBlocks}.
343      */
344     public static final HotSpotForeignCallDescriptor GHASH_PROCESS_BLOCKS = new HotSpotForeignCallDescriptor(LEAF, NOT_REEXECUTABLE, any(), "ghashProcessBlocks", void.class, Word.class,
345                     Word.class, Word.class, int.class);
346 
347     /**
348      * Descriptor for {@code StubRoutines::_base64_encodeBlock}.
349      */
350     public static final HotSpotForeignCallDescriptor BASE64_ENCODE_BLOCK = new HotSpotForeignCallDescriptor(LEAF, NOT_REEXECUTABLE, any(), "base64EncodeBlock", void.class, Word.class,
351                     int.class, int.class, Word.class, int.class, boolean.class);
352 
353     /**
354      * Descriptor for {@code StubRoutines::_counterMode_AESCrypt}.
355      */
356     public static final HotSpotForeignCallDescriptor COUNTERMODE_IMPL_CRYPT = new HotSpotForeignCallDescriptor(LEAF, NOT_REEXECUTABLE, any(), "counterModeAESCrypt", int.class,
357                     Word.class, Word.class, Word.class, Word.class, int.class,
358                     Word.class, Word.class);
359 
counterModeAESCrypt(Word srcAddr, Word dstAddr, Word kPtr, Word cntPtr, int len, Word encCntPtr, Word used)360     public static int counterModeAESCrypt(Word srcAddr, Word dstAddr, Word kPtr, Word cntPtr, int len, Word encCntPtr, Word used) {
361         return counterModeAESCrypt(COUNTERMODE_IMPL_CRYPT, srcAddr, dstAddr, kPtr, cntPtr, len, encCntPtr, used);
362     }
363 
364     @NodeIntrinsic(ForeignCallNode.class)
counterModeAESCrypt(@onstantNodeParameter ForeignCallDescriptor descriptor, Word srcAddr, Word dstAddr, Word kPtr, Word cntPtr, int len, Word encCntPtr, Word used)365     private static native int counterModeAESCrypt(@ConstantNodeParameter ForeignCallDescriptor descriptor, Word srcAddr, Word dstAddr, Word kPtr, Word cntPtr, int len, Word encCntPtr,
366                     Word used);
367 
368     /**
369      * Descriptor for {@code StubRoutines::_vectorizedMismatch}.
370      */
371     public static final HotSpotForeignCallDescriptor VECTORIZED_MISMATCHED = new HotSpotForeignCallDescriptor(LEAF, NOT_REEXECUTABLE, any(), "vectorizedMismatch", int.class, Word.class,
372                     Word.class, int.class, int.class);
373 
vectorizedMismatch(Word aAddr, Word bAddr, int length, int log2ArrayIndexScale)374     public static int vectorizedMismatch(Word aAddr, Word bAddr, int length, int log2ArrayIndexScale) {
375         return vectorizedMismatchStub(VECTORIZED_MISMATCHED, aAddr, bAddr, length, log2ArrayIndexScale);
376     }
377 
378     @NodeIntrinsic(ForeignCallNode.class)
vectorizedMismatchStub(@onstantNodeParameter ForeignCallDescriptor descriptor, Word aAddr, Word bAddr, int length, int log2ArrayIndexScale)379     private static native int vectorizedMismatchStub(@ConstantNodeParameter ForeignCallDescriptor descriptor, Word aAddr, Word bAddr, int length, int log2ArrayIndexScale);
380 
381     /**
382      * @see VMErrorNode
383      */
384     public static final HotSpotForeignCallDescriptor VM_ERROR = new HotSpotForeignCallDescriptor(LEAF_NO_VZERO, REEXECUTABLE, NO_LOCATIONS, "vm_error", void.class, Object.class, Object.class,
385                     long.class);
386 
387     private static final LocationIdentity[] TLAB_LOCATIONS = new LocationIdentity[]{TLAB_TOP_LOCATION, TLAB_END_LOCATION};
388 
389     /**
390      * New multi array stub that throws an {@link OutOfMemoryError} on allocation failure.
391      */
392     public static final HotSpotForeignCallDescriptor NEW_MULTI_ARRAY = new HotSpotForeignCallDescriptor(SAFEPOINT, REEXECUTABLE, TLAB_LOCATIONS, "new_multi_array", Object.class, KlassPointer.class,
393                     int.class, Word.class);
394 
395     /**
396      * New multi array stub that will return null on allocation failure.
397      */
398     public static final HotSpotForeignCallDescriptor NEW_MULTI_ARRAY_OR_NULL = new HotSpotForeignCallDescriptor(SAFEPOINT, REEXECUTABLE, TLAB_LOCATIONS, "new_multi_array_or_null", Object.class,
399                     KlassPointer.class, int.class, Word.class);
400 
401     /**
402      * New array stub that throws an {@link OutOfMemoryError} on allocation failure.
403      */
404     public static final HotSpotForeignCallDescriptor NEW_ARRAY = new HotSpotForeignCallDescriptor(SAFEPOINT, REEXECUTABLE, TLAB_LOCATIONS, "new_array", Object.class, KlassPointer.class, int.class);
405 
406     /**
407      * New array stub that will return null on allocation failure.
408      */
409     public static final HotSpotForeignCallDescriptor NEW_ARRAY_OR_NULL = new HotSpotForeignCallDescriptor(SAFEPOINT, REEXECUTABLE, TLAB_LOCATIONS, "new_array_or_null", Object.class,
410                     KlassPointer.class,
411                     int.class);
412 
413     /**
414      * New instance stub that throws an {@link OutOfMemoryError} on allocation failure.
415      */
416     public static final HotSpotForeignCallDescriptor NEW_INSTANCE = new HotSpotForeignCallDescriptor(SAFEPOINT, REEXECUTABLE, TLAB_LOCATIONS, "new_instance", Object.class, KlassPointer.class);
417 
418     /**
419      * New instance stub that will return null on allocation failure.
420      */
421     public static final HotSpotForeignCallDescriptor NEW_INSTANCE_OR_NULL = new HotSpotForeignCallDescriptor(SAFEPOINT, REEXECUTABLE, TLAB_LOCATIONS, "new_instance_or_null", Object.class,
422                     KlassPointer.class);
423 
424     /**
425      * @see ResolveConstantStubCall
426      */
427     public static final HotSpotForeignCallDescriptor RESOLVE_STRING_BY_SYMBOL = new HotSpotForeignCallDescriptor(SAFEPOINT, REEXECUTABLE, TLAB_LOCATIONS, "resolve_string_by_symbol", Object.class,
428                     Word.class, Word.class);
429 
430     /**
431      * @see ResolveConstantStubCall
432      */
433     public static final HotSpotForeignCallDescriptor RESOLVE_DYNAMIC_INVOKE = new HotSpotForeignCallDescriptor(SAFEPOINT, REEXECUTABLE, any(), "resolve_dynamic_invoke", Object.class, Word.class);
434 
435     /**
436      * @see ResolveConstantStubCall
437      */
438     public static final HotSpotForeignCallDescriptor RESOLVE_KLASS_BY_SYMBOL = new HotSpotForeignCallDescriptor(SAFEPOINT, REEXECUTABLE, any(), "resolve_klass_by_symbol", Word.class, Word.class,
439                     Word.class);
440 
441     /**
442      * @see ResolveConstantStubCall
443      */
444     public static final HotSpotForeignCallDescriptor INITIALIZE_KLASS_BY_SYMBOL = new HotSpotForeignCallDescriptor(SAFEPOINT, NOT_REEXECUTABLE, any(), "initialize_klass_by_symbol", Word.class,
445                     Word.class,
446                     Word.class);
447 
448     /**
449      * @see ResolveConstantStubCall
450      */
451     public static final HotSpotForeignCallDescriptor RESOLVE_METHOD_BY_SYMBOL_AND_LOAD_COUNTERS = new HotSpotForeignCallDescriptor(SAFEPOINT, REEXECUTABLE, NO_LOCATIONS,
452                     "resolve_method_by_symbol_and_load_counters", Word.class, Word.class, Word.class,
453                     Word.class);
454 
455     /**
456      * Tiered support.
457      */
458     public static final HotSpotForeignCallDescriptor INVOCATION_EVENT = new HotSpotForeignCallDescriptor(SAFEPOINT, REEXECUTABLE, NO_LOCATIONS, "invocation_event", void.class,
459                     MethodCountersPointer.class);
460     public static final HotSpotForeignCallDescriptor BACKEDGE_EVENT = new HotSpotForeignCallDescriptor(SAFEPOINT, REEXECUTABLE, NO_LOCATIONS, "backedge_event", void.class, MethodCountersPointer.class,
461                     int.class, int.class);
462 
HotSpotBackend(HotSpotGraalRuntimeProvider runtime, HotSpotProviders providers)463     public HotSpotBackend(HotSpotGraalRuntimeProvider runtime, HotSpotProviders providers) {
464         super(providers);
465         this.runtime = runtime;
466     }
467 
getRuntime()468     public HotSpotGraalRuntimeProvider getRuntime() {
469         return runtime;
470     }
471 
472     /**
473      * Performs any remaining initialization that was deferred until the {@linkplain #getRuntime()
474      * runtime} object was initialized and this backend was registered with it.
475      *
476      * @param jvmciRuntime
477      * @param options
478      */
completeInitialization(HotSpotJVMCIRuntime jvmciRuntime, OptionValues options)479     public void completeInitialization(HotSpotJVMCIRuntime jvmciRuntime, OptionValues options) {
480     }
481 
482     /**
483      * Finds all the registers that are defined by some given LIR.
484      *
485      * @param gen the result to examine
486      * @return the registers that are defined by or used as temps for any instruction in {@code lir}
487      */
gatherDestroyedCallerRegisters(HotSpotLIRGenerationResult gen)488     private EconomicSet<Register> gatherDestroyedCallerRegisters(HotSpotLIRGenerationResult gen) {
489         LIR lir = gen.getLIR();
490         final EconomicSet<Register> preservedRegisters = EconomicSet.create(Equivalence.IDENTITY);
491         final EconomicSet<Register> destroyedRegisters = EconomicSet.create(Equivalence.IDENTITY);
492         ValueConsumer defConsumer = new ValueConsumer() {
493 
494             @Override
495             public void visitValue(Value value, OperandMode mode, EnumSet<OperandFlag> flags) {
496                 if (ValueUtil.isRegister(value)) {
497                     final Register reg = ValueUtil.asRegister(value);
498                     if (!preservedRegisters.contains(reg)) {
499                         destroyedRegisters.add(reg);
500                     }
501                 }
502             }
503         };
504         boolean sawSaveRegisters = false;
505         for (AbstractBlockBase<?> block : lir.codeEmittingOrder()) {
506             if (block == null) {
507                 continue;
508             }
509             // Ignore the effects of instructions bracketed by save/restore
510             SaveRegistersOp save = null;
511             for (LIRInstruction op : lir.getLIRforBlock(block)) {
512                 if (op instanceof LabelOp) {
513                     // Don't consider this as a definition
514                 } else if (op instanceof SaveRegistersOp) {
515                     save = (SaveRegistersOp) op;
516                     sawSaveRegisters = true;
517                     preservedRegisters.addAll(save.getSaveableRegisters());
518                 } else if (op instanceof RestoreRegistersOp) {
519                     save = null;
520                     preservedRegisters.clear();
521                 } else {
522                     op.visitEachTemp(defConsumer);
523                     op.visitEachOutput(defConsumer);
524                 }
525             }
526             assert save == null : "missing RestoreRegistersOp";
527         }
528 
529         if (sawSaveRegisters) {
530             // The return value must be killed so it can be propagated out
531             CallingConvention cc = gen.getCallingConvention();
532             AllocatableValue returnValue = cc.getReturn();
533             if (returnValue != null) {
534                 if (ValueUtil.isRegister(returnValue)) {
535                     destroyedRegisters.add(ValueUtil.asRegister(returnValue));
536                 }
537             }
538         }
539         return translateToCallerRegisters(destroyedRegisters);
540     }
541 
542     /**
543      * Translates a set of registers from the callee's perspective to the caller's perspective. This
544      * is needed for architectures where input/output registers are renamed during a call (e.g.
545      * register windows on SPARC). Registers which are not visible by the caller are removed.
546      */
translateToCallerRegisters(EconomicSet<Register> calleeRegisters)547     protected abstract EconomicSet<Register> translateToCallerRegisters(EconomicSet<Register> calleeRegisters);
548 
549     /**
550      * Updates a given stub with respect to the registers it destroys by
551      * {@link #gatherDestroyedCallerRegisters(HotSpotLIRGenerationResult) computing the destroyed
552      * registers} and removing those registers from the {@linkplain SaveRegistersOp SaveRegistersOp}
553      * as these registers are declared as temporaries in the stub's {@linkplain ForeignCallLinkage
554      * linkage} (and thus will be saved by the stub's caller).
555      *
556      * @param stub the stub to update
557      * @param gen the HotSpotLIRGenerationResult being emitted
558      * @param frameMap used to {@linkplain FrameMap#offsetForStackSlot(StackSlot) convert} a virtual
559      */
updateStub(Stub stub, HotSpotLIRGenerationResult gen, FrameMap frameMap)560     protected void updateStub(Stub stub, HotSpotLIRGenerationResult gen, FrameMap frameMap) {
561         EconomicSet<Register> destroyedRegisters = gatherDestroyedCallerRegisters(gen);
562         EconomicMap<LIRFrameState, SaveRegistersOp> calleeSaveInfo = gen.getCalleeSaveInfo();
563 
564         if (stub.getLinkage().needsDebugInfo() && calleeSaveInfo.isEmpty()) {
565             // This call is a safepoint but no register saving was done so we must ensure that all
566             // registers appear to be killed. The Native ABI may allow caller save registers but
567             // for HotSpot they must be described in a RegisterMap so they are accessible.
568             for (Register r : frameMap.getRegisterConfig().getCallerSaveRegisters()) {
569                 destroyedRegisters.add(r);
570             }
571         }
572 
573         stub.initDestroyedCallerRegisters(destroyedRegisters);
574 
575         MapCursor<LIRFrameState, SaveRegistersOp> cursor = calleeSaveInfo.getEntries();
576         while (cursor.advance()) {
577             SaveRegistersOp save = cursor.getValue();
578             save.remove(destroyedRegisters);
579             if (cursor.getKey() != LIRFrameState.NO_STATE) {
580                 cursor.getKey().debugInfo().setCalleeSaveInfo(save.getMap(frameMap));
581             }
582         }
583     }
584 
585     @Override
getProviders()586     public HotSpotProviders getProviders() {
587         return (HotSpotProviders) super.getProviders();
588     }
589 
590     @Override
getSuites()591     public SuitesProvider getSuites() {
592         return getProviders().getSuites();
593     }
594 
profileInstructions(LIR lir, CompilationResultBuilder crb)595     protected void profileInstructions(LIR lir, CompilationResultBuilder crb) {
596         if (HotSpotBackend.Options.ASMInstructionProfiling.getValue(lir.getOptions()) != null) {
597             HotSpotInstructionProfiling.countInstructions(lir, crb.asm);
598         }
599     }
600 
601     @Override
createCompiledCode(ResolvedJavaMethod method, CompilationRequest compilationRequest, CompilationResult compResult, boolean isDefault, OptionValues options)602     public CompiledCode createCompiledCode(ResolvedJavaMethod method,
603                     CompilationRequest compilationRequest,
604                     CompilationResult compResult,
605                     boolean isDefault,
606                     OptionValues options) {
607         assert !isDefault || compResult.getName() == null : "a default nmethod should have a null name since it is associated with a Method*";
608         HotSpotCompilationRequest compRequest = compilationRequest instanceof HotSpotCompilationRequest ? (HotSpotCompilationRequest) compilationRequest : null;
609         return HotSpotCompiledCodeBuilder.createCompiledCode(getCodeCache(), method, compRequest, compResult, options);
610     }
611 
612     @Override
getCompilationIdentifier(ResolvedJavaMethod resolvedJavaMethod)613     public CompilationIdentifier getCompilationIdentifier(ResolvedJavaMethod resolvedJavaMethod) {
614         if (resolvedJavaMethod instanceof HotSpotResolvedJavaMethod) {
615             HotSpotCompilationRequest request = new HotSpotCompilationRequest((HotSpotResolvedJavaMethod) resolvedJavaMethod, JVMCICompiler.INVOCATION_ENTRY_BCI, 0L);
616             return new HotSpotCompilationIdentifier(request);
617         }
618         return super.getCompilationIdentifier(resolvedJavaMethod);
619     }
620 }
621