Mercurial > hg > graal-compiler
changeset 23078:b00ef2b9cd00
Generate graph builder plugins for @NodeIntrinsic and @Fold methods.
line wrap: on
line diff
--- a/graal/com.oracle.graal.api.replacements/src/com/oracle/graal/api/replacements/SnippetReflectionProvider.java Tue Nov 24 15:21:14 2015 +0100 +++ b/graal/com.oracle.graal.api.replacements/src/com/oracle/graal/api/replacements/SnippetReflectionProvider.java Tue Nov 24 19:31:56 2015 +0100 @@ -182,5 +182,5 @@ * @return the value that should be bound to the parameter when invoking the constructor or null * if this provider cannot provide a value of the requested type */ - Object getInjectedNodeIntrinsicParameter(ResolvedJavaType type); + <T> T getInjectedNodeIntrinsicParameter(Class<T> type); }
--- a/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/Node.java Tue Nov 24 15:21:14 2015 +0100 +++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/Node.java Tue Nov 24 19:31:56 2015 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -163,7 +163,11 @@ * annotated method can be replaced with an instance of the node class denoted by * {@link #value()}. For this reason, the signature of the annotated method must match the * signature (excluding a prefix of {@linkplain InjectedNodeParameter injected} parameters) of a - * factory method named {@code "create"} in the node class. + * constructor in the node class. + * <p> + * If the node class has a static method {@code intrinsify} with a matching signature plus a + * {@code GraphBuilderContext} as first argument, this method is called instead of creating the + * node. */ @java.lang.annotation.Retention(RetentionPolicy.RUNTIME) @java.lang.annotation.Target(ElementType.METHOD)
--- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotBackendFactory.java Tue Nov 24 15:21:14 2015 +0100 +++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotBackendFactory.java Tue Nov 24 19:31:56 2015 +0100 @@ -66,6 +66,7 @@ import com.oracle.graal.phases.tiers.CompilerConfiguration; import com.oracle.graal.phases.util.Providers; import com.oracle.graal.replacements.amd64.AMD64GraphBuilderPlugins; +import com.oracle.graal.word.WordTypes; @ServiceProvider(HotSpotBackendFactory.class) public class AMD64HotSpotBackendFactory implements HotSpotBackendFactory { @@ -112,15 +113,15 @@ HotSpotStampProvider stampProvider = new HotSpotStampProvider(); Providers p = new Providers(metaAccess, codeCache, constantReflection, foreignCalls, lowerer, null, stampProvider); + try (InitTimer rt = timer("create WordTypes")) { + wordTypes = new HotSpotWordTypes(metaAccess, target.wordJavaKind); + } try (InitTimer rt = timer("create SnippetReflection provider")) { - snippetReflection = createSnippetReflection(graalRuntime, constantReflection); + snippetReflection = createSnippetReflection(graalRuntime, constantReflection, wordTypes); } try (InitTimer rt = timer("create Replacements provider")) { replacements = createReplacements(config, p, snippetReflection); } - try (InitTimer rt = timer("create WordTypes")) { - wordTypes = new HotSpotWordTypes(metaAccess, target.wordJavaKind); - } try (InitTimer rt = timer("create GraphBuilderPhase plugins")) { plugins = createGraphBuilderPlugins(config, target, constantReflection, foreignCalls, metaAccess, snippetReflection, replacements, wordTypes, stampProvider); replacements.setGraphBuilderPlugins(plugins); @@ -166,8 +167,8 @@ registers.getHeapBaseRegister())); } - protected HotSpotSnippetReflectionProvider createSnippetReflection(HotSpotGraalRuntimeProvider runtime, HotSpotConstantReflectionProvider constantReflection) { - return new HotSpotSnippetReflectionProvider(runtime, constantReflection); + protected HotSpotSnippetReflectionProvider createSnippetReflection(HotSpotGraalRuntimeProvider runtime, HotSpotConstantReflectionProvider constantReflection, WordTypes wordTypes) { + return new HotSpotSnippetReflectionProvider(runtime, constantReflection, wordTypes); } protected HotSpotLoweringProvider createLowerer(HotSpotGraalRuntimeProvider runtime, HotSpotMetaAccessProvider metaAccess, HotSpotForeignCallsProvider foreignCalls,
--- a/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotBackendFactory.java Tue Nov 24 15:21:14 2015 +0100 +++ b/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotBackendFactory.java Tue Nov 24 19:31:56 2015 +0100 @@ -88,9 +88,9 @@ LoweringProvider lowerer = createLowerer(runtime, metaAccess, foreignCalls, registers, constantReflection, target); HotSpotStampProvider stampProvider = new HotSpotStampProvider(); Providers p = new Providers(metaAccess, codeCache, constantReflection, foreignCalls, lowerer, null, stampProvider); - HotSpotSnippetReflectionProvider snippetReflection = new HotSpotSnippetReflectionProvider(runtime, constantReflection); + HotSpotWordTypes wordTypes = new HotSpotWordTypes(metaAccess, target.wordJavaKind); + HotSpotSnippetReflectionProvider snippetReflection = new HotSpotSnippetReflectionProvider(runtime, constantReflection, wordTypes); HotSpotReplacementsImpl replacements = new HotSpotReplacementsImpl(p, snippetReflection, config, target); - HotSpotWordTypes wordTypes = new HotSpotWordTypes(metaAccess, target.wordJavaKind); Plugins plugins = createGraphBuilderPlugins(config, metaAccess, constantReflection, foreignCalls, stampProvider, snippetReflection, replacements, wordTypes); replacements.setGraphBuilderPlugins(plugins); HotSpotSuitesProvider suites = createSuites(config, runtime, compilerConfiguration, plugins, codeCache);
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotGraphBuilderPlugins.java Tue Nov 24 15:21:14 2015 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotGraphBuilderPlugins.java Tue Nov 24 19:31:56 2015 +0100 @@ -39,6 +39,7 @@ import jdk.vm.ci.meta.MetaAccessProvider; import jdk.vm.ci.meta.ResolvedJavaMethod; import jdk.vm.ci.options.StableOptionValue; +import jdk.vm.ci.service.Services; import sun.reflect.Reflection; import com.oracle.graal.api.replacements.SnippetReflectionProvider; @@ -61,13 +62,14 @@ import com.oracle.graal.nodes.PiNode; import com.oracle.graal.nodes.ValueNode; import com.oracle.graal.nodes.graphbuilderconf.ForeignCallPlugin; +import com.oracle.graal.nodes.graphbuilderconf.GraphBuilderConfiguration.Plugins; import com.oracle.graal.nodes.graphbuilderconf.GraphBuilderContext; import com.oracle.graal.nodes.graphbuilderconf.InvocationPlugin; +import com.oracle.graal.nodes.graphbuilderconf.InvocationPlugin.Receiver; import com.oracle.graal.nodes.graphbuilderconf.InvocationPlugins; +import com.oracle.graal.nodes.graphbuilderconf.InvocationPlugins.Registration; import com.oracle.graal.nodes.graphbuilderconf.MethodSubstitutionPlugin; -import com.oracle.graal.nodes.graphbuilderconf.GraphBuilderConfiguration.Plugins; -import com.oracle.graal.nodes.graphbuilderconf.InvocationPlugin.Receiver; -import com.oracle.graal.nodes.graphbuilderconf.InvocationPlugins.Registration; +import com.oracle.graal.nodes.graphbuilderconf.NodeIntrinsicPluginFactory; import com.oracle.graal.nodes.memory.HeapAccess.BarrierType; import com.oracle.graal.nodes.memory.address.AddressNode; import com.oracle.graal.nodes.memory.address.OffsetAddressNode; @@ -100,8 +102,8 @@ InvocationPlugins invocationPlugins = new HotSpotInvocationPlugins(config, metaAccess); Plugins plugins = new Plugins(invocationPlugins); - NodeIntrinsificationPhase nodeIntrinsificationPhase = new NodeIntrinsificationPhase(metaAccess, constantReflection, snippetReflection, foreignCalls, stampProvider); - NodeIntrinsificationPlugin nodeIntrinsificationPlugin = new NodeIntrinsificationPlugin(metaAccess, nodeIntrinsificationPhase, wordTypes, false); + NodeIntrinsificationPhase nodeIntrinsificationPhase = new NodeIntrinsificationPhase(metaAccess, constantReflection, snippetReflection, foreignCalls, stampProvider, wordTypes); + NodeIntrinsificationPlugin nodeIntrinsificationPlugin = new NodeIntrinsificationPlugin(); HotSpotWordOperationPlugin wordOperationPlugin = new HotSpotWordOperationPlugin(snippetReflection, wordTypes); HotSpotNodePlugin nodePlugin = new HotSpotNodePlugin(wordOperationPlugin, nodeIntrinsificationPlugin); @@ -125,6 +127,10 @@ registerCRC32Plugins(invocationPlugins, config); StandardGraphBuilderPlugins.registerInvocationPlugins(metaAccess, invocationPlugins, true); + for (NodeIntrinsicPluginFactory factory : Services.load(NodeIntrinsicPluginFactory.class)) { + factory.registerPlugin(invocationPlugins, nodeIntrinsificationPhase); + } + return plugins; }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotSnippetReflectionProvider.java Tue Nov 24 15:21:14 2015 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotSnippetReflectionProvider.java Tue Nov 24 19:31:56 2015 +0100 @@ -28,20 +28,22 @@ import jdk.vm.ci.hotspot.HotSpotVMConfig; import jdk.vm.ci.meta.JavaConstant; import jdk.vm.ci.meta.JavaKind; -import jdk.vm.ci.meta.MetaAccessProvider; import jdk.vm.ci.meta.ResolvedJavaType; import com.oracle.graal.api.replacements.SnippetReflectionProvider; import com.oracle.graal.hotspot.HotSpotGraalRuntimeProvider; +import com.oracle.graal.word.WordTypes; public class HotSpotSnippetReflectionProvider implements SnippetReflectionProvider { private final HotSpotGraalRuntimeProvider runtime; private final HotSpotConstantReflectionProvider constantReflection; + private final WordTypes wordTypes; - public HotSpotSnippetReflectionProvider(HotSpotGraalRuntimeProvider runtime, HotSpotConstantReflectionProvider constantReflection) { + public HotSpotSnippetReflectionProvider(HotSpotGraalRuntimeProvider runtime, HotSpotConstantReflectionProvider constantReflection, WordTypes wordTypes) { this.runtime = runtime; this.constantReflection = constantReflection; + this.wordTypes = wordTypes; } @Override @@ -88,29 +90,28 @@ } // Lazily initialized - private ResolvedJavaType wordTypesType; - private ResolvedJavaType runtimeType; - private ResolvedJavaType configType; + private Class<?> wordTypesType; + private Class<?> runtimeType; + private Class<?> configType; - public Object getInjectedNodeIntrinsicParameter(ResolvedJavaType type) { + public <T> T getInjectedNodeIntrinsicParameter(Class<T> type) { // Need to test all fields since there no guarantee under the JMM // about the order in which these fields are written. HotSpotVMConfig config = config(); if (configType == null || wordTypesType == null || configType == null) { - MetaAccessProvider metaAccess = runtime.getHostProviders().getMetaAccess(); - wordTypesType = metaAccess.lookupJavaType(runtime.getHostProviders().getWordTypes().getClass()); - runtimeType = metaAccess.lookupJavaType(runtime.getClass()); - configType = metaAccess.lookupJavaType(config.getClass()); + wordTypesType = wordTypes.getClass(); + runtimeType = runtime.getClass(); + configType = config.getClass(); } if (type.isAssignableFrom(wordTypesType)) { - return runtime.getHostProviders().getWordTypes(); + return type.cast(wordTypes); } if (type.isAssignableFrom(runtimeType)) { - return runtime; + return type.cast(runtime); } if (type.isAssignableFrom(configType)) { - return config; + return type.cast(config); } return null; }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/CRC32Substitutions.java Tue Nov 24 15:21:14 2015 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/CRC32Substitutions.java Tue Nov 24 19:31:56 2015 +0100 @@ -48,7 +48,7 @@ * Gets the address of {@code StubRoutines::x86::_crc_table} in {@code stubRoutines_x86.hpp}. */ @Fold - private static long crcTableAddress() { + static long crcTableAddress() { return config().crcTableAddress; }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/CipherBlockChainingSubstitutions.java Tue Nov 24 15:21:14 2015 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/CipherBlockChainingSubstitutions.java Tue Nov 24 19:31:56 2015 +0100 @@ -71,7 +71,7 @@ } @Fold - private static Class<?> getAESCryptClass() { + static Class<?> getAESCryptClass() { return AESCryptSubstitutions.AESCryptClass; }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/HotSpotReplacementsUtil.java Tue Nov 24 15:21:14 2015 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/HotSpotReplacementsUtil.java Tue Nov 24 19:31:56 2015 +0100 @@ -195,14 +195,14 @@ public static final LocationIdentity TLAB_END_LOCATION = NamedLocationIdentity.mutable("TlabEnd"); @Fold - private static int threadTlabEndOffset() { + static int threadTlabEndOffset() { return config().threadTlabEndOffset(); } public static final LocationIdentity TLAB_START_LOCATION = NamedLocationIdentity.mutable("TlabStart"); @Fold - private static int threadTlabStartOffset() { + static int threadTlabStartOffset() { return config().threadTlabStartOffset(); } @@ -212,7 +212,7 @@ * @see HotSpotVMConfig#pendingExceptionOffset */ @Fold - private static int threadPendingExceptionOffset() { + static int threadPendingExceptionOffset() { return config().pendingExceptionOffset; } @@ -222,14 +222,14 @@ * @see HotSpotVMConfig#pendingDeoptimizationOffset */ @Fold - private static int threadPendingDeoptimizationOffset() { + static int threadPendingDeoptimizationOffset() { return config().pendingDeoptimizationOffset; } public static final LocationIdentity OBJECT_RESULT_LOCATION = NamedLocationIdentity.mutable("ObjectResult"); @Fold - private static int objectResultOffset() { + static int objectResultOffset() { return config().threadObjectResultOffset; } @@ -503,7 +503,7 @@ }; @Fold - private static int hubOffset() { + static int hubOffset() { return config().hubOffset; }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/MonitorSnippets.java Tue Nov 24 15:21:14 2015 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/MonitorSnippets.java Tue Nov 24 19:31:56 2015 +0100 @@ -202,7 +202,7 @@ private static final boolean PROFILE_CONTEXT = false; @Fold - private static boolean doProfile() { + static boolean doProfile() { return Options.ProfileMonitors.getValue(); }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/NewObjectSnippets.java Tue Nov 24 15:21:14 2015 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/NewObjectSnippets.java Tue Nov 24 19:31:56 2015 +0100 @@ -138,7 +138,7 @@ public static final ProfileMode PROFILE_MODE = ProfileMode.AllocatedTypes; @Fold - private static String createName(String path, String typeContext) { + static String createName(String path, String typeContext) { switch (PROFILE_MODE) { case AllocatingMethods: return ""; @@ -155,7 +155,7 @@ } @Fold - private static boolean doProfile() { + static boolean doProfile() { return ProfileAllocations.getValue(); }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/RuntimeStringSnippets.java Tue Nov 24 15:21:14 2015 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/RuntimeStringSnippets.java Tue Nov 24 19:31:56 2015 +0100 @@ -49,7 +49,7 @@ public class RuntimeStringSnippets implements Snippets { @Fold - private static long valueOffset() { + static long valueOffset() { try { return UNSAFE.objectFieldOffset(String.class.getDeclaredField("value")); } catch (Exception e) { @@ -58,7 +58,7 @@ } @Fold - private static long hashOffset() { + static long hashOffset() { try { return UNSAFE.objectFieldOffset(String.class.getDeclaredField("hash")); } catch (Exception e) { @@ -67,7 +67,7 @@ } @Fold - private static long arrayBaseOffset() { + static long arrayBaseOffset() { return UNSAFE.arrayBaseOffset(char[].class); }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/arraycopy/ArrayCopySnippets.java Tue Nov 24 15:21:14 2015 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/arraycopy/ArrayCopySnippets.java Tue Nov 24 19:31:56 2015 +0100 @@ -285,7 +285,7 @@ } @Fold - private static LocationIdentity getArrayLocation(JavaKind kind) { + static LocationIdentity getArrayLocation(JavaKind kind) { return NamedLocationIdentity.getArrayLocation(kind); }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/arraycopy/UnsafeArrayCopySnippets.java Tue Nov 24 15:21:14 2015 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/arraycopy/UnsafeArrayCopySnippets.java Tue Nov 24 19:31:56 2015 +0100 @@ -144,7 +144,7 @@ } @Fold - private static LocationIdentity getArrayLocation(JavaKind kind) { + static LocationIdentity getArrayLocation(JavaKind kind) { return NamedLocationIdentity.getArrayLocation(kind); }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/DeoptimizationStub.java Tue Nov 24 15:21:14 2015 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/DeoptimizationStub.java Tue Nov 24 19:31:56 2015 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -154,7 +154,7 @@ * Stack bang to make sure there's enough room for the interpreter frames. Bang stack for * total size of the interpreter frames plus shadow page size. Bang one page at a time * because large sizes can bang beyond yellow and red zones. - * + * * @deprecated This code should go away as soon as JDK-8032410 hits the Graal repository. */ final int totalFrameSizes = unrollBlock.readInt(deoptimizationUnrollBlockTotalFrameSizesOffset()); @@ -228,7 +228,7 @@ } @Fold - private static int stackShadowPages() { + static int stackShadowPages() { return config().useStackBanging ? config().stackShadowPages : 0; } @@ -241,57 +241,57 @@ */ @Deprecated @Fold - private static int stackBias() { + static int stackBias() { return config().stackBias; } @Fold - private static int deoptimizationUnrollBlockSizeOfDeoptimizedFrameOffset() { + static int deoptimizationUnrollBlockSizeOfDeoptimizedFrameOffset() { return config().deoptimizationUnrollBlockSizeOfDeoptimizedFrameOffset; } @Fold - private static int deoptimizationUnrollBlockCallerAdjustmentOffset() { + static int deoptimizationUnrollBlockCallerAdjustmentOffset() { return config().deoptimizationUnrollBlockCallerAdjustmentOffset; } @Fold - private static int deoptimizationUnrollBlockNumberOfFramesOffset() { + static int deoptimizationUnrollBlockNumberOfFramesOffset() { return config().deoptimizationUnrollBlockNumberOfFramesOffset; } @Fold - private static int deoptimizationUnrollBlockTotalFrameSizesOffset() { + static int deoptimizationUnrollBlockTotalFrameSizesOffset() { return config().deoptimizationUnrollBlockTotalFrameSizesOffset; } @Fold - private static int deoptimizationUnrollBlockUnpackKindOffset() { + static int deoptimizationUnrollBlockUnpackKindOffset() { return config().deoptimizationUnrollBlockUnpackKindOffset; } @Fold - private static int deoptimizationUnrollBlockFrameSizesOffset() { + static int deoptimizationUnrollBlockFrameSizesOffset() { return config().deoptimizationUnrollBlockFrameSizesOffset; } @Fold - private static int deoptimizationUnrollBlockFramePcsOffset() { + static int deoptimizationUnrollBlockFramePcsOffset() { return config().deoptimizationUnrollBlockFramePcsOffset; } @Fold - private static int deoptimizationUnrollBlockInitialInfoOffset() { + static int deoptimizationUnrollBlockInitialInfoOffset() { return config().deoptimizationUnrollBlockInitialInfoOffset; } @Fold - private static int deoptimizationUnpackDeopt() { + static int deoptimizationUnpackDeopt() { return config().deoptimizationUnpackDeopt; } @Fold - private static int deoptimizationUnpackUncommonTrap() { + static int deoptimizationUnpackUncommonTrap() { return config().deoptimizationUnpackUncommonTrap; }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/ExceptionHandlerStub.java Tue Nov 24 15:21:14 2015 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/ExceptionHandlerStub.java Tue Nov 24 19:31:56 2015 +0100 @@ -133,7 +133,7 @@ } @Fold - private static boolean logging() { + static boolean logging() { return Boolean.getBoolean("graal.logExceptionHandlerStub"); } @@ -146,7 +146,7 @@ */ @Fold @SuppressWarnings("all") - private static boolean assertionsEnabled() { + static boolean assertionsEnabled() { boolean enabled = false; assert enabled = true; return enabled || cAssertionsEnabled();
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/NewArrayStub.java Tue Nov 24 15:21:14 2015 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/NewArrayStub.java Tue Nov 24 19:31:56 2015 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -84,7 +84,7 @@ } @Fold - private static boolean logging() { + static boolean logging() { return Boolean.getBoolean("graal.logNewArrayStub"); }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/NewInstanceStub.java Tue Nov 24 15:21:14 2015 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/NewInstanceStub.java Tue Nov 24 19:31:56 2015 +0100 @@ -126,7 +126,7 @@ } @Fold - private static boolean logging() { + static boolean logging() { return Boolean.getBoolean("graal.logNewInstanceStub"); } @@ -294,7 +294,7 @@ } @Fold - private static boolean forceSlowPath() { + static boolean forceSlowPath() { return Boolean.getBoolean("graal.newInstanceStub.forceSlowPath"); }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/StubUtil.java Tue Nov 24 15:21:14 2015 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/StubUtil.java Tue Nov 24 19:31:56 2015 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -252,22 +252,22 @@ } @Fold - private static long verifyOopCounterAddress() { + static long verifyOopCounterAddress() { return config().verifyOopCounterAddress; } @Fold - private static long verifyOopMask() { + static long verifyOopMask() { return config().verifyOopMask; } @Fold - private static long verifyOopBits() { + static long verifyOopBits() { return config().verifyOopBits; } @Fold - private static int hubOffset() { + static int hubOffset() { return config().hubOffset; } }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/UncommonTrapStub.java Tue Nov 24 15:21:14 2015 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/UncommonTrapStub.java Tue Nov 24 19:31:56 2015 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -156,7 +156,7 @@ } @Fold - private static int stackShadowPages() { + static int stackShadowPages() { return config().useStackBanging ? config().stackShadowPages : 0; } @@ -169,52 +169,52 @@ */ @Deprecated @Fold - private static int stackBias() { + static int stackBias() { return config().stackBias; } @Fold - private static int deoptimizationUnrollBlockSizeOfDeoptimizedFrameOffset() { + static int deoptimizationUnrollBlockSizeOfDeoptimizedFrameOffset() { return config().deoptimizationUnrollBlockSizeOfDeoptimizedFrameOffset; } @Fold - private static int deoptimizationUnrollBlockCallerAdjustmentOffset() { + static int deoptimizationUnrollBlockCallerAdjustmentOffset() { return config().deoptimizationUnrollBlockCallerAdjustmentOffset; } @Fold - private static int deoptimizationUnrollBlockNumberOfFramesOffset() { + static int deoptimizationUnrollBlockNumberOfFramesOffset() { return config().deoptimizationUnrollBlockNumberOfFramesOffset; } @Fold - private static int deoptimizationUnrollBlockTotalFrameSizesOffset() { + static int deoptimizationUnrollBlockTotalFrameSizesOffset() { return config().deoptimizationUnrollBlockTotalFrameSizesOffset; } @Fold - private static int deoptimizationUnrollBlockFrameSizesOffset() { + static int deoptimizationUnrollBlockFrameSizesOffset() { return config().deoptimizationUnrollBlockFrameSizesOffset; } @Fold - private static int deoptimizationUnrollBlockFramePcsOffset() { + static int deoptimizationUnrollBlockFramePcsOffset() { return config().deoptimizationUnrollBlockFramePcsOffset; } @Fold - private static int deoptimizationUnrollBlockInitialInfoOffset() { + static int deoptimizationUnrollBlockInitialInfoOffset() { return config().deoptimizationUnrollBlockInitialInfoOffset; } @Fold - private static int deoptimizationUnpackDeopt() { + static int deoptimizationUnpackDeopt() { return config().deoptimizationUnpackDeopt; } @Fold - private static int deoptimizationUnpackUncommonTrap() { + static int deoptimizationUnpackUncommonTrap() { return config().deoptimizationUnpackUncommonTrap; }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/UnwindExceptionToCallerStub.java Tue Nov 24 15:21:14 2015 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/UnwindExceptionToCallerStub.java Tue Nov 24 19:31:56 2015 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -96,7 +96,7 @@ } @Fold - private static boolean logging() { + static boolean logging() { return Boolean.getBoolean("graal.logUnwindExceptionToCallerStub"); } @@ -109,7 +109,7 @@ */ @Fold @SuppressWarnings("all") - private static boolean assertionsEnabled() { + static boolean assertionsEnabled() { boolean enabled = false; assert enabled = true; return enabled || cAssertionsEnabled();
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ValueNode.java Tue Nov 24 15:21:14 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ValueNode.java Tue Nov 24 19:31:56 2015 +0100 @@ -22,11 +22,16 @@ */ package com.oracle.graal.nodes; +import java.util.List; + import jdk.vm.ci.meta.Constant; +import jdk.vm.ci.meta.ConstantReflectionProvider; import jdk.vm.ci.meta.JavaConstant; import jdk.vm.ci.meta.JavaKind; +import com.oracle.graal.api.replacements.SnippetReflectionProvider; import com.oracle.graal.compiler.common.type.Stamp; +import com.oracle.graal.graph.Graph; import com.oracle.graal.graph.Node; import com.oracle.graal.graph.NodeClass; import com.oracle.graal.graph.iterators.NodePredicate; @@ -161,4 +166,9 @@ return super.isAllowedUsageType(type); } } + + public interface NodeIntrinsicConstructor { + + ValueNode newInstance(ConstantReflectionProvider constantReflection, SnippetReflectionProvider snippetReflection, Graph graph, Object[] injectedArguments, List<? extends ValueNode> arguments); + } }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ForeignCallNode.java Tue Nov 24 15:21:14 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ForeignCallNode.java Tue Nov 24 19:31:56 2015 +0100 @@ -42,6 +42,7 @@ import com.oracle.graal.nodes.DeoptimizingNode; import com.oracle.graal.nodes.FrameState; import com.oracle.graal.nodes.ValueNode; +import com.oracle.graal.nodes.graphbuilderconf.GraphBuilderContext; import com.oracle.graal.nodes.memory.AbstractMemoryCheckpoint; import com.oracle.graal.nodes.memory.MemoryCheckpoint; import com.oracle.graal.nodes.spi.LIRLowerable; @@ -61,11 +62,36 @@ protected final ForeignCallDescriptor descriptor; protected int bci = BytecodeFrame.UNKNOWN_BCI; - public ForeignCallNode(@InjectedNodeParameter ForeignCallsProvider foreignCalls, ForeignCallDescriptor descriptor, ValueNode... arguments) { + public static boolean intrinsify(GraphBuilderContext b, @InjectedNodeParameter Stamp returnStamp, @InjectedNodeParameter ForeignCallsProvider foreignCalls, ForeignCallDescriptor descriptor, + ValueNode... arguments) { + ForeignCallNode node = new ForeignCallNode(foreignCalls, descriptor, arguments); + node.setStamp(returnStamp); + + /* + * Need to update the BCI of a ForeignCallNode so that it gets the stateDuring in the case + * that the foreign call can deoptimize. As with all deoptimization, we need a state in a + * non-intrinsic method. + */ + GraphBuilderContext nonIntrinsicAncestor = b.getNonIntrinsicAncestor(); + if (nonIntrinsicAncestor != null) { + node.setBci(nonIntrinsicAncestor.bci()); + } + + JavaKind returnKind = returnStamp.getStackKind(); + if (returnKind == JavaKind.Void) { + b.add(node); + } else { + b.addPush(returnKind, node); + } + + return true; + } + + public ForeignCallNode(ForeignCallsProvider foreignCalls, ForeignCallDescriptor descriptor, ValueNode... arguments) { this(TYPE, foreignCalls, descriptor, arguments); } - public ForeignCallNode(@InjectedNodeParameter ForeignCallsProvider foreignCalls, ForeignCallDescriptor descriptor, Stamp stamp, List<ValueNode> arguments) { + public ForeignCallNode(ForeignCallsProvider foreignCalls, ForeignCallDescriptor descriptor, Stamp stamp, List<ValueNode> arguments) { super(TYPE, stamp); this.arguments = new NodeInputList<>(this, arguments); this.descriptor = descriptor; @@ -73,7 +99,7 @@ assert descriptor.getArgumentTypes().length == this.arguments.size() : "wrong number of arguments to " + this; } - public ForeignCallNode(@InjectedNodeParameter ForeignCallsProvider foreignCalls, ForeignCallDescriptor descriptor, Stamp stamp) { + public ForeignCallNode(ForeignCallsProvider foreignCalls, ForeignCallDescriptor descriptor, Stamp stamp) { super(TYPE, stamp); this.arguments = new NodeInputList<>(this); this.descriptor = descriptor;
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/UnsafeCopyNode.java Tue Nov 24 15:21:14 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/UnsafeCopyNode.java Tue Nov 24 19:31:56 2015 +0100 @@ -25,93 +25,24 @@ import jdk.vm.ci.meta.JavaKind; import jdk.vm.ci.meta.LocationIdentity; -import com.oracle.graal.compiler.common.type.StampFactory; -import com.oracle.graal.graph.NodeClass; -import com.oracle.graal.nodeinfo.InputType; -import com.oracle.graal.nodeinfo.NodeInfo; -import com.oracle.graal.nodes.FixedWithNextNode; -import com.oracle.graal.nodes.FrameState; -import com.oracle.graal.nodes.StateSplit; +import com.oracle.graal.graph.Node.ConstantNodeParameter; +import com.oracle.graal.graph.Node.NodeIntrinsic; import com.oracle.graal.nodes.ValueNode; +import com.oracle.graal.nodes.graphbuilderconf.GraphBuilderContext; /** * Copy a value at a location specified as an offset relative to a source object to another location * specified as an offset relative to destination object. No null checks are performed. - * - * This node must be replaced during processing of node intrinsics with an {@link UnsafeLoadNode} - * and {@link UnsafeStoreNode} pair. */ -@NodeInfo -public final class UnsafeCopyNode extends FixedWithNextNode implements StateSplit { - - public static final NodeClass<UnsafeCopyNode> TYPE = NodeClass.create(UnsafeCopyNode.class); - @Input ValueNode sourceObject; - @Input ValueNode destinationObject; - @Input ValueNode sourceOffset; - @Input ValueNode destinationOffset; - protected final JavaKind accessKind; - protected final LocationIdentity locationIdentity; - @OptionalInput(InputType.State) FrameState stateAfter; - - public UnsafeCopyNode(ValueNode sourceObject, ValueNode sourceOffset, ValueNode destinationObject, ValueNode destinationOffset, JavaKind accessKind, LocationIdentity locationIdentity) { - this(sourceObject, sourceOffset, destinationObject, destinationOffset, accessKind, locationIdentity, null); - } - - public UnsafeCopyNode(ValueNode sourceObject, ValueNode sourceOffset, ValueNode destinationObject, ValueNode destinationOffset, JavaKind accessKind, LocationIdentity locationIdentity, - FrameState stateAfter) { - super(TYPE, StampFactory.forVoid()); - this.sourceObject = sourceObject; - this.sourceOffset = sourceOffset; - this.destinationObject = destinationObject; - this.destinationOffset = destinationOffset; - this.accessKind = accessKind; - this.locationIdentity = locationIdentity; - this.stateAfter = stateAfter; - assert accessKind != JavaKind.Void && accessKind != JavaKind.Illegal; - } - - public ValueNode sourceObject() { - return sourceObject; - } +public final class UnsafeCopyNode { - public ValueNode destinationObject() { - return destinationObject; - } - - public LocationIdentity getLocationIdentity() { - return locationIdentity; - } - - public ValueNode sourceOffset() { - return sourceOffset; - } - - public ValueNode destinationOffset() { - return destinationOffset; - } - - public JavaKind accessKind() { - return accessKind; - } - - public FrameState stateAfter() { - return stateAfter; - } - - public void setStateAfter(FrameState x) { - assert x == null || x.isAlive() : "frame state must be in a graph"; - updateUsages(stateAfter, x); - stateAfter = x; - } - - public boolean hasSideEffect() { + public static boolean intrinsify(GraphBuilderContext b, ValueNode sourceObject, ValueNode sourceOffset, ValueNode destinationObject, ValueNode destinationOffset, JavaKind accessKind, + LocationIdentity locationIdentity) { + UnsafeLoadNode value = b.add(new UnsafeLoadNode(sourceObject, sourceOffset, accessKind, locationIdentity)); + b.add(new UnsafeStoreNode(destinationObject, destinationOffset, value, accessKind, locationIdentity)); return true; } - public FrameState getState() { - return stateAfter; - } - @NodeIntrinsic public static native void copy(Object srcObject, long srcOffset, Object destObject, long destOffset, @ConstantNodeParameter JavaKind kind, @ConstantNodeParameter LocationIdentity locationIdentity); }
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/graphbuilderconf/GeneratedInvocationPlugin.java Tue Nov 24 19:31:56 2015 +0100 @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.nodes.graphbuilderconf; + +import jdk.vm.ci.meta.ResolvedJavaMethod; + +import com.oracle.graal.nodes.ValueNode; + +public abstract class GeneratedInvocationPlugin implements InvocationPlugin { + + public abstract boolean execute(GraphBuilderContext b, ResolvedJavaMethod targetMethod, InvocationPlugin.Receiver receiver, ValueNode[] args); +}
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/graphbuilderconf/InvocationPlugins.java Tue Nov 24 15:21:14 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/graphbuilderconf/InvocationPlugins.java Tue Nov 24 19:31:56 2015 +0100 @@ -566,7 +566,7 @@ assert !p.containsKey(method) : "a plugin is already registered for " + method; p = p.parent; } - if (plugin instanceof ForeignCallPlugin) { + if (plugin instanceof ForeignCallPlugin || plugin instanceof GeneratedInvocationPlugin) { return true; } if (plugin instanceof MethodSubstitutionPlugin) {
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/graphbuilderconf/NodeIntrinsicPluginFactory.java Tue Nov 24 19:31:56 2015 +0100 @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.nodes.graphbuilderconf; + +import com.oracle.graal.compiler.common.type.Stamp; + +public interface NodeIntrinsicPluginFactory { + + public interface InjectionProvider { + + <T> T getInjectedArgument(Class<T> type); + + Stamp getReturnStamp(Class<?> type); + } + + void registerPlugin(InvocationPlugins plugins, InjectionProvider injection); +}
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/memory/WriteNode.java Tue Nov 24 15:21:14 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/memory/WriteNode.java Tue Nov 24 19:31:56 2015 +0100 @@ -49,7 +49,7 @@ public static final NodeClass<WriteNode> TYPE = NodeClass.create(WriteNode.class); - private WriteNode(ValueNode address, LocationIdentity location, ValueNode value, BarrierType barrierType) { + protected WriteNode(ValueNode address, LocationIdentity location, ValueNode value, BarrierType barrierType) { this((AddressNode) address, location, value, barrierType); }
--- a/graal/com.oracle.graal.replacements.amd64/src/com/oracle/graal/replacements/amd64/AMD64MathSubstitutions.java Tue Nov 24 15:21:14 2015 +0100 +++ b/graal/com.oracle.graal.replacements.amd64/src/com/oracle/graal/replacements/amd64/AMD64MathSubstitutions.java Tue Nov 24 19:31:56 2015 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -114,9 +114,9 @@ } } - @NodeIntrinsic(value = ForeignCallNode.class, setStampFromReturnType = true) + @NodeIntrinsic(value = ForeignCallNode.class) private static native double callDouble1(@ConstantNodeParameter ForeignCallDescriptor descriptor, double value); - @NodeIntrinsic(value = ForeignCallNode.class, setStampFromReturnType = true) + @NodeIntrinsic(value = ForeignCallNode.class) private static native double callDouble2(@ConstantNodeParameter ForeignCallDescriptor descriptor, double a, double b); }
--- a/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/ReplacementsParseTest.java Tue Nov 24 15:21:14 2015 +0100 +++ b/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/ReplacementsParseTest.java Tue Nov 24 19:31:56 2015 +0100 @@ -35,6 +35,7 @@ import com.oracle.graal.graph.Node.ConstantNodeParameter; import com.oracle.graal.graph.Node.NodeIntrinsic; import com.oracle.graal.nodes.PiNode; +import com.oracle.graal.nodes.graphbuilderconf.GraphBuilderConfiguration.Plugins; import com.oracle.graal.nodes.spi.Replacements; import com.oracle.graal.runtime.RuntimeProvider; @@ -43,6 +44,14 @@ */ public class ReplacementsParseTest extends GraalCompilerTest { + @Override + protected Plugins getDefaultGraphBuilderPlugins() { + Plugins ret = super.getDefaultGraphBuilderPlugins(); + // manually register generated factory, jvmci service providers don't work from unit tests + new NodeIntrinsicFactory_ReplacementsParseTest_TestMethodsSubstitutions_asNonNullStringIntrinsic_2bfccb54().registerPlugin(ret.getInvocationPlugins(), null); + return ret; + } + private static final Object THROW_EXCEPTION_MARKER = new Object() { @Override public String toString() {
--- a/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/SubstitutionsTest.java Tue Nov 24 15:21:14 2015 +0100 +++ b/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/SubstitutionsTest.java Tue Nov 24 19:31:56 2015 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -46,12 +46,13 @@ import com.oracle.graal.nodes.ValueNode; import com.oracle.graal.nodes.calc.FloatingNode; import com.oracle.graal.nodes.extended.GuardingNode; +import com.oracle.graal.nodes.graphbuilderconf.GraphBuilderConfiguration.Plugins; import com.oracle.graal.nodes.memory.MemoryNode; public class SubstitutionsTest extends GraalCompilerTest { @NodeInfo(allowedUsageTypes = {Memory}) - private static class TestMemory extends FixedWithNextNode implements MemoryNode { + static class TestMemory extends FixedWithNextNode implements MemoryNode { private static final NodeClass<TestMemory> TYPE = NodeClass.create(TestMemory.class); public TestMemory() { @@ -63,7 +64,7 @@ } @NodeInfo(allowedUsageTypes = {Guard}) - private static class TestGuard extends FloatingNode implements GuardingNode { + static class TestGuard extends FloatingNode implements GuardingNode { private static final NodeClass<TestGuard> TYPE = NodeClass.create(TestGuard.class); @Input(Memory) MemoryNode memory; @@ -78,7 +79,7 @@ } @NodeInfo - private static class TestValue extends FloatingNode { + static class TestValue extends FloatingNode { private static final NodeClass<TestValue> TYPE = NodeClass.create(TestValue.class); @Input(Guard) GuardingNode guard; @@ -124,6 +125,16 @@ } @Override + protected Plugins getDefaultGraphBuilderPlugins() { + Plugins ret = super.getDefaultGraphBuilderPlugins(); + // manually register generated factories, jvmci service providers don't work from unit tests + new NodeIntrinsicFactory_SubstitutionsTest_TestGuard_guard_1c2b7e8f().registerPlugin(ret.getInvocationPlugins(), null); + new NodeIntrinsicFactory_SubstitutionsTest_TestMemory_memory().registerPlugin(ret.getInvocationPlugins(), null); + new NodeIntrinsicFactory_SubstitutionsTest_TestValue_value_a22f0f5f().registerPlugin(ret.getInvocationPlugins(), null); + return ret; + } + + @Override protected boolean checkHighTierGraph(StructuredGraph graph) { // Check that the graph contains the expected test nodes. NodeIterable<ReturnNode> retNodes = graph.getNodes().filter(ReturnNode.class);
--- a/graal/com.oracle.graal.replacements.verifier/src/com/oracle/graal/replacements/verifier/APHotSpotSignature.java Tue Nov 24 15:21:14 2015 +0100 +++ b/graal/com.oracle.graal.replacements.verifier/src/com/oracle/graal/replacements/verifier/APHotSpotSignature.java Tue Nov 24 19:31:56 2015 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -26,9 +26,18 @@ import java.util.List; import javax.annotation.processing.ProcessingEnvironment; +import javax.lang.model.element.Element; +import javax.lang.model.element.ElementKind; +import javax.lang.model.element.ExecutableElement; +import javax.lang.model.element.PackageElement; import javax.lang.model.element.TypeElement; +import javax.lang.model.element.VariableElement; +import javax.lang.model.type.ArrayType; +import javax.lang.model.type.DeclaredType; import javax.lang.model.type.TypeKind; import javax.lang.model.type.TypeMirror; +import javax.lang.model.type.TypeVariable; +import javax.lang.model.type.WildcardType; import javax.tools.Diagnostic.Kind; /** @@ -96,6 +105,81 @@ return cur; } + private static void getSignatureName(StringBuilder ret, Element element) { + Element enclosing = element.getEnclosingElement(); + if (enclosing.getKind() == ElementKind.PACKAGE) { + ret.append(((PackageElement) enclosing).getQualifiedName().toString().replace('.', '/')); + ret.append('/'); + } else { + getSignatureName(ret, enclosing); + ret.append('$'); + } + ret.append(element.getSimpleName()); + } + + private static void getSignatureString(StringBuilder ret, TypeMirror type) { + switch (type.getKind()) { + case ARRAY: + ret.append('['); + getSignatureString(ret, ((ArrayType) type).getComponentType()); + break; + case BOOLEAN: + ret.append('Z'); + break; + case BYTE: + ret.append('B'); + break; + case SHORT: + ret.append('S'); + break; + case CHAR: + ret.append('C'); + break; + case INT: + ret.append('I'); + break; + case LONG: + ret.append('J'); + break; + case FLOAT: + ret.append('F'); + break; + case DOUBLE: + ret.append('D'); + break; + case VOID: + ret.append('V'); + break; + case DECLARED: + ret.append('L'); + getSignatureName(ret, ((DeclaredType) type).asElement()); + ret.append(';'); + break; + case TYPEVAR: + getSignatureString(ret, ((TypeVariable) type).getUpperBound()); + break; + case WILDCARD: + getSignatureString(ret, ((WildcardType) type).getExtendsBound()); + break; + case INTERSECTION: + ret.append("Ljava/lang/Object;"); + break; + default: + throw new IllegalArgumentException(type.toString()); + } + } + + public static String toSignature(ExecutableElement intrinsicMethod) { + StringBuilder ret = new StringBuilder(); + ret.append('('); + for (VariableElement param : intrinsicMethod.getParameters()) { + getSignatureString(ret, param.asType()); + } + ret.append(')'); + getSignatureString(ret, intrinsicMethod.getReturnType()); + return ret.toString(); + } + public int getParameterCount(boolean withReceiver) { return arguments.size() + (withReceiver ? 1 : 0); }
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.replacements.verifier/src/com/oracle/graal/replacements/verifier/FoldPluginGenerator.java Tue Nov 24 19:31:56 2015 +0100 @@ -0,0 +1,161 @@ +/* + * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.replacements.verifier; + +import java.io.PrintWriter; +import java.lang.annotation.Annotation; +import java.util.List; + +import javax.annotation.processing.ProcessingEnvironment; +import javax.lang.model.element.AnnotationMirror; +import javax.lang.model.element.Element; +import javax.lang.model.element.ElementKind; +import javax.lang.model.element.ExecutableElement; +import javax.lang.model.element.Modifier; +import javax.lang.model.element.VariableElement; +import javax.lang.model.type.TypeMirror; +import javax.tools.Diagnostic.Kind; + +import com.oracle.graal.api.replacements.Fold; +import com.oracle.graal.replacements.verifier.InjectedDependencies.WellKnownDependency; + +/** + * Create graph builder plugins for {@link Fold} methods. + */ +public class FoldPluginGenerator extends PluginGenerator { + + private class FoldVerifier extends AbstractVerifier { + + public FoldVerifier(ProcessingEnvironment env) { + super(env); + } + + @Override + public void verify(Element element, AnnotationMirror annotation) { + if (element.getKind() != ElementKind.METHOD) { + assert false : "Element is guaranteed to be a method."; + return; + } + + ExecutableElement intrinsicMethod = (ExecutableElement) element; + if (intrinsicMethod.getModifiers().contains(Modifier.PRIVATE)) { + env.getMessager().printMessage(Kind.ERROR, "@Fold method can not be private.", element); + } else { + FoldPluginGenerator.this.createPluginFactory(intrinsicMethod, null, null); + } + } + + @Override + public Class<? extends Annotation> getAnnotationClass() { + return Fold.class; + } + } + + private TypeMirror stringType() { + return env.getElementUtils().getTypeElement("java.lang.String").asType(); + } + + public FoldPluginGenerator(ProcessingEnvironment env) { + super(env); + } + + public AbstractVerifier getVerifier() { + return new FoldVerifier(env); + } + + @Override + protected String getBaseName() { + return "FoldFactory"; + } + + @Override + protected void createImports(PrintWriter out, ExecutableElement intrinsicMethod, ExecutableElement targetMethod) { + out.printf("import jdk.vm.ci.meta.JavaConstant;\n"); + out.printf("import jdk.vm.ci.meta.JavaKind;\n"); + out.printf("import com.oracle.graal.nodes.ConstantNode;\n"); + super.createImports(out, intrinsicMethod, targetMethod); + } + + @Override + protected InjectedDependencies createExecute(PrintWriter out, ExecutableElement intrinsicMethod, ExecutableElement constructor, TypeMirror[] signature) { + InjectedDependencies deps = new InjectedDependencies(); + List<? extends VariableElement> params = intrinsicMethod.getParameters(); + + int idx = 0; + for (VariableElement param : params) { + constantArgument(out, deps, idx, param.asType(), idx); + idx++; + } + + if (intrinsicMethod.getAnnotation(Deprecated.class) != null) { + out.printf(" @SuppressWarnings(\"deprecation\")\n"); + } + out.printf(" %s result = %s.%s(", intrinsicMethod.getReturnType(), intrinsicMethod.getEnclosingElement(), intrinsicMethod.getSimpleName()); + if (idx > 0) { + out.printf("_arg0"); + for (int i = 1; i < idx; i++) { + out.printf(", _arg%d", i); + } + } + out.printf(");\n"); + + TypeMirror returnType = intrinsicMethod.getReturnType(); + switch (returnType.getKind()) { + case BOOLEAN: + out.printf(" JavaConstant constant = JavaConstant.forInt(result ? 1 : 0);\n"); + break; + case BYTE: + case SHORT: + case CHAR: + case INT: + out.printf(" JavaConstant constant = JavaConstant.forInt(result);\n"); + break; + case LONG: + out.printf(" JavaConstant constant = JavaConstant.forLong(result);\n"); + break; + case FLOAT: + out.printf(" JavaConstant constant = JavaConstant.forFloat(result);\n"); + break; + case DOUBLE: + out.printf(" JavaConstant constant = JavaConstant.forDouble(result);\n"); + break; + case ARRAY: + case TYPEVAR: + case DECLARED: + if (returnType.equals(stringType())) { + out.printf(" JavaConstant constant = %s.forString(result);\n", deps.use(WellKnownDependency.CONSTANT_REFLECTION)); + } else { + out.printf(" JavaConstant constant = %s.forObject(result);\n", deps.use(WellKnownDependency.SNIPPET_REFLECTION)); + } + break; + default: + throw new IllegalArgumentException(returnType.toString()); + } + + out.printf(" ConstantNode node = ConstantNode.forConstant(constant, %s, %s);\n", deps.use(WellKnownDependency.META_ACCESS), deps.use(WellKnownDependency.STRUCTURED_GRAPH)); + out.printf(" b.push(JavaKind.%s, node);\n", getReturnKind(intrinsicMethod).name()); + out.printf(" return true;\n"); + + return deps; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.replacements.verifier/src/com/oracle/graal/replacements/verifier/InjectedDependencies.java Tue Nov 24 19:31:56 2015 +0100 @@ -0,0 +1,139 @@ +/* + * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.replacements.verifier; + +import java.util.HashMap; +import java.util.Iterator; + +import javax.annotation.processing.ProcessingEnvironment; +import javax.lang.model.element.ExecutableElement; +import javax.lang.model.type.DeclaredType; +import javax.lang.model.type.TypeMirror; + +import com.oracle.graal.replacements.verifier.InjectedDependencies.Dependency; + +public class InjectedDependencies implements Iterable<Dependency> { + + public abstract static class Dependency { + + public final String name; + public final String type; + + private Dependency(String name, String type) { + this.name = name; + this.type = type; + } + + public abstract String inject(ExecutableElement inject); + } + + private static final class InjectedDependency extends Dependency { + + private InjectedDependency(String name, String type) { + super(name, type); + } + + @Override + public String inject(ExecutableElement inject) { + return String.format("injection.getInjectedArgument(%s.class)", type); + } + } + + private static final class StampDependency extends Dependency { + + private StampDependency() { + super("returnStamp", "com.oracle.graal.compiler.common.type.Stamp"); + } + + @Override + public String inject(ExecutableElement inject) { + return String.format("injection.getReturnStamp(%s.class)", NodeIntrinsicPluginGenerator.getErasedType(inject.getReturnType())); + } + } + + public enum WellKnownDependency { + CONSTANT_REFLECTION("b.getConstantReflection()", "jdk.vm.ci.meta.ConstantReflectionProvider"), + META_ACCESS("b.getMetaAccess()", "jdk.vm.ci.meta.MetaAccessProvider"), + RETURN_STAMP(new StampDependency()), + SNIPPET_REFLECTION(new InjectedDependency("snippetReflection", "com.oracle.graal.api.replacements.SnippetReflectionProvider")), + STAMP_PROVIDER("b.getStampProvider()", "com.oracle.graal.nodes.spi.StampProvider"), + STRUCTURED_GRAPH("b.getGraph()", "com.oracle.graal.nodes.StructuredGraph"); + + private final String expr; + private final String type; + private final Dependency generateMember; + + private WellKnownDependency(String expr, String type) { + this.expr = expr; + this.type = type; + this.generateMember = null; + } + + private WellKnownDependency(Dependency generateMember) { + this.expr = generateMember.name; + this.type = generateMember.type; + this.generateMember = generateMember; + } + + private TypeMirror getType(ProcessingEnvironment env) { + return env.getElementUtils().getTypeElement(type).asType(); + } + } + + private final HashMap<String, Dependency> deps; + + public InjectedDependencies() { + deps = new HashMap<>(); + } + + public String use(WellKnownDependency wellKnown) { + if (wellKnown.generateMember != null) { + deps.put(wellKnown.type, wellKnown.generateMember); + } + return wellKnown.expr; + } + + public String use(ProcessingEnvironment env, DeclaredType type) { + for (WellKnownDependency wellKnown : WellKnownDependency.values()) { + if (env.getTypeUtils().isAssignable(wellKnown.getType(env), type)) { + return use(wellKnown); + } + } + + String typeName = type.toString(); + Dependency ret = deps.get(typeName); + if (ret == null) { + ret = new InjectedDependency("injected" + type.asElement().getSimpleName(), typeName); + deps.put(typeName, ret); + } + return ret.name; + } + + public Iterator<Dependency> iterator() { + return deps.values().iterator(); + } + + public boolean isEmpty() { + return deps.isEmpty(); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.replacements.verifier/src/com/oracle/graal/replacements/verifier/NodeIntrinsicPluginGenerator.java Tue Nov 24 19:31:56 2015 +0100 @@ -0,0 +1,133 @@ +/* + * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.replacements.verifier; + +import java.io.PrintWriter; +import java.util.List; + +import javax.annotation.processing.ProcessingEnvironment; +import javax.lang.model.element.ElementKind; +import javax.lang.model.element.ExecutableElement; +import javax.lang.model.element.VariableElement; +import javax.lang.model.type.DeclaredType; +import javax.lang.model.type.TypeMirror; +import javax.tools.Diagnostic.Kind; + +import jdk.vm.ci.meta.JavaKind; + +import com.oracle.graal.graph.Node.ConstantNodeParameter; +import com.oracle.graal.graph.Node.InjectedNodeParameter; +import com.oracle.graal.graph.Node.NodeIntrinsic; +import com.oracle.graal.replacements.verifier.InjectedDependencies.WellKnownDependency; + +/** + * Create graph builder plugins for {@link NodeIntrinsic} methods. + */ +public class NodeIntrinsicPluginGenerator extends PluginGenerator { + + public NodeIntrinsicPluginGenerator(ProcessingEnvironment env) { + super(env); + } + + private TypeMirror valueNodeType() { + return env.getElementUtils().getTypeElement("com.oracle.graal.nodes.ValueNode").asType(); + } + + @Override + protected String getBaseName() { + return "NodeIntrinsicFactory"; + } + + @Override + protected void createImports(PrintWriter out, ExecutableElement intrinsicMethod, ExecutableElement targetMethod) { + if (targetMethod.getKind() == ElementKind.CONSTRUCTOR && getReturnKind(intrinsicMethod) != JavaKind.Void) { + out.printf("import jdk.vm.ci.meta.JavaKind;\n"); + } + super.createImports(out, intrinsicMethod, targetMethod); + } + + @Override + protected InjectedDependencies createExecute(PrintWriter out, ExecutableElement intrinsicMethod, ExecutableElement constructor, TypeMirror[] signature) { + InjectedDependencies deps = new InjectedDependencies(); + + List<? extends VariableElement> params = constructor.getParameters(); + + boolean customFactory = constructor.getKind() != ElementKind.CONSTRUCTOR; + int idx = customFactory ? 1 : 0; + for (; idx < params.size(); idx++) { + VariableElement param = params.get(idx); + if (param.getAnnotation(InjectedNodeParameter.class) == null) { + break; + } + + out.printf(" %s _arg%d = %s;\n", param.asType(), idx, deps.use(env, (DeclaredType) param.asType())); + } + + for (int i = 0; i < signature.length; i++, idx++) { + if (intrinsicMethod.getParameters().get(i).getAnnotation(ConstantNodeParameter.class) != null) { + constantArgument(out, deps, idx, signature[i], i); + } else { + if (signature[i].equals(valueNodeType())) { + out.printf(" ValueNode _arg%d = args[%d];\n", idx, i); + } else { + out.printf(" %s _arg%d = (%s) args[%d];\n", signature[i], idx, signature[i], i); + } + } + } + + if (customFactory) { + out.printf(" return %s.%s(b", constructor.getEnclosingElement(), constructor.getSimpleName()); + for (int i = 1; i < idx; i++) { + out.printf(", _arg%d", i); + } + out.printf(");\n"); + + if (intrinsicMethod.getAnnotation(NodeIntrinsic.class).setStampFromReturnType()) { + env.getMessager().printMessage(Kind.WARNING, "Ignoring setStampFromReturnType because a custom 'intrinsify' method is used.", intrinsicMethod); + } + } else { + out.printf(" %s node = new %s(", constructor.getEnclosingElement(), constructor.getEnclosingElement()); + if (idx > 0) { + out.printf("_arg0"); + for (int i = 1; i < idx; i++) { + out.printf(", _arg%d", i); + } + } + out.printf(");\n"); + + if (intrinsicMethod.getAnnotation(NodeIntrinsic.class).setStampFromReturnType()) { + out.printf(" node.setStamp(%s);\n", deps.use(WellKnownDependency.RETURN_STAMP)); + } + + JavaKind returnKind = getReturnKind(intrinsicMethod); + if (returnKind == JavaKind.Void) { + out.printf(" b.add(node);\n"); + } else { + out.printf(" b.addPush(JavaKind.%s, node);\n", returnKind.name()); + } + out.printf(" return true;\n"); + } + + return deps; + } +}
--- a/graal/com.oracle.graal.replacements.verifier/src/com/oracle/graal/replacements/verifier/NodeIntrinsicVerifier.java Tue Nov 24 15:21:14 2015 +0100 +++ b/graal/com.oracle.graal.replacements.verifier/src/com/oracle/graal/replacements/verifier/NodeIntrinsicVerifier.java Tue Nov 24 19:31:56 2015 +0100 @@ -73,8 +73,15 @@ return env.getElementUtils().getTypeElement("com.oracle.graal.nodeinfo.StructuralInput").asType(); } + private TypeMirror graphBuilderContextType() { + return env.getElementUtils().getTypeElement("com.oracle.graal.nodes.graphbuilderconf.GraphBuilderContext").asType(); + } + + private final NodeIntrinsicPluginGenerator factoryGen; + public NodeIntrinsicVerifier(ProcessingEnvironment env) { super(env); + factoryGen = new NodeIntrinsicPluginGenerator(env); } @Override @@ -114,20 +121,28 @@ env.getMessager().printMessage(Kind.ERROR, "@NodeIntrinsic cannot have a generic return type.", element, annotation); } - if (isNodeType(nodeClass)) { - if (nodeClass.getModifiers().contains(Modifier.ABSTRACT)) { - env.getMessager().printMessage(Kind.ERROR, String.format("Cannot make @NodeIntrinsic for abstract node class %s.", nodeClass.getSimpleName()), element, annotation); + TypeMirror[] constructorSignature = constructorSignature(intrinsicMethod); + ExecutableElement custom = findCustomIntrinsifyMethod(nodeClass, constructorSignature); + if (custom != null) { + factoryGen.createPluginFactory(intrinsicMethod, custom, constructorSignature); + } else { + if (isNodeType(nodeClass)) { + if (nodeClass.getModifiers().contains(Modifier.ABSTRACT)) { + env.getMessager().printMessage(Kind.ERROR, String.format("Cannot make @NodeIntrinsic for abstract node class %s.", nodeClass.getSimpleName()), element, annotation); + } else { + TypeMirror ret = intrinsicMethod.getReturnType(); + if (env.getTypeUtils().isAssignable(ret, structuralInputType())) { + checkInputType(nodeClass, ret, element, annotation); + } + + ExecutableElement constructor = findConstructor(nodeClass, constructorSignature, intrinsicMethod, annotation); + if (constructor != null) { + factoryGen.createPluginFactory(intrinsicMethod, constructor, constructorSignature); + } + } } else { - TypeMirror ret = intrinsicMethod.getReturnType(); - if (env.getTypeUtils().isAssignable(ret, structuralInputType())) { - checkInputType(nodeClass, ret, element, annotation); - } - - TypeMirror[] constructorSignature = constructorSignature(intrinsicMethod); - findConstructor(nodeClass, constructorSignature, intrinsicMethod, annotation); + env.getMessager().printMessage(Kind.ERROR, String.format("The class %s is not a Node subclass.", nodeClass.getSimpleName()), element, annotation); } - } else { - env.getMessager().printMessage(Kind.ERROR, String.format("The class %s is not a Node subclass.", nodeClass.getSimpleName()), element, annotation); } } @@ -185,47 +200,18 @@ return parameters; } - private void findConstructor(TypeElement nodeClass, TypeMirror[] signature, ExecutableElement intrinsicMethod, AnnotationMirror intrinsicAnnotation) { + private ExecutableElement findConstructor(TypeElement nodeClass, TypeMirror[] signature, ExecutableElement intrinsicMethod, AnnotationMirror intrinsicAnnotation) { List<ExecutableElement> constructors = ElementFilter.constructorsIn(nodeClass.getEnclosedElements()); List<String> failureReasons = new ArrayList<>(); - nextConstructor: for (ExecutableElement constructor : constructors) { - int sIdx = 0; - int cIdx = 0; - while (cIdx < constructor.getParameters().size()) { - VariableElement parameter = constructor.getParameters().get(cIdx++); - if (parameter.getAnnotation(InjectedNodeParameter.class) != null) { - // skip injected parameters - continue; - } - - TypeMirror paramType = parameter.asType(); - if (cIdx == constructor.getParameters().size() && paramType.getKind() == TypeKind.ARRAY) { - // last argument of constructor is varargs, match remaining intrinsic arguments - TypeMirror varargsType = ((ArrayType) paramType).getComponentType(); - while (sIdx < signature.length) { - if (!isTypeCompatible(varargsType, signature[sIdx++])) { - failureReasons.add(String.format("Constructor %s failed because the types of argument %d are incompatible: %s != %s", constructor, sIdx, varargsType, signature[sIdx - 1])); - continue nextConstructor; - } - } - } else if (sIdx >= signature.length) { - // too many arguments in intrinsic method - failureReasons.add(String.format("Too many arguments for %s", constructor)); - continue nextConstructor; - } else if (!isTypeCompatible(paramType, signature[sIdx++])) { - failureReasons.add(String.format("Constructor %s failed because the types of argument %d are incompatible: %s != %s", constructor, sIdx, paramType, signature[sIdx - 1])); - continue nextConstructor; - } + for (ExecutableElement constructor : constructors) { + String failureReason = matchSignature(false, constructor, signature); + if (failureReason == null) { + // found + return constructor; } - if (sIdx == signature.length) { - // found - return; - } - - // too many arguments in constructor - failureReasons.add(String.format("Not enough arguments for %s", constructor)); + failureReasons.add(failureReason); } // not found @@ -236,6 +222,70 @@ env.getMessager().printMessage(Kind.ERROR, reason, intrinsicMethod, intrinsicAnnotation); } } + + return null; + } + + private ExecutableElement findCustomIntrinsifyMethod(TypeElement nodeClass, TypeMirror[] signature) { + List<ExecutableElement> methods = ElementFilter.methodsIn(nodeClass.getEnclosedElements()); + for (ExecutableElement method : methods) { + if (!method.getSimpleName().toString().equals("intrinsify")) { + continue; + } + + if (method.getParameters().isEmpty()) { + continue; + } + + VariableElement firstArg = method.getParameters().get(0); + if (!isTypeCompatible(firstArg.asType(), graphBuilderContextType())) { + continue; + } + + String failureReason = matchSignature(true, method, signature); + if (failureReason == null) { + // found + return method; + } + } + + return null; + } + + private String matchSignature(boolean skipFirst, ExecutableElement method, TypeMirror[] signature) { + int sIdx = 0; + int cIdx = skipFirst ? 1 : 0; + while (cIdx < method.getParameters().size()) { + VariableElement parameter = method.getParameters().get(cIdx++); + if (parameter.getAnnotation(InjectedNodeParameter.class) != null) { + // skip injected parameters + continue; + } + + TypeMirror paramType = parameter.asType(); + if (cIdx == method.getParameters().size() && paramType.getKind() == TypeKind.ARRAY) { + // last argument of constructor is varargs, match remaining intrinsic arguments + TypeMirror varargsType = ((ArrayType) paramType).getComponentType(); + while (sIdx < signature.length) { + if (!isTypeCompatible(varargsType, signature[sIdx++])) { + return String.format("%s failed because the types of argument %d are incompatible: %s != %s", method, sIdx, varargsType, signature[sIdx - 1]); + } + } + } else if (sIdx >= signature.length) { + // too many arguments in intrinsic method + return String.format("Too many arguments for %s", method); + } else if (!isTypeCompatible(paramType, signature[sIdx++])) { + return String.format("%s failed because the types of argument %d are incompatible: %s != %s", method, sIdx, paramType, signature[sIdx - 1]); + } + } + + if (sIdx == signature.length) { + // found + return null; + } + + // too many arguments in constructor + return String.format("Not enough arguments for %s", method); } private boolean isTypeCompatible(TypeMirror originalType, TypeMirror substitutionType) {
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.replacements.verifier/src/com/oracle/graal/replacements/verifier/PluginGenerator.java Tue Nov 24 19:31:56 2015 +0100 @@ -0,0 +1,260 @@ +/* + * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.replacements.verifier; + +import java.io.IOException; +import java.io.PrintWriter; + +import javax.annotation.processing.ProcessingEnvironment; +import javax.lang.model.element.Element; +import javax.lang.model.element.ElementKind; +import javax.lang.model.element.ExecutableElement; +import javax.lang.model.element.PackageElement; +import javax.lang.model.element.TypeElement; +import javax.lang.model.element.VariableElement; +import javax.lang.model.type.ArrayType; +import javax.lang.model.type.DeclaredType; +import javax.lang.model.type.TypeMirror; +import javax.lang.model.type.TypeVariable; +import javax.lang.model.type.WildcardType; +import javax.tools.Diagnostic; +import javax.tools.JavaFileObject; + +import jdk.vm.ci.meta.JavaKind; + +import com.oracle.graal.replacements.verifier.InjectedDependencies.Dependency; +import com.oracle.graal.replacements.verifier.InjectedDependencies.WellKnownDependency; + +public abstract class PluginGenerator { + + protected final ProcessingEnvironment env; + + public PluginGenerator(ProcessingEnvironment env) { + this.env = env; + } + + private TypeMirror resolvedJavaTypeType() { + return env.getElementUtils().getTypeElement("jdk.vm.ci.meta.ResolvedJavaType").asType(); + } + + private static PackageElement getPackage(Element element) { + Element enclosing = element; + while (enclosing != null && enclosing.getKind() != ElementKind.PACKAGE) { + enclosing = enclosing.getEnclosingElement(); + } + return (PackageElement) enclosing; + } + + private static void mkClassName(StringBuilder ret, Element cls) { + Element enclosingClass = cls.getEnclosingElement(); + if (enclosingClass.getKind() == ElementKind.CLASS || enclosingClass.getKind() == ElementKind.INTERFACE) { + mkClassName(ret, enclosingClass); + ret.append('_'); + } + ret.append(cls.getSimpleName()); + } + + static String getErasedType(TypeMirror type) { + switch (type.getKind()) { + case DECLARED: + DeclaredType declared = (DeclaredType) type; + TypeElement element = (TypeElement) declared.asElement(); + return element.getQualifiedName().toString(); + case TYPEVAR: + return getErasedType(((TypeVariable) type).getUpperBound()); + case WILDCARD: + return getErasedType(((WildcardType) type).getExtendsBound()); + case ARRAY: + return getErasedType(((ArrayType) type).getComponentType()) + "[]"; + default: + return type.toString(); + } + } + + protected abstract String getBaseName(); + + private String mkFactoryClassName(ExecutableElement intrinsicMethod) { + StringBuilder ret = new StringBuilder(); + ret.append(getBaseName()); + ret.append('_'); + mkClassName(ret, intrinsicMethod.getEnclosingElement()); + ret.append('_'); + ret.append(intrinsicMethod.getSimpleName()); + if (!intrinsicMethod.getParameters().isEmpty()) { + ret.append('_'); + ret.append(Integer.toHexString(APHotSpotSignature.toSignature(intrinsicMethod).hashCode())); + } + return ret.toString(); + } + + void createPluginFactory(ExecutableElement intrinsicMethod, ExecutableElement targetMethod, TypeMirror[] constructorSignature) { + Element declaringClass = intrinsicMethod.getEnclosingElement(); + PackageElement pkg = getPackage(declaringClass); + + String genClassName = mkFactoryClassName(intrinsicMethod); + + try { + JavaFileObject factory = env.getFiler().createSourceFile(pkg.getQualifiedName() + "." + genClassName, intrinsicMethod); + try (PrintWriter out = new PrintWriter(factory.openWriter())) { + out.printf("// CheckStyle: stop header check\n"); + out.printf("// CheckStyle: stop line length check\n"); + out.printf("// GENERATED CONTENT - DO NOT EDIT\n"); + out.printf("package %s;\n", pkg.getQualifiedName()); + out.printf("\n"); + createImports(out, intrinsicMethod, targetMethod); + out.printf("\n"); + out.printf("@ServiceProvider(NodeIntrinsicPluginFactory.class)\n"); + out.printf("public class %s implements NodeIntrinsicPluginFactory {\n", genClassName); + out.printf("\n"); + out.printf(" private static final class Plugin extends GeneratedInvocationPlugin {\n"); + out.printf("\n"); + + out.printf(" @Override\n"); + out.printf(" public boolean execute(GraphBuilderContext b, ResolvedJavaMethod targetMethod, InvocationPlugin.Receiver receiver, ValueNode[] args) {\n"); + out.printf(" if (!b.parsingIntrinsic()) {\n"); + out.printf(" return false;\n"); + out.printf(" }\n"); + InjectedDependencies deps = createExecute(out, intrinsicMethod, targetMethod, constructorSignature); + out.printf(" }\n"); + + createPrivateMembers(out, intrinsicMethod, deps); + + out.printf(" }\n"); + out.printf("\n"); + createPluginFactoryMethod(out, intrinsicMethod, deps); + out.printf("}\n"); + } + } catch (IOException e) { + env.getMessager().printMessage(Diagnostic.Kind.ERROR, e.getMessage()); + } + } + + protected abstract InjectedDependencies createExecute(PrintWriter out, ExecutableElement intrinsicMethod, ExecutableElement constructor, TypeMirror[] signature); + + protected void createImports(PrintWriter out, @SuppressWarnings("unused") ExecutableElement intrinsicMethod, @SuppressWarnings("unused") ExecutableElement targetMethod) { + out.printf("import jdk.vm.ci.meta.ResolvedJavaMethod;\n"); + out.printf("import jdk.vm.ci.service.ServiceProvider;\n"); + out.printf("\n"); + out.printf("import com.oracle.graal.nodes.ValueNode;\n"); + out.printf("import com.oracle.graal.nodes.graphbuilderconf.GraphBuilderContext;\n"); + out.printf("import com.oracle.graal.nodes.graphbuilderconf.GeneratedInvocationPlugin;\n"); + out.printf("import com.oracle.graal.nodes.graphbuilderconf.InvocationPlugin;\n"); + out.printf("import com.oracle.graal.nodes.graphbuilderconf.InvocationPlugins;\n"); + out.printf("import com.oracle.graal.nodes.graphbuilderconf.NodeIntrinsicPluginFactory;\n"); + } + + private static void createPrivateMembers(PrintWriter out, ExecutableElement intrinsicMethod, InjectedDependencies deps) { + if (!deps.isEmpty()) { + out.printf("\n"); + for (Dependency dep : deps) { + out.printf(" private final %s %s;\n", dep.type, dep.name); + } + + out.printf("\n"); + out.printf(" private Plugin(InjectionProvider injection) {\n"); + for (Dependency dep : deps) { + out.printf(" this.%s = %s;\n", dep.name, dep.inject(intrinsicMethod)); + } + out.printf(" }\n"); + } + } + + private static void createPluginFactoryMethod(PrintWriter out, ExecutableElement intrinsicMethod, InjectedDependencies deps) { + out.printf(" public void registerPlugin(InvocationPlugins plugins, InjectionProvider injection) {\n"); + out.printf(" Plugin plugin = new Plugin(%s);\n", deps.isEmpty() ? "" : "injection"); + out.printf(" plugins.register(plugin, %s.class, \"%s\"", intrinsicMethod.getEnclosingElement(), intrinsicMethod.getSimpleName()); + for (VariableElement arg : intrinsicMethod.getParameters()) { + out.printf(", %s.class", getErasedType(arg.asType())); + } + out.printf(");\n"); + out.printf(" }\n"); + } + + protected static JavaKind getReturnKind(ExecutableElement method) { + switch (method.getReturnType().getKind()) { + case BOOLEAN: + case BYTE: + case SHORT: + case CHAR: + case INT: + return JavaKind.Int; + case LONG: + return JavaKind.Long; + case FLOAT: + return JavaKind.Float; + case DOUBLE: + return JavaKind.Double; + case VOID: + return JavaKind.Void; + case ARRAY: + case TYPEVAR: + case DECLARED: + return JavaKind.Object; + default: + throw new IllegalArgumentException(method.getReturnType().toString()); + } + } + + protected void constantArgument(PrintWriter out, InjectedDependencies deps, int argIdx, TypeMirror type, int nodeIdx) { + out.printf(" %s _arg%d;\n", type, argIdx); + out.printf(" if (args[%d].isConstant()) {\n", nodeIdx); + if (type.equals(resolvedJavaTypeType())) { + out.printf(" _arg%d = %s.asJavaType(args[%d].asConstant());\n", argIdx, deps.use(WellKnownDependency.CONSTANT_REFLECTION), nodeIdx); + } else { + switch (type.getKind()) { + case BOOLEAN: + out.printf(" _arg%d = args[%d].asJavaConstant().asInt() != 0;\n", argIdx, nodeIdx); + break; + case BYTE: + out.printf(" _arg%d = (byte) args[%d].asJavaConstant().asInt();\n", argIdx, nodeIdx); + break; + case CHAR: + out.printf(" _arg%d = (char) args[%d].asJavaConstant().asInt();\n", argIdx, nodeIdx); + break; + case SHORT: + out.printf(" _arg%d = (short) args[%d].asJavaConstant().asInt();\n", argIdx, nodeIdx); + break; + case INT: + out.printf(" _arg%d = args[%d].asJavaConstant().asInt();\n", argIdx, nodeIdx); + break; + case LONG: + out.printf(" _arg%d = args[%d].asJavaConstant().asLong();\n", argIdx, nodeIdx); + break; + case FLOAT: + out.printf(" _arg%d = args[%d].asJavaConstant().asFloat();\n", argIdx, nodeIdx); + break; + case DOUBLE: + out.printf(" _arg%d = args[%d].asJavaConstant().asDouble();\n", argIdx, nodeIdx); + break; + case DECLARED: + out.printf(" _arg%d = %s.asObject(%s.class, args[%d].asJavaConstant());\n", argIdx, deps.use(WellKnownDependency.SNIPPET_REFLECTION), type, nodeIdx); + break; + default: + throw new IllegalArgumentException(); + } + } + out.printf(" } else {\n"); + out.printf(" return false;\n"); + out.printf(" }\n"); + } +}
--- a/graal/com.oracle.graal.replacements.verifier/src/com/oracle/graal/replacements/verifier/VerifierAnnotationProcessor.java Tue Nov 24 15:21:14 2015 +0100 +++ b/graal/com.oracle.graal.replacements.verifier/src/com/oracle/graal/replacements/verifier/VerifierAnnotationProcessor.java Tue Nov 24 19:31:56 2015 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -84,6 +84,7 @@ verifiers.add(new ClassSubstitutionVerifier(this.processingEnv)); verifiers.add(new MethodSubstitutionVerifier(this.processingEnv)); verifiers.add(new NodeIntrinsicVerifier(this.processingEnv)); + verifiers.add(new FoldPluginGenerator(this.processingEnv).getVerifier()); } return verifiers; }
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/NodeIntrinsicFactory.java Tue Nov 24 19:31:56 2015 +0100 @@ -0,0 +1,176 @@ +/* + * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.replacements; + +import java.lang.reflect.Array; +import java.util.List; + +import jdk.vm.ci.meta.Constant; +import jdk.vm.ci.meta.ConstantReflectionProvider; +import jdk.vm.ci.meta.JavaConstant; +import jdk.vm.ci.meta.JavaKind; +import jdk.vm.ci.meta.ResolvedJavaMethod; +import jdk.vm.ci.meta.ResolvedJavaType; + +import com.oracle.graal.api.replacements.SnippetReflectionProvider; +import com.oracle.graal.compiler.common.type.Stamp; +import com.oracle.graal.graph.NodeClass; +import com.oracle.graal.graph.NodeInputList; +import com.oracle.graal.nodeinfo.NodeInfo; +import com.oracle.graal.nodes.FixedWithNextNode; +import com.oracle.graal.nodes.StructuredGraph; +import com.oracle.graal.nodes.ValueNode; + +@NodeInfo +public final class NodeIntrinsicFactory extends FixedWithNextNode { + + public static final NodeClass<NodeIntrinsicFactory> TYPE = NodeClass.create(NodeIntrinsicFactory.class); + + public static final Object GRAPH_MARKER = new Object(); + + private final ResolvedJavaMethod constructor; + private final boolean setStampFromReturnType; + + private final Object[] injectedArguments; + + private final Class<?>[] argumentTypes; + @Input NodeInputList<ValueNode> arguments; + + private final Class<?> varargsType; + @Input NodeInputList<ValueNode> varargs; + + public NodeIntrinsicFactory(Stamp stamp, ResolvedJavaMethod constructor, boolean setStampFromReturnType, Object[] injectedArguments, Class<?>[] argumentTypes, List<ValueNode> arguments) { + this(stamp, constructor, setStampFromReturnType, injectedArguments, argumentTypes, arguments, null, null); + } + + public NodeIntrinsicFactory(Stamp stamp, ResolvedJavaMethod constructor, boolean setStampFromReturnType, Object[] injectedArguments, Class<?>[] argumentTypes, List<ValueNode> arguments, + Class<?> varargsType, List<ValueNode> varargs) { + super(TYPE, stamp); + + this.constructor = constructor; + this.setStampFromReturnType = setStampFromReturnType; + + this.injectedArguments = injectedArguments; + + this.argumentTypes = argumentTypes; + this.arguments = new NodeInputList<>(this, arguments); + + this.varargsType = varargsType; + if (varargs == null) { + this.varargs = new NodeInputList<>(this); + } else { + this.varargs = new NodeInputList<>(this, varargs); + } + } + + private static Object mkConstArgument(Class<?> argType, Constant constant, ConstantReflectionProvider constantReflection, SnippetReflectionProvider snippetReflection) { + if (argType == ResolvedJavaType.class) { + ResolvedJavaType type = constantReflection.asJavaType(constant); + assert type != null; + return type; + } else { + JavaConstant javaConstant = (JavaConstant) constant; + switch (JavaKind.fromJavaClass(argType)) { + case Boolean: + return Boolean.valueOf(javaConstant.asInt() != 0); + case Byte: + return Byte.valueOf((byte) javaConstant.asInt()); + case Short: + return Short.valueOf((short) javaConstant.asInt()); + case Char: + return Character.valueOf((char) javaConstant.asInt()); + case Object: + return snippetReflection.asObject(argType, javaConstant); + default: + return javaConstant.asBoxedPrimitive(); + } + } + } + + public ValueNode intrinsify(StructuredGraph graph, ConstantReflectionProvider constantReflection, SnippetReflectionProvider snippetReflection) { + int totalArgCount = arguments.count(); + if (injectedArguments != null) { + totalArgCount += injectedArguments.length; + } + if (varargsType != null) { + totalArgCount++; + } + + Object[] args = new Object[totalArgCount]; + int idx = 0; + + if (injectedArguments != null) { + for (int i = 0; i < injectedArguments.length; i++) { + if (injectedArguments[i] == GRAPH_MARKER) { + args[idx++] = graph; + } else { + args[idx++] = injectedArguments[i]; + } + } + } + + for (int i = 0; i < arguments.size(); i++) { + ValueNode node = arguments.get(i); + if (argumentTypes[i] == ValueNode.class) { + args[idx++] = node; + } else { + if (!node.isConstant()) { + return null; + } + + args[idx++] = mkConstArgument(argumentTypes[i], node.asConstant(), constantReflection, snippetReflection); + } + } + + if (varargsType != null) { + if (varargsType == ValueNode.class) { + args[idx++] = varargs.toArray(new ValueNode[0]); + } else { + Object array = Array.newInstance(varargsType, varargs.size()); + args[idx++] = array; + + for (int i = 0; i < varargs.size(); i++) { + ValueNode node = varargs.get(i); + if (!node.isConstant()) { + return null; + } + + Object arg = mkConstArgument(varargsType, node.asConstant(), constantReflection, snippetReflection); + if (varargsType.isPrimitive()) { + Array.set(array, i, arg); + } else { + ((Object[]) array)[i] = arg; + } + } + } + } + + assert idx == totalArgCount; + + ValueNode node = (ValueNode) snippetReflection.invoke(constructor, null, args); + if (setStampFromReturnType) { + node.setStamp(this.stamp()); + } + return node; + } +}
--- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/NodeIntrinsificationPhase.java Tue Nov 24 15:21:14 2015 +0100 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/NodeIntrinsificationPhase.java Tue Nov 24 19:31:56 2015 +0100 @@ -22,15 +22,14 @@ */ package com.oracle.graal.replacements; -import static jdk.vm.ci.meta.MetaUtil.resolveJavaTypes; - -import java.lang.reflect.Array; +import java.lang.annotation.Annotation; +import java.lang.reflect.Constructor; +import java.lang.reflect.Executable; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import jdk.vm.ci.common.JVMCIError; -import jdk.vm.ci.meta.Constant; import jdk.vm.ci.meta.ConstantReflectionProvider; import jdk.vm.ci.meta.JavaConstant; import jdk.vm.ci.meta.JavaKind; @@ -39,6 +38,7 @@ import jdk.vm.ci.meta.PrimitiveConstant; import jdk.vm.ci.meta.ResolvedJavaMethod; import jdk.vm.ci.meta.ResolvedJavaType; +import jdk.vm.ci.meta.Signature; import com.oracle.graal.api.replacements.Fold; import com.oracle.graal.api.replacements.SnippetReflectionProvider; @@ -65,32 +65,65 @@ import com.oracle.graal.nodes.extended.UnboxNode; import com.oracle.graal.nodes.extended.UnsafeStoreNode; import com.oracle.graal.nodes.extended.ValueAnchorNode; +import com.oracle.graal.nodes.graphbuilderconf.NodeIntrinsicPluginFactory.InjectionProvider; import com.oracle.graal.nodes.java.CheckCastNode; import com.oracle.graal.nodes.java.LoadFieldNode; import com.oracle.graal.nodes.java.MethodCallTargetNode; import com.oracle.graal.nodes.spi.StampProvider; import com.oracle.graal.nodes.util.GraphUtil; import com.oracle.graal.phases.Phase; +import com.oracle.graal.word.WordTypes; /** * Replaces calls to {@link NodeIntrinsic}s with nodes and calls to methods annotated with * {@link Fold} with the result of invoking the annotated method via reflection. */ -public class NodeIntrinsificationPhase extends Phase { +public class NodeIntrinsificationPhase extends Phase implements InjectionProvider { private final MetaAccessProvider metaAccess; private final ConstantReflectionProvider constantReflection; private final SnippetReflectionProvider snippetReflection; private final ForeignCallsProvider foreignCalls; private final StampProvider stampProvider; + private final WordTypes wordTypes; public NodeIntrinsificationPhase(MetaAccessProvider metaAccess, ConstantReflectionProvider constantReflection, SnippetReflectionProvider snippetReflection, ForeignCallsProvider foreignCalls, - StampProvider stampProvider) { + StampProvider stampProvider, WordTypes wordTypes) { this.metaAccess = metaAccess; this.constantReflection = constantReflection; this.snippetReflection = snippetReflection; this.foreignCalls = foreignCalls; this.stampProvider = stampProvider; + this.wordTypes = wordTypes; + } + + @Override + public Stamp getReturnStamp(Class<?> type) { + JavaKind kind = JavaKind.fromJavaClass(type); + if (kind == JavaKind.Object) { + ResolvedJavaType returnType = metaAccess.lookupJavaType(type); + if (wordTypes.isWord(returnType)) { + return wordTypes.getWordStamp(returnType); + } else { + return StampFactory.declared(returnType); + } + } else { + return StampFactory.forKind(kind); + } + } + + @Override + public <T> T getInjectedArgument(Class<T> type) { + T injected = snippetReflection.getInjectedNodeIntrinsicParameter(type); + if (injected != null) { + return injected; + } else if (type.equals(ForeignCallsProvider.class)) { + return type.cast(foreignCalls); + } else if (type.equals(SnippetReflectionProvider.class)) { + return type.cast(snippetReflection); + } else { + throw new JVMCIError("Cannot handle injected argument of type %s.", type.getName()); + } } @Override @@ -107,7 +140,6 @@ protected boolean tryIntrinsify(MethodCallTargetNode methodCallTargetNode, List<Node> cleanUpReturnList) { ResolvedJavaMethod target = methodCallTargetNode.targetMethod(); - ResolvedJavaType declaringClass = target.getDeclaringClass(); StructuredGraph graph = methodCallTargetNode.graph(); NodeIntrinsic intrinsic = getIntrinsic(target); @@ -125,8 +157,7 @@ // Clean up checkcast instructions inserted by javac if the return type is generic. cleanUpReturnList.add(newInstance); } else if (isFoldable(target)) { - ResolvedJavaType[] parameterTypes = resolveJavaTypes(target.toParameterTypes(), declaringClass); - JavaConstant constant = tryFold(methodCallTargetNode.arguments(), parameterTypes, target); + JavaConstant constant = tryFold(methodCallTargetNode.arguments(), target); if (constant != null && constant.equals(COULD_NOT_FOLD)) { return false; } @@ -153,8 +184,8 @@ } }; - public JavaConstant tryFold(List<ValueNode> args, ResolvedJavaType[] parameterTypes, ResolvedJavaMethod target) { - JavaConstant[] reflectArgs = (JavaConstant[]) prepareArguments(args, parameterTypes, target, true); + public JavaConstant tryFold(List<ValueNode> args, ResolvedJavaMethod target) { + JavaConstant[] reflectArgs = prepareFoldingArguments(args); if (reflectArgs == null) { return COULD_NOT_FOLD; } @@ -169,6 +200,26 @@ } /** + * Select a constructor and prepare the injected arguments for intrinsification of a call to a + * {@link NodeIntrinsic} annotated method. + * + * @param arguments the arguments of the call + * @param stamp the stamp to use for the returned node + * @param method the method annotated with {@link NodeIntrinsic} + * @return an {@link NodeIntrinsicFactory} that can be used to + * {@link NodeIntrinsicFactory#intrinsify intrinsify} the call + */ + public NodeIntrinsicFactory createIntrinsicFactory(List<ValueNode> arguments, Stamp stamp, ResolvedJavaMethod method, NodeIntrinsic intrinsic) { + assert method.getAnnotation(Fold.class) == null; + assert method.isStatic() : "node intrinsic must be static: " + method; + + Class<? extends ValueNode> nodeClass = getNodeClass(method, intrinsic); + Class<?>[] parameterTypes = prepareIntrinsicArgumentTypes(method); + + return createIntrinsicFactory(nodeClass, parameterTypes, arguments, stamp, intrinsic.setStampFromReturnType()); + } + + /** * Attempts to create a node to replace a call to a {@link NodeIntrinsic} annotated method. * * @param arguments the arguments of the call @@ -179,20 +230,8 @@ * representing the intrinsic */ public ValueNode createIntrinsicNode(List<ValueNode> arguments, Stamp stamp, ResolvedJavaMethod method, StructuredGraph graph, NodeIntrinsic intrinsic) { - assert method.getAnnotation(Fold.class) == null; - assert method.isStatic() : "node intrinsic must be static: " + method; - - ResolvedJavaType[] parameterTypes = resolveJavaTypes(method.toParameterTypes(), method.getDeclaringClass()); - - // Prepare the arguments for the reflective constructor call on the node class. - Object[] nodeConstructorArguments = prepareArguments(arguments, parameterTypes, method, false); - if (nodeConstructorArguments == null) { - return null; - } - - // Create the new node instance. - ResolvedJavaType c = getNodeClass(method, intrinsic); - return createNodeInstance(graph, c, parameterTypes, stamp, intrinsic.setStampFromReturnType(), nodeConstructorArguments); + NodeIntrinsicFactory factory = createIntrinsicFactory(arguments, stamp, method, intrinsic); + return factory.intrinsify(graph, constantReflection, snippetReflection); } /** @@ -209,185 +248,183 @@ return method.getAnnotation(Fold.class) != null; } - /** - * Converts the arguments of an invoke node to object values suitable for use as the arguments - * to a reflective invocation of a Java constructor or method. - * - * @param folding specifies if the invocation is for handling a {@link Fold} annotation - * @return the arguments for the reflective invocation or null if an argument of {@code invoke} - * that is expected to be constant isn't - */ - private Object[] prepareArguments(List<ValueNode> arguments, ResolvedJavaType[] parameterTypes, ResolvedJavaMethod target, boolean folding) { - Object[] reflectionCallArguments = folding ? new JavaConstant[arguments.size()] : new Object[arguments.size()]; - for (int i = 0; i < reflectionCallArguments.length; ++i) { + private Class<?>[] prepareIntrinsicArgumentTypes(ResolvedJavaMethod target) { + Signature signature = target.getSignature(); + boolean hasReceiver = !target.isStatic(); + + Class<?>[] argumentTypes = new Class<?>[signature.getParameterCount(hasReceiver)]; + for (int i = 0; i < argumentTypes.length; i++) { int parameterIndex = i; - if (!target.isStatic()) { + if (hasReceiver) { parameterIndex--; } - ValueNode argument = arguments.get(i); - if (folding || target.getParameterAnnotation(ConstantNodeParameter.class, parameterIndex) != null) { - if (!(argument instanceof ConstantNode)) { - return null; + if (target.getParameterAnnotation(ConstantNodeParameter.class, parameterIndex) != null) { + ResolvedJavaType type = signature.getParameterType(parameterIndex, target.getDeclaringClass()).resolve(target.getDeclaringClass()); + Class<?> cls; + if (type.isPrimitive()) { + cls = type.getJavaKind().toJavaClass(); + } else { + cls = snippetReflection.asObject(Class.class, type.getJavaClass()); } - ConstantNode constantNode = (ConstantNode) argument; - Constant constant = constantNode.asConstant(); /* - * For intrinsification (but not for folding) if we have a Class<?> object we want - * the corresponding ResolvedJavaType. + * If the node intrinsic method has a constant Class<?> argument, the node + * constructor wants the corresponding ResolvedJavaType. */ - ResolvedJavaType type = folding ? null : constantReflection.asJavaType(constant); - Object arg; - if (type != null) { - /* If we found such a type then it's our arg */ - arg = type; - parameterTypes[i] = metaAccess.lookupJavaType(ResolvedJavaType.class); + if (cls.equals(Class.class)) { + argumentTypes[i] = ResolvedJavaType.class; } else { - JavaConstant javaConstant = (JavaConstant) constant; - if (folding) { - /* For folding we want JavaConstants */ - arg = javaConstant; - } else { - /* For intrinsification we want want corresponding objects */ - if (parameterTypes[i].getJavaKind() == JavaKind.Boolean) { - arg = Boolean.valueOf(javaConstant.asInt() != 0); - } else if (parameterTypes[i].getJavaKind() == JavaKind.Byte) { - arg = Byte.valueOf((byte) javaConstant.asInt()); - } else if (parameterTypes[i].getJavaKind() == JavaKind.Short) { - arg = Short.valueOf((short) javaConstant.asInt()); - } else if (parameterTypes[i].getJavaKind() == JavaKind.Char) { - arg = Character.valueOf((char) javaConstant.asInt()); - } else if (parameterTypes[i].getJavaKind() == JavaKind.Object) { - arg = snippetReflection.asObject(parameterTypes[i], javaConstant); - } else { - arg = javaConstant.asBoxedPrimitive(); - } - } + argumentTypes[i] = cls; } + } else { + argumentTypes[i] = ValueNode.class; + } + } - assert folding || !(arg instanceof JavaConstant); - reflectionCallArguments[i] = arg; - } else { - reflectionCallArguments[i] = argument; - parameterTypes[i] = metaAccess.lookupJavaType(ValueNode.class); + return argumentTypes; + } + + /** + * Converts the arguments of an invoke node to object values suitable for use as the arguments + * to a reflective invocation of a ResolvedJavaMethod. + * + * @return the arguments for the reflective invocation or null if an argument of {@code invoke} + * is not constant + */ + private static JavaConstant[] prepareFoldingArguments(List<ValueNode> arguments) { + JavaConstant[] reflectionCallArguments = new JavaConstant[arguments.size()]; + for (int i = 0; i < reflectionCallArguments.length; ++i) { + ValueNode argument = arguments.get(i); + if (!(argument instanceof ConstantNode)) { + return null; } + + ConstantNode constantNode = (ConstantNode) argument; + reflectionCallArguments[i] = (JavaConstant) constantNode.asConstant(); } return reflectionCallArguments; } - public ResolvedJavaType getNodeClass(ResolvedJavaMethod target, NodeIntrinsic intrinsic) { - ResolvedJavaType result; + public Class<? extends ValueNode> getNodeClass(ResolvedJavaMethod target, NodeIntrinsic intrinsic) { + Class<?> result; if (intrinsic.value() == NodeIntrinsic.class) { - result = target.getDeclaringClass(); + ResolvedJavaType type = target.getDeclaringClass(); + result = snippetReflection.asObject(Class.class, type.getJavaClass()); } else { - result = metaAccess.lookupJavaType(intrinsic.value()); + result = intrinsic.value(); } - assert metaAccess.lookupJavaType(ValueNode.class).isAssignableFrom(result) : "Node intrinsic class " + result.toJavaName(false) + " derived from @" + NodeIntrinsic.class.getSimpleName() + - " annotation on " + target.format("%H.%n(%p)") + " is not a subclass of " + ValueNode.class; - return result; + assert ValueNode.class.isAssignableFrom(result) : "Node intrinsic class " + result + " derived from @" + NodeIntrinsic.class.getSimpleName() + " annotation on " + target.format("%H.%n(%p)") + + " is not a subclass of " + ValueNode.class; + return result.asSubclass(ValueNode.class); } - protected ValueNode createNodeInstance(StructuredGraph graph, ResolvedJavaType nodeClass, ResolvedJavaType[] parameterTypes, Stamp invokeStamp, boolean setStampFromReturnType, - Object[] nodeConstructorArguments) { - ResolvedJavaMethod constructor = null; - Object[] arguments = null; + protected NodeIntrinsicFactory createIntrinsicFactory(Class<? extends ValueNode> nodeClass, Class<?>[] parameterTypes, List<ValueNode> arguments, Stamp invokeStamp, boolean setStampFromReturnType) { + NodeIntrinsicFactory ret = null; - for (ResolvedJavaMethod c : nodeClass.getDeclaredConstructors()) { - Object[] match = match(graph, invokeStamp, c, parameterTypes, nodeConstructorArguments); + for (Constructor<?> c : nodeClass.getDeclaredConstructors()) { + NodeIntrinsicFactory match = match(invokeStamp, setStampFromReturnType, c, parameterTypes, arguments); if (match != null) { - if (constructor == null) { - constructor = c; - arguments = match; + if (ret == null) { + ret = match; if (!Debug.isEnabled()) { // Don't verify there's a unique match in non-debug mode break; } } else { - throw new JVMCIError("Found multiple constructors in %s compatible with signature %s: %s, %s", nodeClass.toJavaName(), sigString(parameterTypes), constructor, c); + throw new JVMCIError("Found multiple constructors in %s compatible with signature %s", nodeClass.getName(), sigString(parameterTypes)); } } } - if (constructor == null) { - throw new JVMCIError("Could not find constructor in %s compatible with signature %s", nodeClass.toJavaName(), sigString(parameterTypes)); + + if (ret == null) { + throw new JVMCIError("Could not find constructor in %s compatible with signature %s", nodeClass.getName(), sigString(parameterTypes)); } - try { - ValueNode intrinsicNode = (ValueNode) invokeConstructor(constructor, arguments); - - if (setStampFromReturnType) { - intrinsicNode.setStamp(invokeStamp); - } - return intrinsicNode; - } catch (Exception e) { - throw new RuntimeException(constructor + Arrays.toString(nodeConstructorArguments), e); - } + return ret; } protected Object invokeConstructor(ResolvedJavaMethod constructor, Object[] arguments) { return snippetReflection.invoke(constructor, null, arguments); } - private static String sigString(ResolvedJavaType[] types) { + private static String sigString(Class<?>[] types) { StringBuilder sb = new StringBuilder("("); for (int i = 0; i < types.length; i++) { if (i != 0) { sb.append(", "); } - sb.append(types[i].toJavaName()); + sb.append(types[i].getSimpleName()); } return sb.append(")").toString(); } - private static boolean checkNoMoreInjected(ResolvedJavaMethod c, int start) { - int count = c.getSignature().getParameterCount(false); + private static boolean checkNoMoreInjected(Constructor<?> c, int start) { + int count = c.getParameterCount(); for (int i = start; i < count; i++) { - if (c.getParameterAnnotation(InjectedNodeParameter.class, i) != null) { - throw new JVMCIError("Injected parameter %d of type %s must precede all non-injected parameters of %s", i, - c.getSignature().getParameterType(i, c.getDeclaringClass()).toJavaName(false), c.format("%H.%n(%p)")); + if (getParameterAnnotation(c, InjectedNodeParameter.class, i) != null) { + throw new JVMCIError("Injected parameter %d of type %s must precede all non-injected parameters of %s", i, c.getParameterTypes()[i], c.toString()); } } return true; } - private Object[] match(StructuredGraph graph, Stamp invokeStamp, ResolvedJavaMethod c, ResolvedJavaType[] parameterTypes, Object[] nodeConstructorArguments) { - Object[] arguments = null; - Object[] injected = null; + private static <T extends Annotation> T getParameterAnnotation(Executable e, Class<T> annotationClass, int parameterIndex) { + if (parameterIndex >= 0) { + Annotation[][] parameterAnnotations = e.getParameterAnnotations(); + for (Annotation a : parameterAnnotations[parameterIndex]) { + if (a.annotationType() == annotationClass) { + return annotationClass.cast(a); + } + } + } + return null; + } - ResolvedJavaType[] signature = resolveJavaTypes(c.getSignature().toParameterTypes(null), c.getDeclaringClass()); + private NodeIntrinsicFactory match(Stamp invokeStamp, boolean setStampFromReturnType, Constructor<?> c, Class<?>[] parameterTypes, List<ValueNode> argumentNodes) { + Class<?>[] signature = c.getParameterTypes(); + + int injectedCount = 0; for (int i = 0; i < signature.length; i++) { - if (c.getParameterAnnotation(InjectedNodeParameter.class, i) != null) { - injected = injected == null ? new Object[1] : Arrays.copyOf(injected, injected.length + 1); - Object injectedParameter = snippetReflection.getInjectedNodeIntrinsicParameter(signature[i]); - if (injectedParameter != null) { - injected[injected.length - 1] = injectedParameter; - } else if (signature[i].equals(metaAccess.lookupJavaType(MetaAccessProvider.class))) { - injected[injected.length - 1] = metaAccess; - } else if (signature[i].equals(metaAccess.lookupJavaType(StructuredGraph.class))) { - injected[injected.length - 1] = graph; - } else if (signature[i].equals(metaAccess.lookupJavaType(ForeignCallsProvider.class))) { - injected[injected.length - 1] = foreignCalls; - } else if (signature[i].equals(metaAccess.lookupJavaType(SnippetReflectionProvider.class))) { - injected[injected.length - 1] = snippetReflection; - } else if (signature[i].isAssignableFrom(metaAccess.lookupJavaType(Stamp.class))) { - injected[injected.length - 1] = invokeStamp; - } else if (signature[i].isAssignableFrom(metaAccess.lookupJavaType(StampProvider.class))) { - injected[injected.length - 1] = stampProvider; - } else { - throw new JVMCIError("Cannot handle injected argument of type %s in %s", signature[i].toJavaName(), c.format("%H.%n(%p)")); - } + if (getParameterAnnotation(c, InjectedNodeParameter.class, i) != null) { + injectedCount++; } else { assert checkNoMoreInjected(c, i); break; } } - if (injected != null) { + + Object[] injected = null; + if (injectedCount > 0) { + injected = new Object[injectedCount]; + for (int i = 0; i < injected.length; i++) { + assert getParameterAnnotation(c, InjectedNodeParameter.class, i) != null; + Object injectedParameter = snippetReflection.getInjectedNodeIntrinsicParameter(signature[i]); + if (injectedParameter != null) { + injected[i] = injectedParameter; + } else if (signature[i].equals(MetaAccessProvider.class)) { + injected[i] = metaAccess; + } else if (signature[i].equals(StructuredGraph.class)) { + injected[i] = NodeIntrinsicFactory.GRAPH_MARKER; + } else if (signature[i].equals(ForeignCallsProvider.class)) { + injected[i] = foreignCalls; + } else if (signature[i].equals(SnippetReflectionProvider.class)) { + injected[i] = snippetReflection; + } else if (signature[i].isAssignableFrom(Stamp.class)) { + injected[i] = invokeStamp; + } else if (signature[i].isAssignableFrom(StampProvider.class)) { + injected[i] = stampProvider; + } else { + throw new JVMCIError("Cannot handle injected argument of type %s in %s", signature[i].getName(), c.toString()); + } + } + // Chop injected arguments from signature signature = Arrays.copyOfRange(signature, injected.length, signature.length); } if (Arrays.equals(parameterTypes, signature)) { // Exact match - arguments = nodeConstructorArguments; + return new NodeIntrinsicFactory(invokeStamp, metaAccess.lookupJavaMethod(c), setStampFromReturnType, injected, parameterTypes, argumentNodes); } else if (signature.length > 0 && signature[signature.length - 1].isArray()) { // Last constructor parameter is an array, so check if we have a vararg match @@ -401,35 +438,22 @@ } } - ResolvedJavaType componentType = signature[fixedArgs].getComponentType(); + Class<?> componentType = signature[fixedArgs].getComponentType(); assert componentType != null; - for (int i = fixedArgs; i < nodeConstructorArguments.length; i++) { + for (int i = fixedArgs; i < argumentNodes.size(); i++) { if (!parameterTypes[i].equals(componentType)) { return null; } } - arguments = Arrays.copyOf(nodeConstructorArguments, fixedArgs + 1); - arguments[fixedArgs] = snippetReflection.newArray(componentType, nodeConstructorArguments.length - fixedArgs); - Object varargs = arguments[fixedArgs]; - for (int i = fixedArgs; i < nodeConstructorArguments.length; i++) { - if (componentType.isPrimitive()) { - Array.set(varargs, i - fixedArgs, nodeConstructorArguments[i]); - } else { - ((Object[]) varargs)[i - fixedArgs] = nodeConstructorArguments[i]; - } - } + List<ValueNode> fixed = argumentNodes.subList(0, fixedArgs); + List<ValueNode> varargs = argumentNodes.subList(fixedArgs, argumentNodes.size()); + + return new NodeIntrinsicFactory(invokeStamp, metaAccess.lookupJavaMethod(c), setStampFromReturnType, injected, parameterTypes, fixed, componentType, varargs); + } else { return null; } - - if (injected != null) { - Object[] copy = new Object[injected.length + arguments.length]; - System.arraycopy(injected, 0, copy, 0, injected.length); - System.arraycopy(arguments, 0, copy, injected.length, arguments.length); - arguments = copy; - } - return arguments; } private static String sourceLocation(Node n) {
--- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/NodeIntrinsificationPlugin.java Tue Nov 24 15:21:14 2015 +0100 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/NodeIntrinsificationPlugin.java Tue Nov 24 19:31:56 2015 +0100 @@ -22,55 +22,21 @@ */ package com.oracle.graal.replacements; -import static com.oracle.graal.replacements.NodeIntrinsificationPhase.COULD_NOT_FOLD; -import static jdk.vm.ci.meta.MetaUtil.resolveJavaTypes; - -import java.util.Arrays; -import java.util.List; - import jdk.vm.ci.common.JVMCIError; -import jdk.vm.ci.meta.JavaConstant; import jdk.vm.ci.meta.JavaKind; -import jdk.vm.ci.meta.JavaType; -import jdk.vm.ci.meta.MetaAccessProvider; import jdk.vm.ci.meta.ResolvedJavaMethod; -import jdk.vm.ci.meta.ResolvedJavaType; -import jdk.vm.ci.meta.Signature; import com.oracle.graal.api.replacements.Fold; -import com.oracle.graal.compiler.common.type.ObjectStamp; -import com.oracle.graal.compiler.common.type.Stamp; -import com.oracle.graal.compiler.common.type.StampFactory; import com.oracle.graal.debug.MethodFilter; import com.oracle.graal.graph.Node.NodeIntrinsic; -import com.oracle.graal.nodeinfo.InputType; -import com.oracle.graal.nodeinfo.StructuralInput; -import com.oracle.graal.nodeinfo.StructuralInput.MarkerType; -import com.oracle.graal.nodes.ConstantNode; import com.oracle.graal.nodes.ValueNode; -import com.oracle.graal.nodes.extended.ForeignCallNode; -import com.oracle.graal.nodes.extended.UnsafeCopyNode; -import com.oracle.graal.nodes.extended.UnsafeLoadNode; -import com.oracle.graal.nodes.extended.UnsafeStoreNode; import com.oracle.graal.nodes.graphbuilderconf.GraphBuilderContext; import com.oracle.graal.nodes.graphbuilderconf.NodePlugin; -import com.oracle.graal.word.WordTypes; /** * An {@link NodePlugin} that handles methods annotated by {@link Fold} and {@link NodeIntrinsic}. */ public class NodeIntrinsificationPlugin implements NodePlugin { - protected final NodeIntrinsificationPhase nodeIntrinsification; - private final WordTypes wordTypes; - private final ResolvedJavaType structuralInputType; - private final boolean mustIntrinsify; - - public NodeIntrinsificationPlugin(MetaAccessProvider metaAccess, NodeIntrinsificationPhase nodeIntrinsification, WordTypes wordTypes, boolean mustIntrinsify) { - this.nodeIntrinsification = nodeIntrinsification; - this.wordTypes = wordTypes; - this.mustIntrinsify = mustIntrinsify; - this.structuralInputType = metaAccess.lookupJavaType(StructuralInput.class); - } /** * Calls in replacements to methods matching one of these filters are elided. Only void methods @@ -89,46 +55,7 @@ @Override public boolean handleInvoke(GraphBuilderContext b, ResolvedJavaMethod method, ValueNode[] args) { - NodeIntrinsic intrinsic = nodeIntrinsification.getIntrinsic(method); - if (intrinsic != null) { - Signature sig = method.getSignature(); - JavaKind returnKind = sig.getReturnKind(); - Stamp stamp = StampFactory.forKind(returnKind); - if (returnKind == JavaKind.Object) { - JavaType returnType = sig.getReturnType(method.getDeclaringClass()); - if (returnType instanceof ResolvedJavaType) { - ResolvedJavaType resolvedReturnType = (ResolvedJavaType) returnType; - if (wordTypes.isWord(resolvedReturnType)) { - stamp = wordTypes.getWordStamp(resolvedReturnType); - } else { - stamp = StampFactory.declared(resolvedReturnType); - } - } - } - - boolean result = processNodeIntrinsic(b, method, intrinsic, Arrays.asList(args), returnKind, stamp); - if (!result && mustIntrinsify) { - reportIntrinsificationFailure(b, method, args); - } - return result; - - } else if (nodeIntrinsification.isFoldable(method)) { - ResolvedJavaType[] parameterTypes = resolveJavaTypes(method.toParameterTypes(), method.getDeclaringClass()); - JavaConstant constant = nodeIntrinsification.tryFold(Arrays.asList(args), parameterTypes, method); - if (!COULD_NOT_FOLD.equals(constant)) { - if (constant != null) { - // Replace the invoke with the result of the call - b.push(method.getSignature().getReturnKind(), ConstantNode.forConstant(constant, b.getMetaAccess(), b.getGraph())); - } else { - // This must be a void invoke - assert method.getSignature().getReturnKind() == JavaKind.Void; - } - return true; - } else if (mustIntrinsify) { - reportIntrinsificationFailure(b, method, args); - } - - } else if (MethodsElidedInSnippets != null) { + if (MethodsElidedInSnippets != null) { if (MethodFilter.matches(MethodsElidedInSnippets, method)) { if (method.getSignature().getReturnKind() != JavaKind.Void) { throw new JVMCIError("Cannot elide non-void method " + method.format("%H.%n(%p)")); @@ -138,79 +65,4 @@ } return false; } - - private static boolean reportIntrinsificationFailure(GraphBuilderContext b, ResolvedJavaMethod method, ValueNode[] args) { - StringBuilder msg = new StringBuilder(); - msg.append("Call in ").append(b.getMethod().format("%H.%n(%p)")); - msg.append(" to ").append(method.format("%H.%n(%p)")); - msg.append(" cannot be intrinsified or folded, probably because an argument is not a constant. Arguments: "); - String sep = ""; - for (ValueNode node : args) { - msg.append(sep).append(node.toString()); - sep = ", "; - } - throw new JVMCIError(msg.toString()); - } - - private InputType getInputType(ResolvedJavaType type) { - if (type != null && structuralInputType.isAssignableFrom(type)) { - MarkerType markerType = type.getAnnotation(MarkerType.class); - if (markerType != null) { - return markerType.value(); - } else { - throw JVMCIError.shouldNotReachHere(String.format("%s extends StructuralInput, but is not annotated with @MarkerType", type)); - } - } else { - return InputType.Value; - } - } - - private boolean processNodeIntrinsic(GraphBuilderContext b, ResolvedJavaMethod method, NodeIntrinsic intrinsic, List<ValueNode> args, JavaKind returnKind, Stamp stamp) { - ValueNode res = createNodeIntrinsic(b, method, intrinsic, args, stamp); - if (res == null) { - return false; - } - if (res instanceof UnsafeCopyNode) { - UnsafeCopyNode copy = (UnsafeCopyNode) res; - UnsafeLoadNode value = b.add(new UnsafeLoadNode(copy.sourceObject(), copy.sourceOffset(), copy.accessKind(), copy.getLocationIdentity())); - b.add(new UnsafeStoreNode(copy.destinationObject(), copy.destinationOffset(), value, copy.accessKind(), copy.getLocationIdentity())); - return true; - } else if (res instanceof ForeignCallNode) { - /* - * Need to update the BCI of a ForeignCallNode so that it gets the stateDuring in the - * case that the foreign call can deoptimize. As with all deoptimization, we need a - * state in a non-intrinsic method. - */ - GraphBuilderContext nonIntrinsicAncestor = b.getNonIntrinsicAncestor(); - if (nonIntrinsicAncestor != null) { - ForeignCallNode foreign = (ForeignCallNode) res; - foreign.setBci(nonIntrinsicAncestor.bci()); - } - } - - boolean nonValueType = false; - if (returnKind == JavaKind.Object && stamp instanceof ObjectStamp) { - ResolvedJavaType type = ((ObjectStamp) stamp).type(); - if (type != null && structuralInputType.isAssignableFrom(type)) { - assert res.isAllowedUsageType(getInputType(type)); - nonValueType = true; - } - } - - if (returnKind != JavaKind.Void) { - assert nonValueType || res.getStackKind() != JavaKind.Void; - res = b.addPush(returnKind, res); - } else { - assert res.getStackKind() == JavaKind.Void; - res = b.add(res); - } - - return true; - } - - private ValueNode createNodeIntrinsic(GraphBuilderContext b, ResolvedJavaMethod method, NodeIntrinsic intrinsic, List<ValueNode> args, Stamp stamp) { - ValueNode res = nodeIntrinsification.createIntrinsicNode(args, stamp, method, b.getGraph(), intrinsic); - assert res != null : String.format("Could not create node intrinsic for call to %s as one of the arguments expected to be constant isn't: arguments=%s", method.format("%H.%n(%p)"), args); - return res; - } }
--- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/ReplacementsImpl.java Tue Nov 24 15:21:14 2015 +0100 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/ReplacementsImpl.java Tue Nov 24 19:31:56 2015 +0100 @@ -81,6 +81,7 @@ import com.oracle.graal.nodes.StructuredGraph; import com.oracle.graal.nodes.StructuredGraph.AllowAssumptions; import com.oracle.graal.nodes.ValueNode; +import com.oracle.graal.nodes.graphbuilderconf.GeneratedInvocationPlugin; import com.oracle.graal.nodes.graphbuilderconf.GraphBuilderConfiguration; import com.oracle.graal.nodes.graphbuilderconf.GraphBuilderContext; import com.oracle.graal.nodes.graphbuilderconf.InlineInvokePlugin; @@ -120,8 +121,12 @@ return graphBuilderPlugins; } + protected boolean hasGeneratedInvocationPluginAnnotation(ResolvedJavaMethod method) { + return method.getAnnotation(Node.NodeIntrinsic.class) != null || method.getAnnotation(Fold.class) != null; + } + protected boolean hasGenericInvocationPluginAnnotation(ResolvedJavaMethod method) { - return method.getAnnotation(Node.NodeIntrinsic.class) != null || method.getAnnotation(Word.Operation.class) != null || method.getAnnotation(Fold.class) != null; + return method.getAnnotation(Word.Operation.class) != null; } private static final int MAX_GRAPH_INLINING_DEPTH = 100; // more than enough @@ -144,7 +149,8 @@ return null; } if (b.parsingIntrinsic()) { - assert !hasGenericInvocationPluginAnnotation(method) : format("%s should have been handled by %s", method.format("%H.%n(%p)"), NodeIntrinsificationPlugin.class.getName()); + assert !hasGeneratedInvocationPluginAnnotation(method) : format("%s should have been handled by a %s", method.format("%H.%n(%p)"), GeneratedInvocationPlugin.class.getSimpleName()); + assert !hasGenericInvocationPluginAnnotation(method) : format("%s should have been handled by %s", method.format("%H.%n(%p)"), WordOperationPlugin.class.getSimpleName()); assert b.getDepth() < MAX_GRAPH_INLINING_DEPTH : "inlining limit exceeded";
--- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/SnippetCounterNode.java Tue Nov 24 15:21:14 2015 +0100 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/SnippetCounterNode.java Tue Nov 24 19:31:56 2015 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -127,7 +127,7 @@ static class SnippetCounterSnippets implements Snippets { @Fold - private static int countOffset() { + static int countOffset() { try { return (int) UNSAFE.objectFieldOffset(SnippetCounter.class.getDeclaredField("value")); } catch (Exception e) {
--- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/SnippetTemplate.java Tue Nov 24 15:21:14 2015 +0100 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/SnippetTemplate.java Tue Nov 24 19:31:56 2015 +0100 @@ -766,6 +766,12 @@ } } while (exploded); + for (NodeIntrinsicFactory factory : snippetCopy.getNodes().filter(NodeIntrinsicFactory.class)) { + ValueNode intrinsic = factory.intrinsify(snippetCopy, providers.getConstantReflection(), snippetReflection); + assert intrinsic != null; + snippetCopy.replaceFixed(factory, intrinsic); + } + GuardsStage guardsStage = args.cacheKey.guardsStage; // Perform lowering on the snippet if (!guardsStage.allowsFloatingGuards()) {
--- a/mx.graal/suite.py Tue Nov 24 15:21:14 2015 +0100 +++ b/mx.graal/suite.py Tue Nov 24 19:31:56 2015 +0100 @@ -518,6 +518,7 @@ "javaCompliance" : "1.8", "annotationProcessors" : [ "GRAAL_NODEINFO_PROCESSOR", + "GRAAL_REPLACEMENTS_VERIFIER", ], "workingSets" : "Graal,Replacements,AMD64", }, @@ -541,7 +542,10 @@ "com.oracle.graal.compiler.test", "com.oracle.graal.replacements", ], - "annotationProcessors" : ["GRAAL_NODEINFO_PROCESSOR"], + "annotationProcessors" : [ + "GRAAL_NODEINFO_PROCESSOR", + "GRAAL_REPLACEMENTS_VERIFIER" + ], "checkstyle" : "com.oracle.graal.graph", "javaCompliance" : "1.8", "workingSets" : "Graal,Replacements,Test", @@ -1113,6 +1117,7 @@ "dependencies" : ["com.oracle.graal.replacements.verifier"], "distDependencies" : [ "GRAAL_API", + "jvmci:JVMCI_SERVICE_PROCESSOR", ], },