Removing the need for Debugger* and m_shouldPause op_debug check.
<https://webkit.org/b/127532>

Reviewed by Geoffrey Garen.

This patch replaces the checking of the Debugger::m_shouldPause flag
with a procedure to set a SteppingMode flag on all CodeBlocks under
the management of the debugger. This simplifies the op_debug checking
logic in all the execution engines.

* bytecode/CodeBlock.cpp:
* bytecode/CodeBlock.h:
(JSC::CodeBlock::hasDebuggerRequests):
(JSC::CodeBlock::debuggerRequestsAddress):
(JSC::CodeBlock::setSteppingMode):
(JSC::CodeBlock::clearDebuggerRequests):
- CodeBlock::m_debuggerRequests is a union of m_numBreakpoints and the
  new m_steppingMode. The debugger can add/remove breakpoints to the
  CodeBlock as well as set the stepping mode. By having
  m_debuggerRequests as a union of the 2 bit fields, the op_debug code
  can now check if any of the 2 requests made on the CodeBlock is still
  in effect just by testing a single int.

* debugger/Debugger.cpp:
(JSC::Debugger::Debugger):
(JSC::Debugger::detach):
- This was bug from before where I forgot to clear the CodeBlock
  breakpoints before detaching. We now take care of it by clearing all
  debugger requests made to the CodeBlock.

(JSC::Debugger::SetSteppingModeFunctor::SetSteppingModeFunctor):
(JSC::Debugger::SetSteppingModeFunctor::operator()):
(JSC::Debugger::setSteppingMode):
(JSC::Debugger::ClearCodeBlockDebuggerRequestsFunctor::ClearCodeBlockDebuggerRequestsFunctor):
(JSC::Debugger::ClearCodeBlockDebuggerRequestsFunctor::operator()):
(JSC::Debugger::clearBreakpoints):

(JSC::Debugger::ClearDebuggerRequestsFunctor::ClearDebuggerRequestsFunctor):
(JSC::Debugger::ClearDebuggerRequestsFunctor::operator()):
(JSC::Debugger::clearDebuggerRequests):
- We need a distinct clearDebuggerRequests() from clearBreakpoints()
  because:
  1. When we detach a globalObject, we only want to clear the debugger
     requests in CodeBlocks from that global.
  2. Clearing the debugger requests in the CodeBlocks is not the same
     as clearing the breakpoints. The breakpoints are still in effect
     for the next time a globalObject is attached, or for other
     globalObjects that are still attached.

(JSC::Debugger::setPauseOnNextStatement):
(JSC::Debugger::breakProgram):
(JSC::Debugger::stepIntoStatement):
(JSC::Debugger::updateCallFrameAndPauseIfNeeded):
(JSC::Debugger::pauseIfNeeded):
(JSC::Debugger::exception):
(JSC::Debugger::willExecuteProgram):
(JSC::Debugger::didReachBreakpoint):
* debugger/Debugger.h:
- We're always going to support the debugger. So, there's no longer
  a need to check ENABLE(JAVASCRIPT_DEBUGGER). Removed the unneeded code.

* dfg/DFGSpeculativeJIT32_64.cpp:
(JSC::DFG::SpeculativeJIT::compile):
* dfg/DFGSpeculativeJIT64.cpp:
(JSC::DFG::SpeculativeJIT::compile):
* interpreter/Interpreter.cpp:
(JSC::Interpreter::debug):
* jit/JITOpcodes.cpp:
(JSC::JIT::emit_op_debug):
* jit/JITOpcodes32_64.cpp:
(JSC::JIT::emit_op_debug):
* llint/LowLevelInterpreter.asm:
* runtime/JSGlobalObject.h:
(JSC::JSGlobalObject::setDebugger):



