# HG changeset patch # User Doug Simon # Date 1339590264 -7200 # Node ID a7ed598130c2557ca06492ad7bf462d3c61ede3e # Parent 90c4b9c01ded2ab076a51834cff4e2f7faf20266 modified snippet installation to avoid using compiler storage for every method (not just the snippets) processed during installation diff -r 90c4b9c01ded -r a7ed598130c2 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/VMToCompilerImpl.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/VMToCompilerImpl.java Wed Jun 13 13:26:56 2012 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/VMToCompilerImpl.java Wed Jun 13 14:24:24 2012 +0200 @@ -112,8 +112,9 @@ @Override public void run() { VMToCompilerImpl.this.intrinsifyArrayCopy = new IntrinsifyArrayCopyPhase(runtime); - GraalIntrinsics.installIntrinsics(runtime, runtime.getCompiler().getTarget()); - runtime.installSnippets(); + SnippetInstaller installer = new SnippetInstaller(runtime, runtime.getCompiler().getTarget()); + GraalIntrinsics.installIntrinsics(installer); + runtime.installSnippets(installer); } }); diff -r 90c4b9c01ded -r a7ed598130c2 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotRuntime.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotRuntime.java Wed Jun 13 13:26:56 2012 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotRuntime.java Wed Jun 13 14:24:24 2012 +0200 @@ -68,12 +68,12 @@ System.setProperty(Backend.BACKEND_CLASS_PROPERTY, HotSpotAMD64Backend.class.getName()); } - public void installSnippets() { - Snippets.install(this, compiler.getTarget(), SystemSnippets.class); - Snippets.install(this, compiler.getTarget(), UnsafeSnippets.class); - Snippets.install(this, compiler.getTarget(), ArrayCopySnippets.class); - Snippets.install(this, compiler.getTarget(), CheckCastSnippets.class); - Snippets.install(this, compiler.getTarget(), NewInstanceSnippets.class); + public void installSnippets(SnippetInstaller installer) { + installer.install(SystemSnippets.class); + installer.install(UnsafeSnippets.class); + installer.install(ArrayCopySnippets.class); + installer.install(CheckCastSnippets.class); + installer.install(NewInstanceSnippets.class); checkcastSnippets = new CheckCastSnippets.Templates(this); newInstanceSnippets = new NewInstanceSnippets.Templates(this); } diff -r 90c4b9c01ded -r a7ed598130c2 graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/GraalIntrinsics.java --- a/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/GraalIntrinsics.java Wed Jun 13 13:26:56 2012 +0200 +++ b/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/GraalIntrinsics.java Wed Jun 13 14:24:24 2012 +0200 @@ -22,20 +22,18 @@ */ package com.oracle.graal.snippets; -import com.oracle.graal.api.code.*; import com.oracle.graal.compiler.*; -import com.oracle.graal.cri.*; /** * Definition of the snippets that are VM-independent and can be intrinsified by Graal in any VM. */ public class GraalIntrinsics { - public static void installIntrinsics(ExtendedRiRuntime runtime, TargetDescription target) { + public static void installIntrinsics(SnippetInstaller installer) { if (GraalOptions.Intrinsify) { - Snippets.install(runtime, target, MathSnippetsX86.class); - Snippets.install(runtime, target, DoubleSnippets.class); - Snippets.install(runtime, target, FloatSnippets.class); - Snippets.install(runtime, target, NodeClassSnippets.class); + installer.install(MathSnippetsX86.class); + installer.install(DoubleSnippets.class); + installer.install(FloatSnippets.class); + installer.install(NodeClassSnippets.class); } } } diff -r 90c4b9c01ded -r a7ed598130c2 graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/SnippetInstaller.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/SnippetInstaller.java Wed Jun 13 14:24:24 2012 +0200 @@ -0,0 +1,195 @@ +/* + * 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.snippets; + +import java.lang.reflect.*; +import java.util.*; +import java.util.concurrent.*; + +import com.oracle.graal.api.code.*; +import com.oracle.graal.api.meta.*; +import com.oracle.graal.compiler.*; +import com.oracle.graal.compiler.phases.*; +import com.oracle.graal.compiler.util.*; +import com.oracle.graal.cri.*; +import com.oracle.graal.debug.*; +import com.oracle.graal.graph.*; +import com.oracle.graal.java.*; +import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.extended.*; +import com.oracle.graal.nodes.java.*; +import com.oracle.graal.snippets.Snippet.InliningPolicy; + +/** + * Utility for snippet {@linkplain #install(Class) installation}. + */ +public class SnippetInstaller { + + private final ExtendedRiRuntime runtime; + private final TargetDescription target; + private final BoxingMethodPool pool; + + /** + * A graph cache used by this installer to avoid using the compiler + * storage for each method processed during snippet installation. + * Without this, all processed methods are to be determined as + * {@linkplain IntrinsificationPhase#canIntrinsify intrinsifiable}. + */ + private final Map graphCache; + + public SnippetInstaller(ExtendedRiRuntime runtime, TargetDescription target) { + this.runtime = runtime; + this.target = target; + this.pool = new BoxingMethodPool(runtime); + this.graphCache = new HashMap<>(); + } + + /** + * Finds all the snippet methods in a given class, builds a graph for them and + * installs the graph with the key value of {@code Graph.class} in the + * {@linkplain ResolvedJavaMethod#compilerStorage() compiler storage} of each method. + *

