Changeset 29710 in webkit for trunk/JavaScriptCore/kjs


Ignore:
Timestamp:
Jan 21, 2008, 10:18:10 PM (17 years ago)
Author:
[email protected]
Message:

JavaScriptCore:

Reviewed by Maciej Stachowiak.


Fixed http://bugs.webkit.org/show_bug.cgi?id=16909
REGRESSION: Amazon.com crash (ActivationImp)


(and a bunch of other crashes)


Plus, a .7% SunSpider speedup to boot.


Replaced the buggy currentExec and savedExec mechanisms with an
explicit ExecState stack.

  • kjs/collector.cpp: (KJS::Collector::collect): Explicitly mark the ExecState stack.

(KJS::Collector::reportOutOfMemoryToAllExecStates): Slight change in
behavior: We no longer throw an exception in any global ExecStates,
since global ExecStates are more like pseudo-ExecStates, and aren't
used for script execution. (It's unclear what would happen if you left
an exception waiting around in a global ExecState, but it probably
wouldn't be good.)

WebCore:

Reviewed by Maciej Stachowiak.

Adapted WebCore to the fix for http://bugs.webkit.org/show_bug.cgi?id=16909
REGRESSION: Amazon.com crash (ActivationImp)

  • bindings/js/kjs_proxy.cpp: (WebCore::KJSProxy::~KJSProxy): No convenient way to make this assertion anymore. (It wasn't firing for anyone, anyway, so it's no big loss.)
  • bindings/objc/WebScriptObject.mm: (+[WebScriptObject throwException:]): Use the ExecState stack, instead of currentExec. (-[WebScriptObject setException:]): ditto. Also, a slight change in behavior: If no ExecStates are active, we no longer throw an exception in the global ExecState. The JavaScriptCore ChangeLog explains why. This also matches the behavior of +throwException.

LayoutTests:

Layout test for http://bugs.webkit.org/show_bug.cgi?id=16909
REGRESSION: Amazon.com crash (ActivationImp)

  • fast/js/exec-state-marking-expected.txt: Added.
  • fast/js/exec-state-marking.html: Added.
Location:
trunk/JavaScriptCore/kjs
Files:
5 edited

Legend:

Unmodified
Added
Removed
  • trunk/JavaScriptCore/kjs/ExecState.cpp

    r29542 r29710  
    4242// ECMA 10.2
    4343
     44// The constructor for the globalExec pseudo-ExecState
     45ExecState::ExecState(JSGlobalObject* globalObject)
     46    : m_globalObject(globalObject)
     47    , m_exception(0)
     48    , m_propertyNames(CommonIdentifiers::shared())
     49    , m_emptyList(globalEmptyList())
     50    , m_callingExec(0)
     51    , m_scopeNode(0)
     52    , m_function(0)
     53    , m_arguments(0)
     54    , m_activation(0)
     55    , m_localStorage(&globalObject->localStorage())
     56    , m_variableObject(globalObject)
     57    , m_thisVal(globalObject)
     58    , m_iterationDepth(0)
     59    , m_switchDepth(0)
     60    , m_codeType(GlobalCode)
     61{
     62    m_scopeChain.push(globalObject);
     63}
     64
    4465ExecState::ExecState(JSGlobalObject* globalObject, JSObject* /*thisObject*/, ProgramNode* programNode)
    4566    : m_globalObject(globalObject)
     
    4869    , m_emptyList(globalEmptyList())
    4970    , m_callingExec(0)
    50     , m_savedExec(0)
    5171    , m_scopeNode(programNode)
    5272    , m_function(0)
     
    6383    // a script with a this object that's not the same as the global object is broken, and probably
    6484    // has been for some time.
     85    ASSERT(m_scopeNode);
     86    activeExecStates().append(this);
    6587    m_scopeChain.push(globalObject);
    66     if (programNode)
    67         globalObject->setCurrentExec(this);
    6888}
    6989
     
    7494    , m_emptyList(callingExec->m_emptyList)
    7595    , m_callingExec(callingExec)
    76     , m_savedExec(globalObject->currentExec())
    7796    , m_scopeNode(evalNode)
    7897    , m_function(0)
     
    87106    , m_codeType(EvalCode)
    88107{   
    89     globalObject->setCurrentExec(this);
     108    ASSERT(m_scopeNode);
     109    activeExecStates().append(this);
    90110}
    91111
     
    98118    , m_emptyList(callingExec->m_emptyList)
    99119    , m_callingExec(callingExec)
    100     , m_savedExec(globalObject->currentExec())
    101120    , m_scopeNode(functionBodyNode)
    102121    , m_function(func)
     
    108127    , m_codeType(FunctionCode)
    109128{
     129    ASSERT(m_scopeNode);
     130    activeExecStates().append(this);
     131
    110132    ActivationImp* activation = globalObject->pushActivation(this);
    111133    m_activation = activation;
     
    113135    m_variableObject = activation;
    114136    m_scopeChain.push(activation);
    115     globalObject->setCurrentExec(this);
    116137}
    117138
    118139ExecState::~ExecState()
    119140{
    120     if (m_codeType == FunctionCode && m_activation->needsPop())
     141    ASSERT(m_scopeNode && activeExecStates().last() == this || !m_scopeNode);
     142    if (m_scopeNode)
     143        activeExecStates().removeLast();
     144
     145    if (m_activation && m_activation->needsPop())
    121146        m_globalObject->popActivation();
    122    
    123     m_globalObject->setCurrentExec(m_savedExec);
    124 }
    125 
    126 void ExecState::mark()
    127 {
    128     for (ExecState* exec = this; exec; exec = exec->m_callingExec) {
    129         exec->m_scopeChain.mark();
    130 
    131         if (exec->m_savedExec != exec->m_callingExec && exec->m_savedExec)
    132             exec->m_savedExec->mark();
    133     }
    134147}
    135148
     
    146159}
    147160
     161void ExecState::markActiveExecStates()
     162{
     163    ExecStateStack::const_iterator end = activeExecStates().end();
     164    for (ExecStateStack::const_iterator it = activeExecStates().begin(); it != end; ++it)
     165        (*it)->m_scopeChain.mark();
     166}
     167
     168ExecStateStack& ExecState::activeExecStates()
     169{
     170    static ExecStateStack staticActiveExecStates;
     171    return staticActiveExecStates;
     172}
     173
    148174} // namespace KJS
  • trunk/JavaScriptCore/kjs/ExecState.h

    r29425 r29710  
    5252    struct LocalStorageEntry;
    5353   
     54    typedef Vector<ExecState*, 16> ExecStateStack;
     55
    5456    /**
    5557     * Represents the current state of script execution. This is
     
    8688       
    8789        ExecState* callingExecState() { return m_callingExec; }
    88         ExecState* savedExec() { return m_savedExec; }
    8990       
    9091        ActivationImp* activationObject() { return m_activation; }
     
    107108        bool inSwitch() const { return (m_switchDepth > 0); }
    108109
    109         void mark();
    110        
    111110        // These pointers are used to avoid accessing global variables for these,
    112111        // to avoid taking PIC branches in Mach-O binaries.
     
    179178        }
    180179
     180        ExecState(JSGlobalObject*);
    181181        ExecState(JSGlobalObject*, JSObject* thisObject, ProgramNode*);
    182182        ExecState(JSGlobalObject*, EvalNode*, ExecState* callingExecState);
     
    185185        ~ExecState();
    186186
     187        static void markActiveExecStates();
     188        static ExecStateStack& activeExecStates();
     189
    187190    private:
    188191        // ExecStates are always stack-allocated, and the garbage collector
     
    195198
    196199        ExecState* m_callingExec;
    197         ExecState* m_savedExec;
     200
    198201        ScopeNode* m_scopeNode;
    199202       
  • trunk/JavaScriptCore/kjs/JSGlobalObject.cpp

    r29663 r29710  
    136136    d()->timeoutCheckCount = 0;
    137137
    138     d()->currentExec = 0;
    139138    d()->recursion = 0;
    140139    d()->debugger = 0;
     
    472471{
    473472    JSVariableObject::mark();
    474 
    475     if (d()->currentExec)
    476         d()->currentExec->mark();
    477473
    478474    markIfNeeded(d()->globalExec.exception());
  • trunk/JavaScriptCore/kjs/JSGlobalObject.h

    r29663 r29710  
    7777            JSGlobalObjectData(JSGlobalObject* globalObject)
    7878                : JSVariableObjectData(&inlineSymbolTable)
    79                 , globalExec(globalObject, globalObject, 0)
     79                , globalExec(globalObject)
    8080            {
    8181            }
     
    8888           
    8989            ExecState globalExec;
    90             ExecState* currentExec;
    9190            int recursion;
    9291
     
    212211        void setDebugger(Debugger* debugger) { d()->debugger = debugger; }
    213212
    214         void setCurrentExec(ExecState* exec) { d()->currentExec = exec; }
    215         ExecState* currentExec() const { return d()->currentExec; }
    216 
    217213        // FIXME: Let's just pick one compatible behavior and go with it.
    218214        void setCompatMode(CompatMode mode) { d()->compatMode = mode; }
  • trunk/JavaScriptCore/kjs/collector.cpp

    r29611 r29710  
    953953  markStackObjectsConservatively();
    954954  markProtectedObjects();
     955  ExecState::markActiveExecStates();
    955956  List::markProtectedLists();
    956957#if USE(MULTIPLE_THREADS)
     
    10671068void Collector::reportOutOfMemoryToAllExecStates()
    10681069{
    1069     JSGlobalObject* o = JSGlobalObject::head();
    1070     if (!o)
    1071         return;
    1072    
    1073     do {
    1074         ExecState* exec = o->currentExec() ? o->currentExec() : o->globalExec();
    1075         exec->setException(Error::create(exec, GeneralError, "Out of memory"));
    1076         o = o->next();
    1077     } while(o != JSGlobalObject::head());
     1070    ExecStateStack::const_iterator end = ExecState::activeExecStates().end();
     1071    for (ExecStateStack::const_iterator it = ExecState::activeExecStates().begin(); it != end; ++it) {
     1072        (*it)->setException(Error::create(*it, GeneralError, "Out of memory"));
     1073    }
    10781074}
    10791075
Note: See TracChangeset for help on using the changeset viewer.