Store JSStrings instead of jsids in native key iterators, bug 713754. r=dvander

This commit is contained in:
Brian Hackett
2012-01-18 16:56:22 -08:00
parent e29591e921
commit 851444a29f
6 changed files with 61 additions and 60 deletions

View File

@@ -121,7 +121,8 @@ static const gc::AllocKind ITERATOR_FINALIZE_KIND = gc::FINALIZE_OBJECT2;
void
NativeIterator::mark(JSTracer *trc)
{
MarkIdRange(trc, begin(), end(), "props");
for (HeapPtr<JSFlatString> *str = begin(); str < end(); str++)
MarkString(trc, *str, "prop");
if (obj)
MarkObject(trc, obj, "obj");
}
@@ -507,14 +508,20 @@ NativeIterator::allocateIterator(JSContext *cx, uint32_t slength, const AutoIdVe
{
size_t plength = props.length();
NativeIterator *ni = (NativeIterator *)
cx->malloc_(sizeof(NativeIterator) + plength * sizeof(jsid) + slength * sizeof(Shape *));
cx->malloc_(sizeof(NativeIterator)
+ plength * sizeof(JSString *)
+ slength * sizeof(Shape *));
if (!ni)
return NULL;
ni->props_array = ni->props_cursor = (HeapId *) (ni + 1);
ni->props_array = ni->props_cursor = (HeapPtr<JSFlatString> *) (ni + 1);
ni->props_end = ni->props_array + plength;
if (plength) {
for (size_t i = 0; i < plength; i++)
ni->props_array[i].init(props[i]);
for (size_t i = 0; i < plength; i++) {
JSFlatString *str = IdToString(cx, props[i]);
if (!str)
return NULL;
ni->props_array[i].init(str);
}
}
return ni;
}
@@ -916,9 +923,9 @@ js_CloseIterator(JSContext *cx, JSObject *obj)
* false. It also must have a method |matchesAtMostOne| which allows us to
* stop searching after the first deletion if true.
*/
template<typename IdPredicate>
template<typename StringPredicate>
static bool
SuppressDeletedPropertyHelper(JSContext *cx, JSObject *obj, IdPredicate predicate)
SuppressDeletedPropertyHelper(JSContext *cx, JSObject *obj, StringPredicate predicate)
{
JSObject *iterobj = cx->enumerators;
while (iterobj) {
@@ -927,9 +934,9 @@ SuppressDeletedPropertyHelper(JSContext *cx, JSObject *obj, IdPredicate predicat
/* This only works for identified surpressed keys, not values. */
if (ni->isKeyIter() && ni->obj == obj && ni->props_cursor < ni->props_end) {
/* Check whether id is still to come. */
HeapId *props_cursor = ni->current();
HeapId *props_end = ni->end();
for (HeapId *idp = props_cursor; idp < props_end; ++idp) {
HeapPtr<JSFlatString> *props_cursor = ni->current();
HeapPtr<JSFlatString> *props_end = ni->end();
for (HeapPtr<JSFlatString> *idp = props_cursor; idp < props_end; ++idp) {
if (predicate(*idp)) {
/*
* Check whether another property along the prototype chain
@@ -939,13 +946,17 @@ SuppressDeletedPropertyHelper(JSContext *cx, JSObject *obj, IdPredicate predicat
JSObject *proto = obj->getProto();
JSObject *obj2;
JSProperty *prop;
if (!proto->lookupGeneric(cx, *idp, &obj2, &prop))
jsid id;
if (!ValueToId(cx, StringValue(*idp), &id))
return false;
id = js_CheckForStringIndex(id);
if (!proto->lookupGeneric(cx, id, &obj2, &prop))
return false;
if (prop) {
uintN attrs;
if (obj2->isNative())
attrs = ((Shape *) prop)->attributes();
else if (!obj2->getGenericAttributes(cx, *idp, &attrs))
else if (!obj2->getGenericAttributes(cx, id, &attrs))
return false;
if (attrs & JSPROP_ENUMERATE)
@@ -968,7 +979,7 @@ SuppressDeletedPropertyHelper(JSContext *cx, JSObject *obj, IdPredicate predicat
if (idp == props_cursor) {
ni->incCursor();
} else {
for (HeapId *p = idp; p + 1 != props_end; p++)
for (HeapPtr<JSFlatString> *p = idp; p + 1 != props_end; p++)
*p = *(p + 1);
ni->props_end = ni->end() - 1;
}
@@ -986,20 +997,22 @@ SuppressDeletedPropertyHelper(JSContext *cx, JSObject *obj, IdPredicate predicat
return true;
}
class SingleIdPredicate {
jsid id;
class SingleStringPredicate {
JSFlatString *str;
public:
SingleIdPredicate(jsid id) : id(id) {}
SingleStringPredicate(JSFlatString *str) : str(str) {}
bool operator()(jsid id) { return id == this->id; }
bool operator()(JSFlatString *str) { return EqualStrings(str, this->str); }
bool matchesAtMostOne() { return true; }
};
bool
js_SuppressDeletedProperty(JSContext *cx, JSObject *obj, jsid id)
{
id = js_CheckForStringIndex(id);
return SuppressDeletedPropertyHelper(cx, obj, SingleIdPredicate(id));
JSFlatString *str = IdToString(cx, id);
if (!str)
return false;
return SuppressDeletedPropertyHelper(cx, obj, SingleStringPredicate(str));
}
bool
@@ -1008,8 +1021,7 @@ js_SuppressDeletedElement(JSContext *cx, JSObject *obj, uint32_t index)
jsid id;
if (!IndexToId(cx, index, &id))
return false;
JS_ASSERT(id == js_CheckForStringIndex(id));
return SuppressDeletedPropertyHelper(cx, obj, SingleIdPredicate(id));
return js_SuppressDeletedProperty(cx, obj, id);
}
class IndexRangePredicate {
@@ -1018,19 +1030,9 @@ class IndexRangePredicate {
public:
IndexRangePredicate(uint32_t begin, uint32_t end) : begin(begin), end(end) {}
bool operator()(jsid id) {
if (JSID_IS_INT(id)) {
jsint i = JSID_TO_INT(id);
return i > 0 && begin <= uint32_t(i) && uint32_t(i) < end;
}
if (JS_LIKELY(JSID_IS_ATOM(id))) {
JSAtom *atom = JSID_TO_ATOM(id);
uint32_t index;
return atom->isIndex(&index) && begin <= index && index < end;
}
return false;
bool operator()(JSFlatString *str) {
uint32_t index;
return str->isIndex(&index) && begin <= index && index < end;
}
bool matchesAtMostOne() { return false; }
@@ -1083,7 +1085,10 @@ js_IteratorMore(JSContext *cx, JSObject *iterobj, Value *rval)
}
} else {
JS_ASSERT(!ni->isKeyIter());
jsid id = *ni->current();
jsid id;
if (!ValueToId(cx, StringValue(*ni->current()), &id))
return false;
id = js_CheckForStringIndex(id);
ni->incCursor();
if (!ni->obj->getGeneric(cx, id, rval))
return false;
@@ -1110,7 +1115,7 @@ js_IteratorNext(JSContext *cx, JSObject *iterobj, Value *rval)
NativeIterator *ni = iterobj->getNativeIterator();
if (ni->isKeyIter()) {
JS_ASSERT(ni->props_cursor < ni->props_end);
*rval = IdToValue(*ni->current());
*rval = StringValue(*ni->current());
ni->incCursor();
if (rval->isString())