changeset 22503:828c67903db2

Moving profiles into their own project to ensure the core API doesn't reference these utility classes.
author Jaroslav Tulach <jaroslav.tulach@oracle.com>
date Thu, 17 Dec 2015 10:01:38 +0100
parents d2b4fe945c23
children d80a5ff56f51
files mx.truffle/suite.py truffle/com.oracle.truffle.api.dsl/src/com/oracle/truffle/api/dsl/Cached.java truffle/com.oracle.truffle.api.profiles/src/com/oracle/truffle/api/profiles/BranchProfile.java truffle/com.oracle.truffle.api.profiles/src/com/oracle/truffle/api/profiles/ByteValueProfile.java truffle/com.oracle.truffle.api.profiles/src/com/oracle/truffle/api/profiles/ConditionProfile.java truffle/com.oracle.truffle.api.profiles/src/com/oracle/truffle/api/profiles/DoubleValueProfile.java truffle/com.oracle.truffle.api.profiles/src/com/oracle/truffle/api/profiles/FloatValueProfile.java truffle/com.oracle.truffle.api.profiles/src/com/oracle/truffle/api/profiles/IntValueProfile.java truffle/com.oracle.truffle.api.profiles/src/com/oracle/truffle/api/profiles/LongValueProfile.java truffle/com.oracle.truffle.api.profiles/src/com/oracle/truffle/api/profiles/LoopConditionProfile.java truffle/com.oracle.truffle.api.profiles/src/com/oracle/truffle/api/profiles/PrimitiveValueProfile.java truffle/com.oracle.truffle.api.profiles/src/com/oracle/truffle/api/profiles/Profile.java truffle/com.oracle.truffle.api.profiles/src/com/oracle/truffle/api/profiles/ValueProfile.java truffle/com.oracle.truffle.api.profiles/src/com/oracle/truffle/api/profiles/package-info.java truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/profiles/BranchProfile.java truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/profiles/ByteValueProfile.java truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/profiles/ConditionProfile.java truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/profiles/DoubleValueProfile.java truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/profiles/FloatValueProfile.java truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/profiles/IntValueProfile.java truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/profiles/LongValueProfile.java truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/profiles/LoopConditionProfile.java truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/profiles/PrimitiveValueProfile.java truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/profiles/Profile.java truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/profiles/ValueProfile.java truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/profiles/package-info.java
diffstat 26 files changed, 2363 insertions(+), 2352 deletions(-) [+]
line wrap: on
line diff
--- a/mx.truffle/suite.py	Wed Dec 16 15:32:23 2015 -0800
+++ b/mx.truffle/suite.py	Thu Dec 17 10:01:38 2015 +0100
@@ -58,6 +58,7 @@
       "subDir" : "truffle",
       "sourceDirs" : ["src"],
       "dependencies" : [
+        "com.oracle.truffle.api.profiles",
         "com.oracle.truffle.api.interop",
         "com.oracle.truffle.api.vm",
         "mx:JUNIT",
@@ -145,6 +146,15 @@
       "workingSets" : "API,Truffle",
     },
 
+    "com.oracle.truffle.api.profiles" : {
+      "subDir" : "truffle",
+      "sourceDirs" : ["src"],
+      "dependencies" : ["com.oracle.truffle.api"],
+      "checkstyle" : "com.oracle.truffle.api",
+      "javaCompliance" : "1.7",
+      "workingSets" : "API,Truffle",
+    },
+
     "com.oracle.truffle.object" : {
       "subDir" : "truffle",
       "sourceDirs" : ["src"],
@@ -262,6 +272,7 @@
       "dependencies" : [
         "com.oracle.truffle.api.interop.java",
         "com.oracle.truffle.api.dsl",
+        "com.oracle.truffle.api.profiles",
         "com.oracle.truffle.api.vm",
         "com.oracle.truffle.object.basic",
       ],
--- a/truffle/com.oracle.truffle.api.dsl/src/com/oracle/truffle/api/dsl/Cached.java	Wed Dec 16 15:32:23 2015 -0800
+++ b/truffle/com.oracle.truffle.api.dsl/src/com/oracle/truffle/api/dsl/Cached.java	Thu Dec 17 10:01:38 2015 +0100
@@ -26,7 +26,6 @@
 
 import com.oracle.truffle.api.CompilerAsserts;
 import com.oracle.truffle.api.nodes.Node;
-import com.oracle.truffle.api.profiles.BranchProfile;
 
 import java.lang.annotation.ElementType;
 import java.lang.annotation.Retention;
@@ -93,7 +92,7 @@
  *      CompilerAsserts.compilationConstant(cachedOperand);
  *      ...
  *  }
- *
+ * 
  *  Example executions:
  *  execute(1) => doCached(1, 1) // new instantiation, localOperand is bound to 1
  *  execute(0) => doCached(0, 1)
@@ -119,7 +118,7 @@
  *    CompilerAsserts.compilationConstant(cachedOperand);
  *    ...
  * }
- *
+ * 
  * Example executions:
  * execute(0) => doCached(0, 0) // new instantiation, cachedOperand is bound to 0
  * execute(1) => doCached(1, 1) // new instantiation, cachedOperand is bound to 1
@@ -147,10 +146,10 @@
  *    CompilerAsserts.compilationConstant(cachedOperand);
  *    ...
  * }
- *
+ * 
  * &#064;Specialization(contains = &quot;doCached&quot;)
  * void doNormal(int operand) {...}
- *
+ * 
  * Example executions with contains = &quot;doCached&quot;:
  * execute(0) => doCached(0, 0) // new instantiation, cachedOperand is bound to 0
  * execute(1) => doCached(1, 1) // new instantiation, cachedOperand is bound to 1
@@ -158,7 +157,7 @@
  * execute(2) => doCached(2, 2) // new instantiation, cachedOperand is bound to 2
  * execute(3) => doNormal(3)    // new instantiation of doNormal due to limit overflow; doCached gets removed.
  * execute(1) => doNormal(1)
- *
+ * 
  * Example executions without contains = &quot;doCached&quot;:
  * execute(0) => doCached(0, 0) // new instantiation, cachedOperand is bound to 0
  * execute(1) => doCached(1, 1) // new instantiation, cachedOperand is bound to 1
@@ -166,7 +165,7 @@
  * execute(2) => doCached(2, 2) // new instantiation, cachedOperand is bound to 2
  * execute(3) => doNormal(3)    // new instantiation of doNormal due to limit overflow
  * execute(1) => doCached(1, 1)
- *
+ * 
  * </code>
  *
  * </li>
@@ -178,7 +177,7 @@
  * &#064;Specialization
  * void s(int operand, {@code @Cached}(&quot;transformLocal(operand)&quot;) int cachedOperand) {
  * }
- *
+ * 
  * int transformLocal(int operand) {
  *     return operand & 0x42;
  * }
@@ -194,9 +193,9 @@
  * void s(Object operand, {@code @Cached}(&quot;new()&quot;) OtherNode someNode) {
  *     someNode.execute(operand);
  * }
