Merge m-c to m-i
authorPhil Ringnalda <philringnalda@gmail.com>
Tue, 13 Nov 2012 22:18:42 -0800
changeset 113199 2b66b88a0b0f77ea7c5b2c5b0d580ce515dca65c
parent 113198 f539adf0d8a9937c75c344e1faf76b8cdf4630c1 (current diff)
parent 113132 dd68409d78108158a2b9d0f3d3cbba23cf709ecc (diff)
child 113200 2e813df0aca119da2e9e2f9d61c3762e1599f3cc
push idunknown
push userunknown
push dateunknown
milestone19.0a1
Merge m-c to m-i
js/src/jscntxt.h
js/src/jsfun.cpp
js/src/jsinterpinlines.h
js/src/jsscript.cpp
--- 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
@@ -533,22 +533,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();
     }