Merge
authorlana
Thu, 05 Mar 2015 15:22:39 -0800
changeset 29284 6270182c91f4
parent 29279 40ad2b7a63e1 (current diff)
parent 29283 fb47e4d25a9f (diff)
child 29285 878f417a684f
Merge
nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/RuntimeCallSite.java
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/samples/showenv.js	Thu Mar 05 15:22:39 2015 -0800
@@ -0,0 +1,82 @@
+#// Usage: jjs -fx showenv.js
+
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ *   - Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ *
+ *   - Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in the
+ *     documentation and/or other materials provided with the distribution.
+ *
+ *   - Neither the name of Oracle nor the names of its
+ *     contributors may be used to endorse or promote products derived
+ *     from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+ * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+if (!$OPTIONS._fx) {
+    print("Usage: jjs -fx showenv.js");
+    exit(1);
+}
+
+// This script displays environment entries as a HTML table.
+// Demonstrates heredoc to generate HTML content and display
+// using JavaFX WebView.
+
+// JavaFX classes used
+var Scene     = Java.type("javafx.scene.Scene");
+var WebView   = Java.type("javafx.scene.web.WebView");
+
+// JavaFX start method
+function start(stage) {
+    start.title = "Your Environment";
+    var wv = new WebView();
+    var envrows = "";
+    for (var i in $ENV) {
+        envrows += <<TBL
+<tr>
+<td>
+${i}
+</td>
+<td>
+${$ENV[i]}
+</td>
+</tr>
+TBL
+    }
+
+    wv.engine.loadContent(<<EOF
+<html>
+<head>
+<title>
+Your Environment
+</title>
+</head>
+<body>
+<h1>Your Environment</h1>
+<table border="1">
+${envrows}
+</table>
+</body>
+</html>
+EOF, "text/html");
+    stage.scene = new Scene(wv, 750, 500);
+    stage.show();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/samples/showsysprops.js	Thu Mar 05 15:22:39 2015 -0800
@@ -0,0 +1,84 @@
+#// Usage: jjs -fx showsysprops.js
+
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ *   - Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ *
+ *   - Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in the
+ *     documentation and/or other materials provided with the distribution.
+ *
+ *   - Neither the name of Oracle nor the names of its
+ *     contributors may be used to endorse or promote products derived
+ *     from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+ * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+if (!$OPTIONS._fx) {
+    print("Usage: jjs -fx showsysprops.js");
+    exit(1);
+}
+
+// This script displays System properties as a HTML table.
+// Demonstrates heredoc to generate HTML content and display
+// using JavaFX WebView.
+
+// JavaFX, Java classes used
+var Scene     = Java.type("javafx.scene.Scene");
+var System    = Java.type("java.lang.System");
+var WebView   = Java.type("javafx.scene.web.WebView");
+
+// JavaFX start method
+function start(stage) {
+    start.title = "Your System Properties";
+    var wv = new WebView();
+    var sysproprows = "";
+    var sysprops = System.properties;
+    for (var i in sysprops) {
+        sysproprows += <<TBL
+<tr>
+<td>
+${i}
+</td>
+<td>
+${sysprops[i]}
+</td>
+</tr>
+TBL
+    }
+
+    wv.engine.loadContent(<<EOF
+<html>
+<head>
+<title>
+Your System Properties
+</title>
+</head>
+<body>
+<h1>Your System Properties</h1>
+<table border="1">
+${sysproprows}
+</table>
+</body>
+</html>
+EOF, "text/html");
+    stage.scene = new Scene(wv, 750, 500);
+    stage.show();
+}
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/AssignSymbols.java	Thu Mar 05 11:26:22 2015 -0800
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/AssignSymbols.java	Thu Mar 05 15:22:39 2015 -0800
@@ -712,19 +712,8 @@
         return definingFn == function;
     }
 
