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)) {
|
||||
JS_ASSERT(funobj->dslots);
|
||||
JS_ASSERT(JSSLOT_FREE(&js_FunctionClass) == JS_INITIAL_NSLOTS);
|
||||
|
||||
uint32 nslots = JSSLOT_FREE(&js_FunctionClass);
|
||||
JS_ASSERT(nslots == JS_INITIAL_NSLOTS);
|
||||
nslots += js_FunctionClass.reserveSlots(cx, clone);
|
||||
if (!js_AllocSlots(cx, clone, nslots))
|
||||
if (!js_EnsureReservedSlots(cx, clone,
|
||||
fun->countInterpretedReserveSlots())) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
JSUpvarArray *uva = JS_SCRIPT_UPVARS(fun->u.i.script);
|
||||
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);
|
||||
if (!callobj)
|
||||
if (!callobj ||
|
||||
!js_EnsureReservedSlots(cx, callobj, fp->fun->countArgsAndVars())) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
JS_SetPrivate(cx, callobj, fp);
|
||||
JS_ASSERT(fp->fun == GET_FUNCTION_PRIVATE(cx, fp->callee));
|
||||
@ -936,7 +938,6 @@ js_PutCallObject(JSContext *cx, JSStackFrame *fp)
|
||||
JSBool ok;
|
||||
JSFunction *fun;
|
||||
uintN n;
|
||||
JSScope *scope;
|
||||
|
||||
/*
|
||||
* 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));
|
||||
n = fun->countArgsAndVars();
|
||||
if (n != 0) {
|
||||
JS_LOCK_OBJ(cx, callobj);
|
||||
n += JS_INITIAL_NSLOTS;
|
||||
if (n > STOBJ_NSLOTS(callobj))
|
||||
ok &= js_GrowSlots(cx, callobj, n);
|
||||
scope = OBJ_SCOPE(callobj);
|
||||
if (ok) {
|
||||
JS_LOCK_OBJ(cx, callobj);
|
||||
memcpy(callobj->dslots, fp->argv, fun->nargs * sizeof(jsval));
|
||||
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);
|
||||
JS_UNLOCK_OBJ(cx, callobj);
|
||||
}
|
||||
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
/* Clear private pointers to fp, which is about to go away (js_Invoke). */
|
||||
if ((fun->flags & JSFUN_LAMBDA) && fun->atom) {
|
||||
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
|
||||
fun_reserveSlots(JSContext *cx, JSObject *obj)
|
||||
{
|
||||
JSFunction *fun;
|
||||
uint32 nslots;
|
||||
|
||||
/*
|
||||
* We use JS_GetPrivate and not GET_FUNCTION_PRIVATE because during
|
||||
* js_InitFunctionClass invocation the function is called before the
|
||||
* private slot of the function object is set.
|
||||
*/
|
||||
fun = (JSFunction *) JS_GetPrivate(cx, obj);
|
||||
nslots = 0;
|
||||
if (fun && FUN_INTERPRETED(fun) && fun->u.i.script) {
|
||||
if (fun->u.i.nupvars != 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;
|
||||
JSFunction *fun = (JSFunction *) JS_GetPrivate(cx, obj);
|
||||
return (fun && FUN_INTERPRETED(fun))
|
||||
? fun->countInterpretedReserveSlots()
|
||||
: 0;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -2509,16 +2504,20 @@ js_AllocFlatClosure(JSContext *cx, JSFunction *fun, JSObject *scopeChain)
|
||||
? JS_SCRIPT_UPVARS(fun->u.i.script)->length
|
||||
: 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);
|
||||
if (!closure || fun->u.i.nupvars == 0)
|
||||
return closure;
|
||||
|
||||
uint32 nslots = JSSLOT_FREE(&js_FunctionClass);
|
||||
JS_ASSERT(nslots == JS_INITIAL_NSLOTS);
|
||||
nslots += fun_reserveSlots(cx, closure);
|
||||
if (!js_GrowSlots(cx, closure, nslots))
|
||||
if (!js_EnsureReservedSlots(cx, closure,
|
||||
fun->countInterpretedReserveSlots())) {
|
||||
return NULL;
|
||||
|
||||
}
|
||||
return closure;
|
||||
}
|
||||
|
||||
|
@ -162,7 +162,6 @@ struct JSFunction {
|
||||
} u;
|
||||
JSAtom *atom; /* name for diagnostics and decompiling */
|
||||
|
||||
#ifdef __cplusplus
|
||||
bool optimizedClosure() { return FUN_KIND(this) > JSFUN_INTERPRETED; }
|
||||
bool needsWrapper() { return FUN_NULL_CLOSURE(this) && u.i.skipmin != 0; }
|
||||
|
||||
@ -180,7 +179,8 @@ struct JSFunction {
|
||||
JS_ASSERT(FUN_INTERPRETED(this));
|
||||
return countLocalNames() != 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
uint32 countInterpretedReserveSlots() const;
|
||||
};
|
||||
|
||||
/*
|
||||
|
@ -2011,6 +2011,9 @@ static JSFunctionSpec object_static_methods[] = {
|
||||
JS_FS_END
|
||||
};
|
||||
|
||||
static bool
|
||||
AllocSlots(JSContext *cx, JSObject *obj, size_t nslots);
|
||||
|
||||
static inline bool
|
||||
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. */
|
||||
JS_ASSERT(scope->freeslot >= JSSLOT_PRIVATE);
|
||||
if (scope->freeslot > JS_INITIAL_NSLOTS &&
|
||||
!js_AllocSlots(cx, obj, scope->freeslot)) {
|
||||
!AllocSlots(cx, obj, scope->freeslot)) {
|
||||
JSScope::destroy(cx, scope);
|
||||
goto bad;
|
||||
}
|
||||
@ -2600,7 +2603,7 @@ js_PutBlockObject(JSContext *cx, JSBool normalUnwind)
|
||||
if (normalUnwind && count > 1) {
|
||||
--count;
|
||||
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;
|
||||
else
|
||||
memcpy(obj->dslots, fp->slots + depth + 1, count * sizeof(jsval));
|
||||
@ -2976,8 +2979,8 @@ bad:
|
||||
(JS_ASSERT((words) > 1), (words) - 1 + JS_INITIAL_NSLOTS)
|
||||
|
||||
|
||||
bool
|
||||
js_AllocSlots(JSContext *cx, JSObject *obj, size_t nslots)
|
||||
static bool
|
||||
AllocSlots(JSContext *cx, JSObject *obj, size_t nslots)
|
||||
{
|
||||
JS_ASSERT(!obj->dslots);
|
||||
JS_ASSERT(nslots > JS_INITIAL_NSLOTS);
|
||||
@ -3037,7 +3040,7 @@ js_GrowSlots(JSContext *cx, JSObject *obj, size_t nslots)
|
||||
*/
|
||||
jsval* slots = obj->dslots;
|
||||
if (!slots)
|
||||
return js_AllocSlots(cx, obj, nslots);
|
||||
return AllocSlots(cx, obj, nslots);
|
||||
|
||||
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
|
||||
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)
|
||||
nslots += clasp->reserveSlots(cx, obj);
|
||||
JS_ASSERT(slot < nslots);
|
||||
if (!js_AllocSlots(cx, obj, nslots)) {
|
||||
if (!AllocSlots(cx, obj, nslots)) {
|
||||
JS_UNLOCK_SCOPE(cx, scope);
|
||||
return JS_FALSE;
|
||||
}
|
||||
|
@ -578,9 +578,6 @@ js_AllocSlot(JSContext *cx, JSObject *obj, uint32 *slotp);
|
||||
extern void
|
||||
js_FreeSlot(JSContext *cx, JSObject *obj, uint32 slot);
|
||||
|
||||
extern bool
|
||||
js_AllocSlots(JSContext *cx, JSObject *obj, size_t nslots);
|
||||
|
||||
extern bool
|
||||
js_GrowSlots(JSContext *cx, JSObject *obj, size_t nslots);
|
||||
|
||||
@ -594,6 +591,17 @@ js_FreeSlots(JSContext *cx, JSObject *obj)
|
||||
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
|
||||
js_CheckForStringIndex(jsid id);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user