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