git-svn-id: http://svn.webkit.org/repository/webkit/trunk@162711 268f45cc-cd09-0410-ab3c-d52691b4dbfc
diff --git a/Source/JavaScriptCore/ChangeLog b/Source/JavaScriptCore/ChangeLog
index 73c6f99..916f5a5 100644
--- a/Source/JavaScriptCore/ChangeLog
+++ b/Source/JavaScriptCore/ChangeLog
@@ -1,3 +1,80 @@
+2014-01-24  Mark Lam  <mark.lam@apple.com>
+
+        Removing the need for Debugger* and m_shouldPause op_debug check.
+        <https://webkit.org/b/127532>
+
+        Reviewed by Geoffrey Garen.
+
+        This patch replaces the checking of the Debugger::m_shouldPause flag
+        with a procedure to set a SteppingMode flag on all CodeBlocks under
+        the management of the debugger. This simplifies the op_debug checking
+        logic in all the execution engines.
+
+        * bytecode/CodeBlock.cpp:
+        * bytecode/CodeBlock.h:
+        (JSC::CodeBlock::hasDebuggerRequests):
+        (JSC::CodeBlock::debuggerRequestsAddress):
+        (JSC::CodeBlock::setSteppingMode):
+        (JSC::CodeBlock::clearDebuggerRequests):
+        - CodeBlock::m_debuggerRequests is a union of m_numBreakpoints and the
+          new m_steppingMode. The debugger can add/remove breakpoints to the
+          CodeBlock as well as set the stepping mode. By having
+          m_debuggerRequests as a union of the 2 bit fields, the op_debug code
+          can now check if any of the 2 requests made on the CodeBlock is still
+          in effect just by testing a single int.
+
+        * debugger/Debugger.cpp:
+        (JSC::Debugger::Debugger):
+        (JSC::Debugger::detach):
+        - This was bug from before where I forgot to clear the CodeBlock
+          breakpoints before detaching. We now take care of it by clearing all
+          debugger requests made to the CodeBlock.
+
+        (JSC::Debugger::SetSteppingModeFunctor::SetSteppingModeFunctor):
+        (JSC::Debugger::SetSteppingModeFunctor::operator()):
+        (JSC::Debugger::setSteppingMode):
+        (JSC::Debugger::ClearCodeBlockDebuggerRequestsFunctor::ClearCodeBlockDebuggerRequestsFunctor):
+        (JSC::Debugger::ClearCodeBlockDebuggerRequestsFunctor::operator()):
+        (JSC::Debugger::clearBreakpoints):
+
+        (JSC::Debugger::ClearDebuggerRequestsFunctor::ClearDebuggerRequestsFunctor):
+        (JSC::Debugger::ClearDebuggerRequestsFunctor::operator()):
+        (JSC::Debugger::clearDebuggerRequests):
+        - We need a distinct clearDebuggerRequests() from clearBreakpoints()
+          because:
+          1. When we detach a globalObject, we only want to clear the debugger
+             requests in CodeBlocks from that global.
+          2. Clearing the debugger requests in the CodeBlocks is not the same
+             as clearing the breakpoints. The breakpoints are still in effect
+             for the next time a globalObject is attached, or for other
+             globalObjects that are still attached.
+
+        (JSC::Debugger::setPauseOnNextStatement):
+        (JSC::Debugger::breakProgram):
+        (JSC::Debugger::stepIntoStatement):
+        (JSC::Debugger::updateCallFrameAndPauseIfNeeded):
+        (JSC::Debugger::pauseIfNeeded):
+        (JSC::Debugger::exception):
+        (JSC::Debugger::willExecuteProgram):
+        (JSC::Debugger::didReachBreakpoint):
+        * debugger/Debugger.h:
+        - We're always going to support the debugger. So, there's no longer
+          a need to check ENABLE(JAVASCRIPT_DEBUGGER). Removed the unneeded code.
+
+        * dfg/DFGSpeculativeJIT32_64.cpp:
+        (JSC::DFG::SpeculativeJIT::compile):
+        * dfg/DFGSpeculativeJIT64.cpp:
+        (JSC::DFG::SpeculativeJIT::compile):
+        * interpreter/Interpreter.cpp:
+        (JSC::Interpreter::debug):
+        * jit/JITOpcodes.cpp:
+        (JSC::JIT::emit_op_debug):
+        * jit/JITOpcodes32_64.cpp:
+        (JSC::JIT::emit_op_debug):
+        * llint/LowLevelInterpreter.asm:
+        * runtime/JSGlobalObject.h:
+        (JSC::JSGlobalObject::setDebugger):
+
 2014-01-24  Michael Saboff  <msaboff@apple.com>
 
         ARM Offline assembler temporary register allocator has duplicate register when building fat binaries
diff --git a/Source/JavaScriptCore/bytecode/CodeBlock.cpp b/Source/JavaScriptCore/bytecode/CodeBlock.cpp
index 5b53e0b..3b56f14 100644
--- a/Source/JavaScriptCore/bytecode/CodeBlock.cpp
+++ b/Source/JavaScriptCore/bytecode/CodeBlock.cpp
@@ -1469,6 +1469,7 @@
     , m_shouldAlwaysBeInlined(true)
     , m_didFailFTLCompilation(false)
     , m_unlinkedCode(*other.m_vm, other.m_ownerExecutable.get(), other.m_unlinkedCode.get())