+ * If {@code snippetsHolder} is annotated with {@link ClassSubstitution}, then all + * methods in the class are snippets. Otherwise, the snippets are those methods + * annotated with {@link Snippet}. + */ + public void install(Class snippetsHolder) { + if (snippetsHolder.isAnnotationPresent(ClassSubstitution.class)) { + installSubstitutions(snippetsHolder, snippetsHolder.getAnnotation(ClassSubstitution.class).value()); + } else { + installSnippets(snippetsHolder); + } + } + + private void installSnippets(Class< ? extends SnippetsInterface> clazz) { + for (Method method : clazz.getDeclaredMethods()) { + if (method.getAnnotation(Snippet.class) != null) { + int modifiers = method.getModifiers(); + if (Modifier.isAbstract(modifiers) || Modifier.isNative(modifiers)) { + throw new RuntimeException("Snippet must not be abstract or native"); + } + ResolvedJavaMethod snippet = runtime.getResolvedJavaMethod(method); + assert snippet.compilerStorage().get(Graph.class) == null; + StructuredGraph graph = makeGraph(snippet, inliningPolicy(snippet)); + //System.out.println("snippet: " + graph); + snippet.compilerStorage().put(Graph.class, graph); + } + } + } + + private void installSubstitutions(Class< ? extends SnippetsInterface> clazz, Class originalClazz) { + for (Method method : clazz.getDeclaredMethods()) { + try { + Method originalMethod = originalClazz.getDeclaredMethod(method.getName(), method.getParameterTypes()); + if (!originalMethod.getReturnType().isAssignableFrom(method.getReturnType())) { + throw new RuntimeException("Snippet has incompatible return type"); + } + int modifiers = method.getModifiers(); + if (Modifier.isAbstract(modifiers) || Modifier.isNative(modifiers)) { + throw new RuntimeException("Snippet must not be abstract or native"); + } + ResolvedJavaMethod snippet = runtime.getResolvedJavaMethod(method); + StructuredGraph graph = makeGraph(snippet, inliningPolicy(snippet)); + //System.out.println("snippet: " + graph); + runtime.getResolvedJavaMethod(originalMethod).compilerStorage().put(Graph.class, graph); + } catch (NoSuchMethodException e) { + throw new GraalInternalError("Could not resolve method in " + originalClazz + " to substitute with " + method, e); + } + } + } + + private static InliningPolicy inliningPolicy(ResolvedJavaMethod method) { + Class policyClass = InliningPolicy.class; + Snippet snippet = method.getAnnotation(Snippet.class); + if (snippet != null) { + policyClass = snippet.inlining(); + } + if (policyClass == InliningPolicy.class) { + return InliningPolicy.Default; + } + try { + return policyClass.getConstructor().newInstance(); + } catch (Exception e) { + throw new GraalInternalError(e); + } + } + + private StructuredGraph makeGraph(final ResolvedJavaMethod method, final InliningPolicy policy) { + StructuredGraph graph = graphCache.get(method); + if (graph == null) { + graph = buildGraph(method, policy); + //System.out.println("built " + graph); + graphCache.put(method, graph); + } + return graph; + } + + private StructuredGraph buildGraph(final ResolvedJavaMethod method, final InliningPolicy policy) { + final StructuredGraph graph = new StructuredGraph(method); + return Debug.scope("BuildSnippetGraph", new Object[] {method, graph}, new Callable() { + @Override + public StructuredGraph call() throws Exception { + GraphBuilderConfiguration config = GraphBuilderConfiguration.getSnippetDefault(); + GraphBuilderPhase graphBuilder = new GraphBuilderPhase(runtime, config, OptimisticOptimizations.NONE); + graphBuilder.apply(graph); + + Debug.dump(graph, "%s: %s", method.name(), GraphBuilderPhase.class.getSimpleName()); + + new SnippetIntrinsificationPhase(runtime, pool).apply(graph); + + for (Invoke invoke : graph.getInvokes()) { + MethodCallTargetNode callTarget = invoke.callTarget(); + ResolvedJavaMethod callee = callTarget.targetMethod(); + if (policy.shouldInline(callee, method)) { + StructuredGraph targetGraph = makeGraph(callee, policy); + InliningUtil.inline(invoke, targetGraph, true); + Debug.dump(graph, "after inlining %s", callee); + if (GraalOptions.OptCanonicalizer) { + new WordTypeRewriterPhase(target).apply(graph); + new CanonicalizerPhase(target, runtime, null).apply(graph); + } + } + } + + new SnippetIntrinsificationPhase(runtime, pool).apply(graph); + + new WordTypeRewriterPhase(target).apply(graph); + + new DeadCodeEliminationPhase().apply(graph); + if (GraalOptions.OptCanonicalizer) { + new CanonicalizerPhase(target, runtime, null).apply(graph); + } + + for (LoopEndNode end : graph.getNodes(LoopEndNode.class)) { + end.disableSafepoint(); + } + + new InsertStateAfterPlaceholderPhase().apply(graph); + + Debug.dump(graph, "%s: Final", method.name()); + + return graph; + } + }); + } +} diff -r 90c4b9c01ded -r a7ed598130c2 graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/Snippets.java --- a/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/Snippets.java Wed Jun 13 13:26:56 2012 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,163 +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.snippets; - -import java.lang.reflect.*; -import java.util.concurrent.*; - -import com.oracle.graal.api.code.*; -import com.oracle.graal.api.meta.*; -import com.oracle.graal.compiler.*; -import com.oracle.graal.compiler.phases.*; -import com.oracle.graal.compiler.util.*; -import com.oracle.graal.cri.*; -import com.oracle.graal.debug.*; -import com.oracle.graal.graph.*; -import com.oracle.graal.java.*; -import com.oracle.graal.nodes.*; -import com.oracle.graal.nodes.extended.*; -import com.oracle.graal.nodes.java.*; -import com.oracle.graal.snippets.Snippet.InliningPolicy; - -/** - * Utilities for snippet installation and management. - */ -public class Snippets { - - public static void install(ExtendedRiRuntime runtime, TargetDescription target, Class snippetsHolder) { - BoxingMethodPool pool = new BoxingMethodPool(runtime); - if (snippetsHolder.isAnnotationPresent(ClassSubstitution.class)) { - installSubstitution(runtime, target, snippetsHolder, pool, snippetsHolder.getAnnotation(ClassSubstitution.class).value()); - } else { - installSnippets(runtime, target, snippetsHolder, pool); - } - } - - private static void installSnippets(ExtendedRiRuntime runtime, TargetDescription target, Class< ? extends SnippetsInterface> clazz, BoxingMethodPool pool) { - for (Method method : clazz.getDeclaredMethods()) { - if (method.getAnnotation(Snippet.class) != null) { - Method snippet = method; - int modifiers = snippet.getModifiers(); - if (Modifier.isAbstract(modifiers) || Modifier.isNative(modifiers)) { - throw new RuntimeException("Snippet must not be abstract or native"); - } - ResolvedJavaMethod snippetRiMethod = runtime.getResolvedJavaMethod(snippet); - if (snippetRiMethod.compilerStorage().get(Graph.class) == null) { - buildSnippetGraph(snippetRiMethod, runtime, target, pool, inliningPolicy(snippetRiMethod)); - } - } - } - } - - private static InliningPolicy inliningPolicy(ResolvedJavaMethod method) { - Class policyClass = InliningPolicy.class; - Snippet snippet = method.getAnnotation(Snippet.class); - if (snippet != null) { - policyClass = snippet.inlining(); - } - if (policyClass == InliningPolicy.class) { - return InliningPolicy.Default; - } - try { - return policyClass.getConstructor().newInstance(); - } catch (Exception e) { - throw new GraalInternalError(e); - } - } - - private static void installSubstitution(ExtendedRiRuntime runtime, TargetDescription target, Class< ? extends SnippetsInterface> clazz, - BoxingMethodPool pool, Class original) throws GraalInternalError { - for (Method snippet : clazz.getDeclaredMethods()) { - try { - Method method = original.getDeclaredMethod(snippet.getName(), snippet.getParameterTypes()); - if (!method.getReturnType().isAssignableFrom(snippet.getReturnType())) { - throw new RuntimeException("Snippet has incompatible return type"); - } - int modifiers = snippet.getModifiers(); - if (Modifier.isAbstract(modifiers) || Modifier.isNative(modifiers)) { - throw new RuntimeException("Snippet must not be abstract or native"); - } - ResolvedJavaMethod snippetRiMethod = runtime.getResolvedJavaMethod(snippet); - StructuredGraph graph = buildSnippetGraph(snippetRiMethod, runtime, target, pool, inliningPolicy(snippetRiMethod)); - runtime.getResolvedJavaMethod(method).compilerStorage().put(Graph.class, graph); - } catch (NoSuchMethodException e) { - throw new RuntimeException("Could not resolve method to substitute with: " + snippet.getName(), e); - } - } - } - - private static StructuredGraph buildSnippetGraph(final ResolvedJavaMethod snippetRiMethod, final ExtendedRiRuntime runtime, final TargetDescription target, final BoxingMethodPool pool, final InliningPolicy policy) { - final StructuredGraph graph = new StructuredGraph(snippetRiMethod); - return Debug.scope("BuildSnippetGraph", new Object[] {snippetRiMethod, graph}, new Callable() { - @Override - public StructuredGraph call() throws Exception { - GraphBuilderConfiguration config = GraphBuilderConfiguration.getSnippetDefault(); - GraphBuilderPhase graphBuilder = new GraphBuilderPhase(runtime, config, OptimisticOptimizations.NONE); - graphBuilder.apply(graph); - - Debug.dump(graph, "%s: %s", snippetRiMethod.name(), GraphBuilderPhase.class.getSimpleName()); - - new SnippetIntrinsificationPhase(runtime, pool).apply(graph); - - for (Invoke invoke : graph.getInvokes()) { - MethodCallTargetNode callTarget = invoke.callTarget(); - ResolvedJavaMethod method = callTarget.targetMethod(); - if (policy.shouldInline(method, snippetRiMethod)) { - StructuredGraph targetGraph = (StructuredGraph) method.compilerStorage().get(Graph.class); - if (targetGraph == null) { - targetGraph = buildSnippetGraph(method, runtime, target, pool, policy); - } - InliningUtil.inline(invoke, targetGraph, true); - Debug.dump(graph, "after inlining %s", method); - if (GraalOptions.OptCanonicalizer) { - new WordTypeRewriterPhase(target).apply(graph); - new CanonicalizerPhase(target, runtime, null).apply(graph); - } - } - } - - new SnippetIntrinsificationPhase(runtime, pool).apply(graph); - - new WordTypeRewriterPhase(target).apply(graph); - - new DeadCodeEliminationPhase().apply(graph); - if (GraalOptions.OptCanonicalizer) { - new CanonicalizerPhase(target, runtime, null).apply(graph); - } - - for (LoopEndNode end : graph.getNodes(LoopEndNode.class)) { - end.disableSafepoint(); - } - - new InsertStateAfterPlaceholderPhase().apply(graph); - - Debug.dump(graph, "%s: Final", snippetRiMethod.name()); - - snippetRiMethod.compilerStorage().put(Graph.class, graph); - - return graph; - } - }); - - } -}