Merge
authorlana
Thu, 10 Jul 2014 12:41:23 -0700
changeset 25424 000e5d36d0e3
parent 25419 67e118a37f50 (current diff)
parent 25423 ca63828cf996 (diff)
child 25425 a69d849bb635
Merge
nashorn/src/jdk/nashorn/api/scripting/resources/engine.js
--- a/nashorn/src/jdk/nashorn/api/scripting/NashornException.java	Thu Jul 10 12:13:37 2014 -0700
+++ b/nashorn/src/jdk/nashorn/api/scripting/NashornException.java	Thu Jul 10 12:41:23 2014 -0700
@@ -53,9 +53,6 @@
     // underlying ECMA error object - lazily initialized
     private Object ecmaError;
 
-    /** script source name used for "engine.js" */
-    public static final String ENGINE_SCRIPT_SOURCE_NAME = "nashorn:engine/resources/engine.js";
-
     /**
      * Constructor
      *
--- a/nashorn/src/jdk/nashorn/api/scripting/NashornScriptEngine.java	Thu Jul 10 12:13:37 2014 -0700
+++ b/nashorn/src/jdk/nashorn/api/scripting/NashornScriptEngine.java	Thu Jul 10 12:41:23 2014 -0700
@@ -25,8 +25,6 @@
 
 package jdk.nashorn.api.scripting;
 
-import static jdk.nashorn.internal.runtime.ECMAErrors.referenceError;
-import static jdk.nashorn.internal.runtime.ScriptRuntime.UNDEFINED;
 import static jdk.nashorn.internal.runtime.Source.sourceFor;
 
 import java.io.IOException;
@@ -34,13 +32,10 @@
 import java.lang.invoke.MethodHandles;
 import java.lang.reflect.Method;
 import java.lang.reflect.Modifier;
-import java.net.URL;
 import java.security.AccessControlContext;
 import java.security.AccessController;
 import java.security.Permissions;
 import java.security.PrivilegedAction;
-import java.security.PrivilegedActionException;
-import java.security.PrivilegedExceptionAction;
 import java.security.ProtectionDomain;
 import java.text.MessageFormat;
 import java.util.Locale;
@@ -58,7 +53,6 @@
 import jdk.nashorn.internal.objects.Global;
 import jdk.nashorn.internal.runtime.Context;
 import jdk.nashorn.internal.runtime.ErrorManager;
-import jdk.nashorn.internal.runtime.Property;
 import jdk.nashorn.internal.runtime.ScriptFunction;
 import jdk.nashorn.internal.runtime.ScriptObject;
 import jdk.nashorn.internal.runtime.ScriptRuntime;
@@ -98,9 +92,6 @@
     // This is the initial default Nashorn global object.
     // This is used as "shared" global if above option is true.
     private final Global              global;
-    // initialized bit late to be made 'final'.
-    // Property object for "context" property of global object.
-    private volatile Property         contextProperty;
 
     // default options passed to Nashorn Options object
     private static final String[] DEFAULT_OPTIONS = new String[] { "-doe" };
@@ -122,30 +113,6 @@
         }
     }
 
-    // load engine.js
-    private static Source loadEngineJSSource() {
-        final String script = "resources/engine.js";
-        try {
-            return AccessController.doPrivileged(
-                    new PrivilegedExceptionAction<Source>() {
-                        @Override
-                        public Source run() throws IOException {
-                            final URL url = NashornScriptEngine.class.getResource(script);
-                            return sourceFor(NashornException.ENGINE_SCRIPT_SOURCE_NAME, url);
-                        }
-                    }
-            );
-        } catch (final PrivilegedActionException e) {
-            if (Context.DEBUG) {
-                e.printStackTrace();
-            }
-            throw new RuntimeException(e);
-        }
-    }
-
-    // Source object for engine.js
-    private static final Source ENGINE_SCRIPT_SRC = loadEngineJSSource();
-
     NashornScriptEngine(final NashornScriptEngineFactory factory, final ClassLoader appLoader) {
         this(factory, DEFAULT_OPTIONS, appLoader);
     }
@@ -248,33 +215,6 @@
         return getInterfaceInner(thiz, clazz);
     }
 
-    // These are called from the "engine.js" script
-
-    /**
-     * This hook is used to search js global variables exposed from Java code.
-     *
-     * @param self 'this' passed from the script
-     * @param ctxt current ScriptContext in which name is searched
-     * @param name name of the variable searched
-     * @return the value of the named variable
-     */
-    public Object __noSuchProperty__(final Object self, final ScriptContext ctxt, final String name) {
-        if (ctxt != null) {
-            final int scope = ctxt.getAttributesScope(name);
-            final Global ctxtGlobal = getNashornGlobalFrom(ctxt);
-            if (scope != -1) {
-                return ScriptObjectMirror.unwrap(ctxt.getAttribute(name, scope), ctxtGlobal);
-            }
-
-            if (self == UNDEFINED) {
-                // scope access and so throw ReferenceError
-                throw referenceError(ctxtGlobal, "not.defined", name);
-            }
-        }
-
-        return UNDEFINED;
-    }
-
     // Implementation only below this point
 
     private static Source makeSource(final Reader reader, final ScriptContext ctxt) throws ScriptException {
@@ -426,47 +366,12 @@
             }
         }, CREATE_GLOBAL_ACC_CTXT);
 
-        nashornContext.initGlobal(newGlobal);
+        nashornContext.initGlobal(newGlobal, this);
+        newGlobal.setScriptContext(ctxt);
 
-        final int NON_ENUMERABLE_CONSTANT = Property.NOT_ENUMERABLE | Property.NOT_CONFIGURABLE | Property.NOT_WRITABLE;
-        // current ScriptContext exposed as "context"
-        // "context" is non-writable from script - but script engine still
-        // needs to set it and so save the context Property object
-        contextProperty = newGlobal.addOwnProperty("context", NON_ENUMERABLE_CONSTANT, ctxt);
-        // current ScriptEngine instance exposed as "engine". We added @SuppressWarnings("LeakingThisInConstructor") as
-        // NetBeans identifies this assignment as such a leak - this is a false positive as we're setting this property
-        // in the Global of a Context we just created - both the Context and the Global were just created and can not be
-        // seen from another thread outside of this constructor.
-        newGlobal.addOwnProperty("engine", NON_ENUMERABLE_CONSTANT, this);
-        // global script arguments with undefined value
-        newGlobal.addOwnProperty("arguments", Property.NOT_ENUMERABLE, UNDEFINED);
-        // file name default is null
-        newGlobal.addOwnProperty(ScriptEngine.FILENAME, Property.NOT_ENUMERABLE, null);
-        // evaluate engine.js initialization script this new global object
-        try {
-            evalImpl(compileImpl(ENGINE_SCRIPT_SRC, newGlobal), ctxt, newGlobal);
-        } catch (final ScriptException exp) {
-            throw new RuntimeException(exp);
-        }
         return newGlobal;
     }
 
-    // scripts should see "context" and "engine" as variables in the given global object
-    private void setContextVariables(final Global ctxtGlobal, final ScriptContext ctxt) {
-        // set "context" global variable via contextProperty - because this
-        // property is non-writable
-        contextProperty.setValue(ctxtGlobal, ctxtGlobal, ctxt, false);
-        Object args = ScriptObjectMirror.unwrap(ctxt.getAttribute("arguments"), ctxtGlobal);
-        if (args == null || args == UNDEFINED) {
-            args = ScriptRuntime.EMPTY_ARRAY;
-        }
-        // if no arguments passed, expose it
-        if (! (args instanceof ScriptObject)) {
-            args = ctxtGlobal.wrapAsObject(args);
-            ctxtGlobal.set("arguments", args, false);
-        }
-    }
-
     private Object invokeImpl(final Object selfObject, final String name, final Object... args) throws ScriptException, NoSuchMethodException {
         name.getClass(); // null check
 
@@ -533,11 +438,7 @@
             }
 
             final ScriptFunction script = mgcs.getFunction(ctxtGlobal);
