diff options
| author | Lorry Tar Creator <lorry-tar-importer@lorry> | 2015-05-20 09:56:07 +0000 |
|---|---|---|
| committer | Lorry Tar Creator <lorry-tar-importer@lorry> | 2015-05-20 09:56:07 +0000 |
| commit | 41386e9cb918eed93b3f13648cbef387e371e451 (patch) | |
| tree | a97f9d7bd1d9d091833286085f72da9d83fd0606 /Source/JavaScriptCore/debugger | |
| parent | e15dd966d523731101f70ccf768bba12435a0208 (diff) | |
| download | WebKitGtk-tarball-41386e9cb918eed93b3f13648cbef387e371e451.tar.gz | |
webkitgtk-2.4.9webkitgtk-2.4.9
Diffstat (limited to 'Source/JavaScriptCore/debugger')
| -rw-r--r-- | Source/JavaScriptCore/debugger/Breakpoint.h | 34 | ||||
| -rw-r--r-- | Source/JavaScriptCore/debugger/Debugger.cpp | 181 | ||||
| -rw-r--r-- | Source/JavaScriptCore/debugger/Debugger.h | 54 | ||||
| -rw-r--r-- | Source/JavaScriptCore/debugger/DebuggerActivation.cpp | 98 | ||||
| -rw-r--r-- | Source/JavaScriptCore/debugger/DebuggerActivation.h (renamed from Source/JavaScriptCore/debugger/DebuggerScope.h) | 81 | ||||
| -rw-r--r-- | Source/JavaScriptCore/debugger/DebuggerCallFrame.cpp | 93 | ||||
| -rw-r--r-- | Source/JavaScriptCore/debugger/DebuggerCallFrame.h | 26 | ||||
| -rw-r--r-- | Source/JavaScriptCore/debugger/DebuggerEvalEnabler.h | 63 | ||||
| -rw-r--r-- | Source/JavaScriptCore/debugger/DebuggerPrimitives.h | 2 | ||||
| -rw-r--r-- | Source/JavaScriptCore/debugger/DebuggerScope.cpp | 208 |
10 files changed, 238 insertions, 602 deletions
diff --git a/Source/JavaScriptCore/debugger/Breakpoint.h b/Source/JavaScriptCore/debugger/Breakpoint.h index 8518ce469..95b92881d 100644 --- a/Source/JavaScriptCore/debugger/Breakpoint.h +++ b/Source/JavaScriptCore/debugger/Breakpoint.h @@ -27,13 +27,11 @@ #define Breakpoint_h #include "DebuggerPrimitives.h" -#include <wtf/DoublyLinkedList.h> -#include <wtf/RefCounted.h> #include <wtf/text/WTFString.h> namespace JSC { -struct Breakpoint : public DoublyLinkedListNode<Breakpoint> { +struct Breakpoint { Breakpoint() : id(noBreakpointID) , sourceID(noSourceID) @@ -43,7 +41,7 @@ struct Breakpoint : public DoublyLinkedListNode<Breakpoint> { { } - Breakpoint(SourceID sourceID, unsigned line, unsigned column, const String& condition, bool autoContinue) + Breakpoint(SourceID sourceID, unsigned line, unsigned column, String condition, bool autoContinue) : id(noBreakpointID) , sourceID(sourceID) , line(line) @@ -53,16 +51,6 @@ struct Breakpoint : public DoublyLinkedListNode<Breakpoint> { { } - Breakpoint(const Breakpoint& other) - : id(other.id) - , sourceID(other.sourceID) - , line(other.line) - , column(other.column) - , condition(other.condition) - , autoContinue(other.autoContinue) - { - } - BreakpointID id; SourceID sourceID; unsigned line; @@ -71,24 +59,6 @@ struct Breakpoint : public DoublyLinkedListNode<Breakpoint> { bool autoContinue; static const unsigned unspecifiedColumn = UINT_MAX; - -private: - Breakpoint* m_prev; - Breakpoint* m_next; - - friend class WTF::DoublyLinkedListNode<Breakpoint>; -}; - -class BreakpointsList : public DoublyLinkedList<Breakpoint>, - public RefCounted<BreakpointsList> { -public: - ~BreakpointsList() - { - Breakpoint* breakpoint; - while ((breakpoint = removeHead())) - delete breakpoint; - ASSERT(isEmpty()); - } }; } // namespace JSC diff --git a/Source/JavaScriptCore/debugger/Debugger.cpp b/Source/JavaScriptCore/debugger/Debugger.cpp index 4d7871ff8..afa7546c8 100644 --- a/Source/JavaScriptCore/debugger/Debugger.cpp +++ b/Source/JavaScriptCore/debugger/Debugger.cpp @@ -25,12 +25,13 @@ #include "CodeBlock.h" #include "DebuggerCallFrame.h" #include "Error.h" + #include "HeapIterationScope.h" #include "Interpreter.h" #include "JSCJSValueInlines.h" #include "JSFunction.h" #include "JSGlobalObject.h" -#include "JSCInlines.h" +#include "Operations.h" #include "Parser.h" #include "Protect.h" #include "VMEntryScope.h" @@ -43,14 +44,12 @@ class Recompiler : public MarkedBlock::VoidFunctor { public: Recompiler(JSC::Debugger*); ~Recompiler(); - IterationStatus operator()(JSCell*); + void operator()(JSCell*); private: typedef HashSet<FunctionExecutable*> FunctionExecutableSet; typedef HashMap<SourceProvider*, ExecState*> SourceProviderMap; - void visit(JSCell*); - JSC::Debugger* m_debugger; FunctionExecutableSet m_functionExecutables; SourceProviderMap m_sourceProviders; @@ -70,7 +69,7 @@ inline Recompiler::~Recompiler() m_debugger->sourceParsed(iter->value, iter->key, -1, String()); } -inline void Recompiler::visit(JSCell* cell) +inline void Recompiler::operator()(JSCell* cell) { if (!cell->inherits(JSFunction::info())) return; @@ -87,25 +86,19 @@ inline void Recompiler::visit(JSCell* cell) return; ExecState* exec = function->scope()->globalObject()->JSGlobalObject::globalExec(); - executable->clearCode(); - executable->clearUnlinkedCodeForRecompilation(); + executable->clearCodeIfNotCompiling(); + executable->clearUnlinkedCodeForRecompilationIfNotCompiling(); if (m_debugger == function->scope()->globalObject()->debugger()) m_sourceProviders.add(executable->source().provider(), exec); } -inline IterationStatus Recompiler::operator()(JSCell* cell) -{ - visit(cell); - return IterationStatus::Continue; -} - } // namespace namespace JSC { -class DebuggerPausedScope { +class DebuggerCallFrameScope { public: - DebuggerPausedScope(Debugger& debugger) + DebuggerCallFrameScope(Debugger& debugger) : m_debugger(debugger) { ASSERT(!m_debugger.m_currentDebuggerCallFrame); @@ -113,11 +106,11 @@ public: m_debugger.m_currentDebuggerCallFrame = DebuggerCallFrame::create(debugger.m_currentCallFrame); } - ~DebuggerPausedScope() + ~DebuggerCallFrameScope() { if (m_debugger.m_currentDebuggerCallFrame) { m_debugger.m_currentDebuggerCallFrame->invalidate(); - m_debugger.m_currentDebuggerCallFrame = nullptr; + m_debugger.m_currentDebuggerCallFrame = 0; } } @@ -145,13 +138,6 @@ private: Debugger& m_debugger; }; -template<typename Functor> -void Debugger::forEachCodeBlock(Functor& functor) -{ - m_vm->prepareToDeleteCode(); - m_vm->heap.forEachCodeBlock(functor); -} - Debugger::Debugger(bool isInWorkerThread) : m_vm(nullptr) , m_pauseOnExceptionsState(DontPauseOnExceptions) @@ -167,7 +153,6 @@ Debugger::Debugger(bool isInWorkerThread) , m_lastExecutedLine(UINT_MAX) , m_lastExecutedSourceID(noSourceID) , m_topBreakpointID(noBreakpointID) - , m_pausingBreakpointID(noBreakpointID) { } @@ -214,11 +199,6 @@ void Debugger::detach(JSGlobalObject* globalObject, ReasonForDetach reason) m_vm = nullptr; } -bool Debugger::isAttached(JSGlobalObject* globalObject) -{ - return globalObject->debugger() == this; -} - class Debugger::SetSteppingModeFunctor { public: SetSteppingModeFunctor(Debugger* debugger, SteppingMode mode) @@ -245,22 +225,18 @@ private: void Debugger::setSteppingMode(SteppingMode mode) { - if (mode == m_steppingMode || !m_vm) + if (mode == m_steppingMode) return; - - m_vm->prepareToDeleteCode(); - m_steppingMode = mode; + + if (!m_vm) + return; SetSteppingModeFunctor functor(this, mode); m_vm->heap.forEachCodeBlock(functor); } void Debugger::registerCodeBlock(CodeBlock* codeBlock) { - // FIXME: We should never have to jettison a code block (due to pending breakpoints - // or stepping mode) that is being registered. operationOptimize() should have - // prevented the optimizing of such code blocks in the first place. Find a way to - // express this with greater clarity in the code. See <https://webkit.org/b131771>. applyBreakpoints(codeBlock); if (isStepping()) codeBlock->setSteppingMode(CodeBlock::SteppingModeEnabled); @@ -277,7 +253,7 @@ void Debugger::toggleBreakpoint(CodeBlock* codeBlock, Breakpoint& breakpoint, Br unsigned line = breakpoint.line; unsigned column = breakpoint.column; - unsigned startLine = executable->firstLine(); + unsigned startLine = executable->lineNo(); unsigned startColumn = executable->startColumn(); unsigned endLine = executable->lastLine(); unsigned endColumn = executable->endColumn(); @@ -340,7 +316,7 @@ void Debugger::toggleBreakpoint(Breakpoint& breakpoint, Debugger::BreakpointStat if (!m_vm) return; ToggleBreakpointFunctor functor(this, breakpoint, enabledOrNot); - forEachCodeBlock(functor); + m_vm->heap.forEachCodeBlock(functor); } void Debugger::recompileAllJSFunctions(VM* vm) @@ -348,17 +324,11 @@ void Debugger::recompileAllJSFunctions(VM* vm) // If JavaScript is running, it's not safe to recompile, since we'll end // up throwing away code that is live on the stack. if (vm->entryScope) { - auto listener = [] (VM& vm, JSGlobalObject* globalObject) - { - if (Debugger* debugger = globalObject->debugger()) - debugger->recompileAllJSFunctions(&vm); - }; - - vm->entryScope->setEntryScopeDidPopListener(this, listener); + vm->entryScope->setRecompilationNeeded(true); return; } - vm->prepareToDeleteCode(); + vm->prepareToDiscardCode(); Recompiler recompiler(this); HeapIterationScope iterationScope(vm->heap); @@ -376,18 +346,18 @@ BreakpointID Debugger::setBreakpoint(Breakpoint breakpoint, unsigned& actualLine it = m_sourceIDToBreakpoints.set(sourceID, LineToBreakpointsMap()).iterator; LineToBreakpointsMap::iterator breaksIt = it->value.find(line); if (breaksIt == it->value.end()) - breaksIt = it->value.set(line, adoptRef(new BreakpointsList)).iterator; + breaksIt = it->value.set(line, BreakpointsInLine()).iterator; - BreakpointsList& breakpoints = *breaksIt->value; - for (Breakpoint* current = breakpoints.head(); current; current = current->next()) { - if (current->column == column) { + BreakpointsInLine& breakpoints = breaksIt->value; + unsigned breakpointsCount = breakpoints.size(); + for (unsigned i = 0; i < breakpointsCount; i++) + if (breakpoints[i].column == column) { // The breakpoint already exists. We're not allowed to create a new // breakpoint at this location. Rather than returning the breakpointID // of the pre-existing breakpoint, we need to return noBreakpointID // to indicate that we're not creating a new one. return noBreakpointID; } - } BreakpointID id = ++m_topBreakpointID; RELEASE_ASSERT(id != noBreakpointID); @@ -396,9 +366,8 @@ BreakpointID Debugger::setBreakpoint(Breakpoint breakpoint, unsigned& actualLine actualLine = line; actualColumn = column; - Breakpoint* newBreakpoint = new Breakpoint(breakpoint); - breakpoints.append(newBreakpoint); - m_breakpointIDToBreakpoint.set(id, newBreakpoint); + breakpoints.append(breakpoint); + m_breakpointIDToBreakpoint.set(id, &breakpoints.last()); toggleBreakpoint(breakpoint, BreakpointEnabled); @@ -411,35 +380,31 @@ void Debugger::removeBreakpoint(BreakpointID id) BreakpointIDToBreakpointMap::iterator idIt = m_breakpointIDToBreakpoint.find(id); ASSERT(idIt != m_breakpointIDToBreakpoint.end()); - Breakpoint* breakpoint = idIt->value; + Breakpoint& breakpoint = *idIt->value; - SourceID sourceID = breakpoint->sourceID; + SourceID sourceID = breakpoint.sourceID; ASSERT(sourceID); SourceIDToBreakpointsMap::iterator it = m_sourceIDToBreakpoints.find(sourceID); ASSERT(it != m_sourceIDToBreakpoints.end()); - LineToBreakpointsMap::iterator breaksIt = it->value.find(breakpoint->line); + LineToBreakpointsMap::iterator breaksIt = it->value.find(breakpoint.line); ASSERT(breaksIt != it->value.end()); - toggleBreakpoint(*breakpoint, BreakpointDisabled); + toggleBreakpoint(breakpoint, BreakpointDisabled); - BreakpointsList& breakpoints = *breaksIt->value; -#if !ASSERT_DISABLED - bool found = false; - for (Breakpoint* current = breakpoints.head(); current && !found; current = current->next()) { - if (current->id == breakpoint->id) - found = true; - } - ASSERT(found); -#endif + BreakpointsInLine& breakpoints = breaksIt->value; + unsigned breakpointsCount = breakpoints.size(); + for (unsigned i = 0; i < breakpointsCount; i++) { + if (breakpoints[i].id == breakpoint.id) { + breakpoints.remove(i); + m_breakpointIDToBreakpoint.remove(idIt); - m_breakpointIDToBreakpoint.remove(idIt); - breakpoints.remove(breakpoint); - delete breakpoint; - - if (breakpoints.isEmpty()) { - it->value.remove(breaksIt); - if (it->value.isEmpty()) - m_sourceIDToBreakpoints.remove(it); + if (breakpoints.isEmpty()) { + it->value.remove(breaksIt); + if (it->value.isEmpty()) + m_sourceIDToBreakpoints.remove(it); + } + break; + } } } @@ -460,11 +425,12 @@ bool Debugger::hasBreakpoint(SourceID sourceID, const TextPosition& position, Br return false; bool hit = false; - const BreakpointsList& breakpoints = *breaksIt->value; - Breakpoint* breakpoint; - for (breakpoint = breakpoints.head(); breakpoint; breakpoint = breakpoint->next()) { - unsigned breakLine = breakpoint->line; - unsigned breakColumn = breakpoint->column; + const BreakpointsInLine& breakpoints = breaksIt->value; + unsigned breakpointsCount = breakpoints.size(); + unsigned i; + for (i = 0; i < breakpointsCount; i++) { + unsigned breakLine = breakpoints[i].line; + unsigned breakColumn = breakpoints[i].column; // Since frontend truncates the indent, the first statement in a line must match the breakpoint (line,0). ASSERT(this == m_currentCallFrame->codeBlock()->globalObject()->debugger()); if ((line != m_lastExecutedLine && line == breakLine && !breakColumn) @@ -477,18 +443,17 @@ bool Debugger::hasBreakpoint(SourceID sourceID, const TextPosition& position, Br return false; if (hitBreakpoint) - *hitBreakpoint = *breakpoint; + *hitBreakpoint = breakpoints[i]; - if (breakpoint->condition.isEmpty()) + if (breakpoints[i].condition.isEmpty()) return true; // We cannot stop in the debugger while executing condition code, // so make it looks like the debugger is already paused. TemporaryPausedState pausedState(*this); - NakedPtr<Exception> exception; - DebuggerCallFrame* debuggerCallFrame = currentDebuggerCallFrame(); - JSValue result = debuggerCallFrame->evaluate(breakpoint->condition, exception); + JSValue exception; + JSValue result = DebuggerCallFrame::evaluateWithCallFrame(m_currentCallFrame, breakpoints[i].condition, exception); // We can lose the debugger while executing JavaScript. if (!m_currentCallFrame) @@ -530,7 +495,7 @@ void Debugger::clearBreakpoints() if (!m_vm) return; ClearCodeBlockDebuggerRequestsFunctor functor(this); - forEachCodeBlock(functor); + m_vm->heap.forEachCodeBlock(functor); } class Debugger::ClearDebuggerRequestsFunctor { @@ -555,7 +520,7 @@ void Debugger::clearDebuggerRequests(JSGlobalObject* globalObject) { ASSERT(m_vm); ClearDebuggerRequestsFunctor functor(globalObject); - forEachCodeBlock(functor); + m_vm->heap.forEachCodeBlock(functor); } void Debugger::setBreakpointsActivated(bool activated) @@ -620,8 +585,7 @@ void Debugger::stepOutOfFunction() if (!m_isPaused) return; - VMEntryFrame* topVMEntryFrame = m_vm->topVMEntryFrame; - m_pauseOnCallFrame = m_currentCallFrame ? m_currentCallFrame->callerFrame(topVMEntryFrame) : 0; + m_pauseOnCallFrame = m_currentCallFrame ? m_currentCallFrame->callerFrameSkippingVMEntrySentinel() : 0; notifyDoneProcessingDebuggerEvents(); } @@ -657,8 +621,6 @@ void Debugger::pauseIfNeeded(CallFrame* callFrame) bool pauseNow = m_pauseOnNextStatement; pauseNow |= (m_pauseOnCallFrame == m_currentCallFrame); - DebuggerPausedScope debuggerPausedScope(*this); - intptr_t sourceID = DebuggerCallFrame::sourceIDForCallFrame(m_currentCallFrame); TextPosition position = DebuggerCallFrame::positionForCallFrame(m_currentCallFrame); pauseNow |= didHitBreakpoint = hasBreakpoint(sourceID, position, &breakpoint); @@ -666,6 +628,8 @@ void Debugger::pauseIfNeeded(CallFrame* callFrame) if (!pauseNow) return; + DebuggerCallFrameScope debuggerCallFrameScope(*this); + // Make sure we are not going to pause again on breakpoint actions by // reseting the pause state before executing any breakpoint actions. TemporaryPausedState pausedState(*this); @@ -673,20 +637,14 @@ void Debugger::pauseIfNeeded(CallFrame* callFrame) m_pauseOnNextStatement = false; if (didHitBreakpoint) { - handleBreakpointHit(vmEntryGlobalObject, breakpoint); + handleBreakpointHit(breakpoint); // Note that the actions can potentially stop the debugger, so we need to check that // we still have a current call frame when we get back. if (breakpoint.autoContinue || !m_currentCallFrame) return; - m_pausingBreakpointID = breakpoint.id; - } - - { - PauseReasonDeclaration reason(*this, didHitBreakpoint ? PausedForBreakpoint : m_reasonForPause); - handlePause(vmEntryGlobalObject, m_reasonForPause); } - m_pausingBreakpointID = noBreakpointID; + handlePause(m_reasonForPause, vmEntryGlobalObject); if (!m_pauseOnNextStatement && !m_pauseOnCallFrame) { setSteppingMode(SteppingModeDisabled); @@ -694,13 +652,13 @@ void Debugger::pauseIfNeeded(CallFrame* callFrame) } } -void Debugger::exception(CallFrame* callFrame, JSValue exception, bool hasCatchHandler) +void Debugger::exception(CallFrame* callFrame, JSValue exception, bool hasHandler) { if (m_isPaused) return; PauseReasonDeclaration reason(*this, PausedForException); - if (m_pauseOnExceptionsState == PauseOnAllExceptions || (m_pauseOnExceptionsState == PauseOnUncaughtExceptions && !hasCatchHandler)) { + if (m_pauseOnExceptionsState == PauseOnAllExceptions || (m_pauseOnExceptionsState == PauseOnUncaughtExceptions && !hasHandler)) { m_pauseOnNextStatement = true; setSteppingMode(SteppingModeEnabled); } @@ -743,13 +701,10 @@ void Debugger::returnEvent(CallFrame* callFrame) return; // Treat stepping over a return statement like stepping out. - if (m_currentCallFrame == m_pauseOnCallFrame) { - VMEntryFrame* topVMEntryFrame = m_vm->topVMEntryFrame; - m_pauseOnCallFrame = m_currentCallFrame->callerFrame(topVMEntryFrame); - } + if (m_currentCallFrame == m_pauseOnCallFrame) + m_pauseOnCallFrame = m_currentCallFrame->callerFrameSkippingVMEntrySentinel(); - VMEntryFrame* topVMEntryFrame = m_vm->topVMEntryFrame; - m_currentCallFrame = m_currentCallFrame->callerFrame(topVMEntryFrame); + m_currentCallFrame = m_currentCallFrame->callerFrameSkippingVMEntrySentinel(); } void Debugger::willExecuteProgram(CallFrame* callFrame) @@ -779,13 +734,11 @@ void Debugger::didExecuteProgram(CallFrame* callFrame) if (!m_currentCallFrame) return; if (m_currentCallFrame == m_pauseOnCallFrame) { - VMEntryFrame* topVMEntryFrame = m_vm->topVMEntryFrame; - m_pauseOnCallFrame = m_currentCallFrame->callerFrame(topVMEntryFrame); + m_pauseOnCallFrame = m_currentCallFrame->callerFrameSkippingVMEntrySentinel(); if (!m_currentCallFrame) return; } - VMEntryFrame* topVMEntryFrame = m_vm->topVMEntryFrame; - m_currentCallFrame = m_currentCallFrame->callerFrame(topVMEntryFrame); + m_currentCallFrame = m_currentCallFrame->callerFrameSkippingVMEntrySentinel(); } void Debugger::didReachBreakpoint(CallFrame* callFrame) @@ -793,7 +746,7 @@ void Debugger::didReachBreakpoint(CallFrame* callFrame) if (m_isPaused) return; - PauseReasonDeclaration reason(*this, PausedForDebuggerStatement); + PauseReasonDeclaration reason(*this, PausedForBreakpoint); m_pauseOnNextStatement = true; setSteppingMode(SteppingModeEnabled); updateCallFrameAndPauseIfNeeded(callFrame); diff --git a/Source/JavaScriptCore/debugger/Debugger.h b/Source/JavaScriptCore/debugger/Debugger.h index d70f3b76f..f7b734f37 100644 --- a/Source/JavaScriptCore/debugger/Debugger.h +++ b/Source/JavaScriptCore/debugger/Debugger.h @@ -29,12 +29,11 @@ #include <wtf/HashMap.h> #include <wtf/HashSet.h> #include <wtf/RefPtr.h> +#include <wtf/Vector.h> #include <wtf/text/TextPosition.h> namespace JSC { -class CodeBlock; -class Exception; class ExecState; class JSGlobalObject; class SourceProvider; @@ -61,13 +60,12 @@ public: bool needsExceptionCallbacks() const { return m_pauseOnExceptionsState != DontPauseOnExceptions; } + void attach(JSGlobalObject*); enum ReasonForDetach { TerminatingDebuggingSession, GlobalObjectIsDestructing }; - void attach(JSGlobalObject*); - void detach(JSGlobalObject*, ReasonForDetach); - bool isAttached(JSGlobalObject*); + virtual void detach(JSGlobalObject*, ReasonForDetach); BreakpointID setBreakpoint(Breakpoint, unsigned& actualLine, unsigned& actualColumn); void removeBreakpoint(BreakpointID); @@ -84,20 +82,6 @@ public: PauseOnExceptionsState pauseOnExceptionsState() const { return m_pauseOnExceptionsState; } void setPauseOnExceptionsState(PauseOnExceptionsState); - enum ReasonForPause { - NotPaused, - PausedForException, - PausedAtStatement, - PausedAfterCall, - PausedBeforeReturn, - PausedAtStartOfProgram, - PausedAtEndOfProgram, - PausedForBreakpoint, - PausedForDebuggerStatement, - }; - ReasonForPause reasonForPause() const { return m_reasonForPause; } - BreakpointID pausingBreakpointID() const { return m_pausingBreakpointID; } - void setPauseOnNextStatement(bool); void breakProgram(); void continueProgram(); @@ -105,12 +89,12 @@ public: void stepOverStatement(); void stepOutOfFunction(); - bool isPaused() const { return m_isPaused; } + bool isPaused() { return m_isPaused; } bool isStepping() const { return m_steppingMode == SteppingModeEnabled; } virtual void sourceParsed(ExecState*, SourceProvider*, int errorLineNumber, const WTF::String& errorMessage) = 0; - void exception(CallFrame*, JSValue exceptionValue, bool hasCatchHandler); + void exception(CallFrame*, JSValue exceptionValue, bool hasHandler); void atStatement(CallFrame*); void callEvent(CallFrame*); void returnEvent(CallFrame*); @@ -124,15 +108,28 @@ public: protected: virtual bool needPauseHandling(JSGlobalObject*) { return false; } - virtual void handleBreakpointHit(JSGlobalObject*, const Breakpoint&) { } - virtual void handleExceptionInBreakpointCondition(ExecState*, Exception*) const { } - virtual void handlePause(JSGlobalObject*, ReasonForPause) { } + virtual void handleBreakpointHit(const Breakpoint&) { } + virtual void handleExceptionInBreakpointCondition(ExecState*, JSValue exception) const { UNUSED_PARAM(exception); } + + enum ReasonForPause { + NotPaused, + PausedForException, + PausedAtStatement, + PausedAfterCall, + PausedBeforeReturn, + PausedAtStartOfProgram, + PausedAtEndOfProgram, + PausedForBreakpoint + }; + + virtual void handlePause(ReasonForPause, JSGlobalObject*) { } virtual void notifyDoneProcessingDebuggerEvents() { } private: typedef HashMap<BreakpointID, Breakpoint*> BreakpointIDToBreakpointMap; - typedef HashMap<unsigned, RefPtr<BreakpointsList>, WTF::IntHash<int>, WTF::UnsignedWithZeroKeyHashTraits<int>> LineToBreakpointsMap; + typedef Vector<Breakpoint> BreakpointsInLine; + typedef HashMap<unsigned, BreakpointsInLine, WTF::IntHash<int>, WTF::UnsignedWithZeroKeyHashTraits<int>> LineToBreakpointsMap; typedef HashMap<SourceID, LineToBreakpointsMap, WTF::IntHash<SourceID>, WTF::UnsignedWithZeroKeyHashTraits<SourceID>> SourceIDToBreakpointsMap; class ClearCodeBlockDebuggerRequestsFunctor; @@ -185,8 +182,6 @@ private: void clearDebuggerRequests(JSGlobalObject*); - template<typename Functor> inline void forEachCodeBlock(Functor&); - VM* m_vm; HashSet<JSGlobalObject*> m_globalObjects; @@ -196,7 +191,7 @@ private: bool m_breakpointsActivated : 1; bool m_hasHandlerForExceptionCallback : 1; bool m_isInWorkerThread : 1; - unsigned m_steppingMode : 1; // SteppingMode + SteppingMode m_steppingMode : 1; ReasonForPause m_reasonForPause; JSValue m_currentException; @@ -206,13 +201,12 @@ private: SourceID m_lastExecutedSourceID; BreakpointID m_topBreakpointID; - BreakpointID m_pausingBreakpointID; BreakpointIDToBreakpointMap m_breakpointIDToBreakpoint; SourceIDToBreakpointsMap m_sourceIDToBreakpoints; RefPtr<JSC::DebuggerCallFrame> m_currentDebuggerCallFrame; - friend class DebuggerPausedScope; + friend class DebuggerCallFrameScope; friend class TemporaryPausedState; friend class LLIntOffsetsExtractor; }; diff --git a/Source/JavaScriptCore/debugger/DebuggerActivation.cpp b/Source/JavaScriptCore/debugger/DebuggerActivation.cpp new file mode 100644 index 000000000..75b08ea81 --- /dev/null +++ b/Source/JavaScriptCore/debugger/DebuggerActivation.cpp @@ -0,0 +1,98 @@ +/* + * Copyright (C) 2008, 2009 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" +#include "DebuggerActivation.h" + +#include "JSActivation.h" +#include "Operations.h" + +namespace JSC { + +STATIC_ASSERT_IS_TRIVIALLY_DESTRUCTIBLE(DebuggerActivation); + +const ClassInfo DebuggerActivation::s_info = { "DebuggerActivation", &Base::s_info, 0, 0, CREATE_METHOD_TABLE(DebuggerActivation) }; + +DebuggerActivation::DebuggerActivation(VM& vm) + : JSNonFinalObject(vm, vm.debuggerActivationStructure.get()) +{ +} + +void DebuggerActivation::finishCreation(VM& vm, JSObject* activation) +{ + Base::finishCreation(vm); + ASSERT(activation); + ASSERT(activation->isActivationObject()); + m_activation.set(vm, this, jsCast<JSActivation*>(activation)); +} + +void DebuggerActivation::visitChildren(JSCell* cell, SlotVisitor& visitor) +{ + DebuggerActivation* thisObject = jsCast<DebuggerActivation*>(cell); + ASSERT_GC_OBJECT_INHERITS(thisObject, info()); + COMPILE_ASSERT(StructureFlags & OverridesVisitChildren, OverridesVisitChildrenWithoutSettingFlag); + ASSERT(thisObject->structure()->typeInfo().overridesVisitChildren()); + + JSObject::visitChildren(thisObject, visitor); + visitor.append(&thisObject->m_activation); +} + +String DebuggerActivation::className(const JSObject* object) +{ + const DebuggerActivation* thisObject = jsCast<const DebuggerActivation*>(object); + return thisObject->m_activation->methodTable()->className(thisObject->m_activation.get()); +} + +bool DebuggerActivation::getOwnPropertySlot(JSObject* object, ExecState* exec, PropertyName propertyName, PropertySlot& slot) +{ + DebuggerActivation* thisObject = jsCast<DebuggerActivation*>(object); + return thisObject->m_activation->methodTable()->getOwnPropertySlot(thisObject->m_activation.get(), exec, propertyName, slot); +} + +void DebuggerActivation::put(JSCell* cell, ExecState* exec, PropertyName propertyName, JSValue value, PutPropertySlot& slot) +{ + DebuggerActivation* thisObject = jsCast<DebuggerActivation*>(cell); + thisObject->m_activation->methodTable()->put(thisObject->m_activation.get(), exec, propertyName, value, slot); +} + +bool DebuggerActivation::deleteProperty(JSCell* cell, ExecState* exec, PropertyName propertyName) +{ + DebuggerActivation* thisObject = jsCast<DebuggerActivation*>(cell); + return thisObject->m_activation->methodTable()->deleteProperty(thisObject->m_activation.get(), exec, propertyName); +} + +void DebuggerActivation::getOwnPropertyNames(JSObject* object, ExecState* exec, PropertyNameArray& propertyNames, EnumerationMode mode) +{ + DebuggerActivation* thisObject = jsCast<DebuggerActivation*>(object); + thisObject->m_activation->methodTable()->getPropertyNames(thisObject->m_activation.get(), exec, propertyNames, mode); +} + +bool DebuggerActivation::defineOwnProperty(JSObject* object, ExecState* exec, PropertyName propertyName, const PropertyDescriptor& descriptor, bool shouldThrow) +{ + DebuggerActivation* thisObject = jsCast<DebuggerActivation*>(object); + return thisObject->m_activation->methodTable()->defineOwnProperty(thisObject->m_activation.get(), exec, propertyName, descriptor, shouldThrow); +} + +} // namespace JSC diff --git a/Source/JavaScriptCore/debugger/DebuggerScope.h b/Source/JavaScriptCore/debugger/DebuggerActivation.h index e1edb9248..e90383eaa 100644 --- a/Source/JavaScriptCore/debugger/DebuggerScope.h +++ b/Source/JavaScriptCore/debugger/DebuggerActivation.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2008-2009, 2014 Apple Inc. All rights reserved. + * Copyright (C) 2008, 2009 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -23,26 +23,22 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef DebuggerScope_h -#define DebuggerScope_h +#ifndef DebuggerActivation_h +#define DebuggerActivation_h #include "JSObject.h" namespace JSC { -class DebuggerCallFrame; -class JSScope; - -class DebuggerScope : public JSNonFinalObject { +class DebuggerActivation : public JSNonFinalObject { public: typedef JSNonFinalObject Base; - static const unsigned StructureFlags = Base::StructureFlags | OverridesGetOwnPropertySlot | OverridesGetPropertyNames; - static DebuggerScope* create(VM& vm, JSScope* scope) + static DebuggerActivation* create(VM& vm, JSObject* object) { - DebuggerScope* debuggerScope = new (NotNull, allocateCell<DebuggerScope>(vm.heap)) DebuggerScope(vm, scope); - debuggerScope->finishCreation(vm); - return debuggerScope; + DebuggerActivation* activation = new (NotNull, allocateCell<DebuggerActivation>(vm.heap)) DebuggerActivation(vm); + activation->finishCreation(vm, object); + return activation; } static void visitChildren(JSCell*, SlotVisitor&); @@ -55,66 +51,21 @@ public: DECLARE_EXPORT_INFO; - static Structure* createStructure(VM& vm, JSGlobalObject* globalObject) + static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue prototype) { - return Structure::create(vm, globalObject, jsNull(), TypeInfo(ObjectType, StructureFlags), info()); + return Structure::create(vm, globalObject, prototype, TypeInfo(ObjectType, StructureFlags), info()); } - class iterator { - public: - iterator(DebuggerScope* node) - : m_node(node) - { - } - - DebuggerScope* get() { return m_node; } - iterator& operator++() { m_node = m_node->next(); return *this; } - // postfix ++ intentionally omitted - - bool operator==(const iterator& other) const { return m_node == other.m_node; } - bool operator!=(const iterator& other) const { return m_node != other.m_node; } - - private: - DebuggerScope* m_node; - }; - - iterator begin(); - iterator end(); - DebuggerScope* next(); - - void invalidateChain(); - bool isValid() const { return !!m_scope; } +protected: + static const unsigned StructureFlags = OverridesGetOwnPropertySlot | OverridesVisitChildren | JSObject::StructureFlags; - bool isCatchScope() const; - bool isFunctionNameScope() const; - bool isWithScope() const; - bool isGlobalScope() const; - bool isFunctionOrEvalScope() const; - - JSValue caughtValue(ExecState*) const; + JS_EXPORT_PRIVATE void finishCreation(VM&, JSObject* activation); private: - JS_EXPORT_PRIVATE DebuggerScope(VM&, JSScope*); - JS_EXPORT_PRIVATE void finishCreation(VM&); - - JSScope* jsScope() const { return m_scope.get(); } - - WriteBarrier<JSScope> m_scope; - WriteBarrier<DebuggerScope> m_next; - - friend class DebuggerCallFrame; + JS_EXPORT_PRIVATE DebuggerActivation(VM&); + WriteBarrier<JSActivation> m_activation; }; -inline DebuggerScope::iterator DebuggerScope::begin() -{ - return iterator(this); -} - -inline DebuggerScope::iterator DebuggerScope::end() -{ - return iterator(0); -} - } // namespace JSC -#endif // DebuggerScope_h +#endif // DebuggerActivation_h diff --git a/Source/JavaScriptCore/debugger/DebuggerCallFrame.cpp b/Source/JavaScriptCore/debugger/DebuggerCallFrame.cpp index bf093e89b..90cee8c23 100644 --- a/Source/JavaScriptCore/debugger/DebuggerCallFrame.cpp +++ b/Source/JavaScriptCore/debugger/DebuggerCallFrame.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2008, 2013, 2014 Apple Inc. All rights reserved. + * Copyright (C) 2008, 2013 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -10,7 +10,7 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * 3. Neither the name of Apple Inc. ("Apple") nor the names of + * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of * its contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * @@ -29,16 +29,13 @@ #include "config.h" #include "DebuggerCallFrame.h" +#include "JSFunction.h" #include "CodeBlock.h" -#include "DebuggerEvalEnabler.h" -#include "DebuggerScope.h" #include "Interpreter.h" -#include "JSFunction.h" -#include "JSLexicalEnvironment.h" -#include "JSCInlines.h" +#include "Operations.h" #include "Parser.h" #include "StackVisitor.h" -#include "StrongInlines.h" +#include "VMEntryScope.h" namespace JSC { @@ -58,36 +55,13 @@ private: unsigned m_column; }; -class FindCallerMidStackFunctor { -public: - FindCallerMidStackFunctor(CallFrame* callFrame) - : m_callFrame(callFrame) - , m_callerFrame(nullptr) - { } - - StackVisitor::Status operator()(StackVisitor& visitor) - { - if (visitor->callFrame() == m_callFrame) { - m_callerFrame = visitor->callerFrame(); - return StackVisitor::Done; - } - return StackVisitor::Continue; - } - - CallFrame* getCallerFrame() const { return m_callerFrame; } - -private: - CallFrame* m_callFrame; - CallFrame* m_callerFrame; -}; - DebuggerCallFrame::DebuggerCallFrame(CallFrame* callFrame) : m_callFrame(callFrame) { m_position = positionForCallFrame(m_callFrame); } -RefPtr<DebuggerCallFrame> DebuggerCallFrame::callerFrame() +PassRefPtr<DebuggerCallFrame> DebuggerCallFrame::callerFrame() { ASSERT(isValid()); if (!isValid()) @@ -96,12 +70,9 @@ RefPtr<DebuggerCallFrame> DebuggerCallFrame::callerFrame() if (m_caller) return m_caller; - FindCallerMidStackFunctor functor(m_callFrame); - m_callFrame->vm().topCallFrame->iterate(functor); - - CallFrame* callerFrame = functor.getCallerFrame(); + CallFrame* callerFrame = m_callFrame->callerFrameSkippingVMEntrySentinel(); if (!callerFrame) - return nullptr; + return 0; m_caller = DebuggerCallFrame::create(callerFrame); return m_caller; @@ -128,33 +99,19 @@ String DebuggerCallFrame::functionName() const ASSERT(isValid()); if (!isValid()) return String(); - JSFunction* function = jsDynamicCast<JSFunction*>(m_callFrame->callee()); + JSObject* function = m_callFrame->callee(); if (!function) return String(); return getCalculatedDisplayName(m_callFrame, function); } -DebuggerScope* DebuggerCallFrame::scope() +JSScope* DebuggerCallFrame::scope() const { ASSERT(isValid()); if (!isValid()) return 0; - - if (!m_scope) { - VM& vm = m_callFrame->vm(); - JSScope* scope; - CodeBlock* codeBlock = m_callFrame->codeBlock(); - if (codeBlock && codeBlock->scopeRegister().isValid()) - scope = m_callFrame->scope(codeBlock->scopeRegister().offset()); - else if (JSCallee* callee = jsDynamicCast<JSCallee*>(m_callFrame->callee())) - scope = callee->scope(); - else - scope = m_callFrame->lexicalGlobalObject(); - - m_scope.set(vm, DebuggerScope::create(vm, scope)); - } - return m_scope.get(); + return m_callFrame->scope(); } DebuggerCallFrame::Type DebuggerCallFrame::type() const @@ -163,7 +120,7 @@ DebuggerCallFrame::Type DebuggerCallFrame::type() const if (!isValid()) return ProgramType; - if (jsDynamicCast<JSFunction*>(m_callFrame->callee())) + if (m_callFrame->callee()) return FunctionType; return ProgramType; @@ -176,10 +133,14 @@ JSValue DebuggerCallFrame::thisValue() const } // Evaluate some JavaScript code in the scope of this frame. -JSValue DebuggerCallFrame::evaluate(const String& script, NakedPtr<Exception>& exception) +JSValue DebuggerCallFrame::evaluate(const String& script, JSValue& exception) const { ASSERT(isValid()); - CallFrame* callFrame = m_callFrame; + return evaluateWithCallFrame(m_callFrame, script, exception); +} + +JSValue DebuggerCallFrame::evaluateWithCallFrame(CallFrame* callFrame, const String& script, JSValue& exception) +{ if (!callFrame) return jsNull(); @@ -188,15 +149,8 @@ JSValue DebuggerCallFrame::evaluate(const String& script, NakedPtr<Exception>& e if (!callFrame->codeBlock()) return JSValue(); - DebuggerEvalEnabler evalEnabler(callFrame); VM& vm = callFrame->vm(); - auto& codeBlock = *callFrame->codeBlock(); - ThisTDZMode thisTDZMode = codeBlock.unlinkedCodeBlock()->constructorKind() == ConstructorKind::Derived ? ThisTDZMode::AlwaysCheck : ThisTDZMode::CheckIfNeeded; - - VariableEnvironment variablesUnderTDZ; - JSScope::collectVariablesUnderTDZ(scope()->jsScope(), variablesUnderTDZ); - - EvalExecutable* eval = EvalExecutable::create(callFrame, makeSource(script), codeBlock.isStrictMode(), thisTDZMode, &variablesUnderTDZ); + EvalExecutable* eval = EvalExecutable::create(callFrame, makeSource(script), callFrame->codeBlock()->isStrictMode()); if (vm.exception()) { exception = vm.exception(); vm.clearException(); @@ -204,7 +158,7 @@ JSValue DebuggerCallFrame::evaluate(const String& script, NakedPtr<Exception>& e } JSValue thisValue = thisValueForCallFrame(callFrame); - JSValue result = vm.interpreter->execute(eval, callFrame, thisValue, scope()->jsScope()); + JSValue result = vm.interpreter->execute(eval, callFrame, thisValue, callFrame->scope()); if (vm.exception()) { exception = vm.exception(); vm.clearException(); @@ -215,13 +169,10 @@ JSValue DebuggerCallFrame::evaluate(const String& script, NakedPtr<Exception>& e void DebuggerCallFrame::invalidate() { - RefPtr<DebuggerCallFrame> frame = this; + m_callFrame = nullptr; + RefPtr<DebuggerCallFrame> frame = m_caller.release(); while (frame) { frame->m_callFrame = nullptr; - if (frame->m_scope) { - frame->m_scope->invalidateChain(); - frame->m_scope.clear(); - } frame = frame->m_caller.release(); } } diff --git a/Source/JavaScriptCore/debugger/DebuggerCallFrame.h b/Source/JavaScriptCore/debugger/DebuggerCallFrame.h index aa3cca52b..09c3fb9d8 100644 --- a/Source/JavaScriptCore/debugger/DebuggerCallFrame.h +++ b/Source/JavaScriptCore/debugger/DebuggerCallFrame.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2008, 2013, 2014 Apple Inc. All rights reserved. + * Copyright (C) 2008, 2013 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -10,7 +10,7 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * 3. Neither the name of Apple Inc. ("Apple") nor the names of + * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of * its contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * @@ -29,32 +29,26 @@ #ifndef DebuggerCallFrame_h #define DebuggerCallFrame_h +#include "CallFrame.h" #include "DebuggerPrimitives.h" -#include "Strong.h" -#include <wtf/NakedPtr.h> #include <wtf/PassRefPtr.h> #include <wtf/RefCounted.h> #include <wtf/text/TextPosition.h> namespace JSC { -class DebuggerScope; -class Exception; -class ExecState; -typedef ExecState CallFrame; - class DebuggerCallFrame : public RefCounted<DebuggerCallFrame> { public: enum Type { ProgramType, FunctionType }; - static Ref<DebuggerCallFrame> create(CallFrame* callFrame) + static PassRefPtr<DebuggerCallFrame> create(CallFrame* callFrame) { - return adoptRef(*new DebuggerCallFrame(callFrame)); + return adoptRef(new DebuggerCallFrame(callFrame)); } JS_EXPORT_PRIVATE explicit DebuggerCallFrame(CallFrame*); - JS_EXPORT_PRIVATE RefPtr<DebuggerCallFrame> callerFrame(); + JS_EXPORT_PRIVATE PassRefPtr<DebuggerCallFrame> callerFrame(); ExecState* exec() const { return m_callFrame; } JS_EXPORT_PRIVATE SourceID sourceID() const; @@ -64,11 +58,11 @@ public: JS_EXPORT_PRIVATE const TextPosition& position() const { return m_position; } JS_EXPORT_PRIVATE JSGlobalObject* vmEntryGlobalObject() const; - JS_EXPORT_PRIVATE DebuggerScope* scope(); + JS_EXPORT_PRIVATE JSScope* scope() const; JS_EXPORT_PRIVATE String functionName() const; JS_EXPORT_PRIVATE Type type() const; JS_EXPORT_PRIVATE JSValue thisValue() const; - JSValue evaluate(const String&, NakedPtr<Exception>&); + JS_EXPORT_PRIVATE JSValue evaluate(const String&, JSValue& exception) const; bool isValid() const { return !!m_callFrame; } JS_EXPORT_PRIVATE void invalidate(); @@ -76,6 +70,7 @@ public: // The following are only public for the Debugger's use only. They will be // made private soon. Other clients should not use these. + JS_EXPORT_PRIVATE static JSValue evaluateWithCallFrame(CallFrame*, const String& script, JSValue& exception); JS_EXPORT_PRIVATE static TextPosition positionForCallFrame(CallFrame*); JS_EXPORT_PRIVATE static SourceID sourceIDForCallFrame(CallFrame*); static JSValue thisValueForCallFrame(CallFrame*); @@ -84,9 +79,6 @@ private: CallFrame* m_callFrame; RefPtr<DebuggerCallFrame> m_caller; TextPosition m_position; - // The DebuggerPausedScope is responsible for calling invalidate() which, - // in turn, will clear this strong ref. - Strong<DebuggerScope> m_scope; }; } // namespace JSC diff --git a/Source/JavaScriptCore/debugger/DebuggerEvalEnabler.h b/Source/JavaScriptCore/debugger/DebuggerEvalEnabler.h deleted file mode 100644 index bb75b1f15..000000000 --- a/Source/JavaScriptCore/debugger/DebuggerEvalEnabler.h +++ /dev/null @@ -1,63 +0,0 @@ -/* - * Copyright (C) 2014 Apple Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY - * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef DebuggerEvalEnabler_h -#define DebuggerEvalEnabler_h - -#include "CallFrame.h" -#include "JSGlobalObject.h" - -namespace JSC { - -class DebuggerEvalEnabler { -public: - explicit DebuggerEvalEnabler(const ExecState* exec) - : m_exec(exec) - , m_evalWasDisabled(false) - { - if (exec) { - JSGlobalObject* globalObject = exec->lexicalGlobalObject(); - m_evalWasDisabled = !globalObject->evalEnabled(); - if (m_evalWasDisabled) - globalObject->setEvalEnabled(true, globalObject->evalDisabledErrorMessage()); - } - } - - ~DebuggerEvalEnabler() - { - if (m_evalWasDisabled) { - JSGlobalObject* globalObject = m_exec->lexicalGlobalObject(); - globalObject->setEvalEnabled(false, globalObject->evalDisabledErrorMessage()); - } - } - -private: - const ExecState* m_exec; - bool m_evalWasDisabled; -}; - -} // namespace JSC - -#endif // DebuggerEvalEnabler_h diff --git a/Source/JavaScriptCore/debugger/DebuggerPrimitives.h b/Source/JavaScriptCore/debugger/DebuggerPrimitives.h index ab7301b5c..635a5bfe8 100644 --- a/Source/JavaScriptCore/debugger/DebuggerPrimitives.h +++ b/Source/JavaScriptCore/debugger/DebuggerPrimitives.h @@ -26,8 +26,6 @@ #ifndef DebuggerPrimitives_h #define DebuggerPrimitives_h -#include <stddef.h> - namespace JSC { typedef size_t SourceID; diff --git a/Source/JavaScriptCore/debugger/DebuggerScope.cpp b/Source/JavaScriptCore/debugger/DebuggerScope.cpp deleted file mode 100644 index c6eba4e93..000000000 --- a/Source/JavaScriptCore/debugger/DebuggerScope.cpp +++ /dev/null @@ -1,208 +0,0 @@ -/* - * Copyright (C) 2008-2009, 2014 Apple Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY - * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "config.h" -#include "DebuggerScope.h" - -#include "JSLexicalEnvironment.h" -#include "JSCInlines.h" -#include "JSWithScope.h" - -namespace JSC { - -STATIC_ASSERT_IS_TRIVIALLY_DESTRUCTIBLE(DebuggerScope); - -const ClassInfo DebuggerScope::s_info = { "DebuggerScope", &Base::s_info, 0, CREATE_METHOD_TABLE(DebuggerScope) }; - -DebuggerScope::DebuggerScope(VM& vm, JSScope* scope) - : JSNonFinalObject(vm, scope->globalObject()->debuggerScopeStructure()) -{ - ASSERT(scope); - m_scope.set(vm, this, scope); -} - -void DebuggerScope::finishCreation(VM& vm) -{ - Base::finishCreation(vm); -} - -void DebuggerScope::visitChildren(JSCell* cell, SlotVisitor& visitor) -{ - DebuggerScope* thisObject = jsCast<DebuggerScope*>(cell); - ASSERT_GC_OBJECT_INHERITS(thisObject, info()); - JSObject::visitChildren(thisObject, visitor); - visitor.append(&thisObject->m_scope); - visitor.append(&thisObject->m_next); -} - -String DebuggerScope::className(const JSObject* object) -{ - const DebuggerScope* scope = jsCast<const DebuggerScope*>(object); - ASSERT(scope->isValid()); - if (!scope->isValid()) - return String(); - JSObject* thisObject = JSScope::objectAtScope(scope->jsScope()); - return thisObject->methodTable()->className(thisObject); -} - -bool DebuggerScope::getOwnPropertySlot(JSObject* object, ExecState* exec, PropertyName propertyName, PropertySlot& slot) -{ - DebuggerScope* scope = jsCast<DebuggerScope*>(object); - ASSERT(scope->isValid()); - if (!scope->isValid()) - return false; - JSObject* thisObject = JSScope::objectAtScope(scope->jsScope()); - slot.setThisValue(JSValue(thisObject)); - - // By default, JSObject::getPropertySlot() will look in the DebuggerScope's prototype - // chain and not the wrapped scope, and JSObject::getPropertySlot() cannot be overridden - // to behave differently for the DebuggerScope. - // - // Instead, we'll treat all properties in the wrapped scope and its prototype chain as - // the own properties of the DebuggerScope. This is fine because the WebInspector - // does not presently need to distinguish between what's owned at each level in the - // prototype chain. Hence, we'll invoke getPropertySlot() on the wrapped scope here - // instead of getOwnPropertySlot(). - bool result = thisObject->getPropertySlot(exec, propertyName, slot); - if (result && slot.isValue() && slot.getValue(exec, propertyName) == jsTDZValue()) { - // FIXME: - // We hit a scope property that has the TDZ empty value. - // Currently, we just lie to the inspector and claim that this property is undefined. - // This is not ideal and we should fix it. - // https://bugs.webkit.org/show_bug.cgi?id=144977 - slot.setValue(slot.slotBase(), DontEnum, jsUndefined()); - return true; - } - return result; -} - -void DebuggerScope::put(JSCell* cell, ExecState* exec, PropertyName propertyName, JSValue value, PutPropertySlot& slot) -{ - DebuggerScope* scope = jsCast<DebuggerScope*>(cell); - ASSERT(scope->isValid()); - if (!scope->isValid()) - return; - JSObject* thisObject = JSScope::objectAtScope(scope->jsScope()); - slot.setThisValue(JSValue(thisObject)); - thisObject->methodTable()->put(thisObject, exec, propertyName, value, slot); -} - -bool DebuggerScope::deleteProperty(JSCell* cell, ExecState* exec, PropertyName propertyName) -{ - DebuggerScope* scope = jsCast<DebuggerScope*>(cell); - ASSERT(scope->isValid()); - if (!scope->isValid()) - return false; - JSObject* thisObject = JSScope::objectAtScope(scope->jsScope()); - return thisObject->methodTable()->deleteProperty(thisObject, exec, propertyName); -} - -void DebuggerScope::getOwnPropertyNames(JSObject* object, ExecState* exec, PropertyNameArray& propertyNames, EnumerationMode mode) -{ - DebuggerScope* scope = jsCast<DebuggerScope*>(object); - ASSERT(scope->isValid()); - if (!scope->isValid()) - return; - JSObject* thisObject = JSScope::objectAtScope(scope->jsScope()); - thisObject->methodTable()->getPropertyNames(thisObject, exec, propertyNames, mode); -} - -bool DebuggerScope::defineOwnProperty(JSObject* object, ExecState* exec, PropertyName propertyName, const PropertyDescriptor& descriptor, bool shouldThrow) -{ - DebuggerScope* scope = jsCast<DebuggerScope*>(object); - ASSERT(scope->isValid()); - if (!scope->isValid()) - return false; - JSObject* thisObject = JSScope::objectAtScope(scope->jsScope()); - return thisObject->methodTable()->defineOwnProperty(thisObject, exec, propertyName, descriptor, shouldThrow); -} - -DebuggerScope* DebuggerScope::next() -{ - ASSERT(isValid()); - if (!m_next && m_scope->next()) { - VM& vm = *m_scope->vm(); - DebuggerScope* nextScope = create(vm, m_scope->next()); - m_next.set(vm, this, nextScope); - } - return m_next.get(); -} - -void DebuggerScope::invalidateChain() -{ - if (!isValid()) - return; - - DebuggerScope* scope = this; - while (scope) { - DebuggerScope* nextScope = scope->m_next.get(); - scope->m_next.clear(); - scope->m_scope.clear(); // This also marks this scope as invalid. - scope = nextScope; - } -} - -bool DebuggerScope::isCatchScope() const -{ - return m_scope->isCatchScope(); -} - -bool DebuggerScope::isFunctionNameScope() const -{ - return m_scope->isFunctionNameScopeObject(); -} - -bool DebuggerScope::isWithScope() const -{ - return m_scope->isWithScope(); -} - -bool DebuggerScope::isGlobalScope() const -{ - return m_scope->isGlobalObject(); -} - -bool DebuggerScope::isFunctionOrEvalScope() const -{ - // In the current debugger implementation, every function or eval will create an - // lexical environment object. Hence, a lexical environment object implies a - // function or eval scope. - return m_scope->isActivationObject() && !isCatchScope(); -} - -JSValue DebuggerScope::caughtValue(ExecState* exec) const -{ - ASSERT(isCatchScope()); - JSLexicalEnvironment* catchEnvironment = jsCast<JSLexicalEnvironment*>(m_scope.get()); - SymbolTable* catchSymbolTable = catchEnvironment->symbolTable(); - RELEASE_ASSERT(catchSymbolTable->size() == 1); - PropertyName errorName(catchSymbolTable->begin(catchSymbolTable->m_lock)->key.get()); - PropertySlot slot(m_scope.get()); - bool success = catchEnvironment->getOwnPropertySlot(catchEnvironment, exec, errorName, slot); - RELEASE_ASSERT(success && slot.isValue()); - return slot.getValue(exec, errorName); -} - -} // namespace JSC |
