Changeset 162598 in webkit
- Timestamp:
- Jan 22, 2014, 11:39:58 PM (11 years ago)
- Location:
- trunk/Source/JavaScriptCore
- Files:
-
- 13 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/Source/JavaScriptCore/ChangeLog
r162579 r162598 1 2014-01-22 Mark Lam <mark.lam@apple.com> 2 3 Poor man's fast breakpoints for a 2.3x debugger speedup. 4 <https://webkit.org/b/122836> 5 6 Reviewed by Geoffrey Garen. 7 8 Previously we gained back some performance (run at baseline JIT speeds) 9 when the WebInspector is opened provided no breakpoints are set. This 10 was achieved by simply skipping all op_debug callbacks to the debugger 11 if no breakpoints are set. If any breakpoints are set, the debugger will 12 set a m_needsOpDebugCallbacks flag which causes the callbacks to be 13 called, and we don't get the baseline JIT speeds anymore. 14 15 With this patch, we will now track the number of breakpoints set in the 16 CodeBlock that they are set in. The LLINT and baseline JIT code will 17 check CodeBlock::m_numBreakpoints to determine if the op_debug callbacks 18 need to be called. With this, we will only enable op_debug callbacks for 19 CodeBlocks that need it i.e. those with breakpoints set in them. 20 21 Debugger::m_needsOpDebugCallbacks is now obsoleted. The LLINT and baseline 22 JIT code still needs to check Debugger::m_shouldPause to determine if the 23 debugger is in stepping mode and hence, needs op_debug callbacks enabled 24 for everything until the debugger "continues" the run and exit stepping 25 mode. 26 27 Also in this patch, I fixed a regression in DOM breakpoints which relies 28 Debugger::breakProgram() to pause the debugger. 29 30 * bytecode/CodeBlock.cpp: 31 (JSC::CodeBlock::dumpBytecode): 32 - Missed accounting for op_debug's new hasBreakpointFlag operand here when 33 it was added. 34 (JSC::CodeBlock::CodeBlock): 35 (JSC::CodeBlock::hasOpDebugForLineAndColumn): 36 - This is needed in Debugger::toggleBreakpoint() to determine if a 37 breakpoint falls within a CodeBlock or not. Simply checking the bounds 38 of the CodeBlock is insufficient. For example, let's say we have the 39 following JS code: 40 41 // begin global scope 42 function f1() { 43 function f2() { 44 ... // set breakpoint here. 45 } 46 } 47 // end global scope 48 49 Using the CodeBlock bounds alone, the breakpoint above will to appear 50 to be in the global program CodeBlock, and the CodeBlocks for function 51 f1() and f2(). With CodeBlock::hasOpDebugForLineAndColumn() we can 52 rule out the global program CodeBlock and f1(), and only apply the 53 breakpoint to f2(0 where it belongs. 54 55 CodeBlock::hasOpDebugForLineAndColumn() works by iterating over all 56 the opcodes in the CodeBlock to look for op_debug's. For each op_debug, 57 it calls CodeBlock::expressionRangeForBytecodeOffset() to do a binary 58 seach to get the line and column info for that op_debug. This is a 59 N * log(N) algorithm. However, a quick hands on test using the 60 WebInspector (with this patch applied) to exercise setting, breaking 61 on, and clearing breakpoints, as well as stepping through some code 62 shows no noticeable degradation of the user experience compared to the 63 baseline without this patch. 64 65 * bytecode/CodeBlock.h: 66 (JSC::CodeBlock::numBreakpoints): 67 (JSC::CodeBlock::numBreakpointsOffset): 68 (JSC::CodeBlock::addBreakpoint): 69 (JSC::CodeBlock::removeBreakpoint): 70 (JSC::CodeBlock::clearAllBreakpoints): 71 * debugger/Breakpoint.h: 72 - defined Breakpoint::unspecifiedColumn so that we can explicitly indicate 73 when the WebInspector was setting a line breakpoint and did not provide 74 a column value. CodeBlock::hasOpDebugForLineAndColumn() needs this 75 information in order to loosen its matching criteria for op_debug 76 bytecodes for the specified breakpoint line and column values provided 77 by the debugger. 78 79 Previously, we just hijack a 0 value column as an unspecified column. 80 However, the WebInspector operates on 0-based ints for column values. 81 Hence, 0 should be a valid column value and should not be hijacked to 82 mean an unspecified column. 83 84 * debugger/Debugger.cpp: 85 (JSC::Debugger::Debugger): 86 - added tracking of the VM that the debugger is used with. This is 87 needed by Debugger::breakProgram(). 88 89 The VM pointer is attained from the first JSGlobalObject that the debugger 90 attaches to. When the debugger detaches from the last JSGlobalObject, it 91 will nullify its VM pointer to allow a new one to be set on the next 92 attach. 93 94 We were always only using each debugger instance with one VM. This change 95 makes it explicit with an assert to ensure that all globalObjects that 96 the debugger attaches to beongs to the same VM. 97 98 (JSC::Debugger::attach): 99 (JSC::Debugger::detach): 100 (JSC::Debugger::setShouldPause): 101 102 (JSC::Debugger::registerCodeBlock): 103 (JSC::Debugger::unregisterCodeBlock): 104 - registerCodeBlock() is responsible for applying pre-existing breakpoints 105 to new CodeBlocks being installed. Similarly, unregisterCodeBlock() 106 clears the breakpoints. 107 108 (JSC::Debugger::toggleBreakpoint): 109 - This is the workhorse function that checks if a breakpoint falls within 110 a CodeBlock or not. If it does, then it can either enable or disable 111 said breakpoint in the CodeBlock. In the current implementation, 112 enabling/disabling the breakpoint simply means incrementing/decrementing 113 the CodeBlock's m_numBreakpoints. 114 115 (JSC::Debugger::applyBreakpoints): 116 117 (JSC::Debugger::ToggleBreakpointFunctor::ToggleBreakpointFunctor): 118 (JSC::Debugger::ToggleBreakpointFunctor::operator()): 119 (JSC::Debugger::toggleBreakpoint): 120 - Iterates all relevant CodeBlocks and apply the specified breakpoint 121 if appropriate. This is called when a new breakpoint is being defined 122 by the WebInspector and needs to be applied to an already installed 123 CodeBlock. 124 125 (JSC::Debugger::setBreakpoint): 126 (JSC::Debugger::removeBreakpoint): 127 (JSC::Debugger::hasBreakpoint): 128 (JSC::Debugger::ClearBreakpointsFunctor::ClearBreakpointsFunctor): 129 (JSC::Debugger::ClearBreakpointsFunctor::operator()): 130 (JSC::Debugger::clearBreakpoints): 131 132 (JSC::Debugger::breakProgram): 133 - Fixed a regression that broke DOM breakpoints. The issue is that with 134 the skipping of op_debug callbacks, we don't always have an updated 135 m_currentCallFrame. Normally, m_currentCallFrame is provided as arg 136 in the op_debug callback. In this case, we can get the CallFrame* from 137 m_vm->topCallFrame. 138 139 (JSC::Debugger::updateCallFrameAndPauseIfNeeded): 140 (JSC::Debugger::pauseIfNeeded): 141 (JSC::Debugger::willExecuteProgram): 142 * debugger/Debugger.h: 143 (JSC::Debugger::Debugger): 144 (JSC::Debugger::shouldPause): 145 146 * heap/CodeBlockSet.h: 147 (JSC::CodeBlockSet::iterate): 148 * heap/Heap.h: 149 (JSC::Heap::forEachCodeBlock): 150 - Added utility to iterate all CodeBlocks in the heap / VM. 151 152 * interpreter/Interpreter.cpp: 153 (JSC::Interpreter::debug): 154 155 * jit/JITOpcodes.cpp: 156 (JSC::JIT::emit_op_debug): 157 * jit/JITOpcodes32_64.cpp: 158 (JSC::JIT::emit_op_debug): 159 * llint/LowLevelInterpreter.asm: 160 - These now checks CodeBlock::m_numBreakpoints and Debugger::m_shouldPause 161 instead of Debugger::m_needsOpDebugCallbacks. 162 163 * runtime/Executable.cpp: 164 (JSC::ScriptExecutable::installCode): 165 1 166 2014-01-22 Myles C. Maxfield <mmaxfield@apple.com> 2 167 -
trunk/Source/JavaScriptCore/bytecode/CodeBlock.cpp
r162390 r162598 1353 1353 case op_debug: { 1354 1354 int debugHookID = (++it)->u.operand; 1355 int hasBreakpointFlag = (++it)->u.operand; 1355 1356 printLocationAndOp(out, exec, location, it, "debug"); 1356 out.printf("%s ", debugHookName(debugHookID));1357 out.printf("%s %d", debugHookName(debugHookID), hasBreakpointFlag); 1357 1358 break; 1358 1359 } … … 1469 1470 , m_didFailFTLCompilation(false) 1470 1471 , m_unlinkedCode(*other.m_vm, other.m_ownerExecutable.get(), other.m_unlinkedCode.get()) 1472 , m_numBreakpoints(0) 1471 1473 , m_ownerExecutable(*other.m_vm, other.m_ownerExecutable.get(), other.m_ownerExecutable.get()) 1472 1474 , m_vm(other.m_vm) … … 1523 1525 , m_didFailFTLCompilation(false) 1524 1526 , m_unlinkedCode(m_globalObject->vm(), ownerExecutable, unlinkedCodeBlock) 1527 , m_numBreakpoints(0) 1525 1528 , m_ownerExecutable(m_globalObject->vm(), ownerExecutable, ownerExecutable) 1526 1529 , m_vm(unlinkedCodeBlock->vm()) … … 2567 2570 } 2568 2571 2572 bool CodeBlock::hasOpDebugForLineAndColumn(unsigned line, unsigned column) 2573 { 2574 Interpreter* interpreter = vm()->interpreter; 2575 const Instruction* begin = instructions().begin(); 2576 const Instruction* end = instructions().end(); 2577 for (const Instruction* it = begin; it != end;) { 2578 OpcodeID opcodeID = interpreter->getOpcodeID(it->u.opcode); 2579 if (opcodeID == op_debug) { 2580 unsigned bytecodeOffset = it - begin; 2581 int unused; 2582 unsigned opDebugLine; 2583 unsigned opDebugColumn; 2584 expressionRangeForBytecodeOffset(bytecodeOffset, unused, unused, unused, opDebugLine, opDebugColumn); 2585 if (line == opDebugLine && (column == Breakpoint::unspecifiedColumn || column == opDebugColumn)) 2586 return true; 2587 } 2588 it += opcodeLengths[opcodeID]; 2589 } 2590 return false; 2591 } 2592 2569 2593 void CodeBlock::shrinkToFit(ShrinkMode shrinkMode) 2570 2594 { -
trunk/Source/JavaScriptCore/bytecode/CodeBlock.h
r162389 r162598 870 870 unsigned frameRegisterCount(); 871 871 872 bool hasOpDebugForLineAndColumn(unsigned line, unsigned column); 873 874 int numBreakpoints() const { return m_numBreakpoints; } 875 static ptrdiff_t numBreakpointsOffset() { return OBJECT_OFFSETOF(CodeBlock, m_numBreakpoints); } 876 877 void addBreakpoint(int numBreakpoints) { m_numBreakpoints += numBreakpoints; } 878 void removeBreakpoint(int numBreakpoints) 879 { 880 m_numBreakpoints -= numBreakpoints; 881 ASSERT(m_numBreakpoints >= 0); 882 } 883 void clearAllBreakpoints() { m_numBreakpoints = 0; } 884 872 885 // FIXME: Make these remaining members private. 873 886 … … 1006 1019 WriteBarrier<UnlinkedCodeBlock> m_unlinkedCode; 1007 1020 int m_numParameters; 1021 int m_numBreakpoints; 1008 1022 WriteBarrier<ScriptExecutable> m_ownerExecutable; 1009 1023 VM* m_vm; -
trunk/Source/JavaScriptCore/debugger/Breakpoint.h
r158937 r162598 60 60 String condition; 61 61 bool autoContinue; 62 63 static const unsigned unspecifiedColumn = UINT_MAX; 62 64 }; 63 65 -
trunk/Source/JavaScriptCore/debugger/Debugger.cpp
r160082 r162598 1 1 /* 2 * Copyright (C) 2008, 2013 Apple Inc. All rights reserved.2 * Copyright (C) 2008, 2013, 2014 Apple Inc. All rights reserved. 3 3 * Copyright (C) 1999-2001 Harri Porten (porten@kde.org) 4 4 * Copyright (C) 2001 Peter Kelly (pmk@post.com) … … 25 25 #include "Debugger.h" 26 26 27 #include "CodeBlock.h" 27 28 #include "DebuggerCallFrame.h" 28 29 #include "Error.h" 30 29 31 #include "HeapIterationScope.h" 30 32 #include "Interpreter.h" … … 140 142 141 143 Debugger::Debugger(bool isInWorkerThread) 142 : m_pauseOnExceptionsState(DontPauseOnExceptions) 144 : m_vm(nullptr) 145 , m_pauseOnExceptionsState(DontPauseOnExceptions) 143 146 , m_pauseOnNextStatement(false) 144 147 , m_isPaused(false) … … 152 155 , m_lastExecutedSourceID(noSourceID) 153 156 , m_topBreakpointID(noBreakpointID) 154 , m_needsOpDebugCallbacks(false)155 157 , m_shouldPause(false) 156 158 { … … 167 169 { 168 170 ASSERT(!globalObject->debugger()); 171 if (!m_vm) 172 m_vm = &globalObject->vm(); 173 else 174 ASSERT(m_vm == &globalObject->vm()); 169 175 globalObject->setDebugger(this); 170 176 m_globalObjects.add(globalObject); … … 185 191 m_globalObjects.remove(globalObject); 186 192 globalObject->setDebugger(0); 193 if (!m_globalObjects.size()) 194 m_vm = nullptr; 187 195 } 188 196 … … 190 198 { 191 199 m_shouldPause = value; 192 updateNeedForOpDebugCallbacks(); 200 } 201 202 void Debugger::registerCodeBlock(CodeBlock* codeBlock) 203 { 204 applyBreakpoints(codeBlock); 205 } 206 207 void Debugger::unregisterCodeBlock(CodeBlock* codeBlock) 208 { 209 codeBlock->clearAllBreakpoints(); 210 } 211 212 void Debugger::toggleBreakpoint(CodeBlock* codeBlock, Breakpoint& breakpoint, BreakpointState enabledOrNot) 213 { 214 ASSERT(codeBlock->jitCode()->jitType() == JITCode::InterpreterThunk 215 || codeBlock->jitCode()->jitType() == JITCode::BaselineJIT); 216 217 ScriptExecutable* executable = codeBlock->ownerExecutable(); 218 219 SourceID sourceID = static_cast<SourceID>(executable->sourceID()); 220 if (breakpoint.sourceID != sourceID) 221 return; 222 223 unsigned line = breakpoint.line; 224 unsigned column = breakpoint.column; 225 226 unsigned startLine = executable->lineNo(); 227 unsigned startColumn = executable->startColumn(); 228 unsigned endLine = executable->lastLine(); 229 unsigned endColumn = executable->endColumn(); 230 231 // Inspector breakpoint line and column values are zero-based but the executable 232 // and CodeBlock line and column values are one-based. 233 line += 1; 234 column = column ? column + 1 : Breakpoint::unspecifiedColumn; 235 236 if (line < startLine || line > endLine) 237 return; 238 if (column != Breakpoint::unspecifiedColumn) { 239 if (line == startLine && column < startColumn) 240 return; 241 if (line == endLine && column > endColumn) 242 return; 243 } 244 if (!codeBlock->hasOpDebugForLineAndColumn(line, column)) 245 return; 246 247 if (enabledOrNot == BreakpointEnabled) 248 codeBlock->addBreakpoint(1); 249 else 250 codeBlock->removeBreakpoint(1); 251 } 252 253 void Debugger::applyBreakpoints(CodeBlock* codeBlock) 254 { 255 BreakpointIDToBreakpointMap& breakpoints = m_breakpointIDToBreakpoint; 256 for (auto it = breakpoints.begin(); it != breakpoints.end(); ++it) { 257 Breakpoint& breakpoint = *it->value; 258 toggleBreakpoint(codeBlock, breakpoint, BreakpointEnabled); 259 } 260 } 261 262 class Debugger::ToggleBreakpointFunctor { 263 public: 264 ToggleBreakpointFunctor(Debugger* debugger, Breakpoint& breakpoint, BreakpointState enabledOrNot) 265 : m_debugger(debugger) 266 , m_breakpoint(breakpoint) 267 , m_enabledOrNot(enabledOrNot) 268 { 269 } 270 271 bool operator()(CodeBlock* codeBlock) 272 { 273 if (m_debugger == codeBlock->globalObject()->debugger()) 274 m_debugger->toggleBreakpoint(codeBlock, m_breakpoint, m_enabledOrNot); 275 return false; 276 } 277 278 private: 279 Debugger* m_debugger; 280 Breakpoint& m_breakpoint; 281 BreakpointState m_enabledOrNot; 282 }; 283 284 void Debugger::toggleBreakpoint(Breakpoint& breakpoint, Debugger::BreakpointState enabledOrNot) 285 { 286 if (!m_vm) 287 return; 288 HeapIterationScope iterationScope(m_vm->heap); 289 ToggleBreakpointFunctor functor(this, breakpoint, enabledOrNot); 290 m_vm->heap.forEachCodeBlock(functor); 193 291 } 194 292 … … 206 304 HeapIterationScope iterationScope(vm->heap); 207 305 vm->heap.objectSpace().forEachLiveCell(iterationScope, recompiler); 208 }209 210 void Debugger::updateNeedForOpDebugCallbacks()211 {212 size_t numberOfBreakpoints = m_breakpointIDToBreakpoint.size();213 m_needsOpDebugCallbacks = m_shouldPause || numberOfBreakpoints;214 306 } 215 307 … … 248 340 m_breakpointIDToBreakpoint.set(id, &breakpoints.last()); 249 341 250 updateNeedForOpDebugCallbacks();342 toggleBreakpoint(breakpoint, BreakpointEnabled); 251 343 252 344 return id; … … 267 359 LineToBreakpointsMap::iterator breaksIt = it->value.find(breakpoint.line); 268 360 ASSERT(breaksIt != it->value.end()); 361 362 toggleBreakpoint(breakpoint, BreakpointDisabled); 269 363 270 364 BreakpointsInLine& breakpoints = breaksIt->value; … … 283 377 } 284 378 } 285 286 updateNeedForOpDebugCallbacks();287 379 } 288 380 … … 311 403 unsigned breakColumn = breakpoints[i].column; 312 404 // Since frontend truncates the indent, the first statement in a line must match the breakpoint (line,0). 405 ASSERT(this == m_currentCallFrame->codeBlock()->globalObject()->debugger()); 313 406 if ((line != m_lastExecutedLine && line == breakLine && !breakColumn) 314 407 || (line == breakLine && column == breakColumn)) { … … 346 439 } 347 440 441 class Debugger::ClearBreakpointsFunctor { 442 public: 443 ClearBreakpointsFunctor(Debugger* debugger) 444 : m_debugger(debugger) 445 { 446 } 447 448 bool operator()(CodeBlock* codeBlock) 449 { 450 if (codeBlock->numBreakpoints() && m_debugger == codeBlock->globalObject()->debugger()) 451 codeBlock->clearAllBreakpoints(); 452 return false; 453 } 454 455 private: 456 Debugger* m_debugger; 457 }; 458 348 459 void Debugger::clearBreakpoints() 349 460 { … … 352 463 m_sourceIDToBreakpoints.clear(); 353 464 354 updateNeedForOpDebugCallbacks(); 465 if (!m_vm) 466 return; 467 HeapIterationScope iterationScope(m_vm->heap); 468 ClearBreakpointsFunctor functor(this); 469 m_vm->heap.forEachCodeBlock(functor); 355 470 } 356 471 … … 374 489 void Debugger::breakProgram() 375 490 { 376 if (m_isPaused || !m_currentCallFrame)491 if (m_isPaused) 377 492 return; 378 493 379 494 m_pauseOnNextStatement = true; 380 495 setShouldPause(true); 496 m_currentCallFrame = m_vm->topCallFrame; 497 ASSERT(m_currentCallFrame); 381 498 pauseIfNeeded(m_currentCallFrame); 382 499 } … … 433 550 updateCallFrame(callFrame); 434 551 pauseIfNeeded(callFrame); 435 if (! needsOpDebugCallbacks())552 if (!shouldPause()) 436 553 m_currentCallFrame = 0; 437 554 } … … 478 595 if (!m_pauseOnNextStatement && !m_pauseOnCallFrame) { 479 596 setShouldPause(false); 480 if (!needsOpDebugCallbacks()) 481 m_currentCallFrame = 0; 597 m_currentCallFrame = nullptr; 482 598 } 483 599 } … … 549 665 if (!m_isInWorkerThread) 550 666 updateCallFrameAndPauseIfNeeded(callFrame); 551 else if ( needsOpDebugCallbacks())667 else if (shouldPause()) 552 668 updateCallFrame(callFrame); 553 669 } -
trunk/Source/JavaScriptCore/debugger/Debugger.h
r161353 r162598 2 2 * Copyright (C) 1999-2001 Harri Porten (porten@kde.org) 3 3 * Copyright (C) 2001 Peter Kelly (pmk@post.com) 4 * Copyright (C) 2008, 2009, 2013 Apple Inc. All rights reserved.4 * Copyright (C) 2008, 2009, 2013, 2014 Apple Inc. All rights reserved. 5 5 * 6 6 * This library is free software; you can redistribute it and/or … … 49 49 virtual ~Debugger(); 50 50 51 bool needsOpDebugCallbacks() const { return m_needsOpDebugCallbacks; }52 static ptrdiff_t needsOpDebugCallbacksOffset() { return OBJECT_OFFSETOF(Debugger, m_needsOpDebugCallbacks); }51 bool shouldPause() const { return m_shouldPause; } 52 static ptrdiff_t shouldPauseOffset() { return OBJECT_OFFSETOF(Debugger, m_shouldPause); } 53 53 54 54 JSC::DebuggerCallFrame* currentDebuggerCallFrame() const; … … 105 105 void recompileAllJSFunctions(VM*); 106 106 107 void registerCodeBlock(CodeBlock*); 108 void unregisterCodeBlock(CodeBlock*); 109 107 110 protected: 108 111 virtual bool needPauseHandling(JSGlobalObject*) { return false; } … … 129 132 typedef Vector<Breakpoint> BreakpointsInLine; 130 133 typedef HashMap<unsigned, BreakpointsInLine, WTF::IntHash<int>, WTF::UnsignedWithZeroKeyHashTraits<int>> LineToBreakpointsMap; 131 typedef HashMap<SourceID, LineToBreakpointsMap> SourceIDToBreakpointsMap; 134 typedef HashMap<SourceID, LineToBreakpointsMap, WTF::IntHash<SourceID>, WTF::UnsignedWithZeroKeyHashTraits<SourceID>> SourceIDToBreakpointsMap; 135 136 class ToggleBreakpointFunctor; 137 class ClearBreakpointsFunctor; 132 138 133 139 class PauseReasonDeclaration { … … 149 155 bool hasBreakpoint(SourceID, const TextPosition&, Breakpoint* hitBreakpoint); 150 156 151 bool shouldPause() const { return m_shouldPause; }152 157 void setShouldPause(bool); 153 158 void updateNeedForOpDebugCallbacks(); … … 162 167 void pauseIfNeeded(JSC::CallFrame*); 163 168 169 enum BreakpointState { 170 BreakpointDisabled, 171 BreakpointEnabled 172 }; 173 void toggleBreakpoint(CodeBlock*, Breakpoint&, BreakpointState); 174 void applyBreakpoints(CodeBlock*); 175 void toggleBreakpoint(Breakpoint&, BreakpointState); 176 177 VM* m_vm; 164 178 HashSet<JSGlobalObject*> m_globalObjects; 165 179 … … 182 196 SourceIDToBreakpointsMap m_sourceIDToBreakpoints; 183 197 184 bool m_needsOpDebugCallbacks;185 198 bool m_shouldPause; 186 199 … … 196 209 class Debugger { 197 210 public: 198 Debugger(bool = false) : m_needsOpDebugCallbacks(false) { } 199 bool needsOpDebugCallbacks() const { return false; } 211 Debugger(bool = false) 212 : m_shouldPause(false) 213 { 214 } 215 bool shouldPause() const { return false; } 200 216 bool needsExceptionCallbacks() const { return false; } 201 217 void detach(JSGlobalObject*) { } … … 209 225 void didReachBreakpoint(CallFrame*) { } 210 226 211 bool m_needsOpDebugCallbacks; 227 private: 228 bool m_shouldPause; 212 229 }; 213 230 -
trunk/Source/JavaScriptCore/heap/CodeBlockSet.h
r161615 r162598 72 72 void rememberCurrentlyExecutingCodeBlocks(Heap*); 73 73 74 // Visits each CodeBlock in the heap until the visitor function returns true 75 // to indicate that it is done iterating, or until every CodeBlock has been 76 // visited. 77 template<typename Functor> void iterate(Functor& functor) 78 { 79 for (auto &codeBlock : m_set) { 80 bool done = functor(codeBlock); 81 if (done) 82 break; 83 } 84 } 85 74 86 private: 75 87 // This is not a set of RefPtr<CodeBlock> because we need to be able to find -
trunk/Source/JavaScriptCore/heap/Heap.h
r162139 r162598 175 175 template<typename Functor> typename Functor::ReturnType forEachProtectedCell(Functor&); 176 176 template<typename Functor> typename Functor::ReturnType forEachProtectedCell(); 177 template<typename Functor> inline void forEachCodeBlock(Functor&); 177 178 178 179 HandleSet* handleSet() { return &m_handleSet; } … … 433 434 } 434 435 436 template<typename Functor> inline void Heap::forEachCodeBlock(Functor& functor) 437 { 438 return m_codeBlocks.iterate<Functor>(functor); 439 } 440 435 441 inline void* Heap::allocateWithNormalDestructor(size_t bytes) 436 442 { -
trunk/Source/JavaScriptCore/interpreter/Interpreter.cpp
r162156 r162598 1206 1206 { 1207 1207 Debugger* debugger = callFrame->vmEntryGlobalObject()->debugger(); 1208 if (!debugger || !debugger->needsOpDebugCallbacks())1208 if (!debugger) 1209 1209 return; 1210 ASSERT(debugger->shouldPause() || callFrame->codeBlock()->numBreakpoints() || callFrame->hadException()); 1210 1211 1211 1212 switch (debugHookID) { -
trunk/Source/JavaScriptCore/jit/JITOpcodes.cpp
r161364 r162598 716 716 #elif ENABLE(JAVASCRIPT_DEBUGGER) 717 717 JSGlobalObject* globalObject = codeBlock()->globalObject(); 718 Debugger* debugger = globalObject->debugger();719 718 char* debuggerAddress = reinterpret_cast<char*>(globalObject) + JSGlobalObject::debuggerOffset(); 720 719 Jump noDebugger = branchTestPtr(Zero, AbsoluteAddress(debuggerAddress)); 721 char* flagAddress = reinterpret_cast<char*>(debugger) + Debugger::needsOpDebugCallbacksOffset(); 722 Jump skipDebugHook = branchTest8(Zero, AbsoluteAddress(flagAddress)); 720 721 Debugger* debugger = globalObject->debugger(); 722 char* shouldPauseAddress = reinterpret_cast<char*>(debugger) + Debugger::shouldPauseOffset(); 723 Jump callbackNeeded = branchTest8(NonZero, AbsoluteAddress(shouldPauseAddress)); 724 725 char* numBreakpointsAddress = reinterpret_cast<char*>(codeBlock()) + CodeBlock::numBreakpointsOffset(); 726 load32(numBreakpointsAddress, regT0); 727 Jump noBreakpointSet = branchTest32(Zero, regT0); 728 729 callbackNeeded.link(this); 723 730 callOperation(operationDebug, currentInstruction[1].u.operand); 724 skipDebugHook.link(this); 731 732 noBreakpointSet.link(this); 725 733 noDebugger.link(this); 726 734 #else -
trunk/Source/JavaScriptCore/jit/JITOpcodes32_64.cpp
r161364 r162598 998 998 #elif ENABLE(JAVASCRIPT_DEBUGGER) 999 999 JSGlobalObject* globalObject = codeBlock()->globalObject(); 1000 Debugger* debugger = globalObject->debugger();1001 1000 char* debuggerAddress = reinterpret_cast<char*>(globalObject) + JSGlobalObject::debuggerOffset(); 1002 1001 loadPtr(debuggerAddress, regT0); 1003 1002 Jump noDebugger = branchTestPtr(Zero, regT0); 1004 char* flagAddress = reinterpret_cast<char*>(debugger) + Debugger::needsOpDebugCallbacksOffset(); 1005 Jump skipDebugHook = branchTest8(Zero, AbsoluteAddress(flagAddress)); 1003 1004 Debugger* debugger = globalObject->debugger(); 1005 char* shouldPauseAddress = reinterpret_cast<char*>(debugger) + Debugger::shouldPauseOffset(); 1006 Jump callbackNeeded = branchTest8(NonZero, AbsoluteAddress(shouldPauseAddress)); 1007 1008 char* numBreakpointsAddress = reinterpret_cast<char*>(codeBlock()) + CodeBlock::numBreakpointsOffset(); 1009 load32(numBreakpointsAddress, regT0); 1010 Jump noBreakpointSet = branchTest32(Zero, regT0); 1011 1012 callbackNeeded.link(this); 1006 1013 callOperation(operationDebug, currentInstruction[1].u.operand); 1007 skipDebugHook.link(this); 1014 1015 noBreakpointSet.link(this); 1008 1016 noDebugger.link(this); 1009 1017 #else -
trunk/Source/JavaScriptCore/llint/LowLevelInterpreter.asm
r162270 r162598 836 836 _llint_op_debug: 837 837 traceExecution() 838 loadp CodeBlock[cfr], t 0839 loadp CodeBlock::m_globalObject[t 0], t0838 loadp CodeBlock[cfr], t1 839 loadp CodeBlock::m_globalObject[t1], t0 840 840 loadp JSGlobalObject::m_debugger[t0], t0 841 841 btiz t0, .opDebugDone 842 loadb Debugger::m_needsOpDebugCallbacks[t0], t0 843 btbz t0, .opDebugDone 844 842 843 loadb Debugger::m_shouldPause[t0], t0 844 btbnz t0, .opDebugDoCallback 845 846 loadi CodeBlock::m_numBreakpoints[t1], t0 847 btiz t0, .opDebugDone 848 849 .opDebugDoCallback: 845 850 callSlowPath(_llint_slow_path_debug) 846 851 .opDebugDone: -
trunk/Source/JavaScriptCore/runtime/Executable.cpp
r159825 r162598 173 173 if (oldCodeBlock) 174 174 oldCodeBlock->unlinkIncomingCalls(); 175 176 Debugger* debugger = genericCodeBlock->globalObject()->debugger(); 177 if (debugger) 178 debugger->registerCodeBlock(genericCodeBlock); 175 179 } 176 180
Note:
See TracChangeset
for help on using the changeset viewer.