diff --git a/js/src/jsinterp.c b/js/src/jsinterp.c index b7c57288638..184005a236d 100644 --- a/js/src/jsinterp.c +++ b/js/src/jsinterp.c @@ -2326,6 +2326,12 @@ js_Interpret(JSContext *cx, jsval *result) vp = &sp[i - 1]; rval = *vp; + /* + * Save sp in fp now, before any OBJ_* call-outs that might nest + * an interpreter or GC activation on this context. + */ + SAVE_SP(fp); + /* Is this the first iteration ? */ if (JSVAL_IS_VOID(rval)) { /* Yes, create a new JSObject to hold the iterator state */ @@ -2589,6 +2595,7 @@ js_Interpret(JSContext *cx, jsval *result) obj = fp->varobj; atom = GET_ATOM(cx, script, pc); rval = FETCH_OPND(-1); + SAVE_SP(fp); ok = OBJ_DEFINE_PROPERTY(cx, obj, ATOM_TO_JSID(atom), rval, NULL, NULL, JSPROP_ENUMERATE | JSPROP_PERMANENT | @@ -2989,6 +2996,7 @@ js_Interpret(JSContext *cx, jsval *result) #if JS_HAS_INITIALIZERS do_new: #endif + SAVE_SP(fp); vp = sp - (2 + argc); JS_ASSERT(vp >= fp->spbase); @@ -3001,7 +3009,6 @@ js_Interpret(JSContext *cx, jsval *result) OBJ_GET_CLASS(cx, obj2) == &js_FunctionClass || !obj2->map->ops->construct) { - SAVE_SP(fp); fun = js_ValueToFunction(cx, vp, JSV2F_CONSTRUCT); if (!fun) { ok = JS_FALSE; @@ -3038,7 +3045,6 @@ js_Interpret(JSContext *cx, jsval *result) /* Now we have an object with a constructor method; call it. */ vp[1] = OBJECT_TO_JSVAL(obj); - SAVE_SP(fp); ok = js_Invoke(cx, argc, JSINVOKE_CONSTRUCT); RESTORE_SP(fp); LOAD_BRANCH_CALLBACK(cx); @@ -3938,6 +3944,7 @@ js_Interpret(JSContext *cx, jsval *result) #if JS_HAS_EXPORT_IMPORT case JSOP_EXPORTALL: + SAVE_SP(fp); obj = fp->varobj; ida = JS_Enumerate(cx, obj); if (!ida) { @@ -3967,6 +3974,7 @@ js_Interpret(JSContext *cx, jsval *result) atom = GET_ATOM(cx, script, pc); id = ATOM_TO_JSID(atom); obj = fp->varobj; + SAVE_SP(fp); ok = OBJ_LOOKUP_PROPERTY(cx, obj, id, &obj2, &prop); if (!ok) goto out; @@ -4440,6 +4448,7 @@ js_Interpret(JSContext *cx, jsval *result) * have seen the right parent already and created a sufficiently * well-scoped function object. */ + SAVE_SP(fp); parent = fp->scopeChain; if (OBJ_GET_PARENT(cx, obj) != parent) { obj = js_CloneFunctionObject(cx, obj, parent); @@ -4552,6 +4561,7 @@ js_Interpret(JSContext *cx, jsval *result) * Getters and setters are just like watchpoints from an access * control point of view. */ + SAVE_SP(fp); ok = OBJ_CHECK_ACCESS(cx, obj, id, JSACC_WATCH, &rtmp, &attrs); if (!ok) goto out; @@ -4627,6 +4637,7 @@ js_Interpret(JSContext *cx, jsval *result) obj = JSVAL_TO_OBJECT(lval); /* Set the property named by obj[id] to rval. */ + SAVE_SP(fp); ok = OBJ_SET_PROPERTY(cx, obj, id, &rval); if (!ok) goto out; @@ -4635,6 +4646,7 @@ js_Interpret(JSContext *cx, jsval *result) #if JS_HAS_SHARP_VARS case JSOP_DEFSHARP: + SAVE_SP(fp); obj = fp->sharpArray; if (!obj) { obj = js_NewArrayObject(cx, 0, NULL); @@ -4667,6 +4679,7 @@ js_Interpret(JSContext *cx, jsval *result) if (!obj) { rval = JSVAL_VOID; } else { + SAVE_SP(fp); ok = OBJ_GET_PROPERTY(cx, obj, id, &rval); if (!ok) goto out; @@ -4743,6 +4756,7 @@ js_Interpret(JSContext *cx, jsval *result) obj = JSVAL_TO_OBJECT(lval); /* Define obj[id] to contain rval and to be permanent. */ + SAVE_SP(fp); ok = OBJ_DEFINE_PROPERTY(cx, obj, id, rval, NULL, NULL, JSPROP_PERMANENT, NULL); if (!ok)