Remove LIFO invariants from the enumerator list (bug 831626, r=billm).

This commit is contained in:
Bill McCloskey
2013-01-24 11:17:41 -08:00
parent cbb58a076f
commit ffe8179b7f
11 changed files with 173 additions and 55 deletions

View File

@@ -434,13 +434,30 @@ NativeIterator::allocateIterator(JSContext *cx, uint32_t slength, const AutoIdVe
ni->props_array[i].init(str);
}
}
ni->next_ = NULL;
ni->prev_ = NULL;
return ni;
}
NativeIterator *
NativeIterator::allocateSentinel(JSContext *cx)
{
NativeIterator *ni = (NativeIterator *)js_malloc(sizeof(NativeIterator));
if (!ni)
return NULL;
PodZero(ni);
ni->next_ = ni;
ni->prev_ = ni;
return ni;
}
inline void
NativeIterator::init(RawObject obj, unsigned flags, uint32_t slength, uint32_t key)
NativeIterator::init(RawObject obj, RawObject iterObj, unsigned flags, uint32_t slength, uint32_t key)
{
this->obj.init(obj);
this->iterObj_ = iterObj;
this->flags = flags;
this->shapes_array = (Shape **) this->props_end;
this->shapes_length = slength;
@@ -452,8 +469,7 @@ RegisterEnumerator(JSContext *cx, PropertyIteratorObject *iterobj, NativeIterato
{
/* Register non-escaping native enumerators (for-in) with the current context. */
if (ni->flags & JSITER_ENUMERATE) {
ni->next = cx->enumerators;
cx->enumerators = iterobj;
ni->link(cx->compartment->enumerators);
JS_ASSERT(!(ni->flags & JSITER_ACTIVE));
ni->flags |= JSITER_ACTIVE;
@@ -479,7 +495,7 @@ VectorToKeyIterator(JSContext *cx, HandleObject obj, unsigned flags, AutoIdVecto
NativeIterator *ni = NativeIterator::allocateIterator(cx, slength, keys);
if (!ni)
return false;
ni->init(obj, flags, slength, key);
ni->init(obj, iterobj, flags, slength, key);
if (slength) {
/*
@@ -531,7 +547,7 @@ js::VectorToValueIterator(JSContext *cx, HandleObject obj, unsigned flags, AutoI
NativeIterator *ni = NativeIterator::allocateIterator(cx, 0, keys);
if (!ni)
return false;
ni->init(obj, flags, 0, 0);
ni->init(obj, iterobj, flags, 0, 0);
iterobj->setNativeIterator(ni);
vp.setObject(*iterobj);
@@ -1011,8 +1027,7 @@ js::CloseIterator(JSContext *cx, HandleObject obj)
NativeIterator *ni = obj->asPropertyIterator().getNativeIterator();
if (ni->flags & JSITER_ENUMERATE) {
JS_ASSERT(cx->enumerators == obj);
cx->enumerators = ni->next;
ni->unlink();
JS_ASSERT(ni->flags & JSITER_ACTIVE);
ni->flags &= ~JSITER_ACTIVE;
@@ -1048,10 +1063,8 @@ js::UnwindIteratorForUncatchableException(JSContext *cx, RawObject obj)
{
if (obj->isPropertyIterator()) {
NativeIterator *ni = obj->asPropertyIterator().getNativeIterator();
if (ni->flags & JSITER_ENUMERATE) {
JS_ASSERT(cx->enumerators == obj);
cx->enumerators = ni->next;
}
if (ni->flags & JSITER_ENUMERATE)
ni->unlink();
}
}
@@ -1076,10 +1089,11 @@ template<typename StringPredicate>
static bool
SuppressDeletedPropertyHelper(JSContext *cx, HandleObject obj, StringPredicate predicate)
{
RootedPropertyIteratorObject iterobj(cx, cx->enumerators);
while (iterobj) {
NativeIterator *enumeratorList = cx->compartment->enumerators;
NativeIterator *ni = enumeratorList->next();
while (ni != enumeratorList) {
again:
NativeIterator *ni = iterobj->getNativeIterator();
/* 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. */
@@ -1087,6 +1101,12 @@ SuppressDeletedPropertyHelper(JSContext *cx, HandleObject obj, StringPredicate p
HeapPtr<JSFlatString> *props_end = ni->end();
for (HeapPtr<JSFlatString> *idp = props_cursor; idp < props_end; ++idp) {
if (predicate(*idp)) {
/*
* Root the iterobj. This loop can GC, so we want to make sure that if
* the GC removes any elements from the list, it won't remove this one.
*/
AutoObjectRooter iterRoot(cx, ni->iterObj());
/*
* Check whether another property along the prototype chain
* became visible as a result of this deletion.
@@ -1149,7 +1169,7 @@ SuppressDeletedPropertyHelper(JSContext *cx, HandleObject obj, StringPredicate p
}
}
}
iterobj = ni->next;
ni = ni->next();
}
return true;
}
@@ -1467,7 +1487,6 @@ js_NewGenerator(JSContext *cx)
/* Initialize JSGenerator. */
gen->obj.init(obj);
gen->state = JSGEN_NEWBORN;
gen->enumerators = NULL;
gen->fp = genfp;
gen->prevGenerator = NULL;
@@ -1563,14 +1582,10 @@ SendToGenerator(JSContext *cx, JSGeneratorOp op, HandleObject obj,
gen->regs = cx->regs();
cx->enterGenerator(gen); /* OOM check above. */
RootedPropertyIteratorObject enumerators(cx, cx->enumerators);
cx->enumerators = gen->enumerators;
RootedScript script(cx, fp->script());
ok = RunScript(cx, script, fp);
gen->enumerators = cx->enumerators;
cx->enumerators = enumerators;
cx->leaveGenerator(gen);
}
@@ -1783,7 +1798,7 @@ GlobalObject::initIteratorClasses(JSContext *cx, Handle<GlobalObject *> global)
NativeIterator *ni = NativeIterator::allocateIterator(cx, 0, blank);
if (!ni)
return false;
ni->init(NULL, 0 /* flags */, 0, 0);
ni->init(NULL, NULL, 0 /* flags */, 0, 0);
iteratorProto->asPropertyIterator().setNativeIterator(ni);