Get merge building js shell and passing trace/ref tests. Still need to fix up browser

This commit is contained in:
Luke Wagner
2010-07-04 00:12:06 -07:00
parent 4c1e611e2a
commit c069799e2b
49 changed files with 1761 additions and 1339 deletions

View File

@@ -105,10 +105,10 @@ ExtendedClass js_IteratorClass = {
void
NativeIterator::mark(JSTracer *trc)
{
if ((flags & JSITER_FOREACH) == 0)
MarkIdRange(trc, (jsid *)props_array, (jsid *)props_end, "props");
if (isKeyIter())
MarkIdRange(trc, beginKey(), endKey(), "props");
else
MarkValueRange(trc, (Value *)props_array, (Value *)props_end, "props");
MarkValueRange(trc, beginValue(), endValue(), "props");
MarkObject(trc, obj, "obj");
}
@@ -138,6 +138,18 @@ iterator_trace(JSTracer *trc, JSObject *obj)
ni->mark(trc);
}
struct IdHashPolicy {
typedef jsid Lookup;
static HashNumber hash(jsid id) {
return JSID_BITS(id);
}
static bool match(jsid id1, jsid id2) {
return id1 == id2;
}
};
typedef HashSet<jsid, IdHashPolicy, ContextAllocPolicy> IdSet;
static inline bool
NewKeyValuePair(JSContext *cx, jsid id, const Value &val, Value *rval)
{
@@ -151,52 +163,24 @@ NewKeyValuePair(JSContext *cx, jsid id, const Value &val, Value *rval)
return true;
}
template <class T>
static inline void
Reverse(T *beg, T *end)
struct KeyEnumeration
{
while (beg != end) {
if (--end == beg)
return;
T tmp = *beg;
*beg = *end;
*end = tmp;
++beg;
}
}
typedef AutoIdVector ResultVector;
struct IterateKeyResults
{
AutoIdVector vec;
IterateKeyResults(JSContext *cx) : vec(cx) {}
const jsid *begin() const { return vec.begin(); }
size_t length() const { return vec.length(); }
void reverse(size_t startingAt) {
Reverse(vec.begin() + startingAt, vec.end());
}
JS_ALWAYS_INLINE bool addProperty(JSContext *, JSObject *, jsid id, uintN flags)
static JS_ALWAYS_INLINE bool
append(JSContext *, AutoIdVector &vec, JSObject *, jsid id, uintN flags)
{
JS_ASSERT((flags & JSITER_FOREACH) == 0);
return vec.append(id);
}
};
struct IterateValueResults
struct ValueEnumeration
{
AutoValueVector vec;
IterateValueResults(JSContext *cx) : vec(cx) {}
typedef AutoValueVector ResultVector;
const Value *begin() const { return vec.begin(); }
size_t length() const { return vec.length(); }
void reverse(size_t startingAt) {
Reverse(vec.begin() + startingAt, vec.end());
}
bool addProperty(JSContext *cx, JSObject *obj, jsid id, uintN flags)
static JS_ALWAYS_INLINE bool
append(JSContext *cx, AutoValueVector &vec, JSObject *obj, jsid id, uintN flags)
{
JS_ASSERT(flags & JSITER_FOREACH);
@@ -214,70 +198,59 @@ struct IterateValueResults
}
};
struct IdHashPolicy {
typedef jsid Lookup;
static HashNumber hash(jsid id) {
return JSID_BITS(id);
}
static bool match(jsid id1, jsid id2) {
return id1 == id2;
}
};
typedef HashSet<jsid, IdHashPolicy, ContextAllocPolicy> IdSet;
template <class ResultSet>
template <class EnumPolicy>
static inline bool
Enumerate(JSContext *cx, JSObject *obj, JSObject *pobj, jsid id,
bool enumerable, uintN flags, IdSet& seen, ResultSet &results)
bool enumerable, uintN flags, IdSet& ht,
typename EnumPolicy::ResultVector &vec)
{
JS_ASSERT(JSID_IS_INT(id) || JSID_IS_ATOM(id));
if (JS_LIKELY(!(flags & JSITER_OWNONLY))) {
IdSet::AddPtr p = seen.lookupForAdd(id);
IdSet::AddPtr p = ht.lookupForAdd(id);
/* property already encountered, done. */
if (JS_UNLIKELY(!!p))
return true;
/* no need to add properties to the hash table at the end of the prototype chain */
if (pobj->getProto() && !seen.add(p, id))
if (pobj->getProto() && !ht.add(p, id))
return false;
}
if (enumerable || (flags & JSITER_HIDDEN))
return results.addProperty(cx, obj, id, flags);
return EnumPolicy::append(cx, vec, obj, id, flags);
return true;
}
template <class ResultSet>
template <class EnumPolicy>
static bool
EnumerateNativeProperties(JSContext *cx, JSObject *obj, JSObject *pobj, uintN flags,
IdSet &seen, ResultSet &results)
EnumerateNativeProperties(JSContext *cx, JSObject *obj, JSObject *pobj, uintN flags, IdSet &ht,
typename EnumPolicy::ResultVector &vec)
{
JS_LOCK_OBJ(cx, pobj);
size_t initialLength = results.length();
size_t initialLength = vec.length();
/* Collect all unique properties from this object's scope. */
JSScope *scope = pobj->scope();
for (JSScopeProperty *sprop = scope->lastProperty(); sprop; sprop = sprop->parent) {
if (!JSID_IS_DEFAULT_XML_NAMESPACE(sprop->id) &&
!sprop->isAlias() &&
!Enumerate(cx, obj, pobj, sprop->id, sprop->enumerable(), flags, seen, results)) {
!Enumerate<EnumPolicy>(cx, obj, pobj, sprop->id, sprop->enumerable(), flags, ht, vec)) {
return false;
}
}
results.reverse(initialLength);
Reverse(vec.begin() + initialLength, vec.end());
JS_UNLOCK_SCOPE(cx, scope);
return true;
}
template <class ResultSet>
template <class EnumPolicy>
static bool
EnumerateDenseArrayProperties(JSContext *cx, JSObject *obj, JSObject *pobj, uintN flags,
IdSet &seen, ResultSet &results)
IdSet &ht, typename EnumPolicy::ResultVector &vec)
{
size_t count = pobj->getDenseArrayCount();
@@ -287,7 +260,7 @@ EnumerateDenseArrayProperties(JSContext *cx, JSObject *obj, JSObject *pobj, uint
for (size_t i = 0; i < capacity; ++i, ++vp) {
if (!vp->isMagic(JS_ARRAY_HOLE)) {
/* Dense arrays never get so large that i would not fit into an integer id. */
if (!Enumerate(cx, obj, pobj, INT_TO_JSID(i), true, flags, seen, results))
if (!Enumerate<EnumPolicy>(cx, obj, pobj, INT_TO_JSID(i), true, flags, ht, vec))
return false;
}
}
@@ -295,54 +268,12 @@ EnumerateDenseArrayProperties(JSContext *cx, JSObject *obj, JSObject *pobj, uint
return true;
}
inline void
NativeIterator::init(JSObject *obj, uintN flags, uint32 *sarray, uint32 slength, uint32 key)
{
this->obj = obj;
this->flags = flags;
this->shapes_array = (uint32 *) this->props_end;
this->shapes_length = slength;
this->shapes_key = key;
if (slength)
memcpy(this->shapes_array, sarray, slength * sizeof(uint32));
}
NativeIterator *
NativeIterator::allocateKeyIterator(JSContext *cx, uint32 slength,
const jsid *parray, uint32 plength)
{
NativeIterator *ni = (NativeIterator *)
cx->malloc(sizeof(NativeIterator) + plength * sizeof(jsid) + slength * sizeof(uint32));
if (!ni)
return NULL;
ni->props_array = ni->props_cursor = (jsid *) (ni + 1);
ni->props_end = (jsid *)ni->props_array + plength;
if (plength)
memcpy(ni->props_array, parray, plength * sizeof(jsid));
return ni;
}
NativeIterator *
NativeIterator::allocateValueIterator(JSContext *cx, uint32 slength,
const Value *parray, uint32 plength)
{
NativeIterator *ni = (NativeIterator *)
cx->malloc(sizeof(NativeIterator) + plength * sizeof(Value) + slength * sizeof(uint32));
if (!ni)
return NULL;
ni->props_array = ni->props_cursor = (Value *) (ni + 1);
ni->props_end = (Value *)ni->props_array + plength;
if (plength)
memcpy(ni->props_array, parray, plength * sizeof(Value));
return ni;
}
template <class ResultSet>
template <class EnumPolicy>
static bool
Snapshot(JSContext *cx, JSObject *obj, uintN flags, ResultSet &results)
Snapshot(JSContext *cx, JSObject *obj, uintN flags, typename EnumPolicy::ResultVector &vec)
{
IdSet seen(cx);
if (!(flags & JSITER_OWNONLY) && !seen.init(32))
IdSet ht(cx);
if (!(flags & JSITER_OWNONLY) && !ht.init(32))
return NULL;
JSObject *pobj = obj;
@@ -353,10 +284,10 @@ Snapshot(JSContext *cx, JSObject *obj, uintN flags, ResultSet &results)
!(clasp->flags & JSCLASS_NEW_ENUMERATE)) {
if (!clasp->enumerate(cx, pobj))
return false;
if (!EnumerateNativeProperties(cx, obj, pobj, flags, seen, results))
if (!EnumerateNativeProperties<EnumPolicy>(cx, obj, pobj, flags, ht, vec))
return false;
} else if (pobj->isDenseArray()) {
if (!EnumerateDenseArrayProperties(cx, obj, pobj, flags, seen, results))
if (!EnumerateDenseArrayProperties<EnumPolicy>(cx, obj, pobj, flags, ht, vec))
return false;
} else {
if (pobj->isProxy()) {
@@ -369,7 +300,7 @@ Snapshot(JSContext *cx, JSObject *obj, uintN flags, ResultSet &results)
return false;
}
for (size_t n = 0, len = proxyProps.length(); n < len; n++) {
if (!Enumerate(cx, obj, pobj, proxyProps[n], true, flags, seen, results))
if (!Enumerate<EnumPolicy>(cx, obj, pobj, proxyProps[n], true, flags, ht, vec))
return false;
}
/* Proxy objects enumerate the prototype on their own, so we are done here. */
@@ -379,7 +310,7 @@ Snapshot(JSContext *cx, JSObject *obj, uintN flags, ResultSet &results)
if (!pobj->enumerate(cx, JSENUMERATE_INIT, &state, NULL))
return false;
if (state.isMagic(JS_NATIVE_ENUMERATE)) {
if (!EnumerateNativeProperties(cx, obj, pobj, flags, seen, results))
if (!EnumerateNativeProperties<EnumPolicy>(cx, obj, pobj, flags, ht, vec))
return false;
} else {
while (true) {
@@ -388,7 +319,7 @@ Snapshot(JSContext *cx, JSObject *obj, uintN flags, ResultSet &results)
return false;
if (state.isNull())
break;
if (!Enumerate(cx, obj, pobj, id, true, flags, seen, results))
if (!Enumerate<EnumPolicy>(cx, obj, pobj, id, true, flags, ht, vec))
return false;
}
}
@@ -401,52 +332,19 @@ Snapshot(JSContext *cx, JSObject *obj, uintN flags, ResultSet &results)
return true;
}
static NativeIterator *
SnapshotValues(JSContext *cx, JSObject *obj, uintN flags, uint32 *sarray, uint32 slength, uint32 key)
bool
VectorToIdArray(JSContext *cx, AutoIdVector &props, JSIdArray **idap)
{
JS_ASSERT(flags & JSITER_FOREACH);
JS_STATIC_ASSERT(sizeof(JSIdArray) > sizeof(jsid));
size_t len = props.length();
size_t idsz = len * sizeof(jsid);
size_t sz = (sizeof(JSIdArray) - sizeof(jsid)) + idsz;
JSIdArray *ida = static_cast<JSIdArray *>(cx->malloc(sz));
if (!ida)
return false;
IterateValueResults results(cx);
if (!Snapshot(cx, obj, flags, results))
return NULL;
NativeIterator *ni = NativeIterator::allocateValueIterator(cx, slength,
results.begin(), results.length());
if (!ni)
return NULL;
ni->init(obj, flags, sarray, slength, key);
return ni;
}
static NativeIterator *
SnapshotKeys(JSContext *cx, JSObject *obj, uintN flags, uint32 *sarray, uint32 slength, uint32 key)
{
JS_ASSERT(!(flags & JSITER_FOREACH));
IterateKeyResults results(cx);
if (!Snapshot(cx, obj, flags, results))
return NULL;
NativeIterator *ni = NativeIterator::allocateKeyIterator(cx, slength,
results.begin(), results.length());
if (!ni)
return NULL;
ni->init(obj, flags, sarray, slength, key);
return ni;
}
static inline bool
NativeIteratorToJSIdArray(JSContext *cx, NativeIterator *ni, JSIdArray **idap)
{
/* Morph the NativeIterator into a JSIdArray. The caller will deallocate it. */
JS_ASSERT(sizeof(NativeIterator) > sizeof(JSIdArray));
JS_ASSERT(!(ni->flags & JSITER_FOREACH));
JS_ASSERT(ni->props_array == (jsid *) (ni + 1));
size_t length = size_t((jsid *)ni->props_end - (jsid *)ni->props_array);
JSIdArray *ida = (JSIdArray *) (uintptr_t(ni->props_array) - (sizeof(JSIdArray) - sizeof(jsid)));
ida->self = ni;
ida->length = length;
JS_ASSERT(&ida->vector[0] == (jsid *)ni->props_array);
ida->length = static_cast<jsint>(len);
memcpy(ida->vector, props.begin(), idsz);
*idap = ida;
return true;
}
@@ -454,11 +352,7 @@ NativeIteratorToJSIdArray(JSContext *cx, NativeIterator *ni, JSIdArray **idap)
bool
GetPropertyNames(JSContext *cx, JSObject *obj, uintN flags, AutoIdVector &props)
{
#error "either want to have SnapshotKeys fill props or something else...
NativeIterator *ni = SnapshotKeys(cx, obj, flags & (JSITER_OWNONLY | JSITER_HIDDEN), NULL, 0, true);
if (!ni)
return false;
return NativeIteratorToJSIdArray(cx, ni, idap);
return Snapshot<KeyEnumeration>(cx, obj, flags & (JSITER_OWNONLY | JSITER_HIDDEN), props);
}
static inline bool
@@ -526,13 +420,55 @@ NewIteratorObject(JSContext *cx, uintN flags)
if (!obj)
return false;
obj->map = cx->runtime->emptyEnumeratorScope->hold();
obj->init(&js_IteratorClass.base, NULL, NULL, JSVAL_NULL);
obj->init(&js_IteratorClass.base, NULL, NULL, NullTag());
return obj;
}
return NewBuiltinClassInstance(cx, &js_IteratorClass.base);
}
NativeIterator *
NativeIterator::allocateKeyIterator(JSContext *cx, uint32 slength, const AutoIdVector &props)
{
size_t plength = props.length();
NativeIterator *ni = (NativeIterator *)
cx->malloc(sizeof(NativeIterator) + plength * sizeof(jsid) + slength * sizeof(uint32));
if (!ni)
return NULL;
ni->props_array = ni->props_cursor = (jsid *) (ni + 1);
ni->props_end = (jsid *)ni->props_array + plength;
if (plength)
memcpy(ni->props_array, props.begin(), plength * sizeof(jsid));
return ni;
}
NativeIterator *
NativeIterator::allocateValueIterator(JSContext *cx, uint32 slength, const AutoValueVector &props)
{
size_t plength = props.length();
NativeIterator *ni = (NativeIterator *)
cx->malloc(sizeof(NativeIterator) + plength * sizeof(Value) + slength * sizeof(uint32));
if (!ni)
return NULL;
ni->props_array = ni->props_cursor = (Value *) (ni + 1);
ni->props_end = (Value *)ni->props_array + plength;
if (plength)
memcpy(ni->props_array, props.begin(), plength * sizeof(Value));
return ni;
}
inline void
NativeIterator::init(JSObject *obj, uintN flags, const uint32 *sarray, uint32 slength, uint32 key)
{
this->obj = obj;
this->flags = flags;
this->shapes_array = (uint32 *) this->props_end;
this->shapes_length = slength;
this->shapes_key = key;
if (slength)
memcpy(this->shapes_array, sarray, slength * sizeof(uint32));
}
static inline void
RegisterEnumerator(JSContext *cx, JSObject *iterobj, NativeIterator *ni)
{
@@ -543,36 +479,87 @@ RegisterEnumerator(JSContext *cx, JSObject *iterobj, NativeIterator *ni)
}
}
bool
IdVectorToIterator(JSContext *cx, JSObject *obj, uintN flags, AutoIdVector &props, Value *vp)
static inline bool
VectorToKeyIterator(JSContext *cx, JSObject *obj, uintN flags, AutoIdVector &keys,
const uint32 *sarray, uint32 slength, uint32 key, Value *vp)
{
JS_ASSERT(!(flags & JSITER_FOREACH));
JSObject *iterobj = NewIteratorObject(cx, flags);
if (!iterobj)
return false;
vp->setObject(*iterobj);
NativeIterator *ni = NativeIterator::allocateKeyIterator(cx, 0, props);
NativeIterator *ni = NativeIterator::allocateKeyIterator(cx, slength, keys);
if (!ni)
return false;
ni->init(obj, flags, NULL, 0, 0);
/* If this is a for-each iteration, fetch the values or key/value pairs. */
if (flags & JSITER_FOREACH) {
size_t length = props.length();
for (size_t n = 0; n < length; ++n) {
jsval *vp = &ni->begin()[n];
if (!IdToIteratorValue(cx, obj, *vp, flags, vp))
return false;
}
}
return NULL;
ni->init(obj, flags, sarray, slength, key);
iterobj->setNativeIterator(ni);
vp->setObject(*iterobj);
RegisterEnumerator(cx, iterobj, ni);
return true;
}
bool
VectorToKeyIterator(JSContext *cx, JSObject *obj, uintN flags, AutoIdVector &props, Value *vp)
{
return VectorToKeyIterator(cx, obj, flags, props, NULL, 0, 0, vp);
}
static inline bool
VectorToValueIterator(JSContext *cx, JSObject *obj, uintN flags, AutoValueVector &vals,
const uint32 *sarray, uint32 slength, uint32 key, Value *vp)
{
JS_ASSERT(flags & JSITER_FOREACH);
JSObject *iterobj = NewIteratorObject(cx, flags);
if (!iterobj)
return false;
NativeIterator *ni = NativeIterator::allocateValueIterator(cx, slength, vals);
if (!ni)
return NULL;
ni->init(obj, flags, sarray, slength, key);
iterobj->setNativeIterator(ni);
vp->setObject(*iterobj);
RegisterEnumerator(cx, iterobj, ni);
return true;
}
bool
VectorToValueIterator(JSContext *cx, JSObject *obj, uintN flags, AutoValueVector &props, Value *vp)
{
return VectorToValueIterator(cx, obj, flags, props, NULL, 0, 0, vp);
}
bool
EnumeratedIdVectorToIterator(JSContext *cx, JSObject *obj, uintN flags, AutoIdVector &props, Value *vp)
{
if (!(flags & JSITER_FOREACH))
return VectorToKeyIterator(cx, obj, flags, props, vp);
/* For for-each iteration, we need to look up the value of each id. */
size_t plength = props.length();
AutoValueVector vals(cx);
if (!vals.reserve(plength))
return NULL;
for (size_t i = 0; i < plength; ++i) {
if (!ValueEnumeration::append(cx, vals, obj, props[i], flags))
return false;
}
return VectorToValueIterator(cx, obj, flags, vals, vp);
}
typedef Vector<uint32, 8> ShapeVector;
bool
GetIterator(JSContext *cx, JSObject *obj, uintN flags, Value *vp)
{
@@ -632,24 +619,19 @@ GetIterator(JSContext *cx, JSObject *obj, uintN flags, Value *vp)
return true;
}
JSObject *iterobj = NewIteratorObject(cx, flags);
if (!iterobj)
/* NB: for (var p in null) succeeds by iterating over no properties. */
if (flags & JSITER_FOREACH) {
AutoValueVector vals(cx);
if (JS_LIKELY(obj != NULL) && !Snapshot<ValueEnumeration>(cx, obj, flags, vals))
return false;
return VectorToValueIterator(cx, obj, flags, vals, shapes.begin(), shapes.length(), key, vp);
}
AutoIdVector keys(cx);
if (JS_LIKELY(obj != NULL) && !Snapshot<KeyEnumeration>(cx, obj, flags, keys))
return false;
/* Store in *vp to protect it from GC (callers must root vp). */
vp->setObject(*iterobj);
#error "TODO: handle null so that it succeeds with no properties... somehow"
NativeIterator *ni = (flags & JSITER_FOREACH)
? SnapshotValues(cx, obj, flags, shapes.begin(), shapes.length(), key)
: SnapshotKeys(cx, obj, flags, shapes.begin(), shapes.length(), key);
if (!ni)
return false;
iterobj->setNativeIterator(ni);
RegisterEnumerator(cx, iterobj, ni);
return true;
return VectorToKeyIterator(cx, obj, flags, keys, shapes.begin(), shapes.length(), key, vp);
}
static JSObject *
@@ -686,7 +668,7 @@ iterator_next(JSContext *cx, uintN argc, Value *vp)
{
JSObject *obj;
obj = ComputeThisObjectFromVp(cx, vp);
obj = ComputeThisFromVp(cx, vp);
if (!InstanceOf(cx, obj, &js_IteratorClass.base, vp + 2))
return false;
@@ -723,11 +705,10 @@ js_ValueToIterator(JSContext *cx, uintN flags, Value *vp)
*/
cx->iterValue.setMagic(JS_NO_ITER_VALUE);
AutoValueRooter tvr(cx);
JSObject *obj;
if (vp->isObject()) {
/* Common case. */
*tvr.addr() = *vp;
obj = &vp->asObject();
} else {
/*
* Enumerating over null and undefined gives an empty enumerator.
@@ -737,16 +718,18 @@ js_ValueToIterator(JSContext *cx, uintN flags, Value *vp)
* standard.
*/
if ((flags & JSITER_ENUMERATE)) {
if (!js_ValueToObjectOrNull(cx, *vp, tvr.addr()))
if (!js_ValueToObjectOrNull(cx, *vp, &obj))
return false;
if (tvr.value().isNull())
if (!obj)
return GetIterator(cx, NULL, flags, vp);
} else {
if (!js_ValueToNonNullObject(cx, *vp, tvr.addr()))
obj = js_ValueToNonNullObject(cx, *vp);
if (!obj)
return false;
}
}
JSObject *obj = &tvr.value().asObject();
AutoObjectRooter tvr(cx, obj);
Class *clasp = obj->getClass();
ExtendedClass *xclasp;
@@ -824,10 +807,10 @@ js_SuppressDeletedProperty(JSContext *cx, JSObject *obj, jsid id)
again:
NativeIterator *ni = iterobj->getNativeIterator();
/* This only works for identified surpressed keys, not values. */
if ((ni->flags & JSITER_FOREACH) && ni->obj == obj && ni->props_cursor < ni->props_end) {
if (ni->isKeyIter() && ni->obj == obj && ni->props_cursor < ni->props_end) {
/* Check whether id is still to come. */
jsid *props_cursor = (jsid *)ni->props_cursor;
jsid *props_end = (jsid *)ni->props_end;
jsid *props_cursor = ni->currentKey();
jsid *props_end = ni->endKey();
for (jsid *idp = props_cursor; idp < props_end; ++idp) {
if (*idp == id) {
/*
@@ -866,10 +849,10 @@ js_SuppressDeletedProperty(JSContext *cx, JSObject *obj, jsid id)
* If it is the next property to be enumerated, just skip it.
*/
if (idp == props_cursor) {
ni->props_cursor = (jsid *)ni->props_cursor + 1;
ni->incKeyCursor();
} else {
memmove(idp, idp + 1, (props_end - (idp + 1)) * sizeof(jsid));
ni->props_end = (jsid *)ni->props_end - 1;
ni->props_end = ni->endKey() - 1;
}
break;
}
@@ -935,15 +918,15 @@ js_IteratorNext(JSContext *cx, JSObject *iterobj, Value *rval)
*/
NativeIterator *ni = iterobj->getNativeIterator();
JS_ASSERT(ni->props_cursor < ni->props_end);
if ((ni->flags & JSITER_FOREACH) == 0) {
*rval = IdToValue(ni->currentId());
ni->incIdCursor();
if (ni->isKeyIter()) {
*rval = IdToValue(*ni->currentKey());
ni->incKeyCursor();
} else {
*rval = ni->currentValue();
*rval = *ni->currentValue();
ni->incValueCursor();
}
if (rval->isString() || (ni->flags & JSITER_FOREACH))
if (rval->isString() || !ni->isKeyIter())
return true;
JSString *str;
@@ -1097,11 +1080,10 @@ js_NewGenerator(JSContext *cx)
fp->callobj->setPrivate(newfp);
fp->callobj = NULL;
}
JSObject *argsobj = fp->argsObj();
newfp->setArgsObj(argsobj);
if (argsobj) { /* Steal args object. */
argsobj->setPrivate(newfp);
fp->setArgsObj(NULL);
newfp->argsobj = fp->argsobj;
if (fp->argsobj) { /* Steal args object. */
fp->argsobj->setPrivate(newfp);
fp->argsobj = NULL;
}
newfp->script = fp->script;
newfp->fun = fp->fun;
@@ -1217,7 +1199,7 @@ SendToGenerator(JSContext *cx, JSGeneratorOp op, JSObject *obj,
#ifdef DEBUG
JSObject *callobjBefore = fp->callobj;
JSObject *argsobjBefore = fp->argsObj();
JSObject *argsobjBefore = fp->argsobj;
#endif
/*
@@ -1228,8 +1210,8 @@ SendToGenerator(JSContext *cx, JSGeneratorOp op, JSObject *obj,
*/
if (genfp->callobj)
fp->callobj->setPrivate(fp);
if (genfp->argsObj())
fp->argsObj()->setPrivate(fp);
if (genfp->argsobj)
fp->argsobj->setPrivate(fp);
gen->liveFrame = fp;
(void)cx->enterGenerator(gen); /* OOM check above. */
@@ -1249,12 +1231,12 @@ SendToGenerator(JSContext *cx, JSGeneratorOp op, JSObject *obj,
/* Restore call/args/block objects. */
cx->leaveGenerator(gen);
gen->liveFrame = genfp;
if (fp->argsObj())
fp->argsObj()->setPrivate(genfp);
if (fp->argsobj)
fp->argsobj->setPrivate(genfp);
if (fp->callobj)
fp->callobj->setPrivate(genfp);
JS_ASSERT_IF(argsobjBefore, argsobjBefore == fp->argsObj());
JS_ASSERT_IF(argsobjBefore, argsobjBefore == fp->argsobj);
JS_ASSERT_IF(callobjBefore, callobjBefore == fp->callobj);
/* Copy and rebase stack frame/args/slots. Restore "floating" flag. */
@@ -1320,7 +1302,7 @@ generator_op(JSContext *cx, JSGeneratorOp op, Value *vp, uintN argc)
JSObject *obj;
LeaveTrace(cx);
obj = ComputeThisObjectFromVp(cx, vp);
obj = ComputeThisFromVp(cx, vp);
if (!InstanceOf(cx, obj, &js_GeneratorClass.base, vp + 2))
return JS_FALSE;