changeset 4439:f7251c729b31

profiling info first try
author Christian Haeubl <christian.haeubl@oracle.com>
date Thu, 19 Jan 2012 16:29:35 -0800
parents 2bc254976621
children 271220b49abc
files graal/com.oracle.max.cri/src/com/oracle/max/cri/ri/RiProfilingInfo.java graal/com.oracle.max.cri/src/com/oracle/max/cri/ri/RiResolvedMethod.java graal/com.oracle.max.graal.hotspot/src/com/oracle/max/graal/hotspot/HotSpotVMConfig.java graal/com.oracle.max.graal.hotspot/src/com/oracle/max/graal/hotspot/bridge/CompilerToVM.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 src/share/vm/classfile/systemDictionary.hpp src/share/vm/classfile/vmSymbols.hpp src/share/vm/graal/graalCompiler.cpp src/share/vm/graal/graalCompilerToVM.cpp src/share/vm/graal/graalJavaAccess.hpp src/share/vm/oops/methodDataKlass.cpp src/share/vm/oops/methodDataOop.cpp src/share/vm/oops/methodDataOop.hpp
diffstat 17 files changed, 698 insertions(+), 66 deletions(-) [+]
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.cri/src/com/oracle/max/cri/ri/RiProfilingInfo.java	Thu Jan 19 16:29:35 2012 -0800
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2009, 2011, 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.max.cri.ri;
+
+
+/**
+ * Represents profiling information for one specific method.
+ */
+public interface RiProfilingInfo {
+    // iterating the profiling information
+    boolean setBCI(int bci);
+    int currentBCI();
+    boolean next();
+    boolean isAtValidData();
+
+    // invokevirtual/invokeinterface
+    RiResolvedType[] getTypes();
+    double[] getTypeProbabilities();
+
+    // branches
+    double getBranchTakenProbability();
+    double[] getSwitchProbabilities();
+
+    // exceptions
+    boolean hasExceptionOccurred();
+}
--- a/graal/com.oracle.max.cri/src/com/oracle/max/cri/ri/RiResolvedMethod.java	Tue Jan 17 20:35:49 2012 +0100
+++ b/graal/com.oracle.max.cri/src/com/oracle/max/cri/ri/RiResolvedMethod.java	Thu Jan 19 16:29:35 2012 -0800
@@ -159,29 +159,10 @@
     int invocationCount();
 
     /**
-     * Returns an estimate of hot often an exception was seen at the given bytecode.
-     * @return The estimate in percent (0-100), with 0 meaning never and 100 meaning always, or -1 if this information isn't available.
-     */
-    int exceptionProbability(int bci);
-
-    /**
-     * Returns the type profile of the instruction at the given byte code index.
-     * @return The RiTypeProfile information, or null if it isn't available.
+     * Returns an object that provides access to the method's profiling information.
+     * @return The profiling information recorded for this method.
      */
-    RiTypeProfile typeProfile(int bci);
-
-    /**
-     * 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 isn't available.
-     */
-    double branchProbability(int bci);
-
-    /**
-     * Returns an estimate of how often the branches of the switch at the given byte code were taken.
-     * @return The estimated probability, with 0.0 meaning never and 1.0 meaning always, or NULL if this information isn't available.
-     * The default case is specified at the last index.
-     */
-    double[] switchProbability(int bci);
+    RiProfilingInfo profilingInfo();
 
     /**
      * Returns a map that the compiler can use to store objects that should survive the current compilation.
--- a/graal/com.oracle.max.graal.hotspot/src/com/oracle/max/graal/hotspot/HotSpotVMConfig.java	Tue Jan 17 20:35:49 2012 +0100
+++ b/graal/com.oracle.max.graal.hotspot/src/com/oracle/max/graal/hotspot/HotSpotVMConfig.java	Thu Jan 19 16:29:35 2012 -0800
@@ -30,7 +30,7 @@
 public final class HotSpotVMConfig extends CompilerObject {
 
     /**
-     * 
+     *
      */
     private static final long serialVersionUID = -4744897993263044184L;
 
@@ -72,6 +72,17 @@
     public int klassOopOffset;
     public int nmethodEntryOffset;
 
+    // methodData information
+    public int methodDataDataOffset;
+    public int dataLayoutHeaderSizeInBytes;
+    public int dataLayoutTagOffset;
+    public int dataLayoutFlagsOffset;
+    public int dataLayoutBCIOffset;
+    public int dataLayoutCellsOffset;
+    public int dataLayoutCellSize;
+    public int bciProfileWidth;
+    public int typeProfileWidth;
+
     // runtime stubs
     public long debugStub;
     public long instanceofStub;
