Roll out r28106 and r28108. These introduced a frequent assertion failure on page...
authormrowe@apple.com <mrowe@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 28 Nov 2007 13:12:03 +0000 (13:12 +0000)
committermrowe@apple.com <mrowe@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 28 Nov 2007 13:12:03 +0000 (13:12 +0000)
git-svn-id: https://svn.webkit.org/repository/webkit/trunk@28110 268f45cc-cd09-0410-ab3c-d52691b4dbfc

69 files changed:
JavaScriptCore/ChangeLog
JavaScriptCore/JavaScriptCore.exp
JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj
JavaScriptCore/kjs/ExecState.cpp
JavaScriptCore/kjs/ExecState.h
JavaScriptCore/kjs/JSWrapperObject.cpp
JavaScriptCore/kjs/JSWrapperObject.h
JavaScriptCore/kjs/MarkStack.h [deleted file]
JavaScriptCore/kjs/array_instance.cpp
JavaScriptCore/kjs/array_instance.h
JavaScriptCore/kjs/bool_object.cpp
JavaScriptCore/kjs/bool_object.h
JavaScriptCore/kjs/collector.cpp
JavaScriptCore/kjs/collector.h
JavaScriptCore/kjs/error_object.cpp
JavaScriptCore/kjs/error_object.h
JavaScriptCore/kjs/function.cpp
JavaScriptCore/kjs/function.h
JavaScriptCore/kjs/internal.cpp
JavaScriptCore/kjs/interpreter.cpp
JavaScriptCore/kjs/interpreter.h
JavaScriptCore/kjs/list.cpp
JavaScriptCore/kjs/list.h
JavaScriptCore/kjs/object.cpp
JavaScriptCore/kjs/object.h
JavaScriptCore/kjs/property_map.cpp
JavaScriptCore/kjs/property_map.h
JavaScriptCore/kjs/scope_chain.h
JavaScriptCore/kjs/string_object.cpp
JavaScriptCore/kjs/string_object.h
JavaScriptCore/kjs/value.h
JavaScriptGlue/ChangeLog
JavaScriptGlue/JSObject.cpp
JavaScriptGlue/JSObject.h
JavaScriptGlue/JSValueWrapper.cpp
JavaScriptGlue/JSValueWrapper.h
JavaScriptGlue/UserObjectImp.cpp
JavaScriptGlue/UserObjectImp.h
LayoutTests/ChangeLog
LayoutTests/fast/js/gc-breadth-2-expected.txt [deleted file]
LayoutTests/fast/js/gc-breadth-2.html [deleted file]
LayoutTests/fast/js/gc-breadth-expected.txt [deleted file]
LayoutTests/fast/js/gc-breadth.html [deleted file]
LayoutTests/fast/js/gc-depth-expected.txt [deleted file]
LayoutTests/fast/js/gc-depth.html [deleted file]
LayoutTests/fast/js/resources/gc-breadth-2.js [deleted file]
LayoutTests/fast/js/resources/gc-breadth.js [deleted file]
LayoutTests/fast/js/resources/gc-depth.js [deleted file]
WebCore/ChangeLog
WebCore/bindings/js/JSDocumentCustom.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/JSTreeWalkerCustom.cpp
WebCore/bindings/js/JSXMLHttpRequest.cpp
WebCore/bindings/js/JSXMLHttpRequest.h
WebCore/bindings/js/kjs_binding.cpp
WebCore/bindings/js/kjs_binding.h
WebCore/bindings/js/kjs_events.cpp
WebCore/bindings/js/kjs_events.h
WebCore/bindings/js/kjs_window.cpp
WebCore/bindings/js/kjs_window.h
WebCore/bindings/scripts/CodeGeneratorJS.pm
WebCore/dom/Node.cpp
WebCore/dom/Node.h
WebCore/dom/NodeFilter.h
WebCore/dom/NodeFilterCondition.h

index 7a0b62a..203f95f 100644 (file)
@@ -1,195 +1,3 @@
-2007-11-28  Maciej Stachowiak  <mjs@apple.com>
-
-        Add files missing from previous commit.
-
-        * kjs/MarkStack.h: Added.
-
-2007-11-28  Maciej Stachowiak  <mjs@apple.com>
-
-        Not reviewed.
-
-        - Fixed "Stack overflow crash in JavaScript garbage collector mark pass"
-        http://bugs.webkit.org/show_bug.cgi?id=12216
-        
-        Implement mark stack. This version is not suitable for prime time because it makes a
-        huge allocation on every collect, and potentially makes marking of detached subtrees
-        slow. But it is a .2% - .4% speedup even without much tweaking.
-        
-        The basic approach is to replace mark() methods with
-        markChildren(MarkStack&) methods. Reachable references are pushed
-        onto a mark stack (which encapsulates ignoring already-marked
-        references). 
-        
-        Objects are no longer responsible for actually setting their own
-        mark bits, the collector does that. This means that for objects on
-        the number heap we don't have to call markChildren() at all since
-        we know there aren't any.
-        
-        The mark phase of collect pushes roots onto the mark stack
-        and drains it as often as possible.
-        
-        To make this approach viable requires a constant-size mark stack
-        and a slow fallback approach for when the stack size is exceeded,
-        plus optimizations to make the required stack small in common
-        cases. This should be doable.
-
-        * JavaScriptCore.exp: Export new symbols.
-        * JavaScriptCore.xcodeproj/project.pbxproj: Add new file.
-        * kjs/collector.cpp:
-        (KJS::Collector::heapAllocate):
-        (KJS::drainMarkStack): Helper for all of the below.
-        (KJS::Collector::markStackObjectsConservatively): Use mark stack.
-        (KJS::Collector::markCurrentThreadConservatively): ditto
-        (KJS::Collector::markOtherThreadConservatively): ditto
-        (KJS::Collector::markProtectedObjects): ditto
-        (KJS::Collector::markMainThreadOnlyObjects): ditto
-        (KJS::Collector::collect): ditto
-        * kjs/collector.h:
-        (KJS::Collector::cellMayHaveRefs): Helper for MarkStack.
-
-        * kjs/MarkStack.h: Added. The actual mark stack implementation.
-        (KJS::MarkStack::push):
-        (KJS::MarkStack::pushAtom):
-        (KJS::MarkStack::pop):
-        (KJS::MarkStack::isEmpty):
-        (KJS::MarkStack::reserveCapacity):
-
-        Changed mark() methods to markChildren() methods:
-        
-        * kjs/ExecState.cpp:
-        (KJS::ExecState::markChildren):
-        * kjs/ExecState.h:
-        * kjs/JSWrapperObject.cpp:
-        (KJS::JSWrapperObject::markChildren):
-        * kjs/JSWrapperObject.h:
-        * kjs/array_instance.cpp:
-        (KJS::ArrayInstance::markChildren):
-        * kjs/array_instance.h:
-        * kjs/bool_object.cpp:
-        (BooleanInstance::markChildren):
-        * kjs/bool_object.h:
-        * kjs/error_object.cpp:
-        * kjs/error_object.h:
-        * kjs/function.cpp:
-        (KJS::FunctionImp::markChildren):
-        (KJS::Arguments::Arguments):
-        (KJS::Arguments::markChildren):
-        (KJS::ActivationImp::markChildren):
-        * kjs/function.h:
-        * kjs/internal.cpp:
-        (KJS::GetterSetterImp::markChildren):
-        * kjs/interpreter.cpp:
-        (KJS::Interpreter::markRoots):
-        * kjs/interpreter.h:
-        * kjs/list.cpp:
-        (KJS::List::markProtectedListsSlowCase):
-        * kjs/list.h:
-        (KJS::List::markProtectedLists):
-        * kjs/object.cpp:
-        (KJS::JSObject::markChildren):
-        * kjs/object.h:
-        (KJS::ScopeChain::markChildren):
-        * kjs/property_map.cpp:
-        (KJS::PropertyMap::markChildren):
-        * kjs/property_map.h:
-        * kjs/scope_chain.h:
-        * kjs/string_object.cpp:
-        (KJS::StringInstance::markChildren):
-        * kjs/string_object.h:
-
-2007-11-28  Maciej Stachowiak  <mjs@apple.com>
-
-        Reviewed by Darin and Geoff.
-
-        - Fixed "Stack overflow crash in JavaScript garbage collector mark pass"
-        http://bugs.webkit.org/show_bug.cgi?id=12216
-        
-        Implement mark stack. This version is not suitable for prime time because it makes a
-        huge allocation on every collect, and potentially makes marking of detached subtrees
-        slow. But it is an 0.4% SunSpider speedup even without much tweaking.
-        
-        The basic approach is to replace mark() methods with
-        markChildren(MarkStack&) methods. Reachable references are pushed
-        onto a mark stack (which encapsulates ignoring already-marked
-        references). 
-        
-        Objects are no longer responsible for actually setting their own
-        mark bits, the collector does that. This means that for objects on
-        the number heap we don't have to call markChildren() at all since
-        we know there aren't any.
-        
-        The mark phase of collect pushes roots onto the mark stack
-        and drains it as often as possible.
-        
-        To make this approach viable requires a constant-size mark stack
-        and a slow fallback approach for when the stack size is exceeded,
-        plus optimizations to make the required stack small in common
-        cases. This should be doable.
-
-        * JavaScriptCore.exp: Export new symbols.
-        * JavaScriptCore.xcodeproj/project.pbxproj: Add new file.
-        * kjs/collector.cpp:
-        (KJS::Collector::heapAllocate):
-        (KJS::drainMarkStack): Helper for all of the below.
-        (KJS::Collector::markStackObjectsConservatively): Use mark stack.
-        (KJS::Collector::markCurrentThreadConservatively): ditto
-        (KJS::Collector::markOtherThreadConservatively): ditto
-        (KJS::Collector::markProtectedObjects): ditto
-        (KJS::Collector::markMainThreadOnlyObjects): ditto
-        (KJS::Collector::collect): ditto
-        * kjs/collector.h:
-        (KJS::Collector::cellMayHaveRefs): Helper for MarkStack.
-
-        * kjs/MarkStack.h: Added. The actual mark stack implementation.
-        (KJS::MarkStack::push):
-        (KJS::MarkStack::pushAtom):
-        (KJS::MarkStack::pop):
-        (KJS::MarkStack::isEmpty):
-        (KJS::MarkStack::reserveCapacity):
-
-        Changed mark() methods to markChildren() methods:
-        
-        * kjs/ExecState.cpp:
-        (KJS::ExecState::markChildren):
-        * kjs/ExecState.h:
-        * kjs/JSWrapperObject.cpp:
-        (KJS::JSWrapperObject::markChildren):
-        * kjs/JSWrapperObject.h:
-        * kjs/array_instance.cpp:
-        (KJS::ArrayInstance::markChildren):
-        * kjs/array_instance.h:
-        * kjs/bool_object.cpp:
-        (BooleanInstance::markChildren):
-        * kjs/bool_object.h:
-        * kjs/error_object.cpp:
-        * kjs/error_object.h:
-        * kjs/function.cpp:
-        (KJS::FunctionImp::markChildren):
-        (KJS::Arguments::Arguments):
-        (KJS::Arguments::markChildren):
-        (KJS::ActivationImp::markChildren):
-        * kjs/function.h:
-        * kjs/internal.cpp:
-        (KJS::GetterSetterImp::markChildren):
-        * kjs/interpreter.cpp:
-        (KJS::Interpreter::markRoots):
-        * kjs/interpreter.h:
-        * kjs/list.cpp:
-        (KJS::List::markProtectedListsSlowCase):
-        * kjs/list.h:
-        (KJS::List::markProtectedLists):
-        * kjs/object.cpp:
-        (KJS::JSObject::markChildren):
-        * kjs/object.h:
-        (KJS::ScopeChain::markChildren):
-        * kjs/property_map.cpp:
-        (KJS::PropertyMap::markChildren):
-        * kjs/property_map.h:
-        * kjs/scope_chain.h:
-        * kjs/string_object.cpp:
-        (KJS::StringInstance::markChildren):
-        * kjs/string_object.h:
-
 2007-11-27  Alp Toker  <alp@atoker.com>
 
         Reviewed by Mark Rowe.
