Ignore:
Timestamp:
Nov 28, 2007, 2:08:09 AM (17 years ago)
Author:
[email protected]
Message:

JavaScriptCore:

Reviewed by Darin and Geoff.


Implement mark stack. This version is not suitable for prime time because it makes a
huge allocation on every collect, and potentially makes marking of detached subtrees
slow. But it is an 0.4% SunSpider speedup even without much tweaking.


The basic approach is to replace mark() methods with
markChildren(MarkStack&) methods. Reachable references are pushed
onto a mark stack (which encapsulates ignoring already-marked
references).


Objects are no longer responsible for actually setting their own
mark bits, the collector does that. This means that for objects on
the number heap we don't have to call markChildren() at all since
we know there aren't any.


The mark phase of collect pushes roots onto the mark stack
and drains it as often as possible.


To make this approach viable requires a constant-size mark stack
and a slow fallback approach for when the stack size is exceeded,
plus optimizations to make the required stack small in common
cases. This should be doable.

  • JavaScriptCore.exp: Export new symbols.
  • JavaScriptCore.xcodeproj/project.pbxproj: Add new file.
  • kjs/collector.cpp: (KJS::Collector::heapAllocate): (KJS::drainMarkStack): Helper for all of the below. (KJS::Collector::markStackObjectsConservatively): Use mark stack. (KJS::Collector::markCurrentThreadConservatively): ditto (KJS::Collector::markOtherThreadConservatively): ditto (KJS::Collector::markProtectedObjects): ditto (KJS::Collector::markMainThreadOnlyObjects): ditto (KJS::Collector::collect): ditto
  • kjs/collector.h: (KJS::Collector::cellMayHaveRefs): Helper for MarkStack.
  • kjs/MarkStack.h: Added. The actual mark stack implementation. (KJS::MarkStack::push): (KJS::MarkStack::pushAtom): (KJS::MarkStack::pop): (KJS::MarkStack::isEmpty): (KJS::MarkStack::reserveCapacity):

Changed mark() methods to markChildren() methods:


  • kjs/ExecState.cpp: (KJS::ExecState::markChildren):
  • kjs/ExecState.h:
  • kjs/JSWrapperObject.cpp: (KJS::JSWrapperObject::markChildren):
  • kjs/JSWrapperObject.h:
  • kjs/array_instance.cpp: (KJS::ArrayInstance::markChildren):
  • kjs/array_instance.h:
  • kjs/bool_object.cpp: (BooleanInstance::markChildren):
  • kjs/bool_object.h:
  • kjs/error_object.cpp:
  • kjs/error_object.h:
  • kjs/function.cpp: (KJS::FunctionImp::markChildren): (KJS::Arguments::Arguments): (KJS::Arguments::markChildren): (KJS::ActivationImp::markChildren):
  • kjs/function.h:
  • kjs/internal.cpp: (KJS::GetterSetterImp::markChildren):
  • kjs/interpreter.cpp: (KJS::Interpreter::markRoots):
  • kjs/interpreter.h:
  • kjs/list.cpp: (KJS::List::markProtectedListsSlowCase):
  • kjs/list.h: (KJS::List::markProtectedLists):
  • kjs/object.cpp: (KJS::JSObject::markChildren):
  • kjs/object.h: (KJS::ScopeChain::markChildren):
  • kjs/property_map.cpp: (KJS::PropertyMap::markChildren):
  • kjs/property_map.h:
  • kjs/scope_chain.h:
  • kjs/string_object.cpp: (KJS::StringInstance::markChildren):
  • kjs/string_object.h:

JavaScriptGlue:

Reviewed by Darin and Geoff.

Fixups for JavaScriptCore mark stack.

  • JSObject.cpp: (JSUserObject::Mark):
  • JSObject.h:
  • JSValueWrapper.cpp: (JSValueWrapper::JSObjectMark):
  • JSValueWrapper.h:
  • UserObjectImp.cpp:
  • UserObjectImp.h:

WebCore:

Reviewed by Darin and Geoff.

Implement mark stack. This version is not suitable for prime time because it makes a
huge allocation on every collect, and potentially makes marking of detached subtrees
slow. But it is a .2% - .4% speedup even without much tweaking.

