X-Git-Url: https://git.saurik.com/apple/javascriptcore.git/blobdiff_plain/4e4e5a6f2694187498445a6ac6f1634ce8141119..8b637bb680022adfddad653280734877951535a9:/debugger/Debugger.cpp diff --git a/debugger/Debugger.cpp b/debugger/Debugger.cpp index cbcbd21..0f0b31d 100644 --- a/debugger/Debugger.cpp +++ b/debugger/Debugger.cpp @@ -22,14 +22,84 @@ #include "config.h" #include "Debugger.h" -#include "CollectorHeapIterator.h" #include "Error.h" #include "Interpreter.h" #include "JSFunction.h" #include "JSGlobalObject.h" +#include "Operations.h" #include "Parser.h" #include "Protect.h" +namespace { + +using namespace JSC; + +class Recompiler : public MarkedBlock::VoidFunctor { +public: +#if PLATFORM(IOS) + Recompiler(JSC::Debugger*); +#else + Recompiler(Debugger*); +#endif + ~Recompiler(); + void operator()(JSCell*); + +private: + typedef HashSet FunctionExecutableSet; + typedef HashMap SourceProviderMap; + +#if PLATFORM(IOS) + JSC::Debugger* m_debugger; +#else + Debugger* m_debugger; +#endif + FunctionExecutableSet m_functionExecutables; + SourceProviderMap m_sourceProviders; +}; + +#if PLATFORM(IOS) +inline Recompiler::Recompiler(JSC::Debugger* debugger) +#else +inline Recompiler::Recompiler(Debugger* debugger) +#endif + : 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->value, iter->key, -1, String()); +} + +inline void Recompiler::operator()(JSCell* cell) +{ + if (!cell->inherits(&JSFunction::s_info)) + return; + + JSFunction* function = jsCast(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).isNewEntry) + return; + + ExecState* exec = function->scope()->globalObject()->JSGlobalObject::globalExec(); + executable->clearCodeIfNotCompiling(); + executable->clearUnlinkedCodeForRecompilationIfNotCompiling(); + if (m_debugger == function->scope()->globalObject()->debugger()) + m_sourceProviders.add(executable->source().provider(), exec); +} + +} // namespace + namespace JSC { Debugger::~Debugger() @@ -53,60 +123,37 @@ void Debugger::detach(JSGlobalObject* globalObject) globalObject->setDebugger(0); } -void Debugger::recompileAllJSFunctions(JSGlobalData* globalData) +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. - ASSERT(!globalData->dynamicGlobalObject); - if (globalData->dynamicGlobalObject) + ASSERT(!vm->dynamicGlobalObject); + if (vm->dynamicGlobalObject) return; - typedef HashSet FunctionExecutableSet; - typedef HashMap SourceProviderMap; - - FunctionExecutableSet functionExecutables; - SourceProviderMap sourceProviders; - - LiveObjectIterator it = globalData->heap.primaryHeapBegin(); - LiveObjectIterator heapEnd = globalData->heap.primaryHeapEnd(); - for ( ; it != heapEnd; ++it) { - if (!(*it)->inherits(&JSFunction::info)) - continue; - - JSFunction* function = asFunction(*it); - if (function->executable()->isHostFunction()) - continue; - - 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 (!functionExecutables.add(executable).second) - continue; - - ExecState* exec = function->scope().globalObject()->JSGlobalObject::globalExec(); - executable->recompile(exec); - if (function->scope().globalObject()->debugger() == this) - sourceProviders.add(executable->source().provider(), exec); - } - - // Call sourceParsed() after reparsing all functions because it will execute - // JavaScript in the inspector. - SourceProviderMap::const_iterator end = sourceProviders.end(); - for (SourceProviderMap::const_iterator iter = sourceProviders.begin(); iter != end; ++iter) - sourceParsed(iter->second, SourceCode(iter->first), -1, UString()); + Recompiler recompiler(this); + vm->heap.objectSpace().forEachLiveCell(recompiler); } -JSValue evaluateInGlobalCallFrame(const UString& script, JSValue& exception, JSGlobalObject* globalObject) +JSValue evaluateInGlobalCallFrame(const String& script, JSValue& exception, JSGlobalObject* globalObject) { CallFrame* globalCallFrame = globalObject->globalExec(); + VM& vm = globalObject->vm(); - RefPtr eval = EvalExecutable::create(globalCallFrame, makeSource(script)); - JSObject* error = eval->compile(globalCallFrame, globalCallFrame->scopeChain()); - if (error) - return error; + EvalExecutable* eval = EvalExecutable::create(globalCallFrame, vm.codeCache(), makeSource(script), false); + if (!eval) { + exception = vm.exception; + vm.exception = JSValue(); + return exception; + } - return globalObject->globalData()->interpreter->execute(eval.get(), globalCallFrame, globalObject, globalCallFrame->scopeChain(), &exception); + JSValue result = vm.interpreter->execute(eval, globalCallFrame, globalObject, globalCallFrame->scope()); + if (vm.exception) { + exception = vm.exception; + vm.exception = JSValue(); + } + ASSERT(result); + return result; } } // namespace JSC