Bug 510655: set argsobj->private when leaving trace only if created on trace, r=igor
--- a/js/src/jstracer.cpp
+++ b/js/src/jstracer.cpp
@@ -2625,18 +2625,20 @@ FlushNativeStackFrame(JSContext* cx, uns
// Skip over stopFrame itself.
JS_ASSERT(n != 0);
--n;
fp = fp->down;
}
for (; n != 0; fp = fp->down) {
--n;
if (fp->callee) {
- if (fp->argsobj)
- JS_SetPrivate(cx, JSVAL_TO_OBJECT(fp->argsobj), fp);
+ // fp->argsobj->getPrivate() is NULL iff we created argsobj on trace.
+ if (fp->argsobj && !JSVAL_TO_OBJECT(fp->argsobj)->getPrivate()) {
+ JSVAL_TO_OBJECT(fp->argsobj)->setPrivate(fp);
+ }
/*
* We might return from trace with a different callee object, but it still
* has to be the same JSFunction (FIXME: bug 471425, eliminate fp->callee).
*/
JS_ASSERT(JSVAL_IS_OBJECT(fp->argv[-1]));
JS_ASSERT(HAS_FUNCTION_CLASS(JSVAL_TO_OBJECT(fp->argv[-2])));
JS_ASSERT(GET_FUNCTION_PRIVATE(cx, JSVAL_TO_OBJECT(fp->argv[-2])) ==
new file mode 100644
--- /dev/null
+++ b/js/src/trace-test/tests/basic/bug510655.js
@@ -0,0 +1,15 @@
+// This should not crash (or assert in debug builds).
+
+(function () {
+ for (b in [0, 0]) {
+ (eval("\
+ [this\
+ for (b in [\
+ [undefined],\
+ arguments,\
+ [undefined]\
+ ])\
+ ]\
+ "))
+ }
+})()