Changeset 37323 in webkit


Ignore:
Timestamp:
Oct 5, 2008 7:48:08 PM (16 years ago)
Author:
mjs@apple.com
Message:

2008-10-05 Maciej Stachowiak <mjs@apple.com>

Reviewed by Oliver Hunt.



The problem is that dynamicGlobalObject had become O(N) in number
of call frames, but unwinding the stack for an exception called it
for every call frame, resulting in O(N2) behavior for an
exception thrown from inside deep recursion.

Instead of doing it that way, stash the dynamic global object in JSGlobalData.


  • JavaScriptCore.exp:
  • VM/Machine.cpp: (JSC::DynamicGlobalObjectScope::DynamicGlobalObjectScope): Helper class to temporarily store and later restore a dynamicGlobalObject in JSGlobalData. (JSC::DynamicGlobalObjectScope::~DynamicGlobalObjectScope): (JSC::Machine::execute): In each version, establish a DynamicGlobalObjectScope. For ProgramNode, always establish set new dynamicGlobalObject, for FunctionBody and Eval, only if none is currently set.
  • VM/Machine.h:
  • kjs/ExecState.h:
  • kjs/JSGlobalData.cpp: (JSC::JSGlobalData::JSGlobalData): Ininitalize new dynamicGlobalObject field to 0.
  • kjs/JSGlobalData.h:
  • kjs/JSGlobalObject.h: (JSC::ExecState::dynamicGlobalObject): Moved here from ExecState for benefit of inlining. Return lexical global object if this is a globalExec(), otherwise look in JSGlobalData for the one stashed there.
Location:
trunk/JavaScriptCore
Files:
8 edited

Legend:

