changeset 4440:271220b49abc

profiling info fixes
author Christian Haeubl <christian.haeubl@oracle.com>
date Fri, 20 Jan 2012 18:24:17 -0800
parents f7251c729b31
children 4e3aaf14cbc6
files graal/com.oracle.max.cri/src/com/oracle/max/cri/ri/RiProfilingInfo.java graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/InliningPhase.java graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/util/InliningUtil.java graal/com.oracle.max.graal.hotspot/src/com/oracle/max/graal/hotspot/bridge/CompilerToVMImpl.java graal/com.oracle.max.graal.hotspot/src/com/oracle/max/graal/hotspot/ri/HOTSPOTMETHODDATAACCESSOR.JAVA graal/com.oracle.max.graal.hotspot/src/com/oracle/max/graal/hotspot/ri/HOTSPOTPROFILINGINFOIMPL.JAVA graal/com.oracle.max.graal.hotspot/src/com/oracle/max/graal/hotspot/ri/HotSpotMethodData.java graal/com.oracle.max.graal.hotspot/src/com/oracle/max/graal/hotspot/ri/HotSpotMethodResolvedImpl.java graal/com.oracle.max.graal.java/src/com/oracle/max/graal/java/BlockMap.java graal/com.oracle.max.graal.java/src/com/oracle/max/graal/java/GraphBuilderPhase.java
diffstat 10 files changed, 269 insertions(+), 115 deletions(-) [+]
line wrap: on
line diff
--- a/graal/com.oracle.max.cri/src/com/oracle/max/cri/ri/RiProfilingInfo.java	Thu Jan 19 16:29:35 2012 -0800
+++ b/graal/com.oracle.max.cri/src/com/oracle/max/cri/ri/RiProfilingInfo.java	Fri Jan 20 18:24:17 2012 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved.
+ * 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
@@ -27,20 +27,42 @@
  * Represents profiling information for one specific method.
  */
 public interface RiProfilingInfo {
-    // iterating the profiling information
-    boolean setBCI(int bci);
-    int currentBCI();
-    boolean next();
-    boolean isAtValidData();
+    /**
+     * Returns an estimate of how often the branch at the given byte code was taken.
+     * @return The estimated probability, with 0.0 meaning never and 1.0 meaning always, or -1 if this information is not available.
+     */
+    double getBranchTakenProbability(int bci);
+
+    /**
+     * Returns an estimate of how often the switch cases are taken at the given BCI.
+     * @return An array of double values that contains the estimated probabilities, with 0.0 meaning never and 1.0 meaning always,
+     * or null if this information is not available. The default case is stored as the last entry.
+     */
+    double[] getSwitchProbabilities(int bci);
+
+    /**
+     * Returns all types that were encountered at the given BCI.
+     * @return An array containing all types that were encountered during profiling at the given BCI, or null if not available.
+     */
+    RiResolvedType[] getTypes(int bci);
 
-    // invokevirtual/invokeinterface
-    RiResolvedType[] getTypes();
-    double[] getTypeProbabilities();
+    /**
+     * Returns an estimate of how often each individual type is encountered at the given BCI.
+     * @return An array of double values that contains the estimated probabilities, with 0.0 meaning never and 1.0 meaning always,
+     * or null if this information is not available.
+     */
+    double[] getTypeProbabilities(int bci);
 
-    // branches
-    double getBranchTakenProbability();
-    double[] getSwitchProbabilities();
+    /**
+     * Returns true if the given BCI did throw an implicit exception (NullPointerException, ClassCastException,
+     * ArrayStoreException, or ArithmeticException) during profiling.
+     * @return true if any of the exceptions was encountered during profiling, false otherwise.
+     */
+    boolean getImplicitExceptionSeen(int bci);
 
-    // exceptions
-    boolean hasExceptionOccurred();
+    /**
+     * Returns an estimate how often the current BCI was executed.
+     * @return the estimated execution count or -1 if not available.
+     */
+    int getExecutionCount(int bci);
 }
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/InliningPhase.java	Thu Jan 19 16:29:35 2012 -0800
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/InliningPhase.java	Fri Jan 20 18:24:17 2012 -0800
@@ -181,10 +181,11 @@
             if (GraalOptions.ProbabilityAnalysis) {
                 ratio = invoke.node().probability();
             } else {
-                RiTypeProfile profile = caller.typeProfile(invoke.bci());
-                if (profile != null && profile.count > 0) {
+                RiProfilingInfo profilingInfo = method.profilingInfo();
+                int executionCount = profilingInfo.getExecutionCount(invoke.bci());
+                if (executionCount > 0) {
                     RiResolvedMethod parent = invoke.stateAfter().method();
-                    ratio = profile.count / (float) parent.invocationCount();
+                    ratio = executionCount / (float) parent.invocationCount();
                 } else {
                     ratio = 1;
                 }
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/util/InliningUtil.java	Thu Jan 19 16:29:35 2012 -0800
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/util/InliningUtil.java	Fri Jan 20 18:24:17 2012 -0800
@@ -263,14 +263,19 @@
             }
             return null;
         }
