Stack overflow crash in JavaScript garbage collector mark pass
authoroliver@apple.com <oliver@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 11 Aug 2009 04:35:02 +0000 (04:35 +0000)
committeroliver@apple.com <oliver@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 11 Aug 2009 04:35:02 +0000 (04:35 +0000)
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.

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@47022 268f45cc-cd09-0410-ab3c-d52691b4dbfc

110 files changed:
JavaScriptCore/ChangeLog
JavaScriptCore/GNUmakefile.am
JavaScriptCore/JavaScriptCore.exp
JavaScriptCore/JavaScriptCore.gypi
JavaScriptCore/JavaScriptCore.pri
JavaScriptCore/JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.vcproj
JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj
JavaScriptCore/bytecode/CodeBlock.cpp
JavaScriptCore/bytecode/CodeBlock.h
JavaScriptCore/bytecode/EvalCodeCache.h
JavaScriptCore/debugger/DebuggerActivation.cpp
JavaScriptCore/debugger/DebuggerActivation.h
JavaScriptCore/interpreter/Register.h
JavaScriptCore/interpreter/RegisterFile.h
JavaScriptCore/parser/Nodes.cpp
JavaScriptCore/parser/Nodes.h
JavaScriptCore/runtime/ArgList.cpp
JavaScriptCore/runtime/ArgList.h
JavaScriptCore/runtime/Arguments.cpp
JavaScriptCore/runtime/Arguments.h
JavaScriptCore/runtime/Collector.cpp
JavaScriptCore/runtime/Collector.h
JavaScriptCore/runtime/GetterSetter.cpp
JavaScriptCore/runtime/GetterSetter.h
JavaScriptCore/runtime/GlobalEvalFunction.cpp
JavaScriptCore/runtime/GlobalEvalFunction.h
JavaScriptCore/runtime/JSAPIValueWrapper.h
JavaScriptCore/runtime/JSActivation.cpp
JavaScriptCore/runtime/JSActivation.h
JavaScriptCore/runtime/JSArray.cpp
JavaScriptCore/runtime/JSArray.h
JavaScriptCore/runtime/JSCell.h
JavaScriptCore/runtime/JSFunction.cpp
JavaScriptCore/runtime/JSFunction.h
JavaScriptCore/runtime/JSGlobalData.cpp
JavaScriptCore/runtime/JSGlobalData.h
JavaScriptCore/runtime/JSGlobalObject.cpp
JavaScriptCore/runtime/JSGlobalObject.h
JavaScriptCore/runtime/JSNotAnObject.cpp
JavaScriptCore/runtime/JSNotAnObject.h
JavaScriptCore/runtime/JSONObject.cpp
JavaScriptCore/runtime/JSONObject.h
JavaScriptCore/runtime/JSObject.cpp
JavaScriptCore/runtime/JSObject.h
JavaScriptCore/runtime/JSPropertyNameIterator.cpp
JavaScriptCore/runtime/JSPropertyNameIterator.h
JavaScriptCore/runtime/JSStaticScopeObject.cpp
JavaScriptCore/runtime/JSStaticScopeObject.h
JavaScriptCore/runtime/JSType.h
JavaScriptCore/runtime/JSValue.h
JavaScriptCore/runtime/JSWrapperObject.cpp
JavaScriptCore/runtime/JSWrapperObject.h
JavaScriptCore/runtime/MarkStack.cpp [new file with mode: 0644]
JavaScriptCore/runtime/MarkStack.h [new file with mode: 0644]
JavaScriptCore/runtime/MarkStackPosix.cpp [new file with mode: 0644]
JavaScriptCore/runtime/MarkStackWin.cpp [new file with mode: 0644]
JavaScriptCore/runtime/ScopeChain.h
JavaScriptCore/runtime/ScopeChainMark.h
JavaScriptCore/runtime/SmallStrings.cpp
JavaScriptCore/runtime/Structure.h
JavaScriptGlue/ChangeLog
JavaScriptGlue/JSValueWrapper.cpp
JavaScriptGlue/UserObjectImp.cpp
JavaScriptGlue/UserObjectImp.h
LayoutTests/ChangeLog
LayoutTests/fast/js/nested-object-gc-expected.txt [new file with mode: 0644]
LayoutTests/fast/js/nested-object-gc.html [new file with mode: 0644]
LayoutTests/fast/js/resources/js-test-pre.js
LayoutTests/fast/js/resources/nested-object-gc.js [new file with mode: 0644]
WebCore/ChangeLog
WebCore/bindings/js/JSAbstractWorkerCustom.cpp
WebCore/bindings/js/JSDOMApplicationCacheCustom.cpp
WebCore/bindings/js/JSDOMBinding.cpp
WebCore/bindings/js/JSDOMBinding.h
WebCore/bindings/js/JSDOMGlobalObject.cpp
WebCore/bindings/js/JSDOMGlobalObject.h
WebCore/bindings/js/JSDOMWindowCustom.cpp
WebCore/bindings/js/JSDOMWindowShell.cpp
WebCore/bindings/js/JSDOMWindowShell.h
WebCore/bindings/js/JSDedicatedWorkerContextCustom.cpp
WebCore/bindings/js/JSDocumentCustom.cpp
WebCore/bindings/js/JSEventListener.cpp
WebCore/bindings/js/JSEventListener.h
WebCore/bindings/js/JSMessageChannelCustom.cpp
WebCore/bindings/js/JSMessagePortCustom.cpp
WebCore/bindings/js/JSNavigatorCustom.cpp
WebCore/bindings/js/JSNodeCustom.cpp
WebCore/bindings/js/JSNodeFilterCondition.cpp
WebCore/bindings/js/JSNodeFilterCondition.h
WebCore/bindings/js/JSNodeFilterCustom.cpp
WebCore/bindings/js/JSNodeIteratorCustom.cpp
WebCore/bindings/js/JSQuarantinedObjectWrapper.cpp
WebCore/bindings/js/JSQuarantinedObjectWrapper.h
WebCore/bindings/js/JSSVGElementInstanceCustom.cpp
WebCore/bindings/js/JSSharedWorkerContextCustom.cpp
WebCore/bindings/js/JSSharedWorkerCustom.cpp
WebCore/bindings/js/JSStyleSheetCustom.cpp
WebCore/bindings/js/JSTreeWalkerCustom.cpp
WebCore/bindings/js/JSWebSocketCustom.cpp
WebCore/bindings/js/JSWorkerContextCustom.cpp
WebCore/bindings/js/JSWorkerCustom.cpp
WebCore/bindings/js/JSXMLHttpRequestCustom.cpp
WebCore/bindings/js/JSXMLHttpRequestUploadCustom.cpp
WebCore/bindings/scripts/CodeGeneratorJS.pm
WebCore/dom/EventListener.h
WebCore/dom/NodeFilter.h
WebCore/dom/NodeFilterCondition.h
WebCore/dom/RegisteredEventListener.h
WebCore/page/DOMWindow.h
WebCore/workers/WorkerContext.h

index 922f9ce..7d4b3f6 100644 (file)
@@ -1,3 +1,157 @@
+2009-08-07  Oliver Hunt  <oliver@apple.com>
+
+        Reviewed by Gavin Barraclough.
+
+        Stack overflow crash in JavaScript garbage collector mark pass
+        https://bugs.webkit.org/show_bug.cgi?id=12216
+
+        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.
+
+        * GNUmakefile.am
+        * JavaScriptCore.exp:
+        * JavaScriptCore.gypi:
+        * JavaScriptCore.pri:
+        * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.vcproj:
+        * JavaScriptCore.xcodeproj/project.pbxproj:
+        * bytecode/CodeBlock.cpp:
+        (JSC::CodeBlock::markAggregate):
+        * bytecode/CodeBlock.h:
+        * bytecode/EvalCodeCache.h:
+        (JSC::EvalCodeCache::markAggregate):
+        * debugger/DebuggerActivation.cpp:
+        (JSC::DebuggerActivation::markChildren):
+        * debugger/DebuggerActivation.h:
+        * interpreter/Register.h:
+        * interpreter/RegisterFile.h:
+        (JSC::RegisterFile::markGlobals):
+        (JSC::RegisterFile::markCallFrames):
+        * parser/Nodes.cpp:
+        (JSC::ScopeNodeData::markAggregate):
+        (JSC::EvalNode::markAggregate):
+        (JSC::FunctionBodyNode::markAggregate):
+        * parser/Nodes.h:
+        (JSC::ScopeNode::markAggregate):
+        * runtime/ArgList.cpp:
+        (JSC::MarkedArgumentBuffer::markLists):
+        * runtime/ArgList.h:
+        * runtime/Arguments.cpp:
+        (JSC::Arguments::markChildren):
+        * runtime/Arguments.h:
+        * runtime/Collector.cpp:
+        (JSC::Heap::markConservatively):
+        (JSC::Heap::markCurrentThreadConservativelyInternal):
+        (JSC::Heap::markCurrentThreadConservatively):
+        (JSC::Heap::markOtherThreadConservatively):
+        (JSC::Heap::markStackObjectsConservatively):
+        (JSC::Heap::markProtectedObjects):
+        (JSC::Heap::collect):
+        * runtime/Collector.h:
+        * runtime/GetterSetter.cpp:
+        (JSC::GetterSetter::markChildren):
+        * runtime/GetterSetter.h:
+        (JSC::GetterSetter::GetterSetter):
+        (JSC::GetterSetter::createStructure):
+        * runtime/GlobalEvalFunction.cpp:
+        (JSC::GlobalEvalFunction::markChildren):
+        * runtime/GlobalEvalFunction.h:
+        * runtime/JSActivation.cpp:
+        (JSC::JSActivation::markChildren):
+        * runtime/JSActivation.h:
+        * runtime/JSArray.cpp:
+        (JSC::JSArray::markChildren):
+        * runtime/JSArray.h:
+        * runtime/JSCell.h:
+        (JSC::JSCell::markCellDirect):
+        (JSC::JSCell::markChildren):
+        (JSC::JSValue::markDirect):
+        (JSC::JSValue::markChildren):
+        (JSC::JSValue::hasChildren):
+        (JSC::MarkStack::append):
+        (JSC::MarkStack::drain):
+        * runtime/JSFunction.cpp:
+        (JSC::JSFunction::markChildren):
+        * runtime/JSFunction.h:
+        * runtime/JSGlobalData.cpp:
+        (JSC::JSGlobalData::JSGlobalData):
+        * runtime/JSGlobalData.h:
+        * runtime/JSGlobalObject.cpp:
+        (JSC::markIfNeeded):
+        (JSC::JSGlobalObject::markChildren):
+        * runtime/JSGlobalObject.h:
+        * runtime/JSNotAnObject.cpp:
+        (JSC::JSNotAnObject::markChildren):
+        * runtime/JSNotAnObject.h:
+        * runtime/JSONObject.cpp:
+        (JSC::Stringifier::markAggregate):
+        (JSC::JSONObject::markStringifiers):
+        * runtime/JSONObject.h:
+        * runtime/JSObject.cpp:
+        (JSC::JSObject::markChildren):
+        (JSC::JSObject::defineGetter):
+        (JSC::JSObject::defineSetter):
+        * runtime/JSObject.h:
+        * runtime/JSPropertyNameIterator.cpp:
+        (JSC::JSPropertyNameIterator::markChildren):
+        * runtime/JSPropertyNameIterator.h:
+        (JSC::JSPropertyNameIterator::createStructure):
+        (JSC::JSPropertyNameIterator::JSPropertyNameIterator):
+        (JSC::JSPropertyNameIterator::create):
+        * runtime/JSStaticScopeObject.cpp:
+        (JSC::JSStaticScopeObject::markChildren):
+        * runtime/JSStaticScopeObject.h:
+        * runtime/JSType.h:
+        (JSC::):
+        * runtime/JSValue.h:
+        * runtime/JSWrapperObject.cpp:
+        (JSC::JSWrapperObject::markChildren):
+        * runtime/JSWrapperObject.h:
+        * runtime/MarkStack.cpp: Added.
+        (JSC::MarkStack::compact):
+        * runtime/MarkStack.h: Added.
+        (JSC::):
+        (JSC::MarkStack::MarkStack):
+        (JSC::MarkStack::append):
+        (JSC::MarkStack::appendValues):
+        (JSC::MarkStack::~MarkStack):
+        (JSC::MarkStack::MarkSet::MarkSet):
+        (JSC::MarkStack::pageSize):
+        
+        MarkStackArray is a non-shrinking, mmap-based vector type
+        used for storing objects to be marked.
+        (JSC::MarkStack::MarkStackArray::MarkStackArray):
+        (JSC::MarkStack::MarkStackArray::~MarkStackArray):
+        (JSC::MarkStack::MarkStackArray::expand):
+        (JSC::MarkStack::MarkStackArray::append):
+        (JSC::MarkStack::MarkStackArray::removeLast):
+        (JSC::MarkStack::MarkStackArray::isEmpty):
+        (JSC::MarkStack::MarkStackArray::size):
+        (JSC::MarkStack::MarkStackArray::shrinkAllocation):
+        * runtime/MarkStackPosix.cpp: Added.
+        (JSC::MarkStack::allocateStack):
+        (JSC::MarkStack::releaseStack):
+        * runtime/MarkStackWin.cpp: Added.
+        (JSC::MarkStack::allocateStack):
+        (JSC::MarkStack::releaseStack):
+
+        * runtime/ScopeChain.h:
+        * runtime/ScopeChainMark.h:
+        (JSC::ScopeChain::markAggregate):
+        * runtime/SmallStrings.cpp:
+        (JSC::SmallStrings::mark):
+        * runtime/Structure.h:
+        (JSC::Structure::markAggregate):
+
 2009-08-10  Mark Rowe  <mrowe@apple.com>
         
         Reviewed by Darin Adler.
index 2972b73..6b4dc6d 100644 (file)
@@ -191,6 +191,9 @@ javascriptcore_sources += \
        JavaScriptCore/runtime/JSPropertyNameIterator.h \
        JavaScriptCore/runtime/LiteralParser.cpp \
        JavaScriptCore/runtime/LiteralParser.h \
+       JavaScriptCore/runtime/MarkStack.cpp \
+       JavaScriptCore/runtime/MarkStack.h \
+       JavaScriptCore/runtime/MarkStackPosix.cpp \
        JavaScriptCore/runtime/SmallStrings.cpp \
        JavaScriptCore/runtime/SmallStrings.h \
        JavaScriptCore/runtime/Structure.cpp \
@@ -436,6 +439,9 @@ javascriptcore_sources += \
        JavaScriptCore/runtime/JSWrapperObject.h \
        JavaScriptCore/runtime/Lookup.cpp \
        JavaScriptCore/runtime/Lookup.h \
+       JavaScriptCore/runtime/MarkStack.cpp \
+       JavaScriptCore/runtime/MarkStack.h \
+       JavaScriptCore/runtime/MarkStackWin.cpp \
        JavaScriptCore/runtime/MathObject.cpp \
        JavaScriptCore/runtime/MathObject.h \
        JavaScriptCore/runtime/NativeErrorConstructor.cpp \
index 89c124a..3ff0299 100644 (file)
@@ -131,17 +131,17 @@ __ZN3JSC13jsOwnedStringEPNS_12JSGlobalDataERKNS_7UStringE
 __ZN3JSC14JSGlobalObject10globalExecEv
 __ZN3JSC14JSGlobalObject12defineGetterEPNS_9ExecStateERKNS_10IdentifierEPNS_8JSObjectE
 __ZN3JSC14JSGlobalObject12defineSetterEPNS_9ExecStateERKNS_10IdentifierEPNS_8JSObjectE
+__ZN3JSC14JSGlobalObject12markChildrenERNS_9MarkStackE
 __ZN3JSC14JSGlobalObject17putWithAttributesEPNS_9ExecStateERKNS_10IdentifierENS_7JSValueEj
 __ZN3JSC14JSGlobalObject3putEPNS_9ExecStateERKNS_10IdentifierENS_7JSValueERNS_15PutPropertySlotE  
 __ZN3JSC14JSGlobalObject4initEPNS_8JSObjectE
-__ZN3JSC14JSGlobalObject4markEv
 __ZN3JSC14JSGlobalObjectD2Ev
 __ZN3JSC14JSGlobalObjectnwEmPNS_12JSGlobalDataE
 __ZN3JSC14SamplingThread4stopEv
 __ZN3JSC14SamplingThread5startEj
 __ZN3JSC14TimeoutChecker5resetEv
 __ZN3JSC14constructArrayEPNS_9ExecStateERKNS_7ArgListE
-__ZN3JSC15JSWrapperObject4markEv
+__ZN3JSC15JSWrapperObject12markChildrenERNS_9MarkStackE
 __ZN3JSC15toInt32SlowCaseEdRb
 __ZN3JSC16FunctionBodyNode13finishParsingEPNS_10IdentifierEm
 __ZN3JSC16FunctionBodyNode14copyParametersEv
@@ -236,6 +236,7 @@ __ZN3JSC8JSObject12defineGetterEPNS_9ExecStateERKNS_10IdentifierEPS0_
 __ZN3JSC8JSObject12defineSetterEPNS_9ExecStateERKNS_10IdentifierEPS0_
 __ZN3JSC8JSObject12lookupGetterEPNS_9ExecStateERKNS_10IdentifierE
 __ZN3JSC8JSObject12lookupSetterEPNS_9ExecStateERKNS_10IdentifierE
+__ZN3JSC8JSObject12markChildrenERNS_9MarkStackE
 __ZN3JSC8JSObject14deletePropertyEPNS_9ExecStateERKNS_10IdentifierE
 __ZN3JSC8JSObject14deletePropertyEPNS_9ExecStateEj
 __ZN3JSC8JSObject15unwrappedObjectEv
@@ -251,7 +252,6 @@ __ZN3JSC8JSObject22fillGetterPropertySlotERNS_12PropertySlotEPNS_7JSValueE
 __ZN3JSC8JSObject23allocatePropertyStorageEmm
 __ZN3JSC8JSObject3putEPNS_9ExecStateERKNS_10IdentifierENS_7JSValueERNS_15PutPropertySlotE
 __ZN3JSC8JSObject3putEPNS_9ExecStateEjNS_7JSValueE  
-__ZN3JSC8JSObject4markEv
 __ZN3JSC8Profiler13stopProfilingEPNS_9ExecStateERKNS_7UStringE
 __ZN3JSC8Profiler14startProfilingEPNS_9ExecStateERKNS_7UStringE
 __ZN3JSC8Profiler8profilerEv