--- a/graal/com.oracle.max.graal.hotspot/src/com/oracle/max/graal/hotspot/bridge/CompilerToVM.java	Tue Jan 17 20:35:49 2012 +0100
+++ b/graal/com.oracle.max.graal.hotspot/src/com/oracle/max/graal/hotspot/bridge/CompilerToVM.java	Thu Jan 19 16:29:35 2012 -0800
@@ -49,13 +49,7 @@
 
     int RiMethod_invocationCount(HotSpotMethodResolved method);
 
-    int RiMethod_exceptionProbability(HotSpotMethodResolved method, int bci);
-
-    RiTypeProfile RiMethod_typeProfile(HotSpotMethodResolved method, int bci);
-
-    double RiMethod_branchProbability(HotSpotMethodResolved method, int bci);
-
-    double[] RiMethod_switchProbability(HotSpotMethodResolved method, int bci);
+    HotSpotMethodData RiMethod_methodData(HotSpotMethodResolved method);
 
     RiType RiSignature_lookupType(String returnType, HotSpotTypeResolved accessingClass);
 
--- a/graal/com.oracle.max.graal.hotspot/src/com/oracle/max/graal/hotspot/bridge/CompilerToVMImpl.java	Tue Jan 17 20:35:49 2012 +0100
+++ b/graal/com.oracle.max.graal.hotspot/src/com/oracle/max/graal/hotspot/bridge/CompilerToVMImpl.java	Thu Jan 19 16:29:35 2012 -0800
@@ -60,18 +60,6 @@
     public native int RiMethod_invocationCount(HotSpotMethodResolved method);
 
     @Override
-    public native int RiMethod_exceptionProbability(HotSpotMethodResolved method, int bci);
-
-    @Override
-    public native RiTypeProfile RiMethod_typeProfile(HotSpotMethodResolved method, int bci);
-
-    @Override
-    public native double RiMethod_branchProbability(HotSpotMethodResolved method, int bci);
-
-    @Override
-    public native double[] RiMethod_switchProbability(HotSpotMethodResolved method, int bci);
-
-    @Override
     public native RiType RiSignature_lookupType(String returnType, HotSpotTypeResolved accessingClass);
 
     @Override
@@ -123,6 +111,9 @@
     public native boolean RiType_isInitialized(HotSpotTypeResolved klass);
 
     @Override