index b33faef..35f01b7 100644 (file)
@@ -122,10 +122,10 @@ __ZN3KJS11Interpreter17startTimeoutCheckEv
 __ZN3KJS11Interpreter21shouldPrintExceptionsEv
 __ZN3KJS11Interpreter24setShouldPrintExceptionsEb
 __ZN3KJS11Interpreter27resetGlobalObjectPropertiesEv
+__ZN3KJS11Interpreter4markEv
 __ZN3KJS11Interpreter6s_hookE
 __ZN3KJS11Interpreter8evaluateERKNS_7UStringEiPKNS_5UCharEiPNS_7JSValueE
 __ZN3KJS11Interpreter8evaluateERKNS_7UStringEiS3_PNS_7JSValueE
-__ZN3KJS11Interpreter9markRootsERNS_9MarkStackE
 __ZN3KJS11InterpreterC1Ev
 __ZN3KJS11InterpreterC2Ev
 __ZN3KJS11InterpreterD1Ev
@@ -144,7 +144,6 @@ __ZN3KJS13ArrayInstance4infoE
 __ZN3KJS13SavedBuiltinsC1Ev
 __ZN3KJS13SavedBuiltinsD1Ev
 __ZN3KJS13jsOwnedStringERKNS_7UStringE
-__ZN3KJS14StringInstance12markChildrenERNS_9MarkStackE
 __ZN3KJS14StringInstance14deletePropertyEPNS_9ExecStateERKNS_10IdentifierE
 __ZN3KJS14StringInstance16getPropertyNamesEPNS_9ExecStateERNS_17PropertyNameArrayE
 __ZN3KJS14StringInstance18getOwnPropertySlotEPNS_9ExecStateERKNS_10IdentifierERNS_12PropertySlotE
@@ -153,6 +152,7 @@ __ZN3KJS14StringInstance3putEPNS_9ExecStateERKNS_10IdentifierEPNS_7JSValueEi
 __ZN3KJS14StringInstance4infoE
 __ZN3KJS14StringInstanceC1EPNS_8JSObjectERKNS_7UStringE
 __ZN3KJS14StringInstanceC2EPNS_8JSObjectERKNS_7UStringE
+__ZN3KJS15JSWrapperObject4markEv
 __ZN3KJS15SavedPropertiesC1Ev
 __ZN3KJS15SavedPropertiesD1Ev
 __ZN3KJS16RuntimeObjectImp4infoE
@@ -201,7 +201,6 @@ __ZN3KJS8Debugger9exceptionEPNS_9ExecStateEiiPNS_7JSValueE
 __ZN3KJS8DebuggerC2Ev
 __ZN3KJS8DebuggerD2Ev
 __ZN3KJS8JSObject11hasInstanceEPNS_9ExecStateEPNS_7JSValueE
-__ZN3KJS8JSObject12markChildrenERNS_9MarkStackE
 __ZN3KJS8JSObject12removeDirectERKNS_10IdentifierE
 __ZN3KJS8JSObject14callAsFunctionEPNS_9ExecStateEPS0_RKNS_4ListE
 __ZN3KJS8JSObject14deletePropertyEPNS_9ExecStateERKNS_10IdentifierE
@@ -213,6 +212,7 @@ __ZN3KJS8JSObject22fillGetterPropertySlotERNS_12PropertySlotEPPNS_7JSValueE
 __ZN3KJS8JSObject3putEPNS_9ExecStateERKNS_10IdentifierEPNS_7JSValueEi
 __ZN3KJS8JSObject3putEPNS_9ExecStateEjPNS_7JSValueEi
 __ZN3KJS8JSObject4callEPNS_9ExecStateEPS0_RKNS_4ListE
+__ZN3KJS8JSObject4markEv
 __ZN3KJS8JSObject9constructEPNS_9ExecStateERKNS_4ListE
 __ZN3KJS8JSObject9constructEPNS_9ExecStateERKNS_4ListERKNS_10IdentifierERKNS_7UStringEi
 __ZN3KJS8JSObject9putDirectERKNS_10IdentifierEPNS_7JSValueEi
index d81d495..99a0e2f 100644 (file)
@@ -99,7 +99,6 @@
                6592C318098B7DE10003D4F6 /* Vector.h in Headers */ = {isa = PBXBuildFile; fileRef = 6592C316098B7DE10003D4F6 /* Vector.h */; settings = {ATTRIBUTES = (Private, ); }; };
                6592C319098B7DE10003D4F6 /* VectorTraits.h in Headers */ = {isa = PBXBuildFile; fileRef = 6592C317098B7DE10003D4F6 /* VectorTraits.h */; settings = {ATTRIBUTES = (Private, ); }; };
                65A7A5E00CD1D50E00061F8E /* LabelStack.h in Headers */ = {isa = PBXBuildFile; fileRef = 65B813A80CD1D01900DF59D6 /* LabelStack.h */; settings = {ATTRIBUTES = (Private, ); }; };
-               65A8B8DB0CF408F400DC7C27 /* MarkStack.h in Headers */ = {isa = PBXBuildFile; fileRef = 65A8B8D80CF408E900DC7C27 /* MarkStack.h */; settings = {ATTRIBUTES = (Private, ); }; };
                65B1749A09D0FEB700820339 /* array_object.lut.h in Headers */ = {isa = PBXBuildFile; fileRef = 65B1749909D0FEB700820339 /* array_object.lut.h */; };
                65B174F509D100FA00820339 /* math_object.lut.h in Headers */ = {isa = PBXBuildFile; fileRef = 65B174F109D100FA00820339 /* math_object.lut.h */; };
                65B174F609D100FA00820339 /* number_object.lut.h in Headers */ = {isa = PBXBuildFile; fileRef = 65B174F209D100FA00820339 /* number_object.lut.h */; };
                659126BC0BDD1728001921FB /* AllInOneFile.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = AllInOneFile.cpp; sourceTree = "<group>"; };
                6592C316098B7DE10003D4F6 /* Vector.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = Vector.h; sourceTree = "<group>"; };
                6592C317098B7DE10003D4F6 /* VectorTraits.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = VectorTraits.h; sourceTree = "<group>"; };
-               65A8B8D80CF408E900DC7C27 /* MarkStack.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MarkStack.h; sourceTree = "<group>"; };
                65B1749909D0FEB700820339 /* array_object.lut.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = file; name = array_object.lut.h; path = ../../../../../symroots/Debug/DerivedSources/JavaScriptCore/array_object.lut.h; sourceTree = "<group>"; };
                65B174BE09D1000200820339 /* chartables.c */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.c; fileEncoding = 30; path = chartables.c; sourceTree = "<group>"; };
                65B174F109D100FA00820339 /* math_object.lut.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = file; name = math_object.lut.h; path = ../../../../../symroots/Debug/DerivedSources/JavaScriptCore/math_object.lut.h; sourceTree = "<group>"; };
                                F692A8680255597D01FF60F7 /* lookup.cpp */,
                                F692A8690255597D01FF60F7 /* lookup.h */,
                                F692A86A0255597D01FF60F7 /* math_object.cpp */,
-                               65A8B8D80CF408E900DC7C27 /* MarkStack.h */,
                                F692A86B0255597D01FF60F7 /* math_object.h */,
                                F692A86D0255597D01FF60F7 /* nodes.cpp */,
                                F692A86E0255597D01FF60F7 /* nodes.h */,
                                148A1627095D16BB00666D0D /* ListRefPtr.h in Headers */,
                                65F340940CD6C1C000C0CA8B /* LocalStorage.h in Headers */,
                                5DBD18B00C5401A700C15EAE /* MallocZoneSupport.h in Headers */,
-                               65A8B8DB0CF408F400DC7C27 /* MarkStack.h in Headers */,
                                BCF655590A2049710038A194 /* MathExtras.h in Headers */,
                                932F5B840822A1C700736975 /* NP_jsobject.h in Headers */,
                                9303F56A0991190000AD71B8 /* Noncopyable.h in Headers */,
index 5a22e69..f828a69 100644 (file)
@@ -88,10 +88,10 @@ ExecState::~ExecState()
     m_interpreter->setCurrentExec(m_savedExecState);
 }
 
-void ExecState::markChildren(MarkStack& stack)
+void ExecState::mark()
 {
     for (ExecState* exec = this; exec; exec = exec->m_callingExecState)
-        exec->m_scopeChain.markChildren(stack);
+        exec->m_scopeChain.mark();
 }
 
 void ExecState::setGlobalObject(JSGlobalObject* globalObject)
