From 0c1e8c8921378de1970c0742d173fbc6d2ad2818 Mon Sep 17 00:00:00 2001 From: Brendan Eich Date: Thu, 4 Sep 2008 19:30:58 -0700 Subject: [PATCH] Bug 453747 - Avoid overuse of the fun_getProperty class getter to optimize getting and setting random properties on functions. r=mrbkap --- js/src/jsfun.cpp | 80 ++++++++++++++++++++++++++--------------------------- js/src/jstracer.cpp | 3 +- 2 files changed, 41 insertions(+), 42 deletions(-) diff --git a/js/src/jsfun.cpp b/js/src/jsfun.cpp index 5f064a21fb..52ced6560c 100644 --- a/js/src/jsfun.cpp +++ b/js/src/jsfun.cpp @@ -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, diff --git a/js/src/jstracer.cpp b/js/src/jstracer.cpp index a492845d79..4efa287a64 100644 --- a/js/src/jstracer.cpp +++ b/js/src/jstracer.cpp @@ -3979,8 +3979,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); } -- 2.11.4.GIT