+    public native RiProfilingInfo RiMethod_profilingInfo(HotSpotMethodResolved method);
+
+    @Override
     public native RiType getType(Class<?> javaClass);
 
     @Override
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.hotspot/src/com/oracle/max/graal/hotspot/ri/HOTSPOTMETHODDATAACCESSOR.JAVA	Thu Jan 19 16:29:35 2012 -0800
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2011, 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.max.graal.hotspot.ri;
+
+import com.oracle.max.cri.ri.*;
+
+public interface HotSpotMethodDataAccessor {
+    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);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.hotspot/src/com/oracle/max/graal/hotspot/ri/HOTSPOTPROFILINGINFOIMPL.JAVA	Thu Jan 19 16:29:35 2012 -0800
@@ -0,0 +1,104 @@
+/*
+ * Copyright (c) 2011, 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.max.graal.hotspot.ri;
+
+import com.oracle.max.cri.ri.*;
+import com.oracle.max.graal.hotspot.*;
+import com.oracle.max.graal.hotspot.Compiler;
+
+
+public final class HotSpotProfilingInfoImpl extends CompilerObject implements RiProfilingInfo {
+
+    /**
+     *
+     */
+    private static final long serialVersionUID = -8307682725047864875L;
+
+    private boolean atValidData;
+    private int position;
+    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;
+    }
+
+    @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() {
+        return dataAccessor.getTypes(methodData, position);
+    }
+
+    @Override
+    public double[] getTypeProbabilities() {
+        return dataAccessor.getTypeProbabilities(methodData, position);
+    }
+
+    @Override
+    public double getBranchTakenProbability() {
+        return dataAccessor.getBranchTakenProbability(methodData, position);
+    }
+
+    @Override
+    public double[] getSwitchProbabilities() {
+        return dataAccessor.getSwitchProbabilities(methodData, position);
+    }
+
+    @Override
+    public boolean hasExceptionOccurred() {
+        return dataAccessor.hasExceptionOccurred(methodData, position);
+    }
+
+    private boolean seek(int value) {
+        position = value;
+        dataAccessor = methodData.getDataAccessor(position);
+        return dataAccessor != null;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.hotspot/src/com/oracle/max/graal/hotspot/ri/HotSpotMethodData.java	Thu Jan 19 16:29:35 2012 -0800
@@ -0,0 +1,432 @@
+/*
+ * Copyright (c) 2011, 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.max.graal.hotspot.ri;
+
+import sun.misc.*;
+
+import com.oracle.max.cri.ri.*;
+import com.oracle.max.graal.hotspot.*;
+import com.oracle.max.graal.hotspot.Compiler;
+
+
+public final class HotSpotMethodData extends CompilerObject {
+
+    /**
+     *
+     */
+    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[] PROFILE_DATA_ACCESSORS = {
+        null, new BitData(), new CounterData(), new JumpData(),
+        new TypeCheckData(), new VirtualCallData(), new RetData(),
+        new BranchData(), new MultiBranchData(), new ArgInfoData()
+    };
+
+    private Object javaMirror;
+    private int dataSize;
+
+    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) {
+            return null;
+        }
+
+        int tag = AbstractMethodDataAccessor.readTag(this, position);
+        assert tag > 0 && tag < PROFILE_DATA_ACCESSORS.length : "illegal tag";
+        return PROFILE_DATA_ACCESSORS[tag];
+    }
+
+    private int readUnsignedByte(int position, int offsetInCells) {
+        long fullOffset = computeFullOffset(position, offsetInCells);
+        return unsafe.getByte(javaMirror, fullOffset) & 0xFF;
+    }
+
+    private int readUnsignedShort(int position, int offsetInCells) {
+        long fullOffset = computeFullOffset(position, offsetInCells);
+        return unsafe.getShort(javaMirror, fullOffset) & 0xFFFF;
+    }
+
+    private long readUnsignedInt(int position, int offsetInCells) {
+        long fullOffset = computeFullOffset(position, offsetInCells);
+        return unsafe.getInt(javaMirror, fullOffset) & 0xFFFFFFFFL;
+    }
+
+    private int readInt(int position, int offsetInCells) {
+        long fullOffset = computeFullOffset(position, offsetInCells);
+        return unsafe.getInt(javaMirror, fullOffset);
+    }
+
+    private static int computeFullOffset(int position, int offsetInCells) {
+        HotSpotVMConfig config = getHotSpotVMConfig();
+        return config.methodDataDataOffset + position + offsetInCells * config.dataLayoutCellSize;
+    }
+
+    private static HotSpotVMConfig getHotSpotVMConfig() {
+        // TODO: implement, cache config somewhere?
+        return null;
+    }
+
+    private abstract static class AbstractMethodDataAccessor implements HotSpotMethodDataAccessor {
+        private final int tag;
+        private final int staticCellCount;
+
+        protected AbstractMethodDataAccessor(int tag, int staticCellCount) {
+            this.tag = tag;
+            this.staticCellCount = staticCellCount;
+        }
+
+        @Override
+        public int getTag() {
+            return tag;
+        }
+
+        public static int readTag(HotSpotMethodData data, int position) {
+            HotSpotVMConfig config = getHotSpotVMConfig();
+            return data.readUnsignedByte(position, config.dataLayoutTagOffset);
+        }
+
+        @Override
+        public int getBCI(HotSpotMethodData data, int position) {
+            HotSpotVMConfig config = getHotSpotVMConfig();
+            return data.readUnsignedShort(position, config.dataLayoutBCIOffset);
+        }
+
+        @Override
+        public int getSize(HotSpotMethodData data, int position) {
+            HotSpotVMConfig config = getHotSpotVMConfig();
+            return config.dataLayoutHeaderSizeInBytes + (staticCellCount + getDynamicCellCount(data, position)) * config.dataLayoutCellSize;
+        }
+
+        @Override
+        public boolean hasExceptionOccurred(HotSpotMethodData data, int position) {
+            return false;
+        }
+
+        @Override
+        public RiResolvedType[] getTypes(HotSpotMethodData data, int position) {
+            throw new IllegalStateException("not supported by current method data");
+        }
+
+        @Override
+        public double[] getTypeProbabilities(HotSpotMethodData data, int position) {
+            throw new IllegalStateException("not supported by current method data");
+        }
+
+        @Override
+        public double getBranchTakenProbability(HotSpotMethodData data, int position) {
+            throw new IllegalStateException("not supported by current method data");
+        }
+
+        @Override
+        public double[] getSwitchProbabilities(HotSpotMethodData data, int position) {
+            throw new IllegalStateException("not supported by current method data");
+        }
+
+        @Override
+        public long getExecutionCount(HotSpotMethodData data, int position) {
+            throw new IllegalStateException("not supported by current method data");
+        }
+
+        protected int getDynamicCellCount(HotSpotMethodData data, int position) {
+            return 0;
+        }
+    }
+
+    private static class BitData extends AbstractMethodDataAccessor {
+        private static final int BIT_DATA_TAG = 1;
+        private static final int BIT_DATA_CELLS = 0;
+
+        private BitData() {
+            super(BIT_DATA_TAG, BIT_DATA_CELLS);
+        }
+
+        protected BitData(int tag, int staticCellCount) {
+            super(tag, staticCellCount);
+        }
+    }
+
+    private static class CounterData extends BitData {
+        private static final int COUNTER_DATA_TAG = 2;
+        private static final int COUNTER_DATA_CELLS = 1;
+        private static final int COUNTER_DATA_COUNT_OFFSET = 0;
+
+        public CounterData() {
+            super(COUNTER_DATA_TAG, COUNTER_DATA_CELLS);
+        }
+
+        protected CounterData(int tag, int staticCellCount) {
+            super(tag, staticCellCount);
+        }
+
+        @Override
+        public long getExecutionCount(HotSpotMethodData data, int position) {
+            return getCounterValue(data, position);
+        }
+
+        protected long getCounterValue(HotSpotMethodData data, int position) {
+            return data.readUnsignedInt(position, COUNTER_DATA_COUNT_OFFSET);
+        }
+    }
+
+    private static class JumpData extends AbstractMethodDataAccessor {
+        private static final int JUMP_DATA_TAG = 3;
+        private static final int JUMP_DATA_CELLS = 2;
+        protected static final int TAKEN_COUNT_OFFSET = 0;
+        protected static final int TAKEN_DISPLACEMENT_OFFSET = 1;
+
+        public JumpData() {
+            super(JUMP_DATA_TAG, JUMP_DATA_CELLS);
+        }
+
+        protected JumpData(int tag, int staticCellCount) {
+            super(tag, staticCellCount);
+        }
+
+        @Override
+        public double getBranchTakenProbability(HotSpotMethodData data, int position) {
+            return 1;
+        }
+
+        @Override
+        public long getExecutionCount(HotSpotMethodData data, int position) {
+            return data.readUnsignedInt(position, TAKEN_COUNT_OFFSET);
+        }
+
+        public int getDisplacement(HotSpotMethodData data, int position) {
+            return data.readInt(position, TAKEN_DISPLACEMENT_OFFSET);
+        }
+    }
+
+    private static class AbstractTypeData extends CounterData {
+        private static final int RECEIVER_TYPE_DATA_ROW_CELL_COUNT = 2;
+        private static final int RECEIVER_TYPE_DATA_FIRST_RECEIVER_OFFSET = 1;
+        private static final int RECEIVER_TYPE_DATA_FIRST_COUNT_OFFSET = 2;
+
+        protected AbstractTypeData(int tag, int staticCellCount) {
+            super(tag, staticCellCount);
+        }
+
+        @Override
+        public double[] getTypeProbabilities(HotSpotMethodData data, int position) {
+            HotSpotVMConfig config = getHotSpotVMConfig();
+            int typeProfileWidth = config.typeProfileWidth;
+
+            long total = 0;
+            double[] result = new double[typeProfileWidth];
+
+            for (int i = 0; i < typeProfileWidth; i++) {
+                long count = data.readUnsignedInt(position, getCountOffset(i));
+                total += count;
+                result[i] = count;
+            }
+
+            if (total != 0) {
+                for (int i = 0; i < typeProfileWidth; i++) {
+                    result[i] = result[i] / total;
+                }
+            }
+            return result;
+        }
+
+        @Override
+        public RiResolvedType[] getTypes(HotSpotMethodData data, int position) {
+            // TODO: seems to require a native call...
+            return null;
+        }
+
+        @Override
+        protected int getDynamicCellCount(HotSpotMethodData data, int position) {
+            HotSpotVMConfig config = getHotSpotVMConfig();
+            return config.typeProfileWidth * RECEIVER_TYPE_DATA_ROW_CELL_COUNT;
+        }
+
+        private static int getReceiverOffset(int row) {
+            return RECEIVER_TYPE_DATA_FIRST_RECEIVER_OFFSET + row * RECEIVER_TYPE_DATA_ROW_CELL_COUNT;
+        }
+
+        protected static int getCountOffset(int row) {
+            return RECEIVER_TYPE_DATA_FIRST_COUNT_OFFSET + row * RECEIVER_TYPE_DATA_ROW_CELL_COUNT;
+        }
+    }
+
+    private static class TypeCheckData extends AbstractTypeData {
+        private static final int RECEIVER_TYPE_DATA_TAG = 4;
+        private static final int RECEIVER_TYPE_DATA_CELLS = 1;
+
+        public TypeCheckData() {
+            super(RECEIVER_TYPE_DATA_TAG, RECEIVER_TYPE_DATA_CELLS);
+        }
+
+        @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);
+        }
+    }
+
+    private static class VirtualCallData extends AbstractTypeData {
+        private static final int VIRTUAL_CALL_DATA_TAG = 5;
+        private static final int VIRTUAL_CALL_DATA_CELLS = 1;
+
+        public VirtualCallData() {
+            super(VIRTUAL_CALL_DATA_TAG, VIRTUAL_CALL_DATA_CELLS);
+        }
+
+        @Override
+        public long getExecutionCount(HotSpotMethodData data, int position) {
+            HotSpotVMConfig config = getHotSpotVMConfig();
+            int typeProfileWidth = config.typeProfileWidth;
+
+            long total = 0;
+            for (int i = 0; i < typeProfileWidth; i++) {
+                total += data.readUnsignedInt(position, getCountOffset(i));
+            }
+
+            return total + getCounterValue(data, position);
+        }
+    }
+
+    private static class RetData extends CounterData {
+        private static final int RET_DATA_TAG = 6;
+        private static final int RET_DATA_CELLS = 1;
+        private static final int RET_DATA_ROW_CELL_COUNT = 3;
+
+        public RetData() {
+            super(RET_DATA_TAG, RET_DATA_CELLS);
+        }
+
+        @Override
+        protected int getDynamicCellCount(HotSpotMethodData data, int position) {
+            HotSpotVMConfig config = getHotSpotVMConfig();
+            return config.bciProfileWidth * RET_DATA_ROW_CELL_COUNT;
+        }
+    }
+
+    private static class BranchData extends JumpData {
+        private static final int BRANCH_DATA_TAG = 7;
+        private static final int BRANCH_DATA_CELLS = 3;
+        private static final int NOT_TAKEN_COUNT_OFFSET = 2;
+
+        public BranchData() {
+            super(BRANCH_DATA_TAG, BRANCH_DATA_CELLS);
+        }
+
+        @Override
+        public double getBranchTakenProbability(HotSpotMethodData data, int position) {
+            long takenCount = data.readUnsignedInt(position, TAKEN_COUNT_OFFSET);
+            long notTakenCount = data.readUnsignedInt(position, NOT_TAKEN_COUNT_OFFSET);
+            double total = takenCount + notTakenCount;
+            return takenCount / total;
+        }
+    }
+
+    private static class ArrayData extends AbstractMethodDataAccessor {
+        private static final int ARRAY_DATA_LENGTH_OFFSET = 0;
+        private static final int ARRAY_DATA_START_OFFSET = 1;
+
+        public ArrayData(int tag, int staticCellCount) {
+            super(tag, staticCellCount);
+        }
+
+        @Override
+        protected int getDynamicCellCount(HotSpotMethodData data, int position) {
+            return getLength(data, position);
+        }
+
+        protected static int getLength(HotSpotMethodData data, int position) {
+            return data.readInt(position, ARRAY_DATA_LENGTH_OFFSET);
+        }
+
+        protected static int getElementOffset(int index) {
+            return ARRAY_DATA_START_OFFSET + index;
+        }
+    }
+
+    private static class MultiBranchData extends ArrayData {
+        private static final int MULTI_BRANCH_DATA_TAG = 8;
+        private static final int MULTI_BRANCH_DATA_CELLS = 1;
+        private static final int MULTI_BRANCH_DATA_COUNT_OFFSET = 0;
+        private static final int MULTI_BRANCH_DATA_DISPLACEMENT_OFFSET = 1;
+
+        public MultiBranchData() {
+            super(MULTI_BRANCH_DATA_TAG, MULTI_BRANCH_DATA_CELLS);
+        }
+
+        @Override
+        public double[] getSwitchProbabilities(HotSpotMethodData data, int position) {
+            int length = getLength(data, position);
+            long total = 0;
+            double[] result = new double[length];
+
+            for (int i = 0; i < length; i++) {
+                int offset = getCountOffset(i);
+                long count = data.readUnsignedInt(position, offset);
+                total += count;
+                result[i] = count;
+            }
+
+            if (total != 0) {
+                for (int i = 0; i < length; i++) {
+                    result[i] = result[i] / total;
+                }
+            }
+            return result;
+        }
+
+        @Override
+        public long getExecutionCount(HotSpotMethodData data, int position) {
+            int length = getLength(data, position);
+            long total = 0;
+
+            for (int i = 0; i < length; i++) {
+                int offset = getCountOffset(i);
+                total += data.readUnsignedInt(position, offset);
+            }
+
+            return total;
+        }
+
+        private static int getCountOffset(int index) {
+            return getElementOffset(index + MULTI_BRANCH_DATA_COUNT_OFFSET);
+        }
+    }
+
+    private static class ArgInfoData extends ArrayData {
+        private static final int ARG_INFO_DATA_TAG = 9;
+        private static final int ARG_INFO_DATA_CELLS = 1;
+
+        public ArgInfoData() {
+            super(ARG_INFO_DATA_TAG, ARG_INFO_DATA_CELLS);
+        }
+    }
+}
--- a/graal/com.oracle.max.graal.hotspot/src/com/oracle/max/graal/hotspot/ri/HotSpotMethodResolvedImpl.java	Tue Jan 17 20:35:49 2012 +0100
+++ b/graal/com.oracle.max.graal.hotspot/src/com/oracle/max/graal/hotspot/ri/HotSpotMethodResolvedImpl.java	Thu Jan 19 16:29:35 2012 -0800
@@ -55,6 +55,7 @@
     private Boolean hasBalancedMonitors;
     private Map<Object, Object> compilerStorage;
     private RiResolvedType holder;