index 65f233f..5012350 100644 (file)
@@ -100,7 +100,7 @@ namespace KJS  {
 
         void setGlobalObject(JSGlobalObject*);
         
-        void markChildren(MarkStack&);
+        void mark();
         
         // This is a workaround to avoid accessing the global variables for these identifiers in
         // important property lookup functions, to avoid taking PIC branches in Mach-O binaries
index 36e7584..dd161f7 100644 (file)
 
 namespace KJS {
 
-void JSWrapperObject::markChildren(MarkStack& stack
+void JSWrapperObject::mark(
 {
-    JSObject::markChildren(stack);
-    stack.pushAtom(m_internalValue);
+    JSObject::mark();
+    if (m_internalValue && !m_internalValue->marked())
+        m_internalValue->mark();
 }
 
 } // namespace KJS
index d51f0bd..0a06c9f 100644 (file)
@@ -56,7 +56,7 @@ namespace KJS {
          */
         void setInternalValue(JSValue* v);
         
-        virtual void markChildren(MarkStack& stack);
+        virtual void mark();
         
     private:
         JSValue* m_internalValue;
@@ -64,7 +64,7 @@ namespace KJS {
     
     inline JSWrapperObject::JSWrapperObject(JSValue* proto)
         : JSObject(proto)
-        , m_internalValue(jsNull())
+        , m_internalValue(0)
     {
     }
     
diff --git a/JavaScriptCore/kjs/MarkStack.h b/JavaScriptCore/kjs/MarkStack.h
deleted file mode 100644 (file)
index c96b4af..0000000
+++ /dev/null
@@ -1,96 +0,0 @@
-// -*- mode: c++; c-basic-offset: 4 -*-
-/*
- *  Copyright (C) 2007 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
- *  License as published by the Free Software Foundation; either
- *  version 2 of the License, or (at your option) any later version.
- *
- *  This library is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- *  Library General Public License for more details.
- *
- *  You should have received a copy of the GNU Library General Public License
- *  along with this library; see the file COPYING.LIB.  If not, write to
- *  the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- *  Boston, MA 02110-1301, USA.
- *
- */
-
-#ifndef MarkStack_h
-#define MarkStack_h
-
-#include <wtf/Vector.h>
-#include "collector.h"
-#include "value.h"
-#include <stdio.h>
-
-namespace KJS {
-
-    class MarkStack {
-    public:
-        void push(JSValue* value)
-        {
-            if (value->marked())
-                return;
-            JSCell* cell = value->asCell();
-            Collector::markCell(cell);
-            if (!Collector::cellMayHaveRefs(cell))
-                return;
-            ASSERT(m_stack.size() < m_stack.capacity());
-            m_stack.uncheckedAppend(cell);
-        }
-
-        void push(JSCell* cell)
-        {
-            if (cell->marked())
-                return;
-            Collector::markCell(cell);
-            if (!Collector::cellMayHaveRefs(cell))
-                return;
-            ASSERT(m_stack.size() < m_stack.capacity());
-            m_stack.uncheckedAppend(cell);
-        }
-
-        void pushAtom(JSValue* value)
-        {
-            if (value->marked())
-                return;
-            JSCell* cell = value->asCell();
-            Collector::markCell(cell);
-        }
-
-        void pushAtom(JSCell* cell)
-        {
-            if (cell->marked())
-                return;
-            Collector::markCell(cell);
-        }
-
-        JSCell* pop()
-        {
-            ASSERT(m_stack.size() > 0);
-            JSCell* cell = m_stack.last();
-            m_stack.removeLast();
-            return cell;
-        }
-
-        bool isEmpty()
-        {
-            return m_stack.isEmpty();
-        }
-
-        void reserveCapacity(size_t size) 
-        {
-            m_stack.reserveCapacity(size);
-        }
-
-    private:
-        Vector<JSCell*> m_stack;
-    };
-
-}
-
-#endif // MarkStack_h
index e940786..2825132 100644 (file)
@@ -402,23 +402,26 @@ void ArrayInstance::setLength(unsigned newLength)
     m_length = newLength;
 }
 
-void ArrayInstance::markChildren(MarkStack& stack)
+void ArrayInstance::mark()
 {
-    JSObject::markChildren(stack);
+    JSObject::mark();
 
     ArrayStorage* storage = m_storage;
 
     unsigned usedVectorLength = min(m_length, m_vectorLength);
     for (unsigned i = 0; i < usedVectorLength; ++i) {
         JSValue* value = storage->m_vector[i];
-        if (value)
-            stack.push(value);
+        if (value && !value->marked())
+            value->mark();
     }
 
     if (SparseArrayValueMap* map = storage->m_sparseValueMap) {
         SparseArrayValueMap::iterator end = map->end();
-        for (SparseArrayValueMap::iterator it = map->begin(); it != end; ++it)
-            stack.push(it->second);
+        for (SparseArrayValueMap::iterator it = map->begin(); it != end; ++it) {
+            JSValue* value = it->second;
+            if (!value->marked())
+                value->mark();
+        }
     }
 }
 
index bb0a38e..913d0cd 100644 (file)
@@ -42,7 +42,7 @@ namespace KJS {
     virtual bool deleteProperty(ExecState *, unsigned propertyName);
     virtual void getPropertyNames(ExecState*, PropertyNameArray&);
 
-    virtual void markChildren(MarkStack&);
+    virtual void mark();
 
     virtual const ClassInfo* classInfo() const { return &info; }
     static const ClassInfo info;
index a93c53d..916fe53 100644 (file)
@@ -38,12 +38,6 @@ BooleanInstance::BooleanInstance(JSObject *proto)
 {
 }
 
-void BooleanInstance::markChildren(MarkStack& stack)
-{
-    JSObject::markChildren(stack);
-    ASSERT(JSImmediate::isImmediate(internalValue()));
-}
-
 // ------------------------------ BooleanPrototype --------------------------
 
 // ECMA 15.6.4
index 2b8c000..3ab04a7 100644 (file)
@@ -32,7 +32,6 @@ namespace KJS {
     BooleanInstance(JSObject *proto);
 
     virtual const ClassInfo *classInfo() const { return &info; }
-    virtual void markChildren(MarkStack& stack);
     static const ClassInfo info;
   };
 
index 34934e0..7adfb82 100644 (file)
@@ -26,7 +26,6 @@
 #include "ExecState.h"
 #include "internal.h"
 #include "list.h"
-#include "MarkStack.h"
 #include "value.h"
 #include <algorithm>
 #include <setjmp.h>
@@ -278,8 +277,6 @@ collect:
 
     targetBlock = (Block*)allocateBlock();
     targetBlock->freeList = targetBlock->cells;
-    if (heapType == PrimaryHeap)
-        targetBlock->mayHaveRefs = 1;
     targetBlockUsedCells = 0;
     heap.blocks[usedBlocks] = (CollectorBlock*)targetBlock;
     heap.usedBlocks = usedBlocks + 1;
@@ -482,14 +479,7 @@ void Collector::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)
 
-static inline void drainMarkStack(MarkStack& stack)
-{
-    while (!stack.isEmpty())
-        stack.pop()->markChildren(stack);
-}
-
-
-void Collector::markStackObjectsConservatively(MarkStack& stack, void *start, void *end)
+void Collector::markStackObjectsConservatively(void *start, void *end)
 {
   if (start > end) {
     void* tmp = start;
@@ -531,8 +521,8 @@ void Collector::markStackObjectsConservatively(MarkStack& stack, void *start, vo
               if ((primaryBlocks[block] == blockAddr) & (offset <= lastCellOffset)) {
                   if (((CollectorCell*)xAsBits)->u.freeCell.zeroIfFree != 0) {
                       JSCell* imp = reinterpret_cast<JSCell*>(xAsBits);
-                      stack.push(imp);
-                      drainMarkStack(stack);
+                      if (!imp->marked())
+                          imp->mark();
                   }
                   break;
               }
@@ -543,7 +533,7 @@ void Collector::markStackObjectsConservatively(MarkStack& stack, void *start, vo
   }
 }
 
-void Collector::markCurrentThreadConservatively(MarkStack& stack)
+void Collector::markCurrentThreadConservatively()
 {
     // setjmp forces volatile registers onto the stack
     jmp_buf registers;
@@ -560,7 +550,7 @@ void Collector::markCurrentThreadConservatively(MarkStack& stack)
     void* stackPointer = &dummy;
     void* stackBase = currentThreadStackBase();
 
-    markStackObjectsConservatively(stack, stackPointer, stackBase);
+    markStackObjectsConservatively(stackPointer, stackBase);
 }
 
 #if USE(MULTIPLE_THREADS)
@@ -703,7 +693,7 @@ static inline void* otherThreadStackBase(const PlatformThreadRegisters& regs, Co
 #endif
 }
 
-void Collector::markOtherThreadConservatively(MarkStack& stack, Thread* thread)
+void Collector::markOtherThreadConservatively(Thread* thread)
 {
   suspendThread(thread->platformThread);
 
@@ -711,25 +701,25 @@ void Collector::markOtherThreadConservatively(MarkStack& stack, Thread* thread)
   size_t regSize = getPlatformThreadRegisters(thread->platformThread, regs);
 
   // mark the thread's registers
-  markStackObjectsConservatively(stack, (void*)&regs, (void*)((char*)&regs + regSize));
+  markStackObjectsConservatively((void*)&regs, (void*)((char*)&regs + regSize));
  
   void* stackPointer = otherThreadStackPointer(regs);
   void* stackBase = otherThreadStackBase(regs, thread);
-  markStackObjectsConservatively(stack, stackPointer, stackBase);
+  markStackObjectsConservatively(stackPointer, stackBase);
 
   resumeThread(thread->platformThread);
 }
 
 #endif
 
-void Collector::markStackObjectsConservatively(MarkStack& stack)
+void Collector::markStackObjectsConservatively()
 {
-  markCurrentThreadConservatively(stack);
+  markCurrentThreadConservatively();
 
 #if USE(MULTIPLE_THREADS)
   for (Thread *thread = registeredThreads; thread != NULL; thread = thread->next) {
     if (!pthread_equal(thread->posixThread, pthread_self())) {
-        markOtherThreadConservatively(stack, thread);
+      markOtherThreadConservatively(thread);
     }
   }
 #endif
@@ -781,17 +771,18 @@ void Collector::collectOnMainThreadOnly(JSValue* value)
     ++mainThreadOnlyObjectCount;
 }
 
-void Collector::markProtectedObjects(MarkStack& stack)
+void Collector::markProtectedObjects()
 {
   ProtectCountSet& protectedValues = KJS::protectedValues();
   ProtectCountSet::iterator end = protectedValues.end();
   for (ProtectCountSet::iterator it = protectedValues.begin(); it != end; ++it) {
-    stack.push(it->first);
-    drainMarkStack(stack);
+    JSCell *val = it->first;
+    if (!val->marked())
+      val->mark();
   }
 }
 
-void Collector::markMainThreadOnlyObjects(MarkStack& stack)
+void Collector::markMainThreadOnlyObjects()
 {
 #if USE(MULTIPLE_THREADS)
     ASSERT(!onMainThread());
@@ -823,8 +814,7 @@ void Collector::markMainThreadOnlyObjects(MarkStack& stack)
                 if (curBlock->collectOnMainThreadOnly.get(i)) {
                     if (!curBlock->marked.get(i)) {
                         JSCell* imp = reinterpret_cast<JSCell*>(cell);
-                        stack.push(imp);
-                        drainMarkStack(stack);
+                        imp->mark();
                     }
                     if (++count == mainThreadOnlyObjectCount)
                         return;
@@ -960,14 +950,9 @@ bool Collector::collect()
 
   // MARK: first mark all referenced objects recursively starting out from the set of root objects
 
-  size_t originalLiveObjects = primaryHeap.numLiveObjects + numberHeap.numLiveObjects;
-
-  MarkStack stack;
-  stack.reserveCapacity(primaryHeap.numLiveObjects);
-
 #ifndef NDEBUG
   // Forbid malloc during the mark phase. Marking a thread suspends it, so 
-  // a malloc inside markChildren() would risk a deadlock with a thread that had been 
+  // a malloc inside mark() would risk a deadlock with a thread that had been 
   // suspended while holding the malloc lock.
   fastMallocForbid();
 #endif
@@ -975,25 +960,24 @@ bool Collector::collect()
   if (Interpreter::s_hook) {
     Interpreter* scr = Interpreter::s_hook;
     do {
-      scr->markRoots(stack);
-      drainMarkStack(stack);
+      scr->mark();
       scr = scr->next;
     } while (scr != Interpreter::s_hook);
   }
 
-  markStackObjectsConservatively(stack);
-  markProtectedObjects(stack);
-  List::markProtectedLists(stack);
-  drainMarkStack(stack);
+  markStackObjectsConservatively();
+  markProtectedObjects();
+  List::markProtectedLists();
 #if USE(MULTIPLE_THREADS)
   if (!currentThreadIsMainThread)
-    markMainThreadOnlyObjects(stack);
+    markMainThreadOnlyObjects();
 #endif
 
 #ifndef NDEBUG
   fastMallocAllow();
 #endif
     
+  size_t originalLiveObjects = primaryHeap.numLiveObjects + numberHeap.numLiveObjects;
   size_t numLiveObjects = sweep<PrimaryHeap>(currentThreadIsMainThread);
   numLiveObjects += sweep<NumberHeap>(currentThreadIsMainThread);
   
index 60990a6..c8372f7 100644 (file)
 
 namespace KJS {
 
-  class CollectorBlock;
   class JSCell;
   class JSValue;
-  class MarkStack;
+  class CollectorBlock;
 
   class Collector {
   public:
@@ -66,7 +65,6 @@ namespace KJS {
 
     static bool isCellMarked(const JSCell*);
     static void markCell(JSCell*);
-    static bool cellMayHaveRefs(const JSCell*);
 
     enum HeapType { PrimaryHeap, NumberHeap };
 
@@ -80,12 +78,12 @@ namespace KJS {
     Collector();
 
     static void recordExtraCost(size_t);
-    static void markProtectedObjects(MarkStack&);
-    static void markMainThreadOnlyObjects(MarkStack&);
-    static void markCurrentThreadConservatively(MarkStack&);
-    static void markOtherThreadConservatively(MarkStack&, Thread*);
-    static void markStackObjectsConservatively(MarkStack&);
-    static void markStackObjectsConservatively(MarkStack&, void* start, void* end);
+    static void markProtectedObjects();
+    static void markMainThreadOnlyObjects();
+    static void markCurrentThreadConservatively();
+    static void markOtherThreadConservatively(Thread*);
+    static void markStackObjectsConservatively();
+    static void markStackObjectsConservatively(void* start, void* end);
 
     static size_t mainThreadOnlyObjectCount;
     static bool memoryFull;
@@ -109,7 +107,7 @@ namespace KJS {
   const size_t SMALL_CELL_SIZE = CELL_SIZE / 2;
   const size_t CELL_MASK = CELL_SIZE - 1;
   const size_t CELL_ALIGN_MASK = ~CELL_MASK;
-  const size_t CELLS_PER_BLOCK = (BLOCK_SIZE * 8 - sizeof(uint32_t) * 8 - sizeof(uint32_t) * 8 - sizeof(void *) * 8 - 2 * (7 + 3 * 8)) / (CELL_SIZE * 8 + 2);
+  const size_t CELLS_PER_BLOCK = (BLOCK_SIZE * 8 - sizeof(uint32_t) * 8 - sizeof(void *) * 8 - 2 * (7 + 3 * 8)) / (CELL_SIZE * 8 + 2);
   const size_t SMALL_CELLS_PER_BLOCK = 2 * CELLS_PER_BLOCK;
   const size_t BITMAP_SIZE = (CELLS_PER_BLOCK + 7) / 8;
   const size_t BITMAP_WORDS = (BITMAP_SIZE + 3) / sizeof(uint32_t);
@@ -147,7 +145,6 @@ namespace KJS {
     CollectorCell cells[CELLS_PER_BLOCK];
     uint32_t usedCells;
     CollectorCell* freeList;
-    uint32_t mayHaveRefs;
     CollectorBitmap marked;
     CollectorBitmap collectOnMainThreadOnly;
   };
@@ -157,7 +154,6 @@ namespace KJS {
     SmallCollectorCell cells[SMALL_CELLS_PER_BLOCK];
     uint32_t usedCells;
     SmallCollectorCell* freeList;
-    uint32_t mayHaveRefs;
     CollectorBitmap marked;
     CollectorBitmap collectOnMainThreadOnly;
   };
@@ -187,11 +183,6 @@ namespace KJS {
     cellBlock(cell)->marked.set(cellOffset(cell));
   }
 
-  inline bool Collector::cellMayHaveRefs(const JSCell* cell)
-  {
-    return cellBlock(cell)->mayHaveRefs;
-  }
-
   inline void Collector::reportExtraMemoryCost(size_t cost)
   { 
     if (cost > minExtraCostSize) 
index 69a6151..0697f10 100644 (file)
@@ -156,3 +156,9 @@ JSValue* NativeErrorImp::callAsFunction(ExecState* exec, JSObject*, const List&
   return construct(exec, args);
 }
 
+void NativeErrorImp::mark()
+{
+  JSObject::mark();
+  if (proto && !proto->marked())
+    proto->mark();
+}
index 65154a7..3e1ac8a 100644 (file)
@@ -75,6 +75,8 @@ namespace KJS {
     virtual JSObject *construct(ExecState *exec, const List &args);
     virtual JSValue *callAsFunction(ExecState *exec, JSObject *thisObj, const List &args);
 
+    virtual void mark();
+
     virtual const ClassInfo *classInfo() const { return &info; }
     static const ClassInfo info;
   private:
index 49ebd89..1dc40a4 100644 (file)
@@ -61,10 +61,10 @@ FunctionImp::FunctionImp(ExecState* exec, const Identifier& name, FunctionBodyNo
 {
 }
 
-void FunctionImp::markChildren(MarkStack& stack)
+void FunctionImp::mark()
 {
-    InternalFunctionImp::markChildren(stack);
-    _scope.markChildren(stack);
+    InternalFunctionImp::mark();
+    _scope.mark();
 }
 
 JSValue* FunctionImp::callAsFunction(ExecState* exec, JSObject* thisObj, const List& args)
@@ -331,9 +331,9 @@ const ClassInfo Arguments::info = { "Arguments", 0, 0 };
 
 // ECMA 10.1.8
 Arguments::Arguments(ExecState* exec, FunctionImp* func, const List& args, ActivationImp* act)
-  : JSObject(exec->lexicalInterpreter()->builtinObjectPrototype()) 
-  , _activationObject(act)
-  , indexToNameMap(func, args)
+: JSObject(exec->lexicalInterpreter()->builtinObjectPrototype()), 
+_activationObject(act),
+indexToNameMap(func, args)
 {
   putDirect(exec->propertyNames().callee, func, DontEnum);
   putDirect(exec->propertyNames().length, args.size(), DontEnum);
@@ -347,10 +347,11 @@ Arguments::Arguments(ExecState* exec, FunctionImp* func, const List& args, Activ
   }
 }
 
-void Arguments::markChildren(MarkStack& stack
+void Arguments::mark(
 {
-  JSObject::markChildren(stack);
-  stack.push(_activationObject);
+  JSObject::mark();
+  if (_activationObject && !_activationObject->marked())
+    _activationObject->mark();
 }
 
 JSValue* Arguments::mappedIndexGetter(ExecState* exec, JSObject*, const Identifier& propertyName, const PropertySlot& slot)
@@ -483,17 +484,23 @@ void ActivationImp::put(ExecState*, const Identifier& propertyName, JSValue* val
   _prop.put(propertyName, value, attr, (attr == None || attr == DontDelete));
 }
 
-void ActivationImp::markChildren(MarkStack& stack)
+void ActivationImp::mark()
 {
-    JSObject::markChildren(stack);
+    JSObject::mark();
 
     size_t size = d->localStorage.size();
-    for (size_t i = 0; i < size; ++i)
-        stack.push(d->localStorage[i].value);
+    for (size_t i = 0; i < size; ++i) {
+        JSValue* value = d->localStorage[i].value;
+        if (!value->marked())
+            value->mark();
+    }
     
-    stack.push(d->function);
-    if (d->argumentsObject)
-      stack.push(d->argumentsObject);
+    ASSERT(d->function);
+    if (!d->function->marked())
+        d->function->mark();
+
+    if (d->argumentsObject && !d->argumentsObject->marked())
+        d->argumentsObject->mark();
 }
 
 void ActivationImp::createArgumentsObject(ExecState* exec)
index 392127e..5657b1e 100644 (file)
@@ -95,7 +95,7 @@ namespace KJS {
     void setScope(const ScopeChain& s) { _scope = s; }
     const ScopeChain& scope() const { return _scope; }
 
-    virtual void markChildren(MarkStack&);
+    virtual void mark();
 
   private:
     ScopeChain _scope;
@@ -124,7 +124,7 @@ namespace KJS {
   class Arguments : public JSObject {
   public:
     Arguments(ExecState*, FunctionImp* func, const List& args, ActivationImp* act);
-    virtual void markChildren(MarkStack&);
+    virtual void mark();
     virtual bool getOwnPropertySlot(ExecState*, const Identifier&, PropertySlot&);
     virtual void put(ExecState*, const Identifier& propertyName, JSValue* value, int attr = None);
     virtual bool deleteProperty(ExecState*, const Identifier& propertyName);
@@ -164,7 +164,7 @@ namespace KJS {
     virtual const ClassInfo* classInfo() const { return &info; }
     static const ClassInfo info;
 
-    virtual void markChildren(MarkStack&);
+    virtual void mark();
 
     bool isActivation() { return true; }
 
index faf9f98..125244e 100644 (file)
@@ -144,12 +144,14 @@ bool NumberImp::getTruncatedUInt32(uint32_t& uint32) const
 }
 
 // --------------------------- GetterSetterImp ---------------------------------
-void GetterSetterImp::markChildren(MarkStack& stack)
+void GetterSetterImp::mark()
 {
-    if (getter)
-        stack.push(getter);
-    if (setter)
-        stack.push(setter);
+    JSCell::mark();
+    
+    if (getter && !getter->marked())
+        getter->mark();
+    if (setter && !setter->marked())
+        setter->mark();
 }
 
 JSValue* GetterSetterImp::toPrimitive(ExecState*, JSType) const
index eb2bbc8..2d381b2 100644 (file)
@@ -544,80 +544,80 @@ JSObject *Interpreter::builtinURIErrorPrototype() const
   return m_UriErrorPrototype;
 }
 
-void Interpreter::markRoots(MarkStack& stack)
+void Interpreter::mark()
 {
     if (m_currentExec)
-        m_currentExec->markChildren(stack);
-
-    if (m_globalExec.exception())
-        stack.push(m_globalExec.exception());
-
-    if (m_globalObject)
-        stack.push(m_globalObject);
-
-    if (m_Object)
-       stack.push(m_Object);
-    if (m_Function)
-        stack.push(m_Function);
-    if (m_Array)
-        stack.push(m_Array);
-    if (m_Boolean)
-        stack.push(m_Boolean);
-    if (m_String)
-        stack.push(m_String);
-    if (m_Number)
-        stack.push(m_Number);
-    if (m_Date)
-        stack.push(m_Date);
-    if (m_RegExp)
-        stack.push(m_RegExp);
-    if (m_Error)
-        stack.push(m_Error);
-    
-    if (m_ObjectPrototype)
-        stack.push(m_ObjectPrototype);
-    if (m_FunctionPrototype)
-        stack.push(m_FunctionPrototype);
-    if (m_ArrayPrototype)
-        stack.push(m_ArrayPrototype);
-    if (m_BooleanPrototype)
-        stack.push(m_BooleanPrototype);
-    if (m_StringPrototype)
-        stack.push(m_StringPrototype);
-    if (m_NumberPrototype)
-        stack.push(m_NumberPrototype);
-    if (m_DatePrototype)
-        stack.push(m_DatePrototype);
-    if (m_RegExpPrototype)
-        stack.push(m_RegExpPrototype);
-    if (m_ErrorPrototype)
-        stack.push(m_ErrorPrototype);
-    
-    if (m_EvalError)
-        stack.push(m_EvalError);
-    if (m_RangeError)
-        stack.push(m_RangeError);
-    if (m_ReferenceError)
-        stack.push(m_ReferenceError);
-    if (m_SyntaxError)
-        stack.push(m_SyntaxError);
-    if (m_TypeError)
-        stack.push(m_TypeError);
-    if (m_UriError)
-        stack.push(m_UriError);
-    
-    if (m_EvalErrorPrototype)
-        stack.push(m_EvalErrorPrototype);
-    if (m_RangeErrorPrototype)
-        stack.push(m_RangeErrorPrototype);
-    if (m_ReferenceErrorPrototype)
-        stack.push(m_ReferenceErrorPrototype);
-    if (m_SyntaxErrorPrototype)
-        stack.push(m_SyntaxErrorPrototype);
-    if (m_TypeErrorPrototype)
-        stack.push(m_TypeErrorPrototype);
-    if (m_UriErrorPrototype)
-        stack.push(m_UriErrorPrototype);
+        m_currentExec->mark();
+
+    if (m_globalExec.exception() && !m_globalExec.exception()->marked())
+        m_globalExec.exception()->mark();
+
+    if (m_globalObject && !m_globalObject->marked())
+        m_globalObject->mark();
+
+    if (m_Object && !m_Object->marked())
+        m_Object->mark();
+    if (m_Function && !m_Function->marked())
+        m_Function->mark();
+    if (m_Array && !m_Array->marked())
+        m_Array->mark();
+    if (m_Boolean && !m_Boolean->marked())
+        m_Boolean->mark();
+    if (m_String && !m_String->marked())
+        m_String->mark();
+    if (m_Number && !m_Number->marked())
+        m_Number->mark();
+    if (m_Date && !m_Date->marked())
+        m_Date->mark();
+    if (m_RegExp && !m_RegExp->marked())
+        m_RegExp->mark();
+    if (m_Error && !m_Error->marked())
+        m_Error->mark();
+    
+    if (m_ObjectPrototype && !m_ObjectPrototype->marked())
+        m_ObjectPrototype->mark();
+    if (m_FunctionPrototype && !m_FunctionPrototype->marked())
+        m_FunctionPrototype->mark();
+    if (m_ArrayPrototype && !m_ArrayPrototype->marked())
+        m_ArrayPrototype->mark();
+    if (m_BooleanPrototype && !m_BooleanPrototype->marked())
+        m_BooleanPrototype->mark();
+    if (m_StringPrototype && !m_StringPrototype->marked())
+        m_StringPrototype->mark();
+    if (m_NumberPrototype && !m_NumberPrototype->marked())
+        m_NumberPrototype->mark();
+    if (m_DatePrototype && !m_DatePrototype->marked())
+        m_DatePrototype->mark();
+    if (m_RegExpPrototype && !m_RegExpPrototype->marked())
+        m_RegExpPrototype->mark();
+    if (m_ErrorPrototype && !m_ErrorPrototype->marked())
+        m_ErrorPrototype->mark();
+    
+    if (m_EvalError && !m_EvalError->marked())
+        m_EvalError->mark();
+    if (m_RangeError && !m_RangeError->marked())
+        m_RangeError->mark();
+    if (m_ReferenceError && !m_ReferenceError->marked())
+        m_ReferenceError->mark();
+    if (m_SyntaxError && !m_SyntaxError->marked())
+        m_SyntaxError->mark();
+    if (m_TypeError && !m_TypeError->marked())
+        m_TypeError->mark();
+    if (m_UriError && !m_UriError->marked())
+        m_UriError->mark();
+    
+    if (m_EvalErrorPrototype && !m_EvalErrorPrototype->marked())
+        m_EvalErrorPrototype->mark();
+    if (m_RangeErrorPrototype && !m_RangeErrorPrototype->marked())
+        m_RangeErrorPrototype->mark();
+    if (m_ReferenceErrorPrototype && !m_ReferenceErrorPrototype->marked())
+        m_ReferenceErrorPrototype->mark();
+    if (m_SyntaxErrorPrototype && !m_SyntaxErrorPrototype->marked())
+        m_SyntaxErrorPrototype->mark();
+    if (m_TypeErrorPrototype && !m_TypeErrorPrototype->marked())
+        m_TypeErrorPrototype->mark();
+    if (m_UriErrorPrototype && !m_UriErrorPrototype->marked())
+        m_UriErrorPrototype->mark();
 }
 
 static bool printExceptions = false;
index 9f54d3a..3cb86c2 100644 (file)
@@ -290,7 +290,7 @@ namespace KJS {
      * Called during the mark phase of the garbage collector. Subclasses 
      * implementing custom mark methods must make sure to chain to this one.
      */
-    virtual void markRoots(MarkStack&);
+    virtual void mark();
 
     static bool shouldPrintExceptions();
     static void setShouldPrintExceptions(bool);
index f60051f..eec703e 100644 (file)
@@ -43,15 +43,18 @@ List::ListSet& List::markSet()
     return staticMarkSet;
 }
 
-void List::markProtectedListsSlowCase(MarkStack& stack)
+void List::markProtectedListsSlowCase()
 {
     ListSet::iterator end = markSet().end();
     for (ListSet::iterator it = markSet().begin(); it != end; ++it) {
         List* list = *it;
 
         iterator end2 = list->end();
-        for (iterator it2 = list->begin(); it2 != end2; ++it2)
-            stack.push(*it2);
+        for (iterator it2 = list->begin(); it2 != end2; ++it2) {
+            JSValue* v = *it2;
+            if (!v->marked())
+                v->mark();
+        }
     }
 }
 
index 4969b3a..b66e710 100644 (file)
@@ -85,18 +85,18 @@ namespace KJS {
         const_iterator begin() const { return m_vector.begin(); }
         const_iterator end() const { return m_vector.end(); }
 
-        static void markProtectedLists(MarkStack& stack)
+        static void markProtectedLists()
         {
             if (!markSet().size())
                 return;
-            markProtectedListsSlowCase(stack);
+            markProtectedListsSlowCase();
         }
 
         static const List& empty(); // Fast path for an empty list.
 
     private:
         static ListSet& markSet();
-        static void markProtectedListsSlowCase(MarkStack&);
+        static void markProtectedListsSlowCase();
 
         void expandAndAppend(JSValue*);
 
index 8514b0c..13d5e65 100644 (file)
@@ -113,8 +113,10 @@ JSValue *JSObject::call(ExecState *exec, JSObject *thisObj, const List &args)
 
 // ------------------------------ JSObject ------------------------------------
 
-void JSObject::markChildren(MarkStack& stack)
+void JSObject::mark()
 {
+  JSCell::mark();
+
 #if JAVASCRIPT_MARK_TRACING
   static int markStackDepth = 0;
   markStackDepth++;
@@ -124,8 +126,11 @@ void JSObject::markChildren(MarkStack& stack)
   printf("%s (%p)\n", className().UTF8String().c_str(), this);
 #endif
   
-  stack.push(_proto);
-  _prop.markChildren(stack);
+  JSValue *proto = _proto;
+  if (!proto->marked())
+    proto->mark();
+
+  _prop.mark();
   
 #if JAVASCRIPT_MARK_TRACING
   markStackDepth--;
index 531d0d6..1f45f5e 100644 (file)
@@ -27,7 +27,6 @@
 
 #include "JSType.h"
 #include "CommonIdentifiers.h"
-#include "MarkStack.h"
 #include "interpreter.h"
 #include "property_map.h"
 #include "property_slot.h"
@@ -85,7 +84,7 @@ namespace KJS {
     virtual UString toString(ExecState *exec) const;
     virtual JSObject *toObject(ExecState *exec) const;
       
-    virtual void markChildren(MarkStack&);
+    virtual void mark();
       
     JSObject *getGetter() { return getter; }
     void setGetter(JSObject *g) { getter = g; }
@@ -112,7 +111,7 @@ namespace KJS {
      */
     JSObject();
 
-    virtual void markChildren(MarkStack&);
+    virtual void mark();
     virtual JSType type() const;
 
     /**
@@ -587,11 +586,12 @@ ALWAYS_INLINE bool JSObject::getOwnPropertySlot(ExecState* exec, const Identifie
 
 // FIXME: Put this function in a separate file named something like scope_chain_mark.h -- can't put it in scope_chain.h since it depends on JSObject.
 
-inline void ScopeChain::markChildren(MarkStack& stack)
+inline void ScopeChain::mark()
 {
-    for (ScopeChainNode* n = _node; n; n = n->next) {
-        JSObject* o = n->object;
-        stack.push(o);
+    for (ScopeChainNode *n = _node; n; n = n->next) {
+        JSObject *o = n->object;
+        if (!o->marked())
+            o->mark();
     }
 }
 
index 11c796b..45e391a 100644 (file)
@@ -622,19 +622,25 @@ void PropertyMap::remove(const Identifier& name)
     checkConsistency();
 }
 
-void PropertyMap::markChildren(MarkStack& stack) const
+void PropertyMap::mark() const
 {
     if (!m_usingTable) {
 #if USE_SINGLE_ENTRY
-        if (m_singleEntryKey)
-            stack.push(m_u.singleEntryValue);
+        if (m_singleEntryKey) {
+            JSValue* v = m_u.singleEntryValue;
+            if (!v->marked())
+                v->mark();
+        }
 #endif
         return;
     }
 
     unsigned entryCount = m_u.table->keyCount + m_u.table->deletedSentinelCount;
-    for (unsigned i = 1; i <= entryCount; i++)
-        stack.push(m_u.table->entries()[i].value);
+    for (unsigned i = 1; i <= entryCount; i++) {
+        JSValue* v = m_u.table->entries()[i].value;
+        if (!v->marked())
+            v->mark();
+    }
 }
 
 static int comparePropertyMapEntryIndices(const void* a, const void* b)
index 097e5b8..82144ef 100644 (file)
@@ -29,7 +29,6 @@ namespace KJS {
 
     class JSObject;
     class JSValue;
-    class MarkStack;
     class PropertyNameArray;
     
     struct PropertyMapEntry;
@@ -60,7 +59,7 @@ namespace KJS {
         JSValue* get(const Identifier&, unsigned& attributes) const;
         JSValue** getLocation(const Identifier& name);
 
-        void markChildren(MarkStack&) const;
+        void mark() const;
         void getEnumerablePropertyNames(PropertyNameArray&) const;
 
         void save(SavedProperties&) const;
index eb2e89b..a10abcd 100644 (file)
@@ -82,7 +82,7 @@ namespace KJS {
         void push(const ScopeChain &);
         void pop();
         
-        void markChildren(MarkStack&);
+        void mark();
 
 #ifndef NDEBUG        
         void print();
index c772247..c74f549 100644 (file)
@@ -129,12 +129,6 @@ void StringInstance::getPropertyNames(ExecState* exec, PropertyNameArray& proper
   return JSObject::getPropertyNames(exec, propertyNames);
 }
 
-void StringInstance::markChildren(MarkStack& stack) 
-{
-    JSObject::markChildren(stack);
-    stack.pushAtom(internalValue());
-}
-
 // ------------------------------ StringPrototype ---------------------------
 const ClassInfo StringPrototype::info = { "String", &StringInstance::info, &stringTable };
 /* Source for string_object.lut.h
index b295e21..ad3c52a 100644 (file)
@@ -46,7 +46,6 @@ namespace KJS {
     static const ClassInfo info;
 
     StringImp* internalValue() const { return static_cast<StringImp*>(JSWrapperObject::internalValue());}
-    virtual void markChildren(MarkStack& stack);
 
   private:
     bool inlineGetOwnPropertySlot(ExecState*, unsigned, PropertySlot&);
index b826a40..5ebb575 100644 (file)
@@ -33,7 +33,6 @@ namespace KJS {
 class ExecState;
 class JSObject;
 class JSCell;
-class MarkStack;
 
 struct ClassInfo;
 
@@ -48,7 +47,6 @@ struct ClassInfo;
 class JSValue : Noncopyable {
     friend class JSCell; // so it can derive from this class
     friend class Collector; // so it can call asCell()
-    friend class MarkStack; // so it can call asCell()
 
 private:
     JSValue();
@@ -107,7 +105,7 @@ public:
     float toFloat(ExecState*) const;
 
     // Garbage collection.
-    void markChildren(MarkStack&);
+    void mark();
     bool marked() const;
 
     static int32_t toInt32SlowCase(double, bool& ok);
@@ -166,7 +164,7 @@ public:
 
     // Garbage collection.
     void *operator new(size_t);
-    virtual void markChildren(MarkStack&);
+    virtual void mark();
     bool marked() const;
 };
 
@@ -292,8 +290,9 @@ inline bool JSCell::marked() const
     return Collector::isCellMarked(this);
 }
 
-inline void JSCell::markChildren(MarkStack&)
+inline void JSCell::mark()
 {
+    return Collector::markCell(this);
 }
 
 ALWAYS_INLINE JSCell* JSValue::asCell()
@@ -407,10 +406,10 @@ inline bool JSValue::getTruncatedUInt32(uint32_t& v) const
     return JSImmediate::isImmediate(this) ? JSImmediate::getTruncatedUInt32(this, v) : asCell()->getTruncatedUInt32(v);
 }
 
-inline void JSValue::markChildren(MarkStack& stack)
+inline void JSValue::mark()
 {
-    ASSERT(!JSImmediate::isImmediate(this)); // callers should check !marked() before calling markChildren()
-    asCell()->markChildren(stack);
+    ASSERT(!JSImmediate::isImmediate(this)); // callers should check !marked() before calling mark()
+    asCell()->mark();
 }
 
 inline bool JSValue::marked() const
index 0122148..65e4a69 100644 (file)
@@ -1,18 +1,3 @@
-2007-11-28  Maciej Stachowiak  <mjs@apple.com>
-
-        Reviewed by Darin and Geoff.
-
-        Fixups for JavaScriptCore mark stack.
-
-        * JSObject.cpp:
-        (JSUserObject::Mark):
-        * JSObject.h:
-        * JSValueWrapper.cpp:
-        (JSValueWrapper::JSObjectMark):
-        * JSValueWrapper.h:
-        * UserObjectImp.cpp:
-        * UserObjectImp.h:
-
 2007-11-27  Anders Carlsson  <andersca@apple.com>
         
         Build fix.
index d458936..1290cb3 100644 (file)
@@ -122,11 +122,11 @@ UInt8 JSUserObject::Equal(JSBase* other)
     return result;
 }
 
-void JSUserObject::Mark(KJS::MarkStack& stack)
+void JSUserObject::Mark()
 {
     if (fMarkProc)
     {
-        fMarkProc(stack, fData);
+        fMarkProc(fData);
     }
 }
 
index 3d4b394..f0be22e 100644 (file)
@@ -32,7 +32,7 @@
 #include "JSBase.h"
 #include "JSUtils.h"
 
-typedef void (*JSObjectMarkProcPtr)(MarkStack&, void *data);
+typedef void (*JSObjectMarkProcPtr)(void *data);
 JSObjectRef JSObjectCreateInternal(void *data, JSObjectCallBacksPtr callBacks, JSObjectMarkProcPtr markProc, int dataType);
 
 class JSUserObject : public JSBase {
@@ -48,7 +48,7 @@ class JSUserObject : public JSBase {
         CFTypeRef CopyCFValue() const;
         virtual UInt8 Equal(JSBase* other);
         void *GetData();
-        void Mark(KJS::MarkStack&);
+        void Mark();
 
                 int DataType() const { return fDataType; }
     private:
index e3f8024..a101c8c 100644 (file)
@@ -230,11 +230,11 @@ CFTypeRef JSValueWrapper::JSObjectCopyCFValue(void *data)
     return result;
 }
 
-void JSValueWrapper::JSObjectMark(MarkStack& stack, void *data)
+void JSValueWrapper::JSObjectMark(void *data)
 {
     JSValueWrapper* ptr = (JSValueWrapper*)data;
     if (ptr)
     {
-        ptr->fValue->markChildren(stack);
+        ptr->fValue->mark();
     }
 }
index a90f261..5c33297 100644 (file)
@@ -51,7 +51,7 @@ private:
     static void JSObjectSetProperty(void *data, CFStringRef propertyName, JSObjectRef jsValue);
     static JSObjectRef JSObjectCallFunction(void *data, JSObjectRef thisObj, CFArrayRef args);
     static CFTypeRef JSObjectCopyCFValue(void *data);
-    static void JSObjectMark(KJS::MarkStack&, void *data);
+    static void JSObjectMark(void *data);
 };
 
 #endif
index 2517e52..20c06c3 100644 (file)
@@ -406,9 +406,9 @@ UString UserObjectImp::toString(ExecState *exec) const
     return result;
 }
 
-void UserObjectImp::markChildren(MarkStack& stack)
+void UserObjectImp::mark()
 {
-    JSObject::markChildren(stack);
+    JSObject::mark();
     if (fJSUserObject)
-        fJSUserObject->Mark(stack);
+        fJSUserObject->Mark();
 }
index 0b99508..54e5ab6 100644 (file)
@@ -55,7 +55,7 @@ public:
     virtual double toNumber(ExecState *exec) const;
     virtual UString toString(ExecState *exec) const;
 
-    virtual void markChildren(MarkStack& stack);
+    virtual void mark();
 
     JSUserObject *GetJSUserObject() const;
 private:
index 989dba3..7400730 100644 (file)
@@ -1,55 +1,3 @@
-2007-11-28  Maciej Stachowiak  <mjs@apple.com>
-
-        add files missing from previous commit.
-
-        * fast/js/gc-breadth-2-expected.txt: Added.
-        * fast/js/gc-breadth-2.html: Added.
-        * fast/js/gc-breadth-expected.txt: Added.
-        * fast/js/gc-breadth.html: Added.
-        * fast/js/gc-depth-expected.txt: Added.
-        * fast/js/gc-depth.html: Added.
-        * fast/js/resources/gc-breadth-2.js: Added.
-        * fast/js/resources/gc-breadth.js: Added.
-        * fast/js/resources/gc-depth.js: Added.
-
-2007-11-28  Maciej Stachowiak  <mjs@apple.com>
-
-        Not reviewed.
-        
-        - Test cases for "Stack overflow crash in JavaScript garbage collector mark pass"
-        http://bugs.webkit.org/show_bug.cgi?id=12216
-
-        I have fixed this with the mark stack work.
-        
-        * fast/js/gc-breadth-2-expected.txt: Added.
-        * fast/js/gc-breadth-2.html: Added.
-        * fast/js/gc-breadth-expected.txt: Added.
-        * fast/js/gc-breadth.html: Added.
-        * fast/js/gc-depth-expected.txt: Added.
-        * fast/js/gc-depth.html: Added.
-        * fast/js/resources/gc-breadth-2.js: Added.
-        * fast/js/resources/gc-breadth.js: Added.
-        * fast/js/resources/gc-depth.js: Added.
-
-2007-11-28  Maciej Stachowiak  <mjs@apple.com>
-
-        Not reviewed.
-        
-        - Test cases for "Stack overflow crash in JavaScript garbage collector mark pass"
-        http://bugs.webkit.org/show_bug.cgi?id=12216
-
-        I have fixed this with the mark stack work.
-        
-        * fast/js/gc-breadth-2-expected.txt: Added.
-        * fast/js/gc-breadth-2.html: Added.
-        * fast/js/gc-breadth-expected.txt: Added.
-        * fast/js/gc-breadth.html: Added.
-        * fast/js/gc-depth-expected.txt: Added.
-        * fast/js/gc-depth.html: Added.
-        * fast/js/resources/gc-breadth-2.js: Added.
-        * fast/js/resources/gc-breadth.js: Added.
-        * fast/js/resources/gc-depth.js: Added.
-
 2007-11-27  Beth Dakin  <bdakin@apple.com>
 
         Reviewed by Oliver.
diff --git a/LayoutTests/fast/js/gc-breadth-2-expected.txt b/LayoutTests/fast/js/gc-breadth-2-expected.txt
deleted file mode 100644 (file)
index fe88aae..0000000
+++ /dev/null
@@ -1,18 +0,0 @@
-This test makes sure that wide object structures don't lead to GC crashes.
-
-On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
-
-
-PASS successfullyParsed is true
-
-TEST COMPLETE
-
-This test makes sure that wide object structures don't lead to GC crashes.
-
-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/gc-breadth-2.html b/LayoutTests/fast/js/gc-breadth-2.html
deleted file mode 100644 (file)
index 4a6c1d2..0000000
+++ /dev/null
@@ -1,26 +0,0 @@
-<!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/gc-breadth-2.js"></script>
-<script src="resources/js-test-post.js"></script>
-</body>
-</html>
-<!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/gc-breadth-2.js"></script>
-<script src="resources/js-test-post.js"></script>
-</body>
-</html>
diff --git a/LayoutTests/fast/js/gc-breadth-expected.txt b/LayoutTests/fast/js/gc-breadth-expected.txt
deleted file mode 100644 (file)
index fe88aae..0000000
+++ /dev/null
@@ -1,18 +0,0 @@
-This test makes sure that wide object structures don't lead to GC crashes.
-
-On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
-
-
-PASS successfullyParsed is true
-
-TEST COMPLETE
-
-This test makes sure that wide object structures don't lead to GC crashes.
-
-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/gc-breadth.html b/LayoutTests/fast/js/gc-breadth.html
deleted file mode 100644 (file)
index 8d631d7..0000000
+++ /dev/null
@@ -1,26 +0,0 @@
-<!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/gc-breadth.js"></script>
-<script src="resources/js-test-post.js"></script>
-</body>
-</html>
-<!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/gc-breadth.js"></script>
-<script src="resources/js-test-post.js"></script>
-</body>
-</html>
diff --git a/LayoutTests/fast/js/gc-depth-expected.txt b/LayoutTests/fast/js/gc-depth-expected.txt
deleted file mode 100644 (file)
index 25ba143..0000000
+++ /dev/null
@@ -1,18 +0,0 @@
-This test makes sure that deep object structures don't lead to GC crashes.
-
-On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
-
-
-PASS successfullyParsed is true
-
-TEST COMPLETE
-
-This test makes sure that deep object structures don't lead to GC crashes.
-
-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/gc-depth.html b/LayoutTests/fast/js/gc-depth.html
deleted file mode 100644 (file)
index dfb58a1..0000000
+++ /dev/null
@@ -1,26 +0,0 @@
-<!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/gc-depth.js"></script>
-<script src="resources/js-test-post.js"></script>
-</body>
-</html>
-<!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/gc-depth.js"></script>
-<script src="resources/js-test-post.js"></script>
-</body>
-</html>
diff --git a/LayoutTests/fast/js/resources/gc-breadth-2.js b/LayoutTests/fast/js/resources/gc-breadth-2.js
deleted file mode 100644 (file)
index 38455b0..0000000
+++ /dev/null
@@ -1,26 +0,0 @@
-description("This test makes sure that wide object structures don't lead to GC crashes.")
-
-var a = {};
-for (var i = 0; i < 200000; i++) {
-    a[i] = {};
-}
-
-var b = "";
-for (var i = 0; i < 80000; i++) {
-    b += "b";
-}
-
-var successfullyParsed = true;
-description("This test makes sure that wide object structures don't lead to GC crashes.")
-
-var a = {};
-for (var i = 0; i < 200000; i++) {
-    a[i] = {};
-}
-
-var b = "";
-for (var i = 0; i < 80000; i++) {
-    b += "b";
-}
-
-var successfullyParsed = true;
diff --git a/LayoutTests/fast/js/resources/gc-breadth.js b/LayoutTests/fast/js/resources/gc-breadth.js
deleted file mode 100644 (file)
index 45df7bb..0000000
+++ /dev/null
@@ -1,26 +0,0 @@
-description("This test makes sure that wide object structures don't lead to GC crashes.")
-
-var a = [];
-for (var i = 0; i < 200000; i++) {
-    a[i] = [];
-}
-
-var b = "";
-for (var i = 0; i < 80000; i++) {
-    b += "b";
-}
-
-var successfullyParsed = true;
-description("This test makes sure that wide object structures don't lead to GC crashes.")
-
-var a = [];
-for (var i = 0; i < 200000; i++) {
-    a[i] = [];
-}
-
-var b = "";
-for (var i = 0; i < 80000; i++) {
-    b += "b";
-}
-
-var successfullyParsed = true;
diff --git a/LayoutTests/fast/js/resources/gc-depth.js b/LayoutTests/fast/js/resources/gc-depth.js
deleted file mode 100644 (file)
index f6fe7f2..0000000
+++ /dev/null
@@ -1,26 +0,0 @@
-description("This test makes sure that deep object structures don't lead to GC crashes.")
-
-var a = [];
-for (var i = 0; i < 200000; i++) {
-    a = [a];
-}
-
-var b = "";
-for (var i = 0; i < 80000; i++) {
-    b += "b";
-}
-
-var successfullyParsed = true;
-description("This test makes sure that deep object structures don't lead to GC crashes.")
-
-var a = [];
-for (var i = 0; i < 200000; i++) {
-    a = [a];
-}
-
-var b = "";
-for (var i = 0; i < 80000; i++) {
-    b += "b";
-}
-
-var successfullyParsed = true;
index 7826cbd..9e0c71f 100644 (file)
         * platform/graphics/cairo/ImageSourceCairo.cpp:
         (WebCore::ImageSource::frameHasAlphaAtIndex):
 
-2007-11-28  Maciej Stachowiak  <mjs@apple.com>
-
-        Reviewed by Darin and Geoff.
-
-        Implement mark stack. This version is not suitable for prime time because it makes a
-        huge allocation on every collect, and potentially makes marking of detached subtrees
-        slow. But it is a .2% - .4% speedup even without much tweaking.
-
-        I replaced mark() methods with markChildren() as usual. One
-        optimization that is lost is avoiding walking detached DOM
-        subtrees more than once to mark them; since marking is not
-        recursive there's no obvious way to bracket operation on the tree
-        any more.
-
-        * bindings/js/JSDocumentCustom.cpp:
-        (WebCore::JSDocument::markChildren):
-        * bindings/js/JSNodeCustom.cpp:
-        (WebCore::JSNode::markChildren):
-        * bindings/js/JSNodeFilterCondition.cpp:
-        * bindings/js/JSNodeFilterCondition.h:
-        * bindings/js/JSNodeFilterCustom.cpp:
-        (WebCore::JSNodeFilter::markChildren):
-        * bindings/js/JSNodeIteratorCustom.cpp:
-        (WebCore::JSNodeIterator::markChildren):
-        * bindings/js/JSTreeWalkerCustom.cpp:
-        (WebCore::JSTreeWalker::markChildren):
-        * bindings/js/JSXMLHttpRequest.cpp:
-        (KJS::JSXMLHttpRequest::markChildren):
-        * bindings/js/JSXMLHttpRequest.h:
-        * bindings/js/kjs_binding.cpp:
-        (KJS::ScriptInterpreter::markDOMNodesForDocument):
-        * bindings/js/kjs_binding.h:
-        * bindings/js/kjs_events.cpp:
-        (WebCore::JSUnprotectedEventListener::markChildren):
-        * bindings/js/kjs_events.h:
-        * bindings/js/kjs_window.cpp:
-        (KJS::Window::markChildren):
-        * bindings/js/kjs_window.h:
-        * bindings/scripts/CodeGeneratorJS.pm:
-        * dom/Node.cpp:
-        (WebCore::Node::Node):
-        * dom/Node.h:
-        * dom/NodeFilter.h:
-        * dom/NodeFilterCondition.h:
-
 2007-11-27  Alp Toker  <alp@atoker.com>
 
         Reviewed by Mark Rowe.
index 423d44a..20957f0 100644 (file)
@@ -37,10 +37,10 @@ namespace WebCore {
 
 using namespace KJS;
 
-void JSDocument::markChildren(MarkStack& stack)
+void JSDocument::mark()
 {
-    DOMObject::markChildren(stack);
-    ScriptInterpreter::markDOMNodesForDocument(stack, static_cast<Document*>(impl()));
+    DOMObject::mark();
+    ScriptInterpreter::markDOMNodesForDocument(static_cast<Document*>(impl()));
 }
 
 JSValue* JSDocument::location(ExecState* exec) const
index f2ca614..6a5ce1c 100644 (file)
@@ -104,7 +104,7 @@ KJS::JSValue* JSNode::appendChild(KJS::ExecState* exec, const KJS::List& args)
     return KJS::jsNull();
 }
 
-void JSNode::markChildren(KJS::MarkStack& stack)
+void JSNode::mark()
 {
     ASSERT(!marked());
 
@@ -113,7 +113,7 @@ void JSNode::markChildren(KJS::MarkStack& stack)
     // Nodes in the document are kept alive by ScriptInterpreter::mark,
     // so we have no special responsibilities and can just call the base class here.
     if (node->inDocument()) {
-        DOMObject::markChildren(stack);
+        DOMObject::mark();
         return;
     }
 
@@ -123,12 +123,31 @@ void JSNode::markChildren(KJS::MarkStack& stack)
     for (Node* current = m_impl.get(); current; current = current->parentNode())
         root = current;
 
-    // Mark the whole tree
-    for (Node* nodeToMark = root; nodeToMark; nodeToMark = nodeToMark->traverseNextNode())
-        if (JSNode* wrapper = KJS::ScriptInterpreter::getDOMNodeForDocument(m_impl->document(), nodeToMark))
-            stack.push(wrapper);
+    // If we're already marking this tree, then we can simply mark this wrapper
+    // by calling the base class; our caller is iterating the tree.
+    if (root->m_inSubtreeMark) {
+        DOMObject::mark();
+        return;
+    }
 
-    DOMObject::markChildren(stack);
+    // Mark the whole tree; use the global set of roots to avoid reentering.
+    root->m_inSubtreeMark = true;
+    for (Node* nodeToMark = root; nodeToMark; nodeToMark = nodeToMark->traverseNextNode()) {
+        JSNode* wrapper = KJS::ScriptInterpreter::getDOMNodeForDocument(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();
+        }
+    }
+    root->m_inSubtreeMark = false;
 
     // Double check that we actually ended up marked. This assert caught problems in the past.
     ASSERT(marked());
index 2a0e2e2..a48a61e 100644 (file)
@@ -34,9 +34,9 @@ JSNodeFilterCondition::JSNodeFilterCondition(KJS::JSObject* filter)
 {
 }
 
-void JSNodeFilterCondition::markChildren(KJS::MarkStack& stack)
+void JSNodeFilterCondition::mark()
 {
-    stack.push(m_filter);
+    m_filter->mark();
 }
 
 short JSNodeFilterCondition::acceptNode(Node* filterNode) const
index 26c08f5..bd172b9 100644 (file)
@@ -31,7 +31,7 @@ namespace WebCore {
     public:
         JSNodeFilterCondition(KJS::JSObject* filter);
         virtual short acceptNode(Node*) const;
-        virtual void markChildren(KJS::MarkStack&);
+        virtual void mark();
 
     protected:
         KJS::JSObject* m_filter;
index 04481f7..258059c 100644 (file)
 
 namespace WebCore {
 
-    void JSNodeFilter::markChildren(KJS::MarkStack& stack)
+void JSNodeFilter::mark()
 {
-    impl()->markChildren(stack);
-    DOMObject::markChildren(stack);
+    impl()->mark();
+    DOMObject::mark();
 }
 
 NodeFilter* toNodeFilter(KJS::JSValue* val)
index 189e70c..deb0ffe 100644 (file)
 
 namespace WebCore {
 
-void JSNodeIterator::markChildren(KJS::MarkStack& stack)
+void JSNodeIterator::mark()
 {
     if (NodeFilter* filter = m_impl->filter())
-        filter->markChildren(stack);
+        filter->mark();
     
-    DOMObject::markChildren(stack);
+    DOMObject::mark();
 }
 
 }
index 47b5185..c73fe40 100644 (file)
 
 namespace WebCore {
     
-void JSTreeWalker::markChildren(KJS::MarkStack& stack)
+void JSTreeWalker::mark()
 {
     if (NodeFilter* filter = m_impl->filter())
-        filter->markChildren(stack);
+        filter->mark();
     
-    DOMObject::markChildren(stack);
+    DOMObject::mark();
 }
     
 }
index d7345f0..5098785 100644 (file)
@@ -170,18 +170,18 @@ void JSXMLHttpRequest::putValueProperty(ExecState* exec, int token, JSValue* val
     }
 }
 
-void JSXMLHttpRequest::markChildren(KJS::MarkStack& stack)
+void JSXMLHttpRequest::mark()
 {
-    DOMObject::markChildren(stack);
+    DOMObject::mark();
 
     JSUnprotectedEventListener* onReadyStateChangeListener = static_cast<JSUnprotectedEventListener*>(m_impl->onReadyStateChangeListener());
     JSUnprotectedEventListener* onLoadListener = static_cast<JSUnprotectedEventListener*>(m_impl->onLoadListener());
 
     if (onReadyStateChangeListener)
-        onReadyStateChangeListener->markChildren(stack);
+        onReadyStateChangeListener->mark();
 
     if (onLoadListener)
-        onLoadListener->markChildren(stack);
+        onLoadListener->mark();
     
     typedef XMLHttpRequest::EventListenersMap EventListenersMap;
     typedef XMLHttpRequest::ListenerVector ListenerVector;
@@ -189,7 +189,7 @@ void JSXMLHttpRequest::markChildren(KJS::MarkStack& stack)
     for (EventListenersMap::iterator mapIter = eventListeners.begin(); mapIter != eventListeners.end(); ++mapIter) {
         for (ListenerVector::iterator vecIter = mapIter->second.begin(); vecIter != mapIter->second.end(); ++vecIter) {
             JSUnprotectedEventListener* listener = static_cast<JSUnprotectedEventListener*>(vecIter->get());
-            listener->markChildren(stack);
+            listener->mark();
         }
     }
 }
index e3f7e5a..6afb608 100644 (file)
@@ -57,7 +57,7 @@ public:
     virtual void put(ExecState*, const Identifier& propertyName, JSValue* value, int attr = None);
     void putValueProperty(ExecState*, int token, JSValue* value, int /*attr*/);
     virtual bool toBoolean(ExecState*) const { return true; }
-    virtual void markChildren(MarkStack&);
+    virtual void mark();
 
     WebCore::XMLHttpRequest* impl() const { return m_impl.get(); }
 
index ed7b4e3..2dcc9fe 100644 (file)
@@ -210,7 +210,7 @@ void ScriptInterpreter::forgetAllDOMNodesForDocument(Document* document)
     delete map;
 }
 
-void ScriptInterpreter::markDOMNodesForDocument(MarkStack& stack, Document* doc)
+void ScriptInterpreter::markDOMNodesForDocument(Document* doc)
 {
     NodePerDocMap::iterator dictIt = domNodesPerDocument().find(doc);
     if (dictIt != domNodesPerDocument().end()) {
@@ -225,9 +225,9 @@ void ScriptInterpreter::markDOMNodesForDocument(MarkStack& stack, Document* doc)
             // otherwise reachable from JS.
             // However, image elements that aren't in the document are also
             // marked, if they are not done loading yet.
-            if (node->inDocument() || (node->hasTagName(imgTag) &&
-                                       !static_cast<HTMLImageElement*>(node)->haveFiredLoadEvent()))
-                stack.push(jsNode);
+            if (!jsNode->marked() && (node->inDocument() || (node->hasTagName(imgTag) &&
+                                                             !static_cast<HTMLImageElement*>(node)->haveFiredLoadEvent())))
+                jsNode->mark();
         }
     }
 }
index c740225..06c8f72 100644 (file)
@@ -83,7 +83,7 @@ namespace KJS {
         static void forgetDOMNodeForDocument(WebCore::Document*, WebCore::Node*);
         static void forgetAllDOMNodesForDocument(WebCore::Document*);
         static void updateDOMNodeDocument(WebCore::Node*, WebCore::Document* oldDoc, WebCore::Document* newDoc);
-        static void markDOMNodesForDocument(MarkStack&, WebCore::Document*);
+        static void markDOMNodesForDocument(WebCore::Document*);
 
         WebCore::Frame* frame() const { return m_frame; }
 
index e78c8c7..17297b9 100644 (file)
@@ -187,10 +187,10 @@ void JSUnprotectedEventListener::clearWindowObj()
     m_win = 0;
 }
 
-void JSUnprotectedEventListener::markChildren(KJS::MarkStack& stack)
+void JSUnprotectedEventListener::mark()
 {
-    if (m_listener)
-        stack.push(m_listener);
+    if (m_listener && !m_listener->marked())
+        m_listener->mark();
 }
 
 #ifndef NDEBUG
index 52cfb5e..545e002 100644 (file)
@@ -57,7 +57,7 @@ namespace WebCore {
         virtual KJS::JSObject* listenerObj() const;
         virtual KJS::Window* windowObj() const;
         void clearWindowObj();
-        virtual void markChildren(KJS::MarkStack&);
+        virtual void mark();
     private:
         KJS::JSObject* m_listener;
         KJS::Window* m_win;
index 265a954..a123c07 100644 (file)
@@ -290,11 +290,11 @@ Location *Window::location() const
 }
 
 // reference our special objects during garbage collection
-void Window::markChildren(KJS::MarkStack& stack)
+void Window::mark()
 {
-  JSObject::markChildren(stack);
-  if (d->loc)
-      stack.push(d->loc);
+  JSObject::mark();
+  if (d->loc && !d->loc->marked())
+    d->loc->mark();
 }
 
 static bool allowPopUp(ExecState *exec, Window *window)
index d7b46ae..d705b26 100644 (file)
@@ -90,7 +90,7 @@ namespace KJS {
      * was called from.
      */
     static Window* retrieveActive(ExecState*);
-    virtual void markChildren(MarkStack&);
+    virtual void mark();
     virtual bool getOwnPropertySlot(ExecState*, const Identifier&, PropertySlot&);
     JSValue *getValueProperty(ExecState *exec, int token) const;
     virtual void put(ExecState *exec, const Identifier &propertyName, JSValue *value, int attr = None);
index a284db7..6d185cf 100644 (file)
@@ -366,7 +366,7 @@ sub GenerateHeader
 
     # Custom mark function
     if ($dataNode->extendedAttributes->{"CustomMarkFunction"}) {
-        push(@headerContent, "    virtual void markChildren(KJS::MarkStack&);\n\n");
+        push(@headerContent, "    virtual void mark();\n\n");
     }
 
     # Custom pushEventHandlerScope function
index c27100a..dba01bd 100644 (file)
@@ -153,7 +153,8 @@ Node::Node(Document *doc)
       m_hovered(false),
       m_inActiveChain(false),
       m_inDetach(false),
-      m_dispatchingSimulatedEvent(false)
+      m_dispatchingSimulatedEvent(false),
+      m_inSubtreeMark(false)
 {
 #ifndef NDEBUG
     if (shouldIgnoreLeaks)
index 1bdc0b0..72886a0 100644 (file)
@@ -484,7 +484,9 @@ protected:
     bool m_inDetach : 1;
     bool m_dispatchingSimulatedEvent : 1;
 
-    // 1 bit left
+public:
+    bool m_inSubtreeMark : 1;
+    // 0 bits left
 
 private:
     Element* ancestorElement() const;
index 359f223..66b175d 100644 (file)
 #include "NodeFilterCondition.h"
 #include <wtf/RefPtr.h>
 
-namespace KJS {
-    class MarkStack;
-}
-
 namespace WebCore {
 
     class NodeFilter : public RefCounted<NodeFilter> {
@@ -72,7 +68,7 @@ namespace WebCore {
 
         NodeFilter(NodeFilterCondition*);
         short acceptNode(Node*) const;
-        void markChildren(KJS::MarkStack& stack) { m_condition->markChildren(stack); };
+        void mark() { m_condition->mark(); };
 
     private:
         RefPtr<NodeFilterCondition> m_condition;
index 4ee12fd..74fa2fa 100644 (file)
 
 #include <wtf/RefCounted.h>
 
-namespace KJS {
-    class MarkStack;
-}
-
 namespace WebCore {
 
     class Node;
@@ -41,7 +37,7 @@ namespace WebCore {
     public:
         virtual ~NodeFilterCondition() { }
         virtual short acceptNode(Node*) const;
-        virtual void markChildren(KJS::MarkStack&) { }
+        virtual void mark() { }
     };
 
 } // namespace WebCore