Bug 686582 - Begin to specialize ObjectOps::lookupElement to not just delegate to ObjectOps::lookupProperty. r=dvander

--HG--
extra : rebase_source : f04ec73fec1831c717e01779e0d692585f8ed74d
This commit is contained in:
Jeff Walden 2011-08-10 14:54:52 -07:00
parent f53e1c3100
commit 6df15f5190
6 changed files with 103 additions and 20 deletions

View File

@ -686,6 +686,16 @@ array_length_setter(JSContext *cx, JSObject *obj, jsid id, JSBool strict, Value
return true;
}
/* Returns true if the dense array has an own property at the index. */
static inline bool
IsDenseArrayIndex(JSObject *obj, uint32 index)
{
JS_ASSERT(obj->isDenseArray());
return index < obj->getDenseArrayInitializedLength() &&
!obj->getDenseArrayElement(index).isMagic(JS_ARRAY_HOLE);
}
/*
* We have only indexed properties up to initialized length, plus the
* length property. For all else, we delegate to the prototype.
@ -697,8 +707,7 @@ IsDenseArrayId(JSContext *cx, JSObject *obj, jsid id)
uint32 i;
return JSID_IS_ATOM(id, cx->runtime->atomState.lengthAtom) ||
(js_IdIsIndex(id, &i) && i < obj->getDenseArrayInitializedLength() &&
!obj->getDenseArrayElement(i).isMagic(JS_ARRAY_HOLE));
(js_IdIsIndex(id, &i) && IsDenseArrayIndex(obj, i));
}
static JSBool
@ -727,10 +736,21 @@ static JSBool
array_lookupElement(JSContext *cx, JSObject *obj, uint32 index, JSObject **objp,
JSProperty **propp)
{
jsid id;
if (!IndexToId(cx, index, &id))
return false;
return array_lookupProperty(cx, obj, id, objp, propp);
if (!obj->isDenseArray())
return js_LookupElement(cx, obj, index, objp, propp);
if (IsDenseArrayIndex(obj, index)) {
*propp = (JSProperty *) 1; /* non-null to indicate found */
*objp = obj;
return true;
}
if (JSObject *proto = obj->getProto())
return proto->lookupElement(cx, index, objp, propp);
*objp = NULL;
*propp = NULL;
return true;
}
JSBool

View File

@ -5440,6 +5440,16 @@ js_LookupProperty(JSContext *cx, JSObject *obj, jsid id, JSObject **objp,
return LookupPropertyWithFlagsInline(cx, obj, id, cx->resolveFlags, objp, propp);
}
JS_FRIEND_API(JSBool)
js_LookupElement(JSContext *cx, JSObject *obj, uint32 index, JSObject **objp, JSProperty **propp)
{
jsid id;
if (!IndexToId(cx, index, &id))
return false;
return LookupPropertyWithFlagsInline(cx, obj, id, cx->resolveFlags, objp, propp);
}
namespace js {
bool

View File

@ -247,6 +247,9 @@ extern JS_FRIEND_API(JSBool)
js_LookupProperty(JSContext *cx, JSObject *obj, jsid id, JSObject **objp,
JSProperty **propp);
extern JS_FRIEND_API(JSBool)
js_LookupElement(JSContext *cx, JSObject *obj, uint32 index, JSObject **objp, JSProperty **propp);
extern JSBool
js_DefineProperty(JSContext *cx, JSObject *obj, jsid id, const js::Value *value,
js::PropertyOp getter, js::StrictPropertyOp setter, uintN attrs);

View File

@ -1096,10 +1096,8 @@ JSObject::setSharedNonNativeMap()
inline JSBool
JSObject::lookupElement(JSContext *cx, uint32 index, JSObject **objp, JSProperty **propp)
{
jsid id;
if (!js::IndexToId(cx, index, &id))
return false;
return lookupProperty(cx, id, objp, propp);
js::LookupElementOp op = getOps()->lookupElement;
return (op ? op : js_LookupElement)(cx, this, index, objp, propp);
}
inline JSBool

View File

@ -237,12 +237,14 @@ ArrayBuffer::obj_trace(JSTracer *trc, JSObject *obj)
MarkObject(trc, *delegate, "arraybuffer.delegate");
}
static JSProperty * const PROPERTY_FOUND = reinterpret_cast<JSProperty *>(1);
JSBool
ArrayBuffer::obj_lookupProperty(JSContext *cx, JSObject *obj, jsid id,
JSObject **objp, JSProperty **propp)
{
if (JSID_IS_ATOM(id, cx->runtime->atomState.byteLengthAtom)) {
*propp = (JSProperty *) 1;
*propp = PROPERTY_FOUND;
*objp = getArrayBuffer(obj);
return true;
}
@ -281,10 +283,31 @@ JSBool
ArrayBuffer::obj_lookupElement(JSContext *cx, JSObject *obj, uint32 index,
JSObject **objp, JSProperty **propp)
{
jsid id;
if (!IndexToId(cx, index, &id))
JSObject *delegate = DelegateObject(cx, obj);
if (!delegate)
return false;
return obj_lookupProperty(cx, obj, id, objp, propp);
/*
* If false, there was an error, so propagate it.
* Otherwise, if propp is non-null, the property
* was found. Otherwise it was not
* found so look in the prototype chain.
*/
if (!delegate->lookupElement(cx, index, objp, propp))
return false;
if (*propp != NULL) {
if (*objp == delegate)
*objp = obj;
return true;
}
if (JSObject *proto = obj->getProto())
return proto->lookupElement(cx, index, objp, propp);
*objp = NULL;
*propp = NULL;
return true;
}
JSBool
@ -589,7 +612,7 @@ TypedArray::obj_lookupProperty(JSContext *cx, JSObject *obj, jsid id,
JS_ASSERT(tarray);
if (isArrayIndex(cx, tarray, id)) {
*propp = (JSProperty *) 1; /* non-null to indicate found */
*propp = PROPERTY_FOUND;
*objp = obj;
return true;
}
@ -608,10 +631,21 @@ JSBool
TypedArray::obj_lookupElement(JSContext *cx, JSObject *obj, uint32 index,
JSObject **objp, JSProperty **propp)
{
jsid id;
if (!IndexToId(cx, index, &id))
return false;
return obj_lookupProperty(cx, obj, id, objp, propp);
JSObject *tarray = getTypedArray(obj);
JS_ASSERT(tarray);
if (index < getLength(tarray)) {
*propp = PROPERTY_FOUND;
*objp = obj;
return true;
}
if (JSObject *proto = obj->getProto())
return proto->lookupElement(cx, index, objp, propp);
*objp = NULL;
*propp = NULL;
return true;
}
JSBool

View File

@ -4737,10 +4737,28 @@ static JSBool
xml_lookupElement(JSContext *cx, JSObject *obj, uint32 index, JSObject **objp,
JSProperty **propp)
{
JSXML *xml = reinterpret_cast<JSXML *>(obj->getPrivate());
if (!HasIndexedProperty(xml, index)) {
*objp = NULL;
*propp = NULL;
return true;
}
jsid id;
if (!IndexToId(cx, index, &id))
return false;
return xml_lookupProperty(cx, obj, id, objp, propp);
const Shape *shape =
js_AddNativeProperty(cx, obj, id,
Valueify(GetProperty), Valueify(PutProperty),
SHAPE_INVALID_SLOT, JSPROP_ENUMERATE,
0, 0);
if (!shape)
return false;
*objp = obj;
*propp = (JSProperty *) shape;
return true;
}
static JSBool