# HG changeset patch # User Christian Wimmer # Date 1365715323 25200 # Node ID 92d2bedb5dfcd65ad60bf0a6bfbc80e925948833 # Parent 2c933625b355957b05197be79ef158ec31c125b5 Change of Snippet template and instantiation process diff -r 2c933625b355 -r 92d2bedb5dfc graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/VMToCompilerImpl.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/VMToCompilerImpl.java Thu Apr 11 14:20:32 2013 -0700 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/VMToCompilerImpl.java Thu Apr 11 14:22:03 2013 -0700 @@ -152,7 +152,8 @@ @Override public void run() { - for (ReplacementsProvider provider : ServiceLoader.loadInstalled(ReplacementsProvider.class)) { + ServiceLoader serviceLoader = ServiceLoader.loadInstalled(ReplacementsProvider.class); + for (ReplacementsProvider provider : serviceLoader) { provider.registerReplacements(replacements); } runtime.registerReplacements(replacements); diff -r 2c933625b355 -r 92d2bedb5dfc graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotRuntime.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotRuntime.java Thu Apr 11 14:20:32 2013 -0700 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotRuntime.java Thu Apr 11 14:22:03 2013 -0700 @@ -327,17 +327,6 @@ replacements.registerSubstitutions(AESCryptSubstitutions.class); replacements.registerSubstitutions(CipherBlockChainingSubstitutions.class); } - if (GraalOptions.IntrinsifyArrayCopy) { - replacements.registerSnippets(ArrayCopySnippets.class); - } - if (GraalOptions.IntrinsifyObjectClone) { - replacements.registerSnippets(ObjectCloneSnippets.class); - } - - replacements.registerSnippets(BoxingSnippets.class); - for (Class clazz : BoxingSubstitutions.getClasses()) { - replacements.registerSubstitutions(clazz); - } checkcastSnippets = new CheckCastSnippets.Templates(this, replacements, graalRuntime.getTarget()); instanceofSnippets = new InstanceOfSnippets.Templates(this, replacements, graalRuntime.getTarget()); diff -r 2c933625b355 -r 92d2bedb5dfc graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ArrayCopySnippets.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ArrayCopySnippets.java Thu Apr 11 14:20:32 2013 -0700 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ArrayCopySnippets.java Thu Apr 11 14:22:03 2013 -0700 @@ -37,7 +37,6 @@ import com.oracle.graal.nodes.java.*; import com.oracle.graal.phases.*; import com.oracle.graal.replacements.*; -import com.oracle.graal.replacements.Snippet.*; import com.oracle.graal.replacements.nodes.*; import com.oracle.graal.word.*; @@ -75,7 +74,7 @@ private static final Kind VECTOR_KIND = Kind.Long; private static final long VECTOR_SIZE = arrayIndexScale(Kind.Long); - public static void vectorizedCopy(Object src, int srcPos, Object dest, int destPos, int length, @ConstantParameter("baseKind") Kind baseKind) { + private static void vectorizedCopy(Object src, int srcPos, Object dest, int destPos, int length, Kind baseKind) { checkNonNull(src); checkNonNull(dest); checkLimits(src, srcPos, dest, destPos, length); diff -r 2c933625b355 -r 92d2bedb5dfc graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/BoxingSnippets.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/BoxingSnippets.java Thu Apr 11 14:20:32 2013 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,252 +0,0 @@ -/* - * Copyright (c) 2012, 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.hotspot.replacements; - -import static com.oracle.graal.replacements.SnippetTemplate.*; - -import java.lang.reflect.*; - -import com.oracle.graal.api.code.*; -import com.oracle.graal.api.meta.*; -import com.oracle.graal.debug.*; -import com.oracle.graal.graph.Node.NodeIntrinsic; -import com.oracle.graal.nodes.*; -import com.oracle.graal.nodes.calc.*; -import com.oracle.graal.nodes.extended.*; -import com.oracle.graal.nodes.spi.*; -import com.oracle.graal.nodes.type.*; -import com.oracle.graal.phases.*; -import com.oracle.graal.replacements.*; -import com.oracle.graal.replacements.Snippet.Fold; -import com.oracle.graal.replacements.Snippet.Parameter; -import com.oracle.graal.replacements.Snippet.SnippetInliningPolicy; -import com.oracle.graal.replacements.SnippetTemplate.AbstractTemplates; -import com.oracle.graal.replacements.SnippetTemplate.Arguments; -import com.oracle.graal.replacements.SnippetTemplate.Key; -import com.oracle.graal.word.*; - -public class BoxingSnippets implements Snippets { - - /** - * This snippet inlining policy differs from the default one in that it does normal inlining of - * boxing methods like {@link Integer#valueOf(int)} (as opposed to method substitution). - */ - public static class BoxingSnippetInliningPolicy implements SnippetInliningPolicy { - - @Override - public boolean shouldInline(ResolvedJavaMethod method, ResolvedJavaMethod caller) { - if (Modifier.isNative(method.getModifiers())) { - return false; - } - if (method.getAnnotation(Fold.class) != null) { - return false; - } - if (method.getAnnotation(NodeIntrinsic.class) != null) { - return false; - } - if (method.getAnnotation(Word.Operation.class) != null) { - return false; - } - return true; - } - - @Override - public boolean shouldUseReplacement(ResolvedJavaMethod callee, ResolvedJavaMethod methodToParse) { - return false; - } - } - - @Snippet(inlining = BoxingSnippetInliningPolicy.class) - public static Boolean valueOf(@Parameter("value") boolean value) { - valueOfCounter.inc(); - return UnsafeCastNode.unsafeCast(Boolean.valueOf(value), StampFactory.forNodeIntrinsic()); - } - - @Snippet(inlining = BoxingSnippetInliningPolicy.class) - public static Byte valueOf(@Parameter("value") byte value) { - valueOfCounter.inc(); - return UnsafeCastNode.unsafeCast(Byte.valueOf(value), StampFactory.forNodeIntrinsic()); - } - - @Snippet(inlining = BoxingSnippetInliningPolicy.class) - public static Character valueOf(@Parameter("value") char value) { - valueOfCounter.inc(); - return UnsafeCastNode.unsafeCast(Character.valueOf(value), StampFactory.forNodeIntrinsic()); - } - - @Snippet(inlining = BoxingSnippetInliningPolicy.class) - public static Double valueOf(@Parameter("value") double value) { - valueOfCounter.inc(); - return UnsafeCastNode.unsafeCast(Double.valueOf(value), StampFactory.forNodeIntrinsic()); - } - - @Snippet(inlining = BoxingSnippetInliningPolicy.class) - public static Float valueOf(@Parameter("value") float value) { - valueOfCounter.inc(); - return UnsafeCastNode.unsafeCast(Float.valueOf(value), StampFactory.forNodeIntrinsic()); - } - - @Snippet(inlining = BoxingSnippetInliningPolicy.class) - public static Integer valueOf(@Parameter("value") int value) { - valueOfCounter.inc(); - return UnsafeCastNode.unsafeCast(Integer.valueOf(value), StampFactory.forNodeIntrinsic()); - } - - @Snippet(inlining = BoxingSnippetInliningPolicy.class) - public static Long valueOf(@Parameter("value") long value) { - valueOfCounter.inc(); - return UnsafeCastNode.unsafeCast(Long.valueOf(value), StampFactory.forNodeIntrinsic()); - } - - @Snippet(inlining = BoxingSnippetInliningPolicy.class) - public static Short valueOf(@Parameter("value") short value) { - valueOfCounter.inc(); - return UnsafeCastNode.unsafeCast(Short.valueOf(value), StampFactory.forNodeIntrinsic()); - } - - @Snippet(inlining = BoxingSnippetInliningPolicy.class) - public static boolean booleanValue(@Parameter("value") Boolean value) { - valueOfCounter.inc(); - return value.booleanValue(); - } - - @Snippet(inlining = BoxingSnippetInliningPolicy.class) - public static byte byteValue(@Parameter("value") Byte value) { - valueOfCounter.inc(); - return value.byteValue(); - } - - @Snippet(inlining = BoxingSnippetInliningPolicy.class) - public static char charValue(@Parameter("value") Character value) { - valueOfCounter.inc(); - return value.charValue(); - } - - @Snippet(inlining = BoxingSnippetInliningPolicy.class) - public static double doubleValue(@Parameter("value") Double value) { - valueOfCounter.inc(); - return value.doubleValue(); - } - - @Snippet(inlining = BoxingSnippetInliningPolicy.class) - public static float floatValue(@Parameter("value") Float value) { - valueOfCounter.inc(); - return value.floatValue(); - } - - @Snippet(inlining = BoxingSnippetInliningPolicy.class) - public static int intValue(@Parameter("value") Integer value) { - valueOfCounter.inc(); - return value.intValue(); - } - - @Snippet(inlining = BoxingSnippetInliningPolicy.class) - public static long longValue(@Parameter("value") Long value) { - valueOfCounter.inc(); - return value.longValue(); - } - - @Snippet(inlining = BoxingSnippetInliningPolicy.class) - public static short shortValue(@Parameter("value") Short value) { - valueOfCounter.inc(); - return value.shortValue(); - } - - public static FloatingNode canonicalizeBoxing(BoxNode box, MetaAccessProvider runtime) { - ValueNode value = box.getValue(); - if (value.isConstant()) { - Constant sourceConstant = value.asConstant(); - switch (box.getBoxingKind()) { - case Boolean: - return ConstantNode.forObject(Boolean.valueOf(sourceConstant.asInt() != 0), runtime, box.graph()); - case Byte: - return ConstantNode.forObject(Byte.valueOf((byte) sourceConstant.asInt()), runtime, box.graph()); - case Char: - return ConstantNode.forObject(Character.valueOf((char) sourceConstant.asInt()), runtime, box.graph()); - case Short: - return ConstantNode.forObject(Short.valueOf((short) sourceConstant.asInt()), runtime, box.graph()); - case Int: - return ConstantNode.forObject(Integer.valueOf(sourceConstant.asInt()), runtime, box.graph()); - case Long: - return ConstantNode.forObject(Long.valueOf(sourceConstant.asLong()), runtime, box.graph()); - case Float: - return ConstantNode.forObject(Float.valueOf(sourceConstant.asFloat()), runtime, box.graph()); - case Double: - return ConstantNode.forObject(Double.valueOf(sourceConstant.asDouble()), runtime, box.graph()); - default: - assert false : "Unexpected source kind for boxing"; - break; - } - } - return null; - } - - public static class Templates extends AbstractTemplates { - - private final ResolvedJavaMethod[] valueOfMethods = new ResolvedJavaMethod[Kind.values().length]; - private final ResolvedJavaMethod[] unboxMethods = new ResolvedJavaMethod[Kind.values().length]; - - public Templates(CodeCacheProvider runtime, Replacements replacements, TargetDescription target) { - super(runtime, replacements, target, BoxingSnippets.class); - for (Kind kind : new Kind[]{Kind.Boolean, Kind.Byte, Kind.Char, Kind.Double, Kind.Float, Kind.Int, Kind.Long, Kind.Short}) { - valueOfMethods[kind.ordinal()] = snippet("valueOf", kind.toJavaClass()); - unboxMethods[kind.ordinal()] = snippet(kind.getJavaName() + "Value", kind.toBoxedJavaClass()); - } - } - - private ResolvedJavaMethod getValueOf(Kind kind) { - assert valueOfMethods[kind.ordinal()] != null; - return valueOfMethods[kind.ordinal()]; - } - - private ResolvedJavaMethod getUnbox(Kind kind) { - assert unboxMethods[kind.ordinal()] != null; - return unboxMethods[kind.ordinal()]; - } - - public void lower(BoxNode box) { - FloatingNode canonical = canonicalizeBoxing(box, runtime); - if (canonical != null) { - ((StructuredGraph) box.graph()).replaceFixedWithFloating(box, canonical); - } else { - Key key = new Key(getValueOf(box.getBoxingKind())); - Arguments arguments = new Arguments().add("value", box.getValue()); - SnippetTemplate template = cache.get(key); - Debug.log("Lowering integerValueOf in %s: node=%s, template=%s, arguments=%s", box.graph(), box, template, arguments); - template.instantiate(runtime, box, DEFAULT_REPLACER, arguments); - } - } - - public void lower(UnboxNode unbox) { - Key key = new Key(getUnbox(unbox.getBoxingKind())); - Arguments arguments = new Arguments().add("value", unbox.getValue()); - SnippetTemplate template = cache.get(key); - Debug.log("Lowering integerValueOf in %s: node=%s, template=%s, arguments=%s", unbox.graph(), unbox, template, arguments); - template.instantiate(runtime, unbox, DEFAULT_REPLACER, arguments); - } - } - - private static final SnippetCounter.Group integerCounters = GraalOptions.SnippetCounters ? new SnippetCounter.Group("Integer intrinsifications") : null; - private static final SnippetCounter valueOfCounter = new SnippetCounter(integerCounters, "valueOf", "valueOf intrinsification"); - -} diff -r 2c933625b355 -r 92d2bedb5dfc graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/BoxingSubstitutions.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/BoxingSubstitutions.java Thu Apr 11 14:20:32 2013 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,147 +0,0 @@ -/* - * Copyright (c) 2012, 2012, 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.hotspot.replacements; - -import com.oracle.graal.api.meta.*; -import com.oracle.graal.api.replacements.*; -import com.oracle.graal.nodes.extended.*; - -public class BoxingSubstitutions { - - @ClassSubstitution(Boolean.class) - private static class BooleanSubstitutions { - - @MethodSubstitution(forced = true) - public static Boolean valueOf(boolean value) { - return BoxNode.box(value, Boolean.class, Kind.Boolean); - } - - @MethodSubstitution(isStatic = false, forced = true) - public static boolean booleanValue(Boolean value) { - return UnboxNode.unbox(value, Kind.Boolean); - } - } - - @ClassSubstitution(Byte.class) - private static class ByteSubstitutions { - - @MethodSubstitution(forced = true) - public static Byte valueOf(byte value) { - return BoxNode.box(value, Byte.class, Kind.Byte); - } - - @MethodSubstitution(isStatic = false, forced = true) - public static byte byteValue(Byte value) { - return UnboxNode.unbox(value, Kind.Byte); - } - } - - @ClassSubstitution(Character.class) - private static class CharacterSubstitutions { - - @MethodSubstitution(forced = true) - public static Character valueOf(char value) { - return BoxNode.box(value, Character.class, Kind.Char); - } - - @MethodSubstitution(isStatic = false, forced = true) - public static char charValue(Character value) { - return UnboxNode.unbox(value, Kind.Char); - } - } - - @ClassSubstitution(Double.class) - private static class DoubleSubstitutions { - - @MethodSubstitution(forced = true) - public static Double valueOf(double value) { - return BoxNode.box(value, Double.class, Kind.Double); - } - - @MethodSubstitution(isStatic = false, forced = true) - public static double doubleValue(Double value) { - return UnboxNode.unbox(value, Kind.Double); - } - } - - @ClassSubstitution(Float.class) - private static class FloatSubstitutions { - - @MethodSubstitution(forced = true) - public static Float valueOf(float value) { - return BoxNode.box(value, Float.class, Kind.Float); - } - - @MethodSubstitution(isStatic = false, forced = true) - public static float floatValue(Float value) { - return UnboxNode.unbox(value, Kind.Float); - } - } - - @ClassSubstitution(Integer.class) - private static class IntegerSubstitutions { - - @MethodSubstitution(forced = true) - public static Integer valueOf(int value) { - return BoxNode.box(value, Integer.class, Kind.Int); - } - - @MethodSubstitution(isStatic = false, forced = true) - public static int intValue(Integer value) { - return UnboxNode.unbox(value, Kind.Int); - } - } - - @ClassSubstitution(Long.class) - private static class LongSubstitutions { - - @MethodSubstitution(forced = true) - public static Long valueOf(long value) { - return BoxNode.box(value, Long.class, Kind.Long); - } - - @MethodSubstitution(isStatic = false, forced = true) - public static long longValue(Long value) { - return UnboxNode.unbox(value, Kind.Long); - } - } - - @ClassSubstitution(Short.class) - private static class ShortSubstitutions { - - @MethodSubstitution(forced = true) - public static Short valueOf(short value) { - return BoxNode.box(value, Short.class, Kind.Short); - } - - @MethodSubstitution(isStatic = false, forced = true) - public static short shortValue(Short value) { - return UnboxNode.unbox(value, Kind.Short); - } - } - - public static Class[] getClasses() { - return new Class[]{BooleanSubstitutions.class, ByteSubstitutions.class, CharacterSubstitutions.class, DoubleSubstitutions.class, FloatSubstitutions.class, IntegerSubstitutions.class, - LongSubstitutions.class, ShortSubstitutions.class}; - } -} diff -r 2c933625b355 -r 92d2bedb5dfc graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/CheckCastSnippets.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/CheckCastSnippets.java Thu Apr 11 14:20:32 2013 -0700 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/CheckCastSnippets.java Thu Apr 11 14:22:03 2013 -0700 @@ -28,11 +28,9 @@ import static com.oracle.graal.hotspot.replacements.TypeCheckSnippetUtils.*; import static com.oracle.graal.nodes.extended.UnsafeCastNode.*; import static com.oracle.graal.replacements.SnippetTemplate.*; -import static com.oracle.graal.replacements.SnippetTemplate.Arguments.*; import static com.oracle.graal.replacements.nodes.BranchProbabilityNode.*; import com.oracle.graal.api.code.*; -import com.oracle.graal.api.meta.*; import com.oracle.graal.debug.*; import com.oracle.graal.graph.Node.NodeIntrinsic; import com.oracle.graal.hotspot.meta.*; @@ -42,7 +40,11 @@ import com.oracle.graal.nodes.type.*; import com.oracle.graal.phases.*; import com.oracle.graal.replacements.*; -import com.oracle.graal.replacements.Snippet.*; +import com.oracle.graal.replacements.Snippet.ConstantParameter; +import com.oracle.graal.replacements.Snippet.VarargsParameter; +import com.oracle.graal.replacements.SnippetTemplate.AbstractTemplates; +import com.oracle.graal.replacements.SnippetTemplate.Arguments; +import com.oracle.graal.replacements.SnippetTemplate.SnippetInfo; import com.oracle.graal.replacements.nodes.*; import com.oracle.graal.word.*; @@ -58,16 +60,11 @@ @NodeIntrinsic(BreakpointNode.class) static native void bkpt(Object object, Word hub, Word objectHub); - // @formatter:off - /** * Type test used when the type being tested against is a final type. */ @Snippet - public static Object checkcastExact( - @Parameter("object") Object object, - @Parameter("exactHub") Word exactHub, - @ConstantParameter("checkNull") boolean checkNull) { + public static Object checkcastExact(Object object, Word exactHub, @ConstantParameter boolean checkNull) { if (checkNull && object == null) { probability(NOT_FREQUENT_PROBABILITY); isNull.inc(); @@ -76,30 +73,25 @@ if (objectHub.notEqual(exactHub)) { probability(DEOPT_PATH_PROBABILITY); exactMiss.inc(); - //bkpt(object, exactHub, objectHub); DeoptimizeNode.deopt(InvalidateReprofile, ClassCastException); } exactHit.inc(); } - /* make sure that the unsafeCast is done *after* the check above, - * cf. ReadAfterCheckCast */ + /* + * make sure that the unsafeCast is done *after* the check above, cf. ReadAfterCheckCast + */ BeginNode anchorNode = BeginNode.anchor(StampFactory.forNodeIntrinsic()); return unsafeCast(verifyOop(object), StampFactory.forNodeIntrinsic(), anchorNode); } /** * Type test used when the type being tested against is a restricted primary type. - * - * This test ignores use of hints altogether as the display-based type check only - * involves one extra load where the second load should hit the same cache line as the - * first. + * + * This test ignores use of hints altogether as the display-based type check only involves one + * extra load where the second load should hit the same cache line as the first. */ @Snippet - public static Object checkcastPrimary( - @Parameter("hub") Word hub, - @Parameter("object") Object object, - @ConstantParameter("checkNull") boolean checkNull, - @ConstantParameter("superCheckOffset") int superCheckOffset) { + public static Object checkcastPrimary(Word hub, Object object, @ConstantParameter int superCheckOffset, @ConstantParameter boolean checkNull) { if (checkNull && object == null) { probability(NOT_FREQUENT_PROBABILITY); isNull.inc(); @@ -120,11 +112,7 @@ * Type test used when the type being tested against is a restricted secondary type. */ @Snippet - public static Object checkcastSecondary( - @Parameter("hub") Word hub, - @Parameter("object") Object object, - @VarargsParameter("hints") Word[] hints, - @ConstantParameter("checkNull") boolean checkNull) { + public static Object checkcastSecondary(Word hub, Object object, @VarargsParameter Word[] hints, @ConstantParameter boolean checkNull) { if (checkNull && object == null) { probability(NOT_FREQUENT_PROBABILITY); isNull.inc(); @@ -149,14 +137,11 @@ } /** - * Type test used when the type being tested against is not known at compile time (e.g. the type test - * in an object array store check). + * Type test used when the type being tested against is not known at compile time (e.g. the type + * test in an object array store check). */ @Snippet - public static Object checkcastDynamic( - @Parameter("hub") Word hub, - @Parameter("object") Object object, - @ConstantParameter("checkNull") boolean checkNull) { + public static Object checkcastDynamic(Word hub, Object object, @ConstantParameter boolean checkNull) { if (checkNull && object == null) { probability(NOT_FREQUENT_PROBABILITY); isNull.inc(); @@ -170,21 +155,15 @@ return unsafeCast(verifyOop(object), StampFactory.forNodeIntrinsic(), anchorNode); } - // @formatter:on - - public static class Templates extends AbstractTemplates { + public static class Templates extends AbstractTemplates { - private final ResolvedJavaMethod exact; - private final ResolvedJavaMethod primary; - private final ResolvedJavaMethod secondary; - private final ResolvedJavaMethod dynamic; + private final SnippetInfo exact = snippet(CheckCastSnippets.class, "checkcastExact"); + private final SnippetInfo primary = snippet(CheckCastSnippets.class, "checkcastPrimary"); + private final SnippetInfo secondary = snippet(CheckCastSnippets.class, "checkcastSecondary"); + private final SnippetInfo dynamic = snippet(CheckCastSnippets.class, "checkcastDynamic"); public Templates(CodeCacheProvider runtime, Replacements replacements, TargetDescription target) { - super(runtime, replacements, target, CheckCastSnippets.class); - exact = snippet("checkcastExact", Object.class, Word.class, boolean.class); - primary = snippet("checkcastPrimary", Word.class, Object.class, boolean.class, int.class); - secondary = snippet("checkcastSecondary", Word.class, Object.class, Word[].class, boolean.class); - dynamic = snippet("checkcastDynamic", Word.class, Object.class, boolean.class); + super(runtime, replacements, target); } /** @@ -193,31 +172,34 @@ public void lower(CheckCastNode checkcast, LoweringTool tool) { StructuredGraph graph = (StructuredGraph) checkcast.graph(); ValueNode object = checkcast.object(); - final HotSpotResolvedObjectType type = (HotSpotResolvedObjectType) checkcast.type(); + HotSpotResolvedObjectType type = (HotSpotResolvedObjectType) checkcast.type(); TypeCheckHints hintInfo = new TypeCheckHints(checkcast.type(), checkcast.profile(), tool.assumptions(), GraalOptions.CheckcastMinHintHitProbability, GraalOptions.CheckcastMaxHints); ValueNode hub = ConstantNode.forConstant(type.klass(), runtime, checkcast.graph()); - boolean checkNull = !object.stamp().nonNull(); - Arguments arguments; - Key key; - assert type != null; + Arguments args; if (hintInfo.exact) { ConstantNode[] hints = createHints(hintInfo, runtime, true, graph).hubs; assert hints.length == 1; - key = new Key(exact).add("checkNull", checkNull); - arguments = arguments("object", object).add("exactHub", hints[0]); + args = new Arguments(exact); + args.add("object", object); + args.add("exactHub", hints[0]); } else if (type.isPrimaryType()) { - key = new Key(primary).add("checkNull", checkNull).add("superCheckOffset", type.superCheckOffset()); - arguments = arguments("hub", hub).add("object", object); + args = new Arguments(primary); + args.add("hub", hub); + args.add("object", object); + args.addConst("superCheckOffset", type.superCheckOffset()); } else { ConstantNode[] hints = createHints(hintInfo, runtime, true, graph).hubs; - key = new Key(secondary).add("hints", Varargs.vargargs(new Word[hints.length], StampFactory.forKind(wordKind()))).add("checkNull", checkNull); - arguments = arguments("hub", hub).add("object", object).add("hints", hints); + args = new Arguments(secondary); + args.add("hub", hub); + args.add("object", object); + args.addVarargs("hints", Word.class, StampFactory.forKind(wordKind()), hints); } + args.addConst("checkNull", !object.stamp().nonNull()); - SnippetTemplate template = cache.get(key); - Debug.log("Lowering checkcast in %s: node=%s, template=%s, arguments=%s", graph, checkcast, template, arguments); - template.instantiate(runtime, checkcast, DEFAULT_REPLACER, arguments); + SnippetTemplate template = template(args); + Debug.log("Lowering checkcast in %s: node=%s, template=%s, arguments=%s", graph, checkcast, template, args); + template.instantiate(runtime, checkcast, DEFAULT_REPLACER, args); } /** @@ -225,16 +207,16 @@ */ public void lower(CheckCastDynamicNode checkcast) { StructuredGraph graph = (StructuredGraph) checkcast.graph(); - ValueNode hub = checkcast.type(); ValueNode object = checkcast.object(); - boolean checkNull = !object.stamp().nonNull(); - Key key = new Key(dynamic).add("checkNull", checkNull); - Arguments arguments = arguments("hub", hub).add("object", object); + Arguments args = new Arguments(dynamic); + args.add("hub", checkcast.type()); + args.add("object", object); + args.addConst("checkNull", !object.stamp().nonNull()); - SnippetTemplate template = cache.get(key); - Debug.log("Lowering dynamic checkcast in %s: node=%s, template=%s, arguments=%s", graph, checkcast, template, arguments); - template.instantiate(runtime, checkcast, DEFAULT_REPLACER, arguments); + SnippetTemplate template = template(args); + Debug.log("Lowering dynamic checkcast in %s: node=%s, template=%s, arguments=%s", graph, checkcast, template, args); + template.instantiate(runtime, checkcast, DEFAULT_REPLACER, args); } } } diff -r 2c933625b355 -r 92d2bedb5dfc graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/InstanceOfSnippets.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/InstanceOfSnippets.java Thu Apr 11 14:20:32 2013 -0700 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/InstanceOfSnippets.java Thu Apr 11 14:22:03 2013 -0700 @@ -24,21 +24,22 @@ import static com.oracle.graal.hotspot.replacements.HotSpotSnippetUtils.*; import static com.oracle.graal.hotspot.replacements.TypeCheckSnippetUtils.*; -import static com.oracle.graal.replacements.Snippet.Varargs.*; -import static com.oracle.graal.replacements.SnippetTemplate.Arguments.*; import static com.oracle.graal.replacements.nodes.BranchProbabilityNode.*; import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; import com.oracle.graal.hotspot.meta.*; +import com.oracle.graal.hotspot.replacements.TypeCheckSnippetUtils.Hints; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.java.*; import com.oracle.graal.nodes.spi.*; import com.oracle.graal.nodes.type.*; import com.oracle.graal.phases.*; import com.oracle.graal.replacements.*; -import com.oracle.graal.replacements.Snippet.*; -import com.oracle.graal.replacements.SnippetTemplate.*; +import com.oracle.graal.replacements.Snippet.ConstantParameter; +import com.oracle.graal.replacements.Snippet.VarargsParameter; +import com.oracle.graal.replacements.SnippetTemplate.Arguments; +import com.oracle.graal.replacements.SnippetTemplate.SnippetInfo; import com.oracle.graal.replacements.nodes.*; import com.oracle.graal.word.*; @@ -52,18 +53,11 @@ */ public class InstanceOfSnippets implements Snippets { - // @formatter:off - /** * A test against a final type. */ @Snippet - public static Object instanceofExact( - @Parameter("object") Object object, - @Parameter("exactHub") Word exactHub, - @Parameter("trueValue") Object trueValue, - @Parameter("falseValue") Object falseValue, - @ConstantParameter("checkNull") boolean checkNull) { + public static Object instanceofExact(Object object, Word exactHub, Object trueValue, Object falseValue, @ConstantParameter boolean checkNull) { if (checkNull && object == null) { probability(NOT_FREQUENT_PROBABILITY); isNull.inc(); @@ -83,13 +77,7 @@ * A test against a primary type. */ @Snippet - public static Object instanceofPrimary( - @Parameter("hub") Word hub, - @Parameter("object") Object object, - @Parameter("trueValue") Object trueValue, - @Parameter("falseValue") Object falseValue, - @ConstantParameter("checkNull") boolean checkNull, - @ConstantParameter("superCheckOffset") int superCheckOffset) { + public static Object instanceofPrimary(Word hub, Object object, @ConstantParameter int superCheckOffset, Object trueValue, Object falseValue, @ConstantParameter boolean checkNull) { if (checkNull && object == null) { probability(NOT_FREQUENT_PROBABILITY); isNull.inc(); @@ -109,14 +97,8 @@ * A test against a restricted secondary type type. */ @Snippet - public static Object instanceofSecondary( - @Parameter("hub") Word hub, - @Parameter("object") Object object, - @Parameter("trueValue") Object trueValue, - @Parameter("falseValue") Object falseValue, - @VarargsParameter("hints") Word[] hints, - @VarargsParameter("hintIsPositive") boolean[] hintIsPositive, - @ConstantParameter("checkNull") boolean checkNull) { + public static Object instanceofSecondary(Word hub, Object object, @VarargsParameter Word[] hints, @VarargsParameter boolean[] hintIsPositive, Object trueValue, Object falseValue, + @ConstantParameter boolean checkNull) { if (checkNull && object == null) { probability(NOT_FREQUENT_PROBABILITY); isNull.inc(); @@ -144,12 +126,7 @@ * Type test used when the type being tested against is not known at compile time. */ @Snippet - public static Object instanceofDynamic( - @Parameter("mirror") Class mirror, - @Parameter("object") Object object, - @Parameter("trueValue") Object trueValue, - @Parameter("falseValue") Object falseValue, - @ConstantParameter("checkNull") boolean checkNull) { + public static Object instanceofDynamic(Class mirror, Object object, Object trueValue, Object falseValue, @ConstantParameter boolean checkNull) { if (checkNull && object == null) { probability(NOT_FREQUENT_PROBABILITY); isNull.inc(); @@ -164,65 +141,63 @@ return trueValue; } - // @formatter:on - - public static class Templates extends InstanceOfSnippetsTemplates { + public static class Templates extends InstanceOfSnippetsTemplates { - private final ResolvedJavaMethod instanceofExact; - private final ResolvedJavaMethod instanceofPrimary; - private final ResolvedJavaMethod instanceofSecondary; - private final ResolvedJavaMethod instanceofDynamic; + private final SnippetInfo instanceofExact = snippet(InstanceOfSnippets.class, "instanceofExact"); + private final SnippetInfo instanceofPrimary = snippet(InstanceOfSnippets.class, "instanceofPrimary"); + private final SnippetInfo instanceofSecondary = snippet(InstanceOfSnippets.class, "instanceofSecondary"); + private final SnippetInfo instanceofDynamic = snippet(InstanceOfSnippets.class, "instanceofDynamic"); public Templates(CodeCacheProvider runtime, Replacements replacements, TargetDescription target) { - super(runtime, replacements, target, InstanceOfSnippets.class); - instanceofExact = snippet("instanceofExact", Object.class, Word.class, Object.class, Object.class, boolean.class); - instanceofPrimary = snippet("instanceofPrimary", Word.class, Object.class, Object.class, Object.class, boolean.class, int.class); - instanceofSecondary = snippet("instanceofSecondary", Word.class, Object.class, Object.class, Object.class, Word[].class, boolean[].class, boolean.class); - instanceofDynamic = snippet("instanceofDynamic", Class.class, Object.class, Object.class, Object.class, boolean.class); + super(runtime, replacements, target); } @Override - protected KeyAndArguments getKeyAndArguments(InstanceOfUsageReplacer replacer, LoweringTool tool) { + protected Arguments makeArguments(InstanceOfUsageReplacer replacer, LoweringTool tool) { if (replacer.instanceOf instanceof InstanceOfNode) { InstanceOfNode instanceOf = (InstanceOfNode) replacer.instanceOf; - ValueNode trueValue = replacer.trueValue; - ValueNode falseValue = replacer.falseValue; ValueNode object = instanceOf.object(); TypeCheckHints hintInfo = new TypeCheckHints(instanceOf.type(), instanceOf.profile(), tool.assumptions(), GraalOptions.InstanceOfMinHintHitProbability, GraalOptions.InstanceOfMaxHints); final HotSpotResolvedObjectType type = (HotSpotResolvedObjectType) instanceOf.type(); ConstantNode hub = ConstantNode.forConstant(type.klass(), runtime, instanceOf.graph()); - boolean checkNull = !object.stamp().nonNull(); - Arguments arguments; - Key key; + + Arguments args; if (hintInfo.exact) { ConstantNode[] hints = createHints(hintInfo, runtime, true, hub.graph()).hubs; assert hints.length == 1; - key = new Key(instanceofExact).add("checkNull", checkNull); - arguments = arguments("object", object).add("exactHub", hints[0]).add("trueValue", trueValue).add("falseValue", falseValue); + args = new Arguments(instanceofExact); + args.add("object", object); + args.add("exactHub", hints[0]); } else if (type.isPrimaryType()) { - key = new Key(instanceofPrimary).add("checkNull", checkNull).add("superCheckOffset", type.superCheckOffset()); - arguments = arguments("hub", hub).add("object", object).add("trueValue", trueValue).add("falseValue", falseValue); + args = new Arguments(instanceofPrimary); + args.add("hub", hub); + args.add("object", object); + args.addConst("superCheckOffset", type.superCheckOffset()); } else { Hints hints = createHints(hintInfo, runtime, false, hub.graph()); - ConstantNode[] hintHubs = hints.hubs; - boolean[] hintIsPositive = hints.isPositive; - Varargs hintsParam = vargargs(new Word[hintHubs.length], StampFactory.forKind(wordKind())); - Varargs hintIsPositiveParam = vargargs(new boolean[hintIsPositive.length], StampFactory.forKind(Kind.Boolean)); - key = new Key(instanceofSecondary).add("hints", hintsParam).add("hintIsPositive", hintIsPositiveParam).add("checkNull", checkNull); - arguments = arguments("hub", hub).add("object", object).add("hints", hintHubs).add("hintIsPositive", hintIsPositive).add("trueValue", trueValue).add("falseValue", falseValue); + args = new Arguments(instanceofSecondary); + args.add("hub", hub); + args.add("object", object); + args.addVarargs("hints", Word.class, StampFactory.forKind(wordKind()), hints.hubs); + args.addVarargs("hintIsPositive", boolean.class, StampFactory.forKind(Kind.Boolean), hints.isPositive); } - return new KeyAndArguments(key, arguments); + args.add("trueValue", replacer.trueValue); + args.add("falseValue", replacer.falseValue); + args.addConst("checkNull", !object.stamp().nonNull()); + return args; + } else { assert replacer.instanceOf instanceof InstanceOfDynamicNode; InstanceOfDynamicNode instanceOf = (InstanceOfDynamicNode) replacer.instanceOf; - ValueNode trueValue = replacer.trueValue; - ValueNode falseValue = replacer.falseValue; ValueNode object = instanceOf.object(); - ValueNode mirror = instanceOf.mirror(); - boolean checkNull = !object.stamp().nonNull(); - Key key = new Key(instanceofDynamic).add("checkNull", checkNull); - Arguments arguments = arguments("mirror", mirror).add("object", object).add("trueValue", trueValue).add("falseValue", falseValue); - return new KeyAndArguments(key, arguments); + + Arguments args = new Arguments(instanceofDynamic); + args.add("mirror", instanceOf.mirror()); + args.add("object", object); + args.add("trueValue", replacer.trueValue); + args.add("falseValue", replacer.falseValue); + args.addConst("checkNull", !object.stamp().nonNull()); + return args; } } } diff -r 2c933625b355 -r 92d2bedb5dfc graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/LoadExceptionObjectSnippets.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/LoadExceptionObjectSnippets.java Thu Apr 11 14:20:32 2013 -0700 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/LoadExceptionObjectSnippets.java Thu Apr 11 14:22:03 2013 -0700 @@ -27,16 +27,13 @@ import static com.oracle.graal.replacements.SnippetTemplate.*; import com.oracle.graal.api.code.*; -import com.oracle.graal.api.meta.*; -import com.oracle.graal.debug.*; -import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.java.*; import com.oracle.graal.nodes.spi.*; import com.oracle.graal.nodes.type.*; import com.oracle.graal.replacements.*; import com.oracle.graal.replacements.SnippetTemplate.AbstractTemplates; import com.oracle.graal.replacements.SnippetTemplate.Arguments; -import com.oracle.graal.replacements.SnippetTemplate.Key; +import com.oracle.graal.replacements.SnippetTemplate.SnippetInfo; import com.oracle.graal.word.*; /** @@ -53,23 +50,17 @@ return unsafeCast(exception, StampFactory.forNodeIntrinsic()); } - public static class Templates extends AbstractTemplates { + public static class Templates extends AbstractTemplates { - private final ResolvedJavaMethod loadException; + private final SnippetInfo loadException = snippet(LoadExceptionObjectSnippets.class, "loadException"); public Templates(CodeCacheProvider runtime, Replacements replacements, TargetDescription target) { - super(runtime, replacements, target, LoadExceptionObjectSnippets.class); - loadException = snippet("loadException"); + super(runtime, replacements, target); } public void lower(LoadExceptionObjectNode loadExceptionObject) { - StructuredGraph graph = (StructuredGraph) loadExceptionObject.graph(); - Arguments arguments = new Arguments(); - - Key key = new Key(loadException); - SnippetTemplate template = cache.get(key); - Debug.log("Lowering exception object in %s: node=%s, template=%s, arguments=%s", graph, loadExceptionObject, template, arguments); - template.instantiate(runtime, loadExceptionObject, DEFAULT_REPLACER, arguments); + Arguments args = new Arguments(loadException); + template(args).instantiate(runtime, loadExceptionObject, DEFAULT_REPLACER, args); } } } diff -r 2c933625b355 -r 92d2bedb5dfc graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/MonitorSnippets.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/MonitorSnippets.java Thu Apr 11 14:20:32 2013 -0700 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/MonitorSnippets.java Thu Apr 11 14:22:03 2013 -0700 @@ -46,7 +46,10 @@ import com.oracle.graal.nodes.spi.*; import com.oracle.graal.phases.common.*; import com.oracle.graal.replacements.*; -import com.oracle.graal.replacements.Snippet.*; +import com.oracle.graal.replacements.Snippet.ConstantParameter; +import com.oracle.graal.replacements.SnippetTemplate.AbstractTemplates; +import com.oracle.graal.replacements.SnippetTemplate.Arguments; +import com.oracle.graal.replacements.SnippetTemplate.SnippetInfo; import com.oracle.graal.word.*; /** @@ -73,7 +76,7 @@ public static final boolean CHECK_BALANCED_MONITORS = Boolean.getBoolean("graal.monitors.checkBalanced"); @Snippet - public static void monitorenter(@Parameter("object") Object object, @ConstantParameter("checkNull") boolean checkNull, @ConstantParameter("trace") boolean trace) { + public static void monitorenter(Object object, @ConstantParameter boolean checkNull, @ConstantParameter boolean trace) { verifyOop(object); if (checkNull && object == null) { @@ -262,7 +265,7 @@ * Calls straight out to the monitorenter stub. */ @Snippet - public static void monitorenterStub(@Parameter("object") Object object, @ConstantParameter("checkNull") boolean checkNull, @ConstantParameter("trace") boolean trace) { + public static void monitorenterStub(Object object, @ConstantParameter boolean checkNull, @ConstantParameter boolean trace) { verifyOop(object); incCounter(); if (checkNull && object == null) { @@ -276,7 +279,7 @@ } @Snippet - public static void monitorexit(@Parameter("object") Object object, @ConstantParameter("trace") boolean trace) { + public static void monitorexit(Object object, @ConstantParameter boolean trace) { trace(trace, " object: 0x%016lx\n", Word.fromObject(object)); if (useBiasedLocking()) { // Check for biased locking unlock case, which is a no-op @@ -328,7 +331,7 @@ * Calls straight out to the monitorexit stub. */ @Snippet - public static void monitorexitStub(@Parameter("object") Object object, @ConstantParameter("trace") boolean trace) { + public static void monitorexitStub(Object object, @ConstantParameter boolean trace) { verifyOop(object); traceObject(trace, "-lock{stub}", object); MonitorExitStubCall.call(object); @@ -398,54 +401,45 @@ } } - public static class Templates extends AbstractTemplates { + public static class Templates extends AbstractTemplates { - private final ResolvedJavaMethod monitorenter; - private final ResolvedJavaMethod monitorexit; - private final ResolvedJavaMethod monitorenterStub; - private final ResolvedJavaMethod monitorexitStub; - private final ResolvedJavaMethod monitorenterEliminated; - private final ResolvedJavaMethod monitorexitEliminated; - private final ResolvedJavaMethod initCounter; - private final ResolvedJavaMethod checkCounter; + private final SnippetInfo monitorenter = snippet(MonitorSnippets.class, "monitorenter"); + private final SnippetInfo monitorexit = snippet(MonitorSnippets.class, "monitorexit"); + private final SnippetInfo monitorenterStub = snippet(MonitorSnippets.class, "monitorenterStub"); + private final SnippetInfo monitorexitStub = snippet(MonitorSnippets.class, "monitorexitStub"); + private final SnippetInfo monitorenterEliminated = snippet(MonitorSnippets.class, "monitorenterEliminated"); + private final SnippetInfo monitorexitEliminated = snippet(MonitorSnippets.class, "monitorexitEliminated"); + private final SnippetInfo initCounter = snippet(MonitorSnippets.class, "initCounter"); + private final SnippetInfo checkCounter = snippet(MonitorSnippets.class, "checkCounter"); + private final boolean useFastLocking; public Templates(CodeCacheProvider runtime, Replacements replacements, TargetDescription target, boolean useFastLocking) { - super(runtime, replacements, target, MonitorSnippets.class); - monitorenter = snippet("monitorenter", Object.class, boolean.class, boolean.class); - monitorexit = snippet("monitorexit", Object.class, boolean.class); - monitorenterStub = snippet("monitorenterStub", Object.class, boolean.class, boolean.class); - monitorexitStub = snippet("monitorexitStub", Object.class, boolean.class); - monitorenterEliminated = snippet("monitorenterEliminated"); - monitorexitEliminated = snippet("monitorexitEliminated"); - initCounter = snippet("initCounter"); - checkCounter = snippet("checkCounter", String.class); + super(runtime, replacements, target); this.useFastLocking = useFastLocking; } public void lower(MonitorEnterNode monitorenterNode, @SuppressWarnings("unused") LoweringTool tool) { StructuredGraph graph = (StructuredGraph) monitorenterNode.graph(); - checkBalancedMonitors(graph); - FrameState stateAfter = monitorenterNode.stateAfter(); - boolean eliminated = monitorenterNode.eliminated(); - ResolvedJavaMethod method = eliminated ? monitorenterEliminated : useFastLocking ? monitorenter : monitorenterStub; - boolean checkNull = !monitorenterNode.object().stamp().nonNull(); - Key key = new Key(method); - if (method != monitorenterEliminated) { - key.add("checkNull", checkNull); - } - if (!eliminated) { - key.add("trace", isTracingEnabledForType(monitorenterNode.object()) || isTracingEnabledForMethod(stateAfter.method()) || isTracingEnabledForMethod(graph.method())); + + Arguments args; + if (monitorenterNode.eliminated()) { + args = new Arguments(monitorenterEliminated); + } else { + if (useFastLocking) { + args = new Arguments(monitorenter); + } else { + args = new Arguments(monitorenterStub); + } + args.add("object", monitorenterNode.object()); + args.addConst("checkNull", !monitorenterNode.object().stamp().nonNull()); + args.addConst("trace", isTracingEnabledForType(monitorenterNode.object()) || isTracingEnabledForMethod(stateAfter.method()) || isTracingEnabledForMethod(graph.method())); } - Arguments arguments = new Arguments(); - if (!eliminated) { - arguments.add("object", monitorenterNode.object()); - } - SnippetTemplate template = cache.get(key); - Map nodes = template.instantiate(runtime, monitorenterNode, DEFAULT_REPLACER, arguments); + Map nodes = template(args).instantiate(runtime, monitorenterNode, DEFAULT_REPLACER, args); + for (Node n : nodes.values()) { if (n instanceof BeginLockScopeNode) { BeginLockScopeNode begin = (BeginLockScopeNode) n; @@ -460,18 +454,22 @@ public void lower(MonitorExitNode monitorexitNode, @SuppressWarnings("unused") LoweringTool tool) { StructuredGraph graph = (StructuredGraph) monitorexitNode.graph(); FrameState stateAfter = monitorexitNode.stateAfter(); - boolean eliminated = monitorexitNode.eliminated(); - ResolvedJavaMethod method = eliminated ? monitorexitEliminated : useFastLocking ? monitorexit : monitorexitStub; - Key key = new Key(method); - if (!eliminated) { - key.add("trace", isTracingEnabledForType(monitorexitNode.object()) || isTracingEnabledForMethod(stateAfter.method()) || isTracingEnabledForMethod(graph.method())); + + Arguments args; + if (monitorexitNode.eliminated()) { + args = new Arguments(monitorexitEliminated); + } else { + if (useFastLocking) { + args = new Arguments(monitorexit); + } else { + args = new Arguments(monitorexitStub); + } + args.add("object", monitorexitNode.object()); + args.addConst("trace", isTracingEnabledForType(monitorexitNode.object()) || isTracingEnabledForMethod(stateAfter.method()) || isTracingEnabledForMethod(graph.method())); } - Arguments arguments = new Arguments(); - if (!eliminated) { - arguments.add("object", monitorexitNode.object()); - } - SnippetTemplate template = cache.get(key); - Map nodes = template.instantiate(runtime, monitorexitNode, DEFAULT_REPLACER, arguments); + + Map nodes = template(args).instantiate(runtime, monitorexitNode, DEFAULT_REPLACER, args); + for (Node n : nodes.values()) { if (n instanceof EndLockScopeNode) { EndLockScopeNode end = (EndLockScopeNode) n; @@ -521,27 +519,27 @@ NodeIterable nodes = graph.getNodes().filter(MonitorCounterNode.class); if (nodes.isEmpty()) { // Only insert the nodes if this is the first monitorenter being lowered. - JavaType returnType = initCounter.getSignature().getReturnType(initCounter.getDeclaringClass()); - MethodCallTargetNode callTarget = graph.add(new MethodCallTargetNode(InvokeKind.Static, initCounter, new ValueNode[0], returnType)); + JavaType returnType = initCounter.getMethod().getSignature().getReturnType(initCounter.getMethod().getDeclaringClass()); + MethodCallTargetNode callTarget = graph.add(new MethodCallTargetNode(InvokeKind.Static, initCounter.getMethod(), new ValueNode[0], returnType)); InvokeNode invoke = graph.add(new InvokeNode(callTarget, 0)); invoke.setStateAfter(graph.start().stateAfter()); graph.addAfterFixed(graph.start(), invoke); - StructuredGraph inlineeGraph = replacements.getSnippet(initCounter); + StructuredGraph inlineeGraph = replacements.getSnippet(initCounter.getMethod()); InliningUtil.inline(invoke, inlineeGraph, false); List rets = graph.getNodes().filter(ReturnNode.class).snapshot(); for (ReturnNode ret : rets) { - returnType = checkCounter.getSignature().getReturnType(checkCounter.getDeclaringClass()); + returnType = checkCounter.getMethod().getSignature().getReturnType(checkCounter.getMethod().getDeclaringClass()); Object msg = ((HotSpotRuntime) runtime).registerGCRoot("unbalanced monitors in " + MetaUtil.format("%H.%n(%p)", graph.method()) + ", count = %d"); ConstantNode errMsg = ConstantNode.forObject(msg, runtime, graph); - callTarget = graph.add(new MethodCallTargetNode(InvokeKind.Static, checkCounter, new ValueNode[]{errMsg}, returnType)); + callTarget = graph.add(new MethodCallTargetNode(InvokeKind.Static, checkCounter.getMethod(), new ValueNode[]{errMsg}, returnType)); invoke = graph.add(new InvokeNode(callTarget, 0)); List stack = Collections.emptyList(); FrameState stateAfter = new FrameState(graph.method(), FrameState.AFTER_BCI, new ValueNode[0], stack, new ValueNode[0], false, false); invoke.setStateAfter(graph.add(stateAfter)); graph.addBeforeFixed(ret, invoke); - inlineeGraph = replacements.getSnippet(checkCounter); + inlineeGraph = replacements.getSnippet(checkCounter.getMethod()); InliningUtil.inline(invoke, inlineeGraph, false); } } diff -r 2c933625b355 -r 92d2bedb5dfc graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/NewObjectSnippets.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/NewObjectSnippets.java Thu Apr 11 14:20:32 2013 -0700 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/NewObjectSnippets.java Thu Apr 11 14:22:03 2013 -0700 @@ -26,9 +26,7 @@ import static com.oracle.graal.hotspot.replacements.HotSpotSnippetUtils.*; import static com.oracle.graal.nodes.extended.UnsafeArrayCastNode.*; import static com.oracle.graal.nodes.extended.UnsafeCastNode.*; -import static com.oracle.graal.replacements.Snippet.Varargs.*; import static com.oracle.graal.replacements.SnippetTemplate.*; -import static com.oracle.graal.replacements.SnippetTemplate.Arguments.*; import static com.oracle.graal.replacements.nodes.BranchProbabilityNode.*; import static com.oracle.graal.replacements.nodes.ExplodeLoopNode.*; @@ -43,7 +41,11 @@ import com.oracle.graal.nodes.type.*; import com.oracle.graal.phases.*; import com.oracle.graal.replacements.*; -import com.oracle.graal.replacements.Snippet.*; +import com.oracle.graal.replacements.Snippet.ConstantParameter; +import com.oracle.graal.replacements.Snippet.VarargsParameter; +import com.oracle.graal.replacements.SnippetTemplate.AbstractTemplates; +import com.oracle.graal.replacements.SnippetTemplate.Arguments; +import com.oracle.graal.replacements.SnippetTemplate.SnippetInfo; import com.oracle.graal.replacements.nodes.*; import com.oracle.graal.word.*; @@ -52,15 +54,16 @@ */ public class NewObjectSnippets implements Snippets { - // @formatter:off - @Snippet - public static Word allocate(@Parameter("size") int size) { + public static Word allocate(int size) { Word thread = thread(); Word top = readTlabTop(thread); Word end = readTlabEnd(thread); Word newTop = top.add(size); - // this check might lead to problems if the TLAB is within 16GB of the address space end (checked in c++ code) + /* + * this check might lead to problems if the TLAB is within 16GB of the address space end + * (checked in c++ code) + */ if (newTop.belowOrEqual(end)) { probability(FAST_PATH_PROBABILITY); writeTlabTop(thread, newTop); @@ -70,13 +73,7 @@ } @Snippet - public static Object initializeObject( - @Parameter("memory") Word memory, - @Parameter("hub") Word hub, - @Parameter("prototypeMarkWord") Word prototypeMarkWord, - @ConstantParameter("size") int size, - @ConstantParameter("fillContents") boolean fillContents, - @ConstantParameter("locked") boolean locked) { + public static Object initializeObject(Word memory, Word hub, Word prototypeMarkWord, @ConstantParameter int size, @ConstantParameter boolean fillContents, @ConstantParameter boolean locked) { Object result; if (memory.equal(0)) { @@ -91,22 +88,17 @@ } result = memory.toObject(); } - /* make sure that the unsafeCast is anchored after initialization, - * see ReadAfterCheckCast and CheckCastSnippets */ + /* + * make sure that the unsafeCast is anchored after initialization, see ReadAfterCheckCast + * and CheckCastSnippets + */ BeginNode anchorNode = BeginNode.anchor(StampFactory.forNodeIntrinsic()); return unsafeCast(verifyOop(result), StampFactory.forNodeIntrinsic(), anchorNode); } @Snippet - public static Object initializeArray( - @Parameter("memory") Word memory, - @Parameter("hub") Word hub, - @Parameter("length") int length, - @Parameter("allocationSize") int allocationSize, - @Parameter("prototypeMarkWord") Word prototypeMarkWord, - @ConstantParameter("headerSize") int headerSize, - @ConstantParameter("fillContents") boolean fillContents, - @ConstantParameter("locked") boolean locked) { + public static Object initializeArray(Word memory, Word hub, int length, int allocationSize, Word prototypeMarkWord, @ConstantParameter int headerSize, @ConstantParameter boolean fillContents, + @ConstantParameter boolean locked) { if (locked) { return initializeArray(memory, hub, length, allocationSize, thread().or(biasedLockPattern()), headerSize, fillContents); } else { @@ -135,13 +127,8 @@ public static final int MAX_ARRAY_FAST_PATH_ALLOCATION_LENGTH = 0x00FFFFFF; @Snippet - public static Object allocateArrayAndInitialize( - @Parameter("length") int length, - @ConstantParameter("alignment") int alignment, - @ConstantParameter("headerSize") int headerSize, - @ConstantParameter("log2ElementSize") int log2ElementSize, - @ConstantParameter("fillContents") boolean fillContents, - @ConstantParameter("type") ResolvedJavaType type) { + public static Object allocateArrayAndInitialize(int length, @ConstantParameter int alignment, @ConstantParameter int headerSize, @ConstantParameter int log2ElementSize, + @ConstantParameter boolean fillContents, @ConstantParameter ResolvedJavaType type) { if (!belowThan(length, MAX_ARRAY_FAST_PATH_ALLOCATION_LENGTH)) { probability(DEOPT_PATH_PROBABILITY); // This handles both negative array sizes and very large array sizes @@ -153,9 +140,10 @@ } /** - * Computes the size of the memory chunk allocated for an array. This size accounts for the array - * header size, boy size and any padding after the last element to satisfy object alignment requirements. - * + * Computes the size of the memory chunk allocated for an array. This size accounts for the + * array header size, boy size and any padding after the last element to satisfy object + * alignment requirements. + * * @param length the number of elements in the array * @param alignment the object alignment requirement * @param headerSize the size of the array header @@ -171,10 +159,7 @@ * Calls the runtime stub for implementing MULTIANEWARRAY. */ @Snippet - public static Object newmultiarray( - @Parameter("hub") Word hub, - @ConstantParameter("rank") int rank, - @VarargsParameter("dimensions") int[] dimensions) { + public static Object newmultiarray(Word hub, @ConstantParameter int rank, @VarargsParameter int[] dimensions) { Word dims = DimensionsNode.allocaDimsArray(rank); ExplodeLoopNode.explodeLoop(); for (int i = 0; i < rank; i++) { @@ -184,9 +169,8 @@ } /** - * Maximum size of an object whose body is initialized by a sequence of - * zero-stores to its fields. Larger objects have their bodies initialized - * in a loop. + * Maximum size of an object whose body is initialized by a sequence of zero-stores to its + * fields. Larger objects have their bodies initialized in a loop. */ private static final int MAX_UNROLLED_OBJECT_ZEROING_SIZE = 10 * wordSize(); @@ -217,7 +201,10 @@ */ public static void formatArray(Word hub, int allocationSize, int length, int headerSize, Word memory, Word prototypeMarkWord, boolean fillContents) { memory.writeInt(arrayLengthOffset(), length, ANY_LOCATION); - // store hub last as the concurrent garbage collectors assume length is valid if hub field is not null + /* + * store hub last as the concurrent garbage collectors assume length is valid if hub field + * is not null + */ initializeObjectHeader(memory, prototypeMarkWord, hub); if (fillContents) { for (int offset = headerSize; offset < allocationSize; offset += wordSize()) { @@ -226,27 +213,19 @@ } } - // @formatter:on - - public static class Templates extends AbstractTemplates { + public static class Templates extends AbstractTemplates { - private final ResolvedJavaMethod allocate; - private final ResolvedJavaMethod initializeObject; - private final ResolvedJavaMethod initializeArray; - private final ResolvedJavaMethod allocateArrayAndInitialize; - private final ResolvedJavaMethod newmultiarray; - private final TargetDescription target; + private final SnippetInfo allocate = snippet(NewObjectSnippets.class, "allocate"); + private final SnippetInfo initializeObject = snippet(NewObjectSnippets.class, "initializeObject"); + private final SnippetInfo initializeArray = snippet(NewObjectSnippets.class, "initializeArray"); + private final SnippetInfo allocateArrayAndInitialize = snippet(NewObjectSnippets.class, "allocateArrayAndInitialize"); + private final SnippetInfo newmultiarray = snippet(NewObjectSnippets.class, "newmultiarray"); + private final boolean useTLAB; public Templates(CodeCacheProvider runtime, Replacements replacements, TargetDescription target, boolean useTLAB) { - super(runtime, replacements, target, NewObjectSnippets.class); - this.target = target; + super(runtime, replacements, target); this.useTLAB = useTLAB; - allocate = snippet("allocate", int.class); - initializeObject = snippet("initializeObject", Word.class, Word.class, Word.class, int.class, boolean.class, boolean.class); - initializeArray = snippet("initializeArray", Word.class, Word.class, int.class, int.class, Word.class, int.class, boolean.class, boolean.class); - allocateArrayAndInitialize = snippet("allocateArrayAndInitialize", int.class, int.class, int.class, int.class, boolean.class, ResolvedJavaType.class); - newmultiarray = snippet("newmultiarray", Word.class, int.class, int[].class); } /** @@ -289,9 +268,10 @@ int log2ElementSize = CodeUtil.log2(target.sizeInBytes(elementKind)); if (!useTLAB) { ConstantNode zero = ConstantNode.defaultForKind(target.wordKind, graph); - // value for 'size' doesn't matter as it isn't used since a stub call will be made - // anyway - // for both allocation and initialization - it just needs to be non-null + /* + * value for 'size' doesn't matter as it isn't used since a stub call will be made + * anyway for both allocation and initialization - it just needs to be non-null + */ ConstantNode size = ConstantNode.forInt(-1, graph); InitializeArrayNode initializeNode = graph.add(new InitializeArrayNode(zero, lengthNode, size, arrayType, newArrayNode.fillContents(), newArrayNode.locked())); graph.replaceFixedWithFixed(newArrayNode, initializeNode); @@ -304,12 +284,17 @@ InitializeArrayNode initializeNode = graph.add(new InitializeArrayNode(tlabAllocateNode, lengthNode, sizeNode, arrayType, newArrayNode.fillContents(), newArrayNode.locked())); graph.replaceFixedWithFixed(newArrayNode, initializeNode); } else { - Key key = new Key(allocateArrayAndInitialize).add("alignment", alignment).add("headerSize", headerSize).add("log2ElementSize", log2ElementSize).add("fillContents", - newArrayNode.fillContents()).add("type", arrayType); - Arguments arguments = new Arguments().add("length", lengthNode); - SnippetTemplate template = cache.get(key); - Debug.log("Lowering allocateArrayAndInitialize in %s: node=%s, template=%s, arguments=%s", graph, newArrayNode, template, arguments); - template.instantiate(runtime, newArrayNode, DEFAULT_REPLACER, arguments); + Arguments args = new Arguments(allocateArrayAndInitialize); + args.add("length", lengthNode); + args.addConst("alignment", alignment); + args.addConst("headerSize", headerSize); + args.addConst("log2ElementSize", log2ElementSize); + args.addConst("fillContents", newArrayNode.fillContents()); + args.addConst("type", arrayType); + + SnippetTemplate template = template(args); + Debug.log("Lowering allocateArrayAndInitialize in %s: node=%s, template=%s, arguments=%s", graph, newArrayNode, template, args); + template.instantiate(runtime, newArrayNode, DEFAULT_REPLACER, args); } } @@ -317,11 +302,11 @@ public void lower(TLABAllocateNode tlabAllocateNode, LoweringTool tool) { StructuredGraph graph = (StructuredGraph) tlabAllocateNode.graph(); ValueNode size = tlabAllocateNode.size(); - Key key = new Key(allocate); - Arguments arguments = arguments("size", size); - SnippetTemplate template = cache.get(key); - Debug.log("Lowering fastAllocate in %s: node=%s, template=%s, arguments=%s", graph, tlabAllocateNode, template, arguments); - template.instantiate(runtime, tlabAllocateNode, DEFAULT_REPLACER, arguments); + Arguments args = new Arguments(allocate).add("size", size); + + SnippetTemplate template = template(args); + Debug.log("Lowering fastAllocate in %s: node=%s, template=%s, arguments=%s", graph, tlabAllocateNode, template, args); + template.instantiate(runtime, tlabAllocateNode, DEFAULT_REPLACER, args); } @SuppressWarnings("unused") @@ -331,12 +316,18 @@ assert !type.isArray(); ConstantNode hub = ConstantNode.forConstant(type.klass(), runtime, graph); int size = instanceSize(type); - Key key = new Key(initializeObject).add("size", size).add("fillContents", initializeNode.fillContents()).add("locked", initializeNode.locked()); ValueNode memory = initializeNode.memory(); - Arguments arguments = arguments("memory", memory).add("hub", hub).add("prototypeMarkWord", type.prototypeMarkWord()); - SnippetTemplate template = cache.get(key); - Debug.log("Lowering initializeObject in %s: node=%s, template=%s, arguments=%s", graph, initializeNode, template, arguments); - template.instantiate(runtime, initializeNode, DEFAULT_REPLACER, arguments); + + Arguments args = new Arguments(initializeObject); + args.add("memory", memory); + args.add("hub", hub); + args.add("prototypeMarkWord", type.prototypeMarkWord()); + args.addConst("size", size).addConst("fillContents", initializeNode.fillContents()); + args.addConst("locked", initializeNode.locked()); + + SnippetTemplate template = template(args); + Debug.log("Lowering initializeObject in %s: node=%s, template=%s, arguments=%s", graph, initializeNode, template, args); + template.instantiate(runtime, initializeNode, DEFAULT_REPLACER, args); } @SuppressWarnings("unused") @@ -348,13 +339,21 @@ ConstantNode hub = ConstantNode.forConstant(type.klass(), runtime, graph); Kind elementKind = elementType.getKind(); final int headerSize = HotSpotRuntime.getArrayBaseOffset(elementKind); - Key key = new Key(initializeArray).add("headerSize", headerSize).add("fillContents", initializeNode.fillContents()).add("locked", initializeNode.locked()); ValueNode memory = initializeNode.memory(); - Arguments arguments = arguments("memory", memory).add("hub", hub).add("prototypeMarkWord", type.prototypeMarkWord()).add("allocationSize", initializeNode.allocationSize()).add("length", - initializeNode.length()); - SnippetTemplate template = cache.get(key); - Debug.log("Lowering initializeArray in %s: node=%s, template=%s, arguments=%s", graph, initializeNode, template, arguments); - template.instantiate(runtime, initializeNode, DEFAULT_REPLACER, arguments); + + Arguments args = new Arguments(initializeArray); + args.add("memory", memory); + args.add("hub", hub); + args.add("length", initializeNode.length()); + args.add("allocationSize", initializeNode.allocationSize()); + args.add("prototypeMarkWord", type.prototypeMarkWord()); + args.addConst("headerSize", headerSize); + args.addConst("fillContents", initializeNode.fillContents()); + args.addConst("locked", initializeNode.locked()); + + SnippetTemplate template = template(args); + Debug.log("Lowering initializeArray in %s: node=%s, template=%s, arguments=%s", graph, initializeNode, template, args); + template.instantiate(runtime, initializeNode, DEFAULT_REPLACER, args); } @SuppressWarnings("unused") @@ -367,10 +366,12 @@ } HotSpotResolvedObjectType type = (HotSpotResolvedObjectType) newmultiarrayNode.type(); ConstantNode hub = ConstantNode.forConstant(type.klass(), runtime, graph); - Key key = new Key(newmultiarray).add("dimensions", vargargs(new int[rank], StampFactory.forKind(Kind.Int))).add("rank", rank); - Arguments arguments = arguments("dimensions", dims).add("hub", hub); - SnippetTemplate template = cache.get(key); - template.instantiate(runtime, newmultiarrayNode, DEFAULT_REPLACER, arguments); + + Arguments args = new Arguments(newmultiarray); + args.add("hub", hub); + args.addConst("rank", rank); + args.addVarargs("dimensions", int.class, StampFactory.forKind(Kind.Int), dims); + template(args).instantiate(runtime, newmultiarrayNode, DEFAULT_REPLACER, args); } private static int instanceSize(HotSpotResolvedObjectType type) { diff -r 2c933625b355 -r 92d2bedb5dfc graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/WriteBarrierSnippets.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/WriteBarrierSnippets.java Thu Apr 11 14:20:32 2013 -0700 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/WriteBarrierSnippets.java Thu Apr 11 14:22:03 2013 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2013, 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 @@ -31,18 +31,17 @@ import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.spi.*; import com.oracle.graal.replacements.*; -import com.oracle.graal.replacements.nodes.*; import com.oracle.graal.replacements.Snippet.ConstantParameter; -import com.oracle.graal.replacements.Snippet.Parameter; import com.oracle.graal.replacements.SnippetTemplate.AbstractTemplates; import com.oracle.graal.replacements.SnippetTemplate.Arguments; -import com.oracle.graal.replacements.SnippetTemplate.Key; +import com.oracle.graal.replacements.SnippetTemplate.SnippetInfo; +import com.oracle.graal.replacements.nodes.*; import com.oracle.graal.word.*; public class WriteBarrierSnippets implements Snippets { @Snippet - public static void serialArrayWriteBarrier(@Parameter("object") Object obj, @Parameter("location") Object location, @ConstantParameter("usePrecise") boolean usePrecise) { + public static void serialArrayWriteBarrier(Object obj, Object location, @ConstantParameter boolean usePrecise) { Object object = FixedValueAnchorNode.getObject(obj); Pointer oop; if (usePrecise) { @@ -62,7 +61,7 @@ } @Snippet - public static void serialArrayRangeWriteBarrier(@Parameter("object") Object object, @Parameter("startIndex") int startIndex, @Parameter("length") int length) { + public static void serialArrayRangeWriteBarrier(Object object, int startIndex, int length) { Object dest = FixedValueAnchorNode.getObject(object); int cardShift = cardTableShift(); long cardStart = cardTableStart(); @@ -77,37 +76,29 @@ } } - public static class Templates extends AbstractTemplates { + public static class Templates extends AbstractTemplates { - private final ResolvedJavaMethod serialArrayWriteBarrier; - private final ResolvedJavaMethod serialArrayRangeWriteBarrier; + private final SnippetInfo serialArrayWriteBarrier = snippet(WriteBarrierSnippets.class, "serialArrayWriteBarrier"); + private final SnippetInfo serialArrayRangeWriteBarrier = snippet(WriteBarrierSnippets.class, "serialArrayRangeWriteBarrier"); public Templates(CodeCacheProvider runtime, Replacements replacements, TargetDescription target) { - super(runtime, replacements, target, WriteBarrierSnippets.class); - serialArrayWriteBarrier = snippet("serialArrayWriteBarrier", Object.class, Object.class, boolean.class); - serialArrayRangeWriteBarrier = snippet("serialArrayRangeWriteBarrier", Object.class, int.class, int.class); + super(runtime, replacements, target); } public void lower(SerialWriteBarrier arrayWriteBarrier, @SuppressWarnings("unused") LoweringTool tool) { - ResolvedJavaMethod method = serialArrayWriteBarrier; - Key key = new Key(method); - key.add("usePrecise", arrayWriteBarrier.usePrecise()); - Arguments arguments = new Arguments(); - arguments.add("object", arrayWriteBarrier.getObject()); - arguments.add("location", arrayWriteBarrier.getLocation()); - SnippetTemplate template = cache.get(key); - template.instantiate(runtime, arrayWriteBarrier, DEFAULT_REPLACER, arguments); + Arguments args = new Arguments(serialArrayWriteBarrier); + args.add("obj", arrayWriteBarrier.getObject()); + args.add("location", arrayWriteBarrier.getLocation()); + args.addConst("usePrecise", arrayWriteBarrier.usePrecise()); + template(args).instantiate(runtime, arrayWriteBarrier, DEFAULT_REPLACER, args); } public void lower(SerialArrayRangeWriteBarrier arrayRangeWriteBarrier, @SuppressWarnings("unused") LoweringTool tool) { - ResolvedJavaMethod method = serialArrayRangeWriteBarrier; - Key key = new Key(method); - Arguments arguments = new Arguments(); - arguments.add("object", arrayRangeWriteBarrier.getObject()); - arguments.add("startIndex", arrayRangeWriteBarrier.getStartIndex()); - arguments.add("length", arrayRangeWriteBarrier.getLength()); - SnippetTemplate template = cache.get(key); - template.instantiate(runtime, arrayRangeWriteBarrier, DEFAULT_REPLACER, arguments); + Arguments args = new Arguments(serialArrayRangeWriteBarrier); + args.add("object", arrayRangeWriteBarrier.getObject()); + args.add("startIndex", arrayRangeWriteBarrier.getStartIndex()); + args.add("length", arrayRangeWriteBarrier.getLength()); + template(args).instantiate(runtime, arrayRangeWriteBarrier, DEFAULT_REPLACER, args); } } } diff -r 2c933625b355 -r 92d2bedb5dfc graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/NewArrayStub.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/NewArrayStub.java Thu Apr 11 14:20:32 2013 -0700 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/NewArrayStub.java Thu Apr 11 14:22:03 2013 -0700 @@ -27,15 +27,15 @@ import static com.oracle.graal.hotspot.stubs.NewInstanceStub.*; import com.oracle.graal.api.code.*; -import com.oracle.graal.api.meta.*; import com.oracle.graal.hotspot.*; import com.oracle.graal.hotspot.meta.*; import com.oracle.graal.hotspot.nodes.*; import com.oracle.graal.hotspot.replacements.*; import com.oracle.graal.nodes.spi.*; import com.oracle.graal.replacements.*; -import com.oracle.graal.replacements.Snippet.*; -import com.oracle.graal.replacements.SnippetTemplate.*; +import com.oracle.graal.replacements.Snippet.ConstantParameter; +import com.oracle.graal.replacements.SnippetTemplate.Arguments; +import com.oracle.graal.replacements.SnippetTemplate.SnippetInfo; import com.oracle.graal.word.*; /** @@ -47,14 +47,19 @@ public class NewArrayStub extends Stub { public NewArrayStub(final HotSpotRuntime runtime, Replacements replacements, TargetDescription target, HotSpotRuntimeCallTarget linkage) { - super(runtime, replacements, target, linkage); + super(runtime, replacements, target, linkage, "newArray"); } @Override - protected void populateKey(Key key) { + protected Arguments makeArguments(SnippetInfo stub) { HotSpotResolvedObjectType intArrayType = (HotSpotResolvedObjectType) runtime.lookupJavaType(int[].class); - Constant intArrayHub = intArrayType.klass(); - key.add("intArrayHub", intArrayHub).add("log", Boolean.getBoolean("graal.logNewArrayStub")); + + Arguments args = new Arguments(stub); + args.add("hub", null); + args.add("length", null); + args.addConst("intArrayHub", intArrayType.klass()); + args.addConst("log", Boolean.getBoolean("graal.logNewArrayStub")); + return args; } /** @@ -67,7 +72,7 @@ * @param log specifies if logging is enabled */ @Snippet - private static Object newArray(@Parameter("hub") Word hub, @Parameter("length") int length, @ConstantParameter("intArrayHub") Word intArrayHub, @ConstantParameter("log") boolean log) { + private static Object newArray(Word hub, int length, @ConstantParameter Word intArrayHub, @ConstantParameter boolean log) { int layoutHelper = hub.readInt(layoutHelperOffset(), FINAL_LOCATION); int log2ElementSize = (layoutHelper >> layoutHelperLog2ElementSizeShift()) & layoutHelperLog2ElementSizeMask(); int headerSize = (layoutHelper >> layoutHelperHeaderSizeShift()) & layoutHelperHeaderSizeMask(); diff -r 2c933625b355 -r 92d2bedb5dfc graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/NewInstanceStub.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/NewInstanceStub.java Thu Apr 11 14:20:32 2013 -0700 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/NewInstanceStub.java Thu Apr 11 14:22:03 2013 -0700 @@ -36,8 +36,8 @@ import com.oracle.graal.replacements.*; import com.oracle.graal.replacements.Snippet.ConstantParameter; import com.oracle.graal.replacements.Snippet.Fold; -import com.oracle.graal.replacements.Snippet.Parameter; -import com.oracle.graal.replacements.SnippetTemplate.Key; +import com.oracle.graal.replacements.SnippetTemplate.Arguments; +import com.oracle.graal.replacements.SnippetTemplate.SnippetInfo; import com.oracle.graal.word.*; /** @@ -49,14 +49,18 @@ public class NewInstanceStub extends Stub { public NewInstanceStub(final HotSpotRuntime runtime, Replacements replacements, TargetDescription target, HotSpotRuntimeCallTarget linkage) { - super(runtime, replacements, target, linkage); + super(runtime, replacements, target, linkage, "newInstance"); } @Override - protected void populateKey(Key key) { + protected Arguments makeArguments(SnippetInfo stub) { HotSpotResolvedObjectType intArrayType = (HotSpotResolvedObjectType) runtime.lookupJavaType(int[].class); - Constant intArrayHub = intArrayType.klass(); - key.add("intArrayHub", intArrayHub).add("log", Boolean.getBoolean("graal.logNewInstanceStub")); + + Arguments args = new Arguments(stub); + args.add("hub", null); + args.addConst("intArrayHub", intArrayType.klass()); + args.addConst("log", Boolean.getBoolean("graal.logNewInstanceStub")); + return args; } /** @@ -67,7 +71,7 @@ * @param intArrayHub the hub for {@code int[].class} */ @Snippet - private static Object newInstance(@Parameter("hub") Word hub, @ConstantParameter("intArrayHub") Word intArrayHub, @ConstantParameter("log") boolean log) { + private static Object newInstance(Word hub, @ConstantParameter Word intArrayHub, @ConstantParameter boolean log) { int sizeInBytes = hub.readInt(klassInstanceSizeOffset(), FINAL_LOCATION); if (!forceSlowPath() && inlineContiguousAllocationSupported()) { if (hub.readInt(klassStateOffset(), CLASS_STATE_LOCATION) == klassStateFullyInitialized()) { diff -r 2c933625b355 -r 92d2bedb5dfc graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/Stub.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/Stub.java Thu Apr 11 14:20:32 2013 -0700 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/Stub.java Thu Apr 11 14:22:03 2013 -0700 @@ -22,9 +22,6 @@ */ package com.oracle.graal.hotspot.stubs; -import static java.lang.reflect.Modifier.*; - -import java.lang.reflect.*; import java.util.concurrent.*; import com.oracle.graal.api.code.*; @@ -42,7 +39,8 @@ import com.oracle.graal.replacements.*; import com.oracle.graal.replacements.Snippet.ConstantParameter; import com.oracle.graal.replacements.SnippetTemplate.AbstractTemplates; -import com.oracle.graal.replacements.SnippetTemplate.Key; +import com.oracle.graal.replacements.SnippetTemplate.Arguments; +import com.oracle.graal.replacements.SnippetTemplate.SnippetInfo; /** * Base class for implementing some low level code providing the out-of-line slow path for a @@ -56,7 +54,7 @@ /** * The method implementing the stub. */ - protected final HotSpotResolvedJavaMethod stubMethod; + protected final SnippetInfo stubInfo; /** * The linkage information for the stub. @@ -69,15 +67,14 @@ protected InstalledCode stubCode; /** - * Creates a new stub container. The new stub still needs to be {@linkplain #getAddress(Backend) - * installed}. + * Creates a new stub container. The new stub still needs to be + * {@linkplain #getAddress(Backend) installed}. * * @param linkage linkage details for a call to the stub */ - @SuppressWarnings("unchecked") - public Stub(HotSpotRuntime runtime, Replacements replacements, TargetDescription target, HotSpotRuntimeCallTarget linkage) { - super(runtime, replacements, target, null); - stubMethod = findStubMethod(runtime, getClass()); + public Stub(HotSpotRuntime runtime, Replacements replacements, TargetDescription target, HotSpotRuntimeCallTarget linkage, String methodName) { + super(runtime, replacements, target); + this.stubInfo = snippet(getClass(), methodName); this.linkage = linkage; } @@ -85,7 +82,7 @@ /** * Adds the {@linkplain ConstantParameter constant} arguments of this stub. */ - protected abstract void populateKey(Key key); + protected abstract Arguments makeArguments(SnippetInfo stub); protected HotSpotRuntime runtime() { return (HotSpotRuntime) runtime; @@ -95,7 +92,7 @@ * Gets the method implementing this stub. */ public ResolvedJavaMethod getMethod() { - return stubMethod; + return stubInfo.getMethod(); } public HotSpotRuntimeCallTarget getLinkage() { @@ -109,25 +106,22 @@ */ public synchronized long getAddress(Backend backend) { if (stubCode == null) { - StructuredGraph graph = replacements.getSnippet(stubMethod); - - Key key = new Key(stubMethod); - populateKey(key); - SnippetTemplate template = cache.get(key); - graph = template.copySpecializedGraph(); + Arguments args = makeArguments(stubInfo); + SnippetTemplate template = template(args); + StructuredGraph graph = template.copySpecializedGraph(); PhasePlan phasePlan = new PhasePlan(); GraphBuilderPhase graphBuilderPhase = new GraphBuilderPhase(runtime, GraphBuilderConfiguration.getDefault(), OptimisticOptimizations.ALL); phasePlan.addPhase(PhasePosition.AFTER_PARSING, graphBuilderPhase); - final CompilationResult compResult = GraalCompiler.compileMethod(runtime(), replacements, backend, runtime().getTarget(), stubMethod, graph, null, phasePlan, - OptimisticOptimizations.ALL, new SpeculationLog()); + final CompilationResult compResult = GraalCompiler.compileMethod(runtime(), replacements, backend, runtime().getTarget(), getMethod(), graph, null, phasePlan, OptimisticOptimizations.ALL, + new SpeculationLog()); - stubCode = Debug.scope("CodeInstall", new Object[]{runtime(), stubMethod}, new Callable() { + stubCode = Debug.scope("CodeInstall", new Object[]{runtime(), getMethod()}, new Callable() { @Override public InstalledCode call() { - InstalledCode installedCode = runtime().addMethod(stubMethod, compResult); - assert installedCode != null : "error installing stub " + stubMethod; + InstalledCode installedCode = runtime().addMethod(getMethod(), compResult); + assert installedCode != null : "error installing stub " + getMethod(); if (Debug.isDumpEnabled()) { Debug.dump(new Object[]{compResult, installedCode}, "After code installation"); } @@ -135,24 +129,8 @@ } }); - assert stubCode != null : "error installing stub " + stubMethod; + assert stubCode != null : "error installing stub " + getMethod(); } return stubCode.getStart(); } - - /** - * Finds the static method annotated with {@link Snippet} in a given class of which there must - * be exactly one. - */ - private static HotSpotResolvedJavaMethod findStubMethod(HotSpotRuntime runtime, Class stubClass) { - HotSpotResolvedJavaMethod m = null; - for (Method candidate : stubClass.getDeclaredMethods()) { - if (isStatic(candidate.getModifiers()) && candidate.getAnnotation(Snippet.class) != null) { - assert m == null : "more than one method annotated with @" + Snippet.class.getSimpleName() + " in " + stubClass; - m = (HotSpotResolvedJavaMethod) runtime.lookupJavaMethod(candidate); - } - } - assert m != null : "no static method annotated with @" + Snippet.class.getSimpleName() + " in " + stubClass; - return m; - } } diff -r 2c933625b355 -r 92d2bedb5dfc graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/Replacements.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/Replacements.java Thu Apr 11 14:20:32 2013 -0700 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/Replacements.java Thu Apr 11 14:22:03 2013 -0700 @@ -63,11 +63,6 @@ Assumptions getAssumptions(); /** - * Registers all the snippet methods defined by a given class. - */ - void registerSnippets(Class snippets); - - /** * Registers all the {@linkplain MethodSubstitution method} and {@linkplain MacroSubstitution * macro} substitutions defined by a given class. */ diff -r 2c933625b355 -r 92d2bedb5dfc graal/com.oracle.graal.replacements.amd64/src/com/oracle/graal/replacements/amd64/AMD64ConvertSnippets.java --- a/graal/com.oracle.graal.replacements.amd64/src/com/oracle/graal/replacements/amd64/AMD64ConvertSnippets.java Thu Apr 11 14:20:32 2013 -0700 +++ b/graal/com.oracle.graal.replacements.amd64/src/com/oracle/graal/replacements/amd64/AMD64ConvertSnippets.java Thu Apr 11 14:22:03 2013 -0700 @@ -23,18 +23,20 @@ package com.oracle.graal.replacements.amd64; import static com.oracle.graal.replacements.SnippetTemplate.*; -import static com.oracle.graal.replacements.SnippetTemplate.Arguments.*; import static com.oracle.graal.replacements.nodes.BranchProbabilityNode.*; +import java.util.*; + import com.oracle.graal.api.code.*; -import com.oracle.graal.api.meta.*; import com.oracle.graal.debug.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.calc.*; import com.oracle.graal.nodes.calc.ConvertNode.Op; import com.oracle.graal.nodes.spi.*; import com.oracle.graal.replacements.*; -import com.oracle.graal.replacements.Snippet.*; +import com.oracle.graal.replacements.SnippetTemplate.AbstractTemplates; +import com.oracle.graal.replacements.SnippetTemplate.Arguments; +import com.oracle.graal.replacements.SnippetTemplate.SnippetInfo; /** * Snippets used for conversion operations on AMD64 where the AMD64 instruction used does not match @@ -54,7 +56,7 @@ * @param result the result produced by the CVTTSS2SI instruction */ @Snippet - public static int f2i(@Parameter("input") float input, @Parameter("result") int result) { + public static int f2i(float input, int result) { if (result == Integer.MIN_VALUE) { probability(NOT_FREQUENT_PROBABILITY); if (Float.isNaN(input)) { @@ -80,7 +82,7 @@ * @param result the result produced by the CVTTSS2SI instruction */ @Snippet - public static long f2l(@Parameter("input") float input, @Parameter("result") long result) { + public static long f2l(float input, long result) { if (result == Long.MIN_VALUE) { probability(NOT_FREQUENT_PROBABILITY); if (Float.isNaN(input)) { @@ -106,7 +108,7 @@ * @param result the result produced by the CVTTSS2SI instruction */ @Snippet - public static int d2i(@Parameter("input") double input, @Parameter("result") int result) { + public static int d2i(double input, int result) { if (result == Integer.MIN_VALUE) { probability(NOT_FREQUENT_PROBABILITY); if (Double.isNaN(input)) { @@ -132,7 +134,7 @@ * @param result the result produced by the CVTTSS2SI instruction */ @Snippet - public static long d2l(@Parameter("input") double input, @Parameter("result") long result) { + public static long d2l(double input, long result) { if (result == Long.MIN_VALUE) { probability(NOT_FREQUENT_PROBABILITY); if (Double.isNaN(input)) { @@ -146,34 +148,26 @@ return result; } - public static class Templates extends AbstractTemplates { + public static class Templates extends AbstractTemplates { - private final ResolvedJavaMethod f2i; - private final ResolvedJavaMethod f2l; - private final ResolvedJavaMethod d2i; - private final ResolvedJavaMethod d2l; + private final EnumMap snippets; public Templates(CodeCacheProvider runtime, Replacements replacements, TargetDescription target) { - super(runtime, replacements, target, AMD64ConvertSnippets.class); - f2i = snippet("f2i", float.class, int.class); - f2l = snippet("f2l", float.class, long.class); - d2i = snippet("d2i", double.class, int.class); - d2l = snippet("d2l", double.class, long.class); + super(runtime, replacements, target); + + snippets = new EnumMap<>(Op.class); + snippets.put(Op.F2I, snippet(AMD64ConvertSnippets.class, "f2i")); + snippets.put(Op.F2L, snippet(AMD64ConvertSnippets.class, "f2l")); + snippets.put(Op.D2I, snippet(AMD64ConvertSnippets.class, "d2i")); + snippets.put(Op.D2L, snippet(AMD64ConvertSnippets.class, "d2l")); } public void lower(ConvertNode convert, LoweringTool tool) { - if (convert.opcode == Op.F2I) { - lower0(convert, tool, f2i); - } else if (convert.opcode == Op.F2L) { - lower0(convert, tool, f2l); - } else if (convert.opcode == Op.D2I) { - lower0(convert, tool, d2i); - } else if (convert.opcode == Op.D2L) { - lower0(convert, tool, d2l); + SnippetInfo key = snippets.get(convert.opcode); + if (key == null) { + return; } - } - private void lower0(ConvertNode convert, LoweringTool tool, ResolvedJavaMethod snippet) { StructuredGraph graph = (StructuredGraph) convert.graph(); // Insert a unique placeholder node in place of the Convert node so that the @@ -183,11 +177,13 @@ LocalNode replacee = graph.add(new LocalNode(Integer.MAX_VALUE, convert.stamp())); convert.replaceAtUsages(replacee); - Key key = new Key(snippet); - Arguments arguments = arguments("input", convert.value()).add("result", convert); - SnippetTemplate template = cache.get(key); - Debug.log("Lowering %s in %s: node=%s, template=%s, arguments=%s", convert.opcode, graph, convert, template, arguments); - template.instantiate(runtime, replacee, DEFAULT_REPLACER, tool, arguments); + Arguments args = new Arguments(key); + args.add("input", convert.value()); + args.add("result", convert); + + SnippetTemplate template = template(args); + Debug.log("Lowering %s in %s: node=%s, template=%s, arguments=%s", convert.opcode, graph, convert, template, args); + template.instantiate(runtime, replacee, DEFAULT_REPLACER, tool, args); } } } diff -r 2c933625b355 -r 92d2bedb5dfc graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/BoxingSnippets.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/BoxingSnippets.java Thu Apr 11 14:22:03 2013 -0700 @@ -0,0 +1,243 @@ +/* + * Copyright (c) 2012, 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.replacements; + +import static com.oracle.graal.replacements.SnippetTemplate.*; + +import java.lang.reflect.*; +import java.util.*; + +import com.oracle.graal.api.code.*; +import com.oracle.graal.api.meta.*; +import com.oracle.graal.debug.*; +import com.oracle.graal.graph.Node.NodeIntrinsic; +import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.calc.*; +import com.oracle.graal.nodes.extended.*; +import com.oracle.graal.nodes.spi.*; +import com.oracle.graal.nodes.type.*; +import com.oracle.graal.phases.*; +import com.oracle.graal.replacements.Snippet.Fold; +import com.oracle.graal.replacements.Snippet.SnippetInliningPolicy; +import com.oracle.graal.replacements.SnippetTemplate.AbstractTemplates; +import com.oracle.graal.replacements.SnippetTemplate.Arguments; +import com.oracle.graal.replacements.SnippetTemplate.SnippetInfo; +import com.oracle.graal.word.*; + +public class BoxingSnippets implements Snippets { + + /** + * This snippet inlining policy differs from the default one in that it does normal inlining of + * boxing methods like {@link Integer#valueOf(int)} (as opposed to method substitution). + */ + public static class BoxingSnippetInliningPolicy implements SnippetInliningPolicy { + + @Override + public boolean shouldInline(ResolvedJavaMethod method, ResolvedJavaMethod caller) { + if (Modifier.isNative(method.getModifiers())) { + return false; + } + if (method.getAnnotation(Fold.class) != null) { + return false; + } + if (method.getAnnotation(NodeIntrinsic.class) != null) { + return false; + } + if (method.getAnnotation(Word.Operation.class) != null) { + return false; + } + return true; + } + + @Override + public boolean shouldUseReplacement(ResolvedJavaMethod callee, ResolvedJavaMethod methodToParse) { + return false; + } + } + + @Snippet(inlining = BoxingSnippetInliningPolicy.class) + public static Boolean booleanValueOf(boolean value) { + valueOfCounter.inc(); + return UnsafeCastNode.unsafeCast(Boolean.valueOf(value), StampFactory.forNodeIntrinsic()); + } + + @Snippet(inlining = BoxingSnippetInliningPolicy.class) + public static Byte byteValueOf(byte value) { + valueOfCounter.inc(); + return UnsafeCastNode.unsafeCast(Byte.valueOf(value), StampFactory.forNodeIntrinsic()); + } + + @Snippet(inlining = BoxingSnippetInliningPolicy.class) + public static Character charValueOf(char value) { + valueOfCounter.inc(); + return UnsafeCastNode.unsafeCast(Character.valueOf(value), StampFactory.forNodeIntrinsic()); + } + + @Snippet(inlining = BoxingSnippetInliningPolicy.class) + public static Double doubleValueOf(double value) { + valueOfCounter.inc(); + return UnsafeCastNode.unsafeCast(Double.valueOf(value), StampFactory.forNodeIntrinsic()); + } + + @Snippet(inlining = BoxingSnippetInliningPolicy.class) + public static Float floatValueOf(float value) { + valueOfCounter.inc(); + return UnsafeCastNode.unsafeCast(Float.valueOf(value), StampFactory.forNodeIntrinsic()); + } + + @Snippet(inlining = BoxingSnippetInliningPolicy.class) + public static Integer intValueOf(int value) { + valueOfCounter.inc(); + return UnsafeCastNode.unsafeCast(Integer.valueOf(value), StampFactory.forNodeIntrinsic()); + } + + @Snippet(inlining = BoxingSnippetInliningPolicy.class) + public static Long longValueOf(long value) { + valueOfCounter.inc(); + return UnsafeCastNode.unsafeCast(Long.valueOf(value), StampFactory.forNodeIntrinsic()); + } + + @Snippet(inlining = BoxingSnippetInliningPolicy.class) + public static Short shortValueOf(short value) { + valueOfCounter.inc(); + return UnsafeCastNode.unsafeCast(Short.valueOf(value), StampFactory.forNodeIntrinsic()); + } + + @Snippet(inlining = BoxingSnippetInliningPolicy.class) + public static boolean booleanValue(Boolean value) { + valueOfCounter.inc(); + return value.booleanValue(); + } + + @Snippet(inlining = BoxingSnippetInliningPolicy.class) + public static byte byteValue(Byte value) { + valueOfCounter.inc(); + return value.byteValue(); + } + + @Snippet(inlining = BoxingSnippetInliningPolicy.class) + public static char charValue(Character value) { + valueOfCounter.inc(); + return value.charValue(); + } + + @Snippet(inlining = BoxingSnippetInliningPolicy.class) + public static double doubleValue(Double value) { + valueOfCounter.inc(); + return value.doubleValue(); + } + + @Snippet(inlining = BoxingSnippetInliningPolicy.class) + public static float floatValue(Float value) { + valueOfCounter.inc(); + return value.floatValue(); + } + + @Snippet(inlining = BoxingSnippetInliningPolicy.class) + public static int intValue(Integer value) { + valueOfCounter.inc(); + return value.intValue(); + } + + @Snippet(inlining = BoxingSnippetInliningPolicy.class) + public static long longValue(Long value) { + valueOfCounter.inc(); + return value.longValue(); + } + + @Snippet(inlining = BoxingSnippetInliningPolicy.class) + public static short shortValue(Short value) { + valueOfCounter.inc(); + return value.shortValue(); + } + + public static FloatingNode canonicalizeBoxing(BoxNode box, MetaAccessProvider runtime) { + ValueNode value = box.getValue(); + if (value.isConstant()) { + Constant sourceConstant = value.asConstant(); + switch (box.getBoxingKind()) { + case Boolean: + return ConstantNode.forObject(Boolean.valueOf(sourceConstant.asInt() != 0), runtime, box.graph()); + case Byte: + return ConstantNode.forObject(Byte.valueOf((byte) sourceConstant.asInt()), runtime, box.graph()); + case Char: + return ConstantNode.forObject(Character.valueOf((char) sourceConstant.asInt()), runtime, box.graph()); + case Short: + return ConstantNode.forObject(Short.valueOf((short) sourceConstant.asInt()), runtime, box.graph()); + case Int: + return ConstantNode.forObject(Integer.valueOf(sourceConstant.asInt()), runtime, box.graph()); + case Long: + return ConstantNode.forObject(Long.valueOf(sourceConstant.asLong()), runtime, box.graph()); + case Float: + return ConstantNode.forObject(Float.valueOf(sourceConstant.asFloat()), runtime, box.graph()); + case Double: + return ConstantNode.forObject(Double.valueOf(sourceConstant.asDouble()), runtime, box.graph()); + default: + assert false : "Unexpected source kind for boxing"; + break; + } + } + return null; + } + + public static class Templates extends AbstractTemplates { + + private final EnumMap boxSnippets = new EnumMap<>(Kind.class); + private final EnumMap unboxSnippets = new EnumMap<>(Kind.class); + + public Templates(CodeCacheProvider runtime, Replacements replacements, TargetDescription target) { + super(runtime, replacements, target); + for (Kind kind : new Kind[]{Kind.Boolean, Kind.Byte, Kind.Char, Kind.Double, Kind.Float, Kind.Int, Kind.Long, Kind.Short}) { + boxSnippets.put(kind, snippet(BoxingSnippets.class, kind.getJavaName() + "ValueOf")); + unboxSnippets.put(kind, snippet(BoxingSnippets.class, kind.getJavaName() + "Value")); + } + } + + public void lower(BoxNode box) { + FloatingNode canonical = canonicalizeBoxing(box, runtime); + if (canonical != null) { + ((StructuredGraph) box.graph()).replaceFixedWithFloating(box, canonical); + } else { + Arguments args = new Arguments(boxSnippets.get(box.getBoxingKind())); + args.add("value", box.getValue()); + + SnippetTemplate template = template(args); + Debug.log("Lowering integerValueOf in %s: node=%s, template=%s, arguments=%s", box.graph(), box, template, args); + template.instantiate(runtime, box, DEFAULT_REPLACER, args); + } + } + + public void lower(UnboxNode unbox) { + Arguments args = new Arguments(unboxSnippets.get(unbox.getBoxingKind())); + args.add("value", unbox.getValue()); + + SnippetTemplate template = template(args); + Debug.log("Lowering integerValueOf in %s: node=%s, template=%s, arguments=%s", unbox.graph(), unbox, template, args); + template.instantiate(runtime, unbox, DEFAULT_REPLACER, args); + } + } + + private static final SnippetCounter.Group integerCounters = GraalOptions.SnippetCounters ? new SnippetCounter.Group("Integer intrinsifications") : null; + private static final SnippetCounter valueOfCounter = new SnippetCounter(integerCounters, "valueOf", "valueOf intrinsification"); + +} diff -r 2c933625b355 -r 92d2bedb5dfc graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/BoxingSubstitutions.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/BoxingSubstitutions.java Thu Apr 11 14:22:03 2013 -0700 @@ -0,0 +1,147 @@ +/* + * Copyright (c) 2012, 2012, 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.replacements; + +import com.oracle.graal.api.meta.*; +import com.oracle.graal.api.replacements.*; +import com.oracle.graal.nodes.extended.*; + +public class BoxingSubstitutions { + + @ClassSubstitution(Boolean.class) + private static class BooleanSubstitutions { + + @MethodSubstitution(forced = true) + public static Boolean valueOf(boolean value) { + return BoxNode.box(value, Boolean.class, Kind.Boolean); + } + + @MethodSubstitution(isStatic = false, forced = true) + public static boolean booleanValue(Boolean value) { + return UnboxNode.unbox(value, Kind.Boolean); + } + } + + @ClassSubstitution(Byte.class) + private static class ByteSubstitutions { + + @MethodSubstitution(forced = true) + public static Byte valueOf(byte value) { + return BoxNode.box(value, Byte.class, Kind.Byte); + } + + @MethodSubstitution(isStatic = false, forced = true) + public static byte byteValue(Byte value) { + return UnboxNode.unbox(value, Kind.Byte); + } + } + + @ClassSubstitution(Character.class) + private static class CharacterSubstitutions { + + @MethodSubstitution(forced = true) + public static Character valueOf(char value) { + return BoxNode.box(value, Character.class, Kind.Char); + } + + @MethodSubstitution(isStatic = false, forced = true) + public static char charValue(Character value) { + return UnboxNode.unbox(value, Kind.Char); + } + } + + @ClassSubstitution(Double.class) + private static class DoubleSubstitutions { + + @MethodSubstitution(forced = true) + public static Double valueOf(double value) { + return BoxNode.box(value, Double.class, Kind.Double); + } + + @MethodSubstitution(isStatic = false, forced = true) + public static double doubleValue(Double value) { + return UnboxNode.unbox(value, Kind.Double); + } + } + + @ClassSubstitution(Float.class) + private static class FloatSubstitutions { + + @MethodSubstitution(forced = true) + public static Float valueOf(float value) { + return BoxNode.box(value, Float.class, Kind.Float); + } + + @MethodSubstitution(isStatic = false, forced = true) + public static float floatValue(Float value) { + return UnboxNode.unbox(value, Kind.Float); + } + } + + @ClassSubstitution(Integer.class) + private static class IntegerSubstitutions { + + @MethodSubstitution(forced = true) + public static Integer valueOf(int value) { + return BoxNode.box(value, Integer.class, Kind.Int); + } + + @MethodSubstitution(isStatic = false, forced = true) + public static int intValue(Integer value) { + return UnboxNode.unbox(value, Kind.Int); + } + } + + @ClassSubstitution(Long.class) + private static class LongSubstitutions { + + @MethodSubstitution(forced = true) + public static Long valueOf(long value) { + return BoxNode.box(value, Long.class, Kind.Long); + } + + @MethodSubstitution(isStatic = false, forced = true) + public static long longValue(Long value) { + return UnboxNode.unbox(value, Kind.Long); + } + } + + @ClassSubstitution(Short.class) + private static class ShortSubstitutions { + + @MethodSubstitution(forced = true) + public static Short valueOf(short value) { + return BoxNode.box(value, Short.class, Kind.Short); + } + + @MethodSubstitution(isStatic = false, forced = true) + public static short shortValue(Short value) { + return UnboxNode.unbox(value, Kind.Short); + } + } + + public static Class[] getClasses() { + return new Class[]{BooleanSubstitutions.class, ByteSubstitutions.class, CharacterSubstitutions.class, DoubleSubstitutions.class, FloatSubstitutions.class, IntegerSubstitutions.class, + LongSubstitutions.class, ShortSubstitutions.class}; + } +} diff -r 2c933625b355 -r 92d2bedb5dfc graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/GraalMethodSubstitutions.java --- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/GraalMethodSubstitutions.java Thu Apr 11 14:20:32 2013 -0700 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/GraalMethodSubstitutions.java Thu Apr 11 14:22:03 2013 -0700 @@ -33,6 +33,10 @@ public class GraalMethodSubstitutions implements ReplacementsProvider { public void registerReplacements(Replacements replacements) { + for (Class clazz : BoxingSubstitutions.getClasses()) { + replacements.registerSubstitutions(clazz); + } + if (GraalOptions.Intrinsify) { replacements.registerSubstitutions(MathSubstitutionsX86.class); replacements.registerSubstitutions(DoubleSubstitutions.class); diff -r 2c933625b355 -r 92d2bedb5dfc graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/InstanceOfSnippetsTemplates.java --- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/InstanceOfSnippetsTemplates.java Thu Apr 11 14:20:32 2013 -0700 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/InstanceOfSnippetsTemplates.java Thu Apr 11 14:22:03 2013 -0700 @@ -34,7 +34,9 @@ import com.oracle.graal.nodes.java.*; import com.oracle.graal.nodes.spi.*; import com.oracle.graal.nodes.util.*; -import com.oracle.graal.replacements.SnippetTemplate.*; +import com.oracle.graal.replacements.SnippetTemplate.AbstractTemplates; +import com.oracle.graal.replacements.SnippetTemplate.Arguments; +import com.oracle.graal.replacements.SnippetTemplate.UsageReplacer; /** * Helper class for lowering {@link InstanceOfNode}s with snippets. The majority of the complexity @@ -49,31 +51,16 @@ * {@link IfNode}. This avoids materializing the instanceof test as a boolean which is then retested * by the {@link IfNode}. */ -public abstract class InstanceOfSnippetsTemplates extends AbstractTemplates { +public abstract class InstanceOfSnippetsTemplates extends AbstractTemplates { - public InstanceOfSnippetsTemplates(MetaAccessProvider runtime, Replacements replacements, TargetDescription target, Class snippetsClass) { - super(runtime, replacements, target, snippetsClass); + public InstanceOfSnippetsTemplates(MetaAccessProvider runtime, Replacements replacements, TargetDescription target) { + super(runtime, replacements, target); } /** - * The key and arguments used to retrieve and instantiate an instanceof snippet template. + * Gets the arguments used to retrieve and instantiate an instanceof snippet template. */ - public static class KeyAndArguments { - - public final Key key; - public final Arguments arguments; - - public KeyAndArguments(Key key, Arguments arguments) { - this.key = key; - this.arguments = arguments; - } - - } - - /** - * Gets the key and arguments used to retrieve and instantiate an instanceof snippet template. - */ - protected abstract KeyAndArguments getKeyAndArguments(InstanceOfUsageReplacer replacer, LoweringTool tool); + protected abstract Arguments makeArguments(InstanceOfUsageReplacer replacer, LoweringTool tool); public void lower(FloatingNode instanceOf, LoweringTool tool) { assert instanceOf instanceof InstanceOfNode || instanceOf instanceof InstanceOfDynamicNode; @@ -90,9 +77,8 @@ // No need to re-instantiate the snippet - just re-use its result replacer.replaceUsingInstantiation(); } else { - KeyAndArguments keyAndArguments = getKeyAndArguments(replacer, tool); - SnippetTemplate template = cache.get(keyAndArguments.key); - template.instantiate(runtime, instanceOf, replacer, tool, keyAndArguments.arguments); + Arguments args = makeArguments(replacer, tool); + template(args).instantiate(runtime, instanceOf, replacer, tool, args); } } diff -r 2c933625b355 -r 92d2bedb5dfc 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 Thu Apr 11 14:20:32 2013 -0700 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/ReplacementsImpl.java Thu Apr 11 14:22:03 2013 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2013, 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 @@ -60,7 +60,6 @@ // These data structures are all fully initialized during single-threaded // compiler startup and so do not need to be concurrent. private final Map registeredMethodSubstitutions; - private final Set registeredSnippets; private final Map> registerMacroSubstitutions; private final Set forcedSubstitutions; @@ -70,36 +69,20 @@ this.assumptions = assumptions; this.graphs = new ConcurrentHashMap<>(); this.registeredMethodSubstitutions = new HashMap<>(); - this.registeredSnippets = new HashSet<>(); this.registerMacroSubstitutions = new HashMap<>(); this.forcedSubstitutions = new HashSet<>(); } - public void registerSnippets(Class snippets) { - assert Snippets.class.isAssignableFrom(snippets); - for (Method method : snippets.getDeclaredMethods()) { - if (method.getAnnotation(Snippet.class) != null) { - int modifiers = method.getModifiers(); - if (Modifier.isAbstract(modifiers) || Modifier.isNative(modifiers)) { - throw new RuntimeException("Snippet must not be abstract or native"); - } - ResolvedJavaMethod snippet = runtime.lookupJavaMethod(method); - registeredSnippets.add(snippet); - } - } - } + public StructuredGraph getSnippet(ResolvedJavaMethod method) { + assert method.getAnnotation(Snippet.class) != null : "Snippet must be annotated with @" + Snippet.class.getSimpleName(); + assert !Modifier.isAbstract(method.getModifiers()) && !Modifier.isNative(method.getModifiers()) : "Snippet must not be abstract or native"; - public StructuredGraph getSnippet(ResolvedJavaMethod method) { - if (!registeredSnippets.contains(method)) { - return null; - } StructuredGraph graph = graphs.get(method); if (graph == null) { graphs.putIfAbsent(method, makeGraph(method, null, inliningPolicy(method))); graph = graphs.get(method); } return graph; - } public StructuredGraph getMethodSubstitution(ResolvedJavaMethod original) { @@ -488,7 +471,6 @@ @Override public Collection getAllReplacements() { HashSet result = new HashSet<>(); - result.addAll(registeredSnippets); result.addAll(registeredMethodSubstitutions.keySet()); result.addAll(registerMacroSubstitutions.keySet()); return result; diff -r 2c933625b355 -r 92d2bedb5dfc graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/Snippet.java --- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/Snippet.java Thu Apr 11 14:20:32 2013 -0700 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/Snippet.java Thu Apr 11 14:22:03 2013 -0700 @@ -27,7 +27,6 @@ import com.oracle.graal.api.meta.*; import com.oracle.graal.graph.Node.NodeIntrinsic; -import com.oracle.graal.nodes.type.*; import com.oracle.graal.replacements.nodes.*; import com.oracle.graal.word.*; @@ -122,20 +121,6 @@ } /** - * Denotes a snippet parameter that will be bound during snippet template - * {@linkplain SnippetTemplate#instantiate instantiation}. - */ - @Retention(RetentionPolicy.RUNTIME) - @Target(ElementType.PARAMETER) - public @interface Parameter { - - /** - * The name of this parameter. - */ - String value(); - } - - /** * Denotes a snippet parameter representing 0 or more arguments that will be bound during * snippet template {@linkplain SnippetTemplate#instantiate instantiation}. During snippet * template creation, its value must be an array whose length specifies the number of arguments @@ -149,11 +134,6 @@ @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.PARAMETER) public @interface VarargsParameter { - - /** - * The name of this parameter. - */ - String value(); } /** @@ -163,61 +143,5 @@ @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.PARAMETER) public @interface ConstantParameter { - - /** - * The name of this constant. - */ - String value(); - } - - /** - * Wrapper for the prototype value of a {@linkplain VarargsParameter varargs} parameter. - */ - public static class Varargs { - - private final Object args; - private final Class argType; - private final int length; - private final Stamp argStamp; - - public static Varargs vargargs(Object array, Stamp argStamp) { - return new Varargs(array, argStamp); - } - - public Varargs(Object array, Stamp argStamp) { - assert array != null; - this.argType = array.getClass().getComponentType(); - this.argStamp = argStamp; - assert this.argType != null; - this.length = java.lang.reflect.Array.getLength(array); - this.args = array; - } - - @Override - public boolean equals(Object obj) { - if (obj instanceof Varargs) { - Varargs other = (Varargs) obj; - return other.argType == argType && other.length == length; - } - return false; - } - - public Object getArray() { - return args; - } - - public Stamp getArgStamp() { - return argStamp; - } - - @Override - public int hashCode() { - return argType.hashCode() ^ length; - } - - @Override - public String toString() { - return argType.getName() + "[" + length + "]"; - } } } diff -r 2c933625b355 -r 92d2bedb5dfc graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/SnippetTemplate.java --- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/SnippetTemplate.java Thu Apr 11 14:20:32 2013 -0700 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/SnippetTemplate.java Thu Apr 11 14:22:03 2013 -0700 @@ -22,11 +22,8 @@ */ package com.oracle.graal.replacements; -import static com.oracle.graal.api.meta.MetaUtil.*; - import java.lang.reflect.*; import java.util.*; -import java.util.Map.Entry; import java.util.concurrent.*; import com.oracle.graal.api.code.*; @@ -42,8 +39,6 @@ import com.oracle.graal.nodes.util.*; import com.oracle.graal.phases.common.*; import com.oracle.graal.replacements.Snippet.ConstantParameter; -import com.oracle.graal.replacements.Snippet.Parameter; -import com.oracle.graal.replacements.Snippet.Varargs; import com.oracle.graal.replacements.Snippet.VarargsParameter; import com.oracle.graal.replacements.nodes.*; import com.oracle.graal.word.*; @@ -53,173 +48,274 @@ * A snippet template is a graph created by parsing a snippet method and then specialized by binding * constants to the snippet's {@link ConstantParameter} parameters. * - * Snippet templates can be managed in a {@link Cache}. + * Snippet templates can be managed in a cache maintained by {@link AbstractTemplates}. */ public class SnippetTemplate { /** - * A snippet template key encapsulates the method from which a snippet was built and the - * arguments used to specialize the snippet. - * - * @see Cache + * Holds the {@link ResolvedJavaMethod} of the snippet, together with some information about the + * method that needs to be computed only once. The {@link SnippetInfo} should be created once + * per snippet an then cached. */ - public static class Key implements Iterable> { + public static class SnippetInfo { + + protected final ResolvedJavaMethod method; + protected final ConstantParameter[] constantParameters; + protected final VarargsParameter[] varargsParameters; + + /** + * The parameter names, taken from the local variables table. Only used for assertion + * checking, so use only within an assert statement. + */ + protected final String[] names; + + protected SnippetInfo(ResolvedJavaMethod method) { + this.method = method; - public final ResolvedJavaMethod method; - private final HashMap map = new HashMap<>(); - private int hash; + assert Modifier.isStatic(method.getModifiers()) : "snippet method must be static: " + MetaUtil.format("%H.%n", method); + int count = method.getSignature().getParameterCount(false); + constantParameters = new ConstantParameter[count]; + varargsParameters = new VarargsParameter[count]; + for (int i = 0; i < count; i++) { + constantParameters[i] = MetaUtil.getParameterAnnotation(ConstantParameter.class, i, method); + varargsParameters[i] = MetaUtil.getParameterAnnotation(VarargsParameter.class, i, method); + + assert !isConstantParameter(i) || !isVarargsParameter(i) : "Parameter cannot be annotated with both @" + ConstantParameter.class.getSimpleName() + " and @" + + VarargsParameter.class.getSimpleName(); + } - public Key(ResolvedJavaMethod method) { - this.method = method; - this.hash = method.hashCode(); + names = new String[count]; + // Retrieve the names only when assertions are turned on. + assert initNames(); + } + + private boolean initNames() { + int slotIdx = 0; + for (int i = 0; i < names.length; i++) { + names[i] = method.getLocalVariableTable().getLocal(slotIdx, 0).getName(); + + Kind kind = method.getSignature().getParameterKind(i); + slotIdx += kind == Kind.Long || kind == Kind.Double ? 2 : 1; + } + return true; } - public Key add(String name, Object value) { - assert !map.containsKey(name); - map.put(name, value); - hash = hash ^ name.hashCode(); - if (value != null) { - hash *= (value.hashCode() + 1); - } + public ResolvedJavaMethod getMethod() { + return method; + } + + public int getParameterCount() { + return constantParameters.length; + } + + public boolean isConstantParameter(int paramIdx) { + return constantParameters[paramIdx] != null; + } + + public boolean isVarargsParameter(int paramIdx) { + return varargsParameters[paramIdx] != null; + } + } + + /** + * Values that are bound to the snippet method parameters. The methods {@link #add}, + * {@link #addConst}, and {@link #addVarargs} must be called in the same order as in the + * signature of the snippet method. The parameter name is passed to the add methods for + * assertion checking, i.e., to enforce that the order matches. Which method needs to be called + * depends on the annotation of the snippet method parameter: + *
    + *
  • Use {@link #add} for a parameter without an annotation. The value is bound when the + * {@link SnippetTemplate} is {@link SnippetTemplate#instantiate instantiated}. + *
  • Use {@link #addConst} for a parameter annotated with {@link ConstantParameter}. The value + * is bound when the {@link SnippetTemplate} is {@link SnippetTemplate#SnippetTemplate created}. + *
  • Use {@link #addVarargs} for an array parameter annotated with {@link VarargsParameter}. A + * separate {@link SnippetTemplate} is {@link SnippetTemplate#SnippetTemplate created} for every + * distinct array length. The actual values are bound when the {@link SnippetTemplate} is + * {@link SnippetTemplate#instantiate instantiated} + *
+ */ + public static class Arguments { + + protected final SnippetInfo info; + protected final CacheKey cacheKey; + protected final Object[] values; + + protected int nextParamIdx; + + public Arguments(SnippetInfo info) { + this.info = info; + this.cacheKey = new CacheKey(info); + this.values = new Object[info.getParameterCount()]; + } + + public Arguments add(String name, Object value) { + assert check(name, false, false); + values[nextParamIdx] = value; + nextParamIdx++; return this; } - public int length() { - return map.size(); + public Arguments addConst(String name, Object value) { + assert check(name, true, false); + values[nextParamIdx] = value; + cacheKey.setParam(nextParamIdx, value); + nextParamIdx++; + return this; } - public Object get(String name) { - return map.get(name); + public Arguments addVarargs(String name, Class componentType, Stamp argStamp, Object value) { + assert check(name, false, true); + Varargs varargs = new Varargs(componentType, argStamp, value); + values[nextParamIdx] = varargs; + // A separate template is necessary for every distinct array length + cacheKey.setParam(nextParamIdx, varargs.length); + nextParamIdx++; + return this; + } + + private boolean check(String name, boolean constParam, boolean varargsParam) { + assert nextParamIdx < info.getParameterCount() : "too many parameters: " + name + " " + this; + assert info.names[nextParamIdx].equals(name) : "wrong parameter name: " + name + " " + this; + assert constParam == info.isConstantParameter(nextParamIdx) : "Parameter " + (constParam ? "not " : "") + "annotated with @" + ConstantParameter.class.getSimpleName() + ": " + name + + " " + this; + assert varargsParam == info.isVarargsParameter(nextParamIdx) : "Parameter " + (varargsParam ? "not " : "") + "annotated with @" + VarargsParameter.class.getSimpleName() + ": " + name + + " " + this; + return true; } @Override - public Iterator> iterator() { - return map.entrySet().iterator(); + public String toString() { + StringBuilder result = new StringBuilder(); + result.append("Parameters<").append(MetaUtil.format("%H.%n", info.method)).append(" ["); + String sep = ""; + for (int i = 0; i < info.getParameterCount(); i++) { + result.append(sep); + if (info.isConstantParameter(i)) { + result.append("const "); + } else if (info.isVarargsParameter(i)) { + result.append("varargs "); + } + result.append(info.names[i]).append(" = ").append(values[i]); + sep = ", "; + } + result.append(">"); + return result.toString(); + } + } + + /** + * Wrapper for the prototype value of a {@linkplain VarargsParameter varargs} parameter. + */ + static class Varargs { + + protected final Class componentType; + protected final Stamp stamp; + protected final Object value; + protected final int length; + + protected Varargs(Class componentType, Stamp stamp, Object value) { + this.componentType = componentType; + this.stamp = stamp; + this.value = value; + if (value instanceof List) { + this.length = ((List) value).size(); + } else { + this.length = Array.getLength(value); + } + } + } + + static class CacheKey { + + private final ResolvedJavaMethod method; + private final Object[] values; + private int hash; + + protected CacheKey(SnippetInfo info) { + this.method = info.method; + this.values = new Object[info.getParameterCount()]; + this.hash = info.method.hashCode(); + } + + protected void setParam(int paramIdx, Object value) { + values[paramIdx] = value; + hash = (hash * 31) ^ (value == null ? 0 : value.hashCode()); } @Override public boolean equals(Object obj) { - if (obj instanceof Key) { - Key other = (Key) obj; - return other.method == method && other.map.equals(map); + if (!(obj instanceof CacheKey)) { + return false; + } + CacheKey other = (CacheKey) obj; + if (method != other.method) { + return false; } - return false; + for (int i = 0; i < values.length; i++) { + if (values[i] != null && !values[i].equals(other.values[i])) { + return false; + } + } + return true; } @Override public int hashCode() { return hash; } - - @Override - public String toString() { - return MetaUtil.format("%h.%n", method) + map.toString(); - } - - public Set names() { - return map.keySet(); - } } /** - * Arguments used to instantiate a template. + * Base class for snippet classes. It provides a cache for {@link SnippetTemplate}s. */ - public static class Arguments implements Iterable> { - - private final HashMap map = new HashMap<>(); - - public static Arguments arguments(String name, Object value) { - return new Arguments().add(name, value); - } - - public Arguments add(String name, Object value) { - assert !map.containsKey(name); - map.put(name, value); - return this; - } - - public int length() { - return map.size(); - } + public abstract static class AbstractTemplates { - @Override - public Iterator> iterator() { - return map.entrySet().iterator(); - } - - @Override - public String toString() { - return map.toString(); - } - } + protected final MetaAccessProvider runtime; + protected final Replacements replacements; + protected final TargetDescription target; + private final ConcurrentHashMap templates; - /** - * A collection of snippet templates accessed by a {@link Key} instance. - */ - public static class Cache { - - private final ConcurrentHashMap templates = new ConcurrentHashMap<>(); - private final MetaAccessProvider runtime; - private final TargetDescription target; - private final Replacements replacements; - - public Cache(MetaAccessProvider runtime, Replacements replacements, TargetDescription target) { + protected AbstractTemplates(MetaAccessProvider runtime, Replacements replacements, TargetDescription target) { this.runtime = runtime; this.replacements = replacements; this.target = target; + this.templates = new ConcurrentHashMap<>(); + } + + protected SnippetInfo snippet(Class declaringClass, String methodName) { + Method found = null; + for (Method method : declaringClass.getDeclaredMethods()) { + if (method.getAnnotation(Snippet.class) != null && method.getName().equals(methodName)) { + assert found == null : "found more than one @" + Snippet.class.getSimpleName() + " method " + methodName + " in " + declaringClass; + found = method; + } + } + assert found != null : "did not find @" + Snippet.class.getSimpleName() + " method " + methodName + " in " + declaringClass; + + return new SnippetInfo(runtime.lookupJavaMethod(found)); } /** * Gets a template for a given key, creating it first if necessary. */ - public SnippetTemplate get(final SnippetTemplate.Key key) { - SnippetTemplate template = templates.get(key); + protected SnippetTemplate template(final Arguments args) { + SnippetTemplate template = templates.get(args.cacheKey); if (template == null) { - template = Debug.scope("SnippetSpecialization", key.method, new Callable() { + template = Debug.scope("SnippetSpecialization", args.info.method, new Callable() { @Override public SnippetTemplate call() throws Exception { - return new SnippetTemplate(runtime, replacements, target, key); + return new SnippetTemplate(runtime, replacements, target, args); } }); - templates.put(key, template); + templates.put(args.cacheKey, template); } return template; } } - public abstract static class AbstractTemplates { - - protected final Cache cache; - protected final MetaAccessProvider runtime; - protected final Replacements replacements; - protected Class snippetsClass; - - public AbstractTemplates(MetaAccessProvider runtime, Replacements replacements, TargetDescription target, Class snippetsClass) { - this.runtime = runtime; - this.replacements = replacements; - if (snippetsClass == null) { - assert this instanceof Snippets; - this.snippetsClass = getClass(); - } else { - this.snippetsClass = snippetsClass; - } - this.cache = new Cache(runtime, replacements, target); - replacements.registerSnippets(this.snippetsClass); - } - - protected ResolvedJavaMethod snippet(String name, Class... parameterTypes) { - try { - ResolvedJavaMethod snippet = runtime.lookupJavaMethod(snippetsClass.getDeclaredMethod(name, parameterTypes)); - assert snippet.getAnnotation(Snippet.class) != null : "snippet is not annotated with @" + Snippet.class.getSimpleName(); - return snippet; - } catch (NoSuchMethodException e) { - throw new GraalInternalError(e); - } - } - } - private static final Object UNUSED_PARAMETER = "DEAD PARAMETER"; + private static final Object CONSTANT_PARAMETER = "CONSTANT"; /** * Determines if any parameter of a given method is annotated with {@link ConstantParameter}. @@ -236,31 +332,25 @@ /** * Creates a snippet template. */ - public SnippetTemplate(MetaAccessProvider runtime, Replacements replacements, TargetDescription target, SnippetTemplate.Key key) { - ResolvedJavaMethod method = key.method; - assert Modifier.isStatic(method.getModifiers()) : "snippet method must be static: " + method; + protected SnippetTemplate(MetaAccessProvider runtime, Replacements replacements, TargetDescription target, Arguments args) { + StructuredGraph snippetGraph = replacements.getSnippet(args.info.method); + + ResolvedJavaMethod method = snippetGraph.method(); Signature signature = method.getSignature(); // Copy snippet graph, replacing constant parameters with given arguments - StructuredGraph snippetGraph = replacements.getSnippet(method); - if (snippetGraph == null) { - throw new GraalInternalError("Snippet has not been registered: %s", format("%H.%n(%p)", method)); - } StructuredGraph snippetCopy = new StructuredGraph(snippetGraph.name, snippetGraph.method()); IdentityHashMap nodeReplacements = new IdentityHashMap<>(); nodeReplacements.put(snippetGraph.start(), snippetCopy.start()); - int parameterCount = signature.getParameterCount(false); - assert checkTemplate(runtime, key, parameterCount, method, signature); + assert checkTemplate(runtime, args, method, signature); - Parameter[] parameterAnnotations = new Parameter[parameterCount]; - VarargsParameter[] varargsParameterAnnotations = new VarargsParameter[parameterCount]; + int parameterCount = args.info.getParameterCount(); ConstantNode[] placeholders = new ConstantNode[parameterCount]; + for (int i = 0; i < parameterCount; i++) { - ConstantParameter c = MetaUtil.getParameterAnnotation(ConstantParameter.class, i, method); - if (c != null) { - String name = c.value(); - Object arg = key.get(name); + if (args.info.isConstantParameter(i)) { + Object arg = args.values[i]; Kind kind = signature.getParameterKind(i); Constant constantArg; if (arg instanceof Constant) { @@ -269,19 +359,12 @@ constantArg = Constant.forBoxed(kind, arg); } nodeReplacements.put(snippetGraph.getLocal(i), ConstantNode.forConstant(constantArg, runtime, snippetCopy)); - } else { - VarargsParameter vp = MetaUtil.getParameterAnnotation(VarargsParameter.class, i, method); - if (vp != null) { - String name = vp.value(); - Varargs varargs = (Varargs) key.get(name); - Object array = varargs.getArray(); - ConstantNode placeholder = ConstantNode.forObject(array, runtime, snippetCopy); - nodeReplacements.put(snippetGraph.getLocal(i), placeholder); - placeholders[i] = placeholder; - varargsParameterAnnotations[i] = vp; - } else { - parameterAnnotations[i] = MetaUtil.getParameterAnnotation(Parameter.class, i, method); - } + } else if (args.info.isVarargsParameter(i)) { + Varargs varargs = (Varargs) args.values[i]; + Object array = Array.newInstance(varargs.componentType, varargs.length); + ConstantNode placeholder = ConstantNode.forObject(array, runtime, snippetCopy); + nodeReplacements.put(snippetGraph.getLocal(i), placeholder); + placeholders[i] = placeholder; } } snippetCopy.addDuplicates(snippetGraph.getNodes(), nodeReplacements); @@ -297,23 +380,23 @@ assert NodeIntrinsificationVerificationPhase.verify(snippetCopy); // Gather the template parameters - parameters = new HashMap<>(); + parameters = new Object[parameterCount]; for (int i = 0; i < parameterCount; i++) { - VarargsParameter vp = varargsParameterAnnotations[i]; - if (vp != null) { + if (args.info.isConstantParameter(i)) { + parameters[i] = CONSTANT_PARAMETER; + } else if (args.info.isVarargsParameter(i)) { assert snippetCopy.getLocal(i) == null; - Varargs varargs = (Varargs) key.get(vp.value()); - Object array = varargs.getArray(); - int length = Array.getLength(array); + Varargs varargs = (Varargs) args.values[i]; + int length = varargs.length; LocalNode[] locals = new LocalNode[length]; - Stamp stamp = varargs.getArgStamp(); + Stamp stamp = varargs.stamp; for (int j = 0; j < length; j++) { assert (parameterCount & 0xFFFF) == parameterCount; int idx = i << 16 | j; LocalNode local = snippetCopy.unique(new LocalNode(idx, stamp)); locals[j] = local; } - parameters.put(vp.value(), locals); + parameters[i] = locals; ConstantNode placeholder = placeholders[i]; assert placeholder != null; @@ -327,15 +410,12 @@ } } } else { - Parameter p = parameterAnnotations[i]; - if (p != null) { - LocalNode local = snippetCopy.getLocal(i); - if (local == null) { - // Parameter value was eliminated - parameters.put(p.value(), UNUSED_PARAMETER); - } else { - parameters.put(p.value(), local); - } + LocalNode local = snippetCopy.getLocal(i); + if (local == null) { + // Parameter value was eliminated + parameters[i] = UNUSED_PARAMETER; + } else { + parameters[i] = local; } } } @@ -434,11 +514,11 @@ return true; } - private static boolean checkVarargs(final ResolvedJavaMethod method, Signature signature, int i, String name, Varargs varargs) { - Object arg = varargs.getArray(); + private static boolean checkVarargs(MetaAccessProvider runtime, final ResolvedJavaMethod method, Signature signature, int i, String name, Varargs varargs) { ResolvedJavaType type = (ResolvedJavaType) signature.getParameterType(i, method.getDeclaringClass()); assert type.isArray() : "varargs parameter must be an array type"; - assert type.isInstance(Constant.forObject(arg)) : "value for " + name + " is not a " + MetaUtil.toJavaName(type) + " instance: " + arg; + assert type.getComponentType().isAssignableFrom(runtime.lookupJavaType(varargs.componentType)) : "componentType for " + name + " not matching " + MetaUtil.toJavaName(type) + " instance: " + + varargs.componentType; return true; } @@ -453,7 +533,7 @@ * {@link LocalNode} instance or a {@link LocalNode} array. For an eliminated parameter, the * value is identical to the key. */ - private final Map parameters; + private final Object[] parameters; /** * The return node (if any) of the snippet. @@ -481,33 +561,33 @@ * * @return the map that will be used to bind arguments to parameters when inlining this template */ - private IdentityHashMap bind(StructuredGraph replaceeGraph, MetaAccessProvider runtime, SnippetTemplate.Arguments args) { + private IdentityHashMap bind(StructuredGraph replaceeGraph, MetaAccessProvider runtime, Arguments args) { IdentityHashMap replacements = new IdentityHashMap<>(); - assert args.length() == parameters.size() : "number of args (" + args.length() + ") != number of parameters (" + parameters.size() + ")"; - for (Map.Entry e : args) { - String name = e.getKey(); - Object parameter = parameters.get(name); - assert parameter != null : this + " has no parameter named " + name; - Object argument = e.getValue(); + assert args.info.getParameterCount() == parameters.length : "number of args (" + args.info.getParameterCount() + ") != number of parameters (" + parameters.length + ")"; + for (int i = 0; i < parameters.length; i++) { + Object parameter = parameters[i]; + assert parameter != null : this + " has no parameter named " + args.info.names[i]; + Object argument = args.values[i]; if (parameter instanceof LocalNode) { if (argument instanceof ValueNode) { replacements.put((LocalNode) parameter, (ValueNode) argument); } else { Kind kind = ((LocalNode) parameter).kind(); - assert argument != null || kind == Kind.Object : this + " cannot accept null for non-object parameter named " + name; + assert argument != null || kind == Kind.Object : this + " cannot accept null for non-object parameter named " + args.info.names[i]; Constant constant = forBoxed(argument, kind); replacements.put((LocalNode) parameter, ConstantNode.forConstant(constant, runtime, replaceeGraph)); } } else if (parameter instanceof LocalNode[]) { LocalNode[] locals = (LocalNode[]) parameter; + Varargs varargs = (Varargs) argument; int length = locals.length; List list = null; Object array = null; - if (argument instanceof List) { - list = (List) argument; + if (varargs.value instanceof List) { + list = (List) varargs.value; assert list.size() == length : length + " != " + list.size(); } else { - array = argument; + array = varargs.value; assert array != null && array.getClass().isArray(); assert Array.getLength(array) == length : length + " != " + Array.getLength(array); } @@ -525,7 +605,7 @@ } } } else { - assert parameter == UNUSED_PARAMETER : "unexpected entry for parameter: " + name + " -> " + parameter; + assert parameter == CONSTANT_PARAMETER || parameter == UNUSED_PARAMETER : "unexpected entry for parameter: " + args.info.names[i] + " -> " + parameter; } } return replacements; @@ -592,7 +672,7 @@ * @param args the arguments to be bound to the flattened positional parameters of the snippet * @return the map of duplicated nodes (original -> duplicate) */ - public Map instantiate(MetaAccessProvider runtime, FixedNode replacee, UsageReplacer replacer, SnippetTemplate.Arguments args) { + public Map instantiate(MetaAccessProvider runtime, FixedNode replacee, UsageReplacer replacer, Arguments args) { // Inline the snippet nodes, replacing parameters with the given args in the process String name = snippet.name == null ? "{copy}" : snippet.name + "{copy}"; @@ -668,7 +748,7 @@ * @param replacer object that replaces the usages of {@code replacee} * @param args the arguments to be bound to the flattened positional parameters of the snippet */ - public void instantiate(MetaAccessProvider runtime, FloatingNode replacee, UsageReplacer replacer, LoweringTool tool, SnippetTemplate.Arguments args) { + public void instantiate(MetaAccessProvider runtime, FloatingNode replacee, UsageReplacer replacer, LoweringTool tool, Arguments args) { // Inline the snippet nodes, replacing parameters with the given args in the process String name = snippet.name == null ? "{copy}" : snippet.name + "{copy}"; @@ -727,12 +807,14 @@ public String toString() { StringBuilder buf = new StringBuilder(snippet.toString()).append('('); String sep = ""; - for (Map.Entry e : parameters.entrySet()) { - String name = e.getKey(); - Object value = e.getValue(); + for (int i = 0; i < parameters.length; i++) { + String name = "[" + i + "]"; + Object value = parameters[i]; buf.append(sep); sep = ", "; - if (value == UNUSED_PARAMETER) { + if (value == null) { + buf.append(" ").append(name); + } else if (value == UNUSED_PARAMETER) { buf.append(" ").append(name); } else if (value instanceof LocalNode) { LocalNode local = (LocalNode) value; @@ -746,42 +828,18 @@ return buf.append(')').toString(); } - private static boolean checkTemplate(MetaAccessProvider runtime, SnippetTemplate.Key key, int parameterCount, ResolvedJavaMethod method, Signature signature) { - Set expected = new HashSet<>(); - for (int i = 0; i < parameterCount; i++) { - ConstantParameter c = MetaUtil.getParameterAnnotation(ConstantParameter.class, i, method); - VarargsParameter vp = MetaUtil.getParameterAnnotation(VarargsParameter.class, i, method); - Parameter p = MetaUtil.getParameterAnnotation(Parameter.class, i, method); - if (c != null) { - assert vp == null && p == null; - String name = c.value(); - expected.add(name); + private static boolean checkTemplate(MetaAccessProvider runtime, Arguments args, ResolvedJavaMethod method, Signature signature) { + for (int i = 0; i < args.info.getParameterCount(); i++) { + if (args.info.isConstantParameter(i)) { Kind kind = signature.getParameterKind(i); - assert key.names().contains(name) : "key for " + method + " is missing \"" + name + "\": " + key; - assert checkConstantArgument(runtime, method, signature, i, c.value(), key.get(name), kind); - } else if (vp != null) { - assert p == null; - String name = vp.value(); - expected.add(name); - assert key.names().contains(name) : "key for " + method + " is missing \"" + name + "\": " + key; - assert key.get(name) instanceof Varargs; - Varargs varargs = (Varargs) key.get(name); - assert checkVarargs(method, signature, i, name, varargs); - } else { - assert p != null : method + ": parameter " + i + " must be annotated with exactly one of " + "@" + ConstantParameter.class.getSimpleName() + " or " + "@" + - VarargsParameter.class.getSimpleName() + " or " + "@" + Parameter.class.getSimpleName(); + assert checkConstantArgument(runtime, method, signature, i, args.info.names[i], args.values[i], kind); + + } else if (args.info.isVarargsParameter(i)) { + assert args.values[i] instanceof Varargs; + Varargs varargs = (Varargs) args.values[i]; + assert checkVarargs(runtime, method, signature, i, args.info.names[i], varargs); } } - if (!key.names().containsAll(expected)) { - expected.removeAll(key.names()); - assert false : expected + " missing from key " + key; - } - if (!expected.containsAll(key.names())) { - Set namesCopy = new HashSet<>(key.names()); - namesCopy.removeAll(expected); - assert false : "parameter(s) " + namesCopy + " should be annotated with @" + ConstantParameter.class.getSimpleName() + " or @" + VarargsParameter.class.getSimpleName() + " in " + - MetaUtil.format("%H.%n(%p)", method); - } return true; } }