Bug 664159 - Fix eval-in-frame crash (r=waldo)
authorLuke Wagner <luke@mozilla.com>
Tue, 14 Jun 2011 17:35:19 -0700
changeset 71057 2ffda60b67dcea9fa8cdd9c0481dd1b7da078955
parent 71056 8159c48ac8c75a1d776659889588459654de0962
child 71058 589c2dd84ce6cdf418dae19a2436579e3c48bde6
push id1
push userroot
push dateMon, 20 Oct 2014 17:29:22 +0000
reviewerswaldo
bugs664159
milestone7.0a1
Bug 664159 - Fix eval-in-frame crash (r=waldo)
js/src/jit-test/tests/basic/testStackIterDebug.js
js/src/vm/Stack.cpp
js/src/vm/Stack.h
--- a/js/src/jit-test/tests/basic/testStackIterDebug.js
+++ b/js/src/jit-test/tests/basic/testStackIterDebug.js
@@ -45,8 +45,18 @@ function assertStackIs(s1) {
 (function f() { evalInFrame(0, "assertStackIs(['eval-code', evalInFrame, f, 'global-code'])", true); })();
 (function f() { (function g() { evalInFrame(1, "assertStackIs(['eval-code', f, 'global-code'])", true); })() })();
 (function f() { (function g() { evalInFrame(1, "assertStackIs(['eval-code', f, 'bound(f)', 'global-code'])", true); })() }).bind()();
 (function f() { (function g() { evalInFrame(1, "assertStackIs(['eval-code', f, 'bound(f)', 'global-code'])", true); }).bind()() }).bind()();
 (function f() { (function g() { evalInFrame(1, "assertStackIs(['eval-code', f, 'bound(f)', 'global-code'])", true); }).bind().bind()() }).bind()();
 
 (function f() { var o = { toString:function() { evalInFrame(1, "assertStackIs(['eval-code', f, 'global-code'])"); }}; [o,o].sort() })();
 (function f() { var o = { toString:function() { evalInFrame(1, "assertStackIs(['eval-code', f, 'global-code'])", true); }}; [o,o].sort() })();
+
+function inner() {
+    (function puppies() {
+        evalInFrame(1, "assertStackIs(['eval-code', inner, String.prototype.replace, outer, String.prototype.replace, 'global-code'])");
+    })();
+}
+function outer() {
+    "bbb".replace(/b/g, inner);
+}
+"aaa".replace(/a/g, outer);
--- a/js/src/vm/Stack.cpp
+++ b/js/src/vm/Stack.cpp
@@ -283,16 +283,22 @@ StackSegment::popRegs(FrameRegs *regs)
 void
 StackSegment::pushCall(CallArgsList &callList)
 {
     callList.prev_ = calls_;
     calls_ = &callList;
 }
 
 void
+StackSegment::pointAtCall(CallArgsList &callList)
+{
+    calls_ = &callList;
+}
+
+void
 StackSegment::popCall()
 {
     calls_ = calls_->prev_;
 }
 
 /*****************************************************************************/
 
 StackSpace::StackSpace()
@@ -642,17 +648,17 @@ ContextStack::pushExecuteFrame(JSContext
 
     StackFrame *fp = reinterpret_cast<StackFrame *>(firstUnused + 2);
     fp->initExecuteFrame(script, prev, seg_->maybeRegs(), thisv, scopeChain, type);
     SetValueRangeToUndefined(fp->slots(), script->nfixed);
     efg->regs_.prepareToRun(*fp, script);
 
     /* pushRegs() below links the prev-frame; manually link the prev-call. */
     if (evalInFrame && evalInFrameCalls)
-        seg_->pushCall(*evalInFrameCalls);
+        seg_->pointAtCall(*evalInFrameCalls);
 
     efg->prevRegs_ = seg_->pushRegs(efg->regs_);
     JS_ASSERT(space().firstUnused() == efg->regs_.sp);
     efg->setPushed(*this);
     return true;
 }
 
 bool
--- a/js/src/vm/Stack.h
+++ b/js/src/vm/Stack.h
@@ -1267,16 +1267,17 @@ class StackSegment
 
     StackFrame *computeNextFrame(const StackFrame *fp) const;
 
     Value *end() const;
 
     FrameRegs *pushRegs(FrameRegs &regs);
     void popRegs(FrameRegs *regs);
     void pushCall(CallArgsList &callList);
+    void pointAtCall(CallArgsList &callList);
     void popCall();
 
     /* For jit access: */
 
     static const size_t offsetOfRegs() { return offsetof(StackSegment, regs_); }
 };
 
 static const size_t VALUES_PER_STACK_SEGMENT = sizeof(StackSegment) / sizeof(Value);