+    , m_steppingMode(SteppingModeDisabled)
     , m_numBreakpoints(0)
     , m_ownerExecutable(*other.m_vm, other.m_ownerExecutable.get(), other.m_ownerExecutable.get())
     , m_vm(other.m_vm)
@@ -1524,6 +1525,7 @@
     , m_shouldAlwaysBeInlined(true)
     , m_didFailFTLCompilation(false)
     , m_unlinkedCode(m_globalObject->vm(), ownerExecutable, unlinkedCodeBlock)
+    , m_steppingMode(SteppingModeDisabled)
     , m_numBreakpoints(0)
     , m_ownerExecutable(m_globalObject->vm(), ownerExecutable, ownerExecutable)
     , m_vm(unlinkedCodeBlock->vm())
diff --git a/Source/JavaScriptCore/bytecode/CodeBlock.h b/Source/JavaScriptCore/bytecode/CodeBlock.h
index 6164a0c..295d18f 100644
--- a/Source/JavaScriptCore/bytecode/CodeBlock.h
+++ b/Source/JavaScriptCore/bytecode/CodeBlock.h
@@ -871,17 +871,23 @@
 
     bool hasOpDebugForLineAndColumn(unsigned line, unsigned column);
 
-    int numBreakpoints() const { return m_numBreakpoints; }
-    static ptrdiff_t numBreakpointsOffset() { return OBJECT_OFFSETOF(CodeBlock, m_numBreakpoints); }
-    void* numBreakpointsAddress() { return &m_numBreakpoints; }
+    int hasDebuggerRequests() const { return !!m_debuggerRequests; }
+    void* debuggerRequestsAddress() { return &m_debuggerRequests; }
 
-    void addBreakpoint(int numBreakpoints) { m_numBreakpoints += numBreakpoints; }
-    void removeBreakpoint(int numBreakpoints)
+    void addBreakpoint(unsigned numBreakpoints) { m_numBreakpoints += numBreakpoints; }
+    void removeBreakpoint(unsigned numBreakpoints)
     {
+        ASSERT(m_numBreakpoints > numBreakpoints);
         m_numBreakpoints -= numBreakpoints;
-        ASSERT(m_numBreakpoints >= 0);
     }
-    void clearAllBreakpoints() { m_numBreakpoints = 0; }
+
+    enum SteppingMode {
+        SteppingModeDisabled,
+        SteppingModeEnabled
+    };
+    void setSteppingMode(SteppingMode mode) { m_steppingMode = mode; }
+
+    void clearDebuggerRequests() { m_debuggerRequests = 0; }
 
     // FIXME: Make these remaining members private.
 
@@ -1019,7 +1025,13 @@
 #endif
     WriteBarrier<UnlinkedCodeBlock> m_unlinkedCode;
     int m_numParameters;
-    int m_numBreakpoints;
+    union {
+        unsigned m_debuggerRequests;
+        struct {
+            unsigned m_steppingMode : 1;
+            unsigned m_numBreakpoints : 31;
+        };
+    };
     WriteBarrier<ScriptExecutable> m_ownerExecutable;
     VM* m_vm;
 
diff --git a/Source/JavaScriptCore/debugger/Debugger.cpp b/Source/JavaScriptCore/debugger/Debugger.cpp
index f0f970d..a9c6ace 100644
--- a/Source/JavaScriptCore/debugger/Debugger.cpp
+++ b/Source/JavaScriptCore/debugger/Debugger.cpp
@@ -148,13 +148,13 @@
     , m_breakpointsActivated(true)
     , m_hasHandlerForExceptionCallback(false)
     , m_isInWorkerThread(isInWorkerThread)
+    , m_steppingMode(SteppingModeDisabled)
     , m_reasonForPause(NotPaused)
     , m_pauseOnCallFrame(0)
     , m_currentCallFrame(0)
     , m_lastExecutedLine(UINT_MAX)
     , m_lastExecutedSourceID(noSourceID)
     , m_topBreakpointID(noBreakpointID)
-    , m_shouldPause(false)
 {
 }
 
@@ -189,24 +189,55 @@
 
     ASSERT(m_globalObjects.contains(globalObject));
     m_globalObjects.remove(globalObject);