-        RiTypeProfile profile = parent.typeProfile(invoke.bci());
-        if (profile != null && profile.probabilities != null && profile.probabilities.length > 0 && profile.morphism == 1) {
+
+        int invokeBCI = invoke.bci();
+        RiProfilingInfo profilingInfo = parent.profilingInfo();
+        RiResolvedType[] types = profilingInfo.getTypes(invokeBCI);
+        double[] typeProbabilities = profilingInfo.getTypeProbabilities(invokeBCI);
+        if (types != null && typeProbabilities != null && types.length == 1) {
+            assert types.length == typeProbabilities.length : "length must match";
             if (GraalOptions.InlineWithTypeCheck) {
                 // type check and inlining...
-                concrete = profile.types[0].resolveMethodImpl(callTarget.targetMethod());
+                concrete = types[0].resolveMethodImpl(callTarget.targetMethod());
                 if (concrete != null && checkTargetConditions(concrete)) {
                     double weight = callback == null ? 0 : callback.inliningWeight(parent, concrete, invoke);
-                    return new TypeGuardInlineInfo(invoke, weight, level, concrete, profile.types[0], profile.probabilities[0]);
+                    return new TypeGuardInlineInfo(invoke, weight, level, concrete, types[0], typeProbabilities[0]);
                 }
                 return null;
             } else {
--- a/graal/com.oracle.max.graal.hotspot/src/com/oracle/max/graal/hotspot/bridge/CompilerToVMImpl.java	Thu Jan 19 16:29:35 2012 -0800
+++ b/graal/com.oracle.max.graal.hotspot/src/com/oracle/max/graal/hotspot/bridge/CompilerToVMImpl.java	Fri Jan 20 18:24:17 2012 -0800
@@ -111,7 +111,7 @@
     public native boolean RiType_isInitialized(HotSpotTypeResolved klass);
 
     @Override
-    public native RiProfilingInfo RiMethod_profilingInfo(HotSpotMethodResolved method);
+    public native HotSpotMethodData RiMethod_methodData(HotSpotMethodResolved method);
 
     @Override
     public native RiType getType(Class<?> javaClass);
--- a/graal/com.oracle.max.graal.hotspot/src/com/oracle/max/graal/hotspot/ri/HOTSPOTMETHODDATAACCESSOR.JAVA	Thu Jan 19 16:29:35 2012 -0800
+++ b/graal/com.oracle.max.graal.hotspot/src/com/oracle/max/graal/hotspot/ri/HOTSPOTMETHODDATAACCESSOR.JAVA	Fri Jan 20 18:24:17 2012 -0800
@@ -28,12 +28,15 @@
     int getTag();
     int getBCI(HotSpotMethodData data, int position);
     int getSize(HotSpotMethodData data, int position);
-    boolean hasExceptionOccurred(HotSpotMethodData data, int position);
-    long getExecutionCount(HotSpotMethodDataAccessor data, int position);
 
     RiResolvedType[] getTypes(HotSpotMethodData data, int position);
     double[] getTypeProbabilities(HotSpotMethodData data, int position);
 
     double getBranchTakenProbability(HotSpotMethodData data, int position);
+
     double[] getSwitchProbabilities(HotSpotMethodData data, int position);
+
+    boolean getImplicitExceptionSeen(HotSpotMethodData data, int position);
+
+    int getExecutionCount(HotSpotMethodData data, int position);
 }
--- a/graal/com.oracle.max.graal.hotspot/src/com/oracle/max/graal/hotspot/ri/HOTSPOTPROFILINGINFOIMPL.JAVA	Thu Jan 19 16:29:35 2012 -0800
+++ b/graal/com.oracle.max.graal.hotspot/src/com/oracle/max/graal/hotspot/ri/HOTSPOTPROFILINGINFOIMPL.JAVA	Fri Jan 20 18:24:17 2012 -0800
@@ -34,71 +34,104 @@
      */
     private static final long serialVersionUID = -8307682725047864875L;
 
-    private boolean atValidData;
     private int position;
+    private int hintPosition;
+    private int hintBCI;
     private HotSpotMethodDataAccessor dataAccessor;
     private HotSpotMethodData methodData;
 
     public HotSpotProfilingInfoImpl(Compiler compiler, HotSpotMethodData methodData) {
         super(compiler);
         this.methodData = methodData;
-        setBCI(0);
-    }
-
-    public boolean setBCI(int value) {
-        assert value >= 0 : "invalid BCI";
-
-        seek(0);
-        while (atValidData && currentBCI() < value) {
-            next();
-        }
-
-        return atValidData;
+        hintPosition = 0;
+        hintBCI = -1;
     }
 
     @Override
-    public int currentBCI() {
-        return dataAccessor.getBCI(methodData, position);
-    }
-
-    @Override
-    public boolean isAtValidData() {
-        return atValidData;
-    }
-
-    @Override
-    public boolean next() {
-        return seek(position + dataAccessor.getSize(methodData, position));
-    }
-
-    @Override
-    public RiResolvedType[] getTypes() {
+    public RiResolvedType[] getTypes(int bci) {
+        findBCI(bci);
         return dataAccessor.getTypes(methodData, position);
     }
 
     @Override
-    public double[] getTypeProbabilities() {
+    public double[] getTypeProbabilities(int bci) {
+        findBCI(bci);
         return dataAccessor.getTypeProbabilities(methodData, position);
     }
 
     @Override
-    public double getBranchTakenProbability() {
+    public double getBranchTakenProbability(int bci) {
+        findBCI(bci);
         return dataAccessor.getBranchTakenProbability(methodData, position);
     }
 
     @Override
-    public double[] getSwitchProbabilities() {
+    public double[] getSwitchProbabilities(int bci) {
+        findBCI(bci);
         return dataAccessor.getSwitchProbabilities(methodData, position);
     }
 
     @Override
-    public boolean hasExceptionOccurred() {
-        return dataAccessor.hasExceptionOccurred(methodData, position);
+    public boolean getImplicitExceptionSeen(int bci) {
+        findBCI(bci);
+        return dataAccessor.getImplicitExceptionSeen(methodData, position);
+    }
+
+    @Override
+    public int getExecutionCount(int bci) {
+        findBCI(bci);
+        return dataAccessor.getExecutionCount(methodData, position);
     }
 
-    private boolean seek(int value) {
-        position = value;
-        dataAccessor = methodData.getDataAccessor(position);
-        return dataAccessor != null;
+    private void findBCI(int targetBCI) {
+        assert targetBCI >= 0 : "invalid BCI";
+
+        if (methodData.hasNormalData()) {
+            int currentPosition = targetBCI < hintBCI ? 0 : hintPosition;
+            HotSpotMethodDataAccessor currentAccessor;
+            while ((currentAccessor = methodData.getNormalData(currentPosition)) != null) {
+                int currentBCI = currentAccessor.getBCI(methodData, currentPosition);
+                if (currentBCI == targetBCI) {
+                    normalDataFound(currentAccessor, currentPosition, currentBCI);
+                    return;
+                } else if (currentBCI > targetBCI) {
+                    break;
+                }
+                currentAccessor = methodData.getNormalData(currentPosition);
+            }
+        }
+
+        if (methodData.hasExtraData()) {
+            int currentPosition = 0;
+            HotSpotMethodDataAccessor currentAccessor;
+            while ((currentAccessor = methodData.getExtraData(currentPosition)) != null) {
+                int currentBCI = currentAccessor.getBCI(methodData, currentPosition);
+                if (currentBCI == targetBCI) {
+                    extraDataFound(currentAccessor, currentPosition);
+                    return;
+                }
+            }
+        }
+
+        noDataFound();
+    }
+
+    private void normalDataFound(HotSpotMethodDataAccessor data, int pos, int bci) {
+        setCurrentData(data, pos);
+        this.hintPosition = position;
+        this.hintBCI = bci;
+    }
+
+    private void extraDataFound(HotSpotMethodDataAccessor data, int pos) {
+        setCurrentData(data, pos);
+    }
+
+    private void noDataFound() {
+        setCurrentData(HotSpotMethodData.getNoDataAccessor(), -1);
+    }
+
+    private void setCurrentData(HotSpotMethodDataAccessor dataAccessor, int position) {
+        this.dataAccessor = dataAccessor;
+        this.position = position;
     }
 }
--- a/graal/com.oracle.max.graal.hotspot/src/com/oracle/max/graal/hotspot/ri/HotSpotMethodData.java	Thu Jan 19 16:29:35 2012 -0800
+++ b/graal/com.oracle.max.graal.hotspot/src/com/oracle/max/graal/hotspot/ri/HotSpotMethodData.java	Fri Jan 20 18:24:17 2012 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
+ * 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
@@ -37,6 +37,7 @@
     private static final long serialVersionUID = -8873133496591225071L;
     // TODO (ch) use same logic as in NodeClass?
     private static final Unsafe unsafe = Unsafe.getUnsafe();
+    private static final HotSpotMethodDataAccessor NO_DATA_ACCESSOR = new NoDataAccessor();
     private static final HotSpotMethodDataAccessor[] PROFILE_DATA_ACCESSORS = {
         null, new BitData(), new CounterData(), new JumpData(),
         new TypeCheckData(), new VirtualCallData(), new RetData(),
@@ -44,22 +45,51 @@
     };
 
     private Object javaMirror;
-    private int dataSize;
+    private int normalDataSize;
+    private int extraDataSize;
 
     private HotSpotMethodData(Compiler compiler) {
         super(compiler);
-        javaMirror = null;
-        dataSize = 0;
         throw new IllegalStateException("this constructor is never actually called, because the objects are allocated from within the VM");
     }
 
-    public HotSpotMethodDataAccessor getDataAccessor(int position) {
-        if (position < 0 || position >= dataSize) {
+    public boolean hasNormalData() {
+        return normalDataSize > 0;
+    }
+
+    public boolean hasExtraData() {
+        return extraDataSize > 0;
+    }
+
+    public boolean isWithinData(int position) {
+        return position >= 0 && position < normalDataSize + extraDataSize;
+    }
+
+    public HotSpotMethodDataAccessor getNormalData(int position) {
+        if (position >= normalDataSize) {
             return null;
         }
 
-        int tag = AbstractMethodDataAccessor.readTag(this, position);
-        assert tag > 0 && tag < PROFILE_DATA_ACCESSORS.length : "illegal tag";
+        HotSpotMethodDataAccessor result = getData(position, 0);
+        assert result != null : "NO_DATA tag is not allowed";
+        return result;
+    }
+
+    public HotSpotMethodDataAccessor getExtraData(int position) {
+        if (position >= extraDataSize) {
+            return null;
+        }
+        return getData(position, normalDataSize);
+    }
+
+    public static HotSpotMethodDataAccessor getNoDataAccessor() {
+        return NO_DATA_ACCESSOR;
+    }
+
+    private HotSpotMethodDataAccessor getData(int position, int displacement) {
+        assert position >= 0 : "out of bounds";
+        int tag = AbstractMethodDataAccessor.readTag(this, displacement + position);
+        assert tag >= 0 && tag < PROFILE_DATA_ACCESSORS.length : "illegal tag";
         return PROFILE_DATA_ACCESSORS[tag];
     }
 
@@ -78,11 +108,20 @@
         return unsafe.getInt(javaMirror, fullOffset) & 0xFFFFFFFFL;
     }
 
+    private int readUnsignedIntAsSignedInt(int position, int offsetInCells) {
+        long value = readUnsignedInt(position, offsetInCells);
+        return truncateLongToInt(value);
+    }
+
     private int readInt(int position, int offsetInCells) {
         long fullOffset = computeFullOffset(position, offsetInCells);
         return unsafe.getInt(javaMirror, fullOffset);
     }
 
+    private static int truncateLongToInt(long value) {
+        return value > Integer.MAX_VALUE ? Integer.MAX_VALUE : (int) value;
+    }
+
     private static int computeFullOffset(int position, int offsetInCells) {
         HotSpotVMConfig config = getHotSpotVMConfig();
         return config.methodDataDataOffset + position + offsetInCells * config.dataLayoutCellSize;
@@ -94,6 +133,8 @@
     }
 
     private abstract static class AbstractMethodDataAccessor implements HotSpotMethodDataAccessor {
+        private static final int IMPLICIT_EXCEPTIONS_MASK = 0x0E;
+
         private final int tag;
         private final int staticCellCount;
 
@@ -125,33 +166,39 @@
         }
 
         @Override
-        public boolean hasExceptionOccurred(HotSpotMethodData data, int position) {
-            return false;
+        public boolean getImplicitExceptionSeen(HotSpotMethodData data, int position) {
+            // TODO (ch) might return true too often because flags are also used for deoptimization reasons
+            return (getFlags(data, position) & IMPLICIT_EXCEPTIONS_MASK) != 0;
         }
 
         @Override
         public RiResolvedType[] getTypes(HotSpotMethodData data, int position) {
-            throw new IllegalStateException("not supported by current method data");
+            return null;
         }
 
         @Override
         public double[] getTypeProbabilities(HotSpotMethodData data, int position) {
-            throw new IllegalStateException("not supported by current method data");
+            return null;
         }
 
         @Override
         public double getBranchTakenProbability(HotSpotMethodData data, int position) {
-            throw new IllegalStateException("not supported by current method data");
+            return -1;
         }
 
         @Override
         public double[] getSwitchProbabilities(HotSpotMethodData data, int position) {
-            throw new IllegalStateException("not supported by current method data");
+            return null;
         }
 
         @Override
-        public long getExecutionCount(HotSpotMethodData data, int position) {
-            throw new IllegalStateException("not supported by current method data");
+        public int getExecutionCount(HotSpotMethodData data, int position) {
+            return -1;
+        }
+
+        protected int getFlags(HotSpotMethodData data, int position) {
+            HotSpotVMConfig config = getHotSpotVMConfig();
+            return data.readUnsignedByte(position, config.dataLayoutFlagsOffset);
         }
 
         protected int getDynamicCellCount(HotSpotMethodData data, int position) {
@@ -159,9 +206,30 @@
         }
     }
 
+    private static class NoDataAccessor extends AbstractMethodDataAccessor {
+        private static final int NO_DATA_TAG = 0;
+        private static final int NO_DATA_SIZE = 0;
+
+        protected NoDataAccessor() {
+            super(NO_DATA_TAG, NO_DATA_SIZE);
+        }
+
+        @Override
+        public int getBCI(HotSpotMethodData data, int position) {
+            return -1;
+        }
+
+
+        @Override
+        public boolean getImplicitExceptionSeen(HotSpotMethodData data, int position) {
+            return false;
+        }
+    }
+
     private static class BitData extends AbstractMethodDataAccessor {
         private static final int BIT_DATA_TAG = 1;
         private static final int BIT_DATA_CELLS = 0;
+        private static final int BIT_DATA_NULL_SEEN_FLAG = 0x01;
 
         private BitData() {
             super(BIT_DATA_TAG, BIT_DATA_CELLS);
@@ -170,6 +238,10 @@
         protected BitData(int tag, int staticCellCount) {
             super(tag, staticCellCount);
         }
+
+        public boolean getNullSeen(HotSpotMethodData data, int position) {
+            return (getFlags(data, position) & BIT_DATA_NULL_SEEN_FLAG) != 0;
+        }
     }
 
     private static class CounterData extends BitData {
@@ -186,12 +258,12 @@
         }
 
         @Override
-        public long getExecutionCount(HotSpotMethodData data, int position) {
+        public int getExecutionCount(HotSpotMethodData data, int position) {
             return getCounterValue(data, position);
         }
 
-        protected long getCounterValue(HotSpotMethodData data, int position) {
-            return data.readUnsignedInt(position, COUNTER_DATA_COUNT_OFFSET);
+        protected int getCounterValue(HotSpotMethodData data, int position) {
+            return data.readUnsignedIntAsSignedInt(position, COUNTER_DATA_COUNT_OFFSET);
         }
     }
 
@@ -215,8 +287,8 @@
         }
 
         @Override
-        public long getExecutionCount(HotSpotMethodData data, int position) {
-            return data.readUnsignedInt(position, TAKEN_COUNT_OFFSET);
+        public int getExecutionCount(HotSpotMethodData data, int position) {
+            return data.readUnsignedIntAsSignedInt(position, TAKEN_COUNT_OFFSET);
         }
 
         public int getDisplacement(HotSpotMethodData data, int position) {
@@ -285,12 +357,8 @@
         }
 
         @Override
-        public long getExecutionCount(HotSpotMethodData data, int position) {
-            throw new IllegalStateException("not supported by current method data");
-        }
-
-        public long getTypeCheckFailedCount(HotSpotMethodData data, int position) {
-            return super.getCounterValue(data, position);
+        public int getExecutionCount(HotSpotMethodData data, int position) {
+            return -1;
         }
     }
 
@@ -303,7 +371,7 @@
         }
 
         @Override
-        public long getExecutionCount(HotSpotMethodData data, int position) {
+        public int getExecutionCount(HotSpotMethodData data, int position) {
             HotSpotVMConfig config = getHotSpotVMConfig();
             int typeProfileWidth = config.typeProfileWidth;
 
@@ -312,7 +380,8 @@
                 total += data.readUnsignedInt(position, getCountOffset(i));
             }
 
-            return total + getCounterValue(data, position);
+            total += getCounterValue(data, position);
+            return truncateLongToInt(total);
         }
     }
 
@@ -399,12 +468,19 @@
                 for (int i = 0; i < length; i++) {
                     result[i] = result[i] / total;
                 }
+
+                // default case is expected as last entry
+                if (length >= 2) {
+                    double defaultCase = result[0];
+                    result[0] = result[length - 1];
+                    result[length - 1] = defaultCase;
+                }
             }
             return result;
         }
 
         @Override
-        public long getExecutionCount(HotSpotMethodData data, int position) {
+        public int getExecutionCount(HotSpotMethodData data, int position) {
             int length = getLength(data, position);
             long total = 0;
 
@@ -413,7 +489,7 @@
                 total += data.readUnsignedInt(position, offset);
             }
 
-            return total;
+            return truncateLongToInt(total);
         }
 
         private static int getCountOffset(int index) {
--- a/graal/com.oracle.max.graal.hotspot/src/com/oracle/max/graal/hotspot/ri/HotSpotMethodResolvedImpl.java	Thu Jan 19 16:29:35 2012 -0800
+++ b/graal/com.oracle.max.graal.hotspot/src/com/oracle/max/graal/hotspot/ri/HotSpotMethodResolvedImpl.java	Fri Jan 20 18:24:17 2012 -0800
@@ -220,26 +220,37 @@
         TTY.println("profile info for %s", this);
         TTY.println("canBeStaticallyBound: " + canBeStaticallyBound());
         TTY.println("invocationCount: " + invocationCount());
+        RiProfilingInfo profilingInfo = this.profilingInfo();
         for (int i = 0; i < codeSize(); i++) {
-            if (branchProbability(i) != -1) {
-                TTY.println("  branchProbability@%d: %f", i, branchProbability(i));
+            if (profilingInfo.getExecutionCount(i) != -1) {
+                TTY.println("  executionCount@%d: %d", i, profilingInfo.getExecutionCount(i));
             }
-            if (exceptionProbability(i) > 0) {
-                TTY.println("  exceptionProbability@%d: %d", i, exceptionProbability(i));
+
+            if (profilingInfo.getBranchTakenProbability(i) != -1) {
+                TTY.println("  branchProbability@%d: %f", i, profilingInfo.getBranchTakenProbability(i));
             }
-            RiTypeProfile profile = typeProfile(i);
-            if (profile != null && profile.count > 0) {
-                TTY.print("  profile@%d: count: %d, morphism: %d", i, profile.count, profile.morphism);
-                if (profile.types != null) {
-                    TTY.print(", types:");
-                    for (int i2 = 0; i2 < profile.types.length; i2++) {
-                        TTY.print(" %s (%f)", profile.types[i2], profile.probabilities[i2]);
-                    }
+
+            double[] switchProbabilities = profilingInfo.getSwitchProbabilities(i);
+            if (switchProbabilities != null) {
+                TTY.println("  switchProbabilities@%d:");
+                for (int j = 0; j < switchProbabilities.length; j++) {
+                    TTY.print(" %f", switchProbabilities[j]);
+                }
+            }
+
+            if (profilingInfo.getImplicitExceptionSeen(i)) {
+                TTY.println("  implicitExceptionSeen@%d: true", i);
+            }
+
+            RiResolvedType[] types = profilingInfo.getTypes(i);
+            double[] typeProbabilities = profilingInfo.getTypeProbabilities(i);
+            if (types != null && typeProbabilities != null) {
+                assert types.length == typeProbabilities.length : "length must match";
+                TTY.print("  types@%d:", i);
+                for (int j = 0; j < types.length; j++) {
+                    TTY.print(" %s (%f)", types[j], typeProbabilities[j]);
                 }
                 TTY.println();
-                if (exceptionProbability(i) > 0) {
-                    TTY.println("  exceptionProbability@%d: %d", i, exceptionProbability(i));
-                }
             }
         }
     }
--- a/graal/com.oracle.max.graal.java/src/com/oracle/max/graal/java/BlockMap.java	Thu Jan 19 16:29:35 2012 -0800
+++ b/graal/com.oracle.max.graal.java/src/com/oracle/max/graal/java/BlockMap.java	Fri Jan 20 18:24:17 2012 -0800
@@ -236,6 +236,7 @@
         // mark the entrypoints of basic blocks and build lists of successors for
         // all bytecodes that end basic blocks (i.e. goto, ifs, switches, throw, jsr, returns, ret)
         byte[] code = method.code();
+        RiProfilingInfo profilingInfo = method.profilingInfo();
         Block current = null;
         int bci = 0;
         while (bci < code.length) {
@@ -282,7 +283,7 @@
                 case IFNULL:    // fall through
                 case IFNONNULL: {
                     current = null;
-                    double probability = useBranchPrediction ? method.branchProbability(bci) : -1;
+                    double probability = useBranchPrediction ? profilingInfo.getBranchTakenProbability(bci) : -1;
 
                     Block b1 = probability == 0.0 ? new DeoptBlock(bci + Bytes.beS2(code, bci + 1)) : makeBlock(bci + Bytes.beS2(code, bci + 1));
                     Block b2 = probability == 1.0 ? new DeoptBlock(bci + 3) : makeBlock(bci + 3);
@@ -351,7 +352,7 @@
                     break;
                 }
                 default: {
-                    if (canTrap(opcode, bci)) {
+                    if (canTrap(opcode, bci, profilingInfo)) {
                         canTrap.set(bci);
                     }
                 }
@@ -360,7 +361,7 @@
         }
     }
 
-    public boolean canTrap(int opcode, int bci) {
+    private static boolean canTrap(int opcode, int bci, RiProfilingInfo profilingInfo) {
         switch (opcode) {
             case INVOKESTATIC:
             case INVOKESPECIAL:
@@ -387,7 +388,7 @@
             case PUTFIELD:
             case GETFIELD: {
                 if (GraalOptions.AllowExplicitExceptionChecks) {
-                    return method.exceptionProbability(bci) > 0;
+                    return profilingInfo.getImplicitExceptionSeen(bci);
                 }
             }
         }
--- a/graal/com.oracle.max.graal.java/src/com/oracle/max/graal/java/GraphBuilderPhase.java	Thu Jan 19 16:29:35 2012 -0800
+++ b/graal/com.oracle.max.graal.java/src/com/oracle/max/graal/java/GraphBuilderPhase.java	Fri Jan 20 18:24:17 2012 -0800
@@ -71,6 +71,7 @@
     private RiConstantPool constantPool;
     private RiExceptionHandler[] exceptionHandlers;
     private RiResolvedMethod method;
+    private RiProfilingInfo profilingInfo;
 
     private BytecodeStream stream;           // the bytecode stream
     private final LogStream log;
@@ -115,6 +116,7 @@
     @Override
     protected void run(StructuredGraph graph) {
         method = graph.method();
+        profilingInfo = method.profilingInfo();
         assert method.code() != null : "method must contain bytecodes: " + method;
         this.stream = new BytecodeStream(method.code());
         this.constantPool = method.getConstantPool();
@@ -322,7 +324,7 @@
         assert bci == FrameState.BEFORE_BCI || bci == bci() : "invalid bci";
 
         if (GraalOptions.UseExceptionProbability && method.invocationCount() > GraalOptions.MatureInvocationCount) {
-            if (bci != FrameState.BEFORE_BCI && exceptionObject == null && method.exceptionProbability(bci) == 0) {
+            if (bci != FrameState.BEFORE_BCI && exceptionObject == null && !profilingInfo.getImplicitExceptionSeen(bci)) {
                 return null;
             }
         }
@@ -603,7 +605,7 @@
 
     private void ifNode(ValueNode x, Condition cond, ValueNode y) {
         assert !x.isDeleted() && !y.isDeleted();
-        double probability = method.branchProbability(bci());
+        double probability = profilingInfo.getBranchTakenProbability(bci());
         if (probability < 0) {
             if (GraalOptions.TraceProbability) {
                 TTY.println("missing probability in " + method + " at bci " + bci());
@@ -1132,7 +1134,7 @@
     }
 
     private double[] switchProbability(int numberOfCases, int bci) {
-        double[] prob = method.switchProbability(bci);
+        double[] prob = profilingInfo.getSwitchProbabilities(bci);
         if (prob != null) {
             assert prob.length == numberOfCases;
         } else {