Back out 3da143341145 (bug 784294) and 862f9cd7eb0b (bug 791850) for breaking Jetpack
authorPhil Ringnalda <philringnalda@gmail.com>
Tue, 13 Nov 2012 22:08:22 -0800
changeset 113196 dd68409d78108158a2b9d0f3d3cbba23cf709ecc
parent 113183 4e9567eeb09e41d1b8c71c2ba275c2d7ee2dcec2
child 113197 2b66b88a0b0f77ea7c5b2c5b0d580ce515dca65c
child 113231 fc1684f4d3a9e7d26e5d0cf1de0aec71ea7c7d58
child 127097 0000859b1e36481fbe77037fa2dffeabff838f61
push id17996
push userphilringnalda@gmail.com
push dateWed, 14 Nov 2012 06:19:06 +0000
treeherdermozilla-inbound@2b66b88a0b0f [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
bugs784294, 791850
milestone19.0a1
backs out3da143341145b12a1a42b46b1d669731f096436f
first release with
nightly linux32
dd68409d7810 / 19.0a1 / 20121114030718 / files
nightly linux64
dd68409d7810 / 19.0a1 / 20121114030718 / files
nightly mac
dd68409d7810 / 19.0a1 / 20121114030718 / files
nightly win32
dd68409d7810 / 19.0a1 / 20121114030718 / files
nightly win64
dd68409d7810 / 19.0a1 / 20121114030718 / files
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
releases
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Back out 3da143341145 (bug 784294) and 862f9cd7eb0b (bug 791850) for breaking Jetpack
js/src/builtin/array.js
js/src/frontend/BytecodeEmitter.cpp
js/src/jsapi.cpp
js/src/jsarray.cpp
js/src/jscntxt.cpp
js/src/jscntxt.h
js/src/jsfriendapi.cpp
js/src/jsfun.cpp
js/src/jsfun.h
js/src/jsinterp.cpp
js/src/jsinterpinlines.h
js/src/jsobj.cpp
js/src/jsopcode.cpp
js/src/jsscript.cpp
js/src/jsstr.cpp
js/src/methodjit/InvokeHelpers.cpp
js/src/shell/js.cpp
js/src/vm/GlobalObject.h
--- a/js/src/builtin/array.js
+++ b/js/src/builtin/array.js
@@ -1,338 +1,1 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
- /* ES5 15.4.4.14. */
-function ArrayIndexOf(searchElement/*, fromIndex*/) {
-    /* Step 1. */
-    var O = %ToObject(this);
-
-    /* Steps 2-3. */
-    var len = TO_UINT32(O.length);
-
-    /* Step 4. */
-    if (len === 0)
-        return -1;
-
-    /* Step 5. */
-    var n = arguments.length > 1 ? %ToInteger(arguments[1]) : 0;
-
-    /* Step 6. */
-    if (n >= len)
-        return -1;
-
-    var k;
-    /* Step 7. */
-    if (n >= 0)
-        k = n;
-    /* Step 8. */
-    else {
-        /* Step a. */
-        k = len + n;
-        /* Step b. */
-        if (k < 0)
-            k = 0;
-    }
-
-    /* Step 9. */
-    for (; k < len; k++) {
-        if (k in O && O[k] === searchElement)
-            return k;
-    }
-
-    /* Step 10. */
-    return -1;
-}
-
-function ArrayStaticIndexOf(list, searchElement/*, fromIndex*/) {
-    if (arguments.length < 1)
-        %ThrowError(JSMSG_MISSING_FUN_ARG, 0, 'Array.indexOf');
-    var fromIndex = arguments.length > 2 ? arguments[2] : 0;
-    return %_CallFunction(list, searchElement, fromIndex, ArrayIndexOf);
-}
-
-/* ES5 15.4.4.15. */
-function ArrayLastIndexOf(searchElement/*, fromIndex*/) {
-    /* Step 1. */
-    var O = %ToObject(this);
-
-    /* Steps 2-3. */
-    var len = TO_UINT32(O.length);
-
-    /* Step 4. */
-    if (len === 0)
-        return -1;
-
-    /* Step 5. */
-    var n = arguments.length > 1 ? %ToInteger(arguments[1]) : len - 1;
-
-    /* Steps 6-7. */
-    var k;
-    if (n > len - 1)
-        k = len - 1;
-    else if (n < 0)
-        k = len + n;
-    else
-        k = n;
-
-    /* Step 8. */
-    for (; k >= 0; k--) {
-        if (k in O && O[k] === searchElement)
-            return k;
-    }
-
-    /* Step 9. */
-    return -1;
-}
-
-function ArrayStaticLastIndexOf(list, searchElement/*, fromIndex*/) {
-    if (arguments.length < 1)
-        %ThrowError(JSMSG_MISSING_FUN_ARG, 0, 'Array.lastIndexOf');
-    var fromIndex;
-    if (arguments.length > 2) {
-        fromIndex = arguments[2];
-    } else {
-        var O = %ToObject(list);
-        var len = TO_UINT32(O.length);
-        fromIndex = len - 1;
-    }
-    return %_CallFunction(list, searchElement, fromIndex, ArrayLastIndexOf);
-}
-
-/* ES5 15.4.4.16. */
-function ArrayEvery(callbackfn/*, thisArg*/) {
-    /* Step 1. */
-    var O = %ToObject(this);
-
-    /* Steps 2-3. */
-    var len = TO_UINT32(O.length);
-
-    /* Step 4. */
-    if (arguments.length === 0)
-        %ThrowError(JSMSG_MISSING_FUN_ARG, 0, 'Array.prototype.every');
-    if (!IsCallable(callbackfn))
-        %ThrowError(JSMSG_NOT_FUNCTION, callbackfn);
-
-    /* Step 5. */
-    var T = arguments.length > 1 ? arguments[1] : void 0;
-
-    /* Steps 6-7. */
-    /* Steps a (implicit), and d. */
-    for (var k = 0; k < len; k++) {
-        /* Step b */
-        if (k in O) {
-            /* Step c. */
-            if (!%_CallFunction(T, O[k], k, O, callbackfn))
-                return false;
-        }
-    }
-
-    /* Step 8. */
-    return true;
-}
-
-function ArrayStaticEvery(list, callbackfn/*, thisArg*/) {
-    if (arguments.length < 2)
-        %ThrowError(JSMSG_MISSING_FUN_ARG, 0, 'Array.every');
-    var T = arguments.length > 2 ? arguments[2] : void 0;
-    return %_CallFunction(list, callbackfn, T, ArrayEvery);
-}
-
-/* ES5 15.4.4.17. */
-function ArraySome(callbackfn/*, thisArg*/) {
-    /* Step 1. */
-    var O = %ToObject(this);
-
-    /* Steps 2-3. */
-    var len = TO_UINT32(O.length);
-
-    /* Step 4. */
-    if (arguments.length === 0)
-        %ThrowError(JSMSG_MISSING_FUN_ARG, 0, 'Array.prototype.some');
-    if (!IsCallable(callbackfn))
-        %ThrowError(JSMSG_NOT_FUNCTION, callbackfn);
-
-    /* Step 5. */
-    var T = arguments.length > 1 ? arguments[1] : void 0;
-
-    /* Steps 6-7. */
-    /* Steps a (implicit), and d. */
-    for (var k = 0; k < len; k++) {
-        /* Step b */
-        if (k in O) {
-            /* Step c. */
-            if (%_CallFunction(T, O[k], k, O, callbackfn))
-                return true;
-        }
-    }
-
-    /* Step 8. */
-    return false;
-}
-
-function ArrayStaticSome(list, callbackfn/*, thisArg*/) {
-    if (arguments.length < 2)
-        %ThrowError(JSMSG_MISSING_FUN_ARG, 0, 'Array.some');
-    var T = arguments.length > 2 ? arguments[2] : void 0;
-    return %_CallFunction(list, callbackfn, T, ArraySome);
-}
-
-/* ES5 15.4.4.18. */
-function ArrayForEach(callbackfn/*, thisArg*/) {
-    /* Step 1. */
-    var O = %ToObject(this);
-
-    /* Steps 2-3. */
-    var len = TO_UINT32(O.length);
-
-    /* Step 4. */
-    if (arguments.length === 0)
-        %ThrowError(JSMSG_MISSING_FUN_ARG, 0, 'Array.prototype.forEach');
-    if (!IsCallable(callbackfn))
-        %ThrowError(JSMSG_NOT_FUNCTION, callbackfn);
-
-    /* Step 5. */
-    var T = arguments.length > 1 ? arguments[1] : void 0;
-
-    /* Steps 6-7. */
-    /* Steps a (implicit), and d. */
-    for (var k = 0; k < len; k++) {
-        /* Step b */
-        if (k in O) {
-            /* Step c. */
-            %_CallFunction(T, O[k], k, O, callbackfn);
-        }
-    }
-
-    /* Step 8. */
-    return void 0;
-}
-
-function ArrayStaticForEach(list, callbackfn/*, thisArg*/) {
-    if (arguments.length < 2)
-        %ThrowError(JSMSG_MISSING_FUN_ARG, 0, 'Array.forEach');
-    var T = arguments.length > 2 ? arguments[2] : void 0;
-    %_CallFunction(list, callbackfn, T, ArrayForEach);
-}
-
-/* ES5 15.4.4.21. */
-function ArrayReduce(callbackfn/*, initialValue*/) {
-    /* Step 1. */
-    var O = %ToObject(this);
-
-    /* Steps 2-3. */
-    var len = TO_UINT32(O.length);
-
-    /* Step 4. */
-    if (arguments.length === 0)
-        %ThrowError(JSMSG_MISSING_FUN_ARG, 0, 'Array.prototype.reduce');
-    if (!IsCallable(callbackfn))
-        %ThrowError(JSMSG_NOT_FUNCTION, callbackfn);
-
-    /* Step 6. */
-    var k = 0;
-
-    /* Steps 5, 7-8. */
-    var accumulator;
-    if (arguments.length > 1) {
-        accumulator = arguments[1];
-    } else {
-        /* Step 5. */
-        if (len === 0)
-            %ThrowError(JSMSG_EMPTY_ARRAY_REDUCE);
-        var kPresent = false;
-        for (; k < len; k++) {
-            if (k in O) {
-                accumulator = O[k];
-                kPresent = true;
-                k++;
-                break;
-            }
-        }
-        if (!kPresent)
-            %ThrowError(JSMSG_EMPTY_ARRAY_REDUCE);
-    }
-
-    /* Step 9. */
-    /* Steps a (implicit), and d. */
-    for (; k < len; k++) {
-        /* Step b */
-        if (k in O) {
-            /* Step c. */
-            accumulator = callbackfn(accumulator, O[k], k, O);
-        }
-    }
-
-    /* Step 10. */
-    return accumulator;
-}
-
-function ArrayStaticReduce(list, callbackfn) {
-    if (arguments.length < 2)
-        %ThrowError(JSMSG_MISSING_FUN_ARG, 0, 'Array.reduce');
-    if (arguments.length > 2)
-        %_CallFunction(list, callbackfn, arguments[2], ArrayReduce);
-    else
-        %_CallFunction(list, callbackfn, ArrayReduce);
-}
-
-/* ES5 15.4.4.22. */
-function ArrayReduceRight(callbackfn/*, initialValue*/) {
-    /* Step 1. */
-    var O = %ToObject(this);
-
-    /* Steps 2-3. */
-    var len = TO_UINT32(O.length);
-
-    /* Step 4. */
-    if (arguments.length === 0)
-        %ThrowError(JSMSG_MISSING_FUN_ARG, 0, 'Array.prototype.reduce');
-    if (!IsCallable(callbackfn))
-        %ThrowError(JSMSG_NOT_FUNCTION, callbackfn);
-
-    /* Step 6. */
-    var k = len - 1;
-
-    /* Steps 5, 7-8. */
-    var accumulator;
-    if (arguments.length > 1) {
-        accumulator = arguments[1];
-    } else {
-        /* Step 5. */
-        if (len === 0)
-            %ThrowError(JSMSG_EMPTY_ARRAY_REDUCE);
-        var kPresent = false;
-        for (; k >= 0; k--) {
-            if (k in O) {
-                accumulator = O[k];
-                kPresent = true;
-                k--;
-                break;
-            }
-        }
-        if (!kPresent)
-            %ThrowError(JSMSG_EMPTY_ARRAY_REDUCE);
-    }
-
-    /* Step 9. */
-    /* Steps a (implicit), and d. */
-    for (; k >= 0; k--) {
-        /* Step b */
-        if (k in O) {
-            /* Step c. */
-            accumulator = callbackfn(accumulator, O[k], k, O);
-        }
-    }
-
-    /* Step 10. */
-    return accumulator;
-}
-
-function ArrayStaticReduceRight(list, callbackfn) {
-    if (arguments.length < 2)
-        %ThrowError(JSMSG_MISSING_FUN_ARG, 0, 'Array.reduceRight');
-    if (arguments.length > 2)
-        %_CallFunction(list, callbackfn, arguments[2], ArrayReduceRight);
-    else
-        %_CallFunction(list, callbackfn, ArrayReduceRight);
-}
+//this space intentionally left blank
\ No newline at end of file
--- a/js/src/frontend/BytecodeEmitter.cpp
+++ b/js/src/frontend/BytecodeEmitter.cpp
@@ -2660,17 +2660,17 @@ frontend::EmitFunctionScript(JSContext *
     bool singleton =
         cx->typeInferenceEnabled() &&
         bce->parent &&
         bce->parent->checkSingletonContext();
 
     /* Initialize fun->script() so that the debugger has a valid fun->script(). */
     RootedFunction fun(cx, bce->script->function());
     JS_ASSERT(fun->isInterpreted());
-    JS_ASSERT(!fun->hasScript());
+    JS_ASSERT(!fun->script().unsafeGet());
     fun->setScript(bce->script);
     if (!JSFunction::setTypeForScriptedFunction(cx, fun, singleton))
         return false;
 
     bce->tellDebuggerAboutCompiledScript(cx);
 
     return true;
 }
@@ -4830,17 +4830,17 @@ EmitFor(JSContext *cx, BytecodeEmitter *
 }
 
 static JS_NEVER_INLINE bool
 EmitFunc(JSContext *cx, BytecodeEmitter *bce, ParseNode *pn)
 {
     AssertCanGC();
     RootedFunction fun(cx, pn->pn_funbox->function());
     JS_ASSERT(fun->isInterpreted());
-    if (fun->hasScript()) {
+    if (fun->script().unsafeGet()) {
         /*
          * This second pass is needed to emit JSOP_NOP with a source note
          * for the already-emitted function definition prolog opcode. See
          * comments in EmitStatementList.
          */
         JS_ASSERT(pn->functionIsHoisted());
         JS_ASSERT(bce->sc->isFunction);
         return EmitFunctionDefNop(cx, bce, pn->pn_index);
--- a/js/src/jsapi.cpp
+++ b/js/src/jsapi.cpp
@@ -4990,18 +4990,18 @@ JS_DefineFunctions(JSContext *cx, JSObje
             if (!ctor) {
                 ctor = JS_GetConstructor(cx, obj);
                 if (!ctor)
                     return JS_FALSE;
             }
 
             flags &= ~JSFUN_GENERIC_NATIVE;
             JSFunction *fun = js_DefineFunction(cx, ctor, id, js_generic_native_method_dispatcher,
-                                                fs->nargs + 1, flags,
-                                                JSFunction::ExtendedFinalizeKind);
+                                    fs->nargs + 1, flags, NullPtr(),
+                                    JSFunction::ExtendedFinalizeKind);
             if (!fun)
                 return JS_FALSE;
 
             /*
              * As jsapi.h notes, fs must point to storage that lives as long
              * as fun->object lives.
              */
             fun->setExtendedSlot(0, PrivateValue(fs));
@@ -5012,36 +5012,29 @@ JS_DefineFunctions(JSContext *cx, JSObje
          * self-hosted functions, as that means we're currently setting up
          * the global object that that the self-hosted code is then compiled
          * in. Self-hosted functions can access each other via their names,
          * but not via the builtin classes they get installed into.
          */
         if (fs->selfHostedName && cx->runtime->isSelfHostedGlobal(cx->global()))
             return JS_TRUE;
 
-        /*
-         * Delay cloning self-hosted functions until they are called. This is
-         * achieved by passing js_DefineFunction a NULL JSNative which
-         * produces an interpreted JSFunction where !hasScript. Interpreted
-         * call paths then call InitializeLazyFunctionScript if !hasScript.
-         */
+        Rooted<PropertyName*> selfHostedPropertyName(cx);
         if (fs->selfHostedName) {
-            JSFunction *fun = js_DefineFunction(cx, obj, id, /* native = */ NULL, fs->nargs, 0,
-                                                JSFunction::ExtendedFinalizeKind);
-            if (!fun)
+            JSAtom *selfHostedAtom = Atomize(cx, fs->selfHostedName, strlen(fs->selfHostedName));
+            if (!selfHostedAtom)
                 return JS_FALSE;
-            fun->setIsSelfHostedBuiltin();
-            fun->setExtendedSlot(0, PrivateValue(fs));
-        } else {
-            JSFunction *fun = js_DefineFunction(cx, obj, id, fs->call.op, fs->nargs, flags);
-            if (!fun)
-                return JS_FALSE;
-            if (fs->call.info)
-                fun->setJitInfo(fs->call.info);
+            selfHostedPropertyName = selfHostedAtom->asPropertyName();
         }
+        JSFunction *fun = js_DefineFunction(cx, obj, id, fs->call.op, fs->nargs, flags,
+                                            selfHostedPropertyName);
+        if (!fun)
+            return JS_FALSE;
+        if (fs->call.info)
+            fun->setJitInfo(fs->call.info);
     }
     return JS_TRUE;
 }
 
 JS_PUBLIC_API(JSFunction *)
 JS_DefineFunction(JSContext *cx, JSObject *objArg, const char *name, JSNative call,
                   unsigned nargs, unsigned attrs)
 {
--- a/js/src/jsarray.cpp
+++ b/js/src/jsarray.cpp
@@ -2934,16 +2934,238 @@ array_slice(JSContext *cx, unsigned argc
         if (!hole && !SetArrayElement(cx, nobj, slot - begin, value))
             return JS_FALSE;
     }
 
     args.rval().setObject(*nobj);
     return JS_TRUE;
 }
 
+enum IndexOfKind {
+    IndexOf,
+    LastIndexOf
+};
+
+static JSBool
+array_indexOfHelper(JSContext *cx, IndexOfKind mode, CallArgs &args)
+{
+    uint32_t length, i, stop;
+    int direction;
+    JSBool hole;
+
+    RootedValue tosearch(cx), elt(cx);
+
+    RootedObject obj(cx, ToObject(cx, args.thisv()));
+    if (!obj)
+        return false;
+    if (!GetLengthProperty(cx, obj, &length))
+        return JS_FALSE;
+    if (length == 0)
+        goto not_found;
+
+    if (args.length() <= 1) {
+        i = (mode == LastIndexOf) ? length - 1 : 0;
+        tosearch = (args.length() != 0) ? args[0] : UndefinedValue();
+    } else {
+        double start;
+
+        tosearch = args[0];
+        if (!ToInteger(cx, args[1], &start))
+            return false;
+        if (start < 0) {
+            start += length;
+            if (start < 0) {
+                if (mode == LastIndexOf)
+                    goto not_found;
+                i = 0;
+            } else {
+                i = (uint32_t)start;
+            }
+        } else if (start >= length) {
+            if (mode == IndexOf)
+                goto not_found;
+            i = length - 1;
+        } else {
+            i = (uint32_t)start;
+        }
+    }
+
+    if (mode == LastIndexOf) {
+        stop = 0;
+        direction = -1;
+    } else {
+        stop = length - 1;
+        direction = 1;
+    }
+
+    for (;;) {
+        if (!JS_CHECK_OPERATION_LIMIT(cx) ||
+            !GetElement(cx, obj, (uint32_t)i, &hole, &elt)) {
+            return JS_FALSE;
+        }
+        if (!hole) {
+            bool equal;
+            if (!StrictlyEqual(cx, elt, tosearch, &equal))
+                return false;
+            if (equal) {
+                args.rval().setNumber(i);
+                return true;
+            }
+        }
+        if (i == stop)
+            goto not_found;
+        i += direction;
+    }
+
+  not_found:
+    args.rval().setInt32(-1);
+    return JS_TRUE;
+}
+
+static JSBool
+array_indexOf(JSContext *cx, unsigned argc, Value *vp)
+{
+    CallArgs args = CallArgsFromVp(argc, vp);
+    return array_indexOfHelper(cx, IndexOf, args);
+}
+
+static JSBool
+array_lastIndexOf(JSContext *cx, unsigned argc, Value *vp)
+{
+    CallArgs args = CallArgsFromVp(argc, vp);
+    return array_indexOfHelper(cx, LastIndexOf, args);
+}
+
+/* ECMA 15.4.4.16-15.4.4.18. */
+class ArrayForEachBehavior
+{
+  public:
+    static bool shouldExit(MutableHandleValue callbackRval, MutableHandleValue rval) { return false; }
+    static Value lateExitValue() { return UndefinedValue(); }
+};
+
+class ArrayEveryBehavior
+{
+  public:
+    static bool shouldExit(MutableHandleValue callbackRval, MutableHandleValue rval)
+    {
+        if (!ToBoolean(callbackRval)) {
+            rval.setBoolean(false);
+            return true;
+        }
+        return false;
+    }
+    static Value lateExitValue() { return BooleanValue(true); }
+};
+
+class ArraySomeBehavior
+{
+  public:
+    static bool shouldExit(MutableHandleValue callbackRval, MutableHandleValue rval)
+    {
+        if (ToBoolean(callbackRval)) {
+            rval.setBoolean(true);
+            return true;
+        }
+        return false;
+    }
+    static Value lateExitValue() { return BooleanValue(false); }
+};
+
+template <class Behavior>
+static inline bool
+array_readonlyCommon(JSContext *cx, CallArgs &args)
+{
+    /* Step 1. */
+    RootedObject obj(cx, ToObject(cx, args.thisv()));
+    if (!obj)
+        return false;
+
+    /* Step 2-3. */
+    uint32_t len;
+    if (!GetLengthProperty(cx, obj, &len))
+        return false;
+
+    /* Step 4. */
+    if (args.length() == 0) {
+        js_ReportMissingArg(cx, args.calleev(), 0);
+        return false;
+    }
+    RootedObject callable(cx, ValueToCallable(cx, &args[0]));
+    if (!callable)
+        return false;
+
+    /* Step 5. */
+    RootedValue thisv(cx, args.length() >= 2 ? args[1] : UndefinedValue());
+
+    /* Step 6. */
+    uint32_t k = 0;
+
+    /* Step 7. */
+    RootedValue kValue(cx);
+    FastInvokeGuard fig(cx, ObjectValue(*callable));
+    InvokeArgsGuard &ag = fig.args();
+    while (k < len) {
+        if (!JS_CHECK_OPERATION_LIMIT(cx))
+            return false;
+
+        /* Step a, b, and c.i. */
+        JSBool kNotPresent;
+        if (!GetElement(cx, obj, k, &kNotPresent, &kValue))
+            return false;
+
+        /* Step c.ii-iii. */
+        if (!kNotPresent) {
+            if (!ag.pushed() && !cx->stack.pushInvokeArgs(cx, 3, &ag))
+                return false;
+            ag.setCallee(ObjectValue(*callable));
+            ag.setThis(thisv);
+            ag[0] = kValue;
+            ag[1] = NumberValue(k);
+            ag[2] = ObjectValue(*obj);
+            if (!fig.invoke(cx))
+                return false;
+
+            if (Behavior::shouldExit(ag.rval(), args.rval()))
+                return true;
+        }
+
+        /* Step d. */
+        k++;
+    }
+
+    /* Step 8. */
+    args.rval().set(Behavior::lateExitValue());
+    return true;
+ }
+
+/* ES5 15.4.4.16. */
+static JSBool
+array_every(JSContext *cx, unsigned argc, Value *vp)
+{
+    CallArgs args = CallArgsFromVp(argc, vp);
+    return array_readonlyCommon<ArrayEveryBehavior>(cx, args);
+}
+
+/* ES5 15.4.4.17. */
+static JSBool
+array_some(JSContext *cx, unsigned argc, Value *vp)
+{
+    CallArgs args = CallArgsFromVp(argc, vp);
+    return array_readonlyCommon<ArraySomeBehavior>(cx, args);
+}
+
+/* ES5 15.4.4.18. */
+static JSBool
+array_forEach(JSContext *cx, unsigned argc, Value *vp)
+{
+    CallArgs args = CallArgsFromVp(argc, vp);
+    return array_readonlyCommon<ArrayForEachBehavior>(cx, args);
+}
+
 /* ES5 15.4.4.19. */
 static JSBool
 array_map(JSContext *cx, unsigned argc, Value *vp)
 {
     CallArgs args = CallArgsFromVp(argc, vp);
 
     /* Step 1. */
     RootedObject obj(cx, ToObject(cx, args.thisv()));
@@ -3096,16 +3318,147 @@ array_filter(JSContext *cx, unsigned arg
         k++;
     }
 
     /* Step 10. */
     args.rval().setObject(*arr);
     return true;
 }
 
+/* ES5 15.4.4.21-15.4.4.22. */
+class ArrayReduceBehavior
+{
+  public:
+    static void initialize(uint32_t len, uint32_t *start, uint32_t *end, int32_t *step)
+    {
+        *start = 0;
+        *step = 1;
+        *end = len;
+    }
+};
+
+class ArrayReduceRightBehavior
+{
+  public:
+    static void initialize(uint32_t len, uint32_t *start, uint32_t *end, int32_t *step)
+    {
+        *start = len - 1;
+        *step = -1;
+        /*
+         * We rely on (well defined) unsigned integer underflow to check our
+         * end condition after visiting the full range (including 0).
+         */
+        *end = UINT32_MAX;
+    }
+};
+
+template<class Behavior>
+static inline bool
+array_reduceCommon(JSContext *cx, CallArgs &args)
+{
+    /* Step 1. */
+    RootedObject obj(cx, ToObject(cx, args.thisv()));
+    if (!obj)
+        return false;
+
+    /* Step 2-3. */
+    uint32_t len;
+    if (!GetLengthProperty(cx, obj, &len))
+        return false;
+
+    /* Step 4. */
+    if (args.length() == 0) {
+        js_ReportMissingArg(cx, args.calleev(), 0);
+        return false;
+    }
+    RootedObject callable(cx, ValueToCallable(cx, &args[0]));
+    if (!callable)
+        return false;
+
+    /* Step 5. */
+    if (len == 0 && args.length() < 2) {
+        JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_EMPTY_ARRAY_REDUCE);
+        return false;
+    }
+
+    /* Step 6. */
+    uint32_t k, end;
+    int32_t step;
+    Behavior::initialize(len, &k, &end, &step);
+
+    /* Step 7-8. */
+    RootedValue accumulator(cx);
+    if (args.length() >= 2) {
+        accumulator = args[1];
+    } else {
+        JSBool kNotPresent = true;
+        while (kNotPresent && k != end) {
+            if (!GetElement(cx, obj, k, &kNotPresent, &accumulator))
+                return false;
+            k += step;
+        }
+        if (kNotPresent) {
+            JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_EMPTY_ARRAY_REDUCE);
+            return false;
+        }
+    }
+
+    /* Step 9. */
+    RootedValue kValue(cx);
+    FastInvokeGuard fig(cx, ObjectValue(*callable));
+    InvokeArgsGuard &ag = fig.args();
+    while (k != end) {
+        if (!JS_CHECK_OPERATION_LIMIT(cx))
+            return false;
+
+        /* Step a, b, and c.i. */
+        JSBool kNotPresent;
+        if (!GetElement(cx, obj, k, &kNotPresent, &kValue))
+            return false;
+
+        /* Step c.ii. */
+        if (!kNotPresent) {
+            if (!ag.pushed() && !cx->stack.pushInvokeArgs(cx, 4, &ag))
+                return false;
+            ag.setCallee(ObjectValue(*callable));
+            ag.setThis(UndefinedValue());
+            ag[0] = accumulator;
+            ag[1] = kValue;
+            ag[2] = NumberValue(k);
+            ag[3] = ObjectValue(*obj);
+            if (!fig.invoke(cx))
+                return false;
+            accumulator = ag.rval();
+        }
+
+        /* Step d. */
+        k += step;
+    }
+
+    /* Step 10. */
+    args.rval().set(accumulator);
+    return true;
+}
+
+/* ES5 15.4.4.21. */
+static JSBool
+array_reduce(JSContext *cx, unsigned argc, Value *vp)
+{
+    CallArgs args = CallArgsFromVp(argc, vp);
+    return array_reduceCommon<ArrayReduceBehavior>(cx, args);
+}
+
+/* ES5 15.4.4.22. */
+static JSBool
+array_reduceRight(JSContext *cx, unsigned argc, Value *vp)
+{
+    CallArgs args = CallArgsFromVp(argc, vp);
+    return array_reduceCommon<ArrayReduceRightBehavior>(cx, args);
+}
+
 static JSBool
 array_isArray(JSContext *cx, unsigned argc, Value *vp)
 {
     CallArgs args = CallArgsFromVp(argc, vp);
     bool isArray = args.length() > 0 && IsObjectWithClass(args[0], ESClass_Array, cx);
     args.rval().setBoolean(isArray);
     return true;
 }
@@ -3128,39 +3481,32 @@ static JSFunctionSpec array_methods[] = 
     JS_FN("shift",              array_shift,        0,JSFUN_GENERIC_NATIVE),
     JS_FN("unshift",            array_unshift,      1,JSFUN_GENERIC_NATIVE),
     JS_FN("splice",             array_splice,       2,JSFUN_GENERIC_NATIVE),
 
     /* Pythonic sequence methods. */
     JS_FN("concat",             array_concat,       1,JSFUN_GENERIC_NATIVE),
     JS_FN("slice",              array_slice,        2,JSFUN_GENERIC_NATIVE),
 
-         {"lastIndexOf",        {NULL, NULL},       1,0, "ArrayLastIndexOf"},
-         {"indexOf",            {NULL, NULL},       1,0, "ArrayIndexOf"},
-         {"forEach",            {NULL, NULL},       1,0, "ArrayForEach"},
+    JS_FN("indexOf",            array_indexOf,      1,JSFUN_GENERIC_NATIVE),
+    JS_FN("lastIndexOf",        array_lastIndexOf,  1,JSFUN_GENERIC_NATIVE),
+    JS_FN("forEach",            array_forEach,      1,JSFUN_GENERIC_NATIVE),
     JS_FN("map",                array_map,          1,JSFUN_GENERIC_NATIVE),
-         {"reduce",             {NULL, NULL},       1,0, "ArrayReduce"},
-         {"reduceRight",        {NULL, NULL},       1,0, "ArrayReduceRight"},
+    JS_FN("reduce",             array_reduce,       1,JSFUN_GENERIC_NATIVE),
+    JS_FN("reduceRight",        array_reduceRight,  1,JSFUN_GENERIC_NATIVE),
     JS_FN("filter",             array_filter,       1,JSFUN_GENERIC_NATIVE),
-         {"some",               {NULL, NULL},       1,0, "ArraySome"},
-         {"every",              {NULL, NULL},       1,0, "ArrayEvery"},
+    JS_FN("some",               array_some,         1,JSFUN_GENERIC_NATIVE),
+    JS_FN("every",              array_every,        1,JSFUN_GENERIC_NATIVE),
 
     JS_FN("iterator",           JS_ArrayIterator,   0,0),
     JS_FS_END
 };
 
 static JSFunctionSpec array_static_methods[] = {
     JS_FN("isArray",            array_isArray,      1,0),
-         {"lastIndexOf",        {NULL, NULL},       2,0, "ArrayStaticLastIndexOf"},
-         {"indexOf",            {NULL, NULL},       2,0, "ArrayStaticIndexOf"},
-         {"forEach",            {NULL, NULL},       2,0, "ArrayStaticForEach"},
-         {"every",              {NULL, NULL},       2,0, "ArrayStaticEvery"},
-         {"some",               {NULL, NULL},       2,0, "ArrayStaticSome"},
-         {"reduce",             {NULL, NULL},       2,0, "ArrayStaticReduce"},
-         {"reduceRight",        {NULL, NULL},       2,0, "ArrayStaticReduceRight"},
     JS_FS_END
 };
 
 /* ES5 15.4.2 */
 JSBool
 js_Array(JSContext *cx, unsigned argc, Value *vp)
 {
     CallArgs args = CallArgsFromVp(argc, vp);
--- a/js/src/jscntxt.cpp
+++ b/js/src/jscntxt.cpp
@@ -376,72 +376,52 @@ JSRuntime::initSelfHosting(JSContext *cx
 }
 
 void
 JSRuntime::markSelfHostedGlobal(JSTracer *trc)
 {
     MarkObjectRoot(trc, &selfHostedGlobal_, "self-hosting global");
 }
 
-bool
-JSRuntime::getUnclonedSelfHostedValue(JSContext *cx, Handle<PropertyName*> name,
-                                      MutableHandleValue vp)
+JSFunction *
+JSRuntime::getSelfHostedFunction(JSContext *cx, Handle<PropertyName*> name)
 {
-    RootedObject shg(cx, selfHostedGlobal_);
-    AutoCompartment ac(cx, shg);
-    return JS_GetPropertyById(cx, shg, NameToId(name), vp.address());
+    RootedObject holder(cx, cx->global()->getIntrinsicsHolder());
+    RootedId id(cx, NameToId(name));
+    RootedValue funVal(cx, NullValue());
+    if (!cloneSelfHostedValueById(cx, id, holder, &funVal))
+        return NULL;
+    return funVal.toObject().toFunction();
 }
 
 bool
-JSRuntime::cloneSelfHostedFunctionScript(JSContext *cx, Handle<PropertyName*> name,
-                                         Handle<JSFunction*> targetFun)
+JSRuntime::cloneSelfHostedValueById(JSContext *cx, HandleId id, HandleObject holder, MutableHandleValue vp)
 {
-    RootedValue funVal(cx);
-    if (!getUnclonedSelfHostedValue(cx, name, &funVal))
-        return false;
-
-    Rooted<JSScript*> sourceScript(cx, funVal.toObject().toFunction()->script());
-    JS_ASSERT(!sourceScript->enclosingStaticScope());
-    RawScript cscript = CloneScript(cx, NullPtr(), targetFun, sourceScript);
-    if (!cscript)
-        return false;
-    targetFun->setScript(cscript);
-    cscript->setFunction(targetFun);
-    if (!JSFunction::setTypeForScriptedFunction(cx, targetFun))
-        return false;
-
-    RootedValue targetFunVal(cx, OBJECT_TO_JSVAL(targetFun));
-    DebugOnly<bool> ok = JS_DefinePropertyById(cx, cx->global()->getIntrinsicsHolder(),
-                                               NameToId(name), targetFunVal, NULL, NULL, 0);
-    JS_ASSERT(ok);
-    return true;
-}
-
-bool
-JSRuntime::cloneSelfHostedValue(JSContext *cx, Handle<PropertyName*> name, HandleObject holder,
-                                MutableHandleValue vp)
-{
-    RootedValue funVal(cx);
-    if (!getUnclonedSelfHostedValue(cx, name, &funVal))
-        return false;
+    Value funVal;
+    {
+        RootedObject shg(cx, selfHostedGlobal_);
+        AutoCompartment ac(cx, shg);
+        if (!JS_GetPropertyById(cx, shg, id, &funVal) || !funVal.isObject())
+            return false;
+    }
 
     /*
      * We don't clone if we're operating in the self-hosting global, as that
      * means we're currently executing the self-hosting script while
      * initializing the runtime (see JSRuntime::initSelfHosting).
      */
     if (cx->global() == selfHostedGlobal_) {
-        vp.set(funVal);
+        vp.set(ObjectValue(funVal.toObject()));
     } else {
         RootedObject clone(cx, JS_CloneFunctionObject(cx,  &funVal.toObject(), cx->global()));
         if (!clone)
             return false;
         vp.set(ObjectValue(*clone));
     }
-    DebugOnly<bool> ok = JS_DefinePropertyById(cx, holder, NameToId(name), vp, NULL, NULL, 0);
+    DebugOnly<bool> ok = JS_DefinePropertyById(cx, holder, id, vp, NULL, NULL, 0);
     JS_ASSERT(ok);
     return true;
 }
 
 JSContext *
 js::NewContext(JSRuntime *rt, size_t stackChunkSize)
 {
     JS_AbortIfWrongThread(rt);
--- a/js/src/jscntxt.h
+++ b/js/src/jscntxt.h
@@ -530,22 +530,19 @@ struct JSRuntime : js::RuntimeFriendFiel
     }
 #endif
 
     bool initSelfHosting(JSContext *cx);
     void markSelfHostedGlobal(JSTracer *trc);
     bool isSelfHostedGlobal(js::HandleObject global) {
         return global == selfHostedGlobal_;
     }
-    bool getUnclonedSelfHostedValue(JSContext *cx, js::Handle<js::PropertyName*> name,
-                                    js::MutableHandleValue vp);
-    bool cloneSelfHostedFunctionScript(JSContext *cx, js::Handle<js::PropertyName*> name,
-                                       js::Handle<JSFunction*> targetFun);
-    bool cloneSelfHostedValue(JSContext *cx, js::Handle<js::PropertyName*> name,
-                              js::HandleObject holder, js::MutableHandleValue vp);
+    JSFunction *getSelfHostedFunction(JSContext *cx, js::Handle<js::PropertyName*> name);
+    bool cloneSelfHostedValueById(JSContext *cx, js::HandleId id, js::HandleObject holder,
+                                  js::MutableHandleValue vp);
 
     /* Base address of the native stack for the current thread. */
     uintptr_t           nativeStackBase;
 
     /* The native stack size limit that runtime should not exceed. */
     size_t              nativeStackQuota;
 
     /*
--- a/js/src/jsfriendapi.cpp
+++ b/js/src/jsfriendapi.cpp
@@ -397,17 +397,17 @@ js::DefineFunctionWithReserved(JSContext
     RootedObject obj(cx, objArg);
     JS_THREADSAFE_ASSERT(cx->compartment != cx->runtime->atomsCompartment);
     CHECK_REQUEST(cx);
     assertSameCompartment(cx, obj);
     JSAtom *atom = Atomize(cx, name, strlen(name));
     if (!atom)
         return NULL;
     Rooted<jsid> id(cx, AtomToId(atom));
-    return js_DefineFunction(cx, obj, id, call, nargs, attrs, JSFunction::ExtendedFinalizeKind);
+    return js_DefineFunction(cx, obj, id, call, nargs, attrs, NullPtr(), JSFunction::ExtendedFinalizeKind);
 }
 
 JS_FRIEND_API(JSFunction *)
 js::NewFunctionWithReserved(JSContext *cx, JSNative native, unsigned nargs, unsigned flags,
                             JSObject *parentArg, const char *name)
 {
     RootedObject parent(cx, parentArg);
     JS_THREADSAFE_ASSERT(cx->compartment != cx->runtime->atomsCompartment);
--- a/js/src/jsfun.cpp
+++ b/js/src/jsfun.cpp
@@ -321,18 +321,17 @@ fun_resolve(JSContext *cx, HandleObject 
         return true;
     }
 
     if (JSID_IS_ATOM(id, cx->names().length) || JSID_IS_ATOM(id, cx->names().name)) {
         JS_ASSERT(!IsInternalFunctionObject(obj));
 
         RootedValue v(cx);
         if (JSID_IS_ATOM(id, cx->names().length)) {
-            //FIXME: bug 810715 - deal with lazy interpreted functions with default args
-            uint16_t defaults = fun->hasScript() ? fun->script()->ndefaults : 0;
+            uint16_t defaults = fun->isInterpreted() ? fun->script()->ndefaults : 0;
             v.setInt32(fun->nargs - defaults - fun->hasRest());
         } else {
             v.setString(fun->atom() == NULL ?  cx->runtime->emptyString : fun->atom());
         }
 
         if (!DefineNativeProperty(cx, fun, id, v, JS_PropertyStub, JS_StrictPropertyStub,
                                   JSPROP_PERMANENT | JSPROP_READONLY, 0, 0)) {
             return false;
@@ -479,28 +478,16 @@ js::CloneInterpretedFunction(JSContext *
     if (!JSFunction::setTypeForScriptedFunction(cx, clone))
         return NULL;
 
     RootedScript cloneScript(cx, clone->script());
     js_CallNewScriptHook(cx, cloneScript, clone);
     return clone;
 }
 
-bool
-js::InitializeLazyFunctionScript(JSContext *cx, HandleFunction fun)
-{
-    JS_ASSERT(fun->isLazy());
-    JSFunctionSpec *fs = static_cast<JSFunctionSpec *>(fun->getExtendedSlot(0).toPrivate());
-    RootedAtom funAtom(cx, Atomize(cx, fs->selfHostedName, strlen(fs->selfHostedName)));
-    if (!funAtom)
-        return false;
-    Rooted<PropertyName *> funName(cx, funAtom->asPropertyName());
-    return cx->runtime->cloneSelfHostedFunctionScript(cx, funName, fun);
-}
-
 /*
  * [[HasInstance]] internal method for Function objects: fetch the .prototype
  * property of its 'this' parameter, and walks the prototype chain of v (only
  * if v is an object) returning true if .prototype is found.
  */
 static JSBool
 fun_hasInstance(JSContext *cx, HandleObject objArg, MutableHandleValue v, JSBool *bp)
 {
@@ -541,17 +528,17 @@ JSFunction::trace(JSTracer *trc)
         MarkValueRange(trc, ArrayLength(toExtended()->extendedSlots),
                        toExtended()->extendedSlots, "nativeReserved");
     }
 
     if (atom_)
         MarkString(trc, &atom_, "atom");
 
     if (isInterpreted()) {
-        if (hasScript())
+        if (u.i.script_)
             MarkScriptUnbarriered(trc, &u.i.script_, "script");
         if (u.i.env_)
             MarkObjectUnbarriered(trc, &u.i.env_, "fun_callscope");
     }
 }
 
 static void
 fun_trace(JSTracer *trc, RawObject obj)