@@ -259,6 +259,9 @@ __ZN3JSC8evaluateEPNS_9ExecStateERNS_10ScopeChainERKNS_10SourceCodeENS_7JSValueE
 __ZN3JSC8jsStringEPNS_12JSGlobalDataERKNS_7UStringE
 __ZN3JSC9CodeBlockD1Ev
 __ZN3JSC9CodeBlockD2Ev
+__ZN3JSC9MarkStack10s_pageSizeE
+__ZN3JSC9MarkStack12releaseStackEPvm
+__ZN3JSC9MarkStack13allocateStackEm
 __ZN3JSC9Structure17stopIgnoringLeaksEv
 __ZN3JSC9Structure18startIgnoringLeaksEv
 __ZN3JSC9Structure21addPropertyTransitionEPS0_RKNS_10IdentifierEjPNS_6JSCellERm
@@ -326,6 +329,7 @@ __ZNK3JSC12DateInstance7getTimeERdRi
 __ZNK3JSC12StringObject12toThisStringEPNS_9ExecStateE
 __ZNK3JSC12StringObject8toStringEPNS_9ExecStateE
 __ZNK3JSC14JSGlobalObject14isDynamicScopeEv
+
 __ZNK3JSC16FunctionBodyNode14isHostFunctionEv
 __ZNK3JSC16InternalFunction9classInfoEv
 __ZNK3JSC16JSVariableObject16isVariableObjectEv
index 2d69c7d..462c38f 100644 (file)
             'runtime/LiteralParser.h',
             'runtime/Lookup.cpp',
             'runtime/Lookup.h',
+            'runtime/MarkStack.cpp',
+            'runtime/MarkStack.h',
+            'runtime/MarkStackWin.cpp',
             'runtime/MathObject.cpp',
             'runtime/MathObject.h',
             'runtime/NativeErrorConstructor.cpp',
index 0de4f15..dd48c9a 100644 (file)
@@ -98,6 +98,8 @@ SOURCES += \
     runtime/JSNotAnObject.cpp \
     runtime/JSONObject.cpp \
     runtime/LiteralParser.cpp \
+    runtime/MarkStack.cpp \
+    runtime/MarkStackPosix.cpp \
     runtime/TimeoutChecker.cpp \
     bytecode/CodeBlock.cpp \
     bytecode/StructureStubInfo.cpp \
index 1565d04..1c5e963 100644 (file)
                                >\r
                        </File>\r
                        <File\r
+                               RelativePath="..\..\runtime\MarkStack.h"\r
+                               >\r
+                       </File>\r
+                       <File\r
+                               RelativePath="..\..\runtime\MarkStack.cpp"\r
+                               >\r
+                       </File>\r
+                       <File\r
+                               RelativePath="..\..\runtime\MarkStackWin.cpp"\r
+                               >\r
+                       </File>\r
+                       <File\r
                                RelativePath="..\..\runtime\MathObject.cpp"\r
                                >\r
                        </File>\r
index c48ca1f..6c3d49f 100644 (file)
                A72700900DAC6BBC00E548D7 /* JSNotAnObject.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A72700780DAC605600E548D7 /* JSNotAnObject.cpp */; };
                A72701B90DADE94900E548D7 /* ExceptionHelpers.h in Headers */ = {isa = PBXBuildFile; fileRef = A72701B30DADE94900E548D7 /* ExceptionHelpers.h */; };
                A727FF6B0DA3092200E548D7 /* JSPropertyNameIterator.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A727FF660DA3053B00E548D7 /* JSPropertyNameIterator.cpp */; };
+               A74B3499102A5F8E0032AB98 /* MarkStack.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A74B3498102A5F8E0032AB98 /* MarkStack.cpp */; };
                A766B44F0EE8DCD1009518CA /* ExecutableAllocator.h in Headers */ = {isa = PBXBuildFile; fileRef = A7B48DB50EE74CFC00DCBDB6 /* ExecutableAllocator.h */; settings = {ATTRIBUTES = (Private, ); }; };
                A76EE6590FAE59D5003F069A /* NativeFunctionWrapper.h in Headers */ = {isa = PBXBuildFile; fileRef = A76EE6580FAE59D5003F069A /* NativeFunctionWrapper.h */; settings = {ATTRIBUTES = (Private, ); }; };
+               A7795590101A74D500114E55 /* MarkStack.h in Headers */ = {isa = PBXBuildFile; fileRef = A779558F101A74D500114E55 /* MarkStack.h */; settings = {ATTRIBUTES = (Private, ); }; };
                A782F1A50EEC9FA20036273F /* ExecutableAllocatorPosix.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A782F1A40EEC9FA20036273F /* ExecutableAllocatorPosix.cpp */; };
                A791EF280F11E07900AE1F68 /* JSByteArray.h in Headers */ = {isa = PBXBuildFile; fileRef = A791EF260F11E07900AE1F68 /* JSByteArray.h */; settings = {ATTRIBUTES = (Private, ); }; };
                A791EF290F11E07900AE1F68 /* JSByteArray.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A791EF270F11E07900AE1F68 /* JSByteArray.cpp */; };
                A7A1F7AC0F252B3C00E184E2 /* ByteArray.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A7A1F7AA0F252B3C00E184E2 /* ByteArray.cpp */; };
                A7A1F7AD0F252B3C00E184E2 /* ByteArray.h in Headers */ = {isa = PBXBuildFile; fileRef = A7A1F7AB0F252B3C00E184E2 /* ByteArray.h */; settings = {ATTRIBUTES = (Private, ); }; };
                A7B48F490EE8936F00DCBDB6 /* ExecutableAllocator.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A7B48DB60EE74CFC00DCBDB6 /* ExecutableAllocator.cpp */; };
+               A7C530E4102A3813005BC741 /* MarkStackPosix.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A7C530E3102A3813005BC741 /* MarkStackPosix.cpp */; };
                A7E2EA6B0FB460CF00601F06 /* LiteralParser.h in Headers */ = {isa = PBXBuildFile; fileRef = A7E2EA690FB460CF00601F06 /* LiteralParser.h */; };
                A7E2EA6C0FB460CF00601F06 /* LiteralParser.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A7E2EA6A0FB460CF00601F06 /* LiteralParser.cpp */; };
                A7F9935F0FD7325100A0B2D0 /* JSONObject.h in Headers */ = {isa = PBXBuildFile; fileRef = A7F9935D0FD7325100A0B2D0 /* JSONObject.h */; };
                A72701B30DADE94900E548D7 /* ExceptionHelpers.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ExceptionHelpers.h; sourceTree = "<group>"; };
                A727FF650DA3053B00E548D7 /* JSPropertyNameIterator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSPropertyNameIterator.h; sourceTree = "<group>"; };
                A727FF660DA3053B00E548D7 /* JSPropertyNameIterator.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSPropertyNameIterator.cpp; sourceTree = "<group>"; };
+               A74B3498102A5F8E0032AB98 /* MarkStack.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MarkStack.cpp; sourceTree = "<group>"; };
                A76EE6580FAE59D5003F069A /* NativeFunctionWrapper.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = NativeFunctionWrapper.h; sourceTree = "<group>"; };
+               A779558F101A74D500114E55 /* MarkStack.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MarkStack.h; sourceTree = "<group>"; };
                A782F1A40EEC9FA20036273F /* ExecutableAllocatorPosix.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ExecutableAllocatorPosix.cpp; sourceTree = "<group>"; };
                A791EF260F11E07900AE1F68 /* JSByteArray.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSByteArray.h; sourceTree = "<group>"; };
                A791EF270F11E07900AE1F68 /* JSByteArray.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSByteArray.cpp; sourceTree = "<group>"; };
                A7A1F7AB0F252B3C00E184E2 /* ByteArray.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ByteArray.h; sourceTree = "<group>"; };
                A7B48DB50EE74CFC00DCBDB6 /* ExecutableAllocator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ExecutableAllocator.h; sourceTree = "<group>"; };
                A7B48DB60EE74CFC00DCBDB6 /* ExecutableAllocator.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ExecutableAllocator.cpp; sourceTree = "<group>"; };
+               A7C530E3102A3813005BC741 /* MarkStackPosix.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MarkStackPosix.cpp; sourceTree = "<group>"; };
                A7E2EA690FB460CF00601F06 /* LiteralParser.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LiteralParser.h; sourceTree = "<group>"; };
                A7E2EA6A0FB460CF00601F06 /* LiteralParser.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = LiteralParser.cpp; sourceTree = "<group>"; };
                A7E42C180E3938830065A544 /* JSStaticScopeObject.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSStaticScopeObject.h; sourceTree = "<group>"; };
                                6507D2970E871E4A00D7D896 /* TypeInfo.h */,
                                F692A8850255597D01FF60F7 /* UString.cpp */,
                                F692A8860255597D01FF60F7 /* UString.h */,
+                               A779558F101A74D500114E55 /* MarkStack.h */,
+                               A7C530E3102A3813005BC741 /* MarkStackPosix.cpp */,
+                               A74B3498102A5F8E0032AB98 /* MarkStack.cpp */,
                        );
                        path = runtime;
                        sourceTree = "<group>";
                                1429DAE00ED2645B00B89619 /* WRECGenerator.h in Headers */,
                                1429DABF0ED263E700B89619 /* WRECParser.h in Headers */,
                                9688CB160ED12B4E001D649F /* X86Assembler.h in Headers */,
+                               A7795590101A74D500114E55 /* MarkStack.h in Headers */,
                        );
                        runOnlyForDeploymentPostprocessing = 0;
                };
                                1429DA820ED2482900B89619 /* WRECFunctors.cpp in Sources */,
                                1429DAE10ED2645B00B89619 /* WRECGenerator.cpp in Sources */,
                                1429DAC00ED263E700B89619 /* WRECParser.cpp in Sources */,
+                               A7C530E4102A3813005BC741 /* MarkStackPosix.cpp in Sources */,
+                               A74B3499102A5F8E0032AB98 /* MarkStack.cpp in Sources */,
                        );
                        runOnlyForDeploymentPostprocessing = 0;
                };
index 0a7b2f5..e22f25a 100644 (file)
@@ -1428,20 +1428,21 @@ void CodeBlock::refStructures(Instruction* vPC) const
     ASSERT(vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id) || vPC[0].u.opcode == interpreter->getOpcode(op_put_by_id) || vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id_generic) || vPC[0].u.opcode == interpreter->getOpcode(op_put_by_id_generic));
 }
 
-void CodeBlock::mark()
+void CodeBlock::markAggregate(MarkStack& markStack)
 {
-    for (size_t i = 0; i < m_constantRegisters.size(); ++i)
+    for (size_t i = 0; i < m_constantRegisters.size(); ++i) {
         if (!m_constantRegisters[i].marked())
-            m_constantRegisters[i].mark();
+            markStack.append(m_constantRegisters[i].jsValue());
+    }
 
     for (size_t i = 0; i < m_functionExpressions.size(); ++i)
-        m_functionExpressions[i]->body()->mark();
+        m_functionExpressions[i]->body()->markAggregate(markStack);
 
     if (m_rareData) {
         for (size_t i = 0; i < m_rareData->m_functions.size(); ++i)
-            m_rareData->m_functions[i]->body()->mark();
+            m_rareData->m_functions[i]->body()->markAggregate(markStack);
 
-        m_rareData->m_evalCodeCache.mark();
+        m_rareData->m_evalCodeCache.markAggregate(markStack);
     }
 }
 
