Back out 3da143341145 (bug 784294) and 862f9cd7eb0b (bug 791850) for breaking Jetpack

This commit is contained in:
Phil Ringnalda 2012-11-13 22:08:22 -08:00
parent f7ae30d43f
commit 0b198716f3
18 changed files with 444 additions and 475 deletions

View File

@ -1,338 +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

View File

@ -2665,7 +2665,7 @@ frontend::EmitFunctionScript(JSContext *cx, BytecodeEmitter *bce, ParseNode *bod
/* 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;
@ -4835,7 +4835,7 @@ 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

View File

@ -4995,8 +4995,8 @@ JS_DefineFunctions(JSContext *cx, JSObject *objArg, JSFunctionSpec *fs)
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;
@ -5017,26 +5017,19 @@ JS_DefineFunctions(JSContext *cx, JSObject *objArg, JSFunctionSpec *fs)
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;
}

View File

@ -2939,6 +2939,228 @@ array_slice(JSContext *cx, unsigned argc, Value *vp)
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)
@ -3101,6 +3323,137 @@ array_filter(JSContext *cx, unsigned argc, Value *vp)
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)
{
@ -3133,15 +3486,15 @@ static JSFunctionSpec array_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
@ -3149,13 +3502,6 @@ static JSFunctionSpec array_methods[] = {
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
};

View File

@ -381,47 +381,27 @@ 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
@ -429,14 +409,14 @@ JSRuntime::cloneSelfHostedValue(JSContext *cx, Handle<PropertyName*> name, Handl
* 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;
}

View File

@ -535,12 +535,9 @@ struct JSRuntime : js::RuntimeFriendFields
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;

View File

@ -402,7 +402,7 @@ js::DefineFunctionWithReserved(JSContext *cx, JSObject *objArg, const char *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 *)

View File

@ -326,8 +326,7 @@ fun_resolve(JSContext *cx, HandleObject obj, HandleId id, unsigned flags,
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());
@ -484,18 +483,6 @@ js::CloneInterpretedFunction(JSContext *cx, HandleObject enclosingScope, HandleF
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
@ -546,7 +533,7 @@ JSFunction::trace(JSTracer *trc)
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");
@ -637,17 +624,16 @@ js::FunctionToString(JSContext *cx, HandleFunction fun, bool bodyOnly, bool lamb
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.
@ -1138,7 +1124,7 @@ fun_isGenerator(JSContext *cx, unsigned argc, Value *vp)
}
bool result = false;
if (fun->hasScript()) {
if (fun->isInterpreted()) {
RawScript script = fun->script().get(nogc);
JS_ASSERT(script->length != 0);
result = script->isGenerator;
@ -1544,6 +1530,7 @@ js_CloneFunctionObject(JSContext *cx, HandleFunction fun, HandleObject parent,
*/
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());
@ -1571,7 +1558,7 @@ js_CloneFunctionObject(JSContext *cx, HandleFunction fun, HandleObject parent,
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;
@ -1593,13 +1580,23 @@ js_DefineFunction(JSContext *cx, HandleObject obj, HandleId id, Native native,
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;

View File

@ -84,8 +84,6 @@ struct JSFunction : public JSObject
/* 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; }
@ -169,7 +167,7 @@ struct JSFunction : public JSObject
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_);
}
@ -290,7 +288,7 @@ js_CloneFunctionObject(JSContext *cx, js::HandleFunction fun,
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 {
@ -336,9 +334,6 @@ XDRInterpretedFunction(XDRState<mode> *xdr, HandleObject enclosingScope,
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>

View File

@ -368,9 +368,6 @@ js::InvokeKernel(JSContext *cx, CallArgs args, MaybeConstruct construct)
if (fun->isNative())
return CallJSNative(cx, fun->native(), args);
if (fun->isLazy() && !InitializeLazyFunctionScript(cx, fun))
return false;
if (!TypeMonitorCall(cx, args, construct))
return false;
@ -2342,8 +2339,6 @@ BEGIN_CASE(JSOP_FUNCALL)
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;

View File

@ -1020,7 +1020,7 @@ class FastInvokeGuard
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();
}

View File

@ -5283,7 +5283,7 @@ dumpValue(const Value &v)
} 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);

View File

@ -1113,7 +1113,7 @@ js_NewPrinter(JSContext *cx, const char *name, JSFunction *fun,
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;

View File

@ -1841,6 +1841,8 @@ JSScript::isShortRunning()
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
@ -1852,7 +1854,7 @@ JSScript::enclosingScriptsCompiledSuccessfully() const
while (enclosing) {
if (enclosing->isFunction()) {
RawFunction fun = enclosing->toFunction();
if (!fun->hasScript())
if (!fun->script().get(nogc))
return false;
enclosing = fun->script()->enclosingScope_;
} else {

View File

@ -2366,7 +2366,7 @@ LambdaIsGetElem(JSObject &lambda)
return NULL;
JSFunction *fun = lambda.toFunction();
if (!fun->hasScript())
if (!fun->isInterpreted())
return NULL;
RawScript script = fun->script().get(nogc);

View File

@ -284,10 +284,6 @@ UncachedInlineCall(VMFrame &f, InitialFrameFlags initial,
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);

View File

@ -2212,7 +2212,7 @@ Clone(JSContext *cx, unsigned argc, jsval *vp)
}
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;

View File

@ -392,8 +392,13 @@ class GlobalObject : public JSObject
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;