X-Git-Url: https://git.saurik.com/apple/javascriptcore.git/blobdiff_plain/ba379fdc102753d6be2c4d937058fe40257329fe..14957cd040308e3eeec43d26bae5d76da13fcd85:/debugger/Debugger.cpp?ds=sidebyside diff --git a/debugger/Debugger.cpp b/debugger/Debugger.cpp index 7d791e7..64f6002 100644 --- a/debugger/Debugger.cpp +++ b/debugger/Debugger.cpp @@ -22,16 +22,72 @@ #include "config.h" #include "Debugger.h" -#include "JSGlobalObject.h" +#include "Error.h" #include "Interpreter.h" +#include "JSFunction.h" +#include "JSGlobalObject.h" #include "Parser.h" +#include "Protect.h" -namespace JSC { +namespace { + +using namespace JSC; + +class Recompiler { +public: + Recompiler(Debugger*); + ~Recompiler(); + void operator()(JSCell*); + +private: + typedef HashSet FunctionExecutableSet; + typedef HashMap SourceProviderMap; + + Debugger* m_debugger; + FunctionExecutableSet m_functionExecutables; + SourceProviderMap m_sourceProviders; +}; -Debugger::Debugger() +inline Recompiler::Recompiler(Debugger* debugger) + : m_debugger(debugger) { } +inline Recompiler::~Recompiler() +{ + // Call sourceParsed() after reparsing all functions because it will execute + // JavaScript in the inspector. + SourceProviderMap::const_iterator end = m_sourceProviders.end(); + for (SourceProviderMap::const_iterator iter = m_sourceProviders.begin(); iter != end; ++iter) + m_debugger->sourceParsed(iter->second, iter->first, -1, UString()); +} + +inline void Recompiler::operator()(JSCell* cell) +{ + if (!cell->inherits(&JSFunction::s_info)) + return; + + JSFunction* function = asFunction(cell); + if (function->executable()->isHostFunction()) + return; + + FunctionExecutable* executable = function->jsExecutable(); + + // Check if the function is already in the set - if so, + // we've already retranslated it, nothing to do here. + if (!m_functionExecutables.add(executable).second) + return; + + ExecState* exec = function->scope()->globalObject->JSGlobalObject::globalExec(); + executable->discardCode(); + if (m_debugger == function->scope()->globalObject->debugger()) + m_sourceProviders.add(executable->source().provider(), exec); +} + +} // namespace + +namespace JSC { + Debugger::~Debugger() { HashSet::iterator end = m_globalObjects.end(); @@ -53,18 +109,37 @@ void Debugger::detach(JSGlobalObject* globalObject) globalObject->setDebugger(0); } +void Debugger::recompileAllJSFunctions(JSGlobalData* globalData) +{ + // If JavaScript is running, it's not safe to recompile, since we'll end + // up throwing away code that is live on the stack. + ASSERT(!globalData->dynamicGlobalObject); + if (globalData->dynamicGlobalObject) + return; + + Recompiler recompiler(this); + globalData->heap.forEach(recompiler); +} + JSValue evaluateInGlobalCallFrame(const UString& script, JSValue& exception, JSGlobalObject* globalObject) { CallFrame* globalCallFrame = globalObject->globalExec(); + JSGlobalData& globalData = globalObject->globalData(); - int errLine; - UString errMsg; - SourceCode source = makeSource(script); - RefPtr evalNode = globalObject->globalData()->parser->parse(globalCallFrame, globalObject->debugger(), source, &errLine, &errMsg); - if (!evalNode) - return Error::create(globalCallFrame, SyntaxError, errMsg, errLine, source.provider()->asID(), source.provider()->url()); + EvalExecutable* eval = EvalExecutable::create(globalCallFrame, makeSource(script), false); + if (!eval) { + exception = globalData.exception; + globalData.exception = JSValue(); + return exception; + } - return globalObject->globalData()->interpreter->execute(evalNode.get(), globalCallFrame, globalObject, globalCallFrame->scopeChain(), &exception); + JSValue result = globalData.interpreter->execute(eval, globalCallFrame, globalObject, globalCallFrame->scopeChain()); + if (globalData.exception) { + exception = globalData.exception; + globalData.exception = JSValue(); + } + ASSERT(result); + return result; } } // namespace JSC