+
+    clearDebuggerRequests(globalObject);
     globalObject->setDebugger(0);
     if (!m_globalObjects.size())
         m_vm = nullptr;
 }
 
-void Debugger::setShouldPause(bool value)
+class Debugger::SetSteppingModeFunctor {
+public:
+    SetSteppingModeFunctor(Debugger* debugger, SteppingMode mode)
+        : m_debugger(debugger)
+        , m_mode(mode)
+    {
+    }
+
+    bool operator()(CodeBlock* codeBlock)
+    {
+        if (m_debugger == codeBlock->globalObject()->debugger()) {
+            if (m_mode == SteppingModeEnabled)
+                codeBlock->setSteppingMode(CodeBlock::SteppingModeEnabled);
+            else
+                codeBlock->setSteppingMode(CodeBlock::SteppingModeDisabled);
+        }
+        return false;
+    }
+
+private:
+    Debugger* m_debugger;
+    SteppingMode m_mode;
+};
+
+void Debugger::setSteppingMode(SteppingMode mode)
 {
-    m_shouldPause = value;
+    if (mode == m_steppingMode)
+        return;
+    m_steppingMode = mode;
+
+    if (!m_vm)
+        return;
+    HeapIterationScope iterationScope(m_vm->heap);
+    SetSteppingModeFunctor functor(this, mode);
+    m_vm->heap.forEachCodeBlock(functor);
 }
 
 void Debugger::registerCodeBlock(CodeBlock* codeBlock)
 {
     applyBreakpoints(codeBlock);
-}
-
-void Debugger::unregisterCodeBlock(CodeBlock* codeBlock)
-{
-    codeBlock->clearAllBreakpoints();
+    if (isStepping())
+        codeBlock->setSteppingMode(CodeBlock::SteppingModeEnabled);
 }
 
 void Debugger::toggleBreakpoint(CodeBlock* codeBlock, Breakpoint& breakpoint, BreakpointState enabledOrNot)
@@ -435,17 +466,17 @@
     return result.toBoolean(m_currentCallFrame);
 }
 
-class Debugger::ClearBreakpointsFunctor {
+class Debugger::ClearCodeBlockDebuggerRequestsFunctor {
 public:
-    ClearBreakpointsFunctor(Debugger* debugger)
+    ClearCodeBlockDebuggerRequestsFunctor(Debugger* debugger)
         : m_debugger(debugger)
     {
     }
 
     bool operator()(CodeBlock* codeBlock)
     {
-        if (codeBlock->numBreakpoints() && m_debugger == codeBlock->globalObject()->debugger())
-            codeBlock->clearAllBreakpoints();
+        if (codeBlock->hasDebuggerRequests() && m_debugger == codeBlock->globalObject()->debugger())
+            codeBlock->clearDebuggerRequests();
         return false;
     }
 
@@ -462,7 +493,33 @@
     if (!m_vm)
         return;
     HeapIterationScope iterationScope(m_vm->heap);
-    ClearBreakpointsFunctor functor(this);
+    ClearCodeBlockDebuggerRequestsFunctor functor(this);
+    m_vm->heap.forEachCodeBlock(functor);
+}
+
+class Debugger::ClearDebuggerRequestsFunctor {
+public:
+    ClearDebuggerRequestsFunctor(JSGlobalObject* globalObject)
+        : m_globalObject(globalObject)
+    {
+    }
+
+    bool operator()(CodeBlock* codeBlock)
+    {
+        if (codeBlock->hasDebuggerRequests() && m_globalObject == codeBlock->globalObject())
+            codeBlock->clearDebuggerRequests();
+        return false;
+    }
+
+private:
+    JSGlobalObject* m_globalObject;
+};
+
+void Debugger::clearDebuggerRequests(JSGlobalObject* globalObject)
+{
+    ASSERT(m_vm);
+    HeapIterationScope iterationScope(m_vm->heap);
+    ClearDebuggerRequestsFunctor functor(globalObject);
     m_vm->heap.forEachCodeBlock(functor);
 }
 
@@ -480,7 +537,7 @@
 {
     m_pauseOnNextStatement = pause;
     if (pause)
-        setShouldPause(true);
+        setSteppingMode(SteppingModeEnabled);
 }
 
 void Debugger::breakProgram()
@@ -489,7 +546,7 @@
         return;
 
     m_pauseOnNextStatement = true;
-    setShouldPause(true);
+    setSteppingMode(SteppingModeEnabled);
     m_currentCallFrame = m_vm->topCallFrame;
     ASSERT(m_currentCallFrame);
     pauseIfNeeded(m_currentCallFrame);
@@ -510,7 +567,7 @@
         return;
 
     m_pauseOnNextStatement = true;
-    setShouldPause(true);
+    setSteppingMode(SteppingModeEnabled);
     notifyDoneProcessingDebuggerEvents();
 }
 