Unmodified
Added
Removed
  • trunk/JavaScriptCore/ChangeLog

    r37321 r37323  
     12008-10-05  Maciej Stachowiak  <mjs@apple.com>
     2
     3        Reviewed by Oliver Hunt.
     4       
     5        - fixed "REGRESSION (r37297): fast/js/deep-recursion-test takes too long and times out"
     6        https://bugs.webkit.org/show_bug.cgi?id=21375
     7       
     8        The problem is that dynamicGlobalObject had become O(N) in number
     9        of call frames, but unwinding the stack for an exception called it
     10        for every call frame, resulting in O(N^2) behavior for an
     11        exception thrown from inside deep recursion.
     12
     13        Instead of doing it that way, stash the dynamic global object in JSGlobalData.
     14       
     15        * JavaScriptCore.exp:
     16        * VM/Machine.cpp:
     17        (JSC::DynamicGlobalObjectScope::DynamicGlobalObjectScope): Helper class to temporarily
     18        store and later restore a dynamicGlobalObject in JSGlobalData.
     19        (JSC::DynamicGlobalObjectScope::~DynamicGlobalObjectScope):
     20        (JSC::Machine::execute): In each version, establish a DynamicGlobalObjectScope.
     21        For ProgramNode, always establish set new dynamicGlobalObject, for FunctionBody and Eval,
     22        only if none is currently set.
     23        * VM/Machine.h:
     24        * kjs/ExecState.h:
     25        * kjs/JSGlobalData.cpp:
     26        (JSC::JSGlobalData::JSGlobalData): Ininitalize new dynamicGlobalObject field to 0.
     27        * kjs/JSGlobalData.h:
     28        * kjs/JSGlobalObject.h:
     29        (JSC::ExecState::dynamicGlobalObject): Moved here from ExecState for benefit of inlining.
     30        Return lexical global object if this is a globalExec(), otherwise look in JSGlobalData
     31        for the one stashed there.
     32
    1332008-10-05  Sam Weinig  <sam@webkit.org>
    234
  • trunk/JavaScriptCore/JavaScriptCore.exp

    r37275 r37323  
    207207__ZN3JSC7CStringaSERKS0_
    208208__ZN3JSC7JSArray4infoE
    209 __ZN3JSC7Machine14firstCallFrameEPKNS_8RegisterE
    210209__ZN3JSC7Profile10restoreAllEv
    211210__ZN3JSC7Profile5focusEPKNS_11ProfileNodeE
  • trunk/JavaScriptCore/VM/Machine.cpp

    r37297 r37323  
    869869}
    870870
     871class DynamicGlobalObjectScope {
     872public:
     873    DynamicGlobalObjectScope(ExecState* exec, JSGlobalObject* dynamicGlobalObject)
     874        : m_exec(exec)
     875        , m_savedGlobalObject(exec->globalData().dynamicGlobalObject)
     876    {
     877        exec->globalData().dynamicGlobalObject = dynamicGlobalObject;
     878    }
     879
     880    ~DynamicGlobalObjectScope()
     881    {
     882        m_exec->globalData().dynamicGlobalObject = m_savedGlobalObject;
     883    }
     884
     885private:
     886    ExecState* m_exec;
     887    JSGlobalObject* m_savedGlobalObject;
     888};
     889
    871890JSValue* Machine::execute(ProgramNode* programNode, ExecState* exec, ScopeChainNode* scopeChain, JSObject* thisObj, JSValue** exception)
    872891{
     
    886905        return jsNull();
    887906    }
     907
     908    DynamicGlobalObjectScope globalObjectScope(exec, scopeChain->globalObject());
    888909
    889910    JSGlobalObject* lastGlobalObject = m_registerFile.globalObject();
     
    921942
    922943    m_registerFile.shrink(oldEnd);
     944
    923945    return result;
    924946}
     
    940962        return jsNull();
    941963    }
     964
     965    DynamicGlobalObjectScope globalObjectScope(exec, exec->globalData().dynamicGlobalObject ? exec->globalData().dynamicGlobalObject : scopeChain->globalObject());
    942966
    943967    Register* argv = oldEnd;
     
    9921016        return jsNull();
    9931017    }
     1018
     1019    DynamicGlobalObjectScope globalObjectScope(exec, exec->globalData().dynamicGlobalObject ? exec->globalData().dynamicGlobalObject : scopeChain->globalObject());
    9941020
    9951021    EvalCodeBlock* codeBlock = &evalNode->byteCode(scopeChain);
     
    39493975}
    39503976
    3951 const Register* Machine::firstCallFrame(const Register* callFrame)
    3952 {
    3953     const Register* first = 0;
    3954     for (const Register* frame = callFrame; frame; frame = stripHostCallFrameBit(frame[RegisterFile::CallerRegisters].r()))
    3955         first = frame;
    3956     return first;
    3957 }
    3958 
    39593977Register* Machine::callFrame(ExecState* exec, InternalFunction* function) const
    39603978{
  • trunk/JavaScriptCore/VM/Machine.h

    r37297 r37323  
    104104        void retrieveLastCaller(ExecState* exec, int& lineNumber, intptr_t& sourceID, UString& sourceURL, JSValue*& function) const;
    105105       
    106         static const Register* firstCallFrame(const Register* callFrame);
    107106        static ScopeChainNode* scopeChain(const Register* r) { return r[RegisterFile::ScopeChain].scopeChain(); }
    108107        static CodeBlock* codeBlock(const Register* r) { return r[RegisterFile::CodeBlock].codeBlock(); }
  • trunk/JavaScriptCore/kjs/ExecState.h

    r37297 r37323  
    4444
    4545        // Global object in which execution began.
    46         JSGlobalObject* dynamicGlobalObject()
    47         {
    48             return Machine::scopeChain(Machine::firstCallFrame(this))->globalObject();
    49         }
     46        JSGlobalObject* dynamicGlobalObject();
    5047
    5148        // Global object in which the currently executing code was defined.
  • trunk/JavaScriptCore/kjs/JSGlobalData.cpp

    r37297 r37323  
    9292    , parser(new Parser)
    9393    , head(0)
     94    , dynamicGlobalObject(0)
    9495    , isSharedInstance(isShared)
    9596    , clientData(0)
  • trunk/JavaScriptCore/kjs/JSGlobalData.h

    r37297 r37323  
    9999
    100100        JSGlobalObject* head;
     101        JSGlobalObject* dynamicGlobalObject;
    101102
    102103        bool isSharedInstance;
  • trunk/JavaScriptCore/kjs/JSGlobalObject.h

    r37297 r37323  
    331331    }
    332332
     333    inline JSGlobalObject* ExecState::dynamicGlobalObject()
     334    {
     335        if (this == lexicalGlobalObject()->globalExec())
     336            return lexicalGlobalObject();
     337
     338        // For any ExecState that's not a globalExec, the
     339        // dynamic global object must be set since code is running
     340        ASSERT(globalData().dynamicGlobalObject);
     341        return globalData().dynamicGlobalObject;
     342    }
     343   
    333344} // namespace JSC
    334345
Note: See TracChangeset for help on using the changeset viewer.