Merge
authorlana
Wed, 09 Apr 2014 09:20:03 -0700
changeset 23768 10ddc9305893
parent 23759 8b15a2eac05d (current diff)
parent 23767 7c0614b75e23 (diff)
child 23772 1b70f28ef99f
Merge
--- a/nashorn/README	Wed Apr 02 22:00:15 2014 -0700
+++ b/nashorn/README	Wed Apr 09 09:20:03 2014 -0700
@@ -81,13 +81,13 @@
     
 After that, you can run the tests using:
     cd make
-    ant test
+    ant clean test
     
 You can also run the ECMA-262 test suite with Nashorn. In order to do
 that, you will need to get a copy of it and put it in
 test/script/external/test262 directory. A convenient way to do it is:
 
-   hg clone http://hg.ecmascript.org/tests/test262/ test/script/external/test262
+   git clone https://github.com/tc39/test262 test/script/external/test262
     
 Alternatively, you can check it out elsewhere and make
 test/script/external/test262 a symbolic link to that directory. After
@@ -95,6 +95,11 @@
 
     cd nashorn~jdk8/nashorn/make
     ant test262
+
+Ant target to get/update external test suites:
+
+    ant externals
+    ant update-externals
     
 These tests take time, so we have a parallelized runner for them that
 takes advantage of all processor cores on the computer:
--- a/nashorn/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/MemberInfo.java	Wed Apr 02 22:00:15 2014 -0700
+++ b/nashorn/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/MemberInfo.java	Wed Apr 09 09:20:03 2014 -0700
@@ -22,40 +22,62 @@
  * or visit www.oracle.com if you need additional information or have any
  * questions.
  */
-
 package jdk.nashorn.internal.tools.nasgen;
 
 import static jdk.nashorn.internal.tools.nasgen.StringConstants.OBJECT_ARRAY_DESC;
 import static jdk.nashorn.internal.tools.nasgen.StringConstants.OBJECT_DESC;
+import static jdk.nashorn.internal.tools.nasgen.StringConstants.SCRIPTOBJECT_DESC;
+import static jdk.nashorn.internal.tools.nasgen.StringConstants.STRING_DESC;
 
 import jdk.internal.org.objectweb.asm.Opcodes;
 import jdk.internal.org.objectweb.asm.Type;
 import jdk.nashorn.internal.objects.annotations.Where;
