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
parent 2843975354
commit ce684a0a6e
2 changed files with 41 additions and 42 deletions

View File

@ -1,5 +1,5 @@
/* -*- 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 *****
* 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
};
/*
* 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
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;
}
/*
* 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
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 (!js_DefineNativeProperty(cx, obj,
ATOM_TO_JSID(atom), JSVAL_VOID,
NULL, NULL, lfp->attrs,
SPROP_HAS_SHORTID, lfp->tinyid,
NULL)) {
fun_getProperty, JS_PropertyStub,
lfp->attrs, SPROP_HAS_SHORTID,
lfp->tinyid, NULL)) {
return JS_FALSE;
}
*objp = obj;
@ -1504,7 +1504,7 @@ JS_FRIEND_DATA(JSClass) js_FunctionClass = {
JSCLASS_HAS_PRIVATE | JSCLASS_NEW_RESOLVE | JSCLASS_HAS_RESERVED_SLOTS(2) |
JSCLASS_MARK_IS_TRACE | JSCLASS_HAS_CACHED_PROTO(JSProto_Function),
JS_PropertyStub, JS_PropertyStub,
fun_getProperty, JS_PropertyStub,
JS_PropertyStub, JS_PropertyStub,
fun_enumerate, (JSResolveOp)fun_resolve,
fun_convert, fun_finalize,
NULL, NULL,

View File

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