Bug 453747 - Avoid overuse of the fun_getProperty class getter to optimize getting and setting random properties on functions. r=mrbkap

This commit is contained in:
Brendan Eich 2008-09-04 21:56:37 -07:00
Родитель fb36f5d923
Коммит 45164ec2af
2 изменённых файлов: 41 добавлений и 42 удалений

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

@ -1,5 +1,5 @@
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
* vim: set ts=8 sw=4 et tw=78: * vim: set ts=8 sw=4 et tw=99:
* *
* ***** BEGIN LICENSE BLOCK ***** * ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
@ -960,41 +960,6 @@ JS_FRIEND_DATA(JSClass) js_CallClass = {
JS_CLASS_TRACE(args_or_call_trace), call_reserveSlots JS_CLASS_TRACE(args_or_call_trace), call_reserveSlots
}; };
/*
* ECMA-262 specifies that length is a property of function object instances,
* but we can avoid that space cost by delegating to a prototype property that
* is JSPROP_PERMANENT and JSPROP_SHARED. Each fun_getProperty call computes
* a fresh length value based on the arity of the individual function object's
* private data.
*
* The extensions below other than length, i.e., the ones not in ECMA-262,
* are neither JSPROP_READONLY nor JSPROP_SHARED, because for compatibility
* with ECMA we must allow a delegating object to override them. Therefore to
* avoid entraining garbage in Function.prototype slots, they must be resolved
* in non-prototype function objects, wherefore the lazy_function_props table
* and fun_resolve's use of it.
*/
#define LENGTH_PROP_ATTRS (JSPROP_READONLY|JSPROP_PERMANENT|JSPROP_SHARED)
static JSPropertySpec function_props[] = {
{js_length_str, ARGS_LENGTH, LENGTH_PROP_ATTRS, 0,0},
{0,0,0,0,0}
};
typedef struct LazyFunctionProp {
uint16 atomOffset;
int8 tinyid;
uint8 attrs;
} LazyFunctionProp;
/* NB: no sentinel at the end -- use JS_ARRAY_LENGTH to bound loops. */
static LazyFunctionProp lazy_function_props[] = {
{ATOM_OFFSET(arguments), CALL_ARGUMENTS, JSPROP_PERMANENT},
{ATOM_OFFSET(arity), FUN_ARITY, JSPROP_PERMANENT},
{ATOM_OFFSET(caller), FUN_CALLER, JSPROP_PERMANENT},
{ATOM_OFFSET(name), FUN_NAME, JSPROP_PERMANENT},
};
static JSBool static JSBool
fun_getProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp) fun_getProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
{ {
@ -1092,6 +1057,41 @@ fun_getProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
return JS_TRUE; return JS_TRUE;
} }
/*
* ECMA-262 specifies that length is a property of function object instances,
* but we can avoid that space cost by delegating to a prototype property that
* is JSPROP_PERMANENT and JSPROP_SHARED. Each fun_getProperty call computes
* a fresh length value based on the arity of the individual function object's
* private data.
*
* The extensions below other than length, i.e., the ones not in ECMA-262,
* are neither JSPROP_READONLY nor JSPROP_SHARED, because for compatibility
* with ECMA we must allow a delegating object to override them. Therefore to
* avoid entraining garbage in Function.prototype slots, they must be resolved
* in non-prototype function objects, wherefore the lazy_function_props table
* and fun_resolve's use of it.
*/
#define LENGTH_PROP_ATTRS (JSPROP_READONLY|JSPROP_PERMANENT|JSPROP_SHARED)
static JSPropertySpec function_props[] = {
{js_length_str, ARGS_LENGTH, LENGTH_PROP_ATTRS, fun_getProperty, JS_PropertyStub},
{0,0,0,0,0}
};
typedef struct LazyFunctionProp {
uint16 atomOffset;
int8 tinyid;
uint8 attrs;
} LazyFunctionProp;
/* NB: no sentinel at the end -- use JS_ARRAY_LENGTH to bound loops. */
static LazyFunctionProp lazy_function_props[] = {
{ATOM_OFFSET(arguments), CALL_ARGUMENTS, JSPROP_PERMANENT},
{ATOM_OFFSET(arity), FUN_ARITY, JSPROP_PERMANENT},
{ATOM_OFFSET(caller), FUN_CALLER, JSPROP_PERMANENT},
{ATOM_OFFSET(name), FUN_NAME, JSPROP_PERMANENT},
};
static JSBool static JSBool
fun_enumerate(JSContext *cx, JSObject *obj) fun_enumerate(JSContext *cx, JSObject *obj)
{ {
@ -1182,9 +1182,9 @@ fun_resolve(JSContext *cx, JSObject *obj, jsval id, uintN flags,
if (id == ATOM_KEY(atom)) { if (id == ATOM_KEY(atom)) {
if (!js_DefineNativeProperty(cx, obj, if (!js_DefineNativeProperty(cx, obj,
ATOM_TO_JSID(atom), JSVAL_VOID, ATOM_TO_JSID(atom), JSVAL_VOID,
NULL, NULL, lfp->attrs, fun_getProperty, JS_PropertyStub,
SPROP_HAS_SHORTID, lfp->tinyid, lfp->attrs, SPROP_HAS_SHORTID,
NULL)) { lfp->tinyid, NULL)) {
return JS_FALSE; return JS_FALSE;
} }
*objp = obj; *objp = obj;
@ -1504,7 +1504,7 @@ JS_FRIEND_DATA(JSClass) js_FunctionClass = {
JSCLASS_HAS_PRIVATE | JSCLASS_NEW_RESOLVE | JSCLASS_HAS_RESERVED_SLOTS(2) | JSCLASS_HAS_PRIVATE | JSCLASS_NEW_RESOLVE | JSCLASS_HAS_RESERVED_SLOTS(2) |
JSCLASS_MARK_IS_TRACE | JSCLASS_HAS_CACHED_PROTO(JSProto_Function), JSCLASS_MARK_IS_TRACE | JSCLASS_HAS_CACHED_PROTO(JSProto_Function),
JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_PropertyStub,
fun_getProperty, JS_PropertyStub, JS_PropertyStub, JS_PropertyStub,
fun_enumerate, (JSResolveOp)fun_resolve, fun_enumerate, (JSResolveOp)fun_resolve,
fun_convert, fun_finalize, fun_convert, fun_finalize,
NULL, NULL, NULL, NULL,

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

@ -3951,8 +3951,7 @@ TraceRecorder::record_JSOP_NEW()
LIns* args[] = { get(&fval), cx_ins }; LIns* args[] = { get(&fval), cx_ins };
LIns* tv_ins = lir->insCall(F_FastNewObject, args); LIns* tv_ins = lir->insCall(F_FastNewObject, args);
guard(false, lir->ins_eq0(tv_ins), OOM_EXIT); guard(false, lir->ins_eq0(tv_ins), OOM_EXIT);
jsval& tv = stackval(0 - (1 + argc)); set(&tval, tv_ins);
set(&tv, tv_ins);
return interpretedFunctionCall(fval, fun, argc); return interpretedFunctionCall(fval, fun, argc);
} }