I replaced mark() methods with markChildren() as usual. One
optimization that is lost is avoiding walking detached DOM
subtrees more than once to mark them; since marking is not
recursive there's no obvious way to bracket operation on the tree
any more.

  • bindings/js/JSDocumentCustom.cpp: (WebCore::JSDocument::markChildren):
  • bindings/js/JSNodeCustom.cpp: (WebCore::JSNode::markChildren):
  • bindings/js/JSNodeFilterCondition.cpp:
  • bindings/js/JSNodeFilterCondition.h:
  • bindings/js/JSNodeFilterCustom.cpp: (WebCore::JSNodeFilter::markChildren):
  • bindings/js/JSNodeIteratorCustom.cpp: (WebCore::JSNodeIterator::markChildren):
  • bindings/js/JSTreeWalkerCustom.cpp: (WebCore::JSTreeWalker::markChildren):
  • bindings/js/JSXMLHttpRequest.cpp: (KJS::JSXMLHttpRequest::markChildren):
  • bindings/js/JSXMLHttpRequest.h:
  • bindings/js/kjs_binding.cpp: (KJS::ScriptInterpreter::markDOMNodesForDocument):
  • bindings/js/kjs_binding.h:
  • bindings/js/kjs_events.cpp: (WebCore::JSUnprotectedEventListener::markChildren):
  • bindings/js/kjs_events.h:
  • bindings/js/kjs_window.cpp: (KJS::Window::markChildren):
  • bindings/js/kjs_window.h:
  • bindings/scripts/CodeGeneratorJS.pm:
  • dom/Node.cpp: (WebCore::Node::Node):
  • dom/Node.h:
  • dom/NodeFilter.h:
  • dom/NodeFilterCondition.h:

LayoutTests:

Not reviewed.


I have fixed this with the mark stack work.


  • fast/js/gc-breadth-2-expected.txt: Added.
  • fast/js/gc-breadth-2.html: Added.
  • fast/js/gc-breadth-expected.txt: Added.
  • fast/js/gc-breadth.html: Added.
  • fast/js/gc-depth-expected.txt: Added.
  • fast/js/gc-depth.html: Added.
  • fast/js/resources/gc-breadth-2.js: Added.
  • fast/js/resources/gc-breadth.js: Added.
  • fast/js/resources/gc-depth.js: Added.
File:
1 edited

