# HG changeset patch # User Thomas Wuerthinger # Date 1424097802 -3600 # Node ID 95258dae67ef2eeb22cbd069ae0adf15f0d16ffd # Parent 7e2c87dae93e91ce0d63b0928dae71b3d2e597e9# Parent 47fcd91a38c58073a6f15b91c2fb0507357542ae Merge. diff -r 7e2c87dae93e -r 95258dae67ef 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 Mon Feb 16 15:43:03 2015 +0100 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/GraalCompilerTest.java Mon Feb 16 15:43:22 2015 +0100 @@ -800,9 +800,8 @@ protected PhaseSuite getCustomGraphBuilderSuite(GraphBuilderConfiguration gbConf) { PhaseSuite suite = getDefaultGraphBuilderSuite().copy(); ListIterator> iterator = suite.findPhase(GraphBuilderPhase.class); - GraphBuilderPhase graphBuilderPhase = (GraphBuilderPhase) iterator.previous(); iterator.remove(); - iterator.add(new GraphBuilderPhase(gbConf, graphBuilderPhase.getGraphBuilderPlugins())); + iterator.add(new GraphBuilderPhase(gbConf)); return suite; } diff -r 7e2c87dae93e -r 95258dae67ef 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 Mon Feb 16 15:43:03 2015 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotHostBackend.java Mon Feb 16 15:43:22 2015 +0100 @@ -68,7 +68,7 @@ try (InitTimer st = timer("graphBuilderPlugins.initialize")) { GraphBuilderPhase phase = (GraphBuilderPhase) providers.getSuites().getDefaultGraphBuilderSuite().findPhase(GraphBuilderPhase.class).previous(); - GraphBuilderPlugins plugins = phase.getGraphBuilderPlugins(); + InvocationPlugins plugins = phase.getGraphBuilderConfig().getInvocationPlugins(); registerGraphBuilderPlugins(providers.getMetaAccess(), plugins); } @@ -101,7 +101,7 @@ } } - protected void registerGraphBuilderPlugins(MetaAccessProvider metaAccess, GraphBuilderPlugins plugins) { + protected void registerGraphBuilderPlugins(MetaAccessProvider metaAccess, InvocationPlugins plugins) { StandardGraphBuilderPlugins.registerPlugins(metaAccess, plugins); HotSpotGraphBuilderPlugins.registerPlugins(metaAccess, plugins); } diff -r 7e2c87dae93e -r 95258dae67ef 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 Mon Feb 16 15:43:03 2015 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotGraphBuilderPlugins.java Mon Feb 16 15:43:22 2015 +0100 @@ -28,9 +28,9 @@ import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.hotspot.replacements.*; import com.oracle.graal.java.*; -import com.oracle.graal.java.GraphBuilderPlugins.InvocationPlugin; -import com.oracle.graal.java.GraphBuilderPlugins.Registration; -import com.oracle.graal.java.GraphBuilderPlugins.Registration.Receiver; +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.calc.*; import com.oracle.graal.nodes.extended.*; @@ -42,7 +42,7 @@ * Provider of HotSpot specific {@link GraphBuilderPlugin}s. */ public class HotSpotGraphBuilderPlugins { - public static void registerPlugins(MetaAccessProvider metaAccess, GraphBuilderPlugins plugins) { + public static void registerPlugins(MetaAccessProvider metaAccess, InvocationPlugins plugins) { // Object.class Registration r = new Registration(plugins, metaAccess, Object.class); r.register1("getClass", Receiver.class, new InvocationPlugin() { diff -r 7e2c87dae93e -r 95258dae67ef 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 Mon Feb 16 15:43:03 2015 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotSuitesProvider.java Mon Feb 16 15:43:22 2015 +0100 @@ -31,8 +31,9 @@ import com.oracle.graal.hotspot.phases.*; import com.oracle.graal.java.*; import com.oracle.graal.java.GraphBuilderConfiguration.DebugInfoMode; -import com.oracle.graal.java.GraphBuilderPlugins.InlineInvokePlugin; +import com.oracle.graal.java.GraphBuilderPlugin.InlineInvokePlugin; import com.oracle.graal.lir.phases.*; +import com.oracle.graal.nodes.*; import com.oracle.graal.options.*; import com.oracle.graal.options.DerivedOptionValue.OptionSupplier; import com.oracle.graal.phases.*; @@ -106,9 +107,12 @@ PhaseSuite suite = new PhaseSuite<>(); GraphBuilderConfiguration config = GraphBuilderConfiguration.getDefault(); config.setInlineInvokePlugin(new InlineInvokePlugin() { - public boolean shouldInlineInvoke(ResolvedJavaMethod method, int depth) { - return GraalOptions.InlineDuringParsing.getValue() && method.getCode().length <= GraalOptions.TrivialInliningSize.getValue() && - depth < GraalOptions.InlineDuringParsingMaxDepth.getValue(); + public ResolvedJavaMethod getInlinedMethod(GraphBuilderContext builder, ResolvedJavaMethod method, ValueNode[] args, JavaType returnType, int depth) { + if (GraalOptions.InlineDuringParsing.getValue() && method.getCode().length <= GraalOptions.TrivialInliningSize.getValue() && + depth < GraalOptions.InlineDuringParsingMaxDepth.getValue()) { + return method; + } + return null; } }); suite.appendPhase(new GraphBuilderPhase(config)); diff -r 7e2c87dae93e -r 95258dae67ef 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 Mon Feb 16 15:43:03 2015 +0100 +++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/AbstractBytecodeParser.java Mon Feb 16 15:43:22 2015 +0100 @@ -37,6 +37,8 @@ import com.oracle.graal.compiler.common.calc.*; import com.oracle.graal.debug.*; import com.oracle.graal.java.BciBlockMapping.BciBlock; +import com.oracle.graal.java.GraphBuilderPlugin.InvocationPlugin; +import com.oracle.graal.java.GraphBuilderPlugin.LoadFieldPlugin; import com.oracle.graal.nodes.*; import com.oracle.graal.options.*; import com.oracle.graal.phases.*; @@ -699,7 +701,7 @@ Kind kind = field.getKind(); T receiver = frameState.apop(); if ((field instanceof ResolvedJavaField) && ((ResolvedJavaField) field).getDeclaringClass().isInitialized()) { - GraphBuilderPlugins.LoadFieldPlugin loadFieldPlugin = this.graphBuilderConfig.getLoadFieldPlugin(); + LoadFieldPlugin loadFieldPlugin = this.graphBuilderConfig.getLoadFieldPlugin(); if (loadFieldPlugin == null || !loadFieldPlugin.apply((GraphBuilderContext) this, (ValueNode) receiver, (ResolvedJavaField) field)) { appendOptimizedLoadField(kind, genLoadField(receiver, (ResolvedJavaField) field)); } @@ -748,7 +750,7 @@ private void genGetStatic(JavaField field) { Kind kind = field.getKind(); if (field instanceof ResolvedJavaField && ((ResolvedJavaType) field.getDeclaringClass()).isInitialized()) { - GraphBuilderPlugins.LoadFieldPlugin loadFieldPlugin = this.graphBuilderConfig.getLoadFieldPlugin(); + InvocationPlugin.LoadFieldPlugin loadFieldPlugin = this.graphBuilderConfig.getLoadFieldPlugin(); if (loadFieldPlugin == null || !loadFieldPlugin.apply((GraphBuilderContext) this, (ResolvedJavaField) field)) { appendOptimizedLoadField(kind, genLoadField(null, (ResolvedJavaField) field)); } diff -r 7e2c87dae93e -r 95258dae67ef graal/com.oracle.graal.java/src/com/oracle/graal/java/DefaultGraphBuilderPlugins.java --- a/graal/com.oracle.graal.java/src/com/oracle/graal/java/DefaultGraphBuilderPlugins.java Mon Feb 16 15:43:03 2015 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,68 +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.java; - -import java.util.*; -import java.util.stream.*; - -import com.oracle.graal.api.meta.*; - -/** - * Default implementation of {@link GraphBuilderPlugins} that uses a map. - */ -public class DefaultGraphBuilderPlugins implements GraphBuilderPlugins { - - private final Map plugins = new HashMap<>(); - - /** - * Registers an invocation plugin for a given method. There must be no plugin currently - * registered for {@code method}. - */ - public void register(ResolvedJavaMethod method, InvocationPlugin plugin) { - assert InvocationPluginChecker.check(method, plugin); - GraphBuilderPlugin oldValue = plugins.put(method, plugin); - // System.out.println("registered: " + plugin); - assert oldValue == null; - } - - /** - * Gets the plugin for a given method. - * - * @param method the method to lookup - * @return the plugin associated with {@code method} or {@code null} if none exists - */ - public InvocationPlugin lookupInvocation(ResolvedJavaMethod method) { - return plugins.get(method); - } - - public DefaultGraphBuilderPlugins copy() { - DefaultGraphBuilderPlugins result = new DefaultGraphBuilderPlugins(); - result.plugins.putAll(plugins); - return result; - } - - @Override - public String toString() { - return plugins.keySet().stream().map(m -> m.format("%H.%n(%p)")).collect(Collectors.joining(", ")); - } -} diff -r 7e2c87dae93e -r 95258dae67ef graal/com.oracle.graal.java/src/com/oracle/graal/java/GraalDirectivePlugins.java --- a/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraalDirectivePlugins.java Mon Feb 16 15:43:03 2015 +0100 +++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraalDirectivePlugins.java Mon Feb 16 15:43:22 2015 +0100 @@ -24,15 +24,15 @@ import com.oracle.graal.api.directives.*; import com.oracle.graal.api.meta.*; -import com.oracle.graal.java.GraphBuilderPlugins.InvocationPlugin; -import com.oracle.graal.java.GraphBuilderPlugins.Registration; +import com.oracle.graal.java.GraphBuilderPlugin.InvocationPlugin; +import com.oracle.graal.java.InvocationPlugins.Registration; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.debug.*; import com.oracle.graal.nodes.extended.*; public class GraalDirectivePlugins { - public static void registerPlugins(MetaAccessProvider metaAccess, GraphBuilderPlugins plugins) { + public static void registerPlugins(MetaAccessProvider metaAccess, InvocationPlugins plugins) { Registration r = new Registration(plugins, metaAccess, GraalDirectives.class); r.register0("deoptimize", new InvocationPlugin() { public boolean apply(GraphBuilderContext builder) { diff -r 7e2c87dae93e -r 95258dae67ef 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 Mon Feb 16 15:43:03 2015 +0100 +++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderConfiguration.java Mon Feb 16 15:43:22 2015 +0100 @@ -26,6 +26,10 @@ import com.oracle.graal.api.meta.*; import com.oracle.graal.compiler.common.*; +import com.oracle.graal.java.GraphBuilderPlugin.InlineInvokePlugin; +import com.oracle.graal.java.GraphBuilderPlugin.LoadFieldPlugin; +import com.oracle.graal.java.GraphBuilderPlugin.LoopExplosionPlugin; +import com.oracle.graal.java.GraphBuilderPlugin.ParameterPlugin; import com.oracle.graal.nodes.*; public class GraphBuilderConfiguration { @@ -36,10 +40,11 @@ private final ResolvedJavaType[] skippedExceptionTypes; private final DebugInfoMode debugInfoMode; private final boolean doLivenessAnalysis; - private GraphBuilderPlugins.LoadFieldPlugin loadFieldPlugin; - private GraphBuilderPlugins.ParameterPlugin parameterPlugin; - private GraphBuilderPlugins.InlineInvokePlugin inlineInvokePlugin; - private GraphBuilderPlugins.LoopExplosionPlugin loopExplosionPlugin; + private final InvocationPlugins invocationPlugins = new InvocationPlugins(); + private LoadFieldPlugin loadFieldPlugin; + private ParameterPlugin parameterPlugin; + private InlineInvokePlugin inlineInvokePlugin; + private LoopExplosionPlugin loopExplosionPlugin; public static enum DebugInfoMode { SafePointsOnly, @@ -96,11 +101,15 @@ return new GraphBuilderConfiguration(eagerResolving, omitAllExceptionEdges, debugInfoMode, skippedExceptionTypes, newLivenessAnalysis); } - public GraphBuilderPlugins.LoadFieldPlugin getLoadFieldPlugin() { + public InvocationPlugins getInvocationPlugins() { + return invocationPlugins; + } + + public LoadFieldPlugin getLoadFieldPlugin() { return loadFieldPlugin; } - public void setLoadFieldPlugin(GraphBuilderPlugins.LoadFieldPlugin loadFieldPlugin) { + public void setLoadFieldPlugin(LoadFieldPlugin loadFieldPlugin) { this.loadFieldPlugin = loadFieldPlugin; } @@ -153,27 +162,27 @@ return eagerResolving; } - public GraphBuilderPlugins.ParameterPlugin getParameterPlugin() { + public ParameterPlugin getParameterPlugin() { return parameterPlugin; } - public void setParameterPlugin(GraphBuilderPlugins.ParameterPlugin parameterPlugin) { + public void setParameterPlugin(ParameterPlugin parameterPlugin) { this.parameterPlugin = parameterPlugin; } - public GraphBuilderPlugins.InlineInvokePlugin getInlineInvokePlugin() { + public InlineInvokePlugin getInlineInvokePlugin() { return inlineInvokePlugin; } - public void setInlineInvokePlugin(GraphBuilderPlugins.InlineInvokePlugin inlineInvokePlugin) { + public void setInlineInvokePlugin(InlineInvokePlugin inlineInvokePlugin) { this.inlineInvokePlugin = inlineInvokePlugin; } - public GraphBuilderPlugins.LoopExplosionPlugin getLoopExplosionPlugin() { + public LoopExplosionPlugin getLoopExplosionPlugin() { return loopExplosionPlugin; } - public void setLoopExplosionPlugin(GraphBuilderPlugins.LoopExplosionPlugin loopExplosionPlugin) { + public void setLoopExplosionPlugin(LoopExplosionPlugin loopExplosionPlugin) { this.loopExplosionPlugin = loopExplosionPlugin; } } diff -r 7e2c87dae93e -r 95258dae67ef 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 Mon Feb 16 15:43:03 2015 +0100 +++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPhase.java Mon Feb 16 15:43:22 2015 +0100 @@ -45,9 +45,9 @@ import com.oracle.graal.java.BciBlockMapping.BciBlock; import com.oracle.graal.java.BciBlockMapping.ExceptionDispatchBlock; import com.oracle.graal.java.BciBlockMapping.LocalLiveness; -import com.oracle.graal.java.GraphBuilderPlugins.InlineInvokePlugin; -import com.oracle.graal.java.GraphBuilderPlugins.InvocationPlugin; -import com.oracle.graal.java.GraphBuilderPlugins.LoopExplosionPlugin; +import com.oracle.graal.java.GraphBuilderPlugin.InlineInvokePlugin; +import com.oracle.graal.java.GraphBuilderPlugin.InvocationPlugin; +import com.oracle.graal.java.GraphBuilderPlugin.LoopExplosionPlugin; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.CallTargetNode.InvokeKind; import com.oracle.graal.nodes.calc.*; @@ -65,30 +65,20 @@ public class GraphBuilderPhase extends BasePhase { private final GraphBuilderConfiguration graphBuilderConfig; - private final GraphBuilderPlugins graphBuilderPlugins; public GraphBuilderPhase(GraphBuilderConfiguration config) { - this(config, new DefaultGraphBuilderPlugins()); - } - - public GraphBuilderPhase(GraphBuilderConfiguration config, GraphBuilderPlugins graphBuilderPlugins) { this.graphBuilderConfig = config; - this.graphBuilderPlugins = graphBuilderPlugins; } @Override protected void run(StructuredGraph graph, HighTierContext context) { - new Instance(context.getMetaAccess(), context.getStampProvider(), null, null, context.getConstantReflection(), graphBuilderConfig, graphBuilderPlugins, context.getOptimisticOptimizations()).run(graph); + new Instance(context.getMetaAccess(), context.getStampProvider(), null, null, context.getConstantReflection(), graphBuilderConfig, context.getOptimisticOptimizations()).run(graph); } public GraphBuilderConfiguration getGraphBuilderConfig() { return graphBuilderConfig; } - public GraphBuilderPlugins getGraphBuilderPlugins() { - return graphBuilderPlugins; - } - public static class Instance extends Phase { protected StructuredGraph currentGraph; @@ -98,7 +88,6 @@ private ResolvedJavaMethod rootMethod; private final GraphBuilderConfiguration graphBuilderConfig; - private final GraphBuilderPlugins graphBuilderPlugins; private final OptimisticOptimizations optimisticOpts; private final StampProvider stampProvider; private final ConstantReflectionProvider constantReflection; @@ -114,12 +103,11 @@ } public Instance(MetaAccessProvider metaAccess, StampProvider stampProvider, SnippetReflectionProvider snippetReflectionProvider, Replacements replacements, - ConstantReflectionProvider constantReflection, GraphBuilderConfiguration graphBuilderConfig, GraphBuilderPlugins graphBuilderPlugins, OptimisticOptimizations optimisticOpts) { + ConstantReflectionProvider constantReflection, GraphBuilderConfiguration graphBuilderConfig, OptimisticOptimizations optimisticOpts) { this.graphBuilderConfig = graphBuilderConfig; this.optimisticOpts = optimisticOpts; this.metaAccess = metaAccess; this.stampProvider = stampProvider; - this.graphBuilderPlugins = graphBuilderPlugins; this.constantReflection = constantReflection; this.snippetReflectionProvider = snippetReflectionProvider; this.replacements = replacements; @@ -128,7 +116,7 @@ public Instance(MetaAccessProvider metaAccess, StampProvider stampProvider, ConstantReflectionProvider constantReflection, GraphBuilderConfiguration graphBuilderConfig, OptimisticOptimizations optimisticOpts) { - this(metaAccess, stampProvider, null, null, constantReflection, graphBuilderConfig, null, optimisticOpts); + this(metaAccess, stampProvider, null, null, constantReflection, graphBuilderConfig, optimisticOpts); } @Override @@ -866,37 +854,39 @@ } } - if (graphBuilderPlugins != null) { - if (tryUsingInvocationPlugin(args, targetMethod, resultType)) { + if (tryUsingInvocationPlugin(args, targetMethod, resultType)) { + if (GraalOptions.TraceInlineDuringParsing.getValue()) { + for (int i = 0; i < this.currentDepth; ++i) { + TTY.print(' '); + } + TTY.println("Used invocation plugin for " + targetMethod); + } + return; + } + + InlineInvokePlugin inlineInvokePlugin = graphBuilderConfig.getInlineInvokePlugin(); + if (inlineInvokePlugin != null && invokeKind.isDirect() && targetMethod.canBeInlined() && targetMethod.hasBytecodes() && + (replacements == null || (replacements.getMethodSubstitution(targetMethod) == null && replacements.getMacroSubstitution(targetMethod) == null))) { + + ResolvedJavaMethod inlinedMethod = inlineInvokePlugin.getInlinedMethod(this, targetMethod, args, returnType, currentDepth); + if (inlinedMethod != null) { if (GraalOptions.TraceInlineDuringParsing.getValue()) { + int bci = this.bci(); for (int i = 0; i < this.currentDepth; ++i) { TTY.print(' '); } - TTY.println("Used invocation plugin for " + targetMethod); + StackTraceElement stackTraceElement = this.method.asStackTraceElement(bci); + String s = String.format("%s (%s:%d)", method.getName(), stackTraceElement.getFileName(), stackTraceElement.getLineNumber()); + TTY.print(s); + TTY.println(" inlining call " + targetMethod.getName()); } + + ResolvedJavaMethod inlinedTargetMethod = inlinedMethod; + parseAndInlineCallee(inlinedTargetMethod, args); + inlineInvokePlugin.postInline(inlinedTargetMethod); return; } } - InlineInvokePlugin inlineInvokePlugin = graphBuilderConfig.getInlineInvokePlugin(); - if (inlineInvokePlugin != null && invokeKind.isDirect() && targetMethod.canBeInlined() && targetMethod.hasBytecodes() && - (replacements == null || (replacements.getMethodSubstitution(targetMethod) == null && replacements.getMacroSubstitution(targetMethod) == null)) && - inlineInvokePlugin.shouldInlineInvoke(targetMethod, currentDepth)) { - if (GraalOptions.TraceInlineDuringParsing.getValue()) { - int bci = this.bci(); - for (int i = 0; i < this.currentDepth; ++i) { - TTY.print(' '); - } - StackTraceElement stackTraceElement = this.method.asStackTraceElement(bci); - String s = String.format("%s (%s:%d)", method.getName(), stackTraceElement.getFileName(), stackTraceElement.getLineNumber()); - TTY.print(s); - TTY.println(" inlining call " + targetMethod.getName()); - } - - ResolvedJavaMethod inlinedTargetMethod = inlineInvokePlugin.inlinedMethod(this, targetMethod, args); - parseAndInlineCallee(inlinedTargetMethod, args); - inlineInvokePlugin.postInline(inlinedTargetMethod); - return; - } MethodCallTargetNode callTarget = currentGraph.add(createMethodCallTarget(invokeKind, targetMethod, args, returnType)); @@ -913,7 +903,7 @@ } private boolean tryUsingInvocationPlugin(ValueNode[] args, ResolvedJavaMethod targetMethod, Kind resultType) { - InvocationPlugin plugin = graphBuilderPlugins.lookupInvocation(targetMethod); + InvocationPlugin plugin = graphBuilderConfig.getInvocationPlugins().lookupInvocation(targetMethod); if (plugin != null) { int beforeStackSize = frameState.stackSize; boolean needsNullCheck = !targetMethod.isStatic() && !StampTool.isPointerNonNull(args[0].stamp()); diff -r 7e2c87dae93e -r 95258dae67ef 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 Mon Feb 16 15:43:03 2015 +0100 +++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPlugin.java Mon Feb 16 15:43:22 2015 +0100 @@ -22,13 +22,141 @@ */ package com.oracle.graal.java; +import com.oracle.graal.api.meta.*; +import com.oracle.graal.compiler.common.*; +import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.calc.*; + /** * Marker interface for graph builder plugins. - * - * Concrete plugins implement one of the sub-interfaces of this interface. - * - * @see GraphBuilderPlugins - * @see GraphBuilderPlugins.Registration */ public interface GraphBuilderPlugin { + + public interface LoadFieldPlugin extends GraphBuilderPlugin { + @SuppressWarnings("unused") + default boolean apply(GraphBuilderContext builder, ValueNode receiver, ResolvedJavaField field) { + return false; + } + + @SuppressWarnings("unused") + default boolean apply(GraphBuilderContext graphBuilderContext, ResolvedJavaField staticField) { + return false; + } + + default boolean tryConstantFold(GraphBuilderContext builder, MetaAccessProvider metaAccess, ConstantReflectionProvider constantReflection, ResolvedJavaField field, JavaConstant asJavaConstant) { + JavaConstant result = constantReflection.readConstantFieldValue(field, asJavaConstant); + if (result != null) { + ConstantNode constantNode = builder.append(ConstantNode.forConstant(result, metaAccess)); + builder.push(constantNode.getKind().getStackKind(), constantNode); + return true; + } + return false; + } + } + + /** + * Plugin for customizing how the graph builder handles a CHECKCAST instruction in the context + * of the instruction that consumes it from the stack. + */ + public interface CheckCastPlugin extends GraphBuilderPlugin { + boolean apply(GraphBuilderContext builder, ResolvedJavaType type, ValueNode object, JavaTypeProfile profileForTypeCheck); + } + + public interface InlineInvokePlugin extends GraphBuilderPlugin { + + default void postInline(@SuppressWarnings("unused") ResolvedJavaMethod inlinedTargetMethod) { + + } + + ResolvedJavaMethod getInlinedMethod(GraphBuilderContext builder, ResolvedJavaMethod method, ValueNode[] args, JavaType returnType, int depth); + } + + public interface LoopExplosionPlugin extends GraphBuilderPlugin { + boolean shouldExplodeLoops(ResolvedJavaMethod method); + } + + public interface ParameterPlugin extends GraphBuilderPlugin { + FloatingNode interceptParameter(int index); + } + + /** + * Plugin for handling an invocation based on the annotations of the invoked method. + */ + public interface AnnotatedInvocationPlugin extends GraphBuilderPlugin { + /** + * Executes this plugin for an invocation of a given method with a given set of arguments. + * + * @return {@code true} if this plugin handled the invocation, {@code false} if not + */ + boolean apply(GraphBuilderContext builder, ResolvedJavaMethod method, ValueNode[] args); + } + + /** + * Plugin for handling a specific method invocation. + */ + public interface InvocationPlugin extends GraphBuilderPlugin { + /** + * @see #execute(GraphBuilderContext, InvocationPlugin, ValueNode[]) + */ + default boolean apply(GraphBuilderContext builder) { + throw invalidHandler(builder); + } + + /** + * @see #execute(GraphBuilderContext, InvocationPlugin, ValueNode[]) + */ + default boolean apply(GraphBuilderContext builder, ValueNode arg) { + throw invalidHandler(builder, arg); + } + + /** + * @see #execute(GraphBuilderContext, InvocationPlugin, ValueNode[]) + */ + default boolean apply(GraphBuilderContext builder, ValueNode arg1, ValueNode arg2) { + throw invalidHandler(builder, arg1, arg2); + } + + /** + * @see #execute(GraphBuilderContext, InvocationPlugin, ValueNode[]) + */ + default boolean apply(GraphBuilderContext builder, ValueNode arg1, ValueNode arg2, ValueNode arg3) { + throw invalidHandler(builder, arg1, arg2, arg3); + } + + /** + * @see #execute(GraphBuilderContext, InvocationPlugin, ValueNode[]) + */ + default boolean apply(GraphBuilderContext builder, ValueNode arg1, ValueNode arg2, ValueNode arg3, ValueNode arg4) { + throw invalidHandler(builder, arg1, arg2, arg3, arg4); + } + + /** + * 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. + * + * @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. + */ + static boolean execute(GraphBuilderContext builder, InvocationPlugin plugin, ValueNode[] args) { + if (args.length == 0) { + return plugin.apply(builder); + } else if (args.length == 1) { + return plugin.apply(builder, args[0]); + } else if (args.length == 2) { + return plugin.apply(builder, args[0], args[1]); + } else if (args.length == 3) { + return plugin.apply(builder, args[0], args[1], args[2]); + } else if (args.length == 4) { + return plugin.apply(builder, args[0], args[1], args[2], args[3]); + } else { + throw plugin.invalidHandler(builder, 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); + } + } } diff -r 7e2c87dae93e -r 95258dae67ef graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPlugins.java --- a/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPlugins.java Mon Feb 16 15:43:03 2015 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,309 +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.java; - -import static java.lang.String.*; - -import java.lang.reflect.*; -import java.util.*; - -import com.oracle.graal.api.meta.*; -import com.oracle.graal.compiler.common.*; -import com.oracle.graal.nodes.*; -import com.oracle.graal.nodes.calc.*; - -/** - * Interface for managing a set of graph builder {@link GraphBuilderPlugin}s. - */ -public interface GraphBuilderPlugins { - - public interface LoadFieldPlugin extends GraphBuilderPlugin { - @SuppressWarnings("unused") - default boolean apply(GraphBuilderContext builder, ValueNode receiver, ResolvedJavaField field) { - return false; - } - - @SuppressWarnings("unused") - default boolean apply(GraphBuilderContext graphBuilderContext, ResolvedJavaField staticField) { - return false; - } - } - - public interface ParameterPlugin extends GraphBuilderPlugin { - FloatingNode interceptParameter(int index); - } - - public interface InlineInvokePlugin extends GraphBuilderPlugin { - default ResolvedJavaMethod inlinedMethod(@SuppressWarnings("unused") GraphBuilderContext builder, ResolvedJavaMethod original, @SuppressWarnings("unused") ValueNode[] arguments) { - return original; - } - - boolean shouldInlineInvoke(ResolvedJavaMethod method, int depth); - - default void postInline(@SuppressWarnings("unused") ResolvedJavaMethod inlinedTargetMethod) { - - } - } - - public interface LoopExplosionPlugin extends GraphBuilderPlugin { - boolean shouldExplodeLoops(ResolvedJavaMethod method); - } - - /** - * Plugin for handling a method invocation. - */ - public interface InvocationPlugin extends GraphBuilderPlugin { - /** - * @see #execute(GraphBuilderContext, InvocationPlugin, ValueNode[]) - */ - default boolean apply(GraphBuilderContext builder) { - throw invalidHandler(builder); - } - - /** - * @see #execute(GraphBuilderContext, InvocationPlugin, ValueNode[]) - */ - default boolean apply(GraphBuilderContext builder, ValueNode arg) { - throw invalidHandler(builder, arg); - } - - /** - * @see #execute(GraphBuilderContext, InvocationPlugin, ValueNode[]) - */ - default boolean apply(GraphBuilderContext builder, ValueNode arg1, ValueNode arg2) { - throw invalidHandler(builder, arg1, arg2); - } - - /** - * @see #execute(GraphBuilderContext, InvocationPlugin, ValueNode[]) - */ - default boolean apply(GraphBuilderContext builder, ValueNode arg1, ValueNode arg2, ValueNode arg3) { - throw invalidHandler(builder, arg1, arg2, arg3); - } - - /** - * @see #execute(GraphBuilderContext, InvocationPlugin, ValueNode[]) - */ - default boolean apply(GraphBuilderContext builder, ValueNode arg1, ValueNode arg2, ValueNode arg3, ValueNode arg4) { - throw invalidHandler(builder, arg1, arg2, arg3, arg4); - } - - /** - * 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. - * - * @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. - */ - static boolean execute(GraphBuilderContext builder, InvocationPlugin plugin, ValueNode[] args) { - if (args.length == 0) { - return plugin.apply(builder); - } else if (args.length == 1) { - return plugin.apply(builder, args[0]); - } else if (args.length == 2) { - return plugin.apply(builder, args[0], args[1]); - } else if (args.length == 3) { - return plugin.apply(builder, args[0], args[1], args[2]); - } else if (args.length == 4) { - return plugin.apply(builder, args[0], args[1], args[2], args[3]); - } else { - throw plugin.invalidHandler(builder, 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); - } - } - - /** - * Utility for {@linkplain GraphBuilderPlugins#register(ResolvedJavaMethod, InvocationPlugin) - * registration} of plugins. - */ - public static class Registration { - - /** - * Sentinel class for use with {@link Registration#register1}, - * {@link Registration#register2} or {@link Registration#register3} to denote the receiver - * argument for a non-static method. - */ - public static final class Receiver { - private Receiver() { - throw GraalInternalError.shouldNotReachHere(); - } - } - - private final GraphBuilderPlugins plugins; - private final MetaAccessProvider metaAccess; - private final Class declaringClass; - - /** - * Creates an object for registering plugins for methods declared by a given class. - * - * @param plugins where to register the plugins - * @param metaAccess used to resolve classes and methods - * @param declaringClass the class declaring the methods for which plugins will be - * registered via this object - */ - public Registration(GraphBuilderPlugins plugins, MetaAccessProvider metaAccess, Class declaringClass) { - this.plugins = plugins; - this.metaAccess = metaAccess; - this.declaringClass = declaringClass; - } - - /** - * Registers a plugin for a method with no arguments. - * - * @param name the name of the method - * @param plugin the plugin to be registered - */ - public void register0(String name, InvocationPlugin plugin) { - plugins.register(resolve(metaAccess, declaringClass, name), plugin); - } - - /** - * Registers a plugin for a method with 1 argument. - * - * @param name the name of the method - * @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); - } - - /** - * Registers a plugin for a method with 2 arguments. - * - * @param name the name of the method - * @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); - } - - /** - * Registers a plugin for a method with 3 arguments. - * - * @param name the name of the method - * @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); - } - - /** - * Registers a plugin for a method with 4 arguments. - * - * @param name the name of the method - * @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); - } - - /** - * Resolves a method given a declaring class, name and parameter types. - */ - public static ResolvedJavaMethod resolve(MetaAccessProvider metaAccess, Class declaringClass, String name, Class... parameterTypes) { - try { - return metaAccess.lookupJavaMethod(name.equals("") ? declaringClass.getDeclaredConstructor(parameterTypes) : declaringClass.getDeclaredMethod(name, parameterTypes)); - } catch (NoSuchMethodException | SecurityException e) { - throw new GraalInternalError(e); - } - } - } - - public static class InvocationPluginChecker { - /** - * The set of all {@link InvocationPlugin#apply} method signatures. - */ - static final Class[][] SIGS; - static { - ArrayList[]> sigs = new ArrayList<>(5); - 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) { - sigs.add(null); - } - sigs.set(sig.length - 1, 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), - ValueNode.class.getSimpleName()); - SIGS = sigs.toArray(new Class[sigs.size()][]); - } - - public static boolean check(ResolvedJavaMethod method, InvocationPlugin plugin) { - int arguments = method.getSignature().getParameterCount(!method.isStatic()); - assert arguments < SIGS.length : format("need to extend %s to support method with %d arguments: %s", InvocationPlugin.class.getSimpleName(), arguments, method.format("%H.%n(%p)")); - Method expected = null; - for (Method m : plugin.getClass().getDeclaredMethods()) { - if (m.getName().equals("apply")) { - Class[] parameterTypes = m.getParameterTypes(); - assert Arrays.equals(SIGS[arguments], parameterTypes) : format("graph builder plugin for %s has wrong signature%nexpected: (%s)%n actual: (%s)", method.format("%H.%n(%p)"), - sigString(SIGS[arguments]), sigString(m.getParameterTypes())); - expected = m; - } - } - assert expected != null : format("graph builder plugin %s must define exactly one \"apply\" method, none found", plugin); - return true; - } - - protected static String sigString(Class... sig) { - StringBuilder sb = new StringBuilder(); - for (Class t : sig) { - if (sb.length() != 0) { - sb.append(", "); - } - sb.append(t.getSimpleName()); - } - return sb.toString(); - } - - } - - /** - * Registers an {@link InvocationPlugin} for a given method. There must be no plugin currently - * registered for {@code method}. - */ - void register(ResolvedJavaMethod method, InvocationPlugin plugin); - - /** - * Gets the {@link InvocationPlugin} for a given method. - * - * @param method the method to lookup - * @return the plugin associated with {@code method} or {@code null} if none exists - */ - InvocationPlugin lookupInvocation(ResolvedJavaMethod method); - - DefaultGraphBuilderPlugins copy(); -} diff -r 7e2c87dae93e -r 95258dae67ef 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 Mon Feb 16 15:43:03 2015 +0100 +++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/HIRFrameStateBuilder.java Mon Feb 16 15:43:22 2015 +0100 @@ -32,7 +32,7 @@ import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.debug.*; import com.oracle.graal.java.BciBlockMapping.LocalLiveness; -import com.oracle.graal.java.GraphBuilderPlugins.ParameterPlugin; +import com.oracle.graal.java.GraphBuilderPlugin.ParameterPlugin; import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.calc.*; diff -r 7e2c87dae93e -r 95258dae67ef graal/com.oracle.graal.java/src/com/oracle/graal/java/InvocationPlugins.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/InvocationPlugins.java Mon Feb 16 15:43:22 2015 +0100 @@ -0,0 +1,239 @@ +/* + * 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.java; + +import static java.lang.String.*; + +import java.lang.reflect.*; +import java.util.*; +import java.util.stream.*; + +import com.oracle.graal.api.meta.*; +import com.oracle.graal.compiler.common.*; +import com.oracle.graal.java.GraphBuilderPlugin.InvocationPlugin; +import com.oracle.graal.nodes.*; + +/** + * Manages a set of {@link InvocationPlugin}s. + */ +public class InvocationPlugins { + /** + * Utility for {@linkplain InvocationPlugins#register(ResolvedJavaMethod, InvocationPlugin) + * registration} of invocation plugins. + */ + public static class Registration { + + /** + * Sentinel class for use with {@link Registration#register1}, + * {@link Registration#register2} or {@link Registration#register3} to denote the receiver + * argument for a non-static method. + */ + public static final class Receiver { + private Receiver() { + throw GraalInternalError.shouldNotReachHere(); + } + } + + private final InvocationPlugins plugins; + private final MetaAccessProvider metaAccess; + private final Class declaringClass; + + /** + * Creates an object for registering {@link InvocationPlugin}s for methods declared by a + * given class. + * + * @param plugins where to register the plugins + * @param metaAccess used to resolve classes and methods + * @param declaringClass the class declaring the methods for which plugins will be + * registered via this object + */ + public Registration(InvocationPlugins plugins, MetaAccessProvider metaAccess, Class declaringClass) { + this.plugins = plugins; + this.metaAccess = metaAccess; + this.declaringClass = declaringClass; + } + + /** + * Registers a plugin for a method with no arguments. + * + * @param name the name of the method + * @param plugin the plugin to be registered + */ + public void register0(String name, InvocationPlugin plugin) { + plugins.register(resolve(metaAccess, declaringClass, name), plugin); + } + + /** + * Registers a plugin for a method with 1 argument. + * + * @param name the name of the method + * @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); + } + + /** + * Registers a plugin for a method with 2 arguments. + * + * @param name the name of the method + * @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); + } + + /** + * Registers a plugin for a method with 3 arguments. + * + * @param name the name of the method + * @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); + } + + /** + * Registers a plugin for a method with 4 arguments. + * + * @param name the name of the method + * @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); + } + + /** + * Resolves a method given a declaring class, name and parameter types. + */ + public static ResolvedJavaMethod resolve(MetaAccessProvider metaAccess, Class declaringClass, String name, Class... parameterTypes) { + try { + return metaAccess.lookupJavaMethod(name.equals("") ? declaringClass.getDeclaredConstructor(parameterTypes) : declaringClass.getDeclaredMethod(name, parameterTypes)); + } catch (NoSuchMethodException | SecurityException e) { + throw new GraalInternalError(e); + } + } + } + + private final Map plugins = new HashMap<>(); + + /** + * The invocation plugins deferred to if a plugin is not found in this object. + */ + private InvocationPlugins defaults; + + /** + * Registers an invocation plugin for a given method. There must be no plugin currently + * registered for {@code method}. + */ + public void register(ResolvedJavaMethod method, InvocationPlugin plugin) { + assert Checker.check(method, plugin); + GraphBuilderPlugin oldValue = plugins.put(method, plugin); + // System.out.println("registered: " + plugin); + assert oldValue == null; + } + + /** + * Gets the plugin for a given method. + * + * @param method the method to lookup + * @return the plugin associated with {@code method} or {@code null} if none exists + */ + public InvocationPlugin lookupInvocation(ResolvedJavaMethod method) { + InvocationPlugin res = plugins.get(method); + if (res == null && defaults != null) { + return defaults.lookupInvocation(method); + } + return res; + } + + /** + * Sets the invocation plugins {@linkplain #lookupInvocation(ResolvedJavaMethod) searched} if a + * plugin is not found in this object. + */ + public InvocationPlugins setDefaults(InvocationPlugins defaults) { + InvocationPlugins old = this.defaults; + this.defaults = defaults; + return old; + } + + @Override + public String toString() { + return plugins.keySet().stream().map(m -> m.format("%H.%n(%p)")).collect(Collectors.joining(", ")); + } + + private static class Checker { + /** + * The set of all {@link InvocationPlugin#apply} method signatures. + */ + static final Class[][] SIGS; + static { + ArrayList[]> sigs = new ArrayList<>(5); + 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) { + sigs.add(null); + } + sigs.set(sig.length - 1, 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), + ValueNode.class.getSimpleName()); + SIGS = sigs.toArray(new Class[sigs.size()][]); + } + + public static boolean check(ResolvedJavaMethod method, InvocationPlugin plugin) { + int arguments = method.getSignature().getParameterCount(!method.isStatic()); + assert arguments < SIGS.length : format("need to extend %s to support method with %d arguments: %s", InvocationPlugin.class.getSimpleName(), arguments, method.format("%H.%n(%p)")); + Method expected = null; + for (Method m : plugin.getClass().getDeclaredMethods()) { + if (m.getName().equals("apply")) { + Class[] parameterTypes = m.getParameterTypes(); + assert Arrays.equals(SIGS[arguments], parameterTypes) : format("graph builder plugin for %s has wrong signature%nexpected: (%s)%n actual: (%s)", method.format("%H.%n(%p)"), + sigString(SIGS[arguments]), sigString(m.getParameterTypes())); + expected = m; + } + } + assert expected != null : format("graph builder plugin %s must define exactly one \"apply\" method, none found", plugin); + return true; + } + + protected static String sigString(Class... sig) { + StringBuilder sb = new StringBuilder(); + for (Class t : sig) { + if (sb.length() != 0) { + sb.append(", "); + } + sb.append(t.getSimpleName()); + } + return sb.toString(); + } + } +} diff -r 7e2c87dae93e -r 95258dae67ef graal/com.oracle.graal.java/src/com/oracle/graal/java/StandardGraphBuilderPlugins.java --- a/graal/com.oracle.graal.java/src/com/oracle/graal/java/StandardGraphBuilderPlugins.java Mon Feb 16 15:43:03 2015 +0100 +++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/StandardGraphBuilderPlugins.java Mon Feb 16 15:43:22 2015 +0100 @@ -25,9 +25,9 @@ import static com.oracle.graal.java.GraphBuilderContext.*; import com.oracle.graal.api.meta.*; -import com.oracle.graal.java.GraphBuilderPlugins.InvocationPlugin; -import com.oracle.graal.java.GraphBuilderPlugins.Registration; -import com.oracle.graal.java.GraphBuilderPlugins.Registration.Receiver; +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.calc.*; import com.oracle.graal.nodes.extended.*; @@ -37,7 +37,7 @@ * Provider of non-runtime specific {@link GraphBuilderPlugin}s. */ public class StandardGraphBuilderPlugins { - public static void registerPlugins(MetaAccessProvider metaAccess, GraphBuilderPlugins plugins) { + public static void registerPlugins(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) { @@ -92,7 +92,7 @@ return true; } - void register(MetaAccessProvider metaAccess, GraphBuilderPlugins plugins) { + void register(MetaAccessProvider metaAccess, InvocationPlugins plugins) { ResolvedJavaMethod method = Registration.resolve(metaAccess, kind.toBoxedJavaClass(), "valueOf", kind.toJavaClass()); plugins.register(method, this); } @@ -112,7 +112,7 @@ return true; } - void register(MetaAccessProvider metaAccess, GraphBuilderPlugins plugins) { + void register(MetaAccessProvider metaAccess, InvocationPlugins plugins) { String name = kind.toJavaClass().getSimpleName() + "Value"; ResolvedJavaMethod method = Registration.resolve(metaAccess, kind.toBoxedJavaClass(), name); plugins.register(method, this); diff -r 7e2c87dae93e -r 95258dae67ef graal/com.oracle.graal.phases/src/com/oracle/graal/phases/util/GraphOrder.java --- a/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/util/GraphOrder.java Mon Feb 16 15:43:03 2015 +0100 +++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/util/GraphOrder.java Mon Feb 16 15:43:22 2015 +0100 @@ -165,8 +165,8 @@ pendingStateAfter.applyToNonVirtual(new NodeClosure() { @Override public void apply(Node usage, Node nonVirtualNode) { - assert currentState.isMarked(nonVirtualNode) || nonVirtualNode instanceof VirtualObjectNode : nonVirtualNode + " not available at virtualstate " + usage + - " before " + node + " in block " + block + " \n" + list; + assert currentState.isMarked(nonVirtualNode) || nonVirtualNode instanceof VirtualObjectNode || nonVirtualNode instanceof ConstantNode : nonVirtualNode + + " not available at virtualstate " + usage + " before " + node + " in block " + block + " \n" + list; } }); pendingStateAfter = null; @@ -208,7 +208,8 @@ } }); } else { - assert currentState.isMarked(input) || input instanceof VirtualObjectNode : input + " not available at " + node + " in block " + block + "\n" + list; + assert currentState.isMarked(input) || input instanceof VirtualObjectNode || input instanceof ConstantNode : input + " not available at " + node + + " in block " + block + "\n" + list; } } } @@ -217,7 +218,8 @@ AbstractMergeNode merge = ((AbstractEndNode) node).merge(); for (PhiNode phi : merge.phis()) { ValueNode phiValue = phi.valueAt((AbstractEndNode) node); - assert phiValue == null || currentState.isMarked(phiValue) : phiValue + " not available at phi " + phi + " / end " + node + " in block " + block; + assert phiValue == null || currentState.isMarked(phiValue) || phiValue instanceof ConstantNode : phiValue + " not available at phi " + phi + " / end " + node + + " in block " + block; } } if (stateAfter != null) { @@ -230,8 +232,8 @@ pendingStateAfter.applyToNonVirtual(new NodeClosure() { @Override public void apply(Node usage, Node nonVirtualNode) { - assert currentState.isMarked(nonVirtualNode) || nonVirtualNode instanceof VirtualObjectNode : nonVirtualNode + " not available at virtualstate " + usage + - " at end of block " + block + " \n" + list; + assert currentState.isMarked(nonVirtualNode) || nonVirtualNode instanceof VirtualObjectNode || nonVirtualNode instanceof ConstantNode : nonVirtualNode + + " not available at virtualstate " + usage + " at end of block " + block + " \n" + list; } }); } diff -r 7e2c87dae93e -r 95258dae67ef graal/com.oracle.graal.truffle.test/src/com/oracle/graal/truffle/test/PartialEvaluationTest.java --- a/graal/com.oracle.graal.truffle.test/src/com/oracle/graal/truffle/test/PartialEvaluationTest.java Mon Feb 16 15:43:03 2015 +0100 +++ b/graal/com.oracle.graal.truffle.test/src/com/oracle/graal/truffle/test/PartialEvaluationTest.java Mon Feb 16 15:43:22 2015 +0100 @@ -89,7 +89,7 @@ compilable.call(arguments); try (Scope s = Debug.scope("TruffleCompilation", new TruffleDebugJavaMethod(compilable))) { - return truffleCompiler.getPartialEvaluator().createGraph(compilable, allowAssumptions, truffleCompiler.createGraphBuilderSuitePlugins()); + return truffleCompiler.getPartialEvaluator().createGraph(compilable, allowAssumptions); } catch (Throwable e) { throw Debug.handle(e); } diff -r 7e2c87dae93e -r 95258dae67ef 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 Mon Feb 16 15:43:03 2015 +0100 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/PartialEvaluator.java Mon Feb 16 15:43:22 2015 +0100 @@ -38,6 +38,8 @@ import com.oracle.graal.graph.*; import com.oracle.graal.graph.Node; import com.oracle.graal.java.*; +import com.oracle.graal.java.GraphBuilderPlugin.LoadFieldPlugin; +import com.oracle.graal.java.GraphBuilderPlugin.ParameterPlugin; import com.oracle.graal.loop.*; import com.oracle.graal.nodes.CallTargetNode.InvokeKind; import com.oracle.graal.nodes.*; @@ -98,7 +100,7 @@ } } - public StructuredGraph createGraph(final OptimizedCallTarget callTarget, AllowAssumptions allowAssumptions, GraphBuilderPlugins graalPlugins) { + public StructuredGraph createGraph(final OptimizedCallTarget callTarget, AllowAssumptions allowAssumptions) { if (TraceTruffleCompilationHistogram.getValue() || TraceTruffleCompilationDetails.getValue()) { constantReceivers = new HashSet<>(); } @@ -122,7 +124,7 @@ HighTierContext tierContext = new HighTierContext(providers, graphCache, new PhaseSuite(), OptimisticOptimizations.NONE); if (TruffleCompilerOptions.FastPE.getValue()) { - fastPartialEvaluation(callTarget, graph, baseContext, tierContext, graalPlugins); + fastPartialEvaluation(callTarget, graph, baseContext, tierContext); } else { createRootGraph(graph); partialEvaluation(callTarget, graph, baseContext, tierContext); @@ -145,7 +147,7 @@ return graph; } - private class InterceptLoadFieldPlugin implements GraphBuilderPlugins.LoadFieldPlugin { + private class InterceptLoadFieldPlugin implements LoadFieldPlugin { public boolean apply(GraphBuilderContext builder, ValueNode receiver, ResolvedJavaField field) { if (receiver.isConstant()) { @@ -175,7 +177,7 @@ } } - private class InterceptReceiverPlugin implements GraphBuilderPlugins.ParameterPlugin { + private class InterceptReceiverPlugin implements ParameterPlugin { private final Object receiver; @@ -191,7 +193,7 @@ } } - private class InlineInvokePlugin implements GraphBuilderPlugins.InlineInvokePlugin { + private class InlineInvokePlugin implements GraphBuilderPlugin.InlineInvokePlugin { private Stack inlining; private OptimizedDirectCallNode lastDirectCallNode; @@ -201,7 +203,10 @@ this.inlining.push(inlining); } - public ResolvedJavaMethod inlinedMethod(GraphBuilderContext builder, ResolvedJavaMethod original, ValueNode[] arguments) { + public ResolvedJavaMethod getInlinedMethod(GraphBuilderContext builder, ResolvedJavaMethod original, ValueNode[] arguments, JavaType returnType, int depth) { + if (original.getAnnotation(TruffleBoundary.class) != null) { + return null; + } if (original.equals(callSiteProxyMethod)) { ValueNode arg1 = arguments[0]; if (!arg1.isConstant()) { @@ -225,19 +230,14 @@ return original; } - public boolean shouldInlineInvoke(ResolvedJavaMethod method, int depth) { - return method.getAnnotation(TruffleBoundary.class) == null; - } - public void postInline(ResolvedJavaMethod inlinedTargetMethod) { if (inlinedTargetMethod.equals(callInlinedMethod)) { inlining.pop(); } } - } - private class LoopExplosionPlugin implements GraphBuilderPlugins.LoopExplosionPlugin { + private class LoopExplosionPlugin implements GraphBuilderPlugin.LoopExplosionPlugin { public boolean shouldExplodeLoops(ResolvedJavaMethod method) { return method.getAnnotation(ExplodeLoop.class) != null; @@ -246,18 +246,18 @@ } @SuppressWarnings("unused") - private void fastPartialEvaluation(OptimizedCallTarget callTarget, StructuredGraph graph, PhaseContext baseContext, HighTierContext tierContext, GraphBuilderPlugins graalPlugins) { + private void fastPartialEvaluation(OptimizedCallTarget callTarget, StructuredGraph graph, PhaseContext baseContext, HighTierContext tierContext) { GraphBuilderConfiguration newConfig = configForRoot.copy(); + newConfig.getInvocationPlugins().setDefaults(configForRoot.getInvocationPlugins()); newConfig.setLoadFieldPlugin(new InterceptLoadFieldPlugin()); newConfig.setParameterPlugin(new InterceptReceiverPlugin(callTarget)); callTarget.setInlining(new TruffleInlining(callTarget, new DefaultInliningPolicy())); newConfig.setInlineInvokePlugin(new InlineInvokePlugin(callTarget.getInlining())); newConfig.setLoopExplosionPlugin(new LoopExplosionPlugin()); - DefaultGraphBuilderPlugins plugins = graalPlugins == null ? new DefaultGraphBuilderPlugins() : graalPlugins.copy(); - TruffleGraphBuilderPlugins.registerPlugins(providers.getMetaAccess(), plugins); + TruffleGraphBuilderPlugins.registerPlugins(providers.getMetaAccess(), newConfig.getInvocationPlugins()); long ms = System.currentTimeMillis(); new GraphBuilderPhase.Instance(providers.getMetaAccess(), providers.getStampProvider(), this.snippetReflection, providers.getReplacements(), providers.getConstantReflection(), newConfig, - plugins, TruffleCompilerImpl.Optimizations).apply(graph); + TruffleCompilerImpl.Optimizations).apply(graph); System.out.println("# ms: " + (System.currentTimeMillis() - ms)); Debug.dump(graph, "After FastPE"); @@ -265,6 +265,11 @@ Class macroSubstitution = providers.getReplacements().getMacroSubstitution(methodCallTargetNode.targetMethod()); if (macroSubstitution != null) { InliningUtil.inlineMacroNode(methodCallTargetNode.invoke(), methodCallTargetNode.targetMethod(), macroSubstitution); + } else { + StructuredGraph inlineGraph = providers.getReplacements().getMethodSubstitution(methodCallTargetNode.targetMethod()); + if (inlineGraph != null) { + InliningUtil.inline(methodCallTargetNode.invoke(), inlineGraph, true, null); + } } } diff -r 7e2c87dae93e -r 95258dae67ef graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleCompilerImpl.java --- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleCompilerImpl.java Mon Feb 16 15:43:03 2015 +0100 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleCompilerImpl.java Mon Feb 16 15:43:22 2015 +0100 @@ -120,10 +120,10 @@ compilationNotify.notifyCompilationStarted(compilable); try { - GraphBuilderSuiteInfo info = createGraphBuilderSuite(); + PhaseSuite graphBuilderSuite = createGraphBuilderSuite(); try (TimerCloseable a = PartialEvaluationTime.start(); Closeable c = PartialEvaluationMemUse.start()) { - graph = partialEvaluator.createGraph(compilable, AllowAssumptions.YES, info.plugins); + graph = partialEvaluator.createGraph(compilable, AllowAssumptions.YES); } if (Thread.currentThread().isInterrupted()) { @@ -138,7 +138,7 @@ } compilationNotify.notifyCompilationTruffleTierFinished(compilable, graph); - CompilationResult compilationResult = compileMethodHelper(graph, compilable.toString(), info.suite, compilable.getSpeculationLog(), compilable); + CompilationResult compilationResult = compileMethodHelper(graph, compilable.toString(), graphBuilderSuite, compilable.getSpeculationLog(), compilable); compilationNotify.notifyCompilationSuccess(compilable, graph, compilationResult); } catch (Throwable t) { compilationNotify.notifyCompilationFailed(compilable, graph, t); @@ -158,8 +158,8 @@ CodeCacheProvider codeCache = providers.getCodeCache(); CallingConvention cc = getCallingConvention(codeCache, Type.JavaCallee, graph.method(), false); CompilationResult compilationResult = new CompilationResult(name); - result = compileGraph(graph, cc, graph.method(), providers, backend, codeCache.getTarget(), null, graphBuilderSuite == null ? createGraphBuilderSuite().suite : graphBuilderSuite, - Optimizations, getProfilingInfo(graph), speculationLog, suites, lirSuites, compilationResult, CompilationResultBuilderFactory.Default); + result = compileGraph(graph, cc, graph.method(), providers, backend, codeCache.getTarget(), null, graphBuilderSuite, Optimizations, getProfilingInfo(graph), speculationLog, suites, + lirSuites, compilationResult, CompilationResultBuilderFactory.Default); } catch (Throwable e) { throw Debug.handle(e); } @@ -205,22 +205,20 @@ static class GraphBuilderSuiteInfo { final PhaseSuite suite; - final GraphBuilderPlugins plugins; + final InvocationPlugins plugins; - public GraphBuilderSuiteInfo(PhaseSuite suite, GraphBuilderPlugins plugins) { + public GraphBuilderSuiteInfo(PhaseSuite suite, InvocationPlugins plugins) { this.suite = suite; this.plugins = plugins; } } - private GraphBuilderSuiteInfo createGraphBuilderSuite() { + private PhaseSuite createGraphBuilderSuite() { PhaseSuite suite = backend.getSuites().getDefaultGraphBuilderSuite().copy(); ListIterator> iterator = suite.findPhase(GraphBuilderPhase.class); - GraphBuilderPhase graphBuilderPhase = (GraphBuilderPhase) iterator.previous(); iterator.remove(); - GraphBuilderPlugins plugins = graphBuilderPhase.getGraphBuilderPlugins(); - iterator.add(new GraphBuilderPhase(config, plugins)); - return new GraphBuilderSuiteInfo(suite, plugins); + iterator.add(new GraphBuilderPhase(config)); + return suite; } public void processAssumption(Set newAssumptions, Assumption assumption, List manual) { @@ -237,8 +235,4 @@ public PartialEvaluator getPartialEvaluator() { return partialEvaluator; } - - public GraphBuilderPlugins createGraphBuilderSuitePlugins() { - return this.createGraphBuilderSuite().plugins; - } } diff -r 7e2c87dae93e -r 95258dae67ef 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 Mon Feb 16 15:43:03 2015 +0100 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/substitutions/TruffleGraphBuilderPlugins.java Mon Feb 16 15:43:22 2015 +0100 @@ -32,9 +32,9 @@ import com.oracle.graal.compiler.common.calc.*; import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.java.*; -import com.oracle.graal.java.GraphBuilderPlugins.InvocationPlugin; -import com.oracle.graal.java.GraphBuilderPlugins.Registration; -import com.oracle.graal.java.GraphBuilderPlugins.Registration.Receiver; +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.calc.*; import com.oracle.graal.nodes.extended.*; @@ -50,7 +50,7 @@ * Provider of {@link GraphBuilderPlugin}s for Truffle classes. */ public class TruffleGraphBuilderPlugins { - public static void registerPlugins(MetaAccessProvider metaAccess, GraphBuilderPlugins plugins) { + public static void registerPlugins(MetaAccessProvider metaAccess, InvocationPlugins plugins) { // OptimizedAssumption.class Registration r = new Registration(plugins, metaAccess, OptimizedAssumption.class); @@ -78,6 +78,36 @@ return true; } }); + r.register2("addExact", Long.TYPE, Long.TYPE, new InvocationPlugin() { + public boolean apply(GraphBuilderContext builder, ValueNode x, ValueNode y) { + builder.push(Kind.Long, builder.append(new IntegerAddExactNode(x, y))); + return true; + } + }); + r.register2("subtractExact", Integer.TYPE, Integer.TYPE, new InvocationPlugin() { + public boolean apply(GraphBuilderContext builder, ValueNode x, ValueNode y) { + builder.push(Kind.Int.getStackKind(), builder.append(new IntegerSubExactNode(x, y))); + return true; + } + }); + r.register2("subtractExact", Long.TYPE, Long.TYPE, new InvocationPlugin() { + public boolean apply(GraphBuilderContext builder, ValueNode x, ValueNode y) { + builder.push(Kind.Long, builder.append(new IntegerSubExactNode(x, y))); + return true; + } + }); + r.register2("multiplyExact", Integer.TYPE, Integer.TYPE, new InvocationPlugin() { + public boolean apply(GraphBuilderContext builder, ValueNode x, ValueNode y) { + builder.push(Kind.Int.getStackKind(), builder.append(new IntegerMulExactNode(x, y))); + return true; + } + }); + r.register2("multiplyExact", Long.TYPE, Long.TYPE, new InvocationPlugin() { + public boolean apply(GraphBuilderContext builder, ValueNode x, ValueNode y) { + builder.push(Kind.Long, builder.append(new IntegerMulExactNode(x, y))); + return true; + } + }); // CompilerDirectives.class r = new Registration(plugins, metaAccess, CompilerDirectives.class); diff -r 7e2c87dae93e -r 95258dae67ef src/share/tools/IdealGraphVisualizer/View/src/com/sun/hotspot/igv/view/layer.xml --- a/src/share/tools/IdealGraphVisualizer/View/src/com/sun/hotspot/igv/view/layer.xml Mon Feb 16 15:43:03 2015 +0100 +++ b/src/share/tools/IdealGraphVisualizer/View/src/com/sun/hotspot/igv/view/layer.xml Mon Feb 16 15:43:22 2015 +0100 @@ -67,7 +67,7 @@ - + @@ -77,4 +77,12 @@ + + + + + + + + diff -r 7e2c87dae93e -r 95258dae67ef src/share/tools/IdealGraphVisualizer/View/src/com/sun/hotspot/igv/view/propertiesWsmode.xml --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/tools/IdealGraphVisualizer/View/src/com/sun/hotspot/igv/view/propertiesWsmode.xml Mon Feb 16 15:43:22 2015 +0100 @@ -0,0 +1,18 @@ + + + + + + + + + + + + + + + + diff -r 7e2c87dae93e -r 95258dae67ef src/share/tools/IdealGraphVisualizer/View/src/com/sun/hotspot/igv/view/propertiesWstcref.xml --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/tools/IdealGraphVisualizer/View/src/com/sun/hotspot/igv/view/propertiesWstcref.xml Mon Feb 16 15:43:22 2015 +0100 @@ -0,0 +1,11 @@ + + + + + + + + +