changeset 21759:75daca0c6a0f

Merge.
author Thomas Wuerthinger <thomas.wuerthinger@oracle.com>
date Fri, 05 Jun 2015 23:54:02 +0200
parents 532f9b06f54e (current diff) c052d68e7eac (diff)
children 55058b8000ea 0dfd3ea90d33
files graal/com.oracle.graal.java.test/src/com/oracle/graal/java/test/TestBytecodeDisassemblerProvider.java graal/com.oracle.jvmci.meta/src/com/oracle/jvmci/meta/BytecodeDisassemblerProvider.java
diffstat 13 files changed, 149 insertions(+), 145 deletions(-) [+]
line wrap: on
line diff
--- a/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeUsageIterable.java	Fri Jun 05 23:53:43 2015 +0200
+++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeUsageIterable.java	Fri Jun 05 23:54:02 2015 +0200
@@ -28,7 +28,7 @@
 
 class NodeUsageIterable implements NodeIterable<Node> {
 
-    final Node node;
+    private final Node node;
 
     NodeUsageIterable(Node node) {
         this.node = node;
@@ -43,6 +43,11 @@
     }
 
     @Override
+    public Node first() {
+        return node.usage0;
+    }
+
+    @Override
     public boolean isEmpty() {
         return node.usage0 == null;
     }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/InstanceOfSnippets.java	Fri Jun 05 23:53:43 2015 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/InstanceOfSnippets.java	Fri Jun 05 23:54:02 2015 +0200
@@ -93,6 +93,7 @@
                 hintsHit.inc();
                 return positive ? trueValue : falseValue;
             }
+            hintsMiss.inc();
         }
         // This maybe just be a rare event but it might also indicate a phase change
         // in the application. Ideally we want to use DeoptimizationAction.None for
@@ -161,6 +162,7 @@
                 return positive ? trueValue : falseValue;
             }
         }
+        hintsMiss.inc();
         if (!checkSecondarySubType(hub, objectHub)) {
             return falseValue;
         }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/TypeCheckSnippetUtils.java	Fri Jun 05 23:53:43 2015 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/TypeCheckSnippetUtils.java	Fri Jun 05 23:54:02 2015 +0200
@@ -146,6 +146,7 @@
 
     private static final SnippetCounter.Group counters = SnippetCounters.getValue() ? new SnippetCounter.Group("TypeCheck") : null;
     static final SnippetCounter hintsHit = new SnippetCounter(counters, "hintsHit", "hit a hint type");
+    static final SnippetCounter hintsMiss = new SnippetCounter(counters, "hintsMiss", "missed a hint type");
     static final SnippetCounter exactHit = new SnippetCounter(counters, "exactHit", "exact type test succeeded");
     static final SnippetCounter exactMiss = new SnippetCounter(counters, "exactMiss", "exact type test failed");
     static final SnippetCounter isNull = new SnippetCounter(counters, "isNull", "object tested was null");
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/arraycopy/ArrayCopySnippets.java	Fri Jun 05 23:53:43 2015 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/arraycopy/ArrayCopySnippets.java	Fri Jun 05 23:54:02 2015 +0200
@@ -110,16 +110,19 @@
     }
 
     @Snippet