-
-            // set ScriptContext variables if ctxt is non-null
-            if (ctxt != null) {
-                setContextVariables(ctxtGlobal, ctxt);
-            }
+            ctxtGlobal.setScriptContext(ctxt);
             return ScriptObjectMirror.translateUndefined(ScriptObjectMirror.wrap(ScriptRuntime.apply(script, ctxtGlobal), ctxtGlobal));
         } catch (final Exception e) {
             throwAsScriptException(e, ctxtGlobal);
@@ -560,10 +461,7 @@
                 Context.setGlobal(ctxtGlobal);
             }
 
-            // set ScriptContext variables if ctxt is non-null
-            if (ctxt != null) {
-                setContextVariables(ctxtGlobal, ctxt);
-            }
+            ctxtGlobal.setScriptContext(ctxt);
             return ScriptObjectMirror.translateUndefined(ScriptObjectMirror.wrap(ScriptRuntime.apply(script, ctxtGlobal), ctxtGlobal));
         } catch (final Exception e) {
             throwAsScriptException(e, ctxtGlobal);
--- a/nashorn/src/jdk/nashorn/api/scripting/ScriptUtils.java	Thu Jul 10 12:13:37 2014 -0700
+++ b/nashorn/src/jdk/nashorn/api/scripting/ScriptUtils.java	Thu Jul 10 12:41:23 2014 -0700
@@ -25,6 +25,8 @@
 
 package jdk.nashorn.api.scripting;
 
+import static jdk.nashorn.internal.runtime.ECMAErrors.typeError;
+
 import java.lang.invoke.MethodHandle;
 import jdk.internal.dynalink.beans.StaticClass;
 import jdk.internal.dynalink.linker.LinkerServices;
@@ -69,12 +71,15 @@
      * 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 func the function to wrap
      * @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);
+    public static Object makeSynchronizedFunction(final Object func, final Object sync) {
+        if (func instanceof ScriptFunction) {
+           return ((ScriptFunction)func).makeSynchronizedFunction(sync);
+        }
+        throw typeError("not.a.function", ScriptRuntime.safeToString(func));
     }
 
     /**
--- a/nashorn/src/jdk/nashorn/api/scripting/resources/engine.js	Thu Jul 10 12:13:37 2014 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,101 +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.
- *
- * 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.
- */
-
-/**
- * This script file is executed by script engine at the construction
- * of the every new Global object. The functions here assume global variables
- * "context" of type javax.script.ScriptContext and "engine" of the type
- * jdk.nashorn.api.scripting.NashornScriptEngine.
- **/
-
-Object.defineProperty(this, "__noSuchProperty__", {
-    configurable: true,
-    enumerable: false,
-    writable: true,
-    value: function (name) {
-        'use strict';
-        return engine.__noSuchProperty__(this, context, name);
-    }
-});
-
-function print() {
-    var writer = context != null? context.writer : engine.context.writer;
-    if (! (writer instanceof java.io.PrintWriter)) {
-        writer = new java.io.PrintWriter(writer);
-    }
-    
-    var buf = new java.lang.StringBuilder();
-    for (var i = 0; i < arguments.length; i++) {
-        if (i != 0) {
-            buf.append(' ');
-        }
-        buf.append(String(arguments[i]));
-    }
-    writer.println(buf.toString());
-}
-
-/**
- * This is C-like printf
- *
- * @param format string to format the rest of the print items
- * @param args variadic argument list
- */
-Object.defineProperty(this, "printf", {
-    configurable: true,
-    enumerable: false,
-    writable: true,
-    value: function (format, args/*, more args*/) {
-        print(sprintf.apply(this, arguments));
-    }
-});
-
-/**
- * This is C-like sprintf
- *
- * @param format string to format the rest of the print items
- * @param args variadic argument list
- */
-Object.defineProperty(this, "sprintf", {
-    configurable: true,
-    enumerable: false,
-    writable: true,
-    value: function (format, args/*, more args*/) {
-        var len = arguments.length - 1;
-        var array = [];
-
-        if (len < 0) {
-            return "";
-        }
-
-        for (var i = 0; i < len; i++) {
-            if (arguments[i+1] instanceof Date) {
-                array[i] = arguments[i+1].getTime();
-            } else {
-                array[i] = arguments[i+1];
-            }
-        }
-
-        array = Java.to(array);
-        return Packages.jdk.nashorn.api.scripting.ScriptUtils.format(format, array);
-    }
-});
--- a/nashorn/src/jdk/nashorn/internal/codegen/CodeGenerator.java	Thu Jul 10 12:13:37 2014 -0700
+++ b/nashorn/src/jdk/nashorn/internal/codegen/CodeGenerator.java	Thu Jul 10 12:41:23 2014 -0700
@@ -1317,20 +1317,14 @@
 
                         // Load up self (scope).
                         method.loadCompilerConstant(SCOPE);
-                        final CallNode.EvalArgs evalArgs = callNode.getEvalArgs();
+                        final List<Expression> evalArgs = callNode.getEvalArgs().getArgs();
                         // load evaluated code
-                        loadExpressionAsObject(evalArgs.getCode());
+                        loadExpressionAsObject(evalArgs.get(0));
                         // load second and subsequent args for side-effect
-                        final List<Expression> callArgs = callNode.getArgs();
-                        final int numArgs = callArgs.size();
+                        final int numArgs = evalArgs.size();
                         for (int i = 1; i < numArgs; i++) {
-                            loadExpressionUnbounded(callArgs.get(i)).pop();
+                            loadAndDiscard(evalArgs.get(i));
                         }
-                        // special/extra 'eval' arguments
-                        loadExpressionUnbounded(evalArgs.getThis());
-                        method.load(evalArgs.getLocation());
-                        method.load(evalArgs.getStrictMode());
-                        method.convert(Type.OBJECT);
                         method._goto(invoke_direct_eval);
 
                         method.label(is_not_eval);
@@ -1339,7 +1333,7 @@
                         // This is some scope 'eval' or global eval replaced by user
                         // but not the built-in ECMAScript 'eval' function call
                         method.loadNull();
-                        argsCount = loadArgs(callArgs);
+                        argsCount = loadArgs(callNode.getArgs());
                     }
 
                     @Override
@@ -1349,6 +1343,11 @@
                         method._goto(eval_done);
 
                         method.label(invoke_direct_eval);
+                        // Special/extra 'eval' arguments. These can be loaded late (in consumeStack) as we know none of
+                        // them can ever be optimistic.
+                        method.loadCompilerConstant(THIS);
+                        method.load(callNode.getEvalArgs().getLocation());
+                        method.load(CodeGenerator.this.lc.getCurrentFunction().isStrict());
                         // direct call to Global.directEval
                         globalDirectEval();
                         convertOptimisticReturnValue();
