changeset 642:676cd7bf5e09 jdk8-b113

Merge
author lana
date Thu, 17 Oct 2013 16:19:45 -0700
parents adc5639fc4b9 (diff) 103590fc1e0a (current diff)
children 79f7b79bf97b b5b4c98b072b
files
diffstat 103 files changed, 2352 insertions(+), 1691 deletions(-) [+]
line wrap: on
line diff
--- a/src/jdk/internal/dynalink/beans/SingleDynamicMethod.java	Thu Oct 17 09:41:14 2013 -0700
+++ b/src/jdk/internal/dynalink/beans/SingleDynamicMethod.java	Thu Oct 17 16:19:45 2013 -0700
@@ -91,6 +91,7 @@
 import jdk.internal.dynalink.CallSiteDescriptor;
 import jdk.internal.dynalink.linker.LinkerServices;
 import jdk.internal.dynalink.support.Guards;
+import jdk.internal.dynalink.support.Lookup;
 
 /**
  * Base class for dynamic methods that dispatch to a single target Java method or constructor. Handles adaptation of the
@@ -100,6 +101,9 @@
  * @version $Id: $
  */
 abstract class SingleDynamicMethod extends DynamicMethod {
+
+    private static final MethodHandle CAN_CONVERT_TO = Lookup.findOwnStatic(MethodHandles.lookup(), "canConvertTo", boolean.class, LinkerServices.class, Class.class, Object.class);
+
     SingleDynamicMethod(String name) {
         super(name);
     }
@@ -201,23 +205,69 @@
                 return createConvertingInvocation(target, linkerServices, callSiteType).asVarargsCollector(
                         callSiteLastArgType);
             }
-            if(!linkerServices.canConvert(callSiteLastArgType, varArgType)) {
-                // Call site signature guarantees the argument can definitely not be an array (i.e. it is primitive);
-                // link immediately to a vararg-packing method handle.
-                return createConvertingInvocation(collectArguments(fixTarget, argsLen), linkerServices, callSiteType);
+
+            // This method handle takes the single argument and packs it into a newly allocated single-element array. It
+            // will be used when the incoming argument can't be converted to the vararg array type (the "vararg packer"
+            // method).
+            final MethodHandle varArgCollectingInvocation = createConvertingInvocation(collectArguments(fixTarget,
+                    argsLen), linkerServices, callSiteType);
+
+            // Is call site type assignable from an array type (e.g. Object:int[], or Object[]:String[])
+            final boolean isAssignableFromArray = callSiteLastArgType.isAssignableFrom(varArgType);
+            // Do we have a custom conversion that can potentially convert the call site type to an array?
+            final boolean isCustomConvertible = linkerServices.canConvert(callSiteLastArgType, varArgType);
+            if(!isAssignableFromArray && !isCustomConvertible) {
+                // Call site signature guarantees the argument can definitely not be converted to an array (i.e. it is
+                // primitive), and no conversion can help with it either. Link immediately to a vararg-packing method
+                // handle.
+                return varArgCollectingInvocation;
             }
-            // Call site signature makes no guarantees that the single argument in the vararg position will be
-            // compatible across all invocations. Need to insert an appropriate guard and fall back to generic vararg
-            // method when it is not.
-            return MethodHandles.guardWithTest(Guards.isInstance(varArgType, fixParamsLen, callSiteType),
-                    createConvertingInvocation(fixTarget, linkerServices, callSiteType),
-                    createConvertingInvocation(collectArguments(fixTarget, argsLen), linkerServices, callSiteType));
+
+            // This method handle employs language-specific conversions to convert the last argument into an array of
+            // vararg type.
+            final MethodHandle arrayConvertingInvocation = createConvertingInvocation(MethodHandles.filterArguments(
+                    fixTarget, fixParamsLen, linkerServices.getTypeConverter(callSiteLastArgType, varArgType)),
+                    linkerServices, callSiteType);
+
+            // This method handle determines whether the value can be converted to the array of vararg type using a
+            // language-specific conversion.
+            final MethodHandle canConvertArgToArray = MethodHandles.insertArguments(CAN_CONVERT_TO, 0, linkerServices,
+                    varArgType);
+
+            // This one adjusts the previous one for the location of the argument and the call site type.
+            final MethodHandle canConvertLastArgToArray = MethodHandles.dropArguments(canConvertArgToArray, 0,
+                    MethodType.genericMethodType(fixParamsLen).parameterList()).asType(callSiteType.changeReturnType(boolean.class));
+
+            // This one takes the previous ones and combines them into a method handle that converts the argument into
+            // a vararg array when it can, otherwise falls back to the vararg packer.
+            final MethodHandle convertToArrayWhenPossible = MethodHandles.guardWithTest(canConvertLastArgToArray,
+                    arrayConvertingInvocation, varArgCollectingInvocation);
+
+            if(isAssignableFromArray) {
+                return MethodHandles.guardWithTest(
+                        // Is incoming parameter already a compatible array?
+                        Guards.isInstance(varArgType, fixParamsLen, callSiteType),
+                        // Yes: just pass it to the method
+                        createConvertingInvocation(fixTarget, linkerServices, callSiteType),
+                        // No: either go through a custom conversion, or if it is not possible, go directly to the
+                        // vararg packer.
+                        isCustomConvertible ? convertToArrayWhenPossible : varArgCollectingInvocation);
+            }
+
+            // Just do the custom conversion with fallback to the vararg packer logic.
+            assert isCustomConvertible;
+            return convertToArrayWhenPossible;
         }
 
         // Remaining case: more than one vararg.
         return createConvertingInvocation(collectArguments(fixTarget, argsLen), linkerServices, callSiteType);
     }
 
+    @SuppressWarnings("unused")
+    private static boolean canConvertTo(final LinkerServices linkerServices, Class<?> to, Object obj) {
+        return obj == null ? false : linkerServices.canConvert(obj.getClass(), to);
+    }
+
     /**
      * Creates a method handle out of the original target that will collect the varargs for the exact component type of
      * the varArg array. Note that this will nicely trigger language-specific type converters for exactly those varargs
--- a/src/jdk/internal/dynalink/support/Guards.java	Thu Oct 17 09:41:14 2013 -0700
+++ b/src/jdk/internal/dynalink/support/Guards.java	Thu Oct 17 16:19:45 2013 -0700
@@ -88,6 +88,7 @@
 import java.lang.invoke.MethodType;
 import java.util.logging.Level;
 import java.util.logging.Logger;
+import jdk.internal.dynalink.DynamicLinker;
 import jdk.internal.dynalink.linker.LinkerServices;
 
 /**
@@ -115,11 +116,11 @@
     public static MethodHandle isOfClass(Class<?> clazz, MethodType type) {
         final Class<?> declaredType = type.parameterType(0);
         if(clazz == declaredType) {
-            LOG.log(Level.WARNING, "isOfClassGuardAlwaysTrue", new Object[] { clazz.getName(), 0, type });
+            LOG.log(Level.WARNING, "isOfClassGuardAlwaysTrue", new Object[] { clazz.getName(), 0, type, DynamicLinker.getLinkedCallSiteLocation() });
             return constantTrue(type);
         }
         if(!declaredType.isAssignableFrom(clazz)) {
-            LOG.log(Level.WARNING, "isOfClassGuardAlwaysFalse", new Object[] { clazz.getName(), 0, type });
+            LOG.log(Level.WARNING, "isOfClassGuardAlwaysFalse", new Object[] { clazz.getName(), 0, type, DynamicLinker.getLinkedCallSiteLocation() });
             return constantFalse(type);
         }
         return getClassBoundArgumentTest(IS_OF_CLASS, clazz, 0, type);
@@ -152,11 +153,11 @@
     public static MethodHandle isInstance(Class<?> clazz, int pos, MethodType type) {
         final Class<?> declaredType = type.parameterType(pos);
         if(clazz.isAssignableFrom(declaredType)) {
-            LOG.log(Level.WARNING, "isInstanceGuardAlwaysTrue", new Object[] { clazz.getName(), pos, type });
+            LOG.log(Level.WARNING, "isInstanceGuardAlwaysTrue", new Object[] { clazz.getName(), pos, type, DynamicLinker.getLinkedCallSiteLocation() });
             return constantTrue(type);
         }
         if(!declaredType.isAssignableFrom(clazz)) {
-            LOG.log(Level.WARNING, "isInstanceGuardAlwaysFalse", new Object[] { clazz.getName(), pos, type });
+            LOG.log(Level.WARNING, "isInstanceGuardAlwaysFalse", new Object[] { clazz.getName(), pos, type, DynamicLinker.getLinkedCallSiteLocation() });
             return constantFalse(type);
         }
         return getClassBoundArgumentTest(IS_INSTANCE, clazz, pos, type);
@@ -174,11 +175,11 @@
     public static MethodHandle isArray(int pos, MethodType type) {
         final Class<?> declaredType = type.parameterType(pos);
         if(declaredType.isArray()) {
-            LOG.log(Level.WARNING, "isArrayGuardAlwaysTrue", new Object[] { pos, type });
+            LOG.log(Level.WARNING, "isArrayGuardAlwaysTrue", new Object[] { pos, type, DynamicLinker.getLinkedCallSiteLocation() });
             return constantTrue(type);
         }
         if(!declaredType.isAssignableFrom(Object[].class)) {
-            LOG.log(Level.WARNING, "isArrayGuardAlwaysFalse", new Object[] { pos, type });
+            LOG.log(Level.WARNING, "isArrayGuardAlwaysFalse", new Object[] { pos, type, DynamicLinker.getLinkedCallSiteLocation() });
             return constantFalse(type);
         }
         return asType(IS_ARRAY, pos, type);
--- a/src/jdk/internal/dynalink/support/messages.properties	Thu Oct 17 09:41:14 2013 -0700
+++ b/src/jdk/internal/dynalink/support/messages.properties	Thu Oct 17 16:19:45 2013 -0700
@@ -76,11 +76,11 @@
 #      OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
 #      ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
-isInstanceGuardAlwaysTrue=isInstance guard for {0} in position {1} in method type {2} will always return true
-isInstanceGuardAlwaysFalse=isInstance guard for {0} in position {1} in method type {2} will always return false
+isInstanceGuardAlwaysTrue=isInstance guard for {0} in position {1} in method type {2} at {3} will always return true
+isInstanceGuardAlwaysFalse=isInstance guard for {0} in position {1} in method type {2} at {3} will always return false
 
-isOfClassGuardAlwaysTrue=isOfClass guard for {0} in position {1} in method type {2} will always return true
-isOfClassGuardAlwaysFalse=isOfClass guard for {0} in position {1} in method type {2} will always return false
+isOfClassGuardAlwaysTrue=isOfClass guard for {0} in position {1} in method type {2} at {3} will always return true
+isOfClassGuardAlwaysFalse=isOfClass guard for {0} in position {1} in method type {2} at {3} will always return false
 
-isArrayGuardAlwaysTrue=isArray guard in position {0} in method type {1} will always return true
-isArrayGuardAlwaysFalse=isArray guard in position {0} in method type {1} will always return false
\ No newline at end of file
+isArrayGuardAlwaysTrue=isArray guard in position {0} in method type {1} at {2} will always return true
+isArrayGuardAlwaysFalse=isArray guard in position {0} in method type {1} at {2} will always return false
\ No newline at end of file
--- a/src/jdk/nashorn/api/scripting/JSObject.java	Thu Oct 17 09:41:14 2013 -0700
+++ b/src/jdk/nashorn/api/scripting/JSObject.java	Thu Oct 17 16:19:45 2013 -0700
@@ -46,7 +46,7 @@
      * @param args arguments to method
      * @return result of call
      */
