Ignore:
Timestamp:
Aug 10, 2009, 9:35:02 PM (16 years ago)
Author:
[email protected]
Message:

Stack overflow crash in JavaScript garbage collector mark pass
https://bugs.webkit.org/show_bug.cgi?id=12216

Reviewed by Gavin Barraclough and Sam Weinig

Make the GC mark phase iterative by using an explicit mark stack.
To do this marking any single object is performed in multiple stages

  • The object is appended to the MarkStack, this sets the marked bit for the object using the new markDirect() function, and then returns
  • When the MarkStack is drain()ed the object is popped off the stack and markChildren(MarkStack&) is called on the object to collect all of its children. drain() then repeats until the stack is empty.

Additionally I renamed a number of methods from 'mark' to 'markAggregate'
in order to make it more clear that marking of those object was not
going to result in an actual recursive mark.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/JavaScriptCore/runtime/JSGlobalObject.cpp

    r46963 r47022  
    8181static const int preferredScriptCheckTimeInterval = 1000;
    8282
    83 static inline void markIfNeeded(JSValue v)
    84 {
    85     if (v && !v.marked())
    86         v.mark();
    87 }
    88 
    89 static inline void markIfNeeded(const RefPtr<Structure>& s)
     83static inline void markIfNeeded(MarkStack& markStack, JSValue v)
     84{
     85    if (v)
     86        markStack.append(v);
     87}
     88
     89static inline void markIfNeeded(MarkStack& markStack, const RefPtr<Structure>& s)
    9090{
    9191    if (s)
    92         s->mark();
     92        s->markAggregate(markStack);
    9393}
    9494
     
    358358}
    359359
    360 void JSGlobalObject::mark()
    361 {
    362     JSVariableObject::mark();
     360void JSGlobalObject::markChildren(MarkStack& markStack)
     361{
     362    JSVariableObject::markChildren(markStack);
    363363   
    364364    HashSet<ProgramCodeBlock*>::const_iterator end = codeBlocks().end();
    365365    for (HashSet<ProgramCodeBlock*>::const_iterator it = codeBlocks().begin(); it != end; ++it)
    366         (*it)->mark();
     366        (*it)->markAggregate(markStack);
    367367
    368368    RegisterFile& registerFile = globalData()->interpreter->registerFile();
    369369    if (registerFile.globalObject() == this)
    370         registerFile.markGlobals(&globalData()->heap);
    371 
    372     markIfNeeded(d()->regExpConstructor);
    373     markIfNeeded(d()->errorConstructor);
    374     markIfNeeded(d()->evalErrorConstructor);
    375     markIfNeeded(d()->rangeErrorConstructor);
    376     markIfNeeded(d()->referenceErrorConstructor);
    377     markIfNeeded(d()->syntaxErrorConstructor);
    378     markIfNeeded(d()->typeErrorConstructor);
    379     markIfNeeded(d()->URIErrorConstructor);
    380 
    381     markIfNeeded(d()->evalFunction);
    382     markIfNeeded(d()->callFunction);
    383     markIfNeeded(d()->applyFunction);
    384 
    385     markIfNeeded(d()->objectPrototype);
    386     markIfNeeded(d()->functionPrototype);
    387     markIfNeeded(d()->arrayPrototype);
    388     markIfNeeded(d()->booleanPrototype);
    389     markIfNeeded(d()->stringPrototype);
    390     markIfNeeded(d()->numberPrototype);
    391     markIfNeeded(d()->datePrototype);
    392     markIfNeeded(d()->regExpPrototype);
    393 
    394     markIfNeeded(d()->methodCallDummy);
    395 
    396     markIfNeeded(d()->errorStructure);
     370        registerFile.markGlobals(markStack, &globalData()->heap);
     371
     372    markIfNeeded(markStack, d()->regExpConstructor);
     373    markIfNeeded(markStack, d()->errorConstructor);
     374    markIfNeeded(markStack, d()->evalErrorConstructor);
     375    markIfNeeded(markStack, d()->rangeErrorConstructor);
     376    markIfNeeded(markStack, d()->referenceErrorConstructor);
     377    markIfNeeded(markStack, d()->syntaxErrorConstructor);
     378    markIfNeeded(markStack, d()->typeErrorConstructor);
     379    markIfNeeded(markStack, d()->URIErrorConstructor);
     380
     381    markIfNeeded(markStack, d()->evalFunction);
     382    markIfNeeded(markStack, d()->callFunction);
     383    markIfNeeded(markStack, d()->applyFunction);
     384
     385    markIfNeeded(markStack, d()->objectPrototype);
     386    markIfNeeded(markStack, d()->functionPrototype);
     387    markIfNeeded(markStack, d()->arrayPrototype);
     388    markIfNeeded(markStack, d()->booleanPrototype);
     389    markIfNeeded(markStack, d()->stringPrototype);
     390    markIfNeeded(markStack, d()->numberPrototype);
     391    markIfNeeded(markStack, d()->datePrototype);
     392    markIfNeeded(markStack, d()->regExpPrototype);
     393
     394    markIfNeeded(markStack, d()->methodCallDummy);
     395
     396    markIfNeeded(markStack, d()->errorStructure);
    397397
    398398    // No need to mark the other structures, because their prototypes are all
     
    404404
    405405    size_t size = d()->registerArraySize;
    406     for (size_t i = 0; i < size; ++i) {
    407         Register& r = registerArray[i];
    408         if (!r.marked())
    409             r.mark();
    410     }
     406    markStack.appendValues(reinterpret_cast<JSValue*>(registerArray), size);
    411407}
    412408
Note: See TracChangeset for help on using the changeset viewer.