Legend:

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

    r27885 r28106  
    545545}
    546546
    547 void Interpreter::mark()
     547void Interpreter::markRoots(MarkStack& stack)
    548548{
    549549    if (m_currentExec)
    550         m_currentExec->mark();
    551 
    552     if (m_globalExec.exception() && !m_globalExec.exception()->marked())
    553         m_globalExec.exception()->mark();
    554 
    555     if (m_globalObject && !m_globalObject->marked())
    556         m_globalObject->mark();
    557 
    558     if (m_Object && !m_Object->marked())
    559         m_Object->mark();
    560     if (m_Function && !m_Function->marked())
    561         m_Function->mark();
    562     if (m_Array && !m_Array->marked())
    563         m_Array->mark();
    564     if (m_Boolean && !m_Boolean->marked())
    565         m_Boolean->mark();
    566     if (m_String && !m_String->marked())
    567         m_String->mark();
    568     if (m_Number && !m_Number->marked())
    569         m_Number->mark();
    570     if (m_Date && !m_Date->marked())
    571         m_Date->mark();
    572     if (m_RegExp && !m_RegExp->marked())
    573         m_RegExp->mark();
    574     if (m_Error && !m_Error->marked())
    575         m_Error->mark();
    576    
    577     if (m_ObjectPrototype && !m_ObjectPrototype->marked())
    578         m_ObjectPrototype->mark();
    579     if (m_FunctionPrototype && !m_FunctionPrototype->marked())
    580         m_FunctionPrototype->mark();
    581     if (m_ArrayPrototype && !m_ArrayPrototype->marked())
    582         m_ArrayPrototype->mark();
    583     if (m_BooleanPrototype && !m_BooleanPrototype->marked())
    584         m_BooleanPrototype->mark();
    585     if (m_StringPrototype && !m_StringPrototype->marked())
    586         m_StringPrototype->mark();
    587     if (m_NumberPrototype && !m_NumberPrototype->marked())
    588         m_NumberPrototype->mark();
    589     if (m_DatePrototype && !m_DatePrototype->marked())
    590         m_DatePrototype->mark();
    591     if (m_RegExpPrototype && !m_RegExpPrototype->marked())
    592         m_RegExpPrototype->mark();
    593     if (m_ErrorPrototype && !m_ErrorPrototype->marked())
    594         m_ErrorPrototype->mark();
    595    
    596     if (m_EvalError && !m_EvalError->marked())
    597         m_EvalError->mark();
    598     if (m_RangeError && !m_RangeError->marked())
    599         m_RangeError->mark();
    600     if (m_ReferenceError && !m_ReferenceError->marked())
    601         m_ReferenceError->mark();
    602     if (m_SyntaxError && !m_SyntaxError->marked())
    603         m_SyntaxError->mark();
    604     if (m_TypeError && !m_TypeError->marked())
    605         m_TypeError->mark();
    606     if (m_UriError && !m_UriError->marked())
    607         m_UriError->mark();
    608    
    609     if (m_EvalErrorPrototype && !m_EvalErrorPrototype->marked())
    610         m_EvalErrorPrototype->mark();
    611     if (m_RangeErrorPrototype && !m_RangeErrorPrototype->marked())
    612         m_RangeErrorPrototype->mark();
    613     if (m_ReferenceErrorPrototype && !m_ReferenceErrorPrototype->marked())
    614         m_ReferenceErrorPrototype->mark();
    615     if (m_SyntaxErrorPrototype && !m_SyntaxErrorPrototype->marked())
    616         m_SyntaxErrorPrototype->mark();
    617     if (m_TypeErrorPrototype && !m_TypeErrorPrototype->marked())
    618         m_TypeErrorPrototype->mark();
    619     if (m_UriErrorPrototype && !m_UriErrorPrototype->marked())
    620         m_UriErrorPrototype->mark();
     550        m_currentExec->markChildren(stack);
     551
     552    if (m_globalExec.exception())
     553        stack.push(m_globalExec.exception());
     554
     555    if (m_globalObject)
     556        stack.push(m_globalObject);
     557
     558    if (m_Object)
     559       stack.push(m_Object);
     560    if (m_Function)
     561        stack.push(m_Function);
     562    if (m_Array)
     563        stack.push(m_Array);
     564    if (m_Boolean)
     565        stack.push(m_Boolean);
     566    if (m_String)
     567        stack.push(m_String);
     568    if (m_Number)
     569        stack.push(m_Number);
     570    if (m_Date)
     571        stack.push(m_Date);
     572    if (m_RegExp)
     573        stack.push(m_RegExp);
     574    if (m_Error)
     575        stack.push(m_Error);
     576   
     577    if (m_ObjectPrototype)
     578        stack.push(m_ObjectPrototype);
     579    if (m_FunctionPrototype)
     580        stack.push(m_FunctionPrototype);
     581    if (m_ArrayPrototype)
     582        stack.push(m_ArrayPrototype);
     583    if (m_BooleanPrototype)
     584        stack.push(m_BooleanPrototype);
     585    if (m_StringPrototype)
     586        stack.push(m_StringPrototype);
     587    if (m_NumberPrototype)
     588        stack.push(m_NumberPrototype);
     589    if (m_DatePrototype)
     590        stack.push(m_DatePrototype);
     591    if (m_RegExpPrototype)
     592        stack.push(m_RegExpPrototype);
     593    if (m_ErrorPrototype)
     594        stack.push(m_ErrorPrototype);
     595   
     596    if (m_EvalError)
     597        stack.push(m_EvalError);
     598    if (m_RangeError)
     599        stack.push(m_RangeError);
     600    if (m_ReferenceError)
     601        stack.push(m_ReferenceError);
     602    if (m_SyntaxError)
     603        stack.push(m_SyntaxError);
     604    if (m_TypeError)
     605        stack.push(m_TypeError);
     606    if (m_UriError)
     607        stack.push(m_UriError);
     608   
     609    if (m_EvalErrorPrototype)
     610        stack.push(m_EvalErrorPrototype);
     611    if (m_RangeErrorPrototype)
     612        stack.push(m_RangeErrorPrototype);
     613    if (m_ReferenceErrorPrototype)
     614        stack.push(m_ReferenceErrorPrototype);
     615    if (m_SyntaxErrorPrototype)
     616        stack.push(m_SyntaxErrorPrototype);
     617    if (m_TypeErrorPrototype)
     618        stack.push(m_TypeErrorPrototype);
     619    if (m_UriErrorPrototype)
     620        stack.push(m_UriErrorPrototype);
    621621}
    622622
Note: See TracChangeset for help on using the changeset viewer.