Backed out changeset d02083014f57; build problems in nsXPConnect.cpp
authorJim Blandy <jimb@mozilla.com>
Mon, 06 Jun 2011 09:01:47 -0700
changeset 74465 903f84bae52857b06082a6001f734c0b61243b6a
parent 74464 215d305502a77fcb2bd9772d692745bea7eeb71c
child 74466 8b978fbe8b9c3013e51e4a46b8cd7389550fccc9
push id2
push userbsmedberg@mozilla.com
push dateFri, 19 Aug 2011 14:38:13 +0000
milestone6.0a1
backs outd02083014f57890a0e9977094ff51625e9ead9a6
Backed out changeset d02083014f57; build problems in nsXPConnect.cpp
js/src/jit-test/tests/debug/Debug-ctor-01.js
js/src/jit-test/tests/debug/Debug-ctor-02.js
js/src/jit-test/tests/debug/Debug-ctor-03.js
js/src/jit-test/tests/debug/Debug-ctor.js
js/src/jit-test/tests/debug/Debug-debuggees-01.js
js/src/jit-test/tests/debug/Debug-debuggees-02.js
js/src/jit-test/tests/debug/Debug-debuggees-03.js
js/src/jit-test/tests/debug/Debug-debuggees-04.js
js/src/jit-test/tests/debug/Debug-debuggees-05.js
js/src/jit-test/tests/debug/Debug-debuggees-06.js
js/src/jit-test/tests/debug/Debug-debuggees-07.js
js/src/jit-test/tests/debug/Debug-debuggees-08.js
js/src/jit-test/tests/debug/Debug-debuggees-10.js
js/src/jit-test/tests/debug/Debug-debuggees-12.js
js/src/jit-test/tests/debug/Debug-debuggees-13.js
js/src/jit-test/tests/debug/Debug-debuggees-14.js
js/src/jit-test/tests/debug/Debug-enabled-01.js
js/src/jit-test/tests/debug/Debug-getYoungestFrame-01.js
js/src/jit-test/tests/debug/Debug-getYoungestFrame-02.js
js/src/jit-test/tests/debug/Debug-multi-01.js
js/src/jit-test/tests/debug/Debug-multi-02.js
js/src/jit-test/tests/debug/Debug-multi-03.js
js/src/jit-test/tests/debug/Frame-01.js
js/src/jit-test/tests/debug/Frame-02.js
js/src/jit-test/tests/debug/Frame-03.js
js/src/jit-test/tests/debug/Frame-arguments-01.js
js/src/jit-test/tests/debug/Frame-arguments-02.js
js/src/jit-test/tests/debug/Frame-arguments-03.js
js/src/jit-test/tests/debug/Frame-arguments-04.js
js/src/jit-test/tests/debug/Frame-arguments-05.js
js/src/jit-test/tests/debug/Frame-arguments-06.js
js/src/jit-test/tests/debug/Frame-eval-01.js
js/src/jit-test/tests/debug/Frame-eval-02.js
js/src/jit-test/tests/debug/Frame-eval-03.js
js/src/jit-test/tests/debug/Frame-eval-04.js
js/src/jit-test/tests/debug/Frame-eval-05.js
js/src/jit-test/tests/debug/Frame-eval-06.js
js/src/jit-test/tests/debug/Frame-eval-07.js
js/src/jit-test/tests/debug/Frame-eval-08.js
js/src/jit-test/tests/debug/Frame-eval-09.js
js/src/jit-test/tests/debug/Frame-eval-10.js
js/src/jit-test/tests/debug/Frame-evalWithBindings-01.js
js/src/jit-test/tests/debug/Frame-evalWithBindings-02.js
js/src/jit-test/tests/debug/Frame-evalWithBindings-03.js
js/src/jit-test/tests/debug/Frame-evalWithBindings-04.js
js/src/jit-test/tests/debug/Frame-evalWithBindings-05.js
js/src/jit-test/tests/debug/Frame-evalWithBindings-06.js
js/src/jit-test/tests/debug/Frame-evalWithBindings-07.js
js/src/jit-test/tests/debug/Frame-evalWithBindings-08.js
js/src/jit-test/tests/debug/Frame-evalWithBindings-09.js
js/src/jit-test/tests/debug/Frame-evalWithBindings-10.js
js/src/jit-test/tests/debug/Frame-identity-04.js
js/src/jit-test/tests/debug/Frame-live-03.js
js/src/jit-test/tests/debug/Frame-live-04.js
js/src/jit-test/tests/debug/Frame-older-01.js
js/src/jit-test/tests/debug/Frame-this-01.js
js/src/jit-test/tests/debug/Frame-this-02.js
js/src/jit-test/tests/debug/Frame-this-03.js
js/src/jit-test/tests/debug/Frame-this-04.js
js/src/jit-test/tests/debug/Object-01.js
js/src/jit-test/tests/debug/Object-apply-01.js
js/src/jit-test/tests/debug/Object-apply-02.js
js/src/jit-test/tests/debug/Object-apply-03.js
js/src/jit-test/tests/debug/Object-apply-04.js
js/src/jit-test/tests/debug/Object-callable.js
js/src/jit-test/tests/debug/Object-class.js
js/src/jit-test/tests/debug/Object-identity-01.js
js/src/jit-test/tests/debug/Object-identity-02.js
js/src/jit-test/tests/debug/Object-identity-03.js
js/src/jit-test/tests/debug/Object-name-01.js
js/src/jit-test/tests/debug/Object-name-02.js
js/src/jit-test/tests/debug/Object-parameterNames.js
js/src/jit-test/tests/debug/Object-proto.js
js/src/jit-test/tests/debug/dispatch-01.js
js/src/jit-test/tests/debug/dispatch-02.js
js/src/jit-test/tests/debug/gc-01.js
js/src/jit-test/tests/debug/gc-02.js
js/src/jit-test/tests/debug/gc-03.js
js/src/jit-test/tests/debug/gc-04.js
js/src/jit-test/tests/debug/gc-05.js
js/src/jit-test/tests/debug/gc-06.js
js/src/jit-test/tests/debug/gc-07.js
js/src/jit-test/tests/debug/gc-08.js
js/src/jit-test/tests/debug/hooks-debuggerHandler-01.js
js/src/jit-test/tests/debug/hooks-debuggerHandler-02.js
js/src/jit-test/tests/debug/hooks-debuggerHandler-03.js
js/src/jit-test/tests/debug/hooks-deleted.js
js/src/jit-test/tests/debug/hooks-throw-01.js
js/src/jit-test/tests/debug/hooks-throw-04.js
js/src/jit-test/tests/debug/resumption-01.js
js/src/jit-test/tests/debug/resumption-02.js
js/src/jit-test/tests/debug/surfaces-01.js
js/src/jit-test/tests/debug/surfaces-02.js
js/src/jit-test/tests/debug/surfaces-03.js
js/src/jit-test/tests/debug/uncaughtExceptionHook-01.js
js/src/jit-test/tests/debug/uncaughtExceptionHook-02.js
js/src/jit-test/tests/debug/uncaughtExceptionHook-resumption-01.js
js/src/jit-test/tests/debug/uncaughtExceptionHook-resumption-02.js
js/src/jit-test/tests/debug/uncaughtExceptionHook-resumption-03.js
js/src/jsanalyze.cpp
js/src/jsapi-tests/testDebugger.cpp
js/src/jsapi.cpp
js/src/jscntxt.h
js/src/jscompartment.cpp
js/src/jscompartment.h
js/src/jsdbg.cpp
js/src/jsdbg.h
js/src/jsdbgapi.cpp
js/src/jsgc.cpp
js/src/jsinterpinlines.h
js/src/methodjit/Compiler.cpp
js/src/methodjit/FrameState.cpp
js/src/methodjit/Retcon.cpp
js/src/vm/GlobalObject.cpp
deleted file mode 100644
--- a/js/src/jit-test/tests/debug/Debug-ctor-01.js
+++ /dev/null
@@ -1,21 +0,0 @@
-load(libdir + 'asserts.js');
-
-// Debug rejects arguments that aren't cross-compartment wrappers.
-assertThrowsInstanceOf(function () { Debug(null); }, TypeError);
-assertThrowsInstanceOf(function () { Debug(true); }, TypeError);
-assertThrowsInstanceOf(function () { Debug(42); }, TypeError);
-assertThrowsInstanceOf(function () { Debug("bad"); }, TypeError);
-assertThrowsInstanceOf(function () { Debug(function () {}); }, TypeError);
-assertThrowsInstanceOf(function () { Debug(this); }, TypeError);
-assertThrowsInstanceOf(function () { new Debug(null); }, TypeError);
-assertThrowsInstanceOf(function () { new Debug(true); }, TypeError);
-assertThrowsInstanceOf(function () { new Debug(42); }, TypeError);
-assertThrowsInstanceOf(function () { new Debug("bad"); }, TypeError);
-assertThrowsInstanceOf(function () { new Debug(function () {}); }, TypeError);
-assertThrowsInstanceOf(function () { new Debug(this); }, TypeError);
-
-// From the main compartment, creating a Debug on a sandbox compartment.
-var g = newGlobal('new-compartment');
-var dbg = new Debug(g);
-assertEq(dbg instanceof Debug, true);
-assertEq(Object.getPrototypeOf(dbg), Debug.prototype);
deleted file mode 100644
--- a/js/src/jit-test/tests/debug/Debug-ctor-02.js
+++ /dev/null
@@ -1,17 +0,0 @@
-// |jit-test| debug
-// Test creating a Debug in a sandbox, debugging the initial global.
-//
-// This requires debug mode to already be on in the initial global, since it's
-// always on the stack in the shell. Hence the |jit-test| tag.
-
-load(libdir + 'asserts.js');
-
-var g = newGlobal('new-compartment');
-g.debuggeeGlobal = this;
-g.eval("var dbg = new Debug(debuggeeGlobal);");
-assertEq(g.eval("dbg instanceof Debug"), true);
-
-// The Debug constructor from this compartment will not accept as its argument
-// an Object from this compartment. Shenanigans won't fool the membrane.
-g.parent = this;
-assertThrowsInstanceOf(function () { g.eval("parent.Debug(parent.Object())"); }, TypeError);
deleted file mode 100644
--- a/js/src/jit-test/tests/debug/Debug-ctor-03.js
+++ /dev/null
@@ -1,6 +0,0 @@
-// If the debuggee cannot be put into debug mode, throw.
-var g = newGlobal('new-compartment');
-g.libdir = libdir;
-g.eval("load(libdir + 'asserts.js');");
-g.parent = this;
-g.eval("assertThrowsInstanceOf(function () { new Debug(parent); }, Error);");
new file mode 100644
--- /dev/null
+++ b/js/src/jit-test/tests/debug/Debug-ctor.js
@@ -0,0 +1,34 @@
+// |jit-test| debug
+
+load(libdir + 'asserts.js');
+
+// Debug rejects arguments that aren't cross-compartment wrappers.
+assertThrowsInstanceOf(function () { Debug(null); }, TypeError);
+assertThrowsInstanceOf(function () { Debug(true); }, TypeError);
+assertThrowsInstanceOf(function () { Debug(42); }, TypeError);
+assertThrowsInstanceOf(function () { Debug("bad"); }, TypeError);
+assertThrowsInstanceOf(function () { Debug(function () {}); }, TypeError);
+assertThrowsInstanceOf(function () { Debug(this); }, TypeError);
+assertThrowsInstanceOf(function () { new Debug(null); }, TypeError);
+assertThrowsInstanceOf(function () { new Debug(true); }, TypeError);
+assertThrowsInstanceOf(function () { new Debug(42); }, TypeError);
+assertThrowsInstanceOf(function () { new Debug("bad"); }, TypeError);
+assertThrowsInstanceOf(function () { new Debug(function () {}); }, TypeError);
+assertThrowsInstanceOf(function () { new Debug(this); }, TypeError);
+
+// From the main compartment, creating a Debug on a sandbox compartment.
+var g = newGlobal('new-compartment');
+var dbg = new Debug(g);
+assertEq(dbg instanceof Debug, true);
+assertEq(Object.getPrototypeOf(dbg), Debug.prototype);
+
+// The reverse.
+var g2 = newGlobal('new-compartment');
+g2.debuggeeGlobal = this;
+g2.eval("var dbg = new Debug(debuggeeGlobal);");
+assertEq(g2.eval("dbg instanceof Debug"), true);
+
+// The Debug constructor from this compartment will not accept as its argument
+// an Object from this compartment. Shenanigans won't fool the membrane.
+g2.outer = this;
+assertThrowsInstanceOf(function () { g2.eval("outer.Debug(outer.Object())"); }, TypeError);
--- a/js/src/jit-test/tests/debug/Debug-debuggees-01.js
+++ b/js/src/jit-test/tests/debug/Debug-debuggees-01.js
@@ -1,5 +1,6 @@
+// |jit-test| debug
 // A Debug object created with no argument initially has no debuggees.
 var dbg = new Debug;
 var debuggees = dbg.getDebuggees();
 assertEq(Array.isArray(debuggees), true);
 assertEq(debuggees.length, 0);
