Bug 1155466 - Freshened blocks should pop their old blocks in debug scopes. (r=Waldo)
authorShu-yu Guo <shu@rfrn.org>
Thu, 16 Apr 2015 20:32:49 -0700
changeset 239696 fd1a9a382e7bba119a07869ea392a816f574cae8
parent 239695 1a51b749299f4528524fb259e479d456b309889f
child 239697 66eee8b402fd5dbc78479a55c32bb2aad131c847
push id12444
push userryanvm@gmail.com
push dateFri, 17 Apr 2015 20:04:42 +0000
treeherderfx-team@560a202db924 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersWaldo
bugs1155466
milestone40.0a1
Bug 1155466 - Freshened blocks should pop their old blocks in debug scopes. (r=Waldo)
js/src/jit-test/tests/debug/Environment-identity-05.js
js/src/jit/BaselineCompiler.cpp
js/src/jit/VMFunctions.cpp
js/src/jit/VMFunctions.h
js/src/vm/Interpreter.cpp
new file mode 100644
--- /dev/null
+++ b/js/src/jit-test/tests/debug/Environment-identity-05.js
@@ -0,0 +1,19 @@
+// Tests that freshened blocks behave correctly in Debugger.
+
+var g = newGlobal();
+var dbg = Debugger(g);
+var log = '';
+var oldEnv = null;
+dbg.onDebuggerStatement = function (frame) {
+  if (!oldEnv) {
+    oldEnv = frame.environment;
+  } else {
+    // Block has been freshened by |for (let ...)|, should be different
+    // identity.
+    log += (oldEnv === frame.environment);
+  }
+  log += frame.environment.getVariable("x");
+};
+g.eval("for (let x = 0; x < 2; x++) debugger;");
+gc();
+assertEq(log, "0false1");
--- a/js/src/jit/BaselineCompiler.cpp
+++ b/js/src/jit/BaselineCompiler.cpp
@@ -3020,24 +3020,34 @@ BaselineCompiler::emit_JSOP_POPBLOCKSCOP
 
     return callVM(PopBlockScopeInfo);
 }
 
 typedef bool (*FreshenBlockScopeFn)(JSContext*, BaselineFrame*);
 static const VMFunction FreshenBlockScopeInfo =
     FunctionInfo<FreshenBlockScopeFn>(jit::FreshenBlockScope);
 
+typedef bool (*DebugLeaveThenFreshenBlockScopeFn)(JSContext*, BaselineFrame*, jsbytecode* pc);
+static const VMFunction DebugLeaveThenFreshenBlockScopeInfo =
+    FunctionInfo<DebugLeaveThenFreshenBlockScopeFn>(jit::DebugLeaveThenFreshenBlockScope);
+
 bool
 BaselineCompiler::emit_JSOP_FRESHENBLOCKSCOPE()
 {
     prepareVMCall();
 
     masm.loadBaselineFramePtr(BaselineFrameReg, R0.scratchReg());
+
+    if (compileDebugInstrumentation_) {
+        pushArg(ImmPtr(pc));
+        pushArg(R0.scratchReg());
+        return callVM(DebugLeaveThenFreshenBlockScopeInfo);
+    }
+
     pushArg(R0.scratchReg());
-
     return callVM(FreshenBlockScopeInfo);
 }
 
 typedef bool (*DebugLeaveBlockFn)(JSContext*, BaselineFrame*, jsbytecode*);
 static const VMFunction DebugLeaveBlockInfo = FunctionInfo<DebugLeaveBlockFn>(jit::DebugLeaveBlock);
 
 bool
 BaselineCompiler::emit_JSOP_DEBUGLEAVEBLOCK()
--- a/js/src/jit/VMFunctions.cpp
+++ b/js/src/jit/VMFunctions.cpp
@@ -998,16 +998,23 @@ PopBlockScope(JSContext* cx, BaselineFra
 
 bool
 FreshenBlockScope(JSContext* cx, BaselineFrame* frame)
 {
     return frame->freshenBlock(cx);
 }
 
 bool
+DebugLeaveThenFreshenBlockScope(JSContext* cx, BaselineFrame* frame, jsbytecode* pc)
+{
+    DebugLeaveBlock(cx, frame, pc);
+    return frame->freshenBlock(cx);
+}
+
+bool
 DebugLeaveBlock(JSContext* cx, BaselineFrame* frame, jsbytecode* pc)
 {
     MOZ_ASSERT(frame->script()->baselineScript()->hasDebugInstrumentation());
     if (cx->compartment()->isDebuggee())
         DebugScopes::onPopBlock(cx, frame, pc);
     return true;
 }
 
--- a/js/src/jit/VMFunctions.h
+++ b/js/src/jit/VMFunctions.h
@@ -724,16 +724,17 @@ bool GlobalHasLiveOnDebuggerStatement(JS
 
 bool EnterWith(JSContext* cx, BaselineFrame* frame, HandleValue val,
                Handle<StaticWithObject*> templ);
 bool LeaveWith(JSContext* cx, BaselineFrame* frame);
 
 bool PushBlockScope(JSContext* cx, BaselineFrame* frame, Handle<StaticBlockObject*> block);
 bool PopBlockScope(JSContext* cx, BaselineFrame* frame);
 bool FreshenBlockScope(JSContext* cx, BaselineFrame* frame);
+bool DebugLeaveThenFreshenBlockScope(JSContext* cx, BaselineFrame* frame, jsbytecode* pc);
 bool DebugLeaveBlock(JSContext* cx, BaselineFrame* frame, jsbytecode* pc);
 
 bool InitBaselineFrameForOsr(BaselineFrame* frame, InterpreterFrame* interpFrame,
                              uint32_t numStackValues);
 
 JSObject* CreateDerivedTypedObj(JSContext* cx, HandleObject descr,
                                 HandleObject owner, int32_t offset);
 
--- a/js/src/vm/Interpreter.cpp
+++ b/js/src/vm/Interpreter.cpp
@@ -3802,16 +3802,19 @@ CASE(JSOP_DEBUGLEAVEBLOCK)
 
     if (MOZ_UNLIKELY(cx->compartment()->isDebuggee()))
         DebugScopes::onPopBlock(cx, REGS.fp(), REGS.pc);
 }
 END_CASE(JSOP_DEBUGLEAVEBLOCK)
 
 CASE(JSOP_FRESHENBLOCKSCOPE)
 {
+    if (MOZ_UNLIKELY(cx->compartment()->isDebuggee()))
+        DebugScopes::onPopBlock(cx, REGS.fp(), REGS.pc);
+
     if (!REGS.fp()->freshenBlock(cx))
         goto error;
 }
 END_CASE(JSOP_FRESHENBLOCKSCOPE)
 
 CASE(JSOP_GENERATOR)
 {
     MOZ_ASSERT(!cx->isExceptionPending());