@@ -4438,7 +4437,7 @@
 
     private MethodEmitter globalDirectEval() {
         return method.invokestatic(GLOBAL_OBJECT, "directEval",
-                methodDescriptor(Object.class, Object.class, Object.class, Object.class, Object.class, Object.class));
+                methodDescriptor(Object.class, Object.class, Object.class, Object.class, Object.class, boolean.class));
     }
 
     private abstract class OptimisticOperation {
--- a/nashorn/src/jdk/nashorn/internal/codegen/Lower.java	Thu Jul 10 12:13:37 2014 -0700
+++ b/nashorn/src/jdk/nashorn/internal/codegen/Lower.java	Thu Jul 10 12:41:23 2014 -0700
@@ -27,7 +27,6 @@
 
 import static jdk.nashorn.internal.codegen.CompilerConstants.EVAL;
 import static jdk.nashorn.internal.codegen.CompilerConstants.RETURN;
-import static jdk.nashorn.internal.codegen.CompilerConstants.THIS;
 import static jdk.nashorn.internal.ir.Expression.isAlwaysTrue;
 
 import java.util.ArrayList;
@@ -603,13 +602,11 @@
 
             // 'eval' call with at least one argument
             if (args.size() >= 1 && EVAL.symbolName().equals(callee.getName())) {
-                final FunctionNode currentFunction = lc.getCurrentFunction();
-                return callNode.setEvalArgs(
-                    new CallNode.EvalArgs(
-                        (Expression)ensureUniqueNamesIn(args.get(0)).accept(this),
-                        compilerConstant(THIS),
-                        evalLocation(callee),
-                        currentFunction.isStrict()));
+                final List<Expression> evalArgs = new ArrayList<>(args.size());
+                for(final Expression arg: args) {
+                    evalArgs.add((Expression)ensureUniqueNamesIn(arg).accept(this));
+                }
+                return callNode.setEvalArgs(new CallNode.EvalArgs(evalArgs, evalLocation(callee)));
             }
         }
 
