# HG changeset patch # User Doug Simon # Date 1426590349 -3600 # Node ID b950967f74c7a1f886089698b4e5056dbe69d9ff # Parent 87736c089259dadfb8c95a261b27b3c7e65466e4 replaced HashMap with a side-table (i.e., an array) for looking up InvocationPlugins diff -r 87736c089259 -r b950967f74c7 graal/com.oracle.graal.graphbuilderconf/src/com/oracle/graal/graphbuilderconf/GraphBuilderConfiguration.java --- a/graal/com.oracle.graal.graphbuilderconf/src/com/oracle/graal/graphbuilderconf/GraphBuilderConfiguration.java Sun Mar 15 11:48:14 2015 +0100 +++ b/graal/com.oracle.graal.graphbuilderconf/src/com/oracle/graal/graphbuilderconf/GraphBuilderConfiguration.java Tue Mar 17 12:05:49 2015 +0100 @@ -41,7 +41,7 @@ /** * Creates a copy of a given set of plugins. The {@link InvocationPlugins} in - * {@code copyFrom} become the {@linkplain InvocationPlugins#getDefaults() default} + * {@code copyFrom} become the {@linkplain InvocationPlugins#getParent() default} * {@linkplain #getInvocationPlugins() invocation plugins} in this object. */ public Plugins(Plugins copyFrom) { @@ -164,7 +164,7 @@ /** * Creates a copy of this configuration with all its plugins. The {@link InvocationPlugins} in - * this configuration become the {@linkplain InvocationPlugins#getDefaults defaults} of the + * this configuration become the {@linkplain InvocationPlugins#getParent() parent} of the * {@link InvocationPlugins} in the copy. */ public GraphBuilderConfiguration copy() { diff -r 87736c089259 -r b950967f74c7 graal/com.oracle.graal.graphbuilderconf/src/com/oracle/graal/graphbuilderconf/InvocationPlugin.java --- a/graal/com.oracle.graal.graphbuilderconf/src/com/oracle/graal/graphbuilderconf/InvocationPlugin.java Sun Mar 15 11:48:14 2015 +0100 +++ b/graal/com.oracle.graal.graphbuilderconf/src/com/oracle/graal/graphbuilderconf/InvocationPlugin.java Tue Mar 17 12:05:49 2015 +0100 @@ -32,6 +32,7 @@ * Plugin for handling a specific method invocation. */ public interface InvocationPlugin extends GraphBuilderPlugin { + /** * @see #execute */ diff -r 87736c089259 -r b950967f74c7 graal/com.oracle.graal.graphbuilderconf/src/com/oracle/graal/graphbuilderconf/InvocationPluginIdHolder.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.graphbuilderconf/src/com/oracle/graal/graphbuilderconf/InvocationPluginIdHolder.java Tue Mar 17 12:05:49 2015 +0100 @@ -0,0 +1,42 @@ +/* + * 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.graphbuilderconf; + +import com.oracle.graal.api.meta.*; + +/** + * {@link ResolvedJavaMethod}s that can assign themselves an identifier for use in a side table + * mapping methods to {@link InvocationPlugin}s. + */ +public interface InvocationPluginIdHolder extends ResolvedJavaMethod { + /** + * Sets the unique, positive, non-zero identifier for this method. + */ + void setInvocationPluginId(int id); + + /** + * Gets the identifier set by {@link #setInvocationPluginId(int)} or 0 if no + * {@link InvocationPlugin} identifier was assigned to this method. + */ + int getInvocationPluginId(); +} diff -r 87736c089259 -r b950967f74c7 graal/com.oracle.graal.graphbuilderconf/src/com/oracle/graal/graphbuilderconf/InvocationPlugins.java --- a/graal/com.oracle.graal.graphbuilderconf/src/com/oracle/graal/graphbuilderconf/InvocationPlugins.java Sun Mar 15 11:48:14 2015 +0100 +++ b/graal/com.oracle.graal.graphbuilderconf/src/com/oracle/graal/graphbuilderconf/InvocationPlugins.java Tue Mar 17 12:05:49 2015 +0100 @@ -132,24 +132,31 @@ } } - public static final class MethodInfo { - public final boolean isStatic; - public final Class declaringClass; - public final String name; - public final Class[] argumentTypes; + static final class MethodInfo { + final boolean isStatic; + final Class declaringClass; + final String name; + final Class[] argumentTypes; + final InvocationPlugin plugin; - public MethodInfo(Class declaringClass, String name, Class... argumentTypes) { + int id; + + MethodInfo(InvocationPlugin plugin, Class declaringClass, String name, Class... argumentTypes) { + this.plugin = plugin; this.isStatic = argumentTypes.length == 0 || argumentTypes[0] != Receiver.class; this.declaringClass = declaringClass; this.name = name; this.argumentTypes = argumentTypes; + if (!isStatic) { + argumentTypes[0] = declaringClass; + } } @Override public boolean equals(Object obj) { if (obj instanceof MethodInfo) { MethodInfo that = (MethodInfo) obj; - boolean res = this.declaringClass == that.declaringClass && this.name.equals(that.name) && Arrays.equals(this.argumentTypes, that.argumentTypes); + boolean res = this.name.equals(that.name) && this.declaringClass.equals(that.declaringClass) && Arrays.equals(this.argumentTypes, that.argumentTypes); assert !res || this.isStatic == that.isStatic; return res; } @@ -162,17 +169,17 @@ return declaringClass.getName().hashCode() ^ name.hashCode(); } - public ResolvedJavaMethod resolve(MetaAccessProvider metaAccess) { + ResolvedJavaMethod resolve(MetaAccessProvider metaAccess) { try { + ResolvedJavaMethod method; Class[] parameterTypes = isStatic ? argumentTypes : Arrays.copyOfRange(argumentTypes, 1, argumentTypes.length); - ResolvedJavaMethod resolved; if (name.equals("")) { - resolved = metaAccess.lookupJavaMethod(declaringClass.getDeclaredConstructor(parameterTypes)); + method = metaAccess.lookupJavaMethod(declaringClass.getDeclaredConstructor(parameterTypes)); } else { - resolved = metaAccess.lookupJavaMethod(declaringClass.getDeclaredMethod(name, parameterTypes)); + method = metaAccess.lookupJavaMethod(declaringClass.getDeclaredMethod(name, parameterTypes)); } - assert resolved.isStatic() == isStatic; - return resolved; + assert method.isStatic() == isStatic; + return method; } catch (NoSuchMethodException | SecurityException e) { throw new GraalInternalError(e); } @@ -192,45 +199,54 @@ } protected final MetaAccessProvider metaAccess; - - private final Map registrations; - + private final List registrations; private final Thread registrationThread; /** - * Null while registration is open, non-null when registration is closed. + * The minimum {@linkplain InvocationPluginIdHolder#getInvocationPluginId() id} for a method + * associated with a plugin in {@link #plugins}. */ - private volatile Map plugins; + private int minId = Integer.MAX_VALUE; /** - * The invocation plugins deferred to if a plugin is not found in this object. + * Resolved methods to plugins map. The keys (i.e., indexes) are derived from + * {@link InvocationPluginIdHolder#getInvocationPluginId()}. */ - private InvocationPlugins defaults; + private volatile InvocationPlugin[] plugins; /** - * Creates a set of invocation plugins with a given non-null set of plugins as the - * {@linkplain #getDefaults defaults}. + * The plugins {@linkplain #lookupInvocation(ResolvedJavaMethod) searched} before searching in + * this object. */ - public InvocationPlugins(InvocationPlugins defaults) { + private InvocationPlugins parent; + + private InvocationPlugins(InvocationPlugins parent, MetaAccessProvider metaAccess, int estimatePluginCount) { this.registrationThread = Thread.currentThread(); - this.metaAccess = defaults.getMetaAccess(); - this.registrations = new HashMap<>(); - InvocationPlugins defs = defaults; - // Only adopt non-empty defaults - while (defs != null && defs.size() == 0) { - defs = defs.defaults; + this.metaAccess = metaAccess; + this.registrations = new ArrayList<>(estimatePluginCount); + InvocationPlugins p = parent; + // Only adopt a non-empty parent + while (p != null && p.size() == 0) { + p = p.parent; } - this.defaults = defs; + this.parent = p; + } + + private static final int DEFAULT_ESTIMATE_PLUGIN_COUNT = 16; + + /** + * Creates a set of invocation plugins with a non-null {@linkplain #getParent() parent}. + */ + public InvocationPlugins(InvocationPlugins parent) { + this(parent, parent.metaAccess, DEFAULT_ESTIMATE_PLUGIN_COUNT); } public InvocationPlugins(MetaAccessProvider metaAccess) { - this(metaAccess, 16); + this(metaAccess, DEFAULT_ESTIMATE_PLUGIN_COUNT); } public InvocationPlugins(MetaAccessProvider metaAccess, int estimatePluginCount) { - this.metaAccess = metaAccess; - this.registrations = new HashMap<>(estimatePluginCount); - this.registrationThread = Thread.currentThread(); + this(null, metaAccess, estimatePluginCount); } /** @@ -239,13 +255,14 @@ */ public void register(InvocationPlugin plugin, Class declaringClass, String name, Class... argumentTypes) { assert Thread.currentThread() == registrationThread : "invocation plugin registration must be single threaded"; - MethodInfo method = new MethodInfo(declaringClass, name, argumentTypes); - assert Checker.check(method, plugin); + MethodInfo methodInfo = new MethodInfo(plugin, declaringClass, name, argumentTypes); + assert Checker.check(this, methodInfo, plugin); assert plugins == null : "invocation plugin registration is closed"; - GraphBuilderPlugin oldValue = registrations.put(method, plugin); - assert oldValue == null : "a plugin is already registered for " + method; + registrations.add(methodInfo); } + private static int nextInvocationPluginId = 1; + /** * Gets the plugin for a given method. * @@ -253,40 +270,67 @@ * @return the plugin associated with {@code method} or {@code null} if none exists */ public InvocationPlugin lookupInvocation(ResolvedJavaMethod method) { - InvocationPlugin res = null; + assert method instanceof InvocationPluginIdHolder; + if (parent != null) { + InvocationPlugin plugin = parent.lookupInvocation(method); + if (plugin != null) { + return plugin; + } + } + InvocationPluginIdHolder pluggable = (InvocationPluginIdHolder) method; if (plugins == null) { - synchronized (this) { + // Must synchronize across all InvocationPlugins objects to ensure thread safe + // allocation of InvocationPlugin identifiers + synchronized (InvocationPlugins.class) { if (plugins == null) { if (registrations.isEmpty()) { - plugins = Collections.emptyMap(); + plugins = new InvocationPlugin[0]; } else { - // System.out.println("resolving " + registrations.size() + " plugins"); - plugins = new HashMap<>(registrations.size()); - for (Map.Entry e : registrations.entrySet()) { - plugins.put(e.getKey().resolve(metaAccess), e.getValue()); + int max = Integer.MIN_VALUE; + for (MethodInfo methodInfo : registrations) { + InvocationPluginIdHolder p = (InvocationPluginIdHolder) methodInfo.resolve(metaAccess); + int id = p.getInvocationPluginId(); + if (id == 0) { + id = nextInvocationPluginId++; + p.setInvocationPluginId(id); + } + if (id < minId) { + minId = id; + } + if (id > max) { + max = id; + + } + methodInfo.id = id; + } + + int length = (max - minId) + 1; + plugins = new InvocationPlugin[length]; + for (MethodInfo m : registrations) { + int index = m.id - minId; + plugins[index] = m.plugin; } } } } } - res = plugins.get(method); - if (res == null && defaults != null) { - return defaults.lookupInvocation(method); - } - return res; + + int id = pluggable.getInvocationPluginId(); + int index = id - minId; + return index >= 0 && index < plugins.length ? plugins[index] : null; } /** - * Gets the invocation plugins {@linkplain #lookupInvocation(ResolvedJavaMethod) searched} if a - * plugin is not found in this object. + * Gets the invocation plugins {@linkplain #lookupInvocation(ResolvedJavaMethod) searched} + * before searching in this object. */ - public InvocationPlugins getDefaults() { - return defaults; + public InvocationPlugins getParent() { + return parent; } @Override public String toString() { - return registrations.keySet().stream().map(MethodInfo::toString).collect(Collectors.joining(", ")) + " / defaults: " + this.defaults; + return registrations.stream().map(MethodInfo::toString).collect(Collectors.joining(", ")) + " / parent: " + this.parent; } private static class Checker { @@ -314,7 +358,12 @@ SIGS = sigs.toArray(new Class[sigs.size()][]); } - public static boolean check(MethodInfo method, InvocationPlugin plugin) { + public static boolean check(InvocationPlugins plugins, MethodInfo method, InvocationPlugin plugin) { + InvocationPlugins p = plugins; + while (p != null) { + assert !p.registrations.contains(method) : "a plugin is already registered for " + method; + p = p.parent; + } int arguments = method.argumentTypes.length; assert arguments < SIGS.length : format("need to extend %s to support method with %d arguments: %s", InvocationPlugin.class.getSimpleName(), arguments, method); for (Method m : plugin.getClass().getDeclaredMethods()) { diff -r 87736c089259 -r b950967f74c7 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 Sun Mar 15 11:48:14 2015 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotInlineInvokePlugin.java Tue Mar 17 12:05:49 2015 +0100 @@ -29,7 +29,7 @@ import com.oracle.graal.api.meta.*; import com.oracle.graal.graph.Node.NodeIntrinsic; import com.oracle.graal.graphbuilderconf.*; -import com.oracle.graal.graphbuilderconf.GraphBuilderContext.*; +import com.oracle.graal.graphbuilderconf.GraphBuilderContext.Replacement; import com.oracle.graal.hotspot.word.*; import com.oracle.graal.nodes.*; import com.oracle.graal.replacements.*; diff -r 87736c089259 -r b950967f74c7 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedJavaMethodImpl.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedJavaMethodImpl.java Sun Mar 15 11:48:14 2015 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedJavaMethodImpl.java Tue Mar 17 12:05:49 2015 +0100 @@ -34,6 +34,7 @@ import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; import com.oracle.graal.debug.*; +import com.oracle.graal.graphbuilderconf.*; import com.oracle.graal.hotspot.*; import com.oracle.graal.hotspot.debug.*; import com.oracle.graal.nodes.*; @@ -41,7 +42,7 @@ /** * Implementation of {@link JavaMethod} for resolved HotSpot methods. */ -public final class HotSpotResolvedJavaMethodImpl extends HotSpotMethod implements HotSpotResolvedJavaMethod, HotSpotProxified { +public final class HotSpotResolvedJavaMethodImpl extends HotSpotMethod implements HotSpotResolvedJavaMethod, HotSpotProxified, InvocationPluginIdHolder { private static final long serialVersionUID = -5486975070147586588L; @@ -740,4 +741,15 @@ } return runtime().getCompilerToVM().hasCompiledCodeForOSR(metaspaceMethod, entryBCI, level); } + + private int invocationPluginId; + + public void setInvocationPluginId(int id) { + assert invocationPluginId == 0; + invocationPluginId = id; + } + + public int getInvocationPluginId() { + return invocationPluginId; + } } diff -r 87736c089259 -r b950967f74c7 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 Sun Mar 15 11:48:14 2015 +0100 +++ b/graal/com.oracle.graal.truffle.hotspot/src/com/oracle/graal/truffle/hotspot/HotSpotTruffleRuntime.java Tue Mar 17 12:05:49 2015 +0100 @@ -40,9 +40,12 @@ import com.oracle.graal.compiler.target.*; import com.oracle.graal.debug.*; import com.oracle.graal.debug.Debug.Scope; +import com.oracle.graal.graphbuilderconf.*; +import com.oracle.graal.graphbuilderconf.GraphBuilderConfiguration.Plugins; import com.oracle.graal.hotspot.*; import com.oracle.graal.hotspot.meta.*; import com.oracle.graal.hotspot.nodes.*; +import com.oracle.graal.java.*; import com.oracle.graal.lir.asm.*; import com.oracle.graal.lir.phases.*; import com.oracle.graal.nodes.*; @@ -184,12 +187,18 @@ } private static CompilationResult compileMethod(ResolvedJavaMethod javaMethod) { - Providers providers = getGraalProviders(); - SuitesProvider suitesProvider = Graal.getRequiredCapability(RuntimeProvider.class).getHostBackend().getSuites(); + HotSpotProviders providers = getGraalProviders(); + SuitesProvider suitesProvider = providers.getSuites(); Suites suites = suitesProvider.createSuites(); LIRSuites lirSuites = suitesProvider.createLIRSuites(); removeInliningPhase(suites); StructuredGraph graph = new StructuredGraph(javaMethod, AllowAssumptions.NO); + + MetaAccessProvider metaAccess = providers.getMetaAccess(); + Plugins plugins = new Plugins(new InvocationPlugins(metaAccess)); + GraphBuilderConfiguration config = GraphBuilderConfiguration.getEagerDefault(plugins); + new GraphBuilderPhase.Instance(metaAccess, providers.getStampProvider(), providers.getConstantReflection(), config, 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(); @@ -198,9 +207,9 @@ suites, lirSuites, new CompilationResult(), factory); } - private static Providers getGraalProviders() { + private static HotSpotProviders getGraalProviders() { RuntimeProvider runtimeProvider = Graal.getRequiredCapability(RuntimeProvider.class); - return runtimeProvider.getHostBackend().getProviders(); + return (HotSpotProviders) runtimeProvider.getHostBackend().getProviders(); } private static PhaseSuite getGraphBuilderSuite(SuitesProvider suitesProvider) { diff -r 87736c089259 -r b950967f74c7 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 Sun Mar 15 11:48:14 2015 +0100 +++ b/graal/com.oracle.graal.truffle.test/src/com/oracle/graal/truffle/test/ExactMathTest.java Tue Mar 17 12:05:49 2015 +0100 @@ -34,7 +34,6 @@ @Override protected GraphBuilderConfiguration editGraphBuilderConfiguration(GraphBuilderConfiguration conf) { TruffleGraphBuilderPlugins.registerExactMathPlugins(conf.getPlugins().getInvocationPlugins()); - super.editGraphBuilderConfiguration(conf); return super.editGraphBuilderConfiguration(conf); }