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