index 41cc068..39b1db3 100644 (file)
@@ -255,7 +255,7 @@ namespace JSC {
         CodeBlock(ScopeNode* ownerNode, CodeType, PassRefPtr<SourceProvider>, unsigned sourceOffset);
         ~CodeBlock();
 
-        void mark();
+        void markAggregate(MarkStack&);
         void refStructures(Instruction* vPC) const;
         void derefStructures(Instruction* vPC) const;
 #if ENABLE(JIT_OPTIMIZE_CALL)
index f0ce73e..986525c 100644 (file)
@@ -68,11 +68,11 @@ namespace JSC {
 
         bool isEmpty() const { return m_cacheMap.isEmpty(); }
 
-        void mark()
+        void markAggregate(MarkStack& markStack)
         {
             EvalCacheMap::iterator end = m_cacheMap.end();
             for (EvalCacheMap::iterator ptr = m_cacheMap.begin(); ptr != end; ++ptr)
-                ptr->second->mark();
+                ptr->second->markAggregate(markStack);
         }
     private:
         static const int maxCacheableSourceLength = 256;
index 4b2568f..34d0447 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2008 Apple Inc. All rights reserved.
+ * Copyright (C) 2008, 2009 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -38,11 +38,12 @@ DebuggerActivation::DebuggerActivation(JSObject* activation)
     m_activation = static_cast<JSActivation*>(activation);
 }
 
-void DebuggerActivation::mark()
+void DebuggerActivation::markChildren(MarkStack& markStack)
 {
-    JSObject::mark();
-    if (m_activation && !m_activation->marked())
-        m_activation->mark();
+    JSObject::markChildren(markStack);
+
+    if (m_activation)
+        markStack.append(m_activation);
 }
 
 UString DebuggerActivation::className() const
index 9e1f9f5..82cde4d 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2008 Apple Inc. All rights reserved.
+ * Copyright (C) 2008, 2009 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -36,7 +36,7 @@ namespace JSC {
     public:
         DebuggerActivation(JSObject*);
 
-        virtual void mark();
+        virtual void markChildren(MarkStack&);
         virtual UString className() const;
         virtual bool getOwnPropertySlot(ExecState*, const Identifier& propertyName, PropertySlot&);
         virtual void put(ExecState*, const Identifier& propertyName, JSValue, PutPropertySlot&);
index bead4dc..95ae5f6 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2008 Apple Inc. All rights reserved.
+ * Copyright (C) 2008, 2009 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -56,7 +56,7 @@ namespace JSC {
         JSValue jsValue() const;
 
         bool marked() const;
-        void mark();
+        void markChildren(MarkStack&);
         
         Register(JSActivation*);
         Register(CallFrame*);
@@ -120,11 +120,6 @@ namespace JSC {
         return jsValue().marked();
     }
 
-    ALWAYS_INLINE void Register::mark()
-    {
-        jsValue().mark();
-    }
-    
     // Interpreter functions
 
     ALWAYS_INLINE Register::Register(JSActivation* activation)
index d46bdc9..b5f7452 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2008 Apple Inc. All rights reserved.
+ * Copyright (C) 2008, 2009 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -136,8 +136,8 @@ namespace JSC {
 
         Register* lastGlobal() const { return m_start - m_numGlobals; }
         
-        void markGlobals(Heap* heap) { heap->markConservatively(lastGlobal(), m_start); }
-        void markCallFrames(Heap* heap) { heap->markConservatively(m_start, m_end); }
+        void markGlobals(MarkStack& markStack, Heap* heap) { heap->markConservatively(markStack, lastGlobal(), m_start); }
+        void markCallFrames(MarkStack& markStack, Heap* heap) { heap->markConservatively(markStack, m_start, m_end); }
 
     private:
         void releaseExcessCapacity();
index 65de89c..4324a06 100644 (file)
@@ -1818,14 +1818,14 @@ ScopeNodeData::ScopeNodeData(ParserArena& arena, SourceElements* children, VarSt
         children->releaseContentsIntoVector(m_children);
 }
 
-void ScopeNodeData::mark()
+void ScopeNodeData::markAggregate(MarkStack& markStack)
 {
     FunctionStack::iterator end = m_functionStack.end();
     for (FunctionStack::iterator ptr = m_functionStack.begin(); ptr != end; ++ptr) {
         FunctionBodyNode* body = (*ptr)->body();
         if (!body->isGenerated())
             continue;
-        body->generatedBytecode().mark();
+        body->generatedBytecode().markAggregate(markStack);
     }
 }
 
@@ -1972,10 +1972,10 @@ EvalCodeBlock& EvalNode::bytecodeForExceptionInfoReparse(ScopeChainNode* scopeCh
     return *m_code;
 }
 
-void EvalNode::mark()
+void EvalNode::markAggregate(MarkStack& markStack)
 {
     // We don't need to mark our own CodeBlock as the JSGlobalObject takes care of that
-    data()->mark();
+    data()->markAggregate(markStack);
 }
 
 #if ENABLE(JIT)
@@ -2030,10 +2030,10 @@ void FunctionBodyNode::finishParsing(Identifier* parameters, size_t parameterCou
     m_parameterCount = parameterCount;
 }
 
-void FunctionBodyNode::mark()
+void FunctionBodyNode::markAggregate(MarkStack& markStack)
 {
     if (m_code)
-        m_code->mark();
+        m_code->markAggregate(markStack);
 }
 
 #if ENABLE(JIT)
index 4e5b864..703b384 100644 (file)
@@ -1390,7 +1390,7 @@ namespace JSC {
         int m_numConstants;
         StatementVector m_children;
 
-        void mark();
+        void markAggregate(MarkStack&);
     };
 
     class ScopeNode : public StatementNode, public ParserArenaRefCounted {
@@ -1436,7 +1436,7 @@ namespace JSC {
             return m_data->m_numConstants + 2;
         }
 
-        virtual void mark() { }
+        virtual void markAggregate(MarkStack&) { }
 
 #if ENABLE(JIT)
         JITCode& generatedJITCode()
@@ -1515,7 +1515,7 @@ namespace JSC {
 
         EvalCodeBlock& bytecodeForExceptionInfoReparse(ScopeChainNode*, CodeBlock*);
 
-        virtual void mark();
+        virtual void markAggregate(MarkStack&);
 
 #if ENABLE(JIT)
         JITCode& jitCode(ScopeChainNode* scopeChain)
@@ -1563,7 +1563,7 @@ namespace JSC {
 
         bool isHostFunction() const;
 
-        virtual void mark();
+        virtual void markAggregate(MarkStack&);
 
         void finishParsing(const SourceCode&, ParameterNode*);
         void finishParsing(Identifier* parameters, size_t parameterCount);
index 0b5d958..ab2b5d7 100644 (file)
@@ -1,5 +1,5 @@
 /*
- *  Copyright (C) 2003, 2004, 2005, 2006, 2007 Apple Inc. All rights reserved.
+ *  Copyright (C) 2003, 2004, 2005, 2006, 2007, 2009 Apple Inc. All rights reserved.
  *
  *  This library is free software; you can redistribute it and/or
  *  modify it under the terms of the GNU Library General Public
@@ -37,16 +37,12 @@ void ArgList::getSlice(int startIndex, ArgList& result) const
     result = ArgList(m_args + startIndex, m_argCount - startIndex);
 }
 
-void MarkedArgumentBuffer::markLists(ListSet& markSet)
+void MarkedArgumentBuffer::markLists(MarkStack& markStack, ListSet& markSet)
 {
     ListSet::iterator end = markSet.end();
     for (ListSet::iterator it = markSet.begin(); it != end; ++it) {
         MarkedArgumentBuffer* list = *it;
-
-        iterator end2 = list->end();
-        for (iterator it2 = list->begin(); it2 != end2; ++it2)
-            if (!(*it2).marked())
-                (*it2).mark();
+        markStack.appendValues(reinterpret_cast<JSValue*>(list->m_buffer), list->m_size);
     }
 }
 
index a65f559..ab501b6 100644 (file)
@@ -135,7 +135,7 @@ namespace JSC {
         const_iterator begin() const { return m_buffer; }
         const_iterator end() const { return m_buffer + m_size; }
 
-        static void markLists(ListSet&);
+        static void markLists(MarkStack&, ListSet&);
 
     private:
         void slowAppend(JSValue);
index f867fe8..ec9c450 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *  Copyright (C) 1999-2002 Harri Porten (porten@kde.org)
  *  Copyright (C) 2001 Peter Kelly (pmk@post.com)
- *  Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
+ *  Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights reserved.
  *  Copyright (C) 2007 Cameron Zwarich (cwzwarich@uwaterloo.ca)
  *  Copyright (C) 2007 Maks Orlovich
  *
@@ -43,30 +43,22 @@ Arguments::~Arguments()
         delete [] d->extraArguments;
 }
 
-void Arguments::mark()
+void Arguments::markChildren(MarkStack& markStack)
 {
-    JSObject::mark();
+    JSObject::markChildren(markStack);
 
-    if (d->registerArray) {
-        for (unsigned i = 0; i < d->numParameters; ++i) {
-            if (!d->registerArray[i].marked())
-                d->registerArray[i].mark();
-        }
-    }
+    if (d->registerArray)
+        markStack.appendValues(reinterpret_cast<JSValue*>(d->registerArray.get()), d->numParameters);
 
     if (d->extraArguments) {
         unsigned numExtraArguments = d->numArguments - d->numParameters;
-        for (unsigned i = 0; i < numExtraArguments; ++i) {
-            if (!d->extraArguments[i].marked())
-                d->extraArguments[i].mark();
-        }
+        markStack.appendValues(reinterpret_cast<JSValue*>(d->extraArguments), numExtraArguments);
     }
 
-    if (!d->callee->marked())
-        d->callee->mark();
+    markStack.append(d->callee);
 
-    if (d->activation && !d->activation->marked())
-        d->activation->mark();
+    if (d->activation)
+        markStack.append(d->activation);
 }
 
 void Arguments::copyToRegisters(ExecState* exec, Register* buffer, uint32_t maxSize)
index 0fa944c..79fe720 100644 (file)
@@ -1,6 +1,6 @@
 /*
  *  Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
- *  Copyright (C) 2003, 2006, 2007, 2008 Apple Inc. All rights reserved.
+ *  Copyright (C) 2003, 2006, 2007, 2008, 2009 Apple Inc. All rights reserved.
  *  Copyright (C) 2007 Cameron Zwarich (cwzwarich@uwaterloo.ca)
  *  Copyright (C) 2007 Maks Orlovich
  *
@@ -61,7 +61,7 @@ namespace JSC {
 
         static const ClassInfo info;
 
-        virtual void mark();
+        virtual void markChildren(MarkStack&);
 
         void fillArgList(ExecState*, MarkedArgumentBuffer&);
 
index 9a61980..c188016 100644 (file)
@@ -1,5 +1,5 @@
 /*
- *  Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
+ *  Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights reserved.
  *  Copyright (C) 2007 Eric Seidel <eric@webkit.org>
  *
  *  This library is free software; you can redistribute it and/or
@@ -30,6 +30,7 @@
 #include "JSONObject.h"
 #include "JSString.h"
 #include "JSValue.h"
+#include "MarkStack.h"
 #include "Nodes.h"
 #include "Tracing.h"
 #include <algorithm>
@@ -642,7 +643,7 @@ void Heap::registerThread()
 // cell size needs to be a power of two for this to be valid
 #define IS_HALF_CELL_ALIGNED(p) (((intptr_t)(p) & (CELL_MASK >> 1)) == 0)
 
-void Heap::markConservatively(void* start, void* end)
+void Heap::markConservatively(MarkStack& markStack, void* start, void* end)
 {
     if (start > end) {
         void* tmp = start;
@@ -683,9 +684,8 @@ void Heap::markConservatively(void* start, void* end)
             for (size_t block = 0; block < usedPrimaryBlocks; block++) {
                 if ((primaryBlocks[block] == blockAddr) & (offset <= lastCellOffset)) {
                     if (reinterpret_cast<CollectorCell*>(xAsBits)->u.freeCell.zeroIfFree != 0) {
-                        JSCell* imp = reinterpret_cast<JSCell*>(xAsBits);
-                        if (!imp->marked())
-                            imp->mark();
+                        markStack.append(reinterpret_cast<JSCell*>(xAsBits));
+                        markStack.drain();
                     }
                     break;
                 }
@@ -696,15 +696,15 @@ void Heap::markConservatively(void* start, void* end)
     }
 }
 
-void NEVER_INLINE Heap::markCurrentThreadConservativelyInternal()
+void NEVER_INLINE Heap::markCurrentThreadConservativelyInternal(MarkStack& markStack)
 {
     void* dummy;
     void* stackPointer = &dummy;
     void* stackBase = currentThreadStackBase();
-    markConservatively(stackPointer, stackBase);
+    markConservatively(markStack, stackPointer, stackBase);
 }
 
-void Heap::markCurrentThreadConservatively()
+void Heap::markCurrentThreadConservatively(MarkStack& markStack)
 {
     // setjmp forces volatile registers onto the stack
     jmp_buf registers;
@@ -717,7 +717,7 @@ void Heap::markCurrentThreadConservatively()
 #pragma warning(pop)
 #endif
 
-    markCurrentThreadConservativelyInternal();
+    markCurrentThreadConservativelyInternal(markStack);
 }
 
 #if ENABLE(JSC_MULTIPLE_THREADS)
@@ -849,7 +849,7 @@ static inline void* otherThreadStackPointer(const PlatformThreadRegisters& regs)
 #endif
 }
 
-void Heap::markOtherThreadConservatively(Thread* thread)
+void Heap::markOtherThreadConservatively(MarkStack& markStack, Thread* thread)
 {
     suspendThread(thread->platformThread);
 
@@ -857,19 +857,19 @@ void Heap::markOtherThreadConservatively(Thread* thread)
     size_t regSize = getPlatformThreadRegisters(thread->platformThread, regs);
 
     // mark the thread's registers
-    markConservatively(static_cast<void*>(&regs), static_cast<void*>(reinterpret_cast<char*>(&regs) + regSize));
+    markConservatively(markStack, static_cast<void*>(&regs), static_cast<void*>(reinterpret_cast<char*>(&regs) + regSize));
 
     void* stackPointer = otherThreadStackPointer(regs);
-    markConservatively(stackPointer, thread->stackBase);
+    markConservatively(markStack, stackPointer, thread->stackBase);
 
     resumeThread(thread->platformThread);
 }
 
 #endif
 
-void Heap::markStackObjectsConservatively()
+void Heap::markStackObjectsConservatively(MarkStack& markStack)
 {
-    markCurrentThreadConservatively();
+    markCurrentThreadConservatively(markStack);
 
 #if ENABLE(JSC_MULTIPLE_THREADS)
 
@@ -879,7 +879,7 @@ void Heap::markStackObjectsConservatively()
 
 #ifndef NDEBUG
         // Forbid malloc during the mark phase. Marking a thread suspends it, so 
-        // a malloc inside mark() would risk a deadlock with a thread that had been 
+        // a malloc inside markChildren() would risk a deadlock with a thread that had been 
         // suspended while holding the malloc lock.
         fastMallocForbid();
 #endif
@@ -887,7 +887,7 @@ void Heap::markStackObjectsConservatively()
         // and since this is a shared heap, they are real locks.
         for (Thread* thread = m_registeredThreads; thread; thread = thread->next) {
             if (!pthread_equal(thread->posixThread, pthread_self()))
-                markOtherThreadConservatively(thread);
+                markOtherThreadConservatively(markStack, thread);
         }
 #ifndef NDEBUG
         fastMallocAllow();
@@ -947,7 +947,7 @@ Heap* Heap::heap(JSValue v)
     return Heap::cellBlock(v.asCell())->heap;
 }
 
-void Heap::markProtectedObjects()
+void Heap::markProtectedObjects(MarkStack& markStack)
 {
     if (m_protectedValuesMutex)
         m_protectedValuesMutex->lock();
@@ -955,8 +955,10 @@ void Heap::markProtectedObjects()
     ProtectCountSet::iterator end = m_protectedValues.end();
     for (ProtectCountSet::iterator it = m_protectedValues.begin(); it != end; ++it) {
         JSCell* val = it->first;
-        if (!val->marked())
-            val->mark();
+        if (!val->marked()) {
+            markStack.append(val);
+            markStack.drain();
+        }
     }
 
     if (m_protectedValuesMutex)
@@ -1061,7 +1063,7 @@ template <HeapType heapType> size_t Heap::sweep()
     heap.extraCost = 0;
     return numLiveObjects;
 }
-    
+
 bool Heap::collect()
 {
 #ifndef NDEBUG
@@ -1080,20 +1082,22 @@ bool Heap::collect()
     numberHeap.operationInProgress = Collection;
 
     // MARK: first mark all referenced objects recursively starting out from the set of root objects
-
-    markStackObjectsConservatively();
-    markProtectedObjects();
+    MarkStack& markStack = m_globalData->markStack;
+    markStackObjectsConservatively(markStack);
+    markProtectedObjects(markStack);
     if (m_markListSet && m_markListSet->size())
-        MarkedArgumentBuffer::markLists(*m_markListSet);
+        MarkedArgumentBuffer::markLists(markStack, *m_markListSet);
     if (m_globalData->exception && !m_globalData->exception.marked())
-        m_globalData->exception.mark();
-    m_globalData->interpreter->registerFile().markCallFrames(this);
+        markStack.append(m_globalData->exception);
+    m_globalData->interpreter->registerFile().markCallFrames(markStack, this);
     m_globalData->smallStrings.mark();
     if (m_globalData->scopeNodeBeingReparsed)
-        m_globalData->scopeNodeBeingReparsed->mark();
+        m_globalData->scopeNodeBeingReparsed->markAggregate(markStack);
     if (m_globalData->firstStringifierToMark)
-        JSONObject::markStringifiers(m_globalData->firstStringifierToMark);
+        JSONObject::markStringifiers(markStack, m_globalData->firstStringifierToMark);
 
+    markStack.drain();
+    markStack.compact();
     JAVASCRIPTCORE_GC_MARKED();
 
     size_t originalLiveObjects = primaryHeap.numLiveObjects + numberHeap.numLiveObjects;
index 9a88262..877f890 100644 (file)
 
 namespace JSC {
 
-    class MarkedArgumentBuffer;
     class CollectorBlock;
     class JSCell;
     class JSGlobalData;
     class JSValue;
+    class MarkedArgumentBuffer;
+    class MarkStack;
 
     enum OperationInProgress { NoOperation, Allocation, Collection };
     enum HeapType { PrimaryHeap, NumberHeap };
@@ -111,7 +112,7 @@ namespace JSC {
         static bool isCellMarked(const JSCell*);
         static void markCell(JSCell*);
 
-        void markConservatively(void* start, void* end);
+        void markConservatively(MarkStack&, void* start, void* end);
 
         HashSet<MarkedArgumentBuffer*>& markListSet() { if (!m_markListSet) m_markListSet = new HashSet<MarkedArgumentBuffer*>; return *m_markListSet; }
 
@@ -133,11 +134,11 @@ namespace JSC {
         ~Heap();
 
         void recordExtraCost(size_t);
-        void markProtectedObjects();
-        void markCurrentThreadConservatively();
-        void markCurrentThreadConservativelyInternal();
-        void markOtherThreadConservatively(Thread*);
-        void markStackObjectsConservatively();
+        void markProtectedObjects(MarkStack&);
+        void markCurrentThreadConservatively(MarkStack&);
+        void markCurrentThreadConservativelyInternal(MarkStack&);
+        void markOtherThreadConservatively(MarkStack&, Thread*);
+        void markStackObjectsConservatively(MarkStack&);
 
         typedef HashCountedSet<JSCell*> ProtectCountSet;
 
index cd1b40a..cc85354 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *  Copyright (C) 1999-2002 Harri Porten (porten@kde.org)
  *  Copyright (C) 2001 Peter Kelly (pmk@post.com)
- *  Copyright (C) 2004, 2007, 2008 Apple Inc. All rights reserved.
+ *  Copyright (C) 2004, 2007, 2008, 2009 Apple Inc. All rights reserved.
  *
  *  This library is free software; you can redistribute it and/or
  *  modify it under the terms of the GNU Library General Public
 
 namespace JSC {
 
-void GetterSetter::mark()
+void GetterSetter::markChildren(MarkStack& markStack)
 {
-    JSCell::mark();
+    JSCell::markChildren(markStack);
 
     if (m_getter && !m_getter->marked())
-        m_getter->mark();
+        markStack.append(m_getter);
     if (m_setter && !m_setter->marked())
-        m_setter->mark();
+        markStack.append(m_setter);
 }
 
 JSValue GetterSetter::toPrimitive(ExecState*, PreferredPrimitiveType) const
index e6b74a1..67c1473 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *  Copyright (C) 1999-2001 Harri Porten (porten@kde.org)
  *  Copyright (C) 2001 Peter Kelly (pmk@post.com)
- *  Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
+ *  Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights reserved.
  *
  *  This library is free software; you can redistribute it and/or
  *  modify it under the terms of the GNU Library General Public
@@ -33,20 +33,23 @@ namespace JSC {
     // for a property.
     class GetterSetter : public JSCell {
     public:
-        GetterSetter()
-            : JSCell(0)
+        GetterSetter(ExecState* exec)
+            : JSCell(exec->globalData().getterSetterStructure.get())
             , m_getter(0)
             , m_setter(0)
         {
         }
 
-        virtual void mark();
+        virtual void markChildren(MarkStack&);
 
         JSObject* getter() const { return m_getter; }
         void setGetter(JSObject* getter) { m_getter = getter; }
         JSObject* setter() const { return m_setter; }
         void setSetter(JSObject* setter) { m_setter = setter; }
-
+        static PassRefPtr<Structure> createStructure(JSValue prototype)
+        {
+            return Structure::create(prototype, TypeInfo(GetterSetterType));
+        }
     private:
         virtual bool isGetterSetter() const;
 
index b0d4c25..3074f95 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *  Copyright (C) 1999-2002 Harri Porten (porten@kde.org)
  *  Copyright (C) 2001 Peter Kelly (pmk@post.com)
- *  Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
+ *  Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights reserved.
  *  Copyright (C) 2007 Cameron Zwarich (cwzwarich@uwaterloo.ca)
  *  Copyright (C) 2007 Maks Orlovich
  *
@@ -39,11 +39,10 @@ GlobalEvalFunction::GlobalEvalFunction(ExecState* exec, PassRefPtr<Structure> st
     ASSERT_ARG(cachedGlobalObject, cachedGlobalObject);
 }
 
-void GlobalEvalFunction::mark()
+void GlobalEvalFunction::markChildren(MarkStack& markStack)
 {
-    PrototypeFunction::mark();
-    if (!m_cachedGlobalObject->marked())
-        m_cachedGlobalObject->mark();
+    PrototypeFunction::markChildren(markStack);
+    markStack.append(m_cachedGlobalObject);
 }
 
 } // namespace JSC
index 49b1847..cdba4a0 100644 (file)
@@ -1,6 +1,6 @@
 /*
  *  Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
- *  Copyright (C) 2003, 2006, 2007, 2008 Apple Inc. All rights reserved.
+ *  Copyright (C) 2003, 2006, 2007, 2008, 2009 Apple Inc. All rights reserved.
  *  Copyright (C) 2007 Cameron Zwarich (cwzwarich@uwaterloo.ca)
  *  Copyright (C) 2007 Maks Orlovich
  *
@@ -36,7 +36,7 @@ namespace JSC {
         JSGlobalObject* cachedGlobalObject() const { return m_cachedGlobalObject; }
 
     private:
-        virtual void mark();
+        virtual void markChildren(MarkStack&);
 
         JSGlobalObject* m_cachedGlobalObject;
     };
index e16fbba..21a9710 100644 (file)
@@ -26,6 +26,7 @@
 #include <wtf/Platform.h>
 
 #include "JSCell.h"
+#include "CallFrame.h"
 
 namespace JSC {
 
@@ -42,10 +43,15 @@ namespace JSC {
         virtual double toNumber(ExecState*) const;
         virtual UString toString(ExecState*) const;
         virtual JSObject* toObject(ExecState*) const;
+        static PassRefPtr<Structure> createStructure(JSValue prototype)
+        {
+            return Structure::create(prototype, TypeInfo(CompoundType));
+        }
 
+        
     private:
-        JSAPIValueWrapper(JSValue value)
-            : JSCell(0)
+        JSAPIValueWrapper(ExecState* exec, JSValue value)
+            : JSCell(exec->globalData().apiWrapperStructure.get())
             , m_value(value)
         {
         }
@@ -55,7 +61,7 @@ namespace JSC {
 
     inline JSValue jsAPIValueWrapper(ExecState* exec, JSValue value)
     {
-        return new (exec) JSAPIValueWrapper(value);
+        return new (exec) JSAPIValueWrapper(exec, value);
     }
 
 } // namespace JSC
index 3bef263..87adbcd 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2008 Apple Inc. All rights reserved.
+ * Copyright (C) 2008, 2009 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -49,9 +49,9 @@ JSActivation::~JSActivation()
     delete d();
 }
 
-void JSActivation::mark()
+void JSActivation::markChildren(MarkStack& markStack)
 {
-    Base::mark();
+    Base::markChildren(markStack);
 
     Register* registerArray = d()->registerArray.get();
     if (!registerArray)
@@ -59,25 +59,13 @@ void JSActivation::mark()
 
     size_t numParametersMinusThis = d()->functionBody->generatedBytecode().m_numParameters - 1;
 
-    size_t i = 0;
-    size_t count = numParametersMinusThis; 
-    for ( ; i < count; ++i) {
-        Register& r = registerArray[i];
-        if (!r.marked())
-            r.mark();
-    }
+    size_t count = numParametersMinusThis;
+    markStack.appendValues(registerArray, count);
 
     size_t numVars = d()->functionBody->generatedBytecode().m_numVars;
 
     // Skip the call frame, which sits between the parameters and vars.
-    i += RegisterFile::CallFrameHeaderSize;
-    count += RegisterFile::CallFrameHeaderSize + numVars;
-
-    for ( ; i < count; ++i) {
-        Register& r = registerArray[i];
-        if (r.jsValue() && !r.marked())
-            r.mark();
-    }
+    markStack.appendValues(registerArray + count + RegisterFile::CallFrameHeaderSize, numVars, MayContainNullValues);
 }
 
 bool JSActivation::getOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot& slot)
index c183dac..6a08439 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2008 Apple Inc. All rights reserved.
+ * Copyright (C) 2008, 2009 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -46,7 +46,7 @@ namespace JSC {
         JSActivation(CallFrame*, PassRefPtr<FunctionBodyNode>);
         virtual ~JSActivation();
 
-        virtual void mark();
+        virtual void markChildren(MarkStack&);
 
         virtual bool isDynamicScope() const;
 
index 708ef99..7d7d4c4 100644 (file)
@@ -1,6 +1,6 @@
 /*
  *  Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
- *  Copyright (C) 2003, 2007, 2008 Apple Inc. All rights reserved.
+ *  Copyright (C) 2003, 2007, 2008, 2009 Apple Inc. All rights reserved.
  *  Copyright (C) 2003 Peter Kelly (pmk@post.com)
  *  Copyright (C) 2006 Alexey Proskuryakov (ap@nypop.com)
  *
@@ -601,26 +601,19 @@ void JSArray::push(ExecState* exec, JSValue value)
     putSlowCase(exec, m_storage->m_length++, value);
 }
 
-void JSArray::mark()
+void JSArray::markChildren(MarkStack& markStack)
 {
-    JSObject::mark();
+    JSObject::markChildren(markStack);
 
     ArrayStorage* storage = m_storage;
 
     unsigned usedVectorLength = min(storage->m_length, storage->m_vectorLength);
-    for (unsigned i = 0; i < usedVectorLength; ++i) {
-        JSValue value = storage->m_vector[i];
-        if (value && !value.marked())
-            value.mark();
-    }
+    markStack.appendValues(storage->m_vector, usedVectorLength, MayContainNullValues);
 
     if (SparseArrayValueMap* map = storage->m_sparseValueMap) {
         SparseArrayValueMap::iterator end = map->end();
-        for (SparseArrayValueMap::iterator it = map->begin(); it != end; ++it) {
-            JSValue value = it->second;
-            if (!value.marked())
-                value.mark();
-        }
+        for (SparseArrayValueMap::iterator it = map->begin(); it != end; ++it)
+            markStack.append(it->second);
     }
 }
 
index ea490d8..49df6c4 100644 (file)
@@ -1,6 +1,6 @@
 /*
  *  Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
- *  Copyright (C) 2003, 2007, 2008 Apple Inc. All rights reserved.
+ *  Copyright (C) 2003, 2007, 2008, 2009 Apple Inc. All rights reserved.
  *
  *  This library is free software; you can redistribute it and/or
  *  modify it under the terms of the GNU Lesser General Public
@@ -88,7 +88,7 @@ namespace JSC {
         virtual bool deleteProperty(ExecState*, const Identifier& propertyName);
         virtual bool deleteProperty(ExecState*, unsigned propertyName);
         virtual void getPropertyNames(ExecState*, PropertyNameArray&);
-        virtual void mark();
+        virtual void markChildren(MarkStack&);
 
         void* lazyCreationData();
         void setLazyCreationData(void*);
index 024371c..75ccf7f 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *  Copyright (C) 1999-2001 Harri Porten (porten@kde.org)
  *  Copyright (C) 2001 Peter Kelly (pmk@post.com)
- *  Copyright (C) 2003, 2004, 2005, 2007, 2008 Apple Inc. All rights reserved.
+ *  Copyright (C) 2003, 2004, 2005, 2007, 2008, 2009 Apple Inc. All rights reserved.
  *
  *  This library is free software; you can redistribute it and/or
  *  modify it under the terms of the GNU Library General Public
@@ -85,7 +85,9 @@ namespace JSC {
         void* operator new(size_t, ExecState*);
         void* operator new(size_t, JSGlobalData*);
         void* operator new(size_t, void* placementNewDestination) { return placementNewDestination; }
-        virtual void mark();
+
+        void markCellDirect();
+        virtual void markChildren(MarkStack&);
         bool marked() const;
 
         // Object operations, with the toObject operation included.
@@ -153,9 +155,14 @@ namespace JSC {
         return Heap::isCellMarked(this);
     }
 
-    inline void JSCell::mark()
+    inline void JSCell::markCellDirect()
+    {
+        Heap::markCell(this);
+    }
+
+    inline void JSCell::markChildren(MarkStack&)
     {
-        return Heap::markCell(this);
+        ASSERT(marked());
     }
 
     inline void* JSCell::operator new(size_t size, JSGlobalData* globalData)
@@ -224,9 +231,16 @@ namespace JSC {
         return false;
     }
 
-    inline void JSValue::mark()
+    inline void JSValue::markDirect()
     {
-        asCell()->mark(); // callers should check !marked() before calling mark(), so this should only be called with cells
+        ASSERT(!marked());
+        asCell()->markCellDirect();
+    }
+
+    inline void JSValue::markChildren(MarkStack& markStack)
+    {
+        ASSERT(marked());
+        asCell()->markChildren(markStack);
     }
 
     inline bool JSValue::marked() const
@@ -339,6 +353,12 @@ namespace JSC {
             return asCell()->getJSNumber();
         return JSValue();
     }
+    
+    inline bool JSValue::hasChildren() const
+    {
+        return asCell()->structure()->typeInfo().type() >= CompoundType;
+    }
+    
 
     inline JSObject* JSValue::toObject(ExecState* exec) const
     {
@@ -350,6 +370,39 @@ namespace JSC {
         return isCell() ? asCell()->toThisObject(exec) : toThisObjectSlowCase(exec);
     }
 
+    ALWAYS_INLINE void MarkStack::append(JSCell* cell)
+    {
+        ASSERT(cell);
+        if (cell->marked())
+            return;
+        cell->markCellDirect();
+        if (cell->structure()->typeInfo().type() >= CompoundType)
+            m_values.append(cell);
+    }
+
+    inline void MarkStack::drain() {
+        while (!m_markSets.isEmpty() || !m_values.isEmpty()) {
+            while ((!m_markSets.isEmpty()) && m_values.size() < 50) {
+                const MarkSet& current = m_markSets.removeLast();
+                JSValue* ptr = current.m_values;
+                JSValue* end = current.m_end;
+                if (current.m_properties == NoNullValues) {
+                    while (ptr != end)
+                        append(*ptr++);
+                } else {
+                    while (ptr != end) {
+                        if (JSValue value = *ptr++)
+                            append(value);
+                    }
+                }
+            }
+            while (!m_values.isEmpty()) {
+                JSCell* current = m_values.removeLast();
+                ASSERT(current->marked());
+                current->markChildren(*this);
+            }
+        }
+    }
 } // namespace JSC
 
 #endif // JSCell_h
index 7fedad7..84c6263 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *  Copyright (C) 1999-2002 Harri Porten (porten@kde.org)
  *  Copyright (C) 2001 Peter Kelly (pmk@post.com)
- *  Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
+ *  Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights reserved.
  *  Copyright (C) 2007 Cameron Zwarich (cwzwarich@uwaterloo.ca)
  *  Copyright (C) 2007 Maks Orlovich
  *
@@ -83,12 +83,12 @@ JSFunction::~JSFunction()
         scopeChain().~ScopeChain(); // FIXME: Don't we need to do this in the interpreter too?
 }
 
-void JSFunction::mark()
+void JSFunction::markChildren(MarkStack& markStack)
 {
-    Base::mark();
-    m_body->mark();
+    Base::markChildren(markStack);
+    m_body->markAggregate(markStack);
     if (!isHostFunction())
-        scopeChain().mark();
+        scopeChain().markAggregate(markStack);
 }
 
 CallType JSFunction::getCallData(CallData& callData)
index 19b1261..cab1e5b 100644 (file)
@@ -68,7 +68,7 @@ namespace JSC {
         void setBody(PassRefPtr<FunctionBodyNode> body) { m_body = body; }
         FunctionBodyNode* body() const { return m_body.get(); }
 
-        virtual void mark();
+        virtual void markChildren(MarkStack&);
 
         static JS_EXPORTDATA const ClassInfo info;
 
index 156d102..03df41d 100644 (file)
 #include "Collector.h"
 #include "CommonIdentifiers.h"
 #include "FunctionConstructor.h"
+#include "GetterSetter.h"
 #include "Interpreter.h"
 #include "JSActivation.h"
+#include "JSAPIValueWrapper.h"
 #include "JSArray.h"
 #include "JSByteArray.h"
 #include "JSClassRef.h"
 #include "JSFunction.h"
 #include "JSLock.h"
 #include "JSNotAnObject.h"
+#include "JSPropertyNameIterator.h"
 #include "JSStaticScopeObject.h"
 #include "Parser.h"
 #include "Lexer.h"
@@ -118,6 +121,9 @@ JSGlobalData::JSGlobalData(bool isShared, const VPtrSet& vptrSet)
     , stringStructure(JSString::createStructure(jsNull()))
     , notAnObjectErrorStubStructure(JSNotAnObjectErrorStub::createStructure(jsNull()))
     , notAnObjectStructure(JSNotAnObject::createStructure(jsNull()))
+    , propertyNameIteratorStructure(JSPropertyNameIterator::createStructure(jsNull()))
+    , getterSetterStructure(GetterSetter::createStructure(jsNull()))
+    , apiWrapperStructure(JSAPIValueWrapper::createStructure(jsNull()))
 #if USE(JSVALUE32)
     , numberStructure(JSNumberCell::createStructure(jsNull()))
 #endif
index 7434d99..88cb516 100644 (file)
@@ -33,6 +33,7 @@
 #include "ExecutableAllocator.h"
 #include "JITStubs.h"
 #include "JSValue.h"
+#include "MarkStack.h"
 #include "SmallStrings.h"
 #include "TimeoutChecker.h"
 #include <wtf/Forward.h>
@@ -97,6 +98,10 @@ namespace JSC {
         RefPtr<Structure> stringStructure;
         RefPtr<Structure> notAnObjectErrorStubStructure;
         RefPtr<Structure> notAnObjectStructure;
+        RefPtr<Structure> propertyNameIteratorStructure;
+        RefPtr<Structure> getterSetterStructure;
+        RefPtr<Structure> apiWrapperStructure;
+
 #if USE(JSVALUE32)
         RefPtr<Structure> numberStructure;
 #endif
@@ -143,6 +148,7 @@ namespace JSC {
         ScopeNode* scopeNodeBeingReparsed;
         Stringifier* firstStringifierToMark;
 
+        MarkStack markStack;
     private:
         JSGlobalData(bool isShared, const VPtrSet&);
         static JSGlobalData*& sharedInstanceInternal();
index 9cbc65c..a90f18f 100644 (file)
@@ -80,16 +80,16 @@ static const int initialTickCountThreshold = 255;
 // Preferred number of milliseconds between each timeout check
 static const int preferredScriptCheckTimeInterval = 1000;
 
-static inline void markIfNeeded(JSValue v)
+static inline void markIfNeeded(MarkStack& markStack, JSValue v)
 {
-    if (v && !v.marked())
-        v.mark();
+    if (v)
+        markStack.append(v);
 }
 
-static inline void markIfNeeded(const RefPtr<Structure>& s)
+static inline void markIfNeeded(MarkStack& markStack, const RefPtr<Structure>& s)
 {
     if (s)
-        s->mark();
+        s->markAggregate(markStack);
 }
 
 JSGlobalObject::~JSGlobalObject()
@@ -357,43 +357,43 @@ void JSGlobalObject::resetPrototype(JSValue prototype)
         oldLastInPrototypeChain->setPrototype(objectPrototype);
 }
 
-void JSGlobalObject::mark()
+void JSGlobalObject::markChildren(MarkStack& markStack)
 {
-    JSVariableObject::mark();
+    JSVariableObject::markChildren(markStack);
     
     HashSet<ProgramCodeBlock*>::const_iterator end = codeBlocks().end();
     for (HashSet<ProgramCodeBlock*>::const_iterator it = codeBlocks().begin(); it != end; ++it)
-        (*it)->mark();
+        (*it)->markAggregate(markStack);
 
     RegisterFile& registerFile = globalData()->interpreter->registerFile();
     if (registerFile.globalObject() == this)
-        registerFile.markGlobals(&globalData()->heap);
-
-    markIfNeeded(d()->regExpConstructor);
-    markIfNeeded(d()->errorConstructor);
-    markIfNeeded(d()->evalErrorConstructor);
-    markIfNeeded(d()->rangeErrorConstructor);
-    markIfNeeded(d()->referenceErrorConstructor);
-    markIfNeeded(d()->syntaxErrorConstructor);
-    markIfNeeded(d()->typeErrorConstructor);
-    markIfNeeded(d()->URIErrorConstructor);
-
-    markIfNeeded(d()->evalFunction);
-    markIfNeeded(d()->callFunction);
-    markIfNeeded(d()->applyFunction);
-
-    markIfNeeded(d()->objectPrototype);
-    markIfNeeded(d()->functionPrototype);
-    markIfNeeded(d()->arrayPrototype);
-    markIfNeeded(d()->booleanPrototype);
-    markIfNeeded(d()->stringPrototype);
-    markIfNeeded(d()->numberPrototype);
-    markIfNeeded(d()->datePrototype);
-    markIfNeeded(d()->regExpPrototype);
-
-    markIfNeeded(d()->methodCallDummy);
-
-    markIfNeeded(d()->errorStructure);
+        registerFile.markGlobals(markStack, &globalData()->heap);
+
+    markIfNeeded(markStack, d()->regExpConstructor);
+    markIfNeeded(markStack, d()->errorConstructor);
+    markIfNeeded(markStack, d()->evalErrorConstructor);
+    markIfNeeded(markStack, d()->rangeErrorConstructor);
+    markIfNeeded(markStack, d()->referenceErrorConstructor);
+    markIfNeeded(markStack, d()->syntaxErrorConstructor);
+    markIfNeeded(markStack, d()->typeErrorConstructor);
+    markIfNeeded(markStack, d()->URIErrorConstructor);
+
+    markIfNeeded(markStack, d()->evalFunction);
+    markIfNeeded(markStack, d()->callFunction);
+    markIfNeeded(markStack, d()->applyFunction);
+
+    markIfNeeded(markStack, d()->objectPrototype);
+    markIfNeeded(markStack, d()->functionPrototype);
+    markIfNeeded(markStack, d()->arrayPrototype);
+    markIfNeeded(markStack, d()->booleanPrototype);
+    markIfNeeded(markStack, d()->stringPrototype);
+    markIfNeeded(markStack, d()->numberPrototype);
+    markIfNeeded(markStack, d()->datePrototype);
+    markIfNeeded(markStack, d()->regExpPrototype);
+
+    markIfNeeded(markStack, d()->methodCallDummy);
+
+    markIfNeeded(markStack, d()->errorStructure);
 
     // No need to mark the other structures, because their prototypes are all
     // guaranteed to be referenced elsewhere.
@@ -403,11 +403,7 @@ void JSGlobalObject::mark()
         return;
 
     size_t size = d()->registerArraySize;
-    for (size_t i = 0; i < size; ++i) {
-        Register& r = registerArray[i];
-        if (!r.marked())
-            r.mark();
-    }
+    markStack.appendValues(reinterpret_cast<JSValue*>(registerArray), size);
 }
 
 ExecState* JSGlobalObject::globalExec()
index 755a7e1..cda49bd 100644 (file)
@@ -1,6 +1,6 @@
 /*
  *  Copyright (C) 2007 Eric Seidel <eric@webkit.org>
- *  Copyright (C) 2007, 2008 Apple Inc. All rights reserved.
+ *  Copyright (C) 2007, 2008, 2009 Apple Inc. All rights reserved.
  *
  *  This library is free software; you can redistribute it and/or
  *  modify it under the terms of the GNU Library General Public
@@ -166,7 +166,7 @@ namespace JSC {
     public:
         virtual ~JSGlobalObject();
 
-        virtual void mark();
+        virtual void markChildren(MarkStack&);
 
         virtual bool getOwnPropertySlot(ExecState*, const Identifier&, PropertySlot&);
         virtual bool hasOwnPropertyForWrite(ExecState*, const Identifier&);
index 937dc2b..a542a9f 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2008 Apple Inc. All rights reserved.
+ * Copyright (C) 2008, 2009 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -74,11 +74,10 @@ JSObject* JSNotAnObject::toObject(ExecState* exec) const
 }
 
 // Marking
-void JSNotAnObject::mark()
+void JSNotAnObject::markChildren(MarkStack& markStack)
 {
-    JSCell::mark();
-    if (!m_exception->marked())
-        m_exception->mark();
+    JSObject::markChildren(markStack);
+    markStack.append(m_exception);
 }
 
 // JSObject methods
index a8e36bd..b65ff5f 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2008 Apple Inc. All rights reserved.
+ * Copyright (C) 2008, 2009 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -75,7 +75,7 @@ namespace JSC {
         virtual JSObject* toObject(ExecState*) const;
 
         // Marking
-        virtual void mark();
+        virtual void markChildren(MarkStack&);
 
         // JSObject methods
         virtual bool getOwnPropertySlot(ExecState*, const Identifier& propertyName, PropertySlot&);
index 0d447f5..d643808 100644 (file)
@@ -67,7 +67,7 @@ public:
     ~Stringifier();
     JSValue stringify(JSValue);
 
-    void mark();
+    void markAggregate(MarkStack&);
 
 private:
     typedef UString StringBuilder;
@@ -221,15 +221,12 @@ Stringifier::~Stringifier()
     m_exec->globalData().firstStringifierToMark = m_nextStringifierToMark;
 }
 
-void Stringifier::mark()
+void Stringifier::markAggregate(MarkStack& markStack)
 {
     for (Stringifier* stringifier = this; stringifier; stringifier = stringifier->m_nextStringifierToMark) {
         size_t size = m_holderStack.size();
-        for (size_t i = 0; i < size; ++i) {
-            JSObject* object = m_holderStack[i].object();
-            if (!object->marked())
-                object->mark();
-        }
+        for (size_t i = 0; i < size; ++i)
+            markStack.append(m_holderStack[i].object());
     }
 }
 
@@ -584,9 +581,9 @@ bool JSONObject::getOwnPropertySlot(ExecState* exec, const Identifier& propertyN
     return true;
 }
 
-void JSONObject::markStringifiers(Stringifier* stringifier)
+void JSONObject::markStringifiers(MarkStack& markStack, Stringifier* stringifier)
 {
-    stringifier->mark();
+    stringifier->markAggregate(markStack);
 }
 
 class Walker {
index 8d5364a..faca7c7 100644 (file)
@@ -44,7 +44,7 @@ namespace JSC {
             return Structure::create(prototype, TypeInfo(ObjectType));
         }
 
-        static void markStringifiers(Stringifier*);
+        static void markStringifiers(MarkStack&, Stringifier*);
 
     private:
         virtual bool getOwnPropertySlot(ExecState*, const Identifier&, PropertySlot&);
index 415c25d..419dfe9 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *  Copyright (C) 1999-2001 Harri Porten (porten@kde.org)
  *  Copyright (C) 2001 Peter Kelly (pmk@post.com)
- *  Copyright (C) 2003, 2004, 2005, 2006, 2008 Apple Inc. All rights reserved.
+ *  Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009 Apple Inc. All rights reserved.
  *  Copyright (C) 2007 Eric Seidel (eric@webkit.org)
  *
  *  This library is free software; you can redistribute it and/or
@@ -62,21 +62,16 @@ namespace JSC {
 
 ASSERT_CLASS_FITS_IN_CELL(JSObject);
 
-void JSObject::mark()
+void JSObject::markChildren(MarkStack& markStack)
 {
     JSOBJECT_MARK_BEGIN();
 
-    JSCell::mark();
-    m_structure->mark();
+    JSCell::markChildren(markStack);
+    m_structure->markAggregate(markStack);
 
     PropertyStorage storage = propertyStorage();
-
     size_t storageSize = m_structure->propertyStorageSize();
-    for (size_t i = 0; i < storageSize; ++i) {
-        JSValue v = JSValue::decode(storage[i]);
-        if (!v.marked())
-            v.mark();
-    }
+    markStack.appendValues(reinterpret_cast<JSValue*>(storage), storageSize);
 
     JSOBJECT_MARK_END();
 }
@@ -310,7 +305,7 @@ void JSObject::defineGetter(ExecState* exec, const Identifier& propertyName, JSO
     }
 
     PutPropertySlot slot;
-    GetterSetter* getterSetter = new (exec) GetterSetter;
+    GetterSetter* getterSetter = new (exec) GetterSetter(exec);
     putDirectInternal(exec->globalData(), propertyName, getterSetter, Getter, true, slot);
 
     // putDirect will change our Structure if we add a new property. For
@@ -337,7 +332,7 @@ void JSObject::defineSetter(ExecState* exec, const Identifier& propertyName, JSO
     }
 
     PutPropertySlot slot;
-    GetterSetter* getterSetter = new (exec) GetterSetter;
+    GetterSetter* getterSetter = new (exec) GetterSetter(exec);
     putDirectInternal(exec->globalData(), propertyName, getterSetter, Setter, true, slot);
 
     // putDirect will change our Structure if we add a new property. For
index 1a19a23..decd5e9 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *  Copyright (C) 1999-2001 Harri Porten (porten@kde.org)
  *  Copyright (C) 2001 Peter Kelly (pmk@post.com)
- *  Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
+ *  Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights reserved.
  *
  *  This library is free software; you can redistribute it and/or
  *  modify it under the terms of the GNU Library General Public
@@ -73,7 +73,7 @@ namespace JSC {
     public:
         explicit JSObject(PassRefPtr<Structure>);
 
-        virtual void mark();
+        virtual void markChildren(MarkStack&);
 
         // The inline virtual destructor cannot be the first virtual function declared
         // in the class as it results in the vtable being generated as a weak symbol
index 8c7b53d..dc0304f 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2008 Apple Inc. All rights reserved.
+ * Copyright (C) 2008, 2009 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -73,11 +73,11 @@ JSObject* JSPropertyNameIterator::toObject(ExecState*) const
     return 0;
 }
 
-void JSPropertyNameIterator::mark()
+void JSPropertyNameIterator::markChildren(MarkStack& markStack)
 {
-    JSCell::mark();
-    if (m_object && !m_object->marked())
-        m_object->mark();
+    JSCell::markChildren(markStack);
+    if (m_object)
+        markStack.append(m_object);
 }
 
 void JSPropertyNameIterator::invalidate()
index 9817c07..4534528 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2008 Apple Inc. All rights reserved.
+ * Copyright (C) 2008, 2009 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -51,14 +51,18 @@ namespace JSC {
         virtual UString toString(ExecState*) const;
         virtual JSObject* toObject(ExecState*) const;
 
-        virtual void mark();
+        virtual void markChildren(MarkStack&);
 
         JSValue next(ExecState*);
         void invalidate();
-
+        
+        static PassRefPtr<Structure> createStructure(JSValue prototype)
+        {
+            return Structure::create(prototype, TypeInfo(CompoundType));
+        }
     private:
-        JSPropertyNameIterator();
-        JSPropertyNameIterator(JSObject*, PassRefPtr<PropertyNameArrayData> propertyNameArrayData);
+        JSPropertyNameIterator(ExecState*);
+        JSPropertyNameIterator(ExecState*, JSObject*, PassRefPtr<PropertyNameArrayData> propertyNameArrayData);
 
         JSObject* m_object;
         RefPtr<PropertyNameArrayData> m_data;
@@ -66,16 +70,16 @@ namespace JSC {
         PropertyNameArrayData::const_iterator m_end;
     };
 
-inline JSPropertyNameIterator::JSPropertyNameIterator()
-    : JSCell(0)
+inline JSPropertyNameIterator::JSPropertyNameIterator(ExecState* exec)
+    : JSCell(exec->globalData().propertyNameIteratorStructure.get())
     , m_object(0)
     , m_position(0)
     , m_end(0)
 {
 }
 
-inline JSPropertyNameIterator::JSPropertyNameIterator(JSObject* object, PassRefPtr<PropertyNameArrayData> propertyNameArrayData)
-    : JSCell(0)
+inline JSPropertyNameIterator::JSPropertyNameIterator(ExecState* exec, JSObject* object, PassRefPtr<PropertyNameArrayData> propertyNameArrayData)
+    : JSCell(exec->globalData().propertyNameIteratorStructure.get())
     , m_object(object)
     , m_data(propertyNameArrayData)
     , m_position(m_data->begin())
@@ -86,12 +90,12 @@ inline JSPropertyNameIterator::JSPropertyNameIterator(JSObject* object, PassRefP
 inline JSPropertyNameIterator* JSPropertyNameIterator::create(ExecState* exec, JSValue v)
 {
     if (v.isUndefinedOrNull())
-        return new (exec) JSPropertyNameIterator;
+        return new (exec) JSPropertyNameIterator(exec);
 
     JSObject* o = v.toObject(exec);
     PropertyNameArray propertyNames(exec);
     o->getPropertyNames(exec, propertyNames);
-    return new (exec) JSPropertyNameIterator(o, propertyNames.releaseData());
+    return new (exec) JSPropertyNameIterator(exec, o, propertyNames.releaseData());
 }
 
 inline JSValue JSPropertyNameIterator::next(ExecState* exec)
index 85907c8..a877ec6 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2008 Apple Inc. All Rights Reserved.
+ * Copyright (C) 2008, 2009 Apple Inc. All Rights Reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -31,12 +31,10 @@ namespace JSC {
 
 ASSERT_CLASS_FITS_IN_CELL(JSStaticScopeObject);
 
-void JSStaticScopeObject::mark()
+void JSStaticScopeObject::markChildren(MarkStack& markStack)
 {
-    JSVariableObject::mark();
-    
-    if (!d()->registerStore.marked())
-        d()->registerStore.mark();
+    JSVariableObject::markChildren(markStack);
+    markStack.append(d()->registerStore.jsValue());
 }
 
 JSObject* JSStaticScopeObject::toThisObject(ExecState* exec) const
index 2caf540..5eb0e4b 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2008 Apple Inc. All Rights Reserved.
+ * Copyright (C) 2008, 2009 Apple Inc. All Rights Reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -50,7 +50,7 @@ namespace JSC{
             symbolTable().add(ident.ustring().rep(), SymbolTableEntry(-1, attributes));
         }
         virtual ~JSStaticScopeObject();
-        virtual void mark();
+        virtual void markChildren(MarkStack&);
         bool isDynamicScope() const;
         virtual JSObject* toThisObject(ExecState*) const;
         virtual bool getOwnPropertySlot(ExecState*, const Identifier&, PropertySlot&);
index 68f2890..a118b87 100644 (file)
@@ -33,8 +33,11 @@ namespace JSC {
         NumberType        = 3,
         NullType          = 4,
         StringType        = 5,
-        ObjectType        = 6,
-        GetterSetterType  = 7
+        
+        // The CompoundType value must come before any JSType that may have children
+        CompoundType      = 6,
+        ObjectType        = 7,
+        GetterSetterType  = 8
     };
 
 } // namespace JSC
index cbf8fc5..408c187 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *  Copyright (C) 1999-2001 Harri Porten (porten@kde.org)
  *  Copyright (C) 2001 Peter Kelly (pmk@post.com)
- *  Copyright (C) 2003, 2004, 2005, 2007, 2008 Apple Inc. All rights reserved.
+ *  Copyright (C) 2003, 2004, 2005, 2007, 2008, 2009 Apple Inc. All rights reserved.
  *
  *  This library is free software; you can redistribute it and/or
  *  modify it under the terms of the GNU Library General Public
@@ -42,6 +42,7 @@ namespace JSC {
     class JSImmediate;
     class JSObject;
     class JSString;
+    class MarkStack;
     class PropertySlot;
     class PutPropertySlot;
     class UString;
@@ -172,8 +173,10 @@ namespace JSC {
         float toFloat(ExecState* exec) const { return static_cast<float>(toNumber(exec)); }
 
         // Garbage collection.
-        void mark();
+        void markChildren(MarkStack&);
+        bool hasChildren() const;
         bool marked() const;
+        void markDirect();
 
         // Object operations, with the toObject operation included.
         JSValue get(ExecState*, const Identifier& propertyName) const;
index fb57018..2c39f5c 100644 (file)
@@ -1,6 +1,6 @@
 /*
  *  Copyright (C) 2006 Maks Orlovich
- *  Copyright (C) 2006 Apple Computer, Inc.
+ *  Copyright (C) 2006, 2009 Apple, Inc.
  *
  *  This library is free software; you can redistribute it and/or
  *  modify it under the terms of the GNU Library General Public
@@ -26,11 +26,11 @@ namespace JSC {
 
 ASSERT_CLASS_FITS_IN_CELL(JSWrapperObject);
 
-void JSWrapperObject::mark(
+void JSWrapperObject::markChildren(MarkStack& markStack
 {
-    JSObject::mark();
-    if (m_internalValue && !m_internalValue.marked())
-        m_internalValue.mark();
+    JSObject::markChildren(markStack);
+    if (m_internalValue)
+        markStack.append(m_internalValue);
 }
 
 } // namespace JSC
index 2a2e3c6..0b2c680 100644 (file)
@@ -36,7 +36,7 @@ namespace JSC {
         JSValue internalValue() const { return m_internalValue; }
         void setInternalValue(JSValue);
         
-        virtual void mark();
+        virtual void markChildren(MarkStack&);
         
     private:
         JSValue m_internalValue;
diff --git a/JavaScriptCore/runtime/MarkStack.cpp b/JavaScriptCore/runtime/MarkStack.cpp
new file mode 100644 (file)
index 0000000..80dbb17
--- /dev/null
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2009 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+ */
+
+#include "config.h"
+#include "MarkStack.h"
+
+namespace JSC
+{
+
+size_t MarkStack::s_pageSize = 0;
+
+void MarkStack::compact()
+{
+    ASSERT(s_pageSize);
+    m_values.shrinkAllocation(s_pageSize);
+    m_markSets.shrinkAllocation(s_pageSize);
+}
+
+}
diff --git a/JavaScriptCore/runtime/MarkStack.h b/JavaScriptCore/runtime/MarkStack.h
new file mode 100644 (file)
index 0000000..4ec221e
--- /dev/null
@@ -0,0 +1,170 @@
+/*
+ * Copyright (C) 2009 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+ */
+
+#ifndef MarkStack_h
+#define MarkStack_h
+
+#include "JSValue.h"
+
+#include <wtf/Noncopyable.h>
+
+namespace JSC {
+    class Register;
+    
+    enum MarkSetProperties { MayContainNullValues, NoNullValues };
+    
+    class MarkStack : Noncopyable {
+    public:
+        MarkStack()
+            : m_markSets()
+            , m_values()
+        {
+        }
+
+        ALWAYS_INLINE void append(JSValue value)
+        {
+            ASSERT(value);
+            if (value.marked())
+                return;
+            value.markDirect();
+            if (value.hasChildren())
+                m_values.append(value.asCell());
+        }
+
+        ALWAYS_INLINE void append(JSCell* cell);
+        
+        ALWAYS_INLINE void appendValues(Register* values, size_t count, MarkSetProperties properties = NoNullValues)
+        {
+            appendValues(reinterpret_cast<JSValue*>(values), count, properties);
+        }
+
+        ALWAYS_INLINE void appendValues(JSValue* values, size_t count, MarkSetProperties properties = NoNullValues)
+        {
+            if (count)
+                m_markSets.append(MarkSet(values, values + count, properties));
+        }
+
+        inline void drain();
+        void compact();
+
+        ~MarkStack()
+        {
+            ASSERT(m_markSets.isEmpty());
+            ASSERT(m_values.isEmpty());
+        }
+
+    private:
+        struct MarkSet {
+            MarkSet(JSValue* values, JSValue* end, MarkSetProperties properties)
+                : m_values(values)
+                , m_end(end)
+                , m_properties(properties)
+            {
+            }
+            JSValue* m_values;
+            JSValue* m_end;
+            MarkSetProperties m_properties;
+        };
+
+        static void* allocateStack(size_t size);
+        static void releaseStack(void* addr, size_t size);
+
+        static size_t pageSize()
+        {
+            if (!s_pageSize)
+                s_pageSize = getpagesize();
+            return s_pageSize;
+        }
+
+        template <typename T> struct MarkStackArray {
+            MarkStackArray()
+                : m_top(0)
+                , m_allocated(MarkStack::pageSize())
+                , m_capacity(m_allocated / sizeof(T))
+            {
+                m_data = reinterpret_cast<T*>(allocateStack(m_allocated));
+            }
+
+            ~MarkStackArray()
+            {
+                releaseStack(m_data, m_allocated);
+            }
+
+            void expand()
+            {
+                size_t oldAllocation = m_allocated;
+                m_allocated *= 2;
+                m_capacity = m_allocated / sizeof(T);
+                void* newData = allocateStack(m_allocated);
+                memcpy(newData, m_data, oldAllocation);
+                releaseStack(m_data, oldAllocation);
+                m_data = reinterpret_cast<T*>(newData);
+            }
+
+            inline void append(const T& v)
+            {
+                if (m_top == m_capacity)
+                    expand();
+                m_data[m_top++] = v;
+            }
+
+            inline T removeLast()
+            {
+                ASSERT(m_top);
+                return m_data[--m_top];
+            }
+
+            inline bool isEmpty()
+            {
+                return m_top == 0;
+            }
+
+            inline size_t size() { return m_top; }
+
+            inline void shrinkAllocation(size_t size)
+            {
+                ASSERT(size <= m_allocated);
+                ASSERT(0 == (size % MarkStack::pageSize()));
+                if (size == m_allocated)
+                    return;
+                releaseStack(reinterpret_cast<char*>(m_data) + size, m_allocated - size);
+                m_allocated = size;
+                m_capacity = m_allocated / sizeof(T);
+            }
+
+        private:
+            size_t m_top;
+            size_t m_allocated;
+            size_t m_capacity;
+            T* m_data;
+        };
+
+        MarkStackArray<MarkSet> m_markSets;
+        MarkStackArray<JSCell*> m_values;
+        static size_t s_pageSize;
+    };
+}
+
+#endif
diff --git a/JavaScriptCore/runtime/MarkStackPosix.cpp b/JavaScriptCore/runtime/MarkStackPosix.cpp
new file mode 100644 (file)
index 0000000..c41d382
--- /dev/null
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2009 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+ */
+
+#include "config.h"
+
+
+#include "MarkStack.h"
+#include <sys/mman.h>
+
+namespace JSC {
+void* MarkStack::allocateStack(size_t size)
+{
+    return mmap(0, size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON, -1, 0);
+}
+void MarkStack::releaseStack(void* addr, size_t size)
+{
+    munmap(addr, size);
+}
+
+}
diff --git a/JavaScriptCore/runtime/MarkStackWin.cpp b/JavaScriptCore/runtime/MarkStackWin.cpp
new file mode 100644 (file)
index 0000000..46dc488
--- /dev/null
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2009 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+ */
+
+#include "config.h"
+
+
+#include "MarkStack.h"
+
+#include "windows.h"
+
+namespace JSC {
+void* MarkStack::allocateStack(size_t size)
+{
+    return VirtualAlloc(0, size, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
+}
+void MarkStack::releaseStack(void* addr, size_t size)
+{
+    VirtualFree(addr, size, MEM_RELEASE);
+}
+
+}
index 17aff24..23b361e 100644 (file)
@@ -1,5 +1,5 @@
 /*
- *  Copyright (C) 2003, 2008 Apple Inc. All rights reserved.
+ *  Copyright (C) 2003, 2008, 2009 Apple Inc. All rights reserved.
  *
  *  This library is free software; you can redistribute it and/or
  *  modify it under the terms of the GNU Library General Public
@@ -204,7 +204,7 @@ namespace JSC {
         
         JSGlobalObject* globalObject() const { return m_node->globalObject(); }
 
-        void mark() const;
+        void markAggregate(MarkStack&) const;
 
         // Caution: this should only be used if the codeblock this is being used
         // with needs a full scope chain, otherwise this returns the depth of
index b80b8ef..984d101 100644 (file)
@@ -1,5 +1,5 @@
 /*
- *  Copyright (C) 2003, 2006, 2008 Apple Inc. All rights reserved.
+ *  Copyright (C) 2003, 2006, 2008, 2009 Apple Inc. All rights reserved.
  *
  *  This library is free software; you can redistribute it and/or
  *  modify it under the terms of the GNU Library General Public
 
 namespace JSC {
 
-    inline void ScopeChain::mark() const
+    inline void ScopeChain::markAggregate(MarkStack& markStack) const
     {
-        for (ScopeChainNode* n = m_node; n; n = n->next) {
-            JSObject* o = n->object;
-            if (!o->marked())
-                o->mark();
-        }
+        for (ScopeChainNode* n = m_node; n; n = n->next)
+            markStack.append(n->object);
     }
 
 } // namespace JSC
index 9d1f01a..2f92cc1 100644 (file)
@@ -85,10 +85,10 @@ SmallStrings::~SmallStrings()
 void SmallStrings::mark()
 {
     if (m_emptyString && !m_emptyString->marked())
-        m_emptyString->mark();
+        m_emptyString->markCellDirect();
     for (unsigned i = 0; i < numCharactersToStore; ++i) {
         if (m_singleCharacterStrings[i] && !m_singleCharacterStrings[i]->marked())
-            m_singleCharacterStrings[i]->mark();
+            m_singleCharacterStrings[i]->markCellDirect();
     }
 }
 
index 866999d..f3a0c7c 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2008 Apple Inc. All rights reserved.
+ * Copyright (C) 2008, 2009 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -29,6 +29,7 @@
 #include "Identifier.h"
 #include "JSType.h"
 #include "JSValue.h"
+#include "MarkStack.h"
 #include "PropertyMapHashTable.h"
 #include "StructureChain.h"
 #include "StructureTransitionTable.h"
@@ -72,10 +73,9 @@ namespace JSC {
 
         ~Structure();
 
-        void mark()
+        void markAggregate(MarkStack& markStack)
         {
-            if (!m_prototype.marked())
-                m_prototype.mark();
+            markStack.append(m_prototype);
         }
 
         // These should be used with caution.  
index f8220ff..502a764 100644 (file)
@@ -1,3 +1,21 @@
+2009-08-07  Oliver Hunt  <oliver@apple.com>
+
+        Reviewed by Sam Weinig.
+
+        Stack overflow crash in JavaScript garbage collector mark pass
+        https://bugs.webkit.org/show_bug.cgi?id=12216
+
+        Make JSGlue interact with the new iterative mark logic.
+
+        * JSValueWrapper.cpp:
+        (JSValueWrapper::JSObjectMark):
+          Unfortunately JSGlue exposes recursive marking so we can only flatten
+          the recursion.  We just create a local mark stack if necessary and mark
+          the given object iteratively from this point.
+        * UserObjectImp.cpp:
+        (UserObjectImp::markChildren):
+        * UserObjectImp.h:
+
 2009-08-06  Mark Rowe  <mrowe@apple.com>
 
         Rubber-stamped by Sam Weinig.
index bf2aa9c..d649d4a 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2005 Apple Computer, Inc.  All rights reserved.
+ * Copyright (C) 2005, 2009 Apple Computer, Inc.  All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -194,8 +194,11 @@ CFTypeRef JSValueWrapper::JSObjectCopyCFValue(void *data)
 void JSValueWrapper::JSObjectMark(void *data)
 {
     JSValueWrapper* ptr = (JSValueWrapper*)data;
-    if (ptr)
+    if (ptr && !ptr->fValue.get().marked())
     {
-        ptr->fValue.get().mark();
+        // This results in recursive marking but will be otherwise safe and correct.
+        MarkStack markStack;
+        markStack.append(ptr->fValue.get());
+        markStack.drain();
     }
 }
index cf7c278..4e64ab1 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2005, 2008 Apple Inc. All rights reserved.
+ * Copyright (C) 2005, 2008, 2009 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -409,9 +409,9 @@ UString UserObjectImp::toString(ExecState *exec) const
     return result;
 }
 
-void UserObjectImp::mark()
+void UserObjectImp::markChildren(MarkStack& markStack)
 {
-    JSObject::mark();
+    JSObject::markChildren(markStack);
     if (fJSUserObject)
         fJSUserObject->Mark();
 }
index ec48758..9791658 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2005, 2008 Apple Inc. All rights reserved.
+ * Copyright (C) 2005, 2008, 2009 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -55,7 +55,7 @@ public:
     virtual double toNumber(ExecState *exec) const;
     virtual UString toString(ExecState *exec) const;
 
-    virtual void mark();
+    virtual void markChildren(MarkStack&);
 
     JSUserObject *GetJSUserObject() const;
 
index 2da8331..7c9aae3 100644 (file)
@@ -1,3 +1,18 @@
+2009-08-07  Oliver Hunt  <oliver@apple.com>
+
+        Reviewed by Sam Weinig.
+
+        Stack overflow crash in JavaScript garbage collector mark pass
+        https://bugs.webkit.org/show_bug.cgi?id=12216
+
+        Add a testcase that requires marking of a deeply nested object.
+
+        * fast/js/nested-object-gc-expected.txt: Added.
+        * fast/js/nested-object-gc.html: Added.
+        * fast/js/resources/js-test-pre.js:
+            Add a gc() function that triggers a gc or calls the gc controller if it's present
+        * fast/js/resources/nested-object-gc.js: Added.
+
 2009-08-10  Jeremy Orlow  <jorlow@chromium.org>
 
         Reviewed by Brady Eidson.
diff --git a/LayoutTests/fast/js/nested-object-gc-expected.txt b/LayoutTests/fast/js/nested-object-gc-expected.txt
new file mode 100644 (file)
index 0000000..1b908c2
--- /dev/null
@@ -0,0 +1,9 @@
+This test checks whether garbage collection can handle deeply nested objects. It passes if the test does not crash.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
diff --git a/LayoutTests/fast/js/nested-object-gc.html b/LayoutTests/fast/js/nested-object-gc.html
new file mode 100644 (file)
index 0000000..926934a
--- /dev/null
@@ -0,0 +1,13 @@
+<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
+<html>
+<head>
+<link rel="stylesheet" href="resources/js-test-style.css">
+<script src="resources/js-test-pre.js"></script>
+</head>
+<body>
+<p id="description"></p>
+<div id="console"></div>
+<script src="resources/nested-object-gc.js"></script>
+<script src="resources/js-test-post.js"></script>
+</body>
+</html>
index e439706..1a673b8 100644 (file)
@@ -186,3 +186,19 @@ function shouldThrow(_a, _e)
   else
     testFailed(_a + " should throw " + (typeof _e == "undefined" ? "an exception" : _ev) + ". Was " + _av + ".");
 }
+
+function gc() {
+    if (typeof GCController !== "undefined")
+        GCController.collect();
+    else {
+        function gcRec(n) {
+            if (n < 1)
+                return {};
+            var temp = {i: "ab" + i + (i / 100000)};
+            temp += "foo";
+            gcRec(n-1);
+        }
+        for (var i = 0; i < 1000; i++)
+            gcRec(10)
+    }
+}
diff --git a/LayoutTests/fast/js/resources/nested-object-gc.js b/LayoutTests/fast/js/resources/nested-object-gc.js
new file mode 100644 (file)
index 0000000..6eccc12
--- /dev/null
@@ -0,0 +1,15 @@
+description(
+"This test checks whether garbage collection can handle deeply nested objects.  It passes if the test does not crash."
+);
+
+var start = new Date;
+var o = {};
+var a = [];
+for (var i = 0; i < 250000; i++) {
+    o = {o:o};
+    a=[a];
+}
+
+gc();
+
+successfullyParsed = true;
\ No newline at end of file
index 82e6b74..e20185c 100644 (file)
@@ -1,3 +1,88 @@
+2009-08-07  Oliver Hunt  <oliver@apple.com>
+
+        Reviewed by Sam Weinig
+
+        Stack overflow crash in JavaScript garbage collector mark pass
+        https://bugs.webkit.org/show_bug.cgi?id=12216
+
+        Make WebCore use the new iterative marking logic.
+
+        Tests: fast/js/nested-object-gc.html
+
+        * bindings/js/JSAbstractWorkerCustom.cpp:
+        (WebCore::JSAbstractWorker::markChildren):
+        * bindings/js/JSDOMApplicationCacheCustom.cpp:
+        (WebCore::JSDOMApplicationCache::markChildren):
+        * bindings/js/JSDOMBinding.cpp:
+        (WebCore::markDOMNodesForDocument):
+        (WebCore::markActiveObjectsForContext):
+        (WebCore::markDOMObjectWrapper):
+        * bindings/js/JSDOMBinding.h:
+        (WebCore::DOMObjectWithGlobalPointer::markChildren):
+        * bindings/js/JSDOMGlobalObject.cpp:
+        (WebCore::JSDOMGlobalObject::markChildren):
+        * bindings/js/JSDOMGlobalObject.h:
+        * bindings/js/JSDOMWindowCustom.cpp:
+        (WebCore::JSDOMWindow::markChildren):
+        * bindings/js/JSDOMWindowShell.cpp:
+        (WebCore::JSDOMWindowShell::markChildren):
+        * bindings/js/JSDOMWindowShell.h:
+        * bindings/js/JSDedicatedWorkerContextCustom.cpp:
+        (WebCore::JSDedicatedWorkerContext::markChildren):
+        * bindings/js/JSDocumentCustom.cpp:
+        (WebCore::JSDocument::markChildren):
+        * bindings/js/JSEventListener.cpp:
+        (WebCore::JSEventListener::markJSFunction):
+        * bindings/js/JSEventListener.h:
+        * bindings/js/JSMessageChannelCustom.cpp:
+        (WebCore::JSMessageChannel::markChildren):
+        * bindings/js/JSMessagePortCustom.cpp:
+        (WebCore::JSMessagePort::markChildren):
+        * bindings/js/JSNavigatorCustom.cpp:
+        (WebCore::JSNavigator::markChildren):
+        * bindings/js/JSNodeCustom.cpp:
+        (WebCore::JSNode::markChildren):
+        * bindings/js/JSNodeFilterCondition.cpp:
+        (WebCore::JSNodeFilterCondition::markAggregate):
+        * bindings/js/JSNodeFilterCondition.h:
+        * bindings/js/JSNodeFilterCustom.cpp:
+        (WebCore::JSNodeFilter::markChildren):
+        * bindings/js/JSNodeIteratorCustom.cpp:
+        (WebCore::JSNodeIterator::markChildren):
+        * bindings/js/JSQuarantinedObjectWrapper.cpp:
+        (WebCore::JSQuarantinedObjectWrapper::markChildren):
+        * bindings/js/JSQuarantinedObjectWrapper.h:
+        * bindings/js/JSSVGElementInstanceCustom.cpp:
+        (WebCore::JSSVGElementInstance::markChildren):
+        * bindings/js/JSSharedWorkerCustom.cpp:
+        (WebCore::JSSharedWorker::markChildren):
+        * bindings/js/JSStyleSheetCustom.cpp:
+        (WebCore::JSStyleSheet::markChildren):
+        * bindings/js/JSTreeWalkerCustom.cpp:
+        (WebCore::JSTreeWalker::markChildren):
+        * bindings/js/JSWebSocketCustom.cpp:
+        (WebCore::JSWebSocket::markChildren):
+        * bindings/js/JSWorkerContextCustom.cpp:
+        (WebCore::JSWorkerContext::markChildren):
+        * bindings/js/JSWorkerCustom.cpp:
+        (WebCore::JSWorker::markChildren):
+        * bindings/js/JSXMLHttpRequestCustom.cpp:
+        (WebCore::JSXMLHttpRequest::markChildren):
+        * bindings/js/JSXMLHttpRequestUploadCustom.cpp:
+        (WebCore::JSXMLHttpRequestUpload::markChildren):
+        * bindings/scripts/CodeGeneratorJS.pm:
+        * dom/EventListener.h:
+        (WebCore::EventListener::markJSFunction):
+        (WebCore::markIfNotNull):
+        * dom/NodeFilter.h:
+        (WebCore::NodeFilter::markAggregate):
+        * dom/NodeFilterCondition.h:
+        (WebCore::NodeFilterCondition::markAggregate):
+        * dom/RegisteredEventListener.h:
+        (WebCore::markEventListeners):
+        * page/DOMWindow.h:
+        * workers/WorkerContext.h:
+
 2009-08-10  Jeremy Orlow  <jorlow@chromium.org>
 
         Reviewed by Eric Seidel.
index 3146413..003f544 100644 (file)
@@ -1,5 +1,6 @@
 /*
  * Copyright (C) 2009 Google Inc. All rights reserved.
+ * Copyright (C) 2009 Apple, Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions are
@@ -43,18 +44,18 @@ using namespace JSC;
 
 namespace WebCore {
 
-void JSAbstractWorker::mark()
+void JSAbstractWorker::markChildren(MarkStack& markStack)
 {
-    Base::mark();
+    Base::markChildren(markStack);
 
-    markIfNotNull(m_impl->onerror());
+    markIfNotNull(markStack, m_impl->onerror());
 
     typedef AbstractWorker::EventListenersMap EventListenersMap;
     typedef AbstractWorker::ListenerVector ListenerVector;
     EventListenersMap& eventListeners = m_impl->eventListeners();
     for (EventListenersMap::iterator mapIter = eventListeners.begin(); mapIter != eventListeners.end(); ++mapIter) {
         for (ListenerVector::iterator vecIter = mapIter->second.begin(); vecIter != mapIter->second.end(); ++vecIter)
-            (*vecIter)->markJSFunction();
+            (*vecIter)->markJSFunction(markStack);
     }
 }
 
index a7fae78..109308c 100644 (file)
@@ -42,25 +42,25 @@ using namespace JSC;
 
 namespace WebCore {
 
-void JSDOMApplicationCache::mark()
+void JSDOMApplicationCache::markChildren(MarkStack& markStack)
 {
-    Base::mark();
+    Base::markChildren(markStack);
 
-    markIfNotNull(m_impl->onchecking());
-    markIfNotNull(m_impl->onerror());
-    markIfNotNull(m_impl->onnoupdate());
-    markIfNotNull(m_impl->ondownloading());
-    markIfNotNull(m_impl->onprogress());
-    markIfNotNull(m_impl->onupdateready());
-    markIfNotNull(m_impl->oncached());
-    markIfNotNull(m_impl->onobsolete());
+    markIfNotNull(markStack, m_impl->onchecking());
+    markIfNotNull(markStack, m_impl->onerror());
+    markIfNotNull(markStack, m_impl->onnoupdate());
+    markIfNotNull(markStack, m_impl->ondownloading());
+    markIfNotNull(markStack, m_impl->onprogress());
+    markIfNotNull(markStack, m_impl->onupdateready());
+    markIfNotNull(markStack, m_impl->oncached());
+    markIfNotNull(markStack, m_impl->onobsolete());
 
     typedef DOMApplicationCache::EventListenersMap EventListenersMap;
     typedef DOMApplicationCache::ListenerVector ListenerVector;
     EventListenersMap& eventListeners = m_impl->eventListeners();
     for (EventListenersMap::iterator mapIter = eventListeners.begin(); mapIter != eventListeners.end(); ++mapIter) {
         for (ListenerVector::iterator vecIter = mapIter->second.begin(); vecIter != mapIter->second.end(); ++vecIter)
-            (*vecIter)->markJSFunction();
+            (*vecIter)->markJSFunction(markStack);
     }
 }
 
index c9b6d80..566b986 100644 (file)
@@ -293,18 +293,18 @@ static inline bool isObservableThroughDOM(JSNode* jsNode)
     return false;
 }
 
-void markDOMNodesForDocument(Document* doc)
+void markDOMNodesForDocument(MarkStack& markStack, Document* doc)
 {
     JSWrapperCache& nodeDict = doc->wrapperCache();
     JSWrapperCache::iterator nodeEnd = nodeDict.end();
     for (JSWrapperCache::iterator nodeIt = nodeDict.begin(); nodeIt != nodeEnd; ++nodeIt) {
         JSNode* jsNode = nodeIt->second;
-        if (!jsNode->marked() && isObservableThroughDOM(jsNode))
-            jsNode->mark();
+        if (isObservableThroughDOM(jsNode))
+            markStack.append(jsNode);
     }
 }
 
-void markActiveObjectsForContext(JSGlobalData& globalData, ScriptExecutionContext* scriptExecutionContext)
+void markActiveObjectsForContext(MarkStack& markStack, JSGlobalData& globalData, ScriptExecutionContext* scriptExecutionContext)
 {
     // If an element has pending activity that may result in event listeners being called
     // (e.g. an XMLHttpRequest), we need to keep JS wrappers alive.
@@ -317,8 +317,8 @@ void markActiveObjectsForContext(JSGlobalData& globalData, ScriptExecutionContex
             // Generally, an active object with pending activity must have a wrapper to mark its listeners.
             // However, some ActiveDOMObjects don't have JS wrappers (timers created by setTimeout is one example).
             // FIXME: perhaps need to make sure even timers have a markable 'wrapper'.
-            if (wrapper && !wrapper->marked())
-                wrapper->mark();
+            if (wrapper)
+                markStack.append(wrapper);
         }
     }
 
@@ -328,8 +328,8 @@ void markActiveObjectsForContext(JSGlobalData& globalData, ScriptExecutionContex
         // If the message port is remotely entangled, then always mark it as in-use because we can't determine reachability across threads.
         if (!(*iter)->locallyEntangledPort() || (*iter)->hasPendingActivity()) {
             DOMObject* wrapper = getCachedDOMObjectWrapper(globalData, *iter);
-            if (wrapper && !wrapper->marked())
-                wrapper->mark();
+            if (wrapper)
+                markStack.append(wrapper);
         }
     }
 }
@@ -346,14 +346,14 @@ void updateDOMNodeDocument(Node* node, Document* oldDocument, Document* newDocum
     addWrapper(wrapper);
 }
 
-void markDOMObjectWrapper(JSGlobalData& globalData, void* object)
+void markDOMObjectWrapper(MarkStack& markStack, JSGlobalData& globalData, void* object)
 {
     if (!object)
         return;
     DOMObject* wrapper = getCachedDOMObjectWrapper(globalData, object);
-    if (!wrapper || wrapper->marked())
+    if (!wrapper)
         return;
-    wrapper->mark();
+    markStack.append(wrapper);
 }
 
 JSValue jsStringOrNull(ExecState* exec, const String& s)
index 3975940..64cfc3a 100644 (file)
@@ -1,6 +1,6 @@
 /*
  *  Copyright (C) 1999-2001 Harri Porten (porten@kde.org)
- *  Copyright (C) 2003, 2004, 2005, 2006, 2008 Apple Inc. All rights reserved.
+ *  Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009 Apple Inc. All rights reserved.
  *  Copyright (C) 2007 Samuel Weinig <sam@webkit.org>
  *  Copyright (C) 2009 Google, Inc. All rights reserved.
  *
@@ -85,11 +85,10 @@ namespace WebCore {
         }
         virtual ~DOMObjectWithGlobalPointer() {}
 
-        void mark()
+        void markChildren(JSC::MarkStack& markStack)
         {
-            DOMObject::mark();
-            if (!m_globalObject->marked())
-                m_globalObject->mark();
+            DOMObject::markChildren(markStack);
+            markStack.append(m_globalObject);
         }
 
     private:
@@ -137,9 +136,9 @@ namespace WebCore {
     void forgetDOMNode(Document*, Node*);
     void forgetAllDOMNodesForDocument(Document*);
     void updateDOMNodeDocument(Node*, Document* oldDocument, Document* newDocument);
-    void markDOMNodesForDocument(Document*);
-    void markActiveObjectsForContext(JSC::JSGlobalData&, ScriptExecutionContext*);
-    void markDOMObjectWrapper(JSC::JSGlobalData& globalData, void* object);
+    void markDOMNodesForDocument(JSC::MarkStack&, Document*);
+    void markActiveObjectsForContext(JSC::MarkStack&, JSC::JSGlobalData&, ScriptExecutionContext*);
+    void markDOMObjectWrapper(JSC::MarkStack&, JSC::JSGlobalData& globalData, void* object);
 
     JSC::Structure* getCachedDOMStructure(JSDOMGlobalObject*, const JSC::ClassInfo*);
     JSC::Structure* cacheDOMStructure(JSDOMGlobalObject*, PassRefPtr<JSC::Structure>, const JSC::ClassInfo*);
index e3617a4..68a1db9 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2008 Apple Inc. All Rights Reserved.
+ * Copyright (C) 2008, 2009 Apple Inc. All Rights Reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -58,19 +58,17 @@ JSDOMGlobalObject::~JSDOMGlobalObject()
         it->second->clearGlobalObject();
 }
 
-void JSDOMGlobalObject::mark()
+void JSDOMGlobalObject::markChildren(MarkStack& markStack)
 {
-    Base::mark();
+    Base::markChildren(markStack);
 
     JSDOMStructureMap::iterator end = structures().end();
     for (JSDOMStructureMap::iterator it = structures().begin(); it != end; ++it)
-        it->second->mark();
+        it->second->markAggregate(markStack);
 
     JSDOMConstructorMap::iterator end2 = constructors().end();
-    for (JSDOMConstructorMap::iterator it2 = constructors().begin(); it2 != end2; ++it2) {
-        if (!it2->second->marked())
-            it2->second->mark();
-    }
+    for (JSDOMConstructorMap::iterator it2 = constructors().begin(); it2 != end2; ++it2)
+        markStack.append(it2->second);
 }
 
 JSEventListener* JSDOMGlobalObject::findJSEventListener(JSValue val)
index c9b09ef..855691c 100644 (file)
@@ -74,7 +74,7 @@ namespace WebCore {
         void setCurrentEvent(Event*);
         Event* currentEvent() const;
 
-        virtual void mark();
+        virtual void markChildren(JSC::MarkStack&);
 
     protected:
         struct JSDOMGlobalObjectData : public JSC::JSGlobalObject::JSGlobalObjectData {
index 33ac7bb..9798972 100644 (file)
@@ -68,32 +68,32 @@ using namespace JSC;
 
 namespace WebCore {
 
-void JSDOMWindow::mark()
+void JSDOMWindow::markChildren(MarkStack& markStack)
 {
-    Base::mark();
+    Base::markChildren(markStack);
 
-    markEventListeners(impl()->eventListeners());
+    markEventListeners(markStack, impl()->eventListeners());
 
     JSGlobalData& globalData = *Heap::heap(this)->globalData();
 
-    markDOMObjectWrapper(globalData, impl()->optionalConsole());
-    markDOMObjectWrapper(globalData, impl()->optionalHistory());
-    markDOMObjectWrapper(globalData, impl()->optionalLocationbar());
-    markDOMObjectWrapper(globalData, impl()->optionalMenubar());
-    markDOMObjectWrapper(globalData, impl()->optionalNavigator());
-    markDOMObjectWrapper(globalData, impl()->optionalPersonalbar());
-    markDOMObjectWrapper(globalData, impl()->optionalScreen());
-    markDOMObjectWrapper(globalData, impl()->optionalScrollbars());
-    markDOMObjectWrapper(globalData, impl()->optionalSelection());
-    markDOMObjectWrapper(globalData, impl()->optionalStatusbar());
-    markDOMObjectWrapper(globalData, impl()->optionalToolbar());
-    markDOMObjectWrapper(globalData, impl()->optionalLocation());
+    markDOMObjectWrapper(markStack, globalData, impl()->optionalConsole());
+    markDOMObjectWrapper(markStack, globalData, impl()->optionalHistory());
+    markDOMObjectWrapper(markStack, globalData, impl()->optionalLocationbar());
+    markDOMObjectWrapper(markStack, globalData, impl()->optionalMenubar());
+    markDOMObjectWrapper(markStack, globalData, impl()->optionalNavigator());
+    markDOMObjectWrapper(markStack, globalData, impl()->optionalPersonalbar());
+    markDOMObjectWrapper(markStack, globalData, impl()->optionalScreen());
+    markDOMObjectWrapper(markStack, globalData, impl()->optionalScrollbars());
+    markDOMObjectWrapper(markStack, globalData, impl()->optionalSelection());
+    markDOMObjectWrapper(markStack, globalData, impl()->optionalStatusbar());
+    markDOMObjectWrapper(markStack, globalData, impl()->optionalToolbar());
+    markDOMObjectWrapper(markStack, globalData, impl()->optionalLocation());
 #if ENABLE(DOM_STORAGE)
-    markDOMObjectWrapper(globalData, impl()->optionalSessionStorage());
-    markDOMObjectWrapper(globalData, impl()->optionalLocalStorage());
+    markDOMObjectWrapper(markStack, globalData, impl()->optionalSessionStorage());
+    markDOMObjectWrapper(markStack, globalData, impl()->optionalLocalStorage());
 #endif
 #if ENABLE(OFFLINE_WEB_APPLICATIONS)
-    markDOMObjectWrapper(globalData, impl()->optionalApplicationCache());
+    markDOMObjectWrapper(markStack, globalData, impl()->optionalApplicationCache());
 #endif
 }
 
index 1bf478b..efffd42 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2008 Apple Inc. All rights reserved.
+ * Copyright (C) 2008, 2009 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -71,11 +71,11 @@ void JSDOMWindowShell::setWindow(PassRefPtr<DOMWindow> domWindow)
 // JSObject methods
 // ----
 
-void JSDOMWindowShell::mark()
+void JSDOMWindowShell::markChildren(MarkStack& markStack)
 {
-    Base::mark();
-    if (m_window && !m_window->marked())
-        m_window->mark();
+    Base::markChildren(markStack);
+    if (m_window)
+        markStack.append(m_window);
 }
 
 UString JSDOMWindowShell::className() const
index 6f21892..0506283 100644 (file)
@@ -64,7 +64,7 @@ namespace WebCore {
         }
 
     private:
-        virtual void mark();
+        virtual void markChildren(JSC::MarkStack&);
         virtual JSC::UString className() const;
         virtual bool getOwnPropertySlot(JSC::ExecState*, const JSC::Identifier& propertyName, JSC::PropertySlot&);
         virtual void put(JSC::ExecState*, const JSC::Identifier& propertyName, JSC::JSValue, JSC::PutPropertySlot&);
index c45a6a3..657f9b3 100644 (file)
@@ -1,5 +1,6 @@
 /*
  * Copyright (C) 2009 Google Inc. All rights reserved.
+ * Copyright (C) 2009 Apple, Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions are
@@ -38,11 +39,11 @@ using namespace JSC;
 
 namespace WebCore {
 
-void JSDedicatedWorkerContext::mark()
+void JSDedicatedWorkerContext::markChildren(MarkStack& markStack)
 {
-    Base::mark();
+    Base::markChildren(markStack);
 
-    markIfNotNull(impl()->onmessage());
+    markIfNotNull(markStack, impl()->onmessage());
 }
 
 } // namespace WebCore
index 493aaea..39a1fc5 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2007, 2008 Apple Inc. All rights reserved.
+ * Copyright (C) 2007, 2008, 2009 Apple Inc. All rights reserved.
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Library General Public
@@ -39,11 +39,11 @@ using namespace JSC;
 
 namespace WebCore {
 
-void JSDocument::mark()
+void JSDocument::markChildren(MarkStack& markStack)
 {
-    JSNode::mark();
-    markDOMNodesForDocument(impl());
-    markActiveObjectsForContext(*Heap::heap(this)->globalData(), impl());
+    JSNode::markChildren(markStack);
+    markDOMNodesForDocument(markStack, impl());
+    markActiveObjectsForContext(markStack, *Heap::heap(this)->globalData(), impl());
 }
 
 JSValue JSDocument::location(ExecState* exec) const
index a659d3e..42e0281 100644 (file)
@@ -51,12 +51,12 @@ JSObject* JSEventListener::jsFunction() const
     return m_jsFunction;
 }
 
-void JSEventListener::markJSFunction()
+void JSEventListener::markJSFunction(MarkStack& markStack)
 {
-    if (m_jsFunction && !m_jsFunction->marked())
-        m_jsFunction->mark();
-    if (m_globalObject && !m_globalObject->marked())
-        m_globalObject->mark();
+    if (m_jsFunction)
+        markStack.append(m_jsFunction);
+    if (m_globalObject)
+        markStack.append(m_globalObject);
 }
 
 void JSEventListener::handleEvent(Event* event, bool isWindowEvent)
index 2497750..7929169 100644 (file)
@@ -43,7 +43,7 @@ namespace WebCore {
         virtual JSC::JSObject* jsFunction() const;
 
     private:
-        virtual void markJSFunction();
+        virtual void markJSFunction(JSC::MarkStack&);
         virtual void handleEvent(Event*, bool isWindowEvent);
         virtual bool reportError(const String& message, const String& url, int lineNumber);
         virtual bool virtualisAttribute() const;
index d3b5878..574e28a 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2008 Apple Inc. All Rights Reserved.
+ * Copyright (C) 2008, 2009 Apple Inc. All Rights Reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -32,20 +32,20 @@ using namespace JSC;
 
 namespace WebCore {
     
-void JSMessageChannel::mark()
+void JSMessageChannel::markChildren(MarkStack& markStack)
 {
-    Base::mark();
+    Base::markChildren(markStack);
 
     if (MessagePort* port = m_impl->port1()) {
         DOMObject* wrapper = getCachedDOMObjectWrapper(*Heap::heap(this)->globalData(), port);
-        if (wrapper && !wrapper->marked())
-            wrapper->mark();
+        if (wrapper)
+            markStack.append(wrapper);
     }
 
     if (MessagePort* port = m_impl->port2()) {
         DOMObject* wrapper = getCachedDOMObjectWrapper(*Heap::heap(this)->globalData(), port);
-        if (wrapper && !wrapper->marked())
-            wrapper->mark();
+        if (wrapper)
+            markStack.append(wrapper);
     }
 }
 
index 71472d5..c3316c5 100644 (file)
@@ -38,17 +38,17 @@ using namespace JSC;
 
 namespace WebCore {
 
-void JSMessagePort::mark()
+void JSMessagePort::markChildren(MarkStack& markStack)
 {
-    Base::mark();
+    Base::markChildren(markStack);
 
-    markIfNotNull(m_impl->onmessage());
+    markIfNotNull(markStack, m_impl->onmessage());
 
     // If we have a locally entangled port, we can directly mark it as reachable. Ports that are remotely entangled are marked in-use by markActiveObjectsForContext().
     if (MessagePort* entangledPort = m_impl->locallyEntangledPort()) {
         DOMObject* wrapper = getCachedDOMObjectWrapper(*Heap::heap(this)->globalData(), entangledPort);
-        if (wrapper && !wrapper->marked())
-            wrapper->mark();
+        if (wrapper)
+            markStack.append(wrapper);
     }
 
     typedef MessagePort::EventListenersMap EventListenersMap;
@@ -56,7 +56,7 @@ void JSMessagePort::mark()
     EventListenersMap& eventListeners = m_impl->eventListeners();
     for (EventListenersMap::iterator mapIter = eventListeners.begin(); mapIter != eventListeners.end(); ++mapIter) {
         for (ListenerVector::iterator vecIter = mapIter->second.begin(); vecIter != mapIter->second.end(); ++vecIter) 
-            (*vecIter)->markJSFunction();
+            (*vecIter)->markJSFunction(markStack);
     }
 }
 
index ea6cceb..c023931 100644 (file)
@@ -29,13 +29,13 @@ namespace WebCore {
 
 using namespace JSC;
 
-void JSNavigator::mark()
+void JSNavigator::markChildren(MarkStack& markStack)
 {
-    Base::mark();
+    Base::markChildren(markStack);
 
     JSGlobalData& globalData = *Heap::heap(this)->globalData();
 
-    markDOMObjectWrapper(globalData, impl()->optionalGeolocation());
+    markDOMObjectWrapper(markStack, globalData, impl()->optionalGeolocation());
 }
 
 }
index 5213422..cf884b9 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2007 Apple Inc. All rights reserved.
+ * Copyright (C) 2007, 2009 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -136,22 +136,21 @@ void JSNode::pushEventHandlerScope(ExecState*, ScopeChain&) const
 {
 }
 
-void JSNode::mark()
+void JSNode::markChildren(MarkStack& markStack)
 {
-    ASSERT(!marked());
-
     Node* node = m_impl.get();
 
+    Base::markChildren(markStack);
+    markEventListeners(markStack, node->eventListeners());
+
     // Nodes in the document are kept alive by JSDocument::mark, so, if we're in
     // the document, we need to mark the document, but we don't need to explicitly
     // mark any other nodes.
     if (node->inDocument()) {
-        Base::mark();
-        markEventListeners(node->eventListeners());
-        if (Document* doc = node->ownerDocument())
+        if (Document* doc = node->ownerDocument()) {
             if (DOMObject* docWrapper = getCachedDOMObjectWrapper(*Heap::heap(this)->globalData(), doc))
-                if (!docWrapper->marked())
-                    docWrapper->mark();
+                markStack.append(docWrapper);
+        }
         return;
     }
 
@@ -163,33 +162,17 @@ void JSNode::mark()
 
     // Nodes in a subtree are marked by the tree's root, so, if the root is already
     // marking the tree, we don't need to explicitly mark any other nodes.
-    if (root->inSubtreeMark()) {
-        Base::mark();
-        markEventListeners(node->eventListeners());
+    if (root->inSubtreeMark())
         return;
-    }
 
     // Mark the whole tree subtree.
     root->setInSubtreeMark(true);
     for (Node* nodeToMark = root; nodeToMark; nodeToMark = nodeToMark->traverseNextNode()) {
         JSNode* wrapper = getCachedDOMNodeWrapper(m_impl->document(), nodeToMark);
-        if (wrapper) {
-            if (!wrapper->marked())
-                wrapper->mark();
-        } else if (nodeToMark == node) {
-            // This is the case where the map from the document to wrappers has
-            // been cleared out, but a wrapper is being marked. For now, we'll
-            // let the rest of the tree of wrappers get collected, because we have
-            // no good way of finding them. Later we should test behavior of other
-            // browsers and see if we need to preserve other wrappers in this case.
-            if (!marked())
-                mark();
-        }
+        if (wrapper)
+            markStack.append(wrapper);
     }
     root->setInSubtreeMark(false);
-
-    // Double check that we actually ended up marked. This assert caught problems in the past.
-    ASSERT(marked());
 }
 
 static ALWAYS_INLINE JSValue createWrapper(ExecState* exec, JSDOMGlobalObject* globalObject, Node* node)
index 2595af5..a199417 100644 (file)
@@ -1,6 +1,6 @@
 /*
  *  Copyright (C) 2001 Peter Kelly (pmk@post.com)
- *  Copyright (C) 2007, 2008 Apple Inc. All rights reserved.
+ *  Copyright (C) 2007, 2008, 2009 Apple Inc. All rights reserved.
  *
  *  This library is free software; you can redistribute it and/or
  *  modify it under the terms of the GNU Lesser General Public
@@ -36,10 +36,9 @@ JSNodeFilterCondition::JSNodeFilterCondition(JSValue filter)
 {
 }
 
-void JSNodeFilterCondition::mark()
+void JSNodeFilterCondition::markAggregate(MarkStack& markStack)
 {
-    if (!m_filter.marked())
-        m_filter.mark();
+    markStack.append(m_filter);
 }
 
 short JSNodeFilterCondition::acceptNode(JSC::ExecState* exec, Node* filterNode) const
index 3d591c6..b96534a 100644 (file)
@@ -1,6 +1,6 @@
 /*
  *  Copyright (C) 2001 Peter Kelly (pmk@post.com)
- *  Copyright (C) 2007, 2008 Apple Inc. All rights reserved.
+ *  Copyright (C) 2007, 2008, 2009 Apple Inc. All rights reserved.
  *
  *  This library is free software; you can redistribute it and/or
  *  modify it under the terms of the GNU Lesser General Public
@@ -39,7 +39,7 @@ namespace WebCore {
         JSNodeFilterCondition(JSC::JSValue filter);
 
         virtual short acceptNode(ScriptState*, Node*) const;
-        virtual void mark();
+        virtual void markAggregate(JSC::MarkStack&);
 
         mutable JSC::JSValue m_filter;
     };
index a48a59d..09fd110 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2007, 2008 Apple Inc. All rights reserved.
+ * Copyright (C) 2007, 2008, 2009 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -35,10 +35,10 @@ using namespace JSC;
 
 namespace WebCore {
 
-void JSNodeFilter::mark()
+void JSNodeFilter::markChildren(MarkStack& markStack)
 {
-    impl()->mark();
-    Base::mark();
+    Base::markChildren(markStack);
+    impl()->markAggregate(markStack);
 }
 
 JSValue JSNodeFilter::acceptNode(ExecState* exec, const ArgList& args)
index a2b9658..6a09abf 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2006, 2008 Apple Inc. All rights reserved.
+ * Copyright (C) 2006, 2008, 2009 Apple Inc. All rights reserved.
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Library General Public
@@ -29,12 +29,12 @@ using namespace JSC;
 
 namespace WebCore {
 
-void JSNodeIterator::mark()
+void JSNodeIterator::markChildren(MarkStack& markStack)
 {
+    Base::markChildren(markStack);
+
     if (NodeFilter* filter = m_impl->filter())
-        filter->mark();
-    
-    Base::mark();
+        filter->markAggregate(markStack);
 }
 
 JSValue JSNodeIterator::nextNode(ExecState* exec, const ArgList&)
index ad1e556..5f4dfd4 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2008 Apple Inc. All Rights Reserved.
+ * Copyright (C) 2008, 2009 Apple Inc. All Rights Reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -92,14 +92,12 @@ void JSQuarantinedObjectWrapper::transferExceptionToExecState(ExecState* exec) c
     exec->setException(wrapOutgoingValue(unwrappedExecState(), exception));
 }
 
-void JSQuarantinedObjectWrapper::mark()
+void JSQuarantinedObjectWrapper::markChildren(MarkStack& markStack)
 {
-    JSObject::mark();
+    JSObject::markChildren(markStack);
 
-    if (!m_unwrappedObject->marked())
-        m_unwrappedObject->mark();
-    if (!m_unwrappedGlobalObject->marked())
-        m_unwrappedGlobalObject->mark();
+    markStack.append(m_unwrappedObject);
+    markStack.append(m_unwrappedGlobalObject);
 }
 
 bool JSQuarantinedObjectWrapper::getOwnPropertySlot(ExecState* exec, const Identifier& identifier, PropertySlot& slot)
index bf8fddb..08935e7 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2008 Apple Inc. All rights reserved.
+ * Copyright (C) 2008, 2009 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -53,7 +53,7 @@ namespace WebCore {
     protected:
         JSQuarantinedObjectWrapper(JSC::ExecState* unwrappedExec, JSC::JSObject* unwrappedObject, PassRefPtr<JSC::Structure>);
 
-        virtual void mark();
+        virtual void markChildren(JSC::MarkStack&);
 
     private:
         virtual bool getOwnPropertySlot(JSC::ExecState*, const JSC::Identifier&, JSC::PropertySlot&);
index 055368e..6e77f9b 100644 (file)
@@ -1,5 +1,6 @@
 /*
  * Copyright (C) 2008 Nikolas Zimmermann <zimmermann@kde.org>
+ * Copyright (C) 2009 Apple, Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -37,14 +38,14 @@ using namespace JSC;
 
 namespace WebCore {
 
-void JSSVGElementInstance::mark()
+void JSSVGElementInstance::markChildren(MarkStack& markStack)
 {
-    Base::mark();
+    Base::markChildren(markStack);
 
     // Mark the wrapper for our corresponding element, so it can mark its event handlers.
     JSNode* correspondingWrapper = getCachedDOMNodeWrapper(impl()->correspondingElement()->document(), impl()->correspondingElement());
-    if (correspondingWrapper && !correspondingWrapper->marked())
-        correspondingWrapper->mark();
+    if (correspondingWrapper)
+        markStack.append(correspondingWrapper);
 }
 
 JSValue JSSVGElementInstance::addEventListener(ExecState* exec, const ArgList& args)
index 862314d..dca3536 100644 (file)
@@ -38,11 +38,11 @@ using namespace JSC;
 
 namespace WebCore {
 
-void JSSharedWorkerContext::mark()
+void JSSharedWorkerContext::markChildren(MarkStack& markStack)
 {
-    Base::mark();
+    Base::markChildren(markStack);
 
-    markIfNotNull(impl()->onconnect());
+    markIfNotNull(markStack, impl()->onconnect());
 }
 
 } // namespace WebCore
index 8553298..f21f50c 100644 (file)
@@ -41,14 +41,14 @@ using namespace JSC;
 
 namespace WebCore {
 
-void JSSharedWorker::mark()
+void JSSharedWorker::markChildren(MarkStack& markStack)
 {
-    Base::mark();
+    Base::markChildren(markStack);
 
     if (MessagePort* port = impl()->port()) {
         DOMObject* wrapper = getCachedDOMObjectWrapper(*Heap::heap(this)->globalData(), port);
-        if (wrapper && !wrapper->marked())
-            wrapper->mark();
+        if (wrapper)
+            markStack.append(wrapper);
     }
 }
 
index 00dacee..43249dc 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2007, 2008 Apple Inc. All rights reserved.
+ * Copyright (C) 2007, 2008, 2009 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -52,9 +52,9 @@ JSValue toJS(ExecState* exec, JSDOMGlobalObject* globalObject, StyleSheet* style
     return wrapper;
 }
 
-void JSStyleSheet::mark()
+void JSStyleSheet::markChildren(MarkStack& markStack)
 {
-    Base::mark();
+    Base::markChildren(markStack);
 
     // This prevents us from having a style sheet with a dangling ownerNode pointer.
     // A better solution would be to handle this on the DOM side -- if the style sheet
@@ -62,10 +62,8 @@ void JSStyleSheet::mark()
     // be to make ref/deref on the style sheet ref/deref the node instead, but there's
     // a lot of disentangling of the CSS DOM objects that would need to happen first.
     if (Node* ownerNode = impl()->ownerNode()) {
-        if (JSNode* ownerNodeWrapper = getCachedDOMNodeWrapper(ownerNode->document(), ownerNode)) {
-            if (!ownerNodeWrapper->marked())
-                ownerNodeWrapper->mark();
-        }
+        if (JSNode* ownerNodeWrapper = getCachedDOMNodeWrapper(ownerNode->document(), ownerNode))
+            markStack.append(ownerNodeWrapper);
     }
 }
 
index 58eea72..f879cf4 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2006, 2008 Apple Inc. All rights reserved.
+ * Copyright (C) 2006, 2008, 2009 Apple Inc. All rights reserved.
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Library General Public
@@ -29,12 +29,12 @@ using namespace JSC;
 
 namespace WebCore {
     
-void JSTreeWalker::mark()
+void JSTreeWalker::markChildren(MarkStack& markStack)
 {
+    Base::markChildren(markStack);
+
     if (NodeFilter* filter = m_impl->filter())
-        filter->mark();
-    
-    Base::mark();
+        filter->markAggregate(markStack);
 }
     
 JSValue JSTreeWalker::parentNode(ExecState* exec, const ArgList&)
index eca32bf..3aa4b8b 100644 (file)
@@ -1,5 +1,6 @@
 /*
  * Copyright (C) 2009 Google Inc.  All rights reserved.
+ * Copyright (C) 2009 Apple, Inc.  All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions are
@@ -42,11 +43,11 @@ using namespace JSC;
 
 namespace WebCore {
 
-void JSWebSocket::mark()
+void JSWebSocket::markChildren(MarkStack& markStack)
 {
-    Base::mark();
+    Base::markChildren(markStack);
     if (m_impl->readyState() != WebSocket::CLOSED)
-        markIfNotNull(m_impl->onmessage());
+        markIfNotNull(markStack, m_impl->onmessage());
     // FIXME: mark if EventListeners is registered.
 }
 
index 6a7602d..919c81f 100644 (file)
@@ -47,25 +47,25 @@ using namespace JSC;
 
 namespace WebCore {
 
-void JSWorkerContext::mark()
+void JSWorkerContext::markChildren(MarkStack& markStack)
 {
-    Base::mark();
+    Base::markChildren(markStack);
 
     JSGlobalData& globalData = *this->globalData();
 
-    markActiveObjectsForContext(globalData, scriptExecutionContext());
+    markActiveObjectsForContext(markStack, globalData, scriptExecutionContext());
 
-    markDOMObjectWrapper(globalData, impl()->optionalLocation());
-    markDOMObjectWrapper(globalData, impl()->optionalNavigator());
+    markDOMObjectWrapper(markStack, globalData, impl()->optionalLocation());
+    markDOMObjectWrapper(markStack, globalData, impl()->optionalNavigator());
 
-    markIfNotNull(impl()->onerror());
+    markIfNotNull(markStack, impl()->onerror());
 
     typedef WorkerContext::EventListenersMap EventListenersMap;
     typedef WorkerContext::ListenerVector ListenerVector;
     EventListenersMap& eventListeners = impl()->eventListeners();
     for (EventListenersMap::iterator mapIter = eventListeners.begin(); mapIter != eventListeners.end(); ++mapIter) {
         for (ListenerVector::iterator vecIter = mapIter->second.begin(); vecIter != mapIter->second.end(); ++vecIter)
-            (*vecIter)->markJSFunction();
+            (*vecIter)->markJSFunction(markStack);
     }
 }
 
index 6010f83..f5c394b 100644 (file)
@@ -36,11 +36,11 @@ using namespace JSC;
 
 namespace WebCore {
     
-void JSWorker::mark()
+void JSWorker::markChildren(MarkStack& markStack)
 {
-    Base::mark();
+    Base::markChildren(markStack);
 
-    markIfNotNull(static_cast<Worker*>(impl())->onmessage());
+    markIfNotNull(markStack, static_cast<Worker*>(impl())->onmessage());
 }
 
 } // namespace WebCore
index 06a5817..a591fae 100644 (file)
@@ -49,29 +49,29 @@ using namespace JSC;
 
 namespace WebCore {
 
-void JSXMLHttpRequest::mark()
+void JSXMLHttpRequest::markChildren(MarkStack& markStack)
 {
-    Base::mark();
+    Base::markChildren(markStack);
 
     if (XMLHttpRequestUpload* upload = m_impl->optionalUpload()) {
         DOMObject* wrapper = getCachedDOMObjectWrapper(*Heap::heap(this)->globalData(), upload);
-        if (wrapper && !wrapper->marked())
-            wrapper->mark();
+        if (wrapper)
+            markStack.append(wrapper);
     }
 
-    markIfNotNull(m_impl->onreadystatechange());
-    markIfNotNull(m_impl->onabort());
-    markIfNotNull(m_impl->onerror());
-    markIfNotNull(m_impl->onload());
-    markIfNotNull(m_impl->onloadstart());
-    markIfNotNull(m_impl->onprogress());
+    markIfNotNull(markStack, m_impl->onreadystatechange());
+    markIfNotNull(markStack, m_impl->onabort());
+    markIfNotNull(markStack, m_impl->onerror());
+    markIfNotNull(markStack, m_impl->onload());
+    markIfNotNull(markStack, m_impl->onloadstart());
+    markIfNotNull(markStack, m_impl->onprogress());
     
     typedef XMLHttpRequest::EventListenersMap EventListenersMap;
     typedef XMLHttpRequest::ListenerVector ListenerVector;
     EventListenersMap& eventListeners = m_impl->eventListeners();
     for (EventListenersMap::iterator mapIter = eventListeners.begin(); mapIter != eventListeners.end(); ++mapIter) {
         for (ListenerVector::iterator vecIter = mapIter->second.begin(); vecIter != mapIter->second.end(); ++vecIter)
-            (*vecIter)->markJSFunction();
+            (*vecIter)->markJSFunction(markStack);
     }
 }
 
index 597010c..cb6d5f2 100644 (file)
@@ -41,28 +41,28 @@ using namespace JSC;
 
 namespace WebCore {
 
-void JSXMLHttpRequestUpload::mark()
+void JSXMLHttpRequestUpload::markChildren(MarkStack& markStack)
 {
-    Base::mark();
+    Base::markChildren(markStack);
 
     if (XMLHttpRequest* xmlHttpRequest = m_impl->associatedXMLHttpRequest()) {
         DOMObject* wrapper = getCachedDOMObjectWrapper(*Heap::heap(this)->globalData(), xmlHttpRequest);
-        if (wrapper && !wrapper->marked())
-            wrapper->mark();
+        if (wrapper)
+            markStack.append(wrapper);
     }
 
-    markIfNotNull(m_impl->onabort());
-    markIfNotNull(m_impl->onerror());
-    markIfNotNull(m_impl->onload());
-    markIfNotNull(m_impl->onloadstart());
-    markIfNotNull(m_impl->onprogress());
+    markIfNotNull(markStack, m_impl->onabort());
+    markIfNotNull(markStack, m_impl->onerror());
+    markIfNotNull(markStack, m_impl->onload());
+    markIfNotNull(markStack, m_impl->onloadstart());
+    markIfNotNull(markStack, m_impl->onprogress());
     
     typedef XMLHttpRequestUpload::EventListenersMap EventListenersMap;
     typedef XMLHttpRequestUpload::ListenerVector ListenerVector;
     EventListenersMap& eventListeners = m_impl->eventListeners();
     for (EventListenersMap::iterator mapIter = eventListeners.begin(); mapIter != eventListeners.end(); ++mapIter) {
         for (ListenerVector::iterator vecIter = mapIter->second.begin(); vecIter != mapIter->second.end(); ++vecIter)
-            (*vecIter)->markJSFunction();
+            (*vecIter)->markJSFunction(markStack);
     }
 }
 
index 26cf3f5..1918aef 100644 (file)
@@ -504,7 +504,7 @@ sub GenerateHeader
     }
 
     # Custom mark function
-    push(@headerContent, "    virtual void mark();\n\n") if $dataNode->extendedAttributes->{"CustomMarkFunction"};
+    push(@headerContent, "    virtual void markChildren(JSC::MarkStack&);\n\n") if $dataNode->extendedAttributes->{"CustomMarkFunction"};
 
     # Custom pushEventHandlerScope function
     push(@headerContent, "    virtual void pushEventHandlerScope(JSC::ExecState*, JSC::ScopeChain&) const;\n\n") if $dataNode->extendedAttributes->{"CustomPushEventHandlerScope"};
index d288c8d..7c4812f 100644 (file)
@@ -26,6 +26,7 @@
 
 namespace JSC {
     class JSObject;
+    class MarkStack;
 }
 
 namespace WebCore {
@@ -42,7 +43,7 @@ namespace WebCore {
 
 #if USE(JSC)
         virtual JSC::JSObject* jsFunction() const { return 0; }
-        virtual void markJSFunction() { }
+        virtual void markJSFunction(JSC::MarkStack&) { }
 #endif
 
         bool isAttribute() const { return virtualisAttribute(); }
@@ -52,7 +53,7 @@ namespace WebCore {
     };
 
 #if USE(JSC)
-    inline void markIfNotNull(EventListener* listener) { if (listener) listener->markJSFunction(); }
+    inline void markIfNotNull(JSC::MarkStack& markStack, EventListener* listener) { if (listener) listener->markJSFunction(markStack); }
 #endif
 
 }
index 94c87e3..5a542ad 100644 (file)
@@ -3,7 +3,7 @@
  * Copyright (C) 2000 Frederik Holljen (frederik.holljen@hig.no)
  * Copyright (C) 2001 Peter Kelly (pmk@post.com)
  * Copyright (C) 2006 Samuel Weinig (sam.weinig@gmail.com)
- * Copyright (C) 2004, 2008 Apple Inc. All rights reserved.
+ * Copyright (C) 2004, 2008, 2009 Apple Inc. All rights reserved.
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Library General Public
@@ -71,7 +71,7 @@ namespace WebCore {
         }
 
         short acceptNode(ScriptState*, Node*) const;
-        void mark() { m_condition->mark(); };
+        void markAggregate(JSC::MarkStack& markStack) { m_condition->markAggregate(markStack); };
 
         // For non-JS bindings. Silently ignores the JavaScript exception if any.
         short acceptNode(Node* node) const { return acceptNode(scriptStateFromNode(node), node); }
index c94cc9a..0d6313f 100644 (file)
@@ -3,7 +3,7 @@
  * Copyright (C) 2000 Frederik Holljen (frederik.holljen@hig.no)
  * Copyright (C) 2001 Peter Kelly (pmk@post.com)
  * Copyright (C) 2006 Samuel Weinig (sam.weinig@gmail.com)
- * Copyright (C) 2004, 2008 Apple Inc. All rights reserved.
+ * Copyright (C) 2004, 2008, 2009 Apple Inc. All rights reserved.
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Library General Public
 #include "ScriptState.h"
 #include <wtf/RefCounted.h>
 
+namespace JSC {
+    class MarkStack;
+}
+
 namespace WebCore {
 
     class Node;
@@ -36,7 +40,7 @@ namespace WebCore {
     public:
         virtual ~NodeFilterCondition() { }
         virtual short acceptNode(ScriptState*, Node*) const = 0;
-        virtual void mark() { }
+        virtual void markAggregate(JSC::MarkStack&) { }
     };
 
 } // namespace WebCore
index 479c2ff..034f6c3 100644 (file)
@@ -2,7 +2,7 @@
  * Copyright (C) 2001 Peter Kelly (pmk@post.com)
  * Copyright (C) 2001 Tobias Anton (anton@stud.fbi.fh-darmstadt.de)
  * Copyright (C) 2006 Samuel Weinig (sam.weinig@gmail.com)
- * Copyright (C) 2003, 2004, 2005, 2006, 2008 Apple Inc. All rights reserved.
+ * Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009 Apple Inc. All rights reserved.
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Library General Public
@@ -55,10 +55,10 @@ namespace WebCore {
     typedef Vector<RefPtr<RegisteredEventListener> > RegisteredEventListenerVector;
 
 #if USE(JSC)
-    inline void markEventListeners(const RegisteredEventListenerVector& listeners)
+    inline void markEventListeners(JSC::MarkStack& markStack, const RegisteredEventListenerVector& listeners)
     {
         for (size_t i = 0; i < listeners.size(); ++i)
-            listeners[i]->listener()->markJSFunction();
+            listeners[i]->listener()->markJSFunction(markStack);
     }
 
     inline void invalidateEventListeners(const RegisteredEventListenerVector& listeners)
index 9ee537d..01ba066 100644 (file)
@@ -371,7 +371,7 @@ namespace WebCore {
         void captureEvents();
         void releaseEvents();
 
-        // These methods are used for GC marking. See JSDOMWindow::mark() in
+        // These methods are used for GC marking. See JSDOMWindow::markChildren(MarkStack&) in
         // JSDOMWindowCustom.cpp.
         Screen* optionalScreen() const { return m_screen.get(); }
         DOMSelection* optionalSelection() const { return m_selection.get(); }
index 1c40eb0..aa47475 100644 (file)
@@ -106,7 +106,7 @@ namespace WebCore {
 
         virtual void forwardException(const String& errorMessage, int lineNumber, const String& sourceURL) = 0;
 
-        // These methods are used for GC marking. See JSWorkerContext::mark() in
+        // These methods are used for GC marking. See JSWorkerContext::markChildren(MarkStack&) in
         // JSWorkerContextCustom.cpp.
         WorkerNavigator* optionalNavigator() const { return m_navigator.get(); }
         WorkerLocation* optionalLocation() const { return m_location.get(); }