Home | History | Annotate | Download | only in debugger
      1 /*
      2  *  Copyright (C) 2008 Apple Inc. All rights reserved.
      3  *  Copyright (C) 1999-2001 Harri Porten (porten (at) kde.org)
      4  *  Copyright (C) 2001 Peter Kelly (pmk (at) 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 "Parser.h"
     30 #include "Protect.h"
     31 
     32 namespace {
     33 
     34 using namespace JSC;
     35 
     36 class Recompiler {
     37 public:
     38     Recompiler(Debugger*);
     39     ~Recompiler();
     40     void operator()(JSCell*);
     41 
     42 private:
     43     typedef HashSet<FunctionExecutable*> FunctionExecutableSet;
     44     typedef HashMap<SourceProvider*, ExecState*> SourceProviderMap;
     45 
     46     Debugger* m_debugger;
     47     FunctionExecutableSet m_functionExecutables;
     48     SourceProviderMap m_sourceProviders;
     49 };
     50 
     51 inline Recompiler::Recompiler(Debugger* debugger)
     52     : m_debugger(debugger)
     53 {
     54 }
     55 
     56 inline Recompiler::~Recompiler()
     57 {
     58     // Call sourceParsed() after reparsing all functions because it will execute
     59     // JavaScript in the inspector.
     60     SourceProviderMap::const_iterator end = m_sourceProviders.end();
     61     for (SourceProviderMap::const_iterator iter = m_sourceProviders.begin(); iter != end; ++iter)
     62         m_debugger->sourceParsed(iter->second, iter->first, -1, UString());
     63 }
     64 
     65 inline void Recompiler::operator()(JSCell* cell)
     66 {
     67     if (!cell->inherits(&JSFunction::s_info))
     68         return;
     69 
     70     JSFunction* function = asFunction(cell);
     71     if (function->executable()->isHostFunction())
     72         return;
     73 
     74     FunctionExecutable* executable = function->jsExecutable();
     75 
     76     // Check if the function is already in the set - if so,
     77     // we've already retranslated it, nothing to do here.
     78     if (!m_functionExecutables.add(executable).second)
     79         return;
     80 
     81     ExecState* exec = function->scope()->globalObject->JSGlobalObject::globalExec();
     82     executable->discardCode();
     83     if (m_debugger == function->scope()->globalObject->debugger())
     84         m_sourceProviders.add(executable->source().provider(), exec);
     85 }
     86 
     87 } // namespace
     88 
     89 namespace JSC {
     90 
     91 Debugger::~Debugger()
     92 {
     93     HashSet<JSGlobalObject*>::iterator end = m_globalObjects.end();
     94     for (HashSet<JSGlobalObject*>::iterator it = m_globalObjects.begin(); it != end; ++it)
     95         (*it)->setDebugger(0);
     96 }
     97 
     98 void Debugger::attach(JSGlobalObject* globalObject)
     99 {
    100     ASSERT(!globalObject->debugger());
    101     globalObject->setDebugger(this);
    102     m_globalObjects.add(globalObject);
    103 }
    104 
    105 void Debugger::detach(JSGlobalObject* globalObject)
    106 {
    107     ASSERT(m_globalObjects.contains(globalObject));
    108     m_globalObjects.remove(globalObject);
    109     globalObject->setDebugger(0);
    110 }
    111 
    112 void Debugger::recompileAllJSFunctions(JSGlobalData* globalData)
    113 {
    114     // If JavaScript is running, it's not safe to recompile, since we'll end
    115     // up throwing away code that is live on the stack.
    116     ASSERT(!globalData->dynamicGlobalObject);
    117     if (globalData->dynamicGlobalObject)
    118         return;
    119 
    120     Recompiler recompiler(this);
    121     globalData->heap.forEach(recompiler);
    122 }
    123 
    124 JSValue evaluateInGlobalCallFrame(const UString& script, JSValue& exception, JSGlobalObject* globalObject)
    125 {
    126     CallFrame* globalCallFrame = globalObject->globalExec();
    127     JSGlobalData& globalData = globalObject->globalData();
    128 
    129     EvalExecutable* eval = EvalExecutable::create(globalCallFrame, makeSource(script), false);
    130     if (!eval) {
    131         exception = globalData.exception;
    132         globalData.exception = JSValue();
    133         return exception;
    134     }
    135 
    136     JSValue result = globalData.interpreter->execute(eval, globalCallFrame, globalObject, globalCallFrame->scopeChain());
    137     if (globalData.exception) {
    138         exception = globalData.exception;
    139         globalData.exception = JSValue();
    140     }
    141     ASSERT(result);
    142     return result;
    143 }
    144 
    145 } // namespace JSC
    146