-    public static void arraycopyExactIntrinsic(Object src, int srcPos, Object dest, int destPos, int length, @ConstantParameter Kind elementKind, @ConstantParameter SnippetCounter counter) {
+    public static void arraycopyExactIntrinsic(Object src, int srcPos, Object dest, int destPos, int length, @ConstantParameter Kind elementKind, @ConstantParameter SnippetCounter counter,
+                    @ConstantParameter SnippetCounter copiedCounter) {
         Object nonNullSrc = GraalDirectives.guardingNonNull(src);
         Object nonNullDest = GraalDirectives.guardingNonNull(dest);
         checkLimits(nonNullSrc, srcPos, nonNullDest, destPos, length);
         counter.inc();
+        copiedCounter.add(length);
         ArrayCopyCallNode.arraycopy(nonNullSrc, srcPos, nonNullDest, destPos, length, elementKind);
         if (length == 0) {
             zeroLengthDynamicCounter.inc();
         } else {
             nonZeroLengthDynamicCounter.inc();
+            nonZeroLengthDynamicCopiedCounter.add(length);
         }
     }
 
@@ -128,7 +131,8 @@
      * inputs but not the other.
      */
     @Snippet
-    public static void arraycopyPredictedExactIntrinsic(Object src, int srcPos, Object dest, int destPos, int length, @ConstantParameter Kind elementKind, @ConstantParameter SnippetCounter counter) {
+    public static void arraycopyPredictedExactIntrinsic(Object src, int srcPos, Object dest, int destPos, int length, @ConstantParameter Kind elementKind, @ConstantParameter SnippetCounter counter,
+                    @ConstantParameter SnippetCounter copiedCounter) {
         Object nonNullSrc = GraalDirectives.guardingNonNull(src);
         Object nonNullDest = GraalDirectives.guardingNonNull(dest);
         KlassPointer srcHub = loadHub(nonNullSrc);
@@ -138,25 +142,31 @@
         }
         checkLimits(nonNullSrc, srcPos, nonNullDest, destPos, length);
         counter.inc();
+        copiedCounter.add(length);
         ArrayCopyCallNode.arraycopy(nonNullSrc, srcPos, nonNullDest, destPos, length, elementKind);
         if (length == 0) {
             zeroLengthDynamicCounter.inc();
         } else {
             nonZeroLengthDynamicCounter.inc();
+            nonZeroLengthDynamicCopiedCounter.add(length);
         }
     }
 
     @Snippet
-    public static void arraycopyPredictedObjectWork(Object nonNullSrc, int srcPos, Object nonNullDest, int destPos, int length, KlassPointer objectArrayKlass, @ConstantParameter SnippetCounter counter) {
+    public static void arraycopyPredictedObjectWork(Object nonNullSrc, int srcPos, Object nonNullDest, int destPos, int length, KlassPointer objectArrayKlass,
+                    @ConstantParameter SnippetCounter counter, @ConstantParameter SnippetCounter copiedCounter) {
         if (length > 0) {
             KlassPointer srcHub = loadHub(nonNullSrc);
             KlassPointer destHub = loadHub(nonNullDest);
             if (probability(FAST_PATH_PROBABILITY, srcHub == destHub || destHub == objectArrayKlass)) {
                 counter.inc();
+                copiedCounter.add(length);
                 predictedObjectArrayCopyFastPathCounter.inc();
+                predictedObjectArrayCopyFastPathCopiedCounter.add(length);
                 ArrayCopyCallNode.arraycopyObjectKillsAny(nonNullSrc, srcPos, nonNullDest, destPos, length);
             } else {
                 predictedObjectArrayCopySlowPathCounter.inc();
+                predictedObjectArrayCopySlowPathCopiedCounter.add(length);
                 System.arraycopy(nonNullSrc, srcPos, nonNullDest, destPos, length);
             }
         }
@@ -179,6 +189,7 @@
             zeroLengthDynamicCounter.inc();
         } else {
             nonZeroLengthDynamicCounter.inc();
+            nonZeroLengthDynamicCopiedCounter.add(length);
         }
         ArrayCopySlowPathNode.arraycopy(nonNullSrc, srcPos, nonNullDest, destPos, length, elementKind, slowPath);
     }
@@ -191,11 +202,13 @@
             if (probability(SLOW_PATH_PROBABILITY, srcKlass == destKlass)) {
                 // no storecheck required.
                 objectCheckcastSameTypeCounter.inc();
+                objectCheckcastSameTypeCopiedCounter.add(length);
                 ArrayCopyCallNode.arraycopyObjectKillsAny(nonNullSrc, srcPos, nonNullDest, destPos, length);
             } else {
                 KlassPointer destElemKlass = destKlass.readKlassPointer(arrayClassElementOffset(), OBJ_ARRAY_KLASS_ELEMENT_KLASS_LOCATION);
                 Word superCheckOffset = Word.signed(destElemKlass.readInt(superCheckOffsetOffset(), KLASS_SUPER_CHECK_OFFSET_LOCATION));
                 objectCheckcastCounter.inc();
+                objectCheckcastCopiedCounter.add(length);
                 int copiedElements = CheckcastArrayCopyCallNode.checkcastArraycopy(nonNullSrc, srcPos, nonNullDest, destPos, length, superCheckOffset, destElemKlass, false);
                 if (copiedElements != 0) {
                     /*
@@ -221,13 +234,16 @@
             checkLimits(nonNullSrc, srcPos, nonNullDest, destPos, length);
             if (probability(FAST_PATH_PROBABILITY, isObjectArray)) {
                 genericObjectExactCallCounter.inc();
+                genericObjectExactCallCopiedCounter.add(length);
                 ArrayCopyCallNode.disjointArraycopy(nonNullSrc, srcPos, nonNullDest, destPos, length, Kind.Object);
             } else {
                 genericPrimitiveCallCounter.inc();
+                genericPrimitiveCallCopiedCounter.add(length);
                 UnsafeArrayCopyNode.arraycopyPrimitive(nonNullSrc, srcPos, nonNullDest, destPos, length, layoutHelper);
             }
         } else {
             SystemArraycopyCounter.inc();
+            SystemArraycopyCopiedCounter.add(length);
             System.arraycopy(nonNullSrc, srcPos, nonNullDest, destPos, length);
         }
     }
@@ -273,17 +289,23 @@
 
     private static final SnippetCounter.Group counters = SnippetCounters.getValue() ? new SnippetCounter.Group("System.arraycopy") : null;
 
-    private static final SnippetCounter objectCheckcastCounter = new SnippetCounter(counters, "Object[]", "arraycopy for non-exact Object[] arrays");
-    private static final SnippetCounter objectCheckcastSameTypeCounter = new SnippetCounter(counters, "Object[]", "arraycopy call for src.klass == dest.klass Object[] arrays");
-    private static final SnippetCounter predictedObjectArrayCopySlowPathCounter = new SnippetCounter(counters, "Object[]", "used System.arraycopy slow path for predicted Object[] arrays");
-    private static final SnippetCounter predictedObjectArrayCopyFastPathCounter = new SnippetCounter(counters, "Object[]", "used oop_arraycopy for predicted Object[] arrays");
+    private static final SnippetCounter objectCheckcastCounter = new SnippetCounter(counters, "Object[]{non-exact}", "arraycopy for non-exact Object[] arrays");
+    private static final SnippetCounter objectCheckcastSameTypeCounter = new SnippetCounter(counters, "Object[]{same-type}", "arraycopy call for src.klass == dest.klass Object[] arrays");
+    private static final SnippetCounter predictedObjectArrayCopySlowPathCounter = new SnippetCounter(counters, "Object[]{slow-path}", "used System.arraycopy slow path for predicted Object[] arrays");
+    private static final SnippetCounter predictedObjectArrayCopyFastPathCounter = new SnippetCounter(counters, "Object[]{fast-path}", "used oop_arraycopy for predicted Object[] arrays");
 
     private static final EnumMap<Kind, SnippetCounter> arraycopyCallCounters = new EnumMap<>(Kind.class);
     private static final EnumMap<Kind, SnippetCounter> arraycopyCounters = new EnumMap<>(Kind.class);
 
+    private static final EnumMap<Kind, SnippetCounter> arraycopyCallCopiedCounters = new EnumMap<>(Kind.class);
+    private static final EnumMap<Kind, SnippetCounter> arraycopyCopiedCounters = new EnumMap<>(Kind.class);
+
     static void createArraycopyCounter(Kind kind) {
-        arraycopyCallCounters.put(kind, new SnippetCounter(counters, kind + "[]", "arraycopy call for " + kind + "[] arrays"));
-        arraycopyCounters.put(kind, new SnippetCounter(counters, kind + "[]", "inline arraycopy for " + kind + "[] arrays"));
+        arraycopyCallCounters.put(kind, new SnippetCounter(counters, kind + "[]{stub}", "arraycopy call for " + kind + "[] arrays"));
+        arraycopyCounters.put(kind, new SnippetCounter(counters, kind + "[]{inline}", "inline arraycopy for " + kind + "[] arrays"));
+
+        arraycopyCallCopiedCounters.put(kind, new SnippetCounter(copiedCounters, kind + "[]{stub}", "arraycopy call for " + kind + "[] arrays"));
+        arraycopyCopiedCounters.put(kind, new SnippetCounter(copiedCounters, kind + "[]{inline}", "inline arraycopy for " + kind + "[] arrays"));
     }
 
     static {
@@ -308,6 +330,19 @@
     private static final SnippetCounter zeroLengthDynamicCounter = new SnippetCounter(lengthCounters, "0-lengthcopy dynamically", "arraycopy where the length is dynamically 0");
     private static final SnippetCounter nonZeroLengthDynamicCounter = new SnippetCounter(lengthCounters, "non-0-lengthcopy dynamically", "arraycopy where the length is dynamically not zero");
 
+    private static final SnippetCounter.Group copiedCounters = SnippetCounters.getValue() ? new SnippetCounter.Group("System.arraycopy copied elements") : null;
+
+    private static final SnippetCounter nonZeroLengthDynamicCopiedCounter = new SnippetCounter(copiedCounters, "non-0-lengthcopy dynamically", "arraycopy where the length is dynamically not zero");
+    private static final SnippetCounter genericPrimitiveCallCopiedCounter = new SnippetCounter(copiedCounters, "genericPrimitive", "generic arraycopy snippet for primitive arrays");
+    private static final SnippetCounter genericObjectExactCallCopiedCounter = new SnippetCounter(copiedCounters, "genericObjectExact", "generic arraycopy snippet for special object arrays");
+    private static final SnippetCounter SystemArraycopyCopiedCounter = new SnippetCounter(copiedCounters, "genericObject", "call to System.arraycopy");
+
+    private static final SnippetCounter objectCheckcastCopiedCounter = new SnippetCounter(copiedCounters, "Object[]{non-exact}", "arraycopy for non-exact Object[] arrays");
+    private static final SnippetCounter objectCheckcastSameTypeCopiedCounter = new SnippetCounter(copiedCounters, "Object[]{same-type}", "arraycopy call for src.klass == dest.klass Object[] arrays");
+    private static final SnippetCounter predictedObjectArrayCopySlowPathCopiedCounter = new SnippetCounter(copiedCounters, "Object[]{slow-path}",
+                    "used System.arraycopy slow path for predicted Object[] arrays");
+    private static final SnippetCounter predictedObjectArrayCopyFastPathCopiedCounter = new SnippetCounter(copiedCounters, "Object[]{fast-path}", "used oop_arraycopy for predicted Object[] arrays");
+
     public static class Templates extends SnippetTemplate.AbstractTemplates {
 
         public Templates(HotSpotProviders providers, TargetDescription target) {
@@ -474,6 +509,7 @@
                 assert componentKind != null;
                 args.addConst("elementKind", componentKind);
                 args.addConst("counter", arraycopyCallCounters.get(componentKind));
+                args.addConst("copiedCounter", arraycopyCallCopiedCounters.get(componentKind));
             }
             instantiate(args, arraycopy);
         }
@@ -501,6 +537,7 @@
                 ValueNode objectArrayKlass = ConstantNode.forConstant(KlassPointerStamp.klassNonNull(), arrayKlass.klass(), tool.getMetaAccess(), arraycopy.graph());
                 args.add("objectArrayKlass", objectArrayKlass);
                 args.addConst("counter", arraycopyCallCounters.get(Kind.Object));
+                args.addConst("copiedCounter", arraycopyCallCopiedCounters.get(Kind.Object));
             }
             instantiate(args, arraycopy);
         }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/word/MetaspacePointer.java	Fri Jun 05 23:53:43 2015 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/word/MetaspacePointer.java	Fri Jun 05 23:54:02 2015 +0200
@@ -288,6 +288,7 @@
      * @param locationIdentity the identity of the write (see {@link LocationNode})
      * @param val the value to be written to memory
      */
+    @Operation(opcode = Opcode.WRITE_POINTER)
     public abstract void writeByte(WordBase offset, byte val, LocationIdentity locationIdentity);
 
     /**
@@ -302,6 +303,7 @@
      * @param locationIdentity the identity of the write (see {@link LocationNode})
      * @param val the value to be written to memory
      */
+    @Operation(opcode = Opcode.WRITE_POINTER)
     public abstract void writeChar(WordBase offset, char val, LocationIdentity locationIdentity);
 
     /**
@@ -316,6 +318,7 @@
      * @param locationIdentity the identity of the write (see {@link LocationNode})
      * @param val the value to be written to memory
      */
+    @Operation(opcode = Opcode.WRITE_POINTER)
     public abstract void writeShort(WordBase offset, short val, LocationIdentity locationIdentity);
 
     /**
@@ -330,6 +333,7 @@
      * @param locationIdentity the identity of the write (see {@link LocationNode})
      * @param val the value to be written to memory
      */
+    @Operation(opcode = Opcode.WRITE_POINTER)
     public abstract void writeInt(WordBase offset, int val, LocationIdentity locationIdentity);
 
     /**
@@ -344,6 +348,7 @@
      * @param locationIdentity the identity of the write (see {@link LocationNode})
      * @param val the value to be written to memory
      */
+    @Operation(opcode = Opcode.WRITE_POINTER)
     public abstract void writeLong(WordBase offset, long val, LocationIdentity locationIdentity);
 
     /**
@@ -358,6 +363,7 @@
      * @param locationIdentity the identity of the write (see {@link LocationNode})
      * @param val the value to be written to memory
      */
+    @Operation(opcode = Opcode.WRITE_POINTER)
     public abstract void writeFloat(WordBase offset, float val, LocationIdentity locationIdentity);
 
     /**
@@ -372,6 +378,7 @@
      * @param locationIdentity the identity of the write (see {@link LocationNode})
      * @param val the value to be written to memory
      */
+    @Operation(opcode = Opcode.WRITE_POINTER)
     public abstract void writeDouble(WordBase offset, double val, LocationIdentity locationIdentity);
 
     /**
@@ -386,6 +393,7 @@
      * @param locationIdentity the identity of the write (see {@link LocationNode})
      * @param val the value to be written to memory
      */
+    @Operation(opcode = Opcode.WRITE_POINTER)
     public abstract void writeWord(WordBase offset, WordBase val, LocationIdentity locationIdentity);
 
     /**
@@ -400,6 +408,7 @@
      * @param locationIdentity the identity of the write (see {@link LocationNode})
      * @param val the value to be written to memory
      */
+    @Operation(opcode = Opcode.INITIALIZE)
     public abstract void initializeLong(WordBase offset, long val, LocationIdentity locationIdentity);
 
     /**
@@ -414,6 +423,7 @@
      * @param locationIdentity the identity of the write (see {@link LocationNode})
      * @param val the value to be written to memory
      */
+    @Operation(opcode = Opcode.WRITE_POINTER)
     public abstract void writeObject(WordBase offset, Object val, LocationIdentity locationIdentity);
 
     /**
@@ -424,6 +434,7 @@
      * @param locationIdentity the identity of the write (see {@link LocationNode})
      * @param val the value to be written to memory
      */
+    @Operation(opcode = Opcode.WRITE_POINTER)
     public abstract void writeByte(int offset, byte val, LocationIdentity locationIdentity);
 
     /**
@@ -434,6 +445,7 @@
      * @param locationIdentity the identity of the write (see {@link LocationNode})
      * @param val the value to be written to memory
      */
+    @Operation(opcode = Opcode.WRITE_POINTER)
     public abstract void writeChar(int offset, char val, LocationIdentity locationIdentity);
 
     /**
@@ -444,6 +456,7 @@
      * @param locationIdentity the identity of the write (see {@link LocationNode})
      * @param val the value to be written to memory
      */
+    @Operation(opcode = Opcode.WRITE_POINTER)
     public abstract void writeShort(int offset, short val, LocationIdentity locationIdentity);
 
     /**
@@ -454,6 +467,7 @@
      * @param locationIdentity the identity of the write (see {@link LocationNode})
      * @param val the value to be written to memory
      */
+    @Operation(opcode = Opcode.WRITE_POINTER)
     public abstract void writeInt(int offset, int val, LocationIdentity locationIdentity);
 
     /**
@@ -464,6 +478,7 @@
      * @param locationIdentity the identity of the write (see {@link LocationNode})
      * @param val the value to be written to memory
      */
+    @Operation(opcode = Opcode.WRITE_POINTER)
     public abstract void writeLong(int offset, long val, LocationIdentity locationIdentity);
 
     /**
@@ -474,6 +489,7 @@
      * @param locationIdentity the identity of the write (see {@link LocationNode})
      * @param val the value to be written to memory
      */
+    @Operation(opcode = Opcode.WRITE_POINTER)
     public abstract void writeFloat(int offset, float val, LocationIdentity locationIdentity);
 
     /**
@@ -484,6 +500,7 @@
      * @param locationIdentity the identity of the write (see {@link LocationNode})
      * @param val the value to be written to memory
      */
+    @Operation(opcode = Opcode.WRITE_POINTER)
     public abstract void writeDouble(int offset, double val, LocationIdentity locationIdentity);
 
     /**
@@ -494,6 +511,7 @@
      * @param locationIdentity the identity of the write (see {@link LocationNode})
      * @param val the value to be written to memory
      */
+    @Operation(opcode = Opcode.WRITE_POINTER)
     public abstract void writeWord(int offset, WordBase val, LocationIdentity locationIdentity);
 
     /**
@@ -504,6 +522,7 @@
      * @param locationIdentity the identity of the write (see {@link LocationNode})
      * @param val the value to be written to memory
      */
+    @Operation(opcode = Opcode.INITIALIZE)
     public abstract void initializeLong(int offset, long val, LocationIdentity locationIdentity);
 
     /**
@@ -514,6 +533,7 @@
      * @param locationIdentity the identity of the write (see {@link LocationNode})
      * @param val the value to be written to memory
      */
+    @Operation(opcode = Opcode.WRITE_POINTER)
     public abstract void writeObject(int offset, Object val, LocationIdentity locationIdentity);
 
     /**
@@ -527,6 +547,7 @@
      * @param offset the signed offset for the memory access
      * @return the result of the memory access
      */
+    @Operation(opcode = Opcode.READ_POINTER)
     public abstract byte readByte(WordBase offset);
 
     /**
@@ -540,6 +561,7 @@
      * @param offset the signed offset for the memory access
      * @return the result of the memory access
      */
+    @Operation(opcode = Opcode.READ_POINTER)
     public abstract char readChar(WordBase offset);
 
     /**
@@ -553,6 +575,7 @@
      * @param offset the signed offset for the memory access
      * @return the result of the memory access
      */
+    @Operation(opcode = Opcode.READ_POINTER)
     public abstract short readShort(WordBase offset);
 
     /**
@@ -566,6 +589,7 @@
      * @param offset the signed offset for the memory access
      * @return the result of the memory access
      */
+    @Operation(opcode = Opcode.READ_POINTER)
     public abstract int readInt(WordBase offset);
 
     /**
@@ -579,6 +603,7 @@
      * @param offset the signed offset for the memory access
      * @return the result of the memory access
      */
+    @Operation(opcode = Opcode.READ_POINTER)
     public abstract long readLong(WordBase offset);
 
     /**
@@ -592,6 +617,7 @@
      * @param offset the signed offset for the memory access
      * @return the result of the memory access
      */
+    @Operation(opcode = Opcode.READ_POINTER)
     public abstract float readFloat(WordBase offset);
 
     /**
@@ -605,6 +631,7 @@
      * @param offset the signed offset for the memory access
      * @return the result of the memory access
      */
+    @Operation(opcode = Opcode.READ_POINTER)
     public abstract double readDouble(WordBase offset);
 
     /**
@@ -618,6 +645,7 @@
      * @param offset the signed offset for the memory access
      * @return the result of the memory access
      */
+    @Operation(opcode = Opcode.READ_POINTER)
     public abstract Word readWord(WordBase offset);
 
     /**
@@ -631,6 +659,7 @@
      * @param offset the signed offset for the memory access
      * @return the result of the memory access
      */
+    @Operation(opcode = Opcode.READ_POINTER)
     public abstract Object readObject(WordBase offset);
 
     /**
@@ -646,6 +675,7 @@
      * @param barrierType the type of the read barrier to be added
      * @return the result of the memory access
      */
+    @Operation(opcode = Opcode.READ_POINTER)
     public abstract Object readObject(WordBase offset, BarrierType barrierType);
 
     /**
@@ -655,6 +685,7 @@
      * @param offset the signed offset for the memory access
      * @return the result of the memory access
      */
+    @Operation(opcode = Opcode.READ_POINTER)
     public abstract byte readByte(int offset);
 
     /**
@@ -664,6 +695,7 @@
      * @param offset the signed offset for the memory access
      * @return the result of the memory access
      */
+    @Operation(opcode = Opcode.READ_POINTER)
     public abstract char readChar(int offset);
 
     /**
@@ -673,6 +705,7 @@
      * @param offset the signed offset for the memory access
      * @return the result of the memory access
      */
+    @Operation(opcode = Opcode.READ_POINTER)
     public abstract short readShort(int offset);
 
     /**
@@ -682,6 +715,7 @@
      * @param offset the signed offset for the memory access
      * @return the result of the memory access
      */
+    @Operation(opcode = Opcode.READ_POINTER)
     public abstract int readInt(int offset);
 
     /**
@@ -691,6 +725,7 @@
      * @param offset the signed offset for the memory access
      * @return the result of the memory access
      */
+    @Operation(opcode = Opcode.READ_POINTER)
     public abstract long readLong(int offset);
 
     /**
@@ -700,6 +735,7 @@
      * @param offset the signed offset for the memory access
      * @return the result of the memory access
      */
+    @Operation(opcode = Opcode.READ_POINTER)
     public abstract float readFloat(int offset);
 
     /**
@@ -709,6 +745,7 @@
      * @param offset the signed offset for the memory access
      * @return the result of the memory access
      */
+    @Operation(opcode = Opcode.READ_POINTER)
     public abstract double readDouble(int offset);
 
     /**
@@ -718,6 +755,7 @@
      * @param offset the signed offset for the memory access
      * @return the result of the memory access
      */
+    @Operation(opcode = Opcode.READ_POINTER)
     public abstract Word readWord(int offset);
 
     /**
@@ -727,6 +765,7 @@
      * @param offset the signed offset for the memory access
      * @return the result of the memory access
      */
+    @Operation(opcode = Opcode.READ_POINTER)
     public abstract Object readObject(int offset);
 
     /**
@@ -738,6 +777,7 @@
      * @param barrierType the type of the read barrier to be added
      * @return the result of the memory access
      */
+    @Operation(opcode = Opcode.READ_POINTER)
     public abstract Object readObject(int offset, BarrierType barrierType);
 
     /**
@@ -751,6 +791,7 @@
      * @param offset the signed offset for the memory access
      * @param val the value to be written to memory
      */
+    @Operation(opcode = Opcode.WRITE_POINTER)
     public abstract void writeByte(WordBase offset, byte val);
 
     /**
@@ -764,6 +805,7 @@
      * @param offset the signed offset for the memory access
      * @param val the value to be written to memory
      */
+    @Operation(opcode = Opcode.WRITE_POINTER)
     public abstract void writeChar(WordBase offset, char val);
 
     /**
@@ -777,6 +819,7 @@
      * @param offset the signed offset for the memory access
      * @param val the value to be written to memory
      */
+    @Operation(opcode = Opcode.WRITE_POINTER)
     public abstract void writeShort(WordBase offset, short val);
 
     /**
@@ -790,6 +833,7 @@
      * @param offset the signed offset for the memory access
      * @param val the value to be written to memory
      */
+    @Operation(opcode = Opcode.WRITE_POINTER)
     public abstract void writeInt(WordBase offset, int val);
 
     /**
@@ -803,6 +847,7 @@
      * @param offset the signed offset for the memory access
      * @param val the value to be written to memory
      */
+    @Operation(opcode = Opcode.WRITE_POINTER)
     public abstract void writeLong(WordBase offset, long val);
 
     /**
@@ -816,6 +861,7 @@
      * @param offset the signed offset for the memory access
      * @param val the value to be written to memory
      */
+    @Operation(opcode = Opcode.WRITE_POINTER)
     public abstract void writeFloat(WordBase offset, float val);
 
     /**
@@ -829,6 +875,7 @@
      * @param offset the signed offset for the memory access
      * @param val the value to be written to memory
      */
+    @Operation(opcode = Opcode.WRITE_POINTER)
     public abstract void writeDouble(WordBase offset, double val);
 
     /**
@@ -842,6 +889,7 @@
      * @param offset the signed offset for the memory access
      * @param val the value to be written to memory
      */
+    @Operation(opcode = Opcode.WRITE_POINTER)
     public abstract void writeWord(WordBase offset, WordBase val);
 
     /**
@@ -855,6 +903,7 @@
      * @param offset the signed offset for the memory access
      * @param val the value to be written to memory
      */
+    @Operation(opcode = Opcode.WRITE_POINTER)
     public abstract void writeObject(WordBase offset, Object val);
 
     /**
@@ -864,6 +913,7 @@
      * @param offset the signed offset for the memory access
      * @param val the value to be written to memory
      */
+    @Operation(opcode = Opcode.WRITE_POINTER)
     public abstract void writeByte(int offset, byte val);
 
     /**
@@ -873,6 +923,7 @@
      * @param offset the signed offset for the memory access
      * @param val the value to be written to memory
      */
+    @Operation(opcode = Opcode.WRITE_POINTER)
     public abstract void writeChar(int offset, char val);
 
     /**
@@ -882,6 +933,7 @@
      * @param offset the signed offset for the memory access
      * @param val the value to be written to memory
      */
+    @Operation(opcode = Opcode.WRITE_POINTER)
     public abstract void writeShort(int offset, short val);
 
     /**
@@ -891,6 +943,7 @@
      * @param offset the signed offset for the memory access
      * @param val the value to be written to memory
      */
+    @Operation(opcode = Opcode.WRITE_POINTER)
     public abstract void writeInt(int offset, int val);
 
     /**
@@ -900,6 +953,7 @@
      * @param offset the signed offset for the memory access
      * @param val the value to be written to memory
      */
+    @Operation(opcode = Opcode.WRITE_POINTER)
     public abstract void writeLong(int offset, long val);
 
     /**
@@ -909,6 +963,7 @@
      * @param offset the signed offset for the memory access
      * @param val the value to be written to memory
      */
+    @Operation(opcode = Opcode.WRITE_POINTER)
     public abstract void writeFloat(int offset, float val);
 
     /**
@@ -918,6 +973,7 @@
      * @param offset the signed offset for the memory access
      * @param val the value to be written to memory
      */
+    @Operation(opcode = Opcode.WRITE_POINTER)
     public abstract void writeDouble(int offset, double val);
 
     /**
@@ -927,6 +983,7 @@
      * @param offset the signed offset for the memory access
      * @param val the value to be written to memory
      */
+    @Operation(opcode = Opcode.WRITE_POINTER)
     public abstract void writeWord(int offset, WordBase val);
 
     /**
@@ -936,5 +993,6 @@
      * @param offset the signed offset for the memory access
      * @param val the value to be written to memory
      */
+    @Operation(opcode = Opcode.WRITE_POINTER)
     public abstract void writeObject(int offset, Object val);
 }
--- a/graal/com.oracle.graal.java.test/src/com/oracle/graal/java/test/TestBytecodeDisassemblerProvider.java	Fri Jun 05 23:53:43 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,64 +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.java.test;
-
-import com.oracle.jvmci.meta.ResolvedJavaMethod;
-import com.oracle.jvmci.meta.BytecodeDisassemblerProvider;
-import com.oracle.jvmci.runtime.test.*;
-
-import org.junit.*;
-
-import com.oracle.graal.java.*;
-
-/**
- * Tests for {@link BytecodeDisassemblerProvider}.
- */
-public class TestBytecodeDisassemblerProvider extends MethodUniverse {
-
-    public TestBytecodeDisassemblerProvider() {
-    }
-
-    /**
-     * Tests that successive disassembling of the same method produces the same result.
-     */
-    @Test
-    public void disassembleTest() {
-        BytecodeDisassemblerProvider dis = new BytecodeDisassembler();
-        if (dis != null) {
-            int count = 0;
-            for (ResolvedJavaMethod m : methods.values()) {
-                String disasm1 = dis.disassemble(m);
-                String disasm2 = dis.disassemble(m);
-                if (disasm1 == null) {
-                    Assert.assertTrue(disasm2 == null);
-                } else {
-                    Assert.assertTrue(String.valueOf(m), disasm1.length() > 0);
-                    Assert.assertEquals(String.valueOf(m), disasm1, disasm2);
-                }
-                if (count++ > 20) {
-                    break;
-                }
-            }
-        }
-    }
-}
--- a/graal/com.oracle.graal.java/src/com/oracle/graal/java/BytecodeDisassembler.java	Fri Jun 05 23:53:43 2015 +0200
+++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/BytecodeDisassembler.java	Fri Jun 05 23:54:02 2015 +0200
@@ -22,21 +22,15 @@
  */
 package com.oracle.graal.java;
 
+import static com.oracle.graal.bytecode.Bytecodes.*;
+
 import com.oracle.graal.bytecode.*;
-import com.oracle.jvmci.meta.JavaField;
-import com.oracle.jvmci.meta.ResolvedJavaMethod;
-import com.oracle.jvmci.meta.BytecodeDisassemblerProvider;
-import com.oracle.jvmci.meta.JavaConstant;
-import com.oracle.jvmci.meta.JavaType;
-import com.oracle.jvmci.meta.JavaMethod;
-import com.oracle.jvmci.meta.ConstantPool;
-
-import static com.oracle.graal.bytecode.Bytecodes.*;
+import com.oracle.jvmci.meta.*;
 
 /**
  * Utility for producing a {@code javap}-like disassembly of bytecode.
  */
-public class BytecodeDisassembler implements BytecodeDisassemblerProvider {
+public class BytecodeDisassembler {
 
     /**
      * Specifies if the disassembly for a single instruction can span multiple lines.
--- a/graal/com.oracle.graal.java/src/com/oracle/graal/java/BytecodeParser.java	Fri Jun 05 23:53:43 2015 +0200
+++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/BytecodeParser.java	Fri Jun 05 23:54:02 2015 +0200
@@ -931,8 +931,8 @@
         } else {
             dispatchBegin = graph.add(new DispatchBeginNode());
             dispatchState.push(Kind.Object, exceptionObject);
+            dispatchState.setRethrowException(true);
             dispatchBegin.setStateAfter(dispatchState.create(bci, dispatchBegin));
-            dispatchState.setRethrowException(true);
         }
         this.controlFlowSplit = true;
         FixedNode target = createTarget(dispatchBlock, dispatchState);
--- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/ReplacementsImpl.java	Fri Jun 05 23:53:43 2015 +0200
+++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/ReplacementsImpl.java	Fri Jun 05 23:54:02 2015 +0200
@@ -504,12 +504,19 @@
          * Does final processing of a snippet graph.
          */
         protected void finalizeGraph(StructuredGraph graph) {
-            int sideEffectCount = 0;
-            assert (sideEffectCount = graph.getNodes().filter(e -> hasSideEffect(e)).count()) >= 0;
-            new ConvertDeoptimizeToGuardPhase().apply(graph, null);
-            assert sideEffectCount == graph.getNodes().filter(e -> hasSideEffect(e)).count() : "deleted side effecting node";
+            if (!GraalOptions.SnippetCounters.getValue() || graph.getNodes().filter(SnippetCounterNode.class).isEmpty()) {
+                int sideEffectCount = 0;
+                assert (sideEffectCount = graph.getNodes().filter(e -> hasSideEffect(e)).count()) >= 0;
+                new ConvertDeoptimizeToGuardPhase().apply(graph, null);
+                assert sideEffectCount == graph.getNodes().filter(e -> hasSideEffect(e)).count() : "deleted side effecting node";
 
-            new DeadCodeEliminationPhase(Required).apply(graph);
+                new DeadCodeEliminationPhase(Required).apply(graph);
+            } else {
+                // ConvertDeoptimizeToGuardPhase will eliminate snippet counters on paths
+                // that terminate in a deopt so we disable it if the graph contains
+                // snippet counters. The trade off is that we miss out on guard
+                // coalescing opportunities.
+            }
         }
 
         /**
--- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/SnippetCounter.java	Fri Jun 05 23:53:43 2015 +0200
+++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/SnippetCounter.java	Fri Jun 05 23:54:02 2015 +0200
@@ -58,10 +58,13 @@
 
             StringBuilder buf = new StringBuilder(String.format("Counters: %s%n", name));
 
+            String formatString = "  %" + maxNameLen + "s: %6.2f%%%," + (String.format("%,d", total).length() + 2) + "d  // %s%n";
             for (SnippetCounter c : counters) {
                 double percent = total == 0D ? 0D : ((double) (c.value * 100)) / total;
-                buf.append(String.format("  %" + maxNameLen + "s: %5.2f%%%10d  // %s%n", c.name, percent, c.value, c.description));
+                buf.append(String.format(formatString, c.name, percent, c.value, c.description));
             }
+            buf.append(String.format(formatString, "TOTAL", 100.0D, total, ""));
+
             return buf.toString();
         }
     }
@@ -112,8 +115,8 @@
     }
 
     /**
-     * Increments the value of this counter. This method can be safely used in a snippet if it is
-     * invoked on a compile-time constant {@link SnippetCounter} object.
+     * Increments the value of this counter. This method can only be used in a snippet on a
+     * compile-time constant {@link SnippetCounter} object.
      */
     public void inc() {
         if (group != null) {
@@ -122,6 +125,16 @@
     }
 
     /**
+     * Increments the value of this counter. This method can only be used in a snippet on a
+     * compile-time constant {@link SnippetCounter} object.
+     */
+    public void add(int increment) {
+        if (group != null) {
+            SnippetCounterNode.add(this, increment);
+        }
+    }
+
+    /**
      * Gets the value of this counter.
      */
     public long value() {
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/PartialEvaluator.java	Fri Jun 05 23:53:43 2015 +0200
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/PartialEvaluator.java	Fri Jun 05 23:54:02 2015 +0200
@@ -302,8 +302,10 @@
 
         newConfig.setUseProfiling(false);
         Plugins plugins = newConfig.getPlugins();
+        ReplacementsImpl replacements = (ReplacementsImpl) providers.getReplacements();
         plugins.clearInlineInvokePlugins();
-        plugins.appendInlineInvokePlugin(new ParsingInlineInvokePlugin((ReplacementsImpl) providers.getReplacements(), parsingInvocationPlugins, loopExplosionPlugin));
+        plugins.appendInlineInvokePlugin(replacements);
+        plugins.appendInlineInvokePlugin(new ParsingInlineInvokePlugin(replacements, parsingInvocationPlugins, loopExplosionPlugin));
         if (!PrintTruffleExpansionHistogram.getValue()) {
             plugins.appendInlineInvokePlugin(new InlineDuringParsingPlugin());
         }
--- a/graal/com.oracle.jvmci.meta/src/com/oracle/jvmci/meta/BytecodeDisassemblerProvider.java	Fri Jun 05 23:53:43 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,38 +0,0 @@
-/*
- * Copyright (c) 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
- * 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.jvmci.meta;
-
-/**
- * Interface for disassembling bytecode.
- */
-public interface BytecodeDisassemblerProvider {
-
-    /**
-     * Gets a textual disassembly of the bytecode for a given method. In the absence of bytecode
-     * rewriting, disassembling a method will produce the same result.
-     *
-     * @return a non-zero length string containing a disassembly of {@code method}'s bytecode or
-     *         null if {@code method} has no bytecode (i.e., {@code method.getCodeSize() == 0})
-     */
-    String disassemble(ResolvedJavaMethod method);
-}
--- a/mx/suite.py	Fri Jun 05 23:53:43 2015 +0200
+++ b/mx/suite.py	Fri Jun 05 23:54:02 2015 +0200
@@ -973,19 +973,6 @@
       "workingSets" : "Graal,Java",
     },
 
-    "com.oracle.graal.java.test" : {
-      "subDir" : "graal",
-      "sourceDirs" : ["src"],
-      "dependencies" : [
-        "com.oracle.jvmci.runtime.test",
-        "com.oracle.graal.java",
-      ],
-      "checkstyle" : "com.oracle.graal.graph",
-      "javaCompliance" : "1.8",
-      "workingSets" : "API,Graal,Test",
-      "jacoco" : "exclude",
-    },
-
     "com.oracle.graal.graphbuilderconf" : {
       "subDir" : "graal",
       "sourceDirs" : ["src"],