Bug 548671 - Stop using shared-permanent properties "inherited" from the prototype to represent (function(){}).length and [].length. r=jorendorff

This commit is contained in:
Jeff Walden
2010-06-02 23:44:24 -07:00
parent 4d1ce971da
commit 1893aa1071
10 changed files with 114 additions and 72 deletions

View File

@@ -139,7 +139,7 @@ INDEX_TOO_BIG(jsuint index)
JS_STATIC_ASSERT(sizeof(JSScopeProperty) > 4 * sizeof(jsval));
#define ENSURE_SLOW_ARRAY(cx, obj) \
(obj->getClass() == &js_SlowArrayClass || js_MakeArraySlow(cx, obj))
(obj->getClass() == &js_SlowArrayClass || obj->makeDenseArraySlow(cx))
/*
* Determine if the id represents an array index or an XML property index.
@@ -514,7 +514,7 @@ SetArrayElement(JSContext *cx, JSObject *obj, jsdouble index, jsval v)
}
}
if (!js_MakeArraySlow(cx, obj))
if (!obj->makeDenseArraySlow(cx))
return JS_FALSE;
}
@@ -611,11 +611,6 @@ js_IsArrayLike(JSContext *cx, JSObject *obj, JSBool *answerp, jsuint *lengthp)
}
/*
* The 'length' property of all native Array instances is a shared permanent
* property of Array.prototype, so it appears to be a direct property of each
* array instance delegating to that Array.prototype. It accesses the private
* slot reserved by js_ArrayClass.
*
* Since SpiderMonkey supports cross-class prototype-based delegation, we have
* to be careful about the length getter and setter being called on an object
* not of Array class. For the getter, we search obj's prototype chain for the
@@ -868,7 +863,7 @@ array_setProperty(JSContext *cx, JSObject *obj, jsid id, jsval *vp)
return js_SetProperty(cx, obj, id, vp);
if (!js_IdIsIndex(id, &i) || INDEX_TOO_SPARSE(obj, i)) {
if (!js_MakeArraySlow(cx, obj))
if (!obj->makeDenseArraySlow(cx))
return JS_FALSE;
return js_SetProperty(cx, obj, id, vp);
}
@@ -1132,15 +1127,16 @@ JSClass js_SlowArrayClass = {
* Convert an array object from fast-and-dense to slow-and-flexible.
*/
JSBool
js_MakeArraySlow(JSContext *cx, JSObject *obj)
JSObject::makeDenseArraySlow(JSContext *cx)
{
JS_ASSERT(obj->isDenseArray());
JS_ASSERT(isDenseArray());
/*
* Create a native scope. All slow arrays other than Array.prototype get
* the same initial shape.
*/
uint32 emptyShape;
JSObject *obj = this;
JSObject *arrayProto = obj->getProto();
if (arrayProto->getClass() == &js_ObjectClass) {
/* obj is Array.prototype. */
@@ -1165,11 +1161,16 @@ js_MakeArraySlow(JSContext *cx, JSObject *obj)
scope->freeslot = obj->numSlots();
}
/* Begin with the length property to share more of the property tree. */
if (!scope->addProperty(cx, ATOM_TO_JSID(cx->runtime->atomState.lengthAtom),
array_length_getter, array_length_setter,
JSSLOT_ARRAY_LENGTH, JSPROP_PERMANENT | JSPROP_SHARED, 0, 0)) {
goto out_bad;
}
/* Create new properties pointing to existing elements. */
for (uint32 i = 0; i < capacity; i++) {
jsid id;
JSScopeProperty *sprop;
if (!JS_ValueToId(cx, INT_TO_JSVAL(i), &id))
goto out_bad;
@@ -1178,9 +1179,7 @@ js_MakeArraySlow(JSContext *cx, JSObject *obj)
continue;
}
sprop = scope->addDataProperty(cx, id, JS_INITIAL_NSLOTS + i,
JSPROP_ENUMERATE);
if (!sprop)
if (!scope->addDataProperty(cx, id, JS_INITIAL_NSLOTS + i, JSPROP_ENUMERATE))
goto out_bad;
}
@@ -2178,7 +2177,7 @@ array_push1_dense(JSContext* cx, JSObject* obj, jsval v, jsval *rval)
{
uint32 length = obj->getArrayLength();
if (INDEX_TOO_SPARSE(obj, length)) {
if (!js_MakeArraySlow(cx, obj))
if (!obj->makeDenseArraySlow(cx))
return JS_FALSE;
return array_push_slowly(cx, obj, 1, &v, rval);
}
@@ -3049,12 +3048,6 @@ array_isArray(JSContext *cx, uintN argc, jsval *vp)
return JS_TRUE;
}
static JSPropertySpec array_props[] = {
{js_length_str, -1, JSPROP_SHARED | JSPROP_PERMANENT,
array_length_getter, array_length_setter},
{0,0,0,0,0}
};
static JSFunctionSpec array_methods[] = {
#if JS_HAS_TOSOURCE
JS_FN(js_toSource_str, array_toSource, 0,0),
@@ -3185,7 +3178,7 @@ JSObject *
js_InitArrayClass(JSContext *cx, JSObject *obj)
{
JSObject *proto = JS_InitClass(cx, obj, NULL, &js_ArrayClass, js_Array, 1,
array_props, array_methods, NULL, array_static_methods);
NULL, array_methods, NULL, array_static_methods);
/* Initialize the Array prototype object so it gets a length property. */
if (!proto || !InitArrayObject(cx, proto, 0, NULL))