@@ -632,27 +619,26 @@ FindBody(JSContext *cx, HandleFunction f
 
 JSString *
 js::FunctionToString(JSContext *cx, HandleFunction fun, bool bodyOnly, bool lambdaParen)
 {
     AssertCanGC();
     StringBuffer out(cx);
     RootedScript script(cx);
 
-    if (fun->hasScript()) {
+    if (fun->isInterpreted())
         script = fun->script();
-        if (script->isGeneratorExp) {
-            if ((!bodyOnly && !out.append("function genexp() {")) ||
-                !out.append("\n    [generator expression]\n") ||
-                (!bodyOnly && !out.append("}")))
-            {
-                return NULL;
-            }
-            return out.finishString();
+
+    if (fun->isInterpreted() && script->isGeneratorExp) {
+        if ((!bodyOnly && !out.append("function genexp() {")) ||
+            !out.append("\n    [generator expression]\n") ||
+            (!bodyOnly && !out.append("}"))) {
+            return NULL;
         }
+        return out.finishString();
     }
     if (!bodyOnly) {
         // If we're not in pretty mode, put parentheses around lambda functions.
         if (fun->isInterpreted() && !lambdaParen && fun->isLambda()) {
             if (!out.append("("))
                 return NULL;
         }
         if (!out.append("function "))
@@ -1133,17 +1119,17 @@ fun_isGenerator(JSContext *cx, unsigned 
 
     RawFunction fun;
     if (!IsFunctionObject(vp[1], &fun)) {
         JS_SET_RVAL(cx, vp, BooleanValue(false));
         return true;
     }
 
     bool result = false;
-    if (fun->hasScript()) {
+    if (fun->isInterpreted()) {
         RawScript script = fun->script().get(nogc);
         JS_ASSERT(script->length != 0);
         result = script->isGenerator;
     }
 
     JS_SET_RVAL(cx, vp, BooleanValue(result));
     return true;
 }
@@ -1539,16 +1525,17 @@ js_CloneFunctionObject(JSContext *cx, Ha
         /*
          * Across compartments we have to clone the script for interpreted
          * functions. Cross-compartment cloning only happens via JSAPI
          * (JS_CloneFunctionObject) which dynamically ensures that 'script' has
          * no enclosing lexical scope (only the global scope).
          */
         if (clone->isInterpreted()) {
             RootedScript script(cx, clone->script());
+            JS_ASSERT(script);
             JS_ASSERT(script->compartment() == fun->compartment());
             JS_ASSERT_IF(script->compartment() != cx->compartment,
                          !script->enclosingStaticScope());
 
             RootedObject scope(cx, script->enclosingStaticScope());
 
             clone->mutableScript().init(NULL);
 
@@ -1566,17 +1553,17 @@ js_CloneFunctionObject(JSContext *cx, Ha
             Debugger::onNewScript(cx, script, global);
         }
     }
     return clone;
 }
 
 JSFunction *
 js_DefineFunction(JSContext *cx, HandleObject obj, HandleId id, Native native,
-                  unsigned nargs, unsigned flags, AllocKind kind)
+                  unsigned nargs, unsigned flags, Handle<PropertyName*> selfHostedName, AllocKind kind)
 {
     PropertyOp gop;
     StrictPropertyOp sop;
 
     RootedFunction fun(cx);
 
     if (flags & JSFUN_STUB_GSOPS) {
         /*
@@ -1588,23 +1575,33 @@ js_DefineFunction(JSContext *cx, HandleO
         flags &= ~JSFUN_STUB_GSOPS;
         gop = JS_PropertyStub;
         sop = JS_StrictPropertyStub;
     } else {
         gop = NULL;
         sop = NULL;
     }
 
-    JSFunction::Flags funFlags;
-    if (!native)
-        funFlags = JSFunction::INTERPRETED;
-    else
-        funFlags = JSAPIToJSFunctionFlags(flags);
-    RootedAtom atom(cx, JSID_IS_ATOM(id) ? JSID_TO_ATOM(id) : NULL);
-    fun = js_NewFunction(cx, NullPtr(), native, nargs, funFlags, obj, atom, kind);
+    /*
+     * To support specifying both native and self-hosted functions using
+     * JSFunctionSpec, js_DefineFunction can be invoked with either native
+     * or selfHostedName set. It is assumed that selfHostedName is set if
+     * native isn't.
+     */
+    if (native) {
+        JS_ASSERT(!selfHostedName);
+        RootedAtom atom(cx, JSID_IS_ATOM(id) ? JSID_TO_ATOM(id) : NULL);
+        JSFunction::Flags funFlags = JSAPIToJSFunctionFlags(flags);
+        fun = js_NewFunction(cx, NullPtr(), native, nargs,
+                             funFlags, obj, atom, kind);
+    } else {
+        JS_ASSERT(!cx->runtime->isSelfHostedGlobal(cx->global()));
+        fun = cx->runtime->getSelfHostedFunction(cx, selfHostedName);
+        fun->initAtom(JSID_TO_ATOM(id));
+    }
     if (!fun)
         return NULL;
 
     RootedValue funVal(cx, ObjectValue(*fun));
     if (!JSObject::defineGeneric(cx, obj, id, funVal, gop, sop, flags & ~JSFUN_FLAGS_MASK))
         return NULL;
 
     return fun;
--- a/js/src/jsfun.h
+++ b/js/src/jsfun.h
@@ -79,18 +79,16 @@ struct JSFunction : public JSObject
     bool isNative()                 const { return !(flags & INTERPRETED); }
 
     /* Possible attributes of a native function: */
     bool isNativeConstructor()      const { return flags & NATIVE_CTOR; }
 
     /* Possible attributes of an interpreted function: */
     bool isHeavyweight()            const { return flags & HEAVYWEIGHT; }
     bool isFunctionPrototype()      const { return flags & IS_FUN_PROTO; }
-    bool isLazy()                   const { return isInterpreted() && !hasScript(); }
-    bool hasScript()                const { return isInterpreted() && u.i.script_; }
     bool isExprClosure()            const { return flags & EXPR_CLOSURE; }
     bool hasGuessedAtom()           const { return flags & HAS_GUESSED_ATOM; }
     bool isLambda()                 const { return flags & LAMBDA; }
     bool isSelfHostedBuiltin()      const { return flags & SELF_HOSTED; }
     bool isSelfHostedConstructor()  const { return flags & SELF_HOSTED_CTOR; }
     bool hasRest()                  const { return flags & HAS_REST; }
     bool hasDefaults()              const { return flags & HAS_DEFAULTS; }
 
@@ -164,17 +162,17 @@ struct JSFunction : public JSObject
     inline JSObject *environment() const;
     inline void setEnvironment(JSObject *obj);
     inline void initEnvironment(JSObject *obj);
 
     static inline size_t offsetOfEnvironment() { return offsetof(JSFunction, u.i.env_); }
     static inline size_t offsetOfAtom() { return offsetof(JSFunction, atom_); }
 
     js::Return<JSScript*> script() const {
-        JS_ASSERT(hasScript());
+        JS_ASSERT(isInterpreted());
         return JS::HandleScript::fromMarkedLocation(&u.i.script_);
     }
 
     js::HeapPtrScript &mutableScript() {
         JS_ASSERT(isInterpreted());
         return *(js::HeapPtrScript *)&u.i.script_;
     }
 
@@ -285,17 +283,17 @@ js_NewFunction(JSContext *cx, js::Handle
 
 extern JSFunction * JS_FASTCALL
 js_CloneFunctionObject(JSContext *cx, js::HandleFunction fun,
                        js::HandleObject parent, js::HandleObject proto,
                        js::gc::AllocKind kind = JSFunction::FinalizeKind);
 
 extern JSFunction *
 js_DefineFunction(JSContext *cx, js::HandleObject obj, js::HandleId id, JSNative native,
-                  unsigned nargs, unsigned flags,
+                  unsigned nargs, unsigned flags, js::Handle<js::PropertyName*> selfHostedName = JS::NullPtr(),
                   js::gc::AllocKind kind = JSFunction::FinalizeKind);
 
 namespace js {
 
 /*
  * Function extended with reserved slots for use by various kinds of functions.
  * Most functions do not have these extensions, but enough are that efficient
  * storage is required (no malloc'ed reserved slots).
@@ -331,19 +329,16 @@ JSString *FunctionToString(JSContext *cx
 template<XDRMode mode>
 bool
 XDRInterpretedFunction(XDRState<mode> *xdr, HandleObject enclosingScope,
                        HandleScript enclosingScript, MutableHandleObject objp);
 
 extern JSObject *
 CloneInterpretedFunction(JSContext *cx, HandleObject enclosingScope, HandleFunction fun);
 
-bool
-InitializeLazyFunctionScript(JSContext *cx, HandleFunction fun);
-
 /*
  * Report an error that call.thisv is not compatible with the specified class,
  * assuming that the method (clasp->name).prototype.<name of callee function>
  * is what was called.
  */
 extern void
 ReportIncompatibleMethod(JSContext *cx, CallReceiver call, Class *clasp);
 
--- a/js/src/jsinterp.cpp
+++ b/js/src/jsinterp.cpp
@@ -363,19 +363,16 @@ js::InvokeKernel(JSContext *cx, CallArgs
     }
 
     /* Invoke native functions. */
     RootedFunction fun(cx, callee.toFunction());
     JS_ASSERT_IF(construct, !fun->isNativeConstructor());
     if (fun->isNative())
         return CallJSNative(cx, fun->native(), args);
 
-    if (fun->isLazy() && !InitializeLazyFunctionScript(cx, fun))
-        return false;
-
     if (!TypeMonitorCall(cx, args, construct))
         return false;
 
     /* Get pointer to new frame/slots, prepare arguments. */
     InvokeFrameGuard ifg;
     if (!cx->stack.pushInvokeFrame(cx, args, initial, &ifg))
         return false;
 
@@ -2337,18 +2334,16 @@ BEGIN_CASE(JSOP_FUNCALL)
         DO_NEXT_OP(len);
     }
 
     if (!TypeMonitorCall(cx, args, construct))
         goto error;
 
     InitialFrameFlags initial = construct ? INITIAL_CONSTRUCT : INITIAL_NONE;
     bool newType = cx->typeInferenceEnabled() && UseNewType(cx, script, regs.pc);
-    if (fun->isLazy() && !InitializeLazyFunctionScript(cx, fun))
-        goto error;
     RawScript funScript = fun->script().unsafeGet();
     if (!cx->stack.pushInlineFrame(cx, regs, args, *fun, funScript, initial))
         goto error;
 
     SET_SCRIPT(regs.fp()->script());
 #ifdef JS_METHODJIT
     script->resetLoopCount();
 #endif
--- a/js/src/jsinterpinlines.h
+++ b/js/src/jsinterpinlines.h
@@ -1015,17 +1015,17 @@ class FastInvokeGuard
 #endif
     {
         initFunction(fval);
     }
 
     void initFunction(const Value &fval) {
         if (fval.isObject() && fval.toObject().isFunction()) {
             JSFunction *fun = fval.toObject().toFunction();
-            if (fun->hasScript()) {
+            if (fun->isInterpreted()) {
                 fun_ = fun;
                 script_ = fun->script();
             }
         }
     }
 
     InvokeArgsGuard &args() {
         return args_;
--- a/js/src/jsobj.cpp
+++ b/js/src/jsobj.cpp
@@ -5278,17 +5278,17 @@ dumpValue(const Value &v)
     else if (v.isObject() && v.toObject().isFunction()) {
         JSFunction *fun = v.toObject().toFunction();
         if (fun->displayAtom()) {
             fputs("<function ", stderr);
             FileEscapedString(stderr, fun->displayAtom(), 0);
         } else {
             fputs("<unnamed function", stderr);
         }
-        if (fun->hasScript()) {
+        if (fun->isInterpreted()) {
             JSScript *script = fun->script().get(nogc);
             fprintf(stderr, " (%s:%u)",
                     script->filename ? script->filename : "", script->lineno);
         }
         fprintf(stderr, " at %p>", (void *) fun);
     } else if (v.isObject()) {
         JSObject *obj = &v.toObject();
         Class *clasp = obj->getClass();
--- a/js/src/jsopcode.cpp
+++ b/js/src/jsopcode.cpp
@@ -1108,17 +1108,17 @@ js_NewPrinter(JSContext *cx, const char 
     jp->grouped = !!grouped;
     jp->strict = !!strict;
     jp->script = NULL;
     jp->dvgfence = NULL;
     jp->pcstack = NULL;
     jp->fun = fun;
     jp->localNames = NULL;
     jp->decompiledOpcodes = NULL;
-    if (fun && fun->hasScript()) {
+    if (fun && fun->isInterpreted()) {
         if (!SetPrinterLocalNames(cx, fun->script().unsafeGet(), jp)) {
             js_DestroyPrinter(jp);
             return NULL;
         }
     }
     return jp;
 }
 
--- a/js/src/jsscript.cpp
+++ b/js/src/jsscript.cpp
@@ -1836,28 +1836,30 @@ JSScript::isShortRunning()
            && getMaxLoopCount() < 40
 #endif
            ;
 }
 
 bool
 JSScript::enclosingScriptsCompiledSuccessfully() const
 {
+    AutoAssertNoGC nogc;
+
     /*
      * When a nested script is succesfully compiled, it is eagerly given the
      * static JSFunction of its enclosing script. The enclosing function's
      * 'script' field will be NULL until the enclosing script successfully
      * compiles. Thus, we can detect failed compilation by looking for
      * JSFunctions in the enclosingScope chain without scripts.
      */
     RawObject enclosing = enclosingScope_;
     while (enclosing) {
         if (enclosing->isFunction()) {
             RawFunction fun = enclosing->toFunction();
-            if (!fun->hasScript())
+            if (!fun->script().get(nogc))
                 return false;
             enclosing = fun->script()->enclosingScope_;
         } else {
             enclosing = enclosing->asStaticBlock().enclosingStaticScope();
         }
     }
     return true;
 }
--- a/js/src/jsstr.cpp
+++ b/js/src/jsstr.cpp
@@ -2361,17 +2361,17 @@ static JSObject *
 LambdaIsGetElem(JSObject &lambda)
 {
     AutoAssertNoGC nogc;
 
     if (!lambda.isFunction())
         return NULL;
 
     JSFunction *fun = lambda.toFunction();
-    if (!fun->hasScript())
+    if (!fun->isInterpreted())
         return NULL;
 
     RawScript script = fun->script().get(nogc);
     jsbytecode *pc = script->code;
 
     /*
      * JSOP_GETALIASEDVAR tells us exactly where to find the base object 'b'.
      * Rule out the (unlikely) possibility of a heavyweight function since it
--- a/js/src/methodjit/InvokeHelpers.cpp
+++ b/js/src/methodjit/InvokeHelpers.cpp
@@ -279,20 +279,16 @@ ShouldJaegerCompileCallee(JSContext *cx,
 static inline bool
 UncachedInlineCall(VMFrame &f, InitialFrameFlags initial,
                    void **pret, bool *unjittable, uint32_t argc)
 {
     AssertCanGC();
     JSContext *cx = f.cx;
     CallArgs args = CallArgsFromSp(argc, f.regs.sp);
     RootedFunction newfun(cx, args.callee().toFunction());
-
-    if (newfun->isLazy() && !InitializeLazyFunctionScript(cx, newfun))
-        return false;
-
     RootedScript newscript(cx, newfun->script());
 
     bool construct = InitialFrameFlagsAreConstructing(initial);
 
     RootedScript fscript(cx, f.script());
     bool newType = construct && cx->typeInferenceEnabled() &&
         types::UseNewType(cx, fscript, f.pc());
 
--- a/js/src/shell/js.cpp
+++ b/js/src/shell/js.cpp
@@ -2207,17 +2207,17 @@ Clone(JSContext *cx, unsigned argc, jsva
             JSFunction *fun = JS_ValueToFunction(cx, argv[0]);
             if (!fun)
                 return false;
             funobj = JS_GetFunctionObject(fun);
         }
     }
     if (funobj->compartment() != cx->compartment) {
         JSFunction *fun = funobj->toFunction();
-        if (fun->hasScript() && fun->script()->compileAndGo) {
+        if (fun->isInterpreted() && fun->script()->compileAndGo) {
             JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_UNEXPECTED_TYPE,
                                  "function", "compile-and-go");
             return false;
         }
     }
 
     if (argc > 1) {
         if (!JS_ValueToObject(cx, argv[1], parent.address()))
--- a/js/src/vm/GlobalObject.h
+++ b/js/src/vm/GlobalObject.h
@@ -387,18 +387,23 @@ class GlobalObject : public JSObject
         return HasDataProperty(cx, self, NameToId(name), &fun);
     }
 
     bool getIntrinsicValue(JSContext *cx, PropertyName *name, MutableHandleValue value) {
         RootedObject holder(cx, &getSlotRef(INTRINSICS).toObject());
         RootedId id(cx, NameToId(name));
         if (HasDataProperty(cx, holder, id, value.address()))
             return true;
-        Rooted<PropertyName*> rootedName(cx, name);
-        return cx->runtime->cloneSelfHostedValue(cx, rootedName, holder, value);
+        bool ok = cx->runtime->cloneSelfHostedValueById(cx, id, holder, value);
+        if (!ok)
+            return false;
+
+        ok = JS_DefinePropertyById(cx, holder, id, value, NULL, NULL, 0);
+        JS_ASSERT(ok);
+        return true;
     }
 
     inline RegExpStatics *getRegExpStatics() const;
 
     JSObject *getThrowTypeError() const {
         JS_ASSERT(functionObjectClassesInitialized());
         return &getSlot(THROWTYPEERROR).toObject();
     }