--- a/js/src/jit-test/tests/debug/Debug-debuggees-02.js
+++ b/js/src/jit-test/tests/debug/Debug-debuggees-02.js
@@ -1,9 +1,10 @@
-// The array returned by getDebuggees is just a snapshot, not live.
+// |jit-test| debug
+// The array returned by getDebuggees is just a snapshot, not live
 var dbg = new Debug;
 var a1 = dbg.getDebuggees();
 var g = newGlobal('new-compartment');
 var gw = dbg.addDebuggee(g);
 assertEq(gw instanceof Debug.Object, true);
 var a2 = dbg.getDebuggees();
 assertEq(a2.length, 1);
 assertEq(a2[0], gw);
--- a/js/src/jit-test/tests/debug/Debug-debuggees-03.js
+++ b/js/src/jit-test/tests/debug/Debug-debuggees-03.js
@@ -1,8 +1,9 @@
+// |jit-test| debug
 // Debug hooks fire based on debuggees.
 
 var g1 = newGlobal('new-compartment');
 g1.eval("var g2 = newGlobal('same-compartment')");
 var g2 = g1.g2;
 g1.eval("function f() { debugger; g2.g(); }");
 g2.eval("function g() { debugger; }");
 
--- a/js/src/jit-test/tests/debug/Debug-debuggees-04.js
+++ b/js/src/jit-test/tests/debug/Debug-debuggees-04.js
@@ -1,8 +1,9 @@
+// |jit-test| debug
 // hasDebuggee tests.
 
 var g1 = newGlobal('new-compartment'), g1w;
 g1.eval("var g2 = newGlobal('same-compartment')");
 var g2 = g1.g2;
 var g1w, g2w;
 
 var dbg = new Debug;
--- a/js/src/jit-test/tests/debug/Debug-debuggees-05.js
+++ b/js/src/jit-test/tests/debug/Debug-debuggees-05.js
@@ -1,8 +1,9 @@
+// |jit-test| debug
 // addDebuggee returns different Debug.Object wrappers for different Debug objects.
 
 var g = newGlobal('new-compartment');
 var dbg1 = new Debug;
 var gw1 = dbg1.addDebuggee(g);
 var dbg2 = new Debug;
 var gw2 = dbg2.addDebuggee(g);
 assertEq(gw1 !== gw2, true);
--- a/js/src/jit-test/tests/debug/Debug-debuggees-06.js
+++ b/js/src/jit-test/tests/debug/Debug-debuggees-06.js
@@ -1,8 +1,9 @@
+// |jit-test| debug
 // {has,add,remove}Debuggee throw a TypeError if the argument is invalid.
 
 load(libdir + "asserts.js");
 
 var dbg = new Debug;
 
 function check(val) {
     assertThrowsInstanceOf(function () { dbg.hasDebuggee(val); }, TypeError);
--- a/js/src/jit-test/tests/debug/Debug-debuggees-07.js
+++ b/js/src/jit-test/tests/debug/Debug-debuggees-07.js
@@ -1,8 +1,9 @@
+// |jit-test| debug
 // Handle proto-less objects passed to addDebuggee.
 
 var g = newGlobal('new-compartment');
 var obj = g.eval("Object.create(null)");
 var dbg = new Debug;
 
 // hasDebuggee and removeDebuggee must tolerate proto-less objects.
 assertEq(dbg.hasDebuggee(obj), false);
--- a/js/src/jit-test/tests/debug/Debug-debuggees-08.js
+++ b/js/src/jit-test/tests/debug/Debug-debuggees-08.js
@@ -1,8 +1,9 @@
+// |jit-test| debug
 // addDebuggee(obj), where obj is not global, adds obj's global.
 // Adding a debuggee more than once is redundant.
 
 var dbg = new Debug;
 var g = newGlobal('new-compartment');
 var w = dbg.addDebuggee(g);
 assertEq(w instanceof Debug.Object, true);
 
--- a/js/src/jit-test/tests/debug/Debug-debuggees-10.js
+++ b/js/src/jit-test/tests/debug/Debug-debuggees-10.js
@@ -1,9 +1,11 @@
+// |jit-test| debug
 // Allow diamonds in the graph of the compartment "debugs" relation.
+
 var program = newGlobal('new-compartment');
 var d1 = newGlobal('new-compartment');
 d1.top = this;
 var d2 = newGlobal('new-compartment');
 d2.top = this;
 var dbg = new Debug(d1, d2);
 d1.eval("var dbg = new Debug(top.program)");
 d2.eval("var dbg = new Debug(top.program)");
--- a/js/src/jit-test/tests/debug/Debug-debuggees-12.js
+++ b/js/src/jit-test/tests/debug/Debug-debuggees-12.js
@@ -1,9 +1,11 @@
+// |jit-test| debug
 // Events in a non-debuggee are ignored, even if a debuggee is in the same compartment.
+
 var g1 = newGlobal('new-compartment');
 var g2 = g1.eval("newGlobal('same-compartment')");
 var dbg = new Debug(g1);
 var hits = 0;
 dbg.hooks = {debuggerHandler: function () { hits++; }};
 g1.eval("debugger;");
 assertEq(hits, 1);
 g2.eval("debugger;");
--- a/js/src/jit-test/tests/debug/Debug-debuggees-13.js
+++ b/js/src/jit-test/tests/debug/Debug-debuggees-13.js
@@ -1,9 +1,11 @@
+// |jit-test| debug
 // Removing a debuggee does not detach the debugger from a compartment if another debuggee is in it.
+
 var g1 = newGlobal('new-compartment');
 var g2 = g1.eval("newGlobal('same-compartment')");
 var dbg = new Debug(g1, g2);
 var hits = 0;
 dbg.hooks = {debuggerHandler: function (frame) { hits++; }};
 dbg.removeDebuggee(g1);
 g2.eval("debugger;");
 assertEq(hits, 1);
--- a/js/src/jit-test/tests/debug/Debug-debuggees-14.js
+++ b/js/src/jit-test/tests/debug/Debug-debuggees-14.js
@@ -1,7 +1,11 @@
-// Adding a debuggee in a compartment that is already in debug mode works
-// even if a script from that compartment is on the stack.
-var g = newGlobal('new-compartment');
-var dbg1 = Debug(g);
-var dbg2 = Debug();
-g.parent = this;
-g.eval("parent.dbg2.addDebuggee(this);");
+// Reject non-debug-mode debuggees without asserting.
+
+load(libdir + "asserts.js");
+
+function f() {
+    var v = new Debug;
+    var g = newGlobal('new-compartment');
+    v.addDebuggee(g); // don't assert
+}
+
+assertThrowsInstanceOf(f, Error);
--- a/js/src/jit-test/tests/debug/Debug-enabled-01.js
+++ b/js/src/jit-test/tests/debug/Debug-enabled-01.js
@@ -1,8 +1,10 @@
+// |jit-test| debug
+
 var desc = Object.getOwnPropertyDescriptor(Debug.prototype, "enabled");
 assertEq(typeof desc.get, 'function');
 assertEq(typeof desc.set, 'function');
 
 var g = newGlobal('new-compartment');
 var hits;
 var dbg = new Debug(g);
 assertEq(dbg.enabled, true);
--- a/js/src/jit-test/tests/debug/Debug-getYoungestFrame-01.js
+++ b/js/src/jit-test/tests/debug/Debug-getYoungestFrame-01.js
@@ -1,8 +1,9 @@
+// |jit-test| debug
 // getYoungestFrame basics.
 
 load(libdir + "asserts.js");
 
 var g = newGlobal('new-compartment');
 var dbg = new Debug(g);
 assertEq(dbg.getYoungestFrame(), null);
 
--- a/js/src/jit-test/tests/debug/Debug-getYoungestFrame-02.js
+++ b/js/src/jit-test/tests/debug/Debug-getYoungestFrame-02.js
@@ -1,8 +1,9 @@
+// |jit-test| debug
 // Hooks and Debug.prototype.getYoungestFrame produce the same Frame object.
 
 var g = newGlobal('new-compartment');
 var dbg = Debug(g);
 var hits = 0;
 var savedFrame, savedCallee;
 dbg.hooks = {
     debuggerHandler: function (frame) {
--- a/js/src/jit-test/tests/debug/Debug-multi-01.js
+++ b/js/src/jit-test/tests/debug/Debug-multi-01.js
@@ -1,8 +1,9 @@
+// |jit-test| debug
 // When there are multiple debuggers, their hooks are called in order.
 
 var g = newGlobal('new-compartment');
 var log;
 var arr = [];
 
 function addDebug(msg) {
     var dbg = new Debug(g);
--- a/js/src/jit-test/tests/debug/Debug-multi-02.js
+++ b/js/src/jit-test/tests/debug/Debug-multi-02.js
@@ -1,8 +1,9 @@
+// |jit-test| debug
 // Test adding hooks during dispatch. The behavior is deterministic and "nice",
 // but mainly what we are checking here is that we do not crash due to
 // modifying a data structure while we're iterating over it.
 
 var g = newGlobal('new-compartment');
 var n = 0;
 var hits;
 
--- a/js/src/jit-test/tests/debug/Debug-multi-03.js
+++ b/js/src/jit-test/tests/debug/Debug-multi-03.js
@@ -1,8 +1,9 @@
+// |jit-test| debug
 // Q: But who shall debug the debuggers?  A: jimb
 
 var log = '';
 
 function addDebug(g, id) {
     var debuggerGlobal = newGlobal('new-compartment');
     debuggerGlobal.debuggee = g;
     debuggerGlobal.id = id;
--- a/js/src/jit-test/tests/debug/Frame-01.js
+++ b/js/src/jit-test/tests/debug/Frame-01.js
@@ -1,33 +1,70 @@
+// |jit-test| debug
 // Test .type and .generator fields of topmost stack frame passed to debuggerHandler.
 
 var g = newGlobal('new-compartment');
-var dbg = Debug(g);
-var expected, hits;
-dbg.hooks = {
-    debuggerHandler: function (f) {
-        assertEq(Object.getPrototypeOf(f), Debug.Frame.prototype);
-        assertEq(f.type, expected.type);
-        assertEq(f.generator, expected.generator);
-        assertEq(f.constructing, expected.constructing);
-        hits++;
-    }
-};
+g.debuggeeGlobal = this;
+g.eval("var hits;");
+g.eval("(" + function () {
+        var dbg = Debug(debuggeeGlobal);
+        dbg.hooks = {
+            debuggerHandler: function (f) {
+                // print(uneval(expected));
+                assertEq(Object.getPrototypeOf(f), Debug.Frame.prototype);
+                assertEq(f.type, expected.type);
+                assertEq(f.generator, expected.generator);
+                assertEq(f.constructing, expected.constructing);
+                hits++;
+            }
+        };
+    } + ")()");
 
-function test(code, expectobj, expectedHits) {
-    expected = expectobj;
-    hits = 0;
-    g.evaluate(code);
-    assertEq(hits, arguments.length < 3 ? 1 : expectedHits);
+g.expected = { type:"global", generator:false, constructing:false };
+g.hits = 0;
+debugger;
+assertEq(g.hits, 1);
+
+g.expected = { type:"call", generator:false, constructing:false };
+g.hits = 0;
+(function () { debugger; })();
+assertEq(g.hits, 1);
+
+g.expected = { type:"call", generator:false, constructing:true };
+g.hits = 0;
+new function() { debugger; };
+assertEq(g.hits, 1);
+
+g.expected = { type:"call", generator:false, constructing:false };
+g.hits = 0;
+new function () {
+    (function() { debugger; })();
+    assertEq(g.hits, 1);
 }
 
-test("debugger;", {type: "global", generator: false, constructing: false});
-test("(function () { debugger; })();", {type: "call", generator: false, constructing: false});
-test("new function() { debugger; };", {type: "call", generator: false, constructing: true});
-test("new function () { (function() { debugger; })(); }", {type: "call", generator: false, constructing: false});
-test("eval('debugger;');", {type: "eval", generator: false, constructing: false});
-test("this.eval('debugger;');  // indirect eval", {type: "eval", generator: false, constructing: false});
-test("(function () { eval('debugger;'); })();", {type: "eval", generator: false, constructing: false});
-test("new function () { eval('debugger'); }", {type: "eval", generator: false, constructing: false});
-test("function gen() { debugger; yield 1; debugger; }\n" +
-     "for (var x in gen()) {}\n",
-     {type: "call", generator: true, constructing: false}, 2);
+g.expected = { type:"eval", generator:false, constructing:false };
+g.hits = 0;
+eval("debugger;");
+assertEq(g.hits, 1);
+
+g.expected = { type:"eval", generator:false, constructing:false };
+g.hits = 0;
+this.eval("debugger;");  // indirect eval
+assertEq(g.hits, 1);
+
+g.expected = { type:"eval", generator:false, constructing:false };
+g.hits = 0;
+(function () { eval("debugger;"); })();
+assertEq(g.hits, 1);
+
+g.expected = { type:"eval", generator:false, constructing:false };
+g.hits = 0;
+new function () {
+    eval("debugger");
+    assertEq(g.hits, 1);
+}
+
+g.expected = { type:"call", generator:true, constructing:false };
+g.hits = 0;
+function gen() { debugger; yield 1; debugger; }
+for (var x in gen()) {
+}
+assertEq(g.hits, 2);
--- a/js/src/jit-test/tests/debug/Frame-02.js
+++ b/js/src/jit-test/tests/debug/Frame-02.js
@@ -1,26 +1,35 @@
+// |jit-test| debug
 // When the debugger is triggered twice from the same stack frame, the same
 // Debug.Frame object must be passed to the hook both times.
 
 var g = newGlobal('new-compartment');
-var hits, frame;
-var dbg = Debug(g);
-dbg.hooks = {
-    debuggerHandler: function (f) {
-        if (hits++ == 0)
-            frame = f;
-        else
-            assertEq(f, frame);
-    }
-};
+g.debuggeeGlobal = this;
+g.eval("var hits, frame;");
+g.eval("(" + function () {
+        var dbg = Debug(debuggeeGlobal);
+        dbg.hooks = {
+            debuggerHandler: function (f) {
+                if (hits++ == 0)
+                    frame = f;
+                else
+                    assertEq(f, frame);
+            }
+        };
+    } + ")()");
 
-hits = 0;
-g.evaluate("debugger; debugger;");
-assertEq(hits, 2);
+g.hits = 0;
+debugger;
+debugger;
+assertEq(g.hits, 2);
 
-hits = 0;
-g.evaluate("function f() { debugger; debugger; }  f();");
-assertEq(hits, 2);
+g.hits = 0;
+function f() {
+    debugger;
+    debugger;
+}
+f();
+assertEq(g.hits, 2);
 
-hits = 0;
-g.evaluate("eval('debugger; debugger;');");
-assertEq(hits, 2);
+g.hits = 0;
+eval("debugger; debugger;");
+assertEq(g.hits, 2);
--- a/js/src/jit-test/tests/debug/Frame-03.js
+++ b/js/src/jit-test/tests/debug/Frame-03.js
@@ -1,21 +1,26 @@
+// |jit-test| debug
 // When the debugger is triggered from different stack frames that happen to
 // occupy the same memory, it must deliver different Debug.Frame objects.
 
 var g = newGlobal('new-compartment');
-var dbg = Debug(g);
-var hits;
-var a = [];
-dbg.hooks = {
-    debuggerHandler: function (frame) {
-        for (var i = 0; i < a.length; i++) 
-            assertEq(a[i] === frame, false);
-        a.push(frame);
-        hits++;
-    }
-};
+g.debuggeeGlobal = this;
+g.eval("var hits;");
+g.eval("(" + function () {
+        var a = [];
+        var dbg = Debug(debuggeeGlobal);
+        dbg.hooks = {
+            debuggerHandler: function (frame) {
+                for (var i = 0; i < a.length; i++) 
+                    assertEq(a[i] === frame, false);
+                a.push(frame);
+                hits++;
+            }
+        };
+    } + ")()");
 
-g.eval("function f() { debugger; }");
-g.eval("function h() { debugger; f(); }");
-hits = 0;
-g.eval("for (var i = 0; i < 4; i++) h();");
-assertEq(hits, 8);
+function f() { debugger; }
+function h() { debugger; f(); }
+g.hits = 0;
+for (var i = 0; i < 4; i++)
+    h();
+assertEq(g.hits, 8);
--- a/js/src/jit-test/tests/debug/Frame-arguments-01.js
+++ b/js/src/jit-test/tests/debug/Frame-arguments-01.js
@@ -1,8 +1,9 @@
+// |jit-test| debug
 // Frame.prototype.arguments with primitive values
 
 var g = newGlobal('new-compartment');
 g.args = null;
 var dbg = new Debug(g);
 var hits;
 var v;
 dbg.hooks = {
--- a/js/src/jit-test/tests/debug/Frame-arguments-02.js
+++ b/js/src/jit-test/tests/debug/Frame-arguments-02.js
@@ -1,8 +1,9 @@
+// |jit-test| debug
 // Object arguments.
 
 var g = newGlobal('new-compartment');
 var dbg = new Debug(g);
 var hits = 0;
 dbg.hooks = {
     debuggerHandler: function (frame) {
         var args = frame.arguments;
--- a/js/src/jit-test/tests/debug/Frame-arguments-03.js
+++ b/js/src/jit-test/tests/debug/Frame-arguments-03.js
@@ -1,8 +1,9 @@
+// |jit-test| debug
 // Destructuring arguments.
 
 var g = newGlobal('new-compartment');
 var dbg = new Debug(g);
 var hits = 0;
 dbg.hooks = {
     debuggerHandler: function (frame) {
         var args = frame.arguments;
--- a/js/src/jit-test/tests/debug/Frame-arguments-04.js
+++ b/js/src/jit-test/tests/debug/Frame-arguments-04.js
@@ -1,8 +1,9 @@
+// |jit-test| debug
 // frame.arguments works for all live frames
 
 var g = newGlobal('new-compartment');
 var dbg = new Debug(g);
 var hits = 0;
 dbg.hooks = {
     debuggerHandler: function (frame) {
         for (var i = 0; i <= 4; i++) {
--- a/js/src/jit-test/tests/debug/Frame-arguments-05.js
+++ b/js/src/jit-test/tests/debug/Frame-arguments-05.js
@@ -1,8 +1,9 @@
+// |jit-test| debug
 // frame.arguments is "live" (it reflects assignments to arguments).
 
 var g = newGlobal('new-compartment');
 var dbg = new Debug(g);
 var log = '';
 var args;
 dbg.hooks = {
     debuggerHandler: function (frame) {
--- a/js/src/jit-test/tests/debug/Frame-arguments-06.js
+++ b/js/src/jit-test/tests/debug/Frame-arguments-06.js
@@ -1,8 +1,9 @@
+// |jit-test| debug
 // Test extracting frame.arguments element getters and calling them in
 // various awkward ways.
 
 load(libdir + "asserts.js");
 
 var g = newGlobal('new-compartment');
 var dbg = Debug(g);
 var hits = 0;
--- a/js/src/jit-test/tests/debug/Frame-eval-01.js
+++ b/js/src/jit-test/tests/debug/Frame-eval-01.js
@@ -1,8 +1,9 @@
+// |jit-test| debug
 // simplest possible test of Debug.Frame.prototype.eval
 
 var g = newGlobal('new-compartment');
 var dbg = new Debug(g);
 var c;
 dbg.hooks = {debuggerHandler: function (frame) { c = frame.eval("2 + 2"); }};
 g.eval("debugger;");
 assertEq(c.return, 4);
--- a/js/src/jit-test/tests/debug/Frame-eval-02.js
+++ b/js/src/jit-test/tests/debug/Frame-eval-02.js
@@ -1,8 +1,9 @@
+// |jit-test| debug
 // frame.eval() throws if frame is not live
 
 load(libdir + "asserts.js");
 
 var g = newGlobal('new-compartment');
 var dbg = new Debug(g);
 var f;
 dbg.hooks = {debuggerHandler: function (frame) { f = frame; }};
--- a/js/src/jit-test/tests/debug/Frame-eval-03.js
+++ b/js/src/jit-test/tests/debug/Frame-eval-03.js
@@ -1,8 +1,9 @@
+// |jit-test| debug
 // Test eval-ing names in a topmost script frame
 
 load(libdir + "asserts.js");
 
 var g = newGlobal('new-compartment');
 var dbg = new Debug(g);
 var hits = 0;
 dbg.hooks = {
--- a/js/src/jit-test/tests/debug/Frame-eval-04.js
+++ b/js/src/jit-test/tests/debug/Frame-eval-04.js
@@ -1,8 +1,9 @@
+// |jit-test| debug
 // frame.eval SyntaxErrors are reflected, not thrown
 
 var g = newGlobal('new-compartment');
 var dbg = new Debug(g);
 var exc, SEp;
 dbg.hooks = {
     debuggerHandler: function (frame) {
         exc = frame.eval("#$@!").throw;
--- a/js/src/jit-test/tests/debug/Frame-eval-05.js
+++ b/js/src/jit-test/tests/debug/Frame-eval-05.js
@@ -1,8 +1,9 @@
+// |jit-test| debug
 // var declarations in strict frame.eval do not modify the frame
 
 var g = newGlobal('new-compartment');
 var dbg = new Debug(g);
 var cv;
 dbg.hooks = {
     debuggerHandler: function (frame) {
         cv = frame.eval("'use strict'; var a = 2; h();");
--- a/js/src/jit-test/tests/debug/Frame-eval-06.js
+++ b/js/src/jit-test/tests/debug/Frame-eval-06.js
@@ -1,8 +1,9 @@
+// |jit-test| debug
 // frame.eval throws if frame is a generator frame that isn't currently on the stack
 
 load(libdir + "asserts.js");
 
 var g = newGlobal('new-compartment');
 g.eval("function gen(a) { debugger; yield a; }");
 g.eval("function test() { debugger; }");
 var dbg = new Debug(g);
--- a/js/src/jit-test/tests/debug/Frame-eval-07.js
+++ b/js/src/jit-test/tests/debug/Frame-eval-07.js
@@ -1,8 +1,9 @@
+// |jit-test| debug
 // test frame.eval in non-top frames
 
 var g = newGlobal('new-compartment');
 var N = g.N = 12; // must be even
 assertEq(N % 2, 0);
 var dbg = new Debug(g);
 var hits = 0;
 dbg.hooks = {
--- a/js/src/jit-test/tests/debug/Frame-eval-08.js
+++ b/js/src/jit-test/tests/debug/Frame-eval-08.js
@@ -1,8 +1,9 @@
+// |jit-test| debug
 // The arguments can escape from a function via a debugging hook.
 
 var g = newGlobal('new-compartment');
 var dbg = new Debug(g);
 
 // capture arguments object and test function
 var args, testfn;
 dbg.hooks = {
--- a/js/src/jit-test/tests/debug/Frame-eval-09.js
+++ b/js/src/jit-test/tests/debug/Frame-eval-09.js
@@ -1,8 +1,9 @@
+// |jit-test| debug
 // assigning to local variables in frame.eval code
 
 var g = newGlobal('new-compartment');
 var dbg = new Debug(g);
 dbg.hooks = {
     debuggerHandler: function (frame) {
         frame.eval("outerarg = 1; outervar = 2; innerarg = 3; innervar = 4;");
     }
--- a/js/src/jit-test/tests/debug/Frame-eval-10.js
+++ b/js/src/jit-test/tests/debug/Frame-eval-10.js
@@ -1,8 +1,9 @@
+// |jit-test| debug
 // frame.eval returns null if the eval code fails with an uncatchable error.
 var g = newGlobal('new-compartment');
 var dbg = Debug(g);
 var hits = 0;
 dbg.hooks = {
     debuggerHandler: function (frame) {
 	if (hits++ === 0)
 	    assertEq(frame.eval("debugger;"), null);
--- a/js/src/jit-test/tests/debug/Frame-evalWithBindings-01.js
+++ b/js/src/jit-test/tests/debug/Frame-evalWithBindings-01.js
@@ -1,8 +1,9 @@
+// |jit-test| debug
 // evalWithBindings basics
 
 var g = newGlobal('new-compartment');
 var dbg = new Debug(g);
 var hits = 0;
 dbg.hooks = {
     debuggerHandler: function (frame) {
 	assertEq(frame.evalWithBindings("x", {x: 2}).return, 2);
--- a/js/src/jit-test/tests/debug/Frame-evalWithBindings-02.js
+++ b/js/src/jit-test/tests/debug/Frame-evalWithBindings-02.js
@@ -1,9 +1,11 @@
+// |jit-test| debug
 // evalWithBindings to call a method of a debuggee object
+
 var g = newGlobal('new-compartment');
 var dbg = new Debug;
 var global = dbg.addDebuggee(g);
 var hits = 0;
 dbg.hooks = {
     debuggerHandler: function (frame) {
 	var obj = frame.arguments[0];
 	var expected = frame.arguments[1];
--- a/js/src/jit-test/tests/debug/Frame-evalWithBindings-03.js
+++ b/js/src/jit-test/tests/debug/Frame-evalWithBindings-03.js
@@ -1,9 +1,11 @@
+// |jit-test| debug
 // arguments works in evalWithBindings (it does not interpose a function scope)
+
 var g = newGlobal('new-compartment');
 var dbg = new Debug;
 var global = dbg.addDebuggee(g);
 var hits = 0;
 dbg.hooks = {
     debuggerHandler: function (frame) {
 	var argc = frame.arguments.length;
 	assertEq(argc, 7);
--- a/js/src/jit-test/tests/debug/Frame-evalWithBindings-04.js
+++ b/js/src/jit-test/tests/debug/Frame-evalWithBindings-04.js
@@ -1,9 +1,11 @@
+// |jit-test| debug
 // evalWithBindings works on non-top frames.
+
 var g = newGlobal('new-compartment');
 var dbg = new Debug(g);
 var f1;
 var hits = 0;
 dbg.hooks = {
     debuggerHandler: function (frame) {
 	assertEq(frame.older.evalWithBindings("q + r", {r: 3}).return, 5);
 
--- a/js/src/jit-test/tests/debug/Frame-evalWithBindings-05.js
+++ b/js/src/jit-test/tests/debug/Frame-evalWithBindings-05.js
@@ -1,8 +1,9 @@
+// |jit-test| debug
 // evalWithBindings code can assign to the bindings.
 var g = newGlobal('new-compartment');
 var dbg = new Debug(g);
 var hits = 0;
 dbg.hooks = {
     debuggerHandler: function (frame) {
 	assertEq(frame.evalWithBindings("for (i = 0; i < 5; i++) {}  i;", {i: 10}).return, 5);
 	hits++;
--- a/js/src/jit-test/tests/debug/Frame-evalWithBindings-06.js
+++ b/js/src/jit-test/tests/debug/Frame-evalWithBindings-06.js
@@ -1,9 +1,11 @@
+// |jit-test| debug
 // In evalWithBindings code, assignment to any name not in the bindings works just as in eval.
+
 var g = newGlobal('new-compartment');
 var dbg = new Debug(g);
 dbg.hooks = {
     debuggerHandler: function (frame) {
 	assertEq(frame.evalWithBindings("y = z; x = w;", {z: 2, w: 3}).return, 3);
     }
 };
 g.eval("function f(x) { debugger; assertEq(x, 3); }");
--- a/js/src/jit-test/tests/debug/Frame-evalWithBindings-07.js
+++ b/js/src/jit-test/tests/debug/Frame-evalWithBindings-07.js
@@ -1,9 +1,11 @@
+// |jit-test| debug
 // var statements in strict evalWithBindings code behave like strict eval.
+
 var g = newGlobal('new-compartment');
 var dbg = new Debug(g);
 var hits = 0;
 dbg.hooks = {
     debuggerHandler: function (frame) {
 	assertEq(frame.evalWithBindings("var i = a*a + b*b; i === 25;", {a: 3, b: 4}).return, true);
 	hits++;
     }
--- a/js/src/jit-test/tests/debug/Frame-evalWithBindings-08.js
+++ b/js/src/jit-test/tests/debug/Frame-evalWithBindings-08.js
@@ -1,9 +1,11 @@
+// |jit-test| debug
 // evalWithBindings ignores non-enumerable and non-own properties.
+
 var g = newGlobal('new-compartment');
 var dbg = new Debug(g);
 var hits = 0;
 dbg.hooks = {
     debuggerHandler: function (frame) {
 	assertEq(frame.evalWithBindings("toString + constructor + length", []).return, 112233);
 	var obj = Object.create({constructor: "FAIL"}, {length: {value: "fail"}});
 	assertEq(frame.evalWithBindings("toString + constructor + length", obj).return, 112233);
--- a/js/src/jit-test/tests/debug/Frame-evalWithBindings-09.js
+++ b/js/src/jit-test/tests/debug/Frame-evalWithBindings-09.js
@@ -1,9 +1,11 @@
+// |jit-test| debug
 // evalWithBindings code is debuggee code, so it can trip the debugger. It nests!
+
 var g = newGlobal('new-compartment');
 var dbg = new Debug(g);
 var f1;
 var hits = 0;
 dbg.hooks = {
     debuggerHandler: function (frame) {
 	f1 = frame;
 
--- a/js/src/jit-test/tests/debug/Frame-evalWithBindings-10.js
+++ b/js/src/jit-test/tests/debug/Frame-evalWithBindings-10.js
@@ -1,9 +1,11 @@
+// |jit-test| debug
 // Direct eval code under evalWithbindings sees both the bindings and the enclosing scope.
+
 var g = newGlobal('new-compartment');
 var dbg = new Debug(g);
 var hits = 0;
 dbg.hooks = {
     debuggerHandler: function (frame) {
 	var code =
 	    "assertEq(a, 1234);\n" +
 	    "assertEq(b, null);\n" +
--- a/js/src/jit-test/tests/debug/Frame-identity-04.js
+++ b/js/src/jit-test/tests/debug/Frame-identity-04.js
@@ -1,8 +1,9 @@
+// |jit-test| debug
 // Test that on-stack Debug.Frames are not GC'd even if they are only reachable
 // from the js::Debug::frames table.
 
 var g = newGlobal('new-compartment');
 g.eval("function f(n) { if (n) f(n - 1); debugger; }");
 var dbg = new Debug(g);
 var hits = 0;
 dbg.hooks = {
--- a/js/src/jit-test/tests/debug/Frame-live-03.js
+++ b/js/src/jit-test/tests/debug/Frame-live-03.js
@@ -1,18 +1,21 @@
 // |jit-test| debug
 // frame.type throws if !frame.live
 
 load(libdir + "asserts.js");
 
 var g = newGlobal('new-compartment');
-var f;
-Debug(g).hooks = {
-    debuggerHandler: function (frame) {
-        assertEq(frame.type, "call");
-        assertEq(frame.live, true);
-        f = frame;
-    }
-};
+g.debuggeeGlobal = this;
+g.eval("var f;");
+g.eval("(" + function () {
+        Debug(debuggeeGlobal).hooks = {
+            debuggerHandler: function (frame) {
+                assertEq(frame.type, "call");
+                assertEq(frame.live, true);
+                f = frame;
+            }
+        };
+    } + ")()");
 
-g.eval("(function () { debugger; })();");
-assertEq(f.live, false);
-assertThrowsInstanceOf(function () { f.type; }, Error);
+(function () { debugger; })();
+assertEq(g.f.live, false);
+assertThrowsInstanceOf(function () { g.f.type; }, g.Error);
deleted file mode 100644
--- a/js/src/jit-test/tests/debug/Frame-live-04.js
+++ /dev/null
@@ -1,28 +0,0 @@
-// Frame.live is false for frames discarded during uncatchable error unwinding.
-var g = newGlobal('new-compartment');
-var dbg = Debug(g);
-var hits = 0;
-var snapshot;
-dbg.hooks = {
-    debuggerHandler: function (frame) {
-	var stack = [];
-	for (var f = frame; f; f = f.older) {
-	    if (f.type === "call")
-		stack.push(f);
-	}
-	snapshot = stack;
-	if (hits++ === 0)
-	    assertEq(frame.eval("x();"), null);
-	else
-	    return null;
-    }
-};
-
-g.eval("function z() { debugger; }");
-g.eval("function y() { z(); }");
-g.eval("function x() { y(); }");
-assertEq(g.eval("debugger; 'ok';"), "ok");
-assertEq(hits, 2);
-assertEq(snapshot.length, 3);
-for (var i = 0; i < snapshot.length; i++)
-    assertEq(snapshot[i].live, false);
--- a/js/src/jit-test/tests/debug/Frame-older-01.js
+++ b/js/src/jit-test/tests/debug/Frame-older-01.js
@@ -1,22 +1,25 @@
 // |jit-test| debug
 // Basic call chain.
 
 var g = newGlobal('new-compartment');
-var result = null;
-var dbg = new Debug(g);
-dbg.hooks = {
-    debuggerHandler: function (frame) {
-        var a = [];
-        assertEq(frame === frame.older, false);
-        for (; frame; frame = frame.older)
-            a.push(frame.type === 'call' ? frame.callee.name : frame.type);
-        a.reverse();
-        result = a.join(", ");
-    }
-};
+g.debuggeeGlobal = this;
+g.result = null;
+g.eval("(" + function () {
+        var dbg = new Debug(debuggeeGlobal);
+        dbg.hooks = {
+            debuggerHandler: function (frame) {
+                var a = [];
+                assertEq(frame === frame.older, false);
+                for (; frame; frame = frame.older)
+                    a.push(frame.type === 'call' ? frame.callee.name : frame.type);
+                a.reverse();
+                result = a.join(", ");
+            }
+        };
+    } + ")();");
 
-g.eval("function first() { return second(); }");
-g.eval("function second() { return eval('third()'); }");
-g.eval("function third() { debugger; }");
-g.evaluate("first();");
-assertEq(result, "global, first, second, eval, third");
+function first() { return second(); }
+function second() { return eval("third()"); }
+function third() { debugger; }
+first();
+assertEq(g.result, "global, first, second, eval, third");
--- a/js/src/jit-test/tests/debug/Frame-this-01.js
+++ b/js/src/jit-test/tests/debug/Frame-this-01.js
@@ -1,8 +1,9 @@
+// |jit-test| debug
 // Frame.prototype.this in strict-mode functions, with primitive values
 
 var g = newGlobal('new-compartment');
 var dbg = new Debug(g);
 var hits = 0;
 dbg.hooks = {
     debuggerHandler: function (frame) {
         hits++;
--- a/js/src/jit-test/tests/debug/Frame-this-02.js
+++ b/js/src/jit-test/tests/debug/Frame-this-02.js
@@ -1,8 +1,9 @@
+// |jit-test| debug
 // Frame.prototype.this in strict direct eval frames
 
 var g = newGlobal('new-compartment');
 var dbg = new Debug(g);
 var hits = 0;
 dbg.hooks = {
     debuggerHandler: function (frame) {
         hits++;
--- a/js/src/jit-test/tests/debug/Frame-this-03.js
+++ b/js/src/jit-test/tests/debug/Frame-this-03.js
@@ -1,8 +1,9 @@
+// |jit-test| debug
 // Frame.prototype.this in non-strict-mode functions, with primitive values
 
 function classOf(obj) {
     return Object.prototype.toString.call(obj).match(/^\[object (.*)\]$/)[1];
 }
 
 var g = newGlobal('new-compartment');
 var dbg = new Debug(g);
--- a/js/src/jit-test/tests/debug/Frame-this-04.js
+++ b/js/src/jit-test/tests/debug/Frame-this-04.js
@@ -1,8 +1,9 @@
+// |jit-test| debug
 // Debug.Frame.prototype.this in functions, with object values
 
 function classOf(obj) {
     return Object.prototype.toString.call(obj).match(/^\[object (.*)\]$/)[1];
 }
 
 var g = newGlobal('new-compartment');
 var dbg = new Debug(g);
--- a/js/src/jit-test/tests/debug/Object-01.js
+++ b/js/src/jit-test/tests/debug/Object-01.js
@@ -1,8 +1,9 @@
+// |jit-test| debug
 // Debug.Object basics
 
 var g = newGlobal('new-compartment');
 var dbg = Debug(g);
 var hits = 0;
 dbg.hooks = {
     debuggerHandler: function (frame) {
         assertEq(frame.arguments[0], frame.callee);
--- a/js/src/jit-test/tests/debug/Object-apply-01.js
+++ b/js/src/jit-test/tests/debug/Object-apply-01.js
@@ -1,8 +1,9 @@
+// |jit-test| debug
 // tests calling script functions via Debug.Object.prototype.apply/call
 
 load(libdir + "asserts.js");
 
 var g = newGlobal("new-compartment");
 g.eval("function f() { debugger; }");
 var dbg = new Debug(g);
 dbg.hooks = {debuggerHandler: function () {}};
--- a/js/src/jit-test/tests/debug/Object-apply-02.js
+++ b/js/src/jit-test/tests/debug/Object-apply-02.js
@@ -1,8 +1,9 @@
+// |jit-test| debug
 // tests calling native functions via Debug.Object.prototype.apply/call
 
 load(libdir + "asserts.js");
 
 var g = newGlobal("new-compartment");
 g.eval("function f() { debugger; }");
 var dbg = new Debug(g);
 dbg.hooks = {debuggerHandler: function () {}};
--- a/js/src/jit-test/tests/debug/Object-apply-03.js
+++ b/js/src/jit-test/tests/debug/Object-apply-03.js
@@ -1,8 +1,9 @@
+// |jit-test| debug
 // reentering the debugger several times via debuggerHandler and apply/call on a single stack
 
 var g = newGlobal("new-compartment");
 var dbg = Debug(g);
 
 function test(usingApply) {
     dbg.hooks = {
         debuggerHandler: function (frame) {
--- a/js/src/jit-test/tests/debug/Object-apply-04.js
+++ b/js/src/jit-test/tests/debug/Object-apply-04.js
@@ -1,8 +1,9 @@
+// |jit-test| debug
 // Debug.Object.prototype.apply/call works with function proxies
 
 var g = newGlobal('new-compartment');
 g.eval("function f() { debugger; }");
 var dbg = Debug(g);
 var hits = 0;
 dbg.hooks = {
     debuggerHandler: function (frame) {
--- a/js/src/jit-test/tests/debug/Object-callable.js
+++ b/js/src/jit-test/tests/debug/Object-callable.js
@@ -1,8 +1,9 @@
+// |jit-test| debug
 // Test Debug.Object.prototype.callable.
 
 var g = newGlobal('new-compartment');
 var dbg = new Debug(g);
 var hits = 0;
 dbg.hooks = {
     debuggerHandler: function (frame) {
         assertEq(frame.arguments[0].callable, frame.arguments[1]);
--- a/js/src/jit-test/tests/debug/Object-class.js
+++ b/js/src/jit-test/tests/debug/Object-class.js
@@ -1,17 +1,19 @@
-// Basic tests for Debug.Object.prototype.class.
+// |jit-test| debug
+
 var g = newGlobal('new-compartment');
 var dbg = new Debug(g);
 var hits = 0;
 dbg.hooks = {
     debuggerHandler: function (frame) {
         var arr = frame.arguments;
         assertEq(arr[0].class, "Object");
         assertEq(arr[1].class, "Array");
         assertEq(arr[2].class, "Function");
         assertEq(arr[3].class, "Date");
         assertEq(arr[4].class, "Proxy");
         hits++;
     }
 };
+
 g.eval("(function () { debugger; })(Object.prototype, [], eval, new Date, Proxy.create({}));");
 assertEq(hits, 1);
--- a/js/src/jit-test/tests/debug/Object-identity-01.js
+++ b/js/src/jit-test/tests/debug/Object-identity-01.js
@@ -1,9 +1,11 @@
+// |jit-test| debug
 // Two references to the same object get the same Debug.Object wrapper.
+
 var g = newGlobal('new-compartment');
 var dbg = Debug(g);
 var hits = 0;
 dbg.hooks = {
     debuggerHandler: function (frame) {
         assertEq(frame.arguments[0], frame.arguments[1]);
         hits++;
     }
--- a/js/src/jit-test/tests/debug/Object-identity-02.js
+++ b/js/src/jit-test/tests/debug/Object-identity-02.js
@@ -1,9 +1,11 @@
+// |jit-test| debug
 // Different objects get different Debug.Object wrappers.
+
 var g = newGlobal('new-compartment');
 var dbg = Debug(g);
 var hits = 0;
 dbg.hooks = {
     debuggerHandler: function (frame) {
         assertEq(frame.arguments[0] === frame.arguments[1], false);
         hits++;
     }
--- a/js/src/jit-test/tests/debug/Object-identity-03.js
+++ b/js/src/jit-test/tests/debug/Object-identity-03.js
@@ -1,8 +1,9 @@
+// |jit-test| debug
 // The same object gets the same Debug.Object wrapper at different times, if the difference would be observable.
 
 var N = HOTLOOP + 4;
 
 var g = newGlobal('new-compartment');
 var dbg = Debug(g);
 var wrappers = [];
 
--- a/js/src/jit-test/tests/debug/Object-name-01.js
+++ b/js/src/jit-test/tests/debug/Object-name-01.js
@@ -1,9 +1,11 @@
+// |jit-test| debug
 // Debug.Object.prototype.name
+
 var g = newGlobal('new-compartment');
 var dbg = Debug(g);
 var name, hits;
 dbg.hooks = {debuggerHandler: function (frame) { hits++; assertEq(frame.callee.name, name); }};
 
 hits = 0;
 name = "f";
 g.eval("(function f() { debugger; })();");
--- a/js/src/jit-test/tests/debug/Object-name-02.js
+++ b/js/src/jit-test/tests/debug/Object-name-02.js
@@ -1,9 +1,11 @@
+// |jit-test| debug
 // The .name of a non-function object is undefined.
+
 var g = newGlobal('new-compartment');
 var hits = 0;
 var dbg = new Debug(g);
 dbg.hooks = {
     debuggerHandler: function (frame) {
         assertEq(frame.arguments[0].name, undefined);
         hits++;
     }
--- a/js/src/jit-test/tests/debug/Object-parameterNames.js
+++ b/js/src/jit-test/tests/debug/Object-parameterNames.js
@@ -1,8 +1,9 @@
+// |jit-test| debug
 load(libdir + 'array-compare.js');
 
 var g = newGlobal('new-compartment');
 var dbg = new Debug(g);
 var hits = 0;
 dbg.hooks = {
     debuggerHandler: function (frame) {
         var arr = frame.arguments;
--- a/js/src/jit-test/tests/debug/Object-proto.js
+++ b/js/src/jit-test/tests/debug/Object-proto.js
@@ -1,9 +1,9 @@
-// Debug.Object.prototype.proto
+// |jit-test| debug
 var g = newGlobal('new-compartment');
 var dbgeval = function () {
         var dbg = new Debug(g);
         var hits = 0;
         g.eval("function f() { debugger; }");
         var lastval;
         dbg.hooks = {debuggerHandler: function (frame) { lastval = frame.arguments[0]; }};
         return function dbgeval(s) {
--- a/js/src/jit-test/tests/debug/dispatch-01.js
+++ b/js/src/jit-test/tests/debug/dispatch-01.js
@@ -1,8 +1,9 @@
+// |jit-test| debug
 // Test removing hooks during dispatch.
 
 var g = newGlobal('new-compartment');
 var log = '';
 
 function addDebug(n) {
     for (var i = 0; i < n; i++) {
         var dbg = new Debug(g);
--- a/js/src/jit-test/tests/debug/dispatch-02.js
+++ b/js/src/jit-test/tests/debug/dispatch-02.js
@@ -1,8 +1,9 @@
+// |jit-test| debug
 // Disabling a Debug object causes events to stop being delivered to it
 // immediately, even if we're in the middle of dispatching.
 
 var g = newGlobal('new-compartment');
 var log;
 
 var arr = [];
 for (var i = 0; i < 4; i++) {
--- a/js/src/jit-test/tests/debug/gc-01.js
+++ b/js/src/jit-test/tests/debug/gc-01.js
@@ -1,8 +1,9 @@
+// |jit-test| debug
 // Debuggers with enabled hooks should not be GC'd even if they are otherwise
 // unreachable.
 
 var g = newGlobal('new-compartment');
 var actual = 0;
 var expected = 0;
 
 function f() {
--- a/js/src/jit-test/tests/debug/gc-02.js
+++ b/js/src/jit-test/tests/debug/gc-02.js
@@ -1,8 +1,9 @@
+// |jit-test| debug
 // Dispatching an event to a debugger must keep enough of it gc-alive to avoid
 // crashing.
 
 var g = newGlobal('new-compartment');
 var hits;
 
 function addDebug() {
     // These loops are here mainly to defeat the conservative GC. :-\
--- a/js/src/jit-test/tests/debug/gc-03.js
+++ b/js/src/jit-test/tests/debug/gc-03.js
@@ -1,8 +1,9 @@
+// |jit-test| debug
 // Storing a property on a Debug.Object protects it from GC as long as the
 // referent is alive.
 
 var g = newGlobal('new-compartment');
 var N = g.N = 3;
 var dbg = Debug(g);
 
 var i = 0;
--- a/js/src/jit-test/tests/debug/gc-04.js
+++ b/js/src/jit-test/tests/debug/gc-04.js
@@ -1,8 +1,9 @@
+// |jit-test| debug
 // Storing a Debug.Object as a key in a WeakMap protects it from GC as long as
 // the referent is alive.
 
 var g = newGlobal('new-compartment');
 var N = g.N = 10;
 var dbg = Debug(g);
 var cache = new WeakMap;
 
--- a/js/src/jit-test/tests/debug/gc-05.js
+++ b/js/src/jit-test/tests/debug/gc-05.js
@@ -1,8 +1,9 @@
+// |jit-test| debug
 // If a Debug survives its debuggee, its object cache must still be swept.
 
 var g2arr = []; // non-debuggee globals
 var xarr = []; // debuggee objects
 
 var N = 4, M = 4;
 for (var i = 0; i < N; i++) {
     var g1 = newGlobal('new-compartment');
--- a/js/src/jit-test/tests/debug/gc-06.js
+++ b/js/src/jit-test/tests/debug/gc-06.js
@@ -1,6 +1,8 @@
+// |jit-test| debug
 // Debug objects do not keep debuggee globals live.
+
 var dbg = new Debug;
 for (var i = 0; i < 4; i++)
     dbg.addDebuggee(newGlobal('new-compartment'));
 gc();
 assertEq(dbg.getDebuggees().length <= 1, true);
--- a/js/src/jit-test/tests/debug/gc-07.js
+++ b/js/src/jit-test/tests/debug/gc-07.js
@@ -1,9 +1,11 @@
+// |jit-test| debug
 // Don't assert with dead Debug.Object and live cross-compartment wrapper of referent.
+
 var g = newGlobal('new-compartment');
 for (var j = 0; j < 4; j++) {
     var dbg = new Debug;
     dbg.addDebuggee(g);
     dbg.enabled = false;
     dbg = null;
     gc(); gc();
 } 
--- a/js/src/jit-test/tests/debug/gc-08.js
+++ b/js/src/jit-test/tests/debug/gc-08.js
@@ -1,8 +1,9 @@
+// |jit-test| debug
 // Debuggers with enabled throw hooks should not be GC'd even if they are
 // otherwise unreachable.
 
 load(libdir + "asserts.js");
 
 var g = newGlobal('new-compartment');
 var actual = 0;
 var expected = 0;
--- a/js/src/jit-test/tests/debug/hooks-debuggerHandler-01.js
+++ b/js/src/jit-test/tests/debug/hooks-debuggerHandler-01.js
@@ -1,9 +1,14 @@
+// |jit-test| debug
 var g = newGlobal('new-compartment');
 g.log = '';
 
 var dbg = Debug(g);
-var hooks = {debuggerHandler: function (stack) { g.log += '!'; }};
+var hooks = {
+    debuggerHandler: function (stack) {
+        g.log += '!';
+    }
+};
 dbg.hooks = hooks;
 assertEq(dbg.hooks, hooks);
 assertEq(g.eval("log += '1'; debugger; log += '2'; 3;"), 3);
 assertEq(g.log, '1!2');
--- a/js/src/jit-test/tests/debug/hooks-debuggerHandler-02.js
+++ b/js/src/jit-test/tests/debug/hooks-debuggerHandler-02.js
@@ -1,8 +1,9 @@
+// |jit-test| debug
 // Activity in the debugger compartment should not trigger debug hooks.
 
 var g = newGlobal('new-compartment');
 var hit = false;
 
 var dbg = Debug(g);
 dbg.hooks = {
     debuggerHandler: function (stack) {
--- a/js/src/jit-test/tests/debug/hooks-debuggerHandler-03.js
+++ b/js/src/jit-test/tests/debug/hooks-debuggerHandler-03.js
@@ -1,8 +1,9 @@
+// |jit-test| debug
 // A debugger statement in a debuggerHandler should not reenter.
 
 var g = newGlobal('new-compartment');
 var calls = 0;
 
 var dbg = Debug(g);
 dbg.hooks = {
     debuggerHandler: function (stack) {
--- a/js/src/jit-test/tests/debug/hooks-deleted.js
+++ b/js/src/jit-test/tests/debug/hooks-deleted.js
@@ -1,8 +1,9 @@
+// |jit-test| debug
 // If a hook is deleted after setHooks or overwritten with a primitive, it
 // simply isn't called.
 
 var g = newGlobal('new-compartment');
 var hit = false;
 var dbg = new Debug(g);
 dbg.hooks = {debuggerHandler: function (stack) { hit = 'fail';}};
 
--- a/js/src/jit-test/tests/debug/hooks-throw-01.js
+++ b/js/src/jit-test/tests/debug/hooks-throw-01.js
@@ -1,8 +1,9 @@
+// |jit-test| debug
 // Basic throw hook test.
 
 load(libdir + "asserts.js");
 
 var g = newGlobal('new-compartment');
 var dbg = Debug(g);
 var hit = false;
 dbg.hooks = {
--- a/js/src/jit-test/tests/debug/hooks-throw-04.js
+++ b/js/src/jit-test/tests/debug/hooks-throw-04.js
@@ -1,9 +1,11 @@
+// |jit-test| debug
 // hooks.throw is not called for exceptions thrown and handled in the debugger.
+
 var g = newGlobal('new-compartment');
 var dbg = Debug(g);
 g.log = '';
 dbg.hooks = {
     debuggerHandler: function (frame) {
         try {
             throw new Error("oops");
         } catch (exc) {
--- a/js/src/jit-test/tests/debug/resumption-01.js
+++ b/js/src/jit-test/tests/debug/resumption-01.js
@@ -1,13 +1,15 @@
+// |jit-test| debug
 // Simple {throw:} resumption.
 
 load(libdir + "asserts.js");
 
 var g = newGlobal('new-compartment');
+
 var dbg = Debug(g);
 dbg.hooks = {
     debuggerHandler: function (stack) {
         return {throw: "oops"};
     }
 };
 
 assertThrowsValue(function () { g.eval("debugger;"); }, "oops");
--- a/js/src/jit-test/tests/debug/resumption-02.js
+++ b/js/src/jit-test/tests/debug/resumption-02.js
@@ -1,10 +1,13 @@
+// |jit-test| debug
 // Simple {return:} resumption.
+
 var g = newGlobal('new-compartment');
+
 var dbg = Debug(g);
 dbg.hooks = {
     debuggerHandler: function (stack) {
         return {return: 1234};
     }
 };
 
 assertEq(g.eval("debugger; false;"), 1234);
--- a/js/src/jit-test/tests/debug/surfaces-01.js
+++ b/js/src/jit-test/tests/debug/surfaces-01.js
@@ -1,9 +1,9 @@
-// Check superficial characteristics of functions and properties (not functionality).
+// |jit-test| debug
 
 function checkFunction(obj, name, nargs) {
     var desc = Object.getOwnPropertyDescriptor(obj, name);
     assertEq(desc.configurable, true, name + " should be configurable");
     assertEq(desc.writable, true, name + " should be writable");
     assertEq(desc.enumerable, false, name + " should be non-enumerable");
     assertEq(desc.value, obj[name]);  // well obviously
     assertEq(typeof desc.value, 'function', name + " should be a function");
--- a/js/src/jit-test/tests/debug/surfaces-02.js
+++ b/js/src/jit-test/tests/debug/surfaces-02.js
@@ -1,8 +1,9 @@
+// |jit-test| debug
 // Debug.prototype.hooks
 
 load(libdir + 'asserts.js');
 
 var g = newGlobal('new-compartment');
 var dbg = new Debug(g);
 gc();  // don't assert marking dbg.hooks
 var h = dbg.hooks;
--- a/js/src/jit-test/tests/debug/surfaces-03.js
+++ b/js/src/jit-test/tests/debug/surfaces-03.js
@@ -1,8 +1,9 @@
+// |jit-test| debug
 // dumb basics of uncaughtExceptionHook
 
 load(libdir + 'asserts.js');
 
 var desc = Object.getOwnPropertyDescriptor(Debug.prototype, "uncaughtExceptionHook");
 assertEq(typeof desc.get, 'function');
 assertEq(typeof desc.set, 'function');
 
--- a/js/src/jit-test/tests/debug/uncaughtExceptionHook-01.js
+++ b/js/src/jit-test/tests/debug/uncaughtExceptionHook-01.js
@@ -1,8 +1,9 @@
+// |jit-test| debug
 // Uncaught exceptions in the debugger itself are delivered to the
 // uncaughtExceptionHook.
 
 var g = newGlobal('new-compartment');
 var dbg = new Debug(g);
 var log;
 dbg.hooks = {
     debuggerHandler: function () {
--- a/js/src/jit-test/tests/debug/uncaughtExceptionHook-02.js
+++ b/js/src/jit-test/tests/debug/uncaughtExceptionHook-02.js
@@ -1,8 +1,9 @@
+// |jit-test| debug
 // Returning a bad resumption value causes an exception that is reported to the
 // uncaughtExceptionHook.
 
 var g = newGlobal('new-compartment');
 var dbg = new Debug(g);
 dbg.hooks = {debuggerHandler: function () { return {oops: "bad resumption value"}; }};
 dbg.uncaughtExceptionHook = function (exc) {
     assertEq(exc instanceof TypeError, true);
--- a/js/src/jit-test/tests/debug/uncaughtExceptionHook-resumption-01.js
+++ b/js/src/jit-test/tests/debug/uncaughtExceptionHook-resumption-01.js
@@ -1,8 +1,9 @@
+// |jit-test| debug
 // uncaughtExceptionHook returns a resumption value.
 
 load(libdir + "asserts.js");
 
 var g = newGlobal('new-compartment');
 var dbg = new Debug(g);
 var rv;
 dbg.hooks = {debuggerHandler: function () { throw 15; }};
--- a/js/src/jit-test/tests/debug/uncaughtExceptionHook-resumption-02.js
+++ b/js/src/jit-test/tests/debug/uncaughtExceptionHook-resumption-02.js
@@ -1,8 +1,9 @@
+// |jit-test| debug
 // uncaughtExceptionHook resumption value other than undefined causes further
 // hooks to be skipped.
 
 var g = newGlobal('new-compartment');
 var log;
 
 function makeDebug(g, name) {
     var dbg = new Debug(g);
--- a/js/src/jit-test/tests/debug/uncaughtExceptionHook-resumption-03.js
+++ b/js/src/jit-test/tests/debug/uncaughtExceptionHook-resumption-03.js
@@ -1,8 +1,9 @@
+// |jit-test| debug
 // After hooks.throw throws, if uncaughtExceptionHook returns undefined,
 // the original exception continues to propagate.
 
 var g = newGlobal('new-compartment');
 var dbg = new Debug(g);
 var log = '';
 dbg.hooks = {throw: function () { log += "1"; throw new Error("oops"); }};
 dbg.uncaughtExceptionHook = function () { log += "2"; };
--- a/js/src/jsanalyze.cpp
+++ b/js/src/jsanalyze.cpp
@@ -310,32 +310,32 @@ Script::analyze(JSContext *cx, JSScript 
     for (unsigned i = 0; i < nfixed; i++)
         locals[i] = LOCAL_CONDITIONALLY_DEFINED;
 
     /*
      * Treat locals as having a possible use-before-def if they could be accessed
      * by debug code or by eval, or if they could be accessed by an inner script.
      */
 
-    if (script->usesEval || cx->compartment->debugMode()) {
+    if (script->usesEval || cx->compartment->debugMode) {
         for (uint32 i = 0; i < nfixed; i++)
             setLocal(i, LOCAL_USE_BEFORE_DEF);
     }
 
     for (uint32 i = 0; i < script->nClosedVars; i++) {
         uint32 slot = script->getClosedVar(i);
         if (slot < nfixed)
             setLocal(slot, LOCAL_USE_BEFORE_DEF);
     }
 
     /*
      * If the script is in debug mode, JS_SetFrameReturnValue can be called at
      * any safe point.
      */
-    if (cx->compartment->debugMode())
+    if (cx->compartment->debugMode)
         usesRval = true;
 
     /*
      * If we are in the middle of one or more jumps, the offset of the highest
      * target jumping over this bytecode.  Includes implicit jumps from
      * try/catch/finally blocks.
      */
     unsigned forwardJump = 0;
--- a/js/src/jsapi-tests/testDebugger.cpp
+++ b/js/src/jsapi-tests/testDebugger.cpp
@@ -134,13 +134,13 @@ BEGIN_TEST(testDebugger_debugObjectVsDeb
         JSAutoEnterCompartment ae;
         CHECK(ae.enter(cx, debuggee));
         CHECK(JS_SetDebugMode(cx, false));
     }
 
     EVAL("debuggee.eval('debugger; debugger; debugger;');\n"
          "hits;\n",
          &v);
-    CHECK_SAME(v, INT_TO_JSVAL(4));
+    CHECK_SAME(v, JSVAL_ONE);
     
     return true;
 }
 END_TEST(testDebugger_debugObjectVsDebugMode)
--- a/js/src/jsapi.cpp
+++ b/js/src/jsapi.cpp
@@ -702,17 +702,17 @@ JSRuntime::init(uint32 maxbytes)
     stateChange = JS_NEW_CONDVAR(gcLock);
     if (!stateChange)
         return false;
     debuggerLock = JS_NEW_LOCK();
     if (!debuggerLock)
         return false;
 #endif
 
-    debugMode = false;
+    debugMode = JS_FALSE;
     return js_InitThreads(this);
 }
 
 JSRuntime::~JSRuntime()
 {
 #ifdef DEBUG
     /* Don't hurt everyone in leaky ol' Mozilla with a fatal JS_ASSERT! */
     if (!JS_CLIST_IS_EMPTY(&contextList)) {
--- a/js/src/jscntxt.h
+++ b/js/src/jscntxt.h
@@ -490,17 +490,17 @@ struct JSRuntime {
     JSCList             contextList;
 
     /* Per runtime debug hooks -- see jsprvtd.h and jsdbgapi.h. */
     JSDebugHooks        globalDebugHooks;
 
     /*
      * Right now, we only support runtime-wide debugging.
      */
-    bool                debugMode;
+    JSBool              debugMode;
 
 #ifdef JS_TRACER
     /* True if any debug hooks not supported by the JIT are enabled. */
     bool debuggerInhibitsJIT() const {
         return (globalDebugHooks.interruptHook ||
                 globalDebugHooks.callHook);
     }
 #endif
--- a/js/src/jscompartment.cpp
+++ b/js/src/jscompartment.cpp
@@ -82,17 +82,17 @@ JSCompartment::JSCompartment(JSRuntime *
     emptyArgumentsShape(NULL),
     emptyBlockShape(NULL),
     emptyCallShape(NULL),
     emptyDeclEnvShape(NULL),
     emptyEnumeratorShape(NULL),
     emptyWithShape(NULL),
     initialRegExpShape(NULL),
     initialStringShape(NULL),
-    debugModeBits(rt->debugMode * DebugFromC),
+    debugMode(rt->debugMode),
     mathCache(NULL)
 {
     JS_INIT_CLIST(&scripts);
 
     PodArrayZero(scriptsToGC);
 }
 
 JSCompartment::~JSCompartment()
@@ -596,59 +596,8 @@ JSCompartment::incBackEdgeCount(jsbyteco
     return 1;  /* oom not reported by backEdgeTable, so ignore. */
 }
 
 bool
 JSCompartment::isAboutToBeCollected(JSGCInvocationKind gckind)
 {
     return !hold && (arenaListsAreEmpty() || gckind == GC_LAST_CONTEXT);
 }
-
-bool
-JSCompartment::haveScriptsOnStack(JSContext *cx)
-{
-    for (AllFramesIter i(cx); !i.done(); ++i) {
-        JSScript *script = i.fp()->maybeScript();
-        if (script && script->compartment == this)
-            return true;
-    }
-    return false;
-}
-
-bool
-JSCompartment::setDebugModeFromC(JSContext *cx, bool b)
-{
-    bool wasEnabled = debugMode();
-
-    // Debug mode can be enabled only when no scripts from the target
-    // compartment are on the stack. It would even be incorrect to discard just
-    // the non-live scripts' JITScripts because they might share ICs with live
-    // scripts (bug 632343).
-    if (b && !wasEnabled && haveScriptsOnStack(cx)) {
-        JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_DEBUG_NOT_IDLE);
-        return false;
-    }
-
-    debugModeBits = (debugModeBits & ~uintN(DebugFromC)) | (b * DebugFromC);
-    if (b != wasEnabled)
-        updateForDebugMode(cx);
-    return true;
-}
-
-void
-JSCompartment::updateForDebugMode(JSContext *cx)
-{
-#ifdef JS_METHODJIT
-    bool mode = debugMode();
-
-    // Discard JIT code for any scripts that change debugMode. This assumes
-    // that 'comp' is in the same thread as 'cx'.
-    for (JSScript *script = (JSScript *) scripts.next;
-         &script->links != &scripts;
-         script = (JSScript *) script->links.next)
-    {
-        if (script->debugMode != mode) {
-            mjit::ReleaseScriptCode(cx, script);
-            script->debugMode = mode;
-        }
-    }
-#endif
-}
--- a/js/src/jscompartment.h
+++ b/js/src/jscompartment.h
@@ -457,21 +457,18 @@ struct JS_FRIEND_API(JSCompartment) {
      * additions may cause these shapes to not be used by a RegExp or String
      * (even along the entire shape parent chain, should the object go into
      * dictionary mode). But because all the initial properties are
      * non-configurable, they will always map to fixed slots.
      */
     const js::Shape              *initialRegExpShape;
     const js::Shape              *initialStringShape;
 
-  private:
-    enum { DebugFromC = 1, DebugFromJS = 2 };
-    uintN                        debugModeBits;  // see debugMode() below
-  public:
-    JSCList                      scripts;        // scripts in this compartment
+    bool                         debugMode;  // true iff debug mode on
+    JSCList                      scripts;    // scripts in this compartment
 
     js::NativeIterCache          nativeIterCache;
 
     typedef js::Maybe<js::ToSourceCache> LazyToSourceCache;
     LazyToSourceCache            toSourceCache;
 
     JSCompartment(JSRuntime *rt);
     ~JSCompartment();
@@ -526,62 +523,23 @@ struct JS_FRIEND_API(JSCompartment) {
   public:
     js::MathCache *getMathCache(JSContext *cx) {
         return mathCache ? mathCache : allocMathCache(cx);
     }
 
     size_t backEdgeCount(jsbytecode *pc) const;
     size_t incBackEdgeCount(jsbytecode *pc);
 
-    /*
-     * There are dueling APIs for debug mode. It can be enabled or disabled via
-     * JS_SetDebugModeForCompartment. It is automatically enabled and disabled
-     * by Debug objects. Therefore debugModeBits has the DebugFromC bit set if
-     * the C API wants debug mode and the DebugFromJS bit set if debuggees is
-     * nonempty.
-     */
-    bool debugMode() const { return !!debugModeBits; }
-
-    /*
-     * True if any scripts from this compartment are on the JS stack in the
-     * calling thread. cx is a context in the calling thread, and it is assumed
-     * that no other thread is using this compartment.
-     */
-    bool haveScriptsOnStack(JSContext *cx);
-
-    bool setDebugModeFromC(JSContext *cx, bool b);
-
-    /* This is called only when debugMode() has just toggled. */
-    void updateForDebugMode(JSContext *cx);
-
     js::GlobalObjectSet &getDebuggees() { return debuggees; }
-
-    bool addDebuggee(JSContext *cx, js::GlobalObject *global) {
-        bool wasEnabled = debugMode();
-        if (!wasEnabled && haveScriptsOnStack(cx)) {
-            JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_DEBUG_NOT_IDLE);
-            return false;
-        }
-        if (!debuggees.put(global)) {
-            js_ReportOutOfMemory(cx);
-            return false;
-        }
-        debugModeBits |= DebugFromJS;
-        if (!wasEnabled)
-            updateForDebugMode(cx);
-        return true;
+    bool addDebuggee(js::GlobalObject *global) {
+        JS_ASSERT(debugMode);
+        return !!debuggees.put(global);
     }
-
-    void removeDebuggee(JSContext *cx, js::GlobalObject *global) {
-        JS_ASSERT(debuggees.has(global));
+    void removeDebuggee(js::GlobalObject *global) {
         debuggees.remove(global);
-        if (debuggees.empty()) {
-            debugModeBits &= ~DebugFromJS;
-            updateForDebugMode(cx);
-        }
     }
 };
 
 #define JS_SCRIPTS_TO_GC(cx)    ((cx)->compartment->scriptsToGC)
 #define JS_PROPERTY_TREE(cx)    ((cx)->compartment->propertyTree)
 
 #ifdef DEBUG
 #define JS_COMPARTMENT_METER(x) x
--- a/js/src/jsdbg.cpp
+++ b/js/src/jsdbg.cpp
@@ -155,20 +155,26 @@ Debug::Debug(JSObject *dbg, JSObject *ho
     // This always happens within a request on some cx.
     JSRuntime *rt = dbg->compartment()->rt;
     AutoLockGC lock(rt);
     JS_APPEND_LINK(&link, &rt->debuggerList);
 }
 
 Debug::~Debug()
 {
-    JS_ASSERT(debuggees.empty());
+    JS_ASSERT(object->compartment()->rt->gcRunning);
+    if (!debuggees.empty()) {
+        // This happens only during per-compartment GC. See comment in
+        // Debug::sweepAll.
+        JS_ASSERT(object->compartment()->rt->gcCurrentCompartment == object->compartment());
+        for (GlobalObjectSet::Enum e(debuggees); !e.empty(); e.popFront())
+            removeDebuggeeGlobal(e.front(), NULL, &e);
+    }
 
     // This always happens in the GC thread, so no locking is required.
-    JS_ASSERT(object->compartment()->rt->gcRunning);
     JS_REMOVE_LINK(&link);
 }
 
 bool
 Debug::init(JSContext *cx)
 {
     bool ok = frames.init() && objects.init() && debuggees.init();
     if (!ok)
@@ -605,19 +611,18 @@ Debug::trace(JSTracer *trc, JSObject *ob
             JSObject *frameobj = e.front().value;
             JS_ASSERT(frameobj->getPrivate());
             MarkObject(trc, *frameobj, "live Debug.Frame");
         }
     }
 }
 
 void
-Debug::sweepAll(JSContext *cx)
+Debug::sweepAll(JSRuntime *rt)
 {
-    JSRuntime *rt = cx->runtime;
     for (JSCList *p = &rt->debuggerList; (p = JS_NEXT_LINK(p)) != &rt->debuggerList;) {
         Debug *dbg = (Debug *) ((unsigned char *) p - offsetof(Debug, link));
 
         if (dbg->object->isMarked()) {
             // Sweep ObjectMap entries for referents being collected.
             for (ObjectMap::Enum e(dbg->objects); !e.empty(); e.popFront()) {
                 JS_ASSERT(e.front().key->isMarked() == e.front().value->isMarked());
                 if (!e.front().value->isMarked())
@@ -626,59 +631,57 @@ Debug::sweepAll(JSContext *cx)
         } else {
             // If this Debug is being GC'd, detach it from its debuggees. In the case of
             // runtime-wide GC, the debuggee might be GC'd too. Since detaching requires
             // access to both objects, this must be done before finalize time. However, in
             // a per-compartment GC, it is impossible for both objects to be GC'd (since
             // they are in different compartments), so in that case we just wait for
             // Debug::finalize.
             for (GlobalObjectSet::Enum e(dbg->debuggees); !e.empty(); e.popFront())
-                dbg->removeDebuggeeGlobal(cx, e.front(), NULL, &e);
+                dbg->removeDebuggeeGlobal(e.front(), NULL, &e);
         }
 
     }
 
     for (JSCompartment **c = rt->compartments.begin(); c != rt->compartments.end(); c++)
-        sweepCompartment(cx, *c);
+        sweepCompartment(*c);
 }
 
 void
-Debug::detachAllDebuggersFromGlobal(JSContext *cx, GlobalObject *global, GlobalObjectSet::Enum *compartmentEnum)
+Debug::detachAllDebuggersFromGlobal(GlobalObject *global, GlobalObjectSet::Enum *compartmentEnum)
 {
     const GlobalObject::DebugVector *debuggers = global->getDebuggers();
     JS_ASSERT(!debuggers->empty());
     while (!debuggers->empty())
-        debuggers->back()->removeDebuggeeGlobal(cx, global, compartmentEnum, NULL);
+        debuggers->back()->removeDebuggeeGlobal(global, compartmentEnum, NULL);
 }
 
 void
-Debug::sweepCompartment(JSContext *cx, JSCompartment *compartment)
+Debug::sweepCompartment(JSCompartment *compartment)
 {
     // For each debuggee being GC'd, detach it from all its debuggers.
     GlobalObjectSet &debuggees = compartment->getDebuggees();
     for (GlobalObjectSet::Enum e(debuggees); !e.empty(); e.popFront()) {
         GlobalObject *global = e.front();
         if (!global->isMarked())
-            detachAllDebuggersFromGlobal(cx, global, &e);
+            detachAllDebuggersFromGlobal(global, &e);
     }
 }
 
 void
+Debug::detachFromCompartment(JSCompartment *comp)
+{
+    for (GlobalObjectSet::Enum e(comp->getDebuggees()); !e.empty(); e.popFront())
+        detachAllDebuggersFromGlobal(e.front(), &e);
+}
+
+void
 Debug::finalize(JSContext *cx, JSObject *obj)
 {
     Debug *dbg = (Debug *) obj->getPrivate();
-    if (!dbg)
-        return;
-    if (!dbg->debuggees.empty()) {
-        // This happens only during per-compartment GC. See comment in
-        // Debug::sweepAll.
-        JS_ASSERT(cx->runtime->gcCurrentCompartment == dbg->object->compartment());
-        for (GlobalObjectSet::Enum e(dbg->debuggees); !e.empty(); e.popFront())
-            dbg->removeDebuggeeGlobal(cx, e.front(), NULL, &e);
-    }
     cx->delete_(dbg);
 }
 
 Class Debug::jsclass = {
     "Debug", JSCLASS_HAS_PRIVATE | JSCLASS_HAS_RESERVED_SLOTS(JSSLOT_DEBUG_COUNT),
     PropertyStub, PropertyStub, PropertyStub, StrictPropertyStub,
     EnumerateStub, ResolveStub, ConvertStub, Debug::finalize,
     NULL,                 /* reserved0   */
@@ -814,17 +817,17 @@ Debug::removeDebuggee(JSContext *cx, uin
 {
     REQUIRE_ARGC("Debug.removeDebuggee", 1);
     THISOBJ(cx, vp, Debug, "removeDebuggee", thisobj, dbg);
     JSObject *referent = dbg->unwrapDebuggeeArgument(cx, vp);
     if (!referent)
         return false;
     GlobalObject *global = referent->getGlobal();
     if (dbg->debuggees.has(global))
-        dbg->removeDebuggeeGlobal(cx, global, NULL, NULL);
+        dbg->removeDebuggeeGlobal(global, NULL, NULL);
     vp->setUndefined();
     return true;
 }
 
 JSBool
 Debug::hasDebuggee(JSContext *cx, uintN argc, Value *vp)
 {
     REQUIRE_ARGC("Debug.hasDebuggee", 1);
@@ -922,28 +925,32 @@ Debug::construct(JSContext *cx, uintN ar
 
     vp->setObject(*obj);
     return true;
 }
 
 bool
 Debug::addDebuggeeGlobal(JSContext *cx, GlobalObject *obj)
 {
-    JSCompartment *debuggeeCompartment = obj->compartment();
+    if (!obj->compartment()->debugMode) {
+        JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_NEED_DEBUG_MODE);
+        return false;
+    }
 
     // Check for cycles. If obj's compartment is reachable from this Debug
     // object's compartment by following debuggee-to-debugger links, then
     // adding obj would create a cycle. (Typically nobody is debugging the
     // debugger, in which case we zip through this code without looping.)
     Vector<JSCompartment *> visited(cx);
     if (!visited.append(object->compartment()))
         return false;
+    JSCompartment *dest = obj->compartment();
     for (size_t i = 0; i < visited.length(); i++) {
         JSCompartment *c = visited[i];
-        if (c == debuggeeCompartment) {
+        if (c == dest) {
             JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_DEBUG_LOOP);
             return false;
         }
 
         // Find all compartments containing debuggers debugging global objects
         // in c. Add those compartments to visited.
         for (GlobalObjectSet::Range r = c->getDebuggees().all(); !r.empty(); r.popFront()) {
             GlobalObject::DebugVector *v = r.front()->getDebuggers();
@@ -951,43 +958,38 @@ Debug::addDebuggeeGlobal(JSContext *cx, 
                 JSCompartment *next = (*p)->object->compartment();
                 if (visited.find(next) == visited.end() && !visited.append(next))
                     return false;
             }
         }
     }
 
     // Each debugger-debuggee relation must be stored in up to three places.
-    // JSCompartment::addDebuggee enables debug mode if needed.
     GlobalObject::DebugVector *v = obj->getOrCreateDebuggers(cx);
-    if (!v || !v->append(this)) {
-        js_ReportOutOfMemory(cx);
+    if (!v || !v->append(this))
         goto fail1;
-    }
-    if (!debuggees.put(obj)) {
-        js_ReportOutOfMemory(cx);
+    if (!debuggees.put(obj))
         goto fail2;
-    }
-    if (obj->getDebuggers()->length() == 1 && !debuggeeCompartment->addDebuggee(cx, obj))
+    if (obj->getDebuggers()->length() == 1 && !obj->compartment()->addDebuggee(obj))
         goto fail3;
     return true;
 
     // Maintain consistency on error.
 fail3:
     debuggees.remove(obj);
 fail2:
     JS_ASSERT(v->back() == this);
     v->popBack();
 fail1:
+    js_ReportOutOfMemory(cx);
     return false;
 }
 
 void
-Debug::removeDebuggeeGlobal(JSContext *cx, GlobalObject *global,
-                            GlobalObjectSet::Enum *compartmentEnum,
+Debug::removeDebuggeeGlobal(GlobalObject *global, GlobalObjectSet::Enum *compartmentEnum,
                             GlobalObjectSet::Enum *debugEnum)
 {
     // Each debuggee is in two HashSets: one for its compartment and one for
     // its debugger (this). The caller might be enumerating either set; if so,
     // use HashSet::Enum::removeFront rather than HashSet::remove below, to
     // avoid invalidating the live enumerator.
     JS_ASSERT(global->compartment()->getDebuggees().has(global));
     JS_ASSERT_IF(compartmentEnum, compartmentEnum->front() == global);
@@ -1019,17 +1021,17 @@ Debug::removeDebuggeeGlobal(JSContext *c
 
     // The relation must be removed from up to three places: *v and debuggees
     // for sure, and possibly the compartment's debuggee set.
     v->erase(p);
     if (v->empty()) {
         if (compartmentEnum)
             compartmentEnum->removeFront();
         else
-            global->compartment()->removeDebuggee(cx, global);
+            global->compartment()->removeDebuggee(global);
     }
     if (debugEnum)
         debugEnum->removeFront();
     else
         debuggees.remove(global);
 }
 
 JSPropertySpec Debug::properties[] = {
--- a/js/src/jsdbg.h
+++ b/js/src/jsdbg.h
@@ -78,18 +78,17 @@ class Debug {
     // Keys are referents, values are Debug.Object objects. The combination of
     // the a key being live and this Debug being live keeps the corresponding
     // Debug.Object alive.
     typedef HashMap<JSObject *, JSObject *, DefaultHasher<JSObject *>, SystemAllocPolicy>
         ObjectMap;
     ObjectMap objects;
 
     bool addDebuggeeGlobal(JSContext *cx, GlobalObject *obj);
-    void removeDebuggeeGlobal(JSContext *cx, GlobalObject *global,
-                              GlobalObjectSet::Enum *compartmentEnum,
+    void removeDebuggeeGlobal(GlobalObject *global, GlobalObjectSet::Enum *compartmentEnum,
                               GlobalObjectSet::Enum *debugEnum);
 
     JSTrapStatus handleUncaughtException(AutoCompartment &ac, Value *vp, bool callHook);
     JSTrapStatus parseResumptionValue(AutoCompartment &ac, bool ok, const Value &rv, Value *vp,
                                       bool callHook = true);
     JSObject *unwrapDebuggeeArgument(JSContext *cx, Value *vp);
 
     static void trace(JSTracer *trc, JSObject *obj);
@@ -130,16 +129,17 @@ class Debug {
   public:
     Debug(JSObject *dbg, JSObject *hooks);
     ~Debug();
 
     bool init(JSContext *cx);
     inline JSObject *toJSObject() const;
     static inline Debug *fromJSObject(JSObject *obj);
     static Debug *fromChildJSObject(JSObject *obj);
+    static void detachFromCompartment(JSCompartment *comp);
 
     /*********************************** Methods for interaction with the GC. */
 
     // A Debug object is live if:
     //   * the Debug JSObject is live (Debug::trace handles this case); OR
     //   * it is in the middle of dispatching an event (the event dispatching
     //     code roots it in this case); OR
     //   * it is enabled, and it is debugging at least one live compartment,
@@ -148,19 +148,19 @@ class Debug {
     //       - it has a breakpoint set on a live script
     //       - it has a watchpoint set on a live object.
     //
     // The last case is handled by the mark() method. If it finds any Debug
     // objects that are definitely live but not yet marked, it marks them and
     // returns true. If not, it returns false.
     //
     static bool mark(GCMarker *trc, JSCompartment *compartment, JSGCInvocationKind gckind);
-    static void sweepAll(JSContext *cx);
-    static void sweepCompartment(JSContext *cx, JSCompartment *compartment);
-    static void detachAllDebuggersFromGlobal(JSContext *cx, GlobalObject *global,
+    static void sweepAll(JSRuntime *rt);
+    static void sweepCompartment(JSCompartment *compartment);
+    static void detachAllDebuggersFromGlobal(GlobalObject *global,
                                              GlobalObjectSet::Enum *compartmentEnum);
 
     static inline void leaveStackFrame(JSContext *cx);
     static inline JSTrapStatus onDebuggerStatement(JSContext *cx, js::Value *vp);
     static inline JSTrapStatus onThrow(JSContext *cx, js::Value *vp);
 
     /**************************************** Functions for use by jsdbg.cpp. */
 
--- a/js/src/jsdbgapi.cpp
+++ b/js/src/jsdbgapi.cpp
@@ -96,29 +96,29 @@ typedef struct JSTrap {
 
 #define DBG_LOCK(rt)            JS_ACQUIRE_LOCK((rt)->debuggerLock)
 #define DBG_UNLOCK(rt)          JS_RELEASE_LOCK((rt)->debuggerLock)
 #define DBG_LOCK_EVAL(rt,expr)  (DBG_LOCK(rt), (expr), DBG_UNLOCK(rt))
 
 JS_PUBLIC_API(JSBool)
 JS_GetDebugMode(JSContext *cx)
 {
-    return cx->compartment->debugMode();
+    return cx->compartment->debugMode;
 }
 
 JS_PUBLIC_API(JSBool)
 JS_SetDebugMode(JSContext *cx, JSBool debug)
 {
     return JS_SetDebugModeForCompartment(cx, cx->compartment, debug);
 }
 
 JS_PUBLIC_API(void)
 JS_SetRuntimeDebugMode(JSRuntime *rt, JSBool debug)
 {
-    rt->debugMode = !!debug;
+    rt->debugMode = debug;
 }
 
 namespace js {
 
 void
 ScriptDebugPrologue(JSContext *cx, StackFrame *fp)
 {
     if (fp->isFramePushedByExecute()) {
@@ -154,30 +154,83 @@ ScriptDebugEpilogue(JSContext *cx, Stack
     return ok;
 }
 
 } /* namespace js */
 
 JS_FRIEND_API(JSBool)
 JS_SetDebugModeForCompartment(JSContext *cx, JSCompartment *comp, JSBool debug)
 {
-    return comp->setDebugModeFromC(cx, !!debug);
+    if (comp->debugMode == !!debug)
+        return JS_TRUE;
+
+    if (debug) {
+        // This should only be called when no scripts are live. It would even
+        // be incorrect to discard just the non-live scripts' JITScripts
+        // because they might share ICs with live scripts (bug 632343).
+        for (AllFramesIter i(cx); !i.done(); ++i) {
+            JSScript *script = i.fp()->maybeScript();
+            if (script && script->compartment == comp) {
+                JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_DEBUG_NOT_IDLE);
+                return false;
+            }
+        }
+    }
+
+    // All scripts compiled from this point on should be in the requested debugMode.
+    comp->debugMode = !!debug;
+
+    // Detach any debuggers attached to this compartment.
+    if (debug)
+        JS_ASSERT(comp->getDebuggees().empty());
+    else
+        Debug::detachFromCompartment(comp);
+
+    // Discard JIT code for any scripts that change debugMode. This function
+    // assumes that 'comp' is in the same thread as 'cx'.
+#ifdef JS_METHODJIT
+    JS::AutoEnterScriptCompartment ac;
+
+    for (JSScript *script = (JSScript *)comp->scripts.next;
+         &script->links != &comp->scripts;
+         script = (JSScript *)script->links.next)
+    {
+        if (!script->debugMode == !debug)
+            continue;
+
+        /*
+         * If compartment entry fails, debug mode is left partially on, leading
+         * to a small performance overhead but no loss of correctness. We set
+         * the debug flags to false so that the caller will not later attempt
+         * to use debugging features.
+         */
+        if (!ac.entered() && !ac.enter(cx, script)) {
+            comp->debugMode = JS_FALSE;
+            return JS_FALSE;
+        }
+
+        mjit::ReleaseScriptCode(cx, script);
+        script->debugMode = !!debug;
+    }
+#endif
+
+    return JS_TRUE;
 }
 
 JS_FRIEND_API(JSBool)
 js_SetSingleStepMode(JSContext *cx, JSScript *script, JSBool singleStep)
 {
     assertSameCompartment(cx, script);
 
 #ifdef JS_METHODJIT
     if (!script->singleStepMode == !singleStep)
         return JS_TRUE;
 #endif
 
-    JS_ASSERT_IF(singleStep, cx->compartment->debugMode());
+    JS_ASSERT_IF(singleStep, cx->compartment->debugMode);
 
 #ifdef JS_METHODJIT
     /* request the next recompile to inject single step interrupts */
     script->singleStepMode = !!singleStep;
 
     js::mjit::JITScript *jit = script->jitNormal ? script->jitNormal : script->jitCtor;
     if (jit && script->singleStepMode != jit->singleStepMode) {
         js::mjit::Recompiler recompiler(cx, script);
--- a/js/src/jsgc.cpp
+++ b/js/src/jsgc.cpp
@@ -2364,17 +2364,17 @@ MarkAndSweep(JSContext *cx, JSCompartmen
     WeakMap::sweep(cx);
 
     js_SweepAtomState(cx);
 
     /* Finalize watch points associated with unreachable objects. */
     js_SweepWatchPoints(cx);
 
     if (!comp)
-        Debug::sweepAll(cx);
+        Debug::sweepAll(rt);
 
     /*
      * We finalize objects before other GC things to ensure that object's finalizer
      * can access them even if they will be freed. Sweep the runtime's property trees
      * after finalizing objects, in case any had watchpoints referencing tree nodes.
      * Do this before sweeping compartments, so that we sweep all shapes in
      * unreachable compartments.
      */
--- a/js/src/jsinterpinlines.h
+++ b/js/src/jsinterpinlines.h
@@ -348,25 +348,25 @@ ScriptPrologue(JSContext *cx, StackFrame
 
     if (fp->isConstructing()) {
         JSObject *obj = js_CreateThisForFunction(cx, &fp->callee());
         if (!obj)
             return false;
         fp->functionThis().setObject(*obj);
     }
 
-    if (cx->compartment->debugMode())
+    if (cx->compartment->debugMode)
         ScriptDebugPrologue(cx, fp);
     return true;
 }
 
 inline bool
 ScriptEpilogue(JSContext *cx, StackFrame *fp, bool ok)
 {
-    if (cx->compartment->debugMode())
+    if (cx->compartment->debugMode)
         ok = ScriptDebugEpilogue(cx, fp, ok);
 
     /*
      * If inline-constructing, replace primitive rval with the new object
      * passed in via |this|, and instrument this constructor invocation.
      */
     if (fp->isConstructing() && ok) {
         if (fp->returnValue().isPrimitive())
@@ -377,26 +377,26 @@ ScriptEpilogue(JSContext *cx, StackFrame
     return ok;
 }
 
 inline bool
 ScriptPrologueOrGeneratorResume(JSContext *cx, StackFrame *fp)
 {
     if (!fp->isGeneratorFrame())
         return ScriptPrologue(cx, fp);
-    if (cx->compartment->debugMode())
+    if (cx->compartment->debugMode)
         ScriptDebugPrologue(cx, fp);
     return true;
 }
 
 inline bool
 ScriptEpilogueOrGeneratorYield(JSContext *cx, StackFrame *fp, bool ok)
 {
     if (!fp->isYielding())
         return ScriptEpilogue(cx, fp, ok);
-    if (cx->compartment->debugMode())
+    if (cx->compartment->debugMode)
         return ScriptDebugEpilogue(cx, fp, ok);
     return ok;
 }
 
 }  /* namespace js */
 
 #endif /* jsinterpinlines_h__ */
--- a/js/src/methodjit/Compiler.cpp
+++ b/js/src/methodjit/Compiler.cpp
@@ -109,17 +109,17 @@ mjit::Compiler::Compiler(JSContext *cx, 
     setElemICs(CompilerAllocPolicy(cx, *thisFromCtor())),
 #endif
     callPatches(CompilerAllocPolicy(cx, *thisFromCtor())),
     callSites(CompilerAllocPolicy(cx, *thisFromCtor())), 
     doubleList(CompilerAllocPolicy(cx, *thisFromCtor())),
     jumpTables(CompilerAllocPolicy(cx, *thisFromCtor())),
     jumpTableOffsets(CompilerAllocPolicy(cx, *thisFromCtor())),
     stubcc(cx, *thisFromCtor(), frame, script),
-    debugMode_(cx->compartment->debugMode()),
+    debugMode_(cx->compartment->debugMode),
 #if defined JS_TRACER
     addTraceHints(cx->traceJitEnabled),
 #endif
     oomInVector(false),
     applyTricks(NoApplyTricks)
 #if defined DEBUG
     ,pcProfile(NULL)
 #endif
--- a/js/src/methodjit/FrameState.cpp
+++ b/js/src/methodjit/FrameState.cpp
@@ -75,17 +75,17 @@ FrameState::init()
         return true;
     }
 
 #if defined JS_NUNBOX32
     if (!reifier.init(nentries))
         return false;
 #endif
 
-    eval = script->usesEval || cx->compartment->debugMode();
+    eval = script->usesEval || cx->compartment->debugMode;
 
     size_t totalBytes = sizeof(FrameEntry) * nentries +                     // entries[], w/ callee+this
                         sizeof(FrameEntry *) * nentries +                   // tracker.entries
                         (eval
                          ? 0
                          : sizeof(JSPackedBool) * script->nslots) +         // closedVars[]
                         (eval || usesArguments
                          ? 0
--- a/js/src/methodjit/Retcon.cpp
+++ b/js/src/methodjit/Retcon.cpp
@@ -197,17 +197,17 @@ Recompiler::saveTraps(JITScript *jit, Ve
     return true;
 }
 
 bool
 Recompiler::recompile(StackFrame *fp, Vector<PatchableAddress> &patches,
                       Vector<CallSite> &sites)
 {
     /* If we get this far, the script is live, and we better be safe to re-jit. */
-    JS_ASSERT(cx->compartment->debugMode());
+    JS_ASSERT(cx->compartment->debugMode);
     JS_ASSERT(fp);
 
     Compiler c(cx, fp);
     if (!c.loadOldTraps(sites))
         return false;
     if (c.compile() != Compile_Okay)
         return false;
 
--- a/js/src/vm/GlobalObject.cpp
+++ b/js/src/vm/GlobalObject.cpp
@@ -248,18 +248,18 @@ GlobalObject::addDebug(JSContext *cx, De
 {
     DebugVector *vec = getOrCreateDebuggers(cx);
     if (!vec)
         return false;
 #ifdef DEBUG
     for (Debug **p = vec->begin(); p != vec->end(); p++)
         JS_ASSERT(*p != dbg);
 #endif
-    if (vec->empty() && !compartment()->addDebuggee(cx, this))
+    if (vec->empty() && !compartment()->addDebuggee(this))
         return false;
     if (!vec->append(dbg)) {
-        compartment()->removeDebuggee(cx, this);
+        compartment()->removeDebuggee(this);
         return false;
     }
     return true;
 }
 
 } // namespace js