+import jdk.nashorn.internal.runtime.ScriptObject;
 
 /**
  * Details about a Java method or field annotated with any of the field/method
  * annotations from the jdk.nashorn.internal.objects.annotations package.
  */
 public final class MemberInfo implements Cloneable {
+    // class loader of this class
+    private static ClassLoader myLoader = MemberInfo.class.getClassLoader();
+
     /**
      * The different kinds of available class annotations
      */
     public static enum Kind {
-        /** This is a script class */
+
+        /**
+         * This is a script class
+         */
         SCRIPT_CLASS,
-        /** This is a constructor */
+        /**
+         * This is a constructor
+         */
         CONSTRUCTOR,
-        /** This is a function */
+        /**
+         * This is a function
+         */
         FUNCTION,
-        /** This is a getter */
+        /**
+         * This is a getter
+         */
         GETTER,
-        /** This is a setter */
+        /**
+         * This is a setter
+         */
         SETTER,
-        /** This is a property */
+        /**
+         * This is a property
+         */
         PROPERTY,
-        /** This is a specialized version of a function */
+        /**
+         * This is a specialized version of a function
+         */
         SPECIALIZED_FUNCTION,
-        /** This is a specialized version of a constructor */
+        /**
+         * This is a specialized version of a constructor
+         */
         SPECIALIZED_CONSTRUCTOR
     }
 
@@ -194,6 +216,7 @@
 
     /**
      * Check whether this MemberInfo is a getter that resides in the instance
+     *
      * @return true if instance setter
      */
     boolean isInstanceSetter() {
@@ -245,92 +268,201 @@
     }
 
     void verify() {
-        if (kind == Kind.CONSTRUCTOR) {
-            final Type returnType = Type.getReturnType(javaDesc);
-            if (! returnType.toString().equals(OBJECT_DESC)) {
-                error("return value should be of Object type, found" + returnType);
-            }
-            final Type[] argTypes = Type.getArgumentTypes(javaDesc);
-            if (argTypes.length < 2) {
-                error("constructor methods should have at least 2 args");
-            }
-            if (! argTypes[0].equals(Type.BOOLEAN_TYPE)) {
-                error("first argument should be of boolean type, found" + argTypes[0]);
-            }
-            if (! argTypes[1].toString().equals(OBJECT_DESC)) {
-                error("second argument should be of Object type, found" + argTypes[0]);
-            }
+        switch (kind) {
+            case CONSTRUCTOR: {
+                final Type returnType = Type.getReturnType(javaDesc);
+                if (!isJSObjectType(returnType)) {
+                    error("return value of a @Constructor method should be of Object type, found " + returnType);
+                }
+                final Type[] argTypes = Type.getArgumentTypes(javaDesc);
+                if (argTypes.length < 2) {
+                    error("@Constructor methods should have at least 2 args");
+                }
+                if (!argTypes[0].equals(Type.BOOLEAN_TYPE)) {
+                    error("first argument of a @Constructor method should be of boolean type, found " + argTypes[0]);
+                }
+                if (!isJavaLangObject(argTypes[1])) {
+                    error("second argument of a @Constructor method should be of Object type, found " + argTypes[0]);
+                }
 
-            if (argTypes.length > 2) {
-                for (int i = 2; i < argTypes.length - 1; i++) {
-                    if (! argTypes[i].toString().equals(OBJECT_DESC)) {
-                        error(i + "'th argument should be of Object type, found " + argTypes[i]);
+                if (argTypes.length > 2) {
+                    for (int i = 2; i < argTypes.length - 1; i++) {
+                        if (!isJavaLangObject(argTypes[i])) {
+                            error(i + "'th argument of a @Constructor method should be of Object type, found " + argTypes[i]);
+                        }
+                    }
+
+                    final String lastArgTypeDesc = argTypes[argTypes.length - 1].getDescriptor();
+                    final boolean isVarArg = lastArgTypeDesc.equals(OBJECT_ARRAY_DESC);
+                    if (!lastArgTypeDesc.equals(OBJECT_DESC) && !isVarArg) {
+                        error("last argument of a @Constructor method is neither Object nor Object[] type: " + lastArgTypeDesc);
+                    }
+
+                    if (isVarArg && argTypes.length > 3) {
+                        error("vararg of a @Constructor method has more than 3 arguments");
                     }
                 }
-
-                final String lastArgType = argTypes[argTypes.length - 1].toString();
-                final boolean isVarArg = lastArgType.equals(OBJECT_ARRAY_DESC);
-                if (!lastArgType.equals(OBJECT_DESC) && !isVarArg) {
-                    error("last argument is neither Object nor Object[] type: " + lastArgType);
+            }
+            break;
+            case SPECIALIZED_CONSTRUCTOR: {
+                final Type returnType = Type.getReturnType(javaDesc);
+                if (!isJSObjectType(returnType)) {
+                    error("return value of a @SpecializedConstructor method should be a valid JS type, found " + returnType);
                 }
-
-                if (isVarArg && argTypes.length > 3) {
-                    error("vararg constructor has more than 3 arguments");
+                final Type[] argTypes = Type.getArgumentTypes(javaDesc);
+                for (int i = 0; i < argTypes.length; i++) {
+                    if (!isValidJSType(argTypes[i])) {
+                        error(i + "'th argument of a @SpecializedConstructor method is not valid JS type, found " + argTypes[i]);
+                    }
                 }
             }
-        } else if (kind == Kind.FUNCTION) {
-            final Type[] argTypes = Type.getArgumentTypes(javaDesc);
-            if (argTypes.length < 1) {
-                error("function methods should have at least 1 arg");
-            }
-            if (! argTypes[0].toString().equals(OBJECT_DESC)) {
-                error("first argument should be of Object type, found" + argTypes[0]);
-            }
-
-            if (argTypes.length > 1) {
-                for (int i = 1; i < argTypes.length - 1; i++) {
-                    if (! argTypes[i].toString().equals(OBJECT_DESC)) {
-                        error(i + "'th argument should be of Object type, found " + argTypes[i]);
-                    }
+            break;
+            case FUNCTION: {
+                final Type returnType = Type.getReturnType(javaDesc);
+                if (!isValidJSType(returnType)) {
+                    error("return value of a @Function method should be a valid JS type, found " + returnType);
                 }
-
-                final String lastArgType = argTypes[argTypes.length - 1].toString();
-                final boolean isVarArg = lastArgType.equals(OBJECT_ARRAY_DESC);
-                if (!lastArgType.equals(OBJECT_DESC) && !isVarArg) {
-                    error("last argument is neither Object nor Object[] type: " + lastArgType);
+                final Type[] argTypes = Type.getArgumentTypes(javaDesc);
+                if (argTypes.length < 1) {
+                    error("@Function methods should have at least 1 arg");
+                }
+                if (!isJavaLangObject(argTypes[0])) {
+                    error("first argument of a @Function method should be of Object type, found " + argTypes[0]);
                 }
 
-                if (isVarArg && argTypes.length > 2) {
-                    error("vararg function has more than 2 arguments");
+                if (argTypes.length > 1) {
+                    for (int i = 1; i < argTypes.length - 1; i++) {
+                        if (!isJavaLangObject(argTypes[i])) {
+                            error(i + "'th argument of a @Function method should be of Object type, found " + argTypes[i]);
+                        }
+                    }
+
+                    final String lastArgTypeDesc = argTypes[argTypes.length - 1].getDescriptor();
+                    final boolean isVarArg = lastArgTypeDesc.equals(OBJECT_ARRAY_DESC);
+                    if (!lastArgTypeDesc.equals(OBJECT_DESC) && !isVarArg) {
+                        error("last argument of a @Function method is neither Object nor Object[] type: " + lastArgTypeDesc);
+                    }
+
+                    if (isVarArg && argTypes.length > 2) {
+                        error("vararg @Function method has more than 2 arguments");
+                    }
+                }
+            }
+            break;
+            case SPECIALIZED_FUNCTION: {
+                final Type returnType = Type.getReturnType(javaDesc);
+                if (!isValidJSType(returnType)) {
+                    error("return value of a @SpecializedFunction method should be a valid JS type, found " + returnType);
+                }
+                final Type[] argTypes = Type.getArgumentTypes(javaDesc);
+                for (int i = 0; i < argTypes.length; i++) {
+                    if (!isValidJSType(argTypes[i])) {
+                        error(i + "'th argument of a @SpecializedFunction method is not valid JS type, found " + argTypes[i]);
+                    }
                 }
             }
-        } else if (kind == Kind.GETTER) {
-            final Type[] argTypes = Type.getArgumentTypes(javaDesc);
-            if (argTypes.length != 1) {
-                error("getter methods should have one argument");
-            }
-            if (! argTypes[0].toString().equals(OBJECT_DESC)) {
-                error("first argument of getter should be of Object type, found: " + argTypes[0]);
-            }
-            if (Type.getReturnType(javaDesc).equals(Type.VOID_TYPE)) {
-                error("return type of getter should not be void");
+            break;
+            case GETTER: {
+                final Type[] argTypes = Type.getArgumentTypes(javaDesc);
+                if (argTypes.length != 1) {
+                    error("@Getter methods should have one argument");
+                }
+                if (!isJavaLangObject(argTypes[0])) {
+                    error("first argument of a @Getter method should be of Object type, found: " + argTypes[0]);
+                }
+
+                final Type returnType = Type.getReturnType(javaDesc);
+                if (!isJavaLangObject(returnType)) {
+                    error("return type of a @Getter method should be Object, found: " + javaDesc);
+                }
             }
-        } else if (kind == Kind.SETTER) {
-            final Type[] argTypes = Type.getArgumentTypes(javaDesc);
-            if (argTypes.length != 2) {
-                error("setter methods should have two arguments");
+            break;
+            case SETTER: {
+                final Type[] argTypes = Type.getArgumentTypes(javaDesc);
+                if (argTypes.length != 2) {
+                    error("@Setter methods should have two arguments");
+                }
+                if (!isJavaLangObject(argTypes[0])) {
+                    error("first argument of a @Setter method should be of Object type, found: " + argTypes[0]);
+                }
+                if (!Type.getReturnType(javaDesc).toString().equals("V")) {
+                    error("return type of of a @Setter method should be void, found: " + Type.getReturnType(javaDesc));
+                }
             }
-            if (! argTypes[0].toString().equals(OBJECT_DESC)) {
-                error("first argument of setter should be of Object type, found: " + argTypes[0]);
-            }
-            if (!Type.getReturnType(javaDesc).toString().equals("V")) {
-                error("return type of setter should be void, found: " + Type.getReturnType(javaDesc));
+            break;
+            case PROPERTY: {
+                if (where == Where.CONSTRUCTOR) {
+                    if (isStatic()) {
+                        if (!isFinal()) {
+                            error("static Where.CONSTRUCTOR @Property should be final");
+                        }
+
+                        if (!isJSPrimitiveType(Type.getType(javaDesc))) {
+                            error("static Where.CONSTRUCTOR @Property should be a JS primitive");
+                        }
+                    }
+                } else if (where == Where.PROTOTYPE) {
+                    if (isStatic()) {
+                        if (!isFinal()) {
+                            error("static Where.PROTOTYPE @Property should be final");
+                        }
+
+                        if (!isJSPrimitiveType(Type.getType(javaDesc))) {
+                            error("static Where.PROTOTYPE @Property should be a JS primitive");
+                        }
+                    }
+                }
             }
         }
     }
 
+    private static boolean isValidJSType(final Type type) {
+        return isJSPrimitiveType(type) || isJSObjectType(type);
+    }
+
+    private static boolean isJSPrimitiveType(final Type type) {
+        switch (type.getSort()) {
+            case Type.BOOLEAN:
+            case Type.INT:
+            case Type.LONG:
+            case Type.DOUBLE:
+                return true;
+            default:
+                return false;
+        }
+    }
+
+    private static boolean isJSObjectType(final Type type) {
+        return isJavaLangObject(type) || isJavaLangString(type) || isScriptObject(type);
+    }
+
+    private static boolean isJavaLangObject(final Type type) {
+        return type.getDescriptor().equals(OBJECT_DESC);
+    }
+
+    private static boolean isJavaLangString(final Type type) {
+        return type.getDescriptor().equals(STRING_DESC);
+    }
+
+    private static boolean isScriptObject(final Type type) {
+        if (type.getDescriptor().equals(SCRIPTOBJECT_DESC)) {
+            return true;
+        }
+
+        if (type.getSort() == Type.OBJECT) {
+            try {
+                final Class clazz = Class.forName(type.getClassName(), false, myLoader);
+                return ScriptObject.class.isAssignableFrom(clazz);
+            } catch (final ClassNotFoundException cnfe) {
+                return false;
+            }
+        }
+
+        return false;
+    }
+
     private void error(final String msg) {
-        throw new RuntimeException(javaName + javaDesc + " : " + msg);
+        throw new RuntimeException(javaName + " of type " + javaDesc + " : " + msg);
     }
 
     /**
--- a/nashorn/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/StringConstants.java	Wed Apr 02 22:00:15 2014 -0700
+++ b/nashorn/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/StringConstants.java	Wed Apr 09 09:20:03 2014 -0700
@@ -61,6 +61,8 @@
     static final String METHODHANDLE_TYPE = TYPE_METHODHANDLE.getInternalName();
     static final String OBJECT_TYPE = TYPE_OBJECT.getInternalName();
     static final String OBJECT_DESC = TYPE_OBJECT.getDescriptor();
+    static final String STRING_TYPE = TYPE_STRING.getInternalName();
+    static final String STRING_DESC = TYPE_STRING.getDescriptor();
     static final String OBJECT_ARRAY_DESC = Type.getDescriptor(Object[].class);
     static final String ARRAYLIST_TYPE = TYPE_ARRAYLIST.getInternalName();
     static final String COLLECTION_TYPE = TYPE_COLLECTION.getInternalName();
@@ -129,6 +131,7 @@
 
     // ScriptObject
     static final String SCRIPTOBJECT_TYPE = TYPE_SCRIPTOBJECT.getInternalName();
+    static final String SCRIPTOBJECT_DESC = TYPE_SCRIPTOBJECT.getDescriptor();
     static final String SCRIPTOBJECT_INIT_DESC = Type.getMethodDescriptor(Type.VOID_TYPE, TYPE_PROPERTYMAP);
 
     static final String GETTER_PREFIX = "G$";
--- a/nashorn/make/build.xml	Wed Apr 02 22:00:15 2014 -0700
+++ b/nashorn/make/build.xml	Wed Apr 09 09:20:03 2014 -0700
@@ -42,6 +42,9 @@
     <condition property="hg.executable" value="/usr/local/bin/hg" else="hg">
       <available file="/usr/local/bin/hg"/>
     </condition>
+    <condition property="git.executable" value="/usr/local/bin/git" else="git">
+      <available file="/usr/local/bin/git"/>
+    </condition>
     <!-- check if JDK already has ASM classes -->
     <available property="asm.available" classname="jdk.internal.org.objectweb.asm.Type"/>
     <!-- check if testng.jar is avaiable -->
@@ -503,18 +506,17 @@
 
   <!-- test262 test suite -->
   <target name="get-test262" depends="init" unless="${test-sys-prop.external.test262}">
-    <!-- clone test262 mercurial repo -->
-    <exec executable="${hg.executable}">
+    <!-- clone test262 git repo -->
+    <exec executable="${git.executable}">
        <arg value="clone"/>
-       <arg value="http://hg.ecmascript.org/tests/test262"/>
+       <arg value="https://github.com/tc39/test262"/>
        <arg value="${test.external.dir}/test262"/>
     </exec>
   </target>
   <target name="update-test262" depends="init" if="${test-sys-prop.external.test262}">
-    <!-- update test262 mercurial repo -->
-    <exec executable="${hg.executable}" dir="${test.external.dir}/test262">
+    <!-- update test262 git repo -->
+    <exec executable="${git.executable}" dir="${test.external.dir}/test262">
        <arg value="pull"/>
-       <arg value="-u"/>
     </exec>
   </target>
 
--- a/nashorn/src/jdk/nashorn/internal/codegen/CodeGenerator.java	Wed Apr 02 22:00:15 2014 -0700
+++ b/nashorn/src/jdk/nashorn/internal/codegen/CodeGenerator.java	Wed Apr 09 09:20:03 2014 -0700
@@ -3228,7 +3228,7 @@
         final String      className          = SCRIPTFUNCTION_IMPL_OBJECT;
         final int         fieldCount         = ObjectClassGenerator.getPaddedFieldCount(functionNode.countThisProperties());
         final String      allocatorClassName = Compiler.binaryName(ObjectClassGenerator.getClassName(fieldCount));
-        final PropertyMap allocatorMap       = PropertyMap.newMap(null, 0, fieldCount, 0);
+        final PropertyMap allocatorMap       = PropertyMap.newMap(null, allocatorClassName, 0, fieldCount, 0);
 
         method._new(className).dup();
         loadConstant(new RecompilableScriptFunctionData(functionNode, compiler.getCodeInstaller(), allocatorClassName, allocatorMap));
--- a/nashorn/src/jdk/nashorn/internal/codegen/Compiler.java	Wed Apr 02 22:00:15 2014 -0700
+++ b/nashorn/src/jdk/nashorn/internal/codegen/Compiler.java	Wed Apr 09 09:20:03 2014 -0700
@@ -405,32 +405,8 @@
         return newFunctionNode;
     }
 
-    private Class<?> install(final String className, final byte[] code) {
-        LOG.fine("Installing class ", className);
-
-        final Class<?> clazz = installer.install(Compiler.binaryName(className), code);
-
-        try {
-            final Object[] constants = getConstantData().toArray();
-            // Need doPrivileged because these fields are private
-            AccessController.doPrivileged(new PrivilegedExceptionAction<Void>() {
-                @Override
-                public Void run() throws Exception {
-                    //use reflection to write source and constants table to installed classes
-                    final Field sourceField    = clazz.getDeclaredField(SOURCE.symbolName());
-                    final Field constantsField = clazz.getDeclaredField(CONSTANTS.symbolName());
-                    sourceField.setAccessible(true);
-                    constantsField.setAccessible(true);
-                    sourceField.set(null, source);
-                    constantsField.set(null, constants);
-                    return null;
-                }
-            });
-        } catch (final PrivilegedActionException e) {
-            throw new RuntimeException(e);
-        }
-
-        return clazz;
+    private Class<?> install(final String className, final byte[] code, final Object[] constants) {
+        return installer.install(className, code, source, constants);
     }
 
     /**
@@ -444,10 +420,15 @@
         assert functionNode.hasState(CompilationState.EMITTED) : functionNode.getName() + " has no bytecode and cannot be installed";
 
         final Map<String, Class<?>> installedClasses = new HashMap<>();
+        final Object[] constants = getConstantData().toArray();
 
         final String   rootClassName = firstCompileUnitName();
         final byte[]   rootByteCode  = bytecode.get(rootClassName);
-        final Class<?> rootClass     = install(rootClassName, rootByteCode);
+        final Class<?> rootClass     = install(rootClassName, rootByteCode, constants);
+
+        if (!isLazy()) {
+            installer.storeCompiledScript(source, rootClassName, bytecode, constants);
+        }
 
         int length = rootByteCode.length;
 
@@ -461,7 +442,7 @@
             final byte[] code = entry.getValue();
             length += code.length;
 
-            installedClasses.put(className, install(className, code));
+            installedClasses.put(className, install(className, code, constants));
         }
 
         for (final CompileUnit unit : compileUnits) {
--- a/nashorn/src/jdk/nashorn/internal/codegen/MapCreator.java	Wed Apr 02 22:00:15 2014 -0700
+++ b/nashorn/src/jdk/nashorn/internal/codegen/MapCreator.java	Wed Apr 09 09:20:03 2014 -0700
@@ -83,7 +83,7 @@
             }
         }
 
-        return PropertyMap.newMap(properties, fieldCount, fieldMaximum, 0);
+        return PropertyMap.newMap(properties, structure.getName(), fieldCount, fieldMaximum, 0);
     }
 
     PropertyMap makeSpillMap(final boolean hasArguments) {
@@ -100,7 +100,7 @@
             }
         }
 
-        return PropertyMap.newMap(properties, 0, 0, spillIndex);
+        return PropertyMap.newMap(properties, structure.getName(), 0, 0, spillIndex);
     }
 
     /**
--- a/nashorn/src/jdk/nashorn/internal/objects/ArrayBufferView.java	Wed Apr 02 22:00:15 2014 -0700
+++ b/nashorn/src/jdk/nashorn/internal/objects/ArrayBufferView.java	Wed Apr 09 09:20:03 2014 -0700
@@ -382,7 +382,7 @@
         return (int) (length & Integer.MAX_VALUE);
     }
 
-    protected static Object subarrayImpl(final Object self, final Object begin0, final Object end0) {
+    protected static ScriptObject subarrayImpl(final Object self, final Object begin0, final Object end0) {
         final ArrayBufferView arrayView = ((ArrayBufferView)self);
         final int elementLength = arrayView.elementLength();
         final int begin = NativeArrayBuffer.adjustIndex(JSType.toInt32(begin0), elementLength);
--- a/nashorn/src/jdk/nashorn/internal/objects/NativeArray.java	Wed Apr 02 22:00:15 2014 -0700
+++ b/nashorn/src/jdk/nashorn/internal/objects/NativeArray.java	Wed Apr 09 09:20:03 2014 -0700
@@ -31,6 +31,7 @@
 import static jdk.nashorn.internal.runtime.PropertyDescriptor.WRITABLE;
 import static jdk.nashorn.internal.runtime.arrays.ArrayLikeIterator.arrayLikeIterator;
 import static jdk.nashorn.internal.runtime.arrays.ArrayLikeIterator.reverseArrayLikeIterator;
+import static jdk.nashorn.internal.runtime.arrays.ArrayIndex.isValidArrayIndex;
 
 import java.lang.invoke.MethodHandle;
 import java.util.ArrayList;
@@ -350,6 +351,27 @@
     }
 
     /**
+     * Spec. mentions use of [[DefineOwnProperty]] for indexed properties in
+     * certain places (eg. Array.prototype.map, filter). We can not use ScriptObject.set
+     * method in such cases. This is because set method uses inherited setters (if any)
+     * from any object in proto chain such as Array.prototype, Object.prototype.
+     * This method directly sets a particular element value in the current object.
+     *
+     * @param index key for property
+     * @param value value to define
+     */
+    @Override
+    public final void defineOwnProperty(final int index, final Object value) {
+        assert isValidArrayIndex(index) : "invalid array index";
+        final long longIndex = ArrayIndex.toLongIndex(index);
+        if (longIndex >= getArray().length()) {
+            // make array big enough to hold..
+            setArray(getArray().ensure(longIndex));
+        }
+        setArray(getArray().set(index, value, false));
+    }
+
+    /**
      * Return the array contents upcasted as an ObjectArray, regardless of
      * representation
      *
@@ -367,7 +389,7 @@
      * @return true if argument is an array
      */
     @Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR)
-    public static Object isArray(final Object self, final Object arg) {
+    public static boolean isArray(final Object self, final Object arg) {
         return isArray(arg) || (arg instanceof JSObject && ((JSObject)arg).isArray());
     }
 
@@ -466,7 +488,7 @@
      * @return locale specific string representation for array
      */
     @Function(attributes = Attribute.NOT_ENUMERABLE)
-    public static Object toLocaleString(final Object self) {
+    public static String toLocaleString(final Object self) {
         final StringBuilder sb = new StringBuilder();
         final Iterator<Object> iter = arrayLikeIterator(self, true);
 
@@ -512,7 +534,7 @@
      * @return the new NativeArray
      */
     @Constructor(arity = 1)
-    public static Object construct(final boolean newObj, final Object self, final Object... args) {
+    public static NativeArray construct(final boolean newObj, final Object self, final Object... args) {
         switch (args.length) {
         case 0:
             return new NativeArray(0);
@@ -565,7 +587,7 @@
      * @return the new NativeArray
      */
     @SpecializedConstructor
-    public static Object construct(final boolean newObj, final Object self) {
+    public static NativeArray construct(final boolean newObj, final Object self) {
         return new NativeArray(0);
     }
 
@@ -580,7 +602,7 @@
      * @return the new NativeArray
      */
     @SpecializedConstructor
-    public static Object construct(final boolean newObj, final Object self, final int length) {
+    public static NativeArray construct(final boolean newObj, final Object self, final int length) {
         if (length >= 0) {
             return new NativeArray(length);
         }
@@ -599,7 +621,7 @@
      * @return the new NativeArray
      */
     @SpecializedConstructor
-    public static Object construct(final boolean newObj, final Object self, final long length) {
+    public static NativeArray construct(final boolean newObj, final Object self, final long length) {
         if (length >= 0L && length <= JSType.MAX_UINT) {
             return new NativeArray(length);
         }
@@ -618,7 +640,7 @@
      * @return the new NativeArray
      */
     @SpecializedConstructor
-    public static Object construct(final boolean newObj, final Object self, final double length) {
+    public static NativeArray construct(final boolean newObj, final Object self, final double length) {
         final long uint32length = JSType.toUint32(length);
 
         if (uint32length == length) {
@@ -636,7 +658,7 @@
      * @return resulting NativeArray
      */
     @Function(attributes = Attribute.NOT_ENUMERABLE, arity = 1)
-    public static Object concat(final Object self, final Object... args) {
+    public static NativeArray concat(final Object self, final Object... args) {
         final ArrayList<Object> list = new ArrayList<>();
         concatToList(list, Global.toObject(self));
 
@@ -683,7 +705,7 @@
      * @return string representation after join
      */
     @Function(attributes = Attribute.NOT_ENUMERABLE)
-    public static Object join(final Object self, final Object separator) {
+    public static String join(final Object self, final Object separator) {
         final StringBuilder    sb   = new StringBuilder();
         final Iterator<Object> iter = arrayLikeIterator(self, true);
         final String           sep  = separator == ScriptRuntime.UNDEFINED ? "," : JSType.toString(separator);
@@ -951,7 +973,7 @@
      * @return sorted array
      */
     @Function(attributes = Attribute.NOT_ENUMERABLE)
-    public static Object sort(final Object self, final Object comparefn) {
+    public static ScriptObject sort(final Object self, final Object comparefn) {
         try {
             final ScriptObject sobj    = (ScriptObject) self;
             final long         len     = JSType.toUint32(sobj.getLength());
@@ -1155,7 +1177,7 @@
      * @return index of element, or -1 if not found
      */
     @Function(attributes = Attribute.NOT_ENUMERABLE, arity = 1)
-    public static Object indexOf(final Object self, final Object searchElement, final Object fromIndex) {
+    public static long indexOf(final Object self, final Object searchElement, final Object fromIndex) {
         try {
             final ScriptObject sobj = (ScriptObject)Global.toObject(self);
             final long         len  = JSType.toUint32(sobj.getLength());
@@ -1191,7 +1213,7 @@
      * @return index of element, or -1 if not found
      */
     @Function(attributes = Attribute.NOT_ENUMERABLE, arity = 1)
-    public static Object lastIndexOf(final Object self, final Object... args) {
+    public static long lastIndexOf(final Object self, final Object... args) {
         try {
             final ScriptObject sobj = (ScriptObject)Global.toObject(self);
             final long         len  = JSType.toUint32(sobj.getLength());
@@ -1226,7 +1248,7 @@
      * @return true if callback function return true for every element in the array, false otherwise
      */
     @Function(attributes = Attribute.NOT_ENUMERABLE, arity = 1)
-    public static Object every(final Object self, final Object callbackfn, final Object thisArg) {
+    public static boolean every(final Object self, final Object callbackfn, final Object thisArg) {
         return applyEvery(Global.toObject(self), callbackfn, thisArg);
     }
 
@@ -1250,7 +1272,7 @@
      * @return true if callback function returned true for any element in the array, false otherwise
      */
     @Function(attributes = Attribute.NOT_ENUMERABLE, arity = 1)
-    public static Object some(final Object self, final Object callbackfn, final Object thisArg) {
+    public static boolean some(final Object self, final Object callbackfn, final Object thisArg) {
         return new IteratorAction<Boolean>(Global.toObject(self), callbackfn, thisArg, false) {
             private final MethodHandle someInvoker = getSOME_CALLBACK_INVOKER();
 
@@ -1291,7 +1313,7 @@
      * @return array with elements transformed by map function
      */
     @Function(attributes = Attribute.NOT_ENUMERABLE, arity = 1)
-    public static Object map(final Object self, final Object callbackfn, final Object thisArg) {
+    public static NativeArray map(final Object self, final Object callbackfn, final Object thisArg) {
         return new IteratorAction<NativeArray>(Global.toObject(self), callbackfn, thisArg, null) {
             private final MethodHandle mapInvoker = getMAP_CALLBACK_INVOKER();
 
@@ -1320,7 +1342,7 @@
      * @return filtered array
      */
     @Function(attributes = Attribute.NOT_ENUMERABLE, arity = 1)
-    public static Object filter(final Object self, final Object callbackfn, final Object thisArg) {
+    public static NativeArray filter(final Object self, final Object callbackfn, final Object thisArg) {
         return new IteratorAction<NativeArray>(Global.toObject(self), callbackfn, thisArg, new NativeArray()) {
             private long to = 0;
             private final MethodHandle filterInvoker = getFILTER_CALLBACK_INVOKER();
--- a/nashorn/src/jdk/nashorn/internal/objects/NativeArrayBuffer.java	Wed Apr 02 22:00:15 2014 -0700
+++ b/nashorn/src/jdk/nashorn/internal/objects/NativeArrayBuffer.java	Wed Apr 09 09:20:03 2014 -0700
@@ -45,7 +45,7 @@
     private static PropertyMap $nasgenmap$;
 
     @Constructor(arity = 1)
-    public static Object constructor(final boolean newObj, final Object self, final Object... args) {
+    public static NativeArrayBuffer constructor(final boolean newObj, final Object self, final Object... args) {
         if (args.length == 0) {
             throw new RuntimeException("missing length argument");
         }
@@ -81,7 +81,7 @@
     }
 
     @Function(attributes = Attribute.NOT_ENUMERABLE)
-    public static Object slice(final Object self, final Object begin0, final Object end0) {
+    public static NativeArrayBuffer slice(final Object self, final Object begin0, final Object end0) {
         final NativeArrayBuffer arrayBuffer = (NativeArrayBuffer)self;
         int begin = JSType.toInt32(begin0);
         int end = end0 != ScriptRuntime.UNDEFINED ? JSType.toInt32(end0) : arrayBuffer.getByteLength();
--- a/nashorn/src/jdk/nashorn/internal/objects/NativeBoolean.java	Wed Apr 02 22:00:15 2014 -0700
+++ b/nashorn/src/jdk/nashorn/internal/objects/NativeBoolean.java	Wed Apr 09 09:20:03 2014 -0700
@@ -110,7 +110,7 @@
      * @return string representation of this boolean
      */
     @Function(attributes = Attribute.NOT_ENUMERABLE)
-    public static Object toString(final Object self) {
+    public static String toString(final Object self) {
         return getBoolean(self).toString();
     }
 
@@ -121,7 +121,7 @@
      * @return value of this boolean
      */
     @Function(attributes = Attribute.NOT_ENUMERABLE)
-    public static Object valueOf(final Object self) {
+    public static boolean valueOf(final Object self) {
         return getBoolean(self);
     }
 
--- a/nashorn/src/jdk/nashorn/internal/objects/NativeDataView.java	Wed Apr 02 22:00:15 2014 -0700
+++ b/nashorn/src/jdk/nashorn/internal/objects/NativeDataView.java	Wed Apr 09 09:20:03 2014 -0700
@@ -131,7 +131,7 @@
      * @return newly constructed DataView object
      */
     @Constructor(arity = 1)
-    public static Object constructor(final boolean newObj, final Object self, final Object... args) {
+    public static NativeDataView constructor(final boolean newObj, final Object self, final Object... args) {
         if (args.length == 0 || !(args[0] instanceof NativeArrayBuffer)) {
             throw typeError("not.an.arraybuffer.in.dataview");
         }
@@ -157,7 +157,7 @@
      * @return newly constructed DataView object
      */
     @SpecializedConstructor
-    public static Object constructor(final boolean newObj, final Object self, final Object arrBuf, final int offset) {
+    public static NativeDataView constructor(final boolean newObj, final Object self, final Object arrBuf, final int offset) {
         if (!(arrBuf instanceof NativeArrayBuffer)) {
             throw typeError("not.an.arraybuffer.in.dataview");
         }
@@ -175,7 +175,7 @@
      * @return newly constructed DataView object
      */
     @SpecializedConstructor
-    public static Object constructor(final boolean newObj, final Object self, final Object arrBuf, final int offset, final int length) {
+    public static NativeDataView constructor(final boolean newObj, final Object self, final Object arrBuf, final int offset, final int length) {
         if (!(arrBuf instanceof NativeArrayBuffer)) {
             throw typeError("not.an.arraybuffer.in.dataview");
         }
--- a/nashorn/src/jdk/nashorn/internal/objects/NativeDate.java	Wed Apr 02 22:00:15 2014 -0700
+++ b/nashorn/src/jdk/nashorn/internal/objects/NativeDate.java	Wed Apr 09 09:20:03 2014 -0700
@@ -226,7 +226,7 @@
      * @return Date interpreted from the string, or NaN for illegal values
      */
     @Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR)
-    public static Object parse(final Object self, final Object string) {
+    public static double parse(final Object self, final Object string) {
         return parseDateString(JSType.toString(string));
     }
 
@@ -238,7 +238,7 @@
      * @return a time clip according to the ECMA specification
      */
     @Function(attributes = Attribute.NOT_ENUMERABLE, arity = 7, where = Where.CONSTRUCTOR)
-    public static Object UTC(final Object self, final Object... args) {
+    public static double UTC(final Object self, final Object... args) {
         final NativeDate nd = new NativeDate(0);
         final double[] d = convertCtorArgs(args);
         final double time = d == null ? Double.NaN : timeClip(makeDate(d));
@@ -253,8 +253,8 @@
      * @return a Date that points to the current moment in time
      */
     @Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR)
-    public static Object now(final Object self) {
-        return (double)System.currentTimeMillis();
+    public static long now(final Object self) {
+        return System.currentTimeMillis();
     }
 
     /**
@@ -264,7 +264,7 @@
      * @return string value that represents the Date in the current time zone
      */
     @Function(attributes = Attribute.NOT_ENUMERABLE)
-    public static Object toString(final Object self) {
+    public static String toString(final Object self) {
         return toStringImpl(self, FORMAT_DATE_TIME);
     }
 
@@ -275,7 +275,7 @@
      * @return string value with the "date" part of the Date in the current time zone
      */
     @Function(attributes = Attribute.NOT_ENUMERABLE)
-    public static Object toDateString(final Object self) {
+    public static String toDateString(final Object self) {
         return toStringImpl(self, FORMAT_DATE);
     }
 
@@ -286,7 +286,7 @@
      * @return string value with "time" part of Date in the current time zone
      */
     @Function(attributes = Attribute.NOT_ENUMERABLE)
-    public static Object toTimeString(final Object self) {
+    public static String toTimeString(final Object self) {
         return toStringImpl(self, FORMAT_TIME);
     }
 
@@ -297,7 +297,7 @@
      * @return string value that represents the Data in the current time zone and locale
      */
     @Function(attributes = Attribute.NOT_ENUMERABLE)
-    public static Object toLocaleString(final Object self) {
+    public static String toLocaleString(final Object self) {
         return toStringImpl(self, FORMAT_LOCAL_DATE_TIME);
     }
 
@@ -308,7 +308,7 @@
      * @return string value with the "date" part of the Date in the current time zone and locale
      */
     @Function(attributes = Attribute.NOT_ENUMERABLE)
-    public static Object toLocaleDateString(final Object self) {
+    public static String toLocaleDateString(final Object self) {
         return toStringImpl(self, FORMAT_LOCAL_DATE);
     }
 
@@ -319,7 +319,7 @@
      * @return string value with the "time" part of Date in the current time zone and locale
      */
     @Function(attributes = Attribute.NOT_ENUMERABLE)
-    public static Object toLocaleTimeString(final Object self) {
+    public static String toLocaleTimeString(final Object self) {
         return toStringImpl(self, FORMAT_LOCAL_TIME);
     }
 
@@ -330,7 +330,7 @@
      * @return valueOf - a number which is this time value
      */
     @Function(attributes = Attribute.NOT_ENUMERABLE)
-    public static Object valueOf(final Object self) {
+    public static double valueOf(final Object self) {
         final NativeDate nd = getNativeDate(self);
         return (nd != null) ? nd.getTime() : Double.NaN;
     }
@@ -342,7 +342,7 @@
      * @return time
      */
     @Function(attributes = Attribute.NOT_ENUMERABLE)
-    public static Object getTime(final Object self) {
+    public static double getTime(final Object self) {
         final NativeDate nd = getNativeDate(self);
         return (nd != null) ? nd.getTime() : Double.NaN;
     }
@@ -365,7 +365,7 @@
      * @return UTC full year
      */
     @Function(attributes = Attribute.NOT_ENUMERABLE)
-    public static Object getUTCFullYear(final Object self) {
+    public static double getUTCFullYear(final Object self) {
         return getUTCField(self, YEAR);
     }
 
@@ -376,7 +376,7 @@
      * @return year
      */
     @Function(attributes = Attribute.NOT_ENUMERABLE)
-    public static Object getYear(final Object self) {
+    public static double getYear(final Object self) {
         final NativeDate nd = getNativeDate(self);
         return (nd != null && nd.isValidDate()) ? (yearFromTime(nd.getLocalTime()) - 1900) : Double.NaN;
     }
@@ -388,7 +388,7 @@
      * @return month
      */
     @Function(attributes = Attribute.NOT_ENUMERABLE)
-    public static Object getMonth(final Object self) {
+    public static double getMonth(final Object self) {
         return getField(self, MONTH);
     }
 
@@ -399,7 +399,7 @@
      * @return UTC month
      */
     @Function(attributes = Attribute.NOT_ENUMERABLE)
-    public static Object getUTCMonth(final Object self) {
+    public static double getUTCMonth(final Object self) {
         return getUTCField(self, MONTH);
     }
 
@@ -410,7 +410,7 @@
      * @return date
      */
     @Function(attributes = Attribute.NOT_ENUMERABLE)
-    public static Object getDate(final Object self) {
+    public static double getDate(final Object self) {
         return getField(self, DAY);
     }
 
@@ -421,7 +421,7 @@
      * @return UTC Date
      */
     @Function(attributes = Attribute.NOT_ENUMERABLE)
-    public static Object getUTCDate(final Object self) {
+    public static double getUTCDate(final Object self) {
         return getUTCField(self, DAY);
     }
 
@@ -432,7 +432,7 @@
      * @return day
      */
     @Function(attributes = Attribute.NOT_ENUMERABLE)
-    public static Object getDay(final Object self) {
+    public static double getDay(final Object self) {
         final NativeDate nd = getNativeDate(self);
         return (nd != null && nd.isValidDate()) ? weekDay(nd.getLocalTime()) : Double.NaN;
     }
@@ -444,7 +444,7 @@
      * @return UTC day
      */
     @Function(attributes = Attribute.NOT_ENUMERABLE)
-    public static Object getUTCDay(final Object self) {
+    public static double getUTCDay(final Object self) {
         final NativeDate nd = getNativeDate(self);
         return (nd != null && nd.isValidDate()) ? weekDay(nd.getTime()) : Double.NaN;
     }
@@ -456,7 +456,7 @@
      * @return hours
      */
     @Function(attributes = Attribute.NOT_ENUMERABLE)
-    public static Object getHours(final Object self) {
+    public static double getHours(final Object self) {
         return getField(self, HOUR);
     }
 
@@ -467,7 +467,7 @@
      * @return UTC hours
      */
     @Function(attributes = Attribute.NOT_ENUMERABLE)
-    public static Object getUTCHours(final Object self) {
+    public static double getUTCHours(final Object self) {
         return getUTCField(self, HOUR);
     }
 
@@ -478,7 +478,7 @@
      * @return minutes
      */
     @Function(attributes = Attribute.NOT_ENUMERABLE)
-    public static Object getMinutes(final Object self) {
+    public static double getMinutes(final Object self) {
         return getField(self, MINUTE);
     }
 
@@ -489,7 +489,7 @@
      * @return UTC minutes
      */
     @Function(attributes = Attribute.NOT_ENUMERABLE)
-    public static Object getUTCMinutes(final Object self) {
+    public static double getUTCMinutes(final Object self) {
         return getUTCField(self, MINUTE);
     }
 
@@ -500,7 +500,7 @@
      * @return seconds
      */
     @Function(attributes = Attribute.NOT_ENUMERABLE)
-    public static Object getSeconds(final Object self) {
+    public static double getSeconds(final Object self) {
         return getField(self, SECOND);
     }
 
@@ -511,7 +511,7 @@
      * @return UTC seconds
      */
     @Function(attributes = Attribute.NOT_ENUMERABLE)
-    public static Object getUTCSeconds(final Object self) {
+    public static double getUTCSeconds(final Object self) {
         return getUTCField(self, SECOND);
     }
 
@@ -522,7 +522,7 @@
      * @return milliseconds
      */
     @Function(attributes = Attribute.NOT_ENUMERABLE)
-    public static Object getMilliseconds(final Object self) {
+    public static double getMilliseconds(final Object self) {
         return getField(self, MILLISECOND);
     }
 
@@ -533,7 +533,7 @@
      * @return UTC milliseconds
      */
     @Function(attributes = Attribute.NOT_ENUMERABLE)
-    public static Object getUTCMilliseconds(final Object self) {
+    public static double getUTCMilliseconds(final Object self) {
         return getUTCField(self, MILLISECOND);
     }
 
@@ -544,7 +544,7 @@
      * @return time zone offset or NaN if N/A
      */
     @Function(attributes = Attribute.NOT_ENUMERABLE)
-    public static Object getTimezoneOffset(final Object self) {
+    public static double getTimezoneOffset(final Object self) {
         final NativeDate nd = getNativeDate(self);
         if (nd != null && nd.isValidDate()) {
             final long msec = (long) nd.getTime();
@@ -561,7 +561,7 @@
      * @return time
      */
     @Function(attributes = Attribute.NOT_ENUMERABLE)
-    public static Object setTime(final Object self, final Object time) {
+    public static double setTime(final Object self, final Object time) {
         final NativeDate nd  = getNativeDate(self);
         final double     num = timeClip(JSType.toNumber(time));
         nd.setTime(num);
@@ -576,7 +576,7 @@
      * @return time
      */
     @Function(attributes = Attribute.NOT_ENUMERABLE, arity = 1)
-    public static Object setMilliseconds(final Object self, final Object... args) {
+    public static double setMilliseconds(final Object self, final Object... args) {
         final NativeDate nd = getNativeDate(self);
         setFields(nd, MILLISECOND, args, true);
         return nd.getTime();
@@ -590,7 +590,7 @@
      * @return time
      */
     @Function(attributes = Attribute.NOT_ENUMERABLE, arity = 1)
-    public static Object setUTCMilliseconds(final Object self, final Object... args) {
+    public static double setUTCMilliseconds(final Object self, final Object... args) {
         final NativeDate nd = getNativeDate(self);
         setFields(nd, MILLISECOND, args, false);
         return nd.getTime();
@@ -604,7 +604,7 @@
      * @return time
      */
     @Function(attributes = Attribute.NOT_ENUMERABLE, arity = 2)
-    public static Object setSeconds(final Object self, final Object... args) {
+    public static double setSeconds(final Object self, final Object... args) {
         final NativeDate nd = getNativeDate(self);
         setFields(nd, SECOND, args, true);
         return nd.getTime();
@@ -618,7 +618,7 @@
      * @return time
      */
     @Function(attributes = Attribute.NOT_ENUMERABLE, arity = 2)
-    public static Object setUTCSeconds(final Object self, final Object... args) {
+    public static double setUTCSeconds(final Object self, final Object... args) {
         final NativeDate nd = getNativeDate(self);
         setFields(nd, SECOND, args, false);
         return nd.getTime();
@@ -632,7 +632,7 @@
      * @return time
      */
     @Function(attributes = Attribute.NOT_ENUMERABLE, arity = 3)
-    public static Object setMinutes(final Object self, final Object... args) {
+    public static double setMinutes(final Object self, final Object... args) {
         final NativeDate nd = getNativeDate(self);
         setFields(nd, MINUTE, args, true);
         return nd.getTime();
@@ -646,7 +646,7 @@
      * @return time
      */
     @Function(attributes = Attribute.NOT_ENUMERABLE, arity = 3)
-    public static Object setUTCMinutes(final Object self, final Object... args) {
+    public static double setUTCMinutes(final Object self, final Object... args) {
         final NativeDate nd = getNativeDate(self);
         setFields(nd, MINUTE, args, false);
         return nd.getTime();
@@ -660,7 +660,7 @@
      * @return time
      */
     @Function(attributes = Attribute.NOT_ENUMERABLE, arity = 4)
-    public static Object setHours(final Object self, final Object... args) {
+    public static double setHours(final Object self, final Object... args) {
         final NativeDate nd = getNativeDate(self);
         setFields(nd, HOUR, args, true);
         return nd.getTime();
@@ -674,7 +674,7 @@
      * @return time
      */
     @Function(attributes = Attribute.NOT_ENUMERABLE, arity = 4)
-    public static Object setUTCHours(final Object self, final Object... args) {
+    public static double setUTCHours(final Object self, final Object... args) {
         final NativeDate nd = getNativeDate(self);
         setFields(nd, HOUR, args, false);
         return nd.getTime();
@@ -688,7 +688,7 @@
      * @return time
      */
     @Function(attributes = Attribute.NOT_ENUMERABLE, arity = 1)
-    public static Object setDate(final Object self, final Object... args) {
+    public static double setDate(final Object self, final Object... args) {
         final NativeDate nd = getNativeDate(self);
         setFields(nd, DAY, args, true);
         return nd.getTime();
@@ -702,7 +702,7 @@
      * @return time
      */
     @Function(attributes = Attribute.NOT_ENUMERABLE, arity = 1)
-    public static Object setUTCDate(final Object self, final Object... args) {
+    public static double setUTCDate(final Object self, final Object... args) {
         final NativeDate nd = getNativeDate(self);
         setFields(nd, DAY, args, false);
         return nd.getTime();
@@ -716,7 +716,7 @@
      * @return time
      */
     @Function(attributes = Attribute.NOT_ENUMERABLE, arity = 2)
-    public static Object setMonth(final Object self, final Object... args) {
+    public static double setMonth(final Object self, final Object... args) {
         final NativeDate nd = getNativeDate(self);
         setFields(nd, MONTH, args, true);
         return nd.getTime();
@@ -730,7 +730,7 @@
      * @return time
      */
     @Function(attributes = Attribute.NOT_ENUMERABLE, arity = 2)
-    public static Object setUTCMonth(final Object self, final Object... args) {
+    public static double setUTCMonth(final Object self, final Object... args) {
         final NativeDate nd = ensureNativeDate(self);
         setFields(nd, MONTH, args, false);
         return nd.getTime();
@@ -744,7 +744,7 @@
      * @return time
      */
     @Function(attributes = Attribute.NOT_ENUMERABLE, arity = 3)
-    public static Object setFullYear(final Object self, final Object... args) {
+    public static double setFullYear(final Object self, final Object... args) {
         final NativeDate nd   = ensureNativeDate(self);
         if (nd.isValidDate()) {
             setFields(nd, YEAR, args, true);
@@ -767,7 +767,7 @@
      * @return time
      */
     @Function(attributes = Attribute.NOT_ENUMERABLE, arity = 3)
-    public static Object setUTCFullYear(final Object self, final Object... args) {
+    public static double setUTCFullYear(final Object self, final Object... args) {
         final NativeDate nd   = ensureNativeDate(self);
         if (nd.isValidDate()) {
             setFields(nd, YEAR, args, false);
@@ -786,7 +786,7 @@
      * @return NativeDate
      */
     @Function(attributes = Attribute.NOT_ENUMERABLE)
-    public static Object setYear(final Object self, final Object year) {
+    public static double setYear(final Object self, final Object year) {
         final NativeDate nd = getNativeDate(self);
         if (isNaN(nd.getTime())) {
             nd.setTime(utc(0, nd.getTimeZone()));
@@ -813,7 +813,7 @@
      * @return string representation of date
      */
     @Function(attributes = Attribute.NOT_ENUMERABLE)
-    public static Object toUTCString(final Object self) {
+    public static String toUTCString(final Object self) {
         return toGMTStringImpl(self);
     }
 
@@ -826,7 +826,7 @@
      * @return string representation of date
      */
     @Function(attributes = Attribute.NOT_ENUMERABLE)
-    public static Object toGMTString(final Object self) {
+    public static String toGMTString(final Object self) {
         return toGMTStringImpl(self);
     }
 
@@ -837,7 +837,7 @@
      * @return string representation of date
      */
     @Function(attributes = Attribute.NOT_ENUMERABLE)
-    public static Object toISOString(final Object self) {
+    public static String toISOString(final Object self) {
         return toISOStringImpl(self);
     }
 
@@ -1282,14 +1282,14 @@
         }
     }
 
-    private static Object getField(final Object self, final int field) {
+    private static double getField(final Object self, final int field) {
         final NativeDate nd = getNativeDate(self);
-        return (nd != null && nd.isValidDate()) ? valueFromTime(field, nd.getLocalTime()) : Double.NaN;
+        return (nd != null && nd.isValidDate()) ? (double)valueFromTime(field, nd.getLocalTime()) : Double.NaN;
     }
 
-    private static Object getUTCField(final Object self, final int field) {
+    private static double getUTCField(final Object self, final int field) {
         final NativeDate nd = getNativeDate(self);
-        return (nd != null && nd.isValidDate()) ? valueFromTime(field, nd.getTime()) : Double.NaN;
+        return (nd != null && nd.isValidDate()) ? (double)valueFromTime(field, nd.getTime()) : Double.NaN;
     }
 
     private static void setFields(final NativeDate nd, final int fieldId, final Object[] args, final boolean local) {
@@ -1344,5 +1344,4 @@
     private TimeZone getTimeZone() {
         return timezone;
     }
-
 }
--- a/nashorn/src/jdk/nashorn/internal/objects/NativeDebug.java	Wed Apr 02 22:00:15 2014 -0700
+++ b/nashorn/src/jdk/nashorn/internal/objects/NativeDebug.java	Wed Apr 09 09:20:03 2014 -0700
@@ -116,7 +116,7 @@
      * @return true if reference identity
      */
     @Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR)
-    public static Object identical(final Object self, final Object obj1, final Object obj2) {
+    public static boolean identical(final Object self, final Object obj1, final Object obj2) {
         return obj1 == obj2;
     }
 
@@ -144,7 +144,7 @@
      * @return return {@link Object#equals(Object)} for objects.
      */
     @Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR)
-    public static Object equals(final Object self, final Object obj1, final Object obj2) {
+    public static boolean equals(final Object self, final Object obj1, final Object obj2) {
         return Objects.equals(obj1, obj2);
     }
 
@@ -156,7 +156,7 @@
      * @return Java string representation of {@code obj}
      */
     @Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR)
-    public static Object toJavaString(final Object self, final Object obj) {
+    public static String toJavaString(final Object self, final Object obj) {
         return Objects.toString(obj);
     }
 
@@ -168,7 +168,7 @@
      * @return string representation
      */
     @Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR)
-    public static Object toIdentString(final Object self, final Object obj) {
+    public static String toIdentString(final Object self, final Object obj) {
         if (obj == null) {
             return "null";
         }
@@ -185,7 +185,7 @@
      * @return listener count
      */
     @Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR)
-    public static Object getListenerCount(final Object self, final Object obj) {
+    public static int getListenerCount(final Object self, final Object obj) {
         return (obj instanceof ScriptObject) ? PropertyListeners.getListenerCount((ScriptObject) obj) : 0;
     }
 
--- a/nashorn/src/jdk/nashorn/internal/objects/NativeError.java	Wed Apr 02 22:00:15 2014 -0700
+++ b/nashorn/src/jdk/nashorn/internal/objects/NativeError.java	Wed Apr 09 09:20:03 2014 -0700
@@ -126,7 +126,7 @@
      * @return NativeError instance
      */
     @Constructor
-    public static Object constructor(final boolean newObj, final Object self, final Object msg) {
+    public static NativeError constructor(final boolean newObj, final Object self, final Object msg) {
         return new NativeError(msg);
     }
 
--- a/nashorn/src/jdk/nashorn/internal/objects/NativeEvalError.java	Wed Apr 02 22:00:15 2014 -0700
+++ b/nashorn/src/jdk/nashorn/internal/objects/NativeEvalError.java	Wed Apr 09 09:20:03 2014 -0700
@@ -98,7 +98,7 @@
      * @return new EvalError
      */
     @Constructor(name = "EvalError")
-    public static Object constructor(final boolean newObj, final Object self, final Object msg) {
+    public static NativeEvalError constructor(final boolean newObj, final Object self, final Object msg) {
         return new NativeEvalError(msg);
     }
 }
--- a/nashorn/src/jdk/nashorn/internal/objects/NativeFloat32Array.java	Wed Apr 02 22:00:15 2014 -0700
+++ b/nashorn/src/jdk/nashorn/internal/objects/NativeFloat32Array.java	Wed Apr 09 09:20:03 2014 -0700
@@ -136,8 +136,8 @@
      * @return new typed array
      */
     @Constructor(arity = 1)
-    public static Object constructor(final boolean newObj, final Object self, final Object... args) {
-        return constructorImpl(args, FACTORY);
+    public static NativeFloat32Array constructor(final boolean newObj, final Object self, final Object... args) {
+        return (NativeFloat32Array)constructorImpl(args, FACTORY);
     }
 
     NativeFloat32Array(final NativeArrayBuffer buffer, final int byteOffset, final int length) {
@@ -192,8 +192,8 @@
      * @return sub array
      */
     @Function(attributes = Attribute.NOT_ENUMERABLE)
-    protected static Object subarray(final Object self, final Object begin, final Object end) {
-        return ArrayBufferView.subarrayImpl(self, begin, end);
+    protected static NativeFloat32Array subarray(final Object self, final Object begin, final Object end) {
+        return (NativeFloat32Array)ArrayBufferView.subarrayImpl(self, begin, end);
     }
 
     @Override
--- a/nashorn/src/jdk/nashorn/internal/objects/NativeFloat64Array.java	Wed Apr 02 22:00:15 2014 -0700
+++ b/nashorn/src/jdk/nashorn/internal/objects/NativeFloat64Array.java	Wed Apr 09 09:20:03 2014 -0700
@@ -146,8 +146,8 @@
      * @return new typed array
      */
     @Constructor(arity = 1)
-    public static Object constructor(final boolean newObj, final Object self, final Object... args) {
-        return constructorImpl(args, FACTORY);
+    public static NativeFloat64Array constructor(final boolean newObj, final Object self, final Object... args) {
+        return (NativeFloat64Array)constructorImpl(args, FACTORY);
     }
 
     NativeFloat64Array(final NativeArrayBuffer buffer, final int byteOffset, final int length) {
@@ -202,8 +202,8 @@
      * @return sub array
      */
     @Function(attributes = Attribute.NOT_ENUMERABLE)
-    protected static Object subarray(final Object self, final Object begin, final Object end) {
-        return ArrayBufferView.subarrayImpl(self, begin, end);
+    protected static NativeFloat64Array subarray(final Object self, final Object begin, final Object end) {
+        return (NativeFloat64Array)ArrayBufferView.subarrayImpl(self, begin, end);
     }
 
     @Override
--- a/nashorn/src/jdk/nashorn/internal/objects/NativeFunction.java	Wed Apr 02 22:00:15 2014 -0700
+++ b/nashorn/src/jdk/nashorn/internal/objects/NativeFunction.java	Wed Apr 09 09:20:03 2014 -0700
@@ -71,7 +71,7 @@
      * @return string representation of Function
      */
     @Function(attributes = Attribute.NOT_ENUMERABLE)
-    public static Object toString(final Object self) {
+    public static String toString(final Object self) {
         if (!(self instanceof ScriptFunction)) {
             throw typeError("not.a.function", ScriptRuntime.safeToString(self));
         }
@@ -174,7 +174,7 @@
      * @return function with bound arguments
      */
     @Function(attributes = Attribute.NOT_ENUMERABLE, arity = 1)
-    public static Object bind(final Object self, final Object... args) {
+    public static ScriptFunction bind(final Object self, final Object... args) {
         if (!(self instanceof ScriptFunction)) {
             throw typeError("not.a.function", ScriptRuntime.safeToString(self));
         }
@@ -199,7 +199,7 @@
      * @return source for function
      */
     @Function(attributes = Attribute.NOT_ENUMERABLE)
-    public static Object toSource(final Object self) {
+    public static String toSource(final Object self) {
         if (!(self instanceof ScriptFunction)) {
             throw typeError("not.a.function", ScriptRuntime.safeToString(self));
         }
@@ -217,7 +217,7 @@
      * @return new NativeFunction
      */
     @Constructor(arity = 1)
-    public static Object function(final boolean newObj, final Object self, final Object... args) {
+    public static ScriptFunction function(final boolean newObj, final Object self, final Object... args) {
         final StringBuilder sb = new StringBuilder();
 
         sb.append("(function (");
@@ -253,7 +253,7 @@
 
         final Global global = Global.instance();
 
-        return Global.directEval(global, sb.toString(), global, "<function>", global.isStrictContext());
+        return (ScriptFunction)Global.directEval(global, sb.toString(), global, "<function>", global.isStrictContext());
     }
 
     private static void checkFunctionParameters(final String params) {
--- a/nashorn/src/jdk/nashorn/internal/objects/NativeInt16Array.java	Wed Apr 02 22:00:15 2014 -0700
+++ b/nashorn/src/jdk/nashorn/internal/objects/NativeInt16Array.java	Wed Apr 09 09:20:03 2014 -0700
@@ -100,8 +100,8 @@
      * @return new typed array
      */
     @Constructor(arity = 1)
-    public static Object constructor(final boolean newObj, final Object self, final Object... args) {
-        return constructorImpl(args, FACTORY);
+    public static NativeInt16Array constructor(final boolean newObj, final Object self, final Object... args) {
+        return (NativeInt16Array)constructorImpl(args, FACTORY);
     }
 
     NativeInt16Array(final NativeArrayBuffer buffer, final int byteOffset, final int byteLength) {
@@ -151,8 +151,8 @@
      * @return sub array
      */
     @Function(attributes = Attribute.NOT_ENUMERABLE)
-    protected static Object subarray(final Object self, final Object begin, final Object end) {
-        return ArrayBufferView.subarrayImpl(self, begin, end);
+    protected static NativeInt16Array subarray(final Object self, final Object begin, final Object end) {
+        return (NativeInt16Array)ArrayBufferView.subarrayImpl(self, begin, end);
     }
 
     @Override
--- a/nashorn/src/jdk/nashorn/internal/objects/NativeInt32Array.java	Wed Apr 02 22:00:15 2014 -0700
+++ b/nashorn/src/jdk/nashorn/internal/objects/NativeInt32Array.java	Wed Apr 09 09:20:03 2014 -0700
@@ -103,8 +103,8 @@
      * @return new typed array
      */
     @Constructor(arity = 1)
-    public static Object constructor(final boolean newObj, final Object self, final Object... args) {
-        return constructorImpl(args, FACTORY);
+    public static NativeInt32Array constructor(final boolean newObj, final Object self, final Object... args) {
+        return (NativeInt32Array)constructorImpl(args, FACTORY);
     }
 
     NativeInt32Array(final NativeArrayBuffer buffer, final int byteOffset, final int length) {
@@ -154,8 +154,8 @@
      * @return sub array
      */
     @Function(attributes = Attribute.NOT_ENUMERABLE)
-    protected static Object subarray(final Object self, final Object begin, final Object end) {
-        return ArrayBufferView.subarrayImpl(self, begin, end);
+    protected static NativeInt32Array subarray(final Object self, final Object begin, final Object end) {
+        return (NativeInt32Array)ArrayBufferView.subarrayImpl(self, begin, end);
     }
 
     @Override
--- a/nashorn/src/jdk/nashorn/internal/objects/NativeInt8Array.java	Wed Apr 02 22:00:15 2014 -0700
+++ b/nashorn/src/jdk/nashorn/internal/objects/NativeInt8Array.java	Wed Apr 09 09:20:03 2014 -0700
@@ -93,8 +93,8 @@
      * @return new typed array
      */
     @Constructor(arity = 1)
-    public static Object constructor(final boolean newObj, final Object self, final Object... args) {
-        return constructorImpl(args, FACTORY);
+    public static NativeInt8Array constructor(final boolean newObj, final Object self, final Object... args) {
+        return (NativeInt8Array)constructorImpl(args, FACTORY);
     }
 
     NativeInt8Array(final NativeArrayBuffer buffer, final int byteOffset, final int length) {
@@ -144,8 +144,8 @@
      * @return sub array
      */
     @Function(attributes = Attribute.NOT_ENUMERABLE)
-    protected static Object subarray(final Object self, final Object begin, final Object end) {
-        return ArrayBufferView.subarrayImpl(self, begin, end);
+    protected static NativeInt8Array subarray(final Object self, final Object begin, final Object end) {
+        return (NativeInt8Array)ArrayBufferView.subarrayImpl(self, begin, end);
     }
 
     @Override
--- a/nashorn/src/jdk/nashorn/internal/objects/NativeJSAdapter.java	Wed Apr 02 22:00:15 2014 -0700
+++ b/nashorn/src/jdk/nashorn/internal/objects/NativeJSAdapter.java	Wed Apr 09 09:20:03 2014 -0700
@@ -536,7 +536,7 @@
      * @return new NativeJSAdapter
      */
     @Constructor
-    public static Object construct(final boolean isNew, final Object self, final Object... args) {
+    public static NativeJSAdapter construct(final boolean isNew, final Object self, final Object... args) {
         Object proto     = UNDEFINED;
         Object overrides = UNDEFINED;
         Object adaptee;
--- a/nashorn/src/jdk/nashorn/internal/objects/NativeJava.java	Wed Apr 02 22:00:15 2014 -0700
+++ b/nashorn/src/jdk/nashorn/internal/objects/NativeJava.java	Wed Apr 09 09:20:03 2014 -0700
@@ -75,7 +75,7 @@
      * @see #type(Object, Object)
      */
     @Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR)
-    public static Object isType(final Object self, final Object type) {
+    public static boolean isType(final Object self, final Object type) {
         return type instanceof StaticClass;
     }
 
@@ -338,7 +338,7 @@
      * null.
      */
     @Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR)
-    public static Object from(final Object self, final Object objArray) {
+    public static NativeArray from(final Object self, final Object objArray) {
         if (objArray == null) {
             return null;
         } else if (objArray instanceof Collection) {
--- a/nashorn/src/jdk/nashorn/internal/objects/NativeJavaImporter.java	Wed Apr 02 22:00:15 2014 -0700
+++ b/nashorn/src/jdk/nashorn/internal/objects/NativeJavaImporter.java	Wed Apr 09 09:20:03 2014 -0700
@@ -86,7 +86,7 @@
      * @return NativeJavaImporter instance
      */
     @Constructor(arity = 1)
-    public static Object constructor(final boolean isNew, final Object self, final Object... args) {
+    public static NativeJavaImporter constructor(final boolean isNew, final Object self, final Object... args) {
         return new NativeJavaImporter(args);
     }
 
--- a/nashorn/src/jdk/nashorn/internal/objects/NativeNumber.java	Wed Apr 02 22:00:15 2014 -0700
+++ b/nashorn/src/jdk/nashorn/internal/objects/NativeNumber.java	Wed Apr 09 09:20:03 2014 -0700
@@ -185,7 +185,7 @@
      * @return number in decimal fixed point notation
      */
     @Function(attributes = Attribute.NOT_ENUMERABLE)
-    public static Object toFixed(final Object self, final Object fractionDigits) {
+    public static String toFixed(final Object self, final Object fractionDigits) {
         final int f = JSType.toInteger(fractionDigits);
         if (f < 0 || f > 20) {
             throw rangeError("invalid.fraction.digits", "toFixed");
@@ -217,7 +217,7 @@
      * @return number in decimal exponential notation
      */
     @Function(attributes = Attribute.NOT_ENUMERABLE)
-    public static Object toExponential(final Object self, final Object fractionDigits) {
+    public static String toExponential(final Object self, final Object fractionDigits) {
         final double  x         = getNumberValue(self);
         final boolean trimZeros = fractionDigits == UNDEFINED;
         final int     f         = trimZeros ? 16 : JSType.toInteger(fractionDigits);
@@ -245,7 +245,7 @@
      * @return number in decimal exponentiation notation or decimal fixed notation depending on {@code precision}
      */
     @Function(attributes = Attribute.NOT_ENUMERABLE)
-    public static Object toPrecision(final Object self, final Object precision) {
+    public static String toPrecision(final Object self, final Object precision) {
         final double x = getNumberValue(self);
         if (precision == UNDEFINED) {
             return JSType.toString(x);
@@ -278,7 +278,7 @@
      * @return string representation of this Number in the given radix
      */
     @Function(attributes = Attribute.NOT_ENUMERABLE)
-    public static Object toString(final Object self, final Object radix) {
+    public static String toString(final Object self, final Object radix) {
         if (radix != UNDEFINED) {
             final int intRadix = JSType.toInteger(radix);
             if (intRadix != 10) {
@@ -299,7 +299,7 @@
      * @return localized string for this Number
      */
     @Function(attributes = Attribute.NOT_ENUMERABLE)
-    public static Object toLocaleString(final Object self) {
+    public static String toLocaleString(final Object self) {
         return JSType.toString(getNumberValue(self));
     }
 
@@ -308,10 +308,10 @@
      * ECMA 15.7.4.4 Number.prototype.valueOf ( )
      *
      * @param self self reference
-     * @return boxed number value for this Number
+     * @return number value for this Number
      */
     @Function(attributes = Attribute.NOT_ENUMERABLE)
-    public static Object valueOf(final Object self) {
+    public static double valueOf(final Object self) {
         return getNumberValue(self);
     }
 
--- a/nashorn/src/jdk/nashorn/internal/objects/NativeObject.java	Wed Apr 02 22:00:15 2014 -0700
+++ b/nashorn/src/jdk/nashorn/internal/objects/NativeObject.java	Wed Apr 09 09:20:03 2014 -0700
@@ -111,7 +111,7 @@
      * @return the 'obj' object
      */
     @Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR)
-    public static Object setIndexedPropertiesToExternalArrayData(final Object self, final Object obj, final Object buf) {
+    public static ScriptObject setIndexedPropertiesToExternalArrayData(final Object self, final Object obj, final Object buf) {
         Global.checkObject(obj);
         final ScriptObject sobj = (ScriptObject)obj;
         if (buf instanceof ByteBuffer) {
@@ -203,7 +203,7 @@
      * @return array of property names
      */
     @Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR)
-    public static Object getOwnPropertyNames(final Object self, final Object obj) {
+    public static ScriptObject getOwnPropertyNames(final Object self, final Object obj) {
         if (obj instanceof ScriptObject) {
             return new NativeArray(((ScriptObject)obj).getOwnKeys(true));
         } else if (obj instanceof ScriptObjectMirror) {
@@ -222,7 +222,7 @@
      * @return object created
      */
     @Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR)
-    public static Object create(final Object self, final Object proto, final Object props) {
+    public static ScriptObject create(final Object self, final Object proto, final Object props) {
         if (proto != null) {
             Global.checkObject(proto);
         }
@@ -248,10 +248,11 @@
      * @return object
      */
     @Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR)
-    public static Object defineProperty(final Object self, final Object obj, final Object prop, final Object attr) {
+    public static ScriptObject defineProperty(final Object self, final Object obj, final Object prop, final Object attr) {
         Global.checkObject(obj);
-        ((ScriptObject)obj).defineOwnProperty(JSType.toString(prop), attr, true);
-        return obj;
+        final ScriptObject sobj = (ScriptObject)obj;
+        sobj.defineOwnProperty(JSType.toString(prop), attr, true);
+        return sobj;
     }
 
     /**
@@ -263,7 +264,7 @@
      * @return object
      */
     @Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR)
-    public static Object defineProperties(final Object self, final Object obj, final Object props) {
+    public static ScriptObject defineProperties(final Object self, final Object obj, final Object props) {
         Global.checkObject(obj);
 
         final ScriptObject sobj     = (ScriptObject)obj;
@@ -342,7 +343,7 @@
      * @return true if sealed, false otherwise
      */
     @Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR)
-    public static Object isSealed(final Object self, final Object obj) {
+    public static boolean isSealed(final Object self, final Object obj) {
         if (obj instanceof ScriptObject) {
             return ((ScriptObject)obj).isSealed();
         } else if (obj instanceof ScriptObjectMirror) {
@@ -360,7 +361,7 @@
      * @return true if object is frozen, false otherwise
      */
     @Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR)
-    public static Object isFrozen(final Object self, final Object obj) {
+    public static boolean isFrozen(final Object self, final Object obj) {
         if (obj instanceof ScriptObject) {
             return ((ScriptObject)obj).isFrozen();
         } else if (obj instanceof ScriptObjectMirror) {
@@ -378,7 +379,7 @@
      * @return true if object is extensible, false otherwise
      */
     @Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR)
-    public static Object isExtensible(final Object self, final Object obj) {
+    public static boolean isExtensible(final Object self, final Object obj) {
         if (obj instanceof ScriptObject) {
             return ((ScriptObject)obj).isExtensible();
         } else if (obj instanceof ScriptObjectMirror) {
@@ -396,7 +397,7 @@
      * @return array of keys in object
      */
     @Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR)
-    public static Object keys(final Object self, final Object obj) {
+    public static ScriptObject keys(final Object self, final Object obj) {
         if (obj instanceof ScriptObject) {
             final ScriptObject sobj = (ScriptObject)obj;
             return new NativeArray(sobj.getOwnKeys(false));
@@ -453,7 +454,7 @@
      * @return ToString of object
      */
     @Function(attributes = Attribute.NOT_ENUMERABLE)
-    public static Object toString(final Object self) {
+    public static String toString(final Object self) {
         return ScriptRuntime.builtinObjectToString(self);
     }
 
@@ -506,7 +507,7 @@
      * @return true if property exists in object
      */
     @Function(attributes = Attribute.NOT_ENUMERABLE)
-    public static Object hasOwnProperty(final Object self, final Object v) {
+    public static boolean hasOwnProperty(final Object self, final Object v) {
         // Convert ScriptObjects to primitive with String.class hint
         // but no need to convert other primitives to string.
         final Object key = JSType.toPrimitive(v, String.class);
@@ -523,7 +524,7 @@
      * @return true if object is prototype of v
      */
     @Function(attributes = Attribute.NOT_ENUMERABLE)
-    public static Object isPrototypeOf(final Object self, final Object v) {
+    public static boolean isPrototypeOf(final Object self, final Object v) {
         if (!(v instanceof ScriptObject)) {
             return false;
         }
@@ -549,7 +550,7 @@
      * @return true if property is enumerable
      */
     @Function(attributes = Attribute.NOT_ENUMERABLE)
-    public static Object propertyIsEnumerable(final Object self, final Object v) {
+    public static boolean propertyIsEnumerable(final Object self, final Object v) {
         final String str = JSType.toString(v);
         final Object obj = Global.toObject(self);
 
--- a/nashorn/src/jdk/nashorn/internal/objects/NativeRangeError.java	Wed Apr 02 22:00:15 2014 -0700
+++ b/nashorn/src/jdk/nashorn/internal/objects/NativeRangeError.java	Wed Apr 09 09:20:03 2014 -0700
@@ -98,7 +98,7 @@
      * @return new RangeError
      */
     @Constructor(name = "RangeError")
-    public static Object constructor(final boolean newObj, final Object self, final Object msg) {
+    public static NativeRangeError constructor(final boolean newObj, final Object self, final Object msg) {
         return new NativeRangeError(msg);
     }
 }
--- a/nashorn/src/jdk/nashorn/internal/objects/NativeReferenceError.java	Wed Apr 02 22:00:15 2014 -0700
+++ b/nashorn/src/jdk/nashorn/internal/objects/NativeReferenceError.java	Wed Apr 09 09:20:03 2014 -0700
@@ -98,7 +98,7 @@
      * @return new ReferenceError
      */
     @Constructor(name = "ReferenceError")
-    public static Object constructor(final boolean newObj, final Object self, final Object msg) {
+    public static NativeReferenceError constructor(final boolean newObj, final Object self, final Object msg) {
         return new NativeReferenceError(msg);
     }
 }
--- a/nashorn/src/jdk/nashorn/internal/objects/NativeRegExp.java	Wed Apr 02 22:00:15 2014 -0700
+++ b/nashorn/src/jdk/nashorn/internal/objects/NativeRegExp.java	Wed Apr 09 09:20:03 2014 -0700
@@ -122,7 +122,7 @@
      * @return new NativeRegExp
      */
     @Constructor(arity = 2)
-    public static Object constructor(final boolean isNew, final Object self, final Object... args) {
+    public static NativeRegExp constructor(final boolean isNew, final Object self, final Object... args) {
         if (args.length > 1) {
             return newRegExp(args[0], args[1]);
         } else if (args.length > 0) {
@@ -142,7 +142,7 @@
      * @return new NativeRegExp
      */
     @SpecializedConstructor
-    public static Object constructor(final boolean isNew, final Object self) {
+    public static NativeRegExp constructor(final boolean isNew, final Object self) {
         return new NativeRegExp("", "");
     }
 
@@ -157,7 +157,7 @@
      * @return new NativeRegExp
      */
     @SpecializedConstructor
-    public static Object constructor(final boolean isNew, final Object self, final Object pattern) {
+    public static NativeRegExp constructor(final boolean isNew, final Object self, final Object pattern) {
         return newRegExp(pattern, UNDEFINED);
     }
 
@@ -173,7 +173,7 @@
      * @return new NativeRegExp
      */
     @SpecializedConstructor
-    public static Object constructor(final boolean isNew, final Object self, final Object pattern, final Object flags) {
+    public static NativeRegExp constructor(final boolean isNew, final Object self, final Object pattern, final Object flags) {
         return newRegExp(pattern, flags);
     }
 
@@ -283,7 +283,7 @@
      * @return new NativeRegExp
      */
     @Function(attributes = Attribute.NOT_ENUMERABLE)
-    public static Object compile(final Object self, final Object pattern, final Object flags) {
+    public static ScriptObject compile(final Object self, final Object pattern, final Object flags) {
         final NativeRegExp regExp   = checkRegExp(self);
         final NativeRegExp compiled = newRegExp(pattern, flags);
         // copy over regexp to 'self'
@@ -302,7 +302,7 @@
      * @return array containing the matches or {@code null} if no match
      */
     @Function(attributes = Attribute.NOT_ENUMERABLE)
-    public static Object exec(final Object self, final Object string) {
+    public static ScriptObject exec(final Object self, final Object string) {
         return checkRegExp(self).exec(JSType.toString(string));
     }
 
@@ -314,7 +314,7 @@
      * @return true if matches found, false otherwise
      */
     @Function(attributes = Attribute.NOT_ENUMERABLE)
-    public static Object test(final Object self, final Object string) {
+    public static boolean test(final Object self, final Object string) {
         return checkRegExp(self).test(JSType.toString(string));
     }
 
@@ -325,7 +325,7 @@
      * @return string version of regexp
      */
     @Function(attributes = Attribute.NOT_ENUMERABLE)
-    public static Object toString(final Object self) {
+    public static String toString(final Object self) {
         return checkRegExp(self).toString();
     }
 
@@ -618,7 +618,7 @@
      * @param string String to match.
      * @return NativeArray of matches, string or null.
      */
-    public Object exec(final String string) {
+    public NativeRegExpExecResult exec(final String string) {
         final RegExpResult match = execInner(string);
 
         if (match == null) {
@@ -635,7 +635,7 @@
      * @param string String to match.
      * @return True if a match is found.
      */
-    public Object test(final String string) {
+    public boolean test(final String string) {
         return execInner(string) != null;
     }
 
@@ -649,7 +649,7 @@
      * @param replacement Replacement string.
      * @return String with substitutions.
      */
-    Object replace(final String string, final String replacement, final ScriptFunction function) {
+    String replace(final String string, final String replacement, final ScriptFunction function) {
         final RegExpMatcher matcher = regexp.match(string);
 
         if (matcher == null) {
@@ -804,7 +804,7 @@
      * @param limit  Split limit.
      * @return Array of substrings.
      */
-    Object split(final String string, final long limit) {
+    NativeArray split(final String string, final long limit) {
         if (limit == 0L) {
             return new NativeArray();
         }
@@ -867,7 +867,7 @@
      * @param string String to match.
      * @return Index of match.
      */
-    Object search(final String string) {
+    int search(final String string) {
         final RegExpResult match = execInner(string);
 
         if (match == null) {
--- a/nashorn/src/jdk/nashorn/internal/objects/NativeString.java	Wed Apr 02 22:00:15 2014 -0700
+++ b/nashorn/src/jdk/nashorn/internal/objects/NativeString.java	Wed Apr 09 09:20:03 2014 -0700
@@ -425,7 +425,7 @@
      * @return string with arguments translated to charcodes
      */
     @Function(attributes = Attribute.NOT_ENUMERABLE, arity = 1, where = Where.CONSTRUCTOR)
-    public static Object fromCharCode(final Object self, final Object... args) {
+    public static String fromCharCode(final Object self, final Object... args) {
         final char[] buf = new char[args.length];
         int index = 0;
         for (final Object arg : args) {
@@ -441,7 +441,7 @@
      * @return string with one charcode
      */
     @SpecializedFunction
-    public static Object fromCharCode(final Object self, final Object value) {
+    public static String fromCharCode(final Object self, final Object value) {
         try {
             return "" + (char)JSType.toUint16(((Number)value).doubleValue());
         } catch (final ClassCastException e) {
@@ -456,7 +456,7 @@
      * @return string with one charcode
      */
     @SpecializedFunction
-    public static Object fromCharCode(final Object self, final int value) {
+    public static String fromCharCode(final Object self, final int value) {
         return "" + (char)(value & 0xffff);
     }
 
@@ -467,7 +467,7 @@
      * @return string with one charcode
      */
     @SpecializedFunction
-    public static Object fromCharCode(final Object self, final long value) {
+    public static String fromCharCode(final Object self, final long value) {
         return "" + (char)((int)value & 0xffff);
     }
 
@@ -478,7 +478,7 @@
      * @return string with one charcode
      */
     @SpecializedFunction
-    public static Object fromCharCode(final Object self, final double value) {
+    public static String fromCharCode(final Object self, final double value) {
         return "" + (char)JSType.toUint16(value);
     }
 
@@ -488,7 +488,7 @@
      * @return self as string
      */
     @Function(attributes = Attribute.NOT_ENUMERABLE)
-    public static Object toString(final Object self) {
+    public static String toString(final Object self) {
         return getString(self);
     }
 
@@ -498,7 +498,7 @@
      * @return self as string
      */
     @Function(attributes = Attribute.NOT_ENUMERABLE)
-    public static Object valueOf(final Object self) {
+    public static String valueOf(final Object self) {
         return getString(self);
     }
 
@@ -509,7 +509,7 @@
      * @return string representing the char at the given position
      */
     @Function(attributes = Attribute.NOT_ENUMERABLE)
-    public static Object charAt(final Object self, final Object pos) {
+    public static String charAt(final Object self, final Object pos) {
         return charAtImpl(checkObjectToString(self), JSType.toInteger(pos));
     }
 
@@ -546,7 +546,7 @@
      * @return number representing charcode at position
      */
     @Function(attributes = Attribute.NOT_ENUMERABLE)
-    public static Object charCodeAt(final Object self, final Object pos) {
+    public static double charCodeAt(final Object self, final Object pos) {
         return charCodeAtImpl(checkObjectToString(self), JSType.toInteger(pos));
     }
 
@@ -601,7 +601,7 @@
      * @return position of first match or -1
      */
     @Function(attributes = Attribute.NOT_ENUMERABLE, arity = 1)
-    public static Object indexOf(final Object self, final Object search, final Object pos) {
+    public static int indexOf(final Object self, final Object search, final Object pos) {
         final String str = checkObjectToString(self);
         return str.indexOf(JSType.toString(search), JSType.toInteger(pos));
     }
@@ -649,7 +649,7 @@
      * @return last position of match or -1
      */
     @Function(attributes = Attribute.NOT_ENUMERABLE, arity = 1)
-    public static Object lastIndexOf(final Object self, final Object search, final Object pos) {
+    public static int lastIndexOf(final Object self, final Object search, final Object pos) {
 
         final String str       = checkObjectToString(self);
         final String searchStr = JSType.toString(search);
@@ -680,7 +680,7 @@
      * @return result of locale sensitive comparison operation between {@code self} and {@code that}
      */
     @Function(attributes = Attribute.NOT_ENUMERABLE)
-    public static Object localeCompare(final Object self, final Object that) {
+    public static double localeCompare(final Object self, final Object that) {
 
         final String   str      = checkObjectToString(self);
         final Collator collator = Collator.getInstance(Global.getEnv()._locale);
@@ -698,7 +698,7 @@
      * @return array of regexp matches
      */
     @Function(attributes = Attribute.NOT_ENUMERABLE)
-    public static Object match(final Object self, final Object regexp) {
+    public static ScriptObject match(final Object self, final Object regexp) {
 
         final String str = checkObjectToString(self);
 
@@ -745,7 +745,7 @@
      * @return string after replacement
      */
     @Function(attributes = Attribute.NOT_ENUMERABLE)
-    public static Object replace(final Object self, final Object string, final Object replacement) {
+    public static String replace(final Object self, final Object string, final Object replacement) {
 
         final String str = checkObjectToString(self);
 
@@ -771,7 +771,7 @@
      * @return offset where match occurred
      */
     @Function(attributes = Attribute.NOT_ENUMERABLE)
-    public static Object search(final Object self, final Object string) {
+    public static int search(final Object self, final Object string) {
 
         final String       str          = checkObjectToString(self);
         final NativeRegExp nativeRegExp = Global.toRegExp(string == UNDEFINED ? "" : string);
@@ -788,7 +788,7 @@
      * @return sliced out substring
      */
     @Function(attributes = Attribute.NOT_ENUMERABLE)
-    public static Object slice(final Object self, final Object start, final Object end) {
+    public static String slice(final Object self, final Object start, final Object end) {
 
         final String str      = checkObjectToString(self);
         if (end == UNDEFINED) {
@@ -805,7 +805,7 @@
      * @return sliced out substring
      */
     @SpecializedFunction
-    public static Object slice(final Object self, final int start) {
+    public static String slice(final Object self, final int start) {
         final String str = checkObjectToString(self);
         final int from = (start < 0) ? Math.max(str.length() + start, 0) : Math.min(start, str.length());
 
@@ -820,7 +820,7 @@
      * @return sliced out substring
      */
     @SpecializedFunction
-    public static Object slice(final Object self, final double start) {
+    public static String slice(final Object self, final double start) {
         return slice(self, (int)start);
     }
 
@@ -833,7 +833,7 @@
      * @return sliced out substring
      */
     @SpecializedFunction
-    public static Object slice(final Object self, final int start, final int end) {
+    public static String slice(final Object self, final int start, final int end) {
 
         final String str = checkObjectToString(self);
         final int len    = str.length();
@@ -853,7 +853,7 @@
      * @return sliced out substring
      */
     @SpecializedFunction
-    public static Object slice(final Object self, final double start, final double end) {
+    public static String slice(final Object self, final double start, final double end) {
         return slice(self, (int)start, (int)end);
     }
 
@@ -866,7 +866,7 @@
      * @return array object in which splits have been placed
      */
     @Function(attributes = Attribute.NOT_ENUMERABLE)
-    public static Object split(final Object self, final Object separator, final Object limit) {
+    public static ScriptObject split(final Object self, final Object separator, final Object limit) {
         final String str = checkObjectToString(self);
         final long lim = (limit == UNDEFINED) ? JSType.MAX_UINT : JSType.toUint32(limit);
 
@@ -882,7 +882,7 @@
         return splitString(str, JSType.toString(separator), lim);
     }
 
-    private static Object splitString(String str, String separator, long limit) {
+    private static ScriptObject splitString(String str, String separator, long limit) {
         if (separator.isEmpty()) {
             final int length = (int) Math.min(str.length(), limit);
             final Object[] array = new Object[length];
@@ -923,7 +923,7 @@
      * @return substring given start and length of section
      */
     @Function(attributes = Attribute.NOT_ENUMERABLE)
-    public static Object substr(final Object self, final Object start, final Object length) {
+    public static String substr(final Object self, final Object start, final Object length) {
         final String str       = JSType.toString(self);
         final int    strLength = str.length();
 
@@ -946,7 +946,7 @@
      * @return substring given start and end indexes
      */
     @Function(attributes = Attribute.NOT_ENUMERABLE)
-    public static Object substring(final Object self, final Object start, final Object end) {
+    public static String substring(final Object self, final Object start, final Object end) {
 
         final String str = checkObjectToString(self);
         if (end == UNDEFINED) {
@@ -1026,7 +1026,7 @@
      * @return string to lower case
      */
     @Function(attributes = Attribute.NOT_ENUMERABLE)
-    public static Object toLowerCase(final Object self) {
+    public static String toLowerCase(final Object self) {
         return checkObjectToString(self).toLowerCase(Locale.ROOT);
     }
 
@@ -1036,7 +1036,7 @@
      * @return string to locale sensitive lower case
      */
     @Function(attributes = Attribute.NOT_ENUMERABLE)
-    public static Object toLocaleLowerCase(final Object self) {
+    public static String toLocaleLowerCase(final Object self) {
         return checkObjectToString(self).toLowerCase(Global.getEnv()._locale);
     }
 
@@ -1046,7 +1046,7 @@
      * @return string to upper case
      */
     @Function(attributes = Attribute.NOT_ENUMERABLE)
-    public static Object toUpperCase(final Object self) {
+    public static String toUpperCase(final Object self) {
         return checkObjectToString(self).toUpperCase(Locale.ROOT);
     }
 
@@ -1056,7 +1056,7 @@
      * @return string to locale sensitive upper case
      */
     @Function(attributes = Attribute.NOT_ENUMERABLE)
-    public static Object toLocaleUpperCase(final Object self) {
+    public static String toLocaleUpperCase(final Object self) {
         return checkObjectToString(self).toUpperCase(Global.getEnv()._locale);
     }
 
@@ -1066,7 +1066,7 @@
      * @return string trimmed from whitespace
      */
     @Function(attributes = Attribute.NOT_ENUMERABLE)
-    public static Object trim(final Object self) {
+    public static String trim(final Object self) {
 
         final String str = checkObjectToString(self);
         int start = 0;
@@ -1088,7 +1088,7 @@
      * @return string trimmed left from whitespace
      */
     @Function(attributes = Attribute.NOT_ENUMERABLE)
-    public static Object trimLeft(final Object self) {
+    public static String trimLeft(final Object self) {
 
         final String str = checkObjectToString(self);
         int start = 0;
@@ -1107,7 +1107,7 @@
      * @return string trimmed right from whitespace
      */
     @Function(attributes = Attribute.NOT_ENUMERABLE)
-    public static Object trimRight(final Object self) {
+    public static String trimRight(final Object self) {
 
         final String str = checkObjectToString(self);
         int start = 0;
@@ -1120,7 +1120,7 @@
         return str.substring(start, end + 1);
     }
 
-    private static Object newObj(final Object self, final CharSequence str) {
+    private static ScriptObject newObj(final Object self, final CharSequence str) {
         return new NativeString(str);
     }
 
--- a/nashorn/src/jdk/nashorn/internal/objects/NativeSyntaxError.java	Wed Apr 02 22:00:15 2014 -0700
+++ b/nashorn/src/jdk/nashorn/internal/objects/NativeSyntaxError.java	Wed Apr 09 09:20:03 2014 -0700
@@ -94,7 +94,7 @@
      * @return new SyntaxError
      */
     @Constructor(name = "SyntaxError")
-    public static Object constructor(final boolean newObj, final Object self, final Object msg) {
+    public static NativeSyntaxError constructor(final boolean newObj, final Object self, final Object msg) {
         return new NativeSyntaxError(msg);
     }
 }
--- a/nashorn/src/jdk/nashorn/internal/objects/NativeTypeError.java	Wed Apr 02 22:00:15 2014 -0700
+++ b/nashorn/src/jdk/nashorn/internal/objects/NativeTypeError.java	Wed Apr 09 09:20:03 2014 -0700
@@ -94,7 +94,7 @@
      * @return new TypeError
      */
     @Constructor(name = "TypeError")
-    public static Object constructor(final boolean newObj, final Object self, final Object msg) {
+    public static NativeTypeError constructor(final boolean newObj, final Object self, final Object msg) {
         return new NativeTypeError(msg);
     }
 }
--- a/nashorn/src/jdk/nashorn/internal/objects/NativeURIError.java	Wed Apr 02 22:00:15 2014 -0700
+++ b/nashorn/src/jdk/nashorn/internal/objects/NativeURIError.java	Wed Apr 09 09:20:03 2014 -0700
@@ -93,7 +93,7 @@
      * @return new URIError
      */
     @Constructor(name = "URIError")
-    public static Object constructor(final boolean newObj, final Object self, final Object msg) {
+    public static NativeURIError constructor(final boolean newObj, final Object self, final Object msg) {
         return new NativeURIError(msg);
     }
 }
--- a/nashorn/src/jdk/nashorn/internal/objects/NativeUint16Array.java	Wed Apr 02 22:00:15 2014 -0700
+++ b/nashorn/src/jdk/nashorn/internal/objects/NativeUint16Array.java	Wed Apr 09 09:20:03 2014 -0700
@@ -99,8 +99,8 @@
      * @return new typed array
      */
     @Constructor(arity = 1)
-    public static Object constructor(final boolean newObj, final Object self, final Object... args) {
-        return constructorImpl(args, FACTORY);
+    public static NativeUint16Array constructor(final boolean newObj, final Object self, final Object... args) {
+        return (NativeUint16Array)constructorImpl(args, FACTORY);
     }
 
     NativeUint16Array(final NativeArrayBuffer buffer, final int byteOffset, final int length) {
@@ -150,8 +150,8 @@
      * @return sub array
      */
     @Function(attributes = Attribute.NOT_ENUMERABLE)
-    protected static Object subarray(final Object self, final Object begin, final Object end) {
-        return ArrayBufferView.subarrayImpl(self, begin, end);
+    protected static NativeUint16Array subarray(final Object self, final Object begin, final Object end) {
+        return (NativeUint16Array)ArrayBufferView.subarrayImpl(self, begin, end);
     }
 
     @Override
--- a/nashorn/src/jdk/nashorn/internal/objects/NativeUint32Array.java	Wed Apr 02 22:00:15 2014 -0700
+++ b/nashorn/src/jdk/nashorn/internal/objects/NativeUint32Array.java	Wed Apr 09 09:20:03 2014 -0700
@@ -118,8 +118,8 @@
      * @return new typed array
      */
     @Constructor(arity = 1)
-    public static Object constructor(final boolean newObj, final Object self, final Object... args) {
-        return constructorImpl(args, FACTORY);
+    public static NativeUint32Array constructor(final boolean newObj, final Object self, final Object... args) {
+        return (NativeUint32Array)constructorImpl(args, FACTORY);
     }
 
     NativeUint32Array(final NativeArrayBuffer buffer, final int byteOffset, final int length) {
@@ -169,8 +169,8 @@
      * @return sub array
      */
     @Function(attributes = Attribute.NOT_ENUMERABLE)
-    protected static Object subarray(final Object self, final Object begin, final Object end) {
-        return ArrayBufferView.subarrayImpl(self, begin, end);
+    protected static NativeUint32Array subarray(final Object self, final Object begin, final Object end) {
+        return (NativeUint32Array)ArrayBufferView.subarrayImpl(self, begin, end);
     }
 
     @Override
--- a/nashorn/src/jdk/nashorn/internal/objects/NativeUint8Array.java	Wed Apr 02 22:00:15 2014 -0700
+++ b/nashorn/src/jdk/nashorn/internal/objects/NativeUint8Array.java	Wed Apr 09 09:20:03 2014 -0700
@@ -92,8 +92,8 @@
      * @return new typed array
      */
     @Constructor(arity = 1)
-    public static Object constructor(final boolean newObj, final Object self, final Object... args) {
-        return constructorImpl(args, FACTORY);
+    public static NativeUint8Array constructor(final boolean newObj, final Object self, final Object... args) {
+        return (NativeUint8Array)constructorImpl(args, FACTORY);
     }
 
     NativeUint8Array(final NativeArrayBuffer buffer, final int byteOffset, final int length) {
@@ -143,8 +143,8 @@
      * @return sub array
      */
     @Function(attributes = Attribute.NOT_ENUMERABLE)
-    protected static Object subarray(final Object self, final Object begin, final Object end) {
-        return ArrayBufferView.subarrayImpl(self, begin, end);
+    protected static NativeUint8Array subarray(final Object self, final Object begin, final Object end) {
+        return (NativeUint8Array)ArrayBufferView.subarrayImpl(self, begin, end);
     }
 
     @Override
--- a/nashorn/src/jdk/nashorn/internal/objects/NativeUint8ClampedArray.java	Wed Apr 02 22:00:15 2014 -0700
+++ b/nashorn/src/jdk/nashorn/internal/objects/NativeUint8ClampedArray.java	Wed Apr 09 09:20:03 2014 -0700
@@ -109,8 +109,8 @@
      * @return new typed array
      */
     @Constructor(arity = 1)
-    public static Object constructor(final boolean newObj, final Object self, final Object... args) {
-        return constructorImpl(args, FACTORY);
+    public static NativeUint8ClampedArray constructor(final boolean newObj, final Object self, final Object... args) {
+        return (NativeUint8ClampedArray)constructorImpl(args, FACTORY);
     }
 
     NativeUint8ClampedArray(final NativeArrayBuffer buffer, final int byteOffset, final int length) {
@@ -160,8 +160,8 @@
      * @return sub array
      */
     @Function(attributes = Attribute.NOT_ENUMERABLE)
-    protected static Object subarray(final Object self, final Object begin, final Object end) {
-        return ArrayBufferView.subarrayImpl(self, begin, end);
+    protected static NativeUint8ClampedArray subarray(final Object self, final Object begin, final Object end) {
+        return (NativeUint8ClampedArray)ArrayBufferView.subarrayImpl(self, begin, end);
     }
 
     @Override
--- a/nashorn/src/jdk/nashorn/internal/parser/Parser.java	Wed Apr 02 22:00:15 2014 -0700
+++ b/nashorn/src/jdk/nashorn/internal/parser/Parser.java	Wed Apr 09 09:20:03 2014 -0700
@@ -1700,9 +1700,11 @@
                 // ECMA 12.4.1 strict mode restrictions
                 verifyStrictIdent(exception, "catch argument");
 
-                // Check for conditional catch.
+                // Nashorn extension: catch clause can have optional
+                // condition. So, a single try can have more than one
+                // catch clause each with it's own condition.
                 final Expression ifExpression;
-                if (type == IF) {
+                if (!env._no_syntax_extensions && type == IF) {
                     next();
                     // Get the exception condition.
                     ifExpression = expression();
--- a/nashorn/src/jdk/nashorn/internal/runtime/AccessorProperty.java	Wed Apr 02 22:00:15 2014 -0700
+++ b/nashorn/src/jdk/nashorn/internal/runtime/AccessorProperty.java	Wed Apr 09 09:20:03 2014 -0700
@@ -39,6 +39,9 @@
 import static jdk.nashorn.internal.lookup.Lookup.MH;
 import static jdk.nashorn.internal.lookup.MethodHandleFactory.stripName;
 
+import java.io.IOException;
+import java.io.ObjectInputStream;
+import java.io.Serializable;
 import java.lang.invoke.MethodHandle;
 import java.lang.invoke.MethodHandles;
 import java.lang.invoke.MethodType;
@@ -51,11 +54,12 @@
  * An AccessorProperty is the most generic property type. An AccessorProperty is
  * represented as fields in a ScriptObject class.
  */
-public final class AccessorProperty extends Property {
+public final class AccessorProperty extends Property implements Serializable {
     private static final MethodHandles.Lookup lookup = MethodHandles.lookup();
     private static final MethodHandle REPLACE_MAP = findOwnMH("replaceMap", Object.class, Object.class, PropertyMap.class, String.class, Class.class, Class.class);
 
     private static final int NOOF_TYPES = getNumberOfAccessorTypes();
+    private static final long serialVersionUID = 3371720170182154920L;
 
     /**
      * Properties in different maps for the same structure class will share their field getters and setters. This could
@@ -71,7 +75,7 @@
     };
 
     /** Property getter cache */
-    private MethodHandle[] getters = new MethodHandle[NOOF_TYPES];
+    private transient MethodHandle[] getters = new MethodHandle[NOOF_TYPES];
 
     private static final MethodType[] ACCESSOR_GETTER_TYPES = new MethodType[NOOF_TYPES];
     private static final MethodType[] ACCESSOR_SETTER_TYPES = new MethodType[NOOF_TYPES];
@@ -122,16 +126,16 @@
     }
 
     /** Seed getter for the primitive version of this field (in -Dnashorn.fields.dual=true mode) */
-    private MethodHandle primitiveGetter;
+    private transient MethodHandle primitiveGetter;
 
     /** Seed setter for the primitive version of this field (in -Dnashorn.fields.dual=true mode) */
-    private MethodHandle primitiveSetter;
+    private transient MethodHandle primitiveSetter;
 
     /** Seed getter for the Object version of this field */
-    private MethodHandle objectGetter;
+    private transient MethodHandle objectGetter;
 
     /** Seed setter for the Object version of this field */
-    private MethodHandle objectSetter;
+    private transient MethodHandle objectSetter;
 
     /**
      * Current type of this object, in object only mode, this is an Object.class. In dual-fields mode
@@ -243,6 +247,12 @@
     public AccessorProperty(final String key, final int flags, final Class<?> structure, final int slot) {
         super(key, flags, slot);
 
+        initGetterSetter(structure);
+    }
+
+    private void initGetterSetter(final Class<?> structure) {
+        final int slot = getSlot();
+        final String key = getKey();
         /*
          * primitiveGetter and primitiveSetter are only used in dual fields mode. Setting them to null also
          * works in dual field mode, it only means that the property never has a primitive
@@ -305,6 +315,12 @@
         setCurrentType(property.getCurrentType());
     }
 
+    private void readObject(final ObjectInputStream s) throws IOException, ClassNotFoundException {
+        s.defaultReadObject();
+        // Restore getters array
+        getters = new MethodHandle[NOOF_TYPES];
+    }
+
     private static MethodHandle bindTo(final MethodHandle mh, final Object receiver) {
         if (mh == null) {
             return null;
@@ -364,6 +380,16 @@
     }
 
     @Override
+    void initMethodHandles(final Class<?> structure) {
+        if (!ScriptObject.class.isAssignableFrom(structure) || !StructureLoader.isStructureClass(structure.getName())) {
+            throw new IllegalArgumentException();
+        }
+        if (!isSpill()) {
+            initGetterSetter(structure);
+        }
+    }
+
+    @Override
     public MethodHandle getGetter(final Class<?> type) {
         final int i = getAccessorTypeIndex(type);
         ensureObjectGetter();
--- a/nashorn/src/jdk/nashorn/internal/runtime/CodeInstaller.java	Wed Apr 02 22:00:15 2014 -0700
+++ b/nashorn/src/jdk/nashorn/internal/runtime/CodeInstaller.java	Wed Apr 09 09:20:03 2014 -0700
@@ -25,6 +25,7 @@
 
 package jdk.nashorn.internal.runtime;
 
+import java.util.Map;
 import jdk.nashorn.internal.codegen.ClassEmitter;
 
 /**
@@ -52,7 +53,7 @@
      * @param bytecode  bytecode
      * @return the installed class
      */
-    public Class<?> install(final String className, final byte[] bytecode);
+    public Class<?> install(final String className, final byte[] bytecode, final Source source, final Object[] constants);
 
     /**
      * Verify generated bytecode before emission. This is called back from the
@@ -74,4 +75,13 @@
      * @return unique eval id
      */
     public long getUniqueEvalId();
+
+    /**
+     * Store a compiled script for later reuse
+     * @param source the script source
+     * @param mainClassName the main class name
+     * @param classBytes map of class names to class bytes
+     * @param constants constants array
+     */
+    public void storeCompiledScript(Source source, String mainClassName, Map<String, byte[]> classBytes, Object[] constants);
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/src/jdk/nashorn/internal/runtime/CodeStore.java	Wed Apr 09 09:20:03 2014 -0700
@@ -0,0 +1,179 @@
+/*
+ * 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.  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.runtime;
+
+import java.io.BufferedInputStream;
+import java.io.BufferedOutputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.io.Serializable;
+import java.security.AccessController;
+import java.security.PrivilegedActionException;
+import java.security.PrivilegedExceptionAction;
+import java.util.Base64;
+import java.util.Map;
+
+/**
+ * A code cache for persistent caching of compiled scripts.
+ */
+final class CodeStore {
+
+    private final File dir;
+    private final int minSize;
+
+    // Message digest to file name encoder
+    private final static Base64.Encoder BASE64 = Base64.getUrlEncoder().withoutPadding();
+
+    // Default minimum size for storing a compiled script class
+    private final static int DEFAULT_MIN_SIZE = 1000;
+
+    /**
+     * Constructor
+     * @param path directory to store code in
+     * @throws IOException
+     */
+    public CodeStore(final String path) throws IOException {
+        this(path, DEFAULT_MIN_SIZE);
+    }
+
+    /**
+     * Constructor
+     * @param path directory to store code in
+     * @param minSize minimum file size for caching scripts
+     * @throws IOException
+     */
+    public CodeStore(final String path, final int minSize) throws IOException {
+        this.dir = new File(path);
+        this.minSize = minSize;
+        checkDirectory(this.dir);
+    }
+
+    private static void checkDirectory(final File dir) throws IOException {
+        try {
+            AccessController.doPrivileged(new PrivilegedExceptionAction<Void>() {
+                @Override
+                public Void run() throws IOException {
+                    if (!dir.exists() && !dir.mkdirs()) {
+                        throw new IOException("Could not create directory: " + dir);
+                    } else if (!dir.isDirectory()) {
+                        throw new IOException("Not a directory: " + dir);
+                    } else if (!dir.canRead() || !dir.canWrite()) {
+                        throw new IOException("Directory not readable or writable: " + dir);
+                    }
+                    return null;
+                }
+            });
+        } catch (PrivilegedActionException e) {
+            throw (IOException) e.getException();
+        }
+    }
+
+    /**
+     * Return a compiled script from the cache, or null if it isn't found.
+     *
+     * @param source the source
+     * @return the compiled script or null
+     * @throws IOException
+     * @throws ClassNotFoundException
+     */
+    public CompiledScript getScript(final Source source) throws IOException, ClassNotFoundException {
+        if (source.getLength() < minSize) {
+            return null;
+        }
+
+        final String digest = BASE64.encodeToString(source.getDigest());
+        final File file = new File(dir, digest);
+
+        try {
+            return AccessController.doPrivileged(new PrivilegedExceptionAction<CompiledScript>() {
+                @Override
+                public CompiledScript run() throws IOException, ClassNotFoundException {
+                    if (!file.exists()) {
+                        return null;
+                    }
+                    try (ObjectInputStream in = new ObjectInputStream(new BufferedInputStream(new FileInputStream(file)))) {
+                        CompiledScript compiledScript = (CompiledScript) in.readObject();
+                        compiledScript.setSource(source);
+                        return compiledScript;
+                    }
+                }
+            });
+        } catch (PrivilegedActionException e) {
+            final Exception ex = e.getException();
+            if (ex instanceof IOException) {
+                throw  (IOException) ex;
+            } else if (ex instanceof ClassNotFoundException) {
+                throw (ClassNotFoundException) ex;
+            }
+            throw (new RuntimeException(ex));
+        }
+    }
+
+    /**
+     * Store a compiled script in the cache.
+     *
+     * @param source the source
+     * @param mainClassName the main class name
+     * @param classBytes a map of class bytes
+     * @param constants the constants array
+     * @throws IOException
+     */
+    public void putScript(final Source source, final String mainClassName, final Map<String, byte[]> classBytes, final Object[] constants)
+            throws IOException {
+        if (source.getLength() < minSize) {
+            return;
+        }
+        for (final Object constant : constants) {
+            // Make sure all constant data is serializable
+            if (! (constant instanceof Serializable)) {
+                return;
+            }
+        }
+
+        final String digest = BASE64.encodeToString(source.getDigest());
+        final File file = new File(dir, digest);
+        final CompiledScript script = new CompiledScript(source, mainClassName, classBytes, constants);
+
+        try {
+            AccessController.doPrivileged(new PrivilegedExceptionAction<Void>() {
+                @Override
+                public Void run() throws IOException {
+                    try (ObjectOutputStream out = new ObjectOutputStream(new BufferedOutputStream(new FileOutputStream(file)))) {
+                        out.writeObject(script);
+                    }
+                    return null;
+                }
+            });
+        } catch (PrivilegedActionException e) {
+             throw (IOException) e.getException();
+        }
+    }
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/src/jdk/nashorn/internal/runtime/CompiledScript.java	Wed Apr 09 09:20:03 2014 -0700
@@ -0,0 +1,127 @@
+/*
+ * 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.  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.runtime;
+
+import java.io.Serializable;
+import java.util.Arrays;
+import java.util.Map;
+
+/**
+ * Class representing a compiled script.
+ */
+final class CompiledScript implements Serializable {
+
+    /** Main class name. */
+    private final String mainClassName;
+
+    /** Map of class names to class bytes. */
+    private final Map<String, byte[]> classBytes;
+
+    /** Constants array. */
+    private final Object[] constants;
+
+    /** The source */
+    private transient Source source;
+
+    private static final long serialVersionUID = 2958227232195298340L;
+
+    /**
+     * Constructor.
+     *
+     * @param mainClassName main class name
+     * @param classBytes map of class names to class bytes
+     * @param constants constants array
+     */
+    CompiledScript(final Source source, final String mainClassName, final Map<String, byte[]> classBytes, final Object[] constants) {
+        this.source = source;
+        this.mainClassName = mainClassName;
+        this.classBytes = classBytes;
+        this.constants = constants;
+    }
+
+    /**
+     * Returns the main class name.
+     * @return the main class name
+     */
+    public String getMainClassName() {
+        return mainClassName;
+    }
+
+    /**
+     * Returns a map of class names to class bytes.
+     * @return map of class bytes
+     */
+    public Map<String, byte[]> getClassBytes() {
+        return classBytes;
+    }
+
+    /**
+     * Returns the constants array.
+     * @return constants array
+     */
+    public Object[] getConstants() {
+        return constants;
+    }
+
+    /**
+     * Returns the source of this cached script.
+     * @return the source
+     */
+    public Source getSource() {
+        return source;
+    }
+
+    /**
+     * Sets the source of this cached script.
+     * @param source the source
+     */
+    void setSource(final Source source) {
+        this.source = source;
+    }
+
+    @Override
+    public int hashCode() {
+        int hash = mainClassName.hashCode();
+        hash = 31 * hash + classBytes.hashCode();
+        hash = 31 * hash + Arrays.hashCode(constants);
+        return hash;
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (obj == this) {
+            return true;
+        }
+        if (!(obj instanceof CompiledScript)) {
+            return false;
+        }
+
+        final CompiledScript cs = (CompiledScript) obj;
+        return mainClassName.equals(cs.mainClassName)
+                && classBytes.equals(cs.classBytes)
+                && Arrays.equals(constants, cs.constants);
+    }
+}
--- a/nashorn/src/jdk/nashorn/internal/runtime/Context.java	Wed Apr 02 22:00:15 2014 -0700
+++ b/nashorn/src/jdk/nashorn/internal/runtime/Context.java	Wed Apr 09 09:20:03 2014 -0700
@@ -25,7 +25,9 @@
 
 package jdk.nashorn.internal.runtime;
 
+import static jdk.nashorn.internal.codegen.CompilerConstants.CONSTANTS;
 import static jdk.nashorn.internal.codegen.CompilerConstants.RUN_SCRIPT;
+import static jdk.nashorn.internal.codegen.CompilerConstants.SOURCE;
 import static jdk.nashorn.internal.codegen.CompilerConstants.STRICT_MODE;
 import static jdk.nashorn.internal.lookup.Lookup.MH;
 import static jdk.nashorn.internal.runtime.ECMAErrors.typeError;
@@ -38,6 +40,7 @@
 import java.lang.invoke.MethodHandles;
 import java.lang.ref.ReferenceQueue;
 import java.lang.ref.SoftReference;
+import java.lang.reflect.Field;
 import java.lang.reflect.Modifier;
 import java.net.MalformedURLException;
 import java.net.URL;
@@ -47,7 +50,10 @@
 import java.security.CodeSource;
 import java.security.Permissions;
 import java.security.PrivilegedAction;
+import java.security.PrivilegedActionException;
+import java.security.PrivilegedExceptionAction;
 import java.security.ProtectionDomain;
+import java.util.HashMap;
 import java.util.LinkedHashMap;
 import java.util.Map;
 import java.util.concurrent.atomic.AtomicLong;
@@ -133,8 +139,32 @@
         }
 
         @Override
-        public Class<?> install(final String className, final byte[] bytecode) {
-            return loader.installClass(className, bytecode, codeSource);
+        public Class<?> install(final String className, final byte[] bytecode, final Source source, final Object[] constants) {
+            Compiler.LOG.fine("Installing class ", className);
+
+            final String   binaryName = Compiler.binaryName(className);
+            final Class<?> clazz      = loader.installClass(binaryName, bytecode, codeSource);
+
+            try {
+                // Need doPrivileged because these fields are private
+                AccessController.doPrivileged(new PrivilegedExceptionAction<Void>() {
+                    @Override
+                    public Void run() throws Exception {
+                        //use reflection to write source and constants table to installed classes
+                        final Field sourceField    = clazz.getDeclaredField(SOURCE.symbolName());
+                        final Field constantsField = clazz.getDeclaredField(CONSTANTS.symbolName());
+                        sourceField.setAccessible(true);
+                        constantsField.setAccessible(true);
+                        sourceField.set(null, source);
+                        constantsField.set(null, constants);
+                        return null;
+                    }
+                });
+            } catch (final PrivilegedActionException e) {
+                throw new RuntimeException(e);
+            }
+
+            return clazz;
         }
 
         @Override
@@ -151,6 +181,18 @@
         public long getUniqueEvalId() {
             return context.getUniqueEvalId();
         }
+
+        @Override
+        public void storeCompiledScript(final Source source, final String mainClassName,
+                                        final Map<String, byte[]> classBytes, final Object[] constants) {
+            if (context.codeStore != null) {
+                try {
+                    context.codeStore.putScript(source, mainClassName, classBytes, constants);
+                } catch (final IOException e) {
+                    throw new RuntimeException(e);
+                }
+            }
+        }
     }
 
     /** Is Context global debug mode enabled ? */
@@ -158,9 +200,12 @@
 
     private static final ThreadLocal<Global> currentGlobal = new ThreadLocal<>();
 
-    // class cache
+    // in-memory cache for loaded classes
     private ClassCache classCache;
 
+    // persistent code store
+    private CodeStore codeStore;
+
     /**
      * Get the current global scope
      * @return the current global scope
@@ -368,6 +413,19 @@
             classCache = new ClassCache(cacheSize);
         }
 
+        if (env._persistent_cache) {
+            if (env._lazy_compilation || env._specialize_calls != null) {
+                getErr().println("Can not use persistent class caching with lazy compilation or call specialization.");
+            } else {
+                try {
+                    final String cacheDir = Options.getStringProperty("nashorn.persistent.code.cache", "nashorn_code_cache");
+                    codeStore = new CodeStore(cacheDir);
+                } catch (IOException e) {
+                    throw new RuntimeException("Error initializing code cache", e);
+                }
+            }
+        }
+
         // print version info if asked.
         if (env._version) {
             getErr().println("nashorn " + Version.version());
@@ -932,17 +990,32 @@
             return script;
         }
 
-        final FunctionNode functionNode = new Parser(env, source, errMan, strict).parse();
-        if (errors.hasErrors()) {
-            return null;
+        CompiledScript compiledScript = null;
+        FunctionNode functionNode = null;
+
+        if (!env._parse_only && codeStore != null) {
+            try {
+                compiledScript = codeStore.getScript(source);
+            } catch (IOException | ClassNotFoundException e) {
+                Compiler.LOG.warning("Error loading ", source, " from cache: ", e);
+                // Fall back to normal compilation
+            }
         }
 
-        if (env._print_ast) {
-            getErr().println(new ASTWriter(functionNode));
-        }
+        if (compiledScript == null) {
+            functionNode = new Parser(env, source, errMan, strict).parse();
+
+            if (errors.hasErrors()) {
+                return null;
+            }
 
-        if (env._print_parse) {
-            getErr().println(new PrintVisitor(functionNode));
+            if (env._print_ast) {
+                getErr().println(new ASTWriter(functionNode));
+            }
+
+            if (env._print_parse) {
+                getErr().println(new PrintVisitor(functionNode));
+            }
         }
 
         if (env._parse_only) {
@@ -954,12 +1027,15 @@
         final CodeSource   cs     = new CodeSource(url, (CodeSigner[])null);
         final CodeInstaller<ScriptEnvironment> installer = new ContextCodeInstaller(this, loader, cs);
 
-        final Compiler compiler = new Compiler(installer, strict);
+        if (functionNode != null) {
+            final Compiler compiler = new Compiler(installer, strict);
+            final FunctionNode newFunctionNode = compiler.compile(functionNode);
+            script = compiler.install(newFunctionNode);
+        } else {
+            script = install(compiledScript, installer);
+        }
 
-        final FunctionNode newFunctionNode = compiler.compile(functionNode);
-        script = compiler.install(newFunctionNode);
         cacheClass(source, script);
-
         return script;
     }
 
@@ -981,6 +1057,42 @@
         return uniqueScriptId.getAndIncrement();
     }
 
+
+    /**
+     * Install a previously compiled class from the code cache.
+     *
+     * @param compiledScript cached script containing class bytes and constants
+     * @return main script class
+     */
+    private Class<?> install(final CompiledScript compiledScript, final CodeInstaller<ScriptEnvironment> installer) {
+
+        final Map<String, Class<?>> installedClasses = new HashMap<>();
+        final Source   source        = compiledScript.getSource();
+        final Object[] constants     = compiledScript.getConstants();
+        final String   rootClassName = compiledScript.getMainClassName();
+        final byte[]   rootByteCode  = compiledScript.getClassBytes().get(rootClassName);
+        final Class<?> rootClass     = installer.install(rootClassName, rootByteCode, source, constants);
+
+        installedClasses.put(rootClassName, rootClass);
+
+        for (final Map.Entry<String, byte[]> entry : compiledScript.getClassBytes().entrySet()) {
+            final String className = entry.getKey();
+            if (className.equals(rootClassName)) {
+                continue;
+            }
+            final byte[] code = entry.getValue();
+
+            installedClasses.put(className, installer.install(className, code, source, constants));
+        }
+        for (Object constant : constants) {
+            if (constant instanceof RecompilableScriptFunctionData) {
+                ((RecompilableScriptFunctionData) constant).setCodeAndSource(installedClasses, source);
+            }
+        }
+
+        return rootClass;
+    }
+
     /**
      * Cache for compiled script classes.
      */
--- a/nashorn/src/jdk/nashorn/internal/runtime/JSONFunctions.java	Wed Apr 02 22:00:15 2014 -0700
+++ b/nashorn/src/jdk/nashorn/internal/runtime/JSONFunctions.java	Wed Apr 09 09:20:03 2014 -0700
@@ -101,7 +101,6 @@
     // apply 'reviver' function if available
     private static Object applyReviver(final Global global, final Object unfiltered, final Object reviver) {
         if (reviver instanceof ScriptFunction) {
-            assert global instanceof Global;
             final ScriptObject root = global.newObject();
             root.addOwnProperty("", Property.WRITABLE_ENUMERABLE_CONFIGURABLE, unfiltered);
             return walk(root, "", (ScriptFunction)reviver);
--- a/nashorn/src/jdk/nashorn/internal/runtime/Property.java	Wed Apr 02 22:00:15 2014 -0700
+++ b/nashorn/src/jdk/nashorn/internal/runtime/Property.java	Wed Apr 09 09:20:03 2014 -0700
@@ -29,6 +29,7 @@
 import static jdk.nashorn.internal.runtime.PropertyDescriptor.ENUMERABLE;
 import static jdk.nashorn.internal.runtime.PropertyDescriptor.WRITABLE;
 
+import java.io.Serializable;
 import java.lang.invoke.MethodHandle;
 import java.util.Objects;
 import jdk.nashorn.internal.codegen.ObjectClassGenerator;
@@ -43,7 +44,7 @@
  * @see AccessorProperty
  * @see UserAccessorProperty
  */
-public abstract class Property {
+public abstract class Property implements Serializable {
     /*
      * ECMA 8.6.1 Property Attributes
      *
@@ -100,6 +101,8 @@
     /** Property field number or spill slot. */
     private final int slot;
 
+    private static final long serialVersionUID = 2099814273074501176L;
+
     /**
      * Constructor
      *
@@ -358,6 +361,13 @@
     public abstract MethodHandle getGetter(final Class<?> type);
 
     /**
+     * Hook to initialize method handles after deserialization.
+     *
+     * @param structure the structure class
+     */
+    abstract void initMethodHandles(final Class<?> structure);
+
+    /**
      * Get the key for this property. This key is an ordinary string. The "name".
      * @return key for property
      */
--- a/nashorn/src/jdk/nashorn/internal/runtime/PropertyMap.java	Wed Apr 02 22:00:15 2014 -0700
+++ b/nashorn/src/jdk/nashorn/internal/runtime/PropertyMap.java	Wed Apr 09 09:20:03 2014 -0700
@@ -29,6 +29,10 @@
 import static jdk.nashorn.internal.runtime.arrays.ArrayIndex.getArrayIndex;
 import static jdk.nashorn.internal.runtime.arrays.ArrayIndex.isValidArrayIndex;
 
+import java.io.IOException;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.io.Serializable;
 import java.lang.invoke.SwitchPoint;
 import java.lang.ref.SoftReference;
 import java.util.Arrays;
@@ -37,6 +41,7 @@
 import java.util.Iterator;
 import java.util.NoSuchElementException;
 import java.util.WeakHashMap;
+import jdk.nashorn.internal.scripts.JO;
 
 /**
  * Map of object properties. The PropertyMap is the "template" for JavaScript object
@@ -47,7 +52,7 @@
  * All property maps are immutable. If a property is added, modified or removed, the mutator
  * will return a new map.
  */
-public final class PropertyMap implements Iterable<Object> {
+public final class PropertyMap implements Iterable<Object>, Serializable {
     /** Used for non extensible PropertyMaps, negative logic as the normal case is extensible. See {@link ScriptObject#preventExtensions()} */
     public static final int NOT_EXTENSIBLE        = 0b0000_0001;
     /** Does this map contain valid array keys? */
@@ -57,7 +62,7 @@
     private int flags;
 
     /** Map of properties. */
-    private final PropertyHashMap properties;
+    private transient PropertyHashMap properties;
 
     /** Number of fields in use. */
     private int fieldCount;
@@ -68,17 +73,22 @@
     /** Length of spill in use. */
     private int spillLength;
 
+    /** Structure class name */
+    private String className;
+
     /** {@link SwitchPoint}s for gets on inherited properties. */
-    private HashMap<String, SwitchPoint> protoGetSwitches;
+    private transient HashMap<String, SwitchPoint> protoGetSwitches;
 
     /** History of maps, used to limit map duplication. */
-    private WeakHashMap<Property, SoftReference<PropertyMap>> history;
+    private transient WeakHashMap<Property, SoftReference<PropertyMap>> history;
 
     /** History of prototypes, used to limit map duplication. */
-    private WeakHashMap<PropertyMap, SoftReference<PropertyMap>> protoHistory;
+    private transient WeakHashMap<PropertyMap, SoftReference<PropertyMap>> protoHistory;
 
     /** property listeners */
-    private PropertyListeners listeners;
+    private transient PropertyListeners listeners;
+
+    private static final long serialVersionUID = -7041836752008732533L;
 
     /**
      * Constructor.
@@ -89,8 +99,10 @@
      * @param spillLength  Number of spill slots used.
      * @param containsArrayKeys True if properties contain numeric keys
      */
-    private PropertyMap(final PropertyHashMap properties, final int fieldCount, final int fieldMaximum, final int spillLength, final boolean containsArrayKeys) {
+    private PropertyMap(final PropertyHashMap properties, final String className, final int fieldCount,
+                        final int fieldMaximum, final int spillLength, final boolean containsArrayKeys) {
         this.properties   = properties;
+        this.className    = className;
         this.fieldCount   = fieldCount;
         this.fieldMaximum = fieldMaximum;
         this.spillLength  = spillLength;
@@ -145,7 +157,25 @@
         if (Context.DEBUG) {
             duplicatedCount++;
         }
-        return new PropertyMap(this.properties, 0, 0, 0, containsArrayKeys());
+        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());
+    }
+
+    private void readObject(final ObjectInputStream in) throws IOException, ClassNotFoundException {
+        in.defaultReadObject();
+
+        final Property[] props = (Property[]) in.readObject();
+        this.properties = EMPTY_HASHMAP.immutableAdd(props);
+
+        assert className != null;
+        final Class<?> structure = Context.forStructureClass(className);
+        for (Property prop : props) {
+            prop.initMethodHandles(structure);
+        }
     }
 
     /**
@@ -160,9 +190,9 @@
      * @param spillLength  Number of used spill slots.
      * @return New {@link PropertyMap}.
      */
-    public static PropertyMap newMap(final Collection<Property> properties, final int fieldCount, final int fieldMaximum,  final int spillLength) {
+    public static PropertyMap newMap(final Collection<Property> properties, final String className, final int fieldCount, final int fieldMaximum,  final int spillLength) {
         PropertyHashMap newProperties = EMPTY_HASHMAP.immutableAdd(properties);
-        return new PropertyMap(newProperties, fieldCount, fieldMaximum, spillLength, false);
+        return new PropertyMap(newProperties, className, fieldCount, fieldMaximum, spillLength, false);
     }
 
     /**
@@ -175,7 +205,7 @@
      * @return New {@link PropertyMap}.
      */
     public static PropertyMap newMap(final Collection<Property> properties) {
-        return (properties == null || properties.isEmpty())? newMap() : newMap(properties, 0, 0, 0);
+        return (properties == null || properties.isEmpty())? newMap() : newMap(properties, JO.class.getName(), 0, 0, 0);
     }
 
     /**
@@ -184,7 +214,7 @@
      * @return New empty {@link PropertyMap}.
      */
     public static PropertyMap newMap() {
-        return new PropertyMap(EMPTY_HASHMAP, 0, 0, 0, false);
+        return new PropertyMap(EMPTY_HASHMAP, JO.class.getName(), 0, 0, 0, false);
     }
 
     /**
--- a/nashorn/src/jdk/nashorn/internal/runtime/RecompilableScriptFunctionData.java	Wed Apr 02 22:00:15 2014 -0700
+++ b/nashorn/src/jdk/nashorn/internal/runtime/RecompilableScriptFunctionData.java	Wed Apr 09 09:20:03 2014 -0700
@@ -27,14 +27,15 @@
 
 import static jdk.nashorn.internal.lookup.Lookup.MH;
 
+import java.io.Serializable;
 import java.lang.invoke.MethodHandle;
 import java.lang.invoke.MethodHandles;
 import java.lang.invoke.MethodType;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.LinkedList;
+import java.util.Map;
 import jdk.internal.dynalink.support.NameCodec;
-
 import jdk.nashorn.internal.codegen.Compiler;
 import jdk.nashorn.internal.codegen.CompilerConstants;
 import jdk.nashorn.internal.codegen.FunctionSignature;
@@ -43,6 +44,7 @@
 import jdk.nashorn.internal.ir.FunctionNode.CompilationState;
 import jdk.nashorn.internal.parser.Token;
 import jdk.nashorn.internal.parser.TokenType;
+import jdk.nashorn.internal.scripts.JS;
 
 /**
  * This is a subclass that represents a script function that may be regenerated,
@@ -50,13 +52,19 @@
  * The common denominator is that it can get new invokers during its lifespan,
  * unlike {@code FinalScriptFunctionData}
  */
-public final class RecompilableScriptFunctionData extends ScriptFunctionData {
+public final class RecompilableScriptFunctionData extends ScriptFunctionData implements Serializable {
 
     /** FunctionNode with the code for this ScriptFunction */
-    private FunctionNode functionNode;
+    private transient FunctionNode functionNode;
 
     /** Source from which FunctionNode was parsed. */
-    private final Source source;
+    private transient Source source;
+
+    /** The line number where this function begins. */
+    private final int lineNumber;
+
+    /** Allows us to retrieve the method handle for this function once the code is compiled */
+    private MethodLocator methodLocator;
 
     /** Token of this function within the source. */
     private final long token;
@@ -65,13 +73,13 @@
     private final PropertyMap allocatorMap;
 
     /** Code installer used for all further recompilation/specialization of this ScriptFunction */
-    private CodeInstaller<ScriptEnvironment> installer;
+    private transient CodeInstaller<ScriptEnvironment> installer;
 
     /** Name of class where allocator function resides */
     private final String allocatorClassName;
 
     /** lazily generated allocator */
-    private MethodHandle allocator;
+    private transient MethodHandle allocator;
 
     private static final MethodHandles.Lookup LOOKUP = MethodHandles.lookup();
 
@@ -79,7 +87,7 @@
      * Used for specialization based on runtime arguments. Whenever we specialize on
      * callsite parameter types at runtime, we need to use a parameter type guard to
      * ensure that the specialized version of the script function continues to be
-     * applicable for a particular callsite *
+     * applicable for a particular callsite.
      */
     private static final MethodHandle PARAM_TYPE_GUARD = findOwnMH("paramTypeGuard", boolean.class, Type[].class,  Object[].class);
 
@@ -88,10 +96,12 @@
      * (or java.lang.Number instance) to specialize the parameter to an integer, if the
      * parameter in question can be represented as one. The double typically only exists
      * because the compiler doesn't know any better than "a number type" and conservatively
-     * picks doubles when it can't prove that an integer addition wouldn't overflow
+     * picks doubles when it can't prove that an integer addition wouldn't overflow.
      */
     private static final MethodHandle ENSURE_INT = findOwnMH("ensureInt", int.class, Object.class);
 
+    private static final long serialVersionUID = 4914839316174633726L;
+
     /**
      * Constructor - public as scripts use it
      *
@@ -104,13 +114,16 @@
         super(functionName(functionNode),
               functionNode.getParameters().size(),
               getFlags(functionNode));
-
         this.functionNode       = functionNode;
         this.source             = functionNode.getSource();
+        this.lineNumber         = functionNode.getLineNumber();
         this.token              = tokenFor(functionNode);
         this.installer          = installer;
         this.allocatorClassName = allocatorClassName;
         this.allocatorMap       = allocatorMap;
+        if (!functionNode.isLazy()) {
+            methodLocator = new MethodLocator(functionNode);
+        }
     }
 
     @Override
@@ -122,16 +135,19 @@
         return "function " + (name == null ? "" : name) + "() { [native code] }";
     }
 
+    public void setCodeAndSource(final Map<String, Class<?>> code, final Source source) {
+        this.source = source;
+        if (methodLocator != null) {
+            methodLocator.setClass(code.get(methodLocator.getClassName()));
+        }
+    }
+
     @Override
     public String toString() {
         final StringBuilder sb = new StringBuilder();
 
         if (source != null) {
-            sb.append(source.getName());
-            if (functionNode != null) {
-                sb.append(':').append(functionNode.getLineNumber());
-            }
-            sb.append(' ');
+            sb.append(source.getName()).append(':').append(lineNumber).append(' ');
         }
 
         return sb.toString() + super.toString();
@@ -204,8 +220,13 @@
             functionNode = compiler.compile(functionNode);
             assert !functionNode.isLazy();
             compiler.install(functionNode);
+            methodLocator = new MethodLocator(functionNode);
             flags = getFlags(functionNode);
         }
+
+        if (functionNode != null) {
+            methodLocator.setClass(functionNode.getCompileUnit().getCode());
+        }
     }
 
     @Override
@@ -221,12 +242,13 @@
          * eager compilation or from running a lazy compile on the lines above
          */
 
-        assert functionNode.hasState(CompilationState.EMITTED) : functionNode.getName() + " " + functionNode.getState() + " " + Debug.id(functionNode);
+        assert functionNode == null || functionNode.hasState(CompilationState.EMITTED) :
+                    functionNode.getName() + " " + functionNode.getState() + " " + Debug.id(functionNode);
 
         // code exists - look it up and add it into the automatically sorted invoker list
         addCode(functionNode);
 
-        if (! functionNode.canSpecialize()) {
+        if (functionNode != null && !functionNode.canSpecialize()) {
             // allow GC to claim IR stuff that is not needed anymore
             functionNode = null;
             installer = null;
@@ -238,13 +260,9 @@
     }
 
     private MethodHandle addCode(final FunctionNode fn, final MethodType runtimeType, final MethodHandle guard, final MethodHandle fallback) {
-        final MethodType targetType = new FunctionSignature(fn).getMethodType();
-        MethodHandle target =
-            MH.findStatic(
-                    LOOKUP,
-                    fn.getCompileUnit().getCode(),
-                    fn.getName(),
-                    targetType);
+        assert methodLocator != null;
+        MethodHandle target = methodLocator.getMethodHandle();
+        final MethodType targetType = methodLocator.getMethodType();
 
         /*
          * For any integer argument. a double that is representable as an integer is OK.
@@ -424,7 +442,6 @@
 
         Compiler.LOG.info("Callsite specialized ", name, " runtimeType=", runtimeType, " parameters=", snapshot.getParameters(), " args=", Arrays.asList(args));
 
-        assert snapshot != null;
         assert snapshot != functionNode;
 
         final Compiler compiler = new Compiler(installer);
@@ -450,5 +467,45 @@
         return MH.findStatic(MethodHandles.lookup(), RecompilableScriptFunctionData.class, name, MH.type(rtype, types));
     }
 
+    /**
+     * Helper class that allows us to retrieve the method handle for this function once it has been generated.
+     */
+    private static class MethodLocator implements Serializable {
+        private transient Class<?> clazz;
+        private final String className;
+        private final String methodName;
+        private final MethodType methodType;
+
+        private static final long serialVersionUID = -5420835725902966692L;
+
+        MethodLocator(final FunctionNode functionNode) {
+            this.className  = functionNode.getCompileUnit().getUnitClassName();
+            this.methodName = functionNode.getName();
+            this.methodType = new FunctionSignature(functionNode).getMethodType();
+
+            assert className != null;
+            assert methodName != null;
+        }
+
+        void setClass(final Class<?> clazz) {
+            if (!JS.class.isAssignableFrom(clazz)) {
+                throw new IllegalArgumentException();
+            }
+            this.clazz = clazz;
+        }
+
+        String getClassName() {
+            return className;
+        }
+
+        MethodType getMethodType() {
+            return methodType;
+        }
+
+        MethodHandle getMethodHandle() {
+            return MH.findStatic(LOOKUP, clazz, methodName, methodType);
+        }
+    }
+
 }
 
--- a/nashorn/src/jdk/nashorn/internal/runtime/ScriptEnvironment.java	Wed Apr 02 22:00:15 2014 -0700
+++ b/nashorn/src/jdk/nashorn/internal/runtime/ScriptEnvironment.java	Wed Apr 09 09:20:03 2014 -0700
@@ -134,6 +134,9 @@
     /** Only parse the source code, do not compile */
     public final boolean _parse_only;
 
+    /** Enable disk cache for compiled scripts */
+    public final boolean _persistent_cache;
+
     /** Print the AST before lowering */
     public final boolean _print_ast;
 
@@ -218,6 +221,7 @@
         _no_syntax_extensions = options.getBoolean("no.syntax.extensions");
         _no_typed_arrays      = options.getBoolean("no.typed.arrays");
         _parse_only           = options.getBoolean("parse.only");
+        _persistent_cache     = options.getBoolean("persistent.code.cache");
         _print_ast            = options.getBoolean("print.ast");
         _print_lower_ast      = options.getBoolean("print.lower.ast");
         _print_code           = options.getBoolean("print.code");
--- a/nashorn/src/jdk/nashorn/internal/runtime/ScriptFunctionData.java	Wed Apr 02 22:00:15 2014 -0700
+++ b/nashorn/src/jdk/nashorn/internal/runtime/ScriptFunctionData.java	Wed Apr 09 09:20:03 2014 -0700
@@ -29,10 +29,10 @@
 import static jdk.nashorn.internal.runtime.ECMAErrors.typeError;
 import static jdk.nashorn.internal.runtime.ScriptRuntime.UNDEFINED;
 
+import java.io.Serializable;
 import java.lang.invoke.MethodHandle;
 import java.lang.invoke.MethodHandles;
 import java.lang.invoke.MethodType;
-import jdk.nashorn.internal.objects.Global;
 import jdk.nashorn.internal.runtime.linker.JavaAdapterFactory;
 
 /**
@@ -40,7 +40,7 @@
  * Instances of this class are created during codegen and stored in script classes'
  * constants array to reduce function instantiation overhead during runtime.
  */
-public abstract class ScriptFunctionData {
+public abstract class ScriptFunctionData implements Serializable {
 
     /** Name of the function or "" for anonynous functions */
     protected final String name;
@@ -74,6 +74,8 @@
     /** Flag for strict constructors */
     public static final int IS_STRICT_CONSTRUCTOR = IS_STRICT | IS_CONSTRUCTOR;
 
+    private static final long serialVersionUID = 4252901245508769114L;
+
     /**
      * Constructor
      *
--- a/nashorn/src/jdk/nashorn/internal/runtime/ScriptObject.java	Wed Apr 02 22:00:15 2014 -0700
+++ b/nashorn/src/jdk/nashorn/internal/runtime/ScriptObject.java	Wed Apr 09 09:20:03 2014 -0700
@@ -593,23 +593,16 @@
     }
 
     /**
-     * Spec. mentions use of [[DefineOwnProperty]] for indexed properties in
-     * certain places (eg. Array.prototype.map, filter). We can not use ScriptObject.set
-     * method in such cases. This is because set method uses inherited setters (if any)
-     * from any object in proto chain such as Array.prototype, Object.prototype.
-     * This method directly sets a particular element value in the current object.
+     * Almost like defineOwnProperty(int,Object) for arrays this one does
+     * not add 'gap' elements (like the array one does).
      *
      * @param index key for property
      * @param value value to define
      */
-    public final void defineOwnProperty(final int index, final Object value) {
+    public void defineOwnProperty(final int index, final Object value) {
         assert isValidArrayIndex(index) : "invalid array index";
         final long longIndex = ArrayIndex.toLongIndex(index);
-        if (longIndex >= getArray().length()) {
-            // make array big enough to hold..
-            setArray(getArray().ensure(longIndex));
-        }
-        setArray(getArray().set(index, value, false));
+        setValueAtArrayIndex(longIndex, index, value, false);
     }
 
     private void checkIntegerKey(final String key) {
@@ -2747,9 +2740,7 @@
      * @param strict are we in strict mode
      */
     private void doesNotHave(final int index, final Object value, final boolean strict) {
-        final long oldLength = getArray().length();
         final long longIndex = ArrayIndex.toLongIndex(index);
-
         if (getMap().containsArrayKeys()) {
             final String key = JSType.toString(longIndex);
             final FindProperty find = findProperty(key, true);
@@ -2760,6 +2751,18 @@
             }
         }
 
+        setValueAtArrayIndex(longIndex, index, value, strict);
+    }
+
+    /**
+     * Handle when an array doesn't have a slot - possibly grow and/or convert array.
+     *
+     * @param index  key as index
+     * @param value  element value
+     * @param strict are we in strict mode
+     */
+    private void setValueAtArrayIndex(final long longIndex, final int index, final Object value, final boolean strict) {
+        final long oldLength = getArray().length();
         if (longIndex >= oldLength) {
             if (!isExtensible()) {
                 if (strict) {
--- a/nashorn/src/jdk/nashorn/internal/runtime/Source.java	Wed Apr 02 22:00:15 2014 -0700
+++ b/nashorn/src/jdk/nashorn/internal/runtime/Source.java	Wed Apr 09 09:20:03 2014 -0700
@@ -39,6 +39,8 @@
 import java.nio.file.Files;
 import java.nio.file.Path;
 import java.nio.file.Paths;
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
 import java.util.Arrays;
 import java.util.Objects;
 import jdk.nashorn.internal.parser.Token;
@@ -71,6 +73,9 @@
     /** Cached hash code */
     private int hash;
 
+    /** Message digest */
+    private byte[] digest;
+
     /** Source URL if available */
     private final URL url;
 
@@ -417,6 +422,40 @@
     }
 
     /**
+     * Get a message digest for this source.
+     *
+     * @return a message digest for this source
+     */
+    public synchronized byte[] getDigest() {
+        if (digest == null) {
+
+            final byte[] bytes = new byte[content.length * 2];
+
+            for (int i = 0; i < content.length; i++) {
+                bytes[i * 2]     = (byte)  (content[i] & 0x00ff);
+                bytes[i * 2 + 1] = (byte) ((content[i] & 0xff00) >> 8);
+            }
+
+            try {
+                final MessageDigest md = MessageDigest.getInstance("SHA-1");
+                if (name != null) {
+                    md.update(name.getBytes(StandardCharsets.UTF_8));
+                }
+                if (base != null) {
+                    md.update(base.getBytes(StandardCharsets.UTF_8));
+                }
+                if (url != null) {
+                    md.update(url.toString().getBytes(StandardCharsets.UTF_8));
+                }
+                digest = md.digest(bytes);
+            } catch (NoSuchAlgorithmException e) {
+                throw new RuntimeException(e);
+            }
+        }
+        return digest;
+    }
+
+    /**
      * Get the base url. This is currently used for testing only
      * @param url a URL
      * @return base URL for url
--- a/nashorn/src/jdk/nashorn/internal/runtime/UserAccessorProperty.java	Wed Apr 02 22:00:15 2014 -0700
+++ b/nashorn/src/jdk/nashorn/internal/runtime/UserAccessorProperty.java	Wed Apr 09 09:20:03 2014 -0700
@@ -187,6 +187,11 @@
     }
 
     @Override
+    void initMethodHandles(final Class<?> structure) {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
     public ScriptFunction getGetterFunction(final ScriptObject obj) {
         final Object value = obj.getSpill(getterSlot);
         return (value instanceof ScriptFunction) ? (ScriptFunction) value : null;
--- a/nashorn/src/jdk/nashorn/internal/runtime/resources/Options.properties	Wed Apr 02 22:00:15 2014 -0700
+++ b/nashorn/src/jdk/nashorn/internal/runtime/resources/Options.properties	Wed Apr 09 09:20:03 2014 -0700
@@ -230,6 +230,14 @@
     desc="Parse without compiling." \
 }
 
+nashorn.option.persistent.code.cache = {            \
+    name="--persistent-code-cache",                 \
+    short_name="-pcc",                              \
+    desc="Enable disk cache for compiled scripts.", \
+    is_undocumented=true,                           \
+    default=false                                   \
+}
+
 nashorn.option.profile.callsites = {   \
     name="--profile-callsites",        \
     short_name="-pcs",                 \
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/basic/JDK-8037562.js	Wed Apr 09 09:20:03 2014 -0700
@@ -0,0 +1,41 @@
+/*
+ * 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-8037562: Nashorn: JSON.parse comes up with nonexistent entries if there are gaps between the keys
+ *
+ * @test
+ * @run
+ */
+
+var strs = [
+    '{ "0":0, "2":2       }',
+    '{ "0":"", "2":""     }',
+    '{ "0":0,  "5":"hello" }',
+    '{ "0":"", "15":3234   }',
+]
+
+for (var i in strs) {
+    print(JSON.stringify(JSON.parse(strs[i])));
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/basic/JDK-8037562.js.EXPECTED	Wed Apr 09 09:20:03 2014 -0700
@@ -0,0 +1,4 @@
+{"0":0,"2":2}
+{"0":"","2":""}
+{"0":0,"5":"hello"}
+{"0":"","15":3234}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/error/JDK-8039047.js	Wed Apr 09 09:20:03 2014 -0700
@@ -0,0 +1,35 @@
+/*
+ * 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-8039047: Parser accepts conditional catch clauses even when --no-syntax-extensions / -nse option is passed
+ *
+ * @option --no-syntax-extensions
+ * @test/compile-error
+ */
+
+try {
+    func()
+} catch (e if e instanceof ReferenceError) {
+    print("Got ReferenceError " + e);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/error/JDK-8039047.js.EXPECTED	Wed Apr 09 09:20:03 2014 -0700
@@ -0,0 +1,6 @@
+test/script/error/JDK-8039047.js:33:11 Expected ) but found if
+} catch (e if e instanceof ReferenceError) {
+           ^
+test/script/error/JDK-8039047.js:35:0 Expected eof but found }
+}
+^
--- a/nashorn/test/src/jdk/nashorn/internal/runtime/NoPersistenceCachingTest.java	Wed Apr 02 22:00:15 2014 -0700
+++ b/nashorn/test/src/jdk/nashorn/internal/runtime/NoPersistenceCachingTest.java	Wed Apr 09 09:20:03 2014 -0700
@@ -37,6 +37,8 @@
 import javax.script.ScriptEngineManager;
 import javax.script.SimpleScriptContext;
 import jdk.nashorn.api.scripting.NashornScriptEngineFactory;
+import org.testng.annotations.AfterTest;
+import org.testng.annotations.BeforeTest;
 
 /**
  * @test
@@ -50,8 +52,8 @@
    private ScriptContext context1, context2, context3;
    private ByteArrayOutputStream stderr;
    private PrintStream prevStderr;
-   private final String script = "print('Hello')";
 
+   @BeforeTest
    public void setupTest() {
       stderr = new ByteArrayOutputStream();
       prevStderr = System.err;
@@ -69,33 +71,33 @@
       }
       String[] options = new String[]{"--log=compiler:finest"};
       engine = nashornFactory.getScriptEngine(options);
+      context1 = engine.getContext();
+      context2 = new SimpleScriptContext();
+      context2.setBindings(engine.createBindings(), ScriptContext.ENGINE_SCOPE);
+      context3 = new SimpleScriptContext();
+      context3.setBindings(engine.createBindings(), ScriptContext.ENGINE_SCOPE);
    }
 
+   @AfterTest
    public void setErrTest() {
       System.setErr(prevStderr);
    }
 
    public void runTest(int numberOfContext, String expectedOutputPattern,
                        int expectedPatternOccurrence) {
-      setupTest();
+
       try {
          switch (numberOfContext) {
          case 2:
-            context1 = engine.getContext();
-            context2 = new SimpleScriptContext();
-            context2.setBindings(engine.createBindings(), ScriptContext.ENGINE_SCOPE);
-            engine.eval(script, context1);
-            engine.eval(script, context2);
+            String scriptTwoContexts = "print('HelloTwoContexts')";
+            engine.eval(scriptTwoContexts, context1);
+            engine.eval(scriptTwoContexts, context2);
             break;
          case 3:
-            context1 = engine.getContext();
-            context2 = new SimpleScriptContext();
-            context2.setBindings(engine.createBindings(), ScriptContext.ENGINE_SCOPE);
-            context3 = new SimpleScriptContext();
-            context3.setBindings(engine.createBindings(), ScriptContext.ENGINE_SCOPE);
-            engine.eval(script, context1);
-            engine.eval(script, context2);
-            engine.eval(script, context3);
+            String scriptThreeContexts = "print('HelloThreeContexts')";
+            engine.eval(scriptThreeContexts, context1);
+            engine.eval(scriptThreeContexts, context2);
+            engine.eval(scriptThreeContexts, context3);
             break;
          }
       } catch (final Exception se) {
@@ -113,7 +115,7 @@
                     + expectedPatternOccurrence + " and found: " + matches + "\n"
               + stderr);
       }
-      setErrTest();
+      stderr.reset();
    }
 
    private static String getCodeCachePattern() {