X-Git-Url: https://git.saurik.com/apple/javascriptcore.git/blobdiff_plain/93a3786624b2768d89bfa27e46598dc64e2fb70a..81345200c95645a1b0d2635520f96ad55dfde63f:/debugger/DebuggerCallFrame.cpp?ds=sidebyside diff --git a/debugger/DebuggerCallFrame.cpp b/debugger/DebuggerCallFrame.cpp index a5d045c..83fb67f 100644 --- a/debugger/DebuggerCallFrame.cpp +++ b/debugger/DebuggerCallFrame.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2008 Apple Inc. All rights reserved. + * Copyright (C) 2008, 2013, 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 @@ -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 Computer, Inc. ("Apple") nor the names of + * 3. Neither the name of Apple 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,81 +29,188 @@ #include "config.h" #include "DebuggerCallFrame.h" -#include "JSFunction.h" #include "CodeBlock.h" #include "Interpreter.h" -#include "Operations.h" +#include "JSActivation.h" +#include "JSFunction.h" +#include "JSCInlines.h" #include "Parser.h" +#include "StackVisitor.h" namespace JSC { -String DebuggerCallFrame::functionName() const +class LineAndColumnFunctor { +public: + StackVisitor::Status operator()(StackVisitor& visitor) + { + visitor->computeLineAndColumn(m_line, m_column); + return StackVisitor::Done; + } + + unsigned line() const { return m_line; } + unsigned column() const { return m_column; } + +private: + unsigned m_line; + unsigned m_column; +}; + +DebuggerCallFrame::DebuggerCallFrame(CallFrame* callFrame) + : m_callFrame(callFrame) { - if (!m_callFrame->codeBlock()) - return String(); + m_position = positionForCallFrame(m_callFrame); +} - if (!m_callFrame->callee()) - return String(); +PassRefPtr DebuggerCallFrame::callerFrame() +{ + ASSERT(isValid()); + if (!isValid()) + return 0; - JSObject* function = m_callFrame->callee(); - if (!function || !function->inherits(&JSFunction::s_info)) - return String(); - return jsCast(function)->name(m_callFrame); + if (m_caller) + return m_caller; + + CallFrame* callerFrame = m_callFrame->callerFrameSkippingVMEntrySentinel(); + if (!callerFrame) + return 0; + + m_caller = DebuggerCallFrame::create(callerFrame); + return m_caller; } - -String DebuggerCallFrame::calculatedFunctionName() const + +JSC::JSGlobalObject* DebuggerCallFrame::vmEntryGlobalObject() const { - if (!m_callFrame->codeBlock()) - return String(); + ASSERT(isValid()); + if (!isValid()) + return 0; + return m_callFrame->vmEntryGlobalObject(); +} - JSObject* function = m_callFrame->callee(); +SourceID DebuggerCallFrame::sourceID() const +{ + ASSERT(isValid()); + if (!isValid()) + return noSourceID; + return sourceIDForCallFrame(m_callFrame); +} +String DebuggerCallFrame::functionName() const +{ + ASSERT(isValid()); + if (!isValid()) + return String(); + JSObject* function = m_callFrame->callee(); if (!function) return String(); return getCalculatedDisplayName(m_callFrame, function); } +JSScope* DebuggerCallFrame::scope() const +{ + ASSERT(isValid()); + if (!isValid()) + return 0; + + CodeBlock* codeBlock = m_callFrame->codeBlock(); + if (codeBlock && codeBlock->needsActivation() && !m_callFrame->hasActivation()) { + JSActivation* activation = JSActivation::create(*codeBlock->vm(), m_callFrame, codeBlock); + m_callFrame->setActivation(activation); + m_callFrame->setScope(activation); + } + + return m_callFrame->scope(); +} + DebuggerCallFrame::Type DebuggerCallFrame::type() const { + ASSERT(isValid()); + if (!isValid()) + return ProgramType; + if (m_callFrame->callee()) return FunctionType; return ProgramType; } -JSObject* DebuggerCallFrame::thisObject() const +JSValue DebuggerCallFrame::thisValue() const { - CodeBlock* codeBlock = m_callFrame->codeBlock(); - if (!codeBlock) - return 0; - - JSValue thisValue = m_callFrame->uncheckedR(codeBlock->thisRegister()).jsValue(); - if (!thisValue.isObject()) - return 0; - - return asObject(thisValue); + ASSERT(isValid()); + return thisValueForCallFrame(m_callFrame); } -JSValue DebuggerCallFrame::evaluate(const String& script, JSValue& exception) const +// Evaluate some JavaScript code in the scope of this frame. +JSValue DebuggerCallFrame::evaluate(const String& script, JSValue& exception) { - if (!m_callFrame->codeBlock()) + ASSERT(isValid()); + CallFrame* callFrame = m_callFrame; + if (!callFrame) + return jsNull(); + + JSLockHolder lock(callFrame); + + if (!callFrame->codeBlock()) return JSValue(); - VM& vm = m_callFrame->vm(); - EvalExecutable* eval = EvalExecutable::create(m_callFrame, m_callFrame->codeBlock()->unlinkedCodeBlock()->codeCacheForEval(), makeSource(script), m_callFrame->codeBlock()->isStrictMode()); - if (vm.exception) { - exception = vm.exception; - vm.exception = JSValue(); + VM& vm = callFrame->vm(); + EvalExecutable* eval = EvalExecutable::create(callFrame, makeSource(script), callFrame->codeBlock()->isStrictMode()); + if (vm.exception()) { + exception = vm.exception(); + vm.clearException(); + return jsUndefined(); } - JSValue result = vm.interpreter->execute(eval, m_callFrame, thisObject(), m_callFrame->scope()); - if (vm.exception) { - exception = vm.exception; - vm.exception = JSValue(); + JSValue thisValue = thisValueForCallFrame(callFrame); + JSValue result = vm.interpreter->execute(eval, callFrame, thisValue, scope()); + if (vm.exception()) { + exception = vm.exception(); + vm.clearException(); } ASSERT(result); return result; } +void DebuggerCallFrame::invalidate() +{ + m_callFrame = nullptr; + RefPtr frame = m_caller.release(); + while (frame) { + frame->m_callFrame = nullptr; + frame = frame->m_caller.release(); + } +} + +TextPosition DebuggerCallFrame::positionForCallFrame(CallFrame* callFrame) +{ + if (!callFrame) + return TextPosition(); + + LineAndColumnFunctor functor; + callFrame->iterate(functor); + return TextPosition(OrdinalNumber::fromOneBasedInt(functor.line()), OrdinalNumber::fromOneBasedInt(functor.column())); +} + +SourceID DebuggerCallFrame::sourceIDForCallFrame(CallFrame* callFrame) +{ + ASSERT(callFrame); + CodeBlock* codeBlock = callFrame->codeBlock(); + if (!codeBlock) + return noSourceID; + return codeBlock->ownerExecutable()->sourceID(); +} + +JSValue DebuggerCallFrame::thisValueForCallFrame(CallFrame* callFrame) +{ + if (!callFrame) + return jsNull(); + + ECMAMode ecmaMode = NotStrictMode; + CodeBlock* codeBlock = callFrame->codeBlock(); + if (codeBlock && codeBlock->isStrictMode()) + ecmaMode = StrictMode; + JSValue thisValue = callFrame->thisValue().toThis(callFrame, ecmaMode); + return thisValue; +} + } // namespace JSC