diff --git a/js/src/jstracer.cpp b/js/src/jstracer.cpp index 14e761eab2b1..1bef06ae2aef 100644 --- a/js/src/jstracer.cpp +++ b/js/src/jstracer.cpp @@ -2226,9 +2226,10 @@ GetUpvarOnTrace(JSContext* cx, uint32 upvarLevel, int32 slot, uint32 callDepth, * stack. */ int32 nativeStackFramePos = state->callstackBase[0]->spoffset; + // Duplicate native stack layout computation: see VisitFrameSlots header comment. for (FrameInfo** fip2 = state->callstackBase; fip2 <= fip; fip2++) - nativeStackFramePos += (*fip2)->spdist; - nativeStackFramePos -= (2 + (*fip)->get_argc()); + nativeStackFramePos += (*fip2)->spdist + 1 /* arguments */; + nativeStackFramePos -= (3 /* callee,this,arguments */ + (*fip)->get_argc()); uint32 native_slot = T::native_slot((*fip)->get_argc(), slot); *result = state->stackBase[nativeStackFramePos + native_slot]; return fi->get_typemap()[native_slot]; diff --git a/js/src/trace-test.js b/js/src/trace-test.js index bf2f9dfbcc2b..60653d1e38fd 100644 --- a/js/src/trace-test.js +++ b/js/src/trace-test.js @@ -5625,6 +5625,31 @@ function testBug507425() { testBug507425.expected = "ok"; test(testBug507425); +function testNestedClosures() { + function f(a, b) { + function g(x, y) { + function h(m, n) { + function k(u, v) { + var s = ''; + for (var i = 0; i < 5; ++i) + s = a + ',' + b + ',' + x + ',' + y + ',' + m + ',' + n + ',' + u + ',' + v; + return s; + } + return k(m+1, n+1); + } + return h(x+1, y+1); + } + return g(a+1, b+1); + } + + var s1; + for (var i = 0; i < 5; ++i) + s1 = f(i, i+i); + return s1; +} +testNestedClosures.expected = '4,8,5,9,6,10,7,11'; +test(testNestedClosures); + /***************************************************************************** * * * _____ _ _ _____ ______ _____ _______ *