Mercurial > hg > graal-compiler
changeset 22457:dfa24d13486e
Drop use of MethodIdMap in InvocationPlugins
author | Tom Rodriguez <tom.rodriguez@oracle.com> |
---|---|
date | Thu, 13 Aug 2015 11:00:54 -0700 |
parents | 122c9802bcaa |
children | c833c866c5c3 |
files | graal/com.oracle.graal.graphbuilderconf/src/com/oracle/graal/graphbuilderconf/InvocationPlugin.java graal/com.oracle.graal.graphbuilderconf/src/com/oracle/graal/graphbuilderconf/InvocationPlugins.java |
diffstat | 2 files changed, 182 insertions(+), 25 deletions(-) [+] |
line wrap: on
line diff
--- a/graal/com.oracle.graal.graphbuilderconf/src/com/oracle/graal/graphbuilderconf/InvocationPlugin.java Thu Aug 13 13:34:30 2015 +0200 +++ b/graal/com.oracle.graal.graphbuilderconf/src/com/oracle/graal/graphbuilderconf/InvocationPlugin.java Thu Aug 13 11:00:54 2015 -0700 @@ -38,8 +38,8 @@ /** * The receiver in a non-static method. The class literal for this interface must be used with - * {@link MethodIdMap#put(Object, boolean, boolean, Class, String, Class...)} to denote the - * receiver argument for such a non-static method. + * {@link InvocationPlugins#put(InvocationPlugin, boolean, boolean, Class, String, Class...)} to + * denote the receiver argument for such a non-static method. */ public interface Receiver { /**
--- a/graal/com.oracle.graal.graphbuilderconf/src/com/oracle/graal/graphbuilderconf/InvocationPlugins.java Thu Aug 13 13:34:30 2015 +0200 +++ b/graal/com.oracle.graal.graphbuilderconf/src/com/oracle/graal/graphbuilderconf/InvocationPlugins.java Thu Aug 13 11:00:54 2015 -0700 @@ -26,11 +26,11 @@ import java.lang.reflect.*; import java.util.*; +import java.util.stream.*; import jdk.internal.jvmci.meta.*; -import jdk.internal.jvmci.meta.MethodIdMap.*; -import com.oracle.graal.graph.*; +import com.oracle.graal.graph.Node; import com.oracle.graal.graph.iterators.*; import com.oracle.graal.nodes.*; @@ -194,7 +194,173 @@ } } - protected final MethodIdMap<InvocationPlugin> plugins; + /** + * Key for a method. + */ + static class MethodKey { + final boolean isStatic; + + /** + * This method is optional. This is used for new API methods not present in previous JDK + * versions. + */ + final boolean isOptional; + + final Class<?> declaringClass; + final String name; + final Class<?>[] argumentTypes; + final InvocationPlugin value; + + MethodKey(InvocationPlugin data, boolean isStatic, boolean isOptional, Class<?> declaringClass, String name, Class<?>... argumentTypes) { + assert isStatic || argumentTypes[0] == declaringClass; + this.value = data; + this.isStatic = isStatic; + this.isOptional = isOptional; + this.declaringClass = declaringClass; + this.name = name; + this.argumentTypes = argumentTypes; + assert isOptional || resolveJava() != null; + } + + @Override + public boolean equals(Object obj) { + if (obj instanceof MethodKey) { + MethodKey that = (MethodKey) obj; + 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; + } + return false; + } + + public int getDeclaredParameterCount() { + return isStatic ? argumentTypes.length : argumentTypes.length - 1; + } + + @Override + public int hashCode() { + // Replay compilation mandates use of stable hash codes + return declaringClass.getName().hashCode() ^ name.hashCode(); + } + + private ResolvedJavaMethod resolve(MetaAccessProvider metaAccess) { + Executable method = resolveJava(); + if (method == null) { + return null; + } + return metaAccess.lookupJavaMethod(method); + } + + private Executable resolveJava() { + try { + Executable res; + Class<?>[] parameterTypes = isStatic ? argumentTypes : Arrays.copyOfRange(argumentTypes, 1, argumentTypes.length); + if (name.equals("<init>")) { + res = declaringClass.getDeclaredConstructor(parameterTypes); + } else { + res = declaringClass.getDeclaredMethod(name, parameterTypes); + } + assert Modifier.isStatic(res.getModifiers()) == isStatic; + return res; + } catch (NoSuchMethodException | SecurityException e) { + if (isOptional) { + return null; + } + throw new InternalError(e); + } + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(declaringClass.getName()).append('.').append(name).append('('); + for (Class<?> p : argumentTypes) { + if (sb.charAt(sb.length() - 1) != '(') { + sb.append(", "); + } + sb.append(p.getSimpleName()); + } + return sb.append(')').toString(); + } + } + + private final MetaAccessProvider metaAccess; + + /** + * Initial list of entries. + */ + private final List<MethodKey> registrations = new ArrayList<>(INITIAL_CAPACITY); + + /** + * Entry map that is initialized upon first call to {@link #get(ResolvedJavaMethod)}. + * + * Note: this must be volatile since double-checked locking is used to initialize it + */ + private volatile Map<ResolvedJavaMethod, InvocationPlugin> entries; + + private static final int INITIAL_CAPACITY = 64; + + /** + * Adds an entry to this map for a specified method. + * + * @param value value to be associated with the specified method + * @param isStatic specifies if the method is static + * @param isOptional specifies if the method is optional + * @param declaringClass the class declaring the method + * @param name the name of the method + * @param argumentTypes the argument types of the method. Element 0 of this array must be + * {@code declaringClass} iff the method is non-static. + * @return an object representing the method + */ + MethodKey put(InvocationPlugin value, boolean isStatic, boolean isOptional, Class<?> declaringClass, String name, Class<?>... argumentTypes) { + assert isStatic || argumentTypes[0] == declaringClass; + MethodKey methodKey = new MethodKey(value, isStatic, isOptional, declaringClass, name, argumentTypes); + assert entries == null : "registration is closed"; + assert !registrations.contains(methodKey) : "a value is already registered for " + methodKey; + registrations.add(methodKey); + return methodKey; + } + + /** + * Determines if a method denoted by a given {@link MethodKey} is in this map. + */ + boolean containsKey(MethodKey key) { + return registrations.contains(key); + } + + InvocationPlugin get(ResolvedJavaMethod method) { + if (entries == null) { + initializeMap(); + } + + return entries.get(method); + } + + /** + * Disallows new registrations of new plugins, and creates the internal tables for method + * lookup. + */ + public void closeRegistration() { + if (entries == null) { + initializeMap(); + } + } + + void initializeMap() { + if (registrations.isEmpty()) { + entries = Collections.emptyMap(); + } else { + Map<ResolvedJavaMethod, InvocationPlugin> newEntries = new HashMap<>(); + for (MethodKey methodKey : registrations) { + ResolvedJavaMethod m = methodKey.resolve(metaAccess); + newEntries.put(m, methodKey.value); + } + entries = newEntries; + } + } + + public int size() { + return registrations.size(); + } /** * The plugins {@linkplain #lookupInvocation(ResolvedJavaMethod) searched} before searching in @@ -203,7 +369,7 @@ protected final InvocationPlugins parent; private InvocationPlugins(InvocationPlugins parent, MetaAccessProvider metaAccess) { - this.plugins = new MethodIdMap<>(metaAccess); + this.metaAccess = metaAccess; InvocationPlugins p = parent; // Only adopt a non-empty parent while (p != null && p.size() == 0) { @@ -216,7 +382,11 @@ * Creates a set of invocation plugins with a non-null {@linkplain #getParent() parent}. */ public InvocationPlugins(InvocationPlugins parent) { - this(parent, parent.plugins.getMetaAccess()); + this(parent, parent.getMetaAccess()); + } + + public MetaAccessProvider getMetaAccess() { + return metaAccess; } public InvocationPlugins(MetaAccessProvider metaAccess) { @@ -228,7 +398,7 @@ if (!isStatic) { argumentTypes[0] = declaringClass; } - MethodKey<InvocationPlugin> methodInfo = plugins.put(plugin, isStatic, isOptional, declaringClass, name, argumentTypes); + MethodKey methodInfo = put(plugin, isStatic, isOptional, declaringClass, name, argumentTypes); assert Checker.check(this, methodInfo, plugin); } @@ -265,22 +435,13 @@ * @return the plugin associated with {@code method} or {@code null} if none exists */ public InvocationPlugin lookupInvocation(ResolvedJavaMethod method) { - assert method instanceof MethodIdHolder; if (parent != null) { InvocationPlugin plugin = parent.lookupInvocation(method); if (plugin != null) { return plugin; } } - return plugins.get((MethodIdHolder) method); - } - - /** - * Disallows new registrations of new plugins, and creates the internal tables for method - * lookup. - */ - public void closeRegistration() { - plugins.createEntries(); + return get(method); } /** @@ -293,7 +454,7 @@ @Override public String toString() { - return plugins + " / parent: " + this.parent; + return registrations.stream().map(MethodKey::toString).collect(Collectors.joining(", ")) + " / parent: " + this.parent; } private static class Checker { @@ -323,10 +484,10 @@ SIGS = sigs.toArray(new Class<?>[sigs.size()][]); } - public static boolean check(InvocationPlugins plugins, MethodKey<InvocationPlugin> method, InvocationPlugin plugin) { + public static boolean check(InvocationPlugins plugins, MethodKey method, InvocationPlugin plugin) { InvocationPlugins p = plugins.parent; while (p != null) { - assert !p.plugins.containsKey(method) : "a plugin is already registered for " + method; + assert !p.containsKey(method) : "a plugin is already registered for " + method; p = p.parent; } if (plugin instanceof ForeignCallPlugin) { @@ -351,10 +512,6 @@ } } - public int size() { - return plugins.size(); - } - /** * Checks a set of nodes added to the graph by an {@link InvocationPlugin}. *