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