# HG changeset patch # User Michael Van De Vanter # Date 1428967588 25200 # Node ID 518ce9a36939d45be7d4460c2dae2209404818b3 # Parent 0b2e4d40b683069d7f9ec0157b797d47cd5e6075# Parent f0d8a33aebd1e67d464ea8479d4777d73c146648 Merge with f0d8a33aebd1e67d464ea8479d4777d73c146648 diff -r 0b2e4d40b683 -r 518ce9a36939 graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/type/AbstractObjectStamp.java --- a/graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/type/AbstractObjectStamp.java Mon Apr 13 16:19:41 2015 -0700 +++ b/graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/type/AbstractObjectStamp.java Mon Apr 13 16:26:28 2015 -0700 @@ -98,9 +98,6 @@ if (this == otherStamp) { return this; } - if (!isCompatible(otherStamp)) { - return StampFactory.illegal(Kind.Illegal); - } AbstractObjectStamp other = (AbstractObjectStamp) otherStamp; if (isIllegal()) { return other; @@ -170,9 +167,6 @@ if (this == otherStamp) { return this; } - if (!isCompatible(otherStamp)) { - return StampFactory.illegal(Kind.Illegal); - } AbstractObjectStamp other = (AbstractObjectStamp) otherStamp; if (isIllegal()) { return this; diff -r 0b2e4d40b683 -r 518ce9a36939 graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/type/FloatStamp.java --- a/graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/type/FloatStamp.java Mon Apr 13 16:19:41 2015 -0700 +++ b/graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/type/FloatStamp.java Mon Apr 13 16:26:28 2015 -0700 @@ -176,9 +176,6 @@ if (otherStamp == this) { return this; } - if (!(otherStamp instanceof FloatStamp)) { - return StampFactory.illegal(Kind.Illegal); - } FloatStamp other = (FloatStamp) otherStamp; assert getBits() == other.getBits(); double meetUpperBound = meetBounds(upperBound, other.upperBound, Math::max); @@ -198,9 +195,6 @@ if (otherStamp == this) { return this; } - if (!(otherStamp instanceof FloatStamp)) { - return StampFactory.illegal(Kind.Illegal); - } FloatStamp other = (FloatStamp) otherStamp; assert getBits() == other.getBits(); double joinUpperBound = Math.min(upperBound, other.upperBound); diff -r 0b2e4d40b683 -r 518ce9a36939 graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/type/IllegalStamp.java --- a/graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/type/IllegalStamp.java Mon Apr 13 16:19:41 2015 -0700 +++ b/graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/type/IllegalStamp.java Mon Apr 13 16:26:28 2015 -0700 @@ -27,7 +27,9 @@ import com.oracle.graal.compiler.common.spi.*; /** - * This stamp represents the illegal type. Values with this type can not exist at run time. + * This stamp represents the type of the {@link Kind#Illegal} value in the second slot of + * {@link Kind#Long} and {@link Kind#Double} values. It can only appear in framestates or virtual + * objects. */ public final class IllegalStamp extends Stamp { @@ -56,7 +58,8 @@ @Override public Stamp constant(Constant c, MetaAccessProvider meta) { - throw GraalInternalError.shouldNotReachHere("illegal stamp has no value"); + assert ((PrimitiveConstant) c).getKind() == Kind.Illegal; + return this; } @Override @@ -66,17 +69,19 @@ @Override public Stamp meet(Stamp other) { + assert other instanceof IllegalStamp; return this; } @Override public Stamp join(Stamp other) { + assert other instanceof IllegalStamp; return this; } @Override public boolean isCompatible(Stamp stamp) { - return false; + return stamp instanceof IllegalStamp; } @Override @@ -91,6 +96,7 @@ @Override public Stamp improveWith(Stamp other) { + assert other instanceof IllegalStamp; return this; } diff -r 0b2e4d40b683 -r 518ce9a36939 graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/type/IntegerStamp.java --- a/graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/type/IntegerStamp.java Mon Apr 13 16:19:41 2015 -0700 +++ b/graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/type/IntegerStamp.java Mon Apr 13 16:26:28 2015 -0700 @@ -253,9 +253,6 @@ if (otherStamp == this) { return this; } - if (!(otherStamp instanceof IntegerStamp)) { - return StampFactory.illegal(Kind.Illegal); - } IntegerStamp other = (IntegerStamp) otherStamp; return createStamp(other, Math.max(upperBound, other.upperBound), Math.min(lowerBound, other.lowerBound), downMask & other.downMask, upMask | other.upMask); } @@ -265,9 +262,6 @@ if (otherStamp == this) { return this; } - if (!(otherStamp instanceof IntegerStamp)) { - return StampFactory.illegal(Kind.Illegal); - } IntegerStamp other = (IntegerStamp) otherStamp; long newDownMask = downMask | other.downMask; long newLowerBound = Math.max(lowerBound, other.lowerBound) | newDownMask; diff -r 0b2e4d40b683 -r 518ce9a36939 graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/type/StampFactory.java --- a/graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/type/StampFactory.java Mon Apr 13 16:19:41 2015 -0700 +++ b/graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/type/StampFactory.java Mon Apr 13 16:26:28 2015 -0700 @@ -76,10 +76,9 @@ for (Kind k : Kind.values()) { if (stampCache[k.ordinal()] != null) { illegalStampCache[k.ordinal()] = stampCache[k.ordinal()].illegal(); - } else { - illegalStampCache[k.ordinal()] = IllegalStamp.getInstance(); } } + illegalStampCache[Kind.Illegal.ordinal()] = IllegalStamp.getInstance(); } public static Stamp tautology() { @@ -122,10 +121,6 @@ return positiveInt; } - public static Stamp illegal() { - return illegal(Kind.Illegal); - } - public static Stamp illegal(Kind kind) { return illegalStampCache[kind.ordinal()]; } diff -r 0b2e4d40b683 -r 518ce9a36939 graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/type/VoidStamp.java --- a/graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/type/VoidStamp.java Mon Apr 13 16:19:41 2015 -0700 +++ b/graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/type/VoidStamp.java Mon Apr 13 16:26:28 2015 -0700 @@ -46,10 +46,8 @@ @Override public Stamp improveWith(Stamp other) { - if (other instanceof VoidStamp) { - return this; - } - return StampFactory.illegal(Kind.Illegal); + assert other instanceof VoidStamp; + return this; } @Override @@ -74,29 +72,19 @@ @Override public Stamp meet(Stamp other) { - if (other instanceof IllegalStamp) { - return other.join(this); - } - if (this == other) { - return this; - } - return StampFactory.illegal(Kind.Illegal); + assert other instanceof VoidStamp; + return this; } @Override public Stamp join(Stamp other) { - if (other instanceof IllegalStamp) { - return other.join(this); - } - if (this == other) { - return this; - } - return StampFactory.illegal(Kind.Illegal); + assert other instanceof VoidStamp; + return this; } @Override public boolean isCompatible(Stamp stamp) { - return this == stamp; + return stamp instanceof VoidStamp; } @Override diff -r 0b2e4d40b683 -r 518ce9a36939 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 Apr 13 16:19:41 2015 -0700 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/GraalCompilerTest.java Mon Apr 13 16:26:28 2015 -0700 @@ -50,7 +50,7 @@ import com.oracle.graal.graph.*; import com.oracle.graal.graphbuilderconf.*; import com.oracle.graal.graphbuilderconf.GraphBuilderConfiguration.Plugins; -import com.oracle.graal.graphbuilderconf.InvocationPlugins.Receiver; +import com.oracle.graal.graphbuilderconf.MethodIdMap.Receiver; import com.oracle.graal.java.*; import com.oracle.graal.lir.asm.*; import com.oracle.graal.lir.phases.*; diff -r 0b2e4d40b683 -r 518ce9a36939 graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/NodeLIRBuilder.java --- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/NodeLIRBuilder.java Mon Apr 13 16:19:41 2015 -0700 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/NodeLIRBuilder.java Mon Apr 13 16:26:28 2015 -0700 @@ -304,7 +304,7 @@ } protected void emitNode(ValueNode node) { - if (Debug.isLogEnabled() && node.stamp() instanceof IllegalStamp) { + if (Debug.isLogEnabled() && node.stamp().isIllegal()) { Debug.log("This node has invalid type, we are emitting dead code(?): %s", node); } if (node instanceof LIRLowerable) { diff -r 0b2e4d40b683 -r 518ce9a36939 graal/com.oracle.graal.graphbuilderconf/src/com/oracle/graal/graphbuilderconf/ForeignCallPlugin.java --- a/graal/com.oracle.graal.graphbuilderconf/src/com/oracle/graal/graphbuilderconf/ForeignCallPlugin.java Mon Apr 13 16:19:41 2015 -0700 +++ b/graal/com.oracle.graal.graphbuilderconf/src/com/oracle/graal/graphbuilderconf/ForeignCallPlugin.java Mon Apr 13 16:26:28 2015 -0700 @@ -24,7 +24,7 @@ import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; -import com.oracle.graal.graphbuilderconf.InvocationPlugins.Receiver; +import com.oracle.graal.graphbuilderconf.MethodIdMap.Receiver; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.extended.*; diff -r 0b2e4d40b683 -r 518ce9a36939 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 Mon Apr 13 16:19:41 2015 -0700 +++ b/graal/com.oracle.graal.graphbuilderconf/src/com/oracle/graal/graphbuilderconf/InvocationPlugin.java Mon Apr 13 16:26:28 2015 -0700 @@ -27,7 +27,7 @@ import com.oracle.graal.api.meta.*; import com.oracle.graal.compiler.common.*; -import com.oracle.graal.graphbuilderconf.InvocationPlugins.Receiver; +import com.oracle.graal.graphbuilderconf.MethodIdMap.Receiver; import com.oracle.graal.nodes.*; /** diff -r 0b2e4d40b683 -r 518ce9a36939 graal/com.oracle.graal.graphbuilderconf/src/com/oracle/graal/graphbuilderconf/InvocationPluginIdHolder.java --- a/graal/com.oracle.graal.graphbuilderconf/src/com/oracle/graal/graphbuilderconf/InvocationPluginIdHolder.java Mon Apr 13 16:19:41 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,42 +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.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 0b2e4d40b683 -r 518ce9a36939 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 Mon Apr 13 16:19:41 2015 -0700 +++ b/graal/com.oracle.graal.graphbuilderconf/src/com/oracle/graal/graphbuilderconf/InvocationPlugins.java Mon Apr 13 16:26:28 2015 -0700 @@ -26,43 +26,19 @@ 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.graph.Node; +import com.oracle.graal.graph.*; import com.oracle.graal.graph.iterators.*; +import com.oracle.graal.graphbuilderconf.MethodIdMap.MethodKey; +import com.oracle.graal.graphbuilderconf.MethodIdMap.Receiver; import com.oracle.graal.nodes.*; -import com.oracle.graal.nodes.type.*; /** * Manages a set of {@link InvocationPlugin}s. */ public class InvocationPlugins { - /** - * Access to the receiver in an {@link InvocationPlugin} for a non-static method. The class - * literal for this interface must be used with - * {@link InvocationPlugins#register(InvocationPlugin, Class, String, Class...)} to denote the - * receiver argument for such a non-static method. - */ - public interface Receiver { - /** - * Gets the receiver value, null checking it first if necessary. - * - * @return the receiver value with a {@linkplain StampTool#isPointerNonNull(ValueNode) - * non-null} stamp - */ - ValueNode get(); - - /** - * Determines if the receiver is constant. - */ - default boolean isConstant() { - return false; - } - } - public static class InvocationPluginReceiver implements Receiver { private final GraphBuilderContext parser; private ValueNode[] args; @@ -195,101 +171,16 @@ } } - static final class MethodInfo { - final boolean isStatic; - final Class declaringClass; - final String name; - final Class[] argumentTypes; - final InvocationPlugin plugin; - - 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; - } - assert resolveJava() != null; - } - - @Override - public boolean equals(Object obj) { - if (obj instanceof MethodInfo) { - MethodInfo that = (MethodInfo) 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; - } - - @Override - public int hashCode() { - // Replay compilation mandates use of stable hash codes - return declaringClass.getName().hashCode() ^ name.hashCode(); - } - - ResolvedJavaMethod resolve(MetaAccessProvider metaAccess) { - return metaAccess.lookupJavaMethod(resolveJava()); - } - - Executable resolveJava() { - try { - Executable res; - Class[] parameterTypes = isStatic ? argumentTypes : Arrays.copyOfRange(argumentTypes, 1, argumentTypes.length); - if (name.equals("")) { - res = declaringClass.getDeclaredConstructor(parameterTypes); - } else { - res = declaringClass.getDeclaredMethod(name, parameterTypes); - } - assert Modifier.isStatic(res.getModifiers()) == isStatic; - return res; - } catch (NoSuchMethodException | SecurityException e) { - throw new GraalInternalError(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(); - } - } - - protected final MetaAccessProvider metaAccess; - private final List registrations; - - /** - * The minimum {@linkplain InvocationPluginIdHolder#getInvocationPluginId() id} for a method - * associated with a plugin in {@link #plugins}. - */ - private int minId = Integer.MAX_VALUE; - - /** - * Resolved methods to plugins map. The keys (i.e., indexes) are derived from - * {@link InvocationPluginIdHolder#getInvocationPluginId()}. - */ - private volatile InvocationPlugin[] plugins; + protected final MethodIdMap plugins; /** * The plugins {@linkplain #lookupInvocation(ResolvedJavaMethod) searched} before searching in * this object. */ - private InvocationPlugins parent; + protected final InvocationPlugins parent; private InvocationPlugins(InvocationPlugins parent, MetaAccessProvider metaAccess) { - this.metaAccess = metaAccess; - this.registrations = new ArrayList<>(INITIAL_PLUGIN_CAPACITY); + this.plugins = new MethodIdMap<>(metaAccess); InvocationPlugins p = parent; // Only adopt a non-empty parent while (p != null && p.size() == 0) { @@ -298,13 +189,11 @@ this.parent = p; } - private static final int INITIAL_PLUGIN_CAPACITY = 64; - /** * Creates a set of invocation plugins with a non-null {@linkplain #getParent() parent}. */ public InvocationPlugins(InvocationPlugins parent) { - this(parent, parent.metaAccess); + this(parent, parent.plugins.getMetaAccess()); } public InvocationPlugins(MetaAccessProvider metaAccess) { @@ -316,14 +205,10 @@ * registered for {@code method}. */ public void register(InvocationPlugin plugin, Class declaringClass, String name, Class... argumentTypes) { - MethodInfo methodInfo = new MethodInfo(plugin, declaringClass, name, argumentTypes); + MethodKey methodInfo = plugins.put(plugin, declaringClass, name, argumentTypes); assert Checker.check(this, methodInfo, plugin); - assert plugins == null : "invocation plugin registration is closed"; - registrations.add(methodInfo); } - private static int nextInvocationPluginId = 1; - /** * Gets the plugin for a given method. * @@ -331,54 +216,14 @@ * @return the plugin associated with {@code method} or {@code null} if none exists */ public InvocationPlugin lookupInvocation(ResolvedJavaMethod method) { - assert method instanceof InvocationPluginIdHolder; + assert method instanceof MethodIdHolder; if (parent != null) { InvocationPlugin plugin = parent.lookupInvocation(method); if (plugin != null) { return plugin; } } - InvocationPluginIdHolder pluggable = (InvocationPluginIdHolder) method; - if (plugins == null) { - // Must synchronize across all InvocationPlugins objects to ensure thread safe - // allocation of InvocationPlugin identifiers - synchronized (InvocationPlugins.class) { - if (plugins == null) { - if (registrations.isEmpty()) { - plugins = new InvocationPlugin[0]; - } else { - 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; - } - } - } - } - } - - int id = pluggable.getInvocationPluginId(); - int index = id - minId; - return index >= 0 && index < plugins.length ? plugins[index] : null; + return plugins.get((MethodIdHolder) method); } /** @@ -391,7 +236,7 @@ @Override public String toString() { - return registrations.stream().map(MethodInfo::toString).collect(Collectors.joining(", ")) + " / parent: " + this.parent; + return plugins + " / parent: " + this.parent; } private static class Checker { @@ -420,10 +265,10 @@ SIGS = sigs.toArray(new Class[sigs.size()][]); } - public static boolean check(InvocationPlugins plugins, MethodInfo method, InvocationPlugin plugin) { - InvocationPlugins p = plugins; + public static boolean check(InvocationPlugins plugins, MethodKey method, InvocationPlugin plugin) { + InvocationPlugins p = plugins.parent; while (p != null) { - assert !p.registrations.contains(method) : "a plugin is already registered for " + method; + assert !p.plugins.containsKey(method) : "a plugin is already registered for " + method; p = p.parent; } if (plugin instanceof ForeignCallPlugin) { @@ -448,12 +293,8 @@ } } - public MetaAccessProvider getMetaAccess() { - return metaAccess; - } - public int size() { - return registrations.size(); + return plugins.size(); } /** diff -r 0b2e4d40b683 -r 518ce9a36939 graal/com.oracle.graal.graphbuilderconf/src/com/oracle/graal/graphbuilderconf/MethodIdHolder.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.graphbuilderconf/src/com/oracle/graal/graphbuilderconf/MethodIdHolder.java Mon Apr 13 16:26:28 2015 -0700 @@ -0,0 +1,96 @@ +/* + * 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 java.util.*; +import java.util.function.*; + +import com.oracle.graal.api.meta.*; + +/** + * {@link ResolvedJavaMethod}s that can be assigned a globally unique identifier for use as keys in + * a {@link MethodIdMap}. This should only be used where the cost of a {@link Map} with + * {@link ResolvedJavaMethod}s as keys is too high. + */ +public interface MethodIdHolder extends ResolvedJavaMethod { + /** + * Sets the unique, positive, non-zero identifier for this method. + */ + void setMethodId(int id); + + /** + * Gets the identifier set by {@link #setMethodId(int)} or 0 if no identifier was assigned to + * this method. + */ + int getMethodId(); + + /** + * A singleton class for allocating globally unique method identifiers. + */ + static final class MethodIdAllocator { + + /** + * Ensures a given method has a unique identifier. + */ + public int assignId(MethodIdHolder holder) { + assert Thread.holdsLock(instance) : "must only be called from within MethodIdHolder.allocateIds"; + int id = holder.getMethodId(); + if (id == 0) { + id = nextId++; + holder.setMethodId(id); + if (idVerifierMap != null) { + idVerifierMap.put(holder, id); + } + } else { + assert idVerifierMap.get(holder) == id; + } + return id; + } + + private int nextId = 1; + private final Map idVerifierMap; + + @SuppressWarnings("all") + private MethodIdAllocator() { + boolean assertionsEnabled = false; + assert assertionsEnabled = true; + idVerifierMap = assertionsEnabled ? new HashMap<>() : null; + } + + /** + * Singleton instance. + */ + private static final MethodIdAllocator instance = new MethodIdAllocator(); + } + + /** + * Executes some given code that ensures some set of {@link ResolvedJavaMethod}s have unique ids + * {@linkplain MethodIdHolder#setMethodId(int) assigned} to them. The + * {@link Consumer#accept(Object)} method of the given object is called under a global lock. + */ + static void assignIds(Consumer methodIdConsumer) { + synchronized (MethodIdAllocator.instance) { + methodIdConsumer.accept(MethodIdAllocator.instance); + } + } +} diff -r 0b2e4d40b683 -r 518ce9a36939 graal/com.oracle.graal.graphbuilderconf/src/com/oracle/graal/graphbuilderconf/MethodIdMap.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.graphbuilderconf/src/com/oracle/graal/graphbuilderconf/MethodIdMap.java Mon Apr 13 16:26:28 2015 -0700 @@ -0,0 +1,253 @@ +/* + * 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 java.lang.reflect.*; +import java.util.*; +import java.util.function.*; +import java.util.stream.*; + +import com.oracle.graal.api.meta.*; +import com.oracle.graal.compiler.common.*; +import com.oracle.graal.graphbuilderconf.MethodIdHolder.MethodIdAllocator; +import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.type.*; + +/** + * A map whose keys are {@link MethodIdHolder}s that doesn't require eager resolution of + * {@link ResolvedJavaMethod}s and has retrieval as fast as array indexing. The constraints on using + * such a map are: + *
    + *
  • at most one value can be added for any key
  • + *
  • no more entries can be added after the first {@linkplain #get(MethodIdHolder) retrieval}
  • + *
+ * + * @param the type of the values in the map + */ +public class MethodIdMap { + + /** + * The receiver in a non-static method. The class literal for this interface must be used with + * {@link MethodIdMap#put(Object, Class, String, Class...)} to denote the receiver argument for + * such a non-static method. + */ + public interface Receiver { + /** + * Gets the receiver value, null checking it first if necessary. + * + * @return the receiver value with a {@linkplain StampTool#isPointerNonNull(ValueNode) + * non-null} stamp + */ + ValueNode get(); + + /** + * Determines if the receiver is constant. + */ + default boolean isConstant() { + return false; + } + } + + /** + * Key for a method. + */ + public static class MethodKey { + final boolean isStatic; + final Class declaringClass; + final String name; + final Class[] argumentTypes; + final T value; + int id; + + MethodKey(T data, Class declaringClass, String name, Class... argumentTypes) { + this.value = data; + this.isStatic = argumentTypes.length == 0 || argumentTypes[0] != Receiver.class; + this.declaringClass = declaringClass; + this.name = name; + this.argumentTypes = argumentTypes; + if (!isStatic) { + argumentTypes[0] = declaringClass; + } + assert 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; + } + + @Override + public int hashCode() { + // Replay compilation mandates use of stable hash codes + return declaringClass.getName().hashCode() ^ name.hashCode(); + } + + private MethodIdHolder resolve(MetaAccessProvider metaAccess) { + return (MethodIdHolder) metaAccess.lookupJavaMethod(resolveJava()); + } + + private Executable resolveJava() { + try { + Executable res; + Class[] parameterTypes = isStatic ? argumentTypes : Arrays.copyOfRange(argumentTypes, 1, argumentTypes.length); + if (name.equals("")) { + res = declaringClass.getDeclaredConstructor(parameterTypes); + } else { + res = declaringClass.getDeclaredMethod(name, parameterTypes); + } + assert Modifier.isStatic(res.getModifiers()) == isStatic; + return res; + } catch (NoSuchMethodException | SecurityException e) { + throw new GraalInternalError(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> registrations; + + /** + * Entry array that is initialized upon first call to {@link #get(MethodIdHolder)}. + * + * Note: this must be volatile since double-checked locking is used to initialize it + */ + private volatile V[] entries; + + /** + * The minimum {@linkplain MethodIdHolder#getMethodId() id} for a key in this map. + */ + private int minId = Integer.MAX_VALUE; + + public MethodIdMap(MetaAccessProvider metaAccess) { + this.metaAccess = metaAccess; + this.registrations = new ArrayList<>(INITIAL_CAPACITY); + } + + 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 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 the + * {@link Class} value for {@link Receiver} iff the method is non-static. + * @return an object representing the method + */ + public MethodKey put(V value, Class declaringClass, String name, Class... argumentTypes) { + MethodKey methodKey = new MethodKey<>(value, 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; + } + + @SuppressWarnings("unchecked") + protected V[] allocateEntries(int length) { + return (V[]) new Object[length]; + } + + /** + * Determines if a method denoted by a given {@link MethodKey} is in this map. + */ + public boolean containsKey(MethodKey key) { + return registrations.contains(key); + } + + public V get(MethodIdHolder method) { + if (entries == null) { + // 'assignIds' synchronizes on a global lock which ensures thread safe + // allocation of identifiers across all MethodIdHolder objects + MethodIdHolder.assignIds(new Consumer() { + + public void accept(MethodIdAllocator idAllocator) { + if (entries == null) { + if (registrations.isEmpty()) { + entries = allocateEntries(0); + } else { + int max = Integer.MIN_VALUE; + for (MethodKey methodKey : registrations) { + MethodIdHolder m = methodKey.resolve(metaAccess); + int id = idAllocator.assignId(m); + if (id < minId) { + minId = id; + } + if (id > max) { + max = id; + } + methodKey.id = id; + } + + int length = (max - minId) + 1; + entries = allocateEntries(length); + for (MethodKey m : registrations) { + int index = m.id - minId; + entries[index] = m.value; + } + } + } + } + }); + } + + int id = method.getMethodId(); + int index = id - minId; + return index >= 0 && index < entries.length ? entries[index] : null; + } + + @Override + public String toString() { + return registrations.stream().map(MethodKey::toString).collect(Collectors.joining(", ")); + } + + public MetaAccessProvider getMetaAccess() { + return metaAccess; + } + + public int size() { + return registrations.size(); + } +} diff -r 0b2e4d40b683 -r 518ce9a36939 graal/com.oracle.graal.graphbuilderconf/src/com/oracle/graal/graphbuilderconf/MethodSubstitutionPlugin.java --- a/graal/com.oracle.graal.graphbuilderconf/src/com/oracle/graal/graphbuilderconf/MethodSubstitutionPlugin.java Mon Apr 13 16:19:41 2015 -0700 +++ b/graal/com.oracle.graal.graphbuilderconf/src/com/oracle/graal/graphbuilderconf/MethodSubstitutionPlugin.java Mon Apr 13 16:26:28 2015 -0700 @@ -30,7 +30,7 @@ import com.oracle.graal.api.meta.*; import com.oracle.graal.compiler.common.*; -import com.oracle.graal.graphbuilderconf.InvocationPlugins.Receiver; +import com.oracle.graal.graphbuilderconf.MethodIdMap.Receiver; import com.oracle.graal.nodes.*; /** @@ -121,8 +121,8 @@ return m; } } - throw new GraalInternalError("No method found in %s compatible with the signature (%s)", declaringClass.getName(), Arrays.asList(parameters).stream().map(c -> c.getSimpleName()).collect( - Collectors.joining(","))); + throw new GraalInternalError("No method found in %s compatible with \"%s(%s)\"", declaringClass.getName(), name, Arrays.asList(parameters).stream().map(c -> c.getSimpleName()).collect( + Collectors.joining(", "))); } /** diff -r 0b2e4d40b683 -r 518ce9a36939 graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/HotSpotCryptoSubstitutionTest.java --- a/graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/HotSpotCryptoSubstitutionTest.java Mon Apr 13 16:19:41 2015 -0700 +++ b/graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/HotSpotCryptoSubstitutionTest.java Mon Apr 13 16:26:28 2015 -0700 @@ -22,7 +22,7 @@ */ package com.oracle.graal.hotspot.test; -import static com.oracle.graal.java.AbstractBytecodeParser.IntrinsicContext.*; +import static com.oracle.graal.java.IntrinsicContext.*; import java.io.*; import java.lang.reflect.*; @@ -39,7 +39,6 @@ import com.oracle.graal.hotspot.*; import com.oracle.graal.hotspot.bridge.CompilerToVM.CodeInstallResult; import com.oracle.graal.hotspot.meta.*; -import com.oracle.graal.java.AbstractBytecodeParser.IntrinsicContext; import com.oracle.graal.java.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.StructuredGraph.*; diff -r 0b2e4d40b683 -r 518ce9a36939 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 Apr 13 16:19:41 2015 -0700 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotGraphBuilderPlugins.java Mon Apr 13 16:26:28 2015 -0700 @@ -34,8 +34,8 @@ import com.oracle.graal.api.replacements.*; import com.oracle.graal.graphbuilderconf.*; import com.oracle.graal.graphbuilderconf.GraphBuilderConfiguration.Plugins; -import com.oracle.graal.graphbuilderconf.InvocationPlugins.Receiver; import com.oracle.graal.graphbuilderconf.InvocationPlugins.Registration; +import com.oracle.graal.graphbuilderconf.MethodIdMap.Receiver; import com.oracle.graal.hotspot.*; import com.oracle.graal.hotspot.nodes.*; import com.oracle.graal.hotspot.nodes.ClassQueryNode.Query; diff -r 0b2e4d40b683 -r 518ce9a36939 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotInvocationPlugins.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotInvocationPlugins.java Mon Apr 13 16:19:41 2015 -0700 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotInvocationPlugins.java Mon Apr 13 16:26:28 2015 -0700 @@ -33,6 +33,7 @@ import com.oracle.graal.graph.*; import com.oracle.graal.graph.iterators.*; import com.oracle.graal.graphbuilderconf.*; +import com.oracle.graal.graphbuilderconf.MethodIdMap.Receiver; import com.oracle.graal.hotspot.*; import com.oracle.graal.hotspot.phases.*; import com.oracle.graal.hotspot.replacements.*; @@ -77,7 +78,7 @@ @Override public InvocationPlugin lookupInvocation(ResolvedJavaMethod method) { if (methodHandleClass == null) { - methodHandleClass = metaAccess.lookupJavaType(MethodHandle.class); + methodHandleClass = plugins.getMetaAccess().lookupJavaType(MethodHandle.class); } if (method.getDeclaringClass().equals(methodHandleClass)) { HotSpotResolvedJavaMethod hsMethod = (HotSpotResolvedJavaMethod) method; diff -r 0b2e4d40b683 -r 518ce9a36939 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 Mon Apr 13 16:19:41 2015 -0700 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedJavaMethodImpl.java Mon Apr 13 16:26:28 2015 -0700 @@ -42,7 +42,7 @@ /** * Implementation of {@link JavaMethod} for resolved HotSpot methods. */ -public final class HotSpotResolvedJavaMethodImpl extends HotSpotMethod implements HotSpotResolvedJavaMethod, HotSpotProxified, InvocationPluginIdHolder { +public final class HotSpotResolvedJavaMethodImpl extends HotSpotMethod implements HotSpotResolvedJavaMethod, HotSpotProxified, MethodIdHolder { private static final long serialVersionUID = -5486975070147586588L; @@ -742,14 +742,14 @@ return runtime().getCompilerToVM().hasCompiledCodeForOSR(metaspaceMethod, entryBCI, level); } - private int invocationPluginId; + private int methodId; - public void setInvocationPluginId(int id) { - assert invocationPluginId == 0; - invocationPluginId = id; + public void setMethodId(int id) { + assert methodId == 0; + methodId = id; } - public int getInvocationPluginId() { - return invocationPluginId; + public int getMethodId() { + return methodId; } } diff -r 0b2e4d40b683 -r 518ce9a36939 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/type/MetaspacePointerStamp.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/type/MetaspacePointerStamp.java Mon Apr 13 16:19:41 2015 -0700 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/type/MetaspacePointerStamp.java Mon Apr 13 16:26:28 2015 -0700 @@ -40,9 +40,7 @@ @Override public Stamp meet(Stamp other) { - if (!isCompatible(other)) { - return StampFactory.illegal(); - } + assert isCompatible(other); return this; } @@ -53,9 +51,7 @@ @Override public Stamp join(Stamp other) { - if (!isCompatible(other)) { - return StampFactory.illegal(); - } + assert isCompatible(other); return this; } diff -r 0b2e4d40b683 -r 518ce9a36939 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/SnippetStub.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/SnippetStub.java Mon Apr 13 16:19:41 2015 -0700 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/SnippetStub.java Mon Apr 13 16:26:28 2015 -0700 @@ -32,7 +32,6 @@ import com.oracle.graal.graphbuilderconf.GraphBuilderConfiguration.Plugins; import com.oracle.graal.hotspot.*; import com.oracle.graal.hotspot.meta.*; -import com.oracle.graal.java.AbstractBytecodeParser.ReplacementContext; import com.oracle.graal.java.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.StructuredGraph.AllowAssumptions; diff -r 0b2e4d40b683 -r 518ce9a36939 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 Apr 13 16:19:41 2015 -0700 +++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/AbstractBytecodeParser.java Mon Apr 13 16:26:28 2015 -0700 @@ -20,30 +20,24 @@ * or visit www.oracle.com if you need additional information or have any * questions. */ - package com.oracle.graal.java; import static com.oracle.graal.api.code.TypeCheckHints.*; import static com.oracle.graal.api.meta.DeoptimizationReason.*; import static com.oracle.graal.bytecode.Bytecodes.*; import static com.oracle.graal.java.AbstractBytecodeParser.Options.*; -import static com.oracle.graal.java.HIRFrameStateBuilder.*; import java.util.*; import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; -import com.oracle.graal.api.replacements.*; import com.oracle.graal.bytecode.*; import com.oracle.graal.compiler.common.*; import com.oracle.graal.compiler.common.calc.*; import com.oracle.graal.debug.*; import com.oracle.graal.graphbuilderconf.*; -import com.oracle.graal.graphbuilderconf.GraphBuilderContext.Replacement; import com.oracle.graal.java.BciBlockMapping.BciBlock; -import com.oracle.graal.java.GraphBuilderPhase.Instance.BytecodeParser; import com.oracle.graal.nodes.*; -import com.oracle.graal.nodes.java.*; import com.oracle.graal.nodes.type.*; import com.oracle.graal.options.*; import com.oracle.graal.phases.*; @@ -83,153 +77,6 @@ } /** - * Information about a substitute method being parsed in lieu of an original method. This can - * happen when a call to a {@link MethodSubstitution} is encountered or the root of compilation - * is a {@link MethodSubstitution} or a snippet. - */ - public static class ReplacementContext implements Replacement { - /** - * The method being replaced. - */ - final ResolvedJavaMethod method; - - /** - * The replacement method. - */ - final ResolvedJavaMethod replacement; - - public ReplacementContext(ResolvedJavaMethod method, ResolvedJavaMethod substitute) { - this.method = method; - this.replacement = substitute; - } - - public ResolvedJavaMethod getOriginalMethod() { - return method; - } - - public ResolvedJavaMethod getReplacementMethod() { - return replacement; - } - - public boolean isIntrinsic() { - return false; - } - - /** - * Determines if a call within the compilation scope of a replacement represents a call to - * the original method. - */ - public boolean isCallToOriginal(ResolvedJavaMethod targetMethod) { - return method.equals(targetMethod) || replacement.equals(targetMethod); - } - - IntrinsicContext asIntrinsic() { - return null; - } - - @Override - public String toString() { - return "Replacement{original: " + method.format("%H.%n(%p)") + ", replacement: " + replacement.format("%H.%n(%p)") + "}"; - } - } - - /** - * Context for a replacement being inlined as a compiler intrinsic. Deoptimization within a - * compiler intrinsic must replay the intrinsified call. This context object retains the - * information required to build a frame state denoting the JVM state just before the - * intrinsified call. - */ - public static class IntrinsicContext extends ReplacementContext { - - /** - * BCI denoting an intrinsic is being parsed for inlining after the caller has been parsed. - */ - public static final int POST_PARSE_INLINE_BCI = -1; - - /** - * BCI denoting an intrinsic is the compilation root. - */ - public static final int ROOT_COMPILATION_BCI = -2; - - /** - * The arguments to the intrinsic. - */ - ValueNode[] args; - - /** - * The BCI of the intrinsified invocation, {@link #POST_PARSE_INLINE_BCI} or - * {@link #ROOT_COMPILATION_BCI}. - */ - final int bci; - - private FrameState stateBeforeCache; - - public IntrinsicContext(ResolvedJavaMethod method, ResolvedJavaMethod substitute, ValueNode[] args, int bci) { - super(method, substitute); - assert bci != POST_PARSE_INLINE_BCI || args == null; - this.args = args; - this.bci = bci; - assert !isCompilationRoot() || method.hasBytecodes() : "Cannot intrinsic for native or abstract method " + method.format("%H.%n(%p)"); - } - - @Override - public boolean isIntrinsic() { - return true; - } - - public boolean isPostParseInlined() { - return bci == POST_PARSE_INLINE_BCI; - } - - public boolean isCompilationRoot() { - return bci == ROOT_COMPILATION_BCI; - } - - public FrameState getInvokeStateBefore(StructuredGraph graph, BytecodeParser parent) { - if (isCompilationRoot()) { - int maxLocals = method.getMaxLocals(); - // The 'args' were initialized based on the intrinsic method but a - // frame state's 'locals' needs to have the same length as the frame - // state method's 'max_locals'. - ValueNode[] locals = maxLocals == args.length ? args : Arrays.copyOf(args, maxLocals); - ValueNode[] stack = EMPTY_ARRAY; - int stackSize = 0; - ValueNode[] locks = EMPTY_ARRAY; - List monitorIds = Collections.emptyList(); - return graph.add(new FrameState(null, method, 0, locals, stack, stackSize, locks, monitorIds, false, false)); - } else if (isPostParseInlined()) { - return graph.add(new FrameState(BytecodeFrame.BEFORE_BCI)); - } else { - assert !parent.parsingReplacement() || parent.replacementContext instanceof IntrinsicContext; - if (stateBeforeCache == null) { - assert stateBeforeCache == null; - - // Find the non-intrinsic ancestor calling the intrinsified method - BytecodeParser ancestor = parent; - while (ancestor.parsingReplacement()) { - assert ancestor.replacementContext instanceof IntrinsicContext; - ancestor = ancestor.getParent(); - } - FrameState stateDuring = ancestor.getFrameState().create(ancestor.bci(), ancestor.getParent(), true); - stateBeforeCache = stateDuring.duplicateModifiedBeforeCall(bci, Kind.Void, args); - } - return stateBeforeCache; - } - } - - @Override - IntrinsicContext asIntrinsic() { - return this; - } - - @Override - public String toString() { - return "Intrinsic{original: " + method.format("%H.%n(%p)") + ", replacement: " + replacement.format("%H.%n(%p)") + ", bci: " + bci + - (args == null ? "" : ", args: " + Arrays.toString(args)) + (stateBeforeCache == null ? "" : ", stateBefore: " + stateBeforeCache) + "}"; - } - } - - /** * The minimum value to which {@link Options#TraceBytecodeParserLevel} must be set to trace the * bytecode instructions as they are parsed. */ diff -r 0b2e4d40b683 -r 518ce9a36939 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 Apr 13 16:19:41 2015 -0700 +++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPhase.java Mon Apr 13 16:26:28 2015 -0700 @@ -50,7 +50,6 @@ import com.oracle.graal.graphbuilderconf.*; import com.oracle.graal.graphbuilderconf.InlineInvokePlugin.InlineInfo; import com.oracle.graal.graphbuilderconf.InvocationPlugins.InvocationPluginReceiver; -import com.oracle.graal.java.AbstractBytecodeParser.ReplacementContext; import com.oracle.graal.java.BciBlockMapping.BciBlock; import com.oracle.graal.java.BciBlockMapping.ExceptionDispatchBlock; import com.oracle.graal.nodeinfo.*; diff -r 0b2e4d40b683 -r 518ce9a36939 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 Apr 13 16:19:41 2015 -0700 +++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/HIRFrameStateBuilder.java Mon Apr 13 16:26:28 2015 -0700 @@ -32,7 +32,6 @@ import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.debug.*; import com.oracle.graal.graphbuilderconf.*; -import com.oracle.graal.java.AbstractBytecodeParser.IntrinsicContext; import com.oracle.graal.java.BciBlockMapping.BciBlock; import com.oracle.graal.java.GraphBuilderPhase.Instance.BytecodeParser; import com.oracle.graal.nodeinfo.*; diff -r 0b2e4d40b683 -r 518ce9a36939 graal/com.oracle.graal.java/src/com/oracle/graal/java/IntrinsicContext.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/IntrinsicContext.java Mon Apr 13 16:26:28 2015 -0700 @@ -0,0 +1,128 @@ +/* + * 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 com.oracle.graal.java.HIRFrameStateBuilder.*; + +import java.util.*; + +import com.oracle.graal.api.code.*; +import com.oracle.graal.api.meta.*; +import com.oracle.graal.java.GraphBuilderPhase.Instance.*; +import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.java.*; + +/** + * Context for a replacement being inlined as a compiler intrinsic. Deoptimization within a compiler + * intrinsic must replay the intrinsified call. This context object retains the information required + * to build a frame state denoting the JVM state just before the intrinsified call. + */ +public class IntrinsicContext extends ReplacementContext { + + /** + * BCI denoting an intrinsic is being parsed for inlining after the caller has been parsed. + */ + public static final int POST_PARSE_INLINE_BCI = -1; + + /** + * BCI denoting an intrinsic is the compilation root. + */ + public static final int ROOT_COMPILATION_BCI = -2; + + /** + * The arguments to the intrinsic. + */ + ValueNode[] args; + + /** + * The BCI of the intrinsified invocation, {@link #POST_PARSE_INLINE_BCI} or + * {@link #ROOT_COMPILATION_BCI}. + */ + final int bci; + + private FrameState stateBeforeCache; + + public IntrinsicContext(ResolvedJavaMethod method, ResolvedJavaMethod substitute, ValueNode[] args, int bci) { + super(method, substitute); + assert bci != POST_PARSE_INLINE_BCI || args == null; + this.args = args; + this.bci = bci; + assert !isCompilationRoot() || method.hasBytecodes() : "Cannot intrinsic for native or abstract method " + method.format("%H.%n(%p)"); + } + + @Override + public boolean isIntrinsic() { + return true; + } + + public boolean isPostParseInlined() { + return bci == POST_PARSE_INLINE_BCI; + } + + public boolean isCompilationRoot() { + return bci == ROOT_COMPILATION_BCI; + } + + public FrameState getInvokeStateBefore(StructuredGraph graph, BytecodeParser parent) { + if (isCompilationRoot()) { + int maxLocals = method.getMaxLocals(); + // The 'args' were initialized based on the intrinsic method but a + // frame state's 'locals' needs to have the same length as the frame + // state method's 'max_locals'. + ValueNode[] locals = maxLocals == args.length ? args : Arrays.copyOf(args, maxLocals); + ValueNode[] stack = EMPTY_ARRAY; + int stackSize = 0; + ValueNode[] locks = EMPTY_ARRAY; + List monitorIds = Collections.emptyList(); + return graph.add(new FrameState(null, method, 0, locals, stack, stackSize, locks, monitorIds, false, false)); + } else if (isPostParseInlined()) { + return graph.add(new FrameState(BytecodeFrame.BEFORE_BCI)); + } else { + assert !parent.parsingReplacement() || parent.replacementContext instanceof IntrinsicContext; + if (stateBeforeCache == null) { + assert stateBeforeCache == null; + + // Find the non-intrinsic ancestor calling the intrinsified method + BytecodeParser ancestor = parent; + while (ancestor.parsingReplacement()) { + assert ancestor.replacementContext instanceof IntrinsicContext; + ancestor = ancestor.getParent(); + } + FrameState stateDuring = ancestor.getFrameState().create(ancestor.bci(), ancestor.getParent(), true); + stateBeforeCache = stateDuring.duplicateModifiedBeforeCall(bci, Kind.Void, args); + } + return stateBeforeCache; + } + } + + @Override + IntrinsicContext asIntrinsic() { + return this; + } + + @Override + public String toString() { + return "Intrinsic{original: " + method.format("%H.%n(%p)") + ", replacement: " + replacement.format("%H.%n(%p)") + ", bci: " + bci + (args == null ? "" : ", args: " + Arrays.toString(args)) + + (stateBeforeCache == null ? "" : ", stateBefore: " + stateBeforeCache) + "}"; + } +} diff -r 0b2e4d40b683 -r 518ce9a36939 graal/com.oracle.graal.java/src/com/oracle/graal/java/ReplacementContext.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/ReplacementContext.java Mon Apr 13 16:26:28 2015 -0700 @@ -0,0 +1,78 @@ +/* + * 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 com.oracle.graal.api.meta.*; +import com.oracle.graal.api.replacements.*; +import com.oracle.graal.graphbuilderconf.GraphBuilderContext.Replacement; + +/** + * Information about a substitute method being parsed in lieu of an original method. This can happen + * when a call to a {@link MethodSubstitution} is encountered or the root of compilation is a + * {@link MethodSubstitution} or a snippet. + */ +public class ReplacementContext implements Replacement { + /** + * The method being replaced. + */ + final ResolvedJavaMethod method; + + /** + * The replacement method. + */ + final ResolvedJavaMethod replacement; + + public ReplacementContext(ResolvedJavaMethod method, ResolvedJavaMethod substitute) { + this.method = method; + this.replacement = substitute; + } + + public ResolvedJavaMethod getOriginalMethod() { + return method; + } + + public ResolvedJavaMethod getReplacementMethod() { + return replacement; + } + + public boolean isIntrinsic() { + return false; + } + + /** + * Determines if a call within the compilation scope of a replacement represents a call to the + * original method. + */ + public boolean isCallToOriginal(ResolvedJavaMethod targetMethod) { + return method.equals(targetMethod) || replacement.equals(targetMethod); + } + + IntrinsicContext asIntrinsic() { + return null; + } + + @Override + public String toString() { + return "Replacement{original: " + method.format("%H.%n(%p)") + ", replacement: " + replacement.format("%H.%n(%p)") + "}"; + } +} diff -r 0b2e4d40b683 -r 518ce9a36939 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/GuardingPiNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/GuardingPiNode.java Mon Apr 13 16:19:41 2015 -0700 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/GuardingPiNode.java Mon Apr 13 16:26:28 2015 -0700 @@ -107,7 +107,7 @@ @Override public Node canonical(CanonicalizerTool tool) { - if (stamp() == StampFactory.illegal(object.getKind())) { + if (stamp().isIllegal()) { // The guard always fails return new DeoptimizeNode(action, reason); } diff -r 0b2e4d40b683 -r 518ce9a36939 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/CheckCastNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/CheckCastNode.java Mon Apr 13 16:19:41 2015 -0700 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/CheckCastNode.java Mon Apr 13 16:26:28 2015 -0700 @@ -116,7 +116,7 @@ Stamp newStamp = StampFactory.declaredTrusted(type).improveWith(object().stamp()); ValueNode condition; ValueNode theValue = object; - if (newStamp instanceof IllegalStamp) { + if (newStamp.isIllegal()) { // This is a check cast that will always fail condition = LogicConstantNode.contradiction(graph()); newStamp = StampFactory.declaredTrusted(type); diff -r 0b2e4d40b683 -r 518ce9a36939 graal/com.oracle.graal.phases/src/com/oracle/graal/phases/graph/InferStamps.java --- a/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/graph/InferStamps.java Mon Apr 13 16:19:41 2015 -0700 +++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/graph/InferStamps.java Mon Apr 13 16:26:28 2015 -0700 @@ -88,7 +88,7 @@ for (Node n : graph.getNodes()) { if (n instanceof ValuePhiNode) { ValueNode node = (ValueNode) n; - assert !(node.stamp() instanceof IllegalStamp) : "Stamp is illegal after analysis. This is not necessarily an error, but a condition that we want to investigate (and then maybe relax or remove the assertion)."; + assert node.stamp().isLegal() : "Stamp is illegal after analysis. This is not necessarily an error, but a condition that we want to investigate (and then maybe relax or remove the assertion)."; } } return true; diff -r 0b2e4d40b683 -r 518ce9a36939 graal/com.oracle.graal.replacements.amd64/src/com/oracle/graal/replacements/amd64/AMD64GraphBuilderPlugins.java --- a/graal/com.oracle.graal.replacements.amd64/src/com/oracle/graal/replacements/amd64/AMD64GraphBuilderPlugins.java Mon Apr 13 16:19:41 2015 -0700 +++ b/graal/com.oracle.graal.replacements.amd64/src/com/oracle/graal/replacements/amd64/AMD64GraphBuilderPlugins.java Mon Apr 13 16:26:28 2015 -0700 @@ -29,10 +29,10 @@ import com.oracle.graal.amd64.*; import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; +import com.oracle.graal.graphbuilderconf.*; import com.oracle.graal.graphbuilderconf.GraphBuilderConfiguration.Plugins; -import com.oracle.graal.graphbuilderconf.*; -import com.oracle.graal.graphbuilderconf.InvocationPlugins.Receiver; import com.oracle.graal.graphbuilderconf.InvocationPlugins.Registration; +import com.oracle.graal.graphbuilderconf.MethodIdMap.Receiver; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.java.*; import com.oracle.graal.replacements.*; diff -r 0b2e4d40b683 -r 518ce9a36939 graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/GraphKit.java --- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/GraphKit.java Mon Apr 13 16:19:41 2015 -0700 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/GraphKit.java Mon Apr 13 16:26:28 2015 -0700 @@ -30,7 +30,6 @@ import com.oracle.graal.graph.*; import com.oracle.graal.graphbuilderconf.*; import com.oracle.graal.graphbuilderconf.GraphBuilderConfiguration.Plugins; -import com.oracle.graal.java.AbstractBytecodeParser.IntrinsicContext; import com.oracle.graal.java.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.CallTargetNode.InvokeKind; diff -r 0b2e4d40b683 -r 518ce9a36939 graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/IntrinsicGraphBuilder.java --- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/IntrinsicGraphBuilder.java Mon Apr 13 16:19:41 2015 -0700 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/IntrinsicGraphBuilder.java Mon Apr 13 16:26:28 2015 -0700 @@ -27,7 +27,7 @@ import com.oracle.graal.compiler.common.*; import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.graphbuilderconf.*; -import com.oracle.graal.graphbuilderconf.InvocationPlugins.Receiver; +import com.oracle.graal.graphbuilderconf.MethodIdMap.Receiver; import com.oracle.graal.nodes.CallTargetNode.InvokeKind; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.StructuredGraph.AllowAssumptions; diff -r 0b2e4d40b683 -r 518ce9a36939 graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/ReplacementsImpl.java --- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/ReplacementsImpl.java Mon Apr 13 16:19:41 2015 -0700 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/ReplacementsImpl.java Mon Apr 13 16:26:28 2015 -0700 @@ -47,8 +47,6 @@ import com.oracle.graal.graphbuilderconf.*; import com.oracle.graal.graphbuilderconf.GraphBuilderConfiguration.Plugins; import com.oracle.graal.graphbuilderconf.GraphBuilderContext.Replacement; -import com.oracle.graal.java.AbstractBytecodeParser.IntrinsicContext; -import com.oracle.graal.java.AbstractBytecodeParser.ReplacementContext; import com.oracle.graal.java.*; import com.oracle.graal.java.GraphBuilderPhase.Instance; import com.oracle.graal.nodes.*; diff -r 0b2e4d40b683 -r 518ce9a36939 graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/StandardGraphBuilderPlugins.java --- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/StandardGraphBuilderPlugins.java Mon Apr 13 16:19:41 2015 -0700 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/StandardGraphBuilderPlugins.java Mon Apr 13 16:26:28 2015 -0700 @@ -38,8 +38,8 @@ import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.graph.*; import com.oracle.graal.graphbuilderconf.*; -import com.oracle.graal.graphbuilderconf.InvocationPlugins.Receiver; import com.oracle.graal.graphbuilderconf.InvocationPlugins.Registration; +import com.oracle.graal.graphbuilderconf.MethodIdMap.Receiver; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.calc.*; import com.oracle.graal.nodes.debug.*; diff -r 0b2e4d40b683 -r 518ce9a36939 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 Apr 13 16:19:41 2015 -0700 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/PartialEvaluator.java Mon Apr 13 16:26:28 2015 -0700 @@ -42,7 +42,6 @@ import com.oracle.graal.nodes.StructuredGraph.AllowAssumptions; import com.oracle.graal.nodes.calc.*; import com.oracle.graal.nodes.java.*; -import com.oracle.graal.nodes.spi.*; import com.oracle.graal.nodes.virtual.*; import com.oracle.graal.options.*; import com.oracle.graal.phases.*; @@ -50,6 +49,7 @@ import com.oracle.graal.phases.common.inlining.*; import com.oracle.graal.phases.tiers.*; import com.oracle.graal.phases.util.*; +import com.oracle.graal.replacements.*; import com.oracle.graal.truffle.debug.*; import com.oracle.graal.truffle.nodes.*; import com.oracle.graal.truffle.nodes.asserts.*; @@ -166,9 +166,9 @@ private Deque inlining; private OptimizedDirectCallNode lastDirectCallNode; - private final Replacements replacements; + private final ReplacementsImpl replacements; - public PEInlineInvokePlugin(TruffleInlining inlining, Replacements replacements) { + public PEInlineInvokePlugin(TruffleInlining inlining, ReplacementsImpl replacements) { this.inlining = new ArrayDeque<>(); this.inlining.push(inlining); this.replacements = replacements; @@ -176,13 +176,17 @@ @Override public InlineInfo getInlineInfo(GraphBuilderContext builder, ResolvedJavaMethod original, ValueNode[] arguments, JavaType returnType) { + InlineInfo inlineInfo = replacements.getInlineInfo(builder, original, arguments, returnType); + if (inlineInfo != null) { + return inlineInfo; + } + if (original.getAnnotation(TruffleBoundary.class) != null) { return null; } - if (replacements != null && replacements.hasSubstitution(original)) { - return null; - } + assert !replacements.hasSubstitution(original) : "Replacements must have been processed by now"; assert !builder.parsingReplacement(); + if (TruffleCompilerOptions.TruffleFunctionInlining.getValue()) { if (original.equals(callSiteProxyMethod)) { ValueNode arg1 = arguments[0]; @@ -219,12 +223,12 @@ private class ParsingInlineInvokePlugin implements InlineInvokePlugin { - private final Replacements replacements; + private final ReplacementsImpl replacements; private final InvocationPlugins invocationPlugins; private final LoopExplosionPlugin loopExplosionPlugin; private final boolean inlineDuringParsing; - public ParsingInlineInvokePlugin(Replacements replacements, InvocationPlugins invocationPlugins, LoopExplosionPlugin loopExplosionPlugin, boolean inlineDuringParsing) { + public ParsingInlineInvokePlugin(ReplacementsImpl replacements, InvocationPlugins invocationPlugins, LoopExplosionPlugin loopExplosionPlugin, boolean inlineDuringParsing) { this.replacements = replacements; this.invocationPlugins = invocationPlugins; this.loopExplosionPlugin = loopExplosionPlugin; @@ -245,15 +249,19 @@ @Override public InlineInfo getInlineInfo(GraphBuilderContext builder, ResolvedJavaMethod original, ValueNode[] arguments, JavaType returnType) { + InlineInfo inlineInfo = replacements.getInlineInfo(builder, original, arguments, returnType); + if (inlineInfo != null) { + return inlineInfo; + } + if (invocationPlugins.lookupInvocation(original) != null || loopExplosionPlugin.shouldExplodeLoops(original)) { return null; } if (original.getAnnotation(TruffleBoundary.class) != null) { return null; } - if (replacements != null && replacements.hasSubstitution(original)) { - return null; - } + assert !replacements.hasSubstitution(original) : "Replacements must have been processed by now"; + if (original.equals(callSiteProxyMethod) || original.equals(callDirectMethod)) { return null; } @@ -298,7 +306,7 @@ plugins.setParameterPlugin(new InterceptReceiverPlugin(callTarget)); callTarget.setInlining(new TruffleInlining(callTarget, new DefaultInliningPolicy())); - InlineInvokePlugin inlinePlugin = new PEInlineInvokePlugin(callTarget.getInlining(), providers.getReplacements()); + InlineInvokePlugin inlinePlugin = new PEInlineInvokePlugin(callTarget.getInlining(), (ReplacementsImpl) providers.getReplacements()); if (PrintTruffleExpansionHistogram.getValue()) { inlinePlugin = new HistogramInlineInvokePlugin(graph, inlinePlugin); } @@ -322,15 +330,16 @@ newConfig.setUseProfiling(false); Plugins plugins = newConfig.getPlugins(); plugins.setLoadFieldPlugin(new InterceptLoadFieldPlugin()); - plugins.setInlineInvokePlugin(new ParsingInlineInvokePlugin(providers.getReplacements(), parsingInvocationPlugins, loopExplosionPlugin, !PrintTruffleExpansionHistogram.getValue())); + plugins.setInlineInvokePlugin(new ParsingInlineInvokePlugin((ReplacementsImpl) providers.getReplacements(), parsingInvocationPlugins, loopExplosionPlugin, + !PrintTruffleExpansionHistogram.getValue())); CachingPEGraphDecoder decoder = new CachingPEGraphDecoder(providers, newConfig, AllowAssumptions.from(graph.getAssumptions() != null)); ParameterPlugin parameterPlugin = new InterceptReceiverPlugin(callTarget); - InvocationPlugins decodingInvocationPlugins = new InvocationPlugins(providers.getMetaAccess()); + InvocationPlugins decodingInvocationPlugins = new InvocationPlugins(parsingInvocationPlugins.getParent()); TruffleGraphBuilderPlugins.registerInvocationPlugins(providers.getMetaAccess(), decodingInvocationPlugins, false, snippetReflection); - InlineInvokePlugin decodingInlinePlugin = new PEInlineInvokePlugin(callTarget.getInlining(), providers.getReplacements()); + InlineInvokePlugin decodingInlinePlugin = new PEInlineInvokePlugin(callTarget.getInlining(), (ReplacementsImpl) providers.getReplacements()); if (PrintTruffleExpansionHistogram.getValue()) { decodingInlinePlugin = new HistogramInlineInvokePlugin(graph, decodingInlinePlugin); } @@ -450,7 +459,9 @@ if (!TruffleCompilerOptions.TruffleInlineAcrossTruffleBoundary.getValue()) { // Do not inline across Truffle boundaries. for (MethodCallTargetNode mct : graph.getNodes(MethodCallTargetNode.TYPE)) { - mct.invoke().setUseForInlining(false); + if (mct.targetMethod().getAnnotation(TruffleBoundary.class) != null) { + mct.invoke().setUseForInlining(false); + } } } } diff -r 0b2e4d40b683 -r 518ce9a36939 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 Apr 13 16:19:41 2015 -0700 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/substitutions/TruffleGraphBuilderPlugins.java Mon Apr 13 16:26:28 2015 -0700 @@ -32,8 +32,8 @@ import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.graph.*; import com.oracle.graal.graphbuilderconf.*; -import com.oracle.graal.graphbuilderconf.InvocationPlugins.Receiver; import com.oracle.graal.graphbuilderconf.InvocationPlugins.Registration; +import com.oracle.graal.graphbuilderconf.MethodIdMap.Receiver; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.calc.*; import com.oracle.graal.nodes.extended.*;