--- a/nashorn/src/jdk/nashorn/internal/ir/CallNode.java	Thu Jul 10 12:13:37 2014 -0700
+++ b/nashorn/src/jdk/nashorn/internal/ir/CallNode.java	Thu Jul 10 12:41:23 2014 -0700
@@ -65,61 +65,35 @@
      * Arguments to be passed to builtin {@code eval} function
      */
     public static class EvalArgs {
-        /** evaluated code */
-        private final Expression code;
-
-        /** 'this' passed to evaluated code */
-        private final IdentNode evalThis;
+        private final List<Expression> args;
 
         /** location string for the eval call */
         private final String location;
 
-        /** is this call from a strict context? */
-        private final boolean strictMode;
-
         /**
          * Constructor
          *
-         * @param code       code to evaluate
-         * @param evalThis   this node
-         * @param location   location for the eval call
-         * @param strictMode is this a call from a strict context?
+         * @param args     arguments to eval
+         * @param location location for the eval call
          */
-        public EvalArgs(final Expression code, final IdentNode evalThis, final String location, final boolean strictMode) {
-            this.code = code;
-            this.evalThis = evalThis;
+        public EvalArgs(final List<Expression> args, final String location) {
+            this.args = args;
             this.location = location;
-            this.strictMode = strictMode;
         }
 
         /**
          * Return the code that is to be eval:ed by this eval function
          * @return code as an AST node
          */
-        public Expression getCode() {
-            return code;
-        }
-
-        private EvalArgs setCode(final Expression code) {
-            if (this.code == code) {
-                return this;
-            }
-            return new EvalArgs(code, evalThis, location, strictMode);
+        public List<Expression> getArgs() {
+            return Collections.unmodifiableList(args);
         }
 
-        /**
-         * Get the {@code this} symbol used to invoke this eval call
-         * @return the {@code this} symbol
-         */
-        public IdentNode getThis() {
-            return this.evalThis;
-        }
-
-        private EvalArgs setThis(final IdentNode evalThis) {
-            if (this.evalThis == evalThis) {
+        private EvalArgs setArgs(final List<Expression> args) {
+            if (this.args == args) {
                 return this;
             }
-            return new EvalArgs(code, evalThis, location, strictMode);
+            return new EvalArgs(args, location);
         }
 
         /**
@@ -129,14 +103,6 @@
         public String getLocation() {
             return this.location;
         }
-
-        /**
-         * Check whether this eval call is executed in strict mode
-         * @return true if executed in strict mode, false otherwise
-         */
-        public boolean getStrictMode() {
-            return this.strictMode;
-        }
     }
 
     /** arguments for 'eval' call. Non-null only if this call node is 'eval' */
@@ -212,8 +178,7 @@
                     setArgs(Node.accept(visitor, Expression.class, args)).
                     setEvalArgs(evalArgs == null ?
                             null :
-                            evalArgs.setCode((Expression)evalArgs.getCode().accept(visitor)).
-                                setThis((IdentNode)evalArgs.getThis().accept(visitor))));
+                            evalArgs.setArgs(Node.accept(visitor, Expression.class, evalArgs.getArgs()))));
             // Theoretically, we'd need to instead pass lc to every setter and do a replacement on each. In practice,
             // setType from TypeOverride can't accept a lc, and we don't necessarily want to go there now.
             if (this != newCallNode) {
--- a/nashorn/src/jdk/nashorn/internal/objects/Global.java	Thu Jul 10 12:13:37 2014 -0700
+++ b/nashorn/src/jdk/nashorn/internal/objects/Global.java	Thu Jul 10 12:41:23 2014 -0700
@@ -27,6 +27,7 @@
 
 import static jdk.nashorn.internal.codegen.CompilerConstants.staticCall;
 import static jdk.nashorn.internal.lookup.Lookup.MH;
+import static jdk.nashorn.internal.runtime.ECMAErrors.referenceError;
 import static jdk.nashorn.internal.runtime.ECMAErrors.typeError;
 import static jdk.nashorn.internal.runtime.ScriptRuntime.UNDEFINED;
 
@@ -45,8 +46,11 @@
 import java.util.concurrent.Callable;
 import java.util.concurrent.ConcurrentHashMap;
 import java.util.concurrent.atomic.AtomicReference;
+import javax.script.ScriptContext;
+import javax.script.ScriptEngine;
 import jdk.internal.dynalink.linker.GuardedInvocation;
 import jdk.internal.dynalink.linker.LinkRequest;
+import jdk.nashorn.api.scripting.ScriptObjectMirror;
 import jdk.nashorn.internal.codegen.ApplySpecialization;
 import jdk.nashorn.internal.codegen.CompilerConstants.Call;
 import jdk.nashorn.internal.lookup.Lookup;
@@ -107,6 +111,10 @@
     /** Name invalidator for things like call/apply */
     public static final Call BOOTSTRAP = staticCall(MethodHandles.lookup(), Global.class, "invalidateNameBootstrap", CallSite.class, MethodHandles.Lookup.class, String.class, MethodType.class);
 
+    /** Nashorn extension: arguments array */
+    @Property(attributes = Attribute.NOT_ENUMERABLE | Attribute.NOT_CONFIGURABLE)
+    public Object arguments;
+
     /** ECMA 15.1.2.2 parseInt (string , radix) */
     @Property(attributes = Attribute.NOT_ENUMERABLE)
     public Object parseInt;
@@ -411,12 +419,13 @@
     // Used to store the last RegExp result to support deprecated RegExp constructor properties
     private RegExpResult lastRegExpResult;
 
-    private static final MethodHandle EVAL              = findOwnMH_S("eval",              Object.class, Object.class, Object.class);
-    private static final MethodHandle PRINT             = findOwnMH_S("print",             Object.class, Object.class, Object[].class);
-    private static final MethodHandle PRINTLN           = findOwnMH_S("println",           Object.class, Object.class, Object[].class);
-    private static final MethodHandle LOAD              = findOwnMH_S("load",              Object.class, Object.class, Object.class);
-    private static final MethodHandle LOADWITHNEWGLOBAL = findOwnMH_S("loadWithNewGlobal", Object.class, Object.class, Object[].class);
-    private static final MethodHandle EXIT              = findOwnMH_S("exit",              Object.class, Object.class, Object.class);
+    private static final MethodHandle EVAL              = findOwnMH_S("eval",                Object.class, Object.class, Object.class);
+    private static final MethodHandle NO_SUCH_PROPERTY  = findOwnMH_S(NO_SUCH_PROPERTY_NAME, Object.class, Object.class, Object.class);
+    private static final MethodHandle PRINT             = findOwnMH_S("print",               Object.class, Object.class, Object[].class);
+    private static final MethodHandle PRINTLN           = findOwnMH_S("println",             Object.class, Object.class, Object[].class);
+    private static final MethodHandle LOAD              = findOwnMH_S("load",                Object.class, Object.class, Object.class);
+    private static final MethodHandle LOADWITHNEWGLOBAL = findOwnMH_S("loadWithNewGlobal",   Object.class, Object.class, Object[].class);
+    private static final MethodHandle EXIT              = findOwnMH_S("exit",                Object.class, Object.class, Object.class);
 
     /** Invalidate a reserved name, such as "apply" or "call" if assigned */
     public MethodHandle INVALIDATE_RESERVED_NAME = MH.bindTo(findOwnMH_V("invalidateReservedName", void.class, String.class), this);
@@ -427,6 +436,20 @@
     // context to which this global belongs to
     private final Context context;
 
+    // current ScriptContext to use - can be null.
+    private ScriptContext scontext;
+    // associated Property object for "context" property.
+    private jdk.nashorn.internal.runtime.Property scontextProperty;
+
+    /**
+     * Set the current script context
+     * @param scontext script context
+     */
+    public void setScriptContext(final ScriptContext scontext) {
+        this.scontext = scontext;
+        scontextProperty.setValue(this, this, scontext, false);
+    }
+
     // global constants for this global - they can be replaced with MethodHandle.constant until invalidated
     private static AtomicReference<GlobalConstants> gcsInstance = new AtomicReference<>();
 
@@ -447,12 +470,7 @@
         // null check on context
         context.getClass();
 
-        /*
-         * Duplicate global's map and use it. This way the initial Map filled
-         * by nasgen (referenced from static field in this class) is retained
-         * 'as is' (as that one is process wide singleton.
-         */
-        return $nasgenmap$.duplicate();
+        return $nasgenmap$;
     }
 
     /**
@@ -483,6 +501,10 @@
         return global;
     }
 
+    private static Global instanceFrom(final Object self) {
+        return self instanceof Global? (Global)self : instance();
+    }
+
     /**
      * Return the global constants map for fields that
      * can be accessed as MethodHandle.constant
@@ -542,13 +564,13 @@
      * as well as our extension builtin objects like "Java", "JSAdapter" as properties
      * of the global scope object.
      */
-    public void initBuiltinObjects() {
+    public void initBuiltinObjects(final ScriptEngine engine) {
         if (this.builtinObject != null) {
             // already initialized, just return
             return;
         }
 
-        init();
+        init(engine);
     }
 
     /**
@@ -849,6 +871,32 @@
     }
 
     /**
+     * Hook to search missing variables in ScriptContext if available
+     * @param self used to detect if scope call or not (this function is 'strict')
+     * @param name name of the variable missing
+     * @return value of the missing variable or undefined (or TypeError for scope search)
+     */
+    public static Object __noSuchProperty__(final Object self, final Object name) {
+        final Global global = Global.instance();
+        final ScriptContext sctxt = global.scontext;
+        final String nameStr = name.toString();
+
+        if (sctxt != null) {
+            final int scope = sctxt.getAttributesScope(nameStr);
+            if (scope != -1) {
+                return ScriptObjectMirror.unwrap(sctxt.getAttribute(nameStr, scope), global);
+            }
+        }
+
+        if (self == UNDEFINED) {
+            // scope access and so throw ReferenceError
+            throw referenceError(global, "not.defined", nameStr);
+        }
+
+        return UNDEFINED;
+    }
+
+    /**
      * This is the eval used when 'indirect' eval call is made.
      *
      * var global = this;
@@ -860,7 +908,7 @@
      * @return the result of eval
      */
     public static Object eval(final Object self, final Object str) {
-        return directEval(self, str, UNDEFINED, UNDEFINED, UNDEFINED);
+        return directEval(self, str, UNDEFINED, UNDEFINED, false);
     }
 
     /**
@@ -876,14 +924,14 @@
      *
      * This is directly invoked from generated when eval(code) is called in user code
      */
-    public static Object directEval(final Object self, final Object str, final Object callThis, final Object location, final Object strict) {
+    public static Object directEval(final Object self, final Object str, final Object callThis, final Object location, final boolean strict) {
         if (!(str instanceof String || str instanceof ConsString)) {
             return str;
         }
-        final Global global = Global.instance();
+        final Global global = Global.instanceFrom(self);
         final ScriptObject scope = self instanceof ScriptObject ? (ScriptObject)self : global;
 
-        return global.getContext().eval(scope, str.toString(), callThis, location, Boolean.TRUE.equals(strict), true);
+        return global.getContext().eval(scope, str.toString(), callThis, location, strict, true);
     }
 
     /**
@@ -895,7 +943,7 @@
      * @return result of print (undefined)
      */
     public static Object print(final Object self, final Object... objects) {
-        return printImpl(false, objects);
+        return Global.instanceFrom(self).printImpl(false, objects);
     }
 
     /**
@@ -907,7 +955,7 @@
      * @return result of println (undefined)
      */
     public static Object println(final Object self, final Object... objects) {
-        return printImpl(true, objects);
+        return Global.instanceFrom(self).printImpl(true, objects);
     }
 
     /**
@@ -921,7 +969,7 @@
      * @throws IOException if source could not be read
      */
     public static Object load(final Object self, final Object source) throws IOException {
-        final Global global = Global.instance();
+        final Global global = Global.instanceFrom(self);
         final ScriptObject scope = self instanceof ScriptObject ? (ScriptObject)self : global;
         return global.getContext().load(scope, source);
     }
@@ -937,7 +985,7 @@
      * @throws IOException if source could not be read
      */
     public static Object loadWithNewGlobal(final Object self, final Object...args) throws IOException {
-        final Global global = Global.instance();
+        final Global global = Global.instanceFrom(self);
         final int length = args.length;
         final boolean hasArgs = 0 < length;
         final Object from = hasArgs ? args[0] : UNDEFINED;
@@ -1604,7 +1652,7 @@
         splitState = state;
     }
 
-    private void init() {
+    private void init(final ScriptEngine engine) {
         assert Context.getGlobal() == this : "this global is not set as current";
 
         final ScriptEnvironment env = getContext().getEnv();
@@ -1705,12 +1753,19 @@
         copyBuiltins();
 
         // expose script (command line) arguments as "arguments" property of global
-        final Object argumentsObject = wrapAsObject(env.getArguments().toArray());
-        final int    argumentsFlags  = Attribute.NOT_ENUMERABLE;
-        addOwnProperty("arguments", argumentsFlags, argumentsObject);
+        arguments = wrapAsObject(env.getArguments().toArray());
         if (env._scripting) {
             // synonym for "arguments" in scripting mode
-            addOwnProperty("$ARG", argumentsFlags, argumentsObject);
+            addOwnProperty("$ARG", Attribute.NOT_ENUMERABLE, arguments);
+        }
+
+        if (engine != null) {
+            final int NOT_ENUMERABLE_NOT_CONFIG = Attribute.NOT_ENUMERABLE | Attribute.NOT_CONFIGURABLE;
+            scontextProperty = addOwnProperty("context", NOT_ENUMERABLE_NOT_CONFIG, null);
+            addOwnProperty("engine", NOT_ENUMERABLE_NOT_CONFIG, engine);
+            // __noSuchProperty__ hook for ScriptContext search of missing variables
+            final ScriptFunction noSuchProp = ScriptFunctionImpl.makeStrictFunction(NO_SUCH_PROPERTY_NAME, NO_SUCH_PROPERTY);
+            addOwnProperty(NO_SUCH_PROPERTY_NAME, Attribute.NOT_ENUMERABLE, noSuchProp);
         }
     }
 
@@ -1878,8 +1933,8 @@
         this.addOwnProperty("Debug", Attribute.NOT_ENUMERABLE, initConstructor("Debug"));
     }
 
-    private static Object printImpl(final boolean newLine, final Object... objects) {
-        final PrintWriter out = Global.getEnv().getOut();
+    private Object printImpl(final boolean newLine, final Object... objects) {
+        final PrintWriter out = scontext != null? new PrintWriter(scontext.getWriter()) : getContext().getEnv().getOut();
         final StringBuilder sb = new StringBuilder();
 
         for (final Object object : objects) {
@@ -2023,12 +2078,11 @@
 
         for (final jdk.nashorn.internal.runtime.Property property : properties) {
             final Object key   = property.getKey();
-            final Object value = ObjectPrototype.get(key);
-
             if (key.equals("constructor")) {
                 continue;
             }
 
+            final Object value = ObjectPrototype.get(key);
             if (value instanceof ScriptFunction) {
                 final ScriptFunction func = (ScriptFunction)value;
                 final ScriptObject prototype = ScriptFunction.getPrototype(func);
--- a/nashorn/src/jdk/nashorn/internal/objects/NativeDebug.java	Thu Jul 10 12:13:37 2014 -0700
+++ b/nashorn/src/jdk/nashorn/internal/objects/NativeDebug.java	Thu Jul 10 12:41:23 2014 -0700
@@ -222,7 +222,6 @@
         out.println("ScriptFunction allocations " + ScriptFunction.getAllocations());
         out.println("PropertyMap count " + PropertyMap.getCount());
         out.println("PropertyMap cloned " + PropertyMap.getClonedCount());
-        out.println("PropertyMap duplicated " + PropertyMap.getDuplicatedCount());
         out.println("PropertyMap history hit " + PropertyMap.getHistoryHit());
         out.println("PropertyMap proto invalidations " + PropertyMap.getProtoInvalidations());
         out.println("PropertyMap proto history hit " + PropertyMap.getProtoHistoryHit());
--- a/nashorn/src/jdk/nashorn/internal/objects/NativeJava.java	Thu Jul 10 12:13:37 2014 -0700
+++ b/nashorn/src/jdk/nashorn/internal/objects/NativeJava.java	Thu Jul 10 12:41:23 2014 -0700
@@ -36,6 +36,7 @@
 import jdk.internal.dynalink.beans.StaticClass;
 import jdk.internal.dynalink.support.TypeUtilities;
 import jdk.nashorn.api.scripting.JSObject;
+import jdk.nashorn.api.scripting.ScriptUtils;
 import jdk.nashorn.internal.objects.annotations.Attribute;
 import jdk.nashorn.internal.objects.annotations.Function;
 import jdk.nashorn.internal.objects.annotations.ScriptClass;
@@ -45,6 +46,7 @@
 import jdk.nashorn.internal.runtime.ListAdapter;
 import jdk.nashorn.internal.runtime.PropertyMap;
 import jdk.nashorn.internal.runtime.ScriptObject;
+import jdk.nashorn.internal.runtime.ScriptFunction;
 import jdk.nashorn.internal.runtime.ScriptRuntime;
 import jdk.nashorn.internal.runtime.linker.Bootstrap;
 import jdk.nashorn.internal.runtime.linker.JavaAdapterFactory;
@@ -80,6 +82,73 @@
     }
 
     /**
+     * Returns synchronized wrapper version of the given ECMAScript function.
+     * @param self not used
+     * @param func the ECMAScript function whose synchronized version is returned.
+     * @param obj the object (i.e, lock) on which the function synchronizes.
+     * @return synchronized wrapper version of the given ECMAScript function.
+     */
+    @Function(name="synchronized", attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR)
+    public static Object synchronizedFunc(final Object self, final Object func, final Object obj) {
+        return ScriptUtils.makeSynchronizedFunction(func, obj);
+    }
+
+    /**
+     * Returns true if the specified object is a Java method.
+     * @param self not used
+     * @param obj the object that is checked if it is a Java method object or not
+     * @return tells whether given object is a Java method object or not.
+     */
+    @Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR)
+    public static boolean isJavaMethod(final Object self, final Object obj) {
+        return Bootstrap.isDynamicMethod(obj);
+    }
+
+    /**
+     * Returns true if the specified object is a java function (but not script function)
+     * @param self not used
+     * @param obj the object that is checked if it is a Java function or not
+     * @return tells whether given object is a Java function or not
+     */
+    @Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR)
+    public static boolean isJavaFunction(final Object self, final Object obj) {
+        return Bootstrap.isCallable(obj) && !(obj instanceof ScriptFunction);
+    }
+
+    /**
+     * Returns true if the specified object is a Java object but not a script object
+     * @param self not used
+     * @param obj the object that is checked
+     * @return tells whether given object is a Java object but not a script object
+     */
+    @Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR)
+    public static boolean isJavaObject(final Object self, final Object obj) {
+        return obj != null && !(obj instanceof ScriptObject);
+    }
+
+    /**
+     * Returns true if the specified object is a ECMAScript object, that is an instance of {@link ScriptObject}.
+     * @param self not used
+     * @param obj the object that is checked if it is a ECMAScript object or not
+     * @return tells whether given object is a ECMAScript object or not.
+     */
+    @Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR)
+    public static boolean isScriptObject(final Object self, final Object obj) {
+        return obj instanceof ScriptObject;
+    }
+
+    /**
+     * Returns true if the specified object is a ECMAScript function, that is an instance of {@link ScriptFunction}.
+     * @param self not used
+     * @param obj the object that is checked if it is a ECMAScript function or not
+     * @return tells whether given object is a ECMAScript function or not.
+     */
+    @Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR)
+    public static boolean isScriptFunction(final Object self, final Object obj) {
+        return obj instanceof ScriptFunction;
+    }
+
+    /**
      * <p>
      * Given a name of a Java type, returns an object representing that type in Nashorn. The Java class of the objects
      * used to represent Java types in Nashorn is not {@link java.lang.Class} but rather {@link StaticClass}. They are
--- a/nashorn/src/jdk/nashorn/internal/objects/ScriptFunctionImpl.java	Thu Jul 10 12:13:37 2014 -0700
+++ b/nashorn/src/jdk/nashorn/internal/objects/ScriptFunctionImpl.java	Thu Jul 10 12:41:23 2014 -0700
@@ -184,6 +184,15 @@
         return new AnonymousFunction();
     }
 
+    private static ScriptFunction makeFunction(final String name, final MethodHandle methodHandle, final MethodHandle[] specs, final int flags) {
+        final ScriptFunctionImpl func = new ScriptFunctionImpl(name, methodHandle, null, specs, flags);
+        func.setPrototype(UNDEFINED);
+        // Non-constructor built-in functions do not have "prototype" property
+        func.deleteOwnProperty(func.getMap().findProperty("prototype"));
+
+        return func;
+    }
+
     /**
      * Factory method for non-constructor built-in functions
      *
@@ -193,12 +202,18 @@
      * @return new ScriptFunction
      */
     static ScriptFunction makeFunction(final String name, final MethodHandle methodHandle, final MethodHandle[] specs) {
-        final ScriptFunctionImpl func = new ScriptFunctionImpl(name, methodHandle, null, specs, ScriptFunctionData.IS_BUILTIN);
-        func.setPrototype(UNDEFINED);
-        // Non-constructor built-in functions do not have "prototype" property
-        func.deleteOwnProperty(func.getMap().findProperty("prototype"));
+        return makeFunction(name, methodHandle, specs, ScriptFunctionData.IS_BUILTIN);
+    }
 
-        return func;
+    /**
+     * Factory method for non-constructor built-in, strict functions
+     *
+     * @param name   function name
+     * @param methodHandle handle for invocation
+     * @return new ScriptFunction
+     */
+    static ScriptFunction makeStrictFunction(final String name, final MethodHandle methodHandle) {
+        return makeFunction(name, methodHandle, null, ScriptFunctionData.IS_BUILTIN | ScriptFunctionData.IS_STRICT );
     }
 
     /**
--- a/nashorn/src/jdk/nashorn/internal/runtime/Context.java	Thu Jul 10 12:13:37 2014 -0700
+++ b/nashorn/src/jdk/nashorn/internal/runtime/Context.java	Thu Jul 10 12:41:23 2014 -0700
@@ -62,6 +62,7 @@
 import java.util.function.Consumer;
 import java.util.function.Supplier;
 import java.util.logging.Level;
+import javax.script.ScriptEngine;
 import jdk.internal.org.objectweb.asm.ClassReader;
 import jdk.internal.org.objectweb.asm.util.CheckClassAdapter;
 import jdk.nashorn.api.scripting.ScriptObjectMirror;
@@ -954,16 +955,17 @@
      * Initialize given global scope object.
      *
      * @param global the global
+     * @param engine the associated ScriptEngine instance, can be null
      * @return the initialized global scope object.
      */
-    public Global initGlobal(final Global global) {
+    public Global initGlobal(final Global global, final ScriptEngine engine) {
         // Need only minimal global object, if we are just compiling.
         if (!env._compile_only) {
             final Global oldGlobal = Context.getGlobal();
             try {
                 Context.setGlobal(global);
                 // initialize global scope with builtin global objects
-                global.initBuiltinObjects();
+                global.initBuiltinObjects(engine);
             } finally {
                 Context.setGlobal(oldGlobal);
             }
@@ -973,6 +975,16 @@
     }
 
     /**
+     * Initialize given global scope object.
+     *
+     * @param global the global
+     * @return the initialized global scope object.
+     */
+    public Global initGlobal(final Global global) {
+        return initGlobal(global, null);
+    }
+
+    /**
      * Return the current global's context
      * @return current global's context
      */
--- a/nashorn/src/jdk/nashorn/internal/runtime/ECMAErrors.java	Thu Jul 10 12:13:37 2014 -0700
+++ b/nashorn/src/jdk/nashorn/internal/runtime/ECMAErrors.java	Thu Jul 10 12:41:23 2014 -0700
@@ -405,12 +405,8 @@
         // Look for script package in class name (into which compiler puts generated code)
         if (className.startsWith(scriptPackage) && !CompilerConstants.isInternalMethodName(frame.getMethodName())) {
             final String source = frame.getFileName();
-            /*
-             * Make sure that it is not some Java code that Nashorn has in that package!
-             * also, we don't want to report JavaScript code that lives in script engine implementation
-             * We want to report only user's own scripts and not any of our own scripts like "engine.js"
-             */
-            return source != null && !source.endsWith(".java") && !source.contains(NashornException.ENGINE_SCRIPT_SOURCE_NAME);
+            // Make sure that it is not some Java code that Nashorn has in that package!
+            return source != null && !source.endsWith(".java");
         }
         return false;
     }
--- a/nashorn/src/jdk/nashorn/internal/runtime/PropertyMap.java	Thu Jul 10 12:13:37 2014 -0700
+++ b/nashorn/src/jdk/nashorn/internal/runtime/PropertyMap.java	Thu Jul 10 12:41:23 2014 -0700
@@ -145,21 +145,6 @@
         this(propertyMap, propertyMap.properties);
     }
 
-    /**
-     * Duplicates this PropertyMap instance. This is used to duplicate 'shared'
-     * maps {@link PropertyMap} used as process wide singletons. Shared maps are
-     * duplicated for every global scope object. That way listeners, proto and property
-     * histories are scoped within a global scope.
-     *
-     * @return Duplicated {@link PropertyMap}.
-     */
-    public PropertyMap duplicate() {
-        if (Context.DEBUG) {
-            duplicatedCount++;
-        }
-        return new PropertyMap(this.properties, this.className, 0, 0, 0, containsArrayKeys());
-    }
-
     private void writeObject(final ObjectOutputStream out) throws IOException {
         out.defaultWriteObject();
         out.writeObject(properties.getProperties());
@@ -968,7 +953,6 @@
     // counters updated only in debug mode
     private static int count;
     private static int clonedCount;
-    private static int duplicatedCount;
     private static int historyHit;
     private static int protoInvalidations;
     private static int protoHistoryHit;
@@ -989,13 +973,6 @@
     }
 
     /**
-     * @return The number of maps that are duplicated.
-     */
-    public static int getDuplicatedCount() {
-        return duplicatedCount;
-    }
-
-    /**
      * @return The number of times history was successfully used.
      */
     public static int getHistoryHit() {
--- a/nashorn/src/jdk/nashorn/internal/runtime/ScriptObject.java	Thu Jul 10 12:13:37 2014 -0700
+++ b/nashorn/src/jdk/nashorn/internal/runtime/ScriptObject.java	Thu Jul 10 12:41:23 2014 -0700
@@ -103,10 +103,10 @@
     public static final String PROTO_PROPERTY_NAME   = "__proto__";
 
     /** Search fall back routine name for "no such method" */
-    static final String NO_SUCH_METHOD_NAME   = "__noSuchMethod__";
+    public static final String NO_SUCH_METHOD_NAME   = "__noSuchMethod__";
 
     /** Search fall back routine name for "no such property" */
-    static final String NO_SUCH_PROPERTY_NAME = "__noSuchProperty__";
+    public static final String NO_SUCH_PROPERTY_NAME = "__noSuchProperty__";
 
     /** Per ScriptObject flag - is this a scope object? */
     public static final int IS_SCOPE       = 1 << 0;
@@ -160,7 +160,8 @@
     static final MethodHandle GLOBALFILTER       = findOwnMH_S("globalFilter", Object.class, Object.class);
 
     private static final MethodHandle TRUNCATINGFILTER   = findOwnMH_S("truncatingFilter", Object[].class, int.class, Object[].class);
-    private static final MethodHandle KNOWNFUNCPROPGUARD = findOwnMH_S("knownFunctionPropertyGuard", boolean.class, Object.class, PropertyMap.class, MethodHandle.class, Object.class, ScriptFunction.class);
+    private static final MethodHandle KNOWNFUNCPROPGUARDSELF = findOwnMH_S("knownFunctionPropertyGuardSelf", boolean.class, Object.class, PropertyMap.class, MethodHandle.class, ScriptFunction.class);
+    private static final MethodHandle KNOWNFUNCPROPGUARDPROTO = findOwnMH_S("knownFunctionPropertyGuardProto", boolean.class, Object.class, PropertyMap.class, MethodHandle.class, int.class, ScriptFunction.class);
 
     private static final ArrayList<MethodHandle> PROTO_FILTERS = new ArrayList<>();
 
@@ -2271,13 +2272,20 @@
                 if (scopeAccess && func.isStrict()) {
                     mh = bindTo(mh, UNDEFINED);
                 }
+
                 return new GuardedInvocation(
                         mh,
-                        //TODO this always does a scriptobject check
-                        getKnownFunctionPropertyGuard(
+                        find.isSelf()?
+                            getKnownFunctionPropertyGuardSelf(
                                 getMap(),
                                 find.getGetter(Object.class, INVALID_PROGRAM_POINT),
-                                find.getOwner(),
+                                func)
+                            :
+                            //TODO this always does a scriptobject check
+                            getKnownFunctionPropertyGuardProto(
+                                getMap(),
+                                find.getGetter(Object.class, INVALID_PROGRAM_POINT),
+                                find.getProtoChainLength(),
                                 func),
                         getProtoSwitchPoint(NO_SUCH_PROPERTY_NAME, find.getOwner()),
                         //TODO this doesn't need a ClassCastException as guard always checks script object
@@ -3595,15 +3603,51 @@
         return MH.findStatic(MethodHandles.lookup(), ScriptObject.class, name, MH.type(rtype, types));
     }
 
-    private static MethodHandle getKnownFunctionPropertyGuard(final PropertyMap map, final MethodHandle getter, final Object where, final ScriptFunction func) {
-        return MH.insertArguments(KNOWNFUNCPROPGUARD, 1, map, getter, where, func);
+    private static MethodHandle getKnownFunctionPropertyGuardSelf(final PropertyMap map, final MethodHandle getter, final ScriptFunction func) {
+        return MH.insertArguments(KNOWNFUNCPROPGUARDSELF, 1, map, getter, func);
     }
 
     @SuppressWarnings("unused")
-    private static boolean knownFunctionPropertyGuard(final Object self, final PropertyMap map, final MethodHandle getter, final Object where, final ScriptFunction func) {
+    private static boolean knownFunctionPropertyGuardSelf(final Object self, final PropertyMap map, final MethodHandle getter, final ScriptFunction func) {
         if (self instanceof ScriptObject && ((ScriptObject)self).getMap() == map) {
             try {
-                return getter.invokeExact(where) == func;
+                return getter.invokeExact(self) == func;
+            } catch (final RuntimeException | Error e) {
+                throw e;
+            } catch (final Throwable t) {
+                throw new RuntimeException(t);
+            }
+        }
+
+        return false;
+    }
+
+    private static MethodHandle getKnownFunctionPropertyGuardProto(final PropertyMap map, final MethodHandle getter, final int depth, final ScriptFunction func) {
+        return MH.insertArguments(KNOWNFUNCPROPGUARDPROTO, 1, map, getter, depth, func);
+    }
+
+    @SuppressWarnings("unused")
+    private static ScriptObject getProto(final ScriptObject self, final int depth) {
+        ScriptObject proto = self;
+        for (int d = 0; d < depth; d++) {
+            proto = proto.getProto();
+            if (proto == null) {
+                return null;
+            }
+        }
+
+        return proto;
+    }
+
+    @SuppressWarnings("unused")
+    private static boolean knownFunctionPropertyGuardProto(final Object self, final PropertyMap map, final MethodHandle getter, final int depth, final ScriptFunction func) {
+        if (self instanceof ScriptObject && ((ScriptObject)self).getMap() == map) {
+            final ScriptObject proto = getProto((ScriptObject)self, depth);
+            if (proto == null) {
+                return false;
+            }
+            try {
+                return getter.invokeExact((Object)proto) == func;
             } catch (final RuntimeException | Error e) {
                 throw e;
             } catch (final Throwable t) {
--- a/nashorn/src/jdk/nashorn/internal/runtime/linker/BoundDynamicMethod.java	Thu Jul 10 12:13:37 2014 -0700
+++ b/nashorn/src/jdk/nashorn/internal/runtime/linker/BoundDynamicMethod.java	Thu Jul 10 12:41:23 2014 -0700
@@ -25,6 +25,7 @@
 
 package jdk.nashorn.internal.runtime.linker;
 
+import java.util.Objects;
 import jdk.internal.dynalink.beans.BeansLinker;
 
 /**
@@ -48,4 +49,9 @@
     Object getBoundThis() {
         return boundThis;
     }
+
+    @Override
+    public String toString() {
+        return dynamicMethod.toString() + " on " + Objects.toString(boundThis);
+    }
 }
--- a/nashorn/test/script/basic/JDK-8047057.js	Thu Jul 10 12:13:37 2014 -0700
+++ b/nashorn/test/script/basic/JDK-8047057.js	Thu Jul 10 12:41:23 2014 -0700
@@ -49,7 +49,7 @@
 makeFuncAndCall("L: { { break L; } return; }");
 makeFuncAndCall("L: { while(0) break L; return; }");
 makeFuncExpectError("L: {while(0) break L; return [](); }", TypeError);
-// makeFuncAndCall("do with({}) break ; while(0);");
+makeFuncAndCall("do with({}) break ; while(0);");
 makeFuncAndCall("while(0) with({}) continue ;");
 makeFuncAndCall("eval([]);");
 makeFuncAndCall("try{} finally{[]}");
@@ -59,10 +59,10 @@
 makeFuncAndCall("try { var x = 1, x = null; } finally { }");
 makeFuncAndCall("try { var x = {}, x = []; } catch(x3) { }");
 makeFuncAndCall("[delete this]");
-// makeFuncAndCall("if(eval('', eval('', function() {}))) { }");
-// makeFuncAndCall("if(eval('', eval('', function() {}))) { }");
-// makeFuncAndCall("eval(\"[,,];\", [11,12,13,14].some)");
-// makeFuncAndCall("eval(\"1.2e3\", ({})[ /x/ ])");
+makeFuncAndCall("if(eval('', eval('', function() {}))) { }");
+makeFuncAndCall("if(eval('', eval('', function() {}))) { }");
+makeFuncAndCall("eval(\"[,,];\", [11,12,13,14].some)");
+makeFuncAndCall("eval(\"1.2e3\", ({})[ /x/ ])");
 makeFuncExpectError("eval(\"x4\", x3);", ReferenceError);
 makeFuncAndCall("with({5.0000000000000000000000: String()}){(false); }");
 makeFuncAndCall("try { var x = undefined, x = 5.0000000000000000000000; } catch(x) { x = undefined; }");
@@ -72,4 +72,4 @@
 makeFuncAndCall("with({8: 'fafafa'.replace()}){ }");
 makeFuncAndCall("(function (x) '' )(true)");
 makeFuncExpectError("new eval(function(){})", TypeError);
-//** makeFuncAndCall('eval("23", ({})[/x/])');
+makeFuncAndCall('eval("23", ({})[/x/])');
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/basic/JDK-8047067.js	Thu Jul 10 12:41:23 2014 -0700
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2010, 2014, 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-8047067: all eval arguments need to be copied in Lower
+ *
+ * @test
+ * @run
+ */
+
+// The second expression triggers optimistic deoptimization, and if not
+// all eval arguments were copied in Lower, we'd end up with duplicate
+// program points that'd cause incorrect continuation program point in
+// the rest-of, and therefore a bad stack, and therefore an AIOOBE in
+// the continuation setup code.
+eval("23", ({})[/x/]) 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/basic/JDK-8049086.js	Thu Jul 10 12:41:23 2014 -0700
@@ -0,0 +1,144 @@
+/*
+ * Copyright (c) 2014, 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-8049086: Minor API convenience functions on "Java" object
+ *
+ * @test
+ * @run
+ */
+
+var System = Java.type("java.lang.System");
+var out = System.out;
+var println = out.println;
+var getProperty = System.getProperty;
+var File = Java.type("java.io.File")["(String)"];
+
+print("println is java method? " + Java.isJavaMethod(println));
+print("println is script function? " + Java.isScriptFunction(println));
+print("getProperty is java method? " + Java.isJavaMethod(getProperty));
+print("getProperty is script function? " + Java.isScriptFunction(getProperty));
+print("File is java method? " + Java.isJavaMethod(File));
+print("File is script function? " + Java.isScriptFunction(File));
+
+print("eval is script function? " + Java.isScriptFunction(eval));
+print("eval is java method? " + Java.isJavaMethod(eval));
+function hello() {}
+print("hello is script function? " + Java.isScriptFunction(hello));
+print("hello is java method? " + Java.isJavaMethod(hello));
+
+print("out is script object? " + Java.isScriptObject(out));
+print("System is script object? " + Java.isScriptObject(System));
+print("Object is script object? " + Java.isScriptObject(Object));
+print("{} is script object? " + Java.isScriptObject({}));
+print("/foo/ is script object? " + Java.isScriptObject(/foo/));
+
+// Java function is anything whose 'typeof' is 'function' but it is not
+// a script function! This includes:
+// (a) Java methods (b) Java classes (as these respond to new)
+// (c) FunctionalInterface objects (d) JSObjects that are 'functions'
+
+print("java.awt.Color is java function? " + Java.isJavaFunction(java.awt.Color));
+print("java.lang.Runnable instance is java function? " 
+    + Java.isJavaFunction(new java.lang.Runnable(function() {})));
+print("eval is java function? " + Java.isJavaFunction(eval));
+print("println is java function? " + Java.isJavaFunction(println));
+print("getProperty is java function? " + Java.isJavaFunction(getProperty));
+
+var JSObject = Java.type("jdk.nashorn.api.scripting.JSObject");
+print("callable JSObject is function? " +
+    Java.isJavaFunction(new JSObject() {
+        isFunction: function() true,
+        call: function() {}
+    })
+);
+
+print("Non callable JSObject is function? " +
+    Java.isJavaFunction(new JSObject() {
+        isFunction: function() false,
+    })
+);
+
+// synchronized function
+var lock = new java.lang.Object();
+
+print("lock is java object? " + Java.isJavaObject(lock));
+print("eval is java object? " + Java.isJavaObject(eval));
+print("{} is java object? " + Java.isJavaObject({}));
+print("/foo/ is java object? " + Java.isJavaObject(/foo/));
+print("[] is java object? " + Java.isJavaObject([]));
+print("java.io.File is java object? " + Java.isJavaObject(java.io.File));
+
+// synchornized function checks
+Java.synchronized(function() {
+    var th = new java.lang.Thread(Java.synchronized(function() {
+        print("new thread");
+        print("notifying..");
+        lock.notifyAll();
+    }, lock));
+    th.start();
+    print("about to wait..");
+    lock.wait();
+    th.join();
+    print("done waiting!");
+}, lock)();
+
+// try Mozilla "sync" as well
+load("nashorn:mozilla_compat.js");
+sync(function() {
+    var th = new java.lang.Thread(sync(function() {
+        print("new thread");
+        print("notifying..");
+        lock.notifyAll();
+    }, lock));
+    th.start();
+    print("about to wait..");
+    lock.wait();
+    th.join();
+    print("done waiting!");
+}, lock)();
+
+function expectTypeError(func) {
+    try {
+        func();
+        throw new Error("should have thrown TypeError");
+    } catch (e) {
+        if (! (e instanceof TypeError)) {
+            fail("Expected TypeError, got " +e);
+        }
+        print(e);
+    }
+}
+
+expectTypeError(function() Java.synchronized(232));
+expectTypeError(function() sync(232));
+expectTypeError(function() Java.synchronized({}));
+expectTypeError(function() sync({}));
+expectTypeError(function() Java.synchronized([]));
+expectTypeError(function() sync([]));
+expectTypeError(function() Java.synchronized("hello"));
+expectTypeError(function() sync("hello"));
+expectTypeError(function() Java.synchronized(null));
+expectTypeError(function() sync(null));
+expectTypeError(function() Java.synchronized(undefined));
+expectTypeError(function() sync(undefined));
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/basic/JDK-8049086.js.EXPECTED	Thu Jul 10 12:41:23 2014 -0700
@@ -0,0 +1,48 @@
+println is java method? true
+println is script function? false
+getProperty is java method? true
+getProperty is script function? false
+File is java method? true
+File is script function? false
+eval is script function? true
+eval is java method? false
+hello is script function? true
+hello is java method? false
+out is script object? false
+System is script object? false
+Object is script object? true
+{} is script object? true
+/foo/ is script object? true
+java.awt.Color is java function? true
+java.lang.Runnable instance is java function? true
+eval is java function? false
+println is java function? true
+getProperty is java function? true
+callable JSObject is function? true
+Non callable JSObject is function? false
+lock is java object? true
+eval is java object? false
+{} is java object? false
+/foo/ is java object? false
+[] is java object? false
+java.io.File is java object? true
+about to wait..
+new thread
+notifying..
+done waiting!
+about to wait..
+new thread
+notifying..
+done waiting!
+TypeError: 232 is not a function
+TypeError: 232 is not a function
+TypeError: [object Object] is not a function
+TypeError: [object Object] is not a function
+TypeError: [object Array] is not a function
+TypeError: [object Array] is not a function
+TypeError: hello is not a function
+TypeError: hello is not a function
+TypeError: null is not a function
+TypeError: null is not a function
+TypeError: undefined is not a function
+TypeError: undefined is not a function
--- a/nashorn/test/src/jdk/nashorn/internal/runtime/CodeStoreAndPathTest.java	Thu Jul 10 12:13:37 2014 -0700
+++ b/nashorn/test/src/jdk/nashorn/internal/runtime/CodeStoreAndPathTest.java	Thu Jul 10 12:41:23 2014 -0700
@@ -136,8 +136,7 @@
             // Check that a new compiled script is stored in existing code cache
             e.eval(code1);
             final DirectoryStream<Path> stream = Files.newDirectoryStream(codeCachePath);
-            // Already one compiled script has been stored in the cache during initialization
-            checkCompiledScripts(stream, 2);
+            checkCompiledScripts(stream, 1);
             // Setting to default current working dir
         } finally {
             System.setProperty("user.dir", oldUserDir);
@@ -154,9 +153,8 @@
         e.eval(code1);
         e.eval(code2);
         e.eval(code3);// less than minimum size for storing
-        // Already one compiled script has been stored in the cache during initialization
         // adding code1 and code2.
         final DirectoryStream<Path> stream = Files.newDirectoryStream(codeCachePath);
-        checkCompiledScripts(stream, 3);
+        checkCompiledScripts(stream, 2);
     }
 }