# HG changeset patch # User Doug Simon # Date 1426102992 -3600 # Node ID 14e703edb2ab5b6b0d81d36f4813a9c0cf6a54c8 # Parent 31fac91ea3b770df79ccdc2393659b4a4dd68f25 use GraphBuilderPlugins for method substitutions, intrinsics and snippets (GRAAL-982) diff -r 31fac91ea3b7 -r 14e703edb2ab graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/GraalOptions.java --- a/graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/GraalOptions.java Wed Mar 11 17:16:30 2015 +0100 +++ b/graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/GraalOptions.java Wed Mar 11 20:43:12 2015 +0100 @@ -57,15 +57,6 @@ @Option(help = "Graphs with less than this number of nodes are trivial and therefore always inlined.", type = OptionType.Expert) public static final OptionValue TrivialInliningSize = new OptionValue<>(10); - @Option(help = "Inlines trivial methods during parsing of the bytecodes.", type = OptionType.Expert) - public static final StableOptionValue InlineDuringParsing = new StableOptionValue<>(false); - - @Option(help = "Traces .", type = OptionType.Debug) - public static final StableOptionValue TraceInlineDuringParsing = new StableOptionValue<>(false); - - @Option(help = "Maximum depth when inlining during parsing.", type = OptionType.Debug) - public static final StableOptionValue InlineDuringParsingMaxDepth = new StableOptionValue<>(10); - @Option(help = "Inlining is explored up to this number of nodes in the graph for each call site.", type = OptionType.Expert) public static final OptionValue MaximumInliningSize = new OptionValue<>(300); diff -r 31fac91ea3b7 -r 14e703edb2ab graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/FinalizableSubclassTest.java --- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/FinalizableSubclassTest.java Wed Mar 11 17:16:30 2015 +0100 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/FinalizableSubclassTest.java Wed Mar 11 20:43:12 2015 +0100 @@ -68,7 +68,7 @@ StructuredGraph graph = new StructuredGraph(javaMethod, allowAssumptions); GraphBuilderConfiguration conf = GraphBuilderConfiguration.getSnippetDefault(); - new GraphBuilderPhase.Instance(getMetaAccess(), getProviders().getStampProvider(), getProviders().getConstantReflection(), conf, OptimisticOptimizations.ALL, false).apply(graph); + new GraphBuilderPhase.Instance(getMetaAccess(), getProviders().getStampProvider(), getProviders().getConstantReflection(), conf, OptimisticOptimizations.ALL, null).apply(graph); HighTierContext context = new HighTierContext(getProviders(), null, getDefaultGraphBuilderSuite(), OptimisticOptimizations.ALL); new InliningPhase(new CanonicalizerPhase()).apply(graph, context); new CanonicalizerPhase().apply(graph, context); diff -r 31fac91ea3b7 -r 14e703edb2ab graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/GraalCompilerTest.java --- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/GraalCompilerTest.java Wed Mar 11 17:16:30 2015 +0100 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/GraalCompilerTest.java Wed Mar 11 20:43:12 2015 +0100 @@ -837,12 +837,23 @@ PhaseSuite suite = getDefaultGraphBuilderSuite().copy(); ListIterator> iterator = suite.findPhase(GraphBuilderPhase.class); GraphBuilderPhase graphBuilderPhase = (GraphBuilderPhase) iterator.previous(); - GraphBuilderConfiguration gbConfCopy = gbConf.copy().copyPluginsFrom(graphBuilderPhase.getGraphBuilderConfig()); + GraphBuilderConfiguration gbConfCopy = editGraphBuilderConfiguration(gbConf.copy().copyPluginsFrom(graphBuilderPhase.getGraphBuilderConfig())); iterator.remove(); iterator.add(new GraphBuilderPhase(gbConfCopy)); return suite; } + protected GraphBuilderConfiguration editGraphBuilderConfiguration(GraphBuilderConfiguration conf) { + editGraphBuilderPlugins(conf.getPlugins()); + return conf; + } + + /** + * @param plugins + */ + protected void editGraphBuilderPlugins(GraphBuilderConfiguration.Plugins plugins) { + } + protected Replacements getReplacements() { return getProviders().getReplacements(); } diff -r 31fac91ea3b7 -r 14e703edb2ab graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ea/EATestBase.java --- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ea/EATestBase.java Wed Mar 11 17:16:30 2015 +0100 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ea/EATestBase.java Wed Mar 11 20:43:12 2015 +0100 @@ -30,7 +30,6 @@ import com.oracle.graal.compiler.test.*; import com.oracle.graal.debug.*; import com.oracle.graal.debug.Debug.Scope; -import com.oracle.graal.java.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.StructuredGraph.AllowAssumptions; import com.oracle.graal.nodes.java.*; @@ -149,10 +148,8 @@ protected void prepareGraph(String snippet, final boolean iterativeEscapeAnalysis) { ResolvedJavaMethod method = getResolvedJavaMethod(snippet); - graph = new StructuredGraph(method, AllowAssumptions.NO); - try (Scope s = Debug.scope(getClass(), graph, method, getCodeCache())) { - new GraphBuilderPhase.Instance(getMetaAccess(), getProviders().getStampProvider(), getProviders().getConstantReflection(), GraphBuilderConfiguration.getEagerDefault(), - OptimisticOptimizations.ALL, false).apply(graph); + try (Scope s = Debug.scope(getClass(), method, getCodeCache())) { + graph = parseEager(method, AllowAssumptions.YES); context = new HighTierContext(getProviders(), null, getDefaultGraphBuilderSuite(), OptimisticOptimizations.ALL); new InliningPhase(new CanonicalizerPhase()).apply(graph, context); new DeadCodeEliminationPhase().apply(graph); diff -r 31fac91ea3b7 -r 14e703edb2ab graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/tutorial/StaticAnalysis.java --- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/tutorial/StaticAnalysis.java Wed Mar 11 17:16:30 2015 +0100 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/tutorial/StaticAnalysis.java Wed Mar 11 20:43:12 2015 +0100 @@ -237,7 +237,7 @@ */ OptimisticOptimizations optimisticOpts = OptimisticOptimizations.NONE; - GraphBuilderPhase.Instance graphBuilder = new GraphBuilderPhase.Instance(metaAccess, stampProvider, null, graphBuilderConfig, optimisticOpts, false); + GraphBuilderPhase.Instance graphBuilder = new GraphBuilderPhase.Instance(metaAccess, stampProvider, null, graphBuilderConfig, optimisticOpts, null); graphBuilder.apply(graph); } catch (Throwable ex) { Debug.handle(ex); diff -r 31fac91ea3b7 -r 14e703edb2ab graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotBackendFactory.java --- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotBackendFactory.java Wed Mar 11 17:16:30 2015 +0100 +++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotBackendFactory.java Wed Mar 11 20:43:12 2015 +0100 @@ -153,6 +153,7 @@ lowerer = createLowerer(runtime, metaAccess, foreignCalls, registers, target); } Providers p = new Providers(metaAccess, codeCache, constantReflection, foreignCalls, lowerer, null, new HotSpotStampProvider()); + try (InitTimer rt = timer("create SnippetReflection provider")) { snippetReflection = createSnippetReflection(runtime); } @@ -163,7 +164,7 @@ disassembler = createDisassembler(runtime); } try (InitTimer rt = timer("create Suites provider")) { - suites = createSuites(runtime, metaAccess, constantReflection, replacements); + suites = createSuites(runtime); } providers = new HotSpotProviders(metaAccess, codeCache, constantReflection, foreignCalls, lowerer, replacements, disassembler, suites, registers, snippetReflection); } @@ -209,8 +210,8 @@ return new HotSpotMetaAccessProvider(runtime); } - protected HotSpotSuitesProvider createSuites(HotSpotGraalRuntimeProvider runtime, MetaAccessProvider metaAccess, ConstantReflectionProvider constantReflection, Replacements replacements) { - return new HotSpotSuitesProvider(runtime, metaAccess, constantReflection, replacements); + protected HotSpotSuitesProvider createSuites(HotSpotGraalRuntimeProvider runtime) { + return new HotSpotSuitesProvider(runtime); } protected HotSpotSnippetReflectionProvider createSnippetReflection(HotSpotGraalRuntimeProvider runtime) { diff -r 31fac91ea3b7 -r 14e703edb2ab graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotBackendFactory.java --- a/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotBackendFactory.java Wed Mar 11 17:16:30 2015 +0100 +++ b/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotBackendFactory.java Wed Mar 11 20:43:12 2015 +0100 @@ -32,7 +32,7 @@ import com.oracle.graal.nodes.spi.*; import com.oracle.graal.phases.util.*; import com.oracle.graal.sparc.*; -import com.oracle.graal.sparc.SPARC.*; +import com.oracle.graal.sparc.SPARC.CPUFeature; @ServiceProvider(HotSpotBackendFactory.class) public class SPARCHotSpotBackendFactory implements HotSpotBackendFactory { @@ -64,14 +64,14 @@ HotSpotSnippetReflectionProvider snippetReflection = new HotSpotSnippetReflectionProvider(runtime); HotSpotReplacementsImpl replacements = new HotSpotReplacementsImpl(p, snippetReflection, runtime.getConfig(), target); HotSpotDisassemblerProvider disassembler = new HotSpotDisassemblerProvider(runtime); - HotSpotSuitesProvider suites = createSuites(runtime, metaAccess, constantReflection, replacements); + HotSpotSuitesProvider suites = createSuites(runtime); HotSpotProviders providers = new HotSpotProviders(metaAccess, codeCache, constantReflection, foreignCalls, lowerer, replacements, disassembler, suites, registers, snippetReflection); return createBackend(runtime, providers); } - protected HotSpotSuitesProvider createSuites(HotSpotGraalRuntimeProvider runtime, MetaAccessProvider metaAccess, ConstantReflectionProvider constantReflection, Replacements replacements) { - return new HotSpotSuitesProvider(runtime, metaAccess, constantReflection, replacements); + protected HotSpotSuitesProvider createSuites(HotSpotGraalRuntimeProvider runtime) { + return new HotSpotSuitesProvider(runtime); } protected HotSpotCodeCacheProvider createCodeCache(HotSpotGraalRuntimeProvider runtime, TargetDescription target, RegisterConfig regConfig) { diff -r 31fac91ea3b7 -r 14e703edb2ab graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/AheadOfTimeCompilationTest.java --- a/graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/AheadOfTimeCompilationTest.java Wed Mar 11 17:16:30 2015 +0100 +++ b/graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/AheadOfTimeCompilationTest.java Wed Mar 11 20:43:12 2015 +0100 @@ -72,7 +72,7 @@ StructuredGraph result = compile("getStaticFinalObject", true); assertDeepEquals(1, getConstantNodes(result).count()); Stamp constantStamp = getConstantNodes(result).first().stamp(); - Assert.assertTrue(constantStamp instanceof KlassPointerStamp); + Assert.assertTrue(constantStamp.toString(), constantStamp instanceof KlassPointerStamp); assertDeepEquals(2, result.getNodes().filter(FloatingReadNode.class).count()); assertDeepEquals(0, result.getNodes().filter(ReadNode.class).count()); } diff -r 31fac91ea3b7 -r 14e703edb2ab graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/HotSpotMethodSubstitutionTest.java --- a/graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/HotSpotMethodSubstitutionTest.java Wed Mar 11 17:16:30 2015 +0100 +++ b/graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/HotSpotMethodSubstitutionTest.java Wed Mar 11 20:43:12 2015 +0100 @@ -25,7 +25,6 @@ import org.junit.*; import com.oracle.graal.api.replacements.*; -import com.oracle.graal.hotspot.replacements.*; import com.oracle.graal.replacements.test.*; /** @@ -37,8 +36,8 @@ public void testObjectSubstitutions() { TestClassA obj = new TestClassA(); - test("getClass0"); - test("objectHashCode"); + testGraph("getClass0"); + testGraph("objectHashCode"); test("getClass0", "a string"); test("objectHashCode", obj); @@ -56,12 +55,12 @@ @Test public void testClassSubstitutions() { - test("getModifiers"); - test("isInterface"); - test("isArray"); - test("isPrimitive"); - test("getSuperClass"); - test("getComponentType"); + testGraph("getModifiers"); + testGraph("isInterface"); + testGraph("isArray"); + testGraph("isPrimitive"); + testGraph("getSuperClass"); + testGraph("getComponentType"); for (Class c : new Class[]{getClass(), Cloneable.class, int[].class, String[][].class}) { test("getModifiers", c); @@ -105,9 +104,9 @@ @Test public void testThreadSubstitutions() { - test("currentThread"); - test("threadIsInterrupted"); - test("threadInterrupted"); + testGraph("currentThread"); + testGraph("threadIsInterrupted"); + testGraph("threadInterrupted"); Thread currentThread = Thread.currentThread(); test("currentThread", currentThread); @@ -131,11 +130,9 @@ @Test public void testSystemSubstitutions() { - test("systemTime"); - test("systemIdentityHashCode"); + testGraph("systemTime"); + testGraph("systemIdentityHashCode"); - SystemSubstitutions.currentTimeMillis(); - SystemSubstitutions.nanoTime(); for (Object o : new Object[]{this, new int[5], new String[2][], new Object()}) { test("systemIdentityHashCode", o); } diff -r 31fac91ea3b7 -r 14e703edb2ab graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/WriteBarrierAdditionTest.java --- a/graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/WriteBarrierAdditionTest.java Wed Mar 11 17:16:30 2015 +0100 +++ b/graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/WriteBarrierAdditionTest.java Wed Mar 11 20:43:12 2015 +0100 @@ -22,12 +22,15 @@ */ package com.oracle.graal.hotspot.test; +import static com.oracle.graal.compiler.common.UnsafeAccess.*; + import java.lang.ref.*; import org.junit.*; +import sun.misc.*; + import com.oracle.graal.api.meta.*; -import com.oracle.graal.compiler.common.*; import com.oracle.graal.compiler.test.*; import com.oracle.graal.debug.*; import com.oracle.graal.debug.Debug.Scope; @@ -157,7 +160,7 @@ } public static Object test5Snippet() throws Exception { - return UnsafeAccess.unsafe.getObject(wr, config.useCompressedOops ? 12L : 16L); + return unsafe.getObject(wr, config.useCompressedOops ? 12L : 16L); } /** @@ -166,7 +169,7 @@ */ @Test public void test6() throws Exception { - test2("testUnsafeLoad", wr, new Long(referentOffset), null); + test2("testUnsafeLoad", unsafe, wr, new Long(referentOffset), null); } /** @@ -175,7 +178,7 @@ */ @Test public void test7() throws Exception { - test2("testUnsafeLoad", con, new Long(referentOffset), null); + test2("testUnsafeLoad", unsafe, con, new Long(referentOffset), null); } /** @@ -185,7 +188,7 @@ */ @Test public void test8() throws Exception { - test2("testUnsafeLoad", wr, new Long(config.useCompressedOops ? 20 : 32), null); + test2("testUnsafeLoad", unsafe, wr, new Long(config.useCompressedOops ? 20 : 32), null); } /** @@ -195,7 +198,7 @@ */ @Test public void test10() throws Exception { - test2("testUnsafeLoad", wr, new Long(config.useCompressedOops ? 6 : 8), new Integer(config.useCompressedOops ? 6 : 8)); + test2("testUnsafeLoad", unsafe, wr, new Long(config.useCompressedOops ? 6 : 8), new Integer(config.useCompressedOops ? 6 : 8)); } /** @@ -205,7 +208,7 @@ */ @Test public void test9() throws Exception { - test2("testUnsafeLoad", wr, new Long(config.useCompressedOops ? 10 : 16), new Integer(config.useCompressedOops ? 10 : 16)); + test2("testUnsafeLoad", unsafe, wr, new Long(config.useCompressedOops ? 10 : 16), new Integer(config.useCompressedOops ? 10 : 16)); } static Object[] src = new Object[1]; @@ -229,16 +232,17 @@ test2("testArrayCopy", src, dst, dst.length); } - public static Object testUnsafeLoad(Object a, Object b, Object c) throws Exception { + public static Object testUnsafeLoad(Unsafe theUnsafe, Object a, Object b, Object c) throws Exception { final int offset = (c == null ? 0 : ((Integer) c).intValue()); final long displacement = (b == null ? 0 : ((Long) b).longValue()); - return UnsafeLoadNode.load(a, offset + displacement, Kind.Object, LocationIdentity.ANY_LOCATION); + return theUnsafe.getObject(a, offset + displacement); } - private HotSpotInstalledCode getInstalledCode(String name) throws Exception { - final ResolvedJavaMethod javaMethod = getResolvedJavaMethod(WriteBarrierAdditionTest.class, name, Object.class, Object.class, Object.class); - final HotSpotInstalledCode installedBenchmarkCode = (HotSpotInstalledCode) getCode(javaMethod); - return installedBenchmarkCode; + private HotSpotInstalledCode getInstalledCode(String name, boolean withUnsafePrefix) throws Exception { + final ResolvedJavaMethod javaMethod = withUnsafePrefix ? getResolvedJavaMethod(WriteBarrierAdditionTest.class, name, Unsafe.class, Object.class, Object.class, Object.class) + : getResolvedJavaMethod(WriteBarrierAdditionTest.class, name, Object.class, Object.class, Object.class); + final HotSpotInstalledCode installedCode = (HotSpotInstalledCode) getCode(javaMethod); + return installedCode; } private void testHelper(final String snippetName, final int expectedBarriers) throws Exception, SecurityException { @@ -294,8 +298,8 @@ } } - private void test2(final String snippet, Object a, Object b, Object c) throws Exception { - HotSpotInstalledCode code = getInstalledCode(snippet); - code.executeVarargs(a, b, c); + private void test2(final String snippet, Object... args) throws Exception { + HotSpotInstalledCode code = getInstalledCode(snippet, args[0] instanceof Unsafe); + code.executeVarargs(args); } } diff -r 31fac91ea3b7 -r 14e703edb2ab graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotHostBackend.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotHostBackend.java Wed Mar 11 17:16:30 2015 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotHostBackend.java Wed Mar 11 20:43:12 2015 +0100 @@ -31,9 +31,9 @@ import com.oracle.graal.debug.Debug.Scope; import com.oracle.graal.hotspot.meta.*; import com.oracle.graal.hotspot.stubs.*; +import com.oracle.graal.java.GraphBuilderConfiguration.Plugins; import com.oracle.graal.java.*; import com.oracle.graal.nodes.spi.*; -import com.oracle.graal.replacements.*; /** * Common functionality of HotSpot host backends. @@ -70,11 +70,14 @@ HotSpotVMConfig config = getRuntime().getConfig(); HotSpotHostForeignCallsProvider foreignCalls = (HotSpotHostForeignCallsProvider) providers.getForeignCalls(); final HotSpotLoweringProvider lowerer = (HotSpotLoweringProvider) providers.getLowerer(); + HotSpotReplacementsImpl replacements = (HotSpotReplacementsImpl) providers.getReplacements(); try (InitTimer st = timer("graphBuilderPlugins.initialize")) { + Plugins plugins = HotSpotGraphBuilderPlugins.create(config, providers); + providers.setGraphBuilderPlugins(plugins); GraphBuilderPhase phase = (GraphBuilderPhase) providers.getSuites().getDefaultGraphBuilderSuite().findPhase(GraphBuilderPhase.class).previous(); - InvocationPlugins plugins = phase.getGraphBuilderConfig().getPlugins().getInvocationPlugins(); - registerInvocationPlugins(providers, plugins); + phase.getGraphBuilderConfig().setPlugins(plugins); + replacements.completeInitialization(plugins); } try (InitTimer st = timer("foreignCalls.initialize")) { @@ -83,7 +86,6 @@ try (InitTimer st = timer("lowerer.initialize")) { lowerer.initialize(providers, config); } - HotSpotReplacementsImpl replacements = (HotSpotReplacementsImpl) providers.getReplacements(); // Install intrinsics. if (Intrinsify.getValue()) { @@ -105,9 +107,4 @@ } } } - - protected void registerInvocationPlugins(HotSpotProviders providers, InvocationPlugins plugins) { - StandardGraphBuilderPlugins.registerInvocationPlugins(providers.getMetaAccess(), plugins); - HotSpotGraphBuilderPlugins.registerInvocationPlugins(providers, plugins); - } } diff -r 31fac91ea3b7 -r 14e703edb2ab graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotReplacementsImpl.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotReplacementsImpl.java Wed Mar 11 17:16:30 2015 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotReplacementsImpl.java Wed Mar 11 20:43:12 2015 +0100 @@ -30,11 +30,9 @@ import com.oracle.graal.compiler.common.*; import com.oracle.graal.hotspot.meta.*; import com.oracle.graal.hotspot.replacements.*; -import com.oracle.graal.hotspot.word.*; import com.oracle.graal.nodes.*; import com.oracle.graal.phases.util.*; import com.oracle.graal.replacements.*; -import com.oracle.graal.word.phases.*; /** * Filters certain method substitutions based on whether there is underlying hardware support for @@ -52,16 +50,8 @@ @Override protected ResolvedJavaMethod registerMethodSubstitution(ClassReplacements cr, Executable originalMethod, Method substituteMethod) { final Class substituteClass = substituteMethod.getDeclaringClass(); - if (substituteClass.getDeclaringClass() == BoxingSubstitutions.class) { - if (config.useHeapProfiler) { - return null; - } - } else if (substituteClass == IntegerSubstitutions.class || substituteClass == LongSubstitutions.class) { - if (substituteMethod.getName().equals("bitCount")) { - if (!config.usePopCountInstruction) { - return null; - } - } else if (substituteMethod.getName().equals("numberOfLeadingZeros")) { + if (substituteClass == IntegerSubstitutions.class || substituteClass == LongSubstitutions.class) { + if (substituteMethod.getName().equals("numberOfLeadingZeros")) { if (config.useCountLeadingZerosInstruction) { return null; } @@ -102,23 +92,4 @@ } return super.getMacroSubstitution(method); } - - @Override - protected GraphMaker createGraphMaker(ResolvedJavaMethod substitute, ResolvedJavaMethod original, FrameStateProcessing frameStateProcessing) { - return new HotSpotGraphMaker(this, substitute, original, frameStateProcessing); - } - - public static class HotSpotGraphMaker extends ReplacementsImpl.GraphMaker { - - public HotSpotGraphMaker(ReplacementsImpl replacements, ResolvedJavaMethod substitute, ResolvedJavaMethod substitutedMethod, FrameStateProcessing frameStateProcessing) { - super(replacements, substitute, substitutedMethod, frameStateProcessing); - } - - @Override - protected void afterParsing(StructuredGraph graph) { - MetaAccessProvider metaAccess = replacements.providers.getMetaAccess(); - new WordTypeVerificationPhase(metaAccess, replacements.snippetReflection, replacements.providers.getConstantReflection(), replacements.target.wordKind).apply(graph); - new HotSpotWordTypeRewriterPhase(metaAccess, replacements.snippetReflection, replacements.providers.getConstantReflection(), replacements.target.wordKind).apply(graph); - } - } } diff -r 31fac91ea3b7 -r 14e703edb2ab graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotAnnotatedInvocationPlugin.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotAnnotatedInvocationPlugin.java Wed Mar 11 17:16:30 2015 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,84 +0,0 @@ -/* - * 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.hotspot.meta; - -import static com.oracle.graal.api.meta.MetaUtil.*; -import static com.oracle.graal.replacements.NodeIntrinsificationPhase.*; - -import java.util.*; - -import com.oracle.graal.api.meta.*; -import com.oracle.graal.compiler.common.type.*; -import com.oracle.graal.graph.Node.*; -import com.oracle.graal.java.*; -import com.oracle.graal.java.GraphBuilderPlugin.*; -import com.oracle.graal.nodes.*; -import com.oracle.graal.replacements.*; - -final class HotSpotAnnotatedInvocationPlugin implements GenericInvocationPlugin { - private final HotSpotSuitesProvider suites; - - public HotSpotAnnotatedInvocationPlugin(HotSpotSuitesProvider suites) { - this.suites = suites; - } - - public boolean apply(GraphBuilderContext builder, ResolvedJavaMethod method, ValueNode[] args) { - if (builder.parsingReplacement()) { - NodeIntrinsificationPhase intrins = suites.getNodeIntrinsification(); - NodeIntrinsic intrinsic = intrins.getIntrinsic(method); - if (intrinsic != null) { - Signature sig = method.getSignature(); - Kind returnKind = sig.getReturnKind(); - Stamp stamp = StampFactory.forKind(returnKind); - if (returnKind == Kind.Object) { - JavaType returnType = sig.getReturnType(method.getDeclaringClass()); - if (returnType instanceof ResolvedJavaType) { - stamp = StampFactory.declared((ResolvedJavaType) returnType); - } - } - - ValueNode res = intrins.createIntrinsicNode(Arrays.asList(args), stamp, method, builder.getGraph(), intrinsic); - res = builder.append(res); - if (res.getKind().getStackKind() != Kind.Void) { - builder.push(returnKind.getStackKind(), res); - } - return true; - } else if (intrins.isFoldable(method)) { - ResolvedJavaType[] parameterTypes = resolveJavaTypes(method.toParameterTypes(), method.getDeclaringClass()); - JavaConstant constant = intrins.tryFold(Arrays.asList(args), parameterTypes, method); - if (!COULD_NOT_FOLD.equals(constant)) { - if (constant != null) { - // Replace the invoke with the result of the call - ConstantNode res = builder.append(ConstantNode.forConstant(constant, suites.getMetaAccess())); - builder.push(res.getKind().getStackKind(), builder.append(res)); - } else { - // This must be a void invoke - assert method.getSignature().getReturnKind() == Kind.Void; - } - return true; - } - } - } - return false; - } -} diff -r 31fac91ea3b7 -r 14e703edb2ab graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotConstantReflectionProvider.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotConstantReflectionProvider.java Wed Mar 11 17:16:30 2015 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotConstantReflectionProvider.java Wed Mar 11 20:43:12 2015 +0100 @@ -24,6 +24,7 @@ import static com.oracle.graal.compiler.common.GraalOptions.*; import static com.oracle.graal.hotspot.HotSpotGraalRuntime.*; +import static com.oracle.graal.hotspot.stubs.SnippetStub.*; import java.lang.reflect.*; import java.util.*; @@ -32,6 +33,7 @@ import com.oracle.graal.compiler.common.*; import com.oracle.graal.graph.*; import com.oracle.graal.hotspot.*; +import com.oracle.graal.hotspot.stubs.*; import com.oracle.graal.options.*; import com.oracle.graal.replacements.*; import com.oracle.graal.replacements.ReplacementsImpl.FrameStateProcessing; @@ -41,6 +43,7 @@ /** * HotSpot implementation of {@link ConstantReflectionProvider}. */ +@SuppressWarnings("unused") public class HotSpotConstantReflectionProvider implements ConstantReflectionProvider, HotSpotProxified { private static final String SystemClassName = "Ljava/lang/System;"; @@ -195,7 +198,7 @@ * {@code receiver} is (assignable to) {@link StableOptionValue}. */ public JavaConstant readConstantFieldValue(JavaField field, JavaConstant receiver) { - assert !ImmutableCode.getValue() || isCalledForSnippets() : receiver; + assert !ImmutableCode.getValue() || isCalledForSnippets() || SnippetGraphUnderConstruction.get() != null || HotSpotLoadFieldPlugin.FieldReadEnabledInImmutableCode.get() == Boolean.TRUE : receiver; HotSpotResolvedJavaField hotspotField = (HotSpotResolvedJavaField) field; if (receiver == null) { @@ -314,7 +317,7 @@ ResolvedJavaMethod initMethod = null; try { Class rjm = ResolvedJavaMethod.class; - makeGraphMethod = metaAccess.lookupJavaMethod(ReplacementsImpl.class.getDeclaredMethod("makeGraph", rjm, rjm, SnippetInliningPolicy.class, FrameStateProcessing.class)); + makeGraphMethod = metaAccess.lookupJavaMethod(ReplacementsImpl.class.getDeclaredMethod("makeGraph", rjm, Object[].class, rjm, SnippetInliningPolicy.class, FrameStateProcessing.class)); initMethod = metaAccess.lookupJavaMethod(SnippetTemplate.AbstractTemplates.class.getDeclaredMethod("template", Arguments.class)); } catch (NoSuchMethodException | SecurityException e) { throw new GraalInternalError(e); diff -r 31fac91ea3b7 -r 14e703edb2ab graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotGraphBuilderPlugins.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotGraphBuilderPlugins.java Wed Mar 11 17:16:30 2015 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotGraphBuilderPlugins.java Wed Mar 11 20:43:12 2015 +0100 @@ -22,89 +22,109 @@ */ package com.oracle.graal.hotspot.meta; -import static com.oracle.graal.api.meta.LocationIdentity.*; +import static com.oracle.graal.hotspot.replacements.HotSpotReplacementsUtil.*; import static com.oracle.graal.java.GraphBuilderContext.*; -import static java.lang.Character.*; +import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; -import com.oracle.graal.api.replacements.*; import com.oracle.graal.compiler.common.type.*; -import com.oracle.graal.hotspot.nodes.type.*; +import com.oracle.graal.hotspot.*; +import com.oracle.graal.hotspot.nodes.*; import com.oracle.graal.hotspot.replacements.*; import com.oracle.graal.hotspot.word.*; +import com.oracle.graal.java.GraphBuilderConfiguration.Plugins; import com.oracle.graal.java.*; import com.oracle.graal.java.GraphBuilderPlugin.InvocationPlugin; import com.oracle.graal.java.InvocationPlugins.Registration; import com.oracle.graal.java.InvocationPlugins.Registration.Receiver; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.HeapAccess.BarrierType; -import com.oracle.graal.nodes.calc.*; import com.oracle.graal.nodes.extended.*; -import com.oracle.graal.nodes.java.*; import com.oracle.graal.nodes.spi.*; import com.oracle.graal.options.*; -import com.oracle.graal.word.*; -import com.oracle.graal.word.nodes.*; +import com.oracle.graal.replacements.*; +import com.oracle.graal.word.phases.*; /** - * Provides HotSpot specific {@link InvocationPlugin}s. + * Defines the {@link Plugins} used when running on HotSpot. */ public class HotSpotGraphBuilderPlugins { - public static void registerInvocationPlugins(HotSpotProviders providers, InvocationPlugins plugins) { + + /** + * Creates a {@link Plugins} object that should be used when running on HotSpot. + */ + public static Plugins create(HotSpotVMConfig config, HotSpotProviders providers) { + MetaAccessProvider metaAccess = providers.getMetaAccess(); - SnippetReflectionProvider snippetReflection = providers.getSnippetReflection(); - Kind wordKind = providers.getCodeCache().getTarget().wordKind; + HotSpotWordTypes wordTypes = providers.getWordTypes(); + InvocationPlugins invocationPlugins = new HotSpotInvocationPlugins(config, metaAccess); - registerObjectPlugins(plugins, metaAccess); - registerClassPlugins(plugins, metaAccess); - registerStableOptionPlugins(plugins, metaAccess); - registerMetaspacePointerPlugins(plugins, metaAccess, snippetReflection, wordKind); + Plugins plugins = new Plugins(invocationPlugins); + NodeIntrinsificationPhase nodeIntrinsification = new NodeIntrinsificationPhase(providers, providers.getSnippetReflection()); + ConstantReflectionProvider constantReflection = providers.getConstantReflection(); + HotSpotWordOperationPlugin wordOperationPlugin = new HotSpotWordOperationPlugin(providers.getSnippetReflection(), wordTypes); + + plugins.setParameterPlugin(new HotSpotParameterPlugin(wordTypes)); + plugins.setLoadFieldPlugin(new HotSpotLoadFieldPlugin(metaAccess, constantReflection)); + plugins.setLoadIndexedPlugin(new HotSpotLoadIndexedPlugin(wordTypes)); + plugins.setInlineInvokePlugin(new HotSpotInlineInvokePlugin(nodeIntrinsification, (ReplacementsImpl) providers.getReplacements())); + plugins.setGenericInvocationPlugin(new DefaultGenericInvocationPlugin(nodeIntrinsification, wordOperationPlugin)); + + registerObjectPlugins(invocationPlugins, metaAccess); + registerSystemPlugins(invocationPlugins, metaAccess, providers.getForeignCalls()); + registerThreadPlugins(invocationPlugins, metaAccess, wordTypes, config); + registerStableOptionPlugins(invocationPlugins, metaAccess); + StandardGraphBuilderPlugins.registerInvocationPlugins(providers.getMetaAccess(), providers.getCodeCache().target.arch, invocationPlugins, !config.useHeapProfiler); + return plugins; } private static void registerObjectPlugins(InvocationPlugins plugins, MetaAccessProvider metaAccess) { Registration r = new Registration(plugins, metaAccess, Object.class); r.register1("getClass", Receiver.class, new InvocationPlugin() { - public boolean apply(GraphBuilderContext builder, ValueNode rcvr) { + public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, ValueNode rcvr) { ObjectStamp objectStamp = (ObjectStamp) rcvr.stamp(); ValueNode mirror; if (objectStamp.isExactType() && objectStamp.nonNull()) { - mirror = builder.append(ConstantNode.forConstant(objectStamp.type().getJavaClass(), builder.getMetaAccess())); + mirror = b.append(ConstantNode.forConstant(objectStamp.type().getJavaClass(), b.getMetaAccess())); } else { - StampProvider stampProvider = builder.getStampProvider(); - LoadHubNode hub = builder.append(new LoadHubNode(stampProvider, nullCheckedValue(builder, rcvr))); - mirror = builder.append(new HubGetClassNode(builder.getMetaAccess(), hub)); + StampProvider stampProvider = b.getStampProvider(); + LoadHubNode hub = b.append(new LoadHubNode(stampProvider, nullCheckedValue(b, rcvr))); + mirror = b.append(new HubGetClassNode(b.getMetaAccess(), hub)); } - builder.push(Kind.Object, mirror); + b.push(Kind.Object, mirror); return true; } }); } - private static void registerClassPlugins(InvocationPlugins plugins, MetaAccessProvider metaAccess) { - Registration r = new Registration(plugins, metaAccess, Class.class); - r.register2("cast", Receiver.class, Object.class, new InvocationPlugin() { - public boolean apply(GraphBuilderContext builder, ValueNode rcvr, ValueNode object) { - if (rcvr.isConstant() && !rcvr.isNullConstant()) { - ResolvedJavaType type = builder.getConstantReflection().asJavaType(rcvr.asConstant()); - if (type != null && !type.isPrimitive()) { - builder.push(Kind.Object, builder.append(CheckCastNode.create(type, object, null, false, builder.getAssumptions()))); - return true; - } - } - return false; + private static void registerSystemPlugins(InvocationPlugins plugins, MetaAccessProvider metaAccess, ForeignCallsProvider foreignCalls) { + Registration r = new Registration(plugins, metaAccess, System.class); + r.register0("currentTimeMillis", new InvocationPlugin() { + public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod) { + b.push(Kind.Long, b.append(new ForeignCallNode(foreignCalls, SystemSubstitutions.JAVA_TIME_MILLIS, StampFactory.forKind(Kind.Long)))); + return true; + } + }); + r.register0("nanoTime", new InvocationPlugin() { + public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod) { + b.push(Kind.Long, b.append(new ForeignCallNode(foreignCalls, SystemSubstitutions.JAVA_TIME_NANOS, StampFactory.forKind(Kind.Long)))); + return true; } }); - r.register2("isInstance", Receiver.class, Object.class, new InvocationPlugin() { - public boolean apply(GraphBuilderContext builder, ValueNode rcvr, ValueNode object) { - if (rcvr.isConstant() && !rcvr.isNullConstant()) { - ResolvedJavaType type = builder.getConstantReflection().asJavaType(rcvr.asConstant()); - if (type != null && !type.isPrimitive()) { - LogicNode node = builder.append(InstanceOfNode.create(type, object, null)); - builder.push(Kind.Boolean.getStackKind(), builder.append(ConditionalNode.create(node))); - return true; - } - } - return false; + } + + private static void registerThreadPlugins(InvocationPlugins plugins, MetaAccessProvider metaAccess, WordTypes wordTypes, HotSpotVMConfig config) { + Registration r = new Registration(plugins, metaAccess, Thread.class); + r.register0("currentThread", new InvocationPlugin() { + public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod) { + CurrentJavaThreadNode thread = b.append(new CurrentJavaThreadNode(wordTypes.getWordKind())); + ConstantLocationNode location = b.append(new ConstantLocationNode(JAVA_THREAD_THREAD_OBJECT_LOCATION, config.threadObjectOffset)); + boolean compressible = false; + ValueNode javaThread = WordOperationPlugin.readOp(b, Kind.Object, thread, location, BarrierType.NONE, compressible); + boolean exactType = compressible; + boolean nonNull = true; + b.push(Kind.Object, b.append(new PiNode(javaThread, metaAccess.lookupJavaType(Thread.class), exactType, nonNull))); + return true; } }); } @@ -112,142 +132,16 @@ private static void registerStableOptionPlugins(InvocationPlugins plugins, MetaAccessProvider metaAccess) { Registration r = new Registration(plugins, metaAccess, StableOptionValue.class); r.register1("getValue", Receiver.class, new InvocationPlugin() { - public boolean apply(GraphBuilderContext builder, ValueNode rcvr) { + public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, ValueNode rcvr) { if (rcvr.isConstant() && !rcvr.isNullConstant()) { Object object = ((HotSpotObjectConstantImpl) rcvr.asConstant()).object(); StableOptionValue option = (StableOptionValue) object; - ConstantNode value = builder.append(ConstantNode.forConstant(HotSpotObjectConstantImpl.forObject(option.getValue()), builder.getMetaAccess())); - builder.push(Kind.Object, value); + ConstantNode value = b.append(ConstantNode.forConstant(HotSpotObjectConstantImpl.forObject(option.getValue()), b.getMetaAccess())); + b.push(Kind.Object, value); return true; } return false; } }); } - - private static void registerMetaspacePointerPlugins(InvocationPlugins plugins, MetaAccessProvider metaAccess, SnippetReflectionProvider snippetReflection, Kind wordKind) { - Registration r = new Registration(plugins, metaAccess, MetaspacePointer.class); - r.register1("isNull", Receiver.class, new InvocationPlugin() { - public boolean apply(GraphBuilderContext builder, ValueNode pointer) { - assert pointer.stamp() instanceof MetaspacePointerStamp; - IsNullNode isNull = builder.append(new IsNullNode(pointer)); - ConstantNode trueValue = builder.append(ConstantNode.forBoolean(true)); - ConstantNode falseValue = builder.append(ConstantNode.forBoolean(false)); - builder.push(Kind.Boolean.getStackKind(), builder.append(new ConditionalNode(isNull, trueValue, falseValue))); - return true; - } - }); - r.register1("asWord", Receiver.class, new InvocationPlugin() { - public boolean apply(GraphBuilderContext builder, ValueNode pointer) { - builder.append(new PointerCastNode(StampFactory.forKind(wordKind), pointer)); - return true; - } - }); - r.register2("readObject", Receiver.class, int.class, new ReadOp(snippetReflection, wordKind, Kind.Object, BarrierType.NONE, true)); - r.register3("readObject", Receiver.class, int.class, LocationIdentity.class, new ReadOp(snippetReflection, wordKind, Kind.Object, BarrierType.NONE, true)); - r.register3("readObject", Receiver.class, int.class, BarrierType.class, new ReadOp(snippetReflection, wordKind, Kind.Object, BarrierType.NONE, true)); - r.register2("readObject", Receiver.class, WordBase.class, new ReadOp(snippetReflection, wordKind, Kind.Object, BarrierType.NONE, true)); - r.register3("readObject", Receiver.class, WordBase.class, LocationIdentity.class, new ReadOp(snippetReflection, wordKind, Kind.Object, BarrierType.NONE, true)); - r.register3("readObject", Receiver.class, WordBase.class, BarrierType.class, new ReadOp(snippetReflection, wordKind, Kind.Object, BarrierType.NONE, true)); - - registerWordOpPlugins(r, snippetReflection, wordKind, Kind.Byte, Kind.Short, Kind.Char, Kind.Int, Kind.Float, Kind.Long, Kind.Double); - } - - private static void registerWordOpPlugins(Registration r, SnippetReflectionProvider snippetReflection, Kind wordKind, Kind... kinds) { - for (Kind kind : kinds) { - String kindName = kind.getJavaName(); - kindName = toUpperCase(kindName.charAt(0)) + kindName.substring(1); - String getName = "read" + kindName; - // String putName = "write" + kindName; - r.register2(getName, Receiver.class, int.class, new ReadOp(snippetReflection, wordKind, kind)); - r.register3(getName, Receiver.class, int.class, LocationIdentity.class, new ReadOp(snippetReflection, wordKind, kind)); - } - } - - static class ReadOp implements InvocationPlugin { - final SnippetReflectionProvider snippetReflection; - final Kind wordKind; - final Kind resultKind; - final BarrierType barrierType; - final boolean compressible; - - public ReadOp(SnippetReflectionProvider snippetReflection, Kind wordKind, Kind resultKind, BarrierType barrierType, boolean compressible) { - this.snippetReflection = snippetReflection; - this.wordKind = wordKind; - this.resultKind = resultKind; - this.barrierType = barrierType; - this.compressible = compressible; - } - - public ReadOp(SnippetReflectionProvider snippetReflection, Kind wordKind, Kind resultKind) { - this(snippetReflection, wordKind, resultKind, BarrierType.NONE, false); - } - - public boolean apply(GraphBuilderContext builder, ValueNode pointer, ValueNode offset) { - LocationNode location = makeLocation(builder, offset, ANY_LOCATION, wordKind); - builder.push(resultKind, builder.append(readOp(builder, resultKind, pointer, location, barrierType, compressible))); - return true; - } - - public boolean apply(GraphBuilderContext builder, ValueNode pointer, ValueNode offset, ValueNode locationIdentityArg) { - assert locationIdentityArg.isConstant(); - LocationIdentity locationIdentity = snippetReflection.asObject(LocationIdentity.class, locationIdentityArg.asJavaConstant()); - LocationNode location = makeLocation(builder, offset, locationIdentity, wordKind); - builder.push(resultKind, builder.append(readOp(builder, resultKind, pointer, location, barrierType, compressible))); - return true; - } - } - - public static ValueNode readOp(GraphBuilderContext builder, Kind readKind, ValueNode base, LocationNode location, BarrierType barrierType, boolean compressible) { - JavaReadNode read = builder.append(new JavaReadNode(readKind, base, location, barrierType, compressible)); - /* - * The read must not float outside its block otherwise it may float above an explicit zero - * check on its base address. - */ - read.setGuard(builder.getCurrentBlockGuard()); - return read; - } - - public static LocationNode makeLocation(GraphBuilderContext builder, ValueNode offset, LocationIdentity locationIdentity, Kind wordKind) { - return builder.append(new IndexedLocationNode(locationIdentity, 0, fromSigned(builder, offset, wordKind), 1)); - } - - public static LocationNode makeLocation(GraphBuilderContext builder, ValueNode offset, ValueNode locationIdentity, Kind wordKind) { - if (locationIdentity.isConstant()) { - return makeLocation(builder, offset, builder.getSnippetReflection().asObject(LocationIdentity.class, locationIdentity.asJavaConstant()), wordKind); - } - return builder.append(new SnippetLocationNode(builder.getSnippetReflection(), locationIdentity, builder.append(ConstantNode.forLong(0)), fromSigned(builder, offset, wordKind), - builder.append(ConstantNode.forInt(1)))); - } - - public static ValueNode fromUnsigned(GraphBuilderContext builder, ValueNode value, Kind wordKind) { - return convert(builder, value, wordKind, true); - } - - public static ValueNode fromSigned(GraphBuilderContext builder, ValueNode value, Kind wordKind) { - return convert(builder, value, wordKind, false); - } - - public static ValueNode toUnsigned(GraphBuilderContext builder, ValueNode value, Kind toKind) { - return convert(builder, value, toKind, true); - } - - public static ValueNode convert(GraphBuilderContext builder, ValueNode value, Kind toKind, boolean unsigned) { - if (value.getKind() == toKind) { - return value; - } - - if (toKind == Kind.Int) { - assert value.getKind() == Kind.Long; - return builder.append(new NarrowNode(value, 32)); - } else { - assert toKind == Kind.Long; - assert value.getKind().getStackKind() == Kind.Int; - if (unsigned) { - return builder.append(new ZeroExtendNode(value, 64)); - } else { - return builder.append(new SignExtendNode(value, 64)); - } - } - } } diff -r 31fac91ea3b7 -r 14e703edb2ab graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotHostForeignCallsProvider.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotHostForeignCallsProvider.java Wed Mar 11 17:16:30 2015 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotHostForeignCallsProvider.java Wed Mar 11 20:43:12 2015 +0100 @@ -138,7 +138,6 @@ } public void initialize(HotSpotProviders providers, HotSpotVMConfig c) { - TargetDescription target = providers.getCodeCache().getTarget(); if (!PreferGraalStubs.getValue()) { registerForeignCall(DEOPTIMIZATION_HANDLER, c.handleDeoptStub, NativeCall, PRESERVES_REGISTERS, LEAF_NOFP, REEXECUTABLE, NO_LOCATIONS); @@ -174,11 +173,11 @@ registerForeignCall(VM_MESSAGE_C, c.vmMessageAddress, NativeCall, DESTROYS_REGISTERS, NOT_LEAF, REEXECUTABLE, NO_LOCATIONS); registerForeignCall(ASSERTION_VM_MESSAGE_C, c.vmMessageAddress, NativeCall, PRESERVES_REGISTERS, LEAF, REEXECUTABLE, NO_LOCATIONS); - link(new NewInstanceStub(providers, target, registerStubCall(NEW_INSTANCE, REEXECUTABLE, NOT_LEAF, ANY_LOCATION))); - link(new NewArrayStub(providers, target, registerStubCall(NEW_ARRAY, REEXECUTABLE, NOT_LEAF, INIT_LOCATION))); - link(new ExceptionHandlerStub(providers, target, foreignCalls.get(EXCEPTION_HANDLER))); - link(new UnwindExceptionToCallerStub(providers, target, registerStubCall(UNWIND_EXCEPTION_TO_CALLER, NOT_REEXECUTABLE, NOT_LEAF, ANY_LOCATION))); - link(new VerifyOopStub(providers, target, registerStubCall(VERIFY_OOP, REEXECUTABLE, LEAF_NOFP, NO_LOCATIONS))); + link(new NewInstanceStub(providers, registerStubCall(NEW_INSTANCE, REEXECUTABLE, NOT_LEAF, ANY_LOCATION))); + link(new NewArrayStub(providers, registerStubCall(NEW_ARRAY, REEXECUTABLE, NOT_LEAF, INIT_LOCATION))); + link(new ExceptionHandlerStub(providers, foreignCalls.get(EXCEPTION_HANDLER))); + link(new UnwindExceptionToCallerStub(providers, registerStubCall(UNWIND_EXCEPTION_TO_CALLER, NOT_REEXECUTABLE, NOT_LEAF, ANY_LOCATION))); + link(new VerifyOopStub(providers, registerStubCall(VERIFY_OOP, REEXECUTABLE, LEAF_NOFP, NO_LOCATIONS))); linkForeignCall(providers, IDENTITY_HASHCODE, c.identityHashCodeAddress, PREPEND_THREAD, NOT_LEAF, NOT_REEXECUTABLE, MARK_WORD_LOCATION); linkForeignCall(providers, REGISTER_FINALIZER, c.registerFinalizerAddress, PREPEND_THREAD, NOT_LEAF, NOT_REEXECUTABLE, ANY_LOCATION); diff -r 31fac91ea3b7 -r 14e703edb2ab graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotInlineInvokePlugin.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotInlineInvokePlugin.java Wed Mar 11 17:16:30 2015 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotInlineInvokePlugin.java Wed Mar 11 20:43:12 2015 +0100 @@ -23,43 +23,54 @@ package com.oracle.graal.hotspot.meta; import static com.oracle.graal.compiler.common.GraalOptions.*; +import static com.oracle.graal.java.AbstractBytecodeParser.Options.*; +import static java.lang.String.*; import com.oracle.graal.api.meta.*; -import com.oracle.graal.graph.Node.*; +import com.oracle.graal.api.replacements.*; +import com.oracle.graal.graph.Node.NodeIntrinsic; +import com.oracle.graal.hotspot.word.*; import com.oracle.graal.java.*; -import com.oracle.graal.java.GraphBuilderPlugin.*; +import com.oracle.graal.java.GraphBuilderPlugin.InlineInvokePlugin; import com.oracle.graal.nodes.*; -import com.oracle.graal.nodes.spi.*; +import com.oracle.graal.replacements.*; +import com.oracle.graal.word.*; -final class HotSpotInlineInvokePlugin implements InlineInvokePlugin { - private final Replacements replacements; - private final HotSpotSuitesProvider suites; +public final class HotSpotInlineInvokePlugin implements InlineInvokePlugin { + private final ReplacementsImpl replacements; + private final NodeIntrinsificationPhase nodeIntrinsification; - public HotSpotInlineInvokePlugin(HotSpotSuitesProvider suites, Replacements replacements) { - this.suites = suites; + public HotSpotInlineInvokePlugin(NodeIntrinsificationPhase nodeIntrinsification, ReplacementsImpl replacements) { + this.nodeIntrinsification = nodeIntrinsification; this.replacements = replacements; } - public ResolvedJavaMethod getInlinedMethod(GraphBuilderContext builder, ResolvedJavaMethod method, ValueNode[] args, JavaType returnType) { + public InlineInfo getInlineInfo(GraphBuilderContext b, ResolvedJavaMethod method, ValueNode[] args, JavaType returnType) { ResolvedJavaMethod subst = replacements.getMethodSubstitutionMethod(method); if (subst != null) { // Forced inlining of intrinsics - return subst; + return new InlineInfo(subst, true); } - if (builder.parsingReplacement()) { - if (suites.getNodeIntrinsification().getIntrinsic(method) != null) { - // @NodeIntrinsic methods are handled by HotSpotAnnotatedInvocationPlugin - return null; - } + if (b.parsingReplacement()) { + assert nodeIntrinsification.getIntrinsic(method) == null && method.getAnnotation(Word.Operation.class) == null && method.getAnnotation(HotSpotOperation.class) == null && + !nodeIntrinsification.isFoldable(method) : format("%s should have been handled by %s", method.format("%H.%n(%p)"), DefaultGenericInvocationPlugin.class.getName()); + // Force inlining when parsing replacements - return method; + return new InlineInfo(method, true); } else { - assert suites.getNodeIntrinsification().getIntrinsic(method) == null : String.format("@%s method %s must only be called from within a replacement%n%s", - NodeIntrinsic.class.getSimpleName(), method.format("%h.%n"), builder); - if (InlineDuringParsing.getValue() && method.hasBytecodes() && method.getCode().length <= TrivialInliningSize.getValue() && builder.getDepth() < InlineDuringParsingMaxDepth.getValue()) { - return method; + assert nodeIntrinsification.getIntrinsic(method) == null : String.format("@%s method %s must only be called from within a replacement%n%s", NodeIntrinsic.class.getSimpleName(), + method.format("%h.%n"), b); + if (InlineDuringParsing.getValue() && method.hasBytecodes() && method.getCode().length <= TrivialInliningSize.getValue() && b.getDepth() < InlineDuringParsingMaxDepth.getValue()) { + return new InlineInfo(method, false); } } return null; } + + public void notifyOfNoninlinedInvoke(GraphBuilderContext b, ResolvedJavaMethod method, Invoke invoke) { + if (b.parsingReplacement()) { + boolean compilingSnippet = b.getRootMethod().getAnnotation(MethodSubstitution.class) == null; + assert compilingSnippet : format("All calls in the replacement %s must be inlined or intrinsified: found call to %s", b.getRootMethod().format("%H.%n(%p)"), method.format("%h.%n(%p)")); + } + } } diff -r 31fac91ea3b7 -r 14e703edb2ab graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotInvocationPlugins.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotInvocationPlugins.java Wed Mar 11 20:43:12 2015 +0100 @@ -0,0 +1,72 @@ +/* + * 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.hotspot.meta; + +import com.oracle.graal.api.meta.*; +import com.oracle.graal.hotspot.*; +import com.oracle.graal.java.*; +import com.oracle.graal.java.GraphBuilderPlugin.*; +import com.oracle.graal.replacements.StandardGraphBuilderPlugins.*; + +/** + * Extension of {@link InvocationPlugins} that disables plugins based on runtime configuration. + */ +final class HotSpotInvocationPlugins extends InvocationPlugins { + final HotSpotVMConfig config; + final MetaAccessProvider metaAccess; + + public HotSpotInvocationPlugins(HotSpotVMConfig config, MetaAccessProvider metaAccess) { + this.config = config; + this.metaAccess = metaAccess; + } + + @Override + public void register(ResolvedJavaMethod method, InvocationPlugin plugin) { + if (!config.usePopCountInstruction) { + if (method.getName().equals("bitCount")) { + assert method.getDeclaringClass().equals(metaAccess.lookupJavaType(Integer.class)) || method.getDeclaringClass().equals(metaAccess.lookupJavaType(Long.class)); + return; + } + } + if (!config.useCountLeadingZerosInstruction) { + if (method.getName().equals("numberOfLeadingZeros")) { + assert method.getDeclaringClass().equals(metaAccess.lookupJavaType(Integer.class)) || method.getDeclaringClass().equals(metaAccess.lookupJavaType(Long.class)); + return; + } + } + if (!config.useCountTrailingZerosInstruction) { + if (method.getName().equals("numberOfTrailingZeros")) { + assert method.getDeclaringClass().equals(metaAccess.lookupJavaType(Integer.class)); + return; + } + } + + if (config.useHeapProfiler) { + if (plugin instanceof BoxPlugin) { + // The heap profiler wants to see all allocations related to boxing + return; + } + } + super.register(method, plugin); + } +} diff -r 31fac91ea3b7 -r 14e703edb2ab graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotLoadFieldPlugin.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotLoadFieldPlugin.java Wed Mar 11 17:16:30 2015 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotLoadFieldPlugin.java Wed Mar 11 20:43:12 2015 +0100 @@ -23,13 +23,15 @@ package com.oracle.graal.hotspot.meta; import static com.oracle.graal.compiler.common.GraalOptions.*; +import static com.oracle.graal.java.AbstractBytecodeParser.Options.*; import com.oracle.graal.api.meta.*; +import com.oracle.graal.api.replacements.*; import com.oracle.graal.java.*; -import com.oracle.graal.java.GraphBuilderPlugin.*; +import com.oracle.graal.java.GraphBuilderPlugin.LoadFieldPlugin; import com.oracle.graal.nodes.*; -final class HotSpotLoadFieldPlugin implements LoadFieldPlugin { +public final class HotSpotLoadFieldPlugin implements LoadFieldPlugin { private final MetaAccessProvider metaAccess; private final ConstantReflectionProvider constantReflection; @@ -38,17 +40,48 @@ this.constantReflection = constantReflection; } - public boolean apply(GraphBuilderContext builder, ValueNode receiver, ResolvedJavaField field) { - if (InlineDuringParsing.getValue() || builder.parsingReplacement()) { + static final ThreadLocal FieldReadEnabledInImmutableCode = new ThreadLocal<>(); + + public boolean apply(GraphBuilderContext b, ValueNode receiver, ResolvedJavaField field) { + if ((InlineDuringParsing.getValue() && !ImmutableCode.getValue()) || b.parsingReplacement()) { if (receiver.isConstant()) { JavaConstant asJavaConstant = receiver.asJavaConstant(); - return tryConstantFold(builder, metaAccess, constantReflection, field, asJavaConstant); + return tryReadField(b, field, asJavaConstant); } } return false; } - public boolean apply(GraphBuilderContext builder, ResolvedJavaField staticField) { - return tryConstantFold(builder, metaAccess, constantReflection, staticField, null); + private boolean tryReadField(GraphBuilderContext b, ResolvedJavaField field, JavaConstant receiver) { + if (ImmutableCode.getValue()) { + FieldReadEnabledInImmutableCode.set(Boolean.TRUE); + } + try { + return tryConstantFold(b, metaAccess, constantReflection, field, receiver); + } finally { + if (ImmutableCode.getValue()) { + FieldReadEnabledInImmutableCode.set(null); + } + } + } + + public boolean apply(GraphBuilderContext b, ResolvedJavaField staticField) { + if ((InlineDuringParsing.getValue() && !ImmutableCode.getValue()) || b.parsingReplacement()) { + // Javac does not allow use of "$assertionsDisabled" for a field name but + // Eclipse does in which case a suffix is added to the generated field. + if (b.parsingReplacement() && staticField.isSynthetic() && staticField.getName().startsWith("$assertionsDisabled")) { + // For methods called indirectly from intrinsics, we (silently) disable + // assertions so that the parser won't see calls to the AssertionError + // constructor (all Invokes must be removed from intrinsics - see + // HotSpotInlineInvokePlugin.notifyOfNoninlinedInvoke). Direct use of + // assertions in intrinsics is forbidden. + assert b.getMethod().getAnnotation(MethodSubstitution.class) == null : "cannot use assertions in " + b.getMethod().format("%H.%n(%p)"); + ConstantNode trueNode = b.append(ConstantNode.forBoolean(true)); + b.push(trueNode.getKind().getStackKind(), trueNode); + return true; + } + return tryReadField(b, staticField, null); + } + return false; } } diff -r 31fac91ea3b7 -r 14e703edb2ab graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotLoadIndexedPlugin.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotLoadIndexedPlugin.java Wed Mar 11 20:43:12 2015 +0100 @@ -0,0 +1,67 @@ +/* + * 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.hotspot.meta; + +import com.oracle.graal.api.meta.*; +import com.oracle.graal.compiler.common.type.*; +import com.oracle.graal.hotspot.nodes.*; +import com.oracle.graal.hotspot.nodes.type.*; +import com.oracle.graal.hotspot.word.*; +import com.oracle.graal.java.*; +import com.oracle.graal.java.GraphBuilderPlugin.LoadIndexedPlugin; +import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.java.*; +import com.oracle.graal.nodes.type.*; + +public final class HotSpotLoadIndexedPlugin implements LoadIndexedPlugin { + private final HotSpotWordTypes wordTypes; + + public HotSpotLoadIndexedPlugin(HotSpotWordTypes wordTypes) { + this.wordTypes = wordTypes; + } + + public boolean apply(GraphBuilderContext b, ValueNode array, ValueNode index, Kind elementKind) { + if (b.parsingReplacement()) { + ResolvedJavaType arrayType = StampTool.typeOrNull(array); + /* + * There are cases where the array does not have a known type yet, i.e., the type is + * null. In that case we assume it is not a word type. + */ + if (arrayType != null && wordTypes.isWord(arrayType.getComponentType()) && elementKind != wordTypes.getWordKind()) { + /* + * The elementKind of the node is a final field, and other information such as the + * stamp depends on elementKind. Therefore, just create a new node and replace the + * old one. + */ + Stamp componentStamp = wordTypes.getWordStamp(arrayType.getComponentType()); + if (componentStamp instanceof MetaspacePointerStamp) { + b.push(elementKind, b.append(new LoadIndexedPointerNode(componentStamp, array, index))); + } else { + b.push(elementKind, b.append(new LoadIndexedNode(array, index, wordTypes.getWordKind()))); + } + return true; + } + } + return false; + } +} diff -r 31fac91ea3b7 -r 14e703edb2ab graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotParameterPlugin.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotParameterPlugin.java Wed Mar 11 20:43:12 2015 +0100 @@ -0,0 +1,50 @@ +/* + * 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.hotspot.meta; + +import com.oracle.graal.api.meta.*; +import com.oracle.graal.compiler.common.type.*; +import com.oracle.graal.java.*; +import com.oracle.graal.java.GraphBuilderPlugin.ParameterPlugin; +import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.calc.*; +import com.oracle.graal.nodes.type.*; +import com.oracle.graal.word.phases.*; + +public final class HotSpotParameterPlugin implements ParameterPlugin { + private final WordTypes wordTypes; + + public HotSpotParameterPlugin(WordTypes wordTypes) { + this.wordTypes = wordTypes; + } + + public FloatingNode interceptParameter(GraphBuilderContext b, int index, Stamp stamp) { + if (b.parsingReplacement()) { + ResolvedJavaType type = StampTool.typeOrNull(stamp); + if (wordTypes.isWord(type)) { + return new ParameterNode(index, wordTypes.getWordStamp(type)); + } + } + return null; + } +} diff -r 31fac91ea3b7 -r 14e703edb2ab graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotProviders.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotProviders.java Wed Mar 11 17:16:30 2015 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotProviders.java Wed Mar 11 20:43:12 2015 +0100 @@ -24,6 +24,8 @@ import com.oracle.graal.api.meta.*; import com.oracle.graal.api.replacements.*; +import com.oracle.graal.hotspot.word.*; +import com.oracle.graal.java.GraphBuilderConfiguration.Plugins; import com.oracle.graal.nodes.spi.*; import com.oracle.graal.phases.tiers.*; import com.oracle.graal.phases.util.*; @@ -38,6 +40,8 @@ private final SuitesProvider suites; private final HotSpotRegistersProvider registers; private final SnippetReflectionProvider snippetReflection; + private final HotSpotWordTypes wordTypes; + private Plugins graphBuilderPlugins; public HotSpotProviders(MetaAccessProvider metaAccess, HotSpotCodeCacheProvider codeCache, ConstantReflectionProvider constantReflection, HotSpotForeignCallsProvider foreignCalls, LoweringProvider lowerer, Replacements replacements, HotSpotDisassemblerProvider disassembler, SuitesProvider suites, HotSpotRegistersProvider registers, @@ -47,6 +51,7 @@ this.suites = suites; this.registers = registers; this.snippetReflection = snippetReflection; + this.wordTypes = new HotSpotWordTypes(metaAccess, codeCache.getTarget().wordKind); } @Override @@ -74,4 +79,17 @@ public SnippetReflectionProvider getSnippetReflection() { return snippetReflection; } + + public void setGraphBuilderPlugins(Plugins plugins) { + graphBuilderPlugins = plugins; + } + + public Plugins getGraphBuilderPlugins() { + assert graphBuilderPlugins != null; + return graphBuilderPlugins; + } + + public HotSpotWordTypes getWordTypes() { + return wordTypes; + } } diff -r 31fac91ea3b7 -r 14e703edb2ab graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotSuitesProvider.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotSuitesProvider.java Wed Mar 11 17:16:30 2015 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotSuitesProvider.java Wed Mar 11 20:43:12 2015 +0100 @@ -24,19 +24,16 @@ import static com.oracle.graal.compiler.common.GraalOptions.*; -import com.oracle.graal.api.meta.*; import com.oracle.graal.hotspot.*; import com.oracle.graal.hotspot.bridge.*; import com.oracle.graal.hotspot.phases.*; import com.oracle.graal.java.*; import com.oracle.graal.java.GraphBuilderConfiguration.DebugInfoMode; import com.oracle.graal.lir.phases.*; -import com.oracle.graal.nodes.spi.*; import com.oracle.graal.options.*; import com.oracle.graal.options.DerivedOptionValue.OptionSupplier; import com.oracle.graal.phases.*; import com.oracle.graal.phases.tiers.*; -import com.oracle.graal.replacements.*; /** * HotSpot implementation of {@link SuitesProvider}. @@ -68,9 +65,9 @@ } - public HotSpotSuitesProvider(HotSpotGraalRuntimeProvider runtime, MetaAccessProvider metaAccess, ConstantReflectionProvider constantReflection, Replacements replacements) { + public HotSpotSuitesProvider(HotSpotGraalRuntimeProvider runtime) { this.runtime = runtime; - this.defaultGraphBuilderSuite = createGraphBuilderSuite(metaAccess, constantReflection, replacements); + this.defaultGraphBuilderSuite = createGraphBuilderSuite(); this.defaultSuites = new DerivedOptionValue<>(new SuitesSupplier()); this.defaultLIRSuites = new DerivedOptionValue<>(new LIRSuitesSupplier()); } @@ -102,26 +99,9 @@ return ret; } - NodeIntrinsificationPhase intrinsifier; - - NodeIntrinsificationPhase getNodeIntrinsification() { - if (intrinsifier == null) { - HotSpotProviders providers = runtime.getHostProviders(); - intrinsifier = new NodeIntrinsificationPhase(providers, providers.getSnippetReflection()); - } - return intrinsifier; - } - - MetaAccessProvider getMetaAccess() { - return runtime.getHostProviders().getMetaAccess(); - } - - protected PhaseSuite createGraphBuilderSuite(MetaAccessProvider metaAccess, ConstantReflectionProvider constantReflection, Replacements replacements) { + protected PhaseSuite createGraphBuilderSuite() { PhaseSuite suite = new PhaseSuite<>(); GraphBuilderConfiguration config = GraphBuilderConfiguration.getDefault(); - config.getPlugins().setLoadFieldPlugin(new HotSpotLoadFieldPlugin(metaAccess, constantReflection)); - config.getPlugins().setInlineInvokePlugin(new HotSpotInlineInvokePlugin(this, replacements)); - config.getPlugins().setGenericInvocationPlugin(new HotSpotAnnotatedInvocationPlugin(this)); suite.appendPhase(new GraphBuilderPhase(config)); return suite; } diff -r 31fac91ea3b7 -r 14e703edb2ab graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotWordOperationPlugin.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotWordOperationPlugin.java Wed Mar 11 20:43:12 2015 +0100 @@ -0,0 +1,134 @@ +/* + * 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.hotspot.meta; + +import static com.oracle.graal.api.meta.LocationIdentity.*; +import static com.oracle.graal.hotspot.word.HotSpotOperation.HotspotOpcode.*; +import static com.oracle.graal.nodes.ConstantNode.*; + +import com.oracle.graal.api.meta.*; +import com.oracle.graal.api.replacements.*; +import com.oracle.graal.compiler.common.*; +import com.oracle.graal.compiler.common.type.*; +import com.oracle.graal.hotspot.nodes.type.*; +import com.oracle.graal.hotspot.word.*; +import com.oracle.graal.hotspot.word.HotSpotOperation.HotspotOpcode; +import com.oracle.graal.java.*; +import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.HeapAccess.BarrierType; +import com.oracle.graal.nodes.calc.*; +import com.oracle.graal.nodes.extended.*; +import com.oracle.graal.replacements.*; +import com.oracle.graal.word.phases.*; + +/** + * Extends {@link WordOperationPlugin} to handle {@linkplain HotSpotOperation HotSpot word + * operations}. + */ +class HotSpotWordOperationPlugin extends WordOperationPlugin { + public HotSpotWordOperationPlugin(SnippetReflectionProvider snippetReflection, WordTypes wordTypes) { + super(snippetReflection, wordTypes); + } + + @Override + public boolean apply(GraphBuilderContext b, ResolvedJavaMethod method, ValueNode[] args) { + if (!wordTypes.isWordOperation(method)) { + return false; + } + + HotSpotOperation operation = method.getAnnotation(HotSpotOperation.class); + if (operation == null) { + processWordOperation(b, args, wordTypes.getWordOperation(method, b.getMethod().getDeclaringClass())); + return true; + } + processHotSpotWordOperation(b, method, args, operation); + return true; + } + + public void processHotSpotWordOperation(GraphBuilderContext b, ResolvedJavaMethod method, ValueNode[] args, HotSpotOperation operation) { + Kind returnKind = method.getSignature().getReturnKind(); + Kind returnStackKind = returnKind.getStackKind(); + switch (operation.opcode()) { + case POINTER_EQ: + case POINTER_NE: + assert args.length == 2; + HotspotOpcode opcode = operation.opcode(); + ValueNode left = args[0]; + ValueNode right = args[1]; + assert left.stamp() instanceof MetaspacePointerStamp : left + " " + left.stamp(); + assert right.stamp() instanceof MetaspacePointerStamp : right + " " + right.stamp(); + assert opcode == POINTER_EQ || opcode == POINTER_NE; + + PointerEqualsNode comparison = b.append(new PointerEqualsNode(left, right)); + ValueNode eqValue = b.append(forBoolean(opcode == POINTER_EQ)); + ValueNode neValue = b.append(forBoolean(opcode == POINTER_NE)); + b.push(returnStackKind, b.append(new ConditionalNode(comparison, eqValue, neValue))); + break; + + case IS_NULL: + assert args.length == 1; + ValueNode pointer = args[0]; + assert pointer.stamp() instanceof MetaspacePointerStamp; + + IsNullNode isNull = b.append(new IsNullNode(pointer)); + b.push(returnStackKind, b.append(new ConditionalNode(isNull, b.append(forBoolean(true)), b.append(forBoolean(false))))); + break; + + case FROM_POINTER: + assert args.length == 1; + b.push(returnStackKind, b.append(new PointerCastNode(StampFactory.forKind(wordKind), args[0]))); + break; + + case TO_KLASS_POINTER: + assert args.length == 1; + b.push(returnStackKind, b.append(new PointerCastNode(KlassPointerStamp.klass(), args[0]))); + break; + + case TO_METHOD_POINTER: + assert args.length == 1; + b.push(returnStackKind, b.append(new PointerCastNode(MethodPointerStamp.method(), args[0]))); + break; + + case READ_KLASS_POINTER: + assert args.length == 2 || args.length == 3; + Stamp readStamp = KlassPointerStamp.klass(); + LocationNode location; + if (args.length == 2) { + location = makeLocation(b, args[1], ANY_LOCATION); + } else { + location = makeLocation(b, args[1], args[2]); + } + ReadNode read = b.append(new ReadNode(args[0], location, readStamp, BarrierType.NONE)); + /* + * The read must not float outside its block otherwise it may float above an + * explicit zero check on its base address. + */ + read.setGuard(AbstractBeginNode.prevBegin(read)); + b.push(returnStackKind, read); + break; + + default: + throw GraalInternalError.shouldNotReachHere("unknown operation: " + operation.opcode()); + } + } +} diff -r 31fac91ea3b7 -r 14e703edb2ab graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/CurrentJavaThreadNode.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/CurrentJavaThreadNode.java Wed Mar 11 17:16:30 2015 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/CurrentJavaThreadNode.java Wed Mar 11 20:43:12 2015 +0100 @@ -43,8 +43,12 @@ protected LIRKind wordKind; public CurrentJavaThreadNode(@InjectedNodeParameter HotSpotGraalRuntimeProvider runtime) { - super(TYPE, StampFactory.forKind(runtime.getTarget().wordKind)); - this.wordKind = LIRKind.value(runtime.getTarget().wordKind); + this(runtime.getTarget().wordKind); + } + + public CurrentJavaThreadNode(Kind wordKind) { + super(TYPE, StampFactory.forKind(wordKind)); + this.wordKind = LIRKind.value(wordKind); } @Override diff -r 31fac91ea3b7 -r 14e703edb2ab graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/AESCryptSubstitutions.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/AESCryptSubstitutions.java Wed Mar 11 17:16:30 2015 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/AESCryptSubstitutions.java Wed Mar 11 20:43:12 2015 +0100 @@ -24,6 +24,7 @@ import static com.oracle.graal.hotspot.HotSpotBackend.*; import static com.oracle.graal.hotspot.replacements.HotSpotReplacementsUtil.*; +import static com.oracle.graal.word.Word.*; import sun.misc.*; import com.oracle.graal.api.meta.*; @@ -89,7 +90,7 @@ private static void crypt(Object rcvr, byte[] in, int inOffset, byte[] out, int outOffset, boolean encrypt) { Object realReceiver = PiNode.piCastNonNull(rcvr, AESCryptClass); Object kObject = UnsafeLoadNode.load(realReceiver, kOffset, Kind.Object, LocationIdentity.ANY_LOCATION); - Word kAddr = (Word) Word.fromObject(kObject).add(arrayBaseOffset(Kind.Byte)); + Word kAddr = fromWordBase(Word.fromObject(kObject).add(arrayBaseOffset(Kind.Byte))); Word inAddr = Word.unsigned(GetObjectAddressNode.get(in) + arrayBaseOffset(Kind.Byte) + inOffset); Word outAddr = Word.unsigned(GetObjectAddressNode.get(out) + arrayBaseOffset(Kind.Byte) + outOffset); if (encrypt) { diff -r 31fac91ea3b7 -r 14e703edb2ab graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/CipherBlockChainingSubstitutions.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/CipherBlockChainingSubstitutions.java Wed Mar 11 17:16:30 2015 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/CipherBlockChainingSubstitutions.java Wed Mar 11 20:43:12 2015 +0100 @@ -97,8 +97,8 @@ Object realReceiver = PiNode.piCastNonNull(rcvr, cipherBlockChainingClass); Object kObject = UnsafeLoadNode.load(embeddedCipher, AESCryptSubstitutions.kOffset, Kind.Object, LocationIdentity.ANY_LOCATION); Object rObject = UnsafeLoadNode.load(realReceiver, rOffset, Kind.Object, LocationIdentity.ANY_LOCATION); - Word kAddr = (Word) Word.fromObject(kObject).add(arrayBaseOffset(Kind.Byte)); - Word rAddr = (Word) Word.fromObject(rObject).add(arrayBaseOffset(Kind.Byte)); + Word kAddr = Word.fromWordBase(Word.fromObject(kObject).add(arrayBaseOffset(Kind.Byte))); + Word rAddr = Word.fromWordBase(Word.fromObject(rObject).add(arrayBaseOffset(Kind.Byte))); Word inAddr = Word.unsigned(GetObjectAddressNode.get(in) + arrayBaseOffset(Kind.Byte) + inOffset); Word outAddr = Word.unsigned(GetObjectAddressNode.get(out) + arrayBaseOffset(Kind.Byte) + outOffset); if (encrypt) { diff -r 31fac91ea3b7 -r 14e703edb2ab graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/HotSpotClassSubstitutions.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/HotSpotClassSubstitutions.java Wed Mar 11 17:16:30 2015 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/HotSpotClassSubstitutions.java Wed Mar 11 20:43:12 2015 +0100 @@ -23,13 +23,13 @@ package com.oracle.graal.hotspot.replacements; import static com.oracle.graal.hotspot.replacements.HotSpotReplacementsUtil.*; -import static com.oracle.graal.nodes.PiNode.*; import java.lang.reflect.*; import com.oracle.graal.api.replacements.*; import com.oracle.graal.hotspot.nodes.*; import com.oracle.graal.hotspot.word.*; +import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.spi.*; import com.oracle.graal.word.*; @@ -110,7 +110,7 @@ } public static Class readJavaMirror(Word klass) { - return piCastExactNonNull(klass.readObject(classMirrorOffset(), CLASS_MIRROR_LOCATION), Class.class); + return PiNode.asNonNullClass(klass.readObject(classMirrorOffset(), CLASS_MIRROR_LOCATION)); } @MacroSubstitution(macro = ClassGetComponentTypeNode.class, isStatic = false) @@ -119,7 +119,7 @@ KlassPointer klass = ClassGetHubNode.readClass(thisObj); if (!klass.isNull()) { if (klassIsArray(klass)) { - return piCastExactNonNull(klass.readObject(arrayKlassComponentMirrorOffset(), ARRAY_KLASS_COMPONENT_MIRROR), Class.class); + return PiNode.asNonNullClass(klass.readObject(arrayKlassComponentMirrorOffset(), ARRAY_KLASS_COMPONENT_MIRROR)); } } return null; diff -r 31fac91ea3b7 -r 14e703edb2ab graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/HotSpotReplacementsUtil.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/HotSpotReplacementsUtil.java Wed Mar 11 17:16:30 2015 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/HotSpotReplacementsUtil.java Wed Mar 11 20:43:12 2015 +0100 @@ -593,22 +593,14 @@ @NodeIntrinsic(value = WriteRegisterNode.class, setStampFromReturnType = true) public static native void writeRegisterAsWord(@ConstantNodeParameter Register register, Word value); - @SuppressWarnings("unused") @NodeIntrinsic(value = UnsafeLoadNode.class, setStampFromReturnType = true) - private static Word loadWordFromObjectIntrinsic(Object object, long offset, @ConstantNodeParameter Kind wordKind, @ConstantNodeParameter LocationIdentity locationIdentity) { - return Word.unsigned(unsafeReadWord(object, offset)); - } - - @SuppressWarnings("unused") - @NodeIntrinsic(value = LoadHubNode.class) - public static KlassPointer loadHubIntrinsic(Object object, GuardingNode anchor) { - return KlassPointer.fromWord(Word.unsigned(unsafeReadKlassPointer(object))); - } + private static native Word loadWordFromObjectIntrinsic(Object object, long offset, @ConstantNodeParameter Kind wordKind, @ConstantNodeParameter LocationIdentity locationIdentity); @NodeIntrinsic(value = LoadHubNode.class) - public static KlassPointer loadHubIntrinsic(Object object) { - return KlassPointer.fromWord(Word.unsigned(unsafeReadKlassPointer(object))); - } + public static native KlassPointer loadHubIntrinsic(Object object, GuardingNode anchor); + + @NodeIntrinsic(value = LoadHubNode.class) + public static native KlassPointer loadHubIntrinsic(Object object); @Fold public static int log2WordSize() { diff -r 31fac91ea3b7 -r 14e703edb2ab graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/LoadExceptionObjectSnippets.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/LoadExceptionObjectSnippets.java Wed Mar 11 17:16:30 2015 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/LoadExceptionObjectSnippets.java Wed Mar 11 20:43:12 2015 +0100 @@ -59,7 +59,7 @@ private static final boolean USE_C_RUNTIME = Boolean.getBoolean("graal.loadExceptionObject.useCRuntime"); @Snippet - public static Throwable loadException(@ConstantParameter Register threadRegister) { + public static Object loadException(@ConstantParameter Register threadRegister) { Word thread = registerAsWord(threadRegister); Object exception = readExceptionOop(thread); writeExceptionOop(thread, null); diff -r 31fac91ea3b7 -r 14e703edb2ab graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/MonitorSnippets.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/MonitorSnippets.java Wed Mar 11 17:16:30 2015 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/MonitorSnippets.java Wed Mar 11 20:43:12 2015 +0100 @@ -501,7 +501,7 @@ invoke.setStateAfter(graph.start().stateAfter()); graph.addAfterFixed(graph.start(), invoke); - StructuredGraph inlineeGraph = providers.getReplacements().getSnippet(initCounter.getMethod()); + StructuredGraph inlineeGraph = providers.getReplacements().getSnippet(initCounter.getMethod(), null); InliningUtil.inline(invoke, inlineeGraph, false, null); List rets = graph.getNodes(ReturnNode.TYPE).snapshot(); diff -r 31fac91ea3b7 -r 14e703edb2ab graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ObjectCloneNode.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ObjectCloneNode.java Wed Mar 11 17:16:30 2015 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ObjectCloneNode.java Wed Mar 11 20:43:12 2015 +0100 @@ -63,7 +63,7 @@ final Replacements replacements = tool.getReplacements(); StructuredGraph snippetGraph = null; try (Scope s = Debug.scope("ArrayCopySnippet", snippetMethod)) { - snippetGraph = replacements.getSnippet(snippetMethod); + snippetGraph = replacements.getSnippet(snippetMethod, null); } catch (Throwable e) { throw Debug.handle(e); } diff -r 31fac91ea3b7 -r 14e703edb2ab graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ObjectCloneSnippets.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ObjectCloneSnippets.java Wed Mar 11 17:16:30 2015 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ObjectCloneSnippets.java Wed Mar 11 20:43:12 2015 +0100 @@ -114,7 +114,7 @@ @Snippet(removeAllFrameStates = true) public static Object[] objectArrayClone(Object[] src) { - Object[] result = (Object[]) DynamicNewArrayNode.newUninitializedArray(GuardingPiNode.guardingNonNull(src.getClass().getComponentType()), src.length, Kind.Object); + Object[] result = (Object[]) DynamicNewArrayNode.newUninitializedArray(GuardingPiNode.asNonNullClass(src.getClass().getComponentType()), src.length, Kind.Object); ArrayCopyCallNode.disjointUninitializedArraycopy(src, 0, result, 0, src.length, Kind.Object); return result; } diff -r 31fac91ea3b7 -r 14e703edb2ab graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ReflectionSubstitutions.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ReflectionSubstitutions.java Wed Mar 11 17:16:30 2015 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ReflectionSubstitutions.java Wed Mar 11 20:43:12 2015 +0100 @@ -42,7 +42,7 @@ @MethodSubstitution public static int getClassAccessFlags(Class aClass) { - KlassPointer klass = ClassGetHubNode.readClass(GuardingPiNode.guardingNonNull(aClass)); + KlassPointer klass = ClassGetHubNode.readClass(GuardingPiNode.asNonNullClass(aClass)); if (klass.isNull()) { // Class for primitive type return Modifier.ABSTRACT | Modifier.FINAL | Modifier.PUBLIC; diff -r 31fac91ea3b7 -r 14e703edb2ab graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/SystemSubstitutions.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/SystemSubstitutions.java Wed Mar 11 17:16:30 2015 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/SystemSubstitutions.java Wed Mar 11 20:43:12 2015 +0100 @@ -27,10 +27,7 @@ import com.oracle.graal.api.meta.*; import com.oracle.graal.api.replacements.*; -import com.oracle.graal.graph.Node.ConstantNodeParameter; -import com.oracle.graal.graph.Node.NodeIntrinsic; import com.oracle.graal.hotspot.replacements.arraycopy.*; -import com.oracle.graal.nodes.extended.*; import com.oracle.graal.nodes.spi.*; /** @@ -45,16 +42,6 @@ @MacroSubstitution(macro = ArrayCopyNode.class) public static native void arraycopy(Object src, int srcPos, Object dest, int destPos, int length); - @MethodSubstitution - public static long currentTimeMillis() { - return callLong(JAVA_TIME_MILLIS); - } - - @MethodSubstitution - public static long nanoTime() { - return callLong(JAVA_TIME_NANOS); - } - @MacroSubstitution(macro = SystemIdentityHashCodeNode.class) @MethodSubstitution public static int identityHashCode(Object x) { @@ -64,13 +51,4 @@ return computeHashCode(x); } - - @NodeIntrinsic(value = ForeignCallNode.class, setStampFromReturnType = true) - public static long callLong(@ConstantNodeParameter ForeignCallDescriptor descriptor) { - if (descriptor == JAVA_TIME_MILLIS) { - return System.currentTimeMillis(); - } - assert descriptor == JAVA_TIME_NANOS; - return System.nanoTime(); - } } diff -r 31fac91ea3b7 -r 14e703edb2ab graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ThreadSubstitutions.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ThreadSubstitutions.java Wed Mar 11 17:16:30 2015 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ThreadSubstitutions.java Wed Mar 11 20:43:12 2015 +0100 @@ -25,15 +25,11 @@ import static com.oracle.graal.api.meta.LocationIdentity.*; import static com.oracle.graal.hotspot.replacements.HotSpotReplacementsUtil.*; -import java.lang.reflect.*; - import com.oracle.graal.api.meta.*; import com.oracle.graal.api.replacements.*; -import com.oracle.graal.compiler.common.*; import com.oracle.graal.graph.Node.ConstantNodeParameter; import com.oracle.graal.graph.Node.NodeIntrinsic; import com.oracle.graal.hotspot.nodes.*; -import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.extended.*; import com.oracle.graal.word.*; @@ -43,14 +39,9 @@ @ClassSubstitution(java.lang.Thread.class) public class ThreadSubstitutions { - @MethodSubstitution - public static Thread currentThread() { - return PiNode.piCastNonNull(CurrentJavaThreadNode.get(getWordKind()).readObject(threadObjectOffset(), JAVA_THREAD_THREAD_OBJECT_LOCATION), Thread.class); - } - @MethodSubstitution(isStatic = false) public static boolean isInterrupted(final Thread thisObject, boolean clearInterrupted) { - Word javaThread = CurrentJavaThreadNode.get(getWordKind()); + Word javaThread = CurrentJavaThreadNode.get(); Object thread = javaThread.readObject(threadObjectOffset(), JAVA_THREAD_THREAD_OBJECT_LOCATION); if (thisObject == thread) { Word osThread = javaThread.readWord(osThreadOffset(), JAVA_THREAD_OSTHREAD_LOCATION); @@ -65,17 +56,6 @@ public static final ForeignCallDescriptor THREAD_IS_INTERRUPTED = new ForeignCallDescriptor("thread_is_interrupted", boolean.class, Object.class, boolean.class); - /** - * @param descriptor - */ @NodeIntrinsic(ForeignCallNode.class) - private static boolean threadIsInterruptedStub(@ConstantNodeParameter ForeignCallDescriptor descriptor, Thread thread, boolean clearIsInterrupted) { - try { - Method isInterrupted = Thread.class.getDeclaredMethod("isInterrupted", boolean.class); - isInterrupted.setAccessible(true); - return (Boolean) isInterrupted.invoke(thread, clearIsInterrupted); - } catch (Exception e) { - throw new GraalInternalError(e); - } - } + private static native boolean threadIsInterruptedStub(@ConstantNodeParameter ForeignCallDescriptor descriptor, Thread thread, boolean clearIsInterrupted); } diff -r 31fac91ea3b7 -r 14e703edb2ab graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/WriteBarrierSnippets.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/WriteBarrierSnippets.java Wed Mar 11 17:16:30 2015 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/WriteBarrierSnippets.java Wed Mar 11 20:43:12 2015 +0100 @@ -79,7 +79,7 @@ serialWriteBarrierCounter.inc(); int cardTableShift = (isImmutableCode() && generatePIC()) ? CardTableShiftNode.cardTableShift() : cardTableShift(); long cardTableAddress = (isImmutableCode() && generatePIC()) ? CardTableAddressNode.cardTableAddress() : cardTableStart(); - Word base = (Word) oop.unsignedShiftRight(cardTableShift); + Word base = Word.fromWordBase(oop.unsignedShiftRight(cardTableShift)); long startAddress = cardTableAddress; int displacement = 0; if (((int) startAddress) == startAddress) { @@ -105,7 +105,7 @@ long end = (dstAddr + header + ((long) startIndex + length - 1) * scale) >>> cardShift; long count = end - start + 1; while (count-- > 0) { - DirectStoreNode.store((start + cardStart) + count, false, Kind.Boolean); + DirectStoreNode.storeBoolean((start + cardStart) + count, false, Kind.Boolean); } } @@ -119,8 +119,8 @@ Object fixedObject = FixedValueAnchorNode.getObject(object); verifyOop(fixedObject); Object fixedExpectedObject = FixedValueAnchorNode.getObject(expectedObject); - Word field = (Word) Word.fromArray(fixedObject, SnippetLocationProxyNode.location(location)); - Word previousOop = (Word) Word.fromObject(fixedExpectedObject); + Word field = Word.fromWordBase(Word.fromArray(fixedObject, SnippetLocationProxyNode.location(location))); + Word previousOop = Word.fromWordBase(Word.fromObject(fixedExpectedObject)); byte markingValue = thread.readByte(g1SATBQueueMarkingOffset()); Word bufferAddress = thread.readWord(g1SATBQueueBufferOffset()); Word indexAddress = thread.add(g1SATBQueueIndexOffset()); @@ -140,7 +140,7 @@ // If the previous value has to be loaded (before the write), the load is issued. // The load is always issued except the cases of CAS and referent field. if (probability(LIKELY_PROBABILITY, doLoad)) { - previousOop = (Word) Word.fromObject(field.readObject(0, BarrierType.NONE)); + previousOop = Word.fromWordBase(Word.fromObject(field.readObject(0, BarrierType.NONE))); if (trace) { log(trace, "[%d] G1-Pre Thread %p Previous Object %p\n ", gcCycle, thread.rawValue(), previousOop.rawValue()); verifyOop(previousOop.toObject()); @@ -176,9 +176,9 @@ validateObject(fixedObject, fixedValue); Word oop; if (usePrecise) { - oop = (Word) Word.fromArray(fixedObject, SnippetLocationProxyNode.location(location)); + oop = Word.fromWordBase(Word.fromArray(fixedObject, SnippetLocationProxyNode.location(location))); } else { - oop = (Word) Word.fromObject(fixedObject); + oop = Word.fromWordBase(Word.fromObject(fixedObject)); } int gcCycle = 0; if (trace) { @@ -186,7 +186,7 @@ log(trace, "[%d] G1-Post Thread: %p Object: %p\n", gcCycle, thread.rawValue(), Word.fromObject(fixedObject).rawValue()); log(trace, "[%d] G1-Post Thread: %p Field: %p\n", gcCycle, thread.rawValue(), oop.rawValue()); } - Word writtenValue = (Word) Word.fromObject(fixedValue); + Word writtenValue = Word.fromWordBase(Word.fromObject(fixedValue)); Word bufferAddress = thread.readWord(g1CardQueueBufferOffset()); Word indexAddress = thread.add(g1CardQueueIndexOffset()); Word indexValue = thread.readWord(g1CardQueueIndexOffset()); diff -r 31fac91ea3b7 -r 14e703edb2ab graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/arraycopy/ArrayCopyNode.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/arraycopy/ArrayCopyNode.java Wed Mar 11 17:16:30 2015 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/arraycopy/ArrayCopyNode.java Wed Mar 11 20:43:12 2015 +0100 @@ -63,7 +63,7 @@ Kind componentKind = srcType.getComponentType().getKind(); final ResolvedJavaMethod snippetMethod = tool.getMetaAccess().lookupJavaMethod(ArrayCopySnippets.getSnippetForKind(componentKind, shouldUnroll(), isExact())); try (Scope s = Debug.scope("ArrayCopySnippet", snippetMethod)) { - return replacements.getSnippet(snippetMethod); + return replacements.getSnippet(snippetMethod, null, null); } catch (Throwable e) { throw Debug.handle(e); } @@ -103,7 +103,7 @@ } snippetGraph = null; try (Scope s = Debug.scope("ArrayCopySnippet", snippetMethod)) { - snippetGraph = replacements.getSnippet(snippetMethod, getTargetMethod()).copy(); + snippetGraph = replacements.getSnippet(snippetMethod, getTargetMethod(), null).copy(); } catch (Throwable e) { throw Debug.handle(e); } diff -r 31fac91ea3b7 -r 14e703edb2ab graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/arraycopy/UnsafeArrayCopySnippets.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/arraycopy/UnsafeArrayCopySnippets.java Wed Mar 11 17:16:30 2015 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/arraycopy/UnsafeArrayCopySnippets.java Wed Mar 11 20:43:12 2015 +0100 @@ -91,42 +91,36 @@ for (long i = 0; i < postLoopBytes; i += elementSize) { srcOffset -= elementSize; destOffset -= elementSize; - Object a = UnsafeLoadNode.load(src, arrayBaseOffset + srcOffset, baseKind, locationIdentity); - UnsafeStoreNode.store(dest, arrayBaseOffset + destOffset, a, baseKind, locationIdentity); + UnsafeCopyNode.copy(src, arrayBaseOffset + srcOffset, dest, arrayBaseOffset + destOffset, baseKind, locationIdentity); } // Main-loop for (long i = 0; i < mainLoopBytes; i += VECTOR_SIZE) { srcOffset -= VECTOR_SIZE; destOffset -= VECTOR_SIZE; - Long a = UnsafeLoadNode.load(src, arrayBaseOffset + srcOffset, VECTOR_KIND, locationIdentity); - UnsafeStoreNode.store(dest, arrayBaseOffset + destOffset, a, VECTOR_KIND, locationIdentity); + UnsafeCopyNode.copy(src, arrayBaseOffset + srcOffset, dest, arrayBaseOffset + destOffset, VECTOR_KIND, locationIdentity); } // Pre-loop for (long i = 0; i < preLoopBytes; i += elementSize) { srcOffset -= elementSize; destOffset -= elementSize; - Object a = UnsafeLoadNode.load(src, arrayBaseOffset + srcOffset, baseKind, locationIdentity); - UnsafeStoreNode.store(dest, arrayBaseOffset + destOffset, a, baseKind, locationIdentity); + UnsafeCopyNode.copy(src, arrayBaseOffset + srcOffset, dest, arrayBaseOffset + destOffset, baseKind, locationIdentity); } } else { // Pre-loop for (long i = 0; i < preLoopBytes; i += elementSize) { - Object a = UnsafeLoadNode.load(src, arrayBaseOffset + srcOffset, baseKind, locationIdentity); - UnsafeStoreNode.store(dest, arrayBaseOffset + destOffset, a, baseKind, locationIdentity); + UnsafeCopyNode.copy(src, arrayBaseOffset + srcOffset, dest, arrayBaseOffset + destOffset, baseKind, locationIdentity); srcOffset += elementSize; destOffset += elementSize; } // Main-loop for (long i = 0; i < mainLoopBytes; i += VECTOR_SIZE) { - Long a = UnsafeLoadNode.load(src, arrayBaseOffset + srcOffset, VECTOR_KIND, locationIdentity); - UnsafeStoreNode.store(dest, arrayBaseOffset + destOffset, a, VECTOR_KIND, locationIdentity); + UnsafeCopyNode.copy(src, arrayBaseOffset + srcOffset, dest, arrayBaseOffset + destOffset, VECTOR_KIND, locationIdentity); srcOffset += VECTOR_SIZE; destOffset += VECTOR_SIZE; } // Post-loop for (long i = 0; i < postLoopBytes; i += elementSize) { - Object a = UnsafeLoadNode.load(src, arrayBaseOffset + srcOffset, baseKind, locationIdentity); - UnsafeStoreNode.store(dest, arrayBaseOffset + destOffset, a, baseKind, locationIdentity); + UnsafeCopyNode.copy(src, arrayBaseOffset + srcOffset, dest, arrayBaseOffset + destOffset, baseKind, locationIdentity); srcOffset += elementSize; destOffset += elementSize; } diff -r 31fac91ea3b7 -r 14e703edb2ab graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/DeoptimizationStub.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/DeoptimizationStub.java Wed Mar 11 17:16:30 2015 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/DeoptimizationStub.java Wed Mar 11 20:43:12 2015 +0100 @@ -84,7 +84,7 @@ private final TargetDescription target; public DeoptimizationStub(HotSpotProviders providers, TargetDescription target, HotSpotForeignCallLinkage linkage) { - super(DeoptimizationStub.class, "deoptimizationHandler", providers, target, linkage); + super(DeoptimizationStub.class, "deoptimizationHandler", providers, linkage); this.target = target; assert PreferGraalStubs.getValue(); } diff -r 31fac91ea3b7 -r 14e703edb2ab graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/ExceptionHandlerStub.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/ExceptionHandlerStub.java Wed Mar 11 17:16:30 2015 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/ExceptionHandlerStub.java Wed Mar 11 20:43:12 2015 +0100 @@ -49,8 +49,8 @@ */ public class ExceptionHandlerStub extends SnippetStub { - public ExceptionHandlerStub(HotSpotProviders providers, TargetDescription target, HotSpotForeignCallLinkage linkage) { - super("exceptionHandler", providers, target, linkage); + public ExceptionHandlerStub(HotSpotProviders providers, HotSpotForeignCallLinkage linkage) { + super("exceptionHandler", providers, linkage); } /** diff -r 31fac91ea3b7 -r 14e703edb2ab graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/ForeignCallStub.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/ForeignCallStub.java Wed Mar 11 17:16:30 2015 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/ForeignCallStub.java Wed Mar 11 20:43:12 2015 +0100 @@ -26,7 +26,6 @@ import static com.oracle.graal.hotspot.HotSpotForeignCallLinkage.RegisterEffect.*; import com.oracle.graal.api.meta.*; -import com.oracle.graal.api.replacements.*; import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.debug.*; import com.oracle.graal.hotspot.*; @@ -34,13 +33,12 @@ import com.oracle.graal.hotspot.meta.*; import com.oracle.graal.hotspot.nodes.*; import com.oracle.graal.hotspot.replacements.*; -import com.oracle.graal.hotspot.word.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.StructuredGraph.AllowAssumptions; -import com.oracle.graal.phases.util.*; import com.oracle.graal.replacements.*; import com.oracle.graal.replacements.nodes.*; import com.oracle.graal.word.*; +import com.oracle.graal.word.phases.*; /** * A {@linkplain #getGraph() generated} stub for a {@link Transition non-leaf} foreign call from @@ -188,16 +186,17 @@ */ @Override protected StructuredGraph getGraph() { + WordTypes wordTypes = providers.getWordTypes(); Class[] args = linkage.getDescriptor().getArgumentTypes(); boolean isObjectResult = linkage.getOutgoingCallingConvention().getReturn().getKind() == Kind.Object; StructuredGraph graph = new StructuredGraph(toString(), null, AllowAssumptions.NO); graph.disableInlinedMethodRecording(); - GraphKit kit = new HotSpotGraphKit(graph, providers); + GraphKit kit = new GraphKit(graph, providers, wordTypes); ParameterNode[] params = createParameters(kit, args); - ReadRegisterNode thread = kit.append(new ReadRegisterNode(providers.getRegisters().getThreadRegister(), true, false)); + ReadRegisterNode thread = kit.append(new ReadRegisterNode(providers.getRegisters().getThreadRegister(), wordTypes.getWordKind(), true, false)); ValueNode result = createTargetCall(kit, params, thread); kit.createInvoke(StubUtil.class, "handlePendingException", thread, ConstantNode.forBoolean(isObjectResult, graph)); if (isObjectResult) { @@ -210,8 +209,7 @@ Debug.dump(graph, "Initial stub graph"); } - kit.rewriteWordTypes(providers.getSnippetReflection()); - kit.inlineInvokes(providers.getSnippetReflection()); + kit.inlineInvokes(); if (Debug.isDumpEnabled()) { Debug.dump(graph, "Stub graph before compilation"); @@ -220,26 +218,13 @@ return graph; } - private static class HotSpotGraphKit extends GraphKit { - - public HotSpotGraphKit(StructuredGraph graph, Providers providers) { - super(graph, providers); - } - - @Override - public void rewriteWordTypes(SnippetReflectionProvider snippetReflection) { - new HotSpotWordTypeRewriterPhase(providers.getMetaAccess(), snippetReflection, providers.getConstantReflection(), providers.getCodeCache().getTarget().wordKind).apply(graph); - } - } - private ParameterNode[] createParameters(GraphKit kit, Class[] args) { ParameterNode[] params = new ParameterNode[args.length]; ResolvedJavaType accessingClass = providers.getMetaAccess().lookupJavaType(getClass()); for (int i = 0; i < args.length; i++) { ResolvedJavaType type = providers.getMetaAccess().lookupJavaType(args[i]).resolve(accessingClass); - Kind kind = type.getKind().getStackKind(); Stamp stamp; - if (kind == Kind.Object) { + if (type.getKind().getStackKind() == Kind.Object) { stamp = StampFactory.declared(type); } else { stamp = StampFactory.forKind(type.getKind()); diff -r 31fac91ea3b7 -r 14e703edb2ab graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/NewArrayStub.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/NewArrayStub.java Wed Mar 11 17:16:30 2015 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/NewArrayStub.java Wed Mar 11 20:43:12 2015 +0100 @@ -38,12 +38,9 @@ import com.oracle.graal.hotspot.nodes.type.*; import com.oracle.graal.hotspot.replacements.*; import com.oracle.graal.hotspot.word.*; -import com.oracle.graal.nodes.StructuredGraph.GuardsStage; -import com.oracle.graal.nodes.spi.*; +import com.oracle.graal.nodes.*; import com.oracle.graal.replacements.*; import com.oracle.graal.replacements.Snippet.ConstantParameter; -import com.oracle.graal.replacements.SnippetTemplate.Arguments; -import com.oracle.graal.replacements.SnippetTemplate.SnippetInfo; import com.oracle.graal.word.*; /** @@ -54,19 +51,19 @@ */ public class NewArrayStub extends SnippetStub { - public NewArrayStub(HotSpotProviders providers, TargetDescription target, HotSpotForeignCallLinkage linkage) { - super("newArray", providers, target, linkage); + public NewArrayStub(HotSpotProviders providers, HotSpotForeignCallLinkage linkage) { + super("newArray", providers, linkage); } @Override - protected Arguments makeArguments(SnippetInfo stub) { + protected Object[] makeConstArgs() { HotSpotResolvedObjectType intArrayType = (HotSpotResolvedObjectType) providers.getMetaAccess().lookupJavaType(int[].class); - - Arguments args = new Arguments(stub, GuardsStage.FLOATING_GUARDS, LoweringTool.StandardLoweringStage.HIGH_TIER); - args.add("hub", null); - args.add("length", null); - args.addConst("intArrayHub", intArrayType.klass(), KlassPointerStamp.klassNonNull()); - args.addConst("threadRegister", providers.getRegisters().getThreadRegister()); + int count = method.getSignature().getParameterCount(false); + Object[] args = new Object[count]; + assert checkConstArg(2, "intArrayHub"); + assert checkConstArg(3, "threadRegister"); + args[2] = ConstantNode.forConstant(KlassPointerStamp.klassNonNull(), intArrayType.klass(), null); + args[3] = providers.getRegisters().getThreadRegister(); return args; } diff -r 31fac91ea3b7 -r 14e703edb2ab graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/NewInstanceStub.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/NewInstanceStub.java Wed Mar 11 17:16:30 2015 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/NewInstanceStub.java Wed Mar 11 20:43:12 2015 +0100 @@ -38,12 +38,9 @@ import com.oracle.graal.hotspot.nodes.type.*; import com.oracle.graal.hotspot.replacements.*; import com.oracle.graal.hotspot.word.*; -import com.oracle.graal.nodes.StructuredGraph.GuardsStage; -import com.oracle.graal.nodes.spi.*; +import com.oracle.graal.nodes.*; import com.oracle.graal.replacements.*; import com.oracle.graal.replacements.Snippet.ConstantParameter; -import com.oracle.graal.replacements.SnippetTemplate.Arguments; -import com.oracle.graal.replacements.SnippetTemplate.SnippetInfo; import com.oracle.graal.word.*; /** @@ -54,18 +51,19 @@ */ public class NewInstanceStub extends SnippetStub { - public NewInstanceStub(HotSpotProviders providers, TargetDescription target, HotSpotForeignCallLinkage linkage) { - super("newInstance", providers, target, linkage); + public NewInstanceStub(HotSpotProviders providers, HotSpotForeignCallLinkage linkage) { + super("newInstance", providers, linkage); } @Override - protected Arguments makeArguments(SnippetInfo stub) { + protected Object[] makeConstArgs() { HotSpotResolvedObjectType intArrayType = (HotSpotResolvedObjectType) providers.getMetaAccess().lookupJavaType(int[].class); - - Arguments args = new Arguments(stub, GuardsStage.FLOATING_GUARDS, LoweringTool.StandardLoweringStage.HIGH_TIER); - args.add("hub", null); - args.addConst("intArrayHub", intArrayType.klass(), KlassPointerStamp.klassNonNull()); - args.addConst("threadRegister", providers.getRegisters().getThreadRegister()); + int count = method.getSignature().getParameterCount(false); + Object[] args = new Object[count]; + assert checkConstArg(1, "intArrayHub"); + assert checkConstArg(2, "threadRegister"); + args[1] = ConstantNode.forConstant(KlassPointerStamp.klassNonNull(), intArrayType.klass(), null); + args[2] = providers.getRegisters().getThreadRegister(); return args; } diff -r 31fac91ea3b7 -r 14e703edb2ab graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/SnippetStub.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/SnippetStub.java Wed Mar 11 17:16:30 2015 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/SnippetStub.java Wed Mar 11 20:43:12 2015 +0100 @@ -22,43 +22,32 @@ */ package com.oracle.graal.hotspot.stubs; -import com.oracle.graal.api.code.*; +import java.lang.reflect.*; + import com.oracle.graal.api.meta.*; import com.oracle.graal.compiler.common.*; +import com.oracle.graal.debug.*; +import com.oracle.graal.debug.Debug.Scope; import com.oracle.graal.hotspot.*; import com.oracle.graal.hotspot.meta.*; +import com.oracle.graal.java.*; +import com.oracle.graal.java.GraphBuilderConfiguration.Plugins; import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.StructuredGraph.AllowAssumptions; import com.oracle.graal.nodes.StructuredGraph.GuardsStage; import com.oracle.graal.nodes.spi.*; +import com.oracle.graal.phases.*; +import com.oracle.graal.phases.common.*; +import com.oracle.graal.phases.tiers.*; import com.oracle.graal.replacements.*; -import com.oracle.graal.replacements.SnippetTemplate.AbstractTemplates; -import com.oracle.graal.replacements.SnippetTemplate.Arguments; -import com.oracle.graal.replacements.SnippetTemplate.SnippetInfo; +import com.oracle.graal.replacements.Snippet.ConstantParameter; /** * Base class for a stub defined by a snippet. */ public abstract class SnippetStub extends Stub implements Snippets { - static class Template extends AbstractTemplates { - - Template(HotSpotProviders providers, TargetDescription target, Class declaringClass, String snippetMethodName) { - super(providers, providers.getSnippetReflection(), target); - this.info = snippet(declaringClass, snippetMethodName); - } - - /** - * Info for the method implementing the stub. - */ - protected final SnippetInfo info; - - protected StructuredGraph getGraph(Arguments args) { - SnippetTemplate template = template(args); - return template.copySpecializedGraph(); - } - } - - protected final Template snippet; + protected final ResolvedJavaMethod method; /** * Creates a new snippet stub. @@ -67,8 +56,8 @@ * this object * @param linkage linkage details for a call to the stub */ - public SnippetStub(String snippetMethodName, HotSpotProviders providers, TargetDescription target, HotSpotForeignCallLinkage linkage) { - this(null, snippetMethodName, providers, target, linkage); + public SnippetStub(String snippetMethodName, HotSpotProviders providers, HotSpotForeignCallLinkage linkage) { + this(null, snippetMethodName, providers, linkage); } /** @@ -80,28 +69,61 @@ * {@code snippetDeclaringClass} * @param linkage linkage details for a call to the stub */ - public SnippetStub(Class snippetDeclaringClass, String snippetMethodName, HotSpotProviders providers, TargetDescription target, HotSpotForeignCallLinkage linkage) { + public SnippetStub(Class snippetDeclaringClass, String snippetMethodName, HotSpotProviders providers, HotSpotForeignCallLinkage linkage) { super(providers, linkage); - this.snippet = new Template(providers, target, snippetDeclaringClass == null ? getClass() : snippetDeclaringClass, snippetMethodName); + Method javaMethod = SnippetTemplate.AbstractTemplates.findMethod(snippetDeclaringClass == null ? getClass() : snippetDeclaringClass, snippetMethodName, null); + this.method = providers.getMetaAccess().lookupJavaMethod(javaMethod); } + public static final ThreadLocal SnippetGraphUnderConstruction = new ThreadLocal<>(); + @Override protected StructuredGraph getGraph() { - return snippet.getGraph(makeArguments(snippet.info)); + GraphBuilderConfiguration config = GraphBuilderConfiguration.getSnippetDefault(); + Plugins defaultPlugins = providers.getGraphBuilderPlugins(); + Plugins plugins = config.getPlugins().updateFrom(defaultPlugins, false); + plugins.getInvocationPlugins().setDefaults(defaultPlugins.getInvocationPlugins()); + plugins.setParameterPlugin(new ConstantBindingParameterPlugin(makeConstArgs(), plugins.getParameterPlugin(), providers.getMetaAccess(), providers.getSnippetReflection())); + + // Stubs cannot have optimistic assumptions since they have + // to be valid for the entire run of the VM. Nor can they be + // evolved or have breakpoints. + final StructuredGraph graph = new StructuredGraph(method, AllowAssumptions.NO); + graph.disableInlinedMethodRecording(); + + assert SnippetGraphUnderConstruction.get() == null; + SnippetGraphUnderConstruction.set(graph); + new GraphBuilderPhase.Instance(providers.getMetaAccess(), providers.getStampProvider(), providers.getConstantReflection(), config, OptimisticOptimizations.NONE, method).apply(graph); + SnippetGraphUnderConstruction.set(null); + + graph.setGuardsStage(GuardsStage.FLOATING_GUARDS); + try (Scope s = Debug.scope("LoweringStub", graph)) { + new LoweringPhase(new CanonicalizerPhase(), LoweringTool.StandardLoweringStage.HIGH_TIER).apply(graph, new PhaseContext(providers)); + } catch (Throwable e) { + throw Debug.handle(e); + } + + return graph; } - /** - * Adds the arguments to this snippet stub. - */ - protected Arguments makeArguments(SnippetInfo stub) { - Arguments args = new Arguments(stub, GuardsStage.FLOATING_GUARDS, LoweringTool.StandardLoweringStage.HIGH_TIER); - for (int i = 0; i < stub.getParameterCount(); i++) { - String name = stub.getParameterName(i); - if (stub.isConstantParameter(i)) { - args.addConst(name, getConstantParameterValue(i, name)); - } else { - assert !stub.isVarargsParameter(i); - args.add(name, null); + protected boolean checkConstArg(int index, String expectedName) { + assert method.getParameterAnnotation(ConstantParameter.class, index) != null : String.format("parameter %d of %s is expected to be constant", index, method.format("%H.%n(%p)")); + LocalVariableTable lvt = method.getLocalVariableTable(); + if (lvt != null) { + Local local = lvt.getLocal(index, 0); + assert local != null; + String actualName = local.getName(); + assert actualName.equals(expectedName) : String.format("parameter %d of %s is expected to be named %s, not %s", index, method.format("%H.%n(%p)"), expectedName, actualName); + } + return true; + } + + protected Object[] makeConstArgs() { + int count = method.getSignature().getParameterCount(false); + Object[] args = new Object[count]; + for (int i = 0; i < args.length; i++) { + if (method.getParameterAnnotation(ConstantParameter.class, i) != null) { + args[i] = getConstantParameterValue(i, null); } } return args; @@ -118,7 +140,7 @@ @Override public ResolvedJavaMethod getInstalledCodeOwner() { - return snippet.info.getMethod(); + return method; } @Override diff -r 31fac91ea3b7 -r 14e703edb2ab graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/UncommonTrapStub.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/UncommonTrapStub.java Wed Mar 11 17:16:30 2015 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/UncommonTrapStub.java Wed Mar 11 20:43:12 2015 +0100 @@ -84,7 +84,7 @@ private final TargetDescription target; public UncommonTrapStub(HotSpotProviders providers, TargetDescription target, HotSpotForeignCallLinkage linkage) { - super(UncommonTrapStub.class, "uncommonTrapHandler", providers, target, linkage); + super(UncommonTrapStub.class, "uncommonTrapHandler", providers, linkage); this.target = target; assert PreferGraalStubs.getValue(); } diff -r 31fac91ea3b7 -r 14e703edb2ab graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/UnwindExceptionToCallerStub.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/UnwindExceptionToCallerStub.java Wed Mar 11 17:16:30 2015 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/UnwindExceptionToCallerStub.java Wed Mar 11 20:43:12 2015 +0100 @@ -46,8 +46,8 @@ */ public class UnwindExceptionToCallerStub extends SnippetStub { - public UnwindExceptionToCallerStub(HotSpotProviders providers, TargetDescription target, HotSpotForeignCallLinkage linkage) { - super("unwindExceptionToCaller", providers, target, linkage); + public UnwindExceptionToCallerStub(HotSpotProviders providers, HotSpotForeignCallLinkage linkage) { + super("unwindExceptionToCaller", providers, linkage); } /** diff -r 31fac91ea3b7 -r 14e703edb2ab graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/VerifyOopStub.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/VerifyOopStub.java Wed Mar 11 17:16:30 2015 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/VerifyOopStub.java Wed Mar 11 20:43:12 2015 +0100 @@ -24,7 +24,6 @@ import static com.oracle.graal.hotspot.stubs.StubUtil.*; -import com.oracle.graal.api.code.*; import com.oracle.graal.hotspot.*; import com.oracle.graal.hotspot.meta.*; import com.oracle.graal.replacements.*; @@ -34,8 +33,8 @@ */ public class VerifyOopStub extends SnippetStub { - public VerifyOopStub(HotSpotProviders providers, TargetDescription target, HotSpotForeignCallLinkage linkage) { - super("verifyOop", providers, target, linkage); + public VerifyOopStub(HotSpotProviders providers, HotSpotForeignCallLinkage linkage) { + super("verifyOop", providers, linkage); } @Snippet diff -r 31fac91ea3b7 -r 14e703edb2ab graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/word/HotSpotWordTypeRewriterPhase.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/word/HotSpotWordTypeRewriterPhase.java Wed Mar 11 17:16:30 2015 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/word/HotSpotWordTypeRewriterPhase.java Wed Mar 11 20:43:12 2015 +0100 @@ -34,44 +34,17 @@ import com.oracle.graal.hotspot.nodes.type.*; import com.oracle.graal.hotspot.word.HotSpotOperation.HotspotOpcode; import com.oracle.graal.nodes.*; -import com.oracle.graal.nodes.HeapAccess.*; +import com.oracle.graal.nodes.HeapAccess.BarrierType; import com.oracle.graal.nodes.calc.*; import com.oracle.graal.nodes.extended.*; import com.oracle.graal.nodes.java.*; -import com.oracle.graal.nodes.type.*; -import com.oracle.graal.word.*; -import com.oracle.graal.word.Word.*; +import com.oracle.graal.word.Word.Operation; import com.oracle.graal.word.phases.*; public class HotSpotWordTypeRewriterPhase extends WordTypeRewriterPhase { - private final ResolvedJavaType klassPointerType; - private final ResolvedJavaType methodPointerType; - public HotSpotWordTypeRewriterPhase(MetaAccessProvider metaAccess, SnippetReflectionProvider snippetReflection, ConstantReflectionProvider constantReflection, Kind wordKind) { - super(metaAccess, snippetReflection, constantReflection, wordKind); - this.klassPointerType = metaAccess.lookupJavaType(KlassPointer.class); - this.methodPointerType = metaAccess.lookupJavaType(MethodPointer.class); - } - - @Override - protected void changeToWord(StructuredGraph graph, ValueNode node) { - ResolvedJavaType baseType = StampTool.typeOrNull(node); - if (baseType != null && baseType.equals(klassPointerType)) { - node.setStamp(KlassPointerStamp.klass()); - } else if (baseType != null && baseType.equals(methodPointerType)) { - node.setStamp(MethodPointerStamp.method()); - } else { - super.changeToWord(graph, node); - } - } - - @Override - protected Kind asKind(JavaType type) { - if (type.equals(klassPointerType) || type.equals(methodPointerType)) { - return wordKind; - } - return super.asKind(type); + super(metaAccess, snippetReflection, constantReflection, new HotSpotWordTypes(metaAccess, wordKind)); } @Override @@ -86,17 +59,16 @@ } } + /** + * Intrinsification of methods that are annotated with {@link Operation} or + * {@link HotSpotOperation}. + */ @Override protected void rewriteInvoke(StructuredGraph graph, MethodCallTargetNode callTargetNode) { ResolvedJavaMethod targetMethod = callTargetNode.targetMethod(); HotSpotOperation operation = targetMethod.getAnnotation(HotSpotOperation.class); if (operation == null) { - Operation wordOperation = targetMethod.getAnnotation(Word.Operation.class); - if (wordOperation != null) { - super.rewriteWordOperation(graph, callTargetNode, targetMethod); - } else { - super.rewriteInvoke(graph, callTargetNode); - } + super.rewriteInvoke(graph, callTargetNode); } else { Invoke invoke = callTargetNode.invoke(); NodeInputList arguments = callTargetNode.arguments(); @@ -115,7 +87,7 @@ case FROM_POINTER: assert arguments.size() == 1; - replace(invoke, graph.unique(new PointerCastNode(StampFactory.forKind(wordKind), arguments.get(0)))); + replace(invoke, graph.unique(new PointerCastNode(StampFactory.forKind(wordTypes.getWordKind()), arguments.get(0)))); break; case TO_KLASS_POINTER: diff -r 31fac91ea3b7 -r 14e703edb2ab graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/word/HotSpotWordTypes.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/word/HotSpotWordTypes.java Wed Mar 11 20:43:12 2015 +0100 @@ -0,0 +1,82 @@ +/* + * Copyright (c) 2012, 2014, 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.hotspot.word; + +import com.oracle.graal.api.meta.*; +import com.oracle.graal.compiler.common.type.*; +import com.oracle.graal.hotspot.nodes.type.*; +import com.oracle.graal.word.phases.*; + +/** + * Extends {@link WordTypes} with information about HotSpot metaspace pointer types. + */ +public class HotSpotWordTypes extends WordTypes { + + /** + * Resolved type for {@link MetaspacePointer}. + */ + private final ResolvedJavaType metaspacePointerType; + + /** + * Resolved type for {@link KlassPointer}. + */ + private final ResolvedJavaType klassPointerType; + + /** + * Resolved type for {@link MethodPointer}. + */ + private final ResolvedJavaType methodPointerType; + + public HotSpotWordTypes(MetaAccessProvider metaAccess, Kind wordKind) { + super(metaAccess, wordKind); + this.metaspacePointerType = metaAccess.lookupJavaType(MetaspacePointer.class); + this.klassPointerType = metaAccess.lookupJavaType(KlassPointer.class); + this.methodPointerType = metaAccess.lookupJavaType(MethodPointer.class); + } + + @Override + public boolean isWord(ResolvedJavaType type) { + if (type != null && metaspacePointerType.isAssignableFrom(type)) { + return true; + } + return super.isWord(type); + } + + @Override + public Kind asKind(JavaType type) { + if (klassPointerType.equals(type) || methodPointerType.equals(type)) { + return getWordKind(); + } + return super.asKind(type); + } + + @Override + public Stamp getWordStamp(ResolvedJavaType type) { + if (type.equals(klassPointerType)) { + return KlassPointerStamp.klass(); + } else if (type.equals(methodPointerType)) { + return MethodPointerStamp.method(); + } + return super.getWordStamp(type); + } +} diff -r 31fac91ea3b7 -r 14e703edb2ab graal/com.oracle.graal.java/src/com/oracle/graal/java/AbstractBytecodeParser.java --- a/graal/com.oracle.graal.java/src/com/oracle/graal/java/AbstractBytecodeParser.java Wed Mar 11 17:16:30 2015 +0100 +++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/AbstractBytecodeParser.java Wed Mar 11 20:43:12 2015 +0100 @@ -26,31 +26,138 @@ import static com.oracle.graal.api.code.TypeCheckHints.*; import static com.oracle.graal.api.meta.DeoptimizationReason.*; import static com.oracle.graal.bytecode.Bytecodes.*; - +import static com.oracle.graal.java.AbstractBytecodeParser.Options.*; import java.util.*; import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; +import com.oracle.graal.api.replacements.*; import com.oracle.graal.bytecode.*; import com.oracle.graal.compiler.common.*; import com.oracle.graal.compiler.common.calc.*; import com.oracle.graal.debug.*; import com.oracle.graal.java.BciBlockMapping.BciBlock; +import com.oracle.graal.java.GraphBuilderPhase.Instance.BytecodeParser; import com.oracle.graal.java.GraphBuilderPlugin.LoadFieldPlugin; +import com.oracle.graal.java.GraphBuilderPlugin.LoadIndexedPlugin; import com.oracle.graal.nodes.*; import com.oracle.graal.options.*; import com.oracle.graal.phases.*; public abstract class AbstractBytecodeParser { - static class Options { + public static class Options { // @formatter:off @Option(help = "The trace level for the bytecode parser used when building a graph from bytecode", type = OptionType.Debug) public static final OptionValue TraceBytecodeParserLevel = new OptionValue<>(0); + + @Option(help = "Inlines trivial methods during parsing of the bytecodes.", type = OptionType.Expert) + public static final StableOptionValue InlineDuringParsing = new StableOptionValue<>(false); + + @Option(help = "Traces inlining eagerly performed during bytecode parsing", type = OptionType.Debug) + public static final StableOptionValue TraceInlineDuringParsing = new StableOptionValue<>(false); + + @Option(help = "Traces use of bytecode parser plugins", type = OptionType.Debug) + public static final StableOptionValue TraceParserPlugins = new StableOptionValue<>(false); + + @Option(help = "Maximum depth when inlining during parsing.", type = OptionType.Debug) + public static final StableOptionValue InlineDuringParsingMaxDepth = new StableOptionValue<>(10); + // @formatter:on } /** + * Information about a substitute method being parsed in lieu of an original method. This can + * happen when a call to a {@link MethodSubstitution} is encountered or the root of compilation + * is a {@link MethodSubstitution} or a snippet. + */ + static class ReplacementContext { + /** + * The method being replaced. + */ + final ResolvedJavaMethod method; + + /** + * The replacement method. + */ + final ResolvedJavaMethod replacement; + + public ReplacementContext(ResolvedJavaMethod method, ResolvedJavaMethod substitute) { + this.method = method; + this.replacement = substitute; + } + + /** + * Determines if a call within the compilation scope of a replacement represents a call to + * the original method. + */ + public boolean isCallToOriginal(ResolvedJavaMethod targetMethod) { + return method.equals(targetMethod) || replacement.equals(targetMethod); + } + + IntrinsicContext asIntrinsic() { + return null; + } + } + + /** + * Context for a replacement being inlined as a compiler intrinsic. Deoptimization within a + * compiler intrinic must replay the intrinsified call. This context object retains the + * information required to build a frame state denoting the JVM state just before the + * intrinsified call. + */ + static class IntrinsicContext extends ReplacementContext { + + /** + * The arguments to the intrinsified invocation. + */ + private final ValueNode[] invokeArgs; + + /** + * The BCI of the intrinsified invocation. + */ + private final int invokeBci; + + private FrameState invokeStateBefore; + private FrameState invokeStateDuring; + + public IntrinsicContext(ResolvedJavaMethod method, ResolvedJavaMethod substitute, ValueNode[] invokeArgs, int invokeBci) { + super(method, substitute); + this.invokeArgs = invokeArgs; + this.invokeBci = invokeBci; + } + + /** + * Gets the frame state that will restart the interpreter just before the intrinsified + * invocation. + */ + public FrameState getInvokeStateBefore(BytecodeParser parent) { + assert !parent.parsingReplacement() || parent.replacementContext instanceof IntrinsicContext; + if (invokeStateDuring == null) { + assert invokeStateBefore == null; + // Find the ancestor calling the replaced method + BytecodeParser ancestor = parent; + while (ancestor.parsingReplacement()) { + ancestor = ancestor.getParent(); + } + invokeStateDuring = ancestor.getFrameState().create(ancestor.bci(), ancestor.getParent(), true); + invokeStateBefore = invokeStateDuring.duplicateModifiedBeforeCall(invokeBci, Kind.Void, invokeArgs); + } + return invokeStateBefore; + } + + public FrameState getInvokeStateDuring() { + assert invokeStateDuring != null : "must only be called after getInvokeStateBefore()"; + return invokeStateDuring; + } + + @Override + IntrinsicContext asIntrinsic() { + return this; + } + } + + /** * The minimum value to which {@link Options#TraceBytecodeParserLevel} must be set to trace the * bytecode instructions as they are parsed. */ @@ -73,18 +180,15 @@ protected final ConstantPool constantPool; protected final MetaAccessProvider metaAccess; - /** - * Specifies if the {@linkplain #getMethod() method} being parsed implements the semantics of - * another method (i.e., an intrinsic) or bytecode instruction (i.e., a snippet). substitution. - */ - protected final boolean parsingReplacement; + protected final ReplacementContext replacementContext; /** * Meters the number of actual bytecodes parsed. */ public static final DebugMetric BytecodesParsed = Debug.metric("BytecodesParsed"); - public AbstractBytecodeParser(MetaAccessProvider metaAccess, ResolvedJavaMethod method, GraphBuilderConfiguration graphBuilderConfig, OptimisticOptimizations optimisticOpts, boolean isReplacement) { + public AbstractBytecodeParser(MetaAccessProvider metaAccess, ResolvedJavaMethod method, GraphBuilderConfiguration graphBuilderConfig, OptimisticOptimizations optimisticOpts, + ReplacementContext replacementContext) { this.graphBuilderConfig = graphBuilderConfig; this.optimisticOpts = optimisticOpts; this.metaAccess = metaAccess; @@ -92,7 +196,7 @@ this.profilingInfo = (graphBuilderConfig.getUseProfiling() ? method.getProfilingInfo() : null); this.constantPool = method.getConstantPool(); this.method = method; - this.parsingReplacement = isReplacement; + this.replacementContext = replacementContext; assert metaAccess != null; } @@ -104,7 +208,7 @@ return stream; } - protected int bci() { + public int bci() { return stream.currentBCI(); } @@ -117,11 +221,11 @@ if (kind == Kind.Object) { value = frameState.xpop(); // astore and astore_ may be used to store a returnAddress (jsr) - assert parsingReplacement || (value.getKind() == Kind.Object || value.getKind() == Kind.Int) : value + ":" + value.getKind(); + assert parsingReplacement() || (value.getKind() == Kind.Object || value.getKind() == Kind.Int) : value + ":" + value.getKind(); } else { value = frameState.pop(kind); } - frameState.storeLocal(index, value); + frameState.storeLocal(index, value, kind); } /** @@ -202,11 +306,28 @@ protected abstract ValueNode genLoadIndexed(ValueNode index, ValueNode array, Kind kind); private void genLoadIndexed(Kind kind) { + emitExplicitExceptions(frameState.peek(1), frameState.peek(0)); ValueNode index = frameState.ipop(); ValueNode array = frameState.apop(); - frameState.push(kind.getStackKind(), append(genLoadIndexed(array, index, kind))); + if (!tryLoadIndexedPlugin(kind, index, array)) { + frameState.push(kind.getStackKind(), append(genLoadIndexed(array, index, kind))); + } + } + + protected abstract void traceWithContext(String format, Object... args); + + protected boolean tryLoadIndexedPlugin(Kind kind, ValueNode index, ValueNode array) { + LoadIndexedPlugin loadIndexedPlugin = graphBuilderConfig.getPlugins().getLoadIndexedPlugin(); + if (loadIndexedPlugin != null && loadIndexedPlugin.apply((GraphBuilderContext) this, array, index, kind)) { + if (TraceParserPlugins.getValue()) { + traceWithContext("used load indexed plugin"); + } + return true; + } else { + return false; + } } protected abstract ValueNode genStoreIndexed(ValueNode array, ValueNode index, Kind kind, ValueNode value); @@ -515,14 +636,14 @@ protected abstract void genThrow(); protected JavaType lookupType(int cpi, int bytecode) { - eagerResolvingForSnippets(cpi, bytecode); + maybeEagerlyResolve(cpi, bytecode); JavaType result = constantPool.lookupType(cpi, bytecode); assert !graphBuilderConfig.unresolvedIsError() || result instanceof ResolvedJavaType; return result; } private JavaMethod lookupMethod(int cpi, int opcode) { - eagerResolvingForSnippets(cpi, opcode); + maybeEagerlyResolve(cpi, opcode); JavaMethod result = constantPool.lookupMethod(cpi, opcode); /* * In general, one cannot assume that the declaring class being initialized is useful, since @@ -535,27 +656,27 @@ } private JavaField lookupField(int cpi, int opcode) { - eagerResolvingForSnippets(cpi, opcode); + maybeEagerlyResolve(cpi, opcode); JavaField result = constantPool.lookupField(cpi, opcode); assert !graphBuilderConfig.unresolvedIsError() || (result instanceof ResolvedJavaField && ((ResolvedJavaField) result).getDeclaringClass().isInitialized()) : result; return result; } private Object lookupConstant(int cpi, int opcode) { - eagerResolvingForSnippets(cpi, opcode); + maybeEagerlyResolve(cpi, opcode); Object result = constantPool.lookupConstant(cpi); assert !graphBuilderConfig.eagerResolving() || !(result instanceof JavaType) || (result instanceof ResolvedJavaType) : result; return result; } - private void eagerResolvingForSnippets(int cpi, int bytecode) { - if (graphBuilderConfig.eagerResolving()) { + private void maybeEagerlyResolve(int cpi, int bytecode) { + if (graphBuilderConfig.eagerResolving() || parsingReplacement()) { constantPool.loadReferencedType(cpi, bytecode); } } private JavaTypeProfile getProfileForTypeCheck(ResolvedJavaType type) { - if (parsingReplacement || profilingInfo == null || !optimisticOpts.useTypeCheckHints() || !canHaveSubtype(type)) { + if (parsingReplacement() || profilingInfo == null || !optimisticOpts.useTypeCheckHints() || !canHaveSubtype(type)) { return null; } else { return profilingInfo.getTypeProfile(bci()); @@ -747,6 +868,10 @@ } } + public boolean tryLoadFieldPlugin(JavaField field, LoadFieldPlugin loadFieldPlugin) { + return loadFieldPlugin.apply((GraphBuilderContext) this, (ResolvedJavaField) field); + } + private void genPutStatic(JavaField field) { ValueNode value = frameState.pop(field.getKind().getStackKind()); if (field instanceof ResolvedJavaField && ((ResolvedJavaType) field.getDeclaringClass()).isInitialized()) { @@ -776,7 +901,7 @@ protected abstract void genInvokeSpecial(JavaMethod target); - protected abstract void genReturn(ValueNode x); + protected abstract void genReturn(ValueNode x, Kind kind); protected abstract ValueNode genMonitorEnter(ValueNode x); @@ -1118,12 +1243,12 @@ case RET : genRet(stream.readLocalIndex()); break; case TABLESWITCH : genSwitch(new BytecodeTableSwitch(getStream(), bci())); break; case LOOKUPSWITCH : genSwitch(new BytecodeLookupSwitch(getStream(), bci())); break; - case IRETURN : genReturn(frameState.ipop()); break; - case LRETURN : genReturn(frameState.lpop()); break; - case FRETURN : genReturn(frameState.fpop()); break; - case DRETURN : genReturn(frameState.dpop()); break; - case ARETURN : genReturn(frameState.apop()); break; - case RETURN : genReturn(null); break; + case IRETURN : genReturn(frameState.ipop(), Kind.Int); break; + case LRETURN : genReturn(frameState.lpop(), Kind.Long); break; + case FRETURN : genReturn(frameState.fpop(), Kind.Float); break; + case DRETURN : genReturn(frameState.dpop(), Kind.Double); break; + case ARETURN : genReturn(frameState.apop(), Kind.Object); break; + case RETURN : genReturn(null, Kind.Void); break; case GETSTATIC : cpi = stream.readCPI(); genGetStatic(lookupField(cpi, opcode)); break; case PUTSTATIC : cpi = stream.readCPI(); genPutStatic(lookupField(cpi, opcode)); break; case GETFIELD : cpi = stream.readCPI(); genGetField(lookupField(cpi, opcode)); break; @@ -1192,4 +1317,8 @@ } Debug.log("%s", sb); } + + public boolean parsingReplacement() { + return replacementContext != null; + } } diff -r 31fac91ea3b7 -r 14e703edb2ab graal/com.oracle.graal.java/src/com/oracle/graal/java/AbstractFrameStateBuilder.java --- a/graal/com.oracle.graal.java/src/com/oracle/graal/java/AbstractFrameStateBuilder.java Wed Mar 11 17:16:30 2015 +0100 +++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/AbstractFrameStateBuilder.java Wed Mar 11 20:43:12 2015 +0100 @@ -26,6 +26,7 @@ import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; import com.oracle.graal.java.BciBlockMapping.BciBlock; +import com.oracle.graal.java.GraphBuilderPhase.Instance.BytecodeParser; public abstract class AbstractFrameStateBuilder> { @@ -35,32 +36,29 @@ protected final T[] stack; protected T[] lockedObjects; - /** - * Specifies if asserting type checks are enabled. - */ - protected final boolean checkTypes; + protected final BytecodeParser parser; /** * @see BytecodeFrame#rethrowException */ protected boolean rethrowException; - public AbstractFrameStateBuilder(ResolvedJavaMethod method, boolean checkTypes) { + public AbstractFrameStateBuilder(ResolvedJavaMethod method, BytecodeParser parser) { this.method = method; + this.parser = parser; this.locals = allocateArray(method.getMaxLocals()); this.stack = allocateArray(Math.max(1, method.getMaxStackSize())); this.lockedObjects = allocateArray(0); - this.checkTypes = checkTypes; } protected AbstractFrameStateBuilder(S other) { this.method = other.method; + this.parser = other.parser; this.stackSize = other.stackSize; this.locals = other.locals.clone(); this.stack = other.stack.clone(); this.lockedObjects = other.lockedObjects.length == 0 ? other.lockedObjects : other.lockedObjects.clone(); this.rethrowException = other.rethrowException; - this.checkTypes = other.checkTypes; assert locals.length == method.getMaxLocals(); assert stack.length == Math.max(1, method.getMaxStackSize()); @@ -178,11 +176,15 @@ public T loadLocal(int i) { T x = locals[i]; assert x != null : i; - assert !checkTypes || (x.getKind().getSlotCount() == 1 || locals[i + 1] == null); - assert !checkTypes || (i == 0 || locals[i - 1] == null || locals[i - 1].getKind().getSlotCount() == 1); + assert parser.parsingReplacement() || (x.getKind().getSlotCount() == 1 || locals[i + 1] == null); + assert parser.parsingReplacement() || (i == 0 || locals[i - 1] == null || locals[i - 1].getKind().getSlotCount() == 1); return x; } + public void storeLocal(int i, T x) { + storeLocal(i, x, x == null ? null : x.getKind()); + } + /** * Stores a given local variable at the specified index. If the value occupies two slots, then * the next local variable index is also overwritten. @@ -190,18 +192,20 @@ * @param i the index at which to store * @param x the instruction which produces the value for the local */ - public void storeLocal(int i, T x) { - assert x == null || !checkTypes || (x.getKind() != Kind.Void && x.getKind() != Kind.Illegal) : "unexpected value: " + x; + public void storeLocal(int i, T x, Kind kind) { + assert x == null || parser.parsingReplacement() || (x.getKind() != Kind.Void && x.getKind() != Kind.Illegal) : "unexpected value: " + x; locals[i] = x; - if (x != null && x.getKind().needsTwoSlots()) { - // if this is a double word, then kill i+1 - locals[i + 1] = null; - } - if (x != null && i > 0) { - T p = locals[i - 1]; - if (p != null && p.getKind().needsTwoSlots()) { - // if there was a double word at i - 1, then kill it - locals[i - 1] = null; + if (x != null) { + if (kind.needsTwoSlots() && !parser.parsingReplacement()) { + // if this is a double word, then kill i+1 + locals[i + 1] = null; + } + if (i > 0 && !parser.parsingReplacement()) { + T p = locals[i - 1]; + if (p != null && p.getKind().needsTwoSlots()) { + // if there was a double word at i - 1, then kill it + locals[i - 1] = null; + } } } } @@ -218,7 +222,7 @@ * @param x the instruction to push onto the stack */ public void push(Kind kind, T x) { - assert !checkTypes || (x.getKind() != Kind.Void && x.getKind() != Kind.Illegal) : x; + assert kind != Kind.Void && kind != Kind.Illegal : kind + ":" + x; xpush(assertKind(kind, x)); if (kind.needsTwoSlots()) { xpush(null); @@ -231,7 +235,7 @@ * @param x the instruction to push onto the stack */ public void xpush(T x) { - assert !checkTypes || (x == null || (x.getKind() != Kind.Void && x.getKind() != Kind.Illegal)); + assert parser.parsingReplacement() || (x == null || (x.getKind() != Kind.Void && x.getKind() != Kind.Illegal)); stack[stackSize++] = x; } @@ -375,7 +379,7 @@ newStackSize--; assert stack[newStackSize].getKind().needsTwoSlots(); } else { - assert !checkTypes || (stack[newStackSize].getKind().getSlotCount() == 1); + assert parser.parsingReplacement() || (stack[newStackSize].getKind().getSlotCount() == 1); } result[i] = stack[newStackSize]; } @@ -411,7 +415,7 @@ } private T assertKind(Kind kind, T x) { - assert x != null && (!checkTypes || x.getKind() == kind) : "kind=" + kind + ", value=" + x + ((x == null) ? "" : ", value.kind=" + x.getKind()); + assert x != null && (parser.parsingReplacement() || x.getKind() == kind) : "kind=" + kind + ", value=" + x + ((x == null) ? "" : ", value.kind=" + x.getKind()); return x; } @@ -431,7 +435,7 @@ } private T assertObject(T x) { - assert x != null && (!checkTypes || (x.getKind() == Kind.Object)); + assert x != null && (parser.parsingReplacement() || (x.getKind() == Kind.Object)); return x; } diff -r 31fac91ea3b7 -r 14e703edb2ab graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderConfiguration.java --- a/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderConfiguration.java Wed Mar 11 17:16:30 2015 +0100 +++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderConfiguration.java Wed Mar 11 20:43:12 2015 +0100 @@ -29,6 +29,7 @@ import com.oracle.graal.java.GraphBuilderPlugin.GenericInvocationPlugin; import com.oracle.graal.java.GraphBuilderPlugin.InlineInvokePlugin; import com.oracle.graal.java.GraphBuilderPlugin.LoadFieldPlugin; +import com.oracle.graal.java.GraphBuilderPlugin.LoadIndexedPlugin; import com.oracle.graal.java.GraphBuilderPlugin.LoopExplosionPlugin; import com.oracle.graal.java.GraphBuilderPlugin.ParameterPlugin; import com.oracle.graal.nodes.*; @@ -38,6 +39,7 @@ public static class Plugins { private InvocationPlugins invocationPlugins; private LoadFieldPlugin loadFieldPlugin; + private LoadIndexedPlugin loadIndexedPlugin; private ParameterPlugin parameterPlugin; private InlineInvokePlugin inlineInvokePlugin; private GenericInvocationPlugin genericInvocationPlugin; @@ -71,6 +73,14 @@ this.loadFieldPlugin = plugin; } + public LoadIndexedPlugin getLoadIndexedPlugin() { + return loadIndexedPlugin; + } + + public void setLoadIndexedPlugin(LoadIndexedPlugin plugin) { + this.loadIndexedPlugin = plugin; + } + public ParameterPlugin getParameterPlugin() { return parameterPlugin; } @@ -101,6 +111,7 @@ } this.parameterPlugin = other.parameterPlugin; this.loadFieldPlugin = other.loadFieldPlugin; + this.loadIndexedPlugin = other.loadIndexedPlugin; this.inlineInvokePlugin = other.inlineInvokePlugin; this.loopExplosionPlugin = other.loopExplosionPlugin; this.genericInvocationPlugin = other.genericInvocationPlugin; diff -r 31fac91ea3b7 -r 14e703edb2ab graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderContext.java --- a/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderContext.java Wed Mar 11 17:16:30 2015 +0100 +++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderContext.java Wed Mar 11 20:43:12 2015 +0100 @@ -27,7 +27,6 @@ import com.oracle.graal.api.replacements.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.calc.*; -import com.oracle.graal.nodes.extended.*; import com.oracle.graal.nodes.spi.*; /** @@ -65,12 +64,28 @@ GraphBuilderContext getParent(); /** - * Gets the inline depth of this context. 0 implies this is the context for the root method. + * Gets the root method for the graph building process. + */ + ResolvedJavaMethod getRootMethod(); + + /** + * Gets the method currently being parsed. + */ + ResolvedJavaMethod getMethod(); + + /** + * Gets the index of the bytecode instruction currently being parsed. + */ + int bci(); + + /** + * Gets the inline depth of this context. 0 implies this is the context for the + * {@linkplain #getRootMethod() root method}. */ int getDepth(); /** - * Determines if the graph builder is parsing a snippet or method substitution. + * Determines if the current parsing context is a snippet or method substitution. */ boolean parsingReplacement(); @@ -85,7 +100,7 @@ return nonNullValue; } - GuardingNode getCurrentBlockGuard(); + boolean eagerResolving(); BailoutException bailout(String string); } diff -r 31fac91ea3b7 -r 14e703edb2ab graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPhase.java --- a/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPhase.java Wed Mar 11 17:16:30 2015 +0100 +++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPhase.java Wed Mar 11 20:43:12 2015 +0100 @@ -27,6 +27,7 @@ import static com.oracle.graal.bytecode.Bytecodes.*; import static com.oracle.graal.compiler.common.GraalOptions.*; import static com.oracle.graal.graph.iterators.NodePredicates.*; +import static com.oracle.graal.java.AbstractBytecodeParser.Options.*; import static com.oracle.graal.nodes.StructuredGraph.*; import static java.lang.String.*; @@ -40,17 +41,20 @@ import com.oracle.graal.compiler.common.calc.*; import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.debug.*; -import com.oracle.graal.debug.Debug.*; +import com.oracle.graal.debug.Debug.Scope; import com.oracle.graal.graph.Graph.Mark; import com.oracle.graal.graph.*; import com.oracle.graal.graph.Node.ValueNumberable; import com.oracle.graal.graph.iterators.*; +import com.oracle.graal.java.AbstractBytecodeParser.ReplacementContext; import com.oracle.graal.java.BciBlockMapping.BciBlock; import com.oracle.graal.java.BciBlockMapping.ExceptionDispatchBlock; import com.oracle.graal.java.GraphBuilderPlugin.GenericInvocationPlugin; import com.oracle.graal.java.GraphBuilderPlugin.InlineInvokePlugin; +import com.oracle.graal.java.GraphBuilderPlugin.InlineInvokePlugin.InlineInfo; import com.oracle.graal.java.GraphBuilderPlugin.InvocationPlugin; import com.oracle.graal.java.GraphBuilderPlugin.LoopExplosionPlugin; +import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.CallTargetNode.InvokeKind; import com.oracle.graal.nodes.calc.*; @@ -75,7 +79,7 @@ @Override protected void run(StructuredGraph graph, HighTierContext context) { - new Instance(context.getMetaAccess(), context.getStampProvider(), null, context.getConstantReflection(), graphBuilderConfig, context.getOptimisticOptimizations(), false).run(graph); + new Instance(context.getMetaAccess(), context.getStampProvider(), null, context.getConstantReflection(), graphBuilderConfig, context.getOptimisticOptimizations(), null).run(graph); } public GraphBuilderConfiguration getGraphBuilderConfig() { @@ -89,7 +93,13 @@ private final MetaAccessProvider metaAccess; private ResolvedJavaMethod rootMethod; - private final boolean rootMethodIsReplacement; + + /** + * If not null, then this indicates {@link #rootMethod} is a replacement or a snippet. + * Furthermore, if it is non-null and not equal to {@link #rootMethod} then this is the + * original method for which a snippet exists (e.g., System.arraycopy()). + */ + private final ResolvedJavaMethod rootMethodIsReplacement; private final GraphBuilderConfiguration graphBuilderConfig; private final OptimisticOptimizations optimisticOpts; @@ -97,15 +107,8 @@ private final ConstantReflectionProvider constantReflection; private final SnippetReflectionProvider snippetReflectionProvider; - /** - * Gets the graph being processed by this builder. - */ - protected StructuredGraph getGraph() { - return currentGraph; - } - public Instance(MetaAccessProvider metaAccess, StampProvider stampProvider, SnippetReflectionProvider snippetReflectionProvider, ConstantReflectionProvider constantReflection, - GraphBuilderConfiguration graphBuilderConfig, OptimisticOptimizations optimisticOpts, boolean rootMethodIsReplacement) { + GraphBuilderConfiguration graphBuilderConfig, OptimisticOptimizations optimisticOpts, ResolvedJavaMethod rootMethodIsReplacement) { this.graphBuilderConfig = graphBuilderConfig; this.optimisticOpts = optimisticOpts; this.metaAccess = metaAccess; @@ -117,7 +120,7 @@ } public Instance(MetaAccessProvider metaAccess, StampProvider stampProvider, ConstantReflectionProvider constantReflection, GraphBuilderConfiguration graphBuilderConfig, - OptimisticOptimizations optimisticOpts, boolean rootMethodIsReplacement) { + OptimisticOptimizations optimisticOpts, ResolvedJavaMethod rootMethodIsReplacement) { this(metaAccess, stampProvider, null, constantReflection, graphBuilderConfig, optimisticOpts, rootMethodIsReplacement); } @@ -128,11 +131,12 @@ int entryBCI = graph.getEntryBCI(); assert method.getCode() != null : "method must contain bytecodes: " + method; this.currentGraph = graph; - HIRFrameStateBuilder frameState = new HIRFrameStateBuilder(method, graph, true, null); - frameState.initializeForMethodStart(graphBuilderConfig.eagerResolving(), this.graphBuilderConfig.getPlugins().getParameterPlugin()); TTY.Filter filter = new TTY.Filter(PrintFilter.getValue(), method); try { - BytecodeParser parser = new BytecodeParser(null, metaAccess, method, graphBuilderConfig, optimisticOpts, entryBCI, rootMethodIsReplacement); + ReplacementContext replacementContext = rootMethodIsReplacement != null ? new ReplacementContext(rootMethodIsReplacement, rootMethod) : null; + BytecodeParser parser = new BytecodeParser(null, metaAccess, method, graphBuilderConfig, optimisticOpts, entryBCI, replacementContext); + HIRFrameStateBuilder frameState = new HIRFrameStateBuilder(parser, method, graph); + frameState.initializeForMethodStart(graphBuilderConfig.eagerResolving() || rootMethodIsReplacement != null, graphBuilderConfig.getPlugins().getParameterPlugin()); parser.build(graph.start(), frameState); parser.connectLoopEndToBegin(); @@ -146,11 +150,15 @@ } // Remove redundant begin nodes. + Debug.dump(graph, "Before removing redundant begins"); for (BeginNode beginNode : currentGraph.getNodes(BeginNode.TYPE)) { Node predecessor = beginNode.predecessor(); if (predecessor instanceof ControlSplitNode) { // The begin node is necessary. } else { + if (beginNode.hasUsages()) { + reanchorGuardedNodes(beginNode); + } GraphUtil.unlinkFixedNode(beginNode); beginNode.safeDelete(); } @@ -162,6 +170,36 @@ ComputeLoopFrequenciesClosure.compute(graph); } + /** + * Removes {@link GuardedNode}s from {@code beginNode}'s usages and re-attaches them to an + * appropriate preceeding {@link GuardingNode}. + */ + protected void reanchorGuardedNodes(BeginNode beginNode) { + // Find the new guarding node + GuardingNode guarding = null; + Node pred = beginNode.predecessor(); + while (pred != null) { + if (pred instanceof BeginNode) { + if (pred.predecessor() instanceof ControlSplitNode) { + guarding = (GuardingNode) pred; + break; + } + } else if (pred.getNodeClass().getAllowedUsageTypes().contains(InputType.Guard)) { + guarding = (GuardingNode) pred; + break; + } + pred = pred.predecessor(); + } + + // Reset the guard for all of beginNode's usages + for (Node usage : beginNode.usages().snapshot()) { + GuardedNode guarded = (GuardedNode) usage; + assert guarded.getGuard() == beginNode; + guarded.setGuard(guarding); + } + assert beginNode.hasNoUsages() : beginNode; + } + @Override protected String getDetailedName() { return getName() + " " + rootMethod.format("%H.%n(%p):%r"); @@ -184,6 +222,18 @@ private int peelIteration; } + @SuppressWarnings("serial") + public class BytecodeParserError extends GraalInternalError { + + public BytecodeParserError(Throwable cause) { + super(cause); + } + + public BytecodeParserError(String msg, Object... args) { + super(msg, args); + } + } + public class BytecodeParser extends AbstractBytecodeParser implements GraphBuilderContext { private BciBlockMapping blockMap; @@ -215,14 +265,9 @@ private FixedWithNextNode[][] firstInstructionMatrix; private HIRFrameStateBuilder[][] entryStateMatrix; - /** - * @param isReplacement specifies if this object is being used to parse a method that - * implements the semantics of another method (i.e., an intrinsic) or - * bytecode instruction (i.e., a snippet) - */ public BytecodeParser(BytecodeParser parent, MetaAccessProvider metaAccess, ResolvedJavaMethod method, GraphBuilderConfiguration graphBuilderConfig, - OptimisticOptimizations optimisticOpts, int entryBCI, boolean isReplacement) { - super(metaAccess, method, graphBuilderConfig, optimisticOpts, isReplacement); + OptimisticOptimizations optimisticOpts, int entryBCI, ReplacementContext replacementContext) { + super(metaAccess, method, graphBuilderConfig, optimisticOpts, replacementContext); this.entryBCI = entryBCI; this.parent = parent; @@ -528,7 +573,6 @@ if (Debug.isDumpEnabled() && DumpDuringGraphBuilding.getValue()) { Debug.dump(currentGraph, "before loop explosion dimension " + context.peelIteration); } - peelIteration(blocks, header, context); explodeLoopsContext.pop(); return header.loopEnd + 1; @@ -540,6 +584,9 @@ private void peelIteration(BciBlock[] blocks, BciBlock header, ExplodedLoopContext context) { while (true) { + if (TraceParserPlugins.getValue()) { + traceWithContext("exploding loop, iteration %d", context.peelIteration); + } processBlock(this, header); int j = header.getId() + 1; while (j <= header.loopEnd) { @@ -1049,7 +1096,7 @@ } JavaType returnType = targetMethod.getSignature().getReturnType(method.getDeclaringClass()); - if (graphBuilderConfig.eagerResolving()) { + if (graphBuilderConfig.eagerResolving() || parsingReplacement()) { returnType = returnType.resolve(targetMethod.getDeclaringClass()); } if (invokeKind.hasReceiver()) { @@ -1060,16 +1107,16 @@ } } - if (tryInvocationPlugin(args, targetMethod, resultType)) { - if (GraalOptions.TraceInlineDuringParsing.getValue()) { - TTY.println(format("%sUsed invocation plugin for %s", nSpaces(getDepth()), targetMethod)); + if (tryGenericInvocationPlugin(args, targetMethod)) { + if (TraceParserPlugins.getValue()) { + traceWithContext("used generic invocation plugin for %s", targetMethod.format("%h.%n(%p)")); } return; } - if (tryAnnotatedInvocationPlugin(args, targetMethod)) { - if (GraalOptions.TraceInlineDuringParsing.getValue()) { - TTY.println(format("%sUsed annotated invocation plugin for %s", nSpaces(getDepth()), targetMethod)); + if (tryInvocationPlugin(args, targetMethod, resultType)) { + if (TraceParserPlugins.getValue()) { + traceWithContext("used invocation plugin for %s", targetMethod.format("%h.%n(%p)")); } return; } @@ -1082,14 +1129,23 @@ // be conservative if information was not recorded (could result in endless // recompiles otherwise) + Invoke invoke; if (graphBuilderConfig.omitAllExceptionEdges() || (optimisticOpts.useExceptionProbability() && profilingInfo != null && profilingInfo.getExceptionSeen(bci()) == TriState.FALSE)) { - createInvoke(callTarget, resultType); + invoke = createInvoke(callTarget, resultType); } else { - InvokeWithExceptionNode invoke = createInvokeWithException(callTarget, resultType); + invoke = createInvokeWithException(callTarget, resultType); AbstractBeginNode beginNode = currentGraph.add(new KillingBeginNode(LocationIdentity.ANY_LOCATION)); invoke.setNext(beginNode); lastInstr = beginNode; } + + InlineInvokePlugin plugin = graphBuilderConfig.getPlugins().getInlineInvokePlugin(); + if (plugin != null) { + if (TraceParserPlugins.getValue()) { + traceWithContext("did not inline %s", targetMethod.format("%h.%n(%p)")); + } + plugin.notifyOfNoninlinedInvoke(this, targetMethod, invoke); + } } private boolean tryInvocationPlugin(ValueNode[] args, ResolvedJavaMethod targetMethod, Kind resultType) { @@ -1099,10 +1155,11 @@ boolean needsNullCheck = !targetMethod.isStatic() && args[0].getKind() == Kind.Object && !StampTool.isPointerNonNull(args[0].stamp()); int nodeCount = currentGraph.getNodeCount(); Mark mark = needsNullCheck ? currentGraph.getMark() : null; - if (InvocationPlugin.execute(this, plugin, args)) { + if (InvocationPlugin.execute(this, targetMethod, plugin, args)) { assert beforeStackSize + resultType.getSlotCount() == frameState.stackSize : "plugin manipulated the stack incorrectly " + targetMethod; - assert !needsNullCheck || args[0].usages().filter(isNotA(FrameState.class)).isEmpty() || containsNullCheckOf(currentGraph.getNewNodes(mark), args[0]) : "plugin needs to null check the receiver of " + - targetMethod + ": " + args[0]; + assert !needsNullCheck || args[0].usages().filter(isNotA(FrameState.class)).isEmpty() || containsNullCheckOf(currentGraph.getNewNodes(mark), args[0]) : format( + "plugin needs to null check the receiver of %s: receiver=%s%n\tplugin at %s", targetMethod.format("%H.%n(%p)"), args[0], + plugin.getApplySourceLocation(metaAccess)); return true; } assert nodeCount == currentGraph.getNodeCount() : "plugin that returns false must not create new nodes"; @@ -1111,7 +1168,7 @@ return false; } - private boolean tryAnnotatedInvocationPlugin(ValueNode[] args, ResolvedJavaMethod targetMethod) { + private boolean tryGenericInvocationPlugin(ValueNode[] args, ResolvedJavaMethod targetMethod) { GenericInvocationPlugin plugin = graphBuilderConfig.getPlugins().getGenericInvocationPlugin(); return plugin != null && plugin.apply(this, targetMethod, args); } @@ -1133,36 +1190,84 @@ if (plugin == null || !invokeKind.isDirect() || !targetMethod.canBeInlined()) { return false; } - ResolvedJavaMethod inlinedMethod = plugin.getInlinedMethod(this, targetMethod, args, returnType); - if (inlinedMethod != null) { - if (TraceInlineDuringParsing.getValue()) { - int bci = this.bci(); - StackTraceElement ste = this.method.asStackTraceElement(bci); - TTY.println(format("%s%s (%s:%d) inlining call to %s", nSpaces(getDepth()), method.getName(), ste.getFileName(), ste.getLineNumber(), inlinedMethod.format("%h.%n(%p)"))); - } - parseAndInlineCallee(inlinedMethod, args, parsingReplacement || inlinedMethod != targetMethod); - plugin.postInline(inlinedMethod); - return true; + InlineInfo inlineInfo = plugin.getInlineInfo(this, targetMethod, args, returnType); + if (inlineInfo != null) { + return inline(plugin, targetMethod, inlineInfo, args); } - return false; } - private void parseAndInlineCallee(ResolvedJavaMethod targetMethod, ValueNode[] args, boolean isReplacement) { - BytecodeParser parser = new BytecodeParser(this, metaAccess, targetMethod, graphBuilderConfig, optimisticOpts, INVOCATION_ENTRY_BCI, isReplacement); - final FrameState[] lazyFrameState = new FrameState[1]; + boolean inline(InlineInvokePlugin plugin, ResolvedJavaMethod targetMethod, InlineInfo inlineInfo, ValueNode[] args) { + int bci = bci(); + ResolvedJavaMethod inlinedMethod = inlineInfo.methodToInline; + if (TraceInlineDuringParsing.getValue() || TraceParserPlugins.getValue()) { + if (targetMethod.equals(inlinedMethod)) { + traceWithContext("inlining call to %s", inlinedMethod.format("%h.%n(%p)")); + } else { + traceWithContext("inlining call to %s as replacement for %s", inlinedMethod.format("%h.%n(%p)"), targetMethod.format("%h.%n(%p)")); + } + } + ReplacementContext context = this.replacementContext; + if (context != null && context.isCallToOriginal(targetMethod)) { + // Self recursive replacement means the original + // method should be called. + if (targetMethod.hasBytecodes()) { + parseAndInlineCallee(context.method, args, null); + } else { + return false; + } + } else { + if (context == null && !inlinedMethod.equals(targetMethod)) { + if (inlineInfo.adoptBeforeCallFrameState) { + context = new IntrinsicContext(targetMethod, inlinedMethod, args, bci); + } else { + context = new ReplacementContext(targetMethod, inlinedMethod); + } + } + parseAndInlineCallee(inlinedMethod, args, context); + if (plugin != null) { + plugin.postInline(inlinedMethod); + } + } + return true; + } - // Replacements often produce nodes with an illegal kind (e.g., pointer stamps) - // so the frame state builder should not check the types flowing through the frame - // since all such assertions are in terms of Java kinds. - boolean checkTypes = !isReplacement; + /** + * Prints a line to {@link TTY} with a prefix indicating the current parse context. The + * prefix is of the form: + * + *
+             * {SPACE * n} {name of method being parsed} "(" {file name} ":" {line number} ")"
+             * 
+ * + * where {@code n} is the current inlining depth. + * + * @param format a format string + * @param args arguments to the format string + */ + @Override + protected void traceWithContext(String format, Object... args) { + StackTraceElement where = method.asStackTraceElement(bci()); + TTY.println(format("%s%s (%s:%d) %s", nSpaces(getDepth()), method.isConstructor() ? method.format("%h.%n") : method.getName(), where.getFileName(), where.getLineNumber(), + format(format, args))); + } - HIRFrameStateBuilder startFrameState = new HIRFrameStateBuilder(targetMethod, currentGraph, checkTypes, () -> { - if (lazyFrameState[0] == null) { - lazyFrameState[0] = createFrameState(bci()); - } - return lazyFrameState[0]; - }); + protected BytecodeParserError asParserError(Throwable e) { + if (e instanceof BytecodeParserError) { + return (BytecodeParserError) e; + } + BytecodeParser bp = this; + BytecodeParserError res = new BytecodeParserError(e); + while (bp != null) { + res.addContext("parsing " + bp.method.asStackTraceElement(bp.bci())); + bp = bp.parent; + } + return res; + } + + private void parseAndInlineCallee(ResolvedJavaMethod targetMethod, ValueNode[] args, ReplacementContext calleeReplacementContext) { + BytecodeParser parser = new BytecodeParser(this, metaAccess, targetMethod, graphBuilderConfig, optimisticOpts, INVOCATION_ENTRY_BCI, calleeReplacementContext); + HIRFrameStateBuilder startFrameState = new HIRFrameStateBuilder(parser, targetMethod, currentGraph); startFrameState.initializeFromArgumentsArray(args); parser.build(this.lastInstr, startFrameState); @@ -1171,7 +1276,7 @@ if (calleeBeforeReturnNode != null) { ValueNode calleeReturnValue = parser.getReturnValue(); if (calleeReturnValue != null) { - frameState.push(calleeReturnValue.getKind().getStackKind(), calleeReturnValue); + frameState.push(targetMethod.getSignature().getReturnKind().getStackKind(), calleeReturnValue); } } @@ -1207,25 +1312,25 @@ } @Override - protected void genReturn(ValueNode x) { + protected void genReturn(ValueNode returnVal, Kind returnKind) { if (parent == null) { frameState.setRethrowException(false); frameState.clearStack(); - beforeReturn(x); - append(new ReturnNode(x)); + beforeReturn(returnVal, returnKind); + append(new ReturnNode(returnVal)); } else { if (blockMap.getReturnCount() == 1 || !controlFlowSplit) { // There is only a single return. - beforeReturn(x); - this.returnValue = x; + beforeReturn(returnVal, returnKind); + this.returnValue = returnVal; this.beforeReturnNode = this.lastInstr; this.lastInstr = null; } else { frameState.setRethrowException(false); frameState.clearStack(); - if (x != null) { - frameState.push(x.getKind(), x); + if (returnVal != null) { + frameState.push(returnKind, returnVal); } assert blockMap.getReturnCount() > 1; appendGoto(blockMap.getReturnBlock()); @@ -1233,12 +1338,12 @@ } } - private void beforeReturn(ValueNode x) { + private void beforeReturn(ValueNode x, Kind kind) { if (graphBuilderConfig.insertNonSafepointDebugInfo()) { append(createInfoPointNode(InfopointReason.METHOD_END)); } - synchronizedEpilogue(BytecodeFrame.AFTER_BCI, x); + synchronizedEpilogue(BytecodeFrame.AFTER_BCI, x, kind); if (frameState.lockDepth() != 0) { throw bailout("unbalanced monitors"); } @@ -1589,7 +1694,11 @@ * the loop begin node created before. */ LoopBeginNode loopBegin = (LoopBeginNode) getFirstInstruction(block, operatingDimension); - Target target = checkLoopExit(currentGraph.add(new LoopEndNode(loopBegin)), block, state); + LoopEndNode loopEnd = currentGraph.add(new LoopEndNode(loopBegin)); + if (parsingReplacement()) { + loopEnd.disableSafepoint(); + } + Target target = checkLoopExit(loopEnd, block, state); FixedNode result = target.fixed; getEntryState(block, operatingDimension).merge(loopBegin, target.state); @@ -1674,7 +1783,7 @@ } context.targetPeelIteration[context.targetPeelIteration.length - 1] = nextPeelIteration++; if (nextPeelIteration > MaximumLoopExplosionCount.getValue()) { - String message = "too many loop explosion interations - does the explosion not terminate for method " + method + "?"; + String message = "too many loop explosion iterations - does the explosion not terminate for method " + method + "?"; if (FailedLoopExplosionIsFatal.getValue()) { throw new RuntimeException(message); } else { @@ -1762,7 +1871,7 @@ Kind returnKind = method.getSignature().getReturnKind().getStackKind(); ValueNode x = returnKind == Kind.Void ? null : frameState.pop(returnKind); assert frameState.stackSize() == 0; - beforeReturn(x); + beforeReturn(x, returnKind); this.returnValue = x; this.beforeReturnNode = this.lastInstr; } @@ -1805,15 +1914,15 @@ private void createUnwind() { assert frameState.stackSize() == 1 : frameState; ValueNode exception = frameState.apop(); - synchronizedEpilogue(BytecodeFrame.AFTER_EXCEPTION_BCI, null); + synchronizedEpilogue(BytecodeFrame.AFTER_EXCEPTION_BCI, null, null); append(new UnwindNode(exception)); } - private void synchronizedEpilogue(int bci, ValueNode currentReturnValue) { + private void synchronizedEpilogue(int bci, ValueNode currentReturnValue, Kind currentReturnValueKind) { if (method.isSynchronized()) { MonitorExitNode monitorExit = genMonitorExit(methodSynchronizedObject, currentReturnValue); if (currentReturnValue != null) { - frameState.push(currentReturnValue.getKind(), currentReturnValue); + frameState.push(currentReturnValueKind, currentReturnValue); } monitorExit.setStateAfter(createFrameState(bci)); assert !frameState.rethrowException(); @@ -1936,7 +2045,12 @@ frameState.insertProxies(x); x.setStateAfter(createFrameState(bci)); } - processBytecode(bci, opcode); + + try { + processBytecode(bci, opcode); + } catch (Throwable e) { + throw asParserError(e); + } if (lastInstr == null || isBlockEnd(lastInstr) || lastInstr.next() != null) { break; @@ -2094,6 +2208,13 @@ FixedNode falseSuccessor = createTarget(falseBlock, frameState, false, true); ValueNode ifNode = genIfNode(condition, trueSuccessor, falseSuccessor, probability); append(ifNode); + if (parsingReplacement()) { + if (x instanceof BranchProbabilityNode) { + ((BranchProbabilityNode) x).simplify(null); + } else if (y instanceof BranchProbabilityNode) { + ((BranchProbabilityNode) y).simplify(null); + } + } } } @@ -2116,7 +2237,8 @@ conditionalNode = currentGraph.addOrUnique(conditionalNode); } if (genReturn) { - this.genReturn(conditionalNode); + Kind returnKind = method.getSignature().getReturnKind().getStackKind(); + this.genReturn(conditionalNode, returnKind); } else { frameState.push(Kind.Int, conditionalNode); appendGoto(trueBlock.getSuccessor(0)); @@ -2212,20 +2334,14 @@ return snippetReflectionProvider; } - public boolean parsingReplacement() { - return parsingReplacement; - } - + /** + * Gets the graph being processed by this builder. + */ public StructuredGraph getGraph() { - return currentGraph; } - public GuardingNode getCurrentBlockGuard() { - return (GuardingNode) getFirstInstruction(currentBlock, getCurrentDimension()); - } - - public GraphBuilderContext getParent() { + public BytecodeParser getParent() { return parent; } @@ -2233,6 +2349,14 @@ return parent == null ? 0 : 1 + parent.getDepth(); } + public ResolvedJavaMethod getRootMethod() { + return rootMethod; + } + + public boolean eagerResolving() { + return graphBuilderConfig.eagerResolving(); + } + @Override public String toString() { Formatter fmt = new Formatter(); @@ -2242,7 +2366,7 @@ if (bp != this) { fmt.format("%n%s", indent); } - fmt.format("%s replacement=%s", bp.method.asStackTraceElement(bp.bci()), parsingReplacement); + fmt.format("%s [bci: %d, replacement: %s]", bp.method.asStackTraceElement(bp.bci()), bci(), bp.parsingReplacement()); bp = bp.parent; indent += " "; } diff -r 31fac91ea3b7 -r 14e703edb2ab graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPlugin.java --- a/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPlugin.java Wed Mar 11 17:16:30 2015 +0100 +++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPlugin.java Wed Mar 11 20:43:12 2015 +0100 @@ -22,8 +22,13 @@ */ package com.oracle.graal.java; +import java.lang.reflect.*; + import com.oracle.graal.api.meta.*; import com.oracle.graal.compiler.common.*; +import com.oracle.graal.compiler.common.type.*; +import com.oracle.graal.java.GraphBuilderPhase.Instance.BytecodeParser; +import com.oracle.graal.java.GraphBuilderPlugin.InlineInvokePlugin.InlineInfo; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.calc.*; @@ -34,7 +39,7 @@ public interface LoadFieldPlugin extends GraphBuilderPlugin { @SuppressWarnings("unused") - default boolean apply(GraphBuilderContext builder, ValueNode receiver, ResolvedJavaField field) { + default boolean apply(GraphBuilderContext b, ValueNode receiver, ResolvedJavaField field) { return false; } @@ -43,38 +48,77 @@ return false; } - default boolean tryConstantFold(GraphBuilderContext builder, MetaAccessProvider metaAccess, ConstantReflectionProvider constantReflection, ResolvedJavaField field, JavaConstant asJavaConstant) { - JavaConstant result = constantReflection.readConstantFieldValue(field, asJavaConstant); + default boolean tryConstantFold(GraphBuilderContext b, MetaAccessProvider metaAccess, ConstantReflectionProvider constantReflection, ResolvedJavaField field, JavaConstant receiver) { + JavaConstant result = constantReflection.readConstantFieldValue(field, receiver); if (result != null) { - ConstantNode constantNode = builder.append(ConstantNode.forConstant(result, metaAccess)); - builder.push(constantNode.getKind().getStackKind(), constantNode); + ConstantNode constantNode = b.append(ConstantNode.forConstant(result, metaAccess)); + b.push(constantNode.getKind().getStackKind(), constantNode); return true; } return false; } } + public interface LoadIndexedPlugin extends GraphBuilderPlugin { + @SuppressWarnings("unused") + default boolean apply(GraphBuilderContext b, ValueNode array, ValueNode index, Kind elementKind) { + return false; + } + } + /** - * Plugin for specifying what is inlined during graph parsing. + * Plugin for specifying what is inlined during graph parsing or for post-processing non-inlined + * invocations that result in {@link Invoke} nodes. */ public interface InlineInvokePlugin extends GraphBuilderPlugin { + public static class InlineInfo { + + /** + * The method to be inlined. If this is not equal to the {@code method} argument passed + * to {@link InlineInvokePlugin#getClass()}, the graph builder context interprets it as + * a {@linkplain GraphBuilderContext#parsingReplacement() replacement}. + */ + public final ResolvedJavaMethod methodToInline; + + /** + * Specifies if {@link #methodToInline} is an intrinsic for the original method. If so, + * any {@link StateSplit} node created in the (recursive) inlining scope will be given a + * frame state that restarts the interpreter just before the intrinsified invocation. + */ + public final boolean adoptBeforeCallFrameState; + + public InlineInfo(ResolvedJavaMethod methodToInline, boolean adoptBeforeCallFrameState) { + this.methodToInline = methodToInline; + this.adoptBeforeCallFrameState = adoptBeforeCallFrameState; + } + } + /** - * Gets the method to be inlined for a call to a given method. A non-null return value other - * than {@code method} is interpreted as a - * {@linkplain GraphBuilderContext#parsingReplacement() replacement} by the graph builder - * context used for inlining it. + * Determines whether a call to a given method is to be inlined. * * @param method the target method of an invoke * @param args the arguments to the invoke * @param returnType the return type derived from {@code method}'s signature - * @return the method to inline for a call to {@code method} or null if the call should not - * be inlined + */ + default InlineInfo getInlineInfo(@SuppressWarnings("unused") GraphBuilderContext b, ResolvedJavaMethod method, ValueNode[] args, JavaType returnType) { + return null; + } + + /** + * @param inlinedTargetMethod */ - ResolvedJavaMethod getInlinedMethod(GraphBuilderContext builder, ResolvedJavaMethod method, ValueNode[] args, JavaType returnType); + default void postInline(ResolvedJavaMethod inlinedTargetMethod) { + } - default void postInline(@SuppressWarnings("unused") ResolvedJavaMethod inlinedTargetMethod) { - + /** + * Notifies this plugin of the {@link Invoke} node created for a method that was not inlined + * per {@link #getInlineInfo}. + * + * @param method the method that was not inlined + * @param invoke the invoke node created for the call to {@code method} + */ + default void notifyOfNoninlinedInvoke(@SuppressWarnings("unused") GraphBuilderContext b, ResolvedJavaMethod method, Invoke invoke) { } } @@ -85,7 +129,7 @@ } public interface ParameterPlugin extends GraphBuilderPlugin { - FloatingNode interceptParameter(int index); + FloatingNode interceptParameter(GraphBuilderContext b, int index, Stamp stamp); } /** @@ -98,7 +142,7 @@ * * @return {@code true} if this plugin handled the invocation, {@code false} if not */ - boolean apply(GraphBuilderContext builder, ResolvedJavaMethod method, ValueNode[] args); + boolean apply(GraphBuilderContext b, ResolvedJavaMethod method, ValueNode[] args); } /** @@ -106,67 +150,99 @@ */ public interface InvocationPlugin extends GraphBuilderPlugin { /** - * @see #execute(GraphBuilderContext, InvocationPlugin, ValueNode[]) + * @see #execute */ - default boolean apply(GraphBuilderContext builder) { - throw invalidHandler(builder); + default boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod) { + throw invalidHandler(b, targetMethod); + } + + /** + * @see #execute + */ + default boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, ValueNode arg) { + throw invalidHandler(b, targetMethod, arg); } /** - * @see #execute(GraphBuilderContext, InvocationPlugin, ValueNode[]) + * @see #execute */ - default boolean apply(GraphBuilderContext builder, ValueNode arg) { - throw invalidHandler(builder, arg); + default boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, ValueNode arg1, ValueNode arg2) { + throw invalidHandler(b, targetMethod, arg1, arg2); } /** - * @see #execute(GraphBuilderContext, InvocationPlugin, ValueNode[]) + * @see #execute */ - default boolean apply(GraphBuilderContext builder, ValueNode arg1, ValueNode arg2) { - throw invalidHandler(builder, arg1, arg2); + default boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, ValueNode arg1, ValueNode arg2, ValueNode arg3) { + throw invalidHandler(b, targetMethod, arg1, arg2, arg3); } /** - * @see #execute(GraphBuilderContext, InvocationPlugin, ValueNode[]) + * @see #execute */ - default boolean apply(GraphBuilderContext builder, ValueNode arg1, ValueNode arg2, ValueNode arg3) { - throw invalidHandler(builder, arg1, arg2, arg3); + default boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, ValueNode arg1, ValueNode arg2, ValueNode arg3, ValueNode arg4) { + throw invalidHandler(b, targetMethod, arg1, arg2, arg3, arg4); } /** - * @see #execute(GraphBuilderContext, InvocationPlugin, ValueNode[]) + * @see #execute */ - default boolean apply(GraphBuilderContext builder, ValueNode arg1, ValueNode arg2, ValueNode arg3, ValueNode arg4) { - throw invalidHandler(builder, arg1, arg2, arg3, arg4); + default boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, ValueNode arg1, ValueNode arg2, ValueNode arg3, ValueNode arg4, ValueNode arg5) { + throw invalidHandler(b, targetMethod, arg1, arg2, arg3, arg4, arg5); } + default ResolvedJavaMethod getSubstitute() { + return null; + } + + boolean ALLOW_INVOCATION_PLUGIN_TO_DO_INLINING = false; + /** * Executes a given plugin against a set of invocation arguments by dispatching to the - * plugin's {@code apply(...)} method that matches the number of arguments. + * {@code apply(...)} method that matches the number of arguments. * - * @return {@code true} if the plugin handled the invocation, {@code false} if the graph - * builder should process the invoke further (e.g., by inlining it or creating an - * {@link Invoke} node). A plugin that does not handle an invocation must not modify - * the graph being constructed. + * @param targetMethod the method for which plugin is being applied + * @return {@code true} if the plugin handled the invocation of {@code targetMethod} + * {@code false} if the graph builder should process the invoke further (e.g., by + * inlining it or creating an {@link Invoke} node). A plugin that does not handle an + * invocation must not modify the graph being constructed. */ - static boolean execute(GraphBuilderContext builder, InvocationPlugin plugin, ValueNode[] args) { + static boolean execute(GraphBuilderContext b, ResolvedJavaMethod targetMethod, InvocationPlugin plugin, ValueNode[] args) { + if (ALLOW_INVOCATION_PLUGIN_TO_DO_INLINING) { + ResolvedJavaMethod subst = plugin.getSubstitute(); + if (subst != null) { + return ((BytecodeParser) b).inline(null, targetMethod, new InlineInfo(subst, false), args); + } + } if (args.length == 0) { - return plugin.apply(builder); + return plugin.apply(b, targetMethod); } else if (args.length == 1) { - return plugin.apply(builder, args[0]); + return plugin.apply(b, targetMethod, args[0]); } else if (args.length == 2) { - return plugin.apply(builder, args[0], args[1]); + return plugin.apply(b, targetMethod, args[0], args[1]); } else if (args.length == 3) { - return plugin.apply(builder, args[0], args[1], args[2]); + return plugin.apply(b, targetMethod, args[0], args[1], args[2]); } else if (args.length == 4) { - return plugin.apply(builder, args[0], args[1], args[2], args[3]); + return plugin.apply(b, targetMethod, args[0], args[1], args[2], args[3]); + } else if (args.length == 5) { + return plugin.apply(b, targetMethod, args[0], args[1], args[2], args[3], args[4]); } else { - throw plugin.invalidHandler(builder, args); + throw plugin.invalidHandler(b, targetMethod, args); } } - default Error invalidHandler(@SuppressWarnings("unused") GraphBuilderContext builder, ValueNode... args) { - return new GraalInternalError("Invocation plugin %s does not handle invocations with %d arguments", getClass().getSimpleName(), args.length); + default Error invalidHandler(@SuppressWarnings("unused") GraphBuilderContext b, ResolvedJavaMethod targetMethod, ValueNode... args) { + return new GraalInternalError("Invocation plugin for %s does not handle invocations with %d arguments", targetMethod.format("%H.%n(%p)"), args.length); + } + + default StackTraceElement getApplySourceLocation(MetaAccessProvider metaAccess) { + Class c = getClass(); + for (Method m : c.getDeclaredMethods()) { + if (m.getName().equals("apply")) { + return metaAccess.lookupJavaMethod(m).asStackTraceElement(0); + } + } + throw new GraalInternalError("could not find method named \"apply\" in " + c.getName()); } } } diff -r 31fac91ea3b7 -r 14e703edb2ab graal/com.oracle.graal.java/src/com/oracle/graal/java/HIRFrameStateBuilder.java --- a/graal/com.oracle.graal.java/src/com/oracle/graal/java/HIRFrameStateBuilder.java Wed Mar 11 17:16:30 2015 +0100 +++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/HIRFrameStateBuilder.java Wed Mar 11 20:43:12 2015 +0100 @@ -25,13 +25,15 @@ import static com.oracle.graal.graph.iterators.NodePredicates.*; import java.util.*; -import java.util.function.*; import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; +import com.oracle.graal.compiler.common.*; import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.debug.*; -import com.oracle.graal.java.BciBlockMapping.*; +import com.oracle.graal.java.AbstractBytecodeParser.IntrinsicContext; +import com.oracle.graal.java.BciBlockMapping.BciBlock; +import com.oracle.graal.java.GraphBuilderPhase.Instance.BytecodeParser; import com.oracle.graal.java.GraphBuilderPlugin.ParameterPlugin; import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; @@ -44,6 +46,7 @@ private static final ValueNode[] EMPTY_ARRAY = new ValueNode[0]; private static final MonitorIdNode[] EMPTY_MONITOR_ARRAY = new MonitorIdNode[0]; + protected final BytecodeParser parser; protected final ResolvedJavaMethod method; protected int stackSize; protected final ValueNode[] locals; @@ -51,18 +54,13 @@ protected ValueNode[] lockedObjects; /** - * Specifies if asserting type checks are enabled. - */ - protected final boolean checkTypes; - - /** * @see BytecodeFrame#rethrowException */ protected boolean rethrowException; private MonitorIdNode[] monitorIds; private final StructuredGraph graph; - private final Supplier outerFrameStateSupplier; + private FrameState outerFrameState; /** * Creates a new frame state builder for the given method and the given target graph. @@ -70,18 +68,17 @@ * @param method the method whose frame is simulated * @param graph the target graph of Graal nodes created by the builder */ - public HIRFrameStateBuilder(ResolvedJavaMethod method, StructuredGraph graph, boolean checkTypes, Supplier outerFrameStateSupplier) { + public HIRFrameStateBuilder(BytecodeParser parser, ResolvedJavaMethod method, StructuredGraph graph) { + this.parser = parser; this.method = method; this.locals = allocateArray(method.getMaxLocals()); this.stack = allocateArray(Math.max(1, method.getMaxStackSize())); this.lockedObjects = allocateArray(0); - this.checkTypes = checkTypes; assert graph != null; this.monitorIds = EMPTY_MONITOR_ARRAY; this.graph = graph; - this.outerFrameStateSupplier = outerFrameStateSupplier; } public void initializeFromArgumentsArray(ValueNode[] arguments) { @@ -97,8 +94,9 @@ Signature sig = method.getSignature(); int max = sig.getParameterCount(false); for (int i = 0; i < max; i++) { + Kind kind = sig.getParameterKind(i); locals[javaIndex] = arguments[index]; - javaIndex += arguments[index].getKind().getSlotCount(); + javaIndex += kind.getSlotCount(); index++; } } @@ -110,11 +108,12 @@ if (!method.isStatic()) { // add the receiver FloatingNode receiver = null; + Stamp receiverStamp = StampFactory.declaredNonNull(method.getDeclaringClass()); if (parameterPlugin != null) { - receiver = parameterPlugin.interceptParameter(index); + receiver = parameterPlugin.interceptParameter(parser, index, receiverStamp); } if (receiver == null) { - receiver = new ParameterNode(javaIndex, StampFactory.declaredNonNull(method.getDeclaringClass())); + receiver = new ParameterNode(javaIndex, receiverStamp); } locals[javaIndex] = graph.unique(receiver); javaIndex = 1; @@ -137,7 +136,7 @@ } FloatingNode param = null; if (parameterPlugin != null) { - param = parameterPlugin.interceptParameter(index); + param = parameterPlugin.interceptParameter(parser, index, stamp); } if (param == null) { param = new ParameterNode(index, stamp); @@ -149,13 +148,13 @@ } private HIRFrameStateBuilder(HIRFrameStateBuilder other) { + this.parser = other.parser; this.method = other.method; this.stackSize = other.stackSize; this.locals = other.locals.clone(); this.stack = other.stack.clone(); this.lockedObjects = other.lockedObjects.length == 0 ? other.lockedObjects : other.lockedObjects.clone(); this.rethrowException = other.rethrowException; - this.checkTypes = other.checkTypes; assert locals.length == method.getMaxLocals(); assert stack.length == Math.max(1, method.getMaxStackSize()); @@ -163,7 +162,6 @@ assert other.graph != null; graph = other.graph; monitorIds = other.monitorIds.length == 0 ? other.monitorIds : other.monitorIds.clone(); - this.outerFrameStateSupplier = other.outerFrameStateSupplier; assert locals.length == method.getMaxLocals(); assert stack.length == Math.max(1, method.getMaxStackSize()); @@ -198,15 +196,42 @@ } public FrameState create(int bci) { - FrameState outerFrameState = null; - if (outerFrameStateSupplier != null) { - outerFrameState = outerFrameStateSupplier.get(); - if (bci == BytecodeFrame.AFTER_EXCEPTION_BCI) { - FrameState newFrameState = outerFrameState.duplicateModified(outerFrameState.bci, true, Kind.Void, this.peek(0)); - return newFrameState; + BytecodeParser parent = parser.getParent(); + if (parser.parsingReplacement()) { + IntrinsicContext intrinsic = parser.replacementContext.asIntrinsic(); + if (intrinsic != null) { + assert parent != null : "intrinsics can only be processed in context of a caller"; + + // We're somewhere in an intrinsic. In this case, we want a frame state + // that will restart the interpreter just before the intrinsified + // invocation. + return intrinsic.getInvokeStateBefore(parent); } } - return graph.add(new FrameState(outerFrameState, method, bci, locals, stack, stackSize, lockedObjects, Arrays.asList(monitorIds), rethrowException, false)); + return create(bci, parent, false); + } + + public FrameState create(int bci, BytecodeParser parent, boolean duringCall) { + if (outerFrameState == null && parent != null) { + outerFrameState = parent.getFrameState().create(parent.bci()); + if (parser.parsingReplacement()) { + IntrinsicContext intrinsic = parser.replacementContext.asIntrinsic(); + if (intrinsic != null) { + // A side-effect of creating the frame state in a replacing + // parent is that the 'during' frame state is created as well + outerFrameState = intrinsic.getInvokeStateDuring(); + } + } + } + if (bci == BytecodeFrame.AFTER_EXCEPTION_BCI && parent != null) { + FrameState newFrameState = outerFrameState.duplicateModified(outerFrameState.bci, true, Kind.Void, this.peek(0)); + return newFrameState; + } + if (bci == BytecodeFrame.INVALID_FRAMESTATE_BCI) { + throw GraalInternalError.shouldNotReachHere(); + // return graph.add(new FrameState(bci)); + } + return graph.add(new FrameState(outerFrameState, method, bci, locals, stack, stackSize, lockedObjects, Arrays.asList(monitorIds), rethrowException, duringCall)); } public HIRFrameStateBuilder copy() { @@ -549,11 +574,15 @@ private boolean assertLoadLocal(int i, ValueNode x) { assert x != null : i; - assert !checkTypes || (x.getKind().getSlotCount() == 1 || locals[i + 1] == null); - assert !checkTypes || (i == 0 || locals[i - 1] == null || locals[i - 1].getKind().getSlotCount() == 1); + assert parser.parsingReplacement() || (x.getKind().getSlotCount() == 1 || locals[i + 1] == null); + assert parser.parsingReplacement() || (i == 0 || locals[i - 1] == null || locals[i - 1].getKind().getSlotCount() == 1); return true; } + public void storeLocal(int i, ValueNode x) { + storeLocal(i, x, x == null ? null : x.getKind()); + } + /** * Stores a given local variable at the specified index. If the value occupies two slots, then * the next local variable index is also overwritten. @@ -561,24 +590,26 @@ * @param i the index at which to store * @param x the instruction which produces the value for the local */ - public void storeLocal(int i, ValueNode x) { + public void storeLocal(int i, ValueNode x, Kind kind) { assert assertStoreLocal(x); locals[i] = x; - if (x != null && x.getKind().needsTwoSlots()) { - // if this is a double word, then kill i+1 - locals[i + 1] = null; - } - if (x != null && i > 0) { - ValueNode p = locals[i - 1]; - if (p != null && p.getKind().needsTwoSlots()) { - // if there was a double word at i - 1, then kill it - locals[i - 1] = null; + if (x != null) { + if (kind.needsTwoSlots() && !parser.parsingReplacement()) { + // if this is a double word, then kill i+1 + locals[i + 1] = null; + } + if (i > 0 && !parser.parsingReplacement()) { + ValueNode p = locals[i - 1]; + if (p != null && p.getKind().needsTwoSlots()) { + // if there was a double word at i - 1, then kill it + locals[i - 1] = null; + } } } } private boolean assertStoreLocal(ValueNode x) { - assert x == null || !checkTypes || (x.getKind() != Kind.Void && x.getKind() != Kind.Illegal) : "unexpected value: " + x; + assert x == null || parser.parsingReplacement() || (x.getKind() != Kind.Void && x.getKind() != Kind.Illegal) : "unexpected value: " + x; return true; } @@ -607,8 +638,8 @@ } private boolean assertPush(Kind kind, ValueNode x) { - assert !checkTypes || (x.getKind() != Kind.Void && x.getKind() != Kind.Illegal); - assert x != null && (!checkTypes || x.getKind() == kind); + assert parser.parsingReplacement() || (x.getKind() != Kind.Void && x.getKind() != Kind.Illegal); + assert x != null && (parser.parsingReplacement() || x.getKind() == kind); return true; } @@ -623,7 +654,7 @@ } private boolean assertXpush(ValueNode x) { - assert !checkTypes || (x == null || (x.getKind() != Kind.Void && x.getKind() != Kind.Illegal)); + assert parser.parsingReplacement() || (x == null || (x.getKind() != Kind.Void && x.getKind() != Kind.Illegal)); return true; } @@ -702,7 +733,7 @@ private boolean assertPop(Kind kind) { assert kind != Kind.Void; ValueNode x = xpeek(); - assert x != null && (!checkTypes || x.getKind() == kind); + assert x != null && (parser.parsingReplacement() || x.getKind() == kind); return true; } @@ -789,7 +820,7 @@ newStackSize--; assert stack[newStackSize].getKind().needsTwoSlots(); } else { - assert !checkTypes || (stack[newStackSize].getKind().getSlotCount() == 1); + assert parser.parsingReplacement() || (stack[newStackSize].getKind().getSlotCount() == 1); } result[i] = stack[newStackSize]; } @@ -856,7 +887,7 @@ } private boolean assertObject(ValueNode x) { - assert x != null && (!checkTypes || (x.getKind() == Kind.Object)); + assert x != null && (parser.parsingReplacement() || (x.getKind() == Kind.Object)); return true; } @@ -910,7 +941,7 @@ if (other.stackSize != stackSize) { return false; } - if (other.checkTypes != checkTypes) { + if (other.parser != parser) { return false; } if (other.rethrowException != rethrowException) { @@ -919,9 +950,6 @@ if (other.graph != graph) { return false; } - if (other.outerFrameStateSupplier != outerFrameStateSupplier) { - return false; - } if (other.locals.length != locals.length) { return false; } diff -r 31fac91ea3b7 -r 14e703edb2ab graal/com.oracle.graal.java/src/com/oracle/graal/java/InvocationPlugins.java --- a/graal/com.oracle.graal.java/src/com/oracle/graal/java/InvocationPlugins.java Wed Mar 11 17:16:30 2015 +0100 +++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/InvocationPlugins.java Wed Mar 11 20:43:12 2015 +0100 @@ -90,8 +90,7 @@ * @param plugin the plugin to be registered */ public void register1(String name, Class arg, InvocationPlugin plugin) { - ResolvedJavaMethod method = arg == Receiver.class ? resolve(metaAccess, declaringClass, name) : resolve(metaAccess, declaringClass, name, arg); - plugins.register(method, plugin); + plugins.register(arg == Receiver.class ? resolve(metaAccess, declaringClass, name) : resolve(metaAccess, declaringClass, name, arg), plugin); } /** @@ -101,8 +100,7 @@ * @param plugin the plugin to be registered */ public void register2(String name, Class arg1, Class arg2, InvocationPlugin plugin) { - ResolvedJavaMethod method = arg1 == Receiver.class ? resolve(metaAccess, declaringClass, name, arg2) : resolve(metaAccess, declaringClass, name, arg1, arg2); - plugins.register(method, plugin); + plugins.register(arg1 == Receiver.class ? resolve(metaAccess, declaringClass, name, arg2) : resolve(metaAccess, declaringClass, name, arg1, arg2), plugin); } /** @@ -112,8 +110,7 @@ * @param plugin the plugin to be registered */ public void register3(String name, Class arg1, Class arg2, Class arg3, InvocationPlugin plugin) { - ResolvedJavaMethod method = arg1 == Receiver.class ? resolve(metaAccess, declaringClass, name, arg2, arg3) : resolve(metaAccess, declaringClass, name, arg1, arg2, arg3); - plugins.register(method, plugin); + plugins.register(arg1 == Receiver.class ? resolve(metaAccess, declaringClass, name, arg2, arg3) : resolve(metaAccess, declaringClass, name, arg1, arg2, arg3), plugin); } /** @@ -123,8 +120,18 @@ * @param plugin the plugin to be registered */ public void register4(String name, Class arg1, Class arg2, Class arg3, Class arg4, InvocationPlugin plugin) { - ResolvedJavaMethod method = arg1 == Receiver.class ? resolve(metaAccess, declaringClass, name, arg2, arg3, arg4) : resolve(metaAccess, declaringClass, name, arg1, arg2, arg3, arg4); - plugins.register(method, plugin); + plugins.register(arg1 == Receiver.class ? resolve(metaAccess, declaringClass, name, arg2, arg3, arg4) : resolve(metaAccess, declaringClass, name, arg1, arg2, arg3, arg4), plugin); + } + + /** + * Registers a plugin for a method with 5 arguments. + * + * @param name the name of the method + * @param plugin the plugin to be registered + */ + public void register5(String name, Class arg1, Class arg2, Class arg3, Class arg4, Class arg5, InvocationPlugin plugin) { + plugins.register(arg1 == Receiver.class ? resolve(metaAccess, declaringClass, name, arg2, arg3, arg4, arg5) : resolve(metaAccess, declaringClass, name, arg1, arg2, arg3, arg4, arg5), + plugin); } /** @@ -197,21 +204,23 @@ } private static class Checker { + private static final int MAX_ARITY = 5; /** * The set of all {@link InvocationPlugin#apply} method signatures. */ static final Class[][] SIGS; static { - ArrayList[]> sigs = new ArrayList<>(5); + ArrayList[]> sigs = new ArrayList<>(MAX_ARITY); for (Method method : InvocationPlugin.class.getDeclaredMethods()) { if (!Modifier.isStatic(method.getModifiers()) && method.getName().equals("apply")) { Class[] sig = method.getParameterTypes(); assert sig[0] == GraphBuilderContext.class; - assert Arrays.asList(Arrays.copyOfRange(sig, 1, sig.length)).stream().allMatch(c -> c == ValueNode.class); - while (sigs.size() < sig.length) { + assert sig[1] == ResolvedJavaMethod.class; + assert Arrays.asList(Arrays.copyOfRange(sig, 2, sig.length)).stream().allMatch(c -> c == ValueNode.class); + while (sigs.size() < sig.length - 1) { sigs.add(null); } - sigs.set(sig.length - 1, sig); + sigs.set(sig.length - 2, sig); } } assert sigs.indexOf(null) == -1 : format("need to add an apply() method to %s that takes %d %s arguments ", InvocationPlugin.class.getName(), sigs.indexOf(null), diff -r 31fac91ea3b7 -r 14e703edb2ab graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/FrameState.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/FrameState.java Wed Mar 11 17:16:30 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/FrameState.java Wed Mar 11 20:43:12 2015 +0100 @@ -223,14 +223,23 @@ } /** - * Creates a copy of this frame state with one stack element of type popKind popped from the - * stack and the values in pushedValues pushed on the stack. The pushedValues will be formatted - * correctly in slot encoding: a long or double will be followed by a null slot. + * Creates a copy of this frame state with one stack element of type {@code popKind} popped from + * the stack. */ public FrameState duplicateModifiedDuringCall(int newBci, Kind popKind) { return duplicateModified(newBci, rethrowException, true, popKind); } + public FrameState duplicateModifiedBeforeCall(int newBci, Kind popKind, ValueNode... pushedValues) { + return duplicateModified(newBci, rethrowException, false, popKind, pushedValues); + } + + /** + * Creates a copy of this frame state with one stack element of type {@code popKind} popped from + * the stack and the values in {@code pushedValues} pushed on the stack. The + * {@code pushedValues} will be formatted correctly in slot encoding: a long or double will be + * followed by a null slot. + */ public FrameState duplicateModified(int newBci, boolean newRethrowException, Kind popKind, ValueNode... pushedValues) { return duplicateModified(newBci, newRethrowException, duringCall, popKind, pushedValues); } diff -r 31fac91ea3b7 -r 14e703edb2ab graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/GuardingPiNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/GuardingPiNode.java Wed Mar 11 17:16:30 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/GuardingPiNode.java Wed Mar 11 20:43:12 2015 +0100 @@ -147,19 +147,17 @@ } @NodeIntrinsic - public static T guardingNonNull(T object) { - if (object == null) { - throw new NullPointerException(); - } - return object; - } - - @NodeIntrinsic - public static native Object guardingPi(Object object, LogicNode condition, @ConstantNodeParameter boolean negateCondition, @ConstantNodeParameter DeoptimizationReason reason, - @ConstantNodeParameter DeoptimizationAction action, @ConstantNodeParameter Stamp stamp); + public static native Object guardingNonNull(Object object); @Override public ValueNode getOriginalNode() { return object; } + + /** + * Casts a value to have an exact, non-null stamp representing {@link Class} that is guarded by + * a null check. + */ + @NodeIntrinsic(GuardingPiNode.class) + public static native Class asNonNullClass(Class c); } diff -r 31fac91ea3b7 -r 14e703edb2ab graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/PiArrayNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/PiArrayNode.java Wed Mar 11 17:16:30 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/PiArrayNode.java Wed Mar 11 20:43:12 2015 +0100 @@ -59,5 +59,5 @@ } @NodeIntrinsic - public static native T piArrayCast(Object object, int length, @ConstantNodeParameter Stamp stamp); + public static native Object piArrayCast(Object object, int length, @ConstantNodeParameter Stamp stamp); } diff -r 31fac91ea3b7 -r 14e703edb2ab graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/PiNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/PiNode.java Wed Mar 11 17:16:30 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/PiNode.java Wed Mar 11 20:43:12 2015 +0100 @@ -34,12 +34,12 @@ import com.oracle.graal.nodes.type.*; /** - * A node that changes the type of its input, usually narrowing it. For example, a PiNode refines - * the type of a receiver during type-guarded inlining to be the type tested by the guard. + * A node that changes the type of its input, usually narrowing it. For example, a {@link PiNode} + * refines the type of a receiver during type-guarded inlining to be the type tested by the guard. * - * In contrast to a {@link GuardedValueNode}, a PiNode is useless as soon as the type of its input - * is as narrow or narrower than the PiNode's type. The PiNode, and therefore also the scheduling - * restriction enforced by the anchor, will go away. + * In contrast to a {@link GuardedValueNode}, a {@link PiNode} is useless as soon as the type of its + * input is as narrow or narrower than the {@link PiNode}'s type. The {@link PiNode}, and therefore + * also the scheduling restriction enforced by the anchor, will go away. */ @NodeInfo public class PiNode extends FloatingGuardedNode implements LIRLowerable, Virtualizable, IterableNodeType, Canonicalizable, ValueProxy { @@ -116,31 +116,37 @@ return object; } - @NodeIntrinsic - public static native T piCast(Object object, @ConstantNodeParameter Stamp stamp); - - @NodeIntrinsic - public static native T piCast(Object object, @ConstantNodeParameter Stamp stamp, GuardingNode anchor); - - public static T piCastExactNonNull(Object object, @ConstantNodeParameter Class toType) { - return piCast(object, toType, true, true); + /** + * Casts an object to have an exact, non-null stamp representing {@link Class}. + */ + public static Class asNonNullClass(Object object) { + return asNonNullClassIntrinsic(object, Class.class, true, true); } - public static T piCastExact(Object object, @ConstantNodeParameter Class toType) { - return piCast(object, toType, true, false); - } + @NodeIntrinsic(PiNode.class) + private static native Class asNonNullClassIntrinsic(Object object, @ConstantNodeParameter Class toType, @ConstantNodeParameter boolean exactType, @ConstantNodeParameter boolean nonNull); + + /** + * Changes the stamp of an object. + */ + @NodeIntrinsic + public static native Object piCast(Object object, @ConstantNodeParameter Stamp stamp); - public static T piCast(Object object, @ConstantNodeParameter Class toType) { - return piCast(object, toType, false, false); - } + /** + * Changes the stamp of an object and ensures the newly stamped value does float above a given + * anchor. + */ + @NodeIntrinsic + public static native Object piCast(Object object, @ConstantNodeParameter Stamp stamp, GuardingNode anchor); - public static T piCastNonNull(Object object, @ConstantNodeParameter Class toType) { + /** + * Changes the stamp of an object to represent a given type and to indicate that the object is + * not null. + */ + public static Object piCastNonNull(Object object, @ConstantNodeParameter Class toType) { return piCast(object, toType, false, true); } - @SuppressWarnings("unused") @NodeIntrinsic - private static T piCast(Object object, @ConstantNodeParameter Class toType, @ConstantNodeParameter boolean exactType, @ConstantNodeParameter boolean nonNull) { - return toType.cast(object); - } + public static native Object piCast(Object object, @ConstantNodeParameter Class toType, @ConstantNodeParameter boolean exactType, @ConstantNodeParameter boolean nonNull); } diff -r 31fac91ea3b7 -r 14e703edb2ab graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/AbsNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/AbsNode.java Wed Mar 11 17:16:30 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/AbsNode.java Wed Mar 11 20:43:12 2015 +0100 @@ -58,14 +58,4 @@ public void generate(NodeMappableLIRBuilder builder, ArithmeticLIRGenerator gen) { builder.setResult(this, gen.emitMathAbs(builder.operand(getValue()))); } - - @NodeIntrinsic - public static float abs(float n) { - return Math.abs(n); - } - - @NodeIntrinsic - public static double abs(double n) { - return Math.abs(n); - } } diff -r 31fac91ea3b7 -r 14e703edb2ab graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/ConditionalNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/ConditionalNode.java Wed Mar 11 17:16:30 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/ConditionalNode.java Wed Mar 11 20:43:12 2015 +0100 @@ -31,7 +31,6 @@ import com.oracle.graal.graph.spi.*; import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; -import com.oracle.graal.nodes.java.*; import com.oracle.graal.nodes.spi.*; /** @@ -141,42 +140,7 @@ generator.emitConditional(this); } - public ConditionalNode(@InjectedNodeParameter StructuredGraph graph, Condition condition, ValueNode x, ValueNode y) { + public ConditionalNode(StructuredGraph graph, Condition condition, ValueNode x, ValueNode y) { this(createCompareNode(graph, condition, x, y, null)); } - - public ConditionalNode(ValueNode type, ValueNode object) { - this(type.graph().unique(new InstanceOfDynamicNode(type, object))); - } - - @NodeIntrinsic - public static native boolean materializeCondition(@ConstantNodeParameter Condition condition, int x, int y); - - @NodeIntrinsic - public static native boolean materializeCondition(@ConstantNodeParameter Condition condition, long x, long y); - - @NodeIntrinsic - public static boolean materializeIsInstance(Class mirror, Object object) { - return mirror.isInstance(object); - } - - /** - * @param thisClass - * @param otherClass - * @param dummy a marker to make this constructor unique for the - * {@link #materializeIsAssignableFrom(Class, Class, int)} NodeIntrinsic - */ - public ConditionalNode(ValueNode thisClass, ValueNode otherClass, int dummy) { - this(thisClass.graph().unique(new ClassIsAssignableFromNode(thisClass, otherClass))); - } - - @SuppressWarnings("unused") - @NodeIntrinsic - private static boolean materializeIsAssignableFrom(Class thisClass, Class otherClass, @ConstantNodeParameter int dummy) { - return thisClass.isAssignableFrom(otherClass); - } - - public static boolean materializeIsAssignableFrom(Class thisClass, Class otherClass) { - return materializeIsAssignableFrom(thisClass, otherClass, 0); - } } diff -r 31fac91ea3b7 -r 14e703edb2ab graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IsNullNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IsNullNode.java Wed Mar 11 17:16:30 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IsNullNode.java Wed Mar 11 20:43:12 2015 +0100 @@ -51,7 +51,7 @@ @Override public boolean verify() { assertTrue(getValue() != null, "is null input must not be null"); - assertTrue(getValue().stamp() instanceof AbstractPointerStamp, "is null input must be a pointer"); + assertTrue(getValue().stamp() instanceof AbstractPointerStamp, "input must be a pointer not %s", getValue().stamp()); return super.verify(); } diff -r 31fac91ea3b7 -r 14e703edb2ab graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/SqrtNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/SqrtNode.java Wed Mar 11 17:16:30 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/SqrtNode.java Wed Mar 11 20:43:12 2015 +0100 @@ -46,9 +46,4 @@ public void generate(NodeMappableLIRBuilder builder, ArithmeticLIRGenerator gen) { builder.setResult(this, gen.emitMathSqrt(builder.operand(getValue()))); } - - @NodeIntrinsic - public static double sqrt(double n) { - return Math.sqrt(n); - } } diff -r 31fac91ea3b7 -r 14e703edb2ab graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/debug/BlackholeNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/debug/BlackholeNode.java Wed Mar 11 17:16:30 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/debug/BlackholeNode.java Wed Mar 11 20:43:12 2015 +0100 @@ -43,31 +43,4 @@ public void generate(NodeLIRBuilderTool gen) { gen.getLIRGeneratorTool().emitBlackhole(gen.operand(value)); } - - @NodeIntrinsic - public static native void consume(boolean v); - - @NodeIntrinsic - public static native void consume(byte v); - - @NodeIntrinsic - public static native void consume(short v); - - @NodeIntrinsic - public static native void consume(char v); - - @NodeIntrinsic - public static native void consume(int v); - - @NodeIntrinsic - public static native void consume(long v); - - @NodeIntrinsic - public static native void consume(float v); - - @NodeIntrinsic - public static native void consume(double v); - - @NodeIntrinsic - public static native void consume(Object v); } diff -r 31fac91ea3b7 -r 14e703edb2ab graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/debug/OpaqueNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/debug/OpaqueNode.java Wed Mar 11 17:16:30 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/debug/OpaqueNode.java Wed Mar 11 20:43:12 2015 +0100 @@ -47,31 +47,4 @@ public void generate(NodeLIRBuilderTool gen) { gen.setResult(this, gen.operand(value)); } - - @NodeIntrinsic - public static native boolean opaque(boolean v); - - @NodeIntrinsic - public static native byte opaque(byte v); - - @NodeIntrinsic - public static native short opaque(short v); - - @NodeIntrinsic - public static native char opaque(char v); - - @NodeIntrinsic - public static native int opaque(int v); - - @NodeIntrinsic - public static native long opaque(long v); - - @NodeIntrinsic - public static native float opaque(float v); - - @NodeIntrinsic - public static native double opaque(double v); - - @NodeIntrinsic - public static native T opaque(T v); } diff -r 31fac91ea3b7 -r 14e703edb2ab graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/BoxNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/BoxNode.java Wed Mar 11 17:16:30 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/BoxNode.java Wed Mar 11 20:43:12 2015 +0100 @@ -80,28 +80,4 @@ tool.createVirtualObject(newVirtual, new ValueNode[]{v}, Collections. emptyList()); tool.replaceWithVirtual(newVirtual); } - - @NodeIntrinsic - public static native Boolean box(boolean value, @ConstantNodeParameter Class clazz, @ConstantNodeParameter Kind kind); - - @NodeIntrinsic - public static native Byte box(byte value, @ConstantNodeParameter Class clazz, @ConstantNodeParameter Kind kind); - - @NodeIntrinsic - public static native Character box(char value, @ConstantNodeParameter Class clazz, @ConstantNodeParameter Kind kind); - - @NodeIntrinsic - public static native Double box(double value, @ConstantNodeParameter Class clazz, @ConstantNodeParameter Kind kind); - - @NodeIntrinsic - public static native Float box(float value, @ConstantNodeParameter Class clazz, @ConstantNodeParameter Kind kind); - - @NodeIntrinsic - public static native Integer box(int value, @ConstantNodeParameter Class clazz, @ConstantNodeParameter Kind kind); - - @NodeIntrinsic - public static native Long box(long value, @ConstantNodeParameter Class clazz, @ConstantNodeParameter Kind kind); - - @NodeIntrinsic - public static native Short box(short value, @ConstantNodeParameter Class clazz, @ConstantNodeParameter Kind kind); } diff -r 31fac91ea3b7 -r 14e703edb2ab graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/BranchProbabilityNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/BranchProbabilityNode.java Wed Mar 11 17:16:30 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/BranchProbabilityNode.java Wed Mar 11 20:43:12 2015 +0100 @@ -110,7 +110,9 @@ if (couldSet) { ValueNode currentCondition = condition; replaceAndDelete(currentCondition); - tool.addToWorkList(currentCondition.usages()); + if (tool != null) { + tool.addToWorkList(currentCondition.usages()); + } } else { if (!isSubstitutionGraph()) { throw new GraalInternalError("Wrong usage of branch probability injection!"); @@ -135,10 +137,7 @@ * @return the condition */ @NodeIntrinsic - public static boolean probability(double probability, boolean condition) { - assert probability >= 0.0 && probability <= 1.0; - return condition; - } + public static native boolean probability(double probability, boolean condition); @Override public void lower(LoweringTool tool) { diff -r 31fac91ea3b7 -r 14e703edb2ab graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/FixedValueAnchorNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/FixedValueAnchorNode.java Wed Mar 11 17:16:30 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/FixedValueAnchorNode.java Wed Mar 11 20:43:12 2015 +0100 @@ -49,7 +49,7 @@ } @NodeIntrinsic - public static native T getObject(Object object); + public static native Object getObject(Object object); @Override public void generate(NodeLIRBuilderTool generator) { diff -r 31fac91ea3b7 -r 14e703edb2ab graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ForeignCallNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ForeignCallNode.java Wed Mar 11 17:16:30 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ForeignCallNode.java Wed Mar 11 20:43:12 2015 +0100 @@ -135,7 +135,7 @@ if ((currentStateAfter.stackSize() > 0 && currentStateAfter.stackAt(currentStateAfter.stackSize() - 1) == this) || (currentStateAfter.stackSize() > 1 && currentStateAfter.stackAt(currentStateAfter.stackSize() - 2) == this)) { // The result of this call is on the top of stack, so roll back to the previous bci. - assert bci != BytecodeFrame.UNKNOWN_BCI; + assert bci != BytecodeFrame.UNKNOWN_BCI : this; newStateDuring = currentStateAfter.duplicateModifiedDuringCall(bci, this.getKind()); } else { newStateDuring = currentStateAfter; diff -r 31fac91ea3b7 -r 14e703edb2ab graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/MembarNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/MembarNode.java Wed Mar 11 17:16:30 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/MembarNode.java Wed Mar 11 20:43:12 2015 +0100 @@ -22,14 +22,7 @@ */ package com.oracle.graal.nodes.extended; -import static com.oracle.graal.compiler.common.UnsafeAccess.*; - -import java.lang.reflect.*; - -import sun.misc.*; - import com.oracle.graal.api.meta.*; -import com.oracle.graal.compiler.common.*; import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.graph.*; import com.oracle.graal.nodeinfo.*; @@ -60,28 +53,6 @@ generator.getLIRGeneratorTool().emitMembar(barriers); } - @SuppressWarnings("unused") @NodeIntrinsic - public static void memoryBarrier(@ConstantNodeParameter int barriers) { - // Overly conservative but it doesn't matter in the interpreter - unsafe.putIntVolatile(dummyBase, dummyOffset, 0); - unsafe.getIntVolatile(dummyBase, dummyOffset); - } - - /** - * An unused field that it used to exercise barriers in the interpreter. This can be replaced - * with direct support for barriers in {@link Unsafe} if/when they become available. - */ - @SuppressWarnings("unused") private static int dummy; - private static Object dummyBase; - private static long dummyOffset; - static { - try { - Field dummyField = MembarNode.class.getDeclaredField("dummy"); - dummyBase = unsafe.staticFieldBase(dummyField); - dummyOffset = unsafe.staticFieldOffset(dummyField); - } catch (Exception e) { - throw new GraalInternalError(e); - } - } + public static native void memoryBarrier(@ConstantNodeParameter int barriers); } diff -r 31fac91ea3b7 -r 14e703edb2ab graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/UnboxNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/UnboxNode.java Wed Mar 11 17:16:30 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/UnboxNode.java Wed Mar 11 20:43:12 2015 +0100 @@ -95,28 +95,4 @@ } return null; } - - @NodeIntrinsic - public static native boolean unbox(Boolean value, @ConstantNodeParameter Kind kind); - - @NodeIntrinsic - public static native byte unbox(Byte value, @ConstantNodeParameter Kind kind); - - @NodeIntrinsic - public static native char unbox(Character value, @ConstantNodeParameter Kind kind); - - @NodeIntrinsic - public static native double unbox(Double value, @ConstantNodeParameter Kind kind); - - @NodeIntrinsic - public static native float unbox(Float value, @ConstantNodeParameter Kind kind); - - @NodeIntrinsic - public static native int unbox(Integer value, @ConstantNodeParameter Kind kind); - - @NodeIntrinsic - public static native long unbox(Long value, @ConstantNodeParameter Kind kind); - - @NodeIntrinsic - public static native short unbox(Short value, @ConstantNodeParameter Kind kind); } diff -r 31fac91ea3b7 -r 14e703edb2ab graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/UnsafeCopyNode.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/UnsafeCopyNode.java Wed Mar 11 20:43:12 2015 +0100 @@ -0,0 +1,111 @@ +/* + * 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 + * 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.extended; + +import com.oracle.graal.api.meta.*; +import com.oracle.graal.compiler.common.type.*; +import com.oracle.graal.graph.*; +import com.oracle.graal.nodeinfo.*; +import com.oracle.graal.nodes.*; + +/** + * 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 TYPE = NodeClass.create(UnsafeCopyNode.class); + @Input ValueNode sourceObject; + @Input ValueNode destinationObject; + @Input ValueNode sourceOffset; + @Input ValueNode destinationOffset; + protected final Kind accessKind; + protected final LocationIdentity locationIdentity; + @OptionalInput(InputType.State) FrameState stateAfter; + + public UnsafeCopyNode(ValueNode sourceObject, ValueNode sourceOffset, ValueNode destinationObject, ValueNode destinationOffset, Kind accessKind, LocationIdentity locationIdentity) { + this(sourceObject, sourceOffset, destinationObject, destinationOffset, accessKind, locationIdentity, null); + } + + public UnsafeCopyNode(ValueNode sourceObject, ValueNode sourceOffset, ValueNode destinationObject, ValueNode destinationOffset, Kind 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 != Kind.Void && accessKind != Kind.Illegal; + } + + public ValueNode sourceObject() { + return sourceObject; + } + + public ValueNode destinationObject() { + return destinationObject; + } + + public LocationIdentity getLocationIdentity() { + return locationIdentity; + } + + public ValueNode sourceOffset() { + return sourceOffset; + } + + public ValueNode destinationOffset() { + return destinationOffset; + } + + public Kind 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() { + return true; + } + + public FrameState getState() { + return stateAfter; + } + + @NodeIntrinsic + public static native void copy(Object srcObject, long srcOffset, Object destObject, long destOffset, @ConstantNodeParameter Kind kind, @ConstantNodeParameter LocationIdentity locationIdentity); +} diff -r 31fac91ea3b7 -r 14e703edb2ab graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/UnsafeLoadNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/UnsafeLoadNode.java Wed Mar 11 17:16:30 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/UnsafeLoadNode.java Wed Mar 11 20:43:12 2015 +0100 @@ -22,8 +22,6 @@ */ package com.oracle.graal.nodes.extended; -import static com.oracle.graal.compiler.common.UnsafeAccess.*; - import com.oracle.graal.api.meta.*; import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.graph.*; @@ -89,34 +87,6 @@ return new UnsafeLoadNode(object(), location, accessKind(), identity, guardingCondition); } - @SuppressWarnings({"unchecked", "unused"}) @NodeIntrinsic - public static T load(Object object, long offset, @ConstantNodeParameter Kind kind, @ConstantNodeParameter LocationIdentity locationIdentity) { - if (kind == Kind.Boolean) { - return (T) (Boolean) unsafe.getBoolean(object, offset); - } - if (kind == Kind.Byte) { - return (T) (Byte) unsafe.getByte(object, offset); - } - if (kind == Kind.Short) { - return (T) (Short) unsafe.getShort(object, offset); - } - if (kind == Kind.Char) { - return (T) (Character) unsafe.getChar(object, offset); - } - if (kind == Kind.Int) { - return (T) (Integer) unsafe.getInt(object, offset); - } - if (kind == Kind.Float) { - return (T) (Float) unsafe.getFloat(object, offset); - } - if (kind == Kind.Long) { - return (T) (Long) unsafe.getLong(object, offset); - } - if (kind == Kind.Double) { - return (T) (Double) unsafe.getDouble(object, offset); - } - assert kind == Kind.Object; - return (T) unsafe.getObject(object, offset); - } + public static native Object load(Object object, long offset, @ConstantNodeParameter Kind kind, @ConstantNodeParameter LocationIdentity locationIdentity); } diff -r 31fac91ea3b7 -r 14e703edb2ab graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/UnsafeStoreNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/UnsafeStoreNode.java Wed Mar 11 17:16:30 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/UnsafeStoreNode.java Wed Mar 11 20:43:12 2015 +0100 @@ -22,8 +22,6 @@ */ package com.oracle.graal.nodes.extended; -import static com.oracle.graal.compiler.common.UnsafeAccess.*; - import com.oracle.graal.api.meta.*; import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.graph.*; @@ -122,60 +120,4 @@ public FrameState getState() { return stateAfter; } - - // specialized on value type until boxing/unboxing is sorted out in intrinsification - - @SuppressWarnings("unused") - @NodeIntrinsic - public static void store(Object object, long offset, Object value, @ConstantNodeParameter Kind kind, @ConstantNodeParameter LocationIdentity locationIdentity) { - unsafe.putObject(object, offset, value); - } - - @SuppressWarnings("unused") - @NodeIntrinsic - public static void store(Object object, long offset, boolean value, @ConstantNodeParameter Kind kind, @ConstantNodeParameter LocationIdentity locationIdentity) { - unsafe.putBoolean(object, offset, value); - } - - @SuppressWarnings("unused") - @NodeIntrinsic - public static void store(Object object, long offset, byte value, @ConstantNodeParameter Kind kind, @ConstantNodeParameter LocationIdentity locationIdentity) { - unsafe.putByte(object, offset, value); - } - - @SuppressWarnings("unused") - @NodeIntrinsic - public static void store(Object object, long offset, char value, @ConstantNodeParameter Kind kind, @ConstantNodeParameter LocationIdentity locationIdentity) { - unsafe.putChar(object, offset, value); - } - - @SuppressWarnings("unused") - @NodeIntrinsic - public static void store(Object object, long offset, double value, @ConstantNodeParameter Kind kind, @ConstantNodeParameter LocationIdentity locationIdentity) { - unsafe.putDouble(object, offset, value); - } - - @SuppressWarnings("unused") - @NodeIntrinsic - public static void store(Object object, long offset, float value, @ConstantNodeParameter Kind kind, @ConstantNodeParameter LocationIdentity locationIdentity) { - unsafe.putFloat(object, offset, value); - } - - @SuppressWarnings("unused") - @NodeIntrinsic - public static void store(Object object, long offset, int value, @ConstantNodeParameter Kind kind, @ConstantNodeParameter LocationIdentity locationIdentity) { - unsafe.putInt(object, offset, value); - } - - @SuppressWarnings("unused") - @NodeIntrinsic - public static void store(Object object, long offset, long value, @ConstantNodeParameter Kind kind, @ConstantNodeParameter LocationIdentity locationIdentity) { - unsafe.putLong(object, offset, value); - } - - @SuppressWarnings("unused") - @NodeIntrinsic - public static void store(Object object, long offset, short value, @ConstantNodeParameter Kind kind, @ConstantNodeParameter LocationIdentity locationIdentity) { - unsafe.putShort(object, offset, value); - } } diff -r 31fac91ea3b7 -r 14e703edb2ab graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/AtomicReadAndAddNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/AtomicReadAndAddNode.java Wed Mar 11 17:16:30 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/AtomicReadAndAddNode.java Wed Mar 11 20:43:12 2015 +0100 @@ -22,7 +22,6 @@ */ package com.oracle.graal.nodes.java; -import static com.oracle.graal.compiler.common.UnsafeAccess.*; import sun.misc.*; import com.oracle.graal.api.meta.*; @@ -76,14 +75,4 @@ Value result = gen.getLIRGeneratorTool().emitAtomicReadAndAdd(address, gen.operand(delta)); gen.setResult(this, result); } - - @NodeIntrinsic - public static int getAndAddInt(Object object, long offset, int delta, @ConstantNodeParameter @SuppressWarnings("unused") LocationIdentity locationIdentity) { - return unsafe.getAndAddInt(object, offset, delta); - } - - @NodeIntrinsic - public static long getAndAddLong(Object object, long offset, long delta, @ConstantNodeParameter @SuppressWarnings("unused") LocationIdentity locationIdentity) { - return unsafe.getAndAddLong(object, offset, delta); - } } diff -r 31fac91ea3b7 -r 14e703edb2ab graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/AtomicReadAndWriteNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/AtomicReadAndWriteNode.java Wed Mar 11 17:16:30 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/AtomicReadAndWriteNode.java Wed Mar 11 20:43:12 2015 +0100 @@ -22,7 +22,6 @@ */ package com.oracle.graal.nodes.java; -import static com.oracle.graal.compiler.common.UnsafeAccess.*; import sun.misc.*; import com.oracle.graal.api.meta.*; @@ -80,23 +79,4 @@ public void lower(LoweringTool tool) { tool.getLowerer().lower(this, tool); } - - @NodeIntrinsic - public static int getAndSetInt(Object object, long offset, int newValue, @SuppressWarnings("unused") @ConstantNodeParameter Kind valueKind, - @ConstantNodeParameter @SuppressWarnings("unused") LocationIdentity locationIdentity) { - return unsafe.getAndSetInt(object, offset, newValue); - } - - @NodeIntrinsic - public static long getAndSetLong(Object object, long offset, long newValue, @SuppressWarnings("unused") @ConstantNodeParameter Kind valueKind, - @ConstantNodeParameter @SuppressWarnings("unused") LocationIdentity locationIdentity) { - return unsafe.getAndSetLong(object, offset, newValue); - } - - @NodeIntrinsic - public static Object getAndSetObject(Object object, long offset, Object newValue, @SuppressWarnings("unused") @ConstantNodeParameter Kind valueKind, - @ConstantNodeParameter @SuppressWarnings("unused") LocationIdentity locationIdentity) { - return unsafe.getAndSetObject(object, offset, newValue); - } - } diff -r 31fac91ea3b7 -r 14e703edb2ab graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/CheckCastDynamicNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/CheckCastDynamicNode.java Wed Mar 11 17:16:30 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/CheckCastDynamicNode.java Wed Mar 11 20:43:12 2015 +0100 @@ -100,7 +100,4 @@ } return this; } - - @NodeIntrinsic - public static native T checkCastDynamic(Class type, Object object, @ConstantNodeParameter boolean forStoreCheck); } diff -r 31fac91ea3b7 -r 14e703edb2ab graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/CheckCastNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/CheckCastNode.java Wed Mar 11 17:16:30 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/CheckCastNode.java Wed Mar 11 20:43:12 2015 +0100 @@ -56,6 +56,7 @@ public CheckCastNode(ResolvedJavaType type, ValueNode object, JavaTypeProfile profile, boolean forStoreCheck) { super(TYPE, StampFactory.declaredTrusted(type)); + assert object.stamp() instanceof ObjectStamp : object + ":" + object.stamp(); assert type != null; this.type = type; this.object = object; @@ -69,6 +70,7 @@ if (synonym != null) { return synonym; } + assert object.stamp() instanceof ObjectStamp : object + ":" + object.stamp(); if (assumptions != null) { ResolvedJavaType uniqueConcreteType = type.findUniqueConcreteSubtype(); if (uniqueConcreteType != null && !uniqueConcreteType.equals(type)) { diff -r 31fac91ea3b7 -r 14e703edb2ab graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/CompareAndSwapNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/CompareAndSwapNode.java Wed Mar 11 17:16:30 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/CompareAndSwapNode.java Wed Mar 11 20:43:12 2015 +0100 @@ -22,8 +22,6 @@ */ package com.oracle.graal.nodes.java; -import static com.oracle.graal.compiler.common.UnsafeAccess.*; - import com.oracle.graal.api.meta.*; import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.graph.*; @@ -88,23 +86,4 @@ public void lower(LoweringTool tool) { tool.getLowerer().lower(this, tool); } - - // specialized on value type until boxing/unboxing is sorted out in intrinsification - @NodeIntrinsic - public static boolean compareAndSwap(Object object, long offset, Object expected, Object newValue, @SuppressWarnings("unused") @ConstantNodeParameter Kind valueKind, - @SuppressWarnings("unused") @ConstantNodeParameter LocationIdentity locationIdentity) { - return unsafe.compareAndSwapObject(object, offset, expected, newValue); - } - - @NodeIntrinsic - public static boolean compareAndSwap(Object object, long offset, long expected, long newValue, @SuppressWarnings("unused") @ConstantNodeParameter Kind valueKind, - @SuppressWarnings("unused") @ConstantNodeParameter LocationIdentity locationIdentity) { - return unsafe.compareAndSwapLong(object, offset, expected, newValue); - } - - @NodeIntrinsic - public static boolean compareAndSwap(Object object, long offset, int expected, int newValue, @SuppressWarnings("unused") @ConstantNodeParameter Kind valueKind, - @SuppressWarnings("unused") @ConstantNodeParameter LocationIdentity locationIdentity) { - return unsafe.compareAndSwapInt(object, offset, expected, newValue); - } } diff -r 31fac91ea3b7 -r 14e703edb2ab graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/DynamicNewArrayNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/DynamicNewArrayNode.java Wed Mar 11 17:16:30 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/DynamicNewArrayNode.java Wed Mar 11 20:43:12 2015 +0100 @@ -23,7 +23,6 @@ //JaCoCo Exclude package com.oracle.graal.nodes.java; -import java.lang.reflect.*; import java.util.*; import com.oracle.graal.api.meta.*; @@ -97,9 +96,7 @@ } @NodeIntrinsic - public static Object newArray(Class componentType, int length) { - return Array.newInstance(componentType, length); - } + public static native Object newArray(Class componentType, int length); @NodeIntrinsic private static native Object newArray(Class componentType, int length, @ConstantNodeParameter boolean fillContents, @ConstantNodeParameter Kind knownElementKind); diff -r 31fac91ea3b7 -r 14e703edb2ab graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/InstanceOfDynamicNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/InstanceOfDynamicNode.java Wed Mar 11 17:16:30 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/InstanceOfDynamicNode.java Wed Mar 11 20:43:12 2015 +0100 @@ -56,7 +56,7 @@ tool.getLowerer().lower(this, tool); } - public ValueNode canonical(CanonicalizerTool tool, ValueNode forObject, ValueNode forMirror) { + public LogicNode canonical(CanonicalizerTool tool, ValueNode forObject, ValueNode forMirror) { if (forMirror.isConstant()) { ResolvedJavaType t = tool.getConstantReflection().asJavaType(forMirror.asConstant()); if (t != null) { diff -r 31fac91ea3b7 -r 14e703edb2ab graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/RegisterFinalizerNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/RegisterFinalizerNode.java Wed Mar 11 17:16:30 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/RegisterFinalizerNode.java Wed Mar 11 20:43:12 2015 +0100 @@ -102,8 +102,6 @@ return true; } - @SuppressWarnings("unused") @NodeIntrinsic - public static void register(Object thisObj) { - } + public static native void register(Object thisObj); } diff -r 31fac91ea3b7 -r 14e703edb2ab graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/Replacements.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/Replacements.java Wed Mar 11 17:16:30 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/Replacements.java Wed Mar 11 20:43:12 2015 +0100 @@ -37,9 +37,10 @@ /** * Gets the snippet graph derived from a given method. * + * @param args arguments to the snippet if available, otherwise {@code null} * @return the snippet graph, if any, that is derived from {@code method} */ - StructuredGraph getSnippet(ResolvedJavaMethod method); + StructuredGraph getSnippet(ResolvedJavaMethod method, Object[] args); /** * Gets the snippet graph derived from a given method. @@ -47,9 +48,10 @@ * @param recursiveEntry if the snippet contains a call to this method, it's considered as * recursive call and won't be processed for {@linkplain MethodSubstitution * substitutions} or {@linkplain MacroSubstitution macro nodes}. + * @param args arguments to the snippet if available, otherwise {@code null} * @return the snippet graph, if any, that is derived from {@code method} */ - StructuredGraph getSnippet(ResolvedJavaMethod method, ResolvedJavaMethod recursiveEntry); + StructuredGraph getSnippet(ResolvedJavaMethod method, ResolvedJavaMethod recursiveEntry, Object[] args); /** * Registers a method as snippet. diff -r 31fac91ea3b7 -r 14e703edb2ab graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/ArraysSubstitutionsTest.java --- a/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/ArraysSubstitutionsTest.java Wed Mar 11 17:16:30 2015 +0100 +++ b/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/ArraysSubstitutionsTest.java Wed Mar 11 20:43:12 2015 +0100 @@ -313,7 +313,7 @@ @Test public void testConstants() { - test("testConstantsSnippet"); + testGraph("testConstantsSnippet"); } public static final int[] constantArray1 = new int[]{1, 2, 3, 4, 5, 6, 7, 8, 9}; diff -r 31fac91ea3b7 -r 14e703edb2ab graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/MethodSubstitutionTest.java --- a/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/MethodSubstitutionTest.java Wed Mar 11 17:16:30 2015 +0100 +++ b/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/MethodSubstitutionTest.java Wed Mar 11 20:43:12 2015 +0100 @@ -47,7 +47,7 @@ */ public abstract class MethodSubstitutionTest extends GraalCompilerTest { - protected StructuredGraph test(final String snippet) { + protected StructuredGraph testGraph(final String snippet) { try (Scope s = Debug.scope("MethodSubstitutionTest", getResolvedJavaMethod(snippet))) { StructuredGraph graph = parseEager(snippet, AllowAssumptions.YES); HighTierContext context = new HighTierContext(getProviders(), null, getDefaultGraphBuilderSuite(), OptimisticOptimizations.ALL); @@ -76,7 +76,7 @@ protected void testSubstitution(String testMethodName, Class intrinsicClass, Class holder, String methodName, Class[] parameterTypes, boolean optional, Object[] args1, Object[] args2) { ResolvedJavaMethod realMethod = getResolvedJavaMethod(holder, methodName, parameterTypes); ResolvedJavaMethod testMethod = getResolvedJavaMethod(testMethodName); - StructuredGraph graph = test(testMethodName); + StructuredGraph graph = testGraph(testMethodName); // Check to see if the resulting graph contains the expected node StructuredGraph replacement = getReplacements().getMethodSubstitution(realMethod); diff -r 31fac91ea3b7 -r 14e703edb2ab graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/ObjectAccessTest.java --- a/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/ObjectAccessTest.java Wed Mar 11 17:16:30 2015 +0100 +++ b/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/ObjectAccessTest.java Wed Mar 11 20:43:12 2015 +0100 @@ -33,7 +33,6 @@ import com.oracle.graal.nodes.extended.*; import com.oracle.graal.replacements.*; import com.oracle.graal.replacements.ReplacementsImpl.FrameStateProcessing; -import com.oracle.graal.replacements.Snippet.SnippetInliningPolicy; import com.oracle.graal.word.*; /** @@ -46,14 +45,12 @@ private final ReplacementsImpl installer; public ObjectAccessTest() { - installer = new ReplacementsImpl(getProviders(), getSnippetReflection(), getTarget()); + installer = (ReplacementsImpl) getReplacements(); } - private static final ThreadLocal inliningPolicy = new ThreadLocal<>(); - @Override protected StructuredGraph parseEager(ResolvedJavaMethod m, AllowAssumptions allowAssumptions) { - return installer.makeGraph(m, null, inliningPolicy.get(), FrameStateProcessing.CollapseFrameForSingleSideEffect); + return installer.makeGraph(m, null, null, null, FrameStateProcessing.CollapseFrameForSingleSideEffect); } @Test diff -r 31fac91ea3b7 -r 14e703edb2ab graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/PointerTest.java --- a/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/PointerTest.java Wed Mar 11 17:16:30 2015 +0100 +++ b/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/PointerTest.java Wed Mar 11 20:43:12 2015 +0100 @@ -52,14 +52,14 @@ public PointerTest() { target = getCodeCache().getTarget(); - installer = new ReplacementsImpl(getProviders(), getSnippetReflection(), getTarget()); + installer = (ReplacementsImpl) getProviders().getReplacements(); } private static final ThreadLocal inliningPolicy = new ThreadLocal<>(); @Override protected StructuredGraph parseEager(ResolvedJavaMethod m, AllowAssumptions allowAssumptions) { - return installer.makeGraph(m, null, inliningPolicy.get(), FrameStateProcessing.CollapseFrameForSingleSideEffect); + return installer.makeGraph(m, null, null, inliningPolicy.get(), FrameStateProcessing.CollapseFrameForSingleSideEffect); } @Test diff -r 31fac91ea3b7 -r 14e703edb2ab graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/StandardMethodSubstitutionsTest.java --- a/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/StandardMethodSubstitutionsTest.java Wed Mar 11 17:16:30 2015 +0100 +++ b/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/StandardMethodSubstitutionsTest.java Wed Mar 11 20:43:12 2015 +0100 @@ -29,7 +29,6 @@ import com.oracle.graal.api.replacements.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.calc.*; -import com.oracle.graal.replacements.*; import com.oracle.graal.replacements.nodes.*; /** @@ -39,16 +38,23 @@ @Test public void testMathSubstitutions() { - assertInGraph(assertNotInGraph(test("mathAbs"), IfNode.class), AbsNode.class); // Java - test("math"); - + assertInGraph(assertNotInGraph(testGraph("mathAbs"), IfNode.class), AbsNode.class); // Java double value = 34567.891D; - assertDeepEquals(Math.sqrt(value), MathSubstitutionsX86.sqrt(value)); - assertDeepEquals(Math.log(value), MathSubstitutionsX86.log(value)); - assertDeepEquals(Math.log10(value), MathSubstitutionsX86.log10(value)); - assertDeepEquals(Math.sin(value), MathSubstitutionsX86.sin(value)); - assertDeepEquals(Math.cos(value), MathSubstitutionsX86.cos(value)); - assertDeepEquals(Math.tan(value), MathSubstitutionsX86.tan(value)); + testGraph("mathCos"); + testGraph("mathLog"); + testGraph("mathLog10"); + testGraph("mathSin"); + testGraph("mathSqrt"); + testGraph("mathTan"); + testGraph("mathAll"); + + test("mathCos", value); + test("mathLog", value); + test("mathLog10", value); + test("mathSin", value); + test("mathSqrt", value); + test("mathTan", value); + test("mathAll", value); } @SuppressWarnings("all") @@ -57,16 +63,44 @@ } @SuppressWarnings("all") - public static double math(double value) { + public static double mathSqrt(double value) { + return Math.sqrt(value); + } + + @SuppressWarnings("all") + public static double mathLog(double value) { + return Math.log(value); + } + + @SuppressWarnings("all") + public static double mathLog10(double value) { + return Math.log10(value); + } + + @SuppressWarnings("all") + public static double mathSin(double value) { + return Math.sin(value); + } + + @SuppressWarnings("all") + public static double mathCos(double value) { + return Math.cos(value); + } + + @SuppressWarnings("all") + public static double mathTan(double value) { + return Math.tan(value); + } + + @SuppressWarnings("all") + public static double mathAll(double value) { return Math.sqrt(value) + Math.log(value) + Math.log10(value) + Math.sin(value) + Math.cos(value) + Math.tan(value); - // Math.exp(value) + - // Math.pow(value, 13); } public void testSubstitution(String testMethodName, Class intrinsicClass, Class holder, String methodName, boolean optional, Object... args) { ResolvedJavaMethod realJavaMethod = getResolvedJavaMethod(holder, methodName); ResolvedJavaMethod testJavaMethod = getResolvedJavaMethod(testMethodName); - StructuredGraph graph = test(testMethodName); + StructuredGraph graph = testGraph(testMethodName); // Check to see if the resulting graph contains the expected node StructuredGraph replacement = getReplacements().getMethodSubstitution(realJavaMethod); @@ -148,8 +182,8 @@ @Test public void testFloatSubstitutions() { - assertInGraph(test("floatToIntBits"), ReinterpretNode.class); // Java - test("intBitsToFloat"); + assertInGraph(testGraph("floatToIntBits"), ReinterpretNode.class); // Java + testGraph("intBitsToFloat"); } @SuppressWarnings("all") @@ -164,8 +198,8 @@ @Test public void testDoubleSubstitutions() { - assertInGraph(test("doubleToLongBits"), ReinterpretNode.class); // Java - test("longBitsToDouble"); + assertInGraph(testGraph("doubleToLongBits"), ReinterpretNode.class); // Java + testGraph("longBitsToDouble"); } @SuppressWarnings("all") @@ -179,22 +213,23 @@ } @SuppressWarnings("all") - public static boolean isInstance(Class clazz) { - return clazz.isInstance(Number.class); + public static boolean isInstance(Class clazz, Object object) { + return clazz.isInstance(object); } @SuppressWarnings("all") - public static boolean isAssignableFrom(Class clazz) { - return clazz.isInstance(Number.class); + public static boolean isAssignableFrom(Class clazz, Class other) { + return clazz.isAssignableFrom(other); } @Test public void testClassSubstitutions() { - test("isInstance"); + testGraph("isInstance"); + testGraph("isAssignableFrom"); for (Class c : new Class[]{getClass(), Cloneable.class, int[].class, String[][].class}) { for (Object o : new Object[]{this, new int[5], new String[2][], new Object()}) { - assertDeepEquals(c.isInstance(o), ClassSubstitutions.isInstance(c, o)); - assertDeepEquals(c.isAssignableFrom(o.getClass()), ClassSubstitutions.isAssignableFrom(c, o.getClass())); + test("isInstance", c, o); + test("isAssignableFrom", c, o.getClass()); } } } diff -r 31fac91ea3b7 -r 14e703edb2ab graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/StringSubstitutionsTest.java --- a/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/StringSubstitutionsTest.java Wed Mar 11 17:16:30 2015 +0100 +++ b/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/StringSubstitutionsTest.java Wed Mar 11 20:43:12 2015 +0100 @@ -38,7 +38,7 @@ public void testSubstitution(String testMethodName, Class intrinsicClass, Class holder, String methodName, boolean optional, Object[] args1, Object[] args2) { ResolvedJavaMethod realMethod = getResolvedJavaMethod(holder, methodName); ResolvedJavaMethod testMethod = getResolvedJavaMethod(testMethodName); - StructuredGraph graph = test(testMethodName); + StructuredGraph graph = testGraph(testMethodName); // Check to see if the resulting graph contains the expected node StructuredGraph replacement = getReplacements().getMethodSubstitution(realMethod); diff -r 31fac91ea3b7 -r 14e703edb2ab graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/UnsafeSubstitutionsTest.java --- a/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/UnsafeSubstitutionsTest.java Wed Mar 11 17:16:30 2015 +0100 +++ b/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/UnsafeSubstitutionsTest.java Wed Mar 11 20:43:12 2015 +0100 @@ -23,10 +23,6 @@ package com.oracle.graal.replacements.test; import static com.oracle.graal.compiler.common.UnsafeAccess.*; -import static com.oracle.graal.replacements.UnsafeSubstitutions.*; - -import java.lang.reflect.*; -import java.util.concurrent.atomic.*; import org.junit.*; @@ -71,7 +67,6 @@ } static class Foo { - boolean z; byte b; short s; @@ -81,130 +76,73 @@ float f; double d; Object o; - - void testGet(Field field, long offset, String getName, Object value) throws Exception { - field.set(this, value); - Method m1 = Unsafe.class.getDeclaredMethod(getName, Object.class, long.class); - Method m2 = UnsafeSubstitutions.class.getDeclaredMethod(getName, Object.class, Object.class, long.class); - Object expected = m1.invoke(unsafe, this, offset); - Object actual = m2.invoke(null, unsafe, this, offset); - Assert.assertEquals(expected, actual); - } - - void testDirect(Field field, long offset, String type, Object value) throws Exception { - if (type.equals("Boolean") || type.equals("Object")) { - // No direct memory access for these types - return; - } - - long address = unsafe.allocateMemory(offset + 16); - - String getName = "get" + type; - String putName = "put" + type; - Method m1 = Unsafe.class.getDeclaredMethod(putName, long.class, field.getType()); - Method m2 = Unsafe.class.getDeclaredMethod(getName, long.class); - - Method m3 = UnsafeSubstitutions.class.getDeclaredMethod(putName, Object.class, long.class, field.getType()); - Method m4 = UnsafeSubstitutions.class.getDeclaredMethod(getName, Object.class, long.class); - - m1.invoke(unsafe, address + offset, value); - Object expected = m2.invoke(unsafe, address + offset); - - m3.invoke(null, unsafe, address + offset, value); - Object actual = m4.invoke(null, unsafe, address + offset); - - unsafe.freeMemory(address); - Assert.assertEquals(expected, actual); - } - - void testPut(Field field, long offset, String putName, Object value) throws Exception { - Object initialValue = field.get(new Foo()); - field.set(this, initialValue); - - try { - Method m1 = Unsafe.class.getDeclaredMethod(putName, Object.class, long.class, field.getType()); - Method m2 = UnsafeSubstitutions.class.getDeclaredMethod(putName, Object.class, Object.class, long.class, field.getType()); - m1.invoke(unsafe, this, offset, value); - Object expected = field.get(this); - m2.invoke(null, unsafe, this, offset, value); - Object actual = field.get(this); - Assert.assertEquals(expected, actual); - } catch (NoSuchMethodException e) { - if (!putName.startsWith("putOrdered")) { - throw e; - } - } - } - - void test(String fieldName, String typeSuffix, Object value) { - try { - Field field = Foo.class.getDeclaredField(fieldName); - long offset = unsafe.objectFieldOffset(field); - testGet(field, offset, "get" + typeSuffix, value); - testGet(field, offset, "get" + typeSuffix + "Volatile", value); - testPut(field, offset, "put" + typeSuffix, value); - testPut(field, offset, "put" + typeSuffix + "Volatile", value); - testPut(field, offset, "putOrdered" + typeSuffix, value); - testDirect(field, offset, typeSuffix, value); - } catch (Exception e) { - throw new AssertionError(e); - } - } } @Test public void testUnsafeSubstitutions() throws Exception { - test("unsafeCompareAndSwapInt"); - test("unsafeCompareAndSwapLong"); - test("unsafeCompareAndSwapObject"); + test("unsafeCompareAndSwapInt", unsafe, supply(() -> new Foo()), fooOffset("i")); + + testGraph("unsafeCompareAndSwapInt"); + testGraph("unsafeCompareAndSwapLong"); + testGraph("unsafeCompareAndSwapObject"); + + testGraph("unsafeGetBoolean"); + testGraph("unsafeGetByte"); + testGraph("unsafeGetShort"); + testGraph("unsafeGetChar"); + testGraph("unsafeGetInt"); + testGraph("unsafeGetLong"); + testGraph("unsafeGetFloat"); + testGraph("unsafeGetDouble"); + testGraph("unsafeGetObject"); - test("unsafeGetBoolean"); - test("unsafeGetByte"); - test("unsafeGetShort"); - test("unsafeGetChar"); - test("unsafeGetInt"); - test("unsafeGetLong"); - test("unsafeGetFloat"); - test("unsafeGetDouble"); - test("unsafeGetObject"); + testGraph("unsafePutBoolean"); + testGraph("unsafePutByte"); + testGraph("unsafePutShort"); + testGraph("unsafePutChar"); + testGraph("unsafePutInt"); + testGraph("unsafePutFloat"); + testGraph("unsafePutDouble"); + testGraph("unsafePutObject"); - test("unsafePutBoolean"); - test("unsafePutByte"); - test("unsafePutShort"); - test("unsafePutChar"); - test("unsafePutInt"); - test("unsafePutFloat"); - test("unsafePutDouble"); - test("unsafePutObject"); + testGraph("unsafeDirectMemoryRead"); + testGraph("unsafeDirectMemoryWrite"); - test("unsafeDirectMemoryRead"); - test("unsafeDirectMemoryWrite"); + test("unsafeCompareAndSwapInt", unsafe, supply(() -> new Foo()), fooOffset("i")); + test("unsafeCompareAndSwapLong", unsafe, supply(() -> new Foo()), fooOffset("l")); + test("unsafeCompareAndSwapObject", unsafe, supply(() -> new Foo()), fooOffset("o")); - AtomicInteger a1 = new AtomicInteger(42); - AtomicInteger a2 = new AtomicInteger(42); - assertDeepEquals(unsafe.compareAndSwapInt(a1, off(a1, "value"), 42, 53), compareAndSwapInt(unsafe, a2, off(a2, "value"), 42, 53)); - assertDeepEquals(a1.get(), a2.get()); - - AtomicLong l1 = new AtomicLong(42); - AtomicLong l2 = new AtomicLong(42); - assertDeepEquals(unsafe.compareAndSwapLong(l1, off(l1, "value"), 42, 53), compareAndSwapLong(unsafe, l2, off(l2, "value"), 42, 53)); - assertDeepEquals(l1.get(), l2.get()); + test("unsafeGetBoolean", unsafe, supply(() -> new Foo()), fooOffset("z")); + test("unsafeGetByte", unsafe, supply(() -> new Foo()), fooOffset("b")); + test("unsafeGetShort", unsafe, supply(() -> new Foo()), fooOffset("s")); + test("unsafeGetChar", unsafe, supply(() -> new Foo()), fooOffset("c")); + test("unsafeGetInt", unsafe, supply(() -> new Foo()), fooOffset("i")); + test("unsafeGetLong", unsafe, supply(() -> new Foo()), fooOffset("l")); + test("unsafeGetFloat", unsafe, supply(() -> new Foo()), fooOffset("f")); + test("unsafeGetDouble", unsafe, supply(() -> new Foo()), fooOffset("d")); + test("unsafeGetObject", unsafe, supply(() -> new Foo()), fooOffset("o")); - AtomicReference o1 = new AtomicReference<>("42"); - AtomicReference o2 = new AtomicReference<>("42"); - assertDeepEquals(unsafe.compareAndSwapObject(o1, off(o1, "value"), "42", "53"), compareAndSwapObject(unsafe, o2, off(o2, "value"), "42", "53")); - assertDeepEquals(o1.get(), o2.get()); + test("unsafePutBoolean", unsafe, supply(() -> new Foo()), fooOffset("z"), true); + test("unsafePutByte", unsafe, supply(() -> new Foo()), fooOffset("b"), (byte) 87); + test("unsafePutShort", unsafe, supply(() -> new Foo()), fooOffset("s"), (short) -93); + test("unsafePutChar", unsafe, supply(() -> new Foo()), fooOffset("c"), 'A'); + test("unsafePutInt", unsafe, supply(() -> new Foo()), fooOffset("i"), 42); + test("unsafePutFloat", unsafe, supply(() -> new Foo()), fooOffset("f"), 58.0F); + test("unsafePutDouble", unsafe, supply(() -> new Foo()), fooOffset("d"), -28736.243465D); + test("unsafePutObject", unsafe, supply(() -> new Foo()), fooOffset("i"), "value1", "value2", "value3"); - Foo f1 = new Foo(); - f1.test("z", "Boolean", Boolean.TRUE); - f1.test("b", "Byte", Byte.MIN_VALUE); - f1.test("s", "Short", Short.MAX_VALUE); - f1.test("c", "Char", '!'); - f1.test("i", "Int", 1010010); - f1.test("f", "Float", -34.5F); - f1.test("l", "Long", 99999L); - f1.test("d", "Double", 1234.5678D); - f1.test("o", "Object", "object"); + long address = unsafe.allocateMemory(8 * Kind.values().length); + test("unsafeDirectMemoryRead", unsafe, address); + test("unsafeDirectMemoryWrite", unsafe, address, 0xCAFEBABEDEADBABEL); + unsafe.freeMemory(address); + } + + private static long fooOffset(String name) { + try { + return unsafe.objectFieldOffset(Foo.class.getDeclaredField(name)); + } catch (NoSuchFieldException | SecurityException e) { + throw new AssertionError(e); + } } @SuppressWarnings("all") @@ -268,78 +206,126 @@ } @SuppressWarnings("all") - public static void unsafePutBoolean(Unsafe unsafe, Object obj, long offset, boolean value) { + public static int unsafePutBoolean(Unsafe unsafe, Object obj, long offset, boolean value) { + int res = 1; unsafe.putBoolean(obj, offset, value); + res += unsafe.getBoolean(obj, offset) ? 3 : 5; unsafe.putBooleanVolatile(obj, offset, value); + res += unsafe.getBoolean(obj, offset) ? 7 : 11; + return res; } @SuppressWarnings("all") - public static void unsafePutByte(Unsafe unsafe, Object obj, long offset, byte value) { - unsafe.putByte(obj, offset, value); - unsafe.putByteVolatile(obj, offset, value); + public static int unsafePutByte(Unsafe unsafe, Object obj, long offset, byte value) { + int res = 1; + unsafe.putByte(obj, offset, (byte) (value + 1)); + res += unsafe.getByte(obj, offset); + unsafe.putByteVolatile(obj, offset, (byte) (value + 2)); + res += unsafe.getByte(obj, offset); + return res; } @SuppressWarnings("all") - public static void unsafePutShort(Unsafe unsafe, Object obj, long offset, short value) { - unsafe.putShort(obj, offset, value); - unsafe.putShortVolatile(obj, offset, value); + public static int unsafePutShort(Unsafe unsafe, Object obj, long offset, short value) { + int res = 1; + unsafe.putShort(obj, offset, (short) (value + 1)); + res += unsafe.getShort(obj, offset); + unsafe.putShortVolatile(obj, offset, (short) (value + 2)); + res += unsafe.getShort(obj, offset); + return res; } @SuppressWarnings("all") - public static void unsafePutChar(Unsafe unsafe, Object obj, long offset, char value) { - unsafe.putChar(obj, offset, value); - unsafe.putCharVolatile(obj, offset, value); + public static int unsafePutChar(Unsafe unsafe, Object obj, long offset, char value) { + int res = 1; + unsafe.putChar(obj, offset, (char) (value + 1)); + res += unsafe.getChar(obj, offset); + unsafe.putCharVolatile(obj, offset, (char) (value + 2)); + res += unsafe.getChar(obj, offset); + return res; } @SuppressWarnings("all") - public static void unsafePutInt(Unsafe unsafe, Object obj, long offset, int value) { + public static int unsafePutInt(Unsafe unsafe, Object obj, long offset, int value) { + int res = 1; unsafe.putInt(obj, offset, value); - unsafe.putIntVolatile(obj, offset, value); - unsafe.putOrderedInt(obj, offset, value); + res += unsafe.getInt(obj, offset); + unsafe.putIntVolatile(obj, offset, value + 1); + res += unsafe.getInt(obj, offset); + unsafe.putOrderedInt(obj, offset, value + 2); + res += unsafe.getInt(obj, offset); + return res; } @SuppressWarnings("all") - public static void unsafePutLong(Unsafe unsafe, Object obj, long offset, long value) { - unsafe.putLong(obj, offset, value); - unsafe.putLongVolatile(obj, offset, value); - unsafe.putOrderedLong(obj, offset, value); + public static long unsafePutLong(Unsafe unsafe, Object obj, long offset, long value) { + long res = 1; + unsafe.putLong(obj, offset, value + 1); + res += unsafe.getLong(obj, offset); + unsafe.putLongVolatile(obj, offset, value + 2); + res += unsafe.getLong(obj, offset); + unsafe.putOrderedLong(obj, offset, value + 3); + res += unsafe.getLong(obj, offset); + return res; } @SuppressWarnings("all") - public static void unsafePutFloat(Unsafe unsafe, Object obj, long offset, float value) { - unsafe.putFloat(obj, offset, value); - unsafe.putFloatVolatile(obj, offset, value); + public static float unsafePutFloat(Unsafe unsafe, Object obj, long offset, float value) { + float res = 1; + unsafe.putFloat(obj, offset, value + 1.0F); + res += unsafe.getFloat(obj, offset); + unsafe.putFloatVolatile(obj, offset, value + 2.0F); + res += unsafe.getFloat(obj, offset); + return res; } @SuppressWarnings("all") - public static void unsafePutDouble(Unsafe unsafe, Object obj, long offset, double value) { + public static double unsafePutDouble(Unsafe unsafe, Object obj, long offset, double value) { + double res = 1; unsafe.putDouble(obj, offset, value); + res += unsafe.getDouble(obj, offset); unsafe.putDoubleVolatile(obj, offset, value); + res += unsafe.getDouble(obj, offset); + return res; } @SuppressWarnings("all") - public static void unsafePutObject(Unsafe unsafe, Object obj, long offset, Object value) { - unsafe.putObject(obj, offset, value); - unsafe.putObjectVolatile(obj, offset, value); - unsafe.putOrderedObject(obj, offset, value); + public static Object[] unsafePutObject(Unsafe unsafe, Object obj, long offset, Object value1, Object value2, Object value3) { + Object[] res = new Object[3]; + unsafe.putObject(obj, offset, value1); + res[0] = unsafe.getObject(obj, offset); + unsafe.putObjectVolatile(obj, offset, value2); + res[1] = unsafe.getObject(obj, offset); + unsafe.putOrderedObject(obj, offset, value3); + res[2] = unsafe.getObject(obj, offset); + return res; } @SuppressWarnings("all") public static double unsafeDirectMemoryRead(Unsafe unsafe, long address) { // Unsafe.getBoolean(long) and Unsafe.getObject(long) do not exist - return unsafe.getByte(address) + unsafe.getShort(address) + unsafe.getChar(address) + unsafe.getInt(address) + unsafe.getLong(address) + unsafe.getFloat(address) + unsafe.getDouble(address); + // @formatter:off + return unsafe.getByte(address) + + unsafe.getShort(address + 8) + + unsafe.getChar(address + 16) + + unsafe.getInt(address + 24) + + unsafe.getLong(address + 32) + + unsafe.getFloat(address + 40) + + unsafe.getDouble(address + 48); + // @formatter:on } @SuppressWarnings("all") - public static void unsafeDirectMemoryWrite(Unsafe unsafe, long address, byte value) { + public static double unsafeDirectMemoryWrite(Unsafe unsafe, long address, long value) { // Unsafe.putBoolean(long) and Unsafe.putObject(long) do not exist - unsafe.putByte(address, value); - unsafe.putShort(address, value); - unsafe.putChar(address, (char) value); - unsafe.putInt(address, value); - unsafe.putLong(address, value); - unsafe.putFloat(address, value); - unsafe.putDouble(address, value); + unsafe.putByte(address + 0, (byte) value); + unsafe.putShort(address + 8, (short) value); + unsafe.putChar(address + 16, (char) value); + unsafe.putInt(address + 24, (int) value); + unsafe.putLong(address + 32, value); + unsafe.putFloat(address + 40, value); + unsafe.putDouble(address + 48, value); + return unsafeDirectMemoryRead(unsafe, address); } @Test diff -r 31fac91ea3b7 -r 14e703edb2ab graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/WordTest.java --- a/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/WordTest.java Wed Mar 11 17:16:30 2015 +0100 +++ b/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/WordTest.java Wed Mar 11 20:43:12 2015 +0100 @@ -30,7 +30,6 @@ import com.oracle.graal.nodes.StructuredGraph.AllowAssumptions; import com.oracle.graal.replacements.*; import com.oracle.graal.replacements.ReplacementsImpl.FrameStateProcessing; -import com.oracle.graal.replacements.Snippet.SnippetInliningPolicy; import com.oracle.graal.word.*; /** @@ -41,14 +40,12 @@ private final ReplacementsImpl installer; public WordTest() { - installer = new ReplacementsImpl(getProviders(), getSnippetReflection(), getTarget()); + installer = (ReplacementsImpl) getReplacements(); } - private static final ThreadLocal inliningPolicy = new ThreadLocal<>(); - @Override protected StructuredGraph parseEager(ResolvedJavaMethod m, AllowAssumptions allowAssumptions) { - return installer.makeGraph(m, null, inliningPolicy.get(), FrameStateProcessing.CollapseFrameForSingleSideEffect); + return installer.makeGraph(m, null, null, null, FrameStateProcessing.CollapseFrameForSingleSideEffect); } @Test diff -r 31fac91ea3b7 -r 14e703edb2ab graal/com.oracle.graal.replacements.verifier/src/com/oracle/graal/replacements/verifier/NodeIntrinsicVerifier.java --- a/graal/com.oracle.graal.replacements.verifier/src/com/oracle/graal/replacements/verifier/NodeIntrinsicVerifier.java Wed Mar 11 17:16:30 2015 +0100 +++ b/graal/com.oracle.graal.replacements.verifier/src/com/oracle/graal/replacements/verifier/NodeIntrinsicVerifier.java Wed Mar 11 20:43:12 2015 +0100 @@ -75,6 +75,9 @@ if (!intrinsicMethod.getModifiers().contains(Modifier.STATIC)) { env.getMessager().printMessage(Kind.ERROR, String.format("A @%s method must be static.", NodeIntrinsic.class.getSimpleName()), element, annotation); } + if (!intrinsicMethod.getModifiers().contains(Modifier.NATIVE)) { + env.getMessager().printMessage(Kind.ERROR, String.format("A @%s method must be native.", NodeIntrinsic.class.getSimpleName()), element, annotation); + } TypeMirror nodeClassMirror = resolveAnnotationValue(TypeMirror.class, findAnnotationValue(annotation, NODE_CLASS_NAME)); TypeElement nodeClass = (TypeElement) env.getTypeUtils().asElement(nodeClassMirror); @@ -89,6 +92,10 @@ } } + if (intrinsicMethod.getReturnType() instanceof TypeVariable) { + 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); diff -r 31fac91ea3b7 -r 14e703edb2ab graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/ArraySubstitutions.java --- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/ArraySubstitutions.java Wed Mar 11 17:16:30 2015 +0100 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/ArraySubstitutions.java Wed Mar 11 20:43:12 2015 +0100 @@ -22,6 +22,9 @@ */ package com.oracle.graal.replacements; +import static com.oracle.graal.nodes.extended.BranchProbabilityNode.*; + +import com.oracle.graal.api.meta.*; import com.oracle.graal.api.replacements.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.java.*; @@ -36,19 +39,19 @@ public static Object newInstance(Class componentType, int length) throws NegativeArraySizeException { // The error cases must be handled here since DynamicNewArrayNode can only deoptimize the // caller in response to exceptions. - if (length < 0) { - throw new NegativeArraySizeException(); + if (probability(SLOW_PATH_PROBABILITY, length < 0)) { + DeoptimizeNode.deopt(DeoptimizationAction.None, DeoptimizationReason.RuntimeConstraint); } - if (componentType == void.class) { - throw new IllegalArgumentException(); + if (probability(SLOW_PATH_PROBABILITY, componentType == void.class)) { + DeoptimizeNode.deopt(DeoptimizationAction.None, DeoptimizationReason.RuntimeConstraint); } - return DynamicNewArrayNode.newArray(GuardingPiNode.guardingNonNull(componentType), length); + return DynamicNewArrayNode.newArray(GuardingPiNode.asNonNullClass(componentType), length); } @MethodSubstitution public static int getLength(Object array) { if (!array.getClass().isArray()) { - throw new IllegalArgumentException("Argument is not an array"); + DeoptimizeNode.deopt(DeoptimizationAction.None, DeoptimizationReason.RuntimeConstraint); } return ArrayLengthNode.arrayLength(array); } diff -r 31fac91ea3b7 -r 14e703edb2ab graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/BlackholeSubstitutions.java --- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/BlackholeSubstitutions.java Wed Mar 11 17:16:30 2015 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,93 +0,0 @@ -/* - * Copyright (c) 2015, 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 com.oracle.graal.api.replacements.*; -import com.oracle.graal.nodes.debug.*; - -/** - * Substitutions for both the old and new versions of JMH Blackhole helper classes. - */ -@ClassSubstitution(className = {"org.openjdk.jmh.infra.Blackhole", "org.openjdk.jmh.logic.BlackHole"}, optional = true) -public class BlackholeSubstitutions { - - @SuppressWarnings("unused") - @MethodSubstitution(isStatic = false, forced = true) - public static void consume(final Object thisObj, Object v) { - BlackholeNode.consume(v); - } - - @SuppressWarnings("unused") - @MethodSubstitution(isStatic = false, forced = true) - public static void consume(final Object thisObj, Object[] v) { - BlackholeNode.consume(v); - } - - @SuppressWarnings("unused") - @MethodSubstitution(isStatic = false, forced = true) - public static void consume(final Object thisObj, byte v) { - BlackholeNode.consume(v); - } - - @SuppressWarnings("unused") - @MethodSubstitution(isStatic = false, forced = true) - public static void consume(final Object thisObj, boolean v) { - BlackholeNode.consume(v); - } - - @SuppressWarnings("unused") - @MethodSubstitution(isStatic = false, forced = true) - public static void consume(final Object thisObj, char v) { - BlackholeNode.consume(v); - } - - @SuppressWarnings("unused") - @MethodSubstitution(isStatic = false, forced = true) - public static void consume(final Object thisObj, short v) { - BlackholeNode.consume(v); - } - - @SuppressWarnings("unused") - @MethodSubstitution(isStatic = false, forced = true) - public static void consume(final Object thisObj, int v) { - BlackholeNode.consume(v); - } - - @SuppressWarnings("unused") - @MethodSubstitution(isStatic = false, forced = true) - public static void consume(final Object thisObj, long v) { - BlackholeNode.consume(v); - } - - @SuppressWarnings("unused") - @MethodSubstitution(isStatic = false, forced = true) - public static void consume(final Object thisObj, float v) { - BlackholeNode.consume(v); - } - - @SuppressWarnings("unused") - @MethodSubstitution(isStatic = false, forced = true) - public static void consume(final Object thisObj, double v) { - BlackholeNode.consume(v); - } -} diff -r 31fac91ea3b7 -r 14e703edb2ab graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/BoxingSnippets.java --- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/BoxingSnippets.java Wed Mar 11 17:16:30 2015 +0100 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/BoxingSnippets.java Wed Mar 11 20:43:12 2015 +0100 @@ -77,49 +77,49 @@ } @Snippet(inlining = BoxingSnippetInliningPolicy.class) - public static Boolean booleanValueOf(boolean value) { + public static Object booleanValueOf(boolean value) { valueOfCounter.inc(); return PiNode.piCast(Boolean.valueOf(value), StampFactory.forNodeIntrinsic()); } @Snippet(inlining = BoxingSnippetInliningPolicy.class) - public static Byte byteValueOf(byte value) { + public static Object byteValueOf(byte value) { valueOfCounter.inc(); return PiNode.piCast(Byte.valueOf(value), StampFactory.forNodeIntrinsic()); } @Snippet(inlining = BoxingSnippetInliningPolicy.class) - public static Character charValueOf(char value) { + public static Object charValueOf(char value) { valueOfCounter.inc(); return PiNode.piCast(Character.valueOf(value), StampFactory.forNodeIntrinsic()); } @Snippet(inlining = BoxingSnippetInliningPolicy.class) - public static Double doubleValueOf(double value) { + public static Object doubleValueOf(double value) { valueOfCounter.inc(); return PiNode.piCast(Double.valueOf(value), StampFactory.forNodeIntrinsic()); } @Snippet(inlining = BoxingSnippetInliningPolicy.class) - public static Float floatValueOf(float value) { + public static Object floatValueOf(float value) { valueOfCounter.inc(); return PiNode.piCast(Float.valueOf(value), StampFactory.forNodeIntrinsic()); } @Snippet(inlining = BoxingSnippetInliningPolicy.class) - public static Integer intValueOf(int value) { + public static Object intValueOf(int value) { valueOfCounter.inc(); return PiNode.piCast(Integer.valueOf(value), StampFactory.forNodeIntrinsic()); } @Snippet(inlining = BoxingSnippetInliningPolicy.class) - public static Long longValueOf(long value) { + public static Object longValueOf(long value) { valueOfCounter.inc(); return PiNode.piCast(Long.valueOf(value), StampFactory.forNodeIntrinsic()); } @Snippet(inlining = BoxingSnippetInliningPolicy.class) - public static Short shortValueOf(short value) { + public static Object shortValueOf(short value) { valueOfCounter.inc(); return PiNode.piCast(Short.valueOf(value), StampFactory.forNodeIntrinsic()); } diff -r 31fac91ea3b7 -r 14e703edb2ab graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/BoxingSubstitutions.java --- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/BoxingSubstitutions.java Wed Mar 11 17:16:30 2015 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,154 +0,0 @@ -/* - * Copyright (c) 2012, 2012, 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 com.oracle.graal.api.meta.*; -import com.oracle.graal.api.replacements.*; -import com.oracle.graal.nodes.extended.*; -import com.oracle.graal.nodes.spi.*; - -public class BoxingSubstitutions { - - @ClassSubstitution(Boolean.class) - private static class BooleanSubstitutions { - - @MethodSubstitution(forced = true) - public static Boolean valueOf(boolean value) { - return BoxNode.box(value, Boolean.class, Kind.Boolean); - } - - @MethodSubstitution(isStatic = false, forced = true) - public static boolean booleanValue(Boolean value) { - return UnboxNode.unbox(value, Kind.Boolean); - } - } - - @ClassSubstitution(Byte.class) - private static class ByteSubstitutions { - - @MethodSubstitution(forced = true) - public static Byte valueOf(byte value) { - return BoxNode.box(value, Byte.class, Kind.Byte); - } - - @MethodSubstitution(isStatic = false, forced = true) - public static byte byteValue(Byte value) { - return UnboxNode.unbox(value, Kind.Byte); - } - } - - @ClassSubstitution(Character.class) - private static class CharacterSubstitutions { - - @MethodSubstitution(forced = true) - public static Character valueOf(char value) { - return BoxNode.box(value, Character.class, Kind.Char); - } - - @MethodSubstitution(isStatic = false, forced = true) - public static char charValue(Character value) { - return UnboxNode.unbox(value, Kind.Char); - } - } - - @ClassSubstitution(Double.class) - private static class DoubleSubstitutions { - - @MethodSubstitution(forced = true) - public static Double valueOf(double value) { - return BoxNode.box(value, Double.class, Kind.Double); - } - - @MethodSubstitution(isStatic = false, forced = true) - public static double doubleValue(Double value) { - return UnboxNode.unbox(value, Kind.Double); - } - } - - @ClassSubstitution(Float.class) - private static class FloatSubstitutions { - - @MethodSubstitution(forced = true) - public static Float valueOf(float value) { - return BoxNode.box(value, Float.class, Kind.Float); - } - - @MethodSubstitution(isStatic = false, forced = true) - public static float floatValue(Float value) { - return UnboxNode.unbox(value, Kind.Float); - } - } - - @ClassSubstitution(Integer.class) - private static class IntegerSubstitutions { - - @MethodSubstitution(forced = true) - public static Integer valueOf(int value) { - return BoxNode.box(value, Integer.class, Kind.Int); - } - - @MethodSubstitution(isStatic = false, forced = true) - public static int intValue(Integer value) { - return UnboxNode.unbox(value, Kind.Int); - } - } - - @ClassSubstitution(Long.class) - private static class LongSubstitutions { - - @MethodSubstitution(forced = true) - public static Long valueOf(long value) { - return BoxNode.box(value, Long.class, Kind.Long); - } - - @MethodSubstitution(isStatic = false, forced = true) - public static long longValue(Long value) { - return UnboxNode.unbox(value, Kind.Long); - } - } - - @ClassSubstitution(Short.class) - private static class ShortSubstitutions { - - @MethodSubstitution(forced = true) - public static Short valueOf(short value) { - return BoxNode.box(value, Short.class, Kind.Short); - } - - @MethodSubstitution(isStatic = false, forced = true) - public static short shortValue(Short value) { - return UnboxNode.unbox(value, Kind.Short); - } - } - - public static void registerReplacements(Replacements replacements) { - replacements.registerSubstitutions(Boolean.class, BooleanSubstitutions.class); - replacements.registerSubstitutions(Character.class, CharacterSubstitutions.class); - replacements.registerSubstitutions(Double.class, DoubleSubstitutions.class); - replacements.registerSubstitutions(Byte.class, ByteSubstitutions.class); - replacements.registerSubstitutions(Float.class, FloatSubstitutions.class); - replacements.registerSubstitutions(Integer.class, IntegerSubstitutions.class); - replacements.registerSubstitutions(Short.class, ShortSubstitutions.class); - replacements.registerSubstitutions(Long.class, LongSubstitutions.class); - } -} diff -r 31fac91ea3b7 -r 14e703edb2ab graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/CharacterSubstitutions.java --- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/CharacterSubstitutions.java Wed Mar 11 17:16:30 2015 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,34 +0,0 @@ -/* - * Copyright (c) 2014, 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 com.oracle.graal.api.replacements.*; -import com.oracle.graal.replacements.nodes.*; - -@ClassSubstitution(Character.class) -public class CharacterSubstitutions { - @MethodSubstitution - public static char reverseBytes(char i) { - return (char) (ReverseBytesNode.reverse(i) >> 16); - } -} diff -r 31fac91ea3b7 -r 14e703edb2ab graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/ClassSubstitutions.java --- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/ClassSubstitutions.java Wed Mar 11 17:16:30 2015 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,43 +0,0 @@ -/* - * 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 com.oracle.graal.api.replacements.*; -import com.oracle.graal.nodes.calc.*; - -/** - * Substitutions for {@link java.lang.Class} methods. - */ -@ClassSubstitution(java.lang.Class.class) -public class ClassSubstitutions { - - @MethodSubstitution(isStatic = false) - public static boolean isInstance(Class thisObj, Object obj) { - return ConditionalNode.materializeIsInstance(thisObj, obj); - } - - @MethodSubstitution(isStatic = false) - public static boolean isAssignableFrom(Class thisClass, Class otherClass) { - return ConditionalNode.materializeIsAssignableFrom(thisClass, otherClass); - } -} diff -r 31fac91ea3b7 -r 14e703edb2ab graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/ConstantBindingParameterPlugin.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/ConstantBindingParameterPlugin.java Wed Mar 11 20:43:12 2015 +0100 @@ -0,0 +1,73 @@ +/* + * 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 com.oracle.graal.api.meta.*; +import com.oracle.graal.api.replacements.*; +import com.oracle.graal.compiler.common.type.*; +import com.oracle.graal.java.*; +import com.oracle.graal.java.GraphBuilderPlugin.ParameterPlugin; +import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.calc.*; + +/** + * A {@link ParameterPlugin} that binds constant values to some parameters. + */ +public class ConstantBindingParameterPlugin implements ParameterPlugin { + private final Object[] constantArgs; + private final ParameterPlugin delegate; + private final MetaAccessProvider metaAccess; + private final SnippetReflectionProvider snippetReflection; + + /** + * Creates a plugin that will create {@link ConstantNode}s for each parameter with an index + * equal to that of a non-null object in {@code constantArgs} (from which the + * {@link ConstantNode} is created if it isn't already a {@link ConstantNode}). For all other + * parameter indexes, {@code delegate} is applied if it is non-null. + */ + public ConstantBindingParameterPlugin(Object[] constantArgs, ParameterPlugin delegate, MetaAccessProvider metaAccess, SnippetReflectionProvider snippetReflection) { + this.constantArgs = constantArgs; + this.delegate = delegate; + this.metaAccess = metaAccess; + this.snippetReflection = snippetReflection; + } + + public FloatingNode interceptParameter(GraphBuilderContext b, int index, Stamp stamp) { + Object arg = constantArgs[index]; + if (arg != null) { + ConstantNode constantNode; + if (arg instanceof ConstantNode) { + constantNode = (ConstantNode) arg; + } else if (arg instanceof Constant) { + constantNode = ConstantNode.forConstant(stamp, (Constant) arg, metaAccess); + } else { + constantNode = ConstantNode.forConstant(snippetReflection.forBoxed(stamp.getStackKind(), arg), metaAccess); + } + return constantNode; + } + if (delegate != null) { + return delegate.interceptParameter(b, index, stamp); + } + return null; + } +} diff -r 31fac91ea3b7 -r 14e703edb2ab graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/DefaultGenericInvocationPlugin.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/DefaultGenericInvocationPlugin.java Wed Mar 11 20:43:12 2015 +0100 @@ -0,0 +1,124 @@ +/* + * 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 static com.oracle.graal.api.meta.MetaUtil.*; +import static com.oracle.graal.replacements.NodeIntrinsificationPhase.*; + +import java.util.*; + +import com.oracle.graal.api.meta.*; +import com.oracle.graal.api.replacements.*; +import com.oracle.graal.compiler.common.type.*; +import com.oracle.graal.graph.Node.NodeIntrinsic; +import com.oracle.graal.java.*; +import com.oracle.graal.java.GraphBuilderPlugin.GenericInvocationPlugin; +import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.extended.*; +import com.oracle.graal.word.phases.*; + +/** + * An {@link GenericInvocationPlugin} that handles methods annotated by {@link Fold}, + * {@link NodeIntrinsic} and all annotations supported by a given {@link WordOperationPlugin}. + */ +public class DefaultGenericInvocationPlugin implements GenericInvocationPlugin { + protected final NodeIntrinsificationPhase nodeIntrinsification; + protected final WordOperationPlugin wordOperationPlugin; + + public DefaultGenericInvocationPlugin(NodeIntrinsificationPhase nodeIntrinsification, WordOperationPlugin wordOperationPlugin) { + this.nodeIntrinsification = nodeIntrinsification; + this.wordOperationPlugin = wordOperationPlugin; + } + + public boolean apply(GraphBuilderContext b, ResolvedJavaMethod method, ValueNode[] args) { + if (wordOperationPlugin.apply(b, method, args)) { + return true; + } else if (b.parsingReplacement() || b.eagerResolving()) { + NodeIntrinsic intrinsic = nodeIntrinsification.getIntrinsic(method); + if (intrinsic != null) { + Signature sig = method.getSignature(); + Kind returnKind = sig.getReturnKind(); + Stamp stamp = StampFactory.forKind(returnKind); + if (returnKind == Kind.Object) { + JavaType returnType = sig.getReturnType(method.getDeclaringClass()); + if (returnType instanceof ResolvedJavaType) { + ResolvedJavaType resolvedReturnType = (ResolvedJavaType) returnType; + WordTypes wordTypes = wordOperationPlugin.getWordTypes(); + if (wordTypes.isWord(resolvedReturnType)) { + stamp = wordTypes.getWordStamp(resolvedReturnType); + } else { + stamp = StampFactory.declared(resolvedReturnType); + } + } + } + + return processNodeIntrinsic(b, method, intrinsic, Arrays.asList(args), returnKind, stamp); + } 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 + ConstantNode res = b.append(ConstantNode.forConstant(constant, b.getMetaAccess())); + b.push(res.getKind().getStackKind(), b.append(res)); + } else { + // This must be a void invoke + assert method.getSignature().getReturnKind() == Kind.Void; + } + return true; + } + } + } + return false; + } + + protected boolean processNodeIntrinsic(GraphBuilderContext b, ResolvedJavaMethod method, NodeIntrinsic intrinsic, List args, Kind 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.append(new UnsafeLoadNode(copy.sourceObject(), copy.sourceOffset(), copy.accessKind(), copy.getLocationIdentity())); + b.append(new UnsafeStoreNode(copy.destinationObject(), copy.destinationOffset(), value, copy.accessKind(), copy.getLocationIdentity())); + return true; + } else if (res instanceof ForeignCallNode) { + ForeignCallNode foreign = (ForeignCallNode) res; + foreign.setBci(b.bci()); + } + + res = b.append(res); + if (res.getKind().getStackKind() != Kind.Void) { + b.push(returnKind.getStackKind(), res); + } + + return true; + } + + protected ValueNode createNodeIntrinsic(GraphBuilderContext b, ResolvedJavaMethod method, NodeIntrinsic intrinsic, List args, Stamp stamp) { + ValueNode res = nodeIntrinsification.createIntrinsicNode(args, stamp, method, b.getGraph(), intrinsic); + assert res != null || b.getRootMethod().getAnnotation(Snippet.class) != 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; + } +} diff -r 31fac91ea3b7 -r 14e703edb2ab graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/DoubleSubstitutions.java --- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/DoubleSubstitutions.java Wed Mar 11 17:16:30 2015 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,56 +0,0 @@ -/* - * Copyright (c) 2011, 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 com.oracle.graal.api.meta.*; -import com.oracle.graal.api.replacements.*; -import com.oracle.graal.nodes.calc.*; - -/** - * Substitutions for {@link java.lang.Double} methods. - */ -@ClassSubstitution(java.lang.Double.class) -public class DoubleSubstitutions { - - private static final long NAN_RAW_LONG_BITS = Double.doubleToRawLongBits(Double.NaN); - - @MethodSubstitution - public static long doubleToRawLongBits(double value) { - return ReinterpretNode.reinterpret(Kind.Long, value); - } - - // TODO This method is not necessary, since the JDK method does exactly this - @MethodSubstitution - public static long doubleToLongBits(double value) { - if (value != value) { - return NAN_RAW_LONG_BITS; - } else { - return doubleToRawLongBits(value); - } - } - - @MethodSubstitution - public static double longBitsToDouble(long bits) { - return ReinterpretNode.reinterpret(Kind.Double, bits); - } -} diff -r 31fac91ea3b7 -r 14e703edb2ab graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/EdgesSubstitutions.java --- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/EdgesSubstitutions.java Wed Mar 11 17:16:30 2015 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,51 +0,0 @@ -/* - * Copyright (c) 2011, 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 com.oracle.graal.api.meta.*; -import com.oracle.graal.api.replacements.*; -import com.oracle.graal.graph.*; -import com.oracle.graal.nodes.*; -import com.oracle.graal.nodes.extended.*; -import com.oracle.graal.replacements.nodes.*; - -/** - * Substitutions for improving the performance of some critical methods in {@link Edges}. These - * substitutions improve the performance by forcing the relevant methods to be inlined - * (intrinsification being a special form of inlining) and removing a checked cast. The latter - * cannot be done directly in Java code as {@link DeferredPiNode} is not available to the project - * containing {@link Edges}. - */ -@ClassSubstitution(Edges.class) -public class EdgesSubstitutions { - - @MethodSubstitution - private static Node getNodeUnsafe(Node node, long offset) { - return PiNode.piCast(UnsafeLoadNode.load(node, offset, Kind.Object, LocationIdentity.ANY_LOCATION), Node.class); - } - - @MethodSubstitution - private static NodeList getNodeListUnsafe(Node node, long offset) { - return PiNode.piCast(UnsafeLoadNode.load(node, offset, Kind.Object, LocationIdentity.ANY_LOCATION), NodeList.class); - } -} diff -r 31fac91ea3b7 -r 14e703edb2ab graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/FloatSubstitutions.java --- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/FloatSubstitutions.java Wed Mar 11 17:16:30 2015 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,56 +0,0 @@ -/* - * Copyright (c) 2011, 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 com.oracle.graal.api.meta.*; -import com.oracle.graal.api.replacements.*; -import com.oracle.graal.nodes.calc.*; - -/** - * Substitutions for {@link java.lang.Float} methods. - */ -@ClassSubstitution(java.lang.Float.class) -public class FloatSubstitutions { - - private static final int NAN_RAW_INT_BITS = Float.floatToRawIntBits(Float.NaN); - - @MethodSubstitution - public static int floatToRawIntBits(float value) { - return ReinterpretNode.reinterpret(Kind.Int, value); - } - - // TODO This method is not necessary, since the JDK method does exactly this - @MethodSubstitution - public static int floatToIntBits(float value) { - if (value != value) { - return NAN_RAW_INT_BITS; - } else { - return floatToRawIntBits(value); - } - } - - @MethodSubstitution - public static float intBitsToFloat(int bits) { - return ReinterpretNode.reinterpret(Kind.Float, bits); - } -} diff -r 31fac91ea3b7 -r 14e703edb2ab graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/GraalDirectivesSubstitutions.java --- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/GraalDirectivesSubstitutions.java Wed Mar 11 17:16:30 2015 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,153 +0,0 @@ -/* - * Copyright (c) 2015, 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 com.oracle.graal.api.directives.*; -import com.oracle.graal.api.meta.*; -import com.oracle.graal.api.replacements.*; -import com.oracle.graal.nodes.*; -import com.oracle.graal.nodes.debug.*; -import com.oracle.graal.nodes.extended.*; -import com.oracle.graal.nodes.spi.*; - -@ClassSubstitution(GraalDirectives.class) -public class GraalDirectivesSubstitutions { - - @MethodSubstitution(forced = true) - public static void deoptimize() { - DeoptimizeNode.deopt(DeoptimizationAction.None, DeoptimizationReason.TransferToInterpreter); - } - - @MethodSubstitution(forced = true) - public static void deoptimizeAndInvalidate() { - DeoptimizeNode.deopt(DeoptimizationAction.InvalidateReprofile, DeoptimizationReason.TransferToInterpreter); - } - - @MethodSubstitution(forced = true) - public static boolean inCompiledCode() { - return true; - } - - /* - * This needs to be a @MacroSubstitution, not a @MethodSubstitution, because we want to get a - * unique ControlFlowAnchorNode for each occurrence of this call. With @MethodSubstitution, we - * would get a clone of a single cached node. - */ - @MacroSubstitution(forced = true, macro = ControlFlowAnchorNode.class) - public static native void controlFlowAnchor(); - - @MethodSubstitution(forced = true) - public static boolean injectBranchProbability(double probability, boolean condition) { - return BranchProbabilityNode.probability(probability, condition); - } - - @MethodSubstitution(forced = true) - public static void blackhole(boolean value) { - BlackholeNode.consume(value); - } - - @MethodSubstitution(forced = true) - public static void blackhole(byte value) { - BlackholeNode.consume(value); - } - - @MethodSubstitution(forced = true) - public static void blackhole(short value) { - BlackholeNode.consume(value); - } - - @MethodSubstitution(forced = true) - public static void blackhole(char value) { - BlackholeNode.consume(value); - } - - @MethodSubstitution(forced = true) - public static void blackhole(int value) { - BlackholeNode.consume(value); - } - - @MethodSubstitution(forced = true) - public static void blackhole(long value) { - BlackholeNode.consume(value); - } - - @MethodSubstitution(forced = true) - public static void blackhole(float value) { - BlackholeNode.consume(value); - } - - @MethodSubstitution(forced = true) - public static void blackhole(double value) { - BlackholeNode.consume(value); - } - - @MethodSubstitution(forced = true) - public static void blackhole(Object value) { - BlackholeNode.consume(value); - } - - @MethodSubstitution(forced = true) - public static boolean opaque(boolean value) { - return OpaqueNode.opaque(value); - } - - @MethodSubstitution(forced = true) - public static byte opaque(byte value) { - return OpaqueNode.opaque(value); - } - - @MethodSubstitution(forced = true) - public static short opaque(short value) { - return OpaqueNode.opaque(value); - } - - @MethodSubstitution(forced = true) - public static char opaque(char value) { - return OpaqueNode.opaque(value); - } - - @MethodSubstitution(forced = true) - public static int opaque(int value) { - return OpaqueNode.opaque(value); - } - - @MethodSubstitution(forced = true) - public static long opaque(long value) { - return OpaqueNode.opaque(value); - } - - @MethodSubstitution(forced = true) - public static float opaque(float value) { - return OpaqueNode.opaque(value); - } - - @MethodSubstitution(forced = true) - public static double opaque(double value) { - return OpaqueNode.opaque(value); - } - - @MethodSubstitution(forced = true) - public static T opaque(T value) { - return OpaqueNode.opaque(value); - } -} diff -r 31fac91ea3b7 -r 14e703edb2ab graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/GraalMethodSubstitutions.java --- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/GraalMethodSubstitutions.java Wed Mar 11 17:16:30 2015 +0100 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/GraalMethodSubstitutions.java Wed Mar 11 20:43:12 2015 +0100 @@ -28,13 +28,10 @@ import java.util.*; import com.oracle.graal.api.code.*; -import com.oracle.graal.api.directives.*; import com.oracle.graal.api.meta.*; import com.oracle.graal.api.replacements.*; import com.oracle.graal.api.runtime.*; -import com.oracle.graal.graph.*; import com.oracle.graal.nodes.spi.*; -import com.oracle.graal.options.*; /** * Method substitutions that are VM-independent. @@ -42,39 +39,14 @@ @ServiceProvider(ReplacementsProvider.class) public class GraalMethodSubstitutions implements ReplacementsProvider { - static class Options { - @Option(help = "") public static final OptionValue UseBlackholeSubstitution = new OptionValue<>(true); - } - public void registerReplacements(MetaAccessProvider metaAccess, LoweringProvider loweringProvider, SnippetReflectionProvider snippetReflection, Replacements replacements, TargetDescription target) { - BoxingSubstitutions.registerReplacements(replacements); - replacements.registerSubstitutions(GraalDirectives.class, GraalDirectivesSubstitutions.class); if (Intrinsify.getValue()) { replacements.registerSubstitutions(Arrays.class, ArraysSubstitutions.class); replacements.registerSubstitutions(Array.class, ArraySubstitutions.class); replacements.registerSubstitutions(String.class, StringSubstitutions.class); replacements.registerSubstitutions(Math.class, MathSubstitutionsX86.class); - replacements.registerSubstitutions(Double.class, DoubleSubstitutions.class); - replacements.registerSubstitutions(Float.class, FloatSubstitutions.class); replacements.registerSubstitutions(Long.class, LongSubstitutions.class); replacements.registerSubstitutions(Integer.class, IntegerSubstitutions.class); - replacements.registerSubstitutions(Character.class, CharacterSubstitutions.class); - replacements.registerSubstitutions(Short.class, ShortSubstitutions.class); - replacements.registerSubstitutions(UnsignedMath.class, UnsignedMathSubstitutions.class); - replacements.registerSubstitutions(Edges.class, EdgesSubstitutions.class); - replacements.registerSubstitutions(Class.class, ClassSubstitutions.class); - } - if (Options.UseBlackholeSubstitution.getValue()) { - replacements.registerSubstitutions(new Type() { - public String getTypeName() { - return "org.openjdk.jmh.infra.Blackhole"; - } - }, BlackholeSubstitutions.class); - replacements.registerSubstitutions(new Type() { - public String getTypeName() { - return "org.openjdk.jmh.logic.BlackHole"; - } - }, BlackholeSubstitutions.class); } } } diff -r 31fac91ea3b7 -r 14e703edb2ab graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/GraphKit.java --- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/GraphKit.java Wed Mar 11 17:16:30 2015 +0100 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/GraphKit.java Wed Mar 11 20:43:12 2015 +0100 @@ -27,13 +27,13 @@ import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; -import com.oracle.graal.api.replacements.*; import com.oracle.graal.graph.*; import com.oracle.graal.java.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.CallTargetNode.InvokeKind; import com.oracle.graal.nodes.calc.*; import com.oracle.graal.nodes.java.*; +import com.oracle.graal.nodes.type.*; import com.oracle.graal.phases.common.*; import com.oracle.graal.phases.common.inlining.*; import com.oracle.graal.phases.util.*; @@ -49,6 +49,7 @@ protected final Providers providers; protected final StructuredGraph graph; + protected final WordTypes wordTypes; protected FixedWithNextNode lastFixedNode; private final List structures; @@ -56,9 +57,10 @@ abstract static class Structure { } - public GraphKit(StructuredGraph graph, Providers providers) { + public GraphKit(StructuredGraph graph, Providers providers, WordTypes wordTypes) { this.providers = providers; this.graph = graph; + this.wordTypes = wordTypes; this.lastFixedNode = graph.start(); structures = new ArrayList<>(); @@ -77,14 +79,21 @@ * @return a node similar to {@code node} if one exists, otherwise {@code node} */ public T unique(T node) { - return graph.unique(node); + return graph.unique(changeToWord(node)); + } + + public T changeToWord(T node) { + if (wordTypes.isWord(node)) { + node.setStamp(wordTypes.getWordStamp(StampTool.typeOrNull(node))); + } + return node; } /** * Appends a fixed node to the graph. */ public T append(T node) { - T result = graph.add(node); + T result = graph.add(changeToWord(node)); assert lastFixedNode != null; assert result.predecessor() == null; graph.addAfterFixed(lastFixedNode, result); @@ -135,11 +144,11 @@ if (frameStateBuilder != null) { if (invoke.getKind() != Kind.Void) { - frameStateBuilder.push(invoke.getKind(), invoke); + frameStateBuilder.push(returnType.getKind(), invoke); } invoke.setStateAfter(frameStateBuilder.create(bci)); if (invoke.getKind() != Kind.Void) { - frameStateBuilder.pop(invoke.getKind()); + frameStateBuilder.pop(returnType.getKind()); } } return invoke; @@ -162,15 +171,15 @@ if (signature.getParameterCount(!isStatic) != args.length) { throw new AssertionError(graph + ": wrong number of arguments to " + method); } - int paramNum = 0; - for (int i = 0; i != args.length; i++) { - Kind expected; - if (i == 0 && !isStatic) { - expected = Kind.Object; - } else { - expected = signature.getParameterKind(paramNum++).getStackKind(); - } - Kind actual = args[i].stamp().getStackKind(); + int argIndex = 0; + if (!isStatic) { + Kind expected = wordTypes.asKind(method.getDeclaringClass()); + Kind actual = args[argIndex++].stamp().getStackKind(); + assert expected == actual : graph + ": wrong kind of value for receiver argument of call to " + method + " [" + actual + " != " + expected + "]"; + } + for (int i = 0; i != signature.getParameterCount(false); i++) { + Kind expected = wordTypes.asKind(signature.getParameterType(i, method.getDeclaringClass())).getStackKind(); + Kind actual = args[argIndex++].stamp().getStackKind(); if (expected != actual) { throw new AssertionError(graph + ": wrong kind of value for argument " + i + " of call to " + method + " [" + actual + " != " + expected + "]"); } @@ -179,19 +188,12 @@ } /** - * Rewrite all word types in the graph. - */ - public void rewriteWordTypes(SnippetReflectionProvider snippetReflection) { - new WordTypeRewriterPhase(providers.getMetaAccess(), snippetReflection, providers.getConstantReflection(), providers.getCodeCache().getTarget().wordKind).apply(graph); - } - - /** * Recursively {@linkplain #inline inlines} all invocations currently in the graph. */ - public void inlineInvokes(SnippetReflectionProvider snippetReflection) { + public void inlineInvokes() { while (!graph.getNodes().filter(InvokeNode.class).isEmpty()) { for (InvokeNode invoke : graph.getNodes().filter(InvokeNode.class).snapshot()) { - inline(invoke, snippetReflection); + inline(invoke); } } @@ -204,10 +206,10 @@ * {@linkplain ReplacementsImpl#makeGraph processed} in the same manner as for snippets and * method substitutions. */ - public void inline(InvokeNode invoke, SnippetReflectionProvider snippetReflection) { + public void inline(InvokeNode invoke) { ResolvedJavaMethod method = ((MethodCallTargetNode) invoke.callTarget()).targetMethod(); - ReplacementsImpl repl = new ReplacementsImpl(providers, snippetReflection, providers.getCodeCache().getTarget()); - StructuredGraph calleeGraph = repl.makeGraph(method, null, null, FrameStateProcessing.CollapseFrameForSingleSideEffect); + ReplacementsImpl replacements = (ReplacementsImpl) providers.getReplacements(); + StructuredGraph calleeGraph = replacements.makeGraph(method, null, null, null, FrameStateProcessing.CollapseFrameForSingleSideEffect); InliningUtil.inline(invoke, calleeGraph, false, null); } diff -r 31fac91ea3b7 -r 14e703edb2ab graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/IntegerSubstitutions.java --- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/IntegerSubstitutions.java Wed Mar 11 17:16:30 2015 +0100 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/IntegerSubstitutions.java Wed Mar 11 20:43:12 2015 +0100 @@ -23,18 +23,12 @@ package com.oracle.graal.replacements; import com.oracle.graal.api.replacements.*; -import com.oracle.graal.nodes.calc.*; import com.oracle.graal.replacements.nodes.*; @ClassSubstitution(Integer.class) public class IntegerSubstitutions { @MethodSubstitution - public static int reverseBytes(int i) { - return ReverseBytesNode.reverse(i); - } - - @MethodSubstitution public static int numberOfLeadingZeros(int i) { if (i == 0) { return 32; @@ -49,19 +43,4 @@ } return BitScanForwardNode.unsafeScan(i); } - - @MethodSubstitution - public static int bitCount(int i) { - return BitCountNode.bitCount(i); - } - - @MethodSubstitution - public static int divideUnsigned(int dividend, int divisor) { - return UnsignedDivNode.unsignedDivide(dividend, divisor); - } - - @MethodSubstitution - public static int remainderUnsigned(int dividend, int divisor) { - return UnsignedRemNode.unsignedRemainder(dividend, divisor); - } } diff -r 31fac91ea3b7 -r 14e703edb2ab graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/LongSubstitutions.java --- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/LongSubstitutions.java Wed Mar 11 17:16:30 2015 +0100 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/LongSubstitutions.java Wed Mar 11 20:43:12 2015 +0100 @@ -23,18 +23,12 @@ package com.oracle.graal.replacements; import com.oracle.graal.api.replacements.*; -import com.oracle.graal.nodes.calc.*; import com.oracle.graal.replacements.nodes.*; @ClassSubstitution(Long.class) public class LongSubstitutions { @MethodSubstitution - public static long reverseBytes(long i) { - return ReverseBytesNode.reverse(i); - } - - @MethodSubstitution public static int numberOfLeadingZeros(long i) { if (i == 0) { return 64; @@ -49,19 +43,4 @@ } return BitScanForwardNode.unsafeScan(i); } - - @MethodSubstitution - public static int bitCount(long i) { - return BitCountNode.bitCount(i); - } - - @MethodSubstitution - public static long divideUnsigned(long dividend, long divisor) { - return UnsignedDivNode.unsignedDivide(dividend, divisor); - } - - @MethodSubstitution - public static long remainderUnsigned(long dividend, long divisor) { - return UnsignedRemNode.unsignedRemainder(dividend, divisor); - } } diff -r 31fac91ea3b7 -r 14e703edb2ab graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/MathSubstitutionsX86.java --- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/MathSubstitutionsX86.java Wed Mar 11 17:16:30 2015 +0100 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/MathSubstitutionsX86.java Wed Mar 11 20:43:12 2015 +0100 @@ -26,7 +26,6 @@ import com.oracle.graal.api.replacements.*; import com.oracle.graal.graph.Node.ConstantNodeParameter; import com.oracle.graal.graph.Node.NodeIntrinsic; -import com.oracle.graal.nodes.calc.*; import com.oracle.graal.nodes.extended.*; import com.oracle.graal.nodes.spi.*; import com.oracle.graal.replacements.nodes.*; @@ -40,36 +39,11 @@ private static final double PI_4 = Math.PI / 4; - @MethodSubstitution - public static float abs(float x) { - return AbsNode.abs(x); - } - - @MethodSubstitution - public static double abs(double x) { - return AbsNode.abs(x); - } - - @MethodSubstitution - public static double sqrt(double x) { - return SqrtNode.sqrt(x); - } - - @MethodSubstitution(guard = UnsafeSubstitutions.GetAndSetGuard.class) - public static double log(double x) { - return MathIntrinsicNode.compute(x, Operation.LOG); - } - - @MethodSubstitution(guard = UnsafeSubstitutions.GetAndSetGuard.class) - public static double log10(double x) { - return MathIntrinsicNode.compute(x, Operation.LOG10); - } - /** * Special cases from {@link Math#pow} and __ieee754_pow (in sharedRuntimeTrans.cpp). */ @MacroSubstitution(macro = MathPowNode.class) - @MethodSubstitution(guard = UnsafeSubstitutions.GetAndSetGuard.class) + @MethodSubstitution(guard = MathGuard.class) public static double pow(double x, double y) { // If the second argument is positive or negative zero, then the result is 1.0. if (y == 0) { @@ -103,7 +77,7 @@ // x**0.5 = sqrt(x) if (y == 0.5 && x >= 0) { - return sqrt(x); + return Math.sqrt(x); } return pow(x, y); @@ -115,46 +89,45 @@ // accurate within [-pi/4, pi/4]. Examine the passed value and provide // a slow path for inputs outside of that interval. - @MethodSubstitution(guard = UnsafeSubstitutions.GetAndSetGuard.class) + @MethodSubstitution(guard = MathGuard.class) public static double sin(double x) { - if (abs(x) < PI_4) { + if (Math.abs(x) < PI_4) { return MathIntrinsicNode.compute(x, Operation.SIN); } else { return callDouble(ARITHMETIC_SIN, x); } } - @MethodSubstitution(guard = UnsafeSubstitutions.GetAndSetGuard.class) + @MethodSubstitution(guard = MathGuard.class) public static double cos(double x) { - if (abs(x) < PI_4) { + if (Math.abs(x) < PI_4) { return MathIntrinsicNode.compute(x, Operation.COS); } else { return callDouble(ARITHMETIC_COS, x); } } - @MethodSubstitution(guard = UnsafeSubstitutions.GetAndSetGuard.class) + @MethodSubstitution(guard = MathGuard.class) public static double tan(double x) { - if (abs(x) < PI_4) { + if (Math.abs(x) < PI_4) { return MathIntrinsicNode.compute(x, Operation.TAN); } else { return callDouble(ARITHMETIC_TAN, x); } } + public static class MathGuard implements SubstitutionGuard { + public boolean execute() { + // FIXME should return whether the current compilation target supports these + String arch = System.getProperty("os.arch"); + return arch.equals("amd64") || arch.equals("x86_64"); + } + } + public static final ForeignCallDescriptor ARITHMETIC_SIN = new ForeignCallDescriptor("arithmeticSin", double.class, double.class); public static final ForeignCallDescriptor ARITHMETIC_COS = new ForeignCallDescriptor("arithmeticCos", double.class, double.class); public static final ForeignCallDescriptor ARITHMETIC_TAN = new ForeignCallDescriptor("arithmeticTan", double.class, double.class); @NodeIntrinsic(value = ForeignCallNode.class, setStampFromReturnType = true) - public static double callDouble(@ConstantNodeParameter ForeignCallDescriptor descriptor, double value) { - if (descriptor == ARITHMETIC_SIN) { - return Math.sin(value); - } - if (descriptor == ARITHMETIC_COS) { - return Math.cos(value); - } - assert descriptor == ARITHMETIC_TAN; - return Math.tan(value); - } + public static native double callDouble(@ConstantNodeParameter ForeignCallDescriptor descriptor, double value); } diff -r 31fac91ea3b7 -r 14e703edb2ab graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/NodeIntrinsificationPhase.java --- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/NodeIntrinsificationPhase.java Wed Mar 11 17:16:30 2015 +0100 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/NodeIntrinsificationPhase.java Wed Mar 11 20:43:12 2015 +0100 @@ -259,7 +259,7 @@ return reflectionCallArguments; } - private ResolvedJavaType getNodeClass(ResolvedJavaMethod target, NodeIntrinsic intrinsic) { + public ResolvedJavaType getNodeClass(ResolvedJavaMethod target, NodeIntrinsic intrinsic) { ResolvedJavaType result; if (intrinsic.value() == NodeIntrinsic.class) { result = target.getDeclaringClass(); @@ -283,6 +283,10 @@ if (constructor == null) { constructor = c; arguments = match; + if (!Debug.isEnabled()) { + // Don't verify there's a unique match in non-debug mode + break; + } } else { throw new GraalInternalError("Found multiple constructors in %s compatible with signature %s: %s, %s", nodeClass.toJavaName(), sigString(parameterTypes), constructor, c); } @@ -358,14 +362,14 @@ throw new GraalInternalError("Cannot handle injected argument of type %s in %s", signature[i].toJavaName(), c.format("%H.%n(%p)")); } } else { - if (i > 0) { - // Chop injected arguments from signature - signature = Arrays.copyOfRange(signature, i, signature.length); - } assert checkNoMoreInjected(c, i); break; } } + if (injected != null) { + // Chop injected arguments from signature + signature = Arrays.copyOfRange(signature, injected.length, signature.length); + } if (Arrays.equals(parameterTypes, signature)) { // Exact match diff -r 31fac91ea3b7 -r 14e703edb2ab graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/ReplacementsImpl.java --- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/ReplacementsImpl.java Wed Mar 11 17:16:30 2015 +0100 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/ReplacementsImpl.java Wed Mar 11 20:43:12 2015 +0100 @@ -44,6 +44,7 @@ import com.oracle.graal.graph.Graph.Mark; import com.oracle.graal.graph.*; import com.oracle.graal.java.*; +import com.oracle.graal.java.GraphBuilderConfiguration.Plugins; import com.oracle.graal.java.GraphBuilderPhase.Instance; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.StructuredGraph.AllowAssumptions; @@ -56,7 +57,6 @@ import com.oracle.graal.phases.util.*; import com.oracle.graal.replacements.Snippet.DefaultSnippetInliningPolicy; import com.oracle.graal.replacements.Snippet.SnippetInliningPolicy; -import com.oracle.graal.word.phases.*; public class ReplacementsImpl implements Replacements { @@ -64,12 +64,17 @@ public final SnippetReflectionProvider snippetReflection; public final TargetDescription target; public final NodeIntrinsificationPhase nodeIntrinsificationPhase; + private GraphBuilderConfiguration.Plugins graphBuilderPlugins; /** * The preprocessed replacement graphs. */ protected final ConcurrentMap graphs; + public void completeInitialization(GraphBuilderConfiguration.Plugins plugins) { + this.graphBuilderPlugins = plugins; + } + /** * Encapsulates method and macro substitutions for a single class. */ @@ -252,12 +257,12 @@ return null; } - public StructuredGraph getSnippet(ResolvedJavaMethod method) { - return getSnippet(method, null); + public StructuredGraph getSnippet(ResolvedJavaMethod method, Object[] args) { + return getSnippet(method, null, args); } @Override - public StructuredGraph getSnippet(ResolvedJavaMethod method, ResolvedJavaMethod recursiveEntry) { + public StructuredGraph getSnippet(ResolvedJavaMethod method, ResolvedJavaMethod recursiveEntry, Object[] args) { assert method.getAnnotation(Snippet.class) != null : "Snippet must be annotated with @" + Snippet.class.getSimpleName(); assert method.hasBytecodes() : "Snippet must not be abstract or native"; @@ -266,9 +271,9 @@ try (DebugCloseable a = SnippetPreparationTime.start()) { FrameStateProcessing frameStateProcessing = method.getAnnotation(Snippet.class).removeAllFrameStates() ? FrameStateProcessing.Removal : FrameStateProcessing.CollapseFrameForSingleSideEffect; - StructuredGraph newGraph = makeGraph(method, recursiveEntry, inliningPolicy(method), frameStateProcessing); + StructuredGraph newGraph = makeGraph(method, args, recursiveEntry, inliningPolicy(method), frameStateProcessing); Debug.metric("SnippetNodeCount[%#s]", method).add(newGraph.getNodeCount()); - if (!UseSnippetGraphCache) { + if (!UseSnippetGraphCache || args != null) { return newGraph; } graphs.putIfAbsent(method, newGraph); @@ -306,7 +311,7 @@ } StructuredGraph graph = graphs.get(substitute); if (graph == null) { - graph = makeGraph(substitute, original, inliningPolicy(substitute), FrameStateProcessing.None); + graph = makeGraph(substitute, null, original, inliningPolicy(substitute), FrameStateProcessing.None); graph.freeze(); graphs.putIfAbsent(substitute, graph); graph = graphs.get(substitute); @@ -425,7 +430,7 @@ } } - protected SnippetInliningPolicy inliningPolicy(ResolvedJavaMethod method) { + public SnippetInliningPolicy inliningPolicy(ResolvedJavaMethod method) { Class policyClass = SnippetInliningPolicy.class; Snippet snippet = method.getAnnotation(Snippet.class); if (snippet != null) { @@ -441,13 +446,14 @@ * Creates a preprocessed graph for a snippet or method substitution. * * @param method the snippet or method substitution for which a graph will be created + * @param args * @param original the original method if {@code method} is a {@linkplain MethodSubstitution * substitution} otherwise null * @param policy the inlining policy to use during preprocessing * @param frameStateProcessing controls how {@link FrameState FrameStates} should be handled. */ - public StructuredGraph makeGraph(ResolvedJavaMethod method, ResolvedJavaMethod original, SnippetInliningPolicy policy, FrameStateProcessing frameStateProcessing) { - return createGraphMaker(method, original, frameStateProcessing).makeGraph(policy); + public StructuredGraph makeGraph(ResolvedJavaMethod method, Object[] args, ResolvedJavaMethod original, SnippetInliningPolicy policy, FrameStateProcessing frameStateProcessing) { + return createGraphMaker(method, original, frameStateProcessing).makeGraph(args, policy); } /** @@ -464,7 +470,13 @@ public enum FrameStateProcessing { None, + /** + * @see CollapseFrameForSingleSideEffectPhase + */ CollapseFrameForSingleSideEffect, + /** + * Removes frame states from all nodes in the graph. + */ Removal } @@ -513,12 +525,14 @@ this.frameStateProcessing = frameStateProcessing; } - public StructuredGraph makeGraph(final SnippetInliningPolicy policy) { + public StructuredGraph makeGraph(Object[] args, final SnippetInliningPolicy policy) { try (Scope s = Debug.scope("BuildSnippetGraph", method)) { - StructuredGraph graph = parseGraph(method, policy, 0); + StructuredGraph graph = parseGraph(method, args, policy, 0); - // Cannot have a finalized version of a graph in the cache - graph = graph.copy(); + if (args == null) { + // Cannot have a finalized version of a graph in the cache + graph = graph.copy(); + } finalizeGraph(graph); @@ -589,18 +603,21 @@ private static final int MAX_GRAPH_INLINING_DEPTH = 100; // more than enough - private StructuredGraph parseGraph(final ResolvedJavaMethod methodToParse, final SnippetInliningPolicy policy, int inliningDepth) { - StructuredGraph graph = replacements.graphCache.get(methodToParse); + private StructuredGraph parseGraph(final ResolvedJavaMethod methodToParse, Object[] args, final SnippetInliningPolicy policy, int inliningDepth) { + StructuredGraph graph = args == null ? replacements.graphCache.get(methodToParse) : null; if (graph == null) { StructuredGraph newGraph = null; try (Scope s = Debug.scope("ParseGraph", methodToParse)) { - newGraph = buildGraph(methodToParse, policy == null ? replacements.inliningPolicy(methodToParse) : policy, inliningDepth); + newGraph = buildGraph(methodToParse, args, policy == null ? replacements.inliningPolicy(methodToParse) : policy, inliningDepth); } catch (Throwable e) { throw Debug.handle(e); } - - replacements.graphCache.putIfAbsent(methodToParse, newGraph); - graph = replacements.graphCache.get(methodToParse); + if (args == null) { + replacements.graphCache.putIfAbsent(methodToParse, newGraph); + graph = replacements.graphCache.get(methodToParse); + } else { + graph = newGraph; + } assert graph != null; } return graph; @@ -609,7 +626,7 @@ /** * Builds the initial graph for a snippet. */ - protected StructuredGraph buildInitialGraph(final ResolvedJavaMethod methodToParse) { + protected StructuredGraph buildInitialGraph(final ResolvedJavaMethod methodToParse, Object[] args) { // Replacements cannot have optimistic assumptions since they have // to be valid for the entire run of the VM. final StructuredGraph graph = new StructuredGraph(methodToParse, AllowAssumptions.NO); @@ -623,8 +640,13 @@ if (MethodsElidedInSnippets != null && methodToParse.getSignature().getReturnKind() == Kind.Void && MethodFilter.matches(MethodsElidedInSnippets, methodToParse)) { graph.addAfterFixed(graph.start(), graph.add(new ReturnNode(null))); } else { - createGraphBuilder(metaAccess, replacements.providers.getStampProvider(), replacements.providers.getConstantReflection(), GraphBuilderConfiguration.getSnippetDefault(), - OptimisticOptimizations.NONE).apply(graph); + GraphBuilderConfiguration config = GraphBuilderConfiguration.getSnippetDefault(); + Plugins plugins = config.getPlugins().updateFrom(replacements.graphBuilderPlugins, false); + plugins.getInvocationPlugins().setDefaults(replacements.graphBuilderPlugins.getInvocationPlugins()); + if (args != null) { + plugins.setParameterPlugin(new ConstantBindingParameterPlugin(args, plugins.getParameterPlugin(), metaAccess, replacements.snippetReflection)); + } + createGraphBuilder(metaAccess, replacements.providers.getStampProvider(), replacements.providers.getConstantReflection(), config, OptimisticOptimizations.NONE).apply(graph); } afterParsing(graph); @@ -639,13 +661,14 @@ protected Instance createGraphBuilder(MetaAccessProvider metaAccess, StampProvider stampProvider, ConstantReflectionProvider constantReflection, GraphBuilderConfiguration graphBuilderConfig, OptimisticOptimizations optimisticOpts) { - return new GraphBuilderPhase.Instance(metaAccess, stampProvider, constantReflection, graphBuilderConfig, optimisticOpts, true); + ResolvedJavaMethod rootMethodIsReplacement = substitutedMethod == null ? method : substitutedMethod; + return new GraphBuilderPhase.Instance(metaAccess, stampProvider, constantReflection, graphBuilderConfig, optimisticOpts, rootMethodIsReplacement); } + /** + * @param graph + */ protected void afterParsing(StructuredGraph graph) { - MetaAccessProvider metaAccess = replacements.providers.getMetaAccess(); - new WordTypeVerificationPhase(metaAccess, replacements.snippetReflection, replacements.providers.getConstantReflection(), replacements.target.wordKind).apply(graph); - new WordTypeRewriterPhase(metaAccess, replacements.snippetReflection, replacements.providers.getConstantReflection(), replacements.target.wordKind).apply(graph); } protected Object beforeInline(@SuppressWarnings("unused") MethodCallTargetNode callTarget, @SuppressWarnings("unused") StructuredGraph callee) { @@ -676,10 +699,10 @@ } } - private StructuredGraph buildGraph(final ResolvedJavaMethod methodToParse, final SnippetInliningPolicy policy, int inliningDepth) { + private StructuredGraph buildGraph(final ResolvedJavaMethod methodToParse, Object[] args, final SnippetInliningPolicy policy, int inliningDepth) { assert inliningDepth < MAX_GRAPH_INLINING_DEPTH : "inlining limit exceeded"; assert methodToParse.hasBytecodes() : methodToParse; - final StructuredGraph graph = buildInitialGraph(methodToParse); + final StructuredGraph graph = buildInitialGraph(methodToParse, args); try (Scope s = Debug.scope("buildGraph", graph)) { Set doNotInline = null; for (MethodCallTargetNode callTarget : graph.getNodes(MethodCallTargetNode.TYPE)) { @@ -693,7 +716,7 @@ * calling it instead of the Graal substitution. */ if (substitutedMethod.hasBytecodes()) { - final StructuredGraph originalGraph = buildInitialGraph(substitutedMethod); + final StructuredGraph originalGraph = buildInitialGraph(substitutedMethod, null); Mark mark = graph.getMark(); InliningUtil.inline(callTarget.invoke(), originalGraph, true, null); for (MethodCallTargetNode inlinedCallTarget : graph.getNewNodes(mark).filter(MethodCallTargetNode.class)) { @@ -725,7 +748,7 @@ " while preparing replacement " + method.format("%H.%n(%p)") + ". Placing \"//JaCoCo Exclude\" anywhere in " + methodToParse.getDeclaringClass().getSourceFileName() + " should fix this."); } - targetGraph = parseGraph(callee, policy, inliningDepth + 1); + targetGraph = parseGraph(callee, null, policy, inliningDepth + 1); } Object beforeInlineData = beforeInline(callTarget, targetGraph); InliningUtil.inline(callTarget.invoke(), targetGraph, true, null); @@ -765,7 +788,7 @@ * @param optional if true, resolution failure returns null * @return the resolved class or null if resolution fails and {@code optional} is true */ - static Class resolveClass(String className, boolean optional) { + public static Class resolveClass(String className, boolean optional) { try { // Need to use launcher class path to handle classes // that are not on the boot class path diff -r 31fac91ea3b7 -r 14e703edb2ab graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/ShortSubstitutions.java --- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/ShortSubstitutions.java Wed Mar 11 17:16:30 2015 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,34 +0,0 @@ -/* - * Copyright (c) 2014, 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 com.oracle.graal.api.replacements.*; -import com.oracle.graal.replacements.nodes.*; - -@ClassSubstitution(Short.class) -public class ShortSubstitutions { - @MethodSubstitution - public static short reverseBytes(short i) { - return (short) (ReverseBytesNode.reverse(i) >> 16); - } -} diff -r 31fac91ea3b7 -r 14e703edb2ab graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/SnippetTemplate.java --- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/SnippetTemplate.java Wed Mar 11 17:16:30 2015 +0100 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/SnippetTemplate.java Wed Mar 11 20:43:12 2015 +0100 @@ -483,7 +483,7 @@ } } - private static Method findMethod(Class declaringClass, String methodName, Method except) { + public static Method findMethod(Class declaringClass, String methodName, Method except) { for (Method m : declaringClass.getDeclaredMethods()) { if (m.getName().equals(methodName) && !m.equals(except)) { return m; @@ -555,8 +555,8 @@ */ protected SnippetTemplate(final Providers providers, SnippetReflectionProvider snippetReflection, Arguments args) { this.snippetReflection = snippetReflection; - - StructuredGraph snippetGraph = providers.getReplacements().getSnippet(args.info.method); + Object[] constantArgs = getConstantArgs(args); + StructuredGraph snippetGraph = providers.getReplacements().getSnippet(args.info.method, constantArgs); instantiationTimer = Debug.timer("SnippetTemplateInstantiationTime[%#s]", args); instantiationCounter = Debug.metric("SnippetTemplateInstantiationCount[%#s]", args); @@ -773,6 +773,16 @@ Debug.dump(snippet, "SnippetTemplate final state"); } + protected Object[] getConstantArgs(Arguments args) { + Object[] constantArgs = args.values.clone(); + for (int i = 0; i < args.info.getParameterCount(); i++) { + if (!args.info.isConstantParameter(i)) { + constantArgs[i] = null; + } + } + return constantArgs; + } + private static boolean checkAllVarargPlaceholdersAreDeleted(int parameterCount, VarargsPlaceholderNode[] placeholders) { for (int i = 0; i < parameterCount; i++) { if (placeholders[i] != null) { diff -r 31fac91ea3b7 -r 14e703edb2ab graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/StandardGraphBuilderPlugins.java --- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/StandardGraphBuilderPlugins.java Wed Mar 11 17:16:30 2015 +0100 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/StandardGraphBuilderPlugins.java Wed Mar 11 20:43:12 2015 +0100 @@ -24,11 +24,14 @@ import static com.oracle.graal.api.code.MemoryBarriers.*; import static com.oracle.graal.java.GraphBuilderContext.*; -import static java.lang.Character.*; +import static com.oracle.graal.replacements.nodes.MathIntrinsicNode.Operation.*; import sun.misc.*; +import com.oracle.graal.api.code.*; import com.oracle.graal.api.directives.*; import com.oracle.graal.api.meta.*; +import com.oracle.graal.compiler.common.calc.*; +import com.oracle.graal.graph.*; import com.oracle.graal.java.*; import com.oracle.graal.java.GraphBuilderPlugin.InvocationPlugin; import com.oracle.graal.java.InvocationPlugins.Registration; @@ -38,6 +41,7 @@ import com.oracle.graal.nodes.debug.*; import com.oracle.graal.nodes.extended.*; import com.oracle.graal.nodes.java.*; +import com.oracle.graal.options.*; import com.oracle.graal.replacements.nodes.*; /** @@ -45,54 +49,291 @@ */ public class StandardGraphBuilderPlugins { - public static void registerInvocationPlugins(MetaAccessProvider metaAccess, InvocationPlugins plugins) { + // @formatter:off + static class Options { + @Option(help = "Enable use of intrinsics for the JMH Blackhole class") + public static final OptionValue UseBlackholeSubstitution = new OptionValue<>(true); + } + // @formatter:on + + public static void registerInvocationPlugins(MetaAccessProvider metaAccess, Architecture arch, InvocationPlugins plugins, boolean useBoxingPlugins) { registerObjectPlugins(metaAccess, plugins); - registerMathPlugins(metaAccess, plugins); - registerUnsafePlugins(metaAccess, plugins); + registerClassPlugins(metaAccess, plugins); + registerMathPlugins(metaAccess, arch, plugins); + registerUnsignedMathPlugins(metaAccess, plugins); + registerCharacterPlugins(metaAccess, plugins); + registerShortPlugins(metaAccess, plugins); + registerIntegerLongPlugins(metaAccess, plugins, Kind.Int); + registerIntegerLongPlugins(metaAccess, plugins, Kind.Long); + registerFloatPlugins(metaAccess, plugins); + registerDoublePlugins(metaAccess, plugins); + registerUnsafePlugins(metaAccess, arch, plugins); + registerEdgesPlugins(metaAccess, plugins); registerGraalDirectivesPlugins(metaAccess, plugins); + if (useBoxingPlugins) { + registerBoxingPlugins(metaAccess, plugins); + } + if (Options.UseBlackholeSubstitution.getValue()) { + registerJMHBlackholePlugins(metaAccess, plugins); + } } - private static void registerUnsafePlugins(MetaAccessProvider metaAccess, InvocationPlugins plugins) { + private static void registerUnsafePlugins(MetaAccessProvider metaAccess, Architecture arch, InvocationPlugins plugins) { Registration r = new Registration(plugins, metaAccess, Unsafe.class); for (Kind kind : Kind.values()) { if ((kind.isPrimitive() && kind != Kind.Void) || kind == Kind.Object) { - String kindName = kind.getJavaName(); - kindName = toUpperCase(kindName.charAt(0)) + kindName.substring(1); + Class javaClass = kind == Kind.Object ? Object.class : kind.toJavaClass(); + String kindName = kind.name(); String getName = "get" + kindName; String putName = "put" + kindName; + // Object-based accesses r.register3(getName, Receiver.class, Object.class, long.class, new UnsafeGetPlugin(kind, false)); - r.register4(putName, Receiver.class, Object.class, long.class, kind == Kind.Object ? Object.class : kind.toJavaClass(), new UnsafePutPlugin(kind, false)); + r.register4(putName, Receiver.class, Object.class, long.class, javaClass, new UnsafePutPlugin(kind, false)); + // Volatile object-based accesses r.register3(getName + "Volatile", Receiver.class, Object.class, long.class, new UnsafeGetPlugin(kind, true)); - r.register4(putName + "Volatile", Receiver.class, Object.class, long.class, kind == Kind.Object ? Object.class : kind.toJavaClass(), new UnsafePutPlugin(kind, true)); + r.register4(putName + "Volatile", Receiver.class, Object.class, long.class, javaClass, new UnsafePutPlugin(kind, true)); + // Ordered object-based accesses + if (kind == Kind.Int || kind == Kind.Long || kind == Kind.Object) { + r.register4("putOrdered" + kindName, Receiver.class, Object.class, long.class, javaClass, new UnsafePutPlugin(kind, true)); + } if (kind != Kind.Boolean && kind != Kind.Object) { + // Raw accesses to memory addresses r.register2(getName, Receiver.class, long.class, new UnsafeGetPlugin(kind, false)); r.register3(putName, Receiver.class, long.class, kind.toJavaClass(), new UnsafePutPlugin(kind, false)); } } } + + for (Kind kind : new Kind[]{Kind.Int, Kind.Long, Kind.Object}) { + Class javaClass = kind == Kind.Object ? Object.class : kind.toJavaClass(); + r.register5("compareAndSwap" + kind.name(), Receiver.class, Object.class, long.class, javaClass, javaClass, new InvocationPlugin() { + public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, ValueNode ignoredUnsafe, ValueNode object, ValueNode offset, ValueNode expected, ValueNode x) { + b.push(Kind.Boolean.getStackKind(), b.append(new CompareAndSwapNode(object, offset, expected, x, kind, LocationIdentity.ANY_LOCATION))); + return true; + } + }); + + if (getAndSetEnabled(arch)) { + r.register4("getAndSet" + kind.name(), Receiver.class, Object.class, long.class, javaClass, new InvocationPlugin() { + public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, ValueNode ignoredUnsafe, ValueNode object, ValueNode offset, ValueNode value) { + b.push(kind.getStackKind(), b.append(new AtomicReadAndWriteNode(object, offset, value, kind, LocationIdentity.ANY_LOCATION))); + return true; + } + }); + if (kind != Kind.Object) { + r.register4("getAndAdd" + kind.name(), Receiver.class, Object.class, long.class, javaClass, new InvocationPlugin() { + public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, ValueNode ignoredUnsafe, ValueNode object, ValueNode offset, ValueNode delta) { + b.push(kind.getStackKind(), b.append(new AtomicReadAndAddNode(object, offset, delta, LocationIdentity.ANY_LOCATION))); + return true; + } + }); + } + } + } + } + + /** + * Determines if the platform includes such for intrinsifying the {@link Unsafe#getAndSetInt} + * method family. + */ + public static boolean getAndSetEnabled(Architecture arch) { + // FIXME should return whether the current compilation target supports these + return arch.getName().equals("AMD64"); } - private static void registerMathPlugins(MetaAccessProvider metaAccess, InvocationPlugins plugins) { + private static void registerIntegerLongPlugins(MetaAccessProvider metaAccess, InvocationPlugins plugins, Kind kind) { + Class declaringClass = kind.toBoxedJavaClass(); + Class type = kind.toJavaClass(); + Registration r = new Registration(plugins, metaAccess, declaringClass); + r.register1("reverseBytes", type, new InvocationPlugin() { + public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, ValueNode value) { + b.push(kind, b.append(new ReverseBytesNode(value).canonical(null, value))); + return true; + } + }); + r.register1("bitCount", type, new InvocationPlugin() { + public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, ValueNode value) { + b.push(Kind.Int, b.append(new BitCountNode(value).canonical(null, value))); + return true; + } + }); + r.register2("divideUnsigned", type, type, new InvocationPlugin() { + public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, ValueNode dividend, ValueNode divisor) { + b.push(kind, b.append(new UnsignedDivNode(dividend, divisor).canonical(null, dividend, divisor))); + return true; + } + }); + r.register2("remainderUnsigned", type, type, new InvocationPlugin() { + public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, ValueNode dividend, ValueNode divisor) { + b.push(kind, b.append(new UnsignedDivNode(dividend, divisor).canonical(null, dividend, divisor))); + return true; + } + }); + } + + private static void registerCharacterPlugins(MetaAccessProvider metaAccess, InvocationPlugins plugins) { + Registration r = new Registration(plugins, metaAccess, Character.class); + r.register1("reverseBytes", char.class, new InvocationPlugin() { + public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, ValueNode value) { + // return (char) (Integer.reverse(i) >> 16); + ReverseBytesNode reverse = b.append(new ReverseBytesNode(value)); + RightShiftNode rightShift = b.append(new RightShiftNode(reverse, b.append(ConstantNode.forInt(16)))); + ZeroExtendNode charCast = b.append(new ZeroExtendNode(b.append(new NarrowNode(rightShift, 16)), 32)); + b.push(Kind.Char.getStackKind(), b.append(charCast.canonical(null, value))); + return true; + } + }); + } + + private static void registerShortPlugins(MetaAccessProvider metaAccess, InvocationPlugins plugins) { + Registration r = new Registration(plugins, metaAccess, Short.class); + r.register1("reverseBytes", short.class, new InvocationPlugin() { + public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, ValueNode value) { + // return (short) (Integer.reverse(i) >> 16); + ReverseBytesNode reverse = b.append(new ReverseBytesNode(value)); + RightShiftNode rightShift = b.append(new RightShiftNode(reverse, b.append(ConstantNode.forInt(16)))); + SignExtendNode charCast = b.append(new SignExtendNode(b.append(new NarrowNode(rightShift, 16)), 32)); + b.push(Kind.Short.getStackKind(), b.append(charCast.canonical(null, value))); + return true; + } + }); + } + + private static void registerFloatPlugins(MetaAccessProvider metaAccess, InvocationPlugins plugins) { + Registration r = new Registration(plugins, metaAccess, Float.class); + r.register1("floatToRawIntBits", float.class, new InvocationPlugin() { + public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, ValueNode value) { + b.push(Kind.Int, b.append(new ReinterpretNode(Kind.Int, value).canonical(null, value))); + return true; + } + }); + r.register1("intBitsToFloat", int.class, new InvocationPlugin() { + public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, ValueNode value) { + b.push(Kind.Float, b.append(new ReinterpretNode(Kind.Float, value).canonical(null, value))); + return true; + } + }); + } + + private static void registerDoublePlugins(MetaAccessProvider metaAccess, InvocationPlugins plugins) { + Registration r = new Registration(plugins, metaAccess, Double.class); + r.register1("doubleToRawLongBits", double.class, new InvocationPlugin() { + public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, ValueNode value) { + b.push(Kind.Long, b.append(new ReinterpretNode(Kind.Long, value).canonical(null, value))); + return true; + } + }); + r.register1("longBitsToDouble", long.class, new InvocationPlugin() { + public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, ValueNode value) { + b.push(Kind.Double, b.append(new ReinterpretNode(Kind.Double, value).canonical(null, value))); + return true; + } + }); + } + + private static void registerMathPlugins(MetaAccessProvider metaAccess, Architecture arch, InvocationPlugins plugins) { Registration r = new Registration(plugins, metaAccess, Math.class); r.register1("abs", Float.TYPE, new InvocationPlugin() { - public boolean apply(GraphBuilderContext builder, ValueNode value) { - builder.push(Kind.Float, builder.append(new AbsNode(value))); + public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, ValueNode value) { + b.push(Kind.Float, b.append(new AbsNode(value).canonical(null, value))); return true; } }); r.register1("abs", Double.TYPE, new InvocationPlugin() { - public boolean apply(GraphBuilderContext builder, ValueNode value) { - builder.push(Kind.Double, builder.append(new AbsNode(value))); + public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, ValueNode value) { + b.push(Kind.Double, b.append(new AbsNode(value).canonical(null, value))); return true; } }); r.register1("sqrt", Double.TYPE, new InvocationPlugin() { - public boolean apply(GraphBuilderContext builder, ValueNode value) { - builder.push(Kind.Double, builder.append(new SqrtNode(value))); + public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, ValueNode value) { + b.push(Kind.Double, b.append(new SqrtNode(value).canonical(null, value))); return true; } }); + if (getAndSetEnabled(arch)) { + r.register1("log", Double.TYPE, new InvocationPlugin() { + public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, ValueNode value) { + b.push(Kind.Double, b.append(MathIntrinsicNode.create(value, LOG))); + return true; + } + }); + r.register1("log10", Double.TYPE, new InvocationPlugin() { + public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, ValueNode value) { + b.push(Kind.Double, b.append(MathIntrinsicNode.create(value, LOG10))); + return true; + } + }); + } + } + public static class UnsignedMathPlugin implements InvocationPlugin { + private final Condition condition; + + public UnsignedMathPlugin(Condition condition) { + this.condition = condition; + } + + public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, ValueNode x, ValueNode y) { + // the mirroring and negation operations get the condition into canonical form + boolean mirror = condition.canonicalMirror(); + boolean negate = condition.canonicalNegate(); + StructuredGraph graph = b.getGraph(); + + ValueNode lhs = mirror ? y : x; + ValueNode rhs = mirror ? x : y; + + ValueNode trueValue = ConstantNode.forBoolean(!negate, graph); + ValueNode falseValue = ConstantNode.forBoolean(negate, graph); + + Condition cond = mirror ? condition.mirror() : condition; + if (negate) { + cond = cond.negate(); + } + + LogicNode compare = CompareNode.createCompareNode(graph, cond, lhs, rhs, b.getConstantReflection()); + b.push(Kind.Boolean.getStackKind(), b.append(new ConditionalNode(compare, trueValue, falseValue))); + return true; + } + } + + private static void registerUnsignedMathPlugins(MetaAccessProvider metaAccess, InvocationPlugins plugins) { + Registration r = new Registration(plugins, metaAccess, UnsignedMath.class); + r.register2("aboveThan", int.class, int.class, new UnsignedMathPlugin(Condition.AT)); + r.register2("aboveThan", long.class, long.class, new UnsignedMathPlugin(Condition.AT)); + r.register2("belowThan", int.class, int.class, new UnsignedMathPlugin(Condition.BT)); + r.register2("belowThan", long.class, long.class, new UnsignedMathPlugin(Condition.BT)); + r.register2("aboveOrEqual", int.class, int.class, new UnsignedMathPlugin(Condition.AE)); + r.register2("aboveOrEqual", long.class, long.class, new UnsignedMathPlugin(Condition.AE)); + r.register2("belowOrEqual", int.class, int.class, new UnsignedMathPlugin(Condition.BE)); + r.register2("belowOrEqual", long.class, long.class, new UnsignedMathPlugin(Condition.BE)); + r.register2("divide", int.class, int.class, new InvocationPlugin() { + public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, ValueNode x, ValueNode y) { + b.push(Kind.Int, b.append(new UnsignedDivNode(x, y).canonical(null, x, y))); + return true; + } + }); + r.register2("divide", long.class, long.class, new InvocationPlugin() { + public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, ValueNode x, ValueNode y) { + b.push(Kind.Long, b.append(new UnsignedDivNode(x, y).canonical(null, x, y))); + return true; + } + }); + r.register2("remainder", int.class, int.class, new InvocationPlugin() { + public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, ValueNode x, ValueNode y) { + b.push(Kind.Int, b.append(new UnsignedRemNode(x, y).canonical(null, x, y))); + return true; + } + }); + r.register2("remainder", long.class, long.class, new InvocationPlugin() { + public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, ValueNode x, ValueNode y) { + b.push(Kind.Long, b.append(new UnsignedRemNode(x, y).canonical(null, x, y))); + return true; + } + }); + } + + protected static void registerBoxingPlugins(MetaAccessProvider metaAccess, InvocationPlugins plugins) { for (Kind kind : Kind.values()) { if (kind.isPrimitive() && kind != Kind.Void) { new BoxPlugin(kind).register(metaAccess, plugins); @@ -104,16 +345,75 @@ private static void registerObjectPlugins(MetaAccessProvider metaAccess, InvocationPlugins plugins) { Registration r = new Registration(plugins, metaAccess, Object.class); r.register1("", Receiver.class, new InvocationPlugin() { - public boolean apply(GraphBuilderContext builder, ValueNode object) { - if (RegisterFinalizerNode.mayHaveFinalizer(object, builder.getAssumptions())) { - builder.append(new RegisterFinalizerNode(object)); + public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, ValueNode object) { + if (RegisterFinalizerNode.mayHaveFinalizer(object, b.getAssumptions())) { + b.append(new RegisterFinalizerNode(object)); } return true; } }); } - static class BoxPlugin implements InvocationPlugin { + private static void registerClassPlugins(MetaAccessProvider metaAccess, InvocationPlugins plugins) { + Registration r = new Registration(plugins, metaAccess, Class.class); + r.register2("isInstance", Receiver.class, Object.class, new InvocationPlugin() { + public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, ValueNode type, ValueNode object) { + ValueNode nullCheckedType = nullCheckedValue(b, type); + LogicNode condition = b.append(new InstanceOfDynamicNode(nullCheckedType, object).canonical(null, nullCheckedType, object)); + b.push(Kind.Boolean.getStackKind(), b.append(new ConditionalNode(condition).canonical(null))); + return true; + } + }); + r.register2("isAssignableFrom", Receiver.class, Class.class, new InvocationPlugin() { + public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, ValueNode type, ValueNode otherType) { + ClassIsAssignableFromNode condition = b.append(new ClassIsAssignableFromNode(nullCheckedValue(b, type), otherType)); + b.push(Kind.Boolean.getStackKind(), b.append(new ConditionalNode(condition).canonical(null))); + return true; + } + }); + r.register2("cast", Receiver.class, Object.class, new InvocationPlugin() { + public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, ValueNode rcvr, ValueNode object) { + if (rcvr.isConstant() && !rcvr.isNullConstant()) { + ResolvedJavaType type = b.getConstantReflection().asJavaType(rcvr.asConstant()); + if (type != null && !type.isPrimitive()) { + b.push(Kind.Object, b.append(CheckCastNode.create(type, object, null, false, b.getAssumptions()))); + return true; + } + } + return false; + } + }); + } + + /** + * Substitutions for improving the performance of some critical methods in {@link Edges}. These + * substitutions improve the performance by forcing the relevant methods to be inlined + * (intrinsification being a special form of inlining) and removing a checked cast. The latter + * cannot be done directly in Java code as {@link DeferredPiNode} is not available to the + * project containing {@link Edges}. + */ + private static void registerEdgesPlugins(MetaAccessProvider metaAccess, InvocationPlugins plugins) { + Registration r = new Registration(plugins, metaAccess, Edges.class); + for (Class c : new Class[]{Node.class, NodeList.class}) { + r.register2("get" + c.getSimpleName() + "Unsafe", Node.class, long.class, new InvocationPlugin() { + public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, ValueNode node, ValueNode offset) { + ValueNode value = b.append(new UnsafeLoadNode(node, offset, Kind.Object, LocationIdentity.ANY_LOCATION)); + boolean exactType = false; + boolean nonNull = false; + b.push(Kind.Object, b.append(new PiNode(value, metaAccess.lookupJavaType(c), exactType, nonNull))); + return true; + } + }); + r.register3("put" + c.getSimpleName() + "Unsafe", Node.class, long.class, c, new InvocationPlugin() { + public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, ValueNode node, ValueNode offset, ValueNode value) { + b.append(new UnsafeStoreNode(node, offset, value, Kind.Object, LocationIdentity.ANY_LOCATION)); + return true; + } + }); + } + } + + public static class BoxPlugin implements InvocationPlugin { private final Kind kind; @@ -121,9 +421,17 @@ this.kind = kind; } - public boolean apply(GraphBuilderContext builder, ValueNode value) { - ResolvedJavaType resultType = builder.getMetaAccess().lookupJavaType(kind.toBoxedJavaClass()); - builder.push(Kind.Object, builder.append(new BoxNode(value, resultType, kind))); + public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, ValueNode value) { + if (b.parsingReplacement()) { + ResolvedJavaMethod rootMethod = b.getRootMethod(); + if (b.getMetaAccess().lookupJavaType(BoxingSnippets.class).isAssignableFrom(rootMethod.getDeclaringClass())) { + // Disable invocation plugins for boxing snippets so that the + // original JDK methods are inlined + return false; + } + } + ResolvedJavaType resultType = b.getMetaAccess().lookupJavaType(kind.toBoxedJavaClass()); + b.push(Kind.Object, b.append(new BoxNode(value, resultType, kind))); return true; } @@ -133,7 +441,7 @@ } } - static class UnboxPlugin implements InvocationPlugin { + public static class UnboxPlugin implements InvocationPlugin { private final Kind kind; @@ -141,9 +449,17 @@ this.kind = kind; } - public boolean apply(GraphBuilderContext builder, ValueNode value) { - ValueNode valueNode = UnboxNode.create(builder.getMetaAccess(), builder.getConstantReflection(), nullCheckedValue(builder, value), kind); - builder.push(kind.getStackKind(), builder.append(valueNode)); + public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, ValueNode value) { + if (b.parsingReplacement()) { + ResolvedJavaMethod rootMethod = b.getRootMethod(); + if (b.getMetaAccess().lookupJavaType(BoxingSnippets.class).isAssignableFrom(rootMethod.getDeclaringClass())) { + // Disable invocation plugins for unboxing snippets so that the + // original JDK methods are inlined + return false; + } + } + ValueNode valueNode = UnboxNode.create(b.getMetaAccess(), b.getConstantReflection(), nullCheckedValue(b, value), kind); + b.push(kind.getStackKind(), b.append(valueNode)); return true; } @@ -154,7 +470,7 @@ } } - static class UnsafeGetPlugin implements InvocationPlugin { + public static class UnsafeGetPlugin implements InvocationPlugin { private final Kind returnKind; private final boolean isVolatile; @@ -164,18 +480,18 @@ this.isVolatile = isVolatile; } - public boolean apply(GraphBuilderContext builder, ValueNode ignoredUnsafe, ValueNode address) { - builder.push(returnKind.getStackKind(), builder.append(new DirectReadNode(address, returnKind))); + public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, ValueNode ignoredUnsafe, ValueNode address) { + b.push(returnKind.getStackKind(), b.append(new DirectReadNode(address, returnKind))); return true; } - public boolean apply(GraphBuilderContext builder, ValueNode ignoredUnsafe, ValueNode object, ValueNode offset) { + public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, ValueNode ignoredUnsafe, ValueNode object, ValueNode offset) { if (isVolatile) { - builder.append(new MembarNode(JMM_PRE_VOLATILE_READ)); + b.append(new MembarNode(JMM_PRE_VOLATILE_READ)); } - builder.push(returnKind.getStackKind(), builder.append(new UnsafeLoadNode(object, offset, returnKind, LocationIdentity.ANY_LOCATION))); + b.push(returnKind.getStackKind(), b.append(new UnsafeLoadNode(object, offset, returnKind, LocationIdentity.ANY_LOCATION))); if (isVolatile) { - builder.append(new MembarNode(JMM_POST_VOLATILE_READ)); + b.append(new MembarNode(JMM_POST_VOLATILE_READ)); } return true; } @@ -191,18 +507,18 @@ this.isVolatile = isVolatile; } - public boolean apply(GraphBuilderContext builder, ValueNode ignoredUnsafe, ValueNode address, ValueNode value) { - builder.append(new DirectStoreNode(address, value, kind)); + public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, ValueNode ignoredUnsafe, ValueNode address, ValueNode value) { + b.append(new DirectStoreNode(address, value, kind)); return true; } - public boolean apply(GraphBuilderContext builder, ValueNode ignoredUnsafe, ValueNode object, ValueNode offset, ValueNode value) { + public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, ValueNode ignoredUnsafe, ValueNode object, ValueNode offset, ValueNode value) { if (isVolatile) { - builder.append(new MembarNode(JMM_PRE_VOLATILE_WRITE)); + b.append(new MembarNode(JMM_PRE_VOLATILE_WRITE)); } - builder.append(new UnsafeStoreNode(object, offset, value, kind, LocationIdentity.ANY_LOCATION)); + b.append(new UnsafeStoreNode(object, offset, value, kind, LocationIdentity.ANY_LOCATION)); if (isVolatile) { - builder.append(new MembarNode(JMM_PRE_VOLATILE_WRITE)); + b.append(new MembarNode(JMM_PRE_VOLATILE_WRITE)); } return true; } @@ -211,70 +527,84 @@ private static void registerGraalDirectivesPlugins(MetaAccessProvider metaAccess, InvocationPlugins plugins) { Registration r = new Registration(plugins, metaAccess, GraalDirectives.class); r.register0("deoptimize", new InvocationPlugin() { - public boolean apply(GraphBuilderContext builder) { - builder.append(new DeoptimizeNode(DeoptimizationAction.None, DeoptimizationReason.TransferToInterpreter)); + public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod) { + b.append(new DeoptimizeNode(DeoptimizationAction.None, DeoptimizationReason.TransferToInterpreter)); return true; } }); r.register0("deoptimizeAndInvalidate", new InvocationPlugin() { - public boolean apply(GraphBuilderContext builder) { - builder.append(new DeoptimizeNode(DeoptimizationAction.InvalidateReprofile, DeoptimizationReason.TransferToInterpreter)); + public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod) { + b.append(new DeoptimizeNode(DeoptimizationAction.InvalidateReprofile, DeoptimizationReason.TransferToInterpreter)); return true; } }); r.register0("inCompiledCode", new InvocationPlugin() { - public boolean apply(GraphBuilderContext builder) { - builder.push(Kind.Int, builder.append(ConstantNode.forInt(1))); + public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod) { + b.push(Kind.Int, b.append(ConstantNode.forInt(1))); return true; } }); r.register0("controlFlowAnchor", new InvocationPlugin() { - public boolean apply(GraphBuilderContext builder) { - builder.append(new ControlFlowAnchorNode()); + public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod) { + b.append(new ControlFlowAnchorNode()); return true; } }); r.register2("injectBranchProbability", double.class, boolean.class, new InvocationPlugin() { - public boolean apply(GraphBuilderContext builder, ValueNode probability, ValueNode condition) { - builder.push(Kind.Int, builder.append(new BranchProbabilityNode(probability, condition))); + public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, ValueNode probability, ValueNode condition) { + b.push(Kind.Int, b.append(new BranchProbabilityNode(probability, condition))); return true; } }); InvocationPlugin blackholePlugin = new InvocationPlugin() { - public boolean apply(GraphBuilderContext builder, ValueNode value) { - builder.append(new BlackholeNode(value)); + public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, ValueNode value) { + b.append(new BlackholeNode(value)); return true; } }; for (Kind kind : Kind.values()) { - Class cls = null; - switch (kind) { - case Object: - cls = Object.class; - break; - case Void: - case Illegal: - continue; - default: - cls = kind.toJavaClass(); + if ((kind.isPrimitive() && kind != Kind.Void) || kind == Kind.Object) { + Class javaClass = kind == Kind.Object ? Object.class : kind.toJavaClass(); + r.register1("blackhole", javaClass, blackholePlugin); + + final Kind stackKind = kind.getStackKind(); + r.register1("opaque", javaClass, new InvocationPlugin() { + public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, ValueNode value) { + b.push(stackKind, b.append(new OpaqueNode(value))); + return true; + } + }); } - - r.register1("blackhole", cls, blackholePlugin); - - final Kind stackKind = kind.getStackKind(); - r.register1("opaque", cls, new InvocationPlugin() { - public boolean apply(GraphBuilderContext builder, ValueNode value) { - builder.push(stackKind, builder.append(new OpaqueNode(value))); - return true; - } - }); } } + private static void registerJMHBlackholePlugins(MetaAccessProvider metaAccess, InvocationPlugins plugins) { + InvocationPlugin blackholePlugin = new InvocationPlugin() { + public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, ValueNode blackhole, ValueNode value) { + b.append(new BlackholeNode(value)); + return true; + } + }; + String[] names = {"org.openjdk.jmh.infra.Blackhole", "org.openjdk.jmh.logic.BlackHole"}; + for (String name : names) { + Class blackholeClass; + blackholeClass = ReplacementsImpl.resolveClass(name, true); + if (blackholeClass != null) { + Registration r = new Registration(plugins, metaAccess, blackholeClass); + for (Kind kind : Kind.values()) { + if ((kind.isPrimitive() && kind != Kind.Void) || kind == Kind.Object) { + Class javaClass = kind == Kind.Object ? Object.class : kind.toJavaClass(); + r.register2("consume", Receiver.class, javaClass, blackholePlugin); + } + } + r.register2("consume", Receiver.class, Object[].class, blackholePlugin); + } + } + } } diff -r 31fac91ea3b7 -r 14e703edb2ab graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/UnsafeSubstitutions.java --- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/UnsafeSubstitutions.java Wed Mar 11 17:16:30 2015 +0100 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/UnsafeSubstitutions.java Wed Mar 11 20:43:12 2015 +0100 @@ -22,7 +22,7 @@ */ package com.oracle.graal.replacements; -import static com.oracle.graal.api.code.MemoryBarriers.*; +import static com.oracle.graal.nodes.extended.BranchProbabilityNode.*; import java.lang.reflect.*; @@ -30,9 +30,8 @@ import com.oracle.graal.api.meta.*; import com.oracle.graal.api.replacements.*; -import com.oracle.graal.nodes.extended.*; +import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.java.*; -import com.oracle.graal.replacements.nodes.*; /** * Substitutions for {@link sun.misc.Unsafe} methods. @@ -41,405 +40,16 @@ public class UnsafeSubstitutions { @MethodSubstitution(isStatic = false) - public static boolean compareAndSwapObject(@SuppressWarnings("unused") final Object thisObj, Object o, long offset, Object expected, Object x) { - return CompareAndSwapNode.compareAndSwap(o, offset, expected, x, Kind.Object, LocationIdentity.ANY_LOCATION); - } - - @MethodSubstitution(isStatic = false) - public static boolean compareAndSwapInt(@SuppressWarnings("unused") final Object thisObj, Object o, long offset, int expected, int x) { - return CompareAndSwapNode.compareAndSwap(o, offset, expected, x, Kind.Int, LocationIdentity.ANY_LOCATION); - } - - @MethodSubstitution(isStatic = false) - public static boolean compareAndSwapLong(@SuppressWarnings("unused") final Object thisObj, Object o, long offset, long expected, long x) { - return CompareAndSwapNode.compareAndSwap(o, offset, expected, x, Kind.Long, LocationIdentity.ANY_LOCATION); - } - - @MethodSubstitution(isStatic = false) - public static Object getObject(@SuppressWarnings("unused") final Object thisObj, Object o, long offset) { - return UnsafeLoadNode.load(o, offset, Kind.Object, LocationIdentity.ANY_LOCATION); - } - - @MethodSubstitution(isStatic = false) - public static Object getObjectVolatile(final Object thisObj, Object o, long offset) { - MembarNode.memoryBarrier(JMM_PRE_VOLATILE_READ); - Object result = getObject(thisObj, o, offset); - MembarNode.memoryBarrier(JMM_POST_VOLATILE_READ); - return result; - } - - @MethodSubstitution(isStatic = false) - public static void putObject(@SuppressWarnings("unused") final Object thisObj, Object o, long offset, Object x) { - UnsafeStoreNode.store(o, offset, x, Kind.Object, LocationIdentity.ANY_LOCATION); - } - - @MethodSubstitution(isStatic = false) - public static void putObjectVolatile(final Object thisObj, Object o, long offset, Object x) { - MembarNode.memoryBarrier(JMM_PRE_VOLATILE_WRITE); - putObject(thisObj, o, offset, x); - MembarNode.memoryBarrier(JMM_POST_VOLATILE_WRITE); - } - - @MethodSubstitution(isStatic = false) - public static void putOrderedObject(final Object thisObj, Object o, long offset, Object x) { - MembarNode.memoryBarrier(JMM_PRE_VOLATILE_WRITE); - putObject(thisObj, o, offset, x); - MembarNode.memoryBarrier(JMM_POST_VOLATILE_WRITE); - } - - @MethodSubstitution(isStatic = false) - public static int getInt(@SuppressWarnings("unused") final Object thisObj, Object o, long offset) { - Integer value = UnsafeLoadNode.load(o, offset, Kind.Int, LocationIdentity.ANY_LOCATION); - return value; - } - - @MethodSubstitution(isStatic = false) - public static int getIntVolatile(final Object thisObj, Object o, long offset) { - MembarNode.memoryBarrier(JMM_PRE_VOLATILE_READ); - int result = getInt(thisObj, o, offset); - MembarNode.memoryBarrier(JMM_POST_VOLATILE_READ); - return result; - } - - @MethodSubstitution(isStatic = false) - public static void putInt(@SuppressWarnings("unused") final Object thisObj, Object o, long offset, int x) { - UnsafeStoreNode.store(o, offset, x, Kind.Int, LocationIdentity.ANY_LOCATION); - } - - @MethodSubstitution(isStatic = false) - public static void putIntVolatile(final Object thisObj, Object o, long offset, int x) { - MembarNode.memoryBarrier(JMM_PRE_VOLATILE_WRITE); - putInt(thisObj, o, offset, x); - MembarNode.memoryBarrier(JMM_POST_VOLATILE_WRITE); - } - - @MethodSubstitution(isStatic = false) - public static void putOrderedInt(final Object thisObj, Object o, long offset, int x) { - MembarNode.memoryBarrier(JMM_PRE_VOLATILE_WRITE); - putInt(thisObj, o, offset, x); - MembarNode.memoryBarrier(JMM_POST_VOLATILE_WRITE); - } - - @MethodSubstitution(isStatic = false) - public static boolean getBoolean(@SuppressWarnings("unused") final Object thisObj, Object o, long offset) { - @JavacBug(id = 6995200) - Boolean result = UnsafeLoadNode.load(o, offset, Kind.Boolean, LocationIdentity.ANY_LOCATION); - return result; - } - - @MethodSubstitution(isStatic = false) - public static boolean getBooleanVolatile(final Object thisObj, Object o, long offset) { - MembarNode.memoryBarrier(JMM_PRE_VOLATILE_READ); - boolean result = getBoolean(thisObj, o, offset); - MembarNode.memoryBarrier(JMM_POST_VOLATILE_READ); - return result; - } - - @MethodSubstitution(isStatic = false) - public static void putBoolean(@SuppressWarnings("unused") final Object thisObj, Object o, long offset, boolean x) { - UnsafeStoreNode.store(o, offset, x, Kind.Boolean, LocationIdentity.ANY_LOCATION); - } - - @MethodSubstitution(isStatic = false) - public static void putBooleanVolatile(final Object thisObj, Object o, long offset, boolean x) { - MembarNode.memoryBarrier(JMM_PRE_VOLATILE_WRITE); - putBoolean(thisObj, o, offset, x); - MembarNode.memoryBarrier(JMM_POST_VOLATILE_WRITE); - } - - @MethodSubstitution(isStatic = false) - public static byte getByte(@SuppressWarnings("unused") final Object thisObj, Object o, long offset) { - @JavacBug(id = 6995200) - Byte result = UnsafeLoadNode.load(o, offset, Kind.Byte, LocationIdentity.ANY_LOCATION); - return result; - } - - @MethodSubstitution(isStatic = false) - public static byte getByteVolatile(final Object thisObj, Object o, long offset) { - MembarNode.memoryBarrier(JMM_PRE_VOLATILE_READ); - byte result = getByte(thisObj, o, offset); - MembarNode.memoryBarrier(JMM_POST_VOLATILE_READ); - return result; - } - - @MethodSubstitution(isStatic = false) - public static void putByte(@SuppressWarnings("unused") final Object thisObj, Object o, long offset, byte x) { - UnsafeStoreNode.store(o, offset, x, Kind.Byte, LocationIdentity.ANY_LOCATION); - } - - @MethodSubstitution(isStatic = false) - public static void putByteVolatile(final Object thisObj, Object o, long offset, byte x) { - MembarNode.memoryBarrier(JMM_PRE_VOLATILE_WRITE); - putByte(thisObj, o, offset, x); - MembarNode.memoryBarrier(JMM_POST_VOLATILE_WRITE); - } - - @MethodSubstitution(isStatic = false) - public static short getShort(@SuppressWarnings("unused") final Object thisObj, Object o, long offset) { - @JavacBug(id = 6995200) - Short result = UnsafeLoadNode.load(o, offset, Kind.Short, LocationIdentity.ANY_LOCATION); - return result; - } - - @MethodSubstitution(isStatic = false) - public static short getShortVolatile(final Object thisObj, Object o, long offset) { - MembarNode.memoryBarrier(JMM_PRE_VOLATILE_READ); - short result = getShort(thisObj, o, offset); - MembarNode.memoryBarrier(JMM_POST_VOLATILE_READ); - return result; - } - - @MethodSubstitution(isStatic = false) - public static void putShort(@SuppressWarnings("unused") final Object thisObj, Object o, long offset, short x) { - UnsafeStoreNode.store(o, offset, x, Kind.Short, LocationIdentity.ANY_LOCATION); - } - - @MethodSubstitution(isStatic = false) - public static void putShortVolatile(final Object thisObj, Object o, long offset, short x) { - MembarNode.memoryBarrier(JMM_PRE_VOLATILE_WRITE); - putShort(thisObj, o, offset, x); - MembarNode.memoryBarrier(JMM_POST_VOLATILE_WRITE); - } - - @MethodSubstitution(isStatic = false) - public static char getChar(@SuppressWarnings("unused") final Object thisObj, Object o, long offset) { - @JavacBug(id = 6995200) - Character result = UnsafeLoadNode.load(o, offset, Kind.Char, LocationIdentity.ANY_LOCATION); - return result; - } - - @MethodSubstitution(isStatic = false) - public static char getCharVolatile(final Object thisObj, Object o, long offset) { - MembarNode.memoryBarrier(JMM_PRE_VOLATILE_READ); - char result = getChar(thisObj, o, offset); - MembarNode.memoryBarrier(JMM_POST_VOLATILE_READ); - return result; - } - - @MethodSubstitution(isStatic = false) - public static void putChar(@SuppressWarnings("unused") final Object thisObj, Object o, long offset, char x) { - UnsafeStoreNode.store(o, offset, x, Kind.Char, LocationIdentity.ANY_LOCATION); - } - - @MethodSubstitution(isStatic = false) - public static void putCharVolatile(final Object thisObj, Object o, long offset, char x) { - MembarNode.memoryBarrier(JMM_PRE_VOLATILE_WRITE); - putChar(thisObj, o, offset, x); - MembarNode.memoryBarrier(JMM_POST_VOLATILE_WRITE); - } - - @MethodSubstitution(isStatic = false) - public static long getLong(@SuppressWarnings("unused") final Object thisObj, Object o, long offset) { - @JavacBug(id = 6995200) - Long result = UnsafeLoadNode.load(o, offset, Kind.Long, LocationIdentity.ANY_LOCATION); - return result; - } - - @MethodSubstitution(isStatic = false) - public static long getLongVolatile(final Object thisObj, Object o, long offset) { - MembarNode.memoryBarrier(JMM_PRE_VOLATILE_READ); - long result = getLong(thisObj, o, offset); - MembarNode.memoryBarrier(JMM_POST_VOLATILE_READ); - return result; - } - - @MethodSubstitution(isStatic = false) - public static void putLong(@SuppressWarnings("unused") final Object thisObj, Object o, long offset, long x) { - UnsafeStoreNode.store(o, offset, x, Kind.Long, LocationIdentity.ANY_LOCATION); - } - - @MethodSubstitution(isStatic = false) - public static void putLongVolatile(final Object thisObj, Object o, long offset, long x) { - MembarNode.memoryBarrier(JMM_PRE_VOLATILE_WRITE); - putLong(thisObj, o, offset, x); - MembarNode.memoryBarrier(JMM_POST_VOLATILE_WRITE); - } - - @MethodSubstitution(isStatic = false) - public static void putOrderedLong(final Object thisObj, Object o, long offset, long x) { - MembarNode.memoryBarrier(JMM_PRE_VOLATILE_WRITE); - putLong(thisObj, o, offset, x); - MembarNode.memoryBarrier(JMM_POST_VOLATILE_WRITE); - } - - @MethodSubstitution(isStatic = false) - public static float getFloat(@SuppressWarnings("unused") final Object thisObj, Object o, long offset) { - @JavacBug(id = 6995200) - Float result = UnsafeLoadNode.load(o, offset, Kind.Float, LocationIdentity.ANY_LOCATION); - return result; - } - - @MethodSubstitution(isStatic = false) - public static float getFloatVolatile(final Object thisObj, Object o, long offset) { - MembarNode.memoryBarrier(JMM_PRE_VOLATILE_READ); - float result = getFloat(thisObj, o, offset); - MembarNode.memoryBarrier(JMM_POST_VOLATILE_READ); - return result; - } - - @MethodSubstitution(isStatic = false) - public static void putFloat(@SuppressWarnings("unused") final Object thisObj, Object o, long offset, float x) { - UnsafeStoreNode.store(o, offset, x, Kind.Float, LocationIdentity.ANY_LOCATION); - } - - @MethodSubstitution(isStatic = false) - public static void putFloatVolatile(final Object thisObj, Object o, long offset, float x) { - MembarNode.memoryBarrier(JMM_PRE_VOLATILE_WRITE); - putFloat(thisObj, o, offset, x); - MembarNode.memoryBarrier(JMM_POST_VOLATILE_WRITE); - } - - @MethodSubstitution(isStatic = false) - public static double getDouble(@SuppressWarnings("unused") final Object thisObj, Object o, long offset) { - @JavacBug(id = 6995200) - Double result = UnsafeLoadNode.load(o, offset, Kind.Double, LocationIdentity.ANY_LOCATION); - return result; - } - - @MethodSubstitution(isStatic = false) - public static double getDoubleVolatile(final Object thisObj, Object o, long offset) { - MembarNode.memoryBarrier(JMM_PRE_VOLATILE_READ); - double result = getDouble(thisObj, o, offset); - MembarNode.memoryBarrier(JMM_POST_VOLATILE_READ); - return result; - } - - @MethodSubstitution(isStatic = false) - public static void putDouble(@SuppressWarnings("unused") final Object thisObj, Object o, long offset, double x) { - UnsafeStoreNode.store(o, offset, x, Kind.Double, LocationIdentity.ANY_LOCATION); - } - - @MethodSubstitution(isStatic = false) - public static void putDoubleVolatile(final Object thisObj, Object o, long offset, double x) { - MembarNode.memoryBarrier(JMM_PRE_VOLATILE_WRITE); - putDouble(thisObj, o, offset, x); - MembarNode.memoryBarrier(JMM_POST_VOLATILE_WRITE); - } - - @MethodSubstitution(isStatic = false) - public static void putByte(@SuppressWarnings("unused") final Object thisObj, long address, byte value) { - DirectStoreNode.store(address, value, Kind.Byte); - } - - @MethodSubstitution(isStatic = false) - public static void putShort(@SuppressWarnings("unused") final Object thisObj, long address, short value) { - DirectStoreNode.store(address, value, Kind.Short); - } - - @MethodSubstitution(isStatic = false) - public static void putChar(@SuppressWarnings("unused") final Object thisObj, long address, char value) { - DirectStoreNode.store(address, value, Kind.Char); - } - - @MethodSubstitution(isStatic = false) - public static void putInt(@SuppressWarnings("unused") final Object thisObj, long address, int value) { - DirectStoreNode.store(address, value, Kind.Int); - } - - @MethodSubstitution(isStatic = false) - public static void putLong(@SuppressWarnings("unused") final Object thisObj, long address, long value) { - DirectStoreNode.store(address, value, Kind.Long); - } - - @MethodSubstitution(isStatic = false) - public static void putFloat(@SuppressWarnings("unused") final Object thisObj, long address, float value) { - DirectStoreNode.store(address, value, Kind.Float); - } - - @MethodSubstitution(isStatic = false) - public static void putDouble(@SuppressWarnings("unused") final Object thisObj, long address, double value) { - DirectStoreNode.store(address, value, Kind.Double); - } - - @MethodSubstitution(isStatic = false) - public static byte getByte(@SuppressWarnings("unused") final Object thisObj, long address) { - return DirectReadNode.read(address, Kind.Byte); - } - - @MethodSubstitution(isStatic = false) - public static short getShort(@SuppressWarnings("unused") final Object thisObj, long address) { - return DirectReadNode.read(address, Kind.Short); - } - - @MethodSubstitution(isStatic = false) - public static char getChar(@SuppressWarnings("unused") final Object thisObj, long address) { - return DirectReadNode.read(address, Kind.Char); - } - - @MethodSubstitution(isStatic = false) - public static int getInt(@SuppressWarnings("unused") final Object thisObj, long address) { - return DirectReadNode.read(address, Kind.Int); - } - - @MethodSubstitution(isStatic = false) - public static long getLong(@SuppressWarnings("unused") final Object thisObj, long address) { - return DirectReadNode.read(address, Kind.Long); - } - - @MethodSubstitution(isStatic = false) - public static float getFloat(@SuppressWarnings("unused") final Object thisObj, long address) { - return DirectReadNode.read(address, Kind.Float); - } - - @MethodSubstitution(isStatic = false) - public static double getDouble(@SuppressWarnings("unused") final Object thisObj, long address) { - return DirectReadNode.read(address, Kind.Double); - } - - @MethodSubstitution(isStatic = false) - public static Object allocateInstance(final Unsafe thisObj, Class clazz) throws InstantiationException { - if (clazz.isPrimitive()) { - throw new InstantiationException(clazz.getName()); + public static Object allocateInstance(@SuppressWarnings("unused") final Unsafe thisObj, Class clazz) { + if (probability(SLOW_PATH_PROBABILITY, clazz.isPrimitive())) { + DeoptimizeNode.deopt(DeoptimizationAction.None, DeoptimizationReason.RuntimeConstraint); } - if (clazz.isArray() || clazz.isInterface() || Modifier.isAbstract(clazz.getModifiers())) { - throw new InstantiationException(clazz.getName()); + if (probability(SLOW_PATH_PROBABILITY, clazz.isArray() || clazz.isInterface() || Modifier.isAbstract(clazz.getModifiers()))) { + DeoptimizeNode.deopt(DeoptimizationAction.None, DeoptimizationReason.RuntimeConstraint); } - if (clazz == Class.class) { - thisObj.throwException(new IllegalAccessException(clazz.getName())); + if (probability(SLOW_PATH_PROBABILITY, clazz == Class.class)) { + DeoptimizeNode.deopt(DeoptimizationAction.None, DeoptimizationReason.RuntimeConstraint); } return DynamicNewInstanceNode.allocateInstance(clazz, true); } - - /** - * Guard for {@link Unsafe#getAndSetInt} method family. - */ - public static class GetAndSetGuard implements SubstitutionGuard { - public boolean execute() { - // FIXME should return whether the current compilation target supports these - String arch = System.getProperty("os.arch"); - switch (arch) { - case "amd64": - case "x86_64": - return true; - default: - return false; - } - } - } - - @MethodSubstitution(isStatic = false, guard = GetAndSetGuard.class) - public static int getAndAddInt(@SuppressWarnings("unused") final Object thisObj, Object o, long offset, int delta) { - return AtomicReadAndAddNode.getAndAddInt(o, offset, delta, LocationIdentity.ANY_LOCATION); - } - - @MethodSubstitution(isStatic = false, guard = GetAndSetGuard.class) - public static long getAndAddLong(@SuppressWarnings("unused") final Object thisObj, Object o, long offset, long delta) { - return AtomicReadAndAddNode.getAndAddLong(o, offset, delta, LocationIdentity.ANY_LOCATION); - } - - @MethodSubstitution(isStatic = false, guard = GetAndSetGuard.class) - public static int getAndSetInt(@SuppressWarnings("unused") final Object thisObj, Object o, long offset, int newValue) { - return AtomicReadAndWriteNode.getAndSetInt(o, offset, newValue, Kind.Int, LocationIdentity.ANY_LOCATION); - } - - @MethodSubstitution(isStatic = false, guard = GetAndSetGuard.class) - public static long getAndSetLong(@SuppressWarnings("unused") final Object thisObj, Object o, long offset, long newValue) { - return AtomicReadAndWriteNode.getAndSetLong(o, offset, newValue, Kind.Long, LocationIdentity.ANY_LOCATION); - } - - @MethodSubstitution(isStatic = false, guard = GetAndSetGuard.class) - public static Object getAndSetObject(@SuppressWarnings("unused") final Object thisObj, Object o, long offset, Object newValue) { - return AtomicReadAndWriteNode.getAndSetObject(o, offset, newValue, Kind.Object, LocationIdentity.ANY_LOCATION); - } - } diff -r 31fac91ea3b7 -r 14e703edb2ab graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/UnsignedMathSubstitutions.java --- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/UnsignedMathSubstitutions.java Wed Mar 11 17:16:30 2015 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,127 +0,0 @@ -/* - * Copyright (c) 2011, 2014, 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 static com.oracle.graal.compiler.common.calc.Condition.*; -import static com.oracle.graal.nodes.calc.ConditionalNode.*; - -import com.oracle.graal.api.code.*; -import com.oracle.graal.api.replacements.*; -import com.oracle.graal.nodes.calc.*; - -/** - * Substitutions for {@link UnsignedMath}. - */ -@ClassSubstitution(UnsignedMath.class) -public class UnsignedMathSubstitutions { - - @MethodSubstitution - public static boolean aboveThan(int a, int b) { - return materializeCondition(BT, b, a); - } - - @MethodSubstitution - public static boolean aboveOrEqual(int a, int b) { - return !materializeCondition(BT, a, b); - } - - /** - * Unsigned comparison belowThan for two numbers. - */ - @MethodSubstitution - public static boolean belowThan(int a, int b) { - return materializeCondition(BT, a, b); - } - - /** - * Unsigned comparison belowOrEqual for two numbers. - */ - @MethodSubstitution - public static boolean belowOrEqual(int a, int b) { - return !materializeCondition(BT, b, a); - } - - /** - * Unsigned comparison aboveThan for two numbers. - */ - @MethodSubstitution - public static boolean aboveThan(long a, long b) { - return materializeCondition(BT, b, a); - } - - /** - * Unsigned comparison aboveOrEqual for two numbers. - */ - @MethodSubstitution - public static boolean aboveOrEqual(long a, long b) { - return !materializeCondition(BT, a, b); - } - - /** - * Unsigned comparison belowThan for two numbers. - */ - @MethodSubstitution - public static boolean belowThan(long a, long b) { - return materializeCondition(BT, a, b); - } - - /** - * Unsigned comparison belowOrEqual for two numbers. - */ - @MethodSubstitution - public static boolean belowOrEqual(long a, long b) { - return !materializeCondition(BT, b, a); - } - - /** - * Unsigned division for two numbers. - */ - @MethodSubstitution - public static int divide(int a, int b) { - return UnsignedDivNode.unsignedDivide(a, b); - } - - /** - * Unsigned remainder for two numbers. - */ - @MethodSubstitution - public static int remainder(int a, int b) { - return UnsignedRemNode.unsignedRemainder(a, b); - } - - /** - * Unsigned division for two numbers. - */ - @MethodSubstitution - public static long divide(long a, long b) { - return UnsignedDivNode.unsignedDivide(a, b); - } - - /** - * Unsigned remainder for two numbers. - */ - @MethodSubstitution - public static long remainder(long a, long b) { - return UnsignedRemNode.unsignedRemainder(a, b); - } -} diff -r 31fac91ea3b7 -r 14e703edb2ab graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/WordOperationPlugin.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/WordOperationPlugin.java Wed Mar 11 20:43:12 2015 +0100 @@ -0,0 +1,298 @@ +/* + * 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 static com.oracle.graal.api.meta.LocationIdentity.*; +import static com.oracle.graal.nodes.ConstantNode.*; + +import java.lang.reflect.*; + +import com.oracle.graal.api.meta.*; +import com.oracle.graal.api.replacements.*; +import com.oracle.graal.compiler.common.*; +import com.oracle.graal.compiler.common.calc.*; +import com.oracle.graal.compiler.common.type.*; +import com.oracle.graal.java.*; +import com.oracle.graal.java.GraphBuilderPlugin.GenericInvocationPlugin; +import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.HeapAccess.BarrierType; +import com.oracle.graal.nodes.calc.*; +import com.oracle.graal.nodes.extended.*; +import com.oracle.graal.word.*; +import com.oracle.graal.word.Word.Opcode; +import com.oracle.graal.word.Word.Operation; +import com.oracle.graal.word.nodes.*; +import com.oracle.graal.word.phases.*; + +/** + * A {@link GenericInvocationPlugin} for calls to {@linkplain Operation word operations}. + */ +public class WordOperationPlugin implements GenericInvocationPlugin { + protected final WordTypes wordTypes; + protected final Kind wordKind; + protected final SnippetReflectionProvider snippetReflection; + + public WordOperationPlugin(SnippetReflectionProvider snippetReflection, WordTypes wordTypes) { + this.snippetReflection = snippetReflection; + this.wordTypes = wordTypes; + this.wordKind = wordTypes.getWordKind(); + } + + /** + * Processes a call to a method if it is annotated with {@link Operation} by adding nodes to the + * graph being built that implement the denoted operation. + * + * @return {@code true} iff {@code method} is annotated with {@link Operation} (and was thus + * processed by this method) + */ + public boolean apply(GraphBuilderContext b, ResolvedJavaMethod method, ValueNode[] args) { + if (!wordTypes.isWordOperation(method)) { + return false; + } + processWordOperation(b, args, wordTypes.getWordOperation(method, b.getMethod().getDeclaringClass())); + return true; + } + + protected void processWordOperation(GraphBuilderContext b, ValueNode[] args, ResolvedJavaMethod wordMethod) throws GraalInternalError { + Operation operation = wordMethod.getAnnotation(Word.Operation.class); + Kind returnKind = wordMethod.getSignature().getReturnKind(); + Kind returnStackKind = returnKind.getStackKind(); + switch (operation.opcode()) { + case NODE_CLASS: + assert args.length == 2; + ValueNode left = args[0]; + ValueNode right = operation.rightOperandIsInt() ? toUnsigned(b, args[1], Kind.Int) : fromSigned(b, args[1]); + + b.push(returnStackKind, b.append(createBinaryNodeInstance(operation.node(), left, right))); + break; + + case COMPARISON: + assert args.length == 2; + b.push(returnStackKind, comparisonOp(b, operation.condition(), args[0], fromSigned(b, args[1]))); + break; + + case NOT: + assert args.length == 1; + b.push(returnStackKind, b.append(new XorNode(args[0], b.append(forIntegerKind(wordKind, -1))))); + break; + + case READ_POINTER: + case READ_OBJECT: + case READ_BARRIERED: { + assert args.length == 2 || args.length == 3; + Kind readKind = wordTypes.asKind(wordMethod.getSignature().getReturnType(wordMethod.getDeclaringClass())); + LocationNode location; + if (args.length == 2) { + location = makeLocation(b, args[1], ANY_LOCATION); + } else { + location = makeLocation(b, args[1], args[2]); + } + b.push(returnStackKind, readOp(b, readKind, args[0], location, operation.opcode())); + break; + } + case READ_HEAP: { + assert args.length == 3; + Kind readKind = wordTypes.asKind(wordMethod.getSignature().getReturnType(wordMethod.getDeclaringClass())); + LocationNode location = makeLocation(b, args[1], ANY_LOCATION); + BarrierType barrierType = snippetReflection.asObject(BarrierType.class, args[2].asJavaConstant()); + b.push(returnStackKind, readOp(b, readKind, args[0], location, barrierType, true)); + break; + } + case WRITE_POINTER: + case WRITE_OBJECT: + case WRITE_BARRIERED: + case INITIALIZE: { + assert args.length == 3 || args.length == 4; + Kind writeKind = wordTypes.asKind(wordMethod.getSignature().getParameterType(wordMethod.isStatic() ? 2 : 1, wordMethod.getDeclaringClass())); + LocationNode location; + if (args.length == 3) { + location = makeLocation(b, args[1], LocationIdentity.ANY_LOCATION); + } else { + location = makeLocation(b, args[1], args[3]); + } + writeOp(b, writeKind, args[0], args[2], location, operation.opcode()); + break; + } + case ZERO: + assert args.length == 0; + b.push(returnStackKind, b.append(forIntegerKind(wordKind, 0L))); + break; + + case FROM_UNSIGNED: + assert args.length == 1; + b.push(returnStackKind, fromUnsigned(b, args[0])); + break; + + case FROM_SIGNED: + assert args.length == 1; + b.push(returnStackKind, fromSigned(b, args[0])); + break; + + case TO_RAW_VALUE: + assert args.length == 1; + b.push(returnStackKind, toUnsigned(b, args[0], Kind.Long)); + break; + + case FROM_WORDBASE: + assert args.length == 1; + b.push(returnStackKind, args[0]); + break; + + case FROM_OBJECT: + assert args.length == 1; + WordCastNode objectToWord = b.append(WordCastNode.objectToWord(args[0], wordKind)); + b.push(returnStackKind, objectToWord); + break; + + case FROM_ARRAY: + assert args.length == 2; + b.push(returnStackKind, b.append(new ComputeAddressNode(args[0], args[1], StampFactory.forKind(wordKind)))); + break; + + case TO_OBJECT: + assert args.length == 1; + WordCastNode wordToObject = b.append(WordCastNode.wordToObject(args[0], wordKind)); + b.push(returnStackKind, wordToObject); + break; + + default: + throw new GraalInternalError("Unknown opcode: %s", operation.opcode()); + } + } + + /** + * Create an instance of a binary node which is used to lower {@link Word} operations. This + * method is called for all {@link Word} operations which are annotated with @Operation(node = + * ...) and encapsulates the reflective allocation of the node. + */ + private static ValueNode createBinaryNodeInstance(Class nodeClass, ValueNode left, ValueNode right) { + try { + Constructor cons = nodeClass.getDeclaredConstructor(ValueNode.class, ValueNode.class); + return (ValueNode) cons.newInstance(left, right); + } catch (Throwable ex) { + throw new GraalInternalError(ex).addContext(nodeClass.getName()); + } + } + + private ValueNode comparisonOp(GraphBuilderContext graph, Condition condition, ValueNode left, ValueNode right) { + assert left.getKind() == wordKind && right.getKind() == wordKind; + + // mirroring gets the condition into canonical form + boolean mirror = condition.canonicalMirror(); + + ValueNode a = mirror ? right : left; + ValueNode b = mirror ? left : right; + + CompareNode comparison; + if (condition == Condition.EQ || condition == Condition.NE) { + comparison = new IntegerEqualsNode(a, b); + } else if (condition.isUnsigned()) { + comparison = new IntegerBelowNode(a, b); + } else { + comparison = new IntegerLessThanNode(a, b); + } + + ConstantNode trueValue = graph.append(forInt(1)); + ConstantNode falseValue = graph.append(forInt(0)); + + if (condition.canonicalNegate()) { + ConstantNode temp = trueValue; + trueValue = falseValue; + falseValue = temp; + } + ConditionalNode materialize = graph.append(new ConditionalNode(graph.append(comparison), trueValue, falseValue)); + return materialize; + } + + protected ValueNode readOp(GraphBuilderContext b, Kind readKind, ValueNode base, LocationNode location, Opcode op) { + assert op == Opcode.READ_POINTER || op == Opcode.READ_OBJECT || op == Opcode.READ_BARRIERED; + final BarrierType barrier = (op == Opcode.READ_BARRIERED ? BarrierType.PRECISE : BarrierType.NONE); + final boolean compressible = (op == Opcode.READ_OBJECT || op == Opcode.READ_BARRIERED); + + return readOp(b, readKind, base, location, barrier, compressible); + } + + public static ValueNode readOp(GraphBuilderContext b, Kind readKind, ValueNode base, LocationNode location, BarrierType barrierType, boolean compressible) { + JavaReadNode read = b.append(new JavaReadNode(readKind, base, location, barrierType, compressible)); + /* + * The read must not float outside its block otherwise it may float above an explicit zero + * check on its base address. + */ + read.setGuard(AbstractBeginNode.prevBegin(read)); + return read; + } + + protected void writeOp(GraphBuilderContext b, Kind writeKind, ValueNode base, ValueNode value, LocationNode location, Opcode op) { + assert op == Opcode.WRITE_POINTER || op == Opcode.WRITE_OBJECT || op == Opcode.WRITE_BARRIERED || op == Opcode.INITIALIZE; + final BarrierType barrier = (op == Opcode.WRITE_BARRIERED ? BarrierType.PRECISE : BarrierType.NONE); + final boolean compressible = (op == Opcode.WRITE_OBJECT || op == Opcode.WRITE_BARRIERED); + final boolean initialize = (op == Opcode.INITIALIZE); + b.append(new JavaWriteNode(writeKind, base, value, location, barrier, compressible, initialize)); + } + + public LocationNode makeLocation(GraphBuilderContext b, ValueNode offset, LocationIdentity locationIdentity) { + return b.append(new IndexedLocationNode(locationIdentity, 0, fromSigned(b, offset), 1)); + } + + public LocationNode makeLocation(GraphBuilderContext b, ValueNode offset, ValueNode locationIdentity) { + if (locationIdentity.isConstant()) { + return makeLocation(b, offset, snippetReflection.asObject(LocationIdentity.class, locationIdentity.asJavaConstant())); + } + return b.append(new SnippetLocationNode(snippetReflection, locationIdentity, b.append(ConstantNode.forLong(0)), fromSigned(b, offset), b.append(ConstantNode.forInt(1)))); + } + + public ValueNode fromUnsigned(GraphBuilderContext b, ValueNode value) { + return convert(b, value, wordKind, true); + } + + public ValueNode fromSigned(GraphBuilderContext b, ValueNode value) { + return convert(b, value, wordKind, false); + } + + public ValueNode toUnsigned(GraphBuilderContext b, ValueNode value, Kind toKind) { + return convert(b, value, toKind, true); + } + + public ValueNode convert(GraphBuilderContext b, ValueNode value, Kind toKind, boolean unsigned) { + if (value.getKind() == toKind) { + return value; + } + + if (toKind == Kind.Int) { + assert value.getKind() == Kind.Long; + return b.append(new NarrowNode(value, 32)); + } else { + assert toKind == Kind.Long; + assert value.getKind().getStackKind() == Kind.Int; + if (unsigned) { + return b.append(new ZeroExtendNode(value, 64)); + } else { + return b.append(new SignExtendNode(value, 64)); + } + } + } + + public WordTypes getWordTypes() { + return wordTypes; + } +} diff -r 31fac91ea3b7 -r 14e703edb2ab graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/AssertionNode.java --- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/AssertionNode.java Wed Mar 11 17:16:30 2015 +0100 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/AssertionNode.java Wed Mar 11 20:43:12 2015 +0100 @@ -86,9 +86,6 @@ } } - @SuppressWarnings("unused") @NodeIntrinsic - public static void assertion(@ConstantNodeParameter boolean compileTimeAssertion, boolean value, @ConstantNodeParameter String message) { - assert value : message; - } + public static native void assertion(@ConstantNodeParameter boolean compileTimeAssertion, boolean value, @ConstantNodeParameter String message); } diff -r 31fac91ea3b7 -r 14e703edb2ab graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/BitCountNode.java --- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/BitCountNode.java Wed Mar 11 17:16:30 2015 +0100 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/BitCountNode.java Wed Mar 11 20:43:12 2015 +0100 @@ -47,28 +47,18 @@ IntegerStamp valueStamp = (IntegerStamp) getValue().stamp(); assert (valueStamp.downMask() & CodeUtil.mask(valueStamp.getBits())) == valueStamp.downMask(); assert (valueStamp.upMask() & CodeUtil.mask(valueStamp.getBits())) == valueStamp.upMask(); - return updateStamp(StampFactory.forInteger(Kind.Int, bitCount(valueStamp.downMask()), bitCount(valueStamp.upMask()))); + return updateStamp(StampFactory.forInteger(Kind.Int, Long.bitCount(valueStamp.downMask()), Long.bitCount(valueStamp.upMask()))); } @Override public ValueNode canonical(CanonicalizerTool tool, ValueNode forValue) { if (forValue.isConstant()) { JavaConstant c = forValue.asJavaConstant(); - return ConstantNode.forInt(forValue.getKind() == Kind.Int ? bitCount(c.asInt()) : bitCount(c.asLong())); + return ConstantNode.forInt(forValue.getKind() == Kind.Int ? Integer.bitCount(c.asInt()) : Long.bitCount(c.asLong())); } return this; } - @NodeIntrinsic - public static int bitCount(int v) { - return Integer.bitCount(v); - } - - @NodeIntrinsic - public static int bitCount(long v) { - return Long.bitCount(v); - } - @Override public void generate(NodeLIRBuilderTool gen) { Value result = gen.getLIRGeneratorTool().emitBitCount(gen.operand(getValue())); diff -r 31fac91ea3b7 -r 14e703edb2ab graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/DeferredPiNode.java --- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/DeferredPiNode.java Wed Mar 11 17:16:30 2015 +0100 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/DeferredPiNode.java Wed Mar 11 20:43:12 2015 +0100 @@ -66,5 +66,5 @@ } @NodeIntrinsic - public static native T piCast(Class type, Object object); + public static native Object piCast(Class type, Object object); } diff -r 31fac91ea3b7 -r 14e703edb2ab graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/DirectReadNode.java --- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/DirectReadNode.java Wed Mar 11 17:16:30 2015 +0100 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/DirectReadNode.java Wed Mar 11 20:43:12 2015 +0100 @@ -22,8 +22,6 @@ */ package com.oracle.graal.replacements.nodes; -import static com.oracle.graal.compiler.common.UnsafeAccess.*; - import com.oracle.graal.api.meta.*; import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.graph.*; @@ -81,32 +79,4 @@ } gen.setResult(this, loaded); } - - @SuppressWarnings("unchecked") - @NodeIntrinsic - public static T read(long address, @ConstantNodeParameter Kind kind) { - if (kind == Kind.Boolean) { - return (T) Boolean.valueOf(unsafe.getByte(address) != 0); - } - if (kind == Kind.Byte) { - return (T) (Byte) unsafe.getByte(address); - } - if (kind == Kind.Short) { - return (T) (Short) unsafe.getShort(address); - } - if (kind == Kind.Char) { - return (T) (Character) unsafe.getChar(address); - } - if (kind == Kind.Int) { - return (T) (Integer) unsafe.getInt(address); - } - if (kind == Kind.Float) { - return (T) (Float) unsafe.getFloat(address); - } - if (kind == Kind.Long) { - return (T) (Long) unsafe.getLong(address); - } - assert kind == Kind.Double; - return (T) (Double) unsafe.getDouble(address); - } } diff -r 31fac91ea3b7 -r 14e703edb2ab graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/DirectStoreNode.java --- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/DirectStoreNode.java Wed Mar 11 17:16:30 2015 +0100 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/DirectStoreNode.java Wed Mar 11 20:43:12 2015 +0100 @@ -22,8 +22,6 @@ */ package com.oracle.graal.replacements.nodes; -import static com.oracle.graal.compiler.common.UnsafeAccess.*; - import com.oracle.graal.api.meta.*; import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.graph.*; @@ -66,58 +64,6 @@ return value; } - /* - * The kind of the store is provided explicitly in these intrinsics because it is not always - * possible to determine the kind from the given value during compilation (because stack kinds - * are used). - */ - - @SuppressWarnings("unused") @NodeIntrinsic - public static void store(long address, boolean value, @ConstantNodeParameter Kind kind) { - int b = value ? 1 : 0; - unsafe.putByte(address, (byte) b); - } - - @SuppressWarnings("unused") - @NodeIntrinsic - public static void store(long address, byte value, @ConstantNodeParameter Kind kind) { - unsafe.putByte(address, value); - } - - @SuppressWarnings("unused") - @NodeIntrinsic - public static void store(long address, short value, @ConstantNodeParameter Kind kind) { - unsafe.putShort(address, value); - } - - @SuppressWarnings("unused") - @NodeIntrinsic - public static void store(long address, char value, @ConstantNodeParameter Kind kind) { - unsafe.putChar(address, value); - } - - @SuppressWarnings("unused") - @NodeIntrinsic - public static void store(long address, int value, @ConstantNodeParameter Kind kind) { - unsafe.putInt(address, value); - } - - @SuppressWarnings("unused") - @NodeIntrinsic - public static void store(long address, long value, @ConstantNodeParameter Kind kind) { - unsafe.putLong(address, value); - } - - @SuppressWarnings("unused") - @NodeIntrinsic - public static void store(long address, float value, @ConstantNodeParameter Kind kind) { - unsafe.putFloat(address, value); - } - - @SuppressWarnings("unused") - @NodeIntrinsic - public static void store(long address, double value, @ConstantNodeParameter Kind kind) { - unsafe.putDouble(address, value); - } + public static native void storeBoolean(long address, boolean value, @ConstantNodeParameter Kind kind); } diff -r 31fac91ea3b7 -r 14e703edb2ab graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/MathIntrinsicNode.java --- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/MathIntrinsicNode.java Wed Mar 11 17:16:30 2015 +0100 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/MathIntrinsicNode.java Wed Mar 11 20:43:12 2015 +0100 @@ -51,7 +51,23 @@ return operation; } - public MathIntrinsicNode(ValueNode value, Operation op) { + public static ValueNode create(ValueNode value, Operation op) { + ValueNode c = tryConstantFold(value, op); + if (c != null) { + return c; + } + return new MathIntrinsicNode(value, op); + } + + protected static ValueNode tryConstantFold(ValueNode value, Operation op) { + if (value.isConstant()) { + double ret = doCompute(value.asJavaConstant().asDouble(), op); + return ConstantNode.forDouble(ret); + } + return null; + } + + protected MathIntrinsicNode(ValueNode value, Operation op) { super(TYPE, StampFactory.forKind(Kind.Double), value); assert value.stamp() instanceof FloatStamp && PrimitiveStamp.getBits(value.stamp()) == 64; this.operation = op; @@ -85,17 +101,15 @@ @Override public ValueNode canonical(CanonicalizerTool tool, ValueNode forValue) { - if (forValue.isConstant()) { - double ret = doCompute(forValue.asJavaConstant().asDouble(), operation()); - return ConstantNode.forDouble(ret); + ValueNode c = tryConstantFold(forValue, operation()); + if (c != null) { + return c; } return this; } @NodeIntrinsic - public static double compute(double value, @ConstantNodeParameter Operation op) { - return doCompute(value, op); - } + public static native double compute(double value, @ConstantNodeParameter Operation op); private static double doCompute(double value, Operation op) { switch (op) { diff -r 31fac91ea3b7 -r 14e703edb2ab graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/ReverseBytesNode.java --- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/ReverseBytesNode.java Wed Mar 11 17:16:30 2015 +0100 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/ReverseBytesNode.java Wed Mar 11 20:43:12 2015 +0100 @@ -48,9 +48,9 @@ Stamp newStamp; if (getKind() == Kind.Int) { long mask = CodeUtil.mask(Kind.Int.getBitCount()); - newStamp = IntegerStamp.stampForMask(valueStamp.getBits(), reverse((int) valueStamp.downMask()) & mask, reverse((int) valueStamp.upMask()) & mask); + newStamp = IntegerStamp.stampForMask(valueStamp.getBits(), Integer.reverse((int) valueStamp.downMask()) & mask, Integer.reverse((int) valueStamp.upMask()) & mask); } else if (getKind() == Kind.Long) { - newStamp = IntegerStamp.stampForMask(valueStamp.getBits(), reverse(valueStamp.downMask()), reverse(valueStamp.upMask())); + newStamp = IntegerStamp.stampForMask(valueStamp.getBits(), Long.reverse(valueStamp.downMask()), Long.reverse(valueStamp.upMask())); } else { return false; } @@ -61,21 +61,12 @@ public ValueNode canonical(CanonicalizerTool tool, ValueNode forValue) { if (forValue.isConstant()) { JavaConstant c = forValue.asJavaConstant(); - return ConstantNode.forIntegerKind(getKind(), getKind() == Kind.Int ? reverse(c.asInt()) : reverse(c.asLong())); + long reversed = getKind() == Kind.Int ? Integer.reverseBytes(c.asInt()) : Long.reverseBytes(c.asLong()); + return ConstantNode.forIntegerKind(getKind(), reversed); } return this; } - @NodeIntrinsic - public static int reverse(int v) { - return Integer.reverseBytes(v); - } - - @NodeIntrinsic - public static long reverse(long v) { - return Long.reverseBytes(v); - } - @Override public void generate(NodeLIRBuilderTool gen) { Value result = gen.getLIRGeneratorTool().emitByteSwap(gen.operand(getValue())); diff -r 31fac91ea3b7 -r 14e703edb2ab graal/com.oracle.graal.truffle.hotspot/src/com/oracle/graal/truffle/hotspot/HotSpotTruffleReplacements.java --- a/graal/com.oracle.graal.truffle.hotspot/src/com/oracle/graal/truffle/hotspot/HotSpotTruffleReplacements.java Wed Mar 11 17:16:30 2015 +0100 +++ b/graal/com.oracle.graal.truffle.hotspot/src/com/oracle/graal/truffle/hotspot/HotSpotTruffleReplacements.java Wed Mar 11 20:43:12 2015 +0100 @@ -22,10 +22,8 @@ */ package com.oracle.graal.truffle.hotspot; -import com.oracle.graal.api.meta.*; import com.oracle.graal.api.replacements.*; import com.oracle.graal.api.runtime.*; -import com.oracle.graal.hotspot.*; import com.oracle.graal.nodes.spi.*; import com.oracle.graal.phases.util.*; import com.oracle.graal.runtime.*; @@ -42,9 +40,4 @@ SnippetReflectionProvider snippetReflection = Graal.getRequiredCapability(SnippetReflectionProvider.class); return new HotSpotTruffleReplacements(providers, snippetReflection); } - - @Override - protected GraphMaker createGraphMaker(ResolvedJavaMethod substitute, ResolvedJavaMethod original, FrameStateProcessing frameStateProcessing) { - return new HotSpotReplacementsImpl.HotSpotGraphMaker(this, substitute, original, frameStateProcessing); - } } diff -r 31fac91ea3b7 -r 14e703edb2ab graal/com.oracle.graal.truffle.hotspot/src/com/oracle/graal/truffle/hotspot/HotSpotTruffleRuntime.java --- a/graal/com.oracle.graal.truffle.hotspot/src/com/oracle/graal/truffle/hotspot/HotSpotTruffleRuntime.java Wed Mar 11 17:16:30 2015 +0100 +++ b/graal/com.oracle.graal.truffle.hotspot/src/com/oracle/graal/truffle/hotspot/HotSpotTruffleRuntime.java Wed Mar 11 20:43:12 2015 +0100 @@ -192,7 +192,7 @@ LIRSuites lirSuites = suitesProvider.createLIRSuites(); removeInliningPhase(suites); StructuredGraph graph = new StructuredGraph(javaMethod, AllowAssumptions.NO); - new GraphBuilderPhase.Instance(metaAccess, providers.getStampProvider(), providers.getConstantReflection(), GraphBuilderConfiguration.getEagerDefault(), OptimisticOptimizations.ALL, false).apply(graph); + new GraphBuilderPhase.Instance(metaAccess, providers.getStampProvider(), providers.getConstantReflection(), GraphBuilderConfiguration.getEagerDefault(), OptimisticOptimizations.ALL, null).apply(graph); PhaseSuite graphBuilderSuite = getGraphBuilderSuite(suitesProvider); CallingConvention cc = getCallingConvention(providers.getCodeCache(), Type.JavaCallee, graph.method(), false); Backend backend = Graal.getRequiredCapability(RuntimeProvider.class).getHostBackend(); @@ -315,7 +315,7 @@ public void notifyTransferToInterpreter() { CompilerAsserts.neverPartOfCompilation(); if (TraceTruffleTransferToInterpreter.getValue()) { - Word thread = CurrentJavaThreadNode.get(HotSpotGraalRuntime.runtime().getTarget().wordKind); + Word thread = CurrentJavaThreadNode.get(); boolean deoptimized = thread.readByte(HotSpotGraalRuntime.runtime().getConfig().pendingTransferToInterpreterOffset) != 0; if (deoptimized) { thread.writeByte(HotSpotGraalRuntime.runtime().getConfig().pendingTransferToInterpreterOffset, (byte) 0); diff -r 31fac91ea3b7 -r 14e703edb2ab graal/com.oracle.graal.truffle.test/src/com/oracle/graal/truffle/test/ExactMathTest.java --- a/graal/com.oracle.graal.truffle.test/src/com/oracle/graal/truffle/test/ExactMathTest.java Wed Mar 11 17:16:30 2015 +0100 +++ b/graal/com.oracle.graal.truffle.test/src/com/oracle/graal/truffle/test/ExactMathTest.java Wed Mar 11 20:43:12 2015 +0100 @@ -24,23 +24,17 @@ import org.junit.*; -import com.oracle.graal.api.runtime.*; import com.oracle.graal.compiler.test.*; -import com.oracle.graal.nodes.spi.*; -import com.oracle.graal.runtime.*; +import com.oracle.graal.java.*; import com.oracle.graal.truffle.substitutions.*; import com.oracle.truffle.api.*; public class ExactMathTest extends GraalCompilerTest { - private static boolean substitutionsInstalled; - - public ExactMathTest() { - if (!substitutionsInstalled) { - Replacements replacements = Graal.getRequiredCapability(RuntimeProvider.class).getHostBackend().getProviders().getReplacements(); - replacements.registerSubstitutions(ExactMath.class, ExactMathSubstitutions.class); - substitutionsInstalled = true; - } + @Override + protected void editGraphBuilderPlugins(GraphBuilderConfiguration.Plugins plugins) { + TruffleGraphBuilderPlugins.registerExactMathPlugins(getMetaAccess(), plugins.getInvocationPlugins()); + super.editGraphBuilderPlugins(plugins); } @Test diff -r 31fac91ea3b7 -r 14e703edb2ab graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/PartialEvaluator.java --- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/PartialEvaluator.java Wed Mar 11 17:16:30 2015 +0100 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/PartialEvaluator.java Wed Mar 11 20:43:12 2015 +0100 @@ -31,6 +31,7 @@ import com.oracle.graal.api.meta.*; import com.oracle.graal.api.replacements.*; import com.oracle.graal.compiler.common.*; +import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.debug.*; import com.oracle.graal.debug.Debug.Scope; import com.oracle.graal.debug.internal.*; @@ -176,7 +177,7 @@ this.receiver = receiver; } - public FloatingNode interceptParameter(int index) { + public FloatingNode interceptParameter(GraphBuilderContext b, int index, Stamp stamp) { if (index == 0) { return ConstantNode.forConstant(snippetReflection.forObject(receiver), providers.getMetaAccess()); } @@ -196,7 +197,7 @@ this.replacements = replacements; } - public ResolvedJavaMethod getInlinedMethod(GraphBuilderContext builder, ResolvedJavaMethod original, ValueNode[] arguments, JavaType returnType) { + public InlineInfo getInlineInfo(GraphBuilderContext builder, ResolvedJavaMethod original, ValueNode[] arguments, JavaType returnType) { if (original.getAnnotation(TruffleBoundary.class) != null) { return null; } @@ -220,10 +221,10 @@ if (decision != null && decision.isInline()) { inlining.push(decision); builder.getAssumptions().record(new AssumptionValidAssumption((OptimizedAssumption) decision.getTarget().getNodeRewritingAssumption())); - return callInlinedMethod; + return new InlineInfo(callInlinedMethod, false); } } - return original; + return new InlineInfo(original, false); } public void postInline(ResolvedJavaMethod inlinedTargetMethod) { @@ -261,7 +262,7 @@ plugins.setLoopExplosionPlugin(new LoopExplosionPlugin()); TruffleGraphBuilderPlugins.registerInvocationPlugins(providers.getMetaAccess(), newConfig.getPlugins().getInvocationPlugins()); new GraphBuilderPhase.Instance(providers.getMetaAccess(), providers.getStampProvider(), this.snippetReflection, providers.getConstantReflection(), newConfig, - TruffleCompilerImpl.Optimizations, false).apply(graph); + TruffleCompilerImpl.Optimizations, null).apply(graph); Debug.dump(graph, "After FastPE"); // Perform deoptimize to guard conversion. @@ -335,13 +336,13 @@ } public StructuredGraph createRootGraph(StructuredGraph graph) { - new GraphBuilderPhase.Instance(providers.getMetaAccess(), providers.getStampProvider(), providers.getConstantReflection(), configForRoot, TruffleCompilerImpl.Optimizations, false).apply(graph); + new GraphBuilderPhase.Instance(providers.getMetaAccess(), providers.getStampProvider(), providers.getConstantReflection(), configForRoot, TruffleCompilerImpl.Optimizations, null).apply(graph); return graph; } public StructuredGraph createInlineGraph(String name, StructuredGraph caller) { StructuredGraph graph = new StructuredGraph(name, callInlinedMethod, AllowAssumptions.from(caller.getAssumptions() != null)); - new GraphBuilderPhase.Instance(providers.getMetaAccess(), providers.getStampProvider(), providers.getConstantReflection(), configForRoot, TruffleCompilerImpl.Optimizations, false).apply(graph); + new GraphBuilderPhase.Instance(providers.getMetaAccess(), providers.getStampProvider(), providers.getConstantReflection(), configForRoot, TruffleCompilerImpl.Optimizations, null).apply(graph); return graph; } diff -r 31fac91ea3b7 -r 14e703edb2ab graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleCacheImpl.java --- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleCacheImpl.java Wed Mar 11 17:16:30 2015 +0100 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleCacheImpl.java Wed Mar 11 20:43:12 2015 +0100 @@ -269,7 +269,7 @@ } protected StructuredGraph parseGraph(StructuredGraph graph, final PhaseContext phaseContext) { - new GraphBuilderPhase.Instance(phaseContext.getMetaAccess(), phaseContext.getStampProvider(), null, config, optimisticOptimizations, false).apply(graph); + new GraphBuilderPhase.Instance(phaseContext.getMetaAccess(), phaseContext.getStampProvider(), null, config, optimisticOptimizations, null).apply(graph); return graph; } diff -r 31fac91ea3b7 -r 14e703edb2ab graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleReplacements.java --- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleReplacements.java Wed Mar 11 17:16:30 2015 +0100 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleReplacements.java Wed Mar 11 20:43:12 2015 +0100 @@ -32,7 +32,6 @@ import com.oracle.graal.phases.util.*; import com.oracle.graal.replacements.*; import com.oracle.graal.truffle.substitutions.*; -import com.oracle.graal.truffle.unsafe.*; import com.oracle.truffle.api.*; /** @@ -52,18 +51,13 @@ protected void registerTruffleSubstitutions() { if (!TruffleCompilerOptions.FastPE.getValue()) { registerSubstitutions(CompilerAsserts.class, CompilerAssertsSubstitutions.class); - registerSubstitutions(CompilerDirectives.class, CompilerDirectivesSubstitutions.class); - registerSubstitutions(ExactMath.class, ExactMathSubstitutions.class); registerSubstitutions(OptimizedAssumption.class, OptimizedAssumptionSubstitutions.class); - registerSubstitutions(OptimizedCallTarget.class, OptimizedCallTargetSubstitutions.class); - registerSubstitutions(FrameWithoutBoxing.class, FrameWithoutBoxingSubstitutions.class); - registerSubstitutions(UnsafeAccessImpl.class, UnsafeAccessSubstitutions.class); } } @Override - public StructuredGraph getSnippet(ResolvedJavaMethod method) { - return graalReplacements.getSnippet(method); + public StructuredGraph getSnippet(ResolvedJavaMethod method, Object[] args) { + return graalReplacements.getSnippet(method, null, args); } @Override diff -r 31fac91ea3b7 -r 14e703edb2ab graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/arithmetic/IntegerAddExactNode.java --- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/arithmetic/IntegerAddExactNode.java Wed Mar 11 17:16:30 2015 +0100 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/arithmetic/IntegerAddExactNode.java Wed Mar 11 20:43:12 2015 +0100 @@ -107,14 +107,4 @@ public void lower(LoweringTool tool) { IntegerExactArithmeticSplitNode.lower(tool, this); } - - @NodeIntrinsic - public static int addExact(int a, int b) { - return ExactMath.addExact(a, b); - } - - @NodeIntrinsic - public static long addExact(long a, long b) { - return ExactMath.addExact(a, b); - } } diff -r 31fac91ea3b7 -r 14e703edb2ab graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/arithmetic/IntegerMulExactNode.java --- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/arithmetic/IntegerMulExactNode.java Wed Mar 11 17:16:30 2015 +0100 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/arithmetic/IntegerMulExactNode.java Wed Mar 11 20:43:12 2015 +0100 @@ -90,14 +90,4 @@ public void lower(LoweringTool tool) { IntegerExactArithmeticSplitNode.lower(tool, this); } - - @NodeIntrinsic - public static int multiplyExact(int a, int b) { - return ExactMath.multiplyExact(a, b); - } - - @NodeIntrinsic - public static long multiplyExact(long a, long b) { - return ExactMath.multiplyExact(a, b); - } } diff -r 31fac91ea3b7 -r 14e703edb2ab graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/arithmetic/IntegerMulHighNode.java --- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/arithmetic/IntegerMulHighNode.java Wed Mar 11 17:16:30 2015 +0100 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/arithmetic/IntegerMulHighNode.java Wed Mar 11 20:43:12 2015 +0100 @@ -88,14 +88,4 @@ Value b = builder.operand(getY()); builder.setResult(this, gen.emitMulHigh(a, b)); } - - @NodeIntrinsic - public static int multiplyHigh(int a, int b) { - return ExactMath.multiplyHigh(a, b); - } - - @NodeIntrinsic - public static long multiplyHigh(long a, long b) { - return ExactMath.multiplyHigh(a, b); - } } diff -r 31fac91ea3b7 -r 14e703edb2ab graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/arithmetic/IntegerSubExactNode.java --- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/arithmetic/IntegerSubExactNode.java Wed Mar 11 17:16:30 2015 +0100 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/arithmetic/IntegerSubExactNode.java Wed Mar 11 20:43:12 2015 +0100 @@ -96,12 +96,8 @@ } @NodeIntrinsic - public static int subtractExact(int a, int b) { - return ExactMath.subtractExact(a, b); - } + public static native int subtractExact(int a, int b); @NodeIntrinsic - public static long subtractExact(long a, long b) { - return ExactMath.subtractExact(a, b); - } + public static native long subtractExact(long a, long b); } diff -r 31fac91ea3b7 -r 14e703edb2ab graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/arithmetic/UnsignedMulHighNode.java --- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/arithmetic/UnsignedMulHighNode.java Wed Mar 11 17:16:30 2015 +0100 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/arithmetic/UnsignedMulHighNode.java Wed Mar 11 20:43:12 2015 +0100 @@ -93,14 +93,4 @@ Value b = builder.operand(getY()); builder.setResult(this, gen.emitUMulHigh(a, b)); } - - @NodeIntrinsic - public static int multiplyHighUnsigned(int a, int b) { - return ExactMath.multiplyHighUnsigned(a, b); - } - - @NodeIntrinsic - public static long multiplyHighUnsigned(long a, long b) { - return ExactMath.multiplyHighUnsigned(a, b); - } } diff -r 31fac91ea3b7 -r 14e703edb2ab graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/frame/MaterializeFrameNode.java --- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/frame/MaterializeFrameNode.java Wed Mar 11 17:16:30 2015 +0100 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/frame/MaterializeFrameNode.java Wed Mar 11 20:43:12 2015 +0100 @@ -46,5 +46,5 @@ } @NodeIntrinsic - public static native T materialize(VirtualFrame frame); + public static native MaterializedFrame materialize(VirtualFrame frame); } diff -r 31fac91ea3b7 -r 14e703edb2ab graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/substitutions/CompilerDirectivesSubstitutions.java --- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/substitutions/CompilerDirectivesSubstitutions.java Wed Mar 11 17:16:30 2015 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,85 +0,0 @@ -/* - * Copyright (c) 2013, 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.truffle.substitutions; - -import java.util.concurrent.*; - -import com.oracle.graal.api.meta.*; -import com.oracle.graal.api.replacements.*; -import com.oracle.graal.nodes.*; -import com.oracle.graal.nodes.extended.*; -import com.oracle.graal.nodes.spi.*; -import com.oracle.graal.truffle.nodes.*; -import com.oracle.graal.truffle.nodes.frame.*; -import com.oracle.truffle.api.*; - -@ClassSubstitution(CompilerDirectives.class) -public class CompilerDirectivesSubstitutions { - - @MethodSubstitution - public static void transferToInterpreter() { - DeoptimizeNode.deopt(DeoptimizationAction.None, DeoptimizationReason.TransferToInterpreter); - } - - @MethodSubstitution - public static void transferToInterpreterAndInvalidate() { - DeoptimizeNode.deopt(DeoptimizationAction.InvalidateReprofile, DeoptimizationReason.TransferToInterpreter); - } - - @MethodSubstitution - public static boolean inInterpreter() { - return false; - } - - @MethodSubstitution - public static boolean inCompiledCode() { - return true; - } - - @MethodSubstitution - public static void interpreterOnly(@SuppressWarnings("unused") Runnable runnable) { - } - - @MethodSubstitution - public static T interpreterOnly(@SuppressWarnings("unused") Callable callable) throws Exception { - return null; - } - - @MethodSubstitution - public static boolean injectBranchProbability(double probability, boolean condition) { - return BranchProbabilityNode.probability(probability, condition); - } - - @MacroSubstitution(macro = BailoutNode.class, isStatic = true) - public static native void bailout(String reason); - - @MethodSubstitution - public static boolean isCompilationConstant(Object value) { - return IsCompilationConstantNode.check(value); - } - - @MethodSubstitution - public static void materialize(Object obj) { - ForceMaterializeNode.force(obj); - } -} diff -r 31fac91ea3b7 -r 14e703edb2ab graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/substitutions/ExactMathSubstitutions.java --- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/substitutions/ExactMathSubstitutions.java Wed Mar 11 17:16:30 2015 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,85 +0,0 @@ -/* - * Copyright (c) 2013, 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.truffle.substitutions; - -import com.oracle.graal.api.replacements.*; -import com.oracle.graal.truffle.nodes.arithmetic.*; -import com.oracle.truffle.api.*; - -/** - * Intrinsics for exact math operations that throw an exception in case the operation would overflow - * the allowed range. - */ -@ClassSubstitution(ExactMath.class) -public class ExactMathSubstitutions { - - @MethodSubstitution - public static int addExact(int x, int y) { - return IntegerAddExactNode.addExact(x, y); - } - - @MethodSubstitution - public static long addExact(long x, long y) { - return IntegerAddExactNode.addExact(x, y); - } - - @MethodSubstitution - public static int subtractExact(int x, int y) { - return IntegerSubExactNode.subtractExact(x, y); - } - - @MethodSubstitution - public static long subtractExact(long x, long y) { - return IntegerSubExactNode.subtractExact(x, y); - } - - @MethodSubstitution - public static int multiplyExact(int x, int y) { - return IntegerMulExactNode.multiplyExact(x, y); - } - - @MethodSubstitution - public static long multiplyExact(long x, long y) { - return IntegerMulExactNode.multiplyExact(x, y); - } - - @MethodSubstitution - public static int multiplyHigh(int x, int y) { - return IntegerMulHighNode.multiplyHigh(x, y); - } - - @MethodSubstitution - public static int multiplyHighUnsigned(int x, int y) { - return UnsignedMulHighNode.multiplyHighUnsigned(x, y); - } - - @MethodSubstitution - public static long multiplyHigh(long x, long y) { - return IntegerMulHighNode.multiplyHigh(x, y); - } - - @MethodSubstitution - public static long multiplyHighUnsigned(long x, long y) { - return UnsignedMulHighNode.multiplyHighUnsigned(x, y); - } -} diff -r 31fac91ea3b7 -r 14e703edb2ab graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/substitutions/FrameWithoutBoxingSubstitutions.java --- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/substitutions/FrameWithoutBoxingSubstitutions.java Wed Mar 11 17:16:30 2015 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,72 +0,0 @@ -/* - * Copyright (c) 2014, 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.truffle.substitutions; - -import com.oracle.graal.api.replacements.*; -import com.oracle.graal.nodes.spi.*; -import com.oracle.graal.truffle.*; -import com.oracle.graal.truffle.nodes.frame.*; -import com.oracle.graal.truffle.nodes.typesystem.*; -import com.oracle.truffle.api.frame.*; - -@ClassSubstitution(FrameWithoutBoxing.class) -public class FrameWithoutBoxingSubstitutions { - - @MethodSubstitution(isStatic = false) - public static MaterializedFrame materialize(FrameWithoutBoxing frame) { - return MaterializeFrameNode.materialize(frame); - } - - @MacroSubstitution(macro = UnsafeTypeCastMacroNode.class, isStatic = true) - public static native Object unsafeCast(Object value, Class clazz, boolean condition, boolean nonNull); - - @MacroSubstitution(macro = CustomizedUnsafeLoadMacroNode.class, isStatic = true) - public static native int unsafeGetInt(Object receiver, long offset, boolean condition, Object locationIdentity); - - @MacroSubstitution(macro = CustomizedUnsafeLoadMacroNode.class, isStatic = true) - public static native long unsafeGetLong(Object receiver, long offset, boolean condition, Object locationIdentity); - - @MacroSubstitution(macro = CustomizedUnsafeLoadMacroNode.class, isStatic = true) - public static native float unsafeGetFloat(Object receiver, long offset, boolean condition, Object locationIdentity); - - @MacroSubstitution(macro = CustomizedUnsafeLoadMacroNode.class, isStatic = true) - public static native double unsafeGetDouble(Object receiver, long offset, boolean condition, Object locationIdentity); - - @MacroSubstitution(macro = CustomizedUnsafeLoadMacroNode.class, isStatic = true) - public static native Object unsafeGetObject(Object receiver, long offset, boolean condition, Object locationIdentity); - - @MacroSubstitution(macro = CustomizedUnsafeStoreMacroNode.class, isStatic = true) - public static native void unsafePutInt(Object receiver, long offset, int value, Object locationIdentity); - - @MacroSubstitution(macro = CustomizedUnsafeStoreMacroNode.class, isStatic = true) - public static native void unsafePutLong(Object receiver, long offset, long value, Object locationIdentity); - - @MacroSubstitution(macro = CustomizedUnsafeStoreMacroNode.class, isStatic = true) - public static native void unsafePutFloat(Object receiver, long offset, float value, Object locationIdentity); - - @MacroSubstitution(macro = CustomizedUnsafeStoreMacroNode.class, isStatic = true) - public static native void unsafePutDouble(Object receiver, long offset, double value, Object locationIdentity); - - @MacroSubstitution(macro = CustomizedUnsafeStoreMacroNode.class, isStatic = true) - public static native void unsafePutObject(Object receiver, long offset, Object value, Object locationIdentity); -} diff -r 31fac91ea3b7 -r 14e703edb2ab graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/substitutions/OptimizedCallTargetSubstitutions.java --- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/substitutions/OptimizedCallTargetSubstitutions.java Wed Mar 11 17:16:30 2015 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,44 +0,0 @@ -/* - * Copyright (c) 2013, 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.truffle.substitutions; - -import com.oracle.graal.api.replacements.*; -import com.oracle.graal.compiler.common.type.*; -import com.oracle.graal.nodes.*; -import com.oracle.graal.truffle.*; -import com.oracle.graal.truffle.nodes.frame.*; -import com.oracle.truffle.api.frame.*; - -@ClassSubstitution(OptimizedCallTarget.class) -public class OptimizedCallTargetSubstitutions { - - @MethodSubstitution - private static VirtualFrame createFrame(FrameDescriptor descriptor, Object[] args) { - return NewFrameNode.allocate(FrameWithoutBoxing.class, descriptor, args); - } - - @MethodSubstitution - private static Object castArrayFixedLength(Object[] args, int length) { - return PiArrayNode.piArrayCast(args, length, StampFactory.forNodeIntrinsic()); - } -} diff -r 31fac91ea3b7 -r 14e703edb2ab graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/substitutions/TruffleGraphBuilderPlugins.java --- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/substitutions/TruffleGraphBuilderPlugins.java Wed Mar 11 17:16:30 2015 +0100 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/substitutions/TruffleGraphBuilderPlugins.java Wed Mar 11 20:43:12 2015 +0100 @@ -70,16 +70,16 @@ public static void registerOptimizedAssumptionPlugins(MetaAccessProvider metaAccess, InvocationPlugins plugins) { Registration r = new Registration(plugins, metaAccess, OptimizedAssumption.class); r.register1("isValid", Receiver.class, new InvocationPlugin() { - public boolean apply(GraphBuilderContext builder, ValueNode arg) { + public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, ValueNode arg) { if (arg.isConstant()) { Constant constant = arg.asConstant(); - OptimizedAssumption assumption = builder.getSnippetReflection().asObject(OptimizedAssumption.class, (JavaConstant) constant); - builder.push(Kind.Boolean.getStackKind(), builder.append(ConstantNode.forBoolean(assumption.isValid()))); + OptimizedAssumption assumption = b.getSnippetReflection().asObject(OptimizedAssumption.class, (JavaConstant) constant); + b.push(Kind.Boolean.getStackKind(), b.append(ConstantNode.forBoolean(assumption.isValid()))); if (assumption.isValid()) { - builder.getAssumptions().record(new AssumptionValidAssumption(assumption)); + b.getAssumptions().record(new AssumptionValidAssumption(assumption)); } } else { - throw builder.bailout("assumption could not be reduced to a constant"); + throw b.bailout("assumption could not be reduced to a constant"); } return true; } @@ -89,33 +89,34 @@ public static void registerExactMathPlugins(MetaAccessProvider metaAccess, InvocationPlugins plugins) { Registration r = new Registration(plugins, metaAccess, ExactMath.class); for (Kind kind : new Kind[]{Kind.Int, Kind.Long}) { - r.register2("addExact", kind.toJavaClass(), kind.toJavaClass(), new InvocationPlugin() { - public boolean apply(GraphBuilderContext builder, ValueNode x, ValueNode y) { - builder.push(kind.getStackKind(), builder.append(new IntegerAddExactNode(x, y))); + Class type = kind.toJavaClass(); + r.register2("addExact", type, type, new InvocationPlugin() { + public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, ValueNode x, ValueNode y) { + b.push(kind.getStackKind(), b.append(new IntegerAddExactNode(x, y))); return true; } }); - r.register2("subtractExact", kind.toJavaClass(), kind.toJavaClass(), new InvocationPlugin() { - public boolean apply(GraphBuilderContext builder, ValueNode x, ValueNode y) { - builder.push(kind.getStackKind(), builder.append(new IntegerSubExactNode(x, y))); + r.register2("subtractExact", type, type, new InvocationPlugin() { + public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, ValueNode x, ValueNode y) { + b.push(kind.getStackKind(), b.append(new IntegerSubExactNode(x, y))); return true; } }); - r.register2("multiplyExact", kind.toJavaClass(), kind.toJavaClass(), new InvocationPlugin() { - public boolean apply(GraphBuilderContext builder, ValueNode x, ValueNode y) { - builder.push(kind.getStackKind(), builder.append(new IntegerMulExactNode(x, y))); + r.register2("multiplyExact", type, type, new InvocationPlugin() { + public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, ValueNode x, ValueNode y) { + b.push(kind.getStackKind(), b.append(new IntegerMulExactNode(x, y))); return true; } }); - r.register2("multiplyHigh", kind.toJavaClass(), kind.toJavaClass(), new InvocationPlugin() { - public boolean apply(GraphBuilderContext builder, ValueNode x, ValueNode y) { - builder.push(kind.getStackKind(), builder.append(new IntegerMulHighNode(x, y))); + r.register2("multiplyHigh", type, type, new InvocationPlugin() { + public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, ValueNode x, ValueNode y) { + b.push(kind.getStackKind(), b.append(new IntegerMulHighNode(x, y))); return true; } }); - r.register2("multiplyHighUnsigned", kind.toJavaClass(), kind.toJavaClass(), new InvocationPlugin() { - public boolean apply(GraphBuilderContext builder, ValueNode x, ValueNode y) { - builder.push(kind.getStackKind(), builder.append(new UnsignedMulHighNode(x, y))); + r.register2("multiplyHighUnsigned", type, type, new InvocationPlugin() { + public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, ValueNode x, ValueNode y) { + b.push(kind.getStackKind(), b.append(new UnsignedMulHighNode(x, y))); return true; } }); @@ -125,73 +126,73 @@ public static void registerCompilerDirectivesPlugins(MetaAccessProvider metaAccess, InvocationPlugins plugins) { Registration r = new Registration(plugins, metaAccess, CompilerDirectives.class); r.register0("inInterpreter", new InvocationPlugin() { - public boolean apply(GraphBuilderContext builder) { - builder.push(Kind.Boolean.getStackKind(), builder.append(ConstantNode.forBoolean(false))); + public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod) { + b.push(Kind.Boolean.getStackKind(), b.append(ConstantNode.forBoolean(false))); return true; } }); r.register0("inCompiledCode", new InvocationPlugin() { - public boolean apply(GraphBuilderContext builder) { - builder.push(Kind.Boolean.getStackKind(), builder.append(ConstantNode.forBoolean(true))); + public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod) { + b.push(Kind.Boolean.getStackKind(), b.append(ConstantNode.forBoolean(true))); return true; } }); r.register0("transferToInterpreter", new InvocationPlugin() { - public boolean apply(GraphBuilderContext builder) { - builder.append(new DeoptimizeNode(DeoptimizationAction.None, DeoptimizationReason.TransferToInterpreter)); + public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod) { + b.append(new DeoptimizeNode(DeoptimizationAction.None, DeoptimizationReason.TransferToInterpreter)); return true; } }); r.register0("transferToInterpreterAndInvalidate", new InvocationPlugin() { - public boolean apply(GraphBuilderContext builder) { - builder.append(new DeoptimizeNode(DeoptimizationAction.InvalidateReprofile, DeoptimizationReason.TransferToInterpreter)); + public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod) { + b.append(new DeoptimizeNode(DeoptimizationAction.InvalidateReprofile, DeoptimizationReason.TransferToInterpreter)); return true; } }); r.register1("interpreterOnly", Runnable.class, new InvocationPlugin() { - public boolean apply(GraphBuilderContext builder, ValueNode arg) { + public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, ValueNode arg) { return true; } }); r.register1("interpreterOnly", Callable.class, new InvocationPlugin() { - public boolean apply(GraphBuilderContext builder, ValueNode arg) { + public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, ValueNode arg) { return true; } }); r.register2("injectBranchProbability", double.class, boolean.class, new InvocationPlugin() { - public boolean apply(GraphBuilderContext builder, ValueNode probability, ValueNode condition) { - builder.push(Kind.Boolean.getStackKind(), builder.append(new BranchProbabilityNode(probability, condition))); + public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, ValueNode probability, ValueNode condition) { + b.push(Kind.Boolean.getStackKind(), b.append(new BranchProbabilityNode(probability, condition))); return true; } }); r.register1("bailout", String.class, new InvocationPlugin() { - public boolean apply(GraphBuilderContext builder, ValueNode message) { + public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, ValueNode message) { if (message.isConstant()) { - throw builder.bailout(message.asConstant().toValueString()); + throw b.bailout(message.asConstant().toValueString()); } - throw builder.bailout("bailout (message is not compile-time constant, so no additional information is available)"); + throw b.bailout("bailout (message is not compile-time constant, so no additional information is available)"); } }); r.register1("isCompilationConstant", Object.class, new InvocationPlugin() { - public boolean apply(GraphBuilderContext builder, ValueNode value) { + public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, ValueNode value) { if ((value instanceof BoxNode ? ((BoxNode) value).getValue() : value).isConstant()) { - builder.push(Kind.Boolean.getStackKind(), builder.append(ConstantNode.forBoolean(true))); + b.push(Kind.Boolean.getStackKind(), b.append(ConstantNode.forBoolean(true))); } else { - builder.push(Kind.Boolean.getStackKind(), builder.append(new IsCompilationConstantNode(value))); + b.push(Kind.Boolean.getStackKind(), b.append(new IsCompilationConstantNode(value))); } return true; } }); r.register1("materialize", Object.class, new InvocationPlugin() { - public boolean apply(GraphBuilderContext builder, ValueNode value) { - builder.append(new ForceMaterializeNode(value)); + public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, ValueNode value) { + b.append(new ForceMaterializeNode(value)); return true; } }); r = new Registration(plugins, metaAccess, CompilerAsserts.class); r.register1("partialEvaluationConstant", Object.class, new InvocationPlugin() { - public boolean apply(GraphBuilderContext builder, ValueNode value) { + public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, ValueNode value) { ValueNode curValue = value; if (curValue instanceof BoxNode) { BoxNode boxNode = (BoxNode) curValue; @@ -211,18 +212,18 @@ } sb.append(")"); } - throw builder.bailout("Partial evaluation did not reduce value to a constant, is a regular compiler node: " + sb.toString()); + throw b.bailout("Partial evaluation did not reduce value to a constant, is a regular compiler node: " + sb.toString()); } } }); r.register1("neverPartOfCompilation", String.class, new InvocationPlugin() { - public boolean apply(GraphBuilderContext builder, ValueNode message) { + public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, ValueNode message) { if (message.isConstant()) { String messageString = message.asConstant().toValueString(); - builder.append(new NeverPartOfCompilationNode(messageString)); + b.append(new NeverPartOfCompilationNode(messageString)); return true; } - throw builder.bailout("message for never part of compilation is non-constant"); + throw b.bailout("message for never part of compilation is non-constant"); } }); } @@ -230,9 +231,15 @@ public static void registerOptimizedCallTargetPlugins(MetaAccessProvider metaAccess, InvocationPlugins plugins) { Registration r = new Registration(plugins, metaAccess, OptimizedCallTarget.class); r.register2("createFrame", FrameDescriptor.class, Object[].class, new InvocationPlugin() { - public boolean apply(GraphBuilderContext builder, ValueNode arg1, ValueNode arg2) { + public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, ValueNode descriptor, ValueNode args) { Class frameClass = TruffleCompilerOptions.TruffleUseFrameWithoutBoxing.getValue() ? FrameWithoutBoxing.class : FrameWithBoxing.class; - builder.push(Kind.Object, builder.append(new NewFrameNode(StampFactory.exactNonNull(metaAccess.lookupJavaType(frameClass)), arg1, arg2))); + b.push(Kind.Object, b.append(new NewFrameNode(StampFactory.exactNonNull(metaAccess.lookupJavaType(frameClass)), descriptor, args))); + return true; + } + }); + r.register2("castArrayFixedLength", Object[].class, int.class, new InvocationPlugin() { + public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, ValueNode args, ValueNode length) { + b.push(Kind.Object, b.append(new PiArrayNode(args, length, args.stamp()))); return true; } }); @@ -259,8 +266,8 @@ private static void registerMaterialize(Registration r) { r.register1("materialize", Receiver.class, new InvocationPlugin() { - public boolean apply(GraphBuilderContext builder, ValueNode frame) { - builder.push(Kind.Object, builder.append(new MaterializeFrameNode(frame))); + public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, ValueNode frame) { + b.push(Kind.Object, b.append(new MaterializeFrameNode(frame))); return true; } }); @@ -268,12 +275,12 @@ private static void registerUnsafeCast(Registration r) { r.register4("unsafeCast", Object.class, Class.class, boolean.class, boolean.class, new InvocationPlugin() { - public boolean apply(GraphBuilderContext builder, ValueNode object, ValueNode clazz, ValueNode condition, ValueNode nonNull) { + public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, ValueNode object, ValueNode clazz, ValueNode condition, ValueNode nonNull) { if (clazz.isConstant() && nonNull.isConstant()) { - ConstantReflectionProvider constantReflection = builder.getConstantReflection(); + ConstantReflectionProvider constantReflection = b.getConstantReflection(); ResolvedJavaType javaType = constantReflection.asJavaType(clazz.asConstant()); if (javaType == null) { - builder.push(Kind.Object, object); + b.push(Kind.Object, object); } else { Stamp piStamp = null; if (javaType.isArray()) { @@ -295,10 +302,10 @@ } ConditionAnchorNode valueAnchorNode = null; if (!skipAnchor) { - valueAnchorNode = builder.append(new ConditionAnchorNode(compareNode)); + valueAnchorNode = b.append(new ConditionAnchorNode(compareNode)); } - PiNode piCast = builder.append(new PiNode(object, piStamp, valueAnchorNode)); - builder.push(Kind.Object, piCast); + PiNode piCast = b.append(new PiNode(object, piStamp, valueAnchorNode)); + b.push(Kind.Object, piCast); } return true; } @@ -326,7 +333,7 @@ this.returnKind = returnKind; } - public boolean apply(GraphBuilderContext builder, ValueNode object, ValueNode offset, ValueNode condition, ValueNode location) { + public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, ValueNode object, ValueNode offset, ValueNode condition, ValueNode location) { if (location.isConstant()) { LocationIdentity locationIdentity; if (location.isNullConstant()) { @@ -334,8 +341,8 @@ } else { locationIdentity = ObjectLocationIdentity.create(location.asJavaConstant()); } - LogicNode compare = builder.append(CompareNode.createCompareNode(Condition.EQ, condition, ConstantNode.forBoolean(true, object.graph()), builder.getConstantReflection())); - builder.push(returnKind.getStackKind(), builder.append(new UnsafeLoadNode(object, offset, returnKind, locationIdentity, compare))); + LogicNode compare = b.append(CompareNode.createCompareNode(Condition.EQ, condition, ConstantNode.forBoolean(true, object.graph()), b.getConstantReflection())); + b.push(returnKind.getStackKind(), b.append(new UnsafeLoadNode(object, offset, returnKind, locationIdentity, compare))); return true; } // TODO: should we throw GraalInternalError.shouldNotReachHere() here? @@ -351,7 +358,7 @@ this.kind = kind; } - public boolean apply(GraphBuilderContext builder, ValueNode object, ValueNode offset, ValueNode value, ValueNode location) { + public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, ValueNode object, ValueNode offset, ValueNode value, ValueNode location) { ValueNode locationArgument = location; if (locationArgument.isConstant()) { LocationIdentity locationIdentity; @@ -361,7 +368,7 @@ locationIdentity = ObjectLocationIdentity.create(locationArgument.asJavaConstant()); } - builder.append(new UnsafeStoreNode(object, offset, value, kind, locationIdentity, null)); + b.append(new UnsafeStoreNode(object, offset, value, kind, locationIdentity, null)); return true; } // TODO: should we throw GraalInternalError.shouldNotReachHere() here? diff -r 31fac91ea3b7 -r 14e703edb2ab graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/substitutions/UnsafeAccessSubstitutions.java --- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/substitutions/UnsafeAccessSubstitutions.java Wed Mar 11 17:16:30 2015 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,82 +0,0 @@ -/* - * 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 - * 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.truffle.substitutions; - -import com.oracle.graal.api.replacements.*; -import com.oracle.graal.nodes.spi.*; -import com.oracle.graal.truffle.nodes.typesystem.*; -import com.oracle.graal.truffle.unsafe.*; - -@ClassSubstitution(UnsafeAccessImpl.class) -public class UnsafeAccessSubstitutions { - @MacroSubstitution(macro = UnsafeTypeCastMacroNode.class, isStatic = true) - public static native Object unsafeCast(Object value, Class clazz, boolean condition, boolean nonNull); - - @MacroSubstitution(macro = CustomizedUnsafeLoadMacroNode.class, isStatic = true) - public static native boolean unsafeGetBoolean(Object receiver, long offset, boolean condition, Object locationIdentity); - - @MacroSubstitution(macro = CustomizedUnsafeLoadMacroNode.class, isStatic = true) - public static native byte unsafeGetByte(Object receiver, long offset, boolean condition, Object locationIdentity); - - @MacroSubstitution(macro = CustomizedUnsafeLoadMacroNode.class, isStatic = true) - public static native short unsafeGetShort(Object receiver, long offset, boolean condition, Object locationIdentity); - - @MacroSubstitution(macro = CustomizedUnsafeLoadMacroNode.class, isStatic = true) - public static native int unsafeGetInt(Object receiver, long offset, boolean condition, Object locationIdentity); - - @MacroSubstitution(macro = CustomizedUnsafeLoadMacroNode.class, isStatic = true) - public static native long unsafeGetLong(Object receiver, long offset, boolean condition, Object locationIdentity); - - @MacroSubstitution(macro = CustomizedUnsafeLoadMacroNode.class, isStatic = true) - public static native float unsafeGetFloat(Object receiver, long offset, boolean condition, Object locationIdentity); - - @MacroSubstitution(macro = CustomizedUnsafeLoadMacroNode.class, isStatic = true) - public static native double unsafeGetDouble(Object receiver, long offset, boolean condition, Object locationIdentity); - - @MacroSubstitution(macro = CustomizedUnsafeLoadMacroNode.class, isStatic = true) - public static native Object unsafeGetObject(Object receiver, long offset, boolean condition, Object locationIdentity); - - @MacroSubstitution(macro = CustomizedUnsafeStoreMacroNode.class, isStatic = true) - public static native void unsafePutBoolean(Object receiver, long offset, boolean value, Object locationIdentity); - - @MacroSubstitution(macro = CustomizedUnsafeStoreMacroNode.class, isStatic = true) - public static native void unsafePutByte(Object receiver, long offset, byte value, Object locationIdentity); - - @MacroSubstitution(macro = CustomizedUnsafeStoreMacroNode.class, isStatic = true) - public static native void unsafePutShort(Object receiver, long offset, short value, Object locationIdentity); - - @MacroSubstitution(macro = CustomizedUnsafeStoreMacroNode.class, isStatic = true) - public static native void unsafePutInt(Object receiver, long offset, int value, Object locationIdentity); - - @MacroSubstitution(macro = CustomizedUnsafeStoreMacroNode.class, isStatic = true) - public static native void unsafePutLong(Object receiver, long offset, long value, Object locationIdentity); - - @MacroSubstitution(macro = CustomizedUnsafeStoreMacroNode.class, isStatic = true) - public static native void unsafePutFloat(Object receiver, long offset, float value, Object locationIdentity); - - @MacroSubstitution(macro = CustomizedUnsafeStoreMacroNode.class, isStatic = true) - public static native void unsafePutDouble(Object receiver, long offset, double value, Object locationIdentity); - - @MacroSubstitution(macro = CustomizedUnsafeStoreMacroNode.class, isStatic = true) - public static native void unsafePutObject(Object receiver, long offset, Object value, Object locationIdentity); -} diff -r 31fac91ea3b7 -r 14e703edb2ab graal/com.oracle.graal.word/src/com/oracle/graal/word/Word.java --- a/graal/com.oracle.graal.word/src/com/oracle/graal/word/Word.java Wed Mar 11 17:16:30 2015 +0100 +++ b/graal/com.oracle.graal.word/src/com/oracle/graal/word/Word.java Wed Mar 11 20:43:12 2015 +0100 @@ -72,6 +72,7 @@ FROM_UNSIGNED, FROM_SIGNED, FROM_OBJECT, + FROM_WORDBASE, FROM_ARRAY, TO_OBJECT, TO_RAW_VALUE, @@ -170,6 +171,9 @@ return unbox(); } + @Operation(opcode = Opcode.FROM_WORDBASE) + public static native Word fromWordBase(WordBase val); + @Operation(opcode = Opcode.FROM_OBJECT) public static native Pointer fromObject(Object val); diff -r 31fac91ea3b7 -r 14e703edb2ab graal/com.oracle.graal.word/src/com/oracle/graal/word/phases/WordTypeRewriterPhase.java --- a/graal/com.oracle.graal.word/src/com/oracle/graal/word/phases/WordTypeRewriterPhase.java Wed Mar 11 17:16:30 2015 +0100 +++ b/graal/com.oracle.graal.word/src/com/oracle/graal/word/phases/WordTypeRewriterPhase.java Wed Mar 11 20:43:12 2015 +0100 @@ -55,21 +55,13 @@ protected final MetaAccessProvider metaAccess; protected final SnippetReflectionProvider snippetReflection; protected final ConstantReflectionProvider constantReflection; - protected final ResolvedJavaType wordBaseType; - protected final ResolvedJavaType wordImplType; - protected final ResolvedJavaType objectAccessType; - protected final ResolvedJavaType barrieredAccessType; - protected final Kind wordKind; + protected final WordTypes wordTypes; - public WordTypeRewriterPhase(MetaAccessProvider metaAccess, SnippetReflectionProvider snippetReflection, ConstantReflectionProvider constantReflection, Kind wordKind) { + public WordTypeRewriterPhase(MetaAccessProvider metaAccess, SnippetReflectionProvider snippetReflection, ConstantReflectionProvider constantReflection, WordTypes wordTypes) { this.metaAccess = metaAccess; + this.wordTypes = wordTypes; this.snippetReflection = snippetReflection; this.constantReflection = constantReflection; - this.wordKind = wordKind; - this.wordBaseType = metaAccess.lookupJavaType(WordBase.class); - this.wordImplType = metaAccess.lookupJavaType(Word.class); - this.objectAccessType = metaAccess.lookupJavaType(ObjectAccess.class); - this.barrieredAccessType = metaAccess.lookupJavaType(BarrieredAccess.class); } @Override @@ -91,17 +83,17 @@ * Change the stamp for word nodes from the object stamp ({@link WordBase} or anything extending * or implementing that interface) to the primitive word stamp. */ - protected void changeToWord(StructuredGraph graph, ValueNode node) { - if (isWord(node)) { + private void changeToWord(StructuredGraph graph, ValueNode node) { + if (wordTypes.isWord(node)) { if (node.isConstant()) { ConstantNode oldConstant = (ConstantNode) node; assert oldConstant.asJavaConstant().getKind() == Kind.Object; WordBase value = snippetReflection.asObject(WordBase.class, oldConstant.asJavaConstant()); - ConstantNode newConstant = ConstantNode.forIntegerKind(wordKind, value.rawValue(), node.graph()); + ConstantNode newConstant = ConstantNode.forIntegerKind(wordTypes.getWordKind(), value.rawValue(), node.graph()); graph.replaceFloating(oldConstant, newConstant); } else { - node.setStamp(StampFactory.forKind(wordKind)); + node.setStamp(wordTypes.getWordStamp(StampTool.typeOrNull(node))); } } } @@ -128,7 +120,7 @@ * Remove casts between word types (which by now no longer have kind Object). */ protected void rewriteCheckCast(StructuredGraph graph, CheckCastNode node) { - if (node.getKind() == wordKind) { + if (node.getKind() == wordTypes.getWordKind()) { node.replaceAtUsages(node.object()); graph.removeFixed(node); } @@ -138,7 +130,7 @@ * Remove casts between word types (which by now no longer have kind Object). */ protected void rewritePi(StructuredGraph graph, PiNode node) { - if (node.getKind() == wordKind) { + if (node.getKind() == wordTypes.getWordKind()) { node.replaceAtUsages(node.object()); graph.removeFloating(node); } @@ -165,15 +157,15 @@ * There are cases where the array does not have a known type yet, i.e., the type is null. * In that case we assume it is not a word type. */ - if (arrayType != null && isWord(arrayType.getComponentType()) && node.elementKind() != wordKind) { + if (arrayType != null && wordTypes.isWord(arrayType.getComponentType()) && node.elementKind() != wordTypes.getWordKind()) { /* * The elementKind of the node is a final field, and other information such as the stamp * depends on elementKind. Therefore, just create a new node and replace the old one. */ if (node instanceof LoadIndexedNode) { - graph.replaceFixedWithFixed(node, graph.add(new LoadIndexedNode(node.array(), node.index(), wordKind))); + graph.replaceFixedWithFixed(node, graph.add(new LoadIndexedNode(node.array(), node.index(), wordTypes.getWordKind()))); } else if (node instanceof StoreIndexedNode) { - graph.replaceFixedWithFixed(node, graph.add(new StoreIndexedNode(node.array(), node.index(), wordKind, ((StoreIndexedNode) node).value()))); + graph.replaceFixedWithFixed(node, graph.add(new StoreIndexedNode(node.array(), node.index(), wordTypes.getWordKind(), ((StoreIndexedNode) node).value()))); } else { throw GraalInternalError.shouldNotReachHere(); } @@ -181,28 +173,14 @@ } /** - * Intrinsification of methods defined on the {@link Word} class that are annotated with - * {@link Operation}. + * Intrinsification of methods that are annotated with {@link Operation}. */ protected void rewriteInvoke(StructuredGraph graph, MethodCallTargetNode callTargetNode) { ResolvedJavaMethod targetMethod = callTargetNode.targetMethod(); - final boolean isWordBase = wordBaseType.isAssignableFrom(targetMethod.getDeclaringClass()); - final boolean isObjectAccess = objectAccessType.equals(targetMethod.getDeclaringClass()); - final boolean isBarrieredAccess = barrieredAccessType.equals(targetMethod.getDeclaringClass()); - if (!isWordBase && !isObjectAccess && !isBarrieredAccess) { - /* - * Not a method defined on WordBase or a subclass / subinterface, and not on - * ObjectAccess and not on BarrieredAccess, so nothing to rewrite. - */ - return; + if (wordTypes.isWordOperation(targetMethod)) { + ResolvedJavaMethod wordMethod = wordTypes.getWordOperation(targetMethod, callTargetNode.invoke().getContextType()); + rewriteWordOperation(graph, callTargetNode, wordMethod); } - - if (!callTargetNode.isStatic()) { - assert callTargetNode.receiver().getKind() == wordKind : "changeToWord() missed the receiver " + callTargetNode.receiver(); - assert wordImplType.isLinked(); - targetMethod = wordImplType.resolveConcreteMethod(targetMethod, callTargetNode.invoke().getContextType()); - } - rewriteWordOperation(graph, callTargetNode, targetMethod); } protected void rewriteWordOperation(StructuredGraph graph, MethodCallTargetNode callTargetNode, ResolvedJavaMethod targetMethod) throws GraalInternalError { @@ -232,14 +210,14 @@ case NOT: assert arguments.size() == 1; - replace(invoke, graph.unique(new XorNode(arguments.get(0), ConstantNode.forIntegerKind(wordKind, -1, graph)))); + replace(invoke, graph.unique(new XorNode(arguments.get(0), ConstantNode.forIntegerKind(wordTypes.getWordKind(), -1, graph)))); break; case READ_POINTER: case READ_OBJECT: case READ_BARRIERED: { assert arguments.size() == 2 || arguments.size() == 3; - Kind readKind = asKind(callTargetNode.returnType()); + Kind readKind = wordTypes.asKind(callTargetNode.returnType()); LocationNode location; if (arguments.size() == 2) { location = makeLocation(graph, arguments.get(1), ANY_LOCATION); @@ -251,7 +229,7 @@ } case READ_HEAP: { assert arguments.size() == 3; - Kind readKind = asKind(callTargetNode.returnType()); + Kind readKind = wordTypes.asKind(callTargetNode.returnType()); LocationNode location = makeLocation(graph, arguments.get(1), ANY_LOCATION); BarrierType barrierType = snippetReflection.asObject(BarrierType.class, arguments.get(2).asJavaConstant()); replace(invoke, readOp(graph, readKind, arguments.get(0), invoke, location, barrierType, true)); @@ -262,7 +240,7 @@ case WRITE_BARRIERED: case INITIALIZE: { assert arguments.size() == 3 || arguments.size() == 4; - Kind writeKind = asKind(targetMethod.getSignature().getParameterType(targetMethod.isStatic() ? 2 : 1, targetMethod.getDeclaringClass())); + Kind writeKind = wordTypes.asKind(targetMethod.getSignature().getParameterType(targetMethod.isStatic() ? 2 : 1, targetMethod.getDeclaringClass())); LocationNode location; if (arguments.size() == 3) { location = makeLocation(graph, arguments.get(1), LocationIdentity.ANY_LOCATION); @@ -274,7 +252,7 @@ } case ZERO: assert arguments.size() == 0; - replace(invoke, ConstantNode.forIntegerKind(wordKind, 0L, graph)); + replace(invoke, ConstantNode.forIntegerKind(wordTypes.getWordKind(), 0L, graph)); break; case FROM_UNSIGNED: @@ -294,19 +272,19 @@ case FROM_OBJECT: assert arguments.size() == 1; - WordCastNode objectToWord = graph.add(WordCastNode.objectToWord(arguments.get(0), wordKind)); + WordCastNode objectToWord = graph.add(WordCastNode.objectToWord(arguments.get(0), wordTypes.getWordKind())); graph.addBeforeFixed(invoke.asNode(), objectToWord); replace(invoke, objectToWord); break; case FROM_ARRAY: assert arguments.size() == 2; - replace(invoke, graph.unique(new ComputeAddressNode(arguments.get(0), arguments.get(1), StampFactory.forKind(wordKind)))); + replace(invoke, graph.unique(new ComputeAddressNode(arguments.get(0), arguments.get(1), StampFactory.forKind(wordTypes.getWordKind())))); break; case TO_OBJECT: assert arguments.size() == 1; - WordCastNode wordToObject = graph.add(WordCastNode.wordToObject(arguments.get(0), wordKind)); + WordCastNode wordToObject = graph.add(WordCastNode.wordToObject(arguments.get(0), wordTypes.getWordKind())); graph.addBeforeFixed(invoke.asNode(), wordToObject); replace(invoke, wordToObject); break; @@ -317,11 +295,11 @@ } protected ValueNode fromUnsigned(StructuredGraph graph, ValueNode value) { - return convert(graph, value, wordKind, true); + return convert(graph, value, wordTypes.getWordKind(), true); } private ValueNode fromSigned(StructuredGraph graph, ValueNode value) { - return convert(graph, value, wordKind, false); + return convert(graph, value, wordTypes.getWordKind(), false); } protected ValueNode toUnsigned(StructuredGraph graph, ValueNode value, Kind toKind) { @@ -362,7 +340,7 @@ } private ValueNode comparisonOp(StructuredGraph graph, Condition condition, ValueNode left, ValueNode right) { - assert left.getKind() == wordKind && right.getKind() == wordKind; + assert left.getKind() == wordTypes.getWordKind() && right.getKind() == wordTypes.getWordKind(); // mirroring gets the condition into canonical form boolean mirror = condition.canonicalMirror(); @@ -439,20 +417,4 @@ invoke.asNode().replaceAtUsages(value); GraphUtil.killCFG(invoke.asNode()); } - - protected boolean isWord(ValueNode node) { - return isWord(StampTool.typeOrNull(node)); - } - - protected boolean isWord(ResolvedJavaType type) { - return type != null && wordBaseType.isAssignableFrom(type); - } - - protected Kind asKind(JavaType type) { - if (type instanceof ResolvedJavaType && isWord((ResolvedJavaType) type)) { - return wordKind; - } else { - return type.getKind(); - } - } } diff -r 31fac91ea3b7 -r 14e703edb2ab graal/com.oracle.graal.word/src/com/oracle/graal/word/phases/WordTypeVerificationPhase.java --- a/graal/com.oracle.graal.word/src/com/oracle/graal/word/phases/WordTypeVerificationPhase.java Wed Mar 11 17:16:30 2015 +0100 +++ b/graal/com.oracle.graal.word/src/com/oracle/graal/word/phases/WordTypeVerificationPhase.java Wed Mar 11 20:43:12 2015 +0100 @@ -23,7 +23,6 @@ package com.oracle.graal.word.phases; import com.oracle.graal.api.meta.*; -import com.oracle.graal.api.replacements.*; import com.oracle.graal.compiler.common.*; import com.oracle.graal.graph.*; import com.oracle.graal.graph.Node.NodeIntrinsic; @@ -42,10 +41,10 @@ */ public class WordTypeVerificationPhase extends Phase { - private final WordTypeRewriterPhase wordAccess; + private final WordTypes wordAccess; - public WordTypeVerificationPhase(MetaAccessProvider metaAccess, SnippetReflectionProvider snippetReflection, ConstantReflectionProvider constantReflection, Kind wordKind) { - this.wordAccess = new WordTypeRewriterPhase(metaAccess, snippetReflection, constantReflection, wordKind); + public WordTypeVerificationPhase(MetaAccessProvider metaAccess, Kind wordKind) { + this.wordAccess = new WordTypes(metaAccess, wordKind); } @Override @@ -108,7 +107,7 @@ if (!isStatic) { ValueNode receiver = arguments.get(argc); if (receiver == node && isWord(node)) { - ResolvedJavaMethod resolvedMethod = wordAccess.wordImplType.resolveConcreteMethod(method, invoke.getContextType()); + ResolvedJavaMethod resolvedMethod = wordAccess.getWordImplType().resolveConcreteMethod(method, invoke.getContextType()); verify(resolvedMethod != null, node, invoke.asNode(), "cannot resolve method on Word class: " + method.format("%H.%n(%P) %r")); Operation operation = resolvedMethod.getAnnotation(Word.Operation.class); verify(operation != null, node, invoke.asNode(), "cannot dispatch on word value to non @Operation annotated method " + resolvedMethod); diff -r 31fac91ea3b7 -r 14e703edb2ab graal/com.oracle.graal.word/src/com/oracle/graal/word/phases/WordTypes.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.word/src/com/oracle/graal/word/phases/WordTypes.java Wed Mar 11 20:43:12 2015 +0100 @@ -0,0 +1,140 @@ +/* + * Copyright (c) 2012, 2014, 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.word.phases; + +import com.oracle.graal.api.meta.*; +import com.oracle.graal.compiler.common.type.*; +import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.type.*; +import com.oracle.graal.word.*; +import com.oracle.graal.word.Word.Operation; + +/** + * Encapsulates information for Java types representing raw words (as opposed to Objects). + */ +public class WordTypes { + + /** + * Resolved type for {@link WordBase}. + */ + private final ResolvedJavaType wordBaseType; + + /** + * Resolved type for {@link Word}. + */ + private final ResolvedJavaType wordImplType; + + /** + * Resolved type for {@link ObjectAccess}. + */ + private final ResolvedJavaType objectAccessType; + + /** + * Resolved type for {@link BarrieredAccess}. + */ + private final ResolvedJavaType barrieredAccessType; + + private final Kind wordKind; + + public WordTypes(MetaAccessProvider metaAccess, Kind wordKind) { + this.wordKind = wordKind; + this.wordBaseType = metaAccess.lookupJavaType(WordBase.class); + this.wordImplType = metaAccess.lookupJavaType(Word.class); + this.objectAccessType = metaAccess.lookupJavaType(ObjectAccess.class); + this.barrieredAccessType = metaAccess.lookupJavaType(BarrieredAccess.class); + } + + /** + * Determines if a given method denotes a word operation. + */ + public boolean isWordOperation(ResolvedJavaMethod targetMethod) { + final boolean isObjectAccess = objectAccessType.equals(targetMethod.getDeclaringClass()); + final boolean isBarrieredAccess = barrieredAccessType.equals(targetMethod.getDeclaringClass()); + if (isObjectAccess || isBarrieredAccess) { + assert targetMethod.getAnnotation(Operation.class) != null : targetMethod + " should be annotated with @" + Operation.class.getSimpleName(); + return true; + } + return isWord(targetMethod.getDeclaringClass()); + } + + /** + * Gets the method annotated with {@link Operation} based on a given method that represents a + * word operation (but may not necessarily have the annotation). + * + * @param callingContextType the {@linkplain ResolvedJavaType type} from which + * {@code targetMethod} is invoked + * @return the {@link Operation} method resolved for {@code targetMethod} if any + */ + public ResolvedJavaMethod getWordOperation(ResolvedJavaMethod targetMethod, ResolvedJavaType callingContextType) { + final boolean isWordBase = wordBaseType.isAssignableFrom(targetMethod.getDeclaringClass()); + ResolvedJavaMethod wordMethod = targetMethod; + if (isWordBase && !targetMethod.isStatic()) { + assert wordImplType.isLinked(); + wordMethod = wordImplType.resolveConcreteMethod(targetMethod, callingContextType); + } + assert wordMethod.getAnnotation(Operation.class) != null : wordMethod; + return wordMethod; + } + + /** + * Determines if a given node has a word type. + */ + public boolean isWord(ValueNode node) { + return isWord(StampTool.typeOrNull(node)); + } + + /** + * Determines if a given type is a word type. + */ + public boolean isWord(ResolvedJavaType type) { + return type != null && wordBaseType.isAssignableFrom(type); + } + + /** + * Gets the kind for a given type, returning the {@linkplain #getWordKind() word kind} if + * {@code type} is a {@linkplain #isWord(ResolvedJavaType) word type}. + */ + public Kind asKind(JavaType type) { + if (type instanceof ResolvedJavaType && isWord((ResolvedJavaType) type)) { + return wordKind; + } else { + return type.getKind(); + } + } + + public Kind getWordKind() { + return wordKind; + } + + /** + * Gets the stamp for a given {@linkplain #isWord(ResolvedJavaType) word type}. + */ + public Stamp getWordStamp(ResolvedJavaType type) { + assert isWord(type); + return StampFactory.forKind(wordKind); + } + + public ResolvedJavaType getWordImplType() { + return wordImplType; + } +}