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