+    private HotSpotMethodData methodData;
     private byte[] code;
 
     private HotSpotMethodResolvedImpl() {
@@ -189,24 +190,17 @@
         return null;
     }
 
+    @Override
     public int invocationCount() {
         return compiler.getVMEntries().RiMethod_invocationCount(this);
     }
 
-    public int exceptionProbability(int bci) {
-        return compiler.getVMEntries().RiMethod_exceptionProbability(this, bci);
-    }
-
-    public RiTypeProfile typeProfile(int bci) {
-        return compiler.getVMEntries().RiMethod_typeProfile(this, bci);
-    }
-
-    public double branchProbability(int bci) {
-        return compiler.getVMEntries().RiMethod_branchProbability(this, bci);
-    }
-
-    public double[] switchProbability(int bci) {
-        return compiler.getVMEntries().RiMethod_switchProbability(this, bci);
+    @Override
+    public RiProfilingInfo profilingInfo() {
+        if (methodData == null) {
+            methodData = compiler.getVMEntries().RiMethod_methodData(this);
+        }
+        return new HotSpotProfilingInfoImpl(compiler, methodData);
     }
 
     @Override
--- a/src/share/vm/classfile/systemDictionary.hpp	Tue Jan 17 20:35:49 2012 +0100
+++ b/src/share/vm/classfile/systemDictionary.hpp	Thu Jan 19 16:29:35 2012 -0800
@@ -223,7 +223,7 @@
   template(RiType_klass,                          com_oracle_max_cri_ri_RiType,                                     Opt) \
   template(RiResolvedField_klass,                 com_oracle_max_cri_ri_RiResolvedField,                            Opt) \
   template(RiExceptionHandler_klass,              com_oracle_max_cri_ri_RiExceptionHandler,                         Opt) \
-  template(RiTypeProfile_klass,                   com_oracle_max_cri_ri_RiTypeProfile,                              Opt) \
+  template(RiProfilingInfo_klass,                 com_oracle_max_cri_ri_RiProfilingInfo,                            Opt) \
 
   /*end*/
 
--- a/src/share/vm/classfile/vmSymbols.hpp	Tue Jan 17 20:35:49 2012 +0100
+++ b/src/share/vm/classfile/vmSymbols.hpp	Thu Jan 19 16:29:35 2012 -0800
@@ -284,7 +284,7 @@
   template(com_oracle_max_cri_ri_RiMethod,                            "com/oracle/max/cri/ri/RiMethod")                                   \
   template(com_oracle_max_cri_ri_RiResolvedField,                     "com/oracle/max/cri/ri/RiResolvedField")                            \
   template(com_oracle_max_cri_ri_RiType,                              "com/oracle/max/cri/ri/RiType")                                     \
-  template(com_oracle_max_cri_ri_RiTypeProfile,                       "com/oracle/max/cri/ri/RiTypeProfile")                              \
+  template(com_oracle_max_cri_ri_RiProfilingInfo,                     "com/oracle/max/cri/ri/RiProfilingInfo")                            \
   template(com_oracle_max_cri_ri_RiConstantPool,                      "com/oracle/max/cri/ri/RiConstantPool")                             \
   template(com_oracle_max_cri_ri_RiExceptionHandler,                  "com/oracle/max/cri/ri/RiExceptionHandler")                         \
   template(com_oracle_max_cri_ci_CiAssumptions,                       "com/oracle/max/cri/ci/CiAssumptions")                              \
--- a/src/share/vm/graal/graalCompiler.cpp	Tue Jan 17 20:35:49 2012 +0100
+++ b/src/share/vm/graal/graalCompiler.cpp	Thu Jan 19 16:29:35 2012 -0800
@@ -272,7 +272,24 @@
   HotSpotMethodResolved::set_maxStackSize(obj, method->max_stack());
   
   method->set_graal_mirror(obj());
-  return obj();
+  return obj;
+}
+
+Handle GraalCompiler::createHotSpotProfilingInfo(methodDataHandle method_data, TRAPS) {
+  if(method_data->graal_mirror() != NULL) {
+    assert(method_data->graal_mirror()->is_a(HotSpotProfilingInfo::klass()), "unexpected class");
+    return method_data->graal_mirror();
+  }
+
+  instanceKlass::cast(HotSpotProfilingInfo::klass())->initialize(CHECK_NULL);
+  Handle obj = instanceKlass::cast(HotSpotProfilingInfo::klass())->allocate_instance(CHECK_NULL);
+  assert(obj.not_null, "must be");
+  
+  HotSpotProfilingInfo::set_compiler(obj, VMToCompiler::compilerInstance()());
+  HotSpotProfilingInfo::set_javaMirror(obj, method_data());
+
+  method_data->set_graal_mirror(obj());
+  return obj;
 }
 
 BasicType GraalCompiler::kindToBasicType(jchar ch) {
--- a/src/share/vm/graal/graalCompilerToVM.cpp	Tue Jan 17 20:35:49 2012 +0100
+++ b/src/share/vm/graal/graalCompilerToVM.cpp	Thu Jan 19 16:29:35 2012 -0800
@@ -873,6 +873,7 @@
   set_int(env, config, "threadExceptionPcOffset", in_bytes(JavaThread::exception_pc_offset()));
   set_int(env, config, "threadMultiNewArrayStorage", in_bytes(JavaThread::graal_multinewarray_storage_offset()));
   set_int(env, config, "classMirrorOffset", klassOopDesc::klass_part_offset_in_bytes() + Klass::java_mirror_offset_in_bytes());
+  set_int(env, config, "methodDataDataOffset", in_bytes(methodDataOopDesc::data_offset));
 
   set_long(env, config, "debugStub", VmIds::addStub((address)warning));
   set_long(env, config, "instanceofStub", VmIds::addStub(Runtime1::entry_for(Runtime1::slow_subtype_check_id)));
@@ -985,7 +986,7 @@
 #define METHOD          "Lcom/oracle/max/cri/ri/RiMethod;"
 #define RESOLVED_METHOD "Lcom/oracle/max/graal/hotspot/ri/HotSpotMethodResolved;"
 #define REFLECT_METHOD  "Ljava/lang/reflect/Method;"
-#define TYPE_PROFILE    "Lcom/oracle/max/cri/ri/RiTypeProfile;"
+#define PROFILING_INFO  "Lcom/oracle/max/cri/ri/RiProfilingInfo;"
 #define SIGNATURE       "Lcom/oracle/max/cri/ri/RiSignature;"
 #define FIELD           "Lcom/oracle/max/cri/ri/RiField;"
 #define RESOLVED_FIELD  "Lcom/oracle/max/cri/ri/RiResolvedField;"
--- a/src/share/vm/graal/graalJavaAccess.hpp	Tue Jan 17 20:35:49 2012 +0100
+++ b/src/share/vm/graal/graalJavaAccess.hpp	Thu Jan 19 16:29:35 2012 -0800
@@ -68,6 +68,10 @@
     int_field(HotSpotMethodResolved, maxLocals)                                         \
     int_field(HotSpotMethodResolved, maxStackSize)                                      \
   end_class                                                                             \
+  start_class(HotSpotProfilingInfo)                                                     \
+    oop_field(HotSpotProfilingInfo, compiler, "Lcom/oracle/max/graal/hotspot/Compiler;") \
+    oop_field(HotSpotProfilingInfo, javaMirror, "Ljava/lang/Object;")                   \
+  end_class                                                                             \
   start_class(HotSpotType)                                                              \
     oop_field(HotSpotType, name, "Ljava/lang/String;")                                  \
   end_class                                                                             \
@@ -226,12 +230,6 @@
     oop_field(CiMonitorValue, lockData, "Lcom/oracle/max/cri/ci/CiValue;")              \
     boolean_field(CiMonitorValue, eliminated)                                           \
   end_class                                                                             \
-  start_class(RiTypeProfile)                                                            \
-    int_field(RiTypeProfile, count)                                                     \
-    int_field(RiTypeProfile, morphism)                                                  \
-    oop_field(RiTypeProfile, probabilities, "[F")                                       \
-    oop_field(RiTypeProfile, types, "[Lcom/oracle/max/cri/ri/RiResolvedType;")          \
-  end_class                                                                             \
   /* end*/
 
 #define START_CLASS(name)                       \
--- a/src/share/vm/oops/methodDataKlass.cpp	Tue Jan 17 20:35:49 2012 +0100
+++ b/src/share/vm/oops/methodDataKlass.cpp	Thu Jan 19 16:29:35 2012 -0800
@@ -84,6 +84,7 @@
 
   obj->follow_header();
   MarkSweep::mark_and_push(m->adr_method());
+  MarkSweep::mark_and_push(m->adr_graal_mirror());
   ResourceMark rm;
   for (ProfileData* data = m->first_data();
        m->is_valid(data);
@@ -100,6 +101,7 @@
 
   obj->follow_header(cm);
   PSParallelCompact::mark_and_push(cm, m->adr_method());
+  PSParallelCompact::mark_and_push(cm, m->adr_graal_mirror());
   ResourceMark rm;
   for (ProfileData* data = m->first_data();
        m->is_valid(data);
@@ -119,6 +121,7 @@
 
   obj->oop_iterate_header(blk);
   blk->do_oop(m->adr_method());
+  blk->do_oop(m->adr_graal_mirror());
   ResourceMark rm;
   for (ProfileData* data = m->first_data();
        m->is_valid(data);
@@ -140,6 +143,11 @@
   if (mr.contains(adr)) {
     blk->do_oop(m->adr_method());
   }
+  adr = m->adr_graal_mirror();
+  if(mr.contains(adr)) {
+    blk->do_oop(m->adr_graal_mirror());
+  }
+
   ResourceMark rm;
   for (ProfileData* data = m->first_data();
        m->is_valid(data);
@@ -158,6 +166,7 @@
 
   obj->adjust_header();
   MarkSweep::adjust_pointer(m->adr_method());
+  MarkSweep::adjust_pointer(m->adr_graal_mirror());
   ResourceMark rm;
   ProfileData* data;
   for (data = m->first_data(); m->is_valid(data); data = m->next_data(data)) {
@@ -173,6 +182,11 @@
   methodDataOop m = methodDataOop(obj);
   // This should never point into the young gen.
   assert(!PSScavenge::should_scavenge(m->adr_method()), "Sanity");
+ 
+  oop* adr = m->adr_graal_mirror();
+  if(PSScavenge::should_scavenge(adr)) {
+    pm->claim_or_forward_depth(adr);
+  }
 }
 
 int methodDataKlass::oop_update_pointers(ParCompactionManager* cm, oop obj) {
@@ -180,6 +194,7 @@
   methodDataOop m = methodDataOop(obj);
 
   PSParallelCompact::adjust_pointer(m->adr_method());
+  PSParallelCompact::adjust_pointer(m->adr_graal_mirror());
 
   ResourceMark rm;
   ProfileData* data;
--- a/src/share/vm/oops/methodDataOop.cpp	Tue Jan 17 20:35:49 2012 +0100
+++ b/src/share/vm/oops/methodDataOop.cpp	Thu Jan 19 16:29:35 2012 -0800
@@ -749,6 +749,7 @@
   ResourceMark rm;
   // Set the method back-pointer.
   _method = method();
+  _graal_mirror = NULL;
 
   if (TieredCompilation) {
     _invocation_counter.init();
--- a/src/share/vm/oops/methodDataOop.hpp	Tue Jan 17 20:35:49 2012 +0100
+++ b/src/share/vm/oops/methodDataOop.hpp	Thu Jan 19 16:29:35 2012 -0800
@@ -1194,6 +1194,9 @@
   // Back pointer to the methodOop
   methodOop _method;
 
+  // com/oracle/max/graal/hotspot/HotSpotProfilingInfo mirroring this method
+  oop               _graal_mirror;
+
   // Size of this oop in bytes
   int _size;
 
@@ -1423,6 +1426,10 @@
   // Accessors
   methodOop method() { return _method; }
 
+  // graal mirror
+  oop graal_mirror() const               { return _graal_mirror; }
+  void set_graal_mirror(oop m)           { oop_store((oop*) &_graal_mirror, m); }
+
   // Get the data at an arbitrary (sort of) data index.
   ProfileData* data_at(int data_index);
 
@@ -1520,6 +1527,7 @@
 
   // GC support
   oop* adr_method() const { return (oop*)&_method; }
+  oop* adr_graal_mirror() const { return (oop*)&_graal_mirror; }
   bool object_is_parsable() const { return _size != 0; }
   void set_object_is_parsable(int object_size_in_bytes) { _size = object_size_in_bytes; }