changeset 5333:b1de7c9ab0e0

expanded analysis of compiled checkcast code paths
author Doug Simon <doug.simon@oracle.com>
date Wed, 02 May 2012 11:31:53 +0200
parents 71157e8ea13b
children ecc2b68344de
files graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/ri/HotSpotXirGenerator.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/ri/TemplateFlag.java graal/com.oracle.max.cri/src/com/oracle/max/cri/xir/RiXirGenerator.java
diffstat 3 files changed, 82 insertions(+), 58 deletions(-) [+]
line wrap: on
line diff
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/ri/HotSpotXirGenerator.java	Tue May 01 15:20:49 2012 -0700
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/ri/HotSpotXirGenerator.java	Wed May 02 11:31:53 2012 +0200
@@ -32,7 +32,6 @@
 import sun.misc.*;
 
 import com.oracle.graal.compiler.*;
-import com.oracle.graal.graph.*;
 import com.oracle.graal.hotspot.*;
 import com.oracle.graal.hotspot.Compiler;
 import com.oracle.max.asm.target.amd64.*;
@@ -464,62 +463,36 @@
         }
     };
 
-    private static final CheckcastCounters checkcastCounters = GraalOptions.CheckcastCounters ? new CheckcastCounters() : null;
-
-    public static class CheckcastCounters {
-        long hintsHits;
-        long hintsMisses;
-        long exact;
-        long noHints;
-        long isNull;
-        long exceptions;
+    enum CheckcastCounter {
+        hintsHit("hit one of the hint types"),
+        hintsMissed("missed all of the hint types"),
+        exact("tested type is (statically) final"),
+        noHints_class("profile information is not available for tested class"),
+        noHints_iface("profile information is not available for tested interface"),
+        noHints_unknown("tested type is not a compile-time constant"),
+        isNull("object tested is null"),
+        exception("type test failed with a ClassCastException");
 
-        static final int hintsHitsOffset;
-        static final int hintsMissesOffset;
-        static final int exactOffset;
-        static final int noHintsOffset;
-        static final int isNullOffset;
-        static final int exceptionsOffset;
+        public final String desc;
 
-        static {
-            Unsafe unsafe = Unsafe.getUnsafe();
-            try {
-                hintsHitsOffset = (int) unsafe.objectFieldOffset(CheckcastCounters.class.getDeclaredField("hintsHits"));
-                hintsMissesOffset = (int) unsafe.objectFieldOffset(CheckcastCounters.class.getDeclaredField("hintsMisses"));
-                exactOffset = (int) unsafe.objectFieldOffset(CheckcastCounters.class.getDeclaredField("exact"));
-                noHintsOffset = (int) unsafe.objectFieldOffset(CheckcastCounters.class.getDeclaredField("noHints"));
-                isNullOffset = (int) unsafe.objectFieldOffset(CheckcastCounters.class.getDeclaredField("isNull"));
-                exceptionsOffset = (int) unsafe.objectFieldOffset(CheckcastCounters.class.getDeclaredField("exceptions"));
-            } catch (Exception e) {
-                throw new GraalInternalError(e);
-            }
+        private CheckcastCounter(String desc) {
+            this.desc = desc;
         }
 
-        private static void printCounter(PrintStream out, String label, long count, long total) {
-            double percent = ((double) (count * 100)) / total;
-            out.println(String.format("%16s: %5.2f%%%10d", label, percent, count));
-        }
+        static final CheckcastCounter[] VALUES = values();
+    }
 
-        public void printCounters(PrintStream out) {
-            long total = hintsHits + hintsMisses + exact + noHints + isNull + exceptions;
-            out.println();
-            out.println("** Checkcast counters **");
-            printCounter(out, "hintsHits", hintsHits, total);
-            printCounter(out, "hintsMisses", hintsMisses, total);
-            printCounter(out, "exact", exact, total);
-            printCounter(out, "noHints", noHints, total);
-            printCounter(out, "isNull", isNull, total);
-            printCounter(out, "exceptions", exceptions, total);
-        }
-    }
+    private static final long[] checkcastCounters = new long[CheckcastCounter.VALUES.length];
 
     private IndexTemplates checkCastTemplates = new IndexTemplates(NULL_CHECK, EXACT_HINTS) {
 
-        private void incCounter(CiXirAssembler asm, XirOperand counter, XirParameter counters, int offset) {
-            XirConstant offsetOp = asm.i(offset);
-            asm.pload(CiKind.Long, counter, counters, offsetOp, false);
+        private void incCounter(CiXirAssembler asm, XirOperand counter, XirParameter counters, CheckcastCounter offset) {
+            int disp = Unsafe.getUnsafe().arrayBaseOffset(long[].class);
+            Scale scale = Scale.fromInt(Unsafe.getUnsafe().arrayIndexScale(long[].class));
+            XirConstant index = asm.i(offset.ordinal());
+            asm.pload(CiKind.Long, counter, counters, index, disp, scale, false);
             asm.add(counter, counter, asm.i(1));
-            asm.pstore(CiKind.Long, counters, offsetOp, counter, false);
+            asm.pstore(CiKind.Long, counters, index, counter, disp, scale, false);
         }
 
         @Override
@@ -541,7 +514,7 @@
                 if (counters != null) {
                     XirLabel isNotNull = asm.createInlineLabel("isNull");
                     asm.jneq(isNotNull, object, asm.o(null));
-                    incCounter(asm, counter, counters, CheckcastCounters.isNullOffset);
+                    incCounter(asm, counter, counters, CheckcastCounter.isNull);
                     asm.jmp(success);
                     asm.bindInline(isNotNull);
                 } else {
@@ -554,7 +527,7 @@
             if (hintCount == 0) {
                 assert !exact;
                 if (counters != null) {
-                    incCounter(asm, counter, counters, CheckcastCounters.noHintsOffset);
+                    incCounter(asm, counter, counters, is(NULL_TYPE, flags) ? CheckcastCounter.noHints_unknown : is(INTERFACE_TYPE, flags) ? CheckcastCounter.noHints_iface : CheckcastCounter.noHints_class);
                 }
 
                 checkSubtype(asm, objHub, objHub, hub);
@@ -579,7 +552,7 @@
 
                 if (counters != null) {
                     asm.bindInline(hintsSuccess);
-                    incCounter(asm, counter, counters, exact ? CheckcastCounters.exactOffset : CheckcastCounters.hintsHitsOffset);
+                    incCounter(asm, counter, counters, exact ? CheckcastCounter.exact : CheckcastCounter.hintsHit);
                 }
 
                 asm.bindInline(success);
@@ -588,7 +561,7 @@
                 asm.bindOutOfLine(slowPath);
                 if (!exact) {
                     if (counters != null) {
-                        incCounter(asm, counter, counters, CheckcastCounters.hintsMissesOffset);
+                        incCounter(asm, counter, counters, CheckcastCounter.hintsMissed);
                     }
                     checkSubtype(asm, objHub, objHub, hub);
                     asm.jneq(success, objHub, asm.o(null));
@@ -596,7 +569,7 @@
             }
 
             if (counters != null) {
-                incCounter(asm, counter, counters, CheckcastCounters.exceptionsOffset);
+                incCounter(asm, counter, counters, CheckcastCounter.exception);
             }
             RiDeoptReason deoptReason = exact ? RiDeoptReason.OptimizedTypeCheckViolated : RiDeoptReason.ClassCastException;
             XirOperand scratch = asm.createRegisterTemp("scratch", target.wordKind, AMD64.r10);
@@ -825,11 +798,17 @@
     }
 
     @Override
-    public XirSnippet genCheckCast(XirSite site, XirArgument receiver, XirArgument hub, RiType type, RiResolvedType[] hints, boolean hintsExact) {
+    public XirSnippet genCheckCast(XirSite site, XirArgument receiver, XirArgument hub, RiResolvedType type, RiResolvedType[] hints, boolean hintsExact) {
         final boolean useCounters = GraalOptions.CheckcastCounters;
         if (hints == null || hints.length == 0) {
             if (useCounters) {
-                return new XirSnippet(checkCastTemplates.get(site, 0), XirArgument.forObject(checkcastCounters), receiver, hub);
+                if (type == null) {
+                    return new XirSnippet(checkCastTemplates.get(site, 0, NULL_TYPE), XirArgument.forObject(checkcastCounters), receiver, hub);
+                } else if (type.isInterface()) {
+                    return new XirSnippet(checkCastTemplates.get(site, 0, INTERFACE_TYPE), XirArgument.forObject(checkcastCounters), receiver, hub);
+                } else {
+                    return new XirSnippet(checkCastTemplates.get(site, 0), XirArgument.forObject(checkcastCounters), receiver, hub);
+                }
             } else {
                 return new XirSnippet(checkCastTemplates.get(site, 0), receiver, hub);
             }
@@ -1015,9 +994,42 @@
         }
     }
 
+    private static void printCounter(PrintStream out, CheckcastCounter name, long count, long total) {
+        double percent = ((double) (count * 100)) / total;
+        out.println(String.format("%16s: %5.2f%%%10d  // %s", name, percent, count, name.desc));
+    }
+
+    public static  void printCheckcastCounters(PrintStream out) {
+        class Count implements Comparable<Count> {
+            long c;
+            CheckcastCounter name;
+            Count(long c, CheckcastCounter name) {
+                this.c = c;
+                this.name = name;
+            }
+            public int compareTo(Count o) {
+                return (int) (o.c - c);
+            }
+        }
+
+        long total = 0;
+        Count[] counters = new Count[checkcastCounters.length];
+        for (int i = 0; i < counters.length; i++) {
+            counters[i] = new Count(checkcastCounters[i], CheckcastCounter.VALUES[i]);
+            total += checkcastCounters[i];
+        }
+        Arrays.sort(counters);
+
+        out.println();
+        out.println("** Checkcast counters **");
+        for (Count c : counters) {
+            printCounter(out, c.name, c.c, total);
+        }
+    }
+
     public static void printCounters(PrintStream out) {
         if (GraalOptions.CheckcastCounters) {
-            checkcastCounters.printCounters(out);
+            printCheckcastCounters(out);
         }
     }
 }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/ri/TemplateFlag.java	Tue May 01 15:20:49 2012 -0700
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/ri/TemplateFlag.java	Wed May 02 11:31:53 2012 +0200
@@ -23,7 +23,19 @@
 package com.oracle.graal.hotspot.ri;
 
 enum TemplateFlag {
-    NULL_CHECK, READ_BARRIER, WRITE_BARRIER, STORE_CHECK, BOUNDS_CHECK, GIVEN_LENGTH, INPUTS_DIFFERENT, INPUTS_SAME, STATIC_METHOD, SYNCHRONIZED, EXACT_HINTS;
+    NULL_CHECK,
+    READ_BARRIER,
+    WRITE_BARRIER,
+    STORE_CHECK,
+    BOUNDS_CHECK,
+    GIVEN_LENGTH,
+    INPUTS_DIFFERENT,
+    INPUTS_SAME,
+    STATIC_METHOD,
+    SYNCHRONIZED,
+    INTERFACE_TYPE,
+    NULL_TYPE,
+    EXACT_HINTS;
 
     private static final long FIRST_FLAG = 0x0000000100000000L;
     public static final long FLAGS_MASK = 0x0000FFFF00000000L;
--- a/graal/com.oracle.max.cri/src/com/oracle/max/cri/xir/RiXirGenerator.java	Tue May 01 15:20:49 2012 -0700
+++ b/graal/com.oracle.max.cri/src/com/oracle/max/cri/xir/RiXirGenerator.java	Wed May 02 11:31:53 2012 +0200
@@ -49,7 +49,7 @@
 
     XirSnippet genNewMultiArray(XirSite site, XirArgument[] lengths, RiType type);
 
-    XirSnippet genCheckCast(XirSite site, XirArgument receiver, XirArgument hub, RiType type, RiResolvedType[] hints, boolean hintsExact);
+    XirSnippet genCheckCast(XirSite site, XirArgument receiver, XirArgument hub, RiResolvedType type, RiResolvedType[] hints, boolean hintsExact);
 
     XirSnippet genInstanceOf(XirSite site, XirArgument receiver, XirArgument hub, RiType type, RiResolvedType[] hints, boolean hintsExact);