[bug 424942] optimizing call object property allocation, r=brendan a1.9=mtschrep

This commit is contained in:
igor@mir2.org 2008-03-29 08:48:41 -07:00
Родитель a56e38ef38
Коммит a2f5746dcf
3 изменённых файлов: 119 добавлений и 124 удалений

Просмотреть файл

@ -1353,28 +1353,17 @@ JS_GetPropertyDesc(JSContext *cx, JSObject *obj, JSScopeProperty *sprop,
pd->flags |= ((sprop->attrs & JSPROP_ENUMERATE) ? JSPD_ENUMERATE : 0)
| ((sprop->attrs & JSPROP_READONLY) ? JSPD_READONLY : 0)
| ((sprop->attrs & JSPROP_PERMANENT) ? JSPD_PERMANENT : 0)
| ((sprop->getter == js_GetCallVariable) ? JSPD_VARIABLE : 0);
/* for Call Object 'real' getter isn't passed in to us */
if (OBJ_GET_CLASS(cx, obj) == &js_CallClass &&
sprop->getter == js_CallClass.getProperty) {
/*
* Property of a heavyweight function's variable object having the
* class-default getter. It's either an argument if permanent, or a
* nested function if impermanent. Local variables have a special
* getter (js_GetCallVariable, tested above) and setter, and not the
* class default.
*/
pd->flags |= (sprop->attrs & JSPROP_PERMANENT)
? JSPD_ARGUMENT
: JSPD_VARIABLE;
}
| ((sprop->attrs & JSPROP_PERMANENT) ? JSPD_PERMANENT : 0);
pd->spare = 0;
pd->slot = (pd->flags & (JSPD_ARGUMENT | JSPD_VARIABLE))
? sprop->shortid
: 0;
if (sprop->getter == js_GetCallArg) {
pd->slot = sprop->shortid;
pd->flags |= JSPD_ARGUMENT;
} else if (sprop->getter == js_GetCallVar) {
pd->slot = sprop->shortid;
pd->flags |= JSPD_VARIABLE;
} else {
pd->slot = 0;
}
pd->alias = JSVAL_VOID;
scope = OBJ_SCOPE(obj);
if (SPROP_HAS_VALID_SLOT(sprop, scope)) {

Просмотреть файл

@ -658,93 +658,6 @@ js_PutCallObject(JSContext *cx, JSStackFrame *fp)
return ok;
}
static JSBool
call_getProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
{
JSStackFrame *fp;
jsint slot;
if (!JSVAL_IS_INT(id))
return JS_TRUE;
fp = (JSStackFrame *) JS_GetPrivate(cx, obj);
if (!fp)
return JS_TRUE;
JS_ASSERT(fp->fun);
slot = JSVAL_TO_INT(id);
switch (slot) {
case CALL_ARGUMENTS:
if (!TEST_OVERRIDE_BIT(fp, slot)) {
JSObject *argsobj = js_GetArgsObject(cx, fp);
if (!argsobj)
return JS_FALSE;
*vp = OBJECT_TO_JSVAL(argsobj);
}
break;
default:
if ((uintN)slot < JS_MAX(fp->argc, fp->fun->nargs))
*vp = fp->argv[slot];
break;
}
return JS_TRUE;
}
static JSBool
call_setProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
{
JSStackFrame *fp;
jsint slot;
if (!JSVAL_IS_INT(id))
return JS_TRUE;
fp = (JSStackFrame *) JS_GetPrivate(cx, obj);
if (!fp)
return JS_TRUE;
JS_ASSERT(fp->fun);
slot = JSVAL_TO_INT(id);
switch (slot) {
case CALL_ARGUMENTS:
SET_OVERRIDE_BIT(fp, slot);
break;
default:
if ((uintN)slot < JS_MAX(fp->argc, fp->fun->nargs))
fp->argv[slot] = *vp;
break;
}
return JS_TRUE;
}
JSBool
js_GetCallVariable(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
{
JSStackFrame *fp;
JS_ASSERT(JSVAL_IS_INT(id));
fp = (JSStackFrame *) JS_GetPrivate(cx, obj);
if (fp) {
JS_ASSERT((uintN) JSVAL_TO_INT(id) < fp->nvars);
*vp = fp->vars[JSVAL_TO_INT(id)];
}
return JS_TRUE;
}
JSBool
js_SetCallVariable(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
{
JSStackFrame *fp;
JS_ASSERT(JSVAL_IS_INT(id));
fp = (JSStackFrame *) JS_GetPrivate(cx, obj);
if (fp) {
JS_ASSERT((uintN) JSVAL_TO_INT(id) < fp->nvars);
fp->vars[JSVAL_TO_INT(id)] = *vp;
}
return JS_TRUE;
}
static JSBool
call_enumerate(JSContext *cx, JSObject *obj)
{
@ -815,11 +728,102 @@ call_enumerate(JSContext *cx, JSObject *obj)
return ok;
}
typedef enum JSCallPropertyKind {
JSCPK_ARGUMENTS,
JSCPK_ARG,
JSCPK_VAR
} JSCallPropertyKind;
static JSBool
CallPropertyOp(JSContext *cx, JSObject *obj, jsid id, jsval *vp,
JSCallPropertyKind kind, JSBool setter)
{
JSStackFrame *fp;
JSFunction *fun;
uintN i;
jsval *array;
fp = (JSStackFrame *) JS_GetPrivate(cx, obj);
if (!fp)
return JS_TRUE;
fun = fp->fun;
JS_ASSERT(fun && FUN_INTERPRETED(fun));
if (kind == JSCPK_ARGUMENTS) {
if (setter) {
SET_OVERRIDE_BIT(fp, CALL_ARGUMENTS);
} else if (!TEST_OVERRIDE_BIT(fp, CALL_ARGUMENTS)) {
JSObject *argsobj;
argsobj = js_GetArgsObject(cx, fp);
if (!argsobj)
return JS_FALSE;
*vp = OBJECT_TO_JSVAL(argsobj);
}
return JS_TRUE;
}
JS_ASSERT((int16) JSVAL_TO_INT(id) == JSVAL_TO_INT(id));
i = (uint16) JSVAL_TO_INT(id);
JS_ASSERT_IF(kind == JSCPK_ARG, i < fun->nargs);
JS_ASSERT_IF(kind == JSCPK_VAR, i < fun->u.i.nvars);
JS_ASSERT(fun->u.i.nvars == fp->nvars);
if (kind == JSCPK_ARG) {
array = fp->argv;
} else {
JS_ASSERT(kind == JSCPK_VAR);
array = fp->vars;
}
if (setter)
array[i] = *vp;
else
*vp = array[i];
return JS_TRUE;
}
static JSBool
GetCallArguments(JSContext *cx, JSObject *obj, jsid id, jsval *vp)
{
return CallPropertyOp(cx, obj, id, vp, JSCPK_ARGUMENTS, JS_FALSE);
}
static JSBool
SetCallArguments(JSContext *cx, JSObject *obj, jsid id, jsval *vp)
{
return CallPropertyOp(cx, obj, id, vp, JSCPK_ARGUMENTS, JS_TRUE);
}
JSBool
js_GetCallArg(JSContext *cx, JSObject *obj, jsid id, jsval *vp)
{
return CallPropertyOp(cx, obj, id, vp, JSCPK_ARG, JS_FALSE);
}
static JSBool
SetCallArg(JSContext *cx, JSObject *obj, jsid id, jsval *vp)
{
return CallPropertyOp(cx, obj, id, vp, JSCPK_ARG, JS_TRUE);
}
JSBool
js_GetCallVar(JSContext *cx, JSObject *obj, jsid id, jsval *vp)
{
return CallPropertyOp(cx, obj, id, vp, JSCPK_VAR, JS_FALSE);
}
static JSBool
SetCallVar(JSContext *cx, JSObject *obj, jsid id, jsval *vp)
{
return CallPropertyOp(cx, obj, id, vp, JSCPK_VAR, JS_TRUE);
}
static JSBool
call_resolve(JSContext *cx, JSObject *obj, jsval idval, uintN flags,
JSObject **objp)
{
JSStackFrame *fp;
JSFunction *fun;
jsid id;
JSLocalKind localKind;
JSPropertyOp getter, setter;
@ -829,8 +833,9 @@ call_resolve(JSContext *cx, JSObject *obj, jsval idval, uintN flags,
fp = (JSStackFrame *) JS_GetPrivate(cx, obj);
if (!fp)
return JS_TRUE;
JS_ASSERT(fp->fun);
JS_ASSERT(GET_FUNCTION_PRIVATE(cx, fp->callee) == fp->fun);
fun = fp->fun;
JS_ASSERT(fun);
JS_ASSERT(GET_FUNCTION_PRIVATE(cx, fp->callee) == fun);
if (!JSVAL_IS_STRING(idval))
return JS_TRUE;
@ -838,26 +843,28 @@ call_resolve(JSContext *cx, JSObject *obj, jsval idval, uintN flags,
if (!js_ValueToStringId(cx, idval, &id))
return JS_FALSE;
localKind = js_LookupLocal(cx, fp->fun, JSID_TO_ATOM(id), &slot);
localKind = js_LookupLocal(cx, fun, JSID_TO_ATOM(id), &slot);
if (localKind != JSLOCAL_NONE) {
JS_ASSERT((uint16) slot == slot);
if (localKind == JSLOCAL_ARG) {
JS_ASSERT(slot < fp->fun->nargs);
JS_ASSERT(slot < fun->nargs);
vp = fp->argv;
getter = setter = NULL;
getter = js_GetCallArg;
setter = SetCallArg;
attrs = JSPROP_PERMANENT;
} else {
JS_ASSERT(localKind == JSLOCAL_VAR || localKind == JSLOCAL_CONST);
JS_ASSERT(fp->fun->u.i.nvars == fp->nvars);
JS_ASSERT(slot < fp->nvars);
JS_ASSERT(fun->u.i.nvars == fp->nvars);
JS_ASSERT(slot < fun->u.i.nvars);
vp = fp->vars;
getter = js_GetCallVariable;
setter = js_SetCallVariable;
getter = js_GetCallVar;
setter = SetCallVar;
attrs = (localKind == JSLOCAL_CONST)
? JSPROP_PERMANENT | JSPROP_READONLY
: JSPROP_PERMANENT;
}
if (!js_DefineNativeProperty(cx, obj, id, vp[slot], getter, setter,
attrs, SPROP_HAS_SHORTID, (int) slot,
attrs, SPROP_HAS_SHORTID, (int16) slot,
NULL)) {
return JS_FALSE;
}
@ -871,9 +878,8 @@ call_resolve(JSContext *cx, JSObject *obj, jsval idval, uintN flags,
*/
if (id == ATOM_TO_JSID(cx->runtime->atomState.argumentsAtom)) {
if (!js_DefineNativeProperty(cx, obj, id, JSVAL_VOID,
NULL, NULL, JSPROP_PERMANENT,
SPROP_HAS_SHORTID, CALL_ARGUMENTS,
NULL)) {
GetCallArguments, SetCallArguments,
JSPROP_PERMANENT, 0, 0, NULL)) {
return JS_FALSE;
}
*objp = obj;
@ -902,7 +908,7 @@ JS_FRIEND_DATA(JSClass) js_CallClass = {
JSCLASS_HAS_PRIVATE | JSCLASS_NEW_RESOLVE | JSCLASS_IS_ANONYMOUS |
JSCLASS_MARK_IS_TRACE | JSCLASS_HAS_CACHED_PROTO(JSProto_Call),
JS_PropertyStub, JS_PropertyStub,
call_getProperty, call_setProperty,
JS_PropertyStub, JS_PropertyStub,
call_enumerate, (JSResolveOp)call_resolve,
call_convert, JS_FinalizeStub,
NULL, NULL,

Просмотреть файл

@ -179,10 +179,10 @@ extern JS_FRIEND_API(JSBool)
js_PutCallObject(JSContext *cx, JSStackFrame *fp);
extern JSBool
js_GetCallVariable(JSContext *cx, JSObject *obj, jsval id, jsval *vp);
js_GetCallArg(JSContext *cx, JSObject *obj, jsid id, jsval *vp);
extern JSBool
js_SetCallVariable(JSContext *cx, JSObject *obj, jsval id, jsval *vp);
js_GetCallVar(JSContext *cx, JSObject *obj, jsval id, jsval *vp);
extern JSBool
js_GetArgsValue(JSContext *cx, JSStackFrame *fp, jsval *vp);