1/* 2 * Copyright (C) 2008 Apple Inc. All rights reserved. 3 * Copyright (C) 1999-2001 Harri Porten (porten@kde.org) 4 * Copyright (C) 2001 Peter Kelly (pmk@post.com) 5 * 6 * This library is free software; you can redistribute it and/or 7 * modify it under the terms of the GNU Lesser General Public 8 * License as published by the Free Software Foundation; either 9 * version 2 of the License, or (at your option) any later version. 10 * 11 * This library is distributed in the hope that it will be useful, 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 * Lesser General Public License for more details. 15 * 16 * You should have received a copy of the GNU Lesser General Public 17 * License along with this library; if not, write to the Free Software 18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 19 * 20 */ 21 22#include "config.h" 23#include "Debugger.h" 24 25#include "Error.h" 26#include "Interpreter.h" 27#include "JSFunction.h" 28#include "JSGlobalObject.h" 29#include "Operations.h" 30#include "Parser.h" 31#include "Protect.h" 32 33namespace { 34 35using namespace JSC; 36 37class Recompiler : public MarkedBlock::VoidFunctor { 38public: 39 Recompiler(Debugger*); 40 ~Recompiler(); 41 void operator()(JSCell*); 42 43private: 44 typedef HashSet<FunctionExecutable*> FunctionExecutableSet; 45 typedef HashMap<SourceProvider*, ExecState*> SourceProviderMap; 46 47 Debugger* m_debugger; 48 FunctionExecutableSet m_functionExecutables; 49 SourceProviderMap m_sourceProviders; 50}; 51 52inline Recompiler::Recompiler(Debugger* debugger) 53 : m_debugger(debugger) 54{ 55} 56 57inline Recompiler::~Recompiler() 58{ 59 // Call sourceParsed() after reparsing all functions because it will execute 60 // JavaScript in the inspector. 61 SourceProviderMap::const_iterator end = m_sourceProviders.end(); 62 for (SourceProviderMap::const_iterator iter = m_sourceProviders.begin(); iter != end; ++iter) 63 m_debugger->sourceParsed(iter->value, iter->key, -1, String()); 64} 65 66inline void Recompiler::operator()(JSCell* cell) 67{ 68 if (!cell->inherits(&JSFunction::s_info)) 69 return; 70 71 JSFunction* function = jsCast<JSFunction*>(cell); 72 if (function->executable()->isHostFunction()) 73 return; 74 75 FunctionExecutable* executable = function->jsExecutable(); 76 77 // Check if the function is already in the set - if so, 78 // we've already retranslated it, nothing to do here. 79 if (!m_functionExecutables.add(executable).isNewEntry) 80 return; 81 82 ExecState* exec = function->scope()->globalObject()->JSGlobalObject::globalExec(); 83 executable->clearCodeIfNotCompiling(); 84 executable->clearUnlinkedCodeForRecompilationIfNotCompiling(); 85 if (m_debugger == function->scope()->globalObject()->debugger()) 86 m_sourceProviders.add(executable->source().provider(), exec); 87} 88 89} // namespace 90 91namespace JSC { 92 93Debugger::~Debugger() 94{ 95 HashSet<JSGlobalObject*>::iterator end = m_globalObjects.end(); 96 for (HashSet<JSGlobalObject*>::iterator it = m_globalObjects.begin(); it != end; ++it) 97 (*it)->setDebugger(0); 98} 99 100void Debugger::attach(JSGlobalObject* globalObject) 101{ 102 ASSERT(!globalObject->debugger()); 103 globalObject->setDebugger(this); 104 m_globalObjects.add(globalObject); 105} 106 107void Debugger::detach(JSGlobalObject* globalObject) 108{ 109 ASSERT(m_globalObjects.contains(globalObject)); 110 m_globalObjects.remove(globalObject); 111 globalObject->setDebugger(0); 112} 113 114void Debugger::recompileAllJSFunctions(VM* vm) 115{ 116 // If JavaScript is running, it's not safe to recompile, since we'll end 117 // up throwing away code that is live on the stack. 118 ASSERT(!vm->dynamicGlobalObject); 119 if (vm->dynamicGlobalObject) 120 return; 121 122 Recompiler recompiler(this); 123 vm->heap.objectSpace().forEachLiveCell(recompiler); 124} 125 126JSValue evaluateInGlobalCallFrame(const String& script, JSValue& exception, JSGlobalObject* globalObject) 127{ 128 CallFrame* globalCallFrame = globalObject->globalExec(); 129 VM& vm = globalObject->vm(); 130 131 EvalExecutable* eval = EvalExecutable::create(globalCallFrame, vm.codeCache(), makeSource(script), false); 132 if (!eval) { 133 exception = vm.exception; 134 vm.exception = JSValue(); 135 return exception; 136 } 137 138 JSValue result = vm.interpreter->execute(eval, globalCallFrame, globalObject, globalCallFrame->scope()); 139 if (vm.exception) { 140 exception = vm.exception; 141 vm.exception = JSValue(); 142 } 143 ASSERT(result); 144 return result; 145} 146 147} // namespace JSC 148