-    private void checkConstAssignment(final IdentNode ident) {
-        // Check for reassignment of constant
-        final Symbol symbol = ident.getSymbol();
-        if (symbol.isConst()) {
-            throwParserException(ECMAErrors.getMessage("syntax.error.assign.constant", symbol.getName()), ident);
-        }
-    }
-
     @Override
     public Node leaveBinaryNode(final BinaryNode binaryNode) {
-        if (binaryNode.isAssignment() && binaryNode.lhs() instanceof IdentNode) {
-            checkConstAssignment((IdentNode) binaryNode.lhs());
-        }
         switch (binaryNode.tokenType()) {
         case ASSIGN:
             return leaveASSIGN(binaryNode);
@@ -751,9 +740,6 @@
 
     @Override
     public Node leaveUnaryNode(final UnaryNode unaryNode) {
-        if (unaryNode.isAssignment() && unaryNode.getExpression() instanceof IdentNode) {
-            checkConstAssignment((IdentNode) unaryNode.getExpression());
-        }
         switch (unaryNode.tokenType()) {
         case DELETE:
             return leaveDELETE(unaryNode);
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/BranchOptimizer.java	Thu Mar 05 11:26:22 2015 -0800
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/BranchOptimizer.java	Thu Mar 05 15:22:39 2015 -0800
@@ -105,33 +105,33 @@
 
         case EQ:
         case EQ_STRICT:
-            codegen.loadBinaryOperands(binaryNode);
+            codegen.loadComparisonOperands(binaryNode);
             method.conditionalJump(state ? EQ : NE, true, label);
             return;
 
         case NE:
         case NE_STRICT:
-            codegen.loadBinaryOperands(binaryNode);
+            codegen.loadComparisonOperands(binaryNode);
             method.conditionalJump(state ? NE : EQ, true, label);
             return;
 
         case GE:
-            codegen.loadBinaryOperands(binaryNode);
+            codegen.loadComparisonOperands(binaryNode);
             method.conditionalJump(state ? GE : LT, false, label);
             return;
 
         case GT:
-            codegen.loadBinaryOperands(binaryNode);
+            codegen.loadComparisonOperands(binaryNode);
             method.conditionalJump(state ? GT : LE, false, label);
             return;
 
         case LE:
-            codegen.loadBinaryOperands(binaryNode);
+            codegen.loadComparisonOperands(binaryNode);
             method.conditionalJump(state ? LE : GT, true, label);
             return;
 
         case LT:
-            codegen.loadBinaryOperands(binaryNode);
+            codegen.loadComparisonOperands(binaryNode);
             method.conditionalJump(state ? LT : GE, true, label);
             return;
 
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/CodeGenerator.java	Thu Mar 05 11:26:22 2015 -0800
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/CodeGenerator.java	Thu Mar 05 15:22:39 2015 -0800
@@ -202,6 +202,12 @@
     private static final Call CREATE_FUNCTION_OBJECT_NO_SCOPE = CompilerConstants.staticCallNoLookup(ScriptFunctionImpl.class,
             "create", ScriptFunction.class, Object[].class, int.class);
 
+    private static final Call TO_NUMBER_FOR_EQ = CompilerConstants.staticCallNoLookup(JSType.class,
+            "toNumberForEq", double.class, Object.class);
+    private static final Call TO_NUMBER_FOR_STRICT_EQ = CompilerConstants.staticCallNoLookup(JSType.class,
+            "toNumberForStrictEq", double.class, Object.class);
+
+
     private static final Class<?> ITERATOR_CLASS = Iterator.class;
     static {
         assert ITERATOR_CLASS == CompilerConstants.ITERATOR_PREFIX.type();
@@ -343,8 +349,14 @@
     // This is called the temporal dead zone (TDZ). See https://gist.github.com/rwaldron/f0807a758aa03bcdd58a
     private void checkTemporalDeadZone(final IdentNode identNode) {
         if (identNode.isDead()) {
-            method.load(identNode.getSymbol().getName());
-            method.invoke(ScriptRuntime.THROW_REFERENCE_ERROR);
+            method.load(identNode.getSymbol().getName()).invoke(ScriptRuntime.THROW_REFERENCE_ERROR);
+        }
+    }
+
+    // Runtime check for assignment to ES6 const
+    private void checkAssignTarget(final Expression expression) {
+        if (expression instanceof IdentNode && ((IdentNode)expression).getSymbol().isConst()) {
+            method.load(((IdentNode)expression).getSymbol().getName()).invoke(ScriptRuntime.THROW_CONST_TYPE_ERROR);
         }
     }
 
@@ -612,6 +624,104 @@
         return method;
     }
 
+    /**
+     * Similar to {@link #loadBinaryOperands(BinaryNode)} but used specifically for loading operands of
+     * relational and equality comparison operators where at least one argument is non-object. (When both
+     * arguments are objects, we use {@link ScriptRuntime#EQ(Object, Object)}, {@link ScriptRuntime#LT(Object, Object)}
+     * etc. methods instead. Additionally, {@code ScriptRuntime} methods are used for strict (in)equality comparison
+     * of a boolean to anything that isn't a boolean.) This method handles the special case where one argument
+     * is an object and another is a primitive. Naively, these could also be delegated to {@code ScriptRuntime} methods
+     * by boxing the primitive. However, in all such cases the comparison is performed on numeric values, so it is
+     * possible to strength-reduce the operation by taking the number value of the object argument instead and
+     * comparing that to the primitive value ("primitive" will always be int, long, double, or boolean, and booleans
+     * compare as ints in these cases, so they're essentially numbers too). This method will emit code for loading
+     * arguments for such strength-reduced comparison. When both arguments are primitives, it just delegates to
+     * {@link #loadBinaryOperands(BinaryNode)}.
+     *
+     * @param cmp the comparison operation for which the operands need to be loaded on stack.
+     * @return the current method emitter.
+     */
+    MethodEmitter loadComparisonOperands(final BinaryNode cmp) {
+        final Expression lhs = cmp.lhs();
+        final Expression rhs = cmp.rhs();
+        final Type lhsType = lhs.getType();
+        final Type rhsType = rhs.getType();
+
+        // Only used when not both are object, for that we have ScriptRuntime.LT etc.
+        assert !(lhsType.isObject() && rhsType.isObject());
+
+        if (lhsType.isObject() || rhsType.isObject()) {
+            // We can reorder CONVERT LEFT and LOAD RIGHT only if either the left is a primitive, or the right
+            // is a local. This is more strict than loadBinaryNode reorder criteria, as it can allow JS primitive
+            // types too (notably: String is a JS primitive, but not a JVM primitive). We disallow String otherwise
+            // we would prematurely convert it to number when comparing to an optimistic expression, e.g. in
+            // "Hello" === String("Hello") the RHS starts out as an optimistic-int function call. If we allowed
+            // reordering, we'd end up with ToNumber("Hello") === {I%}String("Hello") that is obviously incorrect.
+            final boolean canReorder = lhsType.isPrimitive() || rhs.isLocal();
+            // If reordering is allowed, and we're using a relational operator (that is, <, <=, >, >=) and not an
+            // (in)equality operator, then we encourage combining of LOAD and CONVERT into a single operation.
+            // This is because relational operators' semantics prescribes vanilla ToNumber() conversion, while
+            // (in)equality operators need the specialized JSType.toNumberFor[Strict]Equals. E.g. in the code snippet
+            // "i < obj.size" (where i is primitive and obj.size is statically an object), ".size" will thus be allowed
+            // to compile as:
+            //   invokedynamic dyn:getProp|getElem|getMethod:size(Object;)D
+            // instead of the more costly:
+            //   invokedynamic dyn:getProp|getElem|getMethod:size(Object;)Object
+            //   invokestatic JSType.toNumber(Object)D
+            // Note also that even if this is allowed, we're only using it on operands that are non-optimistic, as
+            // otherwise the logic for determining effective optimistic-ness would turn an optimistic double return
+            // into a freely coercible one, which would be wrong.
+            final boolean canCombineLoadAndConvert = canReorder && cmp.isRelational();
+
+            // LOAD LEFT
+            loadExpression(lhs, canCombineLoadAndConvert && !lhs.isOptimistic() ? TypeBounds.NUMBER : TypeBounds.UNBOUNDED);
+
+            final Type lhsLoadedType = method.peekType();
+            final TokenType tt = cmp.tokenType();
+            if (canReorder) {
+                // Can reorder CONVERT LEFT and LOAD RIGHT
+                emitObjectToNumberComparisonConversion(method, tt);
+                loadExpression(rhs, canCombineLoadAndConvert && !rhs.isOptimistic() ? TypeBounds.NUMBER : TypeBounds.UNBOUNDED);
+            } else {
+                // Can't reorder CONVERT LEFT and LOAD RIGHT
+                loadExpression(rhs, TypeBounds.UNBOUNDED);
+                if (lhsLoadedType != Type.NUMBER) {
+                    method.swap();
+                    emitObjectToNumberComparisonConversion(method, tt);
+                    method.swap();
+                }
+            }
+
+            // CONVERT RIGHT
+            emitObjectToNumberComparisonConversion(method, tt);
+            return method;
+        }
+        // For primitive operands, just don't do anything special.
+        return loadBinaryOperands(cmp);
+    }
+
+    private static void emitObjectToNumberComparisonConversion(final MethodEmitter method, final TokenType tt) {
+        switch(tt) {
+        case EQ:
+        case NE:
+            if (method.peekType().isObject()) {
+                TO_NUMBER_FOR_EQ.invoke(method);
+                return;
+            }
+            break;
+        case EQ_STRICT:
+        case NE_STRICT:
+            if (method.peekType().isObject()) {
+                TO_NUMBER_FOR_STRICT_EQ.invoke(method);
+                return;
+            }
+            break;
+        default:
+            break;
+        }
+        method.convert(Type.NUMBER);
+    }
+
     private static final Type undefinedToNumber(final Type type) {
         return type == Type.UNDEFINED ? Type.NUMBER : type;
     }
@@ -622,6 +732,7 @@
 
         static final TypeBounds UNBOUNDED = new TypeBounds(Type.UNKNOWN, Type.OBJECT);
         static final TypeBounds INT = exact(Type.INT);
+        static final TypeBounds NUMBER = exact(Type.NUMBER);
         static final TypeBounds OBJECT = exact(Type.OBJECT);
         static final TypeBounds BOOLEAN = exact(Type.BOOLEAN);
 
@@ -787,72 +898,84 @@
 
             @Override
             public boolean enterASSIGN(final BinaryNode binaryNode) {
+                checkAssignTarget(binaryNode.lhs());
                 loadASSIGN(binaryNode);
                 return false;
             }
 
             @Override
             public boolean enterASSIGN_ADD(final BinaryNode binaryNode) {
+                checkAssignTarget(binaryNode.lhs());
                 loadASSIGN_ADD(binaryNode);
                 return false;
             }
 
             @Override
             public boolean enterASSIGN_BIT_AND(final BinaryNode binaryNode) {
+                checkAssignTarget(binaryNode.lhs());
                 loadASSIGN_BIT_AND(binaryNode);
                 return false;
             }
 
             @Override
             public boolean enterASSIGN_BIT_OR(final BinaryNode binaryNode) {
+                checkAssignTarget(binaryNode.lhs());
                 loadASSIGN_BIT_OR(binaryNode);
                 return false;
             }
 
             @Override
             public boolean enterASSIGN_BIT_XOR(final BinaryNode binaryNode) {
+                checkAssignTarget(binaryNode.lhs());
                 loadASSIGN_BIT_XOR(binaryNode);
                 return false;
             }
 
             @Override
             public boolean enterASSIGN_DIV(final BinaryNode binaryNode) {
+                checkAssignTarget(binaryNode.lhs());
                 loadASSIGN_DIV(binaryNode);
                 return false;
             }
 
             @Override
             public boolean enterASSIGN_MOD(final BinaryNode binaryNode) {
+                checkAssignTarget(binaryNode.lhs());
                 loadASSIGN_MOD(binaryNode);
                 return false;
             }
 
             @Override
             public boolean enterASSIGN_MUL(final BinaryNode binaryNode) {
+                checkAssignTarget(binaryNode.lhs());
                 loadASSIGN_MUL(binaryNode);
                 return false;
             }
 
             @Override
             public boolean enterASSIGN_SAR(final BinaryNode binaryNode) {
+                checkAssignTarget(binaryNode.lhs());
                 loadASSIGN_SAR(binaryNode);
                 return false;
             }
 
             @Override
             public boolean enterASSIGN_SHL(final BinaryNode binaryNode) {
+                checkAssignTarget(binaryNode.lhs());
                 loadASSIGN_SHL(binaryNode);
                 return false;
             }
 
             @Override
             public boolean enterASSIGN_SHR(final BinaryNode binaryNode) {
+                checkAssignTarget(binaryNode.lhs());
                 loadASSIGN_SHR(binaryNode);
                 return false;
             }
 
             @Override
             public boolean enterASSIGN_SUB(final BinaryNode binaryNode) {
+                checkAssignTarget(binaryNode.lhs());
                 loadASSIGN_SUB(binaryNode);
                 return false;
             }
@@ -1062,6 +1185,7 @@
 
             @Override
             public boolean enterDECINC(final UnaryNode unaryNode) {
+                checkAssignTarget(unaryNode.getExpression());
                 loadDECINC(unaryNode);
                 return false;
             }
@@ -2737,25 +2861,18 @@
             newRuntimeNode = runtimeNode;
         }
 
-        new OptimisticOperation(newRuntimeNode, TypeBounds.UNBOUNDED) {
-            @Override
-            void loadStack() {
-                for (final Expression arg : args) {
-                    loadExpression(arg, TypeBounds.OBJECT);
-                }
-            }
-            @Override
-            void consumeStack() {
-                method.invokestatic(
-                        CompilerConstants.className(ScriptRuntime.class),
-                        newRuntimeNode.getRequest().toString(),
-                        new FunctionSignature(
-                            false,
-                            false,
-                            newRuntimeNode.getType(),
-                            args.size()).toString());
-            }
-        }.emit();
+        for (final Expression arg : args) {
+            loadExpression(arg, TypeBounds.OBJECT);
+        }
+
+        method.invokestatic(
+                CompilerConstants.className(ScriptRuntime.class),
+                newRuntimeNode.getRequest().toString(),
+                new FunctionSignature(
+                    false,
+                    false,
+                    newRuntimeNode.getType(),
+                    args.size()).toString());
 
         method.convert(newRuntimeNode.getType());
     }
@@ -3970,8 +4087,7 @@
     }
 
     private void loadCmp(final BinaryNode binaryNode, final Condition cond) {
-        assert comparisonOperandsArePrimitive(binaryNode) : binaryNode;
-        loadBinaryOperands(binaryNode);
+        loadComparisonOperands(binaryNode);
 
         final Label trueLabel  = new Label("trueLabel");
         final Label afterLabel = new Label("skip");
@@ -3985,11 +4101,6 @@
         method.label(afterLabel);
     }
 
-    private static boolean comparisonOperandsArePrimitive(final BinaryNode binaryNode) {
-        final Type widest = Type.widest(binaryNode.lhs().getType(), binaryNode.rhs().getType());
-        return widest.isNumeric() || widest.isBoolean();
-    }
-
     private void loadMOD(final BinaryNode binaryNode, final TypeBounds resultBounds) {
         new BinaryArith() {
             @Override
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/LocalVariableTypesCalculator.java	Thu Mar 05 11:26:22 2015 -0800
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/LocalVariableTypesCalculator.java	Thu Mar 05 15:22:39 2015 -0800
@@ -1359,8 +1359,6 @@
                     final Expression lhs = binaryNode.lhs();
                     final Expression rhs = binaryNode.rhs();
 
-                    Type cmpWidest = Type.widest(lhs.getType(), rhs.getType());
-                    boolean newRuntimeNode = false, finalized = false;
                     final TokenType tt = binaryNode.tokenType();
                     switch (tt) {
                     case EQ_STRICT:
@@ -1373,14 +1371,12 @@
                         }
                         // Specialize comparison of boolean with non-boolean
                         if (lhs.getType().isBoolean() != rhs.getType().isBoolean()) {
-                            newRuntimeNode = true;
-                            cmpWidest = Type.OBJECT;
-                            finalized = true;
+                            return new RuntimeNode(binaryNode);
                         }
                         // fallthrough
                     default:
-                        if (newRuntimeNode || cmpWidest.isObject()) {
-                            return new RuntimeNode(binaryNode).setIsFinal(finalized);
+                        if (lhs.getType().isObject() && rhs.getType().isObject()) {
+                            return new RuntimeNode(binaryNode);
                         }
                     }
                 } else if(binaryNode.isOptimisticUndecidedType()) {
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/MethodEmitter.java	Thu Mar 05 11:26:22 2015 -0800
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/MethodEmitter.java	Thu Mar 05 15:22:39 2015 -0800
@@ -94,7 +94,6 @@
 import jdk.nashorn.internal.ir.JoinPredecessor;
 import jdk.nashorn.internal.ir.LiteralNode;
 import jdk.nashorn.internal.ir.LocalVariableConversion;
-import jdk.nashorn.internal.ir.RuntimeNode;
 import jdk.nashorn.internal.ir.Symbol;
 import jdk.nashorn.internal.ir.TryNode;
 import jdk.nashorn.internal.objects.NativeArray;
@@ -174,9 +173,6 @@
     /** Bootstrap for normal indy:s */
     private static final Handle LINKERBOOTSTRAP  = new Handle(H_INVOKESTATIC, Bootstrap.BOOTSTRAP.className(), Bootstrap.BOOTSTRAP.name(), Bootstrap.BOOTSTRAP.descriptor());
 
-    /** Bootstrap for runtime node indy:s */
-    private static final Handle RUNTIMEBOOTSTRAP = new Handle(H_INVOKESTATIC, RuntimeCallSite.BOOTSTRAP.className(), RuntimeCallSite.BOOTSTRAP.name(), RuntimeCallSite.BOOTSTRAP.descriptor());
-
     /** Bootstrap for array populators */
     private static final Handle POPULATE_ARRAY_BOOTSTRAP = new Handle(H_INVOKESTATIC, RewriteException.BOOTSTRAP.className(), RewriteException.BOOTSTRAP.name(), RewriteException.BOOTSTRAP.descriptor());
 
@@ -2188,25 +2184,6 @@
     }
 
     /**
-     * Generate a dynamic call for a runtime node
-     *
-     * @param name       tag for the invoke dynamic for this runtime node
-     * @param returnType return type
-     * @param request    RuntimeNode request
-     *
-     * @return the method emitter
-     */
-    MethodEmitter dynamicRuntimeCall(final String name, final Type returnType, final RuntimeNode.Request request) {
-        debug("dynamic_runtime_call", name, "args=", request.getArity(), "returnType=", returnType);
-        final String signature = getDynamicSignature(returnType, request.getArity());
-        debug("   signature", signature);
-        method.visitInvokeDynamicInsn(name, signature, RUNTIMEBOOTSTRAP);
-        pushType(returnType);
-
-        return this;
-    }
-
-    /**
      * Generate dynamic getter. Pop scope from stack. Push result
      *
      * @param valueType type of the value to set
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/RuntimeCallSite.java	Thu Mar 05 11:26:22 2015 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,683 +0,0 @@
-/*
- * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  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 jdk.nashorn.internal.codegen;
-
-import static jdk.nashorn.internal.codegen.CompilerConstants.staticCallNoLookup;
-import static jdk.nashorn.internal.codegen.types.Type.BOOLEAN;
-import static jdk.nashorn.internal.codegen.types.Type.INT;
-import static jdk.nashorn.internal.lookup.Lookup.MH;
-
-import java.lang.invoke.CallSite;
-import java.lang.invoke.MethodHandle;
-import java.lang.invoke.MethodHandles;
-import java.lang.invoke.MethodType;
-import java.lang.invoke.MutableCallSite;
-import java.util.HashMap;
-import java.util.Map;
-import jdk.nashorn.internal.codegen.CompilerConstants.Call;
-import jdk.nashorn.internal.codegen.types.Type;
-import jdk.nashorn.internal.ir.RuntimeNode;
-import jdk.nashorn.internal.ir.RuntimeNode.Request;
-import jdk.nashorn.internal.lookup.Lookup;
-import jdk.nashorn.internal.runtime.ScriptRuntime;
-import jdk.nashorn.internal.runtime.linker.Bootstrap;
-
-/**
- * Optimistic call site that assumes its Object arguments to be of a boxed type.
- * Gradually reverts to wider boxed types if the assumption for the RuntimeNode
- * is proven wrong. Finally reverts to the generic ScriptRuntime method.
- *
- * This is used from the CodeGenerator when we have a runtime node, but 1 or more
- * primitive arguments. This class generated appropriate specializations, for example
- * {@code Object a === int b} is a good idea to specialize to {@code ((Integer)a).intValue() == b}
- * surrounded by catch blocks that will try less narrow specializations
- */
-public final class RuntimeCallSite extends MutableCallSite {
-    static final Call BOOTSTRAP = staticCallNoLookup(Bootstrap.class, "runtimeBootstrap", CallSite.class, MethodHandles.Lookup.class, String.class, MethodType.class);
-
-    private static final MethodHandle NEXT = findOwnMH_V("next",  MethodHandle.class, String.class);
-
-    private final RuntimeNode.Request request;
-
-    /**
-     * A specialized runtime node, i.e. on where we know at least one more specific type than object
-     */
-    static final class SpecializedRuntimeNode {
-        private static final char REQUEST_SEPARATOR = ':';
-
-        private final RuntimeNode.Request request;
-
-        private final Type[] parameterTypes;
-
-        private final Type   returnType;
-
-        /**
-         * Constructor.
-         *
-         * @param request        runtime node request to specialize
-         * @param parameterTypes parameter types of the call site
-         * @param returnType     return type of the call site
-         */
-        SpecializedRuntimeNode(final RuntimeNode.Request request, final Type[] parameterTypes, final Type returnType) {
-            this.request        = request;
-            this.parameterTypes = parameterTypes;
-            this.returnType     = returnType;
-        }
-
-        /**
-         * The first type to try to use for this generated runtime node
-         *
-         * @return a type
-         */
-        public Type firstTypeGuess() {
-            Type widest = Type.UNKNOWN;
-            for (final Type type : parameterTypes) {
-                if (type.isObject()) {
-                    continue;
-                }
-                widest = Type.widest(type, widest);
-            }
-            widest = Type.widest(widest, firstTypeGuessForObject(request));
-
-            return widest;
-        }
-
-        private static Type firstTypeGuessForObject(final Request request) {
-            switch (request) {
-            case ADD:
-                return INT;
-            default:
-                return BOOLEAN;
-            }
-        }
-
-        Request getRequest() {
-            return request;
-        }
-
-        Type[] getParameterTypes() {
-            return parameterTypes;
-        }
-
-        Type getReturnType() {
-            return returnType;
-        }
-
-        private static char descFor(final Type type) {
-            if (type.isObject()) {
-                return 'O';
-            }
-            return type.getDescriptor().charAt(0);
-        }
-
-        @Override
-        public boolean equals(final Object other) {
-            if (other instanceof SpecializedRuntimeNode) {
-                final SpecializedRuntimeNode otherNode = (SpecializedRuntimeNode)other;
-
-                if (!otherNode.getReturnType().equals(getReturnType())) {
-                    return false;
-                }
-
-                if (getParameterTypes().length != otherNode.getParameterTypes().length) {
-                    return false;
-                }
-
-                for (int i = 0; i < getParameterTypes().length; i++) {
-                    if (!Type.areEquivalent(getParameterTypes()[i], otherNode.getParameterTypes()[i])) {
-                        return false;
-                    }
-                }
-
-                return otherNode.getRequest().equals(getRequest());
-            }
-
-            return false;
-        }
-
-        @Override
-        public int hashCode() {
-            int hashCode = getRequest().toString().hashCode();
-            hashCode ^= getReturnType().hashCode();
-            for (final Type type : getParameterTypes()) {
-                hashCode ^= type.hashCode();
-            }
-            return hashCode;
-        }
-
-        @Override
-        public String toString() {
-            final StringBuilder sb = new StringBuilder();
-            sb.append(getRequest().toString());
-            sb.append(REQUEST_SEPARATOR);
-            sb.append(descFor(getReturnType()));
-
-            for (final Type type : getParameterTypes()) {
-                sb.append(descFor(type));
-            }
-
-            return sb.toString();
-        }
-
-        String getName(final Type extraType) {
-            return toString() + "_" + descFor(extraType);
-        }
-
-        String getInitialName() {
-            return getName(firstTypeGuess());
-        }
-    }
-
-
-    /**
-     * Constructor
-     *
-     * @param type method type for call site
-     * @param name name of runtime call
-     */
-    public RuntimeCallSite(final MethodType type, final String name) {
-        super(type);
-        this.request = Request.valueOf(name.substring(0, name.indexOf(SpecializedRuntimeNode.REQUEST_SEPARATOR)));
-        setTarget(makeMethod(name));
-    }
-
-    private String nextName(final String requestName) {
-        if (requestName.equals(request.toString())) {
-            return null;
-        }
-
-        final char[] c = requestName.toCharArray();
-        final int last = c.length - 1;
-
-        if (c[last - 1] != '_') {
-            return null;
-        }
-
-        switch (c[last]) {
-        case 'Z':
-            c[last] = 'I';
-            break;
-        case 'I':
-            c[last] = 'J';
-            break;
-        case 'J':
-            c[last] = 'D';
-            break;
-        case 'D':
-        default:
-            return request.toString();
-        }
-
-        return new String(c);
-    }
-
-    private boolean isSpecialized(final String requestName) {
-        return nextName(requestName) != null;
-    }
-
-    private MethodHandle makeMethod(final String requestName) {
-        MethodHandle mh;
-
-        if (isSpecialized(requestName)) {
-            final Class<?> boxedType;
-            final Class<?> primitiveType;
-
-            switch (requestName.charAt(requestName.length() - 1)) {
-            case 'Z':
-                boxedType = Boolean.class;
-                primitiveType = int.class;
-                break;
-            case 'I':
-                boxedType = Integer.class;
-                primitiveType = int.class;
-                break;
-            case 'J':
-                boxedType = Long.class;
-                primitiveType = long.class;
-                break;
-            case 'D':
-                boxedType = Number.class;
-                primitiveType = double.class;
-                break;
-            default:
-                throw new RuntimeException("should not reach here");
-            }
-
-            final boolean isStrictCmp = (request == Request.EQ_STRICT || request == Request.NE_STRICT);
-
-            if (isStrictCmp &&
-                    (boxedType != Boolean.class &&
-                        (type().parameterType(0) == boolean.class ||
-                         type().parameterType(1) == boolean.class))) {
-                // number and boolean are never strictly equal, e.g. 0 !== false
-                mh = MH.dropArguments(MH.constant(boolean.class, request == Request.NE_STRICT), 0, type().parameterArray());
-            } else {
-                mh = METHODS.get(request.nonStrictName() + primitiveType.getSimpleName());
-                // unbox objects
-
-                for (int i = 0; i < type().parameterCount(); i++) {
-                    if (!type().parameterType(i).isPrimitive()) {
-                        mh = MH.filterArguments(mh, i, UNBOX.get(boxedType));
-                    }
-                }
-
-                mh = Lookup.filterReturnType(mh, type().returnType());
-                mh = MH.explicitCastArguments(mh, type());
-            }
-
-            final MethodHandle fallback = MH.foldArguments(MethodHandles.exactInvoker(type()), MH.insertArguments(NEXT, 0, this, requestName));
-
-            MethodHandle guard;
-            if (type().parameterType(0).isPrimitive()) {
-                guard = MH.insertArguments(
-                            MH.dropArguments(CHECKCAST, 1, type().parameterType(0)), 0, boxedType);
-            } else if (type().parameterType(1).isPrimitive()) {
-                guard = MH.insertArguments(
-                            MH.dropArguments(CHECKCAST, 2, type().parameterType(1)), 0, boxedType);
-            } else {
-                assert !type().parameterType(0).isPrimitive() && !type().parameterType(1).isPrimitive();
-                guard = MH.insertArguments(CHECKCAST2, 0, boxedType);
-            }
-
-            if (request == Request.ADD && boxedType == Integer.class) {
-                // int add needs additional overflow check
-                MethodHandle addcheck = ADDCHECK;
-                for (int i = 0; i < type().parameterCount(); i++) {
-                    if (!type().parameterType(i).isPrimitive()) {
-                        addcheck = MH.filterArguments(addcheck, i, UNBOX.get(boxedType));
-                    }
-                }
-                addcheck = MH.explicitCastArguments(addcheck, type().changeReturnType(boolean.class));
-                guard    = MH.guardWithTest(upcastGuard(guard), addcheck,
-                                MH.dropArguments(MH.constant(boolean.class, false), 0, type().parameterArray()));
-            }
-
-            return MH.guardWithTest(upcastGuard(guard), mh, fallback);
-        }
-
-        // generic fallback
-        return MH.explicitCastArguments(Lookup.filterReturnType(GENERIC_METHODS.get(request.name()), type().returnType()), type());
-    }
-
-    private MethodHandle upcastGuard(final MethodHandle guard) {
-        return MH.asType(guard, type().changeReturnType(boolean.class));
-    }
-
-    /**
-     * This is public just so that the generated specialization code can
-     * use it to get the next wider typed method
-     *
-     * Do not call directly
-     *
-     * @param name current name (with type) of runtime call at the call site
-     * @return next wider specialization method for this RuntimeCallSite
-     */
-   public MethodHandle next(final String name) {
-        final MethodHandle next = makeMethod(nextName(name));
-        setTarget(next);
-        return next;
-    }
-
-    /** Method cache */
-    private static final Map<String, MethodHandle> METHODS;
-
-    /** Generic method cache */
-    private static final Map<String, MethodHandle> GENERIC_METHODS;
-
-    /** Unbox cache */
-    private static final Map<Class<?>, MethodHandle> UNBOX;
-
-    private static final MethodHandle CHECKCAST  = findOwnMH_S("checkcast", boolean.class, Class.class, Object.class);
-    private static final MethodHandle CHECKCAST2 = findOwnMH_S("checkcast", boolean.class, Class.class, Object.class, Object.class);
-    private static final MethodHandle ADDCHECK   = findOwnMH_S("ADDcheck",  boolean.class, int.class, int.class);
-
-    /**
-     * Build maps of correct boxing operations
-     */
-    static {
-        UNBOX = new HashMap<>();
-        UNBOX.put(Boolean.class, findOwnMH_S("unboxZ", int.class, Object.class));
-        UNBOX.put(Integer.class, findOwnMH_S("unboxI", int.class, Object.class));
-        UNBOX.put(Long.class,    findOwnMH_S("unboxJ", long.class, Object.class));
-        UNBOX.put(Number.class,  findOwnMH_S("unboxD", double.class, Object.class));
-
-        METHODS = new HashMap<>();
-
-        for (final Request req : Request.values()) {
-            if (req.canSpecialize()) {
-                if (req.name().endsWith("_STRICT")) {
-                    continue;
-                }
-
-                final boolean isCmp = Request.isComparison(req);
-
-                METHODS.put(req.name() + "int",    findOwnMH_S(req.name(), (isCmp ? boolean.class : int.class),  int.class, int.class));
-                METHODS.put(req.name() + "long",   findOwnMH_S(req.name(), (isCmp ? boolean.class : long.class), long.class, long.class));
-                METHODS.put(req.name() + "double", findOwnMH_S(req.name(), (isCmp ? boolean.class : double.class), double.class, double.class));
-            }
-        }
-
-        GENERIC_METHODS = new HashMap<>();
-        for (final Request req : Request.values()) {
-            if (req.canSpecialize()) {
-                GENERIC_METHODS.put(req.name(), MH.findStatic(MethodHandles.lookup(), ScriptRuntime.class, req.name(),
-                        MH.type(req.getReturnType().getTypeClass(), Object.class, Object.class)));
-            }
-        }
-    }
-
-    /**
-     * Specialized version of != operator for two int arguments. Do not call directly.
-     * @param a int
-     * @param b int
-     * @return a != b
-     */
-    public static boolean NE(final int a, final int b) {
-        return a != b;
-    }
-
-    /**
-     * Specialized version of != operator for two double arguments. Do not call directly.
-     * @param a double
-     * @param b double
-     * @return a != b
-     */
-    public static boolean NE(final double a, final double b) {
-        return a != b;
-    }
-
-    /**
-     * Specialized version of != operator for two long arguments. Do not call directly.
-     * @param a long
-     * @param b long
-     * @return a != b
-     */
-    public static boolean NE(final long a, final long b) {
-        return a != b;
-    }
-
-    /**
-     * Specialized version of == operator for two int arguments. Do not call directly.
-     * @param a int
-     * @param b int
-     * @return a == b
-     */
-    public static boolean EQ(final int a, final int b) {
-        return a == b;
-    }
-
-    /**
-     * Specialized version of == operator for two double arguments. Do not call directly.
-     * @param a double
-     * @param b double
-     * @return a == b
-     */
-    public static boolean EQ(final double a, final double b) {
-        return a == b;
-    }
-
-    /**
-     * Specialized version of == operator for two long arguments. Do not call directly.
-     * @param a long
-     * @param b long
-     * @return a == b
-     */
-    public static boolean EQ(final long a, final long b) {
-        return a == b;
-    }
-
-    /**
-     * Specialized version of {@literal <} operator for two int arguments. Do not call directly.
-     * @param a int
-     * @param b int
-     * @return a {@code <} b
-     */
-    public static boolean LT(final int a, final int b) {
-        return a < b;
-    }
-
-    /**
-     * Specialized version of {@literal <} operator for two double arguments. Do not call directly.
-     * @param a double
-     * @param b double
-     * @return a {@literal <} b
-     */
-    public static boolean LT(final double a, final double b) {
-        return a < b;
-    }
-
-    /**
-     * Specialized version of {@literal <} operator for two long arguments. Do not call directly.
-     * @param a long
-     * @param b long
-     * @return a {@literal <} b
-     */
-    public static boolean LT(final long a, final long b) {
-        return a < b;
-    }
-
-    /**
-     * Specialized version of {@literal <=} operator for two int arguments. Do not call directly.
-     * @param a int
-     * @param b int
-     * @return a {@literal <=} b
-     */
-    public static boolean LE(final int a, final int b) {
-        return a <= b;
-    }
-
-    /**
-     * Specialized version of {@literal <=} operator for two double arguments. Do not call directly.
-     * @param a double
-     * @param b double
-     * @return a {@literal <=} b
-     */
-    public static boolean LE(final double a, final double b) {
-        return a <= b;
-    }
-
-    /**
-     * Specialized version of {@literal <=} operator for two long arguments. Do not call directly.
-     * @param a long
-     * @param b long
-     * @return a {@literal <=} b
-     */
-    public static boolean LE(final long a, final long b) {
-        return a <= b;
-    }
-
-    /**
-     * Specialized version of {@literal >} operator for two int arguments. Do not call directly.
-     * @param a int
-     * @param b int
-     * @return a {@literal >} b
-     */
-    public static boolean GT(final int a, final int b) {
-        return a > b;
-    }
-
-    /**
-     * Specialized version of {@literal >} operator for two double arguments. Do not call directly.
-     * @param a double
-     * @param b double
-     * @return a {@literal >} b
-     */
-    public static boolean GT(final double a, final double b) {
-        return a > b;
-    }
-
-    /**
-     * Specialized version of {@literal >} operator for two long arguments. Do not call directly.
-     * @param a long
-     * @param b long
-     * @return a {@literal >} b
-     */
-    public static boolean GT(final long a, final long b) {
-        return a > b;
-    }
-
-    /**
-     * Specialized version of {@literal >=} operator for two int arguments. Do not call directly.
-     * @param a int
-     * @param b int
-     * @return a {@literal >=} b
-     */
-    public static boolean GE(final int a, final int b) {
-        return a >= b;
-    }
-
-    /**
-     * Specialized version of {@literal >=} operator for two double arguments. Do not call directly.
-     * @param a double
-     * @param b double
-     * @return a {@literal >=} b
-     */
-    public static boolean GE(final double a, final double b) {
-        return a >= b;
-    }
-
-    /**
-     * Specialized version of {@literal >=} operator for two long arguments. Do not call directly.
-     * @param a long
-     * @param b long
-     * @return a {@code >=} b
-     */
-    public static boolean GE(final long a, final long b) {
-        return a >= b;
-    }
-
-    /**
-     * Specialized version of + operator for two int arguments. Do not call directly.
-     * @param a int
-     * @param b int
-     * @return a + b
-     */
-    public static int ADD(final int a, final int b) {
-        return a + b;
-    }
-
-    /**
-     * Specialized version of + operator for two long arguments. Do not call directly.
-     * @param a long
-     * @param b long
-     * @return a + b
-     */
-    public static long ADD(final long a, final long b) {
-        return a + b;
-    }
-
-    /**
-     * Specialized version of + operator for two double arguments. Do not call directly.
-     * @param a double
-     * @param b double
-     * @return a + b
-     */
-    public static double ADD(final double a, final double b) {
-        return a + b;
-    }
-
-    /**
-     * Check that ints are addition compatible, i.e. their sum is equal to the sum
-     * of them cast to long. Otherwise the addition will overflow. Do not call directly.
-     *
-     * @param a int
-     * @param b int
-     *
-     * @return true if addition does not overflow
-     */
-    public static boolean ADDcheck(final int a, final int b) {
-        return (a + b == (long)a + (long)b);
-    }
-
-    /**
-     * Checkcast used for specialized ops. Do not call directly
-     *
-     * @param type to to check against
-     * @param obj  object to check for type
-     *
-     * @return true if type check holds
-     */
-    public static boolean checkcast(final Class<?> type, final Object obj) {
-        return type.isInstance(obj);
-    }
-
-    /**
-     * Checkcast used for specialized ops. Do not call directly
-     *
-     * @param type type to check against
-     * @param objA first object to check against type
-     * @param objB second object to check against type
-     *
-     * @return true if type check holds for both objects
-     */
-    public static boolean checkcast(final Class<?> type, final Object objA, final Object objB) {
-        return type.isInstance(objA) && type.isInstance(objB);
-    }
-
-    /**
-     * Unbox a java.lang.Boolean. Do not call directly
-     * @param obj object to cast to int and unbox
-     * @return an int value for the boolean, 1 is true, 0 is false
-     */
-    public static int unboxZ(final Object obj) {
-        return (boolean)obj ? 1 : 0;
-    }
-
-    /**
-     * Unbox a java.lang.Integer. Do not call directly
-     * @param obj object to cast to int and unbox
-     * @return an int
-     */
-    public static int unboxI(final Object obj) {
-        return (int)obj;
-    }
-
-    /**
-     * Unbox a java.lang.Long. Do not call directly
-     * @param obj object to cast to long and unbox
-     * @return a long
-     */
-    public static long unboxJ(final Object obj) {
-        return (long)obj;
-    }
-
-    /**
-     * Unbox a java.lang.Number. Do not call directly
-     * @param obj object to cast to Number and unbox
-     * @return a double
-     */
-    public static double unboxD(final Object obj) {
-        return ((Number)obj).doubleValue();
-    }
-
-    private static MethodHandle findOwnMH_S(final String name, final Class<?> rtype, final Class<?>... types) {
-        return MH.findStatic(MethodHandles.lookup(), RuntimeCallSite.class, name, MH.type(rtype, types));
-    }
-
-    private static MethodHandle findOwnMH_V(final String name, final Class<?> rtype, final Class<?>... types) {
-        return MH.findVirtual(MethodHandles.lookup(), RuntimeCallSite.class, name, MH.type(rtype, types));
-    }
-}
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/BinaryNode.java	Thu Mar 05 11:26:22 2015 -0800
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/BinaryNode.java	Thu Mar 05 15:22:39 2015 -0800
@@ -98,7 +98,7 @@
     }
 
     /**
-     * Returns true if the node is a comparison operation.
+     * Returns true if the node is a comparison operation (either equality, inequality, or relational).
      * @return true if the node is a comparison operation.
      */
     public boolean isComparison() {
@@ -118,6 +118,22 @@
     }
 
     /**
+     * Returns true if the node is a relational operation (less than (or equals), greater than (or equals)).
+     * @return true if the node is a relational operation.
+     */
+    public boolean isRelational() {
+        switch (tokenType()) {
+        case LT:
+        case GT:
+        case LE:
+        case GE:
+            return true;
+        default:
+            return false;
+        }
+    }
+
+    /**
      * Returns true if the node is a logical operation.
      * @return true if the node is a logical operation.
      */
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/RuntimeNode.java	Thu Mar 05 11:26:22 2015 -0800
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/RuntimeNode.java	Thu Mar 05 15:22:39 2015 -0800
@@ -25,8 +25,6 @@
 
 package jdk.nashorn.internal.ir;
 
-import static jdk.nashorn.internal.runtime.UnwarrantedOptimismException.INVALID_PROGRAM_POINT;
-
 import java.util.Arrays;
 import java.util.Collections;
 import java.util.List;
@@ -39,7 +37,7 @@
  * IR representation for a runtime call.
  */
 @Immutable
-public class RuntimeNode extends Expression implements Optimistic {
+public class RuntimeNode extends Expression {
     private static final long serialVersionUID = 1L;
 
     /**
@@ -333,11 +331,6 @@
     /** Call arguments. */
     private final List<Expression> args;
 
-    /** is final - i.e. may not be removed again, lower in the code pipeline */
-    private final boolean isFinal;
-
-    private final int programPoint;
-
     /**
      * Constructor
      *
@@ -351,17 +344,13 @@
 
         this.request      = request;
         this.args         = args;
-        this.isFinal      = false;
-        this.programPoint = INVALID_PROGRAM_POINT;
     }
 
-    private RuntimeNode(final RuntimeNode runtimeNode, final Request request, final boolean isFinal, final List<Expression> args, final int programPoint) {
+    private RuntimeNode(final RuntimeNode runtimeNode, final Request request, final List<Expression> args) {
         super(runtimeNode);
 
         this.request      = request;
         this.args         = args;
-        this.isFinal      = isFinal;
-        this.programPoint = programPoint;
     }
 
     /**
@@ -399,8 +388,6 @@
 
         this.request      = request;
         this.args         = args;
-        this.isFinal      = false;
-        this.programPoint = parent instanceof Optimistic ? ((Optimistic)parent).getProgramPoint() : INVALID_PROGRAM_POINT;
     }
 
     /**
@@ -428,32 +415,11 @@
      * @return new runtime node or same if same request
      */
     public RuntimeNode setRequest(final Request request) {
-       if (this.request == request) {
-           return this;
-       }
-       return new RuntimeNode(this, request, isFinal, args, programPoint);
-   }
-
-
-    /**
-     * Is this node final - i.e. it can never be replaced with other nodes again
-     * @return true if final
-     */
-    public boolean isFinal() {
-        return isFinal;
-    }
-
-    /**
-     * Flag this node as final - i.e it may never be replaced with other nodes again
-     * @param isFinal is the node final, i.e. can not be removed and replaced by a less generic one later in codegen
-     * @return same runtime node if already final, otherwise a new one
-     */
-    public RuntimeNode setIsFinal(final boolean isFinal) {
-        if (this.isFinal == isFinal) {
+        if (this.request == request) {
             return this;
         }
-        return new RuntimeNode(this, request, isFinal, args, programPoint);
-    }
+        return new RuntimeNode(this, request, args);
+   }
 
     /**
      * Return type for the ReferenceNode
@@ -510,7 +476,7 @@
         if (this.args == args) {
             return this;
         }
-        return new RuntimeNode(this, request, isFinal, args, programPoint);
+        return new RuntimeNode(this, request, args);
     }
 
     /**
@@ -536,39 +502,4 @@
         }
         return true;
     }
-
-//TODO these are blank for now:
-
-    @Override
-    public int getProgramPoint() {
-        return programPoint;
-    }
-
-    @Override
-    public RuntimeNode setProgramPoint(final int programPoint) {
-        if(this.programPoint == programPoint) {
-            return this;
-        }
-        return new RuntimeNode(this, request, isFinal, args, programPoint);
-    }
-
-    @Override
-    public boolean canBeOptimistic() {
-        return false;
-    }
-
-    @Override
-    public Type getMostOptimisticType() {
-        return getType();
-    }
-
-    @Override
-    public Type getMostPessimisticType() {
-        return getType();
-    }
-
-    @Override
-    public RuntimeNode setType(final Type type) {
-        return this;
-    }
 }
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/lookup/MethodHandleFactory.java	Thu Mar 05 11:26:22 2015 -0800
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/lookup/MethodHandleFactory.java	Thu Mar 05 15:22:39 2015 -0800
@@ -25,6 +25,8 @@
 
 package jdk.nashorn.internal.lookup;
 
+import static jdk.nashorn.internal.runtime.JSType.isString;
+
 import java.io.ByteArrayOutputStream;
 import java.io.PrintStream;
 import java.lang.invoke.MethodHandle;
@@ -36,7 +38,6 @@
 import java.util.Arrays;
 import java.util.List;
 import java.util.logging.Level;
-import jdk.nashorn.internal.runtime.ConsString;
 import jdk.nashorn.internal.runtime.Context;
 import jdk.nashorn.internal.runtime.Debug;
 import jdk.nashorn.internal.runtime.ScriptObject;
@@ -343,7 +344,7 @@
                 final Object d = data[i];
                 if (d == null) {
                     sb.append("<null> ");
-                } else if (d instanceof String || d instanceof ConsString) {
+                } else if (isString(d)) {
                     sb.append(d.toString());
                     sb.append(' ');
                 } else if (d.getClass().isArray()) {
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/Global.java	Thu Mar 05 11:26:22 2015 -0800
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/Global.java	Thu Mar 05 15:22:39 2015 -0800
@@ -28,6 +28,7 @@
 import static jdk.nashorn.internal.lookup.Lookup.MH;
 import static jdk.nashorn.internal.runtime.ECMAErrors.referenceError;
 import static jdk.nashorn.internal.runtime.ECMAErrors.typeError;
+import static jdk.nashorn.internal.runtime.JSType.isString;
 import static jdk.nashorn.internal.runtime.ScriptRuntime.UNDEFINED;
 
 import java.io.IOException;
@@ -55,7 +56,6 @@
 import jdk.nashorn.internal.objects.annotations.Attribute;
 import jdk.nashorn.internal.objects.annotations.Property;
 import jdk.nashorn.internal.objects.annotations.ScriptClass;
-import jdk.nashorn.internal.runtime.ConsString;
 import jdk.nashorn.internal.runtime.Context;
 import jdk.nashorn.internal.runtime.ECMAErrors;
 import jdk.nashorn.internal.runtime.GlobalConstants;
@@ -577,7 +577,7 @@
             return new NativeBoolean((Boolean)obj, this);
         } else if (obj instanceof Number) {
             return new NativeNumber(((Number)obj).doubleValue(), this);
-        } else if (obj instanceof String || obj instanceof ConsString) {
+        } else if (isString(obj)) {
             return new NativeString((CharSequence)obj, this);
         } else if (obj instanceof Object[]) { // extension
             return new NativeArray(ArrayData.allocate((Object[])obj), this);
@@ -604,7 +604,7 @@
      * @return guarded invocation
      */
     public static GuardedInvocation primitiveLookup(final LinkRequest request, final Object self) {
-        if (self instanceof String || self instanceof ConsString) {
+        if (isString(self)) {
             return NativeString.lookupPrimitive(request, self);
         } else if (self instanceof Number) {
             return NativeNumber.lookupPrimitive(request, self);
@@ -621,7 +621,7 @@
      * @return method handle to create wrapper objects for primitive receiver
      */
     public static MethodHandle getPrimitiveWrapFilter(final Object self) {
-        if (self instanceof String || self instanceof ConsString) {
+        if (isString(self)) {
             return NativeString.WRAPFILTER;
         } else if (self instanceof Number) {
             return NativeNumber.WRAPFILTER;
@@ -947,11 +947,11 @@
      * This is directly invoked from generated when eval(code) is called in user code
      */
     public static Object directEval(final Object self, final Object str, final Object callThis, final Object location, final boolean strict) {
-        if (!(str instanceof String || str instanceof ConsString)) {
+        if (!isString(str)) {
             return str;
         }
         final Global global = Global.instanceFrom(self);
-        final ScriptObject scope = self instanceof ScriptObject ? (ScriptObject)self : global;
+        final ScriptObject scope = self instanceof ScriptObject && ((ScriptObject)self).isScope() ? (ScriptObject)self : global;
 
         return global.getContext().eval(scope, str.toString(), callThis, location, strict, true);
     }
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeDate.java	Thu Mar 05 11:26:22 2015 -0800
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeDate.java	Thu Mar 05 15:22:39 2015 -0800
@@ -30,6 +30,7 @@
 import static java.lang.Double.isNaN;
 import static jdk.nashorn.internal.runtime.ECMAErrors.rangeError;
 import static jdk.nashorn.internal.runtime.ECMAErrors.typeError;
+
 import java.util.Locale;
 import java.util.TimeZone;
 import java.util.concurrent.Callable;
@@ -40,7 +41,6 @@
 import jdk.nashorn.internal.objects.annotations.SpecializedFunction;
 import jdk.nashorn.internal.objects.annotations.Where;
 import jdk.nashorn.internal.parser.DateParser;
-import jdk.nashorn.internal.runtime.ConsString;
 import jdk.nashorn.internal.runtime.JSType;
 import jdk.nashorn.internal.runtime.PropertyMap;
 import jdk.nashorn.internal.runtime.ScriptEnvironment;
@@ -183,7 +183,7 @@
         case 1:
             double num;
             final Object arg = JSType.toPrimitive(args[0]);
-            if (arg instanceof String || arg instanceof ConsString) {
+            if (JSType.isString(arg)) {
                 num = parseDateString(arg.toString());
             } else {
                 num = timeClip(JSType.toNumber(args[0]));
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeJSON.java	Thu Mar 05 11:26:22 2015 -0800
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeJSON.java	Thu Mar 05 15:22:39 2015 -0800
@@ -181,7 +181,7 @@
                 }
                 gap = sb.toString();
             }
-        } else if (modSpace instanceof String || modSpace instanceof ConsString) {
+        } else if (JSType.isString(modSpace)) {
             final String str = modSpace.toString();
             gap = str.substring(0, Math.min(10, str.length()));
         } else {
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeString.java	Thu Mar 05 11:26:22 2015 -0800
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeString.java	Thu Mar 05 15:22:39 2015 -0800
@@ -90,7 +90,7 @@
 
     private NativeString(final CharSequence value, final ScriptObject proto, final PropertyMap map) {
         super(proto, map);
-        assert value instanceof String || value instanceof ConsString;
+        assert JSType.isString(value);
         this.value = value;
     }
 
@@ -155,7 +155,7 @@
         final Object self = request.getReceiver();
         final Class<?> returnType = desc.getMethodType().returnType();
 
-        if (returnType == Object.class && (self instanceof String || self instanceof ConsString)) {
+        if (returnType == Object.class && JSType.isString(self)) {
             try {
                 return new GuardedInvocation(MH.findStatic(MethodHandles.lookup(), NativeString.class, "get", desc.getMethodType()), NashornGuards.getInstanceOf2Guard(String.class, ConsString.class));
             } catch (final LookupException e) {
@@ -1312,7 +1312,7 @@
     }
 
     private static CharSequence getCharSequence(final Object self) {
-        if (self instanceof String || self instanceof ConsString) {
+        if (JSType.isString(self)) {
             return (CharSequence)self;
         } else if (self instanceof NativeString) {
             return ((NativeString)self).getValue();
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/ConsString.java	Thu Mar 05 11:26:22 2015 -0800
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/ConsString.java	Thu Mar 05 15:22:39 2015 -0800
@@ -25,6 +25,8 @@
 
 package jdk.nashorn.internal.runtime;
 
+import static jdk.nashorn.internal.runtime.JSType.isString;
+
 import java.util.ArrayDeque;
 import java.util.Deque;
 
@@ -52,8 +54,8 @@
      * @param right right char sequence
      */
     public ConsString(final CharSequence left, final CharSequence right) {
-        assert left instanceof String || left instanceof ConsString;
-        assert right instanceof String || right instanceof ConsString;
+        assert isString(left);
+        assert isString(right);
         this.left = left;
         this.right = right;
         length = left.length() + right.length();
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/JSType.java	Thu Mar 05 11:26:22 2015 -0800
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/JSType.java	Thu Mar 05 15:22:39 2015 -0800
@@ -311,7 +311,7 @@
             return JSType.BOOLEAN;
         }
 
-        if (obj instanceof String || obj instanceof ConsString) {
+        if (isString(obj)) {
             return JSType.STRING;
         }
 
@@ -349,7 +349,7 @@
             return JSType.BOOLEAN;
         }
 
-        if (obj instanceof String || obj instanceof ConsString) {
+        if (isString(obj)) {
             return JSType.STRING;
         }
 
@@ -455,8 +455,7 @@
                obj == ScriptRuntime.UNDEFINED ||
                obj instanceof Boolean ||
                obj instanceof Number ||
-               obj instanceof String ||
-               obj instanceof ConsString;
+               isString(obj);
     }
 
    /**
@@ -577,7 +576,7 @@
             return num != 0 && !Double.isNaN(num);
         }
 
-        if (obj instanceof String || obj instanceof ConsString) {
+        if (isString(obj)) {
             return ((CharSequence)obj).length() > 0;
         }
 
@@ -628,6 +627,15 @@
     }
 
     /**
+     * Returns true if object represents a primitive JavaScript string value.
+     * @param obj the object
+     * @return true if the object represents a primitive JavaScript string value.
+     */
+    public static boolean isString(final Object obj) {
+        return obj instanceof String || obj instanceof ConsString;
+    }
+
+    /**
      * JavaScript compliant conversion of integer to String
      *
      * @param num an integer
@@ -753,6 +761,36 @@
         return toNumberGeneric(obj);
     }
 
+    /**
+     * Converts an object for a comparison with a number. Almost identical to {@link #toNumber(Object)} but
+     * converts {@code null} to {@code NaN} instead of zero, so it won't compare equal to zero.
+     *
+     * @param obj  an object
+     *
+     * @return a number
+     */
+    public static double toNumberForEq(final Object obj) {
+        return obj == null ? Double.NaN : toNumber(obj);
+    }
+
+    /**
+     * Converts an object for strict comparison with a number. Returns {@code NaN} for any object that is not
+     * a {@link Number}, so only boxed numerics can compare strictly equal to numbers.
+     *
+     * @param obj  an object
+     *
+     * @return a number
+     */
+    public static double toNumberForStrictEq(final Object obj) {
+        if (obj instanceof Double) {
+            return (Double)obj;
+        }
+        if (obj instanceof Number) {
+            return ((Number)obj).doubleValue();
+        }
+        return Double.NaN;
+    }
+
 
     /**
      * JavaScript compliant conversion of Boolean to number
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/ScriptFunctionData.java	Thu Mar 05 11:26:22 2015 -0800
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/ScriptFunctionData.java	Thu Mar 05 15:22:39 2015 -0800
@@ -28,6 +28,7 @@
 import static jdk.nashorn.internal.lookup.Lookup.MH;
 import static jdk.nashorn.internal.runtime.ECMAErrors.typeError;
 import static jdk.nashorn.internal.runtime.ScriptRuntime.UNDEFINED;
+
 import java.io.IOException;
 import java.io.ObjectInputStream;
 import java.io.Serializable;
@@ -456,8 +457,7 @@
     }
 
     static boolean isPrimitiveThis(final Object obj) {
-        return obj instanceof String || obj instanceof ConsString ||
-               obj instanceof Number || obj instanceof Boolean;
+        return JSType.isString(obj) || obj instanceof Number || obj instanceof Boolean;
     }
 
     /**
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/ScriptRuntime.java	Thu Mar 05 11:26:22 2015 -0800
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/ScriptRuntime.java	Thu Mar 05 15:22:39 2015 -0800
@@ -32,6 +32,7 @@
 import static jdk.nashorn.internal.runtime.ECMAErrors.syntaxError;
 import static jdk.nashorn.internal.runtime.ECMAErrors.typeError;
 import static jdk.nashorn.internal.runtime.JSType.isRepresentableAsInt;
+import static jdk.nashorn.internal.runtime.JSType.isString;
 
 import java.lang.invoke.MethodHandle;
 import java.lang.invoke.MethodHandles;
@@ -56,7 +57,6 @@
 import jdk.nashorn.internal.parser.Lexer;
 import jdk.nashorn.internal.runtime.linker.Bootstrap;
 
-
 /**
  * Utilities to be called by JavaScript runtime API and generated classes.
  */
@@ -115,6 +115,11 @@
     public static final Call THROW_REFERENCE_ERROR = staticCall(MethodHandles.lookup(), ScriptRuntime.class, "throwReferenceError", void.class, String.class);
 
     /**
+     * Throws a reference error for an undefined variable.
+     */
+    public static final Call THROW_CONST_TYPE_ERROR = staticCall(MethodHandles.lookup(), ScriptRuntime.class, "throwConstTypeError", void.class, String.class);
+
+    /**
      * Used to invalidate builtin names, e.g "Function" mapping to all properties in Function.prototype and Function.prototype itself.
      */
     public static final Call INVALIDATE_RESERVED_BUILTIN_NAME = staticCallNoLookup(ScriptRuntime.class, "invalidateReservedBuiltinName", void.class, String.class);
@@ -403,6 +408,15 @@
     }
 
     /**
+     * Throws a type error for an assignment to a const.
+     *
+     * @param name the const name
+     */
+    public static void throwConstTypeError(final String name) {
+        throw typeError("assign.constant", name);
+    }
+
+    /**
      * Call a script function as a constructor with given args.
      *
      * @param target ScriptFunction object.
@@ -522,8 +536,6 @@
 
     /**
      * ECMA 11.6.1 - The addition operator (+) - generic implementation
-     * Compiler specializes using {@link jdk.nashorn.internal.codegen.RuntimeCallSite}
-     * if any type information is available for any of the operands
      *
      * @param x  first term
      * @param y  second term
@@ -550,8 +562,7 @@
         final Object xPrim = JSType.toPrimitive(x);
         final Object yPrim = JSType.toPrimitive(y);
 
-        if (xPrim instanceof String || yPrim instanceof String
-                || xPrim instanceof ConsString || yPrim instanceof ConsString) {
+        if (isString(xPrim) || isString(yPrim)) {
             try {
                 return new ConsString(JSType.toCharSequence(xPrim), JSType.toCharSequence(yPrim));
             } catch (final IllegalArgumentException iae) {
@@ -940,8 +951,15 @@
      * @return true if x is less than y
      */
     public static boolean LT(final Object x, final Object y) {
-        final Object value = lessThan(x, y, true);
-        return value == UNDEFINED ? false : (Boolean)value;
+        final Object px = JSType.toPrimitive(x, Number.class);
+        final Object py = JSType.toPrimitive(y, Number.class);
+
+        return areBothString(px, py) ? px.toString().compareTo(py.toString()) < 0 :
+            JSType.toNumber(px) < JSType.toNumber(py);
+    }
+
+    private static boolean areBothString(final Object x, final Object y) {
+        return isString(x) && isString(y);
     }
 
     /**
@@ -953,8 +971,11 @@
      * @return true if x is greater than y
      */
     public static boolean GT(final Object x, final Object y) {
-        final Object value = lessThan(y, x, false);
-        return value == UNDEFINED ? false : (Boolean)value;
+        final Object px = JSType.toPrimitive(x, Number.class);
+        final Object py = JSType.toPrimitive(y, Number.class);
+
+        return areBothString(px, py) ? px.toString().compareTo(py.toString()) > 0 :
+            JSType.toNumber(px) > JSType.toNumber(py);
     }
 
     /**
@@ -966,8 +987,11 @@
      * @return true if x is less than or equal to y
      */
     public static boolean LE(final Object x, final Object y) {
-        final Object value = lessThan(y, x, false);
-        return !(Boolean.TRUE.equals(value) || value == UNDEFINED);
+        final Object px = JSType.toPrimitive(x, Number.class);
+        final Object py = JSType.toPrimitive(y, Number.class);
+
+        return areBothString(px, py) ? px.toString().compareTo(py.toString()) <= 0 :
+            JSType.toNumber(px) <= JSType.toNumber(py);
     }
 
     /**
@@ -979,48 +1003,11 @@
      * @return true if x is greater than or equal to y
      */
     public static boolean GE(final Object x, final Object y) {
-        final Object value = lessThan(x, y, true);
-        return !(Boolean.TRUE.equals(value) || value == UNDEFINED);
-    }
-
-    /** ECMA 11.8.5 The Abstract Relational Comparison Algorithm */
-    private static Object lessThan(final Object x, final Object y, final boolean leftFirst) {
-        Object px, py;
-
-        //support e.g. x < y should throw exception correctly if x or y are not numeric
-        if (leftFirst) {
-            px = JSType.toPrimitive(x, Number.class);
-            py = JSType.toPrimitive(y, Number.class);
-        } else {
-            py = JSType.toPrimitive(y, Number.class);
-            px = JSType.toPrimitive(x, Number.class);
-        }
+        final Object px = JSType.toPrimitive(x, Number.class);
+        final Object py = JSType.toPrimitive(y, Number.class);
 
-        if (JSType.ofNoFunction(px) == JSType.STRING && JSType.ofNoFunction(py) == JSType.STRING) {
-            // May be String or ConsString
-            return px.toString().compareTo(py.toString()) < 0;
-        }
-
-        final double nx = JSType.toNumber(px);
-        final double ny = JSType.toNumber(py);
-
-        if (Double.isNaN(nx) || Double.isNaN(ny)) {
-            return UNDEFINED;
-        }
-
-        if (nx == ny) {
-            return false;
-        }
-
-        if (nx > 0 && ny > 0 && Double.isInfinite(nx) && Double.isInfinite(ny)) {
-            return false;
-        }
-
-        if (nx < 0 && ny < 0 && Double.isInfinite(nx) && Double.isInfinite(ny)) {
-            return false;
-        }
-
-        return nx < ny;
+        return areBothString(px, py) ? px.toString().compareTo(py.toString()) >= 0 :
+            JSType.toNumber(px) >= JSType.toNumber(py);
     }
 
     /**
@@ -1033,9 +1020,7 @@
         final Context context = Context.getContextTrusted();
         final SwitchPoint sp = context.getBuiltinSwitchPoint(name);
         assert sp != null;
-        if (sp != null) {
-            context.getLogger(ApplySpecialization.class).info("Overwrote special name '" + name +"' - invalidating switchpoint");
-            SwitchPoint.invalidateAll(new SwitchPoint[] { sp });
-        }
+        context.getLogger(ApplySpecialization.class).info("Overwrote special name '" + name +"' - invalidating switchpoint");
+        SwitchPoint.invalidateAll(new SwitchPoint[] { sp });
     }
 }
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/ScriptingFunctions.java	Thu Mar 05 11:26:22 2015 -0800
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/ScriptingFunctions.java	Thu Mar 05 15:22:39 2015 -0800
@@ -107,7 +107,7 @@
 
         if (file instanceof File) {
             f = (File)file;
-        } else if (file instanceof String || file instanceof ConsString) {
+        } else if (JSType.isString(file)) {
             f = new java.io.File(((CharSequence)file).toString());
         }
 
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/Bootstrap.java	Thu Mar 05 11:26:22 2015 -0800
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/Bootstrap.java	Thu Mar 05 15:22:39 2015 -0800
@@ -48,7 +48,6 @@
 import jdk.nashorn.api.scripting.JSObject;
 import jdk.nashorn.internal.codegen.CompilerConstants.Call;
 import jdk.nashorn.internal.codegen.ObjectClassGenerator;
-import jdk.nashorn.internal.codegen.RuntimeCallSite;
 import jdk.nashorn.internal.lookup.MethodHandleFactory;
 import jdk.nashorn.internal.lookup.MethodHandleFunctionality;
 import jdk.nashorn.internal.objects.ScriptFunctionImpl;
@@ -210,19 +209,6 @@
     }
 
     /**
-     * Bootstrapper for a specialized Runtime call
-     *
-     * @param lookup       lookup
-     * @param initialName  initial name for callsite
-     * @param type         method type for call site
-     *
-     * @return callsite for a runtime node
-     */
-    public static CallSite runtimeBootstrap(final MethodHandles.Lookup lookup, final String initialName, final MethodType type) {
-        return new RuntimeCallSite(type, initialName);
-    }
-
-    /**
      * Boostrapper for math calls that may overflow
      * @param lookup         lookup
      * @param name           name of operation
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/BrowserJSObjectLinker.java	Thu Mar 05 11:26:22 2015 -0800
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/BrowserJSObjectLinker.java	Thu Mar 05 15:22:39 2015 -0800
@@ -25,11 +25,13 @@
 
 package jdk.nashorn.internal.runtime.linker;
 
+import static jdk.nashorn.internal.runtime.JSType.isString;
+import static jdk.nashorn.internal.runtime.linker.BrowserJSObjectLinker.JSObjectHandles.JSOBJECT_CALL;
 import static jdk.nashorn.internal.runtime.linker.BrowserJSObjectLinker.JSObjectHandles.JSOBJECT_GETMEMBER;
 import static jdk.nashorn.internal.runtime.linker.BrowserJSObjectLinker.JSObjectHandles.JSOBJECT_GETSLOT;
 import static jdk.nashorn.internal.runtime.linker.BrowserJSObjectLinker.JSObjectHandles.JSOBJECT_SETMEMBER;
 import static jdk.nashorn.internal.runtime.linker.BrowserJSObjectLinker.JSObjectHandles.JSOBJECT_SETSLOT;
-import static jdk.nashorn.internal.runtime.linker.BrowserJSObjectLinker.JSObjectHandles.JSOBJECT_CALL;
+
 import java.lang.invoke.MethodHandle;
 import java.lang.invoke.MethodHandles;
 import jdk.internal.dynalink.CallSiteDescriptor;
@@ -40,7 +42,6 @@
 import jdk.internal.dynalink.support.CallSiteDescriptorFactory;
 import jdk.nashorn.internal.lookup.MethodHandleFactory;
 import jdk.nashorn.internal.lookup.MethodHandleFunctionality;
-import jdk.nashorn.internal.runtime.ConsString;
 import jdk.nashorn.internal.runtime.JSType;
 
 /**
@@ -186,7 +187,7 @@
             if (index > -1) {
                 return JSOBJECT_GETSLOT.invokeExact(jsobj, index);
             }
-        } else if (key instanceof String || key instanceof ConsString) {
+        } else if (isString(key)) {
             final String name = key.toString();
             if (name.indexOf('(') != -1) {
                 return fallback.invokeExact(jsobj, (Object) name);
@@ -202,7 +203,7 @@
             JSOBJECT_SETSLOT.invokeExact(jsobj, (int)key, value);
         } else if (key instanceof Number) {
             JSOBJECT_SETSLOT.invokeExact(jsobj, getIndex((Number)key), value);
-        } else if (key instanceof String || key instanceof ConsString) {
+        } else if (isString(key)) {
             JSOBJECT_SETMEMBER.invokeExact(jsobj, key.toString(), value);
         }
     }
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/JSObjectLinker.java	Thu Mar 05 11:26:22 2015 -0800
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/JSObjectLinker.java	Thu Mar 05 15:22:39 2015 -0800
@@ -25,6 +25,8 @@
 
 package jdk.nashorn.internal.runtime.linker;
 
+import static jdk.nashorn.internal.runtime.JSType.isString;
+
 import java.lang.invoke.MethodHandle;
 import java.lang.invoke.MethodHandles;
 import java.util.Map;
@@ -38,7 +40,6 @@
 import jdk.nashorn.api.scripting.JSObject;
 import jdk.nashorn.internal.lookup.MethodHandleFactory;
 import jdk.nashorn.internal.lookup.MethodHandleFunctionality;
-import jdk.nashorn.internal.runtime.ConsString;
 import jdk.nashorn.internal.runtime.JSType;
 
 /**
@@ -166,7 +167,7 @@
             if (index > -1) {
                 return ((JSObject)jsobj).getSlot(index);
             }
-        } else if (key instanceof String || key instanceof ConsString) {
+        } else if (isString(key)) {
             final String name = key.toString();
             // get with method name and signature. delegate it to beans linker!
             if (name.indexOf('(') != -1) {
@@ -183,7 +184,7 @@
             ((JSObject)jsobj).setSlot((Integer)key, value);
         } else if (key instanceof Number) {
             ((JSObject)jsobj).setSlot(getIndex((Number)key), value);
-        } else if (key instanceof String || key instanceof ConsString) {
+        } else if (isString(key)) {
             ((JSObject)jsobj).setMember(key.toString(), value);
         }
     }
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/JavaArgumentConverters.java	Thu Mar 05 11:26:22 2015 -0800
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/JavaArgumentConverters.java	Thu Mar 05 15:22:39 2015 -0800
@@ -27,6 +27,7 @@
 
 import static jdk.nashorn.internal.lookup.Lookup.MH;
 import static jdk.nashorn.internal.runtime.ECMAErrors.typeError;
+import static jdk.nashorn.internal.runtime.JSType.isString;
 import static jdk.nashorn.internal.runtime.ScriptRuntime.UNDEFINED;
 
 import java.lang.invoke.MethodHandle;
@@ -78,7 +79,7 @@
         }
 
         if (obj == UNDEFINED) {
-            // NOTE: same reasoning for FindBugs NP_BOOLEAN_RETURN_NUL warning as in the preceding comment.
+            // NOTE: same reasoning for FindBugs NP_BOOLEAN_RETURN_NULL warning as in the preceding comment.
             return null;
         }
 
@@ -87,7 +88,7 @@
             return num != 0 && !Double.isNaN(num);
         }
 
-        if (obj instanceof String || obj instanceof ConsString) {
+        if (isString(obj)) {
             return ((CharSequence) obj).length() > 0;
         }
 
@@ -207,7 +208,7 @@
                 return f.longValue();
             } else if (obj instanceof Number) {
                 return ((Number)obj).longValue();
-            } else if (obj instanceof String || obj instanceof ConsString) {
+            } else if (isString(obj)) {
                 return JSType.toLong(obj);
             } else if (obj instanceof Boolean) {
                 return (Boolean)obj ? 1L : 0L;
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/NashornPrimitiveLinker.java	Thu Mar 05 11:26:22 2015 -0800
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/NashornPrimitiveLinker.java	Thu Mar 05 15:22:39 2015 -0800
@@ -39,6 +39,7 @@
 import jdk.internal.dynalink.support.TypeUtilities;
 import jdk.nashorn.internal.objects.Global;
 import jdk.nashorn.internal.runtime.ConsString;
+import jdk.nashorn.internal.runtime.JSType;
 import jdk.nashorn.internal.runtime.ScriptRuntime;
 
 /**
@@ -170,7 +171,7 @@
 
     @SuppressWarnings("unused")
     private static boolean isJavaScriptPrimitive(final Object o) {
-        return o instanceof String || o instanceof Boolean || o instanceof Number || o instanceof ConsString || o == null;
+        return JSType.isString(o) || o instanceof Boolean || o instanceof Number || o == null;
     }
 
     private static final MethodHandle GUARD_PRIMITIVE = findOwnMH("isJavaScriptPrimitive", boolean.class, Object.class);
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/resources/Messages.properties	Thu Mar 05 11:26:22 2015 -0800
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/resources/Messages.properties	Thu Mar 05 15:22:39 2015 -0800
@@ -167,7 +167,6 @@
 syntax.error.invalid.json=Invalid JSON: {0}
 syntax.error.strict.cant.delete=cannot delete "{0}" in strict mode
 syntax.error.redeclare.variable=Variable "{0}" has already been declared
-syntax.error.assign.constant=Assignment to constant "{0}"
 syntax.error.unprotected.switch.declaration=Unsupported {0} declaration in unprotected switch statement
 
 io.error.cant.write=cannot write "{0}"
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/basic/JDK-8035712.js	Thu Mar 05 15:22:39 2015 -0800
@@ -0,0 +1,282 @@
+/*
+ * 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.
+ * 
+ * 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.
+ */
+
+/**
+ * JDK-8035712: Restore some of the RuntimeCallSite specializations
+ *
+ * @test
+ * @run
+ */
+
+if ((typeof Assert) == "undefined") {
+    Assert = { 
+        assertTrue: function(x) { if(!x) { throw "expected true" } },
+        assertFalse: function(x) { if(x) { throw "expected false" } },
+    };
+}
+
+function nop() {}
+
+function EQ(x, y) {
+    // Exercise normal evaluation
+    Assert.assertTrue (x == y);
+    Assert.assertTrue (y == x);
+    Assert.assertFalse(x != y);
+    Assert.assertFalse(y != x);
+    // Exercise the branch optimizer
+    if (x == y) { nop(); } else { Assert.fail(); }
+    if (y == x) { nop(); } else { Assert.fail(); }
+    if (x != y) { Assert.fail(); } else { nop(); }
+    if (y != x) { Assert.fail(); } else { nop(); }
+}
+
+function NE(x, y) {
+    // Exercise normal evaluation
+    Assert.assertTrue (x != y);
+    Assert.assertTrue (y != x);
+    Assert.assertFalse(x == y);
+    Assert.assertFalse(y == x);
+    // Exercise the branch optimizer
+    if (x != y) { nop(); } else { Assert.fail(); }
+    if (y != x) { nop(); } else { Assert.fail(); }
+    if (x == y) { Assert.fail(); } else { nop(); }
+    if (y == x) { Assert.fail(); } else { nop(); }
+}
+
+function STRICT_EQ(x, y) {
+    // Exercise normal evaluation
+    Assert.assertTrue (x === y);
+    Assert.assertTrue (y === x);
+    Assert.assertFalse(x !== y);
+    Assert.assertFalse(y !== x);
+    // Exercise the branch optimizer
+    if (x === y) { nop(); } else { Assert.fail(); }
+    if (y === x) { nop(); } else { Assert.fail(); }
+    if (x !== y) { Assert.fail(); } else { nop(); }
+    if (y !== x) { Assert.fail(); } else { nop(); }
+}
+
+function STRICT_NE(x, y) {
+    // Exercise normal evaluation
+    Assert.assertTrue (x !== y);
+    Assert.assertTrue (y !== x);
+    Assert.assertFalse(x === y);
+    Assert.assertFalse(y === x);
+    // Exercise the branch optimizer
+    if (x !== y) { nop(); } else { Assert.fail(); }
+    if (y !== x) { nop(); } else { Assert.fail(); }
+    if (x === y) { Assert.fail(); } else { nop(); }
+    if (y === x) { Assert.fail(); } else { nop(); }
+}
+
+function cmpToAnyNumber(cmp, value) {
+    cmp(1, value);
+    cmp(4294967296, value);
+    cmp(1.2, value);
+    cmp(Infinity, value);
+    cmp(-Infinity, value);
+    cmp(1/Infinity, value);
+    cmp(0, value);
+    cmp(-0, value);
+    cmp(true, value);
+    cmp(false, value);
+}
+
+function notEqualToAnyNumber(value) {
+    cmpToAnyNumber(NE, value);
+    cmpToAnyNumber(STRICT_NE, value);
+}
+
+notEqualToAnyNumber(null);
+notEqualToAnyNumber(void 0);
+notEqualToAnyNumber("abc");
+notEqualToAnyNumber({});
+notEqualToAnyNumber(["xyz"]);
+
+function objectWithPrimitiveFunctionNotEqualToAnyNumber(fnName) {
+    var obj = {
+        count: 0
+    };
+    obj[fnName] = function() { this.count++; return "foo"; };
+    notEqualToAnyNumber(obj);
+    // Every NE will invoke it 8 times; cmpToAnyNumber has 10 comparisons
+    // STRICT_NE doesn't invoke toString.
+    Assert.assertTrue(80 === obj.count);
+}
+objectWithPrimitiveFunctionNotEqualToAnyNumber("valueOf");
+objectWithPrimitiveFunctionNotEqualToAnyNumber("toString");
+
+function objectEqualButNotStrictlyEqual(val, obj) {
+    EQ(val, obj);
+    STRICT_NE(val, obj);
+}
+
+function numberEqualButNotStrictlyEqualToObject(num, obj) {
+    objectEqualButNotStrictlyEqual(num, obj);
+    objectEqualButNotStrictlyEqual(num, [obj]);
+    objectEqualButNotStrictlyEqual(num, [[obj]]);
+}
+
+function numberEqualButNotStrictlyEqualToZeroObjects(num) {
+    numberEqualButNotStrictlyEqualToObject(num, [0]);
+    numberEqualButNotStrictlyEqualToObject(num, "");
+    numberEqualButNotStrictlyEqualToObject(num, []);
+    numberEqualButNotStrictlyEqualToObject(num, "0");
+}
+
+numberEqualButNotStrictlyEqualToZeroObjects(0);
+numberEqualButNotStrictlyEqualToZeroObjects(1/Infinity);
+numberEqualButNotStrictlyEqualToZeroObjects(false);
+
+function numberEqualButNotStrictlyEqualToObjectEquivalent(num) {
+    var str = String(num);
+    objectEqualButNotStrictlyEqual(num, str);
+    objectEqualButNotStrictlyEqual(num, { valueOf:  function() { return str }});
+    objectEqualButNotStrictlyEqual(num, { toString: function() { return str }});
+    objectEqualButNotStrictlyEqual(num, { valueOf:  function() { return num }});
+    objectEqualButNotStrictlyEqual(num, { toString: function() { return num }});
+}
+
+numberEqualButNotStrictlyEqualToObjectEquivalent(1);
+numberEqualButNotStrictlyEqualToObjectEquivalent(4294967296);
+numberEqualButNotStrictlyEqualToObjectEquivalent(1.2);
+numberEqualButNotStrictlyEqualToObjectEquivalent(Infinity);
+numberEqualButNotStrictlyEqualToObjectEquivalent(-Infinity);
+numberEqualButNotStrictlyEqualToObjectEquivalent(1/Infinity);
+numberEqualButNotStrictlyEqualToObjectEquivalent(0);
+numberEqualButNotStrictlyEqualToObjectEquivalent(-0);
+
+STRICT_EQ(1, new java.lang.Integer(1));
+STRICT_EQ(1, new java.lang.Double(1));
+STRICT_EQ(1.2, new java.lang.Double(1.2));
+
+function LE(x, y) {
+    // Exercise normal evaluation
+    Assert.assertTrue(x <= y);
+    Assert.assertTrue(y >= x);
+    Assert.assertFalse(x > y);
+    Assert.assertFalse(x < y);
+    // Exercise the branch optimizer
+    if (x <= y) { nop(); } else { Assert.fail(); }
+    if (y >= x) { nop(); } else { Assert.fail(); }
+    if (x > y) { Assert.fail(); } else { nop(); }
+    if (y < x) { Assert.fail(); } else { nop(); }
+}
+
+function mutuallyLessThanOrEqual(x, y) {
+    LE(x, y);
+    LE(y, x);
+}
+
+mutuallyLessThanOrEqual(0, null);
+mutuallyLessThanOrEqual(false, null);
+mutuallyLessThanOrEqual(1/Infinity, null);
+
+function mutuallyLessThanEqualToObjectWithValue(num, val) {
+    mutuallyLessThanOrEqual(num, { valueOf: function() { return val } });
+    mutuallyLessThanOrEqual(num, { toString: function() { return val } });
+}
+
+mutuallyLessThanEqualToObjectWithValue(false, 0);
+mutuallyLessThanEqualToObjectWithValue(false, "");
+
+mutuallyLessThanEqualToObjectWithValue(true, 1);
+mutuallyLessThanEqualToObjectWithValue(true, "1");
+
+function lessThanEqualToObjectEquivalent(num) {
+    var str = String(num);
+    mutuallyLessThanOrEqual(num, str);
+    mutuallyLessThanEqualToObjectWithValue(num, num);
+    mutuallyLessThanEqualToObjectWithValue(num, str);
+}
+
+lessThanEqualToObjectEquivalent(1);
+lessThanEqualToObjectEquivalent(4294967296);
+lessThanEqualToObjectEquivalent(1.2);
+lessThanEqualToObjectEquivalent(Infinity);
+lessThanEqualToObjectEquivalent(-Infinity);
+lessThanEqualToObjectEquivalent(1/Infinity);
+lessThanEqualToObjectEquivalent(0);
+lessThanEqualToObjectEquivalent(-0);
+
+function INCOMPARABLE(x, y) {
+    // Exercise normal evaluation
+    Assert.assertFalse(x < y);
+    Assert.assertFalse(x > y);
+    Assert.assertFalse(x <= y);
+    Assert.assertFalse(x >= y);
+    Assert.assertFalse(y < x);
+    Assert.assertFalse(y > x);
+    Assert.assertFalse(y <= x);
+    Assert.assertFalse(y >= x);
+    // Exercise the branch optimizer
+    if (x < y) { Assert.fail(); } else { nop(); }
+    if (x > y) { Assert.fail(); } else { nop(); }
+    if (x <= y) { Assert.fail(); } else { nop(); }
+    if (x >= y) { Assert.fail(); } else { nop(); }
+    if (y < x) { Assert.fail(); } else { nop(); }
+    if (y > x) { Assert.fail(); } else { nop(); }
+    if (y <= x) { Assert.fail(); } else { nop(); }
+    if (y >= x) { Assert.fail(); } else { nop(); }
+}
+
+function isIncomparable(value) {
+    cmpToAnyNumber(INCOMPARABLE, value);
+}
+
+isIncomparable(void 0);
+isIncomparable({ valueOf: function() { return NaN }});
+isIncomparable({ toString: function() { return NaN }});
+
+// Force ScriptRuntime.LT(Object, Object) etc. comparisons
+function cmpObj(fn, x, y) {
+    fn({valueOf: function() { return x }}, {valueOf: function() { return y }});
+}
+
+function LT(x, y) {
+    Assert.assertTrue(x < y);
+    Assert.assertTrue(y > x);
+    Assert.assertFalse(x >= y);
+    Assert.assertFalse(y <= x);
+}
+
+cmpObj(LT, 1, 2);
+cmpObj(LT, 1, "2");
+cmpObj(LT, "1", 2);
+cmpObj(LT, "a", "b");
+cmpObj(LT, -Infinity, 0);
+cmpObj(LT, 0, Infinity);
+cmpObj(LT, -Infinity, Infinity);
+cmpObj(INCOMPARABLE, 1, NaN);
+cmpObj(INCOMPARABLE, NaN, NaN);
+cmpObj(INCOMPARABLE, "boo", NaN);
+cmpObj(INCOMPARABLE, 1, "boo"); // boo number value will be NaN
+
+// Test that a comparison call site can deoptimize from (int, int) to (object, object)
+(function(){
+    var x = [1,  2,  "a"];
+    var y = [2, "3", "b"];
+    for(var i = 0; i < 3; ++i) {
+        Assert.assertTrue(x[i] < y[i]);
+    }
+})();
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/basic/JDK-8074021.js	Thu Mar 05 15:22:39 2015 -0800
@@ -0,0 +1,41 @@
+/*
+ * 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.
+ * 
+ * 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.
+ */
+
+/**
+ * JDK-8074021: Indirect eval fails when used as an element of an array or as a property of an object
+ *
+ * @test
+ * @run
+ */
+
+var obj = { foo: eval };
+Assert.assertTrue(obj.foo("typeof(print) == 'function'"));
+Assert.assertTrue(obj.foo("RegExp instanceof Function"));
+Assert.assertEquals(obj.foo("String(new Array(2, 4, 3))"), "2,4,3");
+obj.foo("print('hello')");
+
+var args = [ eval ];
+Assert.assertTrue(args[0]("typeof(print) == 'function'"));
+Assert.assertTrue(args[0]("RegExp instanceof Function"));
+Assert.assertEquals(args[0]("String(new Array(2, 4, 3))"), "2,4,3");
+args[0]("print('hello')");
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/basic/JDK-8074021.js.EXPECTED	Thu Mar 05 15:22:39 2015 -0800
@@ -0,0 +1,2 @@
+hello
+hello
--- a/nashorn/test/script/basic/es6/const-reassign.js	Thu Mar 05 11:26:22 2015 -0800
+++ b/nashorn/test/script/basic/es6/const-reassign.js	Thu Mar 05 15:22:39 2015 -0800
@@ -31,144 +31,147 @@
 "use strict";
 
 try {
-    eval('"use strict";\n' +
-        'const x = 2;\n' +
-        'x = 1;\n');
+    const x = 2;
+    x = 1;
+    fail("const assignment didn't throw");
 } catch (e) {
-    print(e.name);
+    print(e);
 }
 
 try {
-    eval('"use strict";\n' +
-        'const x = 2;\n' +
-        'x++;\n');
+    const x = 2;
+    x++;
     fail("const assignment didn't throw");
 } catch (e) {
-    print(e.name);
+    print(e);
 }
 
 try {
-    eval('"use strict";\n' +
-        'const x = 2;\n' +
-        'x--;\n');
+    const x = 2;
+    x--;
     fail("const assignment didn't throw");
 } catch (e) {
-    print(e.name);
+    print(e);
+}
+
+try {
+    const x = 2;
+    ++x;
+    fail("const assignment didn't throw");
+} catch (e) {
+    print(e);
 }
 
 try {
-    eval('"use strict";\n' +
-        'const x = 2;\n' +
-        '++x;\n');
+    const x = 2;
+    --x;
     fail("const assignment didn't throw");
 } catch (e) {
-    print(e.name);
+    print(e);
 }
 
 try {
-    eval('"use strict";\n' +
-        'const x = 2;\n' +
-        '--x;\n');
+    const x = 2;
+    x += 1;
     fail("const assignment didn't throw");
 } catch (e) {
-    print(e.name);
+    print(e);
 }
 
 try {
-    eval('"use strict";\n' +
-        'const x = 2;\n' +
-        'x += 1;\n');
+    const x = 2;
+    x *= 1;
     fail("const assignment didn't throw");
 } catch (e) {
-    print(e.name);
+    print(e);
 }
 
 try {
-    eval('"use strict";\n' +
-        'const x = 2;\n' +
-        'x *= 1;\n');
+    const x = 2;
+    x /= 1;
     fail("const assignment didn't throw");
 } catch (e) {
-    print(e.name);
+    print(e);
 }
 
 try {
-    eval('"use strict";\n' +
-        'const x = 2;\n' +
-        'x /= 1;\n');
+    const x = 2;
+    x %= 1;
     fail("const assignment didn't throw");
 } catch (e) {
-    print(e.name);
+    print(e);
 }
 
 try {
-    eval('"use strict";\n' +
-        'const x = 2;\n' +
-        'x %= 1;\n');
+    const x = 2;
+    x |= 1;
     fail("const assignment didn't throw");
 } catch (e) {
-    print(e.name);
+    print(e);
 }
 
 try {
-    eval('"use strict";\n' +
-        'const x = 2;\n' +
-        'x |= 1;\n');
+    const x = 2;
+    x &= 1;
     fail("const assignment didn't throw");
 } catch (e) {
-    print(e.name);
+    print(e);
 }
 
 try {
-    eval('"use strict";\n' +
-        'const x = 2;\n' +
-        'x &= 1;\n');
+    const x = 2;
+    x ^= 1;
     fail("const assignment didn't throw");
 } catch (e) {
-    print(e.name);
+    print(e);
+}
+
+try {
+    const x = 2;
+    x <<= 1;
+    fail("const assignment didn't throw");
+} catch (e) {
+    print(e);
 }
 
 try {
-    eval('"use strict";\n' +
-        'const x = 2;\n' +
-        'x ^= 1;\n');
+    const x = 2;
+    x >>= 1;
     fail("const assignment didn't throw");
 } catch (e) {
-    print(e.name);
+    print(e);
 }
 
 try {
-    eval('"use strict";\n' +
-        'const x = 2;\n' +
-        'x <<= 1;\n');
+    const x = 2;
+    x >>>= 1;
     fail("const assignment didn't throw");
 } catch (e) {
-    print(e.name);
+    print(e);
 }
 
 try {
-    eval('"use strict";\n' +
-        'const x = 2;\n' +
-        'x >>= 1;\n');
+    const x = 2;
+    delete x;
     fail("const assignment didn't throw");
 } catch (e) {
-    print(e.name);
+    print(e);
 }
 
+const c = 1;
+
 try {
-    eval('"use strict";\n' +
-        'const x = 2;\n' +
-        'x >>>= 1;\n');
+    c = 2;
     fail("const assignment didn't throw");
 } catch (e) {
-    print(e.name);
+    print(e);
 }
 
-try {
-    eval('"use strict";\n' +
-        'const x = 2;\n' +
-        'delete x;\n');
-    fail("const assignment didn't throw");
-} catch (e) {
-    print(e.name);
-}
+(function() {
+    try {
+        c = 2;
+        fail("const assignment didn't throw");
+    } catch (e) {
+        print(e);
+    }
+})();
--- a/nashorn/test/script/basic/es6/const-reassign.js.EXPECTED	Thu Mar 05 11:26:22 2015 -0800
+++ b/nashorn/test/script/basic/es6/const-reassign.js.EXPECTED	Thu Mar 05 15:22:39 2015 -0800
@@ -1,16 +1,18 @@
-SyntaxError
-SyntaxError
-SyntaxError
-SyntaxError
-SyntaxError
-SyntaxError
-SyntaxError
-SyntaxError
-SyntaxError
-SyntaxError
-SyntaxError
-SyntaxError
-SyntaxError
-SyntaxError
-SyntaxError
-SyntaxError
+TypeError: Assignment to constant "x"
+TypeError: Assignment to constant "x"
+TypeError: Assignment to constant "x"
+TypeError: Assignment to constant "x"
+TypeError: Assignment to constant "x"
+TypeError: Assignment to constant "x"
+TypeError: Assignment to constant "x"
+TypeError: Assignment to constant "x"
+TypeError: Assignment to constant "x"
+TypeError: Assignment to constant "x"
+TypeError: Assignment to constant "x"
+TypeError: Assignment to constant "x"
+TypeError: Assignment to constant "x"
+TypeError: Assignment to constant "x"
+TypeError: Assignment to constant "x"
+SyntaxError: cannot delete "x" in strict mode
+TypeError: Assignment to constant "c"
+TypeError: Assignment to constant "c"
--- a/nashorn/test/script/basic/es6/let_const_reuse.js.EXPECTED	Thu Mar 05 11:26:22 2015 -0800
+++ b/nashorn/test/script/basic/es6/let_const_reuse.js.EXPECTED	Thu Mar 05 15:22:39 2015 -0800
@@ -1,8 +1,4 @@
 ReferenceError: "a" is not defined
-SyntaxError: test/script/basic/es6/let_const_reuse.js#35:9<eval>:3:8 Assignment to constant "a"
-        a--
-        ^
-SyntaxError: test/script/basic/es6/let_const_reuse.js#35:9<eval>:3:8 Assignment to constant "a"
-        a--
-        ^
+TypeError: Assignment to constant "a"
+TypeError: Assignment to constant "a"
 ReferenceError: "a" is not defined