- *
+ * 
  * static class OtherNode extends Node {
- *
+ * 
  *     public String execute(Object value) {
  *         throw new UnsupportedOperationException();
  *     }
@@ -208,7 +207,8 @@
  * <li>
  * Java types without public constructor but with a static factory methods can be initialized by
  * just referencing its static factory method and its parameters. In this case
- * {@link BranchProfile#create()} is used to instantiate the {@link BranchProfile} instance.
+ * {@link com.oracle.truffle.api.profiles.BranchProfile#create()} is used to instantiate the
+ * {@link com.oracle.truffle.api.profiles.BranchProfile} instance.
  *
  * <pre>
  * &#064;Specialization
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.api.profiles/src/com/oracle/truffle/api/profiles/BranchProfile.java	Thu Dec 17 10:01:38 2015 +0100
@@ -0,0 +1,143 @@
+/*
+ * Copyright (c) 2013, 2015, 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.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * 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.truffle.api.profiles;
+
+import com.oracle.truffle.api.CompilerDirectives;
+import com.oracle.truffle.api.CompilerDirectives.CompilationFinal;
+import com.oracle.truffle.api.Truffle;
+
+/**
+ * <p>
+ * BranchProfiles are profiles to speculate on branches that are unlikely to be visited. If the
+ * {@link #enter()} method is invoked first the optimized code is invalidated and the branch where
+ * {@link #enter()} is invoked is enabled for compilation. Otherwise if the {@link #enter()} method
+ * was never invoked the branch will not get compiled.
+ * </p>
+ *
+ * <p>
+ * <b> Usage example: </b>
+ *
+ * <pre>
+ * class SampleNode extends Node {
+ * 
+ *     final BranchProfile errorProfile = BranchProfile.create();
+ * 
+ *     void execute(int value) {
+ *         if (value == Integer.MAX_VALUE) {
+ *             errorProfile.enter();
+ *             throw new Error(&quot;Invalid input value&quot;)
+ *         }
+ *         return value;
+ *     }
+ * }
+ * </pre>
+ *
+ * {@inheritDoc}
+ *
+ * @see BranchProfile#enter()
+ */
+public abstract class BranchProfile extends Profile {
+
+    BranchProfile() {
+    }
+
+    /**
+     * Call when an unlikely branch is entered.
+     */
+    public abstract void enter();
+
+    /**
+     * @deprecated it is not reliable when profiling is turned off.
+     */
+    @Deprecated
+    public abstract boolean isVisited();
+
+    /**
+     * Call to create a new instance of a branch profile.
+     */
+    public static BranchProfile create() {
+        if (Truffle.getRuntime().isProfilingEnabled()) {
+            return Enabled.create0();
+        } else {
+            return Disabled.INSTANCE;
+        }
+    }
+
+    static final class Enabled extends BranchProfile {
+
+        @CompilationFinal private boolean visited;
+
+        @Override
+        public void enter() {
+            if (!visited) {
+                CompilerDirectives.transferToInterpreterAndInvalidate();
+                visited = true;
+            }
+        }
+
+        @SuppressWarnings("deprecation")
+        @Override
+        public boolean isVisited() {
+            return visited;
+        }
+
+        @Override
+        public String toString() {
+            return toString(BranchProfile.class, !visited, false, "VISITED");
+        }
+
+        /* Needed for lazy class loading. */
+        static BranchProfile create0() {
+            return new Enabled();
+        }
+    }
+
+    static final class Disabled extends BranchProfile {
+
+        static final BranchProfile INSTANCE = new Disabled();
+
+        @Override
+        protected Object clone() {
+            return INSTANCE;
+        }
+
+        @Override
+        public void enter() {
+        }
+
+        @SuppressWarnings("deprecation")
+        @Override
+        public boolean isVisited() {
+            return true;
+        }
+
+        @Override
+        public String toString() {
+            return toStringDisabled(BranchProfile.class);
+        }
+
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.api.profiles/src/com/oracle/truffle/api/profiles/ByteValueProfile.java	Thu Dec 17 10:01:38 2015 +0100
@@ -0,0 +1,158 @@
+/*
+ * Copyright (c) 2015, 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.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * 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.truffle.api.profiles;
+
+import com.oracle.truffle.api.CompilerDirectives;
+import com.oracle.truffle.api.CompilerDirectives.CompilationFinal;
+import com.oracle.truffle.api.Truffle;
+
+/**
+ * <p>
+ * Specialized value profile to capture certain properties of <code>byte</code> runtime values.
+ * Value profiles require a runtime check in their initialized state to verify their profiled
+ * assumption. Value profiles are limited to capture monomorphic profiles only. This means that if
+ * two or more values are profiled within a single profile then the profile has no effect. If the
+ * value assumption is invalidated in compiled code then it is invalidated.
+ * </p>
+ *
+ * <p>
+ * <b> Usage example: </b>
+ *
+ * <pre>
+ * class SampleNode extends Node {
+ *
+ *     final ByteValueProfile profile = ByteValueProfile.createIdentityProfile();
+ *
+ *     byte execute(byte input) {
+ *         byte profiledValue = profile.profile(input);
+ *         // compiler may know now more about profiledValue
+ *         return profiledValue;
+ *     }
+ * }
+ * </pre>
+ * <p>
+ *
+ *
+ * {@inheritDoc}
+ *
+ * @see #createIdentityProfile()
+ * @see ValueProfile
+ */
+public abstract class ByteValueProfile extends Profile {
+
+    ByteValueProfile() {
+    }
+
+    public abstract byte profile(byte value);
+
+    /**
+     * Returns a value profile that profiles the exact value of a <code>byte</code>.
+     *
+     * @see ByteValueProfile
+     */
+    public static ByteValueProfile createIdentityProfile() {
+        if (Truffle.getRuntime().isProfilingEnabled()) {
+            return Enabled.create();
+        } else {
+            return Disabled.INSTANCE;
+        }
+    }
+
+    static final class Enabled extends ByteValueProfile {
+
+        private static final byte UNINITIALIZED = 0;
+        private static final byte SPECIALIZED = 1;
+        private static final byte GENERIC = 2;
+
+        @CompilationFinal private byte cachedValue;
+        @CompilationFinal private byte state = 0;
+
+        @Override
+        public byte profile(byte value) {
+            byte localState = this.state;
+            if (localState != GENERIC) {
+                if (localState == SPECIALIZED) {
+                    byte v = cachedValue;
+                    if (v == value) {
+                        return v;
+                    }
+                }
+                CompilerDirectives.transferToInterpreterAndInvalidate();
+                if (localState == UNINITIALIZED) {
+                    this.cachedValue = value;
+                    this.state = SPECIALIZED;
+                } else {
+                    this.state = GENERIC;
+                }
+            }
+            return value;
+        }
+
+        boolean isGeneric() {
+            return state == GENERIC;
+        }
+
+        boolean isUninitialized() {
+            return state == UNINITIALIZED;
+        }
+
+        byte getCachedValue() {
+            return cachedValue;
+        }
+
+        @Override
+        public String toString() {
+            return toString(ByteValueProfile.class, state == UNINITIALIZED, state == GENERIC, //
+                            String.format("value == (byte)%s", cachedValue));
+        }
+
+        /* Needed for lazy class loading. */
+        static ByteValueProfile create() {
+            return new Enabled();
+        }
+    }
+
+    static final class Disabled extends ByteValueProfile {
+
+        static final ByteValueProfile INSTANCE = new Disabled();
+
+        @Override
+        protected Object clone() {
+            return INSTANCE;
+        }
+
+        @Override
+        public byte profile(byte value) {
+            return value;
+        }
+
+        @Override
+        public String toString() {
+            return toStringDisabled(ByteValueProfile.class);
+        }
+
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.api.profiles/src/com/oracle/truffle/api/profiles/ConditionProfile.java	Thu Dec 17 10:01:38 2015 +0100
@@ -0,0 +1,242 @@
+/*
+ * Copyright (c) 2014, 2015, 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.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * 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.truffle.api.profiles;
+
+import com.oracle.truffle.api.CompilerDirectives;
+import com.oracle.truffle.api.CompilerDirectives.CompilationFinal;
+import com.oracle.truffle.api.Truffle;
+
+/**
+ * <p>
+ * ConditionProfiles are useful to profile the outcome of conditions.
+ * </p>
+ *
+ * <p>
+ * <b> Usage example: </b>
+ *
+ * <pre>
+ * class AbsoluteNode extends Node {
+ * 
+ *     final ConditionProfile greaterZeroProfile = ConditionProfile.create{Binary,Counting}Profile();
+ * 
+ *     void execute(int value) {
+ *         if (greaterZeroProfile.profile(value >= 0)) {
+ *             return value;
+ *         } else {
+ *             return -value;
+ *         }
+ *     }
+ * }
+ * </pre>
+ *
+ * {@inheritDoc}
+ *
+ * @see #createBinaryProfile()
+ * @see #createCountingProfile()
+ * @see LoopConditionProfile
+ */
+public abstract class ConditionProfile extends Profile {
+
+    ConditionProfile() {
+    }
+
+    public abstract boolean profile(boolean value);
+
+    /**
+     * Returns a {@link ConditionProfile} that speculates on conditions to be never
+     * <code>true</code> or to be never <code>false</code>. Additionally to a binary profile this
+     * method returns a condition profile that also counts the number of times the condition was
+     * true and false. This information is reported to the underlying optimization system using
+     * {@link CompilerDirectives#injectBranchProbability(double, boolean)}. Condition profiles are
+     * intended to be used as part of if conditions.
+     *
+     * @see ConditionProfile
+     * @see #createBinaryProfile()
+     */
+    public static ConditionProfile createCountingProfile() {
+        if (Truffle.getRuntime().isProfilingEnabled()) {
+            return Counting.create();
+        } else {
+            return Disabled.INSTANCE;
+        }
+    }
+
+    /**
+     * Returns a {@link ConditionProfile} that speculates on conditions to be never
+     * <code>true</code> or to be never <code>false</code>. Condition profiles are intended to be
+     * used as part of if conditions.
+     *
+     * @see ConditionProfile
+     * @see ConditionProfile#createCountingProfile()
+     */
+    public static ConditionProfile createBinaryProfile() {
+        if (Truffle.getRuntime().isProfilingEnabled()) {
+            return Binary.create();
+        } else {
+            return Disabled.INSTANCE;
+        }
+    }
+
+    static final class Disabled extends ConditionProfile {
+
+        static final ConditionProfile INSTANCE = new Disabled();
+
+        @Override
+        protected Object clone() {
+            return INSTANCE;
+        }
+
+        @Override
+        public boolean profile(boolean value) {
+            return value;
+        }
+
+        @Override
+        public String toString() {
+            return toStringDisabled(ConditionProfile.class);
+        }
+
+    }
+
+    static final class Counting extends ConditionProfile {
+
+        @CompilationFinal private int trueCount;
+        @CompilationFinal private int falseCount;
+
+        Counting() {
+            /* package protected constructor */
+        }
+
+        @Override
+        public boolean profile(boolean value) {
+            if (CompilerDirectives.inInterpreter()) {
+                if (value) {
+                    // local required to guarantee no overflow in multi-threaded environments
+                    int t = trueCount;
+                    if (t < Integer.MAX_VALUE) {
+                        trueCount = t + 1;
+                    }
+                } else {
+                    // local required to guarantee no overflow in multi-threaded environments
+                    int f = falseCount;
+                    if (f < Integer.MAX_VALUE) {
+                        falseCount = f + 1;
+                    }
+                }
+                // no branch probability calculation in the interpreter
+                return value;
+            } else {
+                // use trueCount and falseCount as locals for compilation speed
+                int t = trueCount;
+                int f = falseCount;
+                if (value) {
+                    if (t == 0) {
+                        CompilerDirectives.transferToInterpreterAndInvalidate();
+                        t = 1;
+                    }
+                } else {
+                    if (f == 0) {
+                        CompilerDirectives.transferToInterpreterAndInvalidate();
+                        f = 1;
+                    }
+                }
+                return CompilerDirectives.injectBranchProbability((double) t / (double) (t + f), value);
+            }
+        }
+
+        int getTrueCount() {
+            return trueCount;
+        }
+
+        int getFalseCount() {
+            return falseCount;
+        }
+
+        @Override
+        public String toString() {
+            int t = trueCount;
+            int f = falseCount;
+            return toString(ConditionProfile.class, trueCount == 0 && falseCount == 0, false, //
+                            String.format("trueProbability=%s (trueCount=%s, falseCount=%s)", (double) t / (double) (t + f), t, f));
+        }
+
+        /* Needed for lazy class loading. */
+        static ConditionProfile create() {
+            return new Counting();
+        }
+    }
+
+    /**
+     * Utility class to speculate on conditions to be never true or to be never false. Condition
+     * profiles are intended to be used as part of if conditions.
+     *
+     * @see ConditionProfile#createBinaryProfile()
+     */
+    static final class Binary extends ConditionProfile {
+
+        @CompilationFinal private boolean wasTrue;
+        @CompilationFinal private boolean wasFalse;
+
+        Binary() {
+            /* package protected constructor */
+        }
+
+        @Override
+        public boolean profile(boolean value) {
+            if (value) {
+                if (!wasTrue) {
+                    CompilerDirectives.transferToInterpreterAndInvalidate();
+                    wasTrue = true;
+                }
+                return true;
+            } else {
+                if (!wasFalse) {
+                    CompilerDirectives.transferToInterpreterAndInvalidate();
+                    wasFalse = true;
+                }
+                return false;
+            }
+        }
+
+        boolean wasTrue() {
+            return wasTrue;
+        }
+
+        boolean wasFalse() {
+            return wasFalse;
+        }
+
+        @Override
+        public String toString() {
+            return String.format("%s(wasTrue=%s, wasFalse=%s)@%x", getClass().getSimpleName(), wasTrue, wasFalse, hashCode());
+        }
+
+        /* Needed for lazy class loading. */
+        static ConditionProfile create() {
+            return new Binary();
+        }
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.api.profiles/src/com/oracle/truffle/api/profiles/DoubleValueProfile.java	Thu Dec 17 10:01:38 2015 +0100
@@ -0,0 +1,160 @@
+/*
+ * Copyright (c) 2015, 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.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * 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.truffle.api.profiles;
+
+import com.oracle.truffle.api.CompilerDirectives;
+import com.oracle.truffle.api.CompilerDirectives.CompilationFinal;
+import com.oracle.truffle.api.Truffle;
+
+/**
+ * <p>
+ * Specialized value profile to capture certain properties of <code>double</code> runtime values.
+ * Value profiles require a runtime check in their initialized state to verify their profiled
+ * assumption. Value profiles are limited to capture monomorphic profiles only. This means that if
+ * two or more values are profiled within a single profile then the profile has no effect. If the
+ * value assumption is invalidated in compiled code then it is invalidated.
+ * </p>
+ *
+ * <p>
+ * <b> Usage example: </b>
+ *
+ * <pre>
+ * class SampleNode extends Node {
+ *
+ *     final DoubleValueProfile profile = DoubleValueProfile.createRawIdentityProfile();
+ *
+ *     double execute(double input) {
+ *         double profiledValue = profile.profile(input);
+ *         // compiler may know now more about profiledValue
+ *         return profiledValue;
+ *     }
+ * }
+ * </pre>
+ * <p>
+ *
+ *
+ * {@inheritDoc}
+ *
+ * @see #createRawIdentityProfile()
+ * @see ValueProfile
+ */
+public abstract class DoubleValueProfile extends Profile {
+
+    DoubleValueProfile() {
+    }
+
+    public abstract double profile(double value);
+
+    /**
+     * Returns a value profile that profiles the exact value of a <code>double</code> using
+     * {@link Double#doubleToRawLongBits(double)}.
+     *
+     * @see IntValueProfile
+     */
+    public static DoubleValueProfile createRawIdentityProfile() {
+        if (Truffle.getRuntime().isProfilingEnabled()) {
+            return Enabled.create();
+        } else {
+            return Disabled.INSTANCE;
+        }
+    }
+
+    static final class Enabled extends DoubleValueProfile {
+
+        private static final byte UNINITIALIZED = 0;
+        private static final byte SPECIALIZED = 1;
+        private static final byte GENERIC = 2;
+
+        @CompilationFinal private double cachedValue;
+        @CompilationFinal private long cachedRawValue;
+        @CompilationFinal private byte state = 0;
+
+        @Override
+        public double profile(double value) {
+            byte localState = this.state;
+            if (localState != GENERIC) {
+                if (localState == SPECIALIZED) {
+                    if (cachedRawValue == Double.doubleToRawLongBits(value)) {
+                        return cachedValue;
+                    }
+                }
+                CompilerDirectives.transferToInterpreterAndInvalidate();
+                if (localState == UNINITIALIZED) {
+                    this.cachedValue = value;
+                    this.cachedRawValue = Double.doubleToRawLongBits(value);
+                    this.state = SPECIALIZED;
+                } else {
+                    this.state = GENERIC;
+                }
+            }
+            return value;
+        }
+
+        boolean isGeneric() {
+            return state == GENERIC;
+        }
+
+        boolean isUninitialized() {
+            return state == UNINITIALIZED;
+        }
+
+        double getCachedValue() {
+            return cachedValue;
+        }
+
+        @Override
+        public String toString() {
+            return toString(DoubleValueProfile.class, state == UNINITIALIZED, state == GENERIC, //
+                            String.format("value == (double)%s (raw %h)", cachedValue, cachedRawValue));
+        }
+
+        /* Needed for lazy class loading. */
+        static DoubleValueProfile create() {
+            return new Enabled();
+        }
+    }
+
+    static final class Disabled extends DoubleValueProfile {
+
+        static final DoubleValueProfile INSTANCE = new Disabled();
+
+        @Override
+        protected Object clone() {
+            return INSTANCE;
+        }
+
+        @Override
+        public double profile(double value) {
+            return value;
+        }
+
+        @Override
+        public String toString() {
+            return toStringDisabled(DoubleValueProfile.class);
+        }
+
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.api.profiles/src/com/oracle/truffle/api/profiles/FloatValueProfile.java	Thu Dec 17 10:01:38 2015 +0100
@@ -0,0 +1,159 @@
+/*
+ * Copyright (c) 2015, 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.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * 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.truffle.api.profiles;
+
+import com.oracle.truffle.api.CompilerDirectives;
+import com.oracle.truffle.api.CompilerDirectives.CompilationFinal;
+import com.oracle.truffle.api.Truffle;
+
+/**
+ * <p>
+ * Specialized value profile to capture certain properties of <code>float</code> runtime values.
+ * Value profiles require a runtime check in their initialized state to verify their profiled
+ * assumption. Value profiles are limited to capture monomorphic profiles only. This means that if
+ * two or more values are profiled within a single profile then the profile has no effect. If the
+ * value assumption is invalidated in compiled code then it is invalidated.
+ * </p>
+ *
+ * <p>
+ * <b> Usage example: </b>
+ *
+ * <pre>
+ * class SampleNode extends Node {
+ * 
+ *     final FloatValueProfile profile = FloatValueProfile.createRawIdentityProfile();
+ * 
+ *     float execute(float input) {
+ *         float profiledValue = profile.profile(input);
+ *         // compiler may know now more about profiledValue
+ *         return profiledValue;
+ *     }
+ * }
+ * </pre>
+ * <p>
+ *
+ *
+ * {@inheritDoc}
+ *
+ * @see #createRawIdentityProfile()
+ * @see ValueProfile
+ */
+public abstract class FloatValueProfile extends Profile {
+
+    FloatValueProfile() {
+    }
+
+    public abstract float profile(float value);
+
+    /**
+     * Returns a value profile that profiles the exact value of a <code>float</code> using
+     * {@link Float#floatToRawIntBits(float)}.
+     *
+     * @see IntValueProfile
+     */
+    public static FloatValueProfile createRawIdentityProfile() {
+        if (Truffle.getRuntime().isProfilingEnabled()) {
+            return Enabled.create();
+        } else {
+            return Disabled.INSTANCE;
+        }
+    }
+
+    static final class Enabled extends FloatValueProfile {
+
+        private static final byte UNINITIALIZED = 0;
+        private static final byte SPECIALIZED = 1;
+        private static final byte GENERIC = 2;
+
+        @CompilationFinal private float cachedValue;
+        @CompilationFinal private int cachedRawValue;
+        @CompilationFinal private byte state = 0;
+
+        @Override
+        public float profile(float value) {
+            byte localState = this.state;
+            if (localState != GENERIC) {
+                if (localState == SPECIALIZED) {
+                    if (cachedRawValue == Float.floatToRawIntBits(value)) {
+                        return cachedValue;
+                    }
+                }
+                CompilerDirectives.transferToInterpreterAndInvalidate();
+                if (localState == UNINITIALIZED) {
+                    this.cachedValue = value;
+                    this.cachedRawValue = Float.floatToRawIntBits(value);
+                    this.state = SPECIALIZED;
+                } else {
+                    this.state = GENERIC;
+                }
+            }
+            return value;
+        }
+
+        boolean isGeneric() {
+            return state == GENERIC;
+        }
+
+        boolean isUninitialized() {
+            return state == UNINITIALIZED;
+        }
+
+        float getCachedValue() {
+            return cachedValue;
+        }
+
+        @Override
+        public String toString() {
+            return toString(FloatValueProfile.class, state == UNINITIALIZED, state == GENERIC, //
+                            String.format("value == (float)%s (raw %h)", cachedValue, cachedRawValue));
+        }
+
+        /* Needed for lazy class loading. */
+        static FloatValueProfile create() {
+            return new Enabled();
+        }
+    }
+
+    static final class Disabled extends FloatValueProfile {
+
+        static final FloatValueProfile INSTANCE = new Disabled();
+
+        @Override
+        protected Object clone() {
+            return INSTANCE;
+        }
+
+        @Override
+        public float profile(float value) {
+            return value;
+        }
+
+        @Override
+        public String toString() {
+            return toStringDisabled(FloatValueProfile.class);
+        }
+
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.api.profiles/src/com/oracle/truffle/api/profiles/IntValueProfile.java	Thu Dec 17 10:01:38 2015 +0100
@@ -0,0 +1,158 @@
+/*
+ * Copyright (c) 2015, 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.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * 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.truffle.api.profiles;
+
+import com.oracle.truffle.api.CompilerDirectives;
+import com.oracle.truffle.api.CompilerDirectives.CompilationFinal;
+import com.oracle.truffle.api.Truffle;
+
+/**
+ * <p>
+ * Specialized value profile to capture certain properties of <code>int</code> runtime values. Value
+ * profiles require a runtime check in their initialized state to verify their profiled assumption.
+ * Value profiles are limited to capture monomorphic profiles only. This means that if two or more
+ * values are profiled within a single profile then the profile has no effect. If the value
+ * assumption is invalidated in compiled code then it is invalidated.
+ * </p>
+ *
+ * <p>
+ * <b> Usage example: </b>
+ *
+ * <pre>
+ * class SampleNode extends Node {
+ *
+ *     final IntValueProfile profile = IntValueProfile.createIdentityProfile();
+ *
+ *     int execute(int input) {
+ *         int profiledValue = profile.profile(input);
+ *         // compiler may know now more about profiledValue
+ *         return profiledValue;
+ *     }
+ * }
+ * </pre>
+ * <p>
+ *
+ *
+ * {@inheritDoc}
+ *
+ * @see #createIdentityProfile()
+ * @see ValueProfile
+ */
+public abstract class IntValueProfile extends Profile {
+
+    IntValueProfile() {
+    }
+
+    public abstract int profile(int value);
+
+    /**
+     * Returns a value profile that profiles the exact value of an <code>int</code>.
+     *
+     * @see IntValueProfile
+     */
+    public static IntValueProfile createIdentityProfile() {
+        if (Truffle.getRuntime().isProfilingEnabled()) {
+            return Enabled.create();
+        } else {
+            return Disabled.INSTANCE;
+        }
+    }
+
+    static final class Enabled extends IntValueProfile {
+
+        private static final byte UNINITIALIZED = 0;
+        private static final byte SPECIALIZED = 1;
+        private static final byte GENERIC = 2;
+
+        @CompilationFinal private int cachedValue;
+        @CompilationFinal private byte state = 0;
+
+        @Override
+        public int profile(int value) {
+            byte localState = this.state;
+            if (localState != GENERIC) {
+                if (localState == SPECIALIZED) {
+                    int v = cachedValue;
+                    if (v == value) {
+                        return v;
+                    }
+                }
+                CompilerDirectives.transferToInterpreterAndInvalidate();
+                if (localState == UNINITIALIZED) {
+                    this.cachedValue = value;
+                    this.state = SPECIALIZED;
+                } else {
+                    this.state = GENERIC;
+                }
+            }
+            return value;
+        }
+
+        boolean isGeneric() {
+            return state == GENERIC;
+        }
+
+        boolean isUninitialized() {
+            return state == UNINITIALIZED;
+        }
+
+        int getCachedValue() {
+            return cachedValue;
+        }
+
+        @Override
+        public String toString() {
+            return toString(IntValueProfile.class, isUninitialized(), isGeneric(), //
+                            String.format("value == (int)%s", cachedValue));
+        }
+
+        /* Needed for lazy class loading. */
+        static IntValueProfile create() {
+            return new Enabled();
+        }
+    }
+
+    static final class Disabled extends IntValueProfile {
+
+        static final IntValueProfile INSTANCE = new Disabled();
+
+        @Override
+        protected Object clone() {
+            return INSTANCE;
+        }
+
+        @Override
+        public int profile(int value) {
+            return value;
+        }
+
+        @Override
+        public String toString() {
+            return toStringDisabled(IntValueProfile.class);
+        }
+
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.api.profiles/src/com/oracle/truffle/api/profiles/LongValueProfile.java	Thu Dec 17 10:01:38 2015 +0100
@@ -0,0 +1,156 @@
+/*
+ * Copyright (c) 2015, 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.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * 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.truffle.api.profiles;
+
+import com.oracle.truffle.api.CompilerDirectives;
+import com.oracle.truffle.api.CompilerDirectives.CompilationFinal;
+import com.oracle.truffle.api.Truffle;
+
+/**
+ * <p>
+ * Specialized value profile to capture certain properties of <code>long</code> runtime values.
+ * Value profiles require a runtime check in their initialized state to verify their profiled
+ * assumption. Value profiles are limited to capture monomorphic profiles only. This means that if
+ * two or more values are profiled within a single profile then the profile has no effect. If the
+ * value assumption is invalidated in compiled code then it is invalidated.
+ * </p>
+ *
+ * <p>
+ * <b> Usage example: </b>
+ *
+ * <pre>
+ * class SampleNode extends Node {
+ *
+ *     final LongValueProfile profile = LongValueProfile.createIdentityProfile();
+ *
+ *     long execute(long input) {
+ *         long profiledValue = profile.profile(input);
+ *         // compiler may know now more about profiledValue
+ *         return profiledValue;
+ *     }
+ * }
+ * </pre>
+ * <p>
+ *
+ * {@inheritDoc}
+ *
+ * @see #createIdentityProfile()
+ * @see ValueProfile
+ */
+public abstract class LongValueProfile extends Profile {
+
+    LongValueProfile() {
+    }
+
+    public abstract long profile(long value);
+
+    /**
+     * Returns a value profile that profiles the exact value of an <code>long</code>.
+     *
+     * @see LongValueProfile
+     */
+    public static LongValueProfile createIdentityProfile() {
+        if (Truffle.getRuntime().isProfilingEnabled()) {
+            return Enabled.create();
+        } else {
+            return Disabled.INSTANCE;
+        }
+    }
+
+    static final class Enabled extends LongValueProfile {
+
+        private static final byte UNINITIALIZED = 0;
+        private static final byte SPECIALIZED = 1;
+        private static final byte GENERIC = 2;
+
+        @CompilationFinal private long cachedValue;
+        @CompilationFinal private byte state = 0;
+
+        @Override
+        public long profile(long value) {
+            byte localState = this.state;
+            if (localState != GENERIC) {
+                if (localState == SPECIALIZED) {
+                    long v = cachedValue;
+                    if (v == value) {
+                        return v;
+                    }
+                }
+                CompilerDirectives.transferToInterpreterAndInvalidate();
+                if (localState == UNINITIALIZED) {
+                    this.cachedValue = value;
+                    this.state = SPECIALIZED;
+                } else {
+                    this.state = GENERIC;
+                }
+            }
+            return value;
+        }
+
+        boolean isGeneric() {
+            return state == GENERIC;
+        }
+
+        boolean isUninitialized() {
+            return state == UNINITIALIZED;
+        }
+
+        long getCachedValue() {
+            return cachedValue;
+        }
+
+        @Override
+        public String toString() {
+            return toString(LongValueProfile.class, state == UNINITIALIZED, state == GENERIC, //
+                            String.format("value == (long)%s", cachedValue));
+        }
+
+        /* Needed for lazy class loading. */
+        static LongValueProfile create() {
+            return new Enabled();
+        }
+    }
+
+    static final class Disabled extends LongValueProfile {
+
+        static final LongValueProfile INSTANCE = new Disabled();
+
+        @Override
+        protected Object clone() {
+            return INSTANCE;
+        }
+
+        @Override
+        public long profile(long value) {
+            return value;
+        }
+
+        @Override
+        public String toString() {
+            return toStringDisabled(LongValueProfile.class);
+        }
+
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.api.profiles/src/com/oracle/truffle/api/profiles/LoopConditionProfile.java	Thu Dec 17 10:01:38 2015 +0100
@@ -0,0 +1,251 @@
+/*
+ * Copyright (c) 2015, 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.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * 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.truffle.api.profiles;
+
+import com.oracle.truffle.api.CompilerDirectives;
+import com.oracle.truffle.api.CompilerDirectives.CompilationFinal;
+import com.oracle.truffle.api.Truffle;
+
+/**
+ * <p>
+ * LoopConditionProfiles are designed to profile the outcome of loop conditions. Loop profiles can
+ * be used to profile unpredictable loops as well as predictable loops.
+ * </p>
+ *
+ * <p>
+ * <b> Arbitrary loop usage example: </b>
+ *
+ * <pre>
+ * class LoopNode extends Node {
+ * 
+ *     final LoopConditionProfile loopProfile = LoopConditionProfile.createCountingProfile();
+ * 
+ *     void execute() {
+ *         // loop count cannot be predicted
+ *         while (loopProfile.profile(Math.random() &gt;= 0.9)) {
+ *             // work
+ *         }
+ *     }
+ * }
+ * </pre>
+ *
+ * </p>
+ *
+ * <p>
+ * <b> Counted loop usage example: </b>
+ *
+ * <pre>
+ * class CountedLoopNode extends Node {
+ * 
+ *     final LoopConditionProfile loopProfile = LoopConditionProfile.createCountingProfile();
+ * 
+ *     void execute(int length) {
+ *         // loop count can be predicted
+ *         loopProfile.profileCounted(length);
+ *         for (int i = 0; loopProfile.inject(i &lt; length); i++) {
+ *             // work
+ *         }
+ *     }
+ * }
+ * </pre>
+ *
+ * </p>
+ * <p>
+ * The advantage of using {@link #profileCounted(long)} to using {@link #profile(boolean)} is that
+ * it incurs less overhead in the interpreter. Using {@link LoopConditionProfile#inject(boolean)} is
+ * a no-op in the interpreter while {@link #profile(boolean)} needs to use a counter for each
+ * iteration.
+ * </p>
+ *
+ *
+ * {@inheritDoc}
+ *
+ * @see #createBinaryProfile()
+ * @see #createCountingProfile()
+ * @see LoopConditionProfile
+ */
+public abstract class LoopConditionProfile extends ConditionProfile {
+
+    LoopConditionProfile() {
+    }
+
+    @Override
+    public abstract boolean profile(boolean value);
+
+    /**
+     * Provides an alternative way to profile counted loops with less interpreter footprint. Please
+     * see {@link LoopConditionProfile} for an usage example.
+     *
+     * @see #inject(boolean)
+     */
+    public abstract void profileCounted(long length);
+
+    /**
+     * Provides an alternative way to profile counted loops with less interpreter footprint. Please
+     * see {@link LoopConditionProfile} for an usage example.
+     *
+     * @see #inject(boolean)
+     */
+    public abstract boolean inject(boolean condition);
+
+    /**
+     * Returns a {@link LoopConditionProfile} that speculates on loop conditions to be never
+     * <code>true</code>. It also captures loop probabilities for the compiler. Loop condition
+     * profiles are intended to be used for loop conditions.
+     *
+     * @see LoopConditionProfile
+     */
+    public static LoopConditionProfile createCountingProfile() {
+        if (Truffle.getRuntime().isProfilingEnabled()) {
+            return Enabled.create();
+        } else {
+            return Disabled.INSTANCE;
+        }
+    }
+
+    static final class Enabled extends LoopConditionProfile {
+
+        @CompilationFinal private long trueCount; // long for long running loops.
+        @CompilationFinal private int falseCount;
+
+        @Override
+        public boolean profile(boolean condition) {
+            if (CompilerDirectives.inInterpreter()) {
+                if (condition) {
+                    // local required to guarantee no overflow in multi-threaded environments
+                    long localTrueCount = trueCount;
+                    if (localTrueCount < Long.MAX_VALUE) {
+                        trueCount = localTrueCount + 1;
+                    }
+                } else {
+                    // local required to guarantee no overflow in multi-threaded environments
+                    int localFalseCount = falseCount;
+                    if (localFalseCount < Integer.MAX_VALUE) {
+                        falseCount = localFalseCount + 1;
+                    }
+                }
+                // no branch probability calculation in the interpreter
+                return condition;
+            } else {
+                long trueCountLocal = trueCount;
+                int falseCountLocal = falseCount;
+                if (trueCountLocal == 0) {
+                    /* Deopt for never entering the loop. */
+                    if (condition) {
+                        CompilerDirectives.transferToInterpreterAndInvalidate();
+                        trueCount = trueCountLocal = 1;
+                    }
+                }
+                /* No deopt for not entering the loop. */
+                return CompilerDirectives.injectBranchProbability(calculateProbability(trueCountLocal, falseCountLocal), condition);
+            }
+        }
+
+        @Override
+        public void profileCounted(long length) {
+            if (CompilerDirectives.inInterpreter()) {
+                long trueCountLocal = trueCount + length;
+                if (trueCountLocal >= 0) { // don't write overflow values
+                    trueCount = trueCountLocal;
+                    int falseCountLocal = falseCount;
+                    if (falseCountLocal < Integer.MAX_VALUE) {
+                        falseCount = falseCountLocal + 1;
+                    }
+                }
+            }
+        }
+
+        @Override
+        public boolean inject(boolean condition) {
+            if (CompilerDirectives.inCompiledCode()) {
+                return CompilerDirectives.injectBranchProbability(calculateProbability(trueCount, falseCount), condition);
+            } else {
+                return condition;
+            }
+        }
+
+        private static double calculateProbability(long trueCountLocal, int falseCountLocal) {
+            if (falseCountLocal == 0 && trueCountLocal == 0) {
+                /* Avoid division by zero if profile was never used. */
+                return 0.0;
+            } else {
+                return (double) trueCountLocal / (double) (trueCountLocal + falseCountLocal);
+            }
+        }
+
+        /* for testing */
+        long getTrueCount() {
+            return trueCount;
+        }
+
+        /* for testing */
+        int getFalseCount() {
+            return falseCount;
+        }
+
+        @Override
+        public String toString() {
+            return toString(LoopConditionProfile.class, falseCount == 0, false, //
+                            String.format("trueProbability=%s (trueCount=%s, falseCount=%s)", calculateProbability(trueCount, falseCount), falseCount, trueCount));
+        }
+
+        /* Needed for lazy class loading. */
+        static LoopConditionProfile create() {
+            return new Enabled();
+        }
+
+    }
+
+    static final class Disabled extends LoopConditionProfile {
+
+        static final LoopConditionProfile INSTANCE = new Disabled();
+
+        @Override
+        protected Object clone() {
+            return INSTANCE;
+        }
+
+        @Override
+        public boolean profile(boolean condition) {
+            return condition;
+        }
+
+        @Override
+        public void profileCounted(long length) {
+        }
+
+        @Override
+        public boolean inject(boolean condition) {
+            return condition;
+        }
+
+        @Override
+        public String toString() {
+            return toStringDisabled(LoopConditionProfile.class);
+        }
+
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.api.profiles/src/com/oracle/truffle/api/profiles/PrimitiveValueProfile.java	Thu Dec 17 10:01:38 2015 +0100
@@ -0,0 +1,427 @@
+/*
+ * Copyright (c) 2014, 2015, 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.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * 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.truffle.api.profiles;
+
+import java.util.Objects;
+
+import com.oracle.truffle.api.CompilerDirectives;
+import com.oracle.truffle.api.CompilerDirectives.CompilationFinal;
+import com.oracle.truffle.api.Truffle;
+
+/**
+ * <p>
+ * Represents a {@link ValueProfile} that speculates on the primitive equality or object identity of
+ * values. Note that for {@code float} and {@code double} values we compare primitive equality via
+ * {@link Float#floatToRawIntBits} and {@link Double#doubleToRawLongBits}, so that for example
+ * {@code -0.0} is not considered the same as {@code 0.0}, even though primitive equality would
+ * normally say that it was.
+ * </p>
+ *
+ * {@inheritDoc}
+ */
+public abstract class PrimitiveValueProfile extends ValueProfile {
+
+    PrimitiveValueProfile() {
+    }
+
+    @Override
+    public abstract <T> T profile(T value);
+
+    public abstract byte profile(byte value);
+
+    public abstract short profile(short value);
+
+    public abstract int profile(int value);
+
+    public abstract long profile(long value);
+
+    public abstract float profile(float value);
+
+    public abstract double profile(double value);
+
+    public abstract boolean profile(boolean value);
+
+    public abstract char profile(char value);
+
+    /**
+     * Returns a {@link PrimitiveValueProfile} that speculates on the primitive equality or object
+     * identity of a value.
+     */
+    public static PrimitiveValueProfile createEqualityProfile() {
+        if (Truffle.getRuntime().isProfilingEnabled()) {
+            return Enabled.create();
+        } else {
+            return Disabled.INSTANCE;
+        }
+    }
+
+    /**
+     * @deprecated going to get removed without replacement
+     */
+    @Deprecated
+    public static boolean exactCompare(float a, float b) {
+        /*
+         * -0.0 == 0.0, but you can tell the difference through other means, so we need to
+         * differentiate.
+         */
+        return Float.floatToRawIntBits(a) == Float.floatToRawIntBits(b);
+    }
+
+    /**
+     * @deprecated going to get removed without replacement
+     */
+    @Deprecated
+    public static boolean exactCompare(double a, double b) {
+        /*
+         * -0.0 == 0.0, but you can tell the difference through other means, so we need to
+         * differentiate.
+         */
+        return Double.doubleToRawLongBits(a) == Double.doubleToRawLongBits(b);
+    }
+
+    static final class Enabled extends PrimitiveValueProfile {
+
+        private static final byte STATE_UNINITIALIZED = 0;
+        private static final byte STATE_BYTE = 1;
+        private static final byte STATE_SHORT = 2;
+        private static final byte STATE_INTEGER = 3;
+        private static final byte STATE_LONG = 4;
+        private static final byte STATE_BOOLEAN = 5;
+        private static final byte STATE_CHARACTER = 6;
+        private static final byte STATE_FLOAT = 7;
+        private static final byte STATE_DOUBLE = 8;
+        private static final byte STATE_IDENTITY = 9;
+        private static final byte STATE_GENERIC = 10;
+
+        @CompilationFinal private byte state = STATE_UNINITIALIZED;
+        @CompilationFinal private Object cachedValue;
+
+        Enabled() {
+        }
+
+        @SuppressWarnings("unchecked")
+        @Override
+        public <T> T profile(T value) {
+            byte s = this.state;
+            Object snapshot;
+            switch (s) {
+                case STATE_BYTE:
+                case STATE_SHORT:
+                case STATE_INTEGER:
+                case STATE_LONG:
+                case STATE_BOOLEAN:
+                case STATE_CHARACTER:
+                    snapshot = this.cachedValue;
+                    if (snapshot.equals(value)) {
+                        return (T) snapshot;
+                    }
+                    break;
+                case STATE_DOUBLE:
+                    snapshot = this.cachedValue;
+                    if (value instanceof Double && exactCompare((Double) snapshot, (Double) value)) {
+                        return (T) snapshot;
+                    }
+                    break;
+                case STATE_FLOAT:
+                    snapshot = this.cachedValue;
+                    if (value instanceof Float && exactCompare((Float) snapshot, (Float) value)) {
+                        return (T) snapshot;
+                    }
+                    break;
+                case STATE_IDENTITY:
+                    snapshot = this.cachedValue;
+                    if (snapshot == value) {
+                        return (T) snapshot;
+                    }
+                    break;
+                case STATE_GENERIC:
+                    return value;
+            }
+            CompilerDirectives.transferToInterpreterAndInvalidate();
+            slowpath(s, value);
+            return value;
+        }
+
+        @Override
+        public byte profile(byte value) {
+            byte s = this.state;
+            if (s != STATE_GENERIC) {
+                if (s == STATE_BYTE) {
+                    byte castCachedValue = (byte) this.cachedValue;
+                    if (castCachedValue == value) {
+                        return castCachedValue;
+                    }
+                }
+                CompilerDirectives.transferToInterpreterAndInvalidate();
+                slowpath(s, value);
+            }
+            return value;
+        }
+
+        @Override
+        public short profile(short value) {
+            byte s = this.state;
+            if (s != STATE_GENERIC) {
+                if (s == STATE_SHORT) {
+                    short castCachedValue = (short) this.cachedValue;
+                    if (castCachedValue == value) {
+                        return castCachedValue;
+                    }
+                }
+                CompilerDirectives.transferToInterpreterAndInvalidate();
+                slowpath(s, value);
+            }
+            return value;
+        }
+
+        @Override
+        public int profile(int value) {
+            byte s = this.state;
+            if (s != STATE_GENERIC) {
+                if (s == STATE_INTEGER) {
+                    int castCachedValue = (int) this.cachedValue;
+                    if (castCachedValue == value) {
+                        return castCachedValue;
+                    }
+                }
+                CompilerDirectives.transferToInterpreterAndInvalidate();
+                slowpath(s, value);
+            }
+            return value;
+        }
+
+        @Override
+        public long profile(long value) {
+            byte s = this.state;
+            if (s != STATE_GENERIC) {
+                if (s == STATE_LONG) {
+                    long castCachedValue = (long) this.cachedValue;
+                    if (castCachedValue == value) {
+                        return castCachedValue;
+                    }
+                }
+                CompilerDirectives.transferToInterpreterAndInvalidate();
+                slowpath(s, value);
+            }
+            return value;
+        }
+
+        @Override
+        public float profile(float value) {
+            byte s = this.state;
+            if (s != STATE_GENERIC) {
+                if (s == STATE_FLOAT) {
+                    float castCachedValue = (float) this.cachedValue;
+                    if (exactCompare(castCachedValue, value)) {
+                        return castCachedValue;
+                    }
+                }
+                CompilerDirectives.transferToInterpreterAndInvalidate();
+                slowpath(s, value);
+            }
+            return value;
+        }
+
+        @Override
+        public double profile(double value) {
+            byte s = this.state;
+            if (s != STATE_GENERIC) {
+                if (s == STATE_DOUBLE) {
+                    double castCachedValue = (double) this.cachedValue;
+                    if (exactCompare(castCachedValue, value)) {
+                        return castCachedValue;
+                    }
+                }
+                CompilerDirectives.transferToInterpreterAndInvalidate();
+                slowpath(s, value);
+            }
+            return value;
+
+        }
+
+        @Override
+        public boolean profile(boolean value) {
+            byte s = this.state;
+            if (s != STATE_GENERIC) {
+                if (s == STATE_BOOLEAN) {
+                    boolean castCachedValue = (boolean) this.cachedValue;
+                    if (castCachedValue == value) {
+                        return castCachedValue;
+                    }
+                }
+                CompilerDirectives.transferToInterpreterAndInvalidate();
+                slowpath(s, value);
+            }
+            return value;
+        }
+
+        @Override
+        public char profile(char value) {
+            byte s = this.state;
+            if (s != STATE_GENERIC) {
+                if (s == STATE_CHARACTER) {
+                    char castCachedValue = (char) this.cachedValue;
+                    if (castCachedValue == value) {
+                        return castCachedValue;
+                    }
+                }
+                CompilerDirectives.transferToInterpreterAndInvalidate();
+                slowpath(s, value);
+            }
+            return value;
+        }
+
+        private void slowpath(byte s, Object value) {
+            if (s == STATE_UNINITIALIZED) {
+                cachedValue = value;
+                state = specialize(value);
+            } else {
+                state = STATE_GENERIC;
+                cachedValue = null;
+            }
+        }
+
+        private static byte specialize(Object value) {
+            if (value instanceof Byte) {
+                return STATE_BYTE;
+            } else if (value instanceof Short) {
+                return STATE_SHORT;
+            } else if (value instanceof Integer) {
+                return STATE_INTEGER;
+            } else if (value instanceof Long) {
+                return STATE_LONG;
+            } else if (value instanceof Boolean) {
+                return STATE_BOOLEAN;
+            } else if (value instanceof Character) {
+                return STATE_CHARACTER;
+            } else if (value instanceof Double) {
+                return STATE_DOUBLE;
+            } else if (value instanceof Float) {
+                return STATE_FLOAT;
+            } else {
+                return STATE_IDENTITY;
+            }
+        }
+
+        boolean isGeneric() {
+            return state == STATE_GENERIC;
+        }
+
+        boolean isUninitialized() {
+            return state == STATE_UNINITIALIZED;
+        }
+
+        Object getCachedValue() {
+            return cachedValue;
+        }
+
+        @Override
+        public String toString() {
+            return toString(PrimitiveValueProfile.class, state == STATE_UNINITIALIZED, state == STATE_GENERIC, formatSpecialization());
+        }
+
+        private String formatSpecialization() {
+            Object snapshot = this.cachedValue;
+            if (state != STATE_UNINITIALIZED && state != STATE_GENERIC) {
+                if (snapshot == null) {
+                    return String.format("value == null");
+                } else {
+                    if (state == STATE_IDENTITY) {
+                        String simpleName = snapshot.getClass().getSimpleName();
+                        return String.format("value == %s@%x", simpleName, Objects.hash(snapshot));
+                    } else {
+                        return String.format("value == (%s)%s", snapshot.getClass().getSimpleName(), snapshot);
+                    }
+                }
+            }
+            return null;
+        }
+
+        /**
+         * Returns a {@link PrimitiveValueProfile} that speculates on the primitive equality or
+         * object identity of a value.
+         */
+        static PrimitiveValueProfile create() {
+            return new Enabled();
+        }
+    }
+
+    static final class Disabled extends PrimitiveValueProfile {
+
+        static final PrimitiveValueProfile INSTANCE = new Disabled();
+
+        @Override
+        public <T> T profile(T value) {
+            return value;
+        }
+
+        @Override
+        public byte profile(byte value) {
+            return value;
+        }
+
+        @Override
+        public short profile(short value) {
+            return value;
+        }
+
+        @Override
+        public int profile(int value) {
+            return value;
+        }
+
+        @Override
+        public long profile(long value) {
+            return value;
+        }
+
+        @Override
+        public float profile(float value) {
+            return value;
+        }
+
+        @Override
+        public double profile(double value) {
+            return value;
+        }
+
+        @Override
+        public boolean profile(boolean value) {
+            return value;
+        }
+
+        @Override
+        public char profile(char value) {
+            return value;
+        }
+
+        @Override
+        public String toString() {
+            return toStringDisabled(PrimitiveValueProfile.class);
+        }
+
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.api.profiles/src/com/oracle/truffle/api/profiles/Profile.java	Thu Dec 17 10:01:38 2015 +0100
@@ -0,0 +1,114 @@
+/*
+ * Copyright (c) 2015, 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.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * 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.truffle.api.profiles;
+
+import com.oracle.truffle.api.Assumption;
+import com.oracle.truffle.api.CompilerDirectives;
+import com.oracle.truffle.api.CompilerDirectives.CompilationFinal;
+import com.oracle.truffle.api.TruffleRuntime;
+import com.oracle.truffle.api.nodes.Node;
+import com.oracle.truffle.api.nodes.NodeCloneable;
+import com.oracle.truffle.api.nodes.RootNode;
+
+/**
+ * <p>
+ * A profile is a Truffle utility class that uses the {@link CompilerDirectives Truffle compiler
+ * directives} to guard for and/or forward runtime information to the compiler.
+ * </p>
+ *
+ * <p>
+ * <b>Usage:</b> Profiles should be stored in <code>final</code> or {@link CompilationFinal
+ * compilation final} fields of node classes to ensure that they can get optimized properly.
+ * Profiles must not be shared between ASTs. Using the same profile multiple times in a single
+ * {@link Node node} or in multiple {@link Node nodes} which {@link Node#getRootNode() link} to the
+ * same {@link RootNode root} is allowed. <b>Never</b> store profiles inside runtime values that
+ * leave the scope of the originating AST. This limitation exists because the used mechanism to
+ * invalidate compiled code performs local invalidations only. For global speculations use
+ * {@link Assumption assumptions} instead.
+ * </p>
+ *
+ * <p>
+ * <b>Compilation:</b> Some profiles like {@link BranchProfile branch} profiles do not induce
+ * additional overhead in compiled code. Others like {@link ValueProfile value} profiles might
+ * require a runtime check to verify their assumptions which are forwarded to the compiler. Even if
+ * profiles do not induce direct overhead in compiled code it still might get invalidated as a
+ * result of using profiles. Invalidating profiles will result in the invalidation of compiled code.
+ * It is therefore essential to place these profiles in way that is neither too aggressive nor too
+ * conservative.
+ * </p>
+ *
+ * <p>
+ * <b>Footprint:</b> Whether profiling information can be forwarded to the compiler depends on the
+ * capabilities of the {@link TruffleRuntime runtime system}. If the runtime returns
+ * <code>true</code> in {@link TruffleRuntime#isProfilingEnabled()} then runtime information will
+ * get collected. This comes at at the cost of additional overhead and footprint in interpreted
+ * mode. Thats why the factory methods of profiles can return implementations where profiling is
+ * disabled. Using disabled profiles makes sense for runtimes that are unable to use the collected
+ * profiling information. Even runtime implementations that are able to use this information might
+ * decide to turn off profiling for benchmarking purposes.
+ * </p>
+ *
+ * <p>
+ * Profile subclasses:
+ * <ul>
+ * <li> {@link BranchProfile} to profile on unlikely branches like errors.</li>
+ * <li> {@link ConditionProfile} to profile on conditionals or boolean values.</li>
+ * <li> {@link LoopConditionProfile} to profile on conditionals of loops with special support for
+ * counted loops.</li>
+ * <li> {@link ValueProfile} to profile on properties like type and identity of values.</li>
+ * <li> {@link ByteValueProfile} to profile on <code>byte</code> values.</li>
+ * <li> {@link IntValueProfile} to profile on <code>int</code> values.</li>
+ * <li> {@link LongValueProfile} to profile on <code>long</code> values.</li>
+ * <li> {@link FloatValueProfile} to profile on <code>float</code> values.</li>
+ * <li> {@link DoubleValueProfile} to profile on <code>double</code> values.</li>
+ * <li> {@link PrimitiveValueProfile} to profile on objects by identity and on primitives by value.</li>
+ * </ul>
+ * </p>
+ *
+ * @see Assumption
+ */
+public abstract class Profile extends NodeCloneable {
+
+    Profile() {
+        /* We don't to allow custom profiles. We want to evolve this API further first. Sorry. */
+    }
+
+    String toStringDisabled(Class<?> profileClass) {
+        return String.format("%s(DISABLED)", profileClass.getSimpleName());
+    }
+
+    String toString(Class<?> profileClass, boolean uninitialized, boolean generic, String specialization) {
+        String s;
+        if (uninitialized) {
+            s = "UNINITIALIZED";
+        } else if (generic) {
+            s = "GENERIC";
+        } else {
+            s = specialization == null ? "" : specialization;
+        }
+        return String.format("%s(%s)@%s", profileClass.getSimpleName(), s, Integer.toHexString(this.hashCode()));
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.api.profiles/src/com/oracle/truffle/api/profiles/ValueProfile.java	Thu Dec 17 10:01:38 2015 +0100
@@ -0,0 +1,334 @@
+/*
+ * Copyright (c) 2014, 2015, 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.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * 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.truffle.api.profiles;
+
+import java.util.Objects;
+
+import com.oracle.truffle.api.CompilerDirectives;
+import com.oracle.truffle.api.CompilerDirectives.CompilationFinal;
+import com.oracle.truffle.api.Truffle;
+
+/**
+ * <p>
+ * Specialized value profile to capture certain properties of <code>Object</code> runtime values.
+ * Value profiles require a runtime check in their initialized state to verify their profiled
+ * assumption. Value profiles are limited to capture monomorphic profiles only. This means that if
+ * two or more identities or classes are profiles within a single profile then the profile has no
+ * effect and no overhead after compilation. There are specialized versions of this profile with
+ * less interpreter footprint for {@link ConditionProfile boolean}, {@link ByteValueProfile byte},
+ * {@link IntValueProfile int}, {@link LongValueProfile long}, {@link FloatValueProfile float} and
+ * {@link DoubleValueProfile double} values.
+ * </p>
+ *
+ * <p>
+ * <b> Usage example: </b>
+ *
+ * <pre>
+ * class SampleNode extends Node {
+ *
+ * final ValueProfile profile = ValueProfile.create{Identity,Class}Profile();
+ *
+ *     Object execute(Object input) {
+ *         Object profiledValue = profile.profile(input);
+ *         // compiler may know now more about profiledValue
+ *         return profieldValue;
+ *     }
+ * }
+ * </pre>
+ * <p>
+ *
+ *
+ * {@inheritDoc}
+ *
+ * @see #createIdentityProfile()
+ * @see #createClassProfile()
+ */
+public abstract class ValueProfile extends Profile {
+
+    ValueProfile() {
+    }
+
+    public abstract <T> T profile(T value);
+
+    /**
+     * <p>
+     * Returns a value profile that profiles the exact class of a value. It will check the class of
+     * the profiled value and provide additional information to the compiler if only non-null values
+     * of exactly one concrete Java class are passed as a parameter to the
+     * {@link ValueProfile#profile} method. This can be beneficial if subsequent code can take
+     * advantage of knowing the concrete class of the value. The profile will degrade to the generic
+     * case if a null value or if at least two instances of two different Java classes are
+     * registered.
+     * </p>
+     *
+     * <p>
+     * <b>Compilation notes:</b> Value profiles require a runtime check in their initialized state
+     * to verify their profiled class. If two classes have been seen on a single profile instance
+     * then this profile will transition to a generic state with no overhead.
+     * </P>
+     *
+     * @see ValueProfile usage example
+     */
+    public static ValueProfile createClassProfile() {
+        if (Truffle.getRuntime().isProfilingEnabled()) {
+            return ExactClass.create();
+        } else {
+            return Disabled.INSTANCE;
+        }
+    }
+
+    /**
+     * <p>
+     * Returns a value profile that profiles the object identity of a value. A single instance can
+     * only profile one particular instance.
+     * </p>
+     *
+     * <p>
+     * <b>Compilation notes:</b> Identity profiles require a runtime check to verify their profiled
+     * object identity. If two identities have been seen on a single profile instance then this
+     * profile will transition to a generic state with no overhead.
+     * </p>
+     */
+    public static ValueProfile createIdentityProfile() {
+        if (Truffle.getRuntime().isProfilingEnabled()) {
+            return Identity.create();
+        } else {
+            return Disabled.INSTANCE;
+        }
+    }
+
+    /**
+     * <p>
+     * Returns a value profile that profiles the object equality of a value. A single instance can
+     * only profile one set of equal values.
+     * </p>
+     *
+     * <p>
+     * <b>Compilation notes:</b> Equality profiles inline the body of the equal method of the first
+     * profiled value in order to verify its assumption. Please take care that you do this only for
+     * equals implementations that your guest language actually has control over otherwise your
+     * compiled code might contain recursions or too much code. If two non equal objects have been
+     * seen on a single profile instance then this profile will transition to a generic state with
+     * no overhead.
+     * </p>
+     */
+    public static ValueProfile createEqualityProfile() {
+        if (Truffle.getRuntime().isProfilingEnabled()) {
+            return Equality.create();
+        } else {
+            return Disabled.INSTANCE;
+        }
+    }
+
+    static final class Disabled extends ValueProfile {
+
+        static final ValueProfile INSTANCE = new Disabled();
+
+        @Override
+        protected Object clone() {
+            return INSTANCE;
+        }
+
+        @Override
+        public <T> T profile(T value) {
+            return value;
+        }
+
+        @Override
+        public String toString() {
+            return toStringDisabled(ValueProfile.class);
+        }
+
+    }
+
+    static final class Equality extends ValueProfile {
+
+        private static final Object GENERIC = new Object();
+
+        @CompilationFinal protected Object cachedValue = null;
+
+        Equality() {
+        }
+
+        @Override
+        @SuppressWarnings("unchecked")
+        public <T> T profile(T newValue) {
+            // Field needs to be cached in local variable for thread safety and startup speed.
+            Object cached = this.cachedValue;
+            if (cached != GENERIC) {
+                if (cached != null && cached.equals(newValue)) {
+                    return (T) cached;
+                } else {
+                    CompilerDirectives.transferToInterpreterAndInvalidate();
+                    if (cached == null && newValue != null) {
+                        cachedValue = newValue;
+                    } else {
+                        cachedValue = GENERIC;
+                    }
+                }
+            }
+            return newValue;
+        }
+
+        public boolean isGeneric() {
+            return getCachedValue() == GENERIC;
+        }
+
+        public boolean isUninitialized() {
+            return getCachedValue() == null;
+        }
+
+        public Object getCachedValue() {
+            return cachedValue;
+        }
+
+        @Override
+        public String toString() {
+            return toString(ValueProfile.class, isUninitialized(), isGeneric(), //
+                            String.format("value == %s@%x", cachedValue != null ? cachedValue.getClass().getSimpleName() : "null", Objects.hash(cachedValue)));
+        }
+
+        /* Needed for lazy class loading. */
+        static ValueProfile create() {
+            return new Equality();
+        }
+
+    }
+
+    static final class Identity extends ValueProfile {
+
+        private static final Object UNINITIALIZED = new Object();
+        private static final Object GENERIC = new Object();
+
+        @CompilationFinal protected Object cachedValue = UNINITIALIZED;
+
+        Identity() {
+        }
+
+        @Override
+        @SuppressWarnings("unchecked")
+        public <T> T profile(T newValue) {
+            // Field needs to be cached in local variable for thread safety and startup speed.
+            Object cached = this.cachedValue;
+            if (cached != GENERIC) {
+                if (cached == newValue) {
+                    return (T) cached;
+                } else {
+                    CompilerDirectives.transferToInterpreterAndInvalidate();
+                    if (cachedValue == UNINITIALIZED) {
+                        cachedValue = newValue;
+                    } else {
+                        cachedValue = GENERIC;
+                    }
+                }
+            }
+            return newValue;
+        }
+
+        public boolean isGeneric() {
+            return getCachedValue() == GENERIC;
+        }
+
+        public boolean isUninitialized() {
+            return getCachedValue() == UNINITIALIZED;
+        }
+
+        public Object getCachedValue() {
+            return cachedValue;
+        }
+
+        @Override
+        public String toString() {
+            return toString(ValueProfile.class, isUninitialized(), isGeneric(), //
+                            String.format("value == %s@%x", cachedValue != null ? cachedValue.getClass().getSimpleName() : "null", Objects.hash(cachedValue)));
+        }
+
+        /* Needed for lazy class loading. */
+        static ValueProfile create() {
+            return new Identity();
+        }
+
+    }
+
+    static final class ExactClass extends ValueProfile {
+
+        @CompilationFinal protected Class<?> cachedClass;
+
+        ExactClass() {
+        }
+
+        public static ValueProfile create() {
+            return new ExactClass();
+        }
+
+        @SuppressWarnings("unchecked")
+        @Override
+        public <T> T profile(T value) {
+            // Field needs to be cached in local variable for thread safety and startup speed.
+            Class<?> clazz = cachedClass;
+            if (clazz != Object.class) {
+                if (clazz != null && value != null && clazz == value.getClass()) {
+                    /*
+                     * The cast is really only for the compiler relevant. It does not perform any
+                     * useful action in the interpreter and only takes time.
+                     */
+                    if (CompilerDirectives.inInterpreter()) {
+                        return value;
+                    } else {
+                        return (T) clazz.cast(value);
+                    }
+                } else {
+                    CompilerDirectives.transferToInterpreterAndInvalidate();
+                    if (clazz == null && value != null) {
+                        cachedClass = value.getClass();
+                    } else {
+                        cachedClass = Object.class;
+                    }
+                }
+            }
+            return value;
+        }
+
+        boolean isGeneric() {
+            return cachedClass == Object.class;
+        }
+
+        boolean isUninitialized() {
+            return cachedClass == null;
+        }
+
+        Class<?> getCachedClass() {
+            return cachedClass;
+        }
+
+        @Override
+        public String toString() {
+            return toString(ValueProfile.class, cachedClass == null, cachedClass == Object.class, //
+                            String.format("value.getClass() == %s.class", cachedClass != null ? cachedClass.getSimpleName() : "null"));
+        }
+
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.api.profiles/src/com/oracle/truffle/api/profiles/package-info.java	Thu Dec 17 10:01:38 2015 +0100
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2015, 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.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * 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.
+ */
+
+/*
+ @ApiInfo(
+ group="Stable"
+ )
+ */
+/**
+ * A profile is a Truffle utility class that uses the
+ * {@link com.oracle.truffle.api.CompilerDirectives Truffle compiler directives} to guard for and/or
+ * forward runtime information to the compiler.
+ *
+ * @see com.oracle.truffle.api.profiles.Profile
+ */
+package com.oracle.truffle.api.profiles;
+
--- a/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/profiles/BranchProfile.java	Wed Dec 16 15:32:23 2015 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,143 +0,0 @@
-/*
- * Copyright (c) 2013, 2015, 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.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * 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.truffle.api.profiles;
-
-import com.oracle.truffle.api.CompilerDirectives;
-import com.oracle.truffle.api.CompilerDirectives.CompilationFinal;
-import com.oracle.truffle.api.Truffle;
-
-/**
- * <p>
- * BranchProfiles are profiles to speculate on branches that are unlikely to be visited. If the
- * {@link #enter()} method is invoked first the optimized code is invalidated and the branch where
- * {@link #enter()} is invoked is enabled for compilation. Otherwise if the {@link #enter()} method
- * was never invoked the branch will not get compiled.
- * </p>
- *
- * <p>
- * <b> Usage example: </b>
- *
- * <pre>
- * class SampleNode extends Node {
- * 
- *     final BranchProfile errorProfile = BranchProfile.create();
- * 
- *     void execute(int value) {
- *         if (value == Integer.MAX_VALUE) {
- *             errorProfile.enter();
- *             throw new Error(&quot;Invalid input value&quot;)
- *         }
- *         return value;
- *     }
- * }
- * </pre>
- *
- * {@inheritDoc}
- *
- * @see BranchProfile#enter()
- */
-public abstract class BranchProfile extends Profile {
-
-    BranchProfile() {
-    }
-
-    /**
-     * Call when an unlikely branch is entered.
-     */
-    public abstract void enter();
-
-    /**
-     * @deprecated it is not reliable when profiling is turned off.
-     */
-    @Deprecated
-    public abstract boolean isVisited();
-
-    /**
-     * Call to create a new instance of a branch profile.
-     */
-    public static BranchProfile create() {
-        if (Truffle.getRuntime().isProfilingEnabled()) {
-            return Enabled.create0();
-        } else {
-            return Disabled.INSTANCE;
-        }
-    }
-
-    static final class Enabled extends BranchProfile {
-
-        @CompilationFinal private boolean visited;
-
-        @Override
-        public void enter() {
-            if (!visited) {
-                CompilerDirectives.transferToInterpreterAndInvalidate();
-                visited = true;
-            }
-        }
-
-        @SuppressWarnings("deprecation")
-        @Override
-        public boolean isVisited() {
-            return visited;
-        }
-
-        @Override
-        public String toString() {
-            return toString(BranchProfile.class, !visited, false, "VISITED");
-        }
-
-        /* Needed for lazy class loading. */
-        static BranchProfile create0() {
-            return new Enabled();
-        }
-    }
-
-    static final class Disabled extends BranchProfile {
-
-        static final BranchProfile INSTANCE = new Disabled();
-
-        @Override
-        protected Object clone() {
-            return INSTANCE;
-        }
-
-        @Override
-        public void enter() {
-        }
-
-        @SuppressWarnings("deprecation")
-        @Override
-        public boolean isVisited() {
-            return true;
-        }
-
-        @Override
-        public String toString() {
-            return toStringDisabled(BranchProfile.class);
-        }
-
-    }
-
-}
--- a/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/profiles/ByteValueProfile.java	Wed Dec 16 15:32:23 2015 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,158 +0,0 @@
-/*
- * Copyright (c) 2015, 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.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * 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.truffle.api.profiles;
-
-import com.oracle.truffle.api.CompilerDirectives;
-import com.oracle.truffle.api.CompilerDirectives.CompilationFinal;
-import com.oracle.truffle.api.Truffle;
-
-/**
- * <p>
- * Specialized value profile to capture certain properties of <code>byte</code> runtime values.
- * Value profiles require a runtime check in their initialized state to verify their profiled
- * assumption. Value profiles are limited to capture monomorphic profiles only. This means that if
- * two or more values are profiled within a single profile then the profile has no effect. If the
- * value assumption is invalidated in compiled code then it is invalidated.
- * </p>
- *
- * <p>
- * <b> Usage example: </b>
- *
- * <pre>
- * class SampleNode extends Node {
- *
- *     final ByteValueProfile profile = ByteValueProfile.createIdentityProfile();
- *
- *     byte execute(byte input) {
- *         byte profiledValue = profile.profile(input);
- *         // compiler may know now more about profiledValue
- *         return profiledValue;
- *     }
- * }
- * </pre>
- * <p>
- *
- *
- * {@inheritDoc}
- *
- * @see #createIdentityProfile()
- * @see ValueProfile
- */
-public abstract class ByteValueProfile extends Profile {
-
-    ByteValueProfile() {
-    }
-
-    public abstract byte profile(byte value);
-
-    /**
-     * Returns a value profile that profiles the exact value of a <code>byte</code>.
-     *
-     * @see ByteValueProfile
-     */
-    public static ByteValueProfile createIdentityProfile() {
-        if (Truffle.getRuntime().isProfilingEnabled()) {
-            return Enabled.create();
-        } else {
-            return Disabled.INSTANCE;
-        }
-    }
-
-    static final class Enabled extends ByteValueProfile {
-
-        private static final byte UNINITIALIZED = 0;
-        private static final byte SPECIALIZED = 1;
-        private static final byte GENERIC = 2;
-
-        @CompilationFinal private byte cachedValue;
-        @CompilationFinal private byte state = 0;
-
-        @Override
-        public byte profile(byte value) {
-            byte localState = this.state;
-            if (localState != GENERIC) {
-                if (localState == SPECIALIZED) {
-                    byte v = cachedValue;
-                    if (v == value) {
-                        return v;
-                    }
-                }
-                CompilerDirectives.transferToInterpreterAndInvalidate();
-                if (localState == UNINITIALIZED) {
-                    this.cachedValue = value;
-                    this.state = SPECIALIZED;
-                } else {
-                    this.state = GENERIC;
-                }
-            }
-            return value;
-        }
-
-        boolean isGeneric() {
-            return state == GENERIC;
-        }
-
-        boolean isUninitialized() {
-            return state == UNINITIALIZED;
-        }
-
-        byte getCachedValue() {
-            return cachedValue;
-        }
-
-        @Override
-        public String toString() {
-            return toString(ByteValueProfile.class, state == UNINITIALIZED, state == GENERIC, //
-                            String.format("value == (byte)%s", cachedValue));
-        }
-
-        /* Needed for lazy class loading. */
-        static ByteValueProfile create() {
-            return new Enabled();
-        }
-    }
-
-    static final class Disabled extends ByteValueProfile {
-
-        static final ByteValueProfile INSTANCE = new Disabled();
-
-        @Override
-        protected Object clone() {
-            return INSTANCE;
-        }
-
-        @Override
-        public byte profile(byte value) {
-            return value;
-        }
-
-        @Override
-        public String toString() {
-            return toStringDisabled(ByteValueProfile.class);
-        }
-
-    }
-
-}
--- a/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/profiles/ConditionProfile.java	Wed Dec 16 15:32:23 2015 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,242 +0,0 @@
-/*
- * Copyright (c) 2014, 2015, 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.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * 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.truffle.api.profiles;
-
-import com.oracle.truffle.api.CompilerDirectives;
-import com.oracle.truffle.api.CompilerDirectives.CompilationFinal;
-import com.oracle.truffle.api.Truffle;
-
-/**
- * <p>
- * ConditionProfiles are useful to profile the outcome of conditions.
- * </p>
- *
- * <p>
- * <b> Usage example: </b>
- *
- * <pre>
- * class AbsoluteNode extends Node {
- * 
- *     final ConditionProfile greaterZeroProfile = ConditionProfile.create{Binary,Counting}Profile();
- * 
- *     void execute(int value) {
- *         if (greaterZeroProfile.profile(value >= 0)) {
- *             return value;
- *         } else {
- *             return -value;
- *         }
- *     }
- * }
- * </pre>
- *
- * {@inheritDoc}
- *
- * @see #createBinaryProfile()
- * @see #createCountingProfile()
- * @see LoopConditionProfile
- */
-public abstract class ConditionProfile extends Profile {
-
-    ConditionProfile() {
-    }
-
-    public abstract boolean profile(boolean value);
-
-    /**
-     * Returns a {@link ConditionProfile} that speculates on conditions to be never
-     * <code>true</code> or to be never <code>false</code>. Additionally to a binary profile this
-     * method returns a condition profile that also counts the number of times the condition was
-     * true and false. This information is reported to the underlying optimization system using
-     * {@link CompilerDirectives#injectBranchProbability(double, boolean)}. Condition profiles are
-     * intended to be used as part of if conditions.
-     *
-     * @see ConditionProfile
-     * @see #createBinaryProfile()
-     */
-    public static ConditionProfile createCountingProfile() {
-        if (Truffle.getRuntime().isProfilingEnabled()) {
-            return Counting.create();
-        } else {
-            return Disabled.INSTANCE;
-        }
-    }
-
-    /**
-     * Returns a {@link ConditionProfile} that speculates on conditions to be never
-     * <code>true</code> or to be never <code>false</code>. Condition profiles are intended to be
-     * used as part of if conditions.
-     *
-     * @see ConditionProfile
-     * @see ConditionProfile#createCountingProfile()
-     */
-    public static ConditionProfile createBinaryProfile() {
-        if (Truffle.getRuntime().isProfilingEnabled()) {
-            return Binary.create();
-        } else {
-            return Disabled.INSTANCE;
-        }
-    }
-
-    static final class Disabled extends ConditionProfile {
-
-        static final ConditionProfile INSTANCE = new Disabled();
-
-        @Override
-        protected Object clone() {
-            return INSTANCE;
-        }
-
-        @Override
-        public boolean profile(boolean value) {
-            return value;
-        }
-
-        @Override
-        public String toString() {
-            return toStringDisabled(ConditionProfile.class);
-        }
-
-    }
-
-    static final class Counting extends ConditionProfile {
-
-        @CompilationFinal private int trueCount;
-        @CompilationFinal private int falseCount;
-
-        Counting() {
-            /* package protected constructor */
-        }
-
-        @Override
-        public boolean profile(boolean value) {
-            if (CompilerDirectives.inInterpreter()) {
-                if (value) {
-                    // local required to guarantee no overflow in multi-threaded environments
-                    int t = trueCount;
-                    if (t < Integer.MAX_VALUE) {
-                        trueCount = t + 1;
-                    }
-                } else {
-                    // local required to guarantee no overflow in multi-threaded environments
-                    int f = falseCount;
-                    if (f < Integer.MAX_VALUE) {
-                        falseCount = f + 1;
-                    }
-                }
-                // no branch probability calculation in the interpreter
-                return value;
-            } else {
-                // use trueCount and falseCount as locals for compilation speed
-                int t = trueCount;
-                int f = falseCount;
-                if (value) {
-                    if (t == 0) {
-                        CompilerDirectives.transferToInterpreterAndInvalidate();
-                        t = 1;
-                    }
-                } else {
-                    if (f == 0) {
-                        CompilerDirectives.transferToInterpreterAndInvalidate();
-                        f = 1;
-                    }
-                }
-                return CompilerDirectives.injectBranchProbability((double) t / (double) (t + f), value);
-            }
-        }
-
-        int getTrueCount() {
-            return trueCount;
-        }
-
-        int getFalseCount() {
-            return falseCount;
-        }
-
-        @Override
-        public String toString() {
-            int t = trueCount;
-            int f = falseCount;
-            return toString(ConditionProfile.class, trueCount == 0 && falseCount == 0, false, //
-                            String.format("trueProbability=%s (trueCount=%s, falseCount=%s)", (double) t / (double) (t + f), t, f));
-        }
-
-        /* Needed for lazy class loading. */
-        static ConditionProfile create() {
-            return new Counting();
-        }
-    }
-
-    /**
-     * Utility class to speculate on conditions to be never true or to be never false. Condition
-     * profiles are intended to be used as part of if conditions.
-     *
-     * @see ConditionProfile#createBinaryProfile()
-     */
-    static final class Binary extends ConditionProfile {
-
-        @CompilationFinal private boolean wasTrue;
-        @CompilationFinal private boolean wasFalse;
-
-        Binary() {
-            /* package protected constructor */
-        }
-
-        @Override
-        public boolean profile(boolean value) {
-            if (value) {
-                if (!wasTrue) {
-                    CompilerDirectives.transferToInterpreterAndInvalidate();
-                    wasTrue = true;
-                }
-                return true;
-            } else {
-                if (!wasFalse) {
-                    CompilerDirectives.transferToInterpreterAndInvalidate();
-                    wasFalse = true;
-                }
-                return false;
-            }
-        }
-
-        boolean wasTrue() {
-            return wasTrue;
-        }
-
-        boolean wasFalse() {
-            return wasFalse;
-        }
-
-        @Override
-        public String toString() {
-            return String.format("%s(wasTrue=%s, wasFalse=%s)@%x", getClass().getSimpleName(), wasTrue, wasFalse, hashCode());
-        }
-
-        /* Needed for lazy class loading. */
-        static ConditionProfile create() {
-            return new Binary();
-        }
-    }
-
-}
--- a/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/profiles/DoubleValueProfile.java	Wed Dec 16 15:32:23 2015 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,160 +0,0 @@
-/*
- * Copyright (c) 2015, 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.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * 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.truffle.api.profiles;
-
-import com.oracle.truffle.api.CompilerDirectives;
-import com.oracle.truffle.api.CompilerDirectives.CompilationFinal;
-import com.oracle.truffle.api.Truffle;
-
-/**
- * <p>
- * Specialized value profile to capture certain properties of <code>double</code> runtime values.
- * Value profiles require a runtime check in their initialized state to verify their profiled
- * assumption. Value profiles are limited to capture monomorphic profiles only. This means that if
- * two or more values are profiled within a single profile then the profile has no effect. If the
- * value assumption is invalidated in compiled code then it is invalidated.
- * </p>
- *
- * <p>
- * <b> Usage example: </b>
- *
- * <pre>
- * class SampleNode extends Node {
- *
- *     final DoubleValueProfile profile = DoubleValueProfile.createRawIdentityProfile();
- *
- *     double execute(double input) {
- *         double profiledValue = profile.profile(input);
- *         // compiler may know now more about profiledValue
- *         return profiledValue;
- *     }
- * }
- * </pre>
- * <p>
- *
- *
- * {@inheritDoc}
- *
- * @see #createRawIdentityProfile()
- * @see ValueProfile
- */
-public abstract class DoubleValueProfile extends Profile {
-
-    DoubleValueProfile() {
-    }
-
-    public abstract double profile(double value);
-
-    /**
-     * Returns a value profile that profiles the exact value of a <code>double</code> using
-     * {@link Double#doubleToRawLongBits(double)}.
-     *
-     * @see IntValueProfile
-     */
-    public static DoubleValueProfile createRawIdentityProfile() {
-        if (Truffle.getRuntime().isProfilingEnabled()) {
-            return Enabled.create();
-        } else {
-            return Disabled.INSTANCE;
-        }
-    }
-
-    static final class Enabled extends DoubleValueProfile {
-
-        private static final byte UNINITIALIZED = 0;
-        private static final byte SPECIALIZED = 1;
-        private static final byte GENERIC = 2;
-
-        @CompilationFinal private double cachedValue;
-        @CompilationFinal private long cachedRawValue;
-        @CompilationFinal private byte state = 0;
-
-        @Override
-        public double profile(double value) {
-            byte localState = this.state;
-            if (localState != GENERIC) {
-                if (localState == SPECIALIZED) {
-                    if (cachedRawValue == Double.doubleToRawLongBits(value)) {
-                        return cachedValue;
-                    }
-                }
-                CompilerDirectives.transferToInterpreterAndInvalidate();
-                if (localState == UNINITIALIZED) {
-                    this.cachedValue = value;
-                    this.cachedRawValue = Double.doubleToRawLongBits(value);
-                    this.state = SPECIALIZED;
-                } else {
-                    this.state = GENERIC;
-                }
-            }
-            return value;
-        }
-
-        boolean isGeneric() {
-            return state == GENERIC;
-        }
-
-        boolean isUninitialized() {
-            return state == UNINITIALIZED;
-        }
-
-        double getCachedValue() {
-            return cachedValue;
-        }
-
-        @Override
-        public String toString() {
-            return toString(DoubleValueProfile.class, state == UNINITIALIZED, state == GENERIC, //
-                            String.format("value == (double)%s (raw %h)", cachedValue, cachedRawValue));
-        }
-
-        /* Needed for lazy class loading. */
-        static DoubleValueProfile create() {
-            return new Enabled();
-        }
-    }
-
-    static final class Disabled extends DoubleValueProfile {
-
-        static final DoubleValueProfile INSTANCE = new Disabled();
-
-        @Override
-        protected Object clone() {
-            return INSTANCE;
-        }
-
-        @Override
-        public double profile(double value) {
-            return value;
-        }
-
-        @Override
-        public String toString() {
-            return toStringDisabled(DoubleValueProfile.class);
-        }
-
-    }
-
-}
--- a/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/profiles/FloatValueProfile.java	Wed Dec 16 15:32:23 2015 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,159 +0,0 @@
-/*
- * Copyright (c) 2015, 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.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * 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.truffle.api.profiles;
-
-import com.oracle.truffle.api.CompilerDirectives;
-import com.oracle.truffle.api.CompilerDirectives.CompilationFinal;
-import com.oracle.truffle.api.Truffle;
-
-/**
- * <p>
- * Specialized value profile to capture certain properties of <code>float</code> runtime values.
- * Value profiles require a runtime check in their initialized state to verify their profiled
- * assumption. Value profiles are limited to capture monomorphic profiles only. This means that if
- * two or more values are profiled within a single profile then the profile has no effect. If the
- * value assumption is invalidated in compiled code then it is invalidated.
- * </p>
- *
- * <p>
- * <b> Usage example: </b>
- *
- * <pre>
- * class SampleNode extends Node {
- * 
- *     final FloatValueProfile profile = FloatValueProfile.createRawIdentityProfile();
- * 
- *     float execute(float input) {
- *         float profiledValue = profile.profile(input);
- *         // compiler may know now more about profiledValue
- *         return profiledValue;
- *     }
- * }
- * </pre>
- * <p>
- *
- *
- * {@inheritDoc}
- *
- * @see #createRawIdentityProfile()
- * @see ValueProfile
- */
-public abstract class FloatValueProfile extends Profile {
-
-    FloatValueProfile() {
-    }
-
-    public abstract float profile(float value);
-
-    /**
-     * Returns a value profile that profiles the exact value of a <code>float</code> using
-     * {@link Float#floatToRawIntBits(float)}.
-     *
-     * @see IntValueProfile
-     */
-    public static FloatValueProfile createRawIdentityProfile() {
-        if (Truffle.getRuntime().isProfilingEnabled()) {
-            return Enabled.create();
-        } else {
-            return Disabled.INSTANCE;
-        }
-    }
-
-    static final class Enabled extends FloatValueProfile {
-
-        private static final byte UNINITIALIZED = 0;
-        private static final byte SPECIALIZED = 1;
-        private static final byte GENERIC = 2;
-
-        @CompilationFinal private float cachedValue;
-        @CompilationFinal private int cachedRawValue;
-        @CompilationFinal private byte state = 0;
-
-        @Override
-        public float profile(float value) {
-            byte localState = this.state;
-            if (localState != GENERIC) {
-                if (localState == SPECIALIZED) {
-                    if (cachedRawValue == Float.floatToRawIntBits(value)) {
-                        return cachedValue;
-                    }
-                }
-                CompilerDirectives.transferToInterpreterAndInvalidate();
-                if (localState == UNINITIALIZED) {
-                    this.cachedValue = value;
-                    this.cachedRawValue = Float.floatToRawIntBits(value);
-                    this.state = SPECIALIZED;
-                } else {
-                    this.state = GENERIC;
-                }
-            }
-            return value;
-        }
-
-        boolean isGeneric() {
-            return state == GENERIC;
-        }
-
-        boolean isUninitialized() {
-            return state == UNINITIALIZED;
-        }
-
-        float getCachedValue() {
-            return cachedValue;
-        }
-
-        @Override
-        public String toString() {
-            return toString(FloatValueProfile.class, state == UNINITIALIZED, state == GENERIC, //
-                            String.format("value == (float)%s (raw %h)", cachedValue, cachedRawValue));
-        }
-
-        /* Needed for lazy class loading. */
-        static FloatValueProfile create() {
-            return new Enabled();
-        }
-    }
-
-    static final class Disabled extends FloatValueProfile {
-
-        static final FloatValueProfile INSTANCE = new Disabled();
-
-        @Override
-        protected Object clone() {
-            return INSTANCE;
-        }
-
-        @Override
-        public float profile(float value) {
-            return value;
-        }
-
-        @Override
-        public String toString() {
-            return toStringDisabled(FloatValueProfile.class);
-        }
-
-    }
-}
--- a/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/profiles/IntValueProfile.java	Wed Dec 16 15:32:23 2015 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,158 +0,0 @@
-/*
- * Copyright (c) 2015, 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.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * 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.truffle.api.profiles;
-
-import com.oracle.truffle.api.CompilerDirectives;
-import com.oracle.truffle.api.CompilerDirectives.CompilationFinal;
-import com.oracle.truffle.api.Truffle;
-
-/**
- * <p>
- * Specialized value profile to capture certain properties of <code>int</code> runtime values. Value
- * profiles require a runtime check in their initialized state to verify their profiled assumption.
- * Value profiles are limited to capture monomorphic profiles only. This means that if two or more
- * values are profiled within a single profile then the profile has no effect. If the value
- * assumption is invalidated in compiled code then it is invalidated.
- * </p>
- *
- * <p>
- * <b> Usage example: </b>
- *
- * <pre>
- * class SampleNode extends Node {
- *
- *     final IntValueProfile profile = IntValueProfile.createIdentityProfile();
- *
- *     int execute(int input) {
- *         int profiledValue = profile.profile(input);
- *         // compiler may know now more about profiledValue
- *         return profiledValue;
- *     }
- * }
- * </pre>
- * <p>
- *
- *
- * {@inheritDoc}
- *
- * @see #createIdentityProfile()
- * @see ValueProfile
- */
-public abstract class IntValueProfile extends Profile {
-
-    IntValueProfile() {
-    }
-
-    public abstract int profile(int value);
-
-    /**
-     * Returns a value profile that profiles the exact value of an <code>int</code>.
-     *
-     * @see IntValueProfile
-     */
-    public static IntValueProfile createIdentityProfile() {
-        if (Truffle.getRuntime().isProfilingEnabled()) {
-            return Enabled.create();
-        } else {
-            return Disabled.INSTANCE;
-        }
-    }
-
-    static final class Enabled extends IntValueProfile {
-
-        private static final byte UNINITIALIZED = 0;
-        private static final byte SPECIALIZED = 1;
-        private static final byte GENERIC = 2;
-
-        @CompilationFinal private int cachedValue;
-        @CompilationFinal private byte state = 0;
-
-        @Override
-        public int profile(int value) {
-            byte localState = this.state;
-            if (localState != GENERIC) {
-                if (localState == SPECIALIZED) {
-                    int v = cachedValue;
-                    if (v == value) {
-                        return v;
-                    }
-                }
-                CompilerDirectives.transferToInterpreterAndInvalidate();
-                if (localState == UNINITIALIZED) {
-                    this.cachedValue = value;
-                    this.state = SPECIALIZED;
-                } else {
-                    this.state = GENERIC;
-                }
-            }
-            return value;
-        }
-
-        boolean isGeneric() {
-            return state == GENERIC;
-        }
-
-        boolean isUninitialized() {
-            return state == UNINITIALIZED;
-        }
-
-        int getCachedValue() {
-            return cachedValue;
-        }
-
-        @Override
-        public String toString() {
-            return toString(IntValueProfile.class, isUninitialized(), isGeneric(), //
-                            String.format("value == (int)%s", cachedValue));
-        }
-
-        /* Needed for lazy class loading. */
-        static IntValueProfile create() {
-            return new Enabled();
-        }
-    }
-
-    static final class Disabled extends IntValueProfile {
-
-        static final IntValueProfile INSTANCE = new Disabled();
-
-        @Override
-        protected Object clone() {
-            return INSTANCE;
-        }
-
-        @Override
-        public int profile(int value) {
-            return value;
-        }
-
-        @Override
-        public String toString() {
-            return toStringDisabled(IntValueProfile.class);
-        }
-
-    }
-
-}
--- a/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/profiles/LongValueProfile.java	Wed Dec 16 15:32:23 2015 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,156 +0,0 @@
-/*
- * Copyright (c) 2015, 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.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * 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.truffle.api.profiles;
-
-import com.oracle.truffle.api.CompilerDirectives;
-import com.oracle.truffle.api.CompilerDirectives.CompilationFinal;
-import com.oracle.truffle.api.Truffle;
-
-/**
- * <p>
- * Specialized value profile to capture certain properties of <code>long</code> runtime values.
- * Value profiles require a runtime check in their initialized state to verify their profiled
- * assumption. Value profiles are limited to capture monomorphic profiles only. This means that if
- * two or more values are profiled within a single profile then the profile has no effect. If the
- * value assumption is invalidated in compiled code then it is invalidated.
- * </p>
- *
- * <p>
- * <b> Usage example: </b>
- *
- * <pre>
- * class SampleNode extends Node {
- *
- *     final LongValueProfile profile = LongValueProfile.createIdentityProfile();
- *
- *     long execute(long input) {
- *         long profiledValue = profile.profile(input);
- *         // compiler may know now more about profiledValue
- *         return profiledValue;
- *     }
- * }
- * </pre>
- * <p>
- *
- * {@inheritDoc}
- *
- * @see #createIdentityProfile()
- * @see ValueProfile
- */
-public abstract class LongValueProfile extends Profile {
-
-    LongValueProfile() {
-    }
-
-    public abstract long profile(long value);
-
-    /**
-     * Returns a value profile that profiles the exact value of an <code>long</code>.
-     *
-     * @see LongValueProfile
-     */
-    public static LongValueProfile createIdentityProfile() {
-        if (Truffle.getRuntime().isProfilingEnabled()) {
-            return Enabled.create();
-        } else {
-            return Disabled.INSTANCE;
-        }
-    }
-
-    static final class Enabled extends LongValueProfile {
-
-        private static final byte UNINITIALIZED = 0;
-        private static final byte SPECIALIZED = 1;
-        private static final byte GENERIC = 2;
-
-        @CompilationFinal private long cachedValue;
-        @CompilationFinal private byte state = 0;
-
-        @Override
-        public long profile(long value) {
-            byte localState = this.state;
-            if (localState != GENERIC) {
-                if (localState == SPECIALIZED) {
-                    long v = cachedValue;
-                    if (v == value) {
-                        return v;
-                    }
-                }
-                CompilerDirectives.transferToInterpreterAndInvalidate();
-                if (localState == UNINITIALIZED) {
-                    this.cachedValue = value;
-                    this.state = SPECIALIZED;
-                } else {
-                    this.state = GENERIC;
-                }
-            }
-            return value;
-        }
-
-        boolean isGeneric() {
-            return state == GENERIC;
-        }
-
-        boolean isUninitialized() {
-            return state == UNINITIALIZED;
-        }
-
-        long getCachedValue() {
-            return cachedValue;
-        }
-
-        @Override
-        public String toString() {
-            return toString(LongValueProfile.class, state == UNINITIALIZED, state == GENERIC, //
-                            String.format("value == (long)%s", cachedValue));
-        }
-
-        /* Needed for lazy class loading. */
-        static LongValueProfile create() {
-            return new Enabled();
-        }
-    }
-
-    static final class Disabled extends LongValueProfile {
-
-        static final LongValueProfile INSTANCE = new Disabled();
-
-        @Override
-        protected Object clone() {
-            return INSTANCE;
-        }
-
-        @Override
-        public long profile(long value) {
-            return value;
-        }
-
-        @Override
-        public String toString() {
-            return toStringDisabled(LongValueProfile.class);
-        }
-
-    }
-}
--- a/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/profiles/LoopConditionProfile.java	Wed Dec 16 15:32:23 2015 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,251 +0,0 @@
-/*
- * Copyright (c) 2015, 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.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * 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.truffle.api.profiles;
-
-import com.oracle.truffle.api.CompilerDirectives;
-import com.oracle.truffle.api.CompilerDirectives.CompilationFinal;
-import com.oracle.truffle.api.Truffle;
-
-/**
- * <p>
- * LoopConditionProfiles are designed to profile the outcome of loop conditions. Loop profiles can
- * be used to profile unpredictable loops as well as predictable loops.
- * </p>
- *
- * <p>
- * <b> Arbitrary loop usage example: </b>
- *
- * <pre>
- * class LoopNode extends Node {
- * 
- *     final LoopConditionProfile loopProfile = LoopConditionProfile.createCountingProfile();
- * 
- *     void execute() {
- *         // loop count cannot be predicted
- *         while (loopProfile.profile(Math.random() &gt;= 0.9)) {
- *             // work
- *         }
- *     }
- * }
- * </pre>
- *
- * </p>
- *
- * <p>
- * <b> Counted loop usage example: </b>
- *
- * <pre>
- * class CountedLoopNode extends Node {
- * 
- *     final LoopConditionProfile loopProfile = LoopConditionProfile.createCountingProfile();
- * 
- *     void execute(int length) {
- *         // loop count can be predicted
- *         loopProfile.profileCounted(length);
- *         for (int i = 0; loopProfile.inject(i &lt; length); i++) {
- *             // work
- *         }
- *     }
- * }
- * </pre>
- *
- * </p>
- * <p>
- * The advantage of using {@link #profileCounted(long)} to using {@link #profile(boolean)} is that
- * it incurs less overhead in the interpreter. Using {@link LoopConditionProfile#inject(boolean)} is
- * a no-op in the interpreter while {@link #profile(boolean)} needs to use a counter for each
- * iteration.
- * </p>
- *
- *
- * {@inheritDoc}
- *
- * @see #createBinaryProfile()
- * @see #createCountingProfile()
- * @see LoopConditionProfile
- */
-public abstract class LoopConditionProfile extends ConditionProfile {
-
-    LoopConditionProfile() {
-    }
-
-    @Override
-    public abstract boolean profile(boolean value);
-
-    /**
-     * Provides an alternative way to profile counted loops with less interpreter footprint. Please
-     * see {@link LoopConditionProfile} for an usage example.
-     *
-     * @see #inject(boolean)
-     */
-    public abstract void profileCounted(long length);
-
-    /**
-     * Provides an alternative way to profile counted loops with less interpreter footprint. Please
-     * see {@link LoopConditionProfile} for an usage example.
-     *
-     * @see #inject(boolean)
-     */
-    public abstract boolean inject(boolean condition);
-
-    /**
-     * Returns a {@link LoopConditionProfile} that speculates on loop conditions to be never
-     * <code>true</code>. It also captures loop probabilities for the compiler. Loop condition
-     * profiles are intended to be used for loop conditions.
-     *
-     * @see LoopConditionProfile
-     */
-    public static LoopConditionProfile createCountingProfile() {
-        if (Truffle.getRuntime().isProfilingEnabled()) {
-            return Enabled.create();
-        } else {
-            return Disabled.INSTANCE;
-        }
-    }
-
-    static final class Enabled extends LoopConditionProfile {
-
-        @CompilationFinal private long trueCount; // long for long running loops.
-        @CompilationFinal private int falseCount;
-
-        @Override
-        public boolean profile(boolean condition) {
-            if (CompilerDirectives.inInterpreter()) {
-                if (condition) {
-                    // local required to guarantee no overflow in multi-threaded environments
-                    long localTrueCount = trueCount;
-                    if (localTrueCount < Long.MAX_VALUE) {
-                        trueCount = localTrueCount + 1;
-                    }
-                } else {
-                    // local required to guarantee no overflow in multi-threaded environments
-                    int localFalseCount = falseCount;
-                    if (localFalseCount < Integer.MAX_VALUE) {
-                        falseCount = localFalseCount + 1;
-                    }
-                }
-                // no branch probability calculation in the interpreter
-                return condition;
-            } else {
-                long trueCountLocal = trueCount;
-                int falseCountLocal = falseCount;
-                if (trueCountLocal == 0) {
-                    /* Deopt for never entering the loop. */
-                    if (condition) {
-                        CompilerDirectives.transferToInterpreterAndInvalidate();
-                        trueCount = trueCountLocal = 1;
-                    }
-                }
-                /* No deopt for not entering the loop. */
-                return CompilerDirectives.injectBranchProbability(calculateProbability(trueCountLocal, falseCountLocal), condition);
-            }
-        }
-
-        @Override
-        public void profileCounted(long length) {
-            if (CompilerDirectives.inInterpreter()) {
-                long trueCountLocal = trueCount + length;
-                if (trueCountLocal >= 0) { // don't write overflow values
-                    trueCount = trueCountLocal;
-                    int falseCountLocal = falseCount;
-                    if (falseCountLocal < Integer.MAX_VALUE) {
-                        falseCount = falseCountLocal + 1;
-                    }
-                }
-            }
-        }
-
-        @Override
-        public boolean inject(boolean condition) {
-            if (CompilerDirectives.inCompiledCode()) {
-                return CompilerDirectives.injectBranchProbability(calculateProbability(trueCount, falseCount), condition);
-            } else {
-                return condition;
-            }
-        }
-
-        private static double calculateProbability(long trueCountLocal, int falseCountLocal) {
-            if (falseCountLocal == 0 && trueCountLocal == 0) {
-                /* Avoid division by zero if profile was never used. */
-                return 0.0;
-            } else {
-                return (double) trueCountLocal / (double) (trueCountLocal + falseCountLocal);
-            }
-        }
-
-        /* for testing */
-        long getTrueCount() {
-            return trueCount;
-        }
-
-        /* for testing */
-        int getFalseCount() {
-            return falseCount;
-        }
-
-        @Override
-        public String toString() {
-            return toString(LoopConditionProfile.class, falseCount == 0, false, //
-                            String.format("trueProbability=%s (trueCount=%s, falseCount=%s)", calculateProbability(trueCount, falseCount), falseCount, trueCount));
-        }
-
-        /* Needed for lazy class loading. */
-        static LoopConditionProfile create() {
-            return new Enabled();
-        }
-
-    }
-
-    static final class Disabled extends LoopConditionProfile {
-
-        static final LoopConditionProfile INSTANCE = new Disabled();
-
-        @Override
-        protected Object clone() {
-            return INSTANCE;
-        }
-
-        @Override
-        public boolean profile(boolean condition) {
-            return condition;
-        }
-
-        @Override
-        public void profileCounted(long length) {
-        }
-
-        @Override
-        public boolean inject(boolean condition) {
-            return condition;
-        }
-
-        @Override
-        public String toString() {
-            return toStringDisabled(LoopConditionProfile.class);
-        }
-
-    }
-
-}
--- a/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/profiles/PrimitiveValueProfile.java	Wed Dec 16 15:32:23 2015 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,427 +0,0 @@
-/*
- * Copyright (c) 2014, 2015, 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.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * 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.truffle.api.profiles;
-
-import java.util.Objects;
-
-import com.oracle.truffle.api.CompilerDirectives;
-import com.oracle.truffle.api.CompilerDirectives.CompilationFinal;
-import com.oracle.truffle.api.Truffle;
-
-/**
- * <p>
- * Represents a {@link ValueProfile} that speculates on the primitive equality or object identity of
- * values. Note that for {@code float} and {@code double} values we compare primitive equality via
- * {@link Float#floatToRawIntBits} and {@link Double#doubleToRawLongBits}, so that for example
- * {@code -0.0} is not considered the same as {@code 0.0}, even though primitive equality would
- * normally say that it was.
- * </p>
- *
- * {@inheritDoc}
- */
-public abstract class PrimitiveValueProfile extends ValueProfile {
-
-    PrimitiveValueProfile() {
-    }
-
-    @Override
-    public abstract <T> T profile(T value);
-
-    public abstract byte profile(byte value);
-
-    public abstract short profile(short value);
-
-    public abstract int profile(int value);
-
-    public abstract long profile(long value);
-
-    public abstract float profile(float value);
-
-    public abstract double profile(double value);
-
-    public abstract boolean profile(boolean value);
-
-    public abstract char profile(char value);
-
-    /**
-     * Returns a {@link PrimitiveValueProfile} that speculates on the primitive equality or object
-     * identity of a value.
-     */
-    public static PrimitiveValueProfile createEqualityProfile() {
-        if (Truffle.getRuntime().isProfilingEnabled()) {
-            return Enabled.create();
-        } else {
-            return Disabled.INSTANCE;
-        }
-    }
-
-    /**
-     * @deprecated going to get removed without replacement
-     */
-    @Deprecated
-    public static boolean exactCompare(float a, float b) {
-        /*
-         * -0.0 == 0.0, but you can tell the difference through other means, so we need to
-         * differentiate.
-         */
-        return Float.floatToRawIntBits(a) == Float.floatToRawIntBits(b);
-    }
-
-    /**
-     * @deprecated going to get removed without replacement
-     */
-    @Deprecated
-    public static boolean exactCompare(double a, double b) {
-        /*
-         * -0.0 == 0.0, but you can tell the difference through other means, so we need to
-         * differentiate.
-         */
-        return Double.doubleToRawLongBits(a) == Double.doubleToRawLongBits(b);
-    }
-
-    static final class Enabled extends PrimitiveValueProfile {
-
-        private static final byte STATE_UNINITIALIZED = 0;
-        private static final byte STATE_BYTE = 1;
-        private static final byte STATE_SHORT = 2;
-        private static final byte STATE_INTEGER = 3;
-        private static final byte STATE_LONG = 4;
-        private static final byte STATE_BOOLEAN = 5;
-        private static final byte STATE_CHARACTER = 6;
-        private static final byte STATE_FLOAT = 7;
-        private static final byte STATE_DOUBLE = 8;
-        private static final byte STATE_IDENTITY = 9;
-        private static final byte STATE_GENERIC = 10;
-
-        @CompilationFinal private byte state = STATE_UNINITIALIZED;
-        @CompilationFinal private Object cachedValue;
-
-        Enabled() {
-        }
-
-        @SuppressWarnings("unchecked")
-        @Override
-        public <T> T profile(T value) {
-            byte s = this.state;
-            Object snapshot;
-            switch (s) {
-                case STATE_BYTE:
-                case STATE_SHORT:
-                case STATE_INTEGER:
-                case STATE_LONG:
-                case STATE_BOOLEAN:
-                case STATE_CHARACTER:
-                    snapshot = this.cachedValue;
-                    if (snapshot.equals(value)) {
-                        return (T) snapshot;
-                    }
-                    break;
-                case STATE_DOUBLE:
-                    snapshot = this.cachedValue;
-                    if (value instanceof Double && exactCompare((Double) snapshot, (Double) value)) {
-                        return (T) snapshot;
-                    }
-                    break;
-                case STATE_FLOAT:
-                    snapshot = this.cachedValue;
-                    if (value instanceof Float && exactCompare((Float) snapshot, (Float) value)) {
-                        return (T) snapshot;
-                    }
-                    break;
-                case STATE_IDENTITY:
-                    snapshot = this.cachedValue;
-                    if (snapshot == value) {
-                        return (T) snapshot;
-                    }
-                    break;
-                case STATE_GENERIC:
-                    return value;
-            }
-            CompilerDirectives.transferToInterpreterAndInvalidate();
-            slowpath(s, value);
-            return value;
-        }
-
-        @Override
-        public byte profile(byte value) {
-            byte s = this.state;
-            if (s != STATE_GENERIC) {
-                if (s == STATE_BYTE) {
-                    byte castCachedValue = (byte) this.cachedValue;
-                    if (castCachedValue == value) {
-                        return castCachedValue;
-                    }
-                }
-                CompilerDirectives.transferToInterpreterAndInvalidate();
-                slowpath(s, value);
-            }
-            return value;
-        }
-
-        @Override
-        public short profile(short value) {
-            byte s = this.state;
-            if (s != STATE_GENERIC) {
-                if (s == STATE_SHORT) {
-                    short castCachedValue = (short) this.cachedValue;
-                    if (castCachedValue == value) {
-                        return castCachedValue;
-                    }
-                }
-                CompilerDirectives.transferToInterpreterAndInvalidate();
-                slowpath(s, value);
-            }
-            return value;
-        }
-
-        @Override
-        public int profile(int value) {
-            byte s = this.state;
-            if (s != STATE_GENERIC) {
-                if (s == STATE_INTEGER) {
-                    int castCachedValue = (int) this.cachedValue;
-                    if (castCachedValue == value) {
-                        return castCachedValue;
-                    }
-                }
-                CompilerDirectives.transferToInterpreterAndInvalidate();
-                slowpath(s, value);
-            }
-            return value;
-        }
-
-        @Override
-        public long profile(long value) {
-            byte s = this.state;
-            if (s != STATE_GENERIC) {
-                if (s == STATE_LONG) {
-                    long castCachedValue = (long) this.cachedValue;
-                    if (castCachedValue == value) {
-                        return castCachedValue;
-                    }
-                }
-                CompilerDirectives.transferToInterpreterAndInvalidate();
-                slowpath(s, value);
-            }
-            return value;
-        }
-
-        @Override
-        public float profile(float value) {
-            byte s = this.state;
-            if (s != STATE_GENERIC) {
-                if (s == STATE_FLOAT) {
-                    float castCachedValue = (float) this.cachedValue;
-                    if (exactCompare(castCachedValue, value)) {
-                        return castCachedValue;
-                    }
-                }
-                CompilerDirectives.transferToInterpreterAndInvalidate();
-                slowpath(s, value);
-            }
-            return value;
-        }
-
-        @Override
-        public double profile(double value) {
-            byte s = this.state;
-            if (s != STATE_GENERIC) {
-                if (s == STATE_DOUBLE) {
-                    double castCachedValue = (double) this.cachedValue;
-                    if (exactCompare(castCachedValue, value)) {
-                        return castCachedValue;
-                    }
-                }
-                CompilerDirectives.transferToInterpreterAndInvalidate();
-                slowpath(s, value);
-            }
-            return value;
-
-        }
-
-        @Override
-        public boolean profile(boolean value) {
-            byte s = this.state;
-            if (s != STATE_GENERIC) {
-                if (s == STATE_BOOLEAN) {
-                    boolean castCachedValue = (boolean) this.cachedValue;
-                    if (castCachedValue == value) {
-                        return castCachedValue;
-                    }
-                }
-                CompilerDirectives.transferToInterpreterAndInvalidate();
-                slowpath(s, value);
-            }
-            return value;
-        }
-
-        @Override
-        public char profile(char value) {
-            byte s = this.state;
-            if (s != STATE_GENERIC) {
-                if (s == STATE_CHARACTER) {
-                    char castCachedValue = (char) this.cachedValue;
-                    if (castCachedValue == value) {
-                        return castCachedValue;
-                    }
-                }
-                CompilerDirectives.transferToInterpreterAndInvalidate();
-                slowpath(s, value);
-            }
-            return value;
-        }
-
-        private void slowpath(byte s, Object value) {
-            if (s == STATE_UNINITIALIZED) {
-                cachedValue = value;
-                state = specialize(value);
-            } else {
-                state = STATE_GENERIC;
-                cachedValue = null;
-            }
-        }
-
-        private static byte specialize(Object value) {
-            if (value instanceof Byte) {
-                return STATE_BYTE;
-            } else if (value instanceof Short) {
-                return STATE_SHORT;
-            } else if (value instanceof Integer) {
-                return STATE_INTEGER;
-            } else if (value instanceof Long) {
-                return STATE_LONG;
-            } else if (value instanceof Boolean) {
-                return STATE_BOOLEAN;
-            } else if (value instanceof Character) {
-                return STATE_CHARACTER;
-            } else if (value instanceof Double) {
-                return STATE_DOUBLE;
-            } else if (value instanceof Float) {
-                return STATE_FLOAT;
-            } else {
-                return STATE_IDENTITY;
-            }
-        }
-
-        boolean isGeneric() {
-            return state == STATE_GENERIC;
-        }
-
-        boolean isUninitialized() {
-            return state == STATE_UNINITIALIZED;
-        }
-
-        Object getCachedValue() {
-            return cachedValue;
-        }
-
-        @Override
-        public String toString() {
-            return toString(PrimitiveValueProfile.class, state == STATE_UNINITIALIZED, state == STATE_GENERIC, formatSpecialization());
-        }
-
-        private String formatSpecialization() {
-            Object snapshot = this.cachedValue;
-            if (state != STATE_UNINITIALIZED && state != STATE_GENERIC) {
-                if (snapshot == null) {
-                    return String.format("value == null");
-                } else {
-                    if (state == STATE_IDENTITY) {
-                        String simpleName = snapshot.getClass().getSimpleName();
-                        return String.format("value == %s@%x", simpleName, Objects.hash(snapshot));
-                    } else {
-                        return String.format("value == (%s)%s", snapshot.getClass().getSimpleName(), snapshot);
-                    }
-                }
-            }
-            return null;
-        }
-
-        /**
-         * Returns a {@link PrimitiveValueProfile} that speculates on the primitive equality or
-         * object identity of a value.
-         */
-        static PrimitiveValueProfile create() {
-            return new Enabled();
-        }
-    }
-
-    static final class Disabled extends PrimitiveValueProfile {
-
-        static final PrimitiveValueProfile INSTANCE = new Disabled();
-
-        @Override
-        public <T> T profile(T value) {
-            return value;
-        }
-
-        @Override
-        public byte profile(byte value) {
-            return value;
-        }
-
-        @Override
-        public short profile(short value) {
-            return value;
-        }
-
-        @Override
-        public int profile(int value) {
-            return value;
-        }
-
-        @Override
-        public long profile(long value) {
-            return value;
-        }
-
-        @Override
-        public float profile(float value) {
-            return value;
-        }
-
-        @Override
-        public double profile(double value) {
-            return value;
-        }
-
-        @Override
-        public boolean profile(boolean value) {
-            return value;
-        }
-
-        @Override
-        public char profile(char value) {
-            return value;
-        }
-
-        @Override
-        public String toString() {
-            return toStringDisabled(PrimitiveValueProfile.class);
-        }
-
-    }
-
-}
--- a/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/profiles/Profile.java	Wed Dec 16 15:32:23 2015 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,114 +0,0 @@
-/*
- * Copyright (c) 2015, 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.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * 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.truffle.api.profiles;
-
-import com.oracle.truffle.api.Assumption;
-import com.oracle.truffle.api.CompilerDirectives;
-import com.oracle.truffle.api.CompilerDirectives.CompilationFinal;
-import com.oracle.truffle.api.TruffleRuntime;
-import com.oracle.truffle.api.nodes.Node;
-import com.oracle.truffle.api.nodes.NodeCloneable;
-import com.oracle.truffle.api.nodes.RootNode;
-
-/**
- * <p>
- * A profile is a Truffle utility class that uses the {@link CompilerDirectives Truffle compiler
- * directives} to guard for and/or forward runtime information to the compiler.
- * </p>
- *
- * <p>
- * <b>Usage:</b> Profiles should be stored in <code>final</code> or {@link CompilationFinal
- * compilation final} fields of node classes to ensure that they can get optimized properly.
- * Profiles must not be shared between ASTs. Using the same profile multiple times in a single
- * {@link Node node} or in multiple {@link Node nodes} which {@link Node#getRootNode() link} to the
- * same {@link RootNode root} is allowed. <b>Never</b> store profiles inside runtime values that
- * leave the scope of the originating AST. This limitation exists because the used mechanism to
- * invalidate compiled code performs local invalidations only. For global speculations use
- * {@link Assumption assumptions} instead.
- * </p>
- *
- * <p>
- * <b>Compilation:</b> Some profiles like {@link BranchProfile branch} profiles do not induce
- * additional overhead in compiled code. Others like {@link ValueProfile value} profiles might
- * require a runtime check to verify their assumptions which are forwarded to the compiler. Even if
- * profiles do not induce direct overhead in compiled code it still might get invalidated as a
- * result of using profiles. Invalidating profiles will result in the invalidation of compiled code.
- * It is therefore essential to place these profiles in way that is neither too aggressive nor too
- * conservative.
- * </p>
- *
- * <p>
- * <b>Footprint:</b> Whether profiling information can be forwarded to the compiler depends on the
- * capabilities of the {@link TruffleRuntime runtime system}. If the runtime returns
- * <code>true</code> in {@link TruffleRuntime#isProfilingEnabled()} then runtime information will
- * get collected. This comes at at the cost of additional overhead and footprint in interpreted
- * mode. Thats why the factory methods of profiles can return implementations where profiling is
- * disabled. Using disabled profiles makes sense for runtimes that are unable to use the collected
- * profiling information. Even runtime implementations that are able to use this information might
- * decide to turn off profiling for benchmarking purposes.
- * </p>
- *
- * <p>
- * Profile subclasses:
- * <ul>
- * <li> {@link BranchProfile} to profile on unlikely branches like errors.</li>
- * <li> {@link ConditionProfile} to profile on conditionals or boolean values.</li>
- * <li> {@link LoopConditionProfile} to profile on conditionals of loops with special support for
- * counted loops.</li>
- * <li> {@link ValueProfile} to profile on properties like type and identity of values.</li>
- * <li> {@link ByteValueProfile} to profile on <code>byte</code> values.</li>
- * <li> {@link IntValueProfile} to profile on <code>int</code> values.</li>
- * <li> {@link LongValueProfile} to profile on <code>long</code> values.</li>
- * <li> {@link FloatValueProfile} to profile on <code>float</code> values.</li>
- * <li> {@link DoubleValueProfile} to profile on <code>double</code> values.</li>
- * <li> {@link PrimitiveValueProfile} to profile on objects by identity and on primitives by value.</li>
- * </ul>
- * </p>
- *
- * @see Assumption
- */
-public abstract class Profile extends NodeCloneable {
-
-    Profile() {
-        /* We don't to allow custom profiles. We want to evolve this API further first. Sorry. */
-    }
-
-    String toStringDisabled(Class<?> profileClass) {
-        return String.format("%s(DISABLED)", profileClass.getSimpleName());
-    }
-
-    String toString(Class<?> profileClass, boolean uninitialized, boolean generic, String specialization) {
-        String s;
-        if (uninitialized) {
-            s = "UNINITIALIZED";
-        } else if (generic) {
-            s = "GENERIC";
-        } else {
-            s = specialization == null ? "" : specialization;
-        }
-        return String.format("%s(%s)@%s", profileClass.getSimpleName(), s, Integer.toHexString(this.hashCode()));
-    }
-
-}
--- a/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/profiles/ValueProfile.java	Wed Dec 16 15:32:23 2015 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,334 +0,0 @@
-/*
- * Copyright (c) 2014, 2015, 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.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * 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.truffle.api.profiles;
-
-import java.util.Objects;
-
-import com.oracle.truffle.api.CompilerDirectives;
-import com.oracle.truffle.api.CompilerDirectives.CompilationFinal;
-import com.oracle.truffle.api.Truffle;
-
-/**
- * <p>
- * Specialized value profile to capture certain properties of <code>Object</code> runtime values.
- * Value profiles require a runtime check in their initialized state to verify their profiled
- * assumption. Value profiles are limited to capture monomorphic profiles only. This means that if
- * two or more identities or classes are profiles within a single profile then the profile has no
- * effect and no overhead after compilation. There are specialized versions of this profile with
- * less interpreter footprint for {@link ConditionProfile boolean}, {@link ByteValueProfile byte},
- * {@link IntValueProfile int}, {@link LongValueProfile long}, {@link FloatValueProfile float} and
- * {@link DoubleValueProfile double} values.
- * </p>
- *
- * <p>
- * <b> Usage example: </b>
- *
- * <pre>
- * class SampleNode extends Node {
- *
- * final ValueProfile profile = ValueProfile.create{Identity,Class}Profile();
- *
- *     Object execute(Object input) {
- *         Object profiledValue = profile.profile(input);
- *         // compiler may know now more about profiledValue
- *         return profieldValue;
- *     }
- * }
- * </pre>
- * <p>
- *
- *
- * {@inheritDoc}
- *
- * @see #createIdentityProfile()
- * @see #createClassProfile()
- */
-public abstract class ValueProfile extends Profile {
-
-    ValueProfile() {
-    }
-
-    public abstract <T> T profile(T value);
-
-    /**
-     * <p>
-     * Returns a value profile that profiles the exact class of a value. It will check the class of
-     * the profiled value and provide additional information to the compiler if only non-null values
-     * of exactly one concrete Java class are passed as a parameter to the
-     * {@link ValueProfile#profile} method. This can be beneficial if subsequent code can take
-     * advantage of knowing the concrete class of the value. The profile will degrade to the generic
-     * case if a null value or if at least two instances of two different Java classes are
-     * registered.
-     * </p>
-     *
-     * <p>
-     * <b>Compilation notes:</b> Value profiles require a runtime check in their initialized state
-     * to verify their profiled class. If two classes have been seen on a single profile instance
-     * then this profile will transition to a generic state with no overhead.
-     * </P>
-     *
-     * @see ValueProfile usage example
-     */
-    public static ValueProfile createClassProfile() {
-        if (Truffle.getRuntime().isProfilingEnabled()) {
-            return ExactClass.create();
-        } else {
-            return Disabled.INSTANCE;
-        }
-    }
-
-    /**
-     * <p>
-     * Returns a value profile that profiles the object identity of a value. A single instance can
-     * only profile one particular instance.
-     * </p>
-     *
-     * <p>
-     * <b>Compilation notes:</b> Identity profiles require a runtime check to verify their profiled
-     * object identity. If two identities have been seen on a single profile instance then this
-     * profile will transition to a generic state with no overhead.
-     * </p>
-     */
-    public static ValueProfile createIdentityProfile() {
-        if (Truffle.getRuntime().isProfilingEnabled()) {
-            return Identity.create();
-        } else {
-            return Disabled.INSTANCE;
-        }
-    }
-
-    /**
-     * <p>
-     * Returns a value profile that profiles the object equality of a value. A single instance can
-     * only profile one set of equal values.
-     * </p>
-     *
-     * <p>
-     * <b>Compilation notes:</b> Equality profiles inline the body of the equal method of the first
-     * profiled value in order to verify its assumption. Please take care that you do this only for
-     * equals implementations that your guest language actually has control over otherwise your
-     * compiled code might contain recursions or too much code. If two non equal objects have been
-     * seen on a single profile instance then this profile will transition to a generic state with
-     * no overhead.
-     * </p>
-     */
-    public static ValueProfile createEqualityProfile() {
-        if (Truffle.getRuntime().isProfilingEnabled()) {
-            return Equality.create();
-        } else {
-            return Disabled.INSTANCE;
-        }
-    }
-
-    static final class Disabled extends ValueProfile {
-
-        static final ValueProfile INSTANCE = new Disabled();
-
-        @Override
-        protected Object clone() {
-            return INSTANCE;
-        }
-
-        @Override
-        public <T> T profile(T value) {
-            return value;
-        }
-
-        @Override
-        public String toString() {
-            return toStringDisabled(ValueProfile.class);
-        }
-
-    }
-
-    static final class Equality extends ValueProfile {
-
-        private static final Object GENERIC = new Object();
-
-        @CompilationFinal protected Object cachedValue = null;
-
-        Equality() {
-        }
-
-        @Override
-        @SuppressWarnings("unchecked")
-        public <T> T profile(T newValue) {
-            // Field needs to be cached in local variable for thread safety and startup speed.
-            Object cached = this.cachedValue;
-            if (cached != GENERIC) {
-                if (cached != null && cached.equals(newValue)) {
-                    return (T) cached;
-                } else {
-                    CompilerDirectives.transferToInterpreterAndInvalidate();
-                    if (cached == null && newValue != null) {
-                        cachedValue = newValue;
-                    } else {
-                        cachedValue = GENERIC;
-                    }
-                }
-            }
-            return newValue;
-        }
-
-        public boolean isGeneric() {
-            return getCachedValue() == GENERIC;
-        }
-
-        public boolean isUninitialized() {
-            return getCachedValue() == null;
-        }
-
-        public Object getCachedValue() {
-            return cachedValue;
-        }
-
-        @Override
-        public String toString() {
-            return toString(ValueProfile.class, isUninitialized(), isGeneric(), //
-                            String.format("value == %s@%x", cachedValue != null ? cachedValue.getClass().getSimpleName() : "null", Objects.hash(cachedValue)));
-        }
-
-        /* Needed for lazy class loading. */
-        static ValueProfile create() {
-            return new Equality();
-        }
-
-    }
-
-    static final class Identity extends ValueProfile {
-
-        private static final Object UNINITIALIZED = new Object();
-        private static final Object GENERIC = new Object();
-
-        @CompilationFinal protected Object cachedValue = UNINITIALIZED;
-
-        Identity() {
-        }
-
-        @Override
-        @SuppressWarnings("unchecked")
-        public <T> T profile(T newValue) {
-            // Field needs to be cached in local variable for thread safety and startup speed.
-            Object cached = this.cachedValue;
-            if (cached != GENERIC) {
-                if (cached == newValue) {
-                    return (T) cached;
-                } else {
-                    CompilerDirectives.transferToInterpreterAndInvalidate();
-                    if (cachedValue == UNINITIALIZED) {
-                        cachedValue = newValue;
-                    } else {
-                        cachedValue = GENERIC;
-                    }
-                }
-            }
-            return newValue;
-        }
-
-        public boolean isGeneric() {
-            return getCachedValue() == GENERIC;
-        }
-
-        public boolean isUninitialized() {
-            return getCachedValue() == UNINITIALIZED;
-        }
-
-        public Object getCachedValue() {
-            return cachedValue;
-        }
-
-        @Override
-        public String toString() {
-            return toString(ValueProfile.class, isUninitialized(), isGeneric(), //
-                            String.format("value == %s@%x", cachedValue != null ? cachedValue.getClass().getSimpleName() : "null", Objects.hash(cachedValue)));
-        }
-
-        /* Needed for lazy class loading. */
-        static ValueProfile create() {
-            return new Identity();
-        }
-
-    }
-
-    static final class ExactClass extends ValueProfile {
-
-        @CompilationFinal protected Class<?> cachedClass;
-
-        ExactClass() {
-        }
-
-        public static ValueProfile create() {
-            return new ExactClass();
-        }
-
-        @SuppressWarnings("unchecked")
-        @Override
-        public <T> T profile(T value) {
-            // Field needs to be cached in local variable for thread safety and startup speed.
-            Class<?> clazz = cachedClass;
-            if (clazz != Object.class) {
-                if (clazz != null && value != null && clazz == value.getClass()) {
-                    /*
-                     * The cast is really only for the compiler relevant. It does not perform any
-                     * useful action in the interpreter and only takes time.
-                     */
-                    if (CompilerDirectives.inInterpreter()) {
-                        return value;
-                    } else {
-                        return (T) clazz.cast(value);
-                    }
-                } else {
-                    CompilerDirectives.transferToInterpreterAndInvalidate();
-                    if (clazz == null && value != null) {
-                        cachedClass = value.getClass();
-                    } else {
-                        cachedClass = Object.class;
-                    }
-                }
-            }
-            return value;
-        }
-
-        boolean isGeneric() {
-            return cachedClass == Object.class;
-        }
-
-        boolean isUninitialized() {
-            return cachedClass == null;
-        }
-
-        Class<?> getCachedClass() {
-            return cachedClass;
-        }
-
-        @Override
-        public String toString() {
-            return toString(ValueProfile.class, cachedClass == null, cachedClass == Object.class, //
-                            String.format("value.getClass() == %s.class", cachedClass != null ? cachedClass.getSimpleName() : "null"));
-        }
-
-    }
-
-}
--- a/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/profiles/package-info.java	Wed Dec 16 15:32:23 2015 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,39 +0,0 @@
-/*
- * Copyright (c) 2015, 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.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * 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.
- */
-
-/*
- @ApiInfo(
- group="Stable"
- )
- */
-/**
- * A profile is a Truffle utility class that uses the
- * {@link com.oracle.truffle.api.CompilerDirectives Truffle compiler directives} to guard for and/or
- * forward runtime information to the compiler.
- *
- * @see com.oracle.truffle.api.profiles.Profile
- */
-package com.oracle.truffle.api.profiles;
-