-    public Object call(Object thiz, Object... args) {
+    public Object call(final Object thiz, final Object... args) {
         throw new UnsupportedOperationException("call");
     }
 
@@ -57,7 +57,7 @@
      * @param args arguments to method
      * @return result of constructor call
      */
-    public Object newObject(Object... args) {
+    public Object newObject(final Object... args) {
         throw new UnsupportedOperationException("newObject");
     }
 
@@ -67,7 +67,7 @@
      * @param s JavaScript expression to evaluate
      * @return evaluation result
      */
-    public Object eval(String s) {
+    public Object eval(final String s) {
         throw new UnsupportedOperationException("eval");
     }
 
@@ -78,7 +78,7 @@
      * @param args arguments to be passed to the member function
      * @return result of call
      */
-    public Object callMember(String name, Object... args) {
+    public Object callMember(final String name, final Object... args) {
         throw new UnsupportedOperationException("call");
     }
 
@@ -88,7 +88,7 @@
      * @param name of member
      * @return member
      */
-    public Object getMember(String name) {
+    public Object getMember(final String name) {
         return null;
     }
 
@@ -98,7 +98,7 @@
      * @param index index slot to retrieve
      * @return member
      */
-    public Object getSlot(int index) {
+    public Object getSlot(final int index) {
         return null;
     }
 
@@ -108,7 +108,7 @@
      * @param name name of member
      * @return true if this object has a member of the given name
      */
-    public boolean hasMember(String name) {
+    public boolean hasMember(final String name) {
         return false;
     }
 
@@ -118,7 +118,7 @@
      * @param slot index to check
      * @return true if this object has a slot
      */
-    public boolean hasSlot(int slot) {
+    public boolean hasSlot(final int slot) {
         return false;
     }
 
@@ -127,7 +127,8 @@
      *
      * @param name name of the member
      */
-    public void removeMember(String name) {
+    public void removeMember(final String name) {
+        //empty
     }
 
     /**
@@ -136,7 +137,8 @@
      * @param name  name of the member
      * @param value value of the member
      */
-    public void setMember(String name, Object value) {
+    public void setMember(final String name, final Object value) {
+        //empty
     }
 
     /**
@@ -145,7 +147,8 @@
      * @param index index of the member slot
      * @param value value of the member
      */
-    public void setSlot(int index, Object value) {
+    public void setSlot(final int index, final Object value) {
+        //empty
     }
 
     // property and value iteration
--- a/src/jdk/nashorn/api/scripting/NashornScriptEngine.java	Thu Oct 17 09:41:14 2013 -0700
+++ b/src/jdk/nashorn/api/scripting/NashornScriptEngine.java	Thu Oct 17 16:19:45 2013 -0700
@@ -285,11 +285,10 @@
                 final URL url = ((URLReader)reader).getURL();
                 final Charset cs = ((URLReader)reader).getCharset();
                 return new Source(url.toString(), url, cs);
-            } else {
-                return new Source(getScriptName(ctxt), Source.readFully(reader));
             }
-        } catch (final IOException ioExp) {
-            throw new ScriptException(ioExp);
+            return new Source(getScriptName(ctxt), Source.readFully(reader));
+        } catch (final IOException e) {
+            throw new ScriptException(e);
         }
     }
 
@@ -576,15 +575,14 @@
         return new CompiledScript() {
             @Override
             public Object eval(final ScriptContext ctxt) throws ScriptException {
-                final ScriptObject global = getNashornGlobalFrom(ctxt);
+                final ScriptObject globalObject = getNashornGlobalFrom(ctxt);
                 // Are we running the script in the correct global?
-                if (func.getScope() == global) {
-                    return evalImpl(func, ctxt, global);
-                } else {
-                    // ScriptContext with a different global. Compile again!
-                    // Note that we may still hit per-global compilation cache.
-                    return evalImpl(compileImpl(source, ctxt), ctxt, global);
+                if (func.getScope() == globalObject) {
+                    return evalImpl(func, ctxt, globalObject);
                 }
+                // ScriptContext with a different global. Compile again!
+                // Note that we may still hit per-global compilation cache.
+                return evalImpl(compileImpl(source, ctxt), ctxt, globalObject);
             }
             @Override
             public ScriptEngine getEngine() {
--- a/src/jdk/nashorn/api/scripting/ScriptUtils.java	Thu Oct 17 09:41:14 2013 -0700
+++ b/src/jdk/nashorn/api/scripting/ScriptUtils.java	Thu Oct 17 16:19:45 2013 -0700
@@ -25,6 +25,7 @@
 
 package jdk.nashorn.api.scripting;
 
+import jdk.nashorn.internal.runtime.ScriptFunction;
 import jdk.nashorn.internal.runtime.ScriptRuntime;
 
 /**
@@ -57,4 +58,17 @@
     public static String format(final String format, final Object[] args) {
         return Formatter.format(format, args);
     }
+
+    /**
+     * Create a wrapper function that calls {@code func} synchronized on {@code sync} or, if that is undefined,
+     * {@code self}. Used to implement "sync" function in resources/mozilla_compat.js.
+     *
+     * @param func the function to invoke
+     * @param sync the object to synchronize on
+     * @return a synchronizing wrapper function
+     */
+    public static Object makeSynchronizedFunction(final ScriptFunction func, final Object sync) {
+        return func.makeSynchronizedFunction(sync);
+    }
+
 }
--- a/src/jdk/nashorn/internal/codegen/Attr.java	Thu Oct 17 09:41:14 2013 -0700
+++ b/src/jdk/nashorn/internal/codegen/Attr.java	Thu Oct 17 16:19:45 2013 -0700
@@ -480,6 +480,10 @@
         }
 
         //unknown parameters are promoted to object type.
+        if (newFunctionNode.hasLazyChildren()) {
+            //the final body has already been assigned as we have left the function node block body by now
+            objectifySymbols(body);
+        }
         newFunctionNode = finalizeParameters(newFunctionNode);
         newFunctionNode = finalizeTypes(newFunctionNode);
         for (final Symbol symbol : newFunctionNode.getDeclaredSymbols()) {
@@ -489,11 +493,6 @@
             }
         }
 
-        if (newFunctionNode.hasLazyChildren()) {
-            //the final body has already been assigned as we have left the function node block body by now
-            objectifySymbols(body);
-        }
-
         List<VarNode> syntheticInitializers = null;
 
         if (body.getFlag(Block.NEEDS_SELF_SYMBOL)) {
@@ -503,8 +502,8 @@
             syntheticInitializers.add(createSyntheticInitializer(newFunctionNode.getIdent(), CALLEE, newFunctionNode));
         }
 
-        if(newFunctionNode.needsArguments()) {
-            if(syntheticInitializers == null) {
+        if (newFunctionNode.needsArguments()) {
+            if (syntheticInitializers == null) {
                 syntheticInitializers = new ArrayList<>(1);
             }
             // "var arguments = :arguments"
@@ -512,12 +511,12 @@
                     ARGUMENTS, newFunctionNode));
         }
 
-        if(syntheticInitializers != null) {
-            final List<Statement> stmts = body.getStatements();
+        if (syntheticInitializers != null) {
+            final List<Statement> stmts = newFunctionNode.getBody().getStatements();
             final List<Statement> newStatements = new ArrayList<>(stmts.size() + syntheticInitializers.size());
             newStatements.addAll(syntheticInitializers);
             newStatements.addAll(stmts);
-            newFunctionNode = newFunctionNode.setBody(lc, body.setStatements(lc, newStatements));
+            newFunctionNode = newFunctionNode.setBody(lc, newFunctionNode.getBody().setStatements(lc, newStatements));
         }
 
         if (returnTypes.peek().isUnknown()) {
@@ -558,12 +557,6 @@
     }
 
     @Override
-    public Node leaveCONVERT(final UnaryNode unaryNode) {
-        assert false : "There should be no convert operators in IR during Attribution";
-        return end(unaryNode);
-    }
-
-    @Override
     public Node leaveIdentNode(final IdentNode identNode) {
         final String name = identNode.getName();
 
@@ -991,7 +984,7 @@
 
     @Override
     public Node leaveNEW(final UnaryNode unaryNode) {
-        return end(ensureSymbol(Type.OBJECT, unaryNode));
+        return end(ensureSymbol(Type.OBJECT, unaryNode.setRHS(((CallNode)unaryNode.rhs()).setIsNew())));
     }
 
     @Override
@@ -1287,7 +1280,9 @@
     private Node leaveCmp(final BinaryNode binaryNode) {
         ensureTypeNotUnknown(binaryNode.lhs());
         ensureTypeNotUnknown(binaryNode.rhs());
-
+        Type widest = Type.widest(binaryNode.lhs().getType(), binaryNode.rhs().getType());
+        ensureSymbol(widest, binaryNode.lhs());
+        ensureSymbol(widest, binaryNode.rhs());
         return end(ensureSymbol(Type.BOOLEAN, binaryNode));
     }
 
@@ -1630,7 +1625,7 @@
                     if (!Type.areEquivalent(from, to) && Type.widest(from, to) == to) {
                         LOG.fine("Had to post pass widen '", node, "' ", Debug.id(node), " from ", node.getType(), " to ", to);
                         Symbol symbol = node.getSymbol();
-                        if(symbol.isShared() && symbol.wouldChangeType(to)) {
+                        if (symbol.isShared() && symbol.wouldChangeType(to)) {
                             symbol = temporarySymbols.getTypedTemporarySymbol(to);
                         }
                         newType(symbol, to);
@@ -1646,40 +1641,105 @@
                     return !node.isLazy();
                 }
 
-                /**
-                 * Eg.
-                 *
-                 * var d = 17;
-                 * var e;
-                 * e = d; //initially typed as int for node type, should retype as double
-                 * e = object;
-                 *
-                 * var d = 17;
-                 * var e;
-                 * e -= d; //initially type number, should number remain with a final conversion supplied by Store. ugly, but the computation result of the sub is numeric
-                 * e = object;
-                 *
-                 */
+                //
+                // Eg.
+                //
+                // var d = 17;
+                // var e;
+                // e = d; //initially typed as int for node type, should retype as double
+                // e = object;
+                //
+                // var d = 17;
+                // var e;
+                // e -= d; //initially type number, should number remain with a final conversion supplied by Store. ugly, but the computation result of the sub is numeric
+                // e = object;
+                //
                 @SuppressWarnings("fallthrough")
                 @Override
                 public Node leaveBinaryNode(final BinaryNode binaryNode) {
                     final Type widest = Type.widest(binaryNode.lhs().getType(), binaryNode.rhs().getType());
                     BinaryNode newBinaryNode = binaryNode;
-                    switch (binaryNode.tokenType()) {
-                    default:
-                        if (!binaryNode.isAssignment() || binaryNode.isSelfModifying()) {
+
+                    if (isAdd(binaryNode)) {
+                        newBinaryNode = (BinaryNode)widen(newBinaryNode, widest);
+                        if (newBinaryNode.getType().isObject() && !isAddString(newBinaryNode)) {
+                            return new RuntimeNode(newBinaryNode, Request.ADD);
+                        }
+                    } else if (binaryNode.isComparison()) {
+                        final Expression lhs = newBinaryNode.lhs();
+                        final Expression rhs = newBinaryNode.rhs();
+
+                        Type cmpWidest = Type.widest(lhs.getType(), rhs.getType());
+
+                        boolean newRuntimeNode = false, finalized = false;
+                        switch (newBinaryNode.tokenType()) {
+                        case EQ_STRICT:
+                        case NE_STRICT:
+                            if (lhs.getType().isBoolean() != rhs.getType().isBoolean()) {
+                                newRuntimeNode = true;
+                                cmpWidest = Type.OBJECT;
+                                finalized = true;
+                            }
+                            //fallthru
+                        default:
+                            if (newRuntimeNode || cmpWidest.isObject()) {
+                                return new RuntimeNode(newBinaryNode, Request.requestFor(binaryNode)).setIsFinal(finalized);
+                            }
                             break;
                         }
+
+                        return newBinaryNode;
+                    } else {
+                        if (!binaryNode.isAssignment() || binaryNode.isSelfModifying()) {
+                            return newBinaryNode;
+                        }
+                        checkThisAssignment(binaryNode);
                         newBinaryNode = newBinaryNode.setLHS(widen(newBinaryNode.lhs(), widest));
-                    case ADD:
                         newBinaryNode = (BinaryNode)widen(newBinaryNode, widest);
                     }
+
                     return newBinaryNode;
+
+                }
+
+                private boolean isAdd(final Node node) {
+                    return node.isTokenType(TokenType.ADD);
+                }
+
+                /**
+                 * Determine if the outcome of + operator is a string.
+                 *
+                 * @param node  Node to test.
+                 * @return true if a string result.
+                 */
+                private boolean isAddString(final Node node) {
+                    if (node instanceof BinaryNode && isAdd(node)) {
+                        final BinaryNode binaryNode = (BinaryNode)node;
+                        final Node lhs = binaryNode.lhs();
+                        final Node rhs = binaryNode.rhs();
+
+                        return isAddString(lhs) || isAddString(rhs);
+                    }
+
+                    return node instanceof LiteralNode<?> && ((LiteralNode<?>)node).isString();
+                }
+
+                private void checkThisAssignment(final BinaryNode binaryNode) {
+                    if (binaryNode.isAssignment()) {
+                        if (binaryNode.lhs() instanceof AccessNode) {
+                            final AccessNode accessNode = (AccessNode) binaryNode.lhs();
+
+                            if (accessNode.getBase().getSymbol().isThis()) {
+                                lc.getCurrentFunction().addThisProperty(accessNode.getProperty().getName());
+                            }
+                        }
+                    }
                 }
             });
             lc.replace(currentFunctionNode, newFunctionNode);
             currentFunctionNode = newFunctionNode;
         } while (!changed.isEmpty());
+
         return currentFunctionNode;
     }
 
@@ -1692,7 +1752,6 @@
         final Expression lhs = binaryNode.lhs();
 
         newType(lhs.getSymbol(), destType); //may not narrow if dest is already wider than destType
-//        ensureSymbol(destType, binaryNode); //for OP= nodes, the node can carry a narrower types than its lhs rhs. This is perfectly fine
 
         return end(ensureSymbol(destType, binaryNode));
     }
--- a/src/jdk/nashorn/internal/codegen/BranchOptimizer.java	Thu Oct 17 09:41:14 2013 -0700
+++ b/src/jdk/nashorn/internal/codegen/BranchOptimizer.java	Thu Oct 17 16:19:45 2013 -0700
@@ -56,10 +56,6 @@
         branchOptimizer(node, label, state);
     }
 
-    private void load(final Expression node) {
-        codegen.load(node);
-    }
-
     private void branchOptimizer(final UnaryNode unaryNode, final Label label, final boolean state) {
         final Expression rhs = unaryNode.rhs();
 
@@ -67,18 +63,16 @@
         case NOT:
             branchOptimizer(rhs, label, !state);
             return;
-        case CONVERT:
+        default:
             if (unaryNode.getType().isBoolean()) {
                 branchOptimizer(rhs, label, state);
                 return;
             }
             break;
-        default:
-            break;
         }
 
         // convert to boolean
-        load(unaryNode);
+        codegen.load(unaryNode);
         method.convert(Type.BOOLEAN);
         if (state) {
             method.ifne(label);
@@ -118,45 +112,33 @@
 
         case EQ:
         case EQ_STRICT:
-            assert rhs.getType().isEquivalentTo(lhs.getType()) : "type mismatch: " + lhs.getSymbol() + " to " + rhs.getSymbol();
-            load(lhs);
-            load(rhs);
+            codegen.loadBinaryOperands(lhs, rhs, Type.widest(lhs.getType(), rhs.getType()));
             method.conditionalJump(state ? EQ : NE, true, label);
             return;
 
         case NE:
         case NE_STRICT:
-            assert rhs.getType().isEquivalentTo(lhs.getType()) : "type mismatch: " + lhs.getSymbol() + " to " + rhs.getSymbol();
-            load(lhs);
-            load(rhs);
+            codegen.loadBinaryOperands(lhs, rhs, Type.widest(lhs.getType(), rhs.getType()));
             method.conditionalJump(state ? NE : EQ, true, label);
             return;
 
         case GE:
-            assert rhs.getType().isEquivalentTo(lhs.getType()) : "type mismatch: " + lhs.getSymbol() + " to " + rhs.getSymbol();
-            load(lhs);
-            load(rhs);
+            codegen.loadBinaryOperands(lhs, rhs, Type.widest(lhs.getType(), rhs.getType()));
             method.conditionalJump(state ? GE : LT, !state, label);
             return;
 
         case GT:
-            assert rhs.getType().isEquivalentTo(lhs.getType()) : "type mismatch: " + lhs.getSymbol() + " to " + rhs.getSymbol();
-            load(lhs);
-            load(rhs);
+            codegen.loadBinaryOperands(lhs, rhs, Type.widest(lhs.getType(), rhs.getType()));
             method.conditionalJump(state ? GT : LE, !state, label);
             return;
 
         case LE:
-            assert rhs.getType().isEquivalentTo(lhs.getType()) : "type mismatch: " + lhs.getSymbol() + " to " + rhs.getSymbol();
-            load(lhs);
-            load(rhs);
+            codegen.loadBinaryOperands(lhs, rhs, Type.widest(lhs.getType(), rhs.getType()));
             method.conditionalJump(state ? LE : GT, state, label);
             return;
 
         case LT:
-            assert rhs.getType().isEquivalentTo(lhs.getType()) : "type mismatch: " + lhs.getSymbol() + " to " + rhs.getSymbol() + " in " + binaryNode;
-            load(lhs);
-            load(rhs);
+            codegen.loadBinaryOperands(lhs, rhs, Type.widest(lhs.getType(), rhs.getType()));
             method.conditionalJump(state ? LT : GE, state, label);
             return;
 
@@ -164,7 +146,7 @@
             break;
         }
 
-        load(binaryNode);
+        codegen.load(binaryNode);
         method.convert(Type.BOOLEAN);
         if (state) {
             method.ifne(label);
@@ -187,7 +169,7 @@
             }
         }
 
-        load(node);
+        codegen.load(node);
         method.convert(Type.BOOLEAN);
         if (state) {
             method.ifne(label);
--- a/src/jdk/nashorn/internal/codegen/CodeGenerator.java	Thu Oct 17 09:41:14 2013 -0700
+++ b/src/jdk/nashorn/internal/codegen/CodeGenerator.java	Thu Oct 17 16:19:45 2013 -0700
@@ -43,7 +43,6 @@
 import static jdk.nashorn.internal.codegen.CompilerConstants.interfaceCallNoLookup;
 import static jdk.nashorn.internal.codegen.CompilerConstants.methodDescriptor;
 import static jdk.nashorn.internal.codegen.CompilerConstants.staticCallNoLookup;
-import static jdk.nashorn.internal.codegen.CompilerConstants.staticField;
 import static jdk.nashorn.internal.codegen.CompilerConstants.typeDescriptor;
 import static jdk.nashorn.internal.codegen.CompilerConstants.virtualCallNoLookup;
 import static jdk.nashorn.internal.ir.Symbol.IS_INTERNAL;
@@ -60,7 +59,6 @@
 import java.util.Iterator;
 import java.util.LinkedList;
 import java.util.List;
-import java.util.Locale;
 import java.util.Set;
 import java.util.TreeMap;
 import jdk.nashorn.internal.codegen.ClassEmitter.Flag;
@@ -111,7 +109,6 @@
 import jdk.nashorn.internal.ir.VarNode;
 import jdk.nashorn.internal.ir.WhileNode;
 import jdk.nashorn.internal.ir.WithNode;
-import jdk.nashorn.internal.ir.debug.ASTWriter;
 import jdk.nashorn.internal.ir.visitor.NodeOperatorVisitor;
 import jdk.nashorn.internal.ir.visitor.NodeVisitor;
 import jdk.nashorn.internal.objects.Global;
@@ -217,12 +214,12 @@
      * @param identNode an identity node to load
      * @return the method generator used
      */
-    private MethodEmitter loadIdent(final IdentNode identNode) {
+    private MethodEmitter loadIdent(final IdentNode identNode, final Type type) {
         final Symbol symbol = identNode.getSymbol();
 
         if (!symbol.isScope()) {
             assert symbol.hasSlot() || symbol.isParam();
-            return method.load(symbol);
+            return method.load(symbol).convert(type);
         }
 
         final String name   = symbol.getName();
@@ -243,11 +240,11 @@
             if (isFastScope(symbol)) {
                 // Only generate shared scope getter for fast-scope symbols so we know we can dial in correct scope.
                 if (symbol.getUseCount() > SharedScopeCall.FAST_SCOPE_GET_THRESHOLD) {
-                    return loadSharedScopeVar(identNode.getType(), symbol, flags);
+                    return loadSharedScopeVar(type, symbol, flags);
                 }
-                return loadFastScopeVar(identNode.getType(), symbol, flags, identNode.isFunction());
+                return loadFastScopeVar(type, symbol, flags, identNode.isFunction());
             }
-            return method.dynamicGet(identNode.getType(), identNode.getName(), flags, identNode.isFunction());
+            return method.dynamicGet(type, identNode.getName(), flags, identNode.isFunction());
         }
     }
 
@@ -313,9 +310,9 @@
         return method.dynamicGet(valueType, symbol.getName(), flags | CALLSITE_FAST_SCOPE, isMethod);
     }
 
-    private MethodEmitter storeFastScopeVar(final Type valueType, final Symbol symbol, final int flags) {
+    private MethodEmitter storeFastScopeVar(final Symbol symbol, final int flags) {
         loadFastScopeProto(symbol, true);
-        method.dynamicSet(valueType, symbol.getName(), flags | CALLSITE_FAST_SCOPE);
+        method.dynamicSet(symbol.getName(), flags | CALLSITE_FAST_SCOPE);
         return method;
     }
 
@@ -359,14 +356,61 @@
      * @return the method emitter used
      */
     MethodEmitter load(final Expression node) {
-        return load(node, false);
+        return load(node, node.hasType() ? node.getType() : null, false);
+    }
+
+    private static boolean safeLiteral(final Expression rhs) {
+        return rhs instanceof LiteralNode && !(rhs instanceof ArrayLiteralNode);
+    }
+
+    MethodEmitter loadBinaryOperands(final Expression lhs, final Expression rhs, final Type type) {
+        return loadBinaryOperands(lhs, rhs, type, false);
     }
 
-    private MethodEmitter load(final Expression node, final boolean baseAlreadyOnStack) {
+    private MethodEmitter loadBinaryOperands(final Expression lhs, final Expression rhs, final Type type, final boolean baseAlreadyOnStack) {
+        // ECMAScript 5.1 specification (sections 11.5-11.11 and 11.13) prescribes that when evaluating a binary
+        // expression "LEFT op RIGHT", the order of operations must be: LOAD LEFT, LOAD RIGHT, CONVERT LEFT, CONVERT
+        // RIGHT, EXECUTE OP. Unfortunately, doing it in this order defeats potential optimizations that arise when we
+        // can combine a LOAD with a CONVERT operation (e.g. use a dynamic getter with the conversion target type as its
+        // return value). What we do here is reorder LOAD RIGHT and CONVERT LEFT when possible; it is possible only when
+        // we can prove that executing CONVERT LEFT can't have a side effect that changes the value of LOAD RIGHT.
+        // Basically, if we know that either LEFT is not an object, or RIGHT is a constant literal, then we can do the
+        // reordering and collapse LOAD/CONVERT into a single operation; otherwise we need to do the more costly
+        // separate operations to preserve specification semantics.
+        final Type lhsType = lhs.getType();
+        if (lhsType.isObject() && !safeLiteral(rhs)) {
+            // Can't reorder. Load and convert separately.
+            load(lhs, lhsType, baseAlreadyOnStack);
+            load(rhs, rhs.getType(), false);
+            // Avoid empty SWAP, SWAP bytecode sequence if CONVERT LEFT is a no-op
+            if (!lhsType.isEquivalentTo(type)) {
+                method.swap();
+                method.convert(type);
+                method.swap();
+            }
+            method.convert(type);
+        } else {
+            // Can reorder. Combine load and convert into single operations.
+            load(lhs, type, baseAlreadyOnStack);
+            load(rhs, type, false);
+        }
+
+        return method;
+    }
+
+    MethodEmitter loadBinaryOperands(final BinaryNode node) {
+        return loadBinaryOperands(node.lhs(), node.rhs(), node.getType(), false);
+    }
+
+    private MethodEmitter load(final Expression node, final Type type) {
+        return load(node, type, false);
+    }
+
+    private MethodEmitter load(final Expression node, final Type type, final boolean baseAlreadyOnStack) {
         final Symbol symbol = node.getSymbol();
 
         // If we lack symbols, we just generate what we see.
-        if (symbol == null) {
+        if (symbol == null || type == null) {
             node.accept(this);
             return method;
         }
@@ -378,10 +422,10 @@
          */
         final CodeGenerator codegen = this;
 
-        node.accept(new NodeVisitor<LexicalContext>(new LexicalContext()) {
+        node.accept(new NodeVisitor<LexicalContext>(lc) {
             @Override
             public boolean enterIdentNode(final IdentNode identNode) {
-                loadIdent(identNode);
+                loadIdent(identNode, type);
                 return false;
             }
 
@@ -391,7 +435,7 @@
                     load(accessNode.getBase()).convert(Type.OBJECT);
                 }
                 assert method.peekType().isObject();
-                method.dynamicGet(node.getType(), accessNode.getProperty().getName(), getCallSiteFlags(), accessNode.isFunction());
+                method.dynamicGet(type, accessNode.getProperty().getName(), getCallSiteFlags(), accessNode.isFunction());
                 return false;
             }
 
@@ -401,7 +445,7 @@
                     load(indexNode.getBase()).convert(Type.OBJECT);
                     load(indexNode.getIndex());
                 }
-                method.dynamicGetIndex(node.getType(), getCallSiteFlags(), indexNode.isFunction());
+                method.dynamicGetIndex(type, getCallSiteFlags(), indexNode.isFunction());
                 return false;
             }
 
@@ -409,14 +453,36 @@
             public boolean enterFunctionNode(FunctionNode functionNode) {
                 // function nodes will always leave a constructed function object on stack, no need to load the symbol
                 // separately as in enterDefault()
+                lc.pop(functionNode);
                 functionNode.accept(codegen);
+                // NOTE: functionNode.accept() will produce a different FunctionNode that we discard. This incidentally
+                // doesn't cause problems as we're never touching FunctionNode again after it's visited here - codegen
+                // is the last element in the compilation pipeline, the AST it produces is not used externally. So, we
+                // re-push the original functionNode.
+                lc.push(functionNode);
+                method.convert(type);
                 return false;
             }
 
             @Override
+            public boolean enterCallNode(CallNode callNode) {
+                return codegen.enterCallNode(callNode, type);
+            }
+
+            @Override
+            public boolean enterLiteralNode(LiteralNode<?> literalNode) {
+                return codegen.enterLiteralNode(literalNode, type);
+            }
+
+            @Override
             public boolean enterDefault(final Node otherNode) {
+                final Node currentDiscard = codegen.lc.getCurrentDiscard();
                 otherNode.accept(codegen); // generate code for whatever we are looking at.
-                method.load(symbol); // load the final symbol to the stack (or nop if no slot, then result is already there)
+                if(currentDiscard != otherNode) {
+                    method.load(symbol); // load the final symbol to the stack (or nop if no slot, then result is already there)
+                    assert method.peekType() != null;
+                    method.convert(type);
+                }
                 return false;
             }
         });
@@ -583,15 +649,19 @@
         return argCount;
     }
 
+
     @Override
     public boolean enterCallNode(final CallNode callNode) {
+        return enterCallNode(callNode, callNode.getType());
+    }
+
+    private boolean enterCallNode(final CallNode callNode, final Type callNodeType) {
         lineNumber(callNode.getLineNumber());
 
         final List<Expression> args = callNode.getArgs();
         final Expression function = callNode.getFunction();
         final Block currentBlock = lc.getCurrentBlock();
         final CodeGeneratorLexicalContext codegenLexicalContext = lc;
-        final Type callNodeType = callNode.getType();
 
         function.accept(new NodeVisitor<LexicalContext>(new LexicalContext()) {
 
@@ -612,16 +682,14 @@
             }
 
             private void scopeCall(final IdentNode node, final int flags) {
-                load(node);
-                method.convert(Type.OBJECT); // foo() makes no sense if foo == 3
+                load(node, Type.OBJECT); // Type.OBJECT as foo() makes no sense if foo == 3
                 // ScriptFunction will see CALLSITE_SCOPE and will bind scope accordingly.
                 method.loadNull(); //the 'this'
                 method.dynamicCall(callNodeType, 2 + loadArgs(args), flags);
             }
 
             private void evalCall(final IdentNode node, final int flags) {
-                load(node);
-                method.convert(Type.OBJECT); // foo() makes no sense if foo == 3
+                load(node, Type.OBJECT); // Type.OBJECT as foo() makes no sense if foo == 3
 
                 final Label not_eval  = new Label("not_eval");
                 final Label eval_done = new Label("eval_done");
@@ -638,8 +706,7 @@
 
                 final CallNode.EvalArgs evalArgs = callNode.getEvalArgs();
                 // load evaluated code
-                load(evalArgs.getCode());
-                method.convert(Type.OBJECT);
+                load(evalArgs.getCode(), Type.OBJECT);
                 // special/extra 'eval' arguments
                 load(evalArgs.getThis());
                 method.load(evalArgs.getLocation());
@@ -690,13 +757,11 @@
 
             @Override
             public boolean enterAccessNode(final AccessNode node) {
-                load(node.getBase());
-                method.convert(Type.OBJECT);
+                load(node.getBase(), Type.OBJECT);
                 method.dup();
                 method.dynamicGet(node.getType(), node.getProperty().getName(), getCallSiteFlags(), true);
                 method.swap();
                 method.dynamicCall(callNodeType, 2 + loadArgs(args), getCallSiteFlags());
-                assert method.peekType().equals(callNodeType);
 
                 return false;
             }
@@ -727,18 +792,17 @@
 
             @Override
             public boolean enterIndexNode(final IndexNode node) {
-                load(node.getBase());
-                method.convert(Type.OBJECT);
+                load(node.getBase(), Type.OBJECT);
                 method.dup();
-                load(node.getIndex());
                 final Type indexType = node.getIndex().getType();
                 if (indexType.isObject() || indexType.isBoolean()) {
-                    method.convert(Type.OBJECT); //TODO
+                    load(node.getIndex(), Type.OBJECT); //TODO
+                } else {
+                    load(node.getIndex());
                 }
                 method.dynamicGetIndex(node.getType(), getCallSiteFlags(), true);
                 method.swap();
                 method.dynamicCall(callNodeType, 2 + loadArgs(args), getCallSiteFlags());
-                assert method.peekType().equals(callNode.getType());
 
                 return false;
             }
@@ -746,11 +810,9 @@
             @Override
             protected boolean enterDefault(final Node node) {
                 // Load up function.
-                load(function);
-                method.convert(Type.OBJECT); //TODO, e.g. booleans can be used as functions
+                load(function, Type.OBJECT); //TODO, e.g. booleans can be used as functions
                 method.loadNull(); // ScriptFunction will figure out the correct this when it sees CALLSITE_SCOPE
                 method.dynamicCall(callNodeType, 2 + loadArgs(args), getCallSiteFlags() | CALLSITE_SCOPE);
-                assert method.peekType().equals(callNode.getType());
 
                 return false;
             }
@@ -853,8 +915,7 @@
 
         final Expression init = forNode.getInit();
 
-        load(modify);
-        assert modify.getType().isObject();
+        load(modify, Type.OBJECT);
         method.invoke(forNode.isForEach() ? ScriptRuntime.TO_VALUE_ITERATOR : ScriptRuntime.TO_PROPERTY_ITERATOR);
         method.store(iter);
         method._goto(forNode.getContinueLabel());
@@ -1203,8 +1264,7 @@
         if (element == null) {
             method.loadEmpty(elementType);
         } else {
-            assert elementType.isEquivalentTo(element.getType()) : "array element type doesn't match array type";
-            load(element);
+            load(element, elementType);
         }
 
         method.arraystore();
@@ -1274,7 +1334,7 @@
     }
 
     // literal values
-    private MethodEmitter load(final LiteralNode<?> node) {
+    private MethodEmitter loadLiteral(final LiteralNode<?> node, final Type type) {
         final Object value = node.getValue();
 
         if (value == null) {
@@ -1294,15 +1354,26 @@
         } else if (value instanceof Boolean) {
             method.load((Boolean)value);
         } else if (value instanceof Integer) {
-            method.load((Integer)value);
+            if(type.isEquivalentTo(Type.NUMBER)) {
+                method.load(((Integer)value).doubleValue());
+            } else if(type.isEquivalentTo(Type.LONG)) {
+                method.load(((Integer)value).longValue());
+            } else {
+                method.load((Integer)value);
+            }
         } else if (value instanceof Long) {
-            method.load((Long)value);
+            if(type.isEquivalentTo(Type.NUMBER)) {
+                method.load(((Long)value).doubleValue());
+            } else {
+                method.load((Long)value);
+            }
         } else if (value instanceof Double) {
             method.load((Double)value);
         } else if (node instanceof ArrayLiteralNode) {
-            final ArrayType type = (ArrayType)node.getType();
-            loadArray((ArrayLiteralNode)node, type);
-            globalAllocateArray(type);
+            final ArrayLiteralNode arrayLiteral = (ArrayLiteralNode)node;
+            final ArrayType atype = arrayLiteral.getArrayType();
+            loadArray(arrayLiteral, atype);
+            globalAllocateArray(atype);
         } else {
             assert false : "Unknown literal for " + node.getClass() + " " + value.getClass() + " " + value;
         }
@@ -1346,8 +1417,12 @@
 
     @Override
     public boolean enterLiteralNode(final LiteralNode<?> literalNode) {
+        return enterLiteralNode(literalNode, literalNode.getType());
+    }
+
+    private boolean enterLiteralNode(final LiteralNode<?> literalNode, final Type type) {
         assert literalNode.getSymbol() != null : literalNode + " has no symbol";
-        load(literalNode).store(literalNode.getSymbol());
+        loadLiteral(literalNode, type).convert(type).store(literalNode.getSymbol());
         return false;
     }
 
@@ -1622,10 +1697,8 @@
                 return enterCmp(lhs, rhs, Condition.GT, type, symbol);
             case ADD:
                 Type widest = Type.widest(lhs.getType(), rhs.getType());
-                load(lhs);
-                method.convert(widest);
-                load(rhs);
-                method.convert(widest);
+                load(lhs, widest);
+                load(rhs, widest);
                 method.add();
                 method.convert(type);
                 method.store(symbol);
@@ -1638,15 +1711,15 @@
         }
 
         if (nullCheck(runtimeNode, args, new FunctionSignature(false, false, runtimeNode.getType(), args).toString())) {
-            return false;
+           return false;
         }
 
         if (!runtimeNode.isFinal() && specializationCheck(runtimeNode.getRequest(), runtimeNode, args)) {
-            return false;
+           return false;
         }
 
         for (final Expression arg : args) {
-            load(arg).convert(Type.OBJECT); //TODO this should not be necessary below Lower
+            load(arg).convert(Type.OBJECT);
         }
 
         method.invokestatic(
@@ -1903,24 +1976,15 @@
                 method.lookupswitch(defaultLabel, ints, labels);
             }
         } else {
-            load(expression);
-
-            if (expression.getType().isInteger()) {
-                method.convert(Type.NUMBER).dup();
-                method.store(tag);
-                method.conditionalJump(Condition.NE, true, defaultLabel);
-            } else {
-                assert tag.getSymbolType().isObject();
-                method.convert(Type.OBJECT); //e.g. 1 literal pushed and tag is object
-                method.store(tag);
-            }
+            load(expression, Type.OBJECT);
+            method.store(tag);
 
             for (final CaseNode caseNode : cases) {
                 final Expression test = caseNode.getTest();
 
                 if (test != null) {
                     method.load(tag);
-                    load(test);
+                    load(test, Type.OBJECT);
                     method.invoke(ScriptRuntime.EQ_STRICT);
                     method.ifne(caseNode.getEntry());
                 }
@@ -1961,8 +2025,7 @@
         final int        line       = throwNode.getLineNumber();
         final int        column     = source.getColumn(position);
 
-        load(expression);
-        assert expression.getType().isObject();
+        load(expression, Type.OBJECT);
 
         method.load(source.getName());
         method.load(line);
@@ -2087,29 +2150,28 @@
 
         lineNumber(varNode);
 
-        final Symbol varSymbol = varNode.getName().getSymbol();
-        assert varSymbol != null : "variable node " + varNode + " requires a name with a symbol";
+        final IdentNode identNode = varNode.getName();
+        final Symbol identSymbol = identNode.getSymbol();
+        assert identSymbol != null : "variable node " + varNode + " requires a name with a symbol";
 
         assert method != null;
 
-        final boolean needsScope = varSymbol.isScope();
+        final boolean needsScope = identSymbol.isScope();
         if (needsScope) {
             method.loadCompilerConstant(SCOPE);
         }
-        load(init);
 
         if (needsScope) {
+            load(init);
             int flags = CALLSITE_SCOPE | getCallSiteFlags();
-            final IdentNode identNode = varNode.getName();
-            final Type type = identNode.getType();
-            if (isFastScope(varSymbol)) {
-                storeFastScopeVar(type, varSymbol, flags);
+            if (isFastScope(identSymbol)) {
+                storeFastScopeVar(identSymbol, flags);
             } else {
-                method.dynamicSet(type, identNode.getName(), flags);
+                method.dynamicSet(identNode.getName(), flags);
             }
         } else {
-            method.convert(varNode.getName().getType()); // aw: convert moved here
-            method.store(varSymbol);
+            load(init, identNode.getType());
+            method.store(identSymbol);
         }
 
         return false;
@@ -2168,8 +2230,7 @@
             tryLabel = null;
         }
 
-        load(expression);
-        assert expression.getType().isObject() : "with expression needs to be object: " + expression;
+        load(expression, Type.OBJECT);
 
         if (hasScope) {
             // Construct a WithObject if we have a scope
@@ -2211,54 +2272,15 @@
 
     @Override
     public boolean enterADD(final UnaryNode unaryNode) {
-        load(unaryNode.rhs());
-        assert unaryNode.rhs().getType().isNumber() : unaryNode.rhs().getType() + " "+ unaryNode.getSymbol();
+        load(unaryNode.rhs(), unaryNode.getType());
+        assert unaryNode.getType().isNumeric();
         method.store(unaryNode.getSymbol());
-
         return false;
     }
 
     @Override
     public boolean enterBIT_NOT(final UnaryNode unaryNode) {
-        load(unaryNode.rhs()).convert(Type.INT).load(-1).xor().store(unaryNode.getSymbol());
-        return false;
-    }
-
-    // do this better with convert calls to method. TODO
-    @Override
-    public boolean enterCONVERT(final UnaryNode unaryNode) {
-        final Expression rhs = unaryNode.rhs();
-        final Type to  = unaryNode.getType();
-
-        if (to.isObject() && rhs instanceof LiteralNode) {
-            final LiteralNode<?> literalNode = (LiteralNode<?>)rhs;
-            final Object value = literalNode.getValue();
-
-            if (value instanceof Number) {
-                assert !to.isArray() : "type hygiene - cannot convert number to array: (" + to.getTypeClass().getSimpleName() + ')' + value;
-                if (value instanceof Integer) {
-                    method.load((Integer)value);
-                } else if (value instanceof Long) {
-                    method.load((Long)value);
-                } else if (value instanceof Double) {
-                    method.load((Double)value);
-                } else {
-                    assert false;
-                }
-                method.convert(Type.OBJECT);
-            } else if (value instanceof Boolean) {
-                method.getField(staticField(Boolean.class, value.toString().toUpperCase(Locale.ENGLISH), Boolean.class));
-            } else {
-                load(rhs);
-                method.convert(unaryNode.getType());
-            }
-        } else {
-            load(rhs);
-            method.convert(unaryNode.getType());
-        }
-
-        method.store(unaryNode.getSymbol());
-
+        load(unaryNode.rhs(), Type.INT).load(-1).xor().store(unaryNode.getSymbol());
         return false;
     }
 
@@ -2276,9 +2298,7 @@
 
             @Override
             protected void evaluate() {
-                load(rhs, true);
-
-                method.convert(type);
+                load(rhs, type, true);
                 if (!isPostfix) {
                     if (type.isInteger()) {
                         method.load(isIncrement ? 1 : -1);
@@ -2344,12 +2364,11 @@
     public boolean enterNOT(final UnaryNode unaryNode) {
         final Expression rhs = unaryNode.rhs();
 
-        load(rhs);
+        load(rhs, Type.BOOLEAN);
 
         final Label trueLabel  = new Label("true");
         final Label afterLabel = new Label("after");
 
-        method.convert(Type.BOOLEAN);
         method.ifne(trueLabel);
         method.load(true);
         method._goto(afterLabel);
@@ -2363,8 +2382,8 @@
 
     @Override
     public boolean enterSUB(final UnaryNode unaryNode) {
-        load(unaryNode.rhs()).neg().store(unaryNode.getSymbol());
-
+        assert unaryNode.getType().isNumeric();
+        load(unaryNode.rhs()).convert(unaryNode.getType()).neg().store(unaryNode.getSymbol());
         return false;
     }
 
@@ -2377,9 +2396,7 @@
     }
 
     private void enterNumericAdd(final Expression lhs, final Expression rhs, final Type type, final Symbol symbol) {
-        assert lhs.getType().equals(rhs.getType()) && lhs.getType().equals(type) : lhs.getType() + " != " + rhs.getType() + " != " + type + " " + new ASTWriter(lhs) + " " + new ASTWriter(rhs);
-        load(lhs);
-        load(rhs);
+        loadBinaryOperands(lhs, rhs, type);
         method.add(); //if the symbol is optimistic, it always needs to be written, not on the stack?
         method.store(symbol);
     }
@@ -2393,8 +2410,7 @@
         if (type.isNumeric()) {
             enterNumericAdd(lhs, rhs, type, binaryNode.getSymbol());
         } else {
-            load(lhs).convert(Type.OBJECT);
-            load(rhs).convert(Type.OBJECT);
+            loadBinaryOperands(binaryNode);
             method.add();
             method.store(binaryNode.getSymbol());
         }
@@ -2439,13 +2455,16 @@
 
         if (!lhsType.isEquivalentTo(rhsType)) {
             //this is OK if scoped, only locals are wrong
-            assert !(lhs instanceof IdentNode) || lhs.getSymbol().isScope() : new ASTWriter(binaryNode);
         }
 
         new Store<BinaryNode>(binaryNode, lhs) {
             @Override
             protected void evaluate() {
-                load(rhs);
+                if ((lhs instanceof IdentNode) && !lhs.getSymbol().isScope()) {
+                    load(rhs, lhsType);
+                } else {
+                    load(rhs);
+                }
             }
         }.store();
 
@@ -2484,8 +2503,7 @@
 
         @Override
         protected void evaluate() {
-            load(assignNode.lhs(), true).convert(opType);
-            load(assignNode.rhs()).convert(opType);
+            loadBinaryOperands(assignNode.lhs(), assignNode.rhs(), opType, true);
             op();
             method.convert(assignNode.getType());
         }
@@ -2656,8 +2674,7 @@
         protected abstract void op();
 
         protected void evaluate(final BinaryNode node) {
-            load(node.lhs());
-            load(node.rhs());
+            loadBinaryOperands(node);
             op();
             method.store(node.getSymbol());
         }
@@ -2739,11 +2756,7 @@
         final Type widest = Type.widest(lhsType, rhsType);
         assert widest.isNumeric() || widest.isBoolean() : widest;
 
-        load(lhs);
-        method.convert(widest);
-        load(rhs);
-        method.convert(widest);
-
+        loadBinaryOperands(lhs, rhs, widest);
         final Label trueLabel  = new Label("trueLabel");
         final Label afterLabel = new Label("skip");
 
@@ -2862,6 +2875,12 @@
     public boolean enterSHR(final BinaryNode binaryNode) {
         new BinaryArith() {
             @Override
+            protected void evaluate(final BinaryNode node) {
+                loadBinaryOperands(node.lhs(), node.rhs(), Type.INT);
+                op();
+                method.store(node.getSymbol());
+            }
+            @Override
             protected void op() {
                 method.shr();
                 method.convert(Type.LONG).load(JSType.MAX_UINT).and();
@@ -2893,26 +2912,22 @@
         final Label  falseLabel = new Label("ternary_false");
         final Label  exitLabel  = new Label("ternary_exit");
 
-        Type widest = Type.widest(trueExpr.getType(), falseExpr.getType());
+        Type widest = Type.widest(ternaryNode.getType(), Type.widest(trueExpr.getType(), falseExpr.getType()));
         if (trueExpr.getType().isArray() || falseExpr.getType().isArray()) { //loadArray creates a Java array type on the stack, calls global allocate, which creates a native array type
             widest = Type.OBJECT;
         }
 
-        load(test);
-        assert test.getType().isBoolean() : "lhs in ternary must be boolean";
-
+        load(test, Type.BOOLEAN);
         // we still keep the conversion here as the AccessSpecializer can have separated the types, e.g. var y = x ? x=55 : 17
         // will left as (Object)x=55 : (Object)17 by Lower. Then the first term can be {I}x=55 of type int, which breaks the
         // symmetry for the temporary slot for this TernaryNode. This is evidence that we assign types and explicit conversions
-        // to early, or Apply the AccessSpecializer too late. We are mostly probably looking for a separate type pass to
+        // too early, or Apply the AccessSpecializer too late. We are mostly probably looking for a separate type pass to
         // do this property. Then we never need any conversions in CodeGenerator
         method.ifeq(falseLabel);
-        load(trueExpr);
-        method.convert(widest);
+        load(trueExpr, widest);
         method._goto(exitLabel);
         method.label(falseLabel);
-        load(falseExpr);
-        method.convert(widest);
+        load(falseExpr, widest);
         method.label(exitLabel);
         method.store(symbol);
 
@@ -3044,8 +3059,7 @@
                     final BaseNode   baseNode = (BaseNode)target;
                     final Expression base     = baseNode.getBase();
 
-                    load(base);
-                    method.convert(Type.OBJECT);
+                    load(base, Type.OBJECT);
                     depth += Type.OBJECT.getSlots();
 
                     if (isSelfModifying()) {
@@ -3064,10 +3078,11 @@
                     enterBaseNode();
 
                     final Expression index = node.getIndex();
-                    // could be boolean here as well
-                    load(index);
                     if (!index.getType().isNumeric()) {
-                        method.convert(Type.OBJECT);
+                        // could be boolean here as well
+                        load(index, Type.OBJECT);
+                    } else {
+                        load(index);
                     }
                     depth += index.getType().getSlots();
 
@@ -3136,8 +3151,6 @@
              * need to do a conversion on non-equivalent types exists, but is
              * very rare. See for example test/script/basic/access-specializer.js
              */
-            method.convert(target.getType());
-
             target.accept(new NodeVisitor<LexicalContext>(new LexicalContext()) {
                 @Override
                 protected boolean enterDefault(Node node) {
@@ -3145,24 +3158,17 @@
                 }
 
                 @Override
-                public boolean enterUnaryNode(final UnaryNode node) {
-                    if (node.tokenType() == TokenType.CONVERT && node.getSymbol() != null) {
-                        method.convert(node.rhs().getType());
-                    }
-                    return true;
-                }
-
-                @Override
                 public boolean enterIdentNode(final IdentNode node) {
                     final Symbol symbol = node.getSymbol();
                     assert symbol != null;
                     if (symbol.isScope()) {
                         if (isFastScope(symbol)) {
-                            storeFastScopeVar(node.getType(), symbol, CALLSITE_SCOPE | getCallSiteFlags());
+                            storeFastScopeVar(symbol, CALLSITE_SCOPE | getCallSiteFlags());
                         } else {
-                            method.dynamicSet(node.getType(), node.getName(), CALLSITE_SCOPE | getCallSiteFlags());
+                            method.dynamicSet(node.getName(), CALLSITE_SCOPE | getCallSiteFlags());
                         }
                     } else {
+                        method.convert(node.getType());
                         method.store(symbol);
                     }
                     return false;
@@ -3171,7 +3177,7 @@
 
                 @Override
                 public boolean enterAccessNode(final AccessNode node) {
-                    method.dynamicSet(node.getProperty().getType(), node.getProperty().getName(), getCallSiteFlags());
+                    method.dynamicSet(node.getProperty().getName(), getCallSiteFlags());
                     return false;
                 }
 
--- a/src/jdk/nashorn/internal/codegen/CompilationPhase.java	Thu Oct 17 09:41:14 2013 -0700
+++ b/src/jdk/nashorn/internal/codegen/CompilationPhase.java	Thu Oct 17 16:19:45 2013 -0700
@@ -162,7 +162,7 @@
     LOWERING_PHASE(EnumSet.of(INITIALIZED, PARSED, CONSTANT_FOLDED)) {
         @Override
         FunctionNode transform(final Compiler compiler, final FunctionNode fn) {
-            return (FunctionNode)fn.accept(new Lower());
+            return (FunctionNode)fn.accept(new Lower(compiler.getCodeInstaller()));
         }
 
         @Override
--- a/src/jdk/nashorn/internal/codegen/CompileUnit.java	Thu Oct 17 09:41:14 2013 -0700
+++ b/src/jdk/nashorn/internal/codegen/CompileUnit.java	Thu Oct 17 16:19:45 2013 -0700
@@ -28,7 +28,7 @@
 /**
  * Used to track split class compilation.
  */
-public class CompileUnit {
+public class CompileUnit implements Comparable<CompileUnit> {
     /** Current class name */
     private final String className;
 
@@ -116,4 +116,9 @@
     public String toString() {
         return "[classname=" + className + " weight=" + weight + '/' + Splitter.SPLIT_THRESHOLD + ']';
     }
+
+    @Override
+    public int compareTo(CompileUnit o) {
+        return className.compareTo(o.className);
+    }
 }
--- a/src/jdk/nashorn/internal/codegen/Compiler.java	Thu Oct 17 09:41:14 2013 -0700
+++ b/src/jdk/nashorn/internal/codegen/Compiler.java	Thu Oct 17 16:19:45 2013 -0700
@@ -36,8 +36,6 @@
 import static jdk.nashorn.internal.codegen.CompilerConstants.THIS;
 import static jdk.nashorn.internal.codegen.CompilerConstants.VARARGS;
 
-import jdk.nashorn.internal.ir.TemporarySymbols;
-
 import java.io.File;
 import java.lang.reflect.Field;
 import java.security.AccessController;
@@ -48,18 +46,20 @@
 import java.util.Comparator;
 import java.util.EnumSet;
 import java.util.HashMap;
-import java.util.HashSet;
+import java.util.LinkedHashMap;
 import java.util.LinkedList;
 import java.util.List;
 import java.util.Map;
 import java.util.Map.Entry;
 import java.util.Set;
+import java.util.TreeSet;
 import java.util.logging.Level;
 import jdk.internal.dynalink.support.NameCodec;
 import jdk.nashorn.internal.codegen.ClassEmitter.Flag;
 import jdk.nashorn.internal.codegen.types.Type;
 import jdk.nashorn.internal.ir.FunctionNode;
 import jdk.nashorn.internal.ir.FunctionNode.CompilationState;
+import jdk.nashorn.internal.ir.TemporarySymbols;
 import jdk.nashorn.internal.ir.debug.ClassHistogramElement;
 import jdk.nashorn.internal.ir.debug.ObjectSizeCalculator;
 import jdk.nashorn.internal.runtime.CodeInstaller;
@@ -256,8 +256,8 @@
         this.sequence      = sequence;
         this.installer     = installer;
         this.constantData  = new ConstantData();
-        this.compileUnits  = new HashSet<>();
-        this.bytecode      = new HashMap<>();
+        this.compileUnits  = new TreeSet<>();
+        this.bytecode      = new LinkedHashMap<>();
     }
 
     private void initCompiler(final FunctionNode functionNode) {
--- a/src/jdk/nashorn/internal/codegen/FinalizeTypes.java	Thu Oct 17 09:41:14 2013 -0700
+++ b/src/jdk/nashorn/internal/codegen/FinalizeTypes.java	Thu Oct 17 16:19:45 2013 -0700
@@ -28,49 +28,22 @@
 import static jdk.nashorn.internal.codegen.CompilerConstants.CALLEE;
 import static jdk.nashorn.internal.codegen.CompilerConstants.SCOPE;
 
-import java.util.ArrayList;
-import java.util.HashSet;
-import java.util.List;
-import jdk.nashorn.internal.codegen.types.Type;
-import jdk.nashorn.internal.ir.AccessNode;
-import jdk.nashorn.internal.ir.Assignment;
 import jdk.nashorn.internal.ir.BinaryNode;
 import jdk.nashorn.internal.ir.Block;
-import jdk.nashorn.internal.ir.CallNode;
-import jdk.nashorn.internal.ir.CaseNode;
-import jdk.nashorn.internal.ir.CatchNode;
 import jdk.nashorn.internal.ir.Expression;
 import jdk.nashorn.internal.ir.ExpressionStatement;
 import jdk.nashorn.internal.ir.ForNode;
 import jdk.nashorn.internal.ir.FunctionNode;
 import jdk.nashorn.internal.ir.FunctionNode.CompilationState;
-import jdk.nashorn.internal.ir.IdentNode;
-import jdk.nashorn.internal.ir.IfNode;
-import jdk.nashorn.internal.ir.IndexNode;
 import jdk.nashorn.internal.ir.LexicalContext;
-import jdk.nashorn.internal.ir.LiteralNode;
-import jdk.nashorn.internal.ir.LiteralNode.ArrayLiteralNode;
 import jdk.nashorn.internal.ir.Node;
-import jdk.nashorn.internal.ir.ReturnNode;
-import jdk.nashorn.internal.ir.RuntimeNode;
-import jdk.nashorn.internal.ir.RuntimeNode.Request;
-import jdk.nashorn.internal.ir.SwitchNode;
 import jdk.nashorn.internal.ir.Symbol;
 import jdk.nashorn.internal.ir.TemporarySymbols;
-import jdk.nashorn.internal.ir.TernaryNode;
-import jdk.nashorn.internal.ir.ThrowNode;
-import jdk.nashorn.internal.ir.TypeOverride;
 import jdk.nashorn.internal.ir.UnaryNode;
-import jdk.nashorn.internal.ir.VarNode;
-import jdk.nashorn.internal.ir.WhileNode;
-import jdk.nashorn.internal.ir.WithNode;
 import jdk.nashorn.internal.ir.visitor.NodeOperatorVisitor;
-import jdk.nashorn.internal.ir.visitor.NodeVisitor;
 import jdk.nashorn.internal.parser.Token;
 import jdk.nashorn.internal.parser.TokenType;
-import jdk.nashorn.internal.runtime.Debug;
 import jdk.nashorn.internal.runtime.DebugLogger;
-import jdk.nashorn.internal.runtime.JSType;
 
 /**
  * Lower to more primitive operations. After lowering, an AST has symbols and
@@ -97,272 +70,32 @@
     }
 
     @Override
-    public Node leaveCallNode(final CallNode callNode) {
-        // AccessSpecializer - call return type may change the access for this location
-        final Node function = callNode.getFunction();
-        if (function instanceof FunctionNode) {
-            return setTypeOverride(callNode, ((FunctionNode)function).getReturnType());
-        }
-        return callNode;
-    }
-
-    private Node leaveUnary(final UnaryNode unaryNode) {
-        return unaryNode.setRHS(convert(unaryNode.rhs(), unaryNode.getType()));
-    }
-
-    @Override
-    public Node leaveADD(final UnaryNode unaryNode) {
-        return leaveUnary(unaryNode);
-    }
-
-    @Override
-    public Node leaveBIT_NOT(final UnaryNode unaryNode) {
-        return leaveUnary(unaryNode);
-    }
-
-    @Override
-    public Node leaveCONVERT(final UnaryNode unaryNode) {
-        assert unaryNode.rhs().tokenType() != TokenType.CONVERT : "convert(convert encountered. check its origin and remove it";
-        return unaryNode;
-    }
-
-    @Override
-    public Node leaveDECINC(final UnaryNode unaryNode) {
-        return specialize(unaryNode).node;
-    }
-
-    @Override
-    public Node leaveNEW(final UnaryNode unaryNode) {
-        assert unaryNode.getSymbol() != null && unaryNode.getSymbol().getSymbolType().isObject();
-        return unaryNode.setRHS(((CallNode)unaryNode.rhs()).setIsNew());
-    }
-
-    @Override
-    public Node leaveSUB(final UnaryNode unaryNode) {
-        return leaveUnary(unaryNode);
-    }
-
-    /**
-     * Add is a special binary, as it works not only on arithmetic, but for
-     * strings etc as well.
-     */
-    @Override
-    public Expression leaveADD(final BinaryNode binaryNode) {
-        final Expression lhs = binaryNode.lhs();
-        final Expression rhs = binaryNode.rhs();
-
-        final Type type = binaryNode.getType();
-
-        if (type.isObject()) {
-            if (!isAddString(binaryNode)) {
-                return new RuntimeNode(binaryNode, Request.ADD);
-            }
+    public Node leaveForNode(final ForNode forNode) {
+        if (forNode.isForIn()) {
+            return forNode;
         }
 
-        return binaryNode.setLHS(convert(lhs, type)).setRHS(convert(rhs, type));
-    }
-
-    @Override
-    public Node leaveAND(final BinaryNode binaryNode) {
-        return binaryNode;
-    }
-
-    @Override
-    public Node leaveASSIGN(final BinaryNode binaryNode) {
-        final SpecializedNode specialized = specialize(binaryNode);
-        final BinaryNode specBinaryNode = (BinaryNode)specialized.node;
-        Type destType = specialized.type;
-        if (destType == null) {
-            destType = specBinaryNode.getType();
-        }
-        // Register assignments to this object in case this is used as constructor
-        if (binaryNode.lhs() instanceof AccessNode) {
-            AccessNode accessNode = (AccessNode) binaryNode.lhs();
-
-            if (accessNode.getBase().getSymbol().isThis()) {
-                lc.getCurrentFunction().addThisProperty(accessNode.getProperty().getName());
-            }
-        }
-        return specBinaryNode.setRHS(convert(specBinaryNode.rhs(), destType));
-    }
-
-    @Override
-    public Node leaveASSIGN_ADD(final BinaryNode binaryNode) {
-        return leaveASSIGN(binaryNode);
-    }
-
-    @Override
-    public Node leaveASSIGN_BIT_AND(final BinaryNode binaryNode) {
-        return leaveASSIGN(binaryNode);
-    }
-
-    @Override
-    public Node leaveASSIGN_BIT_OR(final BinaryNode binaryNode) {
-        return leaveASSIGN(binaryNode);
-    }
-
-    @Override
-    public Node leaveASSIGN_BIT_XOR(final BinaryNode binaryNode) {
-        return leaveASSIGN(binaryNode);
-    }
-
-    @Override
-    public Node leaveASSIGN_DIV(final BinaryNode binaryNode) {
-        return leaveASSIGN(binaryNode);
-    }
+        final Expression init   = forNode.getInit();
+        final Expression test   = forNode.getTest();
+        final Expression modify = forNode.getModify();
 
-    @Override
-    public Node leaveASSIGN_MOD(final BinaryNode binaryNode) {
-        return leaveASSIGN(binaryNode);
-    }
-
-    @Override
-    public Node leaveASSIGN_MUL(final BinaryNode binaryNode) {
-        return leaveASSIGN(binaryNode);
-    }
-
-    @Override
-    public Node leaveASSIGN_SAR(final BinaryNode binaryNode) {
-        return leaveASSIGN(binaryNode);
-    }
-
-    @Override
-    public Node leaveASSIGN_SHL(final BinaryNode binaryNode) {
-        return leaveASSIGN(binaryNode);
-    }
-
-    @Override
-    public Node leaveASSIGN_SHR(final BinaryNode binaryNode) {
-        return leaveASSIGN(binaryNode);
-    }
+        assert test != null || forNode.hasGoto() : "forNode " + forNode + " needs goto and is missing it in " + lc.getCurrentFunction();
 
-    @Override
-    public Node leaveASSIGN_SUB(final BinaryNode binaryNode) {
-        return leaveASSIGN(binaryNode);
-    }
-
-    private boolean symbolIsInteger(final Expression node) {
-        final Symbol symbol = node.getSymbol();
-        assert symbol != null && symbol.getSymbolType().isInteger() : "int coercion expected: " + Debug.id(symbol) + " " + symbol + " " + lc.getCurrentFunction().getSource();
-        return true;
-    }
-
-    @Override
-    public Node leaveBIT_AND(final BinaryNode binaryNode) {
-        assert symbolIsInteger(binaryNode);
-        return leaveBinary(binaryNode, Type.INT, Type.INT);
-    }
-
-    @Override
-    public Node leaveBIT_OR(final BinaryNode binaryNode) {
-        assert symbolIsInteger(binaryNode);
-        return leaveBinary(binaryNode, Type.INT, Type.INT);
-    }
-
-    @Override
-    public Node leaveBIT_XOR(final BinaryNode binaryNode) {
-        assert symbolIsInteger(binaryNode);
-        return leaveBinary(binaryNode, Type.INT, Type.INT);
+        return forNode.
+            setInit(lc, init == null ? null : discard(init)).
+            setModify(lc, modify == null ? null : discard(modify));
     }
 
     @Override
     public Node leaveCOMMALEFT(final BinaryNode binaryNode) {
         assert binaryNode.getSymbol() != null;
-        final BinaryNode newBinaryNode = binaryNode.setRHS(discard(binaryNode.rhs()));
-        // AccessSpecializer - the type of lhs, which is the remaining value of this node may have changed
-        // in that case, update the node type as well
-        return propagateType(newBinaryNode, newBinaryNode.lhs().getType());
+        return binaryNode.setRHS(discard(binaryNode.rhs()));
     }
 
     @Override
     public Node leaveCOMMARIGHT(final BinaryNode binaryNode) {
         assert binaryNode.getSymbol() != null;
-        final BinaryNode newBinaryNode = binaryNode.setLHS(discard(binaryNode.lhs()));
-        // AccessSpecializer - the type of rhs, which is the remaining value of this node may have changed
-        // in that case, update the node type as well
-        return propagateType(newBinaryNode, newBinaryNode.rhs().getType());
-    }
-
-    @Override
-    public Node leaveDIV(final BinaryNode binaryNode) {
-        return leaveBinaryArith(binaryNode);
-    }
-
-
-    @Override
-    public Node leaveEQ(final BinaryNode binaryNode) {
-        return leaveCmp(binaryNode, Request.EQ);
-    }
-
-    @Override
-    public Node leaveEQ_STRICT(final BinaryNode binaryNode) {
-        return leaveCmp(binaryNode, Request.EQ_STRICT);
-    }
-
-    @Override
-    public Node leaveGE(final BinaryNode binaryNode) {
-        return leaveCmp(binaryNode, Request.GE);
-    }
-
-    @Override
-    public Node leaveGT(final BinaryNode binaryNode) {
-        return leaveCmp(binaryNode, Request.GT);
-    }
-
-    @Override
-    public Node leaveLE(final BinaryNode binaryNode) {
-        return leaveCmp(binaryNode, Request.LE);
-    }
-
-    @Override
-    public Node leaveLT(final BinaryNode binaryNode) {
-        return leaveCmp(binaryNode, Request.LT);
-    }
-
-    @Override
-    public Node leaveMOD(final BinaryNode binaryNode) {
-        return leaveBinaryArith(binaryNode);
-    }
-
-    @Override
-    public Node leaveMUL(final BinaryNode binaryNode) {
-        return leaveBinaryArith(binaryNode);
-    }
-
-    @Override
-    public Node leaveNE(final BinaryNode binaryNode) {
-        return leaveCmp(binaryNode, Request.NE);
-    }
-
-    @Override
-    public Node leaveNE_STRICT(final BinaryNode binaryNode) {
-        return leaveCmp(binaryNode, Request.NE_STRICT);
-    }
-
-    @Override
-    public Node leaveOR(final BinaryNode binaryNode) {
-        return binaryNode;
-    }
-
-    @Override
-    public Node leaveSAR(final BinaryNode binaryNode) {
-        return leaveBinary(binaryNode, Type.INT, Type.INT);
-    }
-
-    @Override
-    public Node leaveSHL(final BinaryNode binaryNode) {
-        return leaveBinary(binaryNode, Type.INT, Type.INT);
-    }
-
-    @Override
-    public Node leaveSHR(final BinaryNode binaryNode) {
-        assert binaryNode.getSymbol() != null && binaryNode.getSymbol().getSymbolType().isLong() : "long coercion expected: " + binaryNode.getSymbol();
-        return leaveBinary(binaryNode, Type.INT, Type.INT);
-    }
-
-    @Override
-    public Node leaveSUB(final BinaryNode binaryNode) {
-        return leaveBinaryArith(binaryNode);
+        return binaryNode.setLHS(discard(binaryNode.lhs()));
     }
 
     @Override
@@ -372,38 +105,12 @@
     }
 
     @Override
-    public Node leaveCatchNode(final CatchNode catchNode) {
-        final Expression exceptionCondition = catchNode.getExceptionCondition();
-        if (exceptionCondition != null) {
-            return catchNode.setExceptionCondition(convert(exceptionCondition, Type.BOOLEAN));
-        }
-        return catchNode;
-    }
-
-    @Override
     public Node leaveExpressionStatement(final ExpressionStatement expressionStatement) {
         temporarySymbols.reuse();
         return expressionStatement.setExpression(discard(expressionStatement.getExpression()));
     }
 
     @Override
-    public Node leaveForNode(final ForNode forNode) {
-        final Expression init   = forNode.getInit();
-        final Expression test   = forNode.getTest();
-        final Expression modify = forNode.getModify();
-
-        if (forNode.isForIn()) {
-            return forNode.setModify(lc, convert(forNode.getModify(), Type.OBJECT)); // NASHORN-400
-        }
-        assert test != null || forNode.hasGoto() : "forNode " + forNode + " needs goto and is missing it in " + lc.getCurrentFunction();
-
-        return forNode.
-            setInit(lc, init == null ? null : discard(init)).
-            setTest(lc, test == null ? null : convert(test, Type.BOOLEAN)).
-            setModify(lc, modify == null ? null : discard(modify));
-    }
-
-    @Override
     public boolean enterFunctionNode(final FunctionNode functionNode) {
         if (functionNode.isLazy()) {
             return false;
@@ -430,113 +137,6 @@
         return functionNode.setState(lc, CompilationState.FINALIZED);
     }
 
-    @Override
-    public Node leaveIfNode(final IfNode ifNode) {
-        return ifNode.setTest(convert(ifNode.getTest(), Type.BOOLEAN));
-    }
-
-    @SuppressWarnings("rawtypes")
-    @Override
-    public boolean enterLiteralNode(final LiteralNode literalNode) {
-        if (literalNode instanceof ArrayLiteralNode) {
-            final ArrayLiteralNode arrayLiteralNode = (ArrayLiteralNode)literalNode;
-            final Expression[]     array            = arrayLiteralNode.getValue();
-            final Type             elementType      = arrayLiteralNode.getElementType();
-
-            for (int i = 0; i < array.length; i++) {
-                final Node element = array[i];
-                if (element != null) {
-                    array[i] = convert((Expression)element.accept(this), elementType);
-                }
-            }
-        }
-
-        return false;
-    }
-
-    @Override
-    public Node leaveReturnNode(final ReturnNode returnNode) {
-        final Expression expr = returnNode.getExpression();
-        if (expr != null) {
-            return returnNode.setExpression(convert(expr, lc.getCurrentFunction().getReturnType()));
-        }
-        return returnNode;
-    }
-
-    @Override
-    public Node leaveRuntimeNode(final RuntimeNode runtimeNode) {
-        final List<Expression> args = runtimeNode.getArgs();
-        for (final Expression arg : args) {
-            assert !arg.getType().isUnknown();
-        }
-        return runtimeNode;
-    }
-
-    @Override
-    public Node leaveSwitchNode(final SwitchNode switchNode) {
-        final boolean allInteger = switchNode.getTag().getSymbolType().isInteger();
-
-        if (allInteger) {
-            return switchNode;
-        }
-
-        final Expression     expression  = switchNode.getExpression();
-        final List<CaseNode> cases       = switchNode.getCases();
-        final List<CaseNode> newCases    = new ArrayList<>();
-
-        for (final CaseNode caseNode : cases) {
-            final Expression test = caseNode.getTest();
-            newCases.add(test != null ? caseNode.setTest(convert(test, Type.OBJECT)) : caseNode);
-        }
-
-        return switchNode.
-            setExpression(lc, convert(expression, Type.OBJECT)).
-            setCases(lc, newCases);
-    }
-
-    @Override
-    public Node leaveTernaryNode(final TernaryNode ternaryNode) {
-        return ternaryNode.setTest(convert(ternaryNode.getTest(), Type.BOOLEAN));
-    }
-
-    @Override
-    public Node leaveThrowNode(final ThrowNode throwNode) {
-        return throwNode.setExpression(convert(throwNode.getExpression(), Type.OBJECT));
-    }
-
-    @Override
-    public Node leaveVarNode(final VarNode varNode) {
-        final Expression init = varNode.getInit();
-        if (init != null) {
-            final SpecializedNode specialized = specialize(varNode);
-            final VarNode specVarNode = (VarNode)specialized.node;
-            Type destType = specialized.type;
-            if (destType == null) {
-                destType = specVarNode.getName().getType();
-            }
-            assert specVarNode.getName().hasType() : specVarNode + " doesn't have a type";
-            final Expression convertedInit = convert(init, destType);
-            temporarySymbols.reuse();
-            return specVarNode.setInit(convertedInit);
-        }
-        temporarySymbols.reuse();
-        return varNode;
-    }
-
-    @Override
-    public Node leaveWhileNode(final WhileNode whileNode) {
-        final Expression test = whileNode.getTest();
-        if (test != null) {
-            return whileNode.setTest(lc, convert(test, Type.BOOLEAN));
-        }
-        return whileNode;
-    }
-
-    @Override
-    public Node leaveWithNode(final WithNode withNode) {
-        return withNode.setExpression(lc, convert(withNode.getExpression(), Type.OBJECT));
-    }
-
     private static void updateSymbolsLog(final FunctionNode functionNode, final Symbol symbol, final boolean loseSlot) {
         if (LOG.isEnabled()) {
             if (!symbol.isScope()) {
@@ -583,260 +183,6 @@
         }
     }
 
-    /**
-     * Exit a comparison node and do the appropriate replacements. We need to introduce runtime
-     * nodes late for comparisons as types aren't known until the last minute
-     *
-     * Both compares and adds may turn into runtimes node at this level as when we first bump
-     * into the op in Attr, we may type it according to what we know there, which may be wrong later
-     *
-     * e.g. i (int) < 5 -> normal compare
-     *     i = object
-     *  then the post pass that would add the conversion to the 5 needs to
-     *
-     * @param binaryNode binary node to leave
-     * @param request    runtime request
-     * @return lowered cmp node
-     */
-    @SuppressWarnings("fallthrough")
-    private Node leaveCmp(final BinaryNode binaryNode, final RuntimeNode.Request request) {
-        final Expression lhs    = binaryNode.lhs();
-        final Expression rhs    = binaryNode.rhs();
-
-        Type widest = Type.widest(lhs.getType(), rhs.getType());
-
-        boolean newRuntimeNode = false, finalized = false;
-        switch (request) {
-        case EQ_STRICT:
-        case NE_STRICT:
-            if (lhs.getType().isBoolean() != rhs.getType().isBoolean()) {
-                newRuntimeNode = true;
-                widest = Type.OBJECT;
-                finalized = true;
-            }
-            //fallthru
-        default:
-            if (newRuntimeNode || widest.isObject()) {
-                return new RuntimeNode(binaryNode, request).setIsFinal(finalized);
-            }
-            break;
-        }
-
-        return binaryNode.setLHS(convert(lhs, widest)).setRHS(convert(rhs, widest));
-    }
-
-    /**
-     * Compute the binary arithmetic type given the lhs and an rhs of a binary expression
-     * @param lhsType  the lhs type
-     * @param rhsType  the rhs type
-     * @return the correct binary type
-     */
-    private static Type binaryArithType(final Type lhsType, final Type rhsType) {
-        if (!Compiler.shouldUseIntegerArithmetic()) {
-            return Type.NUMBER;
-        }
-        return Type.widest(lhsType, rhsType, Type.NUMBER);
-    }
-
-    private Node leaveBinaryArith(final BinaryNode binaryNode) {
-        final Type type = binaryArithType(binaryNode.lhs().getType(), binaryNode.rhs().getType());
-        return leaveBinary(binaryNode, type, type);
-    }
-
-    private Node leaveBinary(final BinaryNode binaryNode, final Type lhsType, final Type rhsType) {
-        Node b =  binaryNode.setLHS(convert(binaryNode.lhs(), lhsType)).setRHS(convert(binaryNode.rhs(), rhsType));
-        return b;
-    }
-
-    /**
-     * A symbol (and {@link jdk.nashorn.internal.runtime.Property}) can be tagged as "may be primitive".
-     * This is used a hint for dual fields that it is even worth it to try representing this
-     * field as something other than java.lang.Object.
-     *
-     * @param node node in which to tag symbols as primitive
-     * @param to   which primitive type to use for tagging
-     */
-    private static void setCanBePrimitive(final Node node, final Type to) {
-        final HashSet<Node> exclude = new HashSet<>();
-
-        node.accept(new NodeVisitor<LexicalContext>(new LexicalContext()) {
-            private void setCanBePrimitive(final Symbol symbol) {
-                LOG.info("*** can be primitive symbol ", symbol, " ", Debug.id(symbol));
-                symbol.setCanBePrimitive(to);
-            }
-
-            @Override
-            public boolean enterIdentNode(final IdentNode identNode) {
-                if (!exclude.contains(identNode)) {
-                    setCanBePrimitive(identNode.getSymbol());
-                }
-                return false;
-            }
-
-            @Override
-            public boolean enterAccessNode(final AccessNode accessNode) {
-                setCanBePrimitive(accessNode.getProperty().getSymbol());
-                return false;
-            }
-
-            @Override
-            public boolean enterIndexNode(final IndexNode indexNode) {
-                exclude.add(indexNode.getBase()); //prevent array base node to be flagged as primitive, but k in a[k++] is fine
-                return true;
-            }
-        });
-    }
-
-    private static class SpecializedNode {
-        final Node node;
-        final Type type;
-
-        SpecializedNode(Node node, Type type) {
-            this.node = node;
-            this.type = type;
-        }
-    }
-
-    <T extends Expression> SpecializedNode specialize(final Assignment<T> assignment) {
-        final Node node = ((Node)assignment);
-        final T lhs = assignment.getAssignmentDest();
-        final Expression rhs = assignment.getAssignmentSource();
-
-        if (!canHaveCallSiteType(lhs)) {
-            return new SpecializedNode(node, null);
-        }
-
-        final Type to;
-        if (node.isSelfModifying()) {
-            to = node.getWidestOperationType();
-        } else {
-            to = rhs.getType();
-        }
-
-        if (!isSupportedCallSiteType(to)) {
-            //meaningless to specialize to boolean or object
-            return new SpecializedNode(node, null);
-        }
-
-        final Node newNode = assignment.setAssignmentDest(setTypeOverride(lhs, to));
-        final Node typePropagatedNode;
-        if(newNode instanceof Expression) {
-            typePropagatedNode = propagateType((Expression)newNode, to);
-        } else if(newNode instanceof VarNode) {
-            // VarNode, being a statement, doesn't have its own symbol; it uses the symbol of its name instead.
-            final VarNode varNode = (VarNode)newNode;
-            typePropagatedNode = varNode.setName((IdentNode)propagateType(varNode.getName(), to));
-        } else {
-            throw new AssertionError();
-        }
-        return new SpecializedNode(typePropagatedNode, to);
-    }
-
-
-    /**
-     * Is this a node that can have its type overridden. This is true for
-     * AccessNodes, IndexNodes and IdentNodes
-     *
-     * @param node the node to check
-     * @return true if node can have a callsite type
-     */
-    private static boolean canHaveCallSiteType(final Node node) {
-        return node instanceof TypeOverride && ((TypeOverride<?>)node).canHaveCallSiteType();
-    }
-
-    /**
-     * Is the specialization type supported. Currently we treat booleans as objects
-     * and have no special boolean type accessor, thus booleans are ignored.
-     * TODO - support booleans? NASHORN-590
-     *
-     * @param castTo the type to check
-     * @return true if call site type is supported
-     */
-    private static boolean isSupportedCallSiteType(final Type castTo) {
-        return castTo.isNumeric(); // don't specializable for boolean
-    }
-
-    /**
-     * Override the type of a node for e.g. access specialization of scope
-     * objects. Normally a variable can only get a wider type and narrower type
-     * sets are ignored. Not that a variable can still be on object type as
-     * per the type analysis, but a specific access may be narrower, e.g. if it
-     * is used in an arithmetic op. This overrides a type, regardless of
-     * type environment and is used primarily by the access specializer
-     *
-     * @param node    node for which to change type
-     * @param to      new type
-     */
-    @SuppressWarnings("unchecked")
-    <T extends Expression> T setTypeOverride(final T node, final Type to) {
-        final Type from = node.getType();
-        if (!node.getType().equals(to)) {
-            LOG.info("Changing call override type for '", node, "' from ", node.getType(), " to ", to);
-            if (!to.isObject() && from.isObject()) {
-                setCanBePrimitive(node, to);
-            }
-        }
-        LOG.info("Type override for lhs in '", node, "' => ", to);
-        return ((TypeOverride<T>)node).setType(temporarySymbols, lc, to);
-    }
-
-    /**
-     * Add an explicit conversion. This is needed when attribution has created types
-     * that do not mesh into an op type, e.g. a = b, where b is object and a is double
-     * at the end of Attr, needs explicit conversion logic.
-     *
-     * An explicit conversion can be one of the following:
-     *   + Convert a literal - just replace it with another literal
-     *   + Convert a scope object - just replace the type of the access, e.g. get()D->get()I
-     *   + Explicit convert placement, e.g. a = (double)b - all other cases
-     *
-     * No other part of the world after {@link Attr} may introduce new symbols. This
-     * is the only place.
-     *
-     * @param node node to convert
-     * @param to   destination type
-     * @return     conversion node
-     */
-    private Expression convert(final Expression node, final Type to) {
-        assert !to.isUnknown() : "unknown type for " + node + " class=" + node.getClass();
-        assert node != null : "node is null";
-        assert node.getSymbol() != null : "node " + node + " " + node.getClass() + " has no symbol! " + lc.getCurrentFunction();
-        assert node.tokenType() != TokenType.CONVERT : "assert convert in convert " + node + " in " + lc.getCurrentFunction();
-
-        final Type from = node.getType();
-
-        if (Type.areEquivalent(from, to)) {
-            return node;
-        }
-
-        if (from.isObject() && to.isObject()) {
-            return node;
-        }
-
-        Expression resultNode = node;
-
-        if (node instanceof LiteralNode && !(node instanceof ArrayLiteralNode) && !to.isObject()) {
-            final LiteralNode<?> newNode = new LiteralNodeConstantEvaluator((LiteralNode<?>)node, to).eval();
-            if (newNode != null) {
-                resultNode = newNode;
-            }
-        } else {
-            if (canHaveCallSiteType(node) && isSupportedCallSiteType(to)) {
-                assert node instanceof TypeOverride;
-                return setTypeOverride(node, to);
-            }
-            resultNode = new UnaryNode(Token.recast(node.getToken(), TokenType.CONVERT), node);
-        }
-
-        LOG.info("CONVERT('", node, "', ", to, ") => '", resultNode, "'");
-
-        assert !node.isTerminal();
-
-        //This is the only place in this file that can create new temporaries
-        //FinalizeTypes may not introduce ANY node that is not a conversion.
-        return temporarySymbols.ensureSymbol(lc, to, resultNode);
-    }
-
     private static Expression discard(final Expression node) {
         if (node.getSymbol() != null) {
             final UnaryNode discard = new UnaryNode(Token.recast(node.getToken(), TokenType.DISCARD), node);
@@ -849,82 +195,5 @@
         return node;
     }
 
-    /**
-     * Whenever an expression like an addition or an assignment changes type, it
-     * may be that case that {@link Attr} created a symbol for an intermediate
-     * result of the expression, say for an addition. This also has to be updated
-     * if the expression type changes.
-     *
-     * Assignments use their lhs as node symbol, and in this case we can't modify
-     * it. Then {@link CodeGenerator.Store} needs to do an explicit conversion.
-     * This is happens very rarely.
-     *
-     * @param node
-     * @param to
-     */
-    private Expression propagateType(final Expression node, final Type to) {
-        Symbol symbol = node.getSymbol();
-        if (symbol.isTemp() && symbol.getSymbolType() != to) {
-            symbol = symbol.setTypeOverrideShared(to, temporarySymbols);
-            LOG.info("Type override for temporary in '", node, "' => ", to);
-        }
-        return node.setSymbol(lc, symbol);
-    }
 
-    /**
-     * Determine if the outcome of + operator is a string.
-     *
-     * @param node  Node to test.
-     * @return true if a string result.
-     */
-    private boolean isAddString(final Node node) {
-        if (node instanceof BinaryNode && node.isTokenType(TokenType.ADD)) {
-            final BinaryNode binaryNode = (BinaryNode)node;
-            final Node lhs = binaryNode.lhs();
-            final Node rhs = binaryNode.rhs();
-
-            return isAddString(lhs) || isAddString(rhs);
-        }
-
-        return node instanceof LiteralNode<?> && ((LiteralNode<?>)node).isString();
-    }
-
-    /**
-     * Whenever an explicit conversion is needed and the convertee is a literal, we can
-     * just change the literal
-     */
-    class LiteralNodeConstantEvaluator extends FoldConstants.ConstantEvaluator<LiteralNode<?>> {
-        private final Type type;
-
-        LiteralNodeConstantEvaluator(final LiteralNode<?> parent, final Type type) {
-            super(parent);
-            this.type = type;
-        }
-
-        @Override
-        protected LiteralNode<?> eval() {
-            final Object value = ((LiteralNode<?>)parent).getValue();
-
-            LiteralNode<?> literalNode = null;
-
-            if (type.isString()) {
-                literalNode = LiteralNode.newInstance(token, finish, JSType.toString(value));
-            } else if (type.isBoolean()) {
-                literalNode = LiteralNode.newInstance(token, finish, JSType.toBoolean(value));
-            } else if (type.isInteger()) {
-                literalNode = LiteralNode.newInstance(token, finish, JSType.toInt32(value));
-            } else if (type.isLong()) {
-                literalNode = LiteralNode.newInstance(token, finish, JSType.toLong(value));
-            } else if (type.isNumber() || parent.getType().isNumeric() && !parent.getType().isNumber()) {
-                literalNode = LiteralNode.newInstance(token, finish, JSType.toNumber(value));
-            }
-
-            if (literalNode != null) {
-                //inherit literal symbol for attr.
-                literalNode = (LiteralNode<?>)literalNode.setSymbol(lc, parent.getSymbol());
-            }
-
-            return literalNode;
-        }
-    }
 }
--- a/src/jdk/nashorn/internal/codegen/FoldConstants.java	Thu Oct 17 09:41:14 2013 -0700
+++ b/src/jdk/nashorn/internal/codegen/FoldConstants.java	Thu Oct 17 16:19:45 2013 -0700
@@ -25,6 +25,8 @@
 
 package jdk.nashorn.internal.codegen;
 
+import java.util.ArrayList;
+import java.util.List;
 import jdk.nashorn.internal.codegen.types.Type;
 import jdk.nashorn.internal.ir.BinaryNode;
 import jdk.nashorn.internal.ir.Block;
@@ -37,8 +39,10 @@
 import jdk.nashorn.internal.ir.LiteralNode;
 import jdk.nashorn.internal.ir.LiteralNode.ArrayLiteralNode;
 import jdk.nashorn.internal.ir.Node;
+import jdk.nashorn.internal.ir.Statement;
 import jdk.nashorn.internal.ir.TernaryNode;
 import jdk.nashorn.internal.ir.UnaryNode;
+import jdk.nashorn.internal.ir.VarNode;
 import jdk.nashorn.internal.ir.visitor.NodeVisitor;
 import jdk.nashorn.internal.runtime.DebugLogger;
 import jdk.nashorn.internal.runtime.JSType;
@@ -89,11 +93,21 @@
     public Node leaveIfNode(final IfNode ifNode) {
         final Node test = ifNode.getTest();
         if (test instanceof LiteralNode.PrimitiveLiteralNode) {
-            final Block shortCut = ((LiteralNode.PrimitiveLiteralNode<?>)test).isTrue() ? ifNode.getPass() : ifNode.getFail();
-            if (shortCut != null) {
-                return new BlockStatement(ifNode.getLineNumber(), shortCut);
+            final boolean isTrue = ((LiteralNode.PrimitiveLiteralNode<?>)test).isTrue();
+            final Block executed = isTrue ? ifNode.getPass() : ifNode.getFail();
+            final Block dropped  = isTrue ? ifNode.getFail() : ifNode.getPass();
+            final List<Statement> statements = new ArrayList<>();
+
+            if (executed != null) {
+                statements.addAll(executed.getStatements()); // Get statements form executed branch
             }
-            return new EmptyNode(ifNode);
+            if (dropped != null) {
+                extractVarNodes(dropped, statements); // Get var-nodes from non-executed branch
+            }
+            if (statements.isEmpty()) {
+                return new EmptyNode(ifNode);
+            }
+            return BlockStatement.createReplacement(ifNode, ifNode.getFinish(), statements);
         }
         return ifNode;
     }
@@ -131,6 +145,17 @@
         protected abstract LiteralNode<?> eval();
     }
 
+    private static void extractVarNodes(final Block block, final List<Statement> statements) {
+        final LexicalContext lc = new LexicalContext();
+        block.accept(lc, new NodeVisitor<LexicalContext>(lc) {
+            @Override
+            public boolean enterVarNode(VarNode varNode) {
+                statements.add(varNode.setInit(null));
+                return false;
+            }
+        });
+    }
+
     private static class UnaryNodeConstantEvaluator extends ConstantEvaluator<UnaryNode> {
         UnaryNodeConstantEvaluator(final UnaryNode parent) {
             super(parent);
--- a/src/jdk/nashorn/internal/codegen/Lower.java	Thu Oct 17 09:41:14 2013 -0700
+++ b/src/jdk/nashorn/internal/codegen/Lower.java	Thu Oct 17 16:19:45 2013 -0700
@@ -68,6 +68,7 @@
 import jdk.nashorn.internal.ir.visitor.NodeVisitor;
 import jdk.nashorn.internal.parser.Token;
 import jdk.nashorn.internal.parser.TokenType;
+import jdk.nashorn.internal.runtime.CodeInstaller;
 import jdk.nashorn.internal.runtime.DebugLogger;
 import jdk.nashorn.internal.runtime.ScriptRuntime;
 import jdk.nashorn.internal.runtime.Source;
@@ -86,10 +87,13 @@
 
     private static final DebugLogger LOG = new DebugLogger("lower");
 
+    // needed only to get unique eval id
+    private final CodeInstaller installer;
+
     /**
      * Constructor.
      */
-    Lower() {
+    Lower(final CodeInstaller installer) {
         super(new BlockLexicalContext() {
 
             @Override
@@ -132,6 +136,7 @@
                 return block.setIsTerminal(this, false);
             }
         });
+        this.installer = installer;
     }
 
     @Override
@@ -529,11 +534,17 @@
      */
     private String evalLocation(final IdentNode node) {
         final Source source = lc.getCurrentFunction().getSource();
+        final int pos = node.position();
+        // Code installer is null when running with --compile-only, use 0 as id in that case
+        final long id = installer == null ? 0 : installer.getUniqueEvalId();
         return new StringBuilder().
             append(source.getName()).
             append('#').
-            append(source.getLine(node.position())).
-            append("<eval>").
+            append(source.getLine(pos)).
+            append(':').
+            append(source.getColumn(pos)).
+            append("<eval>@").
+            append(id).
             toString();
     }
 
--- a/src/jdk/nashorn/internal/codegen/MethodEmitter.java	Thu Oct 17 09:41:14 2013 -0700
+++ b/src/jdk/nashorn/internal/codegen/MethodEmitter.java	Thu Oct 17 16:19:45 2013 -0700
@@ -69,7 +69,6 @@
 import java.lang.reflect.Array;
 import java.util.EnumSet;
 import java.util.List;
-
 import jdk.internal.dynalink.support.NameCodec;
 import jdk.internal.org.objectweb.asm.Handle;
 import jdk.internal.org.objectweb.asm.MethodVisitor;
@@ -1560,7 +1559,7 @@
     MethodEmitter convert(final Type to) {
         final Type type = peekType().convert(method, to);
         if (type != null) {
-            if (peekType() != to) {
+            if (!peekType().isEquivalentTo(to)) {
                 debug("convert", peekType(), "->", to);
             }
             popType();
@@ -1790,15 +1789,14 @@
      * @param name      name of property
      * @param flags     call site flags
      */
-     void dynamicSet(final Type valueType, final String name, final int flags) {
+     void dynamicSet(final String name, final int flags) {
         debug("dynamic_set", name, peekType());
 
-        Type type = valueType;
+        Type type = peekType();
         if (type.isObject() || type.isBoolean()) { //promote strings to objects etc
             type = Type.OBJECT;
             convert(Type.OBJECT); //TODO bad- until we specialize boolean setters,
         }
-
         popType(type);
         popType(Type.SCOPE);
 
--- a/src/jdk/nashorn/internal/codegen/Namespace.java	Thu Oct 17 09:41:14 2013 -0700
+++ b/src/jdk/nashorn/internal/codegen/Namespace.java	Thu Oct 17 16:19:45 2013 -0700
@@ -81,7 +81,7 @@
                 final int count = counter + 1;
                 namespaceDirectory.put(base, count);
 
-                return base + "$" + count;
+                return base + '-' + count;
             }
         }
 
--- a/src/jdk/nashorn/internal/codegen/WeighNodes.java	Thu Oct 17 09:41:14 2013 -0700
+++ b/src/jdk/nashorn/internal/codegen/WeighNodes.java	Thu Oct 17 16:19:45 2013 -0700
@@ -297,11 +297,6 @@
     }
 
     @Override
-    public Node leaveCONVERT(final UnaryNode unaryNode) {
-        return unaryNodeWeight(unaryNode);
-    }
-
-    @Override
     public Node leaveDECINC(final UnaryNode unaryNode) {
          return unaryNodeWeight(unaryNode);
     }
--- a/src/jdk/nashorn/internal/codegen/types/BooleanType.java	Thu Oct 17 09:41:14 2013 -0700
+++ b/src/jdk/nashorn/internal/codegen/types/BooleanType.java	Thu Oct 17 16:19:45 2013 -0700
@@ -136,8 +136,7 @@
             invokeStatic(method, JSType.TO_LONG);
         } else if (to.isString()) {
             invokeStatic(method, VALUE_OF);
-            invokeStatic(method, JSType.TO_PRIMITIVE);
-            invokeStatic(method, JSType.TO_STRING);
+            invokeStatic(method, JSType.TO_PRIMITIVE_TO_STRING);
         } else if (to.isObject()) {
             invokeStatic(method, VALUE_OF);
         } else {
--- a/src/jdk/nashorn/internal/codegen/types/ObjectType.java	Thu Oct 17 09:41:14 2013 -0700
+++ b/src/jdk/nashorn/internal/codegen/types/ObjectType.java	Thu Oct 17 16:19:45 2013 -0700
@@ -153,8 +153,7 @@
         } else if (to.isBoolean()) {
             invokeStatic(method, JSType.TO_BOOLEAN);
         } else if (to.isString()) {
-            invokeStatic(method, JSType.TO_PRIMITIVE);
-            invokeStatic(method, JSType.TO_STRING);
+            invokeStatic(method, JSType.TO_PRIMITIVE_TO_STRING);
         } else {
             assert false : "Illegal conversion " + this + " -> " + to + " " + isString() + " " + toString;
         }
--- a/src/jdk/nashorn/internal/codegen/types/Type.java	Thu Oct 17 09:41:14 2013 -0700
+++ b/src/jdk/nashorn/internal/codegen/types/Type.java	Thu Oct 17 16:19:45 2013 -0700
@@ -441,7 +441,12 @@
         if (type0.isArray() && type1.isArray()) {
             return ((ArrayType)type0).getElementType() == ((ArrayType)type1).getElementType() ? type0 : Type.OBJECT;
         } else if (type0.isArray() != type1.isArray()) {
-            return Type.OBJECT; //array and non array is always object, widest(Object[], int) NEVER returns Object[], which has most weight. that does not make sense
+            //array and non array is always object, widest(Object[], int) NEVER returns Object[], which has most weight. that does not make sense
+            return Type.OBJECT;
+        } else if (type0.isObject() && type1.isObject() && ((ObjectType)type0).getTypeClass() != ((ObjectType)type1).getTypeClass()) {
+            // Object<type=String> and Object<type=ScriptFunction> will produce Object
+            // TODO: maybe find most specific common superclass?
+            return Type.OBJECT;
         }
         return type0.weight() > type1.weight() ? type0 : type1;
     }
--- a/src/jdk/nashorn/internal/ir/AccessNode.java	Thu Oct 17 09:41:14 2013 -0700
+++ b/src/jdk/nashorn/internal/ir/AccessNode.java	Thu Oct 17 16:19:45 2013 -0700
@@ -25,7 +25,6 @@
 
 package jdk.nashorn.internal.ir;
 
-import jdk.nashorn.internal.codegen.types.Type;
 import jdk.nashorn.internal.ir.annotations.Immutable;
 import jdk.nashorn.internal.ir.visitor.NodeVisitor;
 
@@ -46,12 +45,12 @@
      * @param property  property
      */
     public AccessNode(final long token, final int finish, final Expression base, final IdentNode property) {
-        super(token, finish, base, false, false);
+        super(token, finish, base, false);
         this.property = property.setIsPropertyName();
     }
 
-    private AccessNode(final AccessNode accessNode, final Expression base, final IdentNode property, final boolean isFunction, final boolean hasCallSiteType) {
-        super(accessNode, base, isFunction, hasCallSiteType);
+    private AccessNode(final AccessNode accessNode, final Expression base, final IdentNode property, final boolean isFunction) {
+        super(accessNode, base, isFunction);
         this.property = property;
     }
 
@@ -73,13 +72,6 @@
     public void toString(final StringBuilder sb) {
         final boolean needsParen = tokenType().needsParens(getBase().tokenType(), true);
 
-        if (hasCallSiteType()) {
-            sb.append('{');
-            final String desc = getType().getDescriptor();
-            sb.append(desc.charAt(desc.length() - 1) == ';' ? "O" : getType().getDescriptor());
-            sb.append('}');
-        }
-
         if (needsParen) {
             sb.append('(');
         }
@@ -107,21 +99,14 @@
         if (this.base == base) {
             return this;
         }
-        return new AccessNode(this, base, property, isFunction(), hasCallSiteType());
+        return new AccessNode(this, base, property, isFunction());
     }
 
     private AccessNode setProperty(final IdentNode property) {
         if (this.property == property) {
             return this;
         }
-        return new AccessNode(this, base, property, isFunction(), hasCallSiteType());
-    }
-
-    @Override
-    public AccessNode setType(final TemporarySymbols ts, final LexicalContext lc, final Type type) {
-        logTypeChange(type);
-        final AccessNode newAccessNode = (AccessNode)setSymbol(lc, getSymbol().setTypeOverrideShared(type, ts));
-        return new AccessNode(newAccessNode, base, property.setType(ts, lc, type), isFunction(), hasCallSiteType());
+        return new AccessNode(this, base, property, isFunction());
     }
 
     @Override
@@ -129,7 +114,7 @@
         if (isFunction()) {
             return this;
         }
-        return new AccessNode(this, base, property, true, hasCallSiteType());
+        return new AccessNode(this, base, property, true);
     }
 
 }
--- a/src/jdk/nashorn/internal/ir/BaseNode.java	Thu Oct 17 09:41:14 2013 -0700
+++ b/src/jdk/nashorn/internal/ir/BaseNode.java	Thu Oct 17 16:19:45 2013 -0700
@@ -25,10 +25,6 @@
 
 package jdk.nashorn.internal.ir;
 
-import static jdk.nashorn.internal.codegen.ObjectClassGenerator.DEBUG_FIELDS;
-
-import jdk.nashorn.internal.codegen.ObjectClassGenerator;
-import jdk.nashorn.internal.codegen.types.Type;
 import jdk.nashorn.internal.ir.annotations.Immutable;
 
 /**
@@ -38,15 +34,13 @@
  * @see IndexNode
  */
 @Immutable
-public abstract class BaseNode extends Expression implements FunctionCall, TypeOverride<BaseNode> {
+public abstract class BaseNode extends Expression implements FunctionCall {
 
     /** Base Node. */
     protected final Expression base;
 
     private final boolean isFunction;
 
-    private final boolean hasCallSiteType;
-
     /**
      * Constructor
      *
@@ -54,13 +48,11 @@
      * @param finish finish
      * @param base   base node
      * @param isFunction is this a function
-     * @param hasCallSiteType does this access have a callsite type
      */
-    public BaseNode(final long token, final int finish, final Expression base, final boolean isFunction, final boolean hasCallSiteType) {
+    public BaseNode(final long token, final int finish, final Expression base, final boolean isFunction) {
         super(token, base.getStart(), finish);
         this.base            = base;
         this.isFunction      = isFunction;
-        this.hasCallSiteType = hasCallSiteType;
     }
 
     /**
@@ -68,13 +60,11 @@
      * @param baseNode node to inherit from
      * @param base base
      * @param isFunction is this a function
-     * @param hasCallSiteType does this access have a callsite type
      */
-    protected BaseNode(final BaseNode baseNode, final Expression base, final boolean isFunction, final boolean hasCallSiteType) {
+    protected BaseNode(final BaseNode baseNode, final Expression base, final boolean isFunction) {
         super(baseNode);
         this.base            = base;
         this.isFunction      = isFunction;
-        this.hasCallSiteType = hasCallSiteType;
     }
 
     /**
@@ -96,26 +86,4 @@
      */
     public abstract BaseNode setIsFunction();
 
-    @Override
-    public boolean canHaveCallSiteType() {
-        return true; //carried by the symbol and always the same nodetype==symboltype
-    }
-
-    /**
-     * Does the access have a call site type override?
-     * @return true if overridden
-     */
-    protected boolean hasCallSiteType() {
-        return hasCallSiteType;
-    }
-
-    /**
-     * Debug type change
-     * @param type new type
-     */
-    protected final void logTypeChange(final Type type) {
-        if (DEBUG_FIELDS && !Type.areEquivalent(getSymbol().getSymbolType(), type)) {
-            ObjectClassGenerator.LOG.info(getClass().getName(), " ", this, " => ", type, " instead of ", getType());
-        }
-    }
 }
--- a/src/jdk/nashorn/internal/ir/CallNode.java	Thu Oct 17 09:41:14 2013 -0700
+++ b/src/jdk/nashorn/internal/ir/CallNode.java	Thu Oct 17 16:19:45 2013 -0700
@@ -36,9 +36,7 @@
  * IR representation for a function call.
  */
 @Immutable
-public final class CallNode extends LexicalContextExpression implements TypeOverride<CallNode> {
-
-    private final Type type;
+public final class CallNode extends LexicalContextExpression {
 
     /** Function identifier or function body. */
     private final Expression function;
@@ -150,18 +148,16 @@
         this.function   = function;
         this.args       = args;
         this.flags      = 0;
-        this.type       = null;
         this.evalArgs   = null;
         this.lineNumber = lineNumber;
     }
 
-    private CallNode(final CallNode callNode, final Expression function, final List<Expression> args, final int flags, final Type type, final EvalArgs evalArgs) {
+    private CallNode(final CallNode callNode, final Expression function, final List<Expression> args, final int flags, final EvalArgs evalArgs) {
         super(callNode);
         this.lineNumber = callNode.lineNumber;
         this.function = function;
         this.args = args;
         this.flags = flags;
-        this.type = type;
         this.evalArgs = evalArgs;
     }
 
@@ -175,29 +171,9 @@
 
     @Override
     public Type getType() {
-        if (hasCallSiteType()) {
-            return type;
-        }
         return function instanceof FunctionNode ? ((FunctionNode)function).getReturnType() : Type.OBJECT;
     }
 
-    @Override
-    public CallNode setType(final TemporarySymbols ts, final LexicalContext lc, final Type type) {
-        if (this.type == type) {
-            return this;
-        }
-        return new CallNode(this, function, args, flags, type, evalArgs);
-    }
-
-    private boolean hasCallSiteType() {
-        return this.type != null;
-    }
-
-    @Override
-    public boolean canHaveCallSiteType() {
-        return true;
-    }
-
     /**
      * Assist in IR navigation.
      *
@@ -212,7 +188,6 @@
                     setFunction((Expression)function.accept(visitor)).
                     setArgs(Node.accept(visitor, Expression.class, args)).
                     setFlags(flags).
-                    setType(null, lc, type).
                     setEvalArgs(evalArgs == null ?
                             null :
                             evalArgs.setCode((Expression)evalArgs.getCode().accept(visitor)).
@@ -229,13 +204,6 @@
 
     @Override
     public void toString(final StringBuilder sb) {
-        if (hasCallSiteType()) {
-            sb.append('{');
-            final String desc = getType().getDescriptor();
-            sb.append(desc.charAt(desc.length() - 1) == ';' ? 'O' : getType().getDescriptor());
-            sb.append('}');
-        }
-
         function.toString(sb);
 
         sb.append('(');
@@ -271,7 +239,7 @@
         if (this.args == args) {
             return this;
         }
-        return new CallNode(this, function, args, flags, type, evalArgs);
+        return new CallNode(this, function, args, flags, evalArgs);
     }
 
     /**
@@ -293,7 +261,7 @@
         if (this.evalArgs == evalArgs) {
             return this;
         }
-        return new CallNode(this, function, args, flags, type, evalArgs);
+        return new CallNode(this, function, args, flags, evalArgs);
     }
 
     /**
@@ -321,7 +289,7 @@
         if (this.function == function) {
             return this;
         }
-        return new CallNode(this, function, args, flags, type, evalArgs);
+        return new CallNode(this, function, args, flags, evalArgs);
     }
 
     /**
@@ -344,6 +312,6 @@
         if (this.flags == flags) {
             return this;
         }
-        return new CallNode(this, function, args, flags, type, evalArgs);
+        return new CallNode(this, function, args, flags, evalArgs);
     }
 }
--- a/src/jdk/nashorn/internal/ir/IdentNode.java	Thu Oct 17 09:41:14 2013 -0700
+++ b/src/jdk/nashorn/internal/ir/IdentNode.java	Thu Oct 17 16:19:45 2013 -0700
@@ -28,9 +28,7 @@
 import static jdk.nashorn.internal.codegen.CompilerConstants.__DIR__;
 import static jdk.nashorn.internal.codegen.CompilerConstants.__FILE__;
 import static jdk.nashorn.internal.codegen.CompilerConstants.__LINE__;
-import static jdk.nashorn.internal.codegen.ObjectClassGenerator.DEBUG_FIELDS;
 
-import jdk.nashorn.internal.codegen.ObjectClassGenerator;
 import jdk.nashorn.internal.codegen.types.Type;
 import jdk.nashorn.internal.ir.annotations.Immutable;
 import jdk.nashorn.internal.ir.visitor.NodeVisitor;
@@ -39,7 +37,7 @@
  * IR representation for an identifier.
  */
 @Immutable
-public final class IdentNode extends Expression implements PropertyKey, TypeOverride<IdentNode>, FunctionCall {
+public final class IdentNode extends Expression implements PropertyKey, FunctionCall {
     private static final int PROPERTY_NAME     = 1 << 0;
     private static final int INITIALIZED_HERE  = 1 << 1;
     private static final int FUNCTION          = 1 << 2;
@@ -101,19 +99,6 @@
         return callSiteType != null;
     }
 
-    @Override
-    public IdentNode setType(final TemporarySymbols ts, final LexicalContext lc, final Type type) {
-        // do NOT, repeat NOT touch the symbol here. it might be a local variable or whatever. This is the override if it isn't
-        if (this.callSiteType == type) {
-            return this;
-        }
-        if (DEBUG_FIELDS && getSymbol() != null && !Type.areEquivalent(getSymbol().getSymbolType(), type)) {
-            ObjectClassGenerator.LOG.info(getClass().getName(), " ", this, " => ", type, " instead of ", getType());
-        }
-
-        return new IdentNode(this, name, type, flags);
-    }
-
     /**
      * Assist in IR navigation.
      *
@@ -154,31 +139,6 @@
     }
 
     /**
-     * We can only override type if the symbol lives in the scope, as otherwise
-     * it is strongly determined by the local variable already allocated.
-     *
-     * <p>We also return true if the symbol represents the return value of a function with a
-     * non-generic return type as in this case we need to propagate the type instead of
-     * converting to object, for example if the symbol is used as the left hand side of an
-     * assignment such as in the code below.</p>
-     *
-     * <pre>
-     *   try {
-     *     return 2;
-     *   } finally {
-     *     return 3;
-     *   }
-     * }
-     * </pre>
-     *
-     * @return true if can have callsite type
-     */
-    @Override
-    public boolean canHaveCallSiteType() {
-        return getSymbol() != null && (getSymbol().isScope() || getSymbol().isNonGenericReturn());
-    }
-
-    /**
      * Check if this IdentNode is a property name
      * @return true if this is a property name
      */
--- a/src/jdk/nashorn/internal/ir/IndexNode.java	Thu Oct 17 09:41:14 2013 -0700
+++ b/src/jdk/nashorn/internal/ir/IndexNode.java	Thu Oct 17 16:19:45 2013 -0700
@@ -25,7 +25,6 @@
 
 package jdk.nashorn.internal.ir;
 
-import jdk.nashorn.internal.codegen.types.Type;
 import jdk.nashorn.internal.ir.annotations.Immutable;
 import jdk.nashorn.internal.ir.visitor.NodeVisitor;
 
@@ -46,12 +45,12 @@
      * @param index   index for access
      */
     public IndexNode(final long token, final int finish, final Expression base, final Expression index) {
-        super(token, finish, base, false, false);
+        super(token, finish, base, false);
         this.index = index;
     }
 
-    private IndexNode(final IndexNode indexNode, final Expression base, final Expression index, final boolean isFunction, final boolean hasCallSiteType) {
-        super(indexNode, base, isFunction, hasCallSiteType);
+    private IndexNode(final IndexNode indexNode, final Expression base, final Expression index, final boolean isFunction) {
+        super(indexNode, base, isFunction);
         this.index = index;
     }
 
@@ -69,13 +68,6 @@
     public void toString(final StringBuilder sb) {
         final boolean needsParen = tokenType().needsParens(base.tokenType(), true);
 
-        if (hasCallSiteType()) {
-            sb.append('{');
-            final String desc = getType().getDescriptor();
-            sb.append(desc.charAt(desc.length() - 1) == ';' ? "O" : getType().getDescriptor());
-            sb.append('}');
-        }
-
         if (needsParen) {
             sb.append('(');
         }
@@ -103,7 +95,7 @@
         if (this.base == base) {
             return this;
         }
-        return new IndexNode(this, base, index, isFunction(), hasCallSiteType());
+        return new IndexNode(this, base, index, isFunction());
     }
 
     /**
@@ -115,7 +107,7 @@
         if(this.index == index) {
             return this;
         }
-        return new IndexNode(this, base, index, isFunction(), hasCallSiteType());
+        return new IndexNode(this, base, index, isFunction());
     }
 
     @Override
@@ -123,14 +115,7 @@
         if (isFunction()) {
             return this;
         }
-        return new IndexNode(this, base, index, true, hasCallSiteType());
-    }
-
-    @Override
-    public IndexNode setType(final TemporarySymbols ts, final LexicalContext lc, final Type type) {
-        logTypeChange(type);
-        final IndexNode newIndexNode = (IndexNode)setSymbol(lc, getSymbol().setTypeOverrideShared(type, ts));
-        return new IndexNode(newIndexNode, base, index, isFunction(), true);
+        return new IndexNode(this, base, index, true);
     }
 
 }
--- a/src/jdk/nashorn/internal/ir/LiteralNode.java	Thu Oct 17 09:41:14 2013 -0700
+++ b/src/jdk/nashorn/internal/ir/LiteralNode.java	Thu Oct 17 16:19:45 2013 -0700
@@ -28,10 +28,13 @@
 import java.util.Arrays;
 import java.util.Collections;
 import java.util.List;
+
 import jdk.nashorn.internal.codegen.CompileUnit;
+import jdk.nashorn.internal.codegen.types.ArrayType;
 import jdk.nashorn.internal.codegen.types.Type;
 import jdk.nashorn.internal.ir.annotations.Immutable;
 import jdk.nashorn.internal.ir.visitor.NodeVisitor;
+import jdk.nashorn.internal.objects.NativeArray;
 import jdk.nashorn.internal.parser.Lexer.LexerToken;
 import jdk.nashorn.internal.parser.Token;
 import jdk.nashorn.internal.parser.TokenType;
@@ -526,12 +529,6 @@
             return object;
         } else if (object instanceof LiteralNode) {
             return objectAsConstant(((LiteralNode<?>)object).getValue());
-        } else if (object instanceof UnaryNode) {
-            final UnaryNode unaryNode = (UnaryNode)object;
-
-            if (unaryNode.isTokenType(TokenType.CONVERT) && unaryNode.getType().isObject()) {
-                return objectAsConstant(unaryNode.rhs());
-            }
         }
 
         return POSTSET_MARKER;
@@ -782,8 +779,11 @@
             return value;
         }
 
-        @Override
-        public Type getType() {
+        /**
+         * Get the array element type as Java format, e.g. [I
+         * @return array element type
+         */
+        public ArrayType getArrayType() {
             if (elementType.isInteger()) {
                 return Type.INT_ARRAY;
             } else if (elementType.isLong()) {
@@ -795,6 +795,11 @@
             }
         }
 
+        @Override
+        public Type getType() {
+            return Type.typeFor(NativeArray.class);
+        }
+
         /**
          * Get the element type of this array literal
          * @return element type
--- a/src/jdk/nashorn/internal/ir/RuntimeNode.java	Thu Oct 17 09:41:14 2013 -0700
+++ b/src/jdk/nashorn/internal/ir/RuntimeNode.java	Thu Oct 17 16:19:45 2013 -0700
@@ -38,7 +38,7 @@
  * IR representation for a runtime call.
  */
 @Immutable
-public class RuntimeNode extends Expression implements TypeOverride<RuntimeNode> {
+public class RuntimeNode extends Expression {
 
     /**
      * Request enum used for meta-information about the runtime request
@@ -159,6 +159,36 @@
         }
 
         /**
+         * Derive a runtime node request type for a node
+         * @param node the node
+         * @return request type
+         */
+        public static Request requestFor(final Node node) {
+            assert node.isComparison();
+            switch (node.tokenType()) {
+            case EQ_STRICT:
+                return Request.EQ_STRICT;
+            case NE_STRICT:
+                return Request.NE_STRICT;
+            case EQ:
+                return Request.EQ;
+            case NE:
+                return Request.NE;
+            case LT:
+                return Request.LT;
+            case LE:
+                return Request.LE;
+            case GT:
+                return Request.GT;
+            case GE:
+                return Request.GE;
+            default:
+                assert false;
+                return null;
+            }
+        }
+
+        /**
          * Is this an EQ or EQ_STRICT?
          *
          * @param request a request
@@ -268,9 +298,6 @@
     /** Call arguments. */
     private final List<Expression> args;
 
-    /** Call site override - e.g. we know that a ScriptRuntime.ADD will return an int */
-    private final Type callSiteType;
-
     /** is final - i.e. may not be removed again, lower in the code pipeline */
     private final boolean isFinal;
 
@@ -287,16 +314,14 @@
 
         this.request      = request;
         this.args         = args;
-        this.callSiteType = null;
         this.isFinal      = false;
     }
 
-    private RuntimeNode(final RuntimeNode runtimeNode, final Request request, final Type callSiteType, final boolean isFinal, final List<Expression> args) {
+    private RuntimeNode(final RuntimeNode runtimeNode, final Request request, final boolean isFinal, final List<Expression> args) {
         super(runtimeNode);
 
         this.request      = request;
         this.args         = args;
-        this.callSiteType = callSiteType;
         this.isFinal      = isFinal;
     }
 
@@ -335,7 +360,6 @@
 
         this.request      = request;
         this.args         = args;
-        this.callSiteType = null;
         this.isFinal      = false;
     }
 
@@ -376,7 +400,7 @@
         if (this.isFinal == isFinal) {
             return this;
         }
-        return new RuntimeNode(this, request, callSiteType, isFinal, args);
+        return new RuntimeNode(this, request, isFinal, args);
     }
 
     /**
@@ -384,24 +408,7 @@
      */
     @Override
     public Type getType() {
-        return hasCallSiteType() ? callSiteType : request.getReturnType();
-    }
-
-    @Override
-    public RuntimeNode setType(final TemporarySymbols ts, final LexicalContext lc, final Type type) {
-        if (this.callSiteType == type) {
-            return this;
-        }
-        return new RuntimeNode(this, request, type, isFinal, args);
-    }
-
-    @Override
-    public boolean canHaveCallSiteType() {
-        return request == Request.ADD;
-    }
-
-    private boolean hasCallSiteType() {
-        return callSiteType != null;
+        return request.getReturnType();
     }
 
     @Override
@@ -450,7 +457,7 @@
         if (this.args == args) {
             return this;
         }
-        return new RuntimeNode(this, request, callSiteType, isFinal, args);
+        return new RuntimeNode(this, request, isFinal, args);
     }
 
     /**
--- a/src/jdk/nashorn/internal/ir/TypeOverride.java	Thu Oct 17 09:41:14 2013 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,62 +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.ir;
-
-import jdk.nashorn.internal.codegen.types.Type;
-
-/**
- * A type override makes it possible to change the return type of a node, if we know
- * that the linker can provide it directly. For example, an identity node that is
- * in the scope, can very well look like an object to the compiler of the method it
- * is in, but if someone does (int)x, it make senses to ask for it directly
- * with an int getter instead of loading it as an object and explicitly converting it
- * by using JSType.toInt32. Especially in scenarios where the field is already stored
- * as a primitive, this will be much faster than the "object is all I see" scope
- * available in the method
- * @param <T> the type of the node implementing the interface
- */
-
-public interface TypeOverride<T extends Node> {
-    /**
-     * Set the override type
-     *
-     * @param ts temporary symbols
-     * @param lc the current lexical context
-     * @param type the type
-     * @return a node equivalent to this one except for the requested change.
-     */
-    public T setType(final TemporarySymbols ts, final LexicalContext lc, final Type type);
-
-    /**
-     * Returns true if this node can have a callsite override, e.g. all scope ident nodes
-     * which lead to dynamic getters can have it, local variable nodes (slots) can't.
-     * Call nodes can have it unconditionally and so on
-     *
-     * @return true if it is possible to assign a type override to this node
-     */
-    public boolean canHaveCallSiteType();
-
-}
--- a/src/jdk/nashorn/internal/ir/UnaryNode.java	Thu Oct 17 09:41:14 2013 -0700
+++ b/src/jdk/nashorn/internal/ir/UnaryNode.java	Thu Oct 17 16:19:45 2013 -0700
@@ -26,7 +26,6 @@
 package jdk.nashorn.internal.ir;
 
 import static jdk.nashorn.internal.parser.TokenType.BIT_NOT;
-import static jdk.nashorn.internal.parser.TokenType.CONVERT;
 import static jdk.nashorn.internal.parser.TokenType.DECPOSTFIX;
 import static jdk.nashorn.internal.parser.TokenType.INCPOSTFIX;
 
@@ -150,19 +149,10 @@
         final TokenType type      = tokenType();
         final String    name      = type.getName();
         final boolean   isPostfix = type == DECPOSTFIX || type == INCPOSTFIX;
-        final boolean   isConvert = type == CONVERT && getSymbol() != null;
 
         boolean rhsParen   = type.needsParens(rhs().tokenType(), false);
-        int     convertPos = 0;
 
-        if (isConvert) {
-            convertPos = sb.length();
-            sb.append("(");
-            sb.append(getType());
-            sb.append(")(");
-        }
-
-        if (!isPostfix && !isConvert) {
+        if (!isPostfix) {
             if (name == null) {
                 sb.append(type.name());
                 rhsParen = true;
@@ -186,16 +176,6 @@
         if (isPostfix) {
             sb.append(type == DECPOSTFIX ? "--" : "++");
         }
-
-        if (isConvert) {
-            // strip extra cast parenthesis which makes the printout harder to read
-            final boolean endsWithParenthesis = sb.charAt(sb.length() - 1) == ')';
-            if (!endsWithParenthesis) {
-                sb.append(')');
-            } else {
-                sb.setCharAt(convertPos, ' ');
-            }
-        }
     }
 
     /**
--- a/src/jdk/nashorn/internal/ir/visitor/NodeOperatorVisitor.java	Thu Oct 17 09:41:14 2013 -0700
+++ b/src/jdk/nashorn/internal/ir/visitor/NodeOperatorVisitor.java	Thu Oct 17 16:19:45 2013 -0700
@@ -51,8 +51,6 @@
             return enterADD(unaryNode);
         case BIT_NOT:
             return enterBIT_NOT(unaryNode);
-        case CONVERT:
-            return enterCONVERT(unaryNode);
         case DELETE:
             return enterDELETE(unaryNode);
         case DISCARD:
@@ -84,8 +82,6 @@
             return leaveADD(unaryNode);
         case BIT_NOT:
             return leaveBIT_NOT(unaryNode);
-        case CONVERT:
-            return leaveCONVERT(unaryNode);
         case DELETE:
             return leaveDELETE(unaryNode);
         case DISCARD:
@@ -323,26 +319,6 @@
     }
 
     /**
-     * Unary enter - callback for entering a conversion
-     *
-     * @param  unaryNode the node
-     * @return true if traversal should continue and node children be traversed, false otherwise
-     */
-    public boolean enterCONVERT(final UnaryNode unaryNode) {
-        return enterDefault(unaryNode);
-    }
-
-    /**
-     * Unary leave - callback for leaving a conversion
-     *
-     * @param  unaryNode the node
-     * @return processed node, which will replace the original one, or the original node
-     */
-    public Node leaveCONVERT(final UnaryNode unaryNode) {
-        return leaveDefault(unaryNode);
-    }
-
-    /**
      * Unary enter - callback for entering a ++ or -- operator
      *
      * @param  unaryNode the node
--- a/src/jdk/nashorn/internal/objects/Global.java	Thu Oct 17 09:41:14 2013 -0700
+++ b/src/jdk/nashorn/internal/objects/Global.java	Thu Oct 17 16:19:45 2013 -0700
@@ -491,8 +491,8 @@
     // GlobalObject interface implementation
 
     @Override
-    public boolean isOfContext(final Context context) {
-        return this.context == context;
+    public boolean isOfContext(final Context ctxt) {
+        return this.context == ctxt;
     }
 
     @Override
--- a/src/jdk/nashorn/internal/objects/NativeArray.java	Thu Oct 17 09:41:14 2013 -0700
+++ b/src/jdk/nashorn/internal/objects/NativeArray.java	Thu Oct 17 16:19:45 2013 -0700
@@ -851,6 +851,10 @@
     @Function(attributes = Attribute.NOT_ENUMERABLE)
     public static Object slice(final Object self, final Object start, final Object end) {
         final Object       obj                 = Global.toObject(self);
+        if (!(obj instanceof ScriptObject)) {
+            return ScriptRuntime.UNDEFINED;
+        }
+
         final ScriptObject sobj                = (ScriptObject)obj;
         final long         len                 = JSType.toUint32(sobj.getLength());
         final long         relativeStart       = JSType.toLong(start);
--- a/src/jdk/nashorn/internal/objects/NativeError.java	Thu Oct 17 09:41:14 2013 -0700
+++ b/src/jdk/nashorn/internal/objects/NativeError.java	Thu Oct 17 16:19:45 2013 -0700
@@ -30,6 +30,7 @@
 
 import java.lang.invoke.MethodHandle;
 import java.lang.invoke.MethodHandles;
+
 import jdk.nashorn.api.scripting.NashornException;
 import jdk.nashorn.internal.objects.annotations.Attribute;
 import jdk.nashorn.internal.objects.annotations.Constructor;
@@ -135,11 +136,12 @@
      * @param errorObj the error object
      * @return undefined
      */
+    @SuppressWarnings("unused")
     @Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR)
     public static Object captureStackTrace(final Object self, final Object errorObj) {
         Global.checkObject(errorObj);
         final ScriptObject sobj = (ScriptObject)errorObj;
-        final ECMAException exp = new ECMAException(sobj, null);
+        new ECMAException(sobj, null); //constructor has side effects
         sobj.delete("stack", false);
         final ScriptFunction getStack = ScriptFunctionImpl.makeFunction("getStack", GET_STACK);
         final ScriptFunction setStack = ScriptFunctionImpl.makeFunction("setStack", SET_STACK);
--- a/src/jdk/nashorn/internal/objects/ScriptFunctionImpl.java	Thu Oct 17 09:41:14 2013 -0700
+++ b/src/jdk/nashorn/internal/objects/ScriptFunctionImpl.java	Thu Oct 17 16:19:45 2013 -0700
@@ -25,6 +25,7 @@
 
 package jdk.nashorn.internal.objects;
 
+import static jdk.nashorn.internal.lookup.Lookup.MH;
 import static jdk.nashorn.internal.runtime.ScriptRuntime.UNDEFINED;
 
 import java.lang.invoke.MethodHandle;
@@ -255,6 +256,12 @@
         return makeFunction(name, methodHandle, null);
     }
 
+    @Override
+    public ScriptFunction makeSynchronizedFunction(final Object sync) {
+        final MethodHandle mh = MH.insertArguments(ScriptFunction.INVOKE_SYNC, 0, this, sync);
+        return makeFunction(getName(), mh);
+    }
+
     /**
      * Same as {@link ScriptFunction#makeBoundFunction(Object, Object[])}. The only reason we override it is so that we
      * can expose it to methods in this package.
--- a/src/jdk/nashorn/internal/parser/Parser.java	Thu Oct 17 09:41:14 2013 -0700
+++ b/src/jdk/nashorn/internal/parser/Parser.java	Thu Oct 17 16:19:45 2013 -0700
@@ -2107,13 +2107,13 @@
             final String ident = (String)expectValue(IDENT);
 
             if (type != COLON) {
-                final long getSetToken = token;
+                final long getSetToken = propertyToken;
 
                 switch (ident) {
                 case "get":
                     final PropertyKey getIdent = propertyName();
                     final String getterName = getIdent.getPropertyName();
-                    final IdentNode getNameNode = new IdentNode(((Node)getIdent).getToken(), finish, "get " + NameCodec.encode(getterName));
+                    final IdentNode getNameNode = new IdentNode(((Node)getIdent).getToken(), finish, NameCodec.encode("get " + getterName));
                     expect(LPAREN);
                     expect(RPAREN);
                     functionNode = functionBody(getSetToken, getNameNode, new ArrayList<IdentNode>(), FunctionNode.Kind.GETTER);
@@ -2122,7 +2122,7 @@
                 case "set":
                     final PropertyKey setIdent = propertyName();
                     final String setterName = setIdent.getPropertyName();
-                    final IdentNode setNameNode = new IdentNode(((Node)setIdent).getToken(), finish, "set " + NameCodec.encode(setterName));
+                    final IdentNode setNameNode = new IdentNode(((Node)setIdent).getToken(), finish, NameCodec.encode("set " + setterName));
                     expect(LPAREN);
                     final IdentNode argIdent = getIdent();
                     verifyStrictIdent(argIdent, "setter argument");
--- a/src/jdk/nashorn/internal/parser/TokenType.java	Thu Oct 17 09:41:14 2013 -0700
+++ b/src/jdk/nashorn/internal/parser/TokenType.java	Thu Oct 17 16:19:45 2013 -0700
@@ -178,7 +178,6 @@
     ARRAY          (LITERAL,  null),
 
     COMMALEFT      (IR,       null),
-    CONVERT        (IR,       null),
     DISCARD        (IR,       null),
     DECPOSTFIX     (IR,       null),
     INCPOSTFIX     (IR,       null);
--- a/src/jdk/nashorn/internal/runtime/CodeInstaller.java	Thu Oct 17 09:41:14 2013 -0700
+++ b/src/jdk/nashorn/internal/runtime/CodeInstaller.java	Thu Oct 17 16:19:45 2013 -0700
@@ -68,4 +68,10 @@
      * @return unique script id
      */
     public long getUniqueScriptId();
+
+    /**
+     * Get next unique eval id
+     * @return unique eval id
+     */
+    public long getUniqueEvalId();
 }
--- a/src/jdk/nashorn/internal/runtime/Context.java	Thu Oct 17 09:41:14 2013 -0700
+++ b/src/jdk/nashorn/internal/runtime/Context.java	Thu Oct 17 16:19:45 2013 -0700
@@ -139,6 +139,11 @@
         public long getUniqueScriptId() {
             return context.getUniqueScriptId();
         }
+
+        @Override
+        public long getUniqueEvalId() {
+            return context.getUniqueEvalId();
+        }
     }
 
     /** Is Context global debug mode enabled ? */
@@ -238,10 +243,14 @@
     /** Unique id for script. Used only when --loader-per-compile=false */
     private final AtomicLong uniqueScriptId;
 
+    /** Unique id for 'eval' */
+    private final AtomicLong uniqueEvalId;
+
     private static final ClassLoader myLoader = Context.class.getClassLoader();
     private static final StructureLoader sharedLoader;
 
-    /*package-private*/ ClassLoader getSharedLoader() {
+    /*package-private*/ @SuppressWarnings("static-method")
+    ClassLoader getSharedLoader() {
         return sharedLoader;
     }
 
@@ -320,6 +329,7 @@
             this.uniqueScriptId = new AtomicLong();
         }
         this.errors    = errors;
+        this.uniqueEvalId = new AtomicLong();
 
         // if user passed -classpath option, make a class loader with that and set it as
         // thread context class loader so that script can access classes from that path.
@@ -625,11 +635,11 @@
      * @param clazz Class object
      * @throw SecurityException if not accessible
      */
-    public static void checkPackageAccess(final Class clazz) {
+    public static void checkPackageAccess(final Class<?> clazz) {
         final SecurityManager sm = System.getSecurityManager();
         if (sm != null) {
-            Class bottomClazz = clazz;
-            while(bottomClazz.isArray()) {
+            Class<?> bottomClazz = clazz;
+            while (bottomClazz.isArray()) {
                 bottomClazz = bottomClazz.getComponentType();
             }
             checkPackageAccess(sm, bottomClazz.getName());
@@ -664,7 +674,7 @@
      * @param clazz Class object
      * @return true if package is accessible, false otherwise
      */
-    private static boolean isAccessiblePackage(final Class clazz) {
+    private static boolean isAccessiblePackage(final Class<?> clazz) {
         try {
             checkPackageAccess(clazz);
             return true;
@@ -838,7 +848,7 @@
         return Context.getContextTrusted();
     }
 
-    private URL getResourceURL(final String resName) throws IOException {
+    private URL getResourceURL(final String resName) {
         // try the classPathLoader if we have and then
         // try the appLoader if non-null.
         if (classPathLoader != null) {
@@ -954,6 +964,10 @@
              }, CREATE_LOADER_ACC_CTXT);
     }
 
+    private long getUniqueEvalId() {
+        return uniqueEvalId.getAndIncrement();
+    }
+
     private long getUniqueScriptId() {
         return uniqueScriptId.getAndIncrement();
     }
--- a/src/jdk/nashorn/internal/runtime/DebugLogger.java	Thu Oct 17 09:41:14 2013 -0700
+++ b/src/jdk/nashorn/internal/runtime/DebugLogger.java	Thu Oct 17 16:19:45 2013 -0700
@@ -65,7 +65,17 @@
         } else {
             this.logger = Logging.getLogger(loggerName);
         }
-        this.isEnabled = logger.getLevel() != Level.OFF;
+        assert logger != null;
+        this.isEnabled = getLevel() != Level.OFF;
+    }
+
+    /**
+     * Do not currently support chaining this with parent logger. Logger level null
+     * means disabled
+     * @return level
+     */
+    private Level getLevel() {
+        return logger.getLevel() == null ? Level.OFF : logger.getLevel();
     }
 
     /**
@@ -126,7 +136,7 @@
      * @return true if level is above the given one
      */
     public boolean levelAbove(final Level level) {
-        return logger.getLevel().intValue() > level.intValue();
+        return getLevel().intValue() > level.intValue();
     }
 
     /**
--- a/src/jdk/nashorn/internal/runtime/GlobalObject.java	Thu Oct 17 09:41:14 2013 -0700
+++ b/src/jdk/nashorn/internal/runtime/GlobalObject.java	Thu Oct 17 16:19:45 2013 -0700
@@ -38,9 +38,10 @@
 public interface GlobalObject {
     /**
      * Is this global of the given Context?
+     * @param ctxt the context
      * @return true if this global belongs to the given Context
      */
-    public boolean isOfContext(Context context);
+    public boolean isOfContext(final Context ctxt);
 
     /**
      * Does this global belong to a strict Context?
--- a/src/jdk/nashorn/internal/runtime/JSType.java	Thu Oct 17 09:41:14 2013 -0700
+++ b/src/jdk/nashorn/internal/runtime/JSType.java	Thu Oct 17 16:19:45 2013 -0700
@@ -31,6 +31,8 @@
 import java.lang.invoke.MethodHandle;
 import java.lang.invoke.MethodHandles;
 import java.lang.reflect.Array;
+import java.util.Deque;
+import java.util.List;
 import jdk.internal.dynalink.beans.StaticClass;
 import jdk.nashorn.api.scripting.JSObject;
 import jdk.nashorn.internal.codegen.CompilerConstants.Call;
@@ -104,14 +106,20 @@
     /** JavaScript compliant conversion function from number to int64 */
     public static final Call TO_INT64_D = staticCall(myLookup, JSType.class, "toInt64", long.class, double.class);
 
-    /** JavaScript compliant conversion function from Object to String */
-    public static final Call TO_STRING = staticCall(myLookup, JSType.class, "toString", String.class, Object.class);
-
     /** JavaScript compliant conversion function from number to String */
     public static final Call TO_STRING_D = staticCall(myLookup, JSType.class, "toString", String.class, double.class);
 
-    /** JavaScript compliant conversion function from Object to primitive */
-    public static final Call TO_PRIMITIVE = staticCall(myLookup, JSType.class, "toPrimitive", Object.class,  Object.class);
+    /** Combined call to toPrimitive followed by toString. */
+    public static final Call TO_PRIMITIVE_TO_STRING = staticCall(myLookup, JSType.class, "toPrimitiveToString", String.class,  Object.class);
+
+    /** Method handle to convert a JS Object to a Java array. */
+    public static final Call TO_JAVA_ARRAY = staticCall(myLookup, JSType.class, "toJavaArray", Object.class, Object.class, Class.class);
+
+    /** Method handle to convert a JS Object to a Java List. */
+    public static final Call TO_JAVA_LIST = staticCall(myLookup, JSType.class, "toJavaList", List.class, Object.class);
+
+    /** Method handle to convert a JS Object to a Java deque. */
+   public static final Call TO_JAVA_DEQUE = staticCall(myLookup, JSType.class, "toJavaDeque", Deque.class, Object.class);
 
     private static final double INT32_LIMIT = 4294967296.0;
 
@@ -273,6 +281,17 @@
     }
 
     /**
+     * Combines a hintless toPrimitive and a toString call.
+     *
+     * @param obj  an object
+     *
+     * @return the string form of the primitive form of the object
+     */
+    public static String toPrimitiveToString(Object obj) {
+        return toString(toPrimitive(obj));
+    }
+
+    /**
      * JavaScript compliant conversion of number to boolean
      *
      * @param num a number
@@ -874,7 +893,7 @@
         if (obj instanceof ScriptObject) {
             return convertArray(((ScriptObject)obj).getArray().asObjectArray(), componentType);
         } else if (obj instanceof JSObject) {
-            final ArrayLikeIterator itr = ArrayLikeIterator.arrayLikeIterator(obj);
+            final ArrayLikeIterator<?> itr = ArrayLikeIterator.arrayLikeIterator(obj);
             final int len = (int) itr.getLength();
             final Object[] res = new Object[len];
             int idx = 0;
@@ -882,6 +901,8 @@
                 res[idx++] = itr.next();
             }
             return convertArray(res, componentType);
+        } else if(obj == null) {
+            return null;
         } else {
             throw new IllegalArgumentException("not a script object");
         }
@@ -911,6 +932,24 @@
     }
 
     /**
+     * Converts a JavaScript object to a Java List. See {@link ListAdapter} for details.
+     * @param obj the object to convert. Can be any array-like object.
+     * @return a List that is live-backed by the JavaScript object.
+     */
+    public static List<?> toJavaList(final Object obj) {
+        return ListAdapter.create(obj);
+    }
+
+    /**
+     * Converts a JavaScript object to a Java Deque. See {@link ListAdapter} for details.
+     * @param obj the object to convert. Can be any array-like object.
+     * @return a Deque that is live-backed by the JavaScript object.
+     */
+    public static Deque<?> toJavaDeque(final Object obj) {
+        return ListAdapter.create(obj);
+    }
+
+    /**
      * Check if an object is null or undefined
      *
      * @param obj object to check
--- a/src/jdk/nashorn/internal/runtime/ListAdapter.java	Thu Oct 17 09:41:14 2013 -0700
+++ b/src/jdk/nashorn/internal/runtime/ListAdapter.java	Thu Oct 17 16:19:45 2013 -0700
@@ -119,10 +119,11 @@
                 });
     }
 
+    /** wrapped object */
     protected final Object obj;
 
     // allow subclasses only in this package
-    ListAdapter(Object obj) {
+    ListAdapter(final Object obj) {
         this.obj = obj;
     }
 
@@ -143,22 +144,32 @@
     }
 
     @Override
-    public final Object get(int index) {
+    public final Object get(final int index) {
         checkRange(index);
         return getAt(index);
     }
 
+    /**
+     * Get object at an index
+     * @param index index in list
+     * @return object
+     */
     protected abstract Object getAt(final int index);
 
     @Override
-    public Object set(int index, Object element) {
+    public Object set(final int index, final Object element) {
         checkRange(index);
         final Object prevValue = getAt(index);
         setAt(index, element);
         return prevValue;
     }
 
-    protected abstract void setAt(int index, Object element);
+    /**
+     * Set object at an index
+     * @param index   index in list
+     * @param element element
+     */
+    protected abstract void setAt(final int index, final Object element);
 
     private void checkRange(int index) {
         if(index < 0 || index >= size()) {
@@ -167,18 +178,18 @@
     }
 
     @Override
-    public final void push(Object e) {
+    public final void push(final Object e) {
         addFirst(e);
     }
 
     @Override
-    public final boolean add(Object e) {
+    public final boolean add(final Object e) {
         addLast(e);
         return true;
     }
 
     @Override
-    public final void addFirst(Object e) {
+    public final void addFirst(final Object e) {
         try {
             final InvokeByName unshiftInvoker = getUNSHIFT();
             final Object fn = unshiftInvoker.getGetter().invokeExact(obj);
@@ -192,7 +203,7 @@
     }
 
     @Override
-    public final void addLast(Object e) {
+    public final void addLast(final Object e) {
         try {
             final InvokeByName pushInvoker = getPUSH();
             final Object fn = pushInvoker.getGetter().invokeExact(obj);
@@ -206,7 +217,7 @@
     }
 
     @Override
-    public final void add(int index, Object e) {
+    public final void add(final int index, final Object e) {
         try {
             if(index < 0) {
                 throw invalidIndex(index);
@@ -225,35 +236,35 @@
                     throw invalidIndex(index);
                 }
             }
-        } catch(RuntimeException | Error ex) {
+        } catch(final RuntimeException | Error ex) {
             throw ex;
-        } catch(Throwable t) {
+        } catch(final Throwable t) {
             throw new RuntimeException(t);
         }
     }
-    private static void checkFunction(Object fn, InvokeByName invoke) {
+    private static void checkFunction(final Object fn, final InvokeByName invoke) {
         if(!(Bootstrap.isCallable(fn))) {
             throw new UnsupportedOperationException("The script object doesn't have a function named " + invoke.getName());
         }
     }
 
-    private static IndexOutOfBoundsException invalidIndex(int index) {
+    private static IndexOutOfBoundsException invalidIndex(final int index) {
         return new IndexOutOfBoundsException(String.valueOf(index));
     }
 
     @Override
-    public final boolean offer(Object e) {
+    public final boolean offer(final Object e) {
         return offerLast(e);
     }
 
     @Override
-    public final boolean offerFirst(Object e) {
+    public final boolean offerFirst(final Object e) {
         addFirst(e);
         return true;
     }
 
     @Override
-    public final boolean offerLast(Object e) {
+    public final boolean offerLast(final Object e) {
         addLast(e);
         return true;
     }
@@ -287,7 +298,7 @@
     }
 
     @Override
-    public final Object remove(int index) {
+    public final Object remove(final int index) {
         if(index < 0) {
             throw invalidIndex(index);
         } else if (index == 0) {
@@ -333,11 +344,11 @@
     }
 
     @Override
-    protected final void removeRange(int fromIndex, int toIndex) {
+    protected final void removeRange(final int fromIndex, final int toIndex) {
         invokeSpliceRemove(fromIndex, toIndex - fromIndex);
     }
 
-    private void invokeSpliceRemove(int fromIndex, int count) {
+    private void invokeSpliceRemove(final int fromIndex, final int count) {
         try {
             final InvokeByName spliceRemoveInvoker = getSPLICE_REMOVE();
             final Object fn = spliceRemoveInvoker.getGetter().invokeExact(obj);
@@ -419,16 +430,16 @@
     }
 
     @Override
-    public final boolean removeFirstOccurrence(Object o) {
+    public final boolean removeFirstOccurrence(final Object o) {
         return removeOccurrence(o, iterator());
     }
 
     @Override
-    public final boolean removeLastOccurrence(Object o) {
+    public final boolean removeLastOccurrence(final Object o) {
         return removeOccurrence(o, descendingIterator());
     }
 
-    private static boolean removeOccurrence(Object o, Iterator<Object> it) {
+    private static boolean removeOccurrence(final Object o, final Iterator<Object> it) {
         while(it.hasNext()) {
             final Object e = it.next();
             if(o == null ? e == null : o.equals(e)) {
--- a/src/jdk/nashorn/internal/runtime/RecompilableScriptFunctionData.java	Thu Oct 17 09:41:14 2013 -0700
+++ b/src/jdk/nashorn/internal/runtime/RecompilableScriptFunctionData.java	Thu Oct 17 16:19:45 2013 -0700
@@ -33,6 +33,7 @@
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.LinkedList;
+import jdk.internal.dynalink.support.NameCodec;
 
 import jdk.nashorn.internal.codegen.Compiler;
 import jdk.nashorn.internal.codegen.CompilerConstants;
@@ -52,7 +53,7 @@
 public final class RecompilableScriptFunctionData extends ScriptFunctionData {
 
     /** FunctionNode with the code for this ScriptFunction */
-    private volatile FunctionNode functionNode;
+    private FunctionNode functionNode;
 
     /** Source from which FunctionNode was parsed. */
     private final Source source;
@@ -64,7 +65,7 @@
     private final PropertyMap allocatorMap;
 
     /** Code installer used for all further recompilation/specialization of this ScriptFunction */
-    private volatile CodeInstaller<ScriptEnvironment> installer;
+    private CodeInstaller<ScriptEnvironment> installer;
 
     /** Name of class where allocator function resides */
     private final String allocatorClassName;
@@ -100,9 +101,7 @@
      * @param allocatorMap       allocator map to seed instances with, when constructing
      */
     public RecompilableScriptFunctionData(final FunctionNode functionNode, final CodeInstaller<ScriptEnvironment> installer, final String allocatorClassName, final PropertyMap allocatorMap) {
-        super(functionNode.isAnonymous() ?
-                "" :
-                functionNode.getIdent().getName(),
+        super(functionName(functionNode),
               functionNode.getParameters().size(),
               functionNode.isStrict(),
               false,
@@ -139,6 +138,20 @@
         return sb.toString() + super.toString();
     }
 
+    private static String functionName(final FunctionNode fn) {
+        if (fn.isAnonymous()) {
+            return "";
+        } else {
+            final FunctionNode.Kind kind = fn.getKind();
+            if (kind == FunctionNode.Kind.GETTER || kind == FunctionNode.Kind.SETTER) {
+                final String name = NameCodec.decode(fn.getIdent().getName());
+                return name.substring(4); // 4 is "get " or "set "
+            } else {
+                return fn.getIdent().getName();
+            }
+        }
+    }
+
     private static long tokenFor(final FunctionNode fn) {
         final int  position   = Token.descPosition(fn.getFirstToken());
         final int  length     = Token.descPosition(fn.getLastToken()) - position + Token.descLength(fn.getLastToken());
@@ -165,7 +178,7 @@
     }
 
     @Override
-    protected void ensureCodeGenerated() {
+    protected synchronized void ensureCodeGenerated() {
          if (!code.isEmpty()) {
              return; // nothing to do, we have code, at least some.
          }
@@ -323,7 +336,7 @@
     }
 
     @Override
-    MethodHandle getBestInvoker(final MethodType callSiteType, final Object[] args) {
+    synchronized MethodHandle getBestInvoker(final MethodType callSiteType, final Object[] args) {
         final MethodType runtimeType = runtimeType(callSiteType, args);
         assert runtimeType.parameterCount() == callSiteType.parameterCount();
 
--- a/src/jdk/nashorn/internal/runtime/ScriptFunction.java	Thu Oct 17 09:41:14 2013 -0700
+++ b/src/jdk/nashorn/internal/runtime/ScriptFunction.java	Thu Oct 17 16:19:45 2013 -0700
@@ -59,6 +59,9 @@
     /** Method handle for name getter for this ScriptFunction */
     public static final MethodHandle G$NAME = findOwnMH("G$name", Object.class, Object.class);
 
+    /** Method handle used for implementing sync() in mozilla_compat */
+    public static final MethodHandle INVOKE_SYNC = findOwnMH("invokeSync", Object.class, ScriptFunction.class, Object.class, Object.class, Object[].class);
+
     /** Method handle for allocate function for this ScriptFunction */
     static final MethodHandle ALLOCATE = findOwnMH("allocate", Object.class);
 
@@ -301,6 +304,14 @@
     public abstract void setPrototype(Object prototype);
 
     /**
+     * Create a function that invokes this function synchronized on {@code sync} or the self object
+     * of the invocation.
+     * @param sync the Object to synchronize on, or undefined
+     * @return synchronized function
+     */
+    public abstract ScriptFunction makeSynchronizedFunction(Object sync);
+
+    /**
      * Return the most appropriate invoke handle if there are specializations
      * @param type most specific method type to look for invocation with
      * @param args args for trampoline invocation
@@ -326,7 +337,7 @@
      * @param self self reference
      * @return bound invoke handle
      */
-    public final MethodHandle getBoundInvokeHandle(final ScriptObject self) {
+    public final MethodHandle getBoundInvokeHandle(final Object self) {
         return MH.bindTo(bindToCalleeIfNeeded(data.getGenericInvoker()), self);
     }
 
@@ -614,6 +625,15 @@
         return result;
     }
 
+    @SuppressWarnings("unused")
+    private static Object invokeSync(final ScriptFunction func, final Object sync, final Object self, final Object... args)
+            throws Throwable {
+        final Object syncObj = sync == UNDEFINED ? self : sync;
+        synchronized (syncObj) {
+            return func.invoke(self, args);
+        }
+    }
+
     private static MethodHandle findOwnMH(final String name, final Class<?> rtype, final Class<?>... types) {
         final Class<?>   own = ScriptFunction.class;
         final MethodType mt  = MH.type(rtype, types);
--- a/src/jdk/nashorn/internal/runtime/ScriptFunctionData.java	Thu Oct 17 09:41:14 2013 -0700
+++ b/src/jdk/nashorn/internal/runtime/ScriptFunctionData.java	Thu Oct 17 16:19:45 2013 -0700
@@ -675,7 +675,7 @@
 
     /**
      * Heuristic to figure out if the method handle has a callee argument. If it's type is either
-     * {@code (boolean, Object, ScriptFunction, ...)} or {@code (Object, ScriptFunction, ...)}, then we'll assume it has
+     * {@code (boolean, ScriptFunction, ...)} or {@code (ScriptFunction, ...)}, then we'll assume it has
      * a callee argument. We need this as the constructor above is not passed this information, and can't just blindly
      * assume it's false (notably, it's being invoked for creation of new scripts, and scripts have scopes, therefore
      * they also always receive a callee).
@@ -692,11 +692,11 @@
             return false;
         }
 
-        if (type.parameterType(0) == boolean.class) {
-            return length > 1 && type.parameterType(1) == ScriptFunction.class;
+        if (type.parameterType(0) == ScriptFunction.class) {
+            return true;
         }
 
-        return type.parameterType(0) == ScriptFunction.class;
+        return length > 1 && type.parameterType(0) == boolean.class && type.parameterType(1) == ScriptFunction.class;
     }
 
     /**
--- a/src/jdk/nashorn/internal/runtime/ScriptLoader.java	Thu Oct 17 09:41:14 2013 -0700
+++ b/src/jdk/nashorn/internal/runtime/ScriptLoader.java	Thu Oct 17 16:19:45 2013 -0700
@@ -64,6 +64,7 @@
                     return context.getSharedLoader().loadClass(name);
                 }
             } catch (final ClassNotFoundException ignored) {
+                //ignored
             }
 
             // throw the original exception from here
--- a/src/jdk/nashorn/internal/runtime/ScriptObject.java	Thu Oct 17 09:41:14 2013 -0700
+++ b/src/jdk/nashorn/internal/runtime/ScriptObject.java	Thu Oct 17 16:19:45 2013 -0700
@@ -37,6 +37,8 @@
 import static jdk.nashorn.internal.runtime.PropertyDescriptor.VALUE;
 import static jdk.nashorn.internal.runtime.PropertyDescriptor.WRITABLE;
 import static jdk.nashorn.internal.runtime.ScriptRuntime.UNDEFINED;
+import static jdk.nashorn.internal.runtime.arrays.ArrayIndex.getArrayIndex;
+import static jdk.nashorn.internal.runtime.arrays.ArrayIndex.isValidArrayIndex;
 
 import java.lang.invoke.MethodHandle;
 import java.lang.invoke.MethodHandles;
@@ -131,6 +133,7 @@
 
     static final MethodHandle GETPROTO           = findOwnMH("getProto", ScriptObject.class);
     static final MethodHandle SETPROTOCHECK      = findOwnMH("setProtoCheck", void.class, Object.class);
+    static final MethodHandle MEGAMORPHIC_GET    = findOwnMH("megamorphicGet", Object.class, String.class, boolean.class);
 
     static final MethodHandle SETFIELD           = findOwnMH("setField",         void.class, CallSiteDescriptor.class, PropertyMap.class, PropertyMap.class, MethodHandle.class, Object.class, Object.class);
     static final MethodHandle SETSPILL           = findOwnMH("setSpill",         void.class, CallSiteDescriptor.class, PropertyMap.class, PropertyMap.class, int.class, Object.class, Object.class);
@@ -388,7 +391,7 @@
             return global.newDataDescriptor(getWithProperty(property), configurable, enumerable, writable);
         }
 
-        final int index = ArrayIndex.getArrayIndex(key);
+        final int index = getArrayIndex(key);
         final ArrayData array = getArray();
 
         if (array.has(index)) {
@@ -592,7 +595,7 @@
      * @param value value to define
      */
     protected final void defineOwnProperty(final int index, final Object value) {
-        assert ArrayIndex.isValidArrayIndex(index) : "invalid array index";
+        assert isValidArrayIndex(index) : "invalid array index";
         final long longIndex = ArrayIndex.toLongIndex(index);
         if (longIndex >= getArray().length()) {
             // make array big enough to hold..
@@ -602,9 +605,9 @@
     }
 
     private void checkIntegerKey(final String key) {
-        final int index = ArrayIndex.getArrayIndex(key);
-
-        if (ArrayIndex.isValidArrayIndex(index)) {
+        final int index = getArrayIndex(key);
+
+        if (isValidArrayIndex(index)) {
             final ArrayData data = getArray();
 
             if (data.has(index)) {
@@ -614,7 +617,7 @@
     }
 
     private void removeArraySlot(final String key) {
-        final int index = ArrayIndex.getArrayIndex(key);
+        final int index = getArrayIndex(key);
         final ArrayData array = getArray();
 
         if (array.has(index)) {
@@ -717,6 +720,28 @@
     }
 
     /**
+     * Low level property API. This is similar to {@link #findProperty(String, boolean)} but returns a
+     * {@code boolean} value instead of a {@link FindProperty} object.
+     * @param key  Property key.
+     * @param deep Whether the search should look up proto chain.
+     * @return true if the property was found.
+     */
+    boolean hasProperty(final String key, final boolean deep) {
+        if (getMap().findProperty(key) != null) {
+            return true;
+        }
+
+        if (deep) {
+            final ScriptObject myProto = getProto();
+            if (myProto != null) {
+                return myProto.hasProperty(key, deep);
+            }
+        }
+
+        return false;
+    }
+
+    /**
      * Add a new property to the object.
      * <p>
      * This a more "low level" way that doesn't involve {@link PropertyDescriptor}s
@@ -1708,8 +1733,11 @@
      */
     protected GuardedInvocation findGetMethod(final CallSiteDescriptor desc, final LinkRequest request, final String operator) {
         final String name = desc.getNameToken(CallSiteDescriptor.NAME_OPERAND);
+        if (request.isCallSiteUnstable()) {
+            return findMegaMorphicGetMethod(desc, name, "getMethod".equals(operator));
+        }
+
         final FindProperty find = findProperty(name, true);
-
         MethodHandle methodHandle;
 
         if (find == null) {
@@ -1727,10 +1755,6 @@
             throw new AssertionError(); // never invoked with any other operation
         }
 
-        if (request.isCallSiteUnstable()) {
-            return findMegaMorphicGetMethod(desc, name);
-        }
-
         final Class<?> returnType = desc.getMethodType().returnType();
         final Property property = find.getProperty();
         methodHandle = find.getGetter(returnType);
@@ -1757,11 +1781,21 @@
         return new GuardedInvocation(Lookup.emptyGetter(returnType), getMap().getProtoGetSwitchPoint(proto, name), guard);
     }
 
-    private static GuardedInvocation findMegaMorphicGetMethod(final CallSiteDescriptor desc, final String name) {
-        final MethodType mhType = desc.getMethodType().insertParameterTypes(1, Object.class);
-        final GuardedInvocation inv = findGetIndexMethod(mhType);
-
-        return inv.replaceMethods(MH.insertArguments(inv.getInvocation(), 1, name), inv.getGuard());
+    private static GuardedInvocation findMegaMorphicGetMethod(final CallSiteDescriptor desc, final String name, final boolean isMethod) {
+        final MethodHandle invoker = MH.insertArguments(MEGAMORPHIC_GET, 1, name, isMethod);
+        final MethodHandle guard = getScriptObjectGuard(desc.getMethodType());
+        return new GuardedInvocation(invoker, guard);
+    }
+
+    @SuppressWarnings("unused")
+    private Object megamorphicGet(final String key, final boolean isMethod) {
+        final FindProperty find = findProperty(key, true);
+
+        if (find != null) {
+            return getObjectValue(find);
+        }
+
+        return isMethod ? getNoSuchMethod(key) : invokeNoSuchProperty(key);
     }
 
     /**
@@ -1810,7 +1844,7 @@
      */
     protected GuardedInvocation findSetMethod(final CallSiteDescriptor desc, final LinkRequest request) {
         final String name = desc.getNameToken(CallSiteDescriptor.NAME_OPERAND);
-        if(request.isCallSiteUnstable()) {
+        if (request.isCallSiteUnstable()) {
             return findMegaMorphicSetMethod(desc, name);
         }
 
@@ -2045,6 +2079,26 @@
         return UNDEFINED;
     }
 
+    /**
+     * Get __noSuchMethod__ as a function bound to this object and {@code name} if it is defined.
+     * @param name the method name
+     * @return the bound function, or undefined
+     */
+    private Object getNoSuchMethod(final String name) {
+        final FindProperty find = findProperty(NO_SUCH_METHOD_NAME, true);
+
+        if (find == null) {
+            return invokeNoSuchProperty(name);
+        }
+
+        final Object value = getObjectValue(find);
+        if (! (value instanceof ScriptFunction)) {
+            return UNDEFINED;
+        }
+
+        return ((ScriptFunction)value).makeBoundFunction(this, new Object[] {name});
+    }
+
     private GuardedInvocation createEmptyGetter(final CallSiteDescriptor desc, final String name) {
         return new GuardedInvocation(Lookup.emptyGetter(desc.getMethodType().returnType()), getMap().getProtoGetSwitchPoint(proto, name), NashornGuards.getMapGuard(getMap()));
     }
@@ -2308,7 +2362,7 @@
     }
 
     private int getInt(final int index, final String key) {
-        if (ArrayIndex.isValidArrayIndex(index)) {
+        if (isValidArrayIndex(index)) {
              for (ScriptObject object = this; ; ) {
                 final FindProperty find = object.findProperty(key, false, false, this);
 
@@ -2339,7 +2393,7 @@
 
     @Override
     public int getInt(final Object key) {
-        final int index = ArrayIndex.getArrayIndex(key);
+        final int index = getArrayIndex(key);
         final ArrayData array = getArray();
 
         if (array.has(index)) {
@@ -2351,7 +2405,7 @@
 
     @Override
     public int getInt(final double key) {
-        final int index = ArrayIndex.getArrayIndex(key);
+        final int index = getArrayIndex(key);
         final ArrayData array = getArray();
 
         if (array.has(index)) {
@@ -2363,7 +2417,7 @@
 
     @Override
     public int getInt(final long key) {
-        final int index = ArrayIndex.getArrayIndex(key);
+        final int index = getArrayIndex(key);
         final ArrayData array = getArray();
 
         if (array.has(index)) {
@@ -2385,7 +2439,7 @@
     }
 
     private long getLong(final int index, final String key) {
-        if (ArrayIndex.isValidArrayIndex(index)) {
+        if (isValidArrayIndex(index)) {
             for (ScriptObject object = this; ; ) {
                 final FindProperty find = object.findProperty(key, false, false, this);
 
@@ -2416,7 +2470,7 @@
 
     @Override
     public long getLong(final Object key) {
-        final int index = ArrayIndex.getArrayIndex(key);
+        final int index = getArrayIndex(key);
         final ArrayData array = getArray();
 
         if (array.has(index)) {
@@ -2428,7 +2482,7 @@
 
     @Override
     public long getLong(final double key) {
-        final int index = ArrayIndex.getArrayIndex(key);
+        final int index = getArrayIndex(key);
         final ArrayData array = getArray();
 
         if (array.has(index)) {
@@ -2440,7 +2494,7 @@
 
     @Override
     public long getLong(final long key) {
-        final int index = ArrayIndex.getArrayIndex(key);
+        final int index = getArrayIndex(key);
         final ArrayData array = getArray();
 
         if (array.has(index)) {
@@ -2462,7 +2516,7 @@
     }
 
     private double getDouble(final int index, final String key) {
-        if (ArrayIndex.isValidArrayIndex(index)) {
+        if (isValidArrayIndex(index)) {
             for (ScriptObject object = this; ; ) {
                 final FindProperty find = object.findProperty(key, false, false, this);
 
@@ -2493,7 +2547,7 @@
 
     @Override
     public double getDouble(final Object key) {
-        final int index = ArrayIndex.getArrayIndex(key);
+        final int index = getArrayIndex(key);
         final ArrayData array = getArray();
 
         if (array.has(index)) {
@@ -2505,7 +2559,7 @@
 
     @Override
     public double getDouble(final double key) {
-        final int index = ArrayIndex.getArrayIndex(key);
+        final int index = getArrayIndex(key);
         final ArrayData array = getArray();
 
         if (array.has(index)) {
@@ -2517,7 +2571,7 @@
 
     @Override
     public double getDouble(final long key) {
-        final int index = ArrayIndex.getArrayIndex(key);
+        final int index = getArrayIndex(key);
         final ArrayData array = getArray();
 
         if (array.has(index)) {
@@ -2539,7 +2593,7 @@
     }
 
     private Object get(final int index, final String key) {
-        if (ArrayIndex.isValidArrayIndex(index)) {
+        if (isValidArrayIndex(index)) {
             for (ScriptObject object = this; ; ) {
                 final FindProperty find = object.findProperty(key, false, false, this);
 
@@ -2570,7 +2624,7 @@
 
     @Override
     public Object get(final Object key) {
-        final int index = ArrayIndex.getArrayIndex(key);
+        final int index = getArrayIndex(key);
         final ArrayData array = getArray();
 
         if (array.has(index)) {
@@ -2582,7 +2636,7 @@
 
     @Override
     public Object get(final double key) {
-        final int index = ArrayIndex.getArrayIndex(key);
+        final int index = getArrayIndex(key);
         final ArrayData array = getArray();
 
         if (array.has(index)) {
@@ -2594,7 +2648,7 @@
 
     @Override
     public Object get(final long key) {
-        final int index = ArrayIndex.getArrayIndex(key);
+        final int index = getArrayIndex(key);
         final ArrayData array = getArray();
 
         if (array.has(index)) {
@@ -2710,9 +2764,9 @@
 
     @Override
     public void set(final Object key, final int value, final boolean strict) {
-        final int index = ArrayIndex.getArrayIndex(key);
-
-        if (ArrayIndex.isValidArrayIndex(index)) {
+        final int index = getArrayIndex(key);
+
+        if (isValidArrayIndex(index)) {
             if (getArray().has(index)) {
                 setArray(getArray().set(index, value, strict));
             } else {
@@ -2722,14 +2776,15 @@
             return;
         }
 
-        set(key, JSType.toObject(value), strict);
+        final String propName = JSType.toString(key);
+        setObject(findProperty(propName, true), strict, propName, JSType.toObject(value));
     }
 
     @Override
     public void set(final Object key, final long value, final boolean strict) {
-        final int index = ArrayIndex.getArrayIndex(key);
-
-        if (ArrayIndex.isValidArrayIndex(index)) {
+        final int index = getArrayIndex(key);
+
+        if (isValidArrayIndex(index)) {
             if (getArray().has(index)) {
                 setArray(getArray().set(index, value, strict));
             } else {
@@ -2739,14 +2794,15 @@
             return;
         }
 
-        set(key, JSType.toObject(value), strict);
+        final String propName = JSType.toString(key);
+        setObject(findProperty(propName, true), strict, propName, JSType.toObject(value));
     }
 
     @Override
     public void set(final Object key, final double value, final boolean strict) {
-        final int index = ArrayIndex.getArrayIndex(key);
-
-        if (ArrayIndex.isValidArrayIndex(index)) {
+        final int index = getArrayIndex(key);
+
+        if (isValidArrayIndex(index)) {
             if (getArray().has(index)) {
                 setArray(getArray().set(index, value, strict));
             } else {
@@ -2756,14 +2812,15 @@
             return;
         }
 
-        set(key, JSType.toObject(value), strict);
+        final String propName = JSType.toString(key);
+        setObject(findProperty(propName, true), strict, propName, JSType.toObject(value));
     }
 
     @Override
     public void set(final Object key, final Object value, final boolean strict) {
-        final int index = ArrayIndex.getArrayIndex(key);
-
-        if (ArrayIndex.isValidArrayIndex(index)) {
+        final int index = getArrayIndex(key);
+
+        if (isValidArrayIndex(index)) {
             if (getArray().has(index)) {
                 setArray(getArray().set(index, value, strict));
             } else {
@@ -2773,17 +2830,15 @@
             return;
         }
 
-        final String       propName = JSType.toString(key);
-        final FindProperty find     = findProperty(propName, true);
-
-        setObject(find, strict, propName, value);
+        final String propName = JSType.toString(key);
+        setObject(findProperty(propName, true), strict, propName, value);
     }
 
     @Override
     public void set(final double key, final int value, final boolean strict) {
-        final int index = ArrayIndex.getArrayIndex(key);
-
-        if (ArrayIndex.isValidArrayIndex(index)) {
+        final int index = getArrayIndex(key);
+
+        if (isValidArrayIndex(index)) {
             if (getArray().has(index)) {
                 setArray(getArray().set(index, value, strict));
             } else {
@@ -2793,14 +2848,15 @@
             return;
         }
 
-        set(JSType.toObject(key), JSType.toObject(value), strict);
+        final String propName = JSType.toString(key);
+        setObject(findProperty(propName, true), strict, propName, JSType.toObject(value));
     }
 
     @Override
     public void set(final double key, final long value, final boolean strict) {
-        final int index = ArrayIndex.getArrayIndex(key);
-
-        if (ArrayIndex.isValidArrayIndex(index)) {
+        final int index = getArrayIndex(key);
+
+        if (isValidArrayIndex(index)) {
             if (getArray().has(index)) {
                 setArray(getArray().set(index, value, strict));
             } else {
@@ -2810,14 +2866,15 @@
             return;
         }
 
-        set(JSType.toObject(key), JSType.toObject(value), strict);
+        final String propName = JSType.toString(key);
+        setObject(findProperty(propName, true), strict, propName, JSType.toObject(value));
     }
 
     @Override
     public void set(final double key, final double value, final boolean strict) {
-        final int index = ArrayIndex.getArrayIndex(key);
-
-        if (ArrayIndex.isValidArrayIndex(index)) {
+        final int index = getArrayIndex(key);
+
+        if (isValidArrayIndex(index)) {
             if (getArray().has(index)) {
                 setArray(getArray().set(index, value, strict));
             } else {
@@ -2827,14 +2884,15 @@
             return;
         }
 
-        set(JSType.toObject(key), JSType.toObject(value), strict);
+        final String propName = JSType.toString(key);
+        setObject(findProperty(propName, true), strict, propName, JSType.toObject(value));
     }
 
     @Override
     public void set(final double key, final Object value, final boolean strict) {
-        final int index = ArrayIndex.getArrayIndex(key);
-
-        if (ArrayIndex.isValidArrayIndex(index)) {
+        final int index = getArrayIndex(key);
+
+        if (isValidArrayIndex(index)) {
             if (getArray().has(index)) {
                 setArray(getArray().set(index, value, strict));
             } else {
@@ -2844,14 +2902,15 @@
             return;
         }
 
-        set(JSType.toObject(key), value, strict);
+        final String propName = JSType.toString(key);
+        setObject(findProperty(propName, true), strict, propName, value);
     }
 
     @Override
     public void set(final long key, final int value, final boolean strict) {
-        final int index = ArrayIndex.getArrayIndex(key);
-
-        if (ArrayIndex.isValidArrayIndex(index)) {
+        final int index = getArrayIndex(key);
+
+        if (isValidArrayIndex(index)) {
             if (getArray().has(index)) {
                 setArray(getArray().set(index, value, strict));
             } else {
@@ -2861,31 +2920,15 @@
             return;
         }
 
-        set(JSType.toObject(key), JSType.toObject(value), strict);
+        final String propName = JSType.toString(key);
+        setObject(findProperty(propName, true), strict, propName, JSType.toObject(value));
     }
 
     @Override
     public void set(final long key, final long value, final boolean strict) {
-        final int index = ArrayIndex.getArrayIndex(key);
-
-        if (ArrayIndex.isValidArrayIndex(index)) {
-            if (getArray().has(index)) {
-                setArray(getArray().set(index, value, strict));
-            } else {
-                doesNotHave(index, value, strict);
-            }
-
-            return;
-        }
-
-        set(JSType.toObject(key), JSType.toObject(value), strict);
-    }
-
-    @Override
-    public void set(final long key, final double value, final boolean strict) {
-        final int index = ArrayIndex.getArrayIndex(key);
-
-        if (ArrayIndex.isValidArrayIndex(index)) {
+        final int index = getArrayIndex(key);
+
+        if (isValidArrayIndex(index)) {
             if (getArray().has(index)) {
                 setArray(getArray().set(index, value, strict));
             } else {
@@ -2895,14 +2938,15 @@
             return;
         }
 
-        set(JSType.toObject(key), JSType.toObject(value), strict);
+        final String propName = JSType.toString(key);
+        setObject(findProperty(propName, true), strict, propName, JSType.toObject(value));
     }
 
     @Override
-    public void set(final long key, final Object value, final boolean strict) {
-        final int index = ArrayIndex.getArrayIndex(key);
-
-        if (ArrayIndex.isValidArrayIndex(index)) {
+    public void set(final long key, final double value, final boolean strict) {
+        final int index = getArrayIndex(key);
+
+        if (isValidArrayIndex(index)) {
             if (getArray().has(index)) {
                 setArray(getArray().set(index, value, strict));
             } else {
@@ -2912,14 +2956,15 @@
             return;
         }
 
-        set(JSType.toObject(key), value, strict);
+        final String propName = JSType.toString(key);
+        setObject(findProperty(propName, true), strict, propName, JSType.toObject(value));
     }
 
     @Override
-    public void set(final int key, final int value, final boolean strict) {
-        final int index = ArrayIndex.getArrayIndex(key);
-
-        if (ArrayIndex.isValidArrayIndex(index)) {
+    public void set(final long key, final Object value, final boolean strict) {
+        final int index = getArrayIndex(key);
+
+        if (isValidArrayIndex(index)) {
             if (getArray().has(index)) {
                 setArray(getArray().set(index, value, strict));
             } else {
@@ -2929,14 +2974,15 @@
             return;
         }
 
-        set(JSType.toObject(key), JSType.toObject(value), strict);
+        final String propName = JSType.toString(key);
+        setObject(findProperty(propName, true), strict, propName, value);
     }
 
     @Override
-    public void set(final int key, final long value, final boolean strict) {
-        final int index = ArrayIndex.getArrayIndex(key);
-
-        if (ArrayIndex.isValidArrayIndex(index)) {
+    public void set(final int key, final int value, final boolean strict) {
+        final int index = getArrayIndex(key);
+
+        if (isValidArrayIndex(index)) {
             if (getArray().has(index)) {
                 setArray(getArray().set(index, value, strict));
             } else {
@@ -2946,14 +2992,15 @@
             return;
         }
 
-        set(JSType.toObject(key), JSType.toObject(value), strict);
+        final String propName = JSType.toString(key);
+        setObject(findProperty(propName, true), strict, propName, JSType.toObject(value));
     }
 
     @Override
-    public void set(final int key, final double value, final boolean strict) {
-        final int index = ArrayIndex.getArrayIndex(key);
-
-        if (ArrayIndex.isValidArrayIndex(index)) {
+    public void set(final int key, final long value, final boolean strict) {
+        final int index = getArrayIndex(key);
+
+        if (isValidArrayIndex(index)) {
             if (getArray().has(index)) {
                 setArray(getArray().set(index, value, strict));
             } else {
@@ -2963,14 +3010,15 @@
             return;
         }
 
-        set(JSType.toObject(key), JSType.toObject(value), strict);
+        final String propName = JSType.toString(key);
+        setObject(findProperty(propName, true), strict, propName, JSType.toObject(value));
     }
 
     @Override
-    public void set(final int key, final Object value, final boolean strict) {
-        final int index = ArrayIndex.getArrayIndex(key);
-
-        if (ArrayIndex.isValidArrayIndex(index)) {
+    public void set(final int key, final double value, final boolean strict) {
+        final int index = getArrayIndex(key);
+
+        if (isValidArrayIndex(index)) {
             if (getArray().has(index)) {
                 setArray(getArray().set(index, value, strict));
             } else {
@@ -2980,14 +3028,33 @@
             return;
         }
 
-        set(JSType.toObject(key), value, strict);
+        final String propName = JSType.toString(key);
+        setObject(findProperty(propName, true), strict, propName, JSType.toObject(value));
+    }
+
+    @Override
+    public void set(final int key, final Object value, final boolean strict) {
+        final int index = getArrayIndex(key);
+
+        if (isValidArrayIndex(index)) {
+            if (getArray().has(index)) {
+                setArray(getArray().set(index, value, strict));
+            } else {
+                doesNotHave(index, value, strict);
+            }
+
+            return;
+        }
+
+        final String propName = JSType.toString(key);
+        setObject(findProperty(propName, true), strict, propName, value);
     }
 
     @Override
     public boolean has(final Object key) {
-        final int index = ArrayIndex.getArrayIndex(key);
-
-        if (ArrayIndex.isValidArrayIndex(index)) {
+        final int index = getArrayIndex(key);
+
+        if (isValidArrayIndex(index)) {
             for (ScriptObject self = this; self != null; self = self.getProto()) {
                 if (self.getArray().has(index)) {
                     return true;
@@ -2995,33 +3062,14 @@
             }
         }
 
-        final FindProperty find = findProperty(JSType.toString(key), true);
-
-        return find != null;
+        return hasProperty(JSType.toString(key), true);
     }
 
     @Override
     public boolean has(final double key) {
-        final int index = ArrayIndex.getArrayIndex(key);
-
-        if (ArrayIndex.isValidArrayIndex(index)) {
-            for (ScriptObject self = this; self != null; self = self.getProto()) {
-                if (self.getArray().has(index)) {
-                    return true;
-                }
-            }
-        }
-
-        final FindProperty find = findProperty(JSType.toString(key), true);
-
-        return find != null;
-    }
-
-    @Override
-    public boolean has(final long key) {
-        final int index = ArrayIndex.getArrayIndex(key);
-
-        if (ArrayIndex.isValidArrayIndex(index)) {
+        final int index = getArrayIndex(key);
+
+        if (isValidArrayIndex(index)) {
             for (ScriptObject self = this; self != null; self = self.getProto()) {
                 if (self.getArray().has(index)) {
                     return true;
@@ -3029,16 +3077,14 @@
             }
         }
 
-        final FindProperty find = findProperty(JSType.toString(key), true);
-
-        return find != null;
+        return hasProperty(JSType.toString(key), true);
     }
 
     @Override
-    public boolean has(final int key) {
-        final int index = ArrayIndex.getArrayIndex(key);
-
-        if (ArrayIndex.isValidArrayIndex(index)) {
+    public boolean has(final long key) {
+        final int index = getArrayIndex(key);
+
+        if (isValidArrayIndex(index)) {
             for (ScriptObject self = this; self != null; self = self.getProto()) {
                 if (self.getArray().has(index)) {
                     return true;
@@ -3046,66 +3092,47 @@
             }
         }
 
-        final FindProperty find = findProperty(JSType.toString(key), true);
-
-        return find != null;
+        return hasProperty(JSType.toString(key), true);
+    }
+
+    @Override
+    public boolean has(final int key) {
+        final int index = getArrayIndex(key);
+
+        if (isValidArrayIndex(index)) {
+            for (ScriptObject self = this; self != null; self = self.getProto()) {
+                if (self.getArray().has(index)) {
+                    return true;
+                }
+            }
+        }
+
+        return hasProperty(JSType.toString(key), true);
     }
 
     @Override
     public boolean hasOwnProperty(final Object key) {
-        final int index = ArrayIndex.getArrayIndex(key);
-
-        if (getArray().has(index)) {
-            return true;
-        }
-
-        final FindProperty find = findProperty(JSType.toString(key), false);
-
-        return find != null;
+        return getArray().has(getArrayIndex(key)) || hasProperty(JSType.toString(key), false);
     }
 
     @Override
     public boolean hasOwnProperty(final int key) {
-        final int index = ArrayIndex.getArrayIndex(key);
-
-        if (getArray().has(index)) {
-            return true;
-        }
-
-        final FindProperty find = findProperty(JSType.toString(key), false);
-
-        return find != null;
+        return getArray().has(getArrayIndex(key)) || hasProperty(JSType.toString(key), false);
     }
 
     @Override
     public boolean hasOwnProperty(final long key) {
-        final int index = ArrayIndex.getArrayIndex(key);
-
-        if (getArray().has(index)) {
-            return true;
-        }
-
-        final FindProperty find = findProperty(JSType.toString(key), false);
-
-        return find != null;
+        return getArray().has(getArrayIndex(key)) || hasProperty(JSType.toString(key), false);
     }
 
     @Override
     public boolean hasOwnProperty(final double key) {
-        final int index = ArrayIndex.getArrayIndex(key);
-
-        if (getArray().has(index)) {
-            return true;
-        }
-
-        final FindProperty find = findProperty(JSType.toString(key), false);
-
-        return find != null;
+        return getArray().has(getArrayIndex(key)) || hasProperty(JSType.toString(key), false);
     }
 
     @Override
     public boolean delete(final int key, final boolean strict) {
-        final int index = ArrayIndex.getArrayIndex(key);
+        final int index = getArrayIndex(key);
         final ArrayData array = getArray();
 
         if (array.has(index)) {
@@ -3121,7 +3148,7 @@
 
     @Override
     public boolean delete(final long key, final boolean strict) {
-        final int index = ArrayIndex.getArrayIndex(key);
+        final int index = getArrayIndex(key);
         final ArrayData array = getArray();
 
         if (array.has(index)) {
@@ -3137,7 +3164,7 @@
 
     @Override
     public boolean delete(final double key, final boolean strict) {
-        final int index = ArrayIndex.getArrayIndex(key);
+        final int index = getArrayIndex(key);
         final ArrayData array = getArray();
 
         if (array.has(index)) {
@@ -3153,7 +3180,7 @@
 
     @Override
     public boolean delete(final Object key, final boolean strict) {
-        final int index = ArrayIndex.getArrayIndex(key);
+        final int index = getArrayIndex(key);
         final ArrayData array = getArray();
 
         if (array.has(index)) {
--- a/src/jdk/nashorn/internal/runtime/WithObject.java	Thu Oct 17 09:41:14 2013 -0700
+++ b/src/jdk/nashorn/internal/runtime/WithObject.java	Thu Oct 17 16:19:45 2013 -0700
@@ -316,6 +316,10 @@
         return expression;
     }
 
+    /**
+     * Get the parent scope for this {@code WithObject}
+     * @return the parent scope
+     */
     public ScriptObject getParentScope() {
         return getProto();
     }
--- a/src/jdk/nashorn/internal/runtime/arrays/JavaArrayIterator.java	Thu Oct 17 09:41:14 2013 -0700
+++ b/src/jdk/nashorn/internal/runtime/arrays/JavaArrayIterator.java	Thu Oct 17 16:19:45 2013 -0700
@@ -77,4 +77,4 @@
     public void remove() {
         throw new UnsupportedOperationException("remove");
     }
-}
\ No newline at end of file
+}
--- a/src/jdk/nashorn/internal/runtime/arrays/ReverseJavaArrayIterator.java	Thu Oct 17 09:41:14 2013 -0700
+++ b/src/jdk/nashorn/internal/runtime/arrays/ReverseJavaArrayIterator.java	Thu Oct 17 16:19:45 2013 -0700
@@ -55,4 +55,4 @@
     protected long bumpIndex() {
         return index--;
     }
-}
\ No newline at end of file
+}
--- a/src/jdk/nashorn/internal/runtime/linker/JSObjectLinker.java	Thu Oct 17 09:41:14 2013 -0700
+++ b/src/jdk/nashorn/internal/runtime/linker/JSObjectLinker.java	Thu Oct 17 16:19:45 2013 -0700
@@ -140,7 +140,7 @@
     @SuppressWarnings("unused")
     private static Object get(final Object jsobj, final Object key) {
         if (key instanceof Integer) {
-            return ((JSObject)jsobj).getSlot((int)(Integer)key);
+            return ((JSObject)jsobj).getSlot((Integer)key);
         } else if (key instanceof Number) {
             final int index = getIndex((Number)key);
             if (index > -1) {
@@ -155,7 +155,7 @@
     @SuppressWarnings("unused")
     private static void put(final Object jsobj, final Object key, final Object value) {
         if (key instanceof Integer) {
-            ((JSObject)jsobj).setSlot((int)(Integer)key, value);
+            ((JSObject)jsobj).setSlot((Integer)key, value);
         } else if (key instanceof Number) {
             ((JSObject)jsobj).setSlot(getIndex((Number)key), value);
         } else if (key instanceof String) {
--- a/src/jdk/nashorn/internal/runtime/linker/JavaAdapterBytecodeGenerator.java	Thu Oct 17 09:41:14 2013 -0700
+++ b/src/jdk/nashorn/internal/runtime/linker/JavaAdapterBytecodeGenerator.java	Thu Oct 17 16:19:45 2013 -0700
@@ -93,7 +93,7 @@
  * its last argument preceded by original constructor arguments. This constructor will use the passed function as the
  * implementation for all abstract methods. For consistency, any concrete methods sharing the single abstract method
  * name will also be overridden by the function. When methods on the adapter instance are invoked, the ScriptFunction is
- * invoked with {@code null} as its "this".
+ * invoked with global or UNDEFINED as its "this" depending whether the function is non-strict or not.
  * </li>
  * <li>
  * If the adapter being generated can have class-level overrides, constructors taking same arguments as the superclass
--- a/src/jdk/nashorn/internal/runtime/linker/JavaAdapterServices.java	Thu Oct 17 09:41:14 2013 -0700
+++ b/src/jdk/nashorn/internal/runtime/linker/JavaAdapterServices.java	Thu Oct 17 16:19:45 2013 -0700
@@ -29,6 +29,7 @@
 
 import java.lang.invoke.MethodHandle;
 import java.lang.invoke.MethodType;
+import jdk.nashorn.internal.runtime.Context;
 import jdk.nashorn.internal.runtime.ScriptFunction;
 import jdk.nashorn.internal.runtime.ScriptObject;
 import jdk.nashorn.internal.runtime.ScriptRuntime;
@@ -53,8 +54,8 @@
      * @return the appropriately adapted method handle for invoking the script function.
      */
     public static MethodHandle getHandle(final ScriptFunction fn, final MethodType type) {
-        // JS "this" will be null for SAMs
-        return adaptHandle(fn.getBoundInvokeHandle(null), type);
+        // JS "this" will be global object or undefined depending on if 'fn' is strict or not
+        return adaptHandle(fn.getBoundInvokeHandle(fn.isStrict()? ScriptRuntime.UNDEFINED : Context.getGlobal()), type);
     }
 
     /**
--- a/src/jdk/nashorn/internal/runtime/linker/JavaArgumentConverters.java	Thu Oct 17 09:41:14 2013 -0700
+++ b/src/jdk/nashorn/internal/runtime/linker/JavaArgumentConverters.java	Thu Oct 17 16:19:45 2013 -0700
@@ -25,9 +25,9 @@
 
 package jdk.nashorn.internal.runtime.linker;
 
+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 static jdk.nashorn.internal.lookup.Lookup.MH;
 
 import java.lang.invoke.MethodHandle;
 import java.lang.invoke.MethodHandles;
@@ -211,6 +211,20 @@
                 return null;
             } else if (obj instanceof Long) {
                 return (Long) obj;
+            } else if (obj instanceof Integer) {
+                return ((Integer)obj).longValue();
+            } else if (obj instanceof Double) {
+                final Double d = (Double)obj;
+                if(Double.isInfinite(d.doubleValue())) {
+                    return 0L;
+                }
+                return d.longValue();
+            } else if (obj instanceof Float) {
+                final Float f = (Float)obj;
+                if(Float.isInfinite(f.floatValue())) {
+                    return 0L;
+                }
+                return f.longValue();
             } else if (obj instanceof Number) {
                 return ((Number)obj).longValue();
             } else if (obj instanceof String || obj instanceof ConsString) {
--- a/src/jdk/nashorn/internal/runtime/linker/NashornLinker.java	Thu Oct 17 09:41:14 2013 -0700
+++ b/src/jdk/nashorn/internal/runtime/linker/NashornLinker.java	Thu Oct 17 16:19:45 2013 -0700
@@ -30,6 +30,8 @@
 import java.lang.invoke.MethodHandle;
 import java.lang.invoke.MethodHandles;
 import java.lang.reflect.Modifier;
+import java.util.Deque;
+import java.util.List;
 import jdk.internal.dynalink.CallSiteDescriptor;
 import jdk.internal.dynalink.linker.ConversionComparator;
 import jdk.internal.dynalink.linker.GuardedInvocation;
@@ -38,6 +40,8 @@
 import jdk.internal.dynalink.linker.LinkerServices;
 import jdk.internal.dynalink.linker.TypeBasedGuardingDynamicLinker;
 import jdk.internal.dynalink.support.Guards;
+import jdk.nashorn.internal.objects.NativeArray;
+import jdk.nashorn.internal.runtime.JSType;
 import jdk.nashorn.internal.runtime.ScriptFunction;
 import jdk.nashorn.internal.runtime.ScriptObject;
 import jdk.nashorn.internal.runtime.Undefined;
@@ -47,6 +51,13 @@
  * includes {@link ScriptFunction} and its subclasses) as well as {@link Undefined}.
  */
 final class NashornLinker implements TypeBasedGuardingDynamicLinker, GuardingTypeConverterFactory, ConversionComparator {
+    private static final ClassValue<MethodHandle> ARRAY_CONVERTERS = new ClassValue<MethodHandle>() {
+        @Override
+        protected MethodHandle computeValue(Class<?> type) {
+            return createArrayConverter(type);
+        }
+    };
+
     /**
      * Returns true if {@code ScriptObject} is assignable from {@code type}, or it is {@code Undefined}.
      */
@@ -103,6 +114,12 @@
         if (mh != null) {
             return new GuardedInvocation(mh, canLinkTypeStatic(sourceType) ? null : IS_NASHORN_OR_UNDEFINED_TYPE);
         }
+
+        GuardedInvocation inv = getArrayConverter(sourceType, targetType);
+        if(inv != null) {
+            return inv;
+        }
+
         return getSamTypeConverter(sourceType, targetType);
     }
 
@@ -129,6 +146,41 @@
         return null;
     }
 
+    /**
+     * Returns a guarded invocation that converts from a source type that is NativeArray to a Java array or List or
+     * Deque type.
+     * @param sourceType the source type (presumably NativeArray a superclass of it)
+     * @param targetType the target type (presumably an array type, or List or Deque)
+     * @return a guarded invocation that converts from the source type to the target type. null is returned if
+     * either the source type is neither NativeArray, nor a superclass of it, or if the target type is not an array
+     * type, List, or Deque.
+     */
+    private static GuardedInvocation getArrayConverter(final Class<?> sourceType, final Class<?> targetType) {
+        final boolean isSourceTypeNativeArray = sourceType == NativeArray.class;
+        // If source type is more generic than ScriptFunction class, we'll need to use a guard
+        final boolean isSourceTypeGeneric = !isSourceTypeNativeArray && sourceType.isAssignableFrom(NativeArray.class);
+
+        if (isSourceTypeNativeArray || isSourceTypeGeneric) {
+            final MethodHandle guard = isSourceTypeGeneric ? IS_NATIVE_ARRAY : null;
+            if(targetType.isArray()) {
+                return new GuardedInvocation(ARRAY_CONVERTERS.get(targetType), guard);
+            }
+            if(targetType == List.class) {
+                return new GuardedInvocation(JSType.TO_JAVA_LIST.methodHandle(), guard);
+            }
+            if(targetType == Deque.class) {
+                return new GuardedInvocation(JSType.TO_JAVA_DEQUE.methodHandle(), guard);
+            }
+        }
+        return null;
+    }
+
+    private static MethodHandle createArrayConverter(final Class<?> type) {
+        assert type.isArray();
+        final MethodHandle converter = MH.insertArguments(JSType.TO_JAVA_ARRAY.methodHandle(), 1, type.getComponentType());
+        return MH.asType(converter, converter.type().changeReturnType(type));
+    }
+
     private static boolean isAutoConvertibleFromFunction(final Class<?> clazz) {
         return isAbstractClass(clazz) && !ScriptObject.class.isAssignableFrom(clazz) &&
                 JavaAdapterFactory.isAutoConvertibleFromFunction(clazz);
@@ -148,7 +200,26 @@
 
     @Override
     public Comparison compareConversion(final Class<?> sourceType, final Class<?> targetType1, final Class<?> targetType2) {
+        if(sourceType == NativeArray.class) {
+            // Prefer lists, as they're less costly to create than arrays.
+            if(isList(targetType1)) {
+                if(!isList(targetType2)) {
+                    return Comparison.TYPE_1_BETTER;
+                }
+            } else if(isList(targetType2)) {
+                return Comparison.TYPE_2_BETTER;
+            }
+            // Then prefer arrays
+            if(targetType1.isArray()) {
+                if(!targetType2.isArray()) {
+                    return Comparison.TYPE_1_BETTER;
+                }
+            } else if(targetType2.isArray()) {
+                return Comparison.TYPE_2_BETTER;
+            }
+        }
         if(ScriptObject.class.isAssignableFrom(sourceType)) {
+            // Prefer interfaces
             if(targetType1.isInterface()) {
                 if(!targetType2.isInterface()) {
                     return Comparison.TYPE_1_BETTER;
@@ -160,7 +231,12 @@
         return Comparison.INDETERMINATE;
     }
 
+    private static boolean isList(Class<?> clazz) {
+        return clazz == List.class || clazz == Deque.class;
+    }
+
     private static final MethodHandle IS_SCRIPT_FUNCTION = Guards.isInstance(ScriptFunction.class, MH.type(Boolean.TYPE, Object.class));
+    private static final MethodHandle IS_NATIVE_ARRAY = Guards.isOfClass(NativeArray.class, MH.type(Boolean.TYPE, Object.class));
 
     private static final MethodHandle IS_NASHORN_OR_UNDEFINED_TYPE = findOwnMH("isNashornTypeOrUndefined",
             Boolean.TYPE, Object.class);
--- a/src/jdk/nashorn/internal/runtime/resources/mozilla_compat.js	Thu Oct 17 09:41:14 2013 -0700
+++ b/src/jdk/nashorn/internal/runtime/resources/mozilla_compat.js	Thu Oct 17 16:19:45 2013 -0700
@@ -41,7 +41,12 @@
     }
 });
 
+
 // importPackage
+// avoid unnecessary chaining of __noSuchProperty__ again
+// in case user loads this script more than once.
+if (typeof importPackage == 'undefined') {
+
 Object.defineProperty(this, "importPackage", {
     configurable: true, enumerable: false, writable: true,
     value: (function() {
@@ -91,6 +96,19 @@
     })()
 });
 
+}
+
+// sync
+Object.defineProperty(this, "sync", {
+    configurable: true, enumerable: false, writable: true,
+    value: function(func, syncobj) {
+        if (arguments.length < 1 || arguments.length > 2 ) {
+            throw "sync(function [,object]) parameter count mismatch";
+        }
+        return Packages.jdk.nashorn.api.scripting.ScriptUtils.makeSynchronizedFunction(func, syncobj);
+    }
+});
+
 // Object.prototype.__defineGetter__
 Object.defineProperty(Object.prototype, "__defineGetter__", {
     configurable: true, enumerable: false, writable: true,
@@ -344,13 +362,16 @@
 // Rhino: global.importClass
 Object.defineProperty(this, "importClass", {
     configurable: true, enumerable: false, writable: true,
-    value: function(clazz) {
-        if (Java.isType(clazz)) {
-            var className = Java.typeName(clazz);
-            var simpleName = className.substring(className.lastIndexOf('.') + 1);
-            this[simpleName] = clazz;
-        } else {
-            throw new TypeError(clazz + " is not a Java class");
+    value: function() {
+        for (var arg in arguments) {
+            var clazz = arguments[arg];
+            if (Java.isType(clazz)) {
+                var className = Java.typeName(clazz);
+                var simpleName = className.substring(className.lastIndexOf('.') + 1);
+                this[simpleName] = clazz;
+            } else {
+                throw new TypeError(clazz + " is not a Java class");
+            }
         }
     }
 });
--- a/test/script/assert.js	Thu Oct 17 09:41:14 2013 -0700
+++ b/test/script/assert.js	Thu Oct 17 16:19:45 2013 -0700
@@ -61,3 +61,22 @@
         }
     }
 });
+
+Object.defineProperty(this, "printError", {
+    configuable: true,
+    enumerable: false,
+    writable: true,
+    value: function (e) {
+        var msg = e.message;
+        var str = e.name + ':';
+        if (e.lineNumber > 0) {
+            str += e.lineNumber + ':';
+        }
+        if (e.columnNumber > 0) {
+            str += e.columnNumber + ':';
+        }
+        str += msg.substring(msg.indexOf(' ') + 1);
+        print(str);
+    }
+});
+
--- a/test/script/basic/JDK-8019508.js	Thu Oct 17 09:41:14 2013 -0700
+++ b/test/script/basic/JDK-8019508.js	Thu Oct 17 16:19:45 2013 -0700
@@ -36,7 +36,7 @@
         if (! (e instanceof SyntaxError)) {
             fail("expected SyntaxError, got " + e);
         }
-        print(e.message.replace(/\\/g, '/'));
+        printError(e);
     }
 }
 
--- a/test/script/basic/JDK-8019508.js.EXPECTED	Thu Oct 17 09:41:14 2013 -0700
+++ b/test/script/basic/JDK-8019508.js.EXPECTED	Thu Oct 17 16:19:45 2013 -0700
@@ -1,12 +1,12 @@
-test/script/basic/JDK-8019508.js#33<eval>:1:2 Expected property id but found ,
+SyntaxError:33:Expected property id but found ,
 ({,})
   ^
-test/script/basic/JDK-8019508.js#33<eval>:1:2 Expected property id but found ,
+SyntaxError:33:Expected property id but found ,
 ({, a:2 })
   ^
-test/script/basic/JDK-8019508.js#33<eval>:1:6 Expected property id but found ,
+SyntaxError:33:Expected property id but found ,
 ({a:3,,})
       ^
-test/script/basic/JDK-8019508.js#33<eval>:1:6 Expected comma but found ident
+SyntaxError:33:Expected comma but found ident
 ({a:3 b:2}
       ^
--- a/test/script/basic/JDK-8019553.js	Thu Oct 17 09:41:14 2013 -0700
+++ b/test/script/basic/JDK-8019553.js	Thu Oct 17 16:19:45 2013 -0700
@@ -33,7 +33,7 @@
         eval(str);
         fail("SyntaxError expected for: " + str);
     } catch (e) {
-        print(e.toString().replace(/\\/g, '/'));
+        printError(e);
     }
 }
 
--- a/test/script/basic/JDK-8019553.js.EXPECTED	Thu Oct 17 09:41:14 2013 -0700
+++ b/test/script/basic/JDK-8019553.js.EXPECTED	Thu Oct 17 16:19:45 2013 -0700
@@ -1,12 +1,12 @@
-SyntaxError: test/script/basic/JDK-8019553.js#33<eval>:1:3 Expected l-value but found +
+SyntaxError:33:Expected l-value but found +
 ++ +3
    ^
-SyntaxError: test/script/basic/JDK-8019553.js#33<eval>:1:3 Expected l-value but found -
+SyntaxError:33:Expected l-value but found -
 ++ -7
    ^
-SyntaxError: test/script/basic/JDK-8019553.js#33<eval>:1:3 Expected l-value but found +
+SyntaxError:33:Expected l-value but found +
 -- +2
    ^
-SyntaxError: test/script/basic/JDK-8019553.js#33<eval>:1:3 Expected l-value but found -
+SyntaxError:33:Expected l-value but found -
 -- -8
    ^
--- a/test/script/basic/JDK-8019791.js	Thu Oct 17 09:41:14 2013 -0700
+++ b/test/script/basic/JDK-8019791.js	Thu Oct 17 16:19:45 2013 -0700
@@ -33,7 +33,7 @@
     eval('"" ~ ""');
     print("FAILED: SyntaxError expected for: \"\" ~ \"\"");
 } catch (e) {
-    print(e.toString().replace(/\\/g, '/'));
+    printError(e);
 }
 
 // Used to crash instead of SyntaxError
@@ -41,7 +41,7 @@
     eval("function() { if (1~0) return 0; return 1 }");
     print("FAILED: SyntaxError expected for: if (1~0) ");
 } catch (e) {
-    print(e.toString().replace(/\\/g, '/'));
+    printError(e);
 }
 
 // The following are valid, but used to crash
--- a/test/script/basic/JDK-8019791.js.EXPECTED	Thu Oct 17 09:41:14 2013 -0700
+++ b/test/script/basic/JDK-8019791.js.EXPECTED	Thu Oct 17 16:19:45 2013 -0700
@@ -1,6 +1,6 @@
-SyntaxError: test/script/basic/JDK-8019791.js#33<eval>:1:3 Expected ; but found ~
+SyntaxError:33:Expected ; but found ~
 "" ~ ""
    ^
-SyntaxError: test/script/basic/JDK-8019791.js#41<eval>:1:18 Expected ) but found ~
+SyntaxError:41:Expected ) but found ~
 function() { if (1~0) return 0; return 1 }
                   ^
--- a/test/script/basic/JDK-8019805.js	Thu Oct 17 09:41:14 2013 -0700
+++ b/test/script/basic/JDK-8019805.js	Thu Oct 17 16:19:45 2013 -0700
@@ -32,5 +32,5 @@
     eval("for each(var v=0;false;);");
     print("FAILED: for each(var v=0; false;); should have thrown error");
 } catch (e) {
-    print(e.toString().replace(/\\/g, '/'));
+    printError(e);
 }
--- a/test/script/basic/JDK-8019805.js.EXPECTED	Thu Oct 17 09:41:14 2013 -0700
+++ b/test/script/basic/JDK-8019805.js.EXPECTED	Thu Oct 17 16:19:45 2013 -0700
@@ -1,3 +1,3 @@
-SyntaxError: test/script/basic/JDK-8019805.js#32<eval>:1:16 for each can only be used with for..in
+SyntaxError:32:for each can only be used with for..in
 for each(var v=0;false;);
                 ^
--- a/test/script/basic/JDK-8025488.js	Thu Oct 17 09:41:14 2013 -0700
+++ b/test/script/basic/JDK-8025488.js	Thu Oct 17 16:19:45 2013 -0700
@@ -40,4 +40,4 @@
 }
 
 var e = new MyError(); 
-print(e.stack);
+print(e.stack.replace(/\\/g, '/'));
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/script/basic/JDK-8026008.js	Thu Oct 17 16:19:45 2013 -0700
@@ -0,0 +1,55 @@
+/*
+ * 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.
+ * 
+ * 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-8026008: Constant folding removes var statement
+ *
+ * @test
+ * @run
+ */
+
+if (false) {
+    var x1 = 10;
+    if (false) {
+        var x2;
+    }
+} else {
+   print(x1, x2);
+}
+
+if (undefined) {
+    var z1;
+    if (null) {
+        var z2;
+    }
+}
+
+print(z1, z2);
+
+if (1) {
+    print(y1, y2);
+} else if (0) {
+    var y1 = 1;
+} else {
+    var y2 = 2
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/script/basic/JDK-8026008.js.EXPECTED	Thu Oct 17 16:19:45 2013 -0700
@@ -0,0 +1,3 @@
+undefined undefined
+undefined undefined
+undefined undefined
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/script/basic/JDK-8026016.js	Thu Oct 17 16:19:45 2013 -0700
@@ -0,0 +1,68 @@
+/*
+ * 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.
+ * 
+ * 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-8026016: too many relinks dominate avatar.js http benchmark
+ *
+ * @test
+ * @run
+ */
+
+function accessMegamorphic() {
+    for (var i = 0; i < 26; i++) {
+        var o = {};
+        o[String.fromCharCode(i + 97)] = 1;
+        o._;
+    }
+}
+
+function invokeMegamorphic() {
+    for (var i = 0; i < 26; i++) {
+        var o = {};
+        o[String.fromCharCode(i + 97)] = 1;
+        try {
+            o._(i);
+        } catch (e) {
+            print(e);
+        }
+    }
+}
+
+Object.prototype.__noSuchProperty__ = function() {
+    print("no such property", Array.prototype.slice.call(arguments));
+};
+
+invokeMegamorphic();
+accessMegamorphic();
+
+Object.prototype.__noSuchMethod__ = function() {
+    print("no such method", Array.prototype.slice.call(arguments));
+};
+
+invokeMegamorphic();
+accessMegamorphic();
+
+Object.prototype.__noSuchMethod__ = "nofunction";
+
+invokeMegamorphic();
+accessMegamorphic();
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/script/basic/JDK-8026016.js.EXPECTED	Thu Oct 17 16:19:45 2013 -0700
@@ -0,0 +1,182 @@
+no such property _
+TypeError: Cannot call undefined
+no such property _
+TypeError: Cannot call undefined
+no such property _
+TypeError: Cannot call undefined
+no such property _
+TypeError: Cannot call undefined
+no such property _
+TypeError: Cannot call undefined
+no such property _
+TypeError: Cannot call undefined
+no such property _
+TypeError: Cannot call undefined
+no such property _
+TypeError: Cannot call undefined
+no such property _
+TypeError: Cannot call undefined
+no such property _
+TypeError: Cannot call undefined
+no such property _
+TypeError: Cannot call undefined
+no such property _
+TypeError: Cannot call undefined
+no such property _
+TypeError: Cannot call undefined
+no such property _
+TypeError: Cannot call undefined
+no such property _
+TypeError: Cannot call undefined
+no such property _
+TypeError: Cannot call undefined
+no such property _
+TypeError: Cannot call undefined
+no such property _
+TypeError: Cannot call undefined
+no such property _
+TypeError: Cannot call undefined
+no such property _
+TypeError: Cannot call undefined
+no such property _
+TypeError: Cannot call undefined
+no such property _
+TypeError: Cannot call undefined
+no such property _
+TypeError: Cannot call undefined
+no such property _
+TypeError: Cannot call undefined
+no such property _
+TypeError: Cannot call undefined
+no such property _
+TypeError: Cannot call undefined
+no such property _
+no such property _
+no such property _
+no such property _
+no such property _
+no such property _
+no such property _
+no such property _
+no such property _
+no such property _
+no such property _
+no such property _
+no such property _
+no such property _
+no such property _
+no such property _
+no such property _
+no such property _
+no such property _
+no such property _
+no such property _
+no such property _
+no such property _
+no such property _
+no such property _
+no such property _
+no such method _,0
+no such method _,1
+no such method _,2
+no such method _,3
+no such method _,4
+no such method _,5
+no such method _,6
+no such method _,7
+no such method _,8
+no such method _,9
+no such method _,10
+no such method _,11
+no such method _,12
+no such method _,13
+no such method _,14
+no such method _,15
+no such method _,16
+no such method _,17
+no such method _,18
+no such method _,19
+no such method _,20
+no such method _,21
+no such method _,22
+no such method _,23
+no such method _,24
+no such method _,25
+no such property _
+no such property _
+no such property _
+no such property _
+no such property _
+no such property _
+no such property _
+no such property _
+no such property _
+no such property _
+no such property _
+no such property _
+no such property _
+no such property _
+no such property _
+no such property _
+no such property _
+no such property _
+no such property _
+no such property _
+no such property _
+no such property _
+no such property _
+no such property _
+no such property _
+no such property _
+TypeError: Cannot call undefined
+TypeError: Cannot call undefined
+TypeError: Cannot call undefined
+TypeError: Cannot call undefined
+TypeError: Cannot call undefined
+TypeError: Cannot call undefined
+TypeError: Cannot call undefined
+TypeError: Cannot call undefined
+TypeError: Cannot call undefined
+TypeError: Cannot call undefined
+TypeError: Cannot call undefined
+TypeError: Cannot call undefined
+TypeError: Cannot call undefined
+TypeError: Cannot call undefined
+TypeError: Cannot call undefined
+TypeError: Cannot call undefined
+TypeError: Cannot call undefined
+TypeError: Cannot call undefined
+TypeError: Cannot call undefined
+TypeError: Cannot call undefined
+TypeError: Cannot call undefined
+TypeError: Cannot call undefined
+TypeError: Cannot call undefined
+TypeError: Cannot call undefined
+TypeError: Cannot call undefined
+TypeError: Cannot call undefined
+no such property _
+no such property _
+no such property _
+no such property _
+no such property _
+no such property _
+no such property _
+no such property _
+no such property _
+no such property _
+no such property _
+no such property _
+no such property _
+no such property _
+no such property _
+no such property _
+no such property _
+no such property _
+no such property _
+no such property _
+no such property _
+no such property _
+no such property _
+no such property _
+no such property _
+no such property _
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/script/basic/JDK-8026112.js	Thu Oct 17 16:19:45 2013 -0700
@@ -0,0 +1,31 @@
+/*
+ * 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.
+ * 
+ * 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-8026112: Function("with(x ? 1e81 : (x2.constructor = 0.1)){}") throws AssertionError: double is not compatible with object
+ *
+ * @test
+ * @run
+ */
+
+Function("with(x ? 1e81 : (x2.constructor = 0.1)){}")
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/script/basic/JDK-8026125.js	Thu Oct 17 16:19:45 2013 -0700
@@ -0,0 +1,32 @@
+/*
+ * 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.
+ * 
+ * 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-8026125: Array.prototype.slice.call(Java.type("java.util.HashMap")) throws ClassCastException: jdk.internal.dynalink.beans.StaticClass cannot be cast to jdk.nashorn.internal.runtime.ScriptObject
+ *
+ * @test
+ * @run
+ */
+
+Array.prototype.splice.call(Java.type("java.util.HashMap"))
+Array.prototype.slice.call(Java.type("java.util.HashMap"))
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/script/basic/JDK-8026137.js	Thu Oct 17 16:19:45 2013 -0700
@@ -0,0 +1,44 @@
+/*
+ * 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.
+ * 
+ * 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-8026137: Binary evaluation order in JavaScript is load load 
+ * convert convert, not load convert load convert.
+ *
+ * @test
+ * @run
+ */
+
+try {
+    (function f() { Object.defineProperty({},"x",{get: function(){return {valueOf:function(){throw 0}}}}).x - Object.defineProperty({},"x",{get: function(){throw 1}}).x })()
+} 
+catch (e) {
+    print(e);
+}
+
+try {
+    ({valueOf: function(){throw 0}}) - ({valueOf: function(){throw 1}} - 1) 
+} catch (e) {
+    print(e);
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/script/basic/JDK-8026137.js.EXPECTED	Thu Oct 17 16:19:45 2013 -0700
@@ -0,0 +1,2 @@
+1
+1
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/script/basic/JDK-8026162.js	Thu Oct 17 16:19:45 2013 -0700
@@ -0,0 +1,48 @@
+/*
+ * 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.
+ * 
+ * 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-8026162: "this" in SAM adapter functions is wrong
+ *
+ * @test
+ * @run
+ */
+
+var global = this;
+
+new java.lang.Runnable(
+  function func() {
+      if (this !== global) {
+          fail("Expected 'this' to be global instance");
+      }
+  }
+).run();
+
+new java.lang.Runnable(
+  function func() {
+      'use strict';
+      if (typeof this != 'undefined') {
+          fail("Expected 'undefined' to be global instance");
+      }
+  }
+).run();
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/script/basic/JDK-8026167.js	Thu Oct 17 16:19:45 2013 -0700
@@ -0,0 +1,50 @@
+/*
+ * 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.
+ * 
+ * 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-8026167: Class cache/reuse of 'eval' scripts results in ClassCastException in some cases.
+ *
+ * @test
+ * @run
+ */
+
+var m = new javax.script.ScriptEngineManager();
+var e = m.getEngineByName('js');
+
+// leave the whitespace - need both eval("e") at same column for this test!
+
+e.eval('function f(e) {            eval("e") } f()');
+e.eval('function f() { var e = 33; eval("e") } f()');
+
+function f() {
+    Function.call.call(function x() { eval("x") }); eval("x") 
+}
+
+try {
+    f();
+    fail("Should have thrown ReferenceError");
+} catch (e) {
+    if (! (e instanceof ReferenceError)) {
+        fail("ReferenceError expected but got " + e);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/script/basic/JDK-8026248.js	Thu Oct 17 16:19:45 2013 -0700
@@ -0,0 +1,51 @@
+/*
+ * 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.
+ * 
+ * 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-8026248: importClass has to be a varargs function
+ *
+ * @test
+ * @run
+ */
+
+load('nashorn:mozilla_compat.js')
+
+importClass(java.io.File, java.io.InputStream) 
+
+print(File)
+print(InputStream)
+
+importClass(java.util.Map, java.util.HashMap, java.io.PrintStream)
+
+print(HashMap)
+print(Map)
+print(PrintStream)
+
+importClass.call(this, java.util.Collections, java.util.List);
+print(Collections)
+print(List)
+
+importClass.apply(this, [ java.util.Queue, java.math.BigInteger, java.math.BigDecimal ]);
+print(Queue)
+print(BigInteger)
+print(BigDecimal)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/script/basic/JDK-8026248.js.EXPECTED	Thu Oct 17 16:19:45 2013 -0700
@@ -0,0 +1,10 @@
+[JavaClass java.io.File]
+[JavaClass java.io.InputStream]
+[JavaClass java.util.HashMap]
+[JavaClass java.util.Map]
+[JavaClass java.io.PrintStream]
+[JavaClass java.util.Collections]
+[JavaClass java.util.List]
+[JavaClass java.util.Queue]
+[JavaClass java.math.BigInteger]
+[JavaClass java.math.BigDecimal]
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/script/basic/JDK-8026264.js	Thu Oct 17 16:19:45 2013 -0700
@@ -0,0 +1,54 @@
+/*
+ * 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.
+ * 
+ * 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-8026264: Getter, setter function name mangling issues
+ *
+ * @test
+ * @run
+ */
+
+var obj = {
+   get ":"(){},
+   set ":"(x){},
+   get ""(){},
+   set ""(x){}
+};
+
+var desc = Object.getOwnPropertyDescriptor(obj, ":");
+if (desc.get.name != ':') {
+    fail("getter name is expected to be ':' got " + desc.get.name);
+}
+
+if (desc.set.name != ':') {
+    fail("setter name is expected to be ':' got " + desc.set.name);
+}
+
+desc = Object.getOwnPropertyDescriptor(obj, "");
+if (desc.get.name != '') {
+    fail("getter name is expected to be '' got " + desc.get.name);
+}
+
+if (desc.set.name != '') {
+    fail("setter name is expected to be '' got " + desc.set.name);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/script/basic/JDK-8026292.js	Thu Oct 17 16:19:45 2013 -0700
@@ -0,0 +1,65 @@
+/*
+ * 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.
+ * 
+ * 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-8026292: Megamorphic setter fails with boolean value
+ *
+ * @test
+ * @run
+ */
+
+function megamorphic(o) {
+    o.w = true;
+    if (!o.w)
+        throw new Error();
+}
+
+// Calls below must exceed megamorphic callsite threshhold
+for (var i = 0; i < 10; i++) {
+    megamorphic({a: 1});
+    megamorphic({b: 1});
+    megamorphic({c: 1});
+    megamorphic({d: 1});
+    megamorphic({e: 1});
+    megamorphic({f: 1});
+    megamorphic({g: 1});
+    megamorphic({h: 1});
+    megamorphic({i: 1});
+    megamorphic({j: 1});
+    megamorphic({k: 1});
+    megamorphic({l: 1});
+    megamorphic({m: 1});
+    megamorphic({n: 1});
+    megamorphic({o: 1});
+    megamorphic({p: 1});
+    megamorphic({q: 1});
+    megamorphic({r: 1});
+    megamorphic({s: 1});
+    megamorphic({t: 1});
+    megamorphic({u: 1});
+    megamorphic({v: 1});
+    megamorphic({w: 1});
+    megamorphic({x: 1});
+    megamorphic({y: 1});
+    megamorphic({z: 1});
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/script/basic/JDK-8026302.js	Thu Oct 17 16:19:45 2013 -0700
@@ -0,0 +1,48 @@
+/*
+ * 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.
+ * 
+ * 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-8026302: source representation of getter and setter methods is wrong
+ *
+ * @test
+ * @run
+ */
+
+var obj = {
+    get "foo"() {},
+    set "foo"(x) {},
+    get bar() {},
+    set bar(x) {},
+    get ":"() {},
+    set ":"(x) {},
+    get 12() {},
+    set 12(x) {},
+    get 1.8e-8() {},
+    set 1.8e-8(x) {}
+}
+
+for (var prop in obj) {
+    var desc = Object.getOwnPropertyDescriptor(obj, prop);
+    print(desc.get);
+    print(desc.set);
+} 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/script/basic/JDK-8026302.js.EXPECTED	Thu Oct 17 16:19:45 2013 -0700
@@ -0,0 +1,10 @@
+get "foo"() {}
+set "foo"(x) {}
+get bar() {}
+set bar(x) {}
+get ":"() {}
+set ":"(x) {}
+get 12() {}
+set 12(x) {}
+get 1.8e-8() {}
+set 1.8e-8(x) {}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/script/basic/JDK-8026317.js	Thu Oct 17 16:19:45 2013 -0700
@@ -0,0 +1,63 @@
+/*
+ * 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.
+ * 
+ * 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-8026317: $ in the function name results in wrong function being invoked
+ *
+ * @test
+ * @run
+ */
+
+function case1() {
+    function g() {
+        return 0
+    }
+    function g() {
+        return 1
+    }
+    function g$1() {
+        return 2
+    }
+
+    return g$1()
+}
+
+print(case1());
+
+function case2() {
+    function g() {
+        return 0
+    }
+
+    var h = function g() {
+        return 1
+    }
+
+    function g$1() {
+        return 2
+    }
+
+    return h()
+}
+
+print(case2());
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/script/basic/JDK-8026317.js.EXPECTED	Thu Oct 17 16:19:45 2013 -0700
@@ -0,0 +1,2 @@
+2
+1
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/script/basic/JDK-8026367.js	Thu Oct 17 16:19:45 2013 -0700
@@ -0,0 +1,61 @@
+/*
+ * 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.
+ * 
+ * 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-8026367: Add a sync keyword to mozilla_compat
+ *
+ * @test
+ * @run
+ */
+
+if (typeof sync === "undefined") {
+    load("nashorn:mozilla_compat.js");
+}
+
+var obj = {
+    count: 0,
+    // Sync called with one argument will synchronize on this-object of invocation
+    inc: sync(function(d) {
+        this.count += d;
+    }),
+    // Pass explicit object to synchronize on as second argument
+    dec: sync(function(d) {
+        this.count -= d;
+    }, obj)
+};
+
+var t1 = new java.lang.Thread(function() {
+    for (var i = 0; i < 100000; i++) obj.inc(1);
+});
+var t2 = new java.lang.Thread(function() {
+    for (var i = 0; i < 100000; i++) obj.dec(1);
+});
+
+t1.start();
+t2.start();
+t1.join();
+t2.join();
+
+if (obj.count !== 0) {
+    throw new Error("Expected count == 0, got " + obj.count);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/script/basic/JDK-8026692.js	Thu Oct 17 16:19:45 2013 -0700
@@ -0,0 +1,32 @@
+/*
+ * 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.
+ * 
+ * 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-8026692: eval() throws NullPointerException with --compile-only
+ *
+ * @test
+ * @option --compile-only
+ * @run
+ */
+
+eval("");
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/script/basic/JDK-8026693.js	Thu Oct 17 16:19:45 2013 -0700
@@ -0,0 +1,33 @@
+/*
+ * 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.
+ * 
+ * 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-8026693: getType() called on DISCARD node
+ *
+ * @test
+ * @run
+ */
+
+function f() {
+    if(x, y) z;
+}
--- a/test/script/basic/NASHORN-100.js	Thu Oct 17 09:41:14 2013 -0700
+++ b/test/script/basic/NASHORN-100.js	Thu Oct 17 16:19:45 2013 -0700
@@ -35,5 +35,5 @@
     if (! (e instanceof SyntaxError)) {
         fail("#2 expected SyntaxError got " + e);
     }
-    print(e.toString().replace(/\\/g, '/'));
+    printError(e);
 }
--- a/test/script/basic/NASHORN-100.js.EXPECTED	Thu Oct 17 09:41:14 2013 -0700
+++ b/test/script/basic/NASHORN-100.js.EXPECTED	Thu Oct 17 16:19:45 2013 -0700
@@ -1,3 +1,3 @@
-SyntaxError: test/script/basic/NASHORN-100.js#32<eval>:1:0 Invalid return statement
+SyntaxError:32:Invalid return statement
 return;
 ^
--- a/test/script/basic/NASHORN-293.js	Thu Oct 17 09:41:14 2013 -0700
+++ b/test/script/basic/NASHORN-293.js	Thu Oct 17 16:19:45 2013 -0700
@@ -40,15 +40,13 @@
     try {
         eval(src);
     } catch (e) {
-        var location =  e.fileName ? e.fileName.slice(-9) : "unknown source";
-        print(e.name, "@", location);
+        printError(e);
     }
 }
 for (var i = 0; i < 3; i++) {
     try {
         eval(src);
     } catch (e) {
-        var location =  e.fileName ? e.fileName.slice(-9) : "unknown source";
-        print(e.name, "@", location);
+        printError(e);
     }
 }
--- a/test/script/basic/NASHORN-293.js.EXPECTED	Thu Oct 17 09:41:14 2013 -0700
+++ b/test/script/basic/NASHORN-293.js.EXPECTED	Thu Oct 17 16:19:45 2013 -0700
@@ -1,9 +1,9 @@
 hello
 hello
 hello
-TypeError @ #41<eval>
-TypeError @ #41<eval>
-TypeError @ #41<eval>
-TypeError @ #49<eval>
-TypeError @ #49<eval>
-TypeError @ #49<eval>
+TypeError:1:read property "foo" from undefined
+TypeError:1:read property "foo" from undefined
+TypeError:1:read property "foo" from undefined
+TypeError:1:read property "foo" from undefined
+TypeError:1:read property "foo" from undefined
+TypeError:1:read property "foo" from undefined
--- a/test/script/basic/NASHORN-40.js	Thu Oct 17 09:41:14 2013 -0700
+++ b/test/script/basic/NASHORN-40.js	Thu Oct 17 16:19:45 2013 -0700
@@ -31,11 +31,11 @@
 try {
     eval("print(.foo)");
 } catch (e) {
-    print(e.toString().replace(/\\/g, '/'));
+    printError(e);
 }
 
 try {
     eval(".bar = 3423;");
 } catch (e) {
-    print(e.toString().replace(/\\/g, '/'));
+    printError(e);
 }
--- a/test/script/basic/NASHORN-40.js.EXPECTED	Thu Oct 17 09:41:14 2013 -0700
+++ b/test/script/basic/NASHORN-40.js.EXPECTED	Thu Oct 17 16:19:45 2013 -0700
@@ -1,6 +1,6 @@
-SyntaxError: test/script/basic/NASHORN-40.js#32<eval>:1:6 Expected an operand but found .
+SyntaxError:32:Expected an operand but found .
 print(.foo)
       ^
-SyntaxError: test/script/basic/NASHORN-40.js#38<eval>:1:0 Expected an operand but found .
+SyntaxError:38:Expected an operand but found .
 .bar = 3423;
 ^
--- a/test/script/basic/NASHORN-51.js	Thu Oct 17 09:41:14 2013 -0700
+++ b/test/script/basic/NASHORN-51.js	Thu Oct 17 16:19:45 2013 -0700
@@ -35,28 +35,28 @@
         eval(literals[i] + "++");
         print("ERROR!! post increment : " + literals[i]);
     } catch (e) {
-        print(e.toString().replace(/\\/g, '/'));
+        printError(e);
     }
 
     try {
         eval(literals[i] + "--");
         print("ERROR!! post decrement : " + literals[i]);
     } catch (e) {
-        print(e.toString().replace(/\\/g, '/'));
+        printError(e);
     }
 
     try {
         eval("++" + literals[i]);
         print("ERROR!! pre increment : " + literals[i]);
     } catch (e) {
-        print(e.toString().replace(/\\/g, '/'));
+        printError(e);
     }
 
     try {
         eval("--" + literals[i]);
         print("ERROR!! pre decrement : " + literals[i]);
     } catch (e) {
-        print(e.toString().replace(/\\/g, '/'));
+        printError(e);
     }
 }
 
--- a/test/script/basic/NASHORN-51.js.EXPECTED	Thu Oct 17 09:41:14 2013 -0700
+++ b/test/script/basic/NASHORN-51.js.EXPECTED	Thu Oct 17 16:19:45 2013 -0700
@@ -1,72 +1,72 @@
-ReferenceError: test/script/basic/NASHORN-51.js#35<eval>:1:0 Invalid left hand side for assignment
+ReferenceError:35:Invalid left hand side for assignment
 1++
 ^
-ReferenceError: test/script/basic/NASHORN-51.js#42<eval>:1:0 Invalid left hand side for assignment
+ReferenceError:42:Invalid left hand side for assignment
 1--
 ^
-ReferenceError: test/script/basic/NASHORN-51.js#49<eval>:1:2 Invalid left hand side for assignment
+ReferenceError:49:Invalid left hand side for assignment
 ++1
   ^
-ReferenceError: test/script/basic/NASHORN-51.js#56<eval>:1:2 Invalid left hand side for assignment
+ReferenceError:56:Invalid left hand side for assignment
 --1
   ^
-ReferenceError: test/script/basic/NASHORN-51.js#35<eval>:1:0 Invalid left hand side for assignment
+ReferenceError:35:Invalid left hand side for assignment
 0++
 ^
-ReferenceError: test/script/basic/NASHORN-51.js#42<eval>:1:0 Invalid left hand side for assignment
+ReferenceError:42:Invalid left hand side for assignment
 0--
 ^
-ReferenceError: test/script/basic/NASHORN-51.js#49<eval>:1:2 Invalid left hand side for assignment
+ReferenceError:49:Invalid left hand side for assignment
 ++0
   ^
-ReferenceError: test/script/basic/NASHORN-51.js#56<eval>:1:2 Invalid left hand side for assignment
+ReferenceError:56:Invalid left hand side for assignment
 --0
   ^
-ReferenceError: test/script/basic/NASHORN-51.js#35<eval>:1:0 Invalid left hand side for assignment
+ReferenceError:35:Invalid left hand side for assignment
 3.14++
 ^
-ReferenceError: test/script/basic/NASHORN-51.js#42<eval>:1:0 Invalid left hand side for assignment
+ReferenceError:42:Invalid left hand side for assignment
 3.14--
 ^
-ReferenceError: test/script/basic/NASHORN-51.js#49<eval>:1:2 Invalid left hand side for assignment
+ReferenceError:49:Invalid left hand side for assignment
 ++3.14
   ^
-ReferenceError: test/script/basic/NASHORN-51.js#56<eval>:1:2 Invalid left hand side for assignment
+ReferenceError:56:Invalid left hand side for assignment
 --3.14
   ^
-ReferenceError: test/script/basic/NASHORN-51.js#35<eval>:1:0 Invalid left hand side for assignment
+ReferenceError:35:Invalid left hand side for assignment
 true++
 ^
-ReferenceError: test/script/basic/NASHORN-51.js#42<eval>:1:0 Invalid left hand side for assignment
+ReferenceError:42:Invalid left hand side for assignment
 true--
 ^
-ReferenceError: test/script/basic/NASHORN-51.js#49<eval>:1:2 Invalid left hand side for assignment
+ReferenceError:49:Invalid left hand side for assignment
 ++true
   ^
-ReferenceError: test/script/basic/NASHORN-51.js#56<eval>:1:2 Invalid left hand side for assignment
+ReferenceError:56:Invalid left hand side for assignment
 --true
   ^
-ReferenceError: test/script/basic/NASHORN-51.js#35<eval>:1:0 Invalid left hand side for assignment
+ReferenceError:35:Invalid left hand side for assignment
 false++
 ^
-ReferenceError: test/script/basic/NASHORN-51.js#42<eval>:1:0 Invalid left hand side for assignment
+ReferenceError:42:Invalid left hand side for assignment
 false--
 ^
-ReferenceError: test/script/basic/NASHORN-51.js#49<eval>:1:2 Invalid left hand side for assignment
+ReferenceError:49:Invalid left hand side for assignment
 ++false
   ^
-ReferenceError: test/script/basic/NASHORN-51.js#56<eval>:1:2 Invalid left hand side for assignment
+ReferenceError:56:Invalid left hand side for assignment
 --false
   ^
-ReferenceError: test/script/basic/NASHORN-51.js#35<eval>:1:0 Invalid left hand side for assignment
+ReferenceError:35:Invalid left hand side for assignment
 null++
 ^
-ReferenceError: test/script/basic/NASHORN-51.js#42<eval>:1:0 Invalid left hand side for assignment
+ReferenceError:42:Invalid left hand side for assignment
 null--
 ^
-ReferenceError: test/script/basic/NASHORN-51.js#49<eval>:1:2 Invalid left hand side for assignment
+ReferenceError:49:Invalid left hand side for assignment
 ++null
   ^
-ReferenceError: test/script/basic/NASHORN-51.js#56<eval>:1:2 Invalid left hand side for assignment
+ReferenceError:56:Invalid left hand side for assignment
 --null
   ^
--- a/test/script/basic/NASHORN-98.js	Thu Oct 17 09:41:14 2013 -0700
+++ b/test/script/basic/NASHORN-98.js	Thu Oct 17 16:19:45 2013 -0700
@@ -34,7 +34,7 @@
     if (! (e instanceof SyntaxError)) {
        fail("syntax error expected here got " + e);
     }
-    print(e.toString().replace(/\\/g, '/'));
+    printError(e);
 } 
 
 try {
@@ -43,5 +43,5 @@
     if (! (e instanceof SyntaxError)) {
        fail("syntax error expected here got " + e);
     }
-    print(e.toString().replace(/\\/g, '/'));
+    printError(e);
 } 
--- a/test/script/basic/NASHORN-98.js.EXPECTED	Thu Oct 17 09:41:14 2013 -0700
+++ b/test/script/basic/NASHORN-98.js.EXPECTED	Thu Oct 17 16:19:45 2013 -0700
@@ -1,6 +1,6 @@
-SyntaxError: test/script/basic/NASHORN-98.js#32<eval>:1:13 Expected comma but found decimal
+SyntaxError:32:Expected comma but found decimal
 var x = [ 23 34 ]
              ^
-SyntaxError: test/script/basic/NASHORN-98.js#41<eval>:1:18 Expected comma but found ident
+SyntaxError:41:Expected comma but found ident
 var x = { foo: 33 bar: 'hello' }
                   ^
--- a/test/script/basic/eval.js	Thu Oct 17 09:41:14 2013 -0700
+++ b/test/script/basic/eval.js	Thu Oct 17 16:19:45 2013 -0700
@@ -69,5 +69,5 @@
     eval("print('hello)");
 } catch (e) {
     print("is syntax error? " + (e instanceof SyntaxError));
-    print(e.toString().replace(/\\/g, '/'));
+    printError(e);
 }
--- a/test/script/basic/eval.js.EXPECTED	Thu Oct 17 09:41:14 2013 -0700
+++ b/test/script/basic/eval.js.EXPECTED	Thu Oct 17 16:19:45 2013 -0700
@@ -10,6 +10,6 @@
 100
 3300
 is syntax error? true
-SyntaxError: test/script/basic/eval.js#69<eval>:1:13 Missing close quote
+SyntaxError:69:Missing close quote
 print('hello)
              ^
--- a/test/script/basic/objects.js.EXPECTED	Thu Oct 17 09:41:14 2013 -0700
+++ b/test/script/basic/objects.js.EXPECTED	Thu Oct 17 16:19:45 2013 -0700
@@ -29,18 +29,18 @@
 abc is configurable? true
 abc is enumerable? true
 abc's value = undefined
-abc's get = abc() { return "abc"; }
+abc's get = get abc() { return "abc"; }
 abc's set = undefined
 xyz is writable? undefined
 xyz is configurable? true
 xyz is enumerable? true
 xyz's value = undefined
 xyz's get = undefined
-xyz's set = xyz(val) { print(val); }
+xyz's set = set xyz(val) { print(val); }
 hey is writable? undefined
 hey is configurable? true
 hey is enumerable? true
 hey's value = undefined
-hey's get = hey() { return "hey"; }
-hey's set = hey(val) { print(val); }
+hey's get = get hey() { return "hey"; }
+hey's set = set hey(val) { print(val); }
 undefined
--- a/test/script/sandbox/loadcompat.js	Thu Oct 17 09:41:14 2013 -0700
+++ b/test/script/sandbox/loadcompat.js	Thu Oct 17 16:19:45 2013 -0700
@@ -48,3 +48,7 @@
 if (typeof importPackage != 'function') {
     fail("importPackage function is missing in compatibility script");
 }
+
+if (typeof sync != 'function') {
+    fail("sync function is missing in compatibility script");
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/src/jdk/nashorn/api/javaaccess/ArrayConversionTest.java	Thu Oct 17 16:19:45 2013 -0700
@@ -0,0 +1,235 @@
+/*
+ * 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.api.javaaccess;
+
+import static org.testng.AssertJUnit.assertEquals;
+import static org.testng.AssertJUnit.assertFalse;
+import static org.testng.AssertJUnit.assertNull;
+import static org.testng.AssertJUnit.assertTrue;
+
+import java.util.Arrays;
+import java.util.List;
+import javax.script.ScriptContext;
+import javax.script.ScriptEngine;
+import javax.script.ScriptEngineManager;
+import javax.script.ScriptException;
+import org.testng.TestNG;
+import org.testng.annotations.AfterClass;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.Test;
+
+public class ArrayConversionTest {
+    private static ScriptEngine e = null;
+
+    public static void main(final String[] args) {
+        TestNG.main(args);
+    }
+
+    @BeforeClass
+    public static void setUpClass() throws ScriptException {
+        e = new ScriptEngineManager().getEngineByName("nashorn");
+    }
+
+    @AfterClass
+    public static void tearDownClass() {
+        e = null;
+    }
+
+    @Test
+    public void testIntArrays() throws ScriptException {
+        runTest("assertNullIntArray", "null");
+        runTest("assertEmptyIntArray", "[]");
+        runTest("assertSingle42IntArray", "[42]");
+        runTest("assertSingle42IntArray", "['42']");
+        runTest("assertIntArrayConversions", "[false, true, NaN, Infinity, -Infinity, 0.4, 0.6, null, undefined, [], {}, [1], [1, 2]]");
+    }
+
+    @Test
+    public void testIntIntArrays() throws ScriptException {
+        runTest("assertNullIntIntArray", "null");
+        runTest("assertEmptyIntIntArray", "[]");
+        runTest("assertSingleEmptyIntIntArray", "[[]]");
+        runTest("assertSingleNullIntIntArray", "[null]");
+        runTest("assertLargeIntIntArray", "[[false], [1], [2, 3], [4, 5, 6], ['7', {valueOf: function() { return 8 }}]]");
+    }
+
+    @Test
+    public void testObjectObjectArrays() throws ScriptException {
+        runTest("assertLargeObjectObjectArray", "[[false], [1], ['foo', 42.3], [{x: 17}]]");
+    }
+
+    @Test
+    public void testBooleanArrays() throws ScriptException {
+        runTest("assertBooleanArrayConversions", "[false, true, '', 'false', 0, 1, 0.4, 0.6, {}, [], [false], [true], NaN, Infinity, null, undefined]");
+    }
+
+    @Test
+    public void testArrayAmbiguity() throws ScriptException {
+        runTest("x", "'abc'");
+        runTest("x", "['foo', 'bar']");
+    }
+
+    @Test
+    public void testListArrays() throws ScriptException {
+        runTest("assertListArray", "[['foo', 'bar'], ['apple', 'orange']]");
+    }
+
+    @Test
+    public void testVarArgs() throws ScriptException {
+        // Sole NativeArray in vararg position becomes vararg array itself
+        runTest("assertVarArg_42_17", "[42, 17]");
+        // NativeArray in vararg position becomes an argument if there are more arguments
+        runTest("assertVarArg_array_17", "[42], 18");
+        // Only NativeArray is converted to vararg array, other objects (e.g. a function) aren't
+        runTest("assertVarArg_function", "function() { return 'Hello' }");
+    }
+
+    private static void runTest(final String testMethodName, final String argument) throws ScriptException {
+        e.eval("Java.type('" + ArrayConversionTest.class.getName() + "')." + testMethodName + "(" + argument + ")");
+    }
+
+    public static void assertNullIntArray(int[] array) {
+        assertNull(array);
+    }
+
+    public static void assertNullIntIntArray(int[][] array) {
+        assertNull(array);
+    }
+
+    public static void assertEmptyIntArray(int[] array) {
+        assertEquals(0, array.length);
+    }
+
+    public static void assertSingle42IntArray(int[] array) {
+        assertEquals(1, array.length);
+        assertEquals(42, array[0]);
+    }
+
+
+    public static void assertIntArrayConversions(int[] array) {
+        assertEquals(13, array.length);
+        assertEquals(0, array[0]); // false
+        assertEquals(1, array[1]); // true
+        assertEquals(0, array[2]); // NaN
+        assertEquals(0, array[3]); // Infinity
+        assertEquals(0, array[4]); // -Infinity
+        assertEquals(0, array[5]); // 0.4
+        assertEquals(0, array[6]); // 0.6 - floor, not round
+        assertEquals(0, array[7]); // null
+        assertEquals(0, array[8]); // undefined
+        assertEquals(0, array[9]); // []
+        assertEquals(0, array[10]); // {}
+        assertEquals(1, array[11]); // [1]
+        assertEquals(0, array[12]); // [1, 2]
+    }
+
+    public static void assertEmptyIntIntArray(int[][] array) {
+        assertEquals(0, array.length);
+    }
+
+    public static void assertSingleEmptyIntIntArray(int[][] array) {
+        assertEquals(1, array.length);
+        assertTrue(Arrays.equals(new int[0], array[0]));
+    }
+
+    public static void assertSingleNullIntIntArray(int[][] array) {
+        assertEquals(1, array.length);
+        assertNull(null, array[0]);
+    }
+
+    public static void assertLargeIntIntArray(int[][] array) {
+        assertEquals(5, array.length);
+        assertTrue(Arrays.equals(new int[] { 0 }, array[0]));
+        assertTrue(Arrays.equals(new int[] { 1 }, array[1]));
+        assertTrue(Arrays.equals(new int[] { 2, 3 }, array[2]));
+        assertTrue(Arrays.equals(new int[] { 4, 5, 6 }, array[3]));
+        assertTrue(Arrays.equals(new int[] { 7, 8 }, array[4]));
+    }
+
+    public static void assertLargeObjectObjectArray(Object[][] array) throws ScriptException {
+        assertEquals(4, array.length);
+        assertTrue(Arrays.equals(new Object[] { Boolean.FALSE }, array[0]));
+        assertTrue(Arrays.equals(new Object[] { 1 }, array[1]));
+        assertTrue(Arrays.equals(new Object[] { "foo", 42.3d }, array[2]));
+        assertEquals(1, array[3].length);
+        e.getBindings(ScriptContext.ENGINE_SCOPE).put("obj", array[3][0]);
+        assertEquals(17, e.eval("obj.x"));
+    }
+
+    public static void assertBooleanArrayConversions(boolean[] array) {
+        assertEquals(16, array.length);
+        assertFalse(array[0]); // false
+        assertTrue(array[1]); // true
+        assertFalse(array[2]); // ''
+        assertTrue(array[3]); // 'false' (yep, every non-empty string converts to true)
+        assertFalse(array[4]); // 0
+        assertTrue(array[5]); // 1
+        assertTrue(array[6]); // 0.4
+        assertTrue(array[7]); // 0.6
+        assertTrue(array[8]); // {}
+        assertTrue(array[9]); // []
+        assertTrue(array[10]); // [false]
+        assertTrue(array[11]); // [true]
+        assertFalse(array[12]); // NaN
+        assertTrue(array[13]); // Infinity
+        assertFalse(array[14]); // null
+        assertFalse(array[15]); // undefined
+    }
+
+    public static void assertListArray(List<?>[] array) {
+        assertEquals(2, array.length);
+        assertEquals(Arrays.asList("foo", "bar"), array[0]);
+        assertEquals(Arrays.asList("apple", "orange"), array[1]);
+    }
+
+    public static void assertVarArg_42_17(Object... args) throws ScriptException {
+        assertEquals(2, args.length);
+        assertEquals(42, ((Number)args[0]).intValue());
+        assertEquals(17, ((Number)args[1]).intValue());
+    }
+
+    public static void assertVarArg_array_17(Object... args) throws ScriptException {
+        assertEquals(2, args.length);
+        e.getBindings(ScriptContext.ENGINE_SCOPE).put("arr", args[0]);
+        assertTrue((Boolean)e.eval("arr instanceof Array && arr.length == 1 && arr[0] == 42"));
+        assertEquals(18, ((Number)args[1]).intValue());
+    }
+
+    public static void assertVarArg_function(Object... args) throws ScriptException {
+        assertEquals(1, args.length);
+        e.getBindings(ScriptContext.ENGINE_SCOPE).put("fn", args[0]);
+        assertEquals("Hello", e.eval("fn()"));
+    }
+
+
+
+    public static void x(String y) {
+        assertEquals("abc", y);
+    }
+    public static void x(String[] y) {
+        assertTrue(Arrays.equals(new String[] { "foo", "bar"}, y));
+    }
+}