зеркало из https://github.com/mozilla/gecko-dev.git
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:
Родитель
fb36f5d923
Коммит
45164ec2af
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Загрузка…
Ссылка в новой задаче