mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-26 06:11:37 +00:00
Store JSStrings instead of jsids in native key iterators, bug 713754. r=dvander
This commit is contained in:
parent
7e3d6561ae
commit
bdf9362d41
@ -177,14 +177,14 @@ IndexToId(JSContext *cx, uint32_t index, jsid *idp)
|
||||
return IndexToIdSlow(cx, index, idp);
|
||||
}
|
||||
|
||||
static JS_ALWAYS_INLINE JSString *
|
||||
static JS_ALWAYS_INLINE JSFlatString *
|
||||
IdToString(JSContext *cx, jsid id)
|
||||
{
|
||||
if (JSID_IS_STRING(id))
|
||||
return JSID_TO_STRING(id);
|
||||
return JSID_TO_ATOM(id);
|
||||
if (JS_LIKELY(JSID_IS_INT(id)))
|
||||
return js_IntToString(cx, JSID_TO_INT(id));
|
||||
return js::ToStringSlow(cx, IdToValue(id));
|
||||
return js_IntToString(cx, JSID_TO_INT(id))->ensureFlat(cx);
|
||||
return ToStringSlow(cx, IdToValue(id))->ensureFlat(cx);
|
||||
}
|
||||
|
||||
} // namespace js
|
||||
|
@ -1350,13 +1350,9 @@ IteratorNext(JSContext *cx, JSObject *iterobj, Value *rval)
|
||||
NativeIterator *ni = iterobj->getNativeIterator();
|
||||
if (ni->isKeyIter()) {
|
||||
JS_ASSERT(ni->props_cursor < ni->props_end);
|
||||
jsid id = *ni->current();
|
||||
if (JSID_IS_ATOM(id)) {
|
||||
rval->setString(JSID_TO_STRING(id));
|
||||
ni->incCursor();
|
||||
return true;
|
||||
}
|
||||
/* Take the slow path if we have to stringify a numeric property name. */
|
||||
rval->setString(*ni->current());
|
||||
ni->incCursor();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return js_IteratorNext(cx, iterobj, rval);
|
||||
|
@ -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())
|
||||
|
@ -62,9 +62,9 @@ namespace js {
|
||||
|
||||
struct NativeIterator {
|
||||
HeapPtrObject obj;
|
||||
HeapId *props_array;
|
||||
HeapId *props_cursor;
|
||||
HeapId *props_end;
|
||||
HeapPtr<JSFlatString> *props_array;
|
||||
HeapPtr<JSFlatString> *props_cursor;
|
||||
HeapPtr<JSFlatString> *props_end;
|
||||
const Shape **shapes_array;
|
||||
uint32_t shapes_length;
|
||||
uint32_t shapes_key;
|
||||
@ -73,11 +73,11 @@ struct NativeIterator {
|
||||
|
||||
bool isKeyIter() const { return (flags & JSITER_FOREACH) == 0; }
|
||||
|
||||
inline HeapId *begin() const {
|
||||
inline HeapPtr<JSFlatString> *begin() const {
|
||||
return props_array;
|
||||
}
|
||||
|
||||
inline HeapId *end() const {
|
||||
inline HeapPtr<JSFlatString> *end() const {
|
||||
return props_end;
|
||||
}
|
||||
|
||||
@ -85,7 +85,7 @@ struct NativeIterator {
|
||||
return end() - begin();
|
||||
}
|
||||
|
||||
HeapId *current() const {
|
||||
HeapPtr<JSFlatString> *current() const {
|
||||
JS_ASSERT(props_cursor < props_end);
|
||||
return props_cursor;
|
||||
}
|
||||
|
@ -673,7 +673,11 @@ Reify(JSContext *cx, JSCompartment *origin, Value *vp)
|
||||
if (!keys.resize(length))
|
||||
return false;
|
||||
for (size_t i = 0; i < length; ++i) {
|
||||
keys[i] = ni->begin()[i];
|
||||
jsid id;
|
||||
if (!ValueToId(cx, StringValue(ni->begin()[i]), &id))
|
||||
return false;
|
||||
id = js_CheckForStringIndex(id);
|
||||
keys[i] = id;
|
||||
if (!origin->wrapId(cx, &keys[i]))
|
||||
return false;
|
||||
}
|
||||
|
@ -6228,15 +6228,11 @@ mjit::Compiler::iterNext(ptrdiff_t offset)
|
||||
/* Get cursor. */
|
||||
masm.loadPtr(Address(T1, offsetof(NativeIterator, props_cursor)), T2);
|
||||
|
||||
/* Test if the jsid is a string. */
|
||||
/* Get the next string in the iterator. */
|
||||
masm.loadPtr(T2, T3);
|
||||
masm.move(T3, T4);
|
||||
masm.andPtr(Imm32(JSID_TYPE_MASK), T4);
|
||||
notFast = masm.branchTestPtr(Assembler::NonZero, T4, T4);
|
||||
stubcc.linkExit(notFast, Uses(1));
|
||||
|
||||
/* It's safe to increase the cursor now. */
|
||||
masm.addPtr(Imm32(sizeof(jsid)), T2, T4);
|
||||
masm.addPtr(Imm32(sizeof(JSString*)), T2, T4);
|
||||
masm.storePtr(T4, Address(T1, offsetof(NativeIterator, props_cursor)));
|
||||
|
||||
frame.freeReg(T4);
|
||||
|
Loading…
Reference in New Issue
Block a user