1 /*
2  * Copyright (c) 2013, 2019, 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.meta;
26 
27 import static jdk.vm.ci.hotspot.HotSpotCallingConventionType.NativeCall;
28 import static org.graalvm.compiler.core.common.GraalOptions.GeneratePIC;
29 import static org.graalvm.compiler.core.target.Backend.ARITHMETIC_DREM;
30 import static org.graalvm.compiler.core.target.Backend.ARITHMETIC_FREM;
31 import static org.graalvm.compiler.hotspot.HotSpotBackend.BACKEDGE_EVENT;
32 import static org.graalvm.compiler.hotspot.HotSpotBackend.BASE64_ENCODE_BLOCK;
33 import static org.graalvm.compiler.hotspot.HotSpotBackend.COUNTERMODE_IMPL_CRYPT;
34 import static org.graalvm.compiler.hotspot.HotSpotBackend.DECRYPT;
35 import static org.graalvm.compiler.hotspot.HotSpotBackend.DECRYPT_BLOCK;
36 import static org.graalvm.compiler.hotspot.HotSpotBackend.DECRYPT_BLOCK_WITH_ORIGINAL_KEY;
37 import static org.graalvm.compiler.hotspot.HotSpotBackend.DECRYPT_WITH_ORIGINAL_KEY;
38 import static org.graalvm.compiler.hotspot.HotSpotBackend.ENCRYPT;
39 import static org.graalvm.compiler.hotspot.HotSpotBackend.ENCRYPT_BLOCK;
40 import static org.graalvm.compiler.hotspot.HotSpotBackend.EXCEPTION_HANDLER;
41 import static org.graalvm.compiler.hotspot.HotSpotBackend.GHASH_PROCESS_BLOCKS;
42 import static org.graalvm.compiler.hotspot.HotSpotBackend.IC_MISS_HANDLER;
43 import static org.graalvm.compiler.hotspot.HotSpotBackend.INITIALIZE_KLASS_BY_SYMBOL;
44 import static org.graalvm.compiler.hotspot.HotSpotBackend.INVOCATION_EVENT;
45 import static org.graalvm.compiler.hotspot.HotSpotBackend.MONTGOMERY_MULTIPLY;
46 import static org.graalvm.compiler.hotspot.HotSpotBackend.MONTGOMERY_SQUARE;
47 import static org.graalvm.compiler.hotspot.HotSpotBackend.MULTIPLY_TO_LEN;
48 import static org.graalvm.compiler.hotspot.HotSpotBackend.MUL_ADD;
49 import static org.graalvm.compiler.hotspot.HotSpotBackend.NEW_ARRAY;
50 import static org.graalvm.compiler.hotspot.HotSpotBackend.NEW_ARRAY_OR_NULL;
51 import static org.graalvm.compiler.hotspot.HotSpotBackend.NEW_INSTANCE;
52 import static org.graalvm.compiler.hotspot.HotSpotBackend.NEW_INSTANCE_OR_NULL;
53 import static org.graalvm.compiler.hotspot.HotSpotBackend.NEW_MULTI_ARRAY;
54 import static org.graalvm.compiler.hotspot.HotSpotBackend.NEW_MULTI_ARRAY_OR_NULL;
55 import static org.graalvm.compiler.hotspot.HotSpotBackend.RESOLVE_DYNAMIC_INVOKE;
56 import static org.graalvm.compiler.hotspot.HotSpotBackend.RESOLVE_KLASS_BY_SYMBOL;
57 import static org.graalvm.compiler.hotspot.HotSpotBackend.RESOLVE_METHOD_BY_SYMBOL_AND_LOAD_COUNTERS;
58 import static org.graalvm.compiler.hotspot.HotSpotBackend.RESOLVE_STRING_BY_SYMBOL;
59 import static org.graalvm.compiler.hotspot.HotSpotBackend.SHA2_IMPL_COMPRESS;
60 import static org.graalvm.compiler.hotspot.HotSpotBackend.SHA2_IMPL_COMPRESS_MB;
61 import static org.graalvm.compiler.hotspot.HotSpotBackend.SHA5_IMPL_COMPRESS;
62 import static org.graalvm.compiler.hotspot.HotSpotBackend.SHA5_IMPL_COMPRESS_MB;
63 import static org.graalvm.compiler.hotspot.HotSpotBackend.SHA_IMPL_COMPRESS;
64 import static org.graalvm.compiler.hotspot.HotSpotBackend.SHA_IMPL_COMPRESS_MB;
65 import static org.graalvm.compiler.hotspot.HotSpotBackend.SQUARE_TO_LEN;
66 import static org.graalvm.compiler.hotspot.HotSpotBackend.UNWIND_EXCEPTION_TO_CALLER;
67 import static org.graalvm.compiler.hotspot.HotSpotBackend.VECTORIZED_MISMATCHED;
68 import static org.graalvm.compiler.hotspot.HotSpotBackend.VM_ERROR;
69 import static org.graalvm.compiler.hotspot.HotSpotBackend.WRONG_METHOD_HANDLER;
70 import static org.graalvm.compiler.hotspot.HotSpotForeignCallLinkage.Reexecutability.NOT_REEXECUTABLE;
71 import static org.graalvm.compiler.hotspot.HotSpotForeignCallLinkage.Reexecutability.REEXECUTABLE;
72 import static org.graalvm.compiler.hotspot.HotSpotForeignCallLinkage.Reexecutability.REEXECUTABLE_ONLY_AFTER_EXCEPTION;
73 import static org.graalvm.compiler.hotspot.HotSpotForeignCallLinkage.RegisterEffect.DESTROYS_REGISTERS;
74 import static org.graalvm.compiler.hotspot.HotSpotForeignCallLinkage.RegisterEffect.PRESERVES_REGISTERS;
75 import static org.graalvm.compiler.hotspot.HotSpotForeignCallLinkage.Transition.LEAF;
76 import static org.graalvm.compiler.hotspot.HotSpotForeignCallLinkage.Transition.LEAF_NO_VZERO;
77 import static org.graalvm.compiler.hotspot.HotSpotForeignCallLinkage.Transition.SAFEPOINT;
78 import static org.graalvm.compiler.hotspot.HotSpotForeignCallLinkage.Transition.STACK_INSPECTABLE_LEAF;
79 import static org.graalvm.compiler.hotspot.HotSpotHostBackend.DEOPTIMIZATION_HANDLER;
80 import static org.graalvm.compiler.hotspot.HotSpotHostBackend.ENABLE_STACK_RESERVED_ZONE;
81 import static org.graalvm.compiler.hotspot.HotSpotHostBackend.THROW_DELAYED_STACKOVERFLOW_ERROR;
82 import static org.graalvm.compiler.hotspot.HotSpotHostBackend.UNCOMMON_TRAP_HANDLER;
83 import static org.graalvm.compiler.hotspot.replacements.AssertionSnippets.ASSERTION_VM_MESSAGE_C;
84 import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.MARK_WORD_LOCATION;
85 import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.TLAB_END_LOCATION;
86 import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.TLAB_TOP_LOCATION;
87 import static org.graalvm.compiler.hotspot.replacements.MonitorSnippets.MONITORENTER;
88 import static org.graalvm.compiler.hotspot.replacements.MonitorSnippets.MONITOREXIT;
89 import static org.graalvm.compiler.hotspot.replacements.NewObjectSnippets.DYNAMIC_NEW_INSTANCE;
90 import static org.graalvm.compiler.hotspot.replacements.NewObjectSnippets.DYNAMIC_NEW_INSTANCE_OR_NULL;
91 import static org.graalvm.compiler.hotspot.replacements.ThreadSubstitutions.THREAD_IS_INTERRUPTED;
92 import static org.graalvm.compiler.hotspot.replacements.WriteBarrierSnippets.G1WBPOSTCALL;
93 import static org.graalvm.compiler.hotspot.replacements.WriteBarrierSnippets.G1WBPRECALL;
94 import static org.graalvm.compiler.hotspot.replacements.WriteBarrierSnippets.VALIDATE_OBJECT;
95 import static org.graalvm.compiler.hotspot.stubs.ExceptionHandlerStub.EXCEPTION_HANDLER_FOR_PC;
96 import static org.graalvm.compiler.hotspot.stubs.StubUtil.VM_MESSAGE_C;
97 import static org.graalvm.compiler.hotspot.stubs.UnwindExceptionToCallerStub.EXCEPTION_HANDLER_FOR_RETURN_ADDRESS;
98 import static org.graalvm.compiler.nodes.java.ForeignCallDescriptors.REGISTER_FINALIZER;
99 import static org.graalvm.compiler.replacements.Log.LOG_OBJECT;
100 import static org.graalvm.compiler.replacements.Log.LOG_PRIMITIVE;
101 import static org.graalvm.compiler.replacements.Log.LOG_PRINTF;
102 import static org.graalvm.compiler.replacements.nodes.BinaryMathIntrinsicNode.BinaryOperation.POW;
103 import static org.graalvm.compiler.replacements.nodes.UnaryMathIntrinsicNode.UnaryOperation.COS;
104 import static org.graalvm.compiler.replacements.nodes.UnaryMathIntrinsicNode.UnaryOperation.EXP;
105 import static org.graalvm.compiler.replacements.nodes.UnaryMathIntrinsicNode.UnaryOperation.LOG;
106 import static org.graalvm.compiler.replacements.nodes.UnaryMathIntrinsicNode.UnaryOperation.LOG10;
107 import static org.graalvm.compiler.replacements.nodes.UnaryMathIntrinsicNode.UnaryOperation.SIN;
108 import static org.graalvm.compiler.replacements.nodes.UnaryMathIntrinsicNode.UnaryOperation.TAN;
109 import static jdk.internal.vm.compiler.word.LocationIdentity.any;
110 
111 import java.util.EnumMap;
112 
113 import jdk.internal.vm.compiler.collections.EconomicMap;
114 import org.graalvm.compiler.core.common.spi.ForeignCallDescriptor;
115 import org.graalvm.compiler.core.common.spi.ForeignCallsProvider;
116 import org.graalvm.compiler.debug.GraalError;
117 import org.graalvm.compiler.hotspot.CompilerRuntimeHotSpotVMConfig;
118 import org.graalvm.compiler.hotspot.GraalHotSpotVMConfig;
119 import org.graalvm.compiler.hotspot.HotSpotForeignCallLinkage;
120 import org.graalvm.compiler.hotspot.HotSpotGraalRuntimeProvider;
121 import org.graalvm.compiler.hotspot.stubs.ArrayStoreExceptionStub;
122 import org.graalvm.compiler.hotspot.stubs.ClassCastExceptionStub;
123 import org.graalvm.compiler.hotspot.stubs.CreateExceptionStub;
124 import org.graalvm.compiler.hotspot.stubs.DivisionByZeroExceptionStub;
125 import org.graalvm.compiler.hotspot.stubs.ExceptionHandlerStub;
126 import org.graalvm.compiler.hotspot.stubs.IntegerExactOverflowExceptionStub;
127 import org.graalvm.compiler.hotspot.stubs.LongExactOverflowExceptionStub;
128 import org.graalvm.compiler.hotspot.stubs.NullPointerExceptionStub;
129 import org.graalvm.compiler.hotspot.stubs.OutOfBoundsExceptionStub;
130 import org.graalvm.compiler.hotspot.stubs.Stub;
131 import org.graalvm.compiler.hotspot.stubs.UnwindExceptionToCallerStub;
132 import org.graalvm.compiler.hotspot.stubs.VerifyOopStub;
133 import org.graalvm.compiler.nodes.NamedLocationIdentity;
134 import org.graalvm.compiler.nodes.extended.BytecodeExceptionNode.BytecodeExceptionKind;
135 import org.graalvm.compiler.options.OptionValues;
136 import org.graalvm.compiler.replacements.arraycopy.ArrayCopyForeignCalls;
137 import org.graalvm.compiler.word.Word;
138 import org.graalvm.compiler.word.WordTypes;
139 import jdk.internal.vm.compiler.word.LocationIdentity;
140 
141 import jdk.vm.ci.code.CodeCacheProvider;
142 import jdk.vm.ci.hotspot.HotSpotJVMCIRuntime;
143 import jdk.vm.ci.meta.JavaKind;
144 import jdk.vm.ci.meta.MetaAccessProvider;
145 
146 /**
147  * HotSpot implementation of {@link ForeignCallsProvider}.
148  */
149 public abstract class HotSpotHostForeignCallsProvider extends HotSpotForeignCallsProviderImpl implements ArrayCopyForeignCalls {
150 
151     public static final ForeignCallDescriptor JAVA_TIME_MILLIS = new ForeignCallDescriptor("javaTimeMillis", long.class);
152     public static final ForeignCallDescriptor JAVA_TIME_NANOS = new ForeignCallDescriptor("javaTimeNanos", long.class);
153 
154     public static final ForeignCallDescriptor NOTIFY = new ForeignCallDescriptor("object_notify", boolean.class, Object.class);
155     public static final ForeignCallDescriptor NOTIFY_ALL = new ForeignCallDescriptor("object_notifyAll", boolean.class, Object.class);
156 
HotSpotHostForeignCallsProvider(HotSpotJVMCIRuntime jvmciRuntime, HotSpotGraalRuntimeProvider runtime, MetaAccessProvider metaAccess, CodeCacheProvider codeCache, WordTypes wordTypes)157     public HotSpotHostForeignCallsProvider(HotSpotJVMCIRuntime jvmciRuntime, HotSpotGraalRuntimeProvider runtime, MetaAccessProvider metaAccess, CodeCacheProvider codeCache,
158                     WordTypes wordTypes) {
159         super(jvmciRuntime, runtime, metaAccess, codeCache, wordTypes);
160     }
161 
link(Stub stub)162     protected static void link(Stub stub) {
163         stub.getLinkage().setCompiledStub(stub);
164     }
165 
166     @Override
lookupCheckcastArraycopyDescriptor(boolean uninit)167     public ForeignCallDescriptor lookupCheckcastArraycopyDescriptor(boolean uninit) {
168         return checkcastArraycopyDescriptors[uninit ? 1 : 0];
169     }
170 
171     @Override
lookupArraycopyDescriptor(JavaKind kind, boolean aligned, boolean disjoint, boolean uninit, boolean killAny)172     public ForeignCallDescriptor lookupArraycopyDescriptor(JavaKind kind, boolean aligned, boolean disjoint, boolean uninit, boolean killAny) {
173         if (uninit) {
174             assert kind == JavaKind.Object;
175             assert !killAny : "unsupported";
176             return uninitObjectArraycopyDescriptors[aligned ? 1 : 0][disjoint ? 1 : 0];
177         }
178         if (killAny) {
179             return arraycopyDescriptorsKillAny[aligned ? 1 : 0][disjoint ? 1 : 0].get(kind);
180         }
181         return arraycopyDescriptors[aligned ? 1 : 0][disjoint ? 1 : 0].get(kind);
182     }
183 
184     @SuppressWarnings("unchecked") private static final EnumMap<JavaKind, ForeignCallDescriptor>[][] arraycopyDescriptors = (EnumMap<JavaKind, ForeignCallDescriptor>[][]) new EnumMap<?, ?>[2][2];
185     @SuppressWarnings("unchecked") private static final EnumMap<JavaKind, ForeignCallDescriptor>[][] arraycopyDescriptorsKillAny = (EnumMap<JavaKind, ForeignCallDescriptor>[][]) new EnumMap<?, ?>[2][2];
186 
187     private static final ForeignCallDescriptor[][] uninitObjectArraycopyDescriptors = new ForeignCallDescriptor[2][2];
188     private static final ForeignCallDescriptor[] checkcastArraycopyDescriptors = new ForeignCallDescriptor[2];
189 
190     static {
191         // Populate the EnumMap instances
192         for (int i = 0; i < arraycopyDescriptors.length; i++) {
193             for (int j = 0; j < arraycopyDescriptors[i].length; j++) {
194                 arraycopyDescriptors[i][j] = new EnumMap<>(JavaKind.class);
195                 arraycopyDescriptorsKillAny[i][j] = new EnumMap<>(JavaKind.class);
196             }
197         }
198     }
199 
registerArraycopyDescriptor(EconomicMap<Long, ForeignCallDescriptor> descMap, JavaKind kind, boolean aligned, boolean disjoint, boolean uninit, boolean killAny, long routine)200     private void registerArraycopyDescriptor(EconomicMap<Long, ForeignCallDescriptor> descMap, JavaKind kind, boolean aligned, boolean disjoint, boolean uninit, boolean killAny, long routine) {
201         ForeignCallDescriptor desc = descMap.get(routine);
202         if (desc == null) {
203             desc = buildDescriptor(kind, aligned, disjoint, uninit, killAny, routine);
204             descMap.put(routine, desc);
205         }
206         if (uninit) {
207             assert kind == JavaKind.Object;
208             uninitObjectArraycopyDescriptors[aligned ? 1 : 0][disjoint ? 1 : 0] = desc;
209         } else if (killAny) {
210             arraycopyDescriptorsKillAny[aligned ? 1 : 0][disjoint ? 1 : 0].put(kind, desc);
211         } else {
212             arraycopyDescriptors[aligned ? 1 : 0][disjoint ? 1 : 0].put(kind, desc);
213         }
214     }
215 
buildDescriptor(JavaKind kind, boolean aligned, boolean disjoint, boolean uninit, boolean killAny, long routine)216     private ForeignCallDescriptor buildDescriptor(JavaKind kind, boolean aligned, boolean disjoint, boolean uninit, boolean killAny, long routine) {
217         assert !uninit || kind == JavaKind.Object;
218         String name = kind + (aligned ? "Aligned" : "") + (disjoint ? "Disjoint" : "") + (uninit ? "Uninit" : "") + "Arraycopy" + (killAny ? "KillAny" : "");
219         ForeignCallDescriptor desc = new ForeignCallDescriptor(name, void.class, Word.class, Word.class, Word.class);
220         LocationIdentity killed = killAny ? LocationIdentity.any() : NamedLocationIdentity.getArrayLocation(kind);
221         registerForeignCall(desc, routine, NativeCall, DESTROYS_REGISTERS, LEAF_NO_VZERO, NOT_REEXECUTABLE, killed);
222         return desc;
223     }
224 
registerCheckcastArraycopyDescriptor(boolean uninit, long routine)225     private void registerCheckcastArraycopyDescriptor(boolean uninit, long routine) {
226         String name = "Object" + (uninit ? "Uninit" : "") + "CheckcastArraycopy";
227         // Input:
228         // c_rarg0 - source array address
229         // c_rarg1 - destination array address
230         // c_rarg2 - element count, treated as ssize_t, can be zero
231         // c_rarg3 - size_t ckoff (super_check_offset)
232         // c_rarg4 - oop ckval (super_klass)
233         // return: 0 = success, n = number of copied elements xor'd with -1.
234         ForeignCallDescriptor desc = new ForeignCallDescriptor(name, int.class, Word.class, Word.class, Word.class, Word.class, Word.class);
235         LocationIdentity killed = NamedLocationIdentity.any();
236         registerForeignCall(desc, routine, NativeCall, DESTROYS_REGISTERS, LEAF_NO_VZERO, NOT_REEXECUTABLE, killed);
237         checkcastArraycopyDescriptors[uninit ? 1 : 0] = desc;
238     }
239 
registerArrayCopy(JavaKind kind, long routine, long alignedRoutine, long disjointRoutine, long alignedDisjointRoutine)240     private void registerArrayCopy(JavaKind kind,
241                     long routine,
242                     long alignedRoutine,
243                     long disjointRoutine,
244                     long alignedDisjointRoutine) {
245         registerArrayCopy(kind, routine, alignedRoutine, disjointRoutine, alignedDisjointRoutine, false);
246     }
247 
registerArrayCopy(JavaKind kind, long routine, long alignedRoutine, long disjointRoutine, long alignedDisjointRoutine, boolean uninit)248     private void registerArrayCopy(JavaKind kind,
249                     long routine,
250                     long alignedRoutine,
251                     long disjointRoutine,
252                     long alignedDisjointRoutine,
253                     boolean uninit) {
254         /*
255          * Sometimes the same function is used for multiple cases so share them when that's the case
256          * but only within the same Kind. For instance short and char are the same copy routines but
257          * they kill different memory so they still have to be distinct.
258          */
259         EconomicMap<Long, ForeignCallDescriptor> descMap = EconomicMap.create();
260         registerArraycopyDescriptor(descMap, kind, false, false, uninit, false, routine);
261         registerArraycopyDescriptor(descMap, kind, true, false, uninit, false, alignedRoutine);
262         registerArraycopyDescriptor(descMap, kind, false, true, uninit, false, disjointRoutine);
263         registerArraycopyDescriptor(descMap, kind, true, true, uninit, false, alignedDisjointRoutine);
264 
265         if (!uninit) {
266             EconomicMap<Long, ForeignCallDescriptor> killAnyDescMap = EconomicMap.create();
267             registerArraycopyDescriptor(killAnyDescMap, kind, false, false, uninit, true, routine);
268             registerArraycopyDescriptor(killAnyDescMap, kind, true, false, uninit, true, alignedRoutine);
269             registerArraycopyDescriptor(killAnyDescMap, kind, false, true, uninit, true, disjointRoutine);
270             registerArraycopyDescriptor(killAnyDescMap, kind, true, true, uninit, true, alignedDisjointRoutine);
271         }
272     }
273 
initialize(HotSpotProviders providers, OptionValues options)274     public void initialize(HotSpotProviders providers, OptionValues options) {
275         GraalHotSpotVMConfig c = runtime.getVMConfig();
276         registerForeignCall(DEOPTIMIZATION_HANDLER, c.handleDeoptStub, NativeCall, PRESERVES_REGISTERS, LEAF_NO_VZERO, REEXECUTABLE, NO_LOCATIONS);
277         registerForeignCall(UNCOMMON_TRAP_HANDLER, c.uncommonTrapStub, NativeCall, PRESERVES_REGISTERS, LEAF_NO_VZERO, REEXECUTABLE, NO_LOCATIONS);
278         registerForeignCall(IC_MISS_HANDLER, c.inlineCacheMissStub, NativeCall, PRESERVES_REGISTERS, LEAF_NO_VZERO, REEXECUTABLE, NO_LOCATIONS);
279 
280         if (c.enableStackReservedZoneAddress != 0) {
281             assert c.throwDelayedStackOverflowErrorEntry != 0 : "both must exist";
282             registerForeignCall(ENABLE_STACK_RESERVED_ZONE, c.enableStackReservedZoneAddress, NativeCall, DESTROYS_REGISTERS, LEAF_NO_VZERO, REEXECUTABLE, NO_LOCATIONS);
283             registerForeignCall(THROW_DELAYED_STACKOVERFLOW_ERROR, c.throwDelayedStackOverflowErrorEntry, NativeCall, DESTROYS_REGISTERS, LEAF_NO_VZERO, REEXECUTABLE, NO_LOCATIONS);
284         }
285 
286         registerForeignCall(JAVA_TIME_MILLIS, c.javaTimeMillisAddress, NativeCall, DESTROYS_REGISTERS, LEAF_NO_VZERO, REEXECUTABLE, NO_LOCATIONS);
287         registerForeignCall(JAVA_TIME_NANOS, c.javaTimeNanosAddress, NativeCall, DESTROYS_REGISTERS, LEAF_NO_VZERO, REEXECUTABLE, NO_LOCATIONS);
288 
289         registerMathStubs(c, providers, options);
290 
291         registerForeignCall(ARITHMETIC_FREM, c.fremAddress, NativeCall, DESTROYS_REGISTERS, LEAF, REEXECUTABLE, NO_LOCATIONS);
292         registerForeignCall(ARITHMETIC_DREM, c.dremAddress, NativeCall, DESTROYS_REGISTERS, LEAF, REEXECUTABLE, NO_LOCATIONS);
293 
294         registerForeignCall(LOAD_AND_CLEAR_EXCEPTION, c.loadAndClearExceptionAddress, NativeCall, DESTROYS_REGISTERS, LEAF_NO_VZERO, REEXECUTABLE_ONLY_AFTER_EXCEPTION, any());
295 
296         registerForeignCall(EXCEPTION_HANDLER_FOR_PC, c.exceptionHandlerForPcAddress, NativeCall, DESTROYS_REGISTERS, SAFEPOINT, REEXECUTABLE, any());
297         registerForeignCall(EXCEPTION_HANDLER_FOR_RETURN_ADDRESS, c.exceptionHandlerForReturnAddressAddress, NativeCall, DESTROYS_REGISTERS, SAFEPOINT, REEXECUTABLE, any());
298 
299         CreateExceptionStub.registerForeignCalls(c, this);
300 
301         /*
302          * This message call is registered twice, where the second one must only be used for calls
303          * that do not return, i.e., that exit the VM.
304          */
305         registerForeignCall(VM_MESSAGE_C, c.vmMessageAddress, NativeCall, DESTROYS_REGISTERS, SAFEPOINT, REEXECUTABLE, NO_LOCATIONS);
306         registerForeignCall(ASSERTION_VM_MESSAGE_C, c.vmMessageAddress, NativeCall, PRESERVES_REGISTERS, LEAF, REEXECUTABLE, NO_LOCATIONS);
307 
308         linkForeignCall(options, providers, NEW_INSTANCE, c.newInstanceAddress, PREPEND_THREAD, SAFEPOINT, REEXECUTABLE, TLAB_TOP_LOCATION, TLAB_END_LOCATION);
309         linkForeignCall(options, providers, NEW_ARRAY, c.newArrayAddress, PREPEND_THREAD, SAFEPOINT, REEXECUTABLE, TLAB_TOP_LOCATION, TLAB_END_LOCATION);
310         linkForeignCall(options, providers, NEW_MULTI_ARRAY, c.newMultiArrayAddress, PREPEND_THREAD, SAFEPOINT, REEXECUTABLE, TLAB_TOP_LOCATION, TLAB_END_LOCATION);
311         linkForeignCall(options, providers, DYNAMIC_NEW_INSTANCE, c.dynamicNewInstanceAddress, PREPEND_THREAD, SAFEPOINT, REEXECUTABLE);
312 
313         if (c.areNullAllocationStubsAvailable()) {
314             linkForeignCall(options, providers, NEW_INSTANCE_OR_NULL, c.newInstanceOrNullAddress, PREPEND_THREAD, SAFEPOINT, REEXECUTABLE, TLAB_TOP_LOCATION, TLAB_END_LOCATION);
315             linkForeignCall(options, providers, NEW_ARRAY_OR_NULL, c.newArrayOrNullAddress, PREPEND_THREAD, SAFEPOINT, REEXECUTABLE, TLAB_TOP_LOCATION, TLAB_END_LOCATION);
316             linkForeignCall(options, providers, NEW_MULTI_ARRAY_OR_NULL, c.newMultiArrayOrNullAddress, PREPEND_THREAD, SAFEPOINT, REEXECUTABLE, TLAB_TOP_LOCATION, TLAB_END_LOCATION);
317             linkForeignCall(options, providers, DYNAMIC_NEW_INSTANCE_OR_NULL, c.dynamicNewInstanceOrNullAddress, PREPEND_THREAD, SAFEPOINT, REEXECUTABLE);
318         }
319 
320         link(new ExceptionHandlerStub(options, providers, foreignCalls.get(EXCEPTION_HANDLER)));
321         link(new UnwindExceptionToCallerStub(options, providers, registerStubCall(UNWIND_EXCEPTION_TO_CALLER, SAFEPOINT, REEXECUTABLE_ONLY_AFTER_EXCEPTION, any())));
322         link(new VerifyOopStub(options, providers, registerStubCall(VERIFY_OOP, LEAF_NO_VZERO, REEXECUTABLE, NO_LOCATIONS)));
323 
324         EnumMap<BytecodeExceptionKind, ForeignCallDescriptor> exceptionRuntimeCalls = DefaultHotSpotLoweringProvider.RuntimeCalls.runtimeCalls;
325         link(new ArrayStoreExceptionStub(options, providers, registerStubCall(exceptionRuntimeCalls.get(BytecodeExceptionKind.ARRAY_STORE), SAFEPOINT, REEXECUTABLE, any())));
326         link(new ClassCastExceptionStub(options, providers, registerStubCall(exceptionRuntimeCalls.get(BytecodeExceptionKind.CLASS_CAST), SAFEPOINT, REEXECUTABLE, any())));
327         link(new NullPointerExceptionStub(options, providers, registerStubCall(exceptionRuntimeCalls.get(BytecodeExceptionKind.NULL_POINTER), SAFEPOINT, REEXECUTABLE, any())));
328         link(new OutOfBoundsExceptionStub(options, providers, registerStubCall(exceptionRuntimeCalls.get(BytecodeExceptionKind.OUT_OF_BOUNDS), SAFEPOINT, REEXECUTABLE, any())));
329         link(new DivisionByZeroExceptionStub(options, providers, registerStubCall(exceptionRuntimeCalls.get(BytecodeExceptionKind.DIVISION_BY_ZERO), SAFEPOINT, REEXECUTABLE, any())));
330         link(new IntegerExactOverflowExceptionStub(options, providers, registerStubCall(exceptionRuntimeCalls.get(BytecodeExceptionKind.INTEGER_EXACT_OVERFLOW), SAFEPOINT, REEXECUTABLE, any())));
331         link(new LongExactOverflowExceptionStub(options, providers, registerStubCall(exceptionRuntimeCalls.get(BytecodeExceptionKind.LONG_EXACT_OVERFLOW), SAFEPOINT, REEXECUTABLE, any())));
332 
333         linkForeignCall(options, providers, IDENTITY_HASHCODE, c.identityHashCodeAddress, PREPEND_THREAD, SAFEPOINT, REEXECUTABLE_ONLY_AFTER_EXCEPTION, MARK_WORD_LOCATION);
334         linkForeignCall(options, providers, REGISTER_FINALIZER, c.registerFinalizerAddress, PREPEND_THREAD, SAFEPOINT, REEXECUTABLE_ONLY_AFTER_EXCEPTION, any());
335         linkForeignCall(options, providers, MONITORENTER, c.monitorenterAddress, PREPEND_THREAD, SAFEPOINT, REEXECUTABLE_ONLY_AFTER_EXCEPTION, any());
336         linkForeignCall(options, providers, MONITOREXIT, c.monitorexitAddress, PREPEND_THREAD, STACK_INSPECTABLE_LEAF, REEXECUTABLE_ONLY_AFTER_EXCEPTION, any());
337         linkForeignCall(options, providers, NOTIFY, c.notifyAddress, PREPEND_THREAD, SAFEPOINT, REEXECUTABLE_ONLY_AFTER_EXCEPTION, any());
338         linkForeignCall(options, providers, NOTIFY_ALL, c.notifyAllAddress, PREPEND_THREAD, SAFEPOINT, REEXECUTABLE_ONLY_AFTER_EXCEPTION, any());
339         linkForeignCall(options, providers, LOG_PRINTF, c.logPrintfAddress, PREPEND_THREAD, LEAF, REEXECUTABLE, NO_LOCATIONS);
340         linkForeignCall(options, providers, LOG_OBJECT, c.logObjectAddress, PREPEND_THREAD, LEAF, REEXECUTABLE, NO_LOCATIONS);
341         linkForeignCall(options, providers, LOG_PRIMITIVE, c.logPrimitiveAddress, PREPEND_THREAD, LEAF, REEXECUTABLE, NO_LOCATIONS);
342         linkForeignCall(options, providers, VM_ERROR, c.vmErrorAddress, PREPEND_THREAD, LEAF_NO_VZERO, REEXECUTABLE, NO_LOCATIONS);
343         linkForeignCall(options, providers, OSR_MIGRATION_END, c.osrMigrationEndAddress, DONT_PREPEND_THREAD, LEAF_NO_VZERO, REEXECUTABLE_ONLY_AFTER_EXCEPTION, NO_LOCATIONS);
344         linkForeignCall(options, providers, G1WBPRECALL, c.writeBarrierPreAddress, PREPEND_THREAD, LEAF_NO_VZERO, REEXECUTABLE, NO_LOCATIONS);
345         linkForeignCall(options, providers, G1WBPOSTCALL, c.writeBarrierPostAddress, PREPEND_THREAD, LEAF_NO_VZERO, REEXECUTABLE, NO_LOCATIONS);
346         linkForeignCall(options, providers, VALIDATE_OBJECT, c.validateObject, PREPEND_THREAD, LEAF_NO_VZERO, REEXECUTABLE, NO_LOCATIONS);
347 
348         if (GeneratePIC.getValue(options)) {
349             registerForeignCall(WRONG_METHOD_HANDLER, c.handleWrongMethodStub, NativeCall, PRESERVES_REGISTERS, LEAF_NO_VZERO, REEXECUTABLE, NO_LOCATIONS);
350             CompilerRuntimeHotSpotVMConfig cr = new CompilerRuntimeHotSpotVMConfig(HotSpotJVMCIRuntime.runtime().getConfigStore());
351             linkForeignCall(options, providers, RESOLVE_STRING_BY_SYMBOL, cr.resolveStringBySymbol, PREPEND_THREAD, SAFEPOINT, REEXECUTABLE, TLAB_TOP_LOCATION, TLAB_END_LOCATION);
352             linkForeignCall(options, providers, RESOLVE_DYNAMIC_INVOKE, cr.resolveDynamicInvoke, PREPEND_THREAD, SAFEPOINT, REEXECUTABLE, any());
353             linkForeignCall(options, providers, RESOLVE_KLASS_BY_SYMBOL, cr.resolveKlassBySymbol, PREPEND_THREAD, SAFEPOINT, REEXECUTABLE, any());
354             linkForeignCall(options, providers, RESOLVE_METHOD_BY_SYMBOL_AND_LOAD_COUNTERS, cr.resolveMethodBySymbolAndLoadCounters, PREPEND_THREAD, SAFEPOINT, REEXECUTABLE, NO_LOCATIONS);
355             linkForeignCall(options, providers, INITIALIZE_KLASS_BY_SYMBOL, cr.initializeKlassBySymbol, PREPEND_THREAD, SAFEPOINT, NOT_REEXECUTABLE, any());
356             linkForeignCall(options, providers, INVOCATION_EVENT, cr.invocationEvent, PREPEND_THREAD, SAFEPOINT, REEXECUTABLE, NO_LOCATIONS);
357             linkForeignCall(options, providers, BACKEDGE_EVENT, cr.backedgeEvent, PREPEND_THREAD, SAFEPOINT, REEXECUTABLE, NO_LOCATIONS);
358         }
359 
360         // Cannot be a leaf as VM acquires Thread_lock which requires thread_in_vm state
361         linkForeignCall(options, providers, THREAD_IS_INTERRUPTED, c.threadIsInterruptedAddress, PREPEND_THREAD, SAFEPOINT, REEXECUTABLE_ONLY_AFTER_EXCEPTION, any());
362 
363         linkForeignCall(options, providers, TEST_DEOPTIMIZE_CALL_INT, c.testDeoptimizeCallInt, PREPEND_THREAD, SAFEPOINT, REEXECUTABLE, any());
364 
365         registerArrayCopy(JavaKind.Byte, c.jbyteArraycopy, c.jbyteAlignedArraycopy, c.jbyteDisjointArraycopy, c.jbyteAlignedDisjointArraycopy);
366         registerArrayCopy(JavaKind.Boolean, c.jbyteArraycopy, c.jbyteAlignedArraycopy, c.jbyteDisjointArraycopy, c.jbyteAlignedDisjointArraycopy);
367         registerArrayCopy(JavaKind.Char, c.jshortArraycopy, c.jshortAlignedArraycopy, c.jshortDisjointArraycopy, c.jshortAlignedDisjointArraycopy);
368         registerArrayCopy(JavaKind.Short, c.jshortArraycopy, c.jshortAlignedArraycopy, c.jshortDisjointArraycopy, c.jshortAlignedDisjointArraycopy);
369         registerArrayCopy(JavaKind.Int, c.jintArraycopy, c.jintAlignedArraycopy, c.jintDisjointArraycopy, c.jintAlignedDisjointArraycopy);
370         registerArrayCopy(JavaKind.Float, c.jintArraycopy, c.jintAlignedArraycopy, c.jintDisjointArraycopy, c.jintAlignedDisjointArraycopy);
371         registerArrayCopy(JavaKind.Long, c.jlongArraycopy, c.jlongAlignedArraycopy, c.jlongDisjointArraycopy, c.jlongAlignedDisjointArraycopy);
372         registerArrayCopy(JavaKind.Double, c.jlongArraycopy, c.jlongAlignedArraycopy, c.jlongDisjointArraycopy, c.jlongAlignedDisjointArraycopy);
373         registerArrayCopy(JavaKind.Object, c.oopArraycopy, c.oopAlignedArraycopy, c.oopDisjointArraycopy, c.oopAlignedDisjointArraycopy);
374         registerArrayCopy(JavaKind.Object, c.oopArraycopyUninit, c.oopAlignedArraycopyUninit, c.oopDisjointArraycopyUninit, c.oopAlignedDisjointArraycopyUninit, true);
375 
376         registerCheckcastArraycopyDescriptor(true, c.checkcastArraycopyUninit);
377         registerCheckcastArraycopyDescriptor(false, c.checkcastArraycopy);
378 
379         registerForeignCall(GENERIC_ARRAYCOPY, c.genericArraycopy, NativeCall, DESTROYS_REGISTERS, LEAF_NO_VZERO, REEXECUTABLE_ONLY_AFTER_EXCEPTION, NamedLocationIdentity.any());
380         registerForeignCall(UNSAFE_ARRAYCOPY, c.unsafeArraycopy, NativeCall, DESTROYS_REGISTERS, LEAF_NO_VZERO, REEXECUTABLE_ONLY_AFTER_EXCEPTION, NamedLocationIdentity.any());
381 
382         if (c.useMultiplyToLenIntrinsic()) {
383             registerForeignCall(MULTIPLY_TO_LEN, c.multiplyToLen, NativeCall, DESTROYS_REGISTERS, LEAF_NO_VZERO, REEXECUTABLE_ONLY_AFTER_EXCEPTION,
384                             NamedLocationIdentity.getArrayLocation(JavaKind.Int));
385         }
386 
387         if (c.useSHA1Intrinsics()) {
388             registerForeignCall(SHA_IMPL_COMPRESS, c.sha1ImplCompress, NativeCall, DESTROYS_REGISTERS, LEAF, REEXECUTABLE_ONLY_AFTER_EXCEPTION, NamedLocationIdentity.any());
389             registerForeignCall(SHA_IMPL_COMPRESS_MB, c.sha1ImplCompressMultiBlock, NativeCall, DESTROYS_REGISTERS, LEAF, REEXECUTABLE_ONLY_AFTER_EXCEPTION, NamedLocationIdentity.any());
390         }
391         if (c.useSHA256Intrinsics()) {
392             registerForeignCall(SHA2_IMPL_COMPRESS, c.sha256ImplCompress, NativeCall, DESTROYS_REGISTERS, LEAF, REEXECUTABLE_ONLY_AFTER_EXCEPTION, NamedLocationIdentity.any());
393             registerForeignCall(SHA2_IMPL_COMPRESS_MB, c.sha256ImplCompressMultiBlock, NativeCall, DESTROYS_REGISTERS, LEAF, REEXECUTABLE_ONLY_AFTER_EXCEPTION, NamedLocationIdentity.any());
394         }
395         if (c.useSHA512Intrinsics()) {
396             registerForeignCall(SHA5_IMPL_COMPRESS, c.sha512ImplCompress, NativeCall, DESTROYS_REGISTERS, LEAF, REEXECUTABLE_ONLY_AFTER_EXCEPTION, NamedLocationIdentity.any());
397             registerForeignCall(SHA5_IMPL_COMPRESS_MB, c.sha512ImplCompressMultiBlock, NativeCall, DESTROYS_REGISTERS, LEAF, REEXECUTABLE_ONLY_AFTER_EXCEPTION, NamedLocationIdentity.any());
398         }
399         if (c.useGHASHIntrinsics()) {
400             registerForeignCall(GHASH_PROCESS_BLOCKS, c.ghashProcessBlocks, NativeCall, DESTROYS_REGISTERS, LEAF, REEXECUTABLE_ONLY_AFTER_EXCEPTION, NamedLocationIdentity.any());
401         }
402         if (c.useBase64Intrinsics()) {
403             registerForeignCall(BASE64_ENCODE_BLOCK, c.base64EncodeBlock, NativeCall, DESTROYS_REGISTERS, LEAF, REEXECUTABLE_ONLY_AFTER_EXCEPTION, NamedLocationIdentity.any());
404         }
405         if (c.useMulAddIntrinsic()) {
406             registerForeignCall(MUL_ADD, c.mulAdd, NativeCall, DESTROYS_REGISTERS, LEAF_NO_VZERO, REEXECUTABLE_ONLY_AFTER_EXCEPTION, NamedLocationIdentity.getArrayLocation(JavaKind.Int));
407         }
408         if (c.useMontgomeryMultiplyIntrinsic()) {
409             registerForeignCall(MONTGOMERY_MULTIPLY, c.montgomeryMultiply, NativeCall, DESTROYS_REGISTERS, LEAF_NO_VZERO, REEXECUTABLE_ONLY_AFTER_EXCEPTION,
410                             NamedLocationIdentity.getArrayLocation(JavaKind.Int));
411         }
412         if (c.useMontgomerySquareIntrinsic()) {
413             registerForeignCall(MONTGOMERY_SQUARE, c.montgomerySquare, NativeCall, DESTROYS_REGISTERS, LEAF_NO_VZERO, REEXECUTABLE_ONLY_AFTER_EXCEPTION,
414                             NamedLocationIdentity.getArrayLocation(JavaKind.Int));
415         }
416         if (c.useSquareToLenIntrinsic()) {
417             registerForeignCall(SQUARE_TO_LEN, c.squareToLen, NativeCall, DESTROYS_REGISTERS, LEAF_NO_VZERO, REEXECUTABLE_ONLY_AFTER_EXCEPTION, NamedLocationIdentity.getArrayLocation(JavaKind.Int));
418         }
419 
420         if (c.useAESIntrinsics) {
421             /*
422              * When the java.ext.dirs property is modified then the crypto classes might not be
423              * found. If that's the case we ignore the ClassNotFoundException and continue since we
424              * cannot replace a non-existing method anyway.
425              */
426             try {
427                 // These stubs do callee saving
428                 registerForeignCall(ENCRYPT_BLOCK, c.aescryptEncryptBlockStub, NativeCall, PRESERVES_REGISTERS, LEAF, REEXECUTABLE_ONLY_AFTER_EXCEPTION,
429                                 NamedLocationIdentity.getArrayLocation(JavaKind.Byte));
430                 registerForeignCall(DECRYPT_BLOCK, c.aescryptDecryptBlockStub, NativeCall, PRESERVES_REGISTERS, LEAF, REEXECUTABLE_ONLY_AFTER_EXCEPTION,
431                                 NamedLocationIdentity.getArrayLocation(JavaKind.Byte));
432                 registerForeignCall(DECRYPT_BLOCK_WITH_ORIGINAL_KEY, c.aescryptDecryptBlockStub, NativeCall, PRESERVES_REGISTERS, LEAF, REEXECUTABLE_ONLY_AFTER_EXCEPTION,
433                                 NamedLocationIdentity.getArrayLocation(JavaKind.Byte));
434             } catch (GraalError e) {
435                 if (!(e.getCause() instanceof ClassNotFoundException)) {
436                     throw e;
437                 }
438             }
439             try {
440                 // These stubs do callee saving
441                 registerForeignCall(ENCRYPT, c.cipherBlockChainingEncryptAESCryptStub, NativeCall, PRESERVES_REGISTERS, LEAF, REEXECUTABLE_ONLY_AFTER_EXCEPTION,
442                                 NamedLocationIdentity.getArrayLocation(JavaKind.Byte));
443                 registerForeignCall(DECRYPT, c.cipherBlockChainingDecryptAESCryptStub, NativeCall, PRESERVES_REGISTERS, LEAF, REEXECUTABLE_ONLY_AFTER_EXCEPTION,
444                                 NamedLocationIdentity.getArrayLocation(JavaKind.Byte));
445                 registerForeignCall(DECRYPT_WITH_ORIGINAL_KEY, c.cipherBlockChainingDecryptAESCryptStub, NativeCall, PRESERVES_REGISTERS, LEAF, REEXECUTABLE_ONLY_AFTER_EXCEPTION,
446                                 NamedLocationIdentity.getArrayLocation(JavaKind.Byte));
447             } catch (GraalError e) {
448                 if (!(e.getCause() instanceof ClassNotFoundException)) {
449                     throw e;
450                 }
451             }
452         }
453 
454         if (c.useAESCTRIntrinsics) {
455             assert (c.counterModeAESCrypt != 0L);
456             registerForeignCall(COUNTERMODE_IMPL_CRYPT, c.counterModeAESCrypt, NativeCall, PRESERVES_REGISTERS, LEAF, REEXECUTABLE_ONLY_AFTER_EXCEPTION,
457                             NamedLocationIdentity.any());
458         }
459 
460         if (c.useVectorizedMismatchIntrinsic) {
461             assert (c.vectorizedMismatch != 0L);
462             registerForeignCall(VECTORIZED_MISMATCHED, c.vectorizedMismatch, NativeCall, PRESERVES_REGISTERS, LEAF, REEXECUTABLE_ONLY_AFTER_EXCEPTION,
463                             NamedLocationIdentity.any());
464 
465         }
466     }
467 
getForeignCall(ForeignCallDescriptor descriptor)468     public HotSpotForeignCallLinkage getForeignCall(ForeignCallDescriptor descriptor) {
469         assert foreignCalls != null : descriptor;
470         return foreignCalls.get(descriptor);
471     }
472 
473     @SuppressWarnings("unused")
registerMathStubs(GraalHotSpotVMConfig hotSpotVMConfig, HotSpotProviders providers, OptionValues options)474     protected void registerMathStubs(GraalHotSpotVMConfig hotSpotVMConfig, HotSpotProviders providers, OptionValues options) {
475         registerForeignCall(SIN.foreignCallDescriptor, hotSpotVMConfig.arithmeticSinAddress, NativeCall, DESTROYS_REGISTERS, LEAF, REEXECUTABLE, NO_LOCATIONS);
476         registerForeignCall(COS.foreignCallDescriptor, hotSpotVMConfig.arithmeticCosAddress, NativeCall, DESTROYS_REGISTERS, LEAF, REEXECUTABLE, NO_LOCATIONS);
477         registerForeignCall(TAN.foreignCallDescriptor, hotSpotVMConfig.arithmeticTanAddress, NativeCall, DESTROYS_REGISTERS, LEAF, REEXECUTABLE, NO_LOCATIONS);
478         registerForeignCall(EXP.foreignCallDescriptor, hotSpotVMConfig.arithmeticExpAddress, NativeCall, DESTROYS_REGISTERS, LEAF, REEXECUTABLE, NO_LOCATIONS);
479         registerForeignCall(LOG.foreignCallDescriptor, hotSpotVMConfig.arithmeticLogAddress, NativeCall, DESTROYS_REGISTERS, LEAF, REEXECUTABLE, NO_LOCATIONS);
480         registerForeignCall(LOG10.foreignCallDescriptor, hotSpotVMConfig.arithmeticLog10Address, NativeCall, DESTROYS_REGISTERS, LEAF, REEXECUTABLE, NO_LOCATIONS);
481         registerForeignCall(POW.foreignCallDescriptor, hotSpotVMConfig.arithmeticPowAddress, NativeCall, DESTROYS_REGISTERS, LEAF, REEXECUTABLE, NO_LOCATIONS);
482     }
483 }
484