author | Phil 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 id | 17996 |
push user | philringnalda@gmail.com |
push date | Wed, 14 Nov 2012 06:19:06 +0000 |
treeherder | mozilla-inbound@2b66b88a0b0f [default view] [failures only] |
perfherder | [talos] [build metrics] [platform microbench] (compared to previous push) |
bugs | 784294, 791850 |
milestone | 19.0a1 |
backs out | 3da143341145b12a1a42b46b1d669731f096436f |
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
19.0a1
/
20121114030718
/
pushlog to previous
nightly linux64
19.0a1
/
20121114030718
/
pushlog to previous
nightly mac
19.0a1
/
20121114030718
/
pushlog to previous
nightly win32
19.0a1
/
20121114030718
/
pushlog to previous
nightly win64
19.0a1
/
20121114030718
/
pushlog to previous
|
--- 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(); }