@@ -546,7 +603,7 @@
 {
     updateCallFrame(callFrame);
     pauseIfNeeded(callFrame);
-    if (!shouldPause())
+    if (!isStepping())
         m_currentCallFrame = 0;
 }
 
@@ -590,7 +647,7 @@
     handlePause(m_reasonForPause, vmEntryGlobalObject);
 
     if (!m_pauseOnNextStatement && !m_pauseOnCallFrame) {
-        setShouldPause(false);
+        setSteppingMode(SteppingModeDisabled);
         m_currentCallFrame = nullptr;
     }
 }
@@ -603,7 +660,7 @@
     PauseReasonDeclaration reason(*this, PausedForException);
     if (m_pauseOnExceptionsState == PauseOnAllExceptions || (m_pauseOnExceptionsState == PauseOnUncaughtExceptions && !hasHandler)) {
         m_pauseOnNextStatement = true;
-        setShouldPause(true);
+        setSteppingMode(SteppingModeEnabled);
     }
 
     m_hasHandlerForExceptionCallback = true;
@@ -661,7 +718,7 @@
     // the debugger implementation to not require callbacks.
     if (!m_isInWorkerThread)
         updateCallFrameAndPauseIfNeeded(callFrame);
-    else if (shouldPause())
+    else if (isStepping())
         updateCallFrame(callFrame);
 }
 
@@ -691,7 +748,7 @@
 
     PauseReasonDeclaration reason(*this, PausedForBreakpoint);
     m_pauseOnNextStatement = true;
-    setShouldPause(true);
+    setSteppingMode(SteppingModeEnabled);
     updateCallFrameAndPauseIfNeeded(callFrame);
 }
 
diff --git a/Source/JavaScriptCore/debugger/Debugger.h b/Source/JavaScriptCore/debugger/Debugger.h
index a7b3200..8b1a08b 100644
--- a/Source/JavaScriptCore/debugger/Debugger.h
+++ b/Source/JavaScriptCore/debugger/Debugger.h
@@ -41,17 +41,11 @@
 
 typedef ExecState CallFrame;
 
-#if ENABLE(JAVASCRIPT_DEBUGGER)
-
 class JS_EXPORT_PRIVATE Debugger {
 public:
     Debugger(bool isInWorkerThread = false);
     virtual ~Debugger();
 
-    bool shouldPause() const { return m_shouldPause; }
-    static ptrdiff_t shouldPauseOffset() { return OBJECT_OFFSETOF(Debugger, m_shouldPause); }
-    void* shouldPauseAddress() { return &m_shouldPause; }
-
     JSC::DebuggerCallFrame* currentDebuggerCallFrame() const;
     bool hasHandlerForExceptionCallback() const
     {
@@ -106,7 +100,6 @@
     void recompileAllJSFunctions(VM*);
 
     void registerCodeBlock(CodeBlock*);
-    void unregisterCodeBlock(CodeBlock*);
 
 protected:
     virtual bool needPauseHandling(JSGlobalObject*) { return false; }
@@ -134,8 +127,10 @@
     typedef HashMap<unsigned, BreakpointsInLine, WTF::IntHash<int>, WTF::UnsignedWithZeroKeyHashTraits<int>> LineToBreakpointsMap;
     typedef HashMap<SourceID, LineToBreakpointsMap, WTF::IntHash<SourceID>, WTF::UnsignedWithZeroKeyHashTraits<SourceID>> SourceIDToBreakpointsMap;
 
+    class ClearCodeBlockDebuggerRequestsFunctor;
+    class ClearDebuggerRequestsFunctor;
+    class SetSteppingModeFunctor;
     class ToggleBreakpointFunctor;
-    class ClearBreakpointsFunctor;
 
     class PauseReasonDeclaration {
     public:
@@ -155,7 +150,6 @@
 
     bool hasBreakpoint(SourceID, const TextPosition&, Breakpoint* hitBreakpoint);
 
-    void setShouldPause(bool);
     void updateNeedForOpDebugCallbacks();
 
     // These update functions are only needed because our current breakpoints are
@@ -167,6 +161,13 @@
     void updateCallFrameAndPauseIfNeeded(JSC::CallFrame*);
     void pauseIfNeeded(JSC::CallFrame*);
 
+    enum SteppingMode {
+        SteppingModeDisabled,
+        SteppingModeEnabled
+    };
+    void setSteppingMode(SteppingMode);
+    bool isStepping() const { return m_steppingMode == SteppingModeEnabled; }
+
     enum BreakpointState {
         BreakpointDisabled,
         BreakpointEnabled
@@ -175,6 +176,8 @@
     void applyBreakpoints(CodeBlock*);
     void toggleBreakpoint(Breakpoint&, BreakpointState);
 
+    void clearDebuggerRequests(JSGlobalObject*);
+
     VM* m_vm;
     HashSet<JSGlobalObject*> m_globalObjects;
 
@@ -184,6 +187,7 @@
     bool m_breakpointsActivated : 1;
     bool m_hasHandlerForExceptionCallback : 1;
     bool m_isInWorkerThread : 1;
+    SteppingMode m_steppingMode : 1;
 
     ReasonForPause m_reasonForPause;
     JSValue m_currentException;
@@ -196,8 +200,6 @@
     BreakpointIDToBreakpointMap m_breakpointIDToBreakpoint;
     SourceIDToBreakpointsMap m_sourceIDToBreakpoints;
 
-    bool m_shouldPause;
-
     RefPtr<JSC::DebuggerCallFrame> m_currentDebuggerCallFrame;
 
     friend class DebuggerCallFrameScope;
@@ -205,32 +207,6 @@
     friend class LLIntOffsetsExtractor;
 };
 
-#else // ENABLE(JAVASCRIPT_DEBUGGER)
-
-class Debugger {
-public:
-    Debugger(bool = false)
-        : m_shouldPause(false)
-    {
-    }
-    bool shouldPause() const { return false; }
-    bool needsExceptionCallbacks() const { return false; }
-    void detach(JSGlobalObject*) { }
-    void sourceParsed(ExecState*, SourceProvider*, int, const WTF::String&) { }
-    void exception(CallFrame*, JSValue, bool) { }
-    void atStatement(CallFrame*) { }
-    void callEvent(CallFrame*) { }
-    void returnEvent(CallFrame*) { }
-    void willExecuteProgram(CallFrame*) { }
-    void didExecuteProgram(CallFrame*) { }
-    void didReachBreakpoint(CallFrame*) { }
-
-private:
-    bool m_shouldPause;
-};
-
-#endif // ENABLE(JAVASCRIPT_DEBUGGER)
-
 } // namespace JSC
 
 #endif // Debugger_h
diff --git a/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp b/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp
index eb31189..fed4acc 100644
--- a/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp
+++ b/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp
@@ -4233,28 +4233,15 @@
         break;
 
     case Breakpoint: {
-        JSGlobalObject* globalObject = m_jit.graph().globalObjectFor(m_currentNode->codeOrigin);
         GPRTemporary temp(this);
-        m_jit.loadPtr(globalObject->debuggerAddress(), temp.gpr());
+        GPRReg debuggerRequestsGPR = temp.gpr();
+        m_jit.load32(m_jit.codeBlock()->debuggerRequestsAddress(), debuggerRequestsGPR);
         speculationCheck(
             DebuggerEvent, JSValueRegs(), 0,
-            m_jit.branchTestPtr(JITCompiler::Zero, temp.gpr()));
-
-        ASSERT(globalObject->hasDebugger());
-        speculationCheck(
-            DebuggerEvent, JSValueRegs(), 0,
-            m_jit.branchTest8(
-                JITCompiler::NonZero,
-                JITCompiler::AbsoluteAddress(globalObject->debugger()->shouldPauseAddress())));
-
-        GPRReg numBreakpointsGPR = temp.gpr();
-        m_jit.load32(m_jit.codeBlock()->numBreakpointsAddress(), numBreakpointsGPR);
-        speculationCheck(
-            DebuggerEvent, JSValueRegs(), 0,
-            m_jit.branchTest32(JITCompiler::NonZero, numBreakpointsGPR));
+            m_jit.branchTest32(JITCompiler::NonZero, debuggerRequestsGPR));
         break;
     }
-        
+
     case ProfileWillCall: {
         JSValueOperand profile(this, node->child1());
         GPRReg profileTagGPR = profile.tagGPR();
diff --git a/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp b/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp
index 9d1d89d..565ae28 100644
--- a/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp
+++ b/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp
@@ -4510,29 +4510,15 @@
         break;
 
     case Breakpoint: {
-        JSGlobalObject* globalObject = m_jit.graph().globalObjectFor(m_currentNode->codeOrigin);
-        speculationCheck(
-            DebuggerEvent, JSValueRegs(), 0,
-            m_jit.branchTestPtr(
-                JITCompiler::Zero,
-                JITCompiler::AbsoluteAddress(globalObject->debuggerAddress())));
-
-        ASSERT(globalObject->hasDebugger());
-        speculationCheck(
-            DebuggerEvent, JSValueRegs(), 0,
-            m_jit.branchTest8(
-                JITCompiler::NonZero,
-                JITCompiler::AbsoluteAddress(globalObject->debugger()->shouldPauseAddress())));
-
         GPRTemporary temp(this);
-        GPRReg numBreakpointsGPR = temp.gpr();
-        m_jit.load32(m_jit.codeBlock()->numBreakpointsAddress(), numBreakpointsGPR);
+        GPRReg debuggerRequestsGPR = temp.gpr();
+        m_jit.load32(m_jit.codeBlock()->debuggerRequestsAddress(), debuggerRequestsGPR);
         speculationCheck(
             DebuggerEvent, JSValueRegs(), 0,
-            m_jit.branchTest32(JITCompiler::NonZero, numBreakpointsGPR));
+            m_jit.branchTest32(JITCompiler::NonZero, debuggerRequestsGPR));
         break;
     }
-        
+
     case ProfileWillCall: {
         JSValueOperand profile(this, node->child1());
         GPRReg profileGPR = profile.gpr();
diff --git a/Source/JavaScriptCore/interpreter/Interpreter.cpp b/Source/JavaScriptCore/interpreter/Interpreter.cpp
index 0b3d0fc..4fbc822 100644
--- a/Source/JavaScriptCore/interpreter/Interpreter.cpp
+++ b/Source/JavaScriptCore/interpreter/Interpreter.cpp
@@ -1207,7 +1207,7 @@
     Debugger* debugger = callFrame->vmEntryGlobalObject()->debugger();
     if (!debugger)
         return;
-    ASSERT(debugger->shouldPause() || callFrame->codeBlock()->numBreakpoints() || callFrame->hadException());
+    ASSERT(callFrame->codeBlock()->hasDebuggerRequests() || callFrame->hadException());
 
     switch (debugHookID) {
         case DidEnterCallFrame:
diff --git a/Source/JavaScriptCore/jit/JITOpcodes.cpp b/Source/JavaScriptCore/jit/JITOpcodes.cpp
index de74778..53f5295 100644
--- a/Source/JavaScriptCore/jit/JITOpcodes.cpp
+++ b/Source/JavaScriptCore/jit/JITOpcodes.cpp
@@ -710,30 +710,10 @@
 
 void JIT::emit_op_debug(Instruction* currentInstruction)
 {
-#if ENABLE(DEBUG_WITH_BREAKPOINT)
-    UNUSED_PARAM(currentInstruction);
-    breakpoint();
-#elif ENABLE(JAVASCRIPT_DEBUGGER)
-    JSGlobalObject* globalObject = codeBlock()->globalObject();
-    char* debuggerAddress = reinterpret_cast<char*>(globalObject) + JSGlobalObject::debuggerOffset();
-    Jump noDebugger = branchTestPtr(Zero, AbsoluteAddress(debuggerAddress));
-
-    Debugger* debugger = globalObject->debugger();
-    char* shouldPauseAddress = reinterpret_cast<char*>(debugger) + Debugger::shouldPauseOffset();
-    Jump callbackNeeded = branchTest8(NonZero, AbsoluteAddress(shouldPauseAddress));
-
-    char* numBreakpointsAddress = reinterpret_cast<char*>(codeBlock()) + CodeBlock::numBreakpointsOffset();
-    load32(numBreakpointsAddress, regT0);
-    Jump noBreakpointSet = branchTest32(Zero, regT0);
-
-    callbackNeeded.link(this);
+    load32(codeBlock()->debuggerRequestsAddress(), regT0);
+    Jump noDebuggerRequests = branchTest32(Zero, regT0);
     callOperation(operationDebug, currentInstruction[1].u.operand);
-
-    noBreakpointSet.link(this);
-    noDebugger.link(this);
-#else
-    UNUSED_PARAM(currentInstruction);
-#endif
+    noDebuggerRequests.link(this);
 }
 
 void JIT::emit_op_eq_null(Instruction* currentInstruction)
diff --git a/Source/JavaScriptCore/jit/JITOpcodes32_64.cpp b/Source/JavaScriptCore/jit/JITOpcodes32_64.cpp
index 31e87db..911135c 100644
--- a/Source/JavaScriptCore/jit/JITOpcodes32_64.cpp
+++ b/Source/JavaScriptCore/jit/JITOpcodes32_64.cpp
@@ -992,31 +992,10 @@
 
 void JIT::emit_op_debug(Instruction* currentInstruction)
 {
-#if ENABLE(DEBUG_WITH_BREAKPOINT)
-    UNUSED_PARAM(currentInstruction);
-    breakpoint();
-#elif ENABLE(JAVASCRIPT_DEBUGGER)
-    JSGlobalObject* globalObject = codeBlock()->globalObject();
-    char* debuggerAddress = reinterpret_cast<char*>(globalObject) + JSGlobalObject::debuggerOffset();
-    loadPtr(debuggerAddress, regT0);
-    Jump noDebugger = branchTestPtr(Zero, regT0);
-
-    Debugger* debugger = globalObject->debugger();
-    char* shouldPauseAddress = reinterpret_cast<char*>(debugger) + Debugger::shouldPauseOffset();
-    Jump callbackNeeded = branchTest8(NonZero, AbsoluteAddress(shouldPauseAddress));
-
-    char* numBreakpointsAddress = reinterpret_cast<char*>(codeBlock()) + CodeBlock::numBreakpointsOffset();
-    load32(numBreakpointsAddress, regT0);
-    Jump noBreakpointSet = branchTest32(Zero, regT0);
-
-    callbackNeeded.link(this);
+    load32(codeBlock()->debuggerRequestsAddress(), regT0);
+    Jump noDebuggerRequests = branchTest32(Zero, regT0);
     callOperation(operationDebug, currentInstruction[1].u.operand);
-
-    noBreakpointSet.link(this);
-    noDebugger.link(this);
-#else
-    UNUSED_PARAM(currentInstruction);
-#endif
+    noDebuggerRequests.link(this);
 }
 
 
diff --git a/Source/JavaScriptCore/llint/LowLevelInterpreter.asm b/Source/JavaScriptCore/llint/LowLevelInterpreter.asm
index cb9e4f6..5f76b11 100644
--- a/Source/JavaScriptCore/llint/LowLevelInterpreter.asm
+++ b/Source/JavaScriptCore/llint/LowLevelInterpreter.asm
@@ -835,18 +835,9 @@
 
 _llint_op_debug:
     traceExecution()
-    loadp CodeBlock[cfr], t1
-    loadp CodeBlock::m_globalObject[t1], t0
-    loadp JSGlobalObject::m_debugger[t0], t0
+    loadp CodeBlock[cfr], t0
+    loadi CodeBlock::m_debuggerRequests[t0], t0
     btiz t0, .opDebugDone
-
-    loadb Debugger::m_shouldPause[t0], t0
-    btbnz t0, .opDebugDoCallback
-
-    loadi CodeBlock::m_numBreakpoints[t1], t0
-    btiz t0, .opDebugDone
-
-.opDebugDoCallback:
     callSlowPath(_llint_slow_path_debug)
 .opDebugDone:                    
     dispatch(3)
diff --git a/Source/JavaScriptCore/runtime/JSGlobalObject.h b/Source/JavaScriptCore/runtime/JSGlobalObject.h
index c7363d9..b0cad3d 100644
--- a/Source/JavaScriptCore/runtime/JSGlobalObject.h
+++ b/Source/JavaScriptCore/runtime/JSGlobalObject.h
@@ -472,8 +472,6 @@
 
     Debugger* debugger() const { return m_debugger; }
     void setDebugger(Debugger* debugger) { m_debugger = debugger; }
-    static ptrdiff_t debuggerOffset() { return OBJECT_OFFSETOF(JSGlobalObject, m_debugger); }
-    void* debuggerAddress() { return &m_debugger; }
 
     const GlobalObjectMethodTable* globalObjectMethodTable() const { return m_globalObjectMethodTable; }