mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
bug 505460 - preallocating reserved slots. r=brendan
This commit is contained in:
parent
a590e2793e
commit
1fcf4af3b3
@ -4354,13 +4354,10 @@ JS_CloneFunctionObject(JSContext *cx, JSObject *funobj, JSObject *parent)
|
|||||||
*/
|
*/
|
||||||
if (FUN_FLAT_CLOSURE(fun)) {
|
if (FUN_FLAT_CLOSURE(fun)) {
|
||||||
JS_ASSERT(funobj->dslots);
|
JS_ASSERT(funobj->dslots);
|
||||||
JS_ASSERT(JSSLOT_FREE(&js_FunctionClass) == JS_INITIAL_NSLOTS);
|
if (!js_EnsureReservedSlots(cx, clone,
|
||||||
|
fun->countInterpretedReserveSlots())) {
|
||||||
uint32 nslots = JSSLOT_FREE(&js_FunctionClass);
|
|
||||||
JS_ASSERT(nslots == JS_INITIAL_NSLOTS);
|
|
||||||
nslots += js_FunctionClass.reserveSlots(cx, clone);
|
|
||||||
if (!js_AllocSlots(cx, clone, nslots))
|
|
||||||
return NULL;
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
JSUpvarArray *uva = JS_SCRIPT_UPVARS(fun->u.i.script);
|
JSUpvarArray *uva = JS_SCRIPT_UPVARS(fun->u.i.script);
|
||||||
JS_ASSERT(uva->length <= size_t(clone->dslots[-1]));
|
JS_ASSERT(uva->length <= size_t(clone->dslots[-1]));
|
||||||
|
@ -897,8 +897,10 @@ js_GetCallObject(JSContext *cx, JSStackFrame *fp)
|
|||||||
}
|
}
|
||||||
|
|
||||||
callobj = js_NewObjectWithGivenProto(cx, &js_CallClass, NULL, fp->scopeChain);
|
callobj = js_NewObjectWithGivenProto(cx, &js_CallClass, NULL, fp->scopeChain);
|
||||||
if (!callobj)
|
if (!callobj ||
|
||||||
|
!js_EnsureReservedSlots(cx, callobj, fp->fun->countArgsAndVars())) {
|
||||||
return NULL;
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
JS_SetPrivate(cx, callobj, fp);
|
JS_SetPrivate(cx, callobj, fp);
|
||||||
JS_ASSERT(fp->fun == GET_FUNCTION_PRIVATE(cx, fp->callee));
|
JS_ASSERT(fp->fun == GET_FUNCTION_PRIVATE(cx, fp->callee));
|
||||||
@ -936,7 +938,6 @@ js_PutCallObject(JSContext *cx, JSStackFrame *fp)
|
|||||||
JSBool ok;
|
JSBool ok;
|
||||||
JSFunction *fun;
|
JSFunction *fun;
|
||||||
uintN n;
|
uintN n;
|
||||||
JSScope *scope;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Since for a call object all fixed slots happen to be taken, we can copy
|
* Since for a call object all fixed slots happen to be taken, we can copy
|
||||||
@ -965,26 +966,15 @@ js_PutCallObject(JSContext *cx, JSStackFrame *fp)
|
|||||||
JS_ASSERT(fun == GetCallObjectFunction(callobj));
|
JS_ASSERT(fun == GetCallObjectFunction(callobj));
|
||||||
n = fun->countArgsAndVars();
|
n = fun->countArgsAndVars();
|
||||||
if (n != 0) {
|
if (n != 0) {
|
||||||
JS_LOCK_OBJ(cx, callobj);
|
|
||||||
n += JS_INITIAL_NSLOTS;
|
n += JS_INITIAL_NSLOTS;
|
||||||
if (n > STOBJ_NSLOTS(callobj))
|
JS_LOCK_OBJ(cx, callobj);
|
||||||
ok &= js_GrowSlots(cx, callobj, n);
|
memcpy(callobj->dslots, fp->argv, fun->nargs * sizeof(jsval));
|
||||||
scope = OBJ_SCOPE(callobj);
|
memcpy(callobj->dslots + fun->nargs, fp->slots,
|
||||||
if (ok) {
|
fun->u.i.nvars * sizeof(jsval));
|
||||||
memcpy(callobj->dslots, fp->argv, fun->nargs * sizeof(jsval));
|
JS_UNLOCK_OBJ(cx, callobj);
|
||||||
memcpy(callobj->dslots + fun->nargs, fp->slots,
|
|
||||||
fun->u.i.nvars * sizeof(jsval));
|
|
||||||
if (scope->owned() && n > scope->freeslot)
|
|
||||||
scope->freeslot = n;
|
|
||||||
}
|
|
||||||
JS_UNLOCK_SCOPE(cx, scope);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/* Clear private pointers to fp, which is about to go away (js_Invoke). */
|
||||||
* Clear private pointers to fp, which is about to go away (js_Invoke).
|
|
||||||
* Do this last because js_GetProperty calls above need to follow the
|
|
||||||
* call object's private slot to find fp.
|
|
||||||
*/
|
|
||||||
if ((fun->flags & JSFUN_LAMBDA) && fun->atom) {
|
if ((fun->flags & JSFUN_LAMBDA) && fun->atom) {
|
||||||
JSObject *env = STOBJ_GET_PARENT(callobj);
|
JSObject *env = STOBJ_GET_PARENT(callobj);
|
||||||
|
|
||||||
@ -1847,26 +1837,31 @@ fun_finalize(JSContext *cx, JSObject *obj)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint32
|
||||||
|
JSFunction::countInterpretedReserveSlots() const
|
||||||
|
{
|
||||||
|
JS_ASSERT(FUN_INTERPRETED(this));
|
||||||
|
|
||||||
|
uint32 nslots = (u.i.nupvars == 0)
|
||||||
|
? 0
|
||||||
|
: JS_SCRIPT_UPVARS(u.i.script)->length;
|
||||||
|
if (u.i.script->regexpsOffset != 0)
|
||||||
|
nslots += JS_SCRIPT_REGEXPS(u.i.script)->length;
|
||||||
|
return nslots;
|
||||||
|
}
|
||||||
|
|
||||||
static uint32
|
static uint32
|
||||||
fun_reserveSlots(JSContext *cx, JSObject *obj)
|
fun_reserveSlots(JSContext *cx, JSObject *obj)
|
||||||
{
|
{
|
||||||
JSFunction *fun;
|
|
||||||
uint32 nslots;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* We use JS_GetPrivate and not GET_FUNCTION_PRIVATE because during
|
* We use JS_GetPrivate and not GET_FUNCTION_PRIVATE because during
|
||||||
* js_InitFunctionClass invocation the function is called before the
|
* js_InitFunctionClass invocation the function is called before the
|
||||||
* private slot of the function object is set.
|
* private slot of the function object is set.
|
||||||
*/
|
*/
|
||||||
fun = (JSFunction *) JS_GetPrivate(cx, obj);
|
JSFunction *fun = (JSFunction *) JS_GetPrivate(cx, obj);
|
||||||
nslots = 0;
|
return (fun && FUN_INTERPRETED(fun))
|
||||||
if (fun && FUN_INTERPRETED(fun) && fun->u.i.script) {
|
? fun->countInterpretedReserveSlots()
|
||||||
if (fun->u.i.nupvars != 0)
|
: 0;
|
||||||
nslots = JS_SCRIPT_UPVARS(fun->u.i.script)->length;
|
|
||||||
if (fun->u.i.script->regexpsOffset != 0)
|
|
||||||
nslots += JS_SCRIPT_REGEXPS(fun->u.i.script)->length;
|
|
||||||
}
|
|
||||||
return nslots;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -2509,16 +2504,20 @@ js_AllocFlatClosure(JSContext *cx, JSFunction *fun, JSObject *scopeChain)
|
|||||||
? JS_SCRIPT_UPVARS(fun->u.i.script)->length
|
? JS_SCRIPT_UPVARS(fun->u.i.script)->length
|
||||||
: 0) == fun->u.i.nupvars);
|
: 0) == fun->u.i.nupvars);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Assert that fun->countInterpretedReserveSlots returns 0 when
|
||||||
|
* fun->u.i.nupvars is zero.
|
||||||
|
*/
|
||||||
|
JS_ASSERT(fun->u.i.script->regexpsOffset == 0);
|
||||||
|
|
||||||
JSObject *closure = js_CloneFunctionObject(cx, fun, scopeChain);
|
JSObject *closure = js_CloneFunctionObject(cx, fun, scopeChain);
|
||||||
if (!closure || fun->u.i.nupvars == 0)
|
if (!closure || fun->u.i.nupvars == 0)
|
||||||
return closure;
|
return closure;
|
||||||
|
if (!js_EnsureReservedSlots(cx, closure,
|
||||||
uint32 nslots = JSSLOT_FREE(&js_FunctionClass);
|
fun->countInterpretedReserveSlots())) {
|
||||||
JS_ASSERT(nslots == JS_INITIAL_NSLOTS);
|
|
||||||
nslots += fun_reserveSlots(cx, closure);
|
|
||||||
if (!js_GrowSlots(cx, closure, nslots))
|
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
|
}
|
||||||
return closure;
|
return closure;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -162,7 +162,6 @@ struct JSFunction {
|
|||||||
} u;
|
} u;
|
||||||
JSAtom *atom; /* name for diagnostics and decompiling */
|
JSAtom *atom; /* name for diagnostics and decompiling */
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
bool optimizedClosure() { return FUN_KIND(this) > JSFUN_INTERPRETED; }
|
bool optimizedClosure() { return FUN_KIND(this) > JSFUN_INTERPRETED; }
|
||||||
bool needsWrapper() { return FUN_NULL_CLOSURE(this) && u.i.skipmin != 0; }
|
bool needsWrapper() { return FUN_NULL_CLOSURE(this) && u.i.skipmin != 0; }
|
||||||
|
|
||||||
@ -180,7 +179,8 @@ struct JSFunction {
|
|||||||
JS_ASSERT(FUN_INTERPRETED(this));
|
JS_ASSERT(FUN_INTERPRETED(this));
|
||||||
return countLocalNames() != 0;
|
return countLocalNames() != 0;
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
uint32 countInterpretedReserveSlots() const;
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -2011,6 +2011,9 @@ static JSFunctionSpec object_static_methods[] = {
|
|||||||
JS_FS_END
|
JS_FS_END
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static bool
|
||||||
|
AllocSlots(JSContext *cx, JSObject *obj, size_t nslots);
|
||||||
|
|
||||||
static inline bool
|
static inline bool
|
||||||
InitScopeForObject(JSContext* cx, JSObject* obj, JSObject* proto, JSObjectOps* ops)
|
InitScopeForObject(JSContext* cx, JSObject* obj, JSObject* proto, JSObjectOps* ops)
|
||||||
{
|
{
|
||||||
@ -2032,7 +2035,7 @@ InitScopeForObject(JSContext* cx, JSObject* obj, JSObject* proto, JSObjectOps* o
|
|||||||
/* Let JSScope::create set freeslot so as to reserve slots. */
|
/* Let JSScope::create set freeslot so as to reserve slots. */
|
||||||
JS_ASSERT(scope->freeslot >= JSSLOT_PRIVATE);
|
JS_ASSERT(scope->freeslot >= JSSLOT_PRIVATE);
|
||||||
if (scope->freeslot > JS_INITIAL_NSLOTS &&
|
if (scope->freeslot > JS_INITIAL_NSLOTS &&
|
||||||
!js_AllocSlots(cx, obj, scope->freeslot)) {
|
!AllocSlots(cx, obj, scope->freeslot)) {
|
||||||
JSScope::destroy(cx, scope);
|
JSScope::destroy(cx, scope);
|
||||||
goto bad;
|
goto bad;
|
||||||
}
|
}
|
||||||
@ -2600,7 +2603,7 @@ js_PutBlockObject(JSContext *cx, JSBool normalUnwind)
|
|||||||
if (normalUnwind && count > 1) {
|
if (normalUnwind && count > 1) {
|
||||||
--count;
|
--count;
|
||||||
JS_LOCK_OBJ(cx, obj);
|
JS_LOCK_OBJ(cx, obj);
|
||||||
if (!js_AllocSlots(cx, obj, JS_INITIAL_NSLOTS + count))
|
if (!AllocSlots(cx, obj, JS_INITIAL_NSLOTS + count))
|
||||||
normalUnwind = JS_FALSE;
|
normalUnwind = JS_FALSE;
|
||||||
else
|
else
|
||||||
memcpy(obj->dslots, fp->slots + depth + 1, count * sizeof(jsval));
|
memcpy(obj->dslots, fp->slots + depth + 1, count * sizeof(jsval));
|
||||||
@ -2976,8 +2979,8 @@ bad:
|
|||||||
(JS_ASSERT((words) > 1), (words) - 1 + JS_INITIAL_NSLOTS)
|
(JS_ASSERT((words) > 1), (words) - 1 + JS_INITIAL_NSLOTS)
|
||||||
|
|
||||||
|
|
||||||
bool
|
static bool
|
||||||
js_AllocSlots(JSContext *cx, JSObject *obj, size_t nslots)
|
AllocSlots(JSContext *cx, JSObject *obj, size_t nslots)
|
||||||
{
|
{
|
||||||
JS_ASSERT(!obj->dslots);
|
JS_ASSERT(!obj->dslots);
|
||||||
JS_ASSERT(nslots > JS_INITIAL_NSLOTS);
|
JS_ASSERT(nslots > JS_INITIAL_NSLOTS);
|
||||||
@ -3037,7 +3040,7 @@ js_GrowSlots(JSContext *cx, JSObject *obj, size_t nslots)
|
|||||||
*/
|
*/
|
||||||
jsval* slots = obj->dslots;
|
jsval* slots = obj->dslots;
|
||||||
if (!slots)
|
if (!slots)
|
||||||
return js_AllocSlots(cx, obj, nslots);
|
return AllocSlots(cx, obj, nslots);
|
||||||
|
|
||||||
size_t oslots = size_t(slots[-1]);
|
size_t oslots = size_t(slots[-1]);
|
||||||
|
|
||||||
@ -3076,6 +3079,28 @@ js_ShrinkSlots(JSContext *cx, JSObject *obj, size_t nslots)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
js_EnsureReservedSlots(JSContext *cx, JSObject *obj, size_t nreserved)
|
||||||
|
{
|
||||||
|
JS_ASSERT(OBJ_IS_NATIVE(obj));
|
||||||
|
JS_ASSERT(!obj->dslots);
|
||||||
|
|
||||||
|
uintN nslots = JSSLOT_FREE(STOBJ_GET_CLASS(obj)) + nreserved;
|
||||||
|
if (nslots > STOBJ_NSLOTS(obj) && !AllocSlots(cx, obj, nslots))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
JSScope *scope = OBJ_SCOPE(obj);
|
||||||
|
if (scope->owned()) {
|
||||||
|
#ifdef JS_THREADSAFE
|
||||||
|
JS_ASSERT(scope->title.ownercx->thread == cx->thread);
|
||||||
|
#endif
|
||||||
|
JS_ASSERT(scope->freeslot == JSSLOT_FREE(STOBJ_GET_CLASS(obj)));
|
||||||
|
if (scope->freeslot < nslots)
|
||||||
|
scope->freeslot = nslots;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
extern JSBool
|
extern JSBool
|
||||||
js_GetClassId(JSContext *cx, JSClass *clasp, jsid *idp)
|
js_GetClassId(JSContext *cx, JSClass *clasp, jsid *idp)
|
||||||
{
|
{
|
||||||
@ -5863,7 +5888,7 @@ js_SetRequiredSlot(JSContext *cx, JSObject *obj, uint32 slot, jsval v)
|
|||||||
if (clasp->reserveSlots)
|
if (clasp->reserveSlots)
|
||||||
nslots += clasp->reserveSlots(cx, obj);
|
nslots += clasp->reserveSlots(cx, obj);
|
||||||
JS_ASSERT(slot < nslots);
|
JS_ASSERT(slot < nslots);
|
||||||
if (!js_AllocSlots(cx, obj, nslots)) {
|
if (!AllocSlots(cx, obj, nslots)) {
|
||||||
JS_UNLOCK_SCOPE(cx, scope);
|
JS_UNLOCK_SCOPE(cx, scope);
|
||||||
return JS_FALSE;
|
return JS_FALSE;
|
||||||
}
|
}
|
||||||
|
@ -578,9 +578,6 @@ js_AllocSlot(JSContext *cx, JSObject *obj, uint32 *slotp);
|
|||||||
extern void
|
extern void
|
||||||
js_FreeSlot(JSContext *cx, JSObject *obj, uint32 slot);
|
js_FreeSlot(JSContext *cx, JSObject *obj, uint32 slot);
|
||||||
|
|
||||||
extern bool
|
|
||||||
js_AllocSlots(JSContext *cx, JSObject *obj, size_t nslots);
|
|
||||||
|
|
||||||
extern bool
|
extern bool
|
||||||
js_GrowSlots(JSContext *cx, JSObject *obj, size_t nslots);
|
js_GrowSlots(JSContext *cx, JSObject *obj, size_t nslots);
|
||||||
|
|
||||||
@ -594,6 +591,17 @@ js_FreeSlots(JSContext *cx, JSObject *obj)
|
|||||||
js_ShrinkSlots(cx, obj, 0);
|
js_ShrinkSlots(cx, obj, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Ensure that the object has at least JSCLASS_RESERVED_SLOTS(clasp)+nreserved
|
||||||
|
* slots. The function can be called only for native objects just created with
|
||||||
|
* js_NewObject or its forms. In particular, the object should not be shared
|
||||||
|
* between threads and its dslots array must be null. nreserved must match the
|
||||||
|
* value that JSClass.reserveSlots (if any) would return after the object is
|
||||||
|
* fully initialized.
|
||||||
|
*/
|
||||||
|
bool
|
||||||
|
js_EnsureReservedSlots(JSContext *cx, JSObject *obj, size_t nreserved);
|
||||||
|
|
||||||
extern jsid
|
extern jsid
|
||||||
js_CheckForStringIndex(jsid id);
|
js_CheckForStringIndex(jsid id);
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user