1 /* 2 * Copyright (c) 2015, 2017, 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 package org.graalvm.compiler.hotspot.meta; 24 25 import static org.graalvm.compiler.core.common.GraalOptions.GeneratePIC; 26 import static org.graalvm.compiler.hotspot.meta.HotSpotAOTProfilingPlugin.Options.TieredAOT; 27 import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.JAVA_THREAD_THREAD_OBJECT_LOCATION; 28 import static org.graalvm.compiler.java.BytecodeParserOptions.InlineDuringParsing; 29 import static org.graalvm.compiler.serviceprovider.JDK9Method.Java8OrEarlier; 30 31 import java.lang.invoke.ConstantCallSite; 32 import java.lang.invoke.MutableCallSite; 33 import java.lang.invoke.VolatileCallSite; 34 import java.lang.reflect.Method; 35 import java.lang.reflect.Modifier; 36 import java.math.BigInteger; 37 import java.util.zip.CRC32; 38 39 import org.graalvm.compiler.api.replacements.SnippetReflectionProvider; 40 import org.graalvm.compiler.bytecode.BytecodeProvider; 41 import org.graalvm.compiler.core.common.spi.ForeignCallsProvider; 42 import org.graalvm.compiler.debug.GraalError; 43 import org.graalvm.compiler.hotspot.GraalHotSpotVMConfig; 44 import org.graalvm.compiler.hotspot.nodes.CurrentJavaThreadNode; 45 import org.graalvm.compiler.hotspot.replacements.AESCryptSubstitutions; 46 import org.graalvm.compiler.hotspot.replacements.BigIntegerSubstitutions; 47 import org.graalvm.compiler.hotspot.replacements.CRC32Substitutions; 48 import org.graalvm.compiler.hotspot.replacements.CallSiteTargetNode; 49 import org.graalvm.compiler.hotspot.replacements.CipherBlockChainingSubstitutions; 50 import org.graalvm.compiler.hotspot.replacements.ClassGetHubNode; 51 import org.graalvm.compiler.hotspot.replacements.HotSpotClassSubstitutions; 52 import org.graalvm.compiler.hotspot.replacements.IdentityHashCodeNode; 53 import org.graalvm.compiler.hotspot.replacements.ObjectCloneNode; 54 import org.graalvm.compiler.hotspot.replacements.ObjectSubstitutions; 55 import org.graalvm.compiler.hotspot.replacements.ReflectionGetCallerClassNode; 56 import org.graalvm.compiler.hotspot.replacements.ReflectionSubstitutions; 57 import org.graalvm.compiler.hotspot.replacements.SHA2Substitutions; 58 import org.graalvm.compiler.hotspot.replacements.SHA5Substitutions; 59 import org.graalvm.compiler.hotspot.replacements.SHASubstitutions; 60 import org.graalvm.compiler.hotspot.replacements.ThreadSubstitutions; 61 import org.graalvm.compiler.hotspot.replacements.arraycopy.ArrayCopyNode; 62 import org.graalvm.compiler.hotspot.word.HotSpotWordTypes; 63 import org.graalvm.compiler.nodes.ConstantNode; 64 import org.graalvm.compiler.nodes.DynamicPiNode; 65 import org.graalvm.compiler.nodes.FixedGuardNode; 66 import org.graalvm.compiler.nodes.LogicNode; 67 import org.graalvm.compiler.nodes.NamedLocationIdentity; 68 import org.graalvm.compiler.nodes.PiNode; 69 import org.graalvm.compiler.nodes.ValueNode; 70 import org.graalvm.compiler.nodes.calc.AddNode; 71 import org.graalvm.compiler.nodes.calc.LeftShiftNode; 72 import org.graalvm.compiler.nodes.graphbuilderconf.ForeignCallPlugin; 73 import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderConfiguration.Plugins; 74 import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderContext; 75 import org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugin; 76 import org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugin.Receiver; 77 import org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugins; 78 import org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugins.Registration; 79 import org.graalvm.compiler.nodes.graphbuilderconf.NodeIntrinsicPluginFactory; 80 import org.graalvm.compiler.nodes.java.InstanceOfDynamicNode; 81 import org.graalvm.compiler.nodes.memory.HeapAccess.BarrierType; 82 import org.graalvm.compiler.nodes.memory.address.AddressNode; 83 import org.graalvm.compiler.nodes.memory.address.OffsetAddressNode; 84 import org.graalvm.compiler.nodes.spi.StampProvider; 85 import org.graalvm.compiler.nodes.util.GraphUtil; 86 import org.graalvm.compiler.options.OptionValues; 87 import org.graalvm.compiler.phases.tiers.CompilerConfiguration; 88 import org.graalvm.compiler.replacements.InlineDuringParsingPlugin; 89 import org.graalvm.compiler.replacements.MethodHandlePlugin; 90 import org.graalvm.compiler.replacements.NodeIntrinsificationProvider; 91 import org.graalvm.compiler.replacements.ReplacementsImpl; 92 import org.graalvm.compiler.replacements.StandardGraphBuilderPlugins; 93 import org.graalvm.compiler.serviceprovider.GraalServices; 94 import org.graalvm.compiler.serviceprovider.JDK9Method; 95 import org.graalvm.compiler.word.WordOperationPlugin; 96 import org.graalvm.compiler.word.WordTypes; 97 import org.graalvm.word.LocationIdentity; 98 99 import jdk.vm.ci.code.CodeUtil; 100 import jdk.vm.ci.meta.ConstantReflectionProvider; 101 import jdk.vm.ci.meta.DeoptimizationAction; 102 import jdk.vm.ci.meta.DeoptimizationReason; 103 import jdk.vm.ci.meta.JavaKind; 104 import jdk.vm.ci.meta.MetaAccessProvider; 105 import jdk.vm.ci.meta.ResolvedJavaMethod; 106 import sun.misc.Unsafe; 107 108 /** 109 * Defines the {@link Plugins} used when running on HotSpot. 110 */ 111 public class HotSpotGraphBuilderPlugins { 112 113 /** 114 * Creates a {@link Plugins} object that should be used when running on HotSpot. 115 * 116 * @param constantReflection 117 * @param snippetReflection 118 * @param foreignCalls 119 * @param stampProvider 120 */ 121 public static Plugins create(CompilerConfiguration compilerConfiguration, GraalHotSpotVMConfig config, HotSpotWordTypes wordTypes, MetaAccessProvider metaAccess, 122 ConstantReflectionProvider constantReflection, SnippetReflectionProvider snippetReflection, ForeignCallsProvider foreignCalls, StampProvider stampProvider, 123 ReplacementsImpl replacements) { 124 InvocationPlugins invocationPlugins = new HotSpotInvocationPlugins(config, compilerConfiguration); 125 126 Plugins plugins = new Plugins(invocationPlugins); 127 NodeIntrinsificationProvider nodeIntrinsificationProvider = new NodeIntrinsificationProvider(metaAccess, snippetReflection, foreignCalls, wordTypes); 128 HotSpotWordOperationPlugin wordOperationPlugin = new HotSpotWordOperationPlugin(snippetReflection, wordTypes); 129 HotSpotNodePlugin nodePlugin = new HotSpotNodePlugin(wordOperationPlugin); 130 131 plugins.appendTypePlugin(nodePlugin); 132 plugins.appendNodePlugin(nodePlugin); 133 OptionValues options = replacements.getOptions(); 134 if (!GeneratePIC.getValue(options)) { 135 plugins.appendNodePlugin(new MethodHandlePlugin(constantReflection.getMethodHandleAccess(), true)); 136 } 137 plugins.appendInlineInvokePlugin(replacements); 138 if (InlineDuringParsing.getValue(options)) { 139 plugins.appendInlineInvokePlugin(new InlineDuringParsingPlugin()); 140 } 141 142 if (GeneratePIC.getValue(options)) { 143 plugins.setClassInitializationPlugin(new HotSpotClassInitializationPlugin()); 144 if (TieredAOT.getValue(options)) { 145 plugins.setProfilingPlugin(new HotSpotAOTProfilingPlugin()); 146 } 147 } 148 149 invocationPlugins.defer(new Runnable() { 150 151 @Override 152 public void run() { 153 BytecodeProvider replacementBytecodeProvider = replacements.getDefaultReplacementBytecodeProvider(); 154 registerObjectPlugins(invocationPlugins, options, replacementBytecodeProvider); 155 registerClassPlugins(plugins, config, replacementBytecodeProvider); 156 registerSystemPlugins(invocationPlugins, foreignCalls); 157 registerThreadPlugins(invocationPlugins, metaAccess, wordTypes, config, replacementBytecodeProvider); 158 if (!GeneratePIC.getValue(options)) { 159 registerCallSitePlugins(invocationPlugins); 160 } 161 registerReflectionPlugins(invocationPlugins, replacementBytecodeProvider); 162 registerConstantPoolPlugins(invocationPlugins, wordTypes, config, replacementBytecodeProvider); 163 registerAESPlugins(invocationPlugins, config, replacementBytecodeProvider); 164 registerCRC32Plugins(invocationPlugins, config, replacementBytecodeProvider); 165 registerBigIntegerPlugins(invocationPlugins, config, replacementBytecodeProvider); 166 registerSHAPlugins(invocationPlugins, config, replacementBytecodeProvider); 167 registerUnsafePlugins(invocationPlugins, replacementBytecodeProvider); 168 StandardGraphBuilderPlugins.registerInvocationPlugins(metaAccess, snippetReflection, invocationPlugins, replacementBytecodeProvider, true); 169 170 for (NodeIntrinsicPluginFactory factory : GraalServices.load(NodeIntrinsicPluginFactory.class)) { 171 factory.registerPlugins(invocationPlugins, nodeIntrinsificationProvider); 172 } 173 } 174 }); 175 return plugins; 176 } 177 178 private static void registerObjectPlugins(InvocationPlugins plugins, OptionValues options, BytecodeProvider bytecodeProvider) { 179 Registration r = new Registration(plugins, Object.class, bytecodeProvider); 180 if (!GeneratePIC.getValue(options)) { 181 // FIXME: clone() requires speculation and requires a fix in here (to check that 182 // b.getAssumptions() != null), and in ReplacementImpl.getSubstitution() where there is 183 // an instantiation of IntrinsicGraphBuilder using a constructor that sets 184 // AllowAssumptions to YES automatically. The former has to inherit the assumptions 185 // settings from the root compile instead. So, for now, I'm disabling it for 186 // GeneratePIC. 187 r.register1("clone", Receiver.class, new InvocationPlugin() { 188 @Override 189 public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver) { 190 ValueNode object = receiver.get(); 191 b.addPush(JavaKind.Object, new ObjectCloneNode(b.getInvokeKind(), targetMethod, b.bci(), b.getInvokeReturnStamp(b.getAssumptions()), object)); 192 return true; 193 } 194 195 @Override 196 public boolean inlineOnly() { 197 return true; 198 } 199 }); 200 } 201 r.registerMethodSubstitution(ObjectSubstitutions.class, "hashCode", Receiver.class); 202 } 203 204 private static void registerClassPlugins(Plugins plugins, GraalHotSpotVMConfig config, BytecodeProvider bytecodeProvider) { 205 Registration r = new Registration(plugins.getInvocationPlugins(), Class.class, bytecodeProvider); 206 207 r.registerMethodSubstitution(HotSpotClassSubstitutions.class, "getModifiers", Receiver.class); 208 r.registerMethodSubstitution(HotSpotClassSubstitutions.class, "isInterface", Receiver.class); 209 r.registerMethodSubstitution(HotSpotClassSubstitutions.class, "isArray", Receiver.class); 210 r.registerMethodSubstitution(HotSpotClassSubstitutions.class, "isPrimitive", Receiver.class); 211 r.registerMethodSubstitution(HotSpotClassSubstitutions.class, "getSuperclass", Receiver.class); 212 213 if (config.getFieldOffset("ArrayKlass::_component_mirror", Integer.class, "oop", Integer.MAX_VALUE) != Integer.MAX_VALUE) { 214 r.registerMethodSubstitution(HotSpotClassSubstitutions.class, "getComponentType", Receiver.class); 215 } 216 217 r.register2("cast", Receiver.class, Object.class, new InvocationPlugin() { 218 @Override 219 public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver, ValueNode object) { 220 ValueNode javaClass = receiver.get(); 221 LogicNode condition = b.append(InstanceOfDynamicNode.create(b.getAssumptions(), b.getConstantReflection(), javaClass, object, true)); 222 if (condition.isTautology()) { 223 b.addPush(JavaKind.Object, object); 224 } else { 225 FixedGuardNode fixedGuard = b.add(new FixedGuardNode(condition, DeoptimizationReason.ClassCastException, DeoptimizationAction.InvalidateReprofile, false)); 226 b.addPush(JavaKind.Object, new DynamicPiNode(object, fixedGuard, javaClass)); 227 } 228 return true; 229 } 230 231 @Override 232 public boolean inlineOnly() { 233 return true; 234 } 235 }); 236 } 237 238 private static void registerCallSitePlugins(InvocationPlugins plugins) { 239 InvocationPlugin plugin = new InvocationPlugin() { 240 @Override 241 public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver) { 242 ValueNode callSite = receiver.get(); 243 ValueNode folded = CallSiteTargetNode.tryFold(GraphUtil.originalValue(callSite), b.getMetaAccess(), b.getAssumptions()); 244 if (folded != null) { 245 b.addPush(JavaKind.Object, folded); 246 } else { 247 b.addPush(JavaKind.Object, new CallSiteTargetNode(b.getInvokeKind(), targetMethod, b.bci(), b.getInvokeReturnStamp(b.getAssumptions()), callSite)); 248 } 249 return true; 250 } 251 252 @Override 253 public boolean inlineOnly() { 254 return true; 255 } 256 }; 257 plugins.register(plugin, ConstantCallSite.class, "getTarget", Receiver.class); 258 plugins.register(plugin, MutableCallSite.class, "getTarget", Receiver.class); 259 plugins.register(plugin, VolatileCallSite.class, "getTarget", Receiver.class); 260 } 261 262 private static void registerReflectionPlugins(InvocationPlugins plugins, BytecodeProvider bytecodeProvider) { 263 Registration r = new Registration(plugins, reflectionClass, bytecodeProvider); 264 r.register0("getCallerClass", new InvocationPlugin() { 265 @Override 266 public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver) { 267 b.addPush(JavaKind.Object, new ReflectionGetCallerClassNode(b.getInvokeKind(), targetMethod, b.bci(), b.getInvokeReturnStamp(b.getAssumptions()))); 268 return true; 269 } 270 271 @Override 272 public boolean inlineOnly() { 273 return true; 274 } 275 }); 276 r.registerMethodSubstitution(ReflectionSubstitutions.class, "getClassAccessFlags", Class.class); 277 } 278 279 private static void registerUnsafePlugins(InvocationPlugins plugins, BytecodeProvider replacementBytecodeProvider) { 280 Registration r; 281 if (Java8OrEarlier) { 282 r = new Registration(plugins, Unsafe.class, replacementBytecodeProvider); 283 } else { 284 r = new Registration(plugins, "jdk.internal.misc.Unsafe", replacementBytecodeProvider); 285 } 286 r.registerMethodSubstitution(HotSpotUnsafeSubstitutions.class, HotSpotUnsafeSubstitutions.copyMemoryName, "copyMemory", Receiver.class, Object.class, long.class, Object.class, long.class, 287 long.class); 288 } 289 290 private static final LocationIdentity INSTANCE_KLASS_CONSTANTS = NamedLocationIdentity.immutable("InstanceKlass::_constants"); 291 private static final LocationIdentity CONSTANT_POOL_LENGTH = NamedLocationIdentity.immutable("ConstantPool::_length"); 292 293 /** 294 * Emits a node to get the metaspace {@code ConstantPool} pointer given the value of the 295 * {@code constantPoolOop} field in a ConstantPool value. 296 * 297 * @param constantPoolOop value of the {@code constantPoolOop} field in a ConstantPool value 298 * @return a node representing the metaspace {@code ConstantPool} pointer associated with 299 * {@code constantPoolOop} 300 */ 301 private static ValueNode getMetaspaceConstantPool(GraphBuilderContext b, ValueNode constantPoolOop, WordTypes wordTypes, GraalHotSpotVMConfig config) { 302 // ConstantPool.constantPoolOop is in fact the holder class. 303 ValueNode value = b.nullCheckedValue(constantPoolOop, DeoptimizationAction.None); 304 ValueNode klass = b.add(ClassGetHubNode.create(value, b.getMetaAccess(), b.getConstantReflection(), false)); 305 306 boolean notCompressible = false; 307 AddressNode constantsAddress = b.add(new OffsetAddressNode(klass, b.add(ConstantNode.forLong(config.instanceKlassConstantsOffset)))); 308 return WordOperationPlugin.readOp(b, wordTypes.getWordKind(), constantsAddress, INSTANCE_KLASS_CONSTANTS, BarrierType.NONE, notCompressible); 309 } 310 311 /** 312 * Emits a node representing an element in a metaspace {@code ConstantPool}. 313 * 314 * @param constantPoolOop value of the {@code constantPoolOop} field in a ConstantPool value 315 */ 316 private static boolean readMetaspaceConstantPoolElement(GraphBuilderContext b, ValueNode constantPoolOop, ValueNode index, JavaKind elementKind, WordTypes wordTypes, GraalHotSpotVMConfig config) { 317 ValueNode constants = getMetaspaceConstantPool(b, constantPoolOop, wordTypes, config); 318 int shift = CodeUtil.log2(wordTypes.getWordKind().getByteCount()); 319 ValueNode scaledIndex = b.add(new LeftShiftNode(index, b.add(ConstantNode.forInt(shift)))); 320 ValueNode offset = b.add(new AddNode(scaledIndex, b.add(ConstantNode.forInt(config.constantPoolSize)))); 321 AddressNode elementAddress = b.add(new OffsetAddressNode(constants, offset)); 322 boolean notCompressible = false; 323 ValueNode elementValue = WordOperationPlugin.readOp(b, elementKind, elementAddress, NamedLocationIdentity.getArrayLocation(elementKind), BarrierType.NONE, notCompressible); 324 b.addPush(elementKind, elementValue); 325 return true; 326 } 327 328 private static void registerConstantPoolPlugins(InvocationPlugins plugins, WordTypes wordTypes, GraalHotSpotVMConfig config, BytecodeProvider bytecodeProvider) { 329 Registration r = new Registration(plugins, constantPoolClass, bytecodeProvider); 330 331 r.register2("getSize0", Receiver.class, Object.class, new InvocationPlugin() { 332 @Override 333 public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver, ValueNode constantPoolOop) { 334 boolean notCompressible = false; 335 ValueNode constants = getMetaspaceConstantPool(b, constantPoolOop, wordTypes, config); 336 AddressNode lengthAddress = b.add(new OffsetAddressNode(constants, b.add(ConstantNode.forLong(config.constantPoolLengthOffset)))); 337 ValueNode length = WordOperationPlugin.readOp(b, JavaKind.Int, lengthAddress, CONSTANT_POOL_LENGTH, BarrierType.NONE, notCompressible); 338 b.addPush(JavaKind.Int, length); 339 return true; 340 } 341 }); 342 343 r.register3("getIntAt0", Receiver.class, Object.class, int.class, new InvocationPlugin() { 344 @Override 345 public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver, ValueNode constantPoolOop, ValueNode index) { 346 return readMetaspaceConstantPoolElement(b, constantPoolOop, index, JavaKind.Int, wordTypes, config); 347 } 348 }); 349 r.register3("getLongAt0", Receiver.class, Object.class, int.class, new InvocationPlugin() { 350 @Override 351 public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver, ValueNode constantPoolOop, ValueNode index) { 352 return readMetaspaceConstantPoolElement(b, constantPoolOop, index, JavaKind.Long, wordTypes, config); 353 } 354 }); 355 r.register3("getFloatAt0", Receiver.class, Object.class, int.class, new InvocationPlugin() { 356 @Override 357 public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver, ValueNode constantPoolOop, ValueNode index) { 358 return readMetaspaceConstantPoolElement(b, constantPoolOop, index, JavaKind.Float, wordTypes, config); 359 } 360 }); 361 r.register3("getDoubleAt0", Receiver.class, Object.class, int.class, new InvocationPlugin() { 362 @Override 363 public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver, ValueNode constantPoolOop, ValueNode index) { 364 return readMetaspaceConstantPoolElement(b, constantPoolOop, index, JavaKind.Double, wordTypes, config); 365 } 366 }); 367 } 368 369 private static void registerSystemPlugins(InvocationPlugins plugins, ForeignCallsProvider foreignCalls) { 370 Registration r = new Registration(plugins, System.class); 371 r.register0("currentTimeMillis", new ForeignCallPlugin(foreignCalls, HotSpotHostForeignCallsProvider.JAVA_TIME_MILLIS)); 372 r.register0("nanoTime", new ForeignCallPlugin(foreignCalls, HotSpotHostForeignCallsProvider.JAVA_TIME_NANOS)); 373 r.register1("identityHashCode", Object.class, new InvocationPlugin() { 374 @Override 375 public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver, ValueNode object) { 376 b.addPush(JavaKind.Int, new IdentityHashCodeNode(object)); 377 return true; 378 } 379 380 @Override 381 public boolean inlineOnly() { 382 return true; 383 } 384 }); 385 r.register5("arraycopy", Object.class, int.class, Object.class, int.class, int.class, new InvocationPlugin() { 386 @Override 387 public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver, ValueNode src, ValueNode srcPos, ValueNode dst, ValueNode dstPos, ValueNode length) { 388 b.add(new ArrayCopyNode(b.bci(), src, srcPos, dst, dstPos, length)); 389 return true; 390 } 391 392 @Override 393 public boolean inlineOnly() { 394 return true; 395 } 396 }); 397 } 398 399 private static void registerThreadPlugins(InvocationPlugins plugins, MetaAccessProvider metaAccess, WordTypes wordTypes, GraalHotSpotVMConfig config, BytecodeProvider bytecodeProvider) { 400 Registration r = new Registration(plugins, Thread.class, bytecodeProvider); 401 r.register0("currentThread", new InvocationPlugin() { 402 @Override 403 public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver) { 404 CurrentJavaThreadNode thread = b.add(new CurrentJavaThreadNode(wordTypes.getWordKind())); 405 boolean compressible = false; 406 ValueNode offset = b.add(ConstantNode.forLong(config.threadObjectOffset)); 407 AddressNode address = b.add(new OffsetAddressNode(thread, offset)); 408 ValueNode javaThread = WordOperationPlugin.readOp(b, JavaKind.Object, address, JAVA_THREAD_THREAD_OBJECT_LOCATION, BarrierType.NONE, compressible); 409 boolean exactType = false; 410 boolean nonNull = true; 411 b.addPush(JavaKind.Object, new PiNode(javaThread, metaAccess.lookupJavaType(Thread.class), exactType, nonNull)); 412 return true; 413 } 414 }); 415 416 r.registerMethodSubstitution(ThreadSubstitutions.class, "isInterrupted", Receiver.class, boolean.class); 417 } 418 419 public static final String cbcEncryptName; 420 public static final String cbcDecryptName; 421 public static final String aesEncryptName; 422 public static final String aesDecryptName; 423 424 public static final String reflectionClass; 425 public static final String constantPoolClass; 426 427 static { 428 if (JDK9Method.Java8OrEarlier) { 429 cbcEncryptName = "encrypt"; 430 cbcDecryptName = "decrypt"; 431 aesEncryptName = "encryptBlock"; 432 aesDecryptName = "decryptBlock"; 433 reflectionClass = "sun.reflect.Reflection"; 434 constantPoolClass = "sun.reflect.ConstantPool"; 435 } else { 436 cbcEncryptName = "implEncrypt"; 437 cbcDecryptName = "implDecrypt"; 438 aesEncryptName = "implEncryptBlock"; 439 aesDecryptName = "implDecryptBlock"; 440 reflectionClass = "jdk.internal.reflect.Reflection"; 441 constantPoolClass = "jdk.internal.reflect.ConstantPool"; 442 } 443 } 444 445 private static void registerAESPlugins(InvocationPlugins plugins, GraalHotSpotVMConfig config, BytecodeProvider bytecodeProvider) { 446 if (config.useAESIntrinsics) { 447 assert config.aescryptEncryptBlockStub != 0L; 448 assert config.aescryptDecryptBlockStub != 0L; 449 assert config.cipherBlockChainingEncryptAESCryptStub != 0L; 450 assert config.cipherBlockChainingDecryptAESCryptStub != 0L; 451 String arch = config.osArch; 452 String decryptSuffix = arch.equals("sparc") ? "WithOriginalKey" : ""; 453 Registration r = new Registration(plugins, "com.sun.crypto.provider.CipherBlockChaining", bytecodeProvider); 454 r.registerMethodSubstitution(CipherBlockChainingSubstitutions.class, cbcEncryptName, Receiver.class, byte[].class, int.class, int.class, byte[].class, int.class); 455 r.registerMethodSubstitution(CipherBlockChainingSubstitutions.class, cbcDecryptName, cbcDecryptName + decryptSuffix, Receiver.class, byte[].class, int.class, int.class, byte[].class, 456 int.class); 457 r = new Registration(plugins, "com.sun.crypto.provider.AESCrypt", bytecodeProvider); 458 r.registerMethodSubstitution(AESCryptSubstitutions.class, aesEncryptName, Receiver.class, byte[].class, int.class, byte[].class, int.class); 459 r.registerMethodSubstitution(AESCryptSubstitutions.class, aesDecryptName, aesDecryptName + decryptSuffix, Receiver.class, byte[].class, int.class, byte[].class, int.class); 460 } 461 } 462 463 private static void registerBigIntegerPlugins(InvocationPlugins plugins, GraalHotSpotVMConfig config, BytecodeProvider bytecodeProvider) { 464 Registration r = new Registration(plugins, BigInteger.class, bytecodeProvider); 465 if (config.useMultiplyToLenIntrinsic()) { 466 assert config.multiplyToLen != 0L; 467 if (Java8OrEarlier) { 468 try { 469 Method m = BigInteger.class.getDeclaredMethod("multiplyToLen", int[].class, int.class, int[].class, int.class, int[].class); 470 if (Modifier.isStatic(m.getModifiers())) { 471 r.registerMethodSubstitution(BigIntegerSubstitutions.class, "multiplyToLen", "multiplyToLenStatic", int[].class, int.class, int[].class, int.class, 472 int[].class); 473 } else { 474 r.registerMethodSubstitution(BigIntegerSubstitutions.class, "multiplyToLen", Receiver.class, int[].class, int.class, int[].class, int.class, 475 int[].class); 476 } 477 } catch (NoSuchMethodException | SecurityException e) { 478 throw new GraalError(e); 479 } 480 } else { 481 r.registerMethodSubstitution(BigIntegerSubstitutions.class, "implMultiplyToLen", "multiplyToLenStatic", int[].class, int.class, int[].class, int.class, 482 int[].class); 483 } 484 } 485 if (config.useMulAddIntrinsic()) { 486 r.registerMethodSubstitution(BigIntegerSubstitutions.class, "implMulAdd", int[].class, int[].class, int.class, int.class, int.class); 487 } 488 if (config.useMontgomeryMultiplyIntrinsic()) { 489 r.registerMethodSubstitution(BigIntegerSubstitutions.class, "implMontgomeryMultiply", int[].class, int[].class, int[].class, int.class, long.class, int[].class); 490 } 491 if (config.useMontgomerySquareIntrinsic()) { 492 r.registerMethodSubstitution(BigIntegerSubstitutions.class, "implMontgomerySquare", int[].class, int[].class, int.class, long.class, int[].class); 493 } 494 if (config.useSquareToLenIntrinsic()) { 495 r.registerMethodSubstitution(BigIntegerSubstitutions.class, "implSquareToLen", int[].class, int.class, int[].class, int.class); 496 } 497 } 498 499 private static void registerSHAPlugins(InvocationPlugins plugins, GraalHotSpotVMConfig config, BytecodeProvider bytecodeProvider) { 500 if (config.useSHA1Intrinsics()) { 501 assert config.sha1ImplCompress != 0L; 502 Registration r = new Registration(plugins, "sun.security.provider.SHA", bytecodeProvider); 503 r.registerMethodSubstitution(SHASubstitutions.class, SHASubstitutions.implCompressName, "implCompress0", Receiver.class, byte[].class, int.class); 504 } 505 if (config.useSHA256Intrinsics()) { 506 assert config.sha256ImplCompress != 0L; 507 Registration r = new Registration(plugins, "sun.security.provider.SHA2", bytecodeProvider); 508 r.registerMethodSubstitution(SHA2Substitutions.class, SHA2Substitutions.implCompressName, "implCompress0", Receiver.class, byte[].class, int.class); 509 } 510 if (config.useSHA512Intrinsics()) { 511 assert config.sha512ImplCompress != 0L; 512 Registration r = new Registration(plugins, "sun.security.provider.SHA5", bytecodeProvider); 513 r.registerMethodSubstitution(SHA5Substitutions.class, SHA5Substitutions.implCompressName, "implCompress0", Receiver.class, byte[].class, int.class); 514 } 515 } 516 517 private static void registerCRC32Plugins(InvocationPlugins plugins, GraalHotSpotVMConfig config, BytecodeProvider bytecodeProvider) { 518 if (config.useCRC32Intrinsics) { 519 Registration r = new Registration(plugins, CRC32.class, bytecodeProvider); 520 r.registerMethodSubstitution(CRC32Substitutions.class, "update", int.class, int.class); 521 if (Java8OrEarlier) { 522 r.registerMethodSubstitution(CRC32Substitutions.class, "updateBytes", int.class, byte[].class, int.class, int.class); 523 r.registerMethodSubstitution(CRC32Substitutions.class, "updateByteBuffer", int.class, long.class, int.class, int.class); 524 } else { 525 r.registerMethodSubstitution(CRC32Substitutions.class, "updateBytes0", int.class, byte[].class, int.class, int.class); 526 r.registerMethodSubstitution(CRC32Substitutions.class, "updateByteBuffer0", int.class, long.class, int.class, int.class); 527 } 528 } 529 } 530 }