[SCM] WebKit Debian packaging branch, webkit-1.2, updated. upstream/1.1.90-6072-g9a69373

ggaren at apple.com ggaren at apple.com
Thu Apr 8 00:34:00 UTC 2010


The following commit has been merged in the webkit-1.2 branch:
commit 64c9630388617bb8c076d7d6ba9d54b0536e9800
Author: ggaren at apple.com <ggaren at apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Date:   Sat Dec 12 07:20:27 2009 +0000

    Rolled out my last patch because the bots were crashing
    
    git-svn-id: http://svn.webkit.org/repository/webkit/trunk@52047 268f45cc-cd09-0410-ab3c-d52691b4dbfc

diff --git a/JavaScriptCore/API/JSBase.cpp b/JavaScriptCore/API/JSBase.cpp
index 6c362c4..4a32d35 100644
--- a/JavaScriptCore/API/JSBase.cpp
+++ b/JavaScriptCore/API/JSBase.cpp
@@ -99,7 +99,7 @@ void JSGarbageCollect(JSContextRef ctx)
     JSLock lock(globalData.isSharedInstance ? LockForReal : SilenceAssertionsOnly);
 
     if (!globalData.heap.isBusy())
-        globalData.heap.collectAllGarbage();
+        globalData.heap.collect();
 
     // FIXME: Perhaps we should trigger a second mark and sweep
     // once the garbage collector is done if this is called when
diff --git a/JavaScriptCore/API/JSContextRef.cpp b/JavaScriptCore/API/JSContextRef.cpp
index 92ad396..e6626b7 100644
--- a/JavaScriptCore/API/JSContextRef.cpp
+++ b/JavaScriptCore/API/JSContextRef.cpp
@@ -133,7 +133,7 @@ void JSGlobalContextRelease(JSGlobalContextRef ctx)
         ASSERT(!globalData.heap.isBusy());
         globalData.heap.destroy();
     } else
-        globalData.heap.collectAllGarbage();
+        globalData.heap.collect();
 
     globalData.deref();
 }
diff --git a/JavaScriptCore/ChangeLog b/JavaScriptCore/ChangeLog
index 8e5b505..eea5200 100644
--- a/JavaScriptCore/ChangeLog
+++ b/JavaScriptCore/ChangeLog
@@ -11,164 +11,6 @@
         (WTF::initializeMainThreadPlatform):
         (WTF::scheduleDispatchFunctionsOnMainThread):
 
-2009-12-11  Geoffrey Garen  <ggaren at apple.com>
-
-        Windows build fix: Export some new symbols.
-
-        * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.def:
-
-2009-12-11  Geoffrey Garen  <ggaren at apple.com>
-
-        Windows build fix: Removed some old exports.
-
-        * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.def:
-
-2009-12-11  Geoffrey Garen  <ggaren at apple.com>
-
-        Windows build fix: Use unsigned instead of uint32_t to avoid dependencies.
-
-        * wtf/StdLibExtras.h:
-        (WTF::bitCount):
-
-2009-12-11  Geoffrey Garen  <ggaren at apple.com>
-
-        Reviewed by Sam Weinig.
-        
-        Changed GC from mark-sweep to mark-allocate.
-        
-        Added WeakGCMap to keep WebCore blissfully ignorant about objects that
-        have become garbage but haven't run their destructors yet.
-        
-        1% SunSpider speedup.
-        7.6% v8 speedup (37% splay speedup).
-        17% speedup on bench-alloc-nonretained.js.
-        18% speedup on bench-alloc-retained.js.
-
-        * API/JSBase.cpp:
-        (JSGarbageCollect):
-        * API/JSContextRef.cpp:
-        * JavaScriptCore.exp:
-        * JavaScriptCore.xcodeproj/project.pbxproj: Updated for renames and new
-        files.
-
-        * debugger/Debugger.cpp:
-        (JSC::Debugger::recompileAllJSFunctions): Updated to use the Collector
-        iterator abstraction.
-
-        * jsc.cpp:
-        (functionGC): Updated for rename.
-
-        * runtime/Collector.cpp: Slightly reduced the number of allocations per
-        collection, so that small workloads only allocate on collector block,
-        rather than two.
-
-        (JSC::Heap::Heap): Updated to use the new allocateBlock function.
-
-        (JSC::Heap::destroy): Updated to use the new freeBlocks function.
-
-        (JSC::Heap::allocateBlock): New function to initialize a block when
-        allocating it.
-
-        (JSC::Heap::freeBlock): Consolidated the responsibility for running
-        destructors into this function.
-
-        (JSC::Heap::freeBlocks): Updated to use freeBlock.
-
-        (JSC::Heap::recordExtraCost): Sweep the heap in this reporting function,
-        so that allocation, which is more common, doesn't have to check extraCost.
-
-        (JSC::Heap::heapAllocate): Run destructors right before recycling a
-        garbage cell. This has better cache utilization than a separate sweep phase.
-
-        (JSC::Heap::resizeBlocks):
-        (JSC::Heap::growBlocks):
-        (JSC::Heap::shrinkBlocks): New set of functions for managing the size of
-        the heap, now that the heap doesn't maintain any information about its
-        size.
-
-        (JSC::isPointerAligned):
-        (JSC::isHalfCellAligned):
-        (JSC::isPossibleCell):
-        (JSC::isCellAligned):
-        (JSC::Heap::markConservatively): Cleaned up this code a bit.
-
-        (JSC::Heap::clearMarkBits):
-        (JSC::Heap::markedCells): Some helper functions for examining the the mark
-        bitmap.
-
-        (JSC::Heap::sweep): Simplified this function by using a DeadObjectIterator.
-
-        (JSC::Heap::markRoots): Reordered some operations for clarity.
-
-        (JSC::Heap::objectCount):
-        (JSC::Heap::addToStatistics):
-        (JSC::Heap::statistics): Rewrote these functions to calculate an object
-        count on demand, since the heap doesn't maintain this information by 
-        itself.
-
-        (JSC::Heap::reset): New function for resetting the heap once we've
-        exhausted heap space.
-
-        (JSC::Heap::collectAllGarbage): This function matches the old collect()
-        behavior, but it's now an uncommon function used only by API.
-
-        * runtime/Collector.h:
-        (JSC::CollectorBitmap::count):
-        (JSC::CollectorBitmap::isEmpty): Added some helper functions for managing
-        the collector mark bitmap.
-
-        (JSC::Heap::reportExtraMemoryCost): Changed reporting from cell equivalents
-        to bytes, so it's easier to understand.
-        
-        * runtime/CollectorHeapIterator.h:
-        (JSC::CollectorHeapIterator::CollectorHeapIterator):
-        (JSC::CollectorHeapIterator::operator!=):
-        (JSC::CollectorHeapIterator::operator*):
-        (JSC::CollectorHeapIterator::advance):
-        (JSC::::LiveObjectIterator):
-        (JSC::::operator):
-        (JSC::::DeadObjectIterator):
-        (JSC::::ObjectIterator): New iterators for encapsulating details about
-        heap layout, and what's live and dead on the heap.
-
-        * runtime/JSArray.cpp:
-        (JSC::JSArray::putSlowCase):
-        (JSC::JSArray::increaseVectorLength): Delay reporting extra cost until
-        we're fully constructed, so the heap mark phase won't visit us in an
-        invalid state.
-
-        * runtime/JSCell.h:
-        (JSC::JSCell::):
-        (JSC::JSCell::createDummyStructure):
-        (JSC::JSCell::JSCell):
-        * runtime/JSGlobalData.cpp:
-        (JSC::JSGlobalData::JSGlobalData):
-        * runtime/JSGlobalData.h: Added a dummy cell to simplify allocation logic.
-
-        * runtime/JSString.h:
-        (JSC::jsSubstring): Don't report extra cost for substrings, since they
-        share a buffer that's already reported extra cost.
-
-        * runtime/Tracing.d:
-        * runtime/Tracing.h: Changed these dtrace hooks not to report object
-        counts, since they're no longer cheap to compute.
-
-        * runtime/UString.h: Updated for renames.
-
-        * runtime/WeakGCMap.h: Added.
-        (JSC::WeakGCMap::isEmpty):
-        (JSC::WeakGCMap::uncheckedGet):
-        (JSC::WeakGCMap::uncheckedBegin):
-        (JSC::WeakGCMap::uncheckedEnd):
-        (JSC::::get):
-        (JSC::::take):
-        (JSC::::set):
-        (JSC::::uncheckedRemove): Mentioned above.
-
-        * wtf/StdLibExtras.h:
-        (WTF::bitCount): Added a bit population count function, so the heap can
-        count live objects to fulfill statistics questions.
-
 2009-12-11  Gavin Barraclough  <barraclough at apple.com>
 
         Reviewed by Oliver Hunt.
diff --git a/JavaScriptCore/JavaScriptCore.exp b/JavaScriptCore/JavaScriptCore.exp
index 4e3cc75..1c91d36 100644
--- a/JavaScriptCore/JavaScriptCore.exp
+++ b/JavaScriptCore/JavaScriptCore.exp
@@ -180,15 +180,16 @@ __ZN3JSC24createStackOverflowErrorEPNS_9ExecStateE
 __ZN3JSC25evaluateInGlobalCallFrameERKNS_7UStringERNS_7JSValueEPNS_14JSGlobalObjectE
 __ZN3JSC35createInterruptedExecutionExceptionEPNS_12JSGlobalDataE
 __ZN3JSC3NaNE
+__ZN3JSC4Heap11objectCountEv
 __ZN3JSC4Heap14primaryHeapEndEv
 __ZN3JSC4Heap15recordExtraCostEm
 __ZN3JSC4Heap16primaryHeapBeginEv
-__ZN3JSC4Heap17collectAllGarbageEv
 __ZN3JSC4Heap17globalObjectCountEv
 __ZN3JSC4Heap20protectedObjectCountEv
 __ZN3JSC4Heap25protectedObjectTypeCountsEv
 __ZN3JSC4Heap26protectedGlobalObjectCountEv
 __ZN3JSC4Heap6isBusyEv
+__ZN3JSC4Heap7collectEv
 __ZN3JSC4Heap7destroyEv
 __ZN3JSC4Heap7protectENS_7JSValueE
 __ZN3JSC4Heap8allocateEm
@@ -367,7 +368,6 @@ __ZNK3JSC18PropertyDescriptor6getterEv
 __ZNK3JSC18PropertyDescriptor6setterEv
 __ZNK3JSC18PropertyDescriptor8writableEv
 __ZNK3JSC4Heap10statisticsEv
-__ZNK3JSC4Heap11objectCountEv
 __ZNK3JSC6JSCell11toPrimitiveEPNS_9ExecStateENS_22PreferredPrimitiveTypeE
 __ZNK3JSC6JSCell12toThisObjectEPNS_9ExecStateE
 __ZNK3JSC6JSCell12toThisStringEPNS_9ExecStateE
diff --git a/JavaScriptCore/JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.def b/JavaScriptCore/JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.def
index a04b3e6..aae8118 100644
--- a/JavaScriptCore/JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.def
+++ b/JavaScriptCore/JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.def
@@ -62,7 +62,7 @@ EXPORTS
     ?classInfo at JSCell@JSC@@UBEPBUClassInfo at 2@XZ
     ?className at JSObject@JSC@@UBE?AVUString at 2@XZ
     ?collate at Collator@WTF@@QBE?AW4Result at 12@PB_WI0I at Z
-    ?collectAllGarbage at Heap@JSC@@QAEXXZ
+    ?collect at Heap@JSC@@QAE_NXZ
     ?computeHash at Rep@UString at JSC@@SAIPBDH at Z
     ?computeHash at Rep@UString at JSC@@SAIPB_WH at Z
     ?configurable at PropertyDescriptor@JSC@@QBE_NXZ
@@ -115,8 +115,8 @@ EXPORTS
     ?detach at Debugger@JSC@@UAEXPAVJSGlobalObject at 2@@Z
     ?detachThread at WTF@@YAXI at Z
     ?didTimeOut at TimeoutChecker@JSC@@QAE_NPAVExecState at 2@@Z
-    ?doubleToStringInJavaScriptFormat at WTF@@YAXNQADPAI at Z
     ?dumpSampleData at JSGlobalData@JSC@@QAEXPAVExecState at 2@@Z
+    ?doubleToStringInJavaScriptFormat at WTF@@YAXNQADPAI at Z
     ?enumerable at PropertyDescriptor@JSC@@QBE_NXZ
     ?equal at Identifier@JSC@@SA_NPBURep at UString@2 at PBD@Z
     ?equal at JSC@@YA_NPBURep at UString@1 at 0@Z
@@ -200,10 +200,12 @@ EXPORTS
     ?materializePropertyMap at Structure@JSC@@AAEXXZ
     ?name at InternalFunction@JSC@@QAEABVUString at 2@PAVExecState at 2@@Z
     ?nonInlineNaN at JSC@@YANXZ
-    ?objectCount at Heap@JSC@@QBEIXZ
+    ?objectCount at Heap@JSC@@QAEIXZ
     ?objectProtoFuncToString at JSC@@YI?AVJSValue at 1@PAVExecState at 1@PAVJSObject at 1@V21 at ABVArgList@1@@Z
     ?parse at Parser@JSC@@AAEXPAVJSGlobalData at 2@PAHPAVUString at 2@@Z
     ?parseDateFromNullTerminatedCharacters at WTF@@YANPBD at Z
+    ?primaryHeapBegin at Heap@JSC@@QAE?AV?$CollectorHeapIterator@$0A@@2 at XZ
+    ?primaryHeapEnd at Heap@JSC@@QAE?AV?$CollectorHeapIterator@$0A@@2 at XZ
     ?profiler at Profiler@JSC@@SAPAV12 at XZ
     ?protect at Heap@JSC@@QAEXVJSValue at 2@@Z
     ?protectedGlobalObjectCount at Heap@JSC@@QAEIXZ
diff --git a/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj b/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj
index 60cd3e4..e766243 100644
--- a/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj
+++ b/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj
@@ -167,7 +167,6 @@
 		14BD59C50A3E8F9F00BAF59C /* JavaScriptCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 932F5BD90822A1C700736975 /* JavaScriptCore.framework */; };
 		14BD5A300A3E91F600BAF59C /* JSContextRef.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 14BD5A290A3E91F600BAF59C /* JSContextRef.cpp */; };
 		14BD5A320A3E91F600BAF59C /* JSValueRef.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 14BD5A2B0A3E91F600BAF59C /* JSValueRef.cpp */; };
-		14BFCE6910CDB1FC00364CCE /* WeakGCMap.h in Headers */ = {isa = PBXBuildFile; fileRef = 14BFCE6810CDB1FC00364CCE /* WeakGCMap.h */; settings = {ATTRIBUTES = (Private, ); }; };
 		14C5242B0F5355E900BA3D04 /* JITStubs.h in Headers */ = {isa = PBXBuildFile; fileRef = 14A6581A0F4E36F4000150FD /* JITStubs.h */; settings = {ATTRIBUTES = (Private, ); }; };
 		14E9D17B107EC469004DDA21 /* JSGlobalObjectFunctions.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BC756FC60E2031B200DE7D12 /* JSGlobalObjectFunctions.cpp */; };
 		14F3488F0E95EF8A003648BC /* CollectorHeapIterator.h in Headers */ = {isa = PBXBuildFile; fileRef = 14F3488E0E95EF8A003648BC /* CollectorHeapIterator.h */; settings = {ATTRIBUTES = (); }; };
@@ -637,7 +636,6 @@
 		14BD5A2A0A3E91F600BAF59C /* JSContextRef.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = JSContextRef.h; sourceTree = "<group>"; };
 		14BD5A2B0A3E91F600BAF59C /* JSValueRef.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = JSValueRef.cpp; sourceTree = "<group>"; };
 		14BD5A2D0A3E91F600BAF59C /* testapi.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; name = testapi.c; path = API/tests/testapi.c; sourceTree = "<group>"; };
-		14BFCE6810CDB1FC00364CCE /* WeakGCMap.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WeakGCMap.h; sourceTree = "<group>"; };
 		14D792640DAA03FB001A9F05 /* RegisterFile.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RegisterFile.h; sourceTree = "<group>"; };
 		14D857740A4696C80032146C /* testapi.js */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.javascript; name = testapi.js; path = API/tests/testapi.js; sourceTree = "<group>"; };
 		14DA818E0D99FD2000B0A4FB /* JSActivation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSActivation.h; sourceTree = "<group>"; };
@@ -1604,7 +1602,6 @@
 				F692A8850255597D01FF60F7 /* UString.cpp */,
 				F692A8860255597D01FF60F7 /* UString.h */,
 				1420BE7A10AA6DDB00F455D2 /* WeakRandom.h */,
-				14BFCE6810CDB1FC00364CCE /* WeakGCMap.h */,
 				A7C2216810C745E000F97913 /* JSZombie.h */,
 				A7C2216B10C7469C00F97913 /* JSZombie.cpp */,
 			);
@@ -2013,7 +2010,6 @@
 				86CAFEE31035DDE60028A609 /* Executable.h in Headers */,
 				142D3939103E4560007DCB52 /* NumericStrings.h in Headers */,
 				A7FB61001040C38B0017A286 /* PropertyDescriptor.h in Headers */,
-				14BFCE6910CDB1FC00364CCE /* WeakGCMap.h in Headers */,
 				BC87CDB910712AD4000614CF /* JSONObject.lut.h in Headers */,
 				148CD1D8108CF902008163C6 /* JSContextRefPrivate.h in Headers */,
 				14A1563210966365006FA260 /* DateInstanceCache.h in Headers */,
diff --git a/JavaScriptCore/debugger/Debugger.cpp b/JavaScriptCore/debugger/Debugger.cpp
index 98d707c..902a802 100644
--- a/JavaScriptCore/debugger/Debugger.cpp
+++ b/JavaScriptCore/debugger/Debugger.cpp
@@ -67,9 +67,8 @@ void Debugger::recompileAllJSFunctions(JSGlobalData* globalData)
     FunctionExecutableSet functionExecutables;
     SourceProviderMap sourceProviders;
 
-    LiveObjectIterator<PrimaryHeap> it = globalData->heap.primaryHeapBegin();
-    LiveObjectIterator<PrimaryHeap> heapEnd = globalData->heap.primaryHeapEnd();
-    for ( ; it != heapEnd; ++it) {
+    Heap::iterator heapEnd = globalData->heap.primaryHeapEnd();
+    for (Heap::iterator it = globalData->heap.primaryHeapBegin(); it != heapEnd; ++it) {
         if (!(*it)->inherits(&JSFunction::info))
             continue;
 
diff --git a/JavaScriptCore/jsc.cpp b/JavaScriptCore/jsc.cpp
index 6c61889..b6bc0aa 100644
--- a/JavaScriptCore/jsc.cpp
+++ b/JavaScriptCore/jsc.cpp
@@ -194,7 +194,7 @@ JSValue JSC_HOST_CALL functionDebug(ExecState* exec, JSObject*, JSValue, const A
 JSValue JSC_HOST_CALL functionGC(ExecState* exec, JSObject*, JSValue, const ArgList&)
 {
     JSLock lock(SilenceAssertionsOnly);
-    exec->heap()->collectAllGarbage();
+    exec->heap()->collect();
     return jsUndefined();
 }
 
diff --git a/JavaScriptCore/runtime/Collector.cpp b/JavaScriptCore/runtime/Collector.cpp
index aa32bcf..1630a58 100644
--- a/JavaScriptCore/runtime/Collector.cpp
+++ b/JavaScriptCore/runtime/Collector.cpp
@@ -104,7 +104,7 @@ namespace JSC {
 
 const size_t GROWTH_FACTOR = 2;
 const size_t LOW_WATER_FACTOR = 4;
-const size_t ALLOCATIONS_PER_COLLECTION = 3600;
+const size_t ALLOCATIONS_PER_COLLECTION = 4000;
 // This value has to be a macro to be used in max() without introducing
 // a PIC branch in Mach-O binaries, see <rdar://problem/5971391>.
 #define MIN_ARRAY_SIZE (static_cast<size_t>(14))
@@ -148,7 +148,7 @@ Heap::Heap(JSGlobalData* globalData)
     , m_globalData(globalData)
 {
     ASSERT(globalData);
-    
+
 #if PLATFORM(SYMBIAN)
     // Symbian OpenC supports mmap but currently not the MAP_ANON flag.
     // Using fastMalloc() does not properly align blocks on 64k boundaries
@@ -170,12 +170,7 @@ Heap::Heap(JSGlobalData* globalData)
 #endif // PLATFORM(SYMBIAN)
     
     memset(&primaryHeap, 0, sizeof(CollectorHeap));
-    allocateBlock<PrimaryHeap>();
-
     memset(&numberHeap, 0, sizeof(CollectorHeap));
-#if USE(JSVALUE32)
-    allocateBlock<NumberHeap>();
-#endif
 }
 
 Heap::~Heap()
@@ -198,8 +193,15 @@ void Heap::destroy()
     delete m_markListSet;
     m_markListSet = 0;
 
-    freeBlocks<PrimaryHeap>();
-    freeBlocks<NumberHeap>();
+    sweep<PrimaryHeap>();
+    // No need to sweep number heap, because the JSNumber destructor doesn't do anything.
+#if ENABLE(JSC_ZOMBIES)
+    ASSERT(primaryHeap.numLiveObjects == primaryHeap.numZombies);
+#else
+    ASSERT(!primaryHeap.numLiveObjects);
+#endif
+    freeBlocks(&primaryHeap);
+    freeBlocks(&numberHeap);
 
 #if ENABLE(JSC_MULTIPLE_THREADS)
     if (m_currentThreadRegistrar) {
@@ -223,6 +225,7 @@ NEVER_INLINE CollectorBlock* Heap::allocateBlock()
 {
 #if PLATFORM(DARWIN)
     vm_address_t address = 0;
+    // FIXME: tag the region as a JavaScriptCore heap when we get a registered VM tag: <rdar://problem/6054788>.
     vm_map(current_task(), &address, BLOCK_SIZE, BLOCK_OFFSET_MASK, VM_FLAGS_ANYWHERE | VM_TAG_FOR_COLLECTOR_MEMORY, MEMORY_OBJECT_NULL, 0, FALSE, VM_PROT_DEFAULT, VM_PROT_DEFAULT, VM_INHERIT_DEFAULT);
 #elif PLATFORM(SYMBIAN)
     // Allocate a 64 kb aligned CollectorBlock
@@ -230,6 +233,8 @@ NEVER_INLINE CollectorBlock* Heap::allocateBlock()
     if (!mask)
         CRASH();
     uintptr_t address = reinterpret_cast<uintptr_t>(mask);
+
+    memset(reinterpret_cast<void*>(address), 0, BLOCK_SIZE);
 #elif PLATFORM(WINCE)
     void* address = VirtualAlloc(NULL, BLOCK_SIZE, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
 #elif PLATFORM(WIN_OS)
@@ -242,6 +247,7 @@ NEVER_INLINE CollectorBlock* Heap::allocateBlock()
 #elif HAVE(POSIX_MEMALIGN)
     void* address;
     posix_memalign(&address, BLOCK_SIZE, BLOCK_SIZE);
+    memset(address, 0, BLOCK_SIZE);
 #else
 
 #if ENABLE(JSC_MULTIPLE_THREADS)
@@ -267,22 +273,13 @@ NEVER_INLINE CollectorBlock* Heap::allocateBlock()
         munmap(reinterpret_cast<char*>(address + adjust + BLOCK_SIZE), extra - adjust);
 
     address += adjust;
+    memset(reinterpret_cast<void*>(address), 0, BLOCK_SIZE);
 #endif
 
-    // Initialize block.
-
     CollectorBlock* block = reinterpret_cast<CollectorBlock*>(address);
+    block->freeList = block->cells;
     block->heap = this;
     block->type = heapType;
-    clearMarkBits<heapType>(block);
-
-    // heapAllocate assumes that it's safe to call a destructor on any cell in the primary heap.
-    if (heapType != NumberHeap) {
-        for (size_t i = 0; i < HeapConstants<heapType>::cellsPerBlock; ++i)
-            new (block->cells + i) JSCell(JSCell::DummyDestructableCell);
-    }
-    
-    // Add block to blocks vector.
 
     CollectorHeap& heap = heapType == PrimaryHeap ? primaryHeap : numberHeap;
     size_t numBlocks = heap.numBlocks;
@@ -304,12 +301,6 @@ NEVER_INLINE void Heap::freeBlock(size_t block)
 {
     CollectorHeap& heap = heapType == PrimaryHeap ? primaryHeap : numberHeap;
 
-    if (heapType != NumberHeap) {
-        ObjectIterator<heapType> it(heap, block);
-        ObjectIterator<heapType> end(heap, block + 1);
-        for ( ; it != end; ++it)
-            (*it)->~JSCell();
-    }
     freeBlock(heap.blocks[block]);
 
     // swap with the last block so we compact as we go
@@ -343,15 +334,13 @@ NEVER_INLINE void Heap::freeBlock(CollectorBlock* block)
 #endif
 }
 
-template <HeapType heapType>
-void Heap::freeBlocks()
+void Heap::freeBlocks(CollectorHeap* heap)
 {
-    CollectorHeap& heap = heapType == PrimaryHeap ? primaryHeap : numberHeap;
-
-    while (heap.usedBlocks)
-        freeBlock<heapType>(0);
-    fastFree(heap.blocks);
-    memset(&heap, 0, sizeof(CollectorHeap));
+    for (size_t i = 0; i < heap->usedBlocks; ++i)
+        if (heap->blocks[i])
+            freeBlock(heap->blocks[i]);
+    fastFree(heap->blocks);
+    memset(heap, 0, sizeof(CollectorHeap));
 }
 
 void Heap::recordExtraCost(size_t cost)
@@ -368,14 +357,6 @@ void Heap::recordExtraCost(size_t cost)
     // collecting more frequently as long as it stays alive.
     // NOTE: we target the primaryHeap unconditionally as JSNumber doesn't modify cost 
 
-    if (primaryHeap.extraCost > maxExtraCost && primaryHeap.extraCost > primaryHeap.usedBlocks * BLOCK_SIZE / 2) {
-        // If the last iteration through the heap deallocated blocks, we need
-        // to clean up remaining garbage before marking. Otherwise, the conservative
-        // marking mechanism might follow a pointer to unmapped memory.
-        if (primaryHeap.didShrink)
-            sweep<PrimaryHeap>();
-        reset();
-    }
     primaryHeap.extraCost += cost;
 }
 
@@ -383,101 +364,101 @@ template <HeapType heapType> ALWAYS_INLINE void* Heap::heapAllocate(size_t s)
 {
     typedef typename HeapConstants<heapType>::Block Block;
     typedef typename HeapConstants<heapType>::Cell Cell;
-    
-    CollectorHeap& heap = heapType == PrimaryHeap ? primaryHeap : numberHeap;
 
+    CollectorHeap& heap = heapType == PrimaryHeap ? primaryHeap : numberHeap;
     ASSERT(JSLock::lockCount() > 0);
     ASSERT(JSLock::currentThreadIsHoldingLock());
     ASSERT_UNUSED(s, s <= HeapConstants<heapType>::cellSize);
 
     ASSERT(heap.operationInProgress == NoOperation);
     ASSERT(heapType == PrimaryHeap || heap.extraCost == 0);
+    // FIXME: If another global variable access here doesn't hurt performance
+    // too much, we could CRASH() in NDEBUG builds, which could help ensure we
+    // don't spend any time debugging cases where we allocate inside an object's
+    // deallocation code.
 
 #if COLLECT_ON_EVERY_ALLOCATION
-    collectAllGarbage();
-    ASSERT(heap.operationInProgress == NoOperation);
+    collect();
 #endif
 
-allocate:
-
-    // Fast case: find the next garbage cell and recycle it.
-
-    do {
-        ASSERT(heap.nextBlock < heap.usedBlocks);
-        Block* block = reinterpret_cast<Block*>(heap.blocks[heap.nextBlock]);
-        do {
-            ASSERT(heap.nextCell < HeapConstants<heapType>::cellsPerBlock);
-            if (!block->marked.get(heap.nextCell >> HeapConstants<heapType>::bitmapShift)) { // Always false for the last cell in the block
-                Cell* cell = block->cells + heap.nextCell;
-                if (heapType != NumberHeap) {
-                    heap.operationInProgress = Allocation;
-                    JSCell* imp = reinterpret_cast<JSCell*>(cell);
-                    imp->~JSCell();
-                    heap.operationInProgress = NoOperation;
-                }
-                ++heap.nextCell;
-                return cell;
-            }
-        } while (++heap.nextCell != HeapConstants<heapType>::cellsPerBlock);
-        heap.nextCell = 0;
-    } while (++heap.nextBlock != heap.usedBlocks);
+    size_t numLiveObjects = heap.numLiveObjects;
+    size_t usedBlocks = heap.usedBlocks;
+    size_t i = heap.firstBlockWithPossibleSpace;
+
+    // if we have a huge amount of extra cost, we'll try to collect even if we still have
+    // free cells left.
+    if (heapType == PrimaryHeap && heap.extraCost > ALLOCATIONS_PER_COLLECTION) {
+        size_t numLiveObjectsAtLastCollect = heap.numLiveObjectsAtLastCollect;
+        size_t numNewObjects = numLiveObjects - numLiveObjectsAtLastCollect;
+        const size_t newCost = numNewObjects + heap.extraCost;
+        if (newCost >= ALLOCATIONS_PER_COLLECTION && newCost >= numLiveObjectsAtLastCollect)
+            goto collect;
+    }
 
-    // Slow case: reached the end of the heap. Mark live objects and start over.
+    ASSERT(heap.operationInProgress == NoOperation);
+#ifndef NDEBUG
+    // FIXME: Consider doing this in NDEBUG builds too (see comment above).
+    heap.operationInProgress = Allocation;
+#endif
 
-    reset();
-    goto allocate;
-}
+scan:
+    Block* targetBlock;
+    size_t targetBlockUsedCells;
+    if (i != usedBlocks) {
+        targetBlock = reinterpret_cast<Block*>(heap.blocks[i]);
+        targetBlockUsedCells = targetBlock->usedCells;
+        ASSERT(targetBlockUsedCells <= HeapConstants<heapType>::cellsPerBlock);
+        while (targetBlockUsedCells == HeapConstants<heapType>::cellsPerBlock) {
+            if (++i == usedBlocks)
+                goto collect;
+            targetBlock = reinterpret_cast<Block*>(heap.blocks[i]);
+            targetBlockUsedCells = targetBlock->usedCells;
+            ASSERT(targetBlockUsedCells <= HeapConstants<heapType>::cellsPerBlock);
+        }
+        heap.firstBlockWithPossibleSpace = i;
+    } else {
 
-template <HeapType heapType>
-void Heap::resizeBlocks()
-{
-    CollectorHeap& heap = heapType == PrimaryHeap ? primaryHeap : numberHeap;
+collect:
+        size_t numLiveObjectsAtLastCollect = heap.numLiveObjectsAtLastCollect;
+        size_t numNewObjects = numLiveObjects - numLiveObjectsAtLastCollect;
+        const size_t newCost = numNewObjects + heap.extraCost;
 
-    heap.didShrink = false;
+        if (newCost >= ALLOCATIONS_PER_COLLECTION && newCost >= numLiveObjectsAtLastCollect) {
+#ifndef NDEBUG
+            heap.operationInProgress = NoOperation;
+#endif
+            bool foundGarbage = collect();
+            numLiveObjects = heap.numLiveObjects;
+            usedBlocks = heap.usedBlocks;
+            i = heap.firstBlockWithPossibleSpace;
+#ifndef NDEBUG
+            heap.operationInProgress = Allocation;
+#endif
+            if (foundGarbage)
+                goto scan;
+        }
 
-    size_t usedCellCount = markedCells<heapType>();
-    size_t minCellCount = usedCellCount + max(ALLOCATIONS_PER_COLLECTION, usedCellCount);
-    size_t minBlockCount = (minCellCount + HeapConstants<heapType>::cellsPerBlock - 1) / HeapConstants<heapType>::cellsPerBlock;
+        // didn't find a block, and GC didn't reclaim anything, need to allocate a new block
+        targetBlock = reinterpret_cast<Block*>(allocateBlock<heapType>());
+        heap.firstBlockWithPossibleSpace = heap.usedBlocks - 1;
+        targetBlockUsedCells = 0;
+    }
 
-    size_t maxCellCount = 1.25f * minCellCount;
-    size_t maxBlockCount = (maxCellCount + HeapConstants<heapType>::cellsPerBlock - 1) / HeapConstants<heapType>::cellsPerBlock;
+    // find a free spot in the block and detach it from the free list
+    Cell* newCell = targetBlock->freeList;
 
-    if (heap.usedBlocks < minBlockCount)
-        growBlocks<heapType>(minBlockCount);
-    else if (heap.usedBlocks > maxBlockCount)
-        shrinkBlocks<heapType>(maxBlockCount);
-}
+    // "next" field is a cell offset -- 0 means next cell, so a zeroed block is already initialized
+    targetBlock->freeList = (newCell + 1) + newCell->u.freeCell.next;
 
-template <HeapType heapType> 
-void Heap::growBlocks(size_t neededBlocks)
-{
-    CollectorHeap& heap = heapType == PrimaryHeap ? primaryHeap : numberHeap;
-    ASSERT(heap.usedBlocks < neededBlocks);
-    while (heap.usedBlocks < neededBlocks)
-        allocateBlock<heapType>();
-}
+    targetBlock->usedCells = static_cast<uint32_t>(targetBlockUsedCells + 1);
+    heap.numLiveObjects = numLiveObjects + 1;
 
-template <HeapType heapType> 
-void Heap::shrinkBlocks(size_t neededBlocks)
-{
-    CollectorHeap& heap = heapType == PrimaryHeap ? primaryHeap : numberHeap;
-    ASSERT(heap.usedBlocks > neededBlocks);
-    
-    // Clear the always-on last bit, so isEmpty() isn't fooled by it.
-    for (size_t i = 0; i < heap.usedBlocks; ++i)
-        heap.blocks[i]->marked.clear((HeapConstants<heapType>::cellsPerBlock - 1) >> HeapConstants<heapType>::bitmapShift);
-
-    for (size_t i = 0; i != heap.usedBlocks && heap.usedBlocks != neededBlocks; ) {
-        if (heap.blocks[i]->marked.isEmpty()) {
-            freeBlock<heapType>(i);
-            heap.didShrink = true;
-        } else
-            ++i;
-    }
+#ifndef NDEBUG
+    // FIXME: Consider doing this in NDEBUG builds too (see comment above).
+    heap.operationInProgress = NoOperation;
+#endif
 
-    // Reset the always-on last bit.
-    for (size_t i = 0; i < heap.usedBlocks; ++i)
-        heap.blocks[i]->marked.set((HeapConstants<heapType>::cellsPerBlock - 1) >> HeapConstants<heapType>::bitmapShift);
+    return newCell;
 }
 
 void* Heap::allocate(size_t s)
@@ -733,37 +714,10 @@ void Heap::registerThread()
 
 #endif
 
-inline bool isPointerAligned(void* p)
-{
-    return (((intptr_t)(p) & (sizeof(char*) - 1)) == 0);
-}
-
-// Cell size needs to be a power of two for isPossibleCell to be valid.
-COMPILE_ASSERT(sizeof(CollectorCell) % 2 == 0, Collector_cell_size_is_power_of_two);
-
-#if USE(JSVALUE32)
-static bool isHalfCellAligned(void *p)
-{
-    return (((intptr_t)(p) & (CELL_MASK >> 1)) == 0);
-}
-
-static inline bool isPossibleCell(void* p)
-{
-    return isHalfCellAligned(p) && p;
-}
-
-#else
+#define IS_POINTER_ALIGNED(p) (((intptr_t)(p) & (sizeof(char*) - 1)) == 0)
 
-static inline bool isCellAligned(void *p)
-{
-    return (((intptr_t)(p) & CELL_MASK) == 0);
-}
-
-static inline bool isPossibleCell(void* p)
-{
-    return isCellAligned(p) && p;
-}
-#endif
+// 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(MarkStack& markStack, void* start, void* end)
 {
@@ -774,49 +728,47 @@ void Heap::markConservatively(MarkStack& markStack, void* start, void* end)
     }
 
     ASSERT((static_cast<char*>(end) - static_cast<char*>(start)) < 0x1000000);
-    ASSERT(isPointerAligned(start));
-    ASSERT(isPointerAligned(end));
+    ASSERT(IS_POINTER_ALIGNED(start));
+    ASSERT(IS_POINTER_ALIGNED(end));
 
     char** p = static_cast<char**>(start);
     char** e = static_cast<char**>(end);
 
+    size_t usedPrimaryBlocks = primaryHeap.usedBlocks;
+    size_t usedNumberBlocks = numberHeap.usedBlocks;
+    CollectorBlock** primaryBlocks = primaryHeap.blocks;
+    CollectorBlock** numberBlocks = numberHeap.blocks;
+
+    const size_t lastCellOffset = sizeof(CollectorCell) * (CELLS_PER_BLOCK - 1);
+
     while (p != e) {
         char* x = *p++;
-        if (isPossibleCell(x)) {
+        if (IS_HALF_CELL_ALIGNED(x) && x) {
             uintptr_t xAsBits = reinterpret_cast<uintptr_t>(x);
             xAsBits &= CELL_ALIGN_MASK;
             uintptr_t offset = xAsBits & BLOCK_OFFSET_MASK;
-
-            const size_t lastCellOffset = sizeof(CollectorCell) * (CELLS_PER_BLOCK - 1);
-            if (offset > lastCellOffset)
-                continue;
-
             CollectorBlock* blockAddr = reinterpret_cast<CollectorBlock*>(xAsBits - offset);
-#if USE(JSVALUE32)
             // Mark the the number heap, we can mark these Cells directly to avoid the virtual call cost
-            size_t usedNumberBlocks = numberHeap.usedBlocks;
-            CollectorBlock** numberBlocks = numberHeap.blocks;
             for (size_t block = 0; block < usedNumberBlocks; block++) {
-                if (numberBlocks[block] == blockAddr) {
+                if ((numberBlocks[block] == blockAddr) & (offset <= lastCellOffset)) {
                     Heap::markCell(reinterpret_cast<JSCell*>(xAsBits));
-                    goto loopEnd;
+                    goto endMarkLoop;
                 }
             }
-#endif
+          
             // Mark the primary heap
-            size_t usedPrimaryBlocks = primaryHeap.usedBlocks;
-            CollectorBlock** primaryBlocks = primaryHeap.blocks;
             for (size_t block = 0; block < usedPrimaryBlocks; block++) {
-                if (primaryBlocks[block] != blockAddr)
-                    continue;
-                markStack.append(reinterpret_cast<JSCell*>(xAsBits));
-                markStack.drain();
-                break;
+                if ((primaryBlocks[block] == blockAddr) & (offset <= lastCellOffset)) {
+                    if (reinterpret_cast<CollectorCell*>(xAsBits)->u.freeCell.zeroIfFree) {
+                        markStack.append(reinterpret_cast<JSCell*>(xAsBits));
+                        markStack.drain();
+                    }
+                    break;
+                }
             }
+        endMarkLoop:
+            ;
         }
-#if USE(JSVALUE32)
-loopEnd:
-#endif
     }
 }
 
@@ -1057,78 +1009,129 @@ void Heap::markProtectedObjects(MarkStack& markStack)
     }
 }
 
-template <HeapType heapType> 
-void Heap::clearMarkBits()
+template <HeapType heapType> size_t Heap::sweep()
 {
-    CollectorHeap& heap = heapType == PrimaryHeap ? primaryHeap : numberHeap;
-    for (size_t i = 0; i < heap.usedBlocks; ++i)
-        clearMarkBits<heapType>(heap.blocks[i]);
-}
-
-template <HeapType heapType> 
-void Heap::clearMarkBits(CollectorBlock* block)
-{
-    // heapAllocate assumes that the last cell in every block is marked.
-    block->marked.clearAll();
-    block->marked.set((HeapConstants<heapType>::cellsPerBlock - 1) >> HeapConstants<heapType>::bitmapShift);
-}
-
-template <HeapType heapType> 
-size_t Heap::markedCells(size_t startBlock, size_t startCell) const
-{
-    const CollectorHeap& heap = heapType == PrimaryHeap ? primaryHeap : numberHeap;
-    ASSERT(startBlock <= heap.usedBlocks);
-    ASSERT(startCell < HeapConstants<heapType>::cellsPerBlock);
-
-    if (startBlock >= heap.usedBlocks)
-        return 0;
-
-    size_t result = 0;
-    result += heap.blocks[startBlock]->marked.count(startCell);
-    for (size_t i = startBlock + 1; i < heap.usedBlocks; ++i)
-        result += heap.blocks[i]->marked.count();
-
-    return result;
-}
-
-template <HeapType heapType> 
-void Heap::sweep()
-{
-    ASSERT(heapType != NumberHeap); // The number heap does not contain meaningful destructors.
+    typedef typename HeapConstants<heapType>::Block Block;
+    typedef typename HeapConstants<heapType>::Cell Cell;
 
+    // SWEEP: delete everything with a zero refcount (garbage) and unmark everything else
     CollectorHeap& heap = heapType == PrimaryHeap ? primaryHeap : numberHeap;
-
-    ASSERT(heap.operationInProgress == NoOperation);
-    if (heap.operationInProgress != NoOperation)
-        CRASH();
-    heap.operationInProgress = Collection;
     
+    size_t emptyBlocks = 0;
+    size_t numLiveObjects = heap.numLiveObjects;
+    
+    for (size_t block = 0; block < heap.usedBlocks; block++) {
+        Block* curBlock = reinterpret_cast<Block*>(heap.blocks[block]);
+        
+        size_t usedCells = curBlock->usedCells;
+        Cell* freeList = curBlock->freeList;
+        
+        if (usedCells == HeapConstants<heapType>::cellsPerBlock) {
+            // special case with a block where all cells are used -- testing indicates this happens often
+            for (size_t i = 0; i < HeapConstants<heapType>::cellsPerBlock; i++) {
+                if (!curBlock->marked.get(i >> HeapConstants<heapType>::bitmapShift)) {
+                    Cell* cell = curBlock->cells + i;
+                    
+                    if (heapType != NumberHeap) {
+                        JSCell* imp = reinterpret_cast<JSCell*>(cell);
+                        // special case for allocated but uninitialized object
+                        // (We don't need this check earlier because nothing prior this point 
+                        // assumes the object has a valid vptr.)
+                        if (cell->u.freeCell.zeroIfFree == 0)
+                            continue;
+#if ENABLE(JSC_ZOMBIES)
+                        if (!imp->isZombie()) {
+                            const ClassInfo* info = imp->classInfo();
+                            imp->~JSCell();
+                            new (imp) JSZombie(info, JSZombie::leakedZombieStructure());
+                            heap.numZombies++;
+                        }
+#else
+                        imp->~JSCell();
+#endif
+                    }
+                    --numLiveObjects;
 #if !ENABLE(JSC_ZOMBIES)
-    Structure* dummyMarkableCellStructure = m_globalData->dummyMarkableCellStructure.get();
+                    --usedCells;
+                    
+                    // put cell on the free list
+                    cell->u.freeCell.zeroIfFree = 0;
+                    cell->u.freeCell.next = freeList - (cell + 1);
+                    freeList = cell;
 #endif
-
-    DeadObjectIterator<heapType> it(heap, heap.nextBlock, heap.nextCell);
-    DeadObjectIterator<heapType> end(heap, heap.usedBlocks);
-    for ( ; it != end; ++it) {
-        JSCell* cell = *it;
+                }
+            }
+        } else {
+            size_t minimumCellsToProcess = usedCells;
+            for (size_t i = 0; (i < minimumCellsToProcess) & (i < HeapConstants<heapType>::cellsPerBlock); i++) {
+                Cell* cell = curBlock->cells + i;
+                if (cell->u.freeCell.zeroIfFree == 0) {
+                    ++minimumCellsToProcess;
+                } else {
+                    if (!curBlock->marked.get(i >> HeapConstants<heapType>::bitmapShift)) {
+                        if (heapType != NumberHeap) {
+                            JSCell* imp = reinterpret_cast<JSCell*>(cell);
 #if ENABLE(JSC_ZOMBIES)
-        if (!cell->isZombie()) {
-            const ClassInfo* info = cell->classInfo();
-            cell->~JSCell();
-            new (cell) JSZombie(info, JSZombie::leakedZombieStructure());
-            Heap::markCell(cell);
-        }
+                            if (!imp->isZombie()) {
+                                const ClassInfo* info = imp->classInfo();
+                                imp->~JSCell();
+                                new (imp) JSZombie(info, JSZombie::leakedZombieStructure());
+                                heap.numZombies++;
+                            }
 #else
-        cell->~JSCell();
-        // Callers of sweep assume it's safe to mark any cell in the heap.
-        new (cell) JSCell(dummyMarkableCellStructure);
+                            imp->~JSCell();
+#endif
+                        }
+#if !ENABLE(JSC_ZOMBIES)
+                        --usedCells;
+                        --numLiveObjects;
+                        
+                        // put cell on the free list
+                        cell->u.freeCell.zeroIfFree = 0;
+                        cell->u.freeCell.next = freeList - (cell + 1); 
+                        freeList = cell;
 #endif
+                    }
+                }
+            }
+        }
+        
+        curBlock->usedCells = static_cast<uint32_t>(usedCells);
+        curBlock->freeList = freeList;
+        curBlock->marked.clearAll();
+        
+        if (!usedCells)
+            ++emptyBlocks;
     }
+    
+    if (heap.numLiveObjects != numLiveObjects)
+        heap.firstBlockWithPossibleSpace = 0;
+    
+    heap.numLiveObjects = numLiveObjects;
+    heap.numLiveObjectsAtLastCollect = numLiveObjects;
+    heap.extraCost = 0;
+    
+    if (!emptyBlocks)
+        return numLiveObjects;
 
-    heap.operationInProgress = NoOperation;
+    size_t neededCells = 1.25f * (numLiveObjects + max(ALLOCATIONS_PER_COLLECTION, numLiveObjects));
+    size_t neededBlocks = (neededCells + HeapConstants<heapType>::cellsPerBlock - 1) / HeapConstants<heapType>::cellsPerBlock;
+    for (size_t block = 0; block < heap.usedBlocks; block++) {
+        if (heap.usedBlocks <= neededBlocks)
+            break;
+
+        Block* curBlock = reinterpret_cast<Block*>(heap.blocks[block]);
+        if (curBlock->usedCells)
+            continue;
+
+        freeBlock<heapType>(block);
+        block--; // Don't move forward a step in this case
+    }
+
+    return numLiveObjects;
 }
 
-void Heap::markRoots()
+bool Heap::collect()
 {
 #ifndef NDEBUG
     if (m_globalData->isSharedInstance) {
@@ -1137,31 +1140,23 @@ void Heap::markRoots()
     }
 #endif
 
-    ASSERT((primaryHeap.operationInProgress == NoOperation) & (numberHeap.operationInProgress == NoOperation));
-    if (!((primaryHeap.operationInProgress == NoOperation) & (numberHeap.operationInProgress == NoOperation)))
+    ASSERT((primaryHeap.operationInProgress == NoOperation) | (numberHeap.operationInProgress == NoOperation));
+    if ((primaryHeap.operationInProgress != NoOperation) | (numberHeap.operationInProgress != NoOperation))
         CRASH();
 
+    JAVASCRIPTCORE_GC_BEGIN();
     primaryHeap.operationInProgress = Collection;
     numberHeap.operationInProgress = Collection;
 
+    // MARK: first mark all referenced objects recursively starting out from the set of root objects
     MarkStack& markStack = m_globalData->markStack;
-
-    // Reset mark bits.
-    clearMarkBits<PrimaryHeap>();
-    clearMarkBits<NumberHeap>();
-
-    // Mark stack roots.
     markStackObjectsConservatively(markStack);
-    m_globalData->interpreter->registerFile().markCallFrames(markStack, this);
-
-    // Mark explicitly registered roots.
     markProtectedObjects(markStack);
-
-    // Mark misc. other roots.
     if (m_markListSet && m_markListSet->size())
         MarkedArgumentBuffer::markLists(markStack, *m_markListSet);
     if (m_globalData->exception)
         markStack.append(m_globalData->exception);
+    m_globalData->interpreter->registerFile().markCallFrames(markStack, this);
     m_globalData->smallStrings.markChildren(markStack);
     if (m_globalData->functionCodeBlockBeingReparsed)
         m_globalData->functionCodeBlockBeingReparsed->markAggregate(markStack);
@@ -1170,41 +1165,41 @@ void Heap::markRoots()
 
     markStack.drain();
     markStack.compact();
+    JAVASCRIPTCORE_GC_MARKED();
+
+    size_t originalLiveObjects = primaryHeap.numLiveObjects + numberHeap.numLiveObjects;
+    size_t numLiveObjects = sweep<PrimaryHeap>();
+    numLiveObjects += sweep<NumberHeap>();
 
     primaryHeap.operationInProgress = NoOperation;
     numberHeap.operationInProgress = NoOperation;
-}
+    JAVASCRIPTCORE_GC_END(originalLiveObjects, numLiveObjects);
 
-size_t Heap::objectCount() const
-{
-    return objectCount<PrimaryHeap>() + objectCount<NumberHeap>();
+    return numLiveObjects < originalLiveObjects;
 }
 
-template <HeapType heapType> 
-size_t Heap::objectCount() const
+size_t Heap::objectCount() 
 {
-    const CollectorHeap& heap = heapType == PrimaryHeap ? primaryHeap : numberHeap;
-
-    return heap.nextBlock * HeapConstants<heapType>::cellsPerBlock // allocated full blocks
-           + heap.nextCell // allocated cells in current block
-           + markedCells<heapType>(heap.nextBlock, heap.nextCell) // marked cells in remainder of heap
-           - heap.usedBlocks; // 1 cell per block is a dummy sentinel
+    return primaryHeap.numLiveObjects + numberHeap.numLiveObjects - m_globalData->smallStrings.count(); 
 }
 
 template <HeapType heapType> 
-void Heap::addToStatistics(Heap::Statistics& statistics) const
+static void addToStatistics(Heap::Statistics& statistics, const CollectorHeap& heap)
 {
-    const CollectorHeap& heap = heapType == PrimaryHeap ? primaryHeap : numberHeap;
-
-    statistics.size += heap.usedBlocks * BLOCK_SIZE;
-    statistics.free += heap.usedBlocks * BLOCK_SIZE - (objectCount<heapType>() * HeapConstants<heapType>::cellSize);
+    typedef HeapConstants<heapType> HC;
+    for (size_t i = 0; i < heap.usedBlocks; ++i) {
+        if (heap.blocks[i]) {
+            statistics.size += BLOCK_SIZE;
+            statistics.free += (HC::cellsPerBlock - heap.blocks[i]->usedCells) * HC::cellSize;
+        }
+    }
 }
 
 Heap::Statistics Heap::statistics() const
 {
     Statistics statistics = { 0, 0 };
-    addToStatistics<PrimaryHeap>(statistics);
-    addToStatistics<NumberHeap>(statistics);
+    JSC::addToStatistics<PrimaryHeap>(statistics, primaryHeap);
+    JSC::addToStatistics<NumberHeap>(statistics, numberHeap);
     return statistics;
 }
 
@@ -1276,68 +1271,14 @@ bool Heap::isBusy()
     return (primaryHeap.operationInProgress != NoOperation) | (numberHeap.operationInProgress != NoOperation);
 }
 
-void Heap::reset()
-{
-    JAVASCRIPTCORE_GC_BEGIN();
-
-    markRoots();
-
-    JAVASCRIPTCORE_GC_MARKED();
-
-    primaryHeap.nextCell = 0;
-    primaryHeap.nextBlock = 0;
-    primaryHeap.extraCost = 0;
-#if ENABLE(JSC_ZOMBIES)
-    sweep<PrimaryHeap>();
-#endif
-    resizeBlocks<PrimaryHeap>();
-
-#if USE(JSVALUE32)
-    numberHeap.nextCell = 0;
-    numberHeap.nextBlock = 0;
-    resizeBlocks<NumberHeap>();
-#endif
-
-    JAVASCRIPTCORE_GC_END();
-}
-
-void Heap::collectAllGarbage()
-{
-    JAVASCRIPTCORE_GC_BEGIN();
-
-    // If the last iteration through the heap deallocated blocks, we need
-    // to clean up remaining garbage before marking. Otherwise, the conservative
-    // marking mechanism might follow a pointer to unmapped memory.
-    if (primaryHeap.didShrink)
-        sweep<PrimaryHeap>();
-
-    markRoots();
-
-    JAVASCRIPTCORE_GC_MARKED();
-
-    primaryHeap.nextCell = 0;
-    primaryHeap.nextBlock = 0;
-    primaryHeap.extraCost = 0;
-    sweep<PrimaryHeap>();
-    resizeBlocks<PrimaryHeap>();
-
-#if USE(JSVALUE32)
-    numberHeap.nextCell = 0;
-    numberHeap.nextBlock = 0;
-    resizeBlocks<NumberHeap>();
-#endif
-
-    JAVASCRIPTCORE_GC_END();
-}
-
-LiveObjectIterator<PrimaryHeap> Heap::primaryHeapBegin()
+Heap::iterator Heap::primaryHeapBegin()
 {
-    return LiveObjectIterator<PrimaryHeap>(primaryHeap, 0);
+    return iterator(primaryHeap.blocks, primaryHeap.blocks + primaryHeap.usedBlocks);
 }
 
-LiveObjectIterator<PrimaryHeap> Heap::primaryHeapEnd()
+Heap::iterator Heap::primaryHeapEnd()
 {
-    return LiveObjectIterator<PrimaryHeap>(primaryHeap, primaryHeap.usedBlocks);
+    return iterator(primaryHeap.blocks + primaryHeap.usedBlocks, primaryHeap.blocks + primaryHeap.usedBlocks);
 }
 
 } // namespace JSC
diff --git a/JavaScriptCore/runtime/Collector.h b/JavaScriptCore/runtime/Collector.h
index c86ca83..9128701 100644
--- a/JavaScriptCore/runtime/Collector.h
+++ b/JavaScriptCore/runtime/Collector.h
@@ -28,9 +28,9 @@
 #include <wtf/HashSet.h>
 #include <wtf/Noncopyable.h>
 #include <wtf/OwnPtr.h>
-#include <wtf/StdLibExtras.h>
 #include <wtf/Threading.h>
 
+// This is supremely lame that we require pthreads to build on windows.
 #if ENABLE(JSC_MULTIPLE_THREADS)
 #include <pthread.h>
 #endif
@@ -49,19 +49,20 @@ namespace JSC {
     enum OperationInProgress { NoOperation, Allocation, Collection };
     enum HeapType { PrimaryHeap, NumberHeap };
 
-    template <HeapType> class LiveObjectIterator;
+    template <HeapType> class CollectorHeapIterator;
 
     struct CollectorHeap {
-        size_t nextBlock;
-        size_t nextCell;
-
         CollectorBlock** blocks;
         size_t numBlocks;
         size_t usedBlocks;
+        size_t firstBlockWithPossibleSpace;
 
+        size_t numLiveObjects;
+        size_t numLiveObjectsAtLastCollect;
         size_t extraCost;
-        
-        bool didShrink;
+#if ENABLE(JSC_ZOMBIES)
+        size_t numZombies;
+#endif
 
         OperationInProgress operationInProgress;
     };
@@ -69,21 +70,21 @@ namespace JSC {
     class Heap : public Noncopyable {
     public:
         class Thread;
+        typedef CollectorHeapIterator<PrimaryHeap> iterator;
 
         void destroy();
 
         void* allocateNumber(size_t);
         void* allocate(size_t);
 
+        bool collect();
         bool isBusy(); // true if an allocation or collection is in progress
-        void collectAllGarbage();
 
-        static const size_t minExtraCost = 256;
-        static const size_t maxExtraCost = 1024 * 1024;
+        static const size_t minExtraCostSize = 256;
 
         void reportExtraMemoryCost(size_t cost);
 
-        size_t objectCount() const;
+        size_t objectCount();
         struct Statistics {
             size_t size;
             size_t free;
@@ -113,14 +114,13 @@ namespace JSC {
         JSGlobalData* globalData() const { return m_globalData; }
         static bool isNumber(JSCell*);
         
-        LiveObjectIterator<PrimaryHeap> primaryHeapBegin();
-        LiveObjectIterator<PrimaryHeap> primaryHeapEnd();
+        // Iterators for the object heap.
+        iterator primaryHeapBegin();
+        iterator primaryHeapEnd();
 
     private:
         template <HeapType heapType> void* heapAllocate(size_t);
-        void reset();
-        void collectRemainingGarbage();
-        template <HeapType heapType> void sweep();
+        template <HeapType heapType> size_t sweep();
         static CollectorBlock* cellBlock(const JSCell*);
         static size_t cellOffset(const JSCell*);
 
@@ -131,20 +131,9 @@ namespace JSC {
         template <HeapType heapType> NEVER_INLINE CollectorBlock* allocateBlock();
         template <HeapType heapType> NEVER_INLINE void freeBlock(size_t);
         NEVER_INLINE void freeBlock(CollectorBlock*);
-        template <HeapType heapType> void freeBlocks();
-        template <HeapType heapType> void resizeBlocks();
-        template <HeapType heapType> void growBlocks(size_t neededBlocks);
-        template <HeapType heapType> void shrinkBlocks(size_t neededBlocks);
-        template <HeapType heapType> void clearMarkBits();
-        template <HeapType heapType> void clearMarkBits(CollectorBlock*);
-        template <HeapType heapType> size_t markedCells(size_t startBlock = 0, size_t startCell = 0) const;
+        void freeBlocks(CollectorHeap*);
 
         void recordExtraCost(size_t);
-
-        template <HeapType heapType> void addToStatistics(Statistics&) const;
-        template <HeapType heapType> size_t objectCount() const;
-
-        void markRoots();
         void markProtectedObjects(MarkStack&);
         void markCurrentThreadConservatively(MarkStack&);
         void markCurrentThreadConservativelyInternal(MarkStack&);
@@ -200,49 +189,44 @@ namespace JSC {
     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 - sizeof(Heap*) - sizeof(HeapType)) * 8 * CELL_SIZE / (8 * CELL_SIZE + 1) / CELL_SIZE; // one bitmap byte can represent 8 cells.
-    
+    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);
-
+  
     struct CollectorBitmap {
         uint32_t bits[BITMAP_WORDS];
         bool get(size_t n) const { return !!(bits[n >> 5] & (1 << (n & 0x1F))); } 
         void set(size_t n) { bits[n >> 5] |= (1 << (n & 0x1F)); } 
         void clear(size_t n) { bits[n >> 5] &= ~(1 << (n & 0x1F)); } 
         void clearAll() { memset(bits, 0, sizeof(bits)); }
-        size_t count(size_t startCell = 0)
-        {
-            size_t result = 0;
-            for ( ; (startCell & 0x1F) != 0; ++startCell) {
-                if (get(startCell))
-                    ++result;
-            }
-            for (size_t i = startCell >> 5; i < BITMAP_WORDS; ++i)
-                result += WTF::bitCount(bits[i]);
-            return result;
-        }
-        size_t isEmpty() // Much more efficient than testing count() == 0.
-        {
-            for (size_t i = 0; i < BITMAP_WORDS; ++i)
-                if (bits[i] != 0)
-                    return false;
-            return true;
-        }
     };
   
     struct CollectorCell {
-        double memory[CELL_ARRAY_LENGTH];
+        union {
+            double memory[CELL_ARRAY_LENGTH];
+            struct {
+                void* zeroIfFree;
+                ptrdiff_t next;
+            } freeCell;
+        } u;
     };
 
     struct SmallCollectorCell {
-        double memory[CELL_ARRAY_LENGTH / 2];
+        union {
+            double memory[CELL_ARRAY_LENGTH / 2];
+            struct {
+                void* zeroIfFree;
+                ptrdiff_t next;
+            } freeCell;
+        } u;
     };
 
     class CollectorBlock {
     public:
         CollectorCell cells[CELLS_PER_BLOCK];
+        uint32_t usedCells;
+        CollectorCell* freeList;
         CollectorBitmap marked;
         Heap* heap;
         HeapType type;
@@ -251,6 +235,8 @@ namespace JSC {
     class SmallCellCollectorBlock {
     public:
         SmallCollectorCell cells[SMALL_CELLS_PER_BLOCK];
+        uint32_t usedCells;
+        SmallCollectorCell* freeList;
         CollectorBitmap marked;
         Heap* heap;
         HeapType type;
@@ -301,8 +287,8 @@ namespace JSC {
 
     inline void Heap::reportExtraMemoryCost(size_t cost)
     {
-        if (cost > minExtraCost) 
-            recordExtraCost(cost);
+        if (cost > minExtraCostSize) 
+            recordExtraCost(cost / (CELL_SIZE * 2)); 
     }
 
 } // namespace JSC
diff --git a/JavaScriptCore/runtime/CollectorHeapIterator.h b/JavaScriptCore/runtime/CollectorHeapIterator.h
index cdd6702..e38a852 100644
--- a/JavaScriptCore/runtime/CollectorHeapIterator.h
+++ b/JavaScriptCore/runtime/CollectorHeapIterator.h
@@ -31,117 +31,58 @@
 
 namespace JSC {
 
-    class CollectorHeapIterator {
+    template <HeapType heapType> class CollectorHeapIterator {
     public:
-        bool operator!=(const CollectorHeapIterator& other);
+        CollectorHeapIterator(CollectorBlock** block, CollectorBlock** endBlock);
+
+        bool operator!=(const CollectorHeapIterator<heapType>& other) { return m_block != other.m_block || m_cell != other.m_cell; }
+        CollectorHeapIterator<heapType>& operator++();
         JSCell* operator*() const;
     
-    protected:
-        CollectorHeapIterator(CollectorHeap&, size_t startBlock, size_t startCell);
-        void advance(size_t cellsPerBlock);
-
-        CollectorHeap& m_heap;
-        size_t m_block;
-        size_t m_cell;
-    };
-
-    template <HeapType heapType>
-    class LiveObjectIterator : public CollectorHeapIterator {
-    public:
-        LiveObjectIterator(CollectorHeap&, size_t startBlock, size_t startCell = 0);
-        LiveObjectIterator<heapType>& operator++();
-    };
-
-    template <HeapType heapType>
-    class DeadObjectIterator : public CollectorHeapIterator {
-    public:
-        DeadObjectIterator(CollectorHeap&, size_t startBlock, size_t startCell = 0);
-        DeadObjectIterator<heapType>& operator++();
-    };
-
-    template <HeapType heapType>
-    class ObjectIterator : public CollectorHeapIterator {
-    public:
-        ObjectIterator(CollectorHeap&, size_t startBlock, size_t startCell = 0);
-        ObjectIterator<heapType>& operator++();
+    private:
+        typedef typename HeapConstants<heapType>::Block Block;
+        typedef typename HeapConstants<heapType>::Cell Cell;
+
+        Block** m_block;
+        Block** m_endBlock;
+        Cell* m_cell;
+        Cell* m_endCell;
     };
 
-    inline CollectorHeapIterator::CollectorHeapIterator(CollectorHeap& heap, size_t startBlock, size_t startCell)
-        : m_heap(heap)
-        , m_block(startBlock)
-        , m_cell(startCell)
-    {
-    }
-
-    inline bool CollectorHeapIterator::operator!=(const CollectorHeapIterator& other)
-    {
-        return m_block != other.m_block || m_cell != other.m_cell;
-    }
-
-    inline JSCell* CollectorHeapIterator::operator*() const
-    {
-        return reinterpret_cast<JSCell*>(m_heap.blocks[m_block]->cells + m_cell);
-    }
-    
-    inline void CollectorHeapIterator::advance(size_t cellsPerBlock)
-    {
-        ++m_cell;
-        if (m_cell == cellsPerBlock) {
-            m_cell = 0;
-            ++m_block;
-        }
-    }
-
-    template <HeapType heapType>
-    inline LiveObjectIterator<heapType>::LiveObjectIterator(CollectorHeap& heap, size_t startBlock, size_t startCell)
-        : CollectorHeapIterator(heap, startBlock, startCell - 1)
-    {
-        ++(*this);
-    }
-
-    template <HeapType heapType>
-    inline LiveObjectIterator<heapType>& LiveObjectIterator<heapType>::operator++()
-    {
-        if (m_block < m_heap.nextBlock || m_cell < m_heap.nextCell) {
-            advance(HeapConstants<heapType>::cellsPerBlock);
-            return *this;
-        }
-
-        do {
-            advance(HeapConstants<heapType>::cellsPerBlock);
-        } while (m_block < m_heap.usedBlocks && !m_heap.blocks[m_block]->marked.get(m_cell));
-        return *this;
-    }
-
-    template <HeapType heapType>
-    inline DeadObjectIterator<heapType>::DeadObjectIterator(CollectorHeap& heap, size_t startBlock, size_t startCell)
-        : CollectorHeapIterator(heap, startBlock, startCell - 1)
+    template <HeapType heapType> 
+    CollectorHeapIterator<heapType>::CollectorHeapIterator(CollectorBlock** block, CollectorBlock** endBlock)
+        : m_block(reinterpret_cast<Block**>(block))
+        , m_endBlock(reinterpret_cast<Block**>(endBlock))
+        , m_cell(m_block == m_endBlock ? 0 : (*m_block)->cells)
+        , m_endCell(m_block == m_endBlock ? 0 : (*m_block)->cells + HeapConstants<heapType>::cellsPerBlock)
     {
-        ++(*this);
+        if (m_cell && m_cell->u.freeCell.zeroIfFree == 0)
+            ++*this;
     }
 
-    template <HeapType heapType>
-    inline DeadObjectIterator<heapType>& DeadObjectIterator<heapType>::operator++()
+    template <HeapType heapType> 
+    CollectorHeapIterator<heapType>& CollectorHeapIterator<heapType>::operator++()
     {
         do {
-            advance(HeapConstants<heapType>::cellsPerBlock);
-            ASSERT(m_block > m_heap.nextBlock || (m_block == m_heap.nextBlock && m_cell >= m_heap.nextCell));
-        } while (m_block < m_heap.usedBlocks && m_heap.blocks[m_block]->marked.get(m_cell));
+            for (++m_cell; m_cell != m_endCell; ++m_cell)
+                if (m_cell->u.freeCell.zeroIfFree != 0) {
+                    return *this;
+                }
+
+            if (++m_block != m_endBlock) {
+                m_cell = (*m_block)->cells;
+                m_endCell = (*m_block)->cells + HeapConstants<heapType>::cellsPerBlock;
+            }
+        } while(m_block != m_endBlock);
+
+        m_cell = 0;
         return *this;
     }
 
-    template <HeapType heapType>
-    inline ObjectIterator<heapType>::ObjectIterator(CollectorHeap& heap, size_t startBlock, size_t startCell)
-        : CollectorHeapIterator(heap, startBlock, startCell - 1)
+    template <HeapType heapType> 
+    JSCell* CollectorHeapIterator<heapType>::operator*() const
     {
-        ++(*this);
-    }
-
-    template <HeapType heapType>
-    inline ObjectIterator<heapType>& ObjectIterator<heapType>::operator++()
-    {
-        advance(HeapConstants<heapType>::cellsPerBlock);
-        return *this;
+        return reinterpret_cast<JSCell*>(m_cell);
     }
 
 } // namespace JSC
diff --git a/JavaScriptCore/runtime/JSArray.cpp b/JavaScriptCore/runtime/JSArray.cpp
index 0d2a9b4..b16d3fa 100644
--- a/JavaScriptCore/runtime/JSArray.cpp
+++ b/JavaScriptCore/runtime/JSArray.cpp
@@ -380,6 +380,8 @@ NEVER_INLINE void JSArray::putSlowCase(ExecState* exec, unsigned i, JSValue valu
 
     unsigned vectorLength = m_vectorLength;
 
+    Heap::heap(this)->reportExtraMemoryCost(storageSize(newVectorLength) - storageSize(vectorLength));
+
     if (newNumValuesInVector == storage->m_numValuesInVector + 1) {
         for (unsigned j = vectorLength; j < newVectorLength; ++j)
             storage->m_vector[j] = JSValue();
@@ -400,8 +402,6 @@ NEVER_INLINE void JSArray::putSlowCase(ExecState* exec, unsigned i, JSValue valu
     m_storage = storage;
 
     checkConsistency();
-
-    Heap::heap(this)->reportExtraMemoryCost(storageSize(newVectorLength) - storageSize(vectorLength));
 }
 
 bool JSArray::deleteProperty(ExecState* exec, const Identifier& propertyName)
@@ -492,15 +492,13 @@ bool JSArray::increaseVectorLength(unsigned newLength)
     if (!tryFastRealloc(storage, storageSize(newVectorLength)).getValue(storage))
         return false;
 
+    Heap::heap(this)->reportExtraMemoryCost(storageSize(newVectorLength) - storageSize(vectorLength));
     m_vectorLength = newVectorLength;
 
     for (unsigned i = vectorLength; i < newVectorLength; ++i)
         storage->m_vector[i] = JSValue();
 
     m_storage = storage;
-
-    Heap::heap(this)->reportExtraMemoryCost(storageSize(newVectorLength) - storageSize(vectorLength));
-
     return true;
 }
 
diff --git a/JavaScriptCore/runtime/JSCell.h b/JavaScriptCore/runtime/JSCell.h
index 5dfe206..c8ba2b8 100644
--- a/JavaScriptCore/runtime/JSCell.h
+++ b/JavaScriptCore/runtime/JSCell.h
@@ -47,18 +47,10 @@ namespace JSC {
 
     private:
         explicit JSCell(Structure*);
-        
-        // Only used for initializing Collector blocks.
-        enum DummyDestructableCellTag { DummyDestructableCell };
-        JSCell(DummyDestructableCellTag);
+        JSCell(); // Only used for initializing Collector blocks.
         virtual ~JSCell();
 
     public:
-        static PassRefPtr<Structure> createDummyStructure()
-        {
-            return Structure::create(jsNull(), TypeInfo(UnspecifiedType));
-        }
-
         // Querying the type.
 #if USE(JSVALUE32)
         bool isNumber() const;
@@ -130,7 +122,8 @@ namespace JSC {
     {
     }
 
-    inline JSCell::JSCell(DummyDestructableCellTag)
+    // Only used for initializing Collector blocks.
+    inline JSCell::JSCell()
     {
     }
 
diff --git a/JavaScriptCore/runtime/JSGlobalData.cpp b/JavaScriptCore/runtime/JSGlobalData.cpp
index 7726f4d..234449f 100644
--- a/JavaScriptCore/runtime/JSGlobalData.cpp
+++ b/JavaScriptCore/runtime/JSGlobalData.cpp
@@ -126,7 +126,6 @@ JSGlobalData::JSGlobalData(bool isShared, const VPtrSet& vptrSet)
     , propertyNameIteratorStructure(JSPropertyNameIterator::createStructure(jsNull()))
     , getterSetterStructure(GetterSetter::createStructure(jsNull()))
     , apiWrapperStructure(JSAPIValueWrapper::createStructure(jsNull()))
-    , dummyMarkableCellStructure(JSCell::createDummyStructure())
 #if USE(JSVALUE32)
     , numberStructure(JSNumberCell::createStructure(jsNull()))
 #endif
diff --git a/JavaScriptCore/runtime/JSGlobalData.h b/JavaScriptCore/runtime/JSGlobalData.h
index 9f725c6..f0c1b5c 100644
--- a/JavaScriptCore/runtime/JSGlobalData.h
+++ b/JavaScriptCore/runtime/JSGlobalData.h
@@ -123,7 +123,6 @@ namespace JSC {
         RefPtr<Structure> propertyNameIteratorStructure;
         RefPtr<Structure> getterSetterStructure;
         RefPtr<Structure> apiWrapperStructure;
-        RefPtr<Structure> dummyMarkableCellStructure;
 
 #if USE(JSVALUE32)
         RefPtr<Structure> numberStructure;
diff --git a/JavaScriptCore/runtime/JSString.h b/JavaScriptCore/runtime/JSString.h
index 81ec1d2..33e60ab 100644
--- a/JavaScriptCore/runtime/JSString.h
+++ b/JavaScriptCore/runtime/JSString.h
@@ -421,7 +421,7 @@ namespace JSC {
             if (c <= 0xFF)
                 return globalData->smallStrings.singleCharacterString(globalData, c);
         }
-        return new (globalData) JSString(globalData, UString(UString::Rep::create(s.rep(), offset, length)), JSString::HasOtherOwner);
+        return new (globalData) JSString(globalData, UString(UString::Rep::create(s.rep(), offset, length)));
     }
 
     inline JSString* jsOwnedString(JSGlobalData* globalData, const UString& s)
diff --git a/JavaScriptCore/runtime/Tracing.d b/JavaScriptCore/runtime/Tracing.d
index da854b9..b9efaff 100644
--- a/JavaScriptCore/runtime/Tracing.d
+++ b/JavaScriptCore/runtime/Tracing.d
@@ -27,7 +27,7 @@ provider JavaScriptCore
 {
     probe gc__begin();
     probe gc__marked();
-    probe gc__end();
+    probe gc__end(int, int);
     
     probe profile__will_execute(int, char*, char*, int);
     probe profile__did_execute(int, char*, char*, int);
diff --git a/JavaScriptCore/runtime/Tracing.h b/JavaScriptCore/runtime/Tracing.h
index c28c85f..e544f66 100644
--- a/JavaScriptCore/runtime/Tracing.h
+++ b/JavaScriptCore/runtime/Tracing.h
@@ -33,7 +33,7 @@
 #define JAVASCRIPTCORE_GC_BEGIN()
 #define JAVASCRIPTCORE_GC_BEGIN_ENABLED() 0
 
-#define JAVASCRIPTCORE_GC_END()
+#define JAVASCRIPTCORE_GC_END(arg0, arg1)
 #define JAVASCRIPTCORE_GC_END_ENABLED() 0
 
 #define JAVASCRIPTCORE_GC_MARKED()
diff --git a/JavaScriptCore/runtime/UString.h b/JavaScriptCore/runtime/UString.h
index a2a0e56..9c2433b 100644
--- a/JavaScriptCore/runtime/UString.h
+++ b/JavaScriptCore/runtime/UString.h
@@ -512,7 +512,7 @@ namespace JSC {
     // huge buffer.
     // FIXME: this should be size_t but that would cause warnings until we
     // fix UString sizes to be size_t instead of int
-    static const int minShareSize = Heap::minExtraCost / sizeof(UChar);
+    static const int minShareSize = Heap::minExtraCostSize / sizeof(UChar);
 
     inline size_t UString::cost() const
     {
diff --git a/JavaScriptCore/runtime/WeakGCMap.h b/JavaScriptCore/runtime/WeakGCMap.h
deleted file mode 100644
index 9d5f8c7..0000000
--- a/JavaScriptCore/runtime/WeakGCMap.h
+++ /dev/null
@@ -1,234 +0,0 @@
-/*
- * 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. AND ITS CONTRIBUTORS ``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 ITS 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 WeakGCMap_h
-#define WeakGCMap_h
-
-#include <wtf/HashMap.h>
-
-namespace JSC {
-
-class JSCell;
-
-// A HashMap whose get() function returns emptyValue() for cells awaiting destruction.
-template<typename KeyType, typename MappedType>
-class WeakGCMap {
-    /*
-    Invariants:
-        * A value enters the WeakGCMap marked. (Guaranteed by set()).
-        * A value that becomes unmarked leaves the WeakGCMap before being recycled. (Guaranteed by the value's destructor removing it from the WeakGCMap.)
-        * A value that becomes unmarked leaves the WeakGCMap before becoming marked again. (Guaranteed by all destructors running before the mark phase begins.)
-        * During the mark phase, all values in the WeakGCMap are valid. (Guaranteed by all destructors running before the mark phase begins.)
-    */
-
-public:
-    typedef typename HashMap<KeyType, MappedType>::iterator iterator;
-    typedef typename HashMap<KeyType, MappedType>::const_iterator const_iterator;
-    
-    bool isEmpty() { return m_map.isEmpty(); }
-
-    MappedType get(const KeyType& key) const;
-    pair<iterator, bool> set(const KeyType&, const MappedType&); 
-    MappedType take(const KeyType& key);
-
-    // These unchecked functions provide access to a value even if the value's
-    // mark bit is not set. This is used, among other things, to retrieve values
-    // during the GC mark phase, which begins by clearing all mark bits.
-
-    MappedType uncheckedGet(const KeyType& key) const { return m_map.get(key); }
-    bool uncheckedRemove(const KeyType&, const MappedType&);
-
-    iterator uncheckedBegin() { return m_map.begin(); }
-    iterator uncheckedEnd() { return m_map.end(); }
-
-    const_iterator uncheckedBegin() const { return m_map.begin(); }
-    const_iterator uncheckedEnd() const { return m_map.end(); }
-
-private:
-    HashMap<KeyType, MappedType> m_map;
-};
-
-template<typename KeyType, typename MappedType>
-MappedType WeakGCMap<KeyType, MappedType>::get(const KeyType& key) const
-{
-    MappedType result = m_map.get(key);
-    if (!Heap::isCellMarked(result))
-        return HashTraits<MappedType>::emptyValue();
-    return result;
-}
-
-template<typename KeyType, typename MappedType>
-MappedType WeakGCMap<KeyType, MappedType>::take(const KeyType& key)
-{
-    MappedType result = m_map.take(key);
-    if (!Heap::isCellMarked(result))
-        return HashTraits<MappedType>::emptyValue();
-    return result;
-}
-
-template<typename KeyType, typename MappedType>
-pair<typename HashMap<KeyType, MappedType>::iterator, bool> WeakGCMap<KeyType, MappedType>::set(const KeyType& key, const MappedType& value)
-{
-    Heap::markCell(value); // If value is newly allocated, it's not marked, so mark it now.
-    pair<iterator, bool> result = m_map.add(key, value);
-    if (!result.second) { // pre-existing entry
-        result.second = !Heap::isCellMarked(result.first->second);
-        result.first->second = value;
-    }
-    return result;
-}
-
-template<typename KeyType, typename MappedType>
-bool WeakGCMap<KeyType, MappedType>::uncheckedRemove(const KeyType& key, const MappedType& value)
-{
-    iterator it = m_map.find(key);
-    if (it == m_map.end())
-        return false;
-    if (it->second != value)
-        return false;
-    m_map.remove(it);
-    return true;
-}
-
-} // namespace JSC
-
-#endif // WeakGCMap_h
-/*
- * 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. AND ITS CONTRIBUTORS ``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 ITS 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 WeakGCMap_h
-#define WeakGCMap_h
-
-#include <wtf/HashMap.h>
-
-namespace JSC {
-
-class JSCell;
-
-// A HashMap whose get() function returns emptyValue() for cells awaiting destruction.
-template<typename KeyType, typename MappedType>
-class WeakGCMap {
-    /*
-    Invariants:
-        * A value enters the WeakGCMap marked. (Guaranteed by set()).
-        * A value that becomes unmarked leaves the WeakGCMap before being recycled. (Guaranteed by the value's destructor removing it from the WeakGCMap.)
-        * A value that becomes unmarked leaves the WeakGCMap before becoming marked again. (Guaranteed by all destructors running before the mark phase begins.)
-        * During the mark phase, all values in the WeakGCMap are valid. (Guaranteed by all destructors running before the mark phase begins.)
-    */
-
-public:
-    typedef typename HashMap<KeyType, MappedType>::iterator iterator;
-    typedef typename HashMap<KeyType, MappedType>::const_iterator const_iterator;
-    
-    bool isEmpty() { return m_map.isEmpty(); }
-
-    MappedType get(const KeyType& key) const;
-    pair<iterator, bool> set(const KeyType&, const MappedType&); 
-    MappedType take(const KeyType& key);
-
-    // These unchecked functions provide access to a value even if the value's
-    // mark bit is not set. This is used, among other things, to retrieve values
-    // during the GC mark phase, which begins by clearing all mark bits.
-
-    MappedType uncheckedGet(const KeyType& key) const { return m_map.get(key); }
-    bool uncheckedRemove(const KeyType&, const MappedType&);
-
-    iterator uncheckedBegin() { return m_map.begin(); }
-    iterator uncheckedEnd() { return m_map.end(); }
-
-    const_iterator uncheckedBegin() const { return m_map.begin(); }
-    const_iterator uncheckedEnd() const { return m_map.end(); }
-
-private:
-    HashMap<KeyType, MappedType> m_map;
-};
-
-template<typename KeyType, typename MappedType>
-MappedType WeakGCMap<KeyType, MappedType>::get(const KeyType& key) const
-{
-    MappedType result = m_map.get(key);
-    if (!Heap::isCellMarked(result))
-        return HashTraits<MappedType>::emptyValue();
-    return result;
-}
-
-template<typename KeyType, typename MappedType>
-MappedType WeakGCMap<KeyType, MappedType>::take(const KeyType& key)
-{
-    MappedType result = m_map.take(key);
-    if (!Heap::isCellMarked(result))
-        return HashTraits<MappedType>::emptyValue();
-    return result;
-}
-
-template<typename KeyType, typename MappedType>
-pair<typename HashMap<KeyType, MappedType>::iterator, bool> WeakGCMap<KeyType, MappedType>::set(const KeyType& key, const MappedType& value)
-{
-    Heap::markCell(value); // If value is newly allocated, it's not marked, so mark it now.
-    pair<iterator, bool> result = m_map.add(key, value);
-    if (!result.second) { // pre-existing entry
-        result.second = !Heap::isCellMarked(result.first->second);
-        result.first->second = value;
-    }
-    return result;
-}
-
-template<typename KeyType, typename MappedType>
-bool WeakGCMap<KeyType, MappedType>::uncheckedRemove(const KeyType& key, const MappedType& value)
-{
-    iterator it = m_map.find(key);
-    if (it == m_map.end())
-        return false;
-    if (it->second != value)
-        return false;
-    m_map.remove(it);
-    return true;
-}
-
-} // namespace JSC
-
-#endif // WeakGCMap_h
diff --git a/JavaScriptCore/wtf/StdLibExtras.h b/JavaScriptCore/wtf/StdLibExtras.h
index 09436ab..dd90c85 100644
--- a/JavaScriptCore/wtf/StdLibExtras.h
+++ b/JavaScriptCore/wtf/StdLibExtras.h
@@ -69,14 +69,6 @@ namespace WTF {
         return u.to;
     }
 
-    // Returns a count of the number of bits set in 'bits'.
-    inline size_t bitCount(unsigned bits)
-    {
-        bits = bits - ((bits >> 1) & 0x55555555);
-        bits = (bits & 0x33333333) + ((bits >> 2) & 0x33333333);
-        return ((bits + (bits >> 4) & 0xF0F0F0F) * 0x1010101) >> 24;
-    }
-
 } // namespace WTF
 
 #endif
diff --git a/JavaScriptGlue/ChangeLog b/JavaScriptGlue/ChangeLog
index d786c6d..95cce28 100644
--- a/JavaScriptGlue/ChangeLog
+++ b/JavaScriptGlue/ChangeLog
@@ -1,13 +1,3 @@
-2009-12-11  Geoffrey Garen  <ggaren at apple.com>
-
-        Reviewed by Sam Weinig.
-        
-        Changed GC from mark-sweep to mark-allocate.
-        
-        * JavaScriptGlue.cpp:
-        (JSCollect): Updated for rename. Fixed a bug where JSGlue would not check
-        to avoid nested GC calls.
-
 2009-12-08  Dmitry Titov  <dimich at chromium.org>
 
         Rubber-stamped by David Levin.
diff --git a/JavaScriptGlue/JavaScriptGlue.cpp b/JavaScriptGlue/JavaScriptGlue.cpp
index e552f19..b4f26e9 100644
--- a/JavaScriptGlue/JavaScriptGlue.cpp
+++ b/JavaScriptGlue/JavaScriptGlue.cpp
@@ -339,9 +339,7 @@ void JSCollect()
     initializeThreading();
 
     JSLock lock(LockForReal);
-    Heap* heap = getThreadGlobalExecState()->heap();
-    if (!heap->isBusy())
-        heap->collectAllGarbage();
+    getThreadGlobalExecState()->heap()->collect();
 }
 
 /*
diff --git a/WebCore/ChangeLog b/WebCore/ChangeLog
index 514cd45..22fcd0f 100644
--- a/WebCore/ChangeLog
+++ b/WebCore/ChangeLog
@@ -1,9 +1,3 @@
-2009-12-11  Geoffrey Garen  <ggaren at apple.com>
-
-        Windows build fix: Removed an incorrect #ifdef.
-
-        * bindings/js/GCController.cpp:
-
 2009-12-11  Eric Roman  <eroman at chromium.org>
 
         Unreviewed build fix.
@@ -14,62 +8,6 @@
         (WebCore::ScriptController::anyPageIsProcessingUserGesture):
         * bindings/v8/ScriptController.h:
 
-2009-12-11  Geoffrey Garen  <ggaren at apple.com>
-
-        Reviewed by Sam Weinig.
-        
-        Changed GC from mark-sweep to mark-allocate.
-
-        * ForwardingHeaders/runtime/WeakGCMap.h: Added.
-        * bindings/js/GCController.cpp:
-        (WebCore::collect):
-        (WebCore::GCController::gcTimerFired):
-        (WebCore::GCController::garbageCollectNow): Updated for rename.
-
-        * bindings/js/JSDOMBinding.cpp:
-        (WebCore::removeWrappers):
-        (WebCore::hasCachedDOMObjectWrapperUnchecked):
-        (WebCore::hasCachedDOMObjectWrapper):
-        (WebCore::hasCachedDOMNodeWrapperUnchecked):
-        (WebCore::forgetDOMObject):
-        (WebCore::forgetDOMNode):
-        (WebCore::isObservableThroughDOM):
-        (WebCore::markDOMNodesForDocument):
-        (WebCore::markDOMObjectWrapper):
-        (WebCore::markDOMNodeWrapper):
-        * bindings/js/JSDOMBinding.h: Changed DOM wrapper maps to be WeakGCMaps.
-        Don't ASSERT that an item must be in the WeakGCMap when its destructor
-        runs, since it might have been overwritten in the map first.
-
-        * bindings/js/JSDocumentCustom.cpp:
-        (WebCore::toJS): Changed Document from a DOM object wrapper to a DOM node
-        wrapper, to simplify some code.
-
-        * bindings/js/JSInspectedObjectWrapper.cpp:
-        (WebCore::JSInspectedObjectWrapper::JSInspectedObjectWrapper):
-        (WebCore::JSInspectedObjectWrapper::~JSInspectedObjectWrapper):
-        * bindings/js/JSInspectorCallbackWrapper.cpp: Use a WeakGCMap for these
-        wrappers.
-
-        * bindings/js/JSNodeCustom.cpp:
-        (WebCore::JSNode::markChildren): Updated for WeakGCMap and Document using
-        a DOM node wrapper instead of a DOM object wrapper.
-
-        * bindings/js/JSSVGPODTypeWrapper.h:
-        (WebCore::JSSVGDynamicPODTypeWrapperCache::wrapperMap):
-        (WebCore::JSSVGDynamicPODTypeWrapperCache::lookupOrCreateWrapper):
-        (WebCore::JSSVGDynamicPODTypeWrapperCache::forgetWrapper):
-        (WebCore::::~JSSVGDynamicPODTypeWrapper): Shined a small beam of sanity
-        on this code. Use hashtable-based lookup in JSSVGPODTypeWrapper.h instead
-        of linear lookup through iteration, since that's what hashtables were
-        invented for. Make JSSVGPODTypeWrapper.h responsible for reomving itself
-        from the table, instead of its JS wrapper, to decouple these objects from
-        GC, and because these objects are refCounted, not solely owned by their
-        JS wrappers.
-
-        * bindings/scripts/CodeGeneratorJS.pm:
-        * dom/Document.h: Adopted changes above.
-
 2009-12-11  Dimitri Glazkov  <dglazkov at chromium.org>
 
         Unreviewed, build fix.
diff --git a/WebCore/ForwardingHeaders/runtime/WeakGCMap.h b/WebCore/ForwardingHeaders/runtime/WeakGCMap.h
deleted file mode 100644
index 89432a8..0000000
--- a/WebCore/ForwardingHeaders/runtime/WeakGCMap.h
+++ /dev/null
@@ -1,4 +0,0 @@
-#ifndef WebCore_FWD_WeakGCMap_h
-#define WebCore_FWD_WeakGCMap_h
-#include <JavaScriptCore/WeakGCMap.h>
-#endif
diff --git a/WebCore/bindings/js/GCController.cpp b/WebCore/bindings/js/GCController.cpp
index 3e5645f..59bcfa3 100644
--- a/WebCore/bindings/js/GCController.cpp
+++ b/WebCore/bindings/js/GCController.cpp
@@ -40,13 +40,17 @@ using namespace JSC;
 
 namespace WebCore {
 
+#if USE(PTHREADS)
+
 static void* collect(void*)
 {
     JSLock lock(SilenceAssertionsOnly);
-    JSDOMWindow::commonJSGlobalData()->heap.collectAllGarbage();
+    JSDOMWindow::commonJSGlobalData()->heap.collect();
     return 0;
 }
 
+#endif
+
 GCController& gcController()
 {
     DEFINE_STATIC_LOCAL(GCController, staticGCController, ());
@@ -66,12 +70,14 @@ void GCController::garbageCollectSoon()
 
 void GCController::gcTimerFired(Timer<GCController>*)
 {
-    collect(0);
+    JSLock lock(SilenceAssertionsOnly);
+    JSDOMWindow::commonJSGlobalData()->heap.collect();
 }
 
 void GCController::garbageCollectNow()
 {
-    collect(0);
+    JSLock lock(SilenceAssertionsOnly);
+    JSDOMWindow::commonJSGlobalData()->heap.collect();
 }
 
 void GCController::garbageCollectOnAlternateThreadForDebugging(bool waitUntilDone)
diff --git a/WebCore/bindings/js/JSDOMBinding.cpp b/WebCore/bindings/js/JSDOMBinding.cpp
index 6faea27..f12c779 100644
--- a/WebCore/bindings/js/JSDOMBinding.cpp
+++ b/WebCore/bindings/js/JSDOMBinding.cpp
@@ -134,15 +134,15 @@ static void removeWrapper(DOMObject* wrapper)
 
 static void removeWrappers(const JSWrapperCache& wrappers)
 {
-    JSWrapperCache::const_iterator wrappersEnd = wrappers.uncheckedEnd();
-    for (JSWrapperCache::const_iterator it = wrappers.uncheckedBegin(); it != wrappersEnd; ++it)
+    JSWrapperCache::const_iterator wrappersEnd = wrappers.end();
+    for (JSWrapperCache::const_iterator it = wrappers.begin(); it != wrappersEnd; ++it)
         removeWrapper(it->second);
 }
 
 static inline void removeWrappers(const DOMObjectWrapperMap& wrappers)
 {
-    DOMObjectWrapperMap::const_iterator wrappersEnd = wrappers.uncheckedEnd();
-    for (DOMObjectWrapperMap::const_iterator it = wrappers.uncheckedBegin(); it != wrappersEnd; ++it)
+    DOMObjectWrapperMap::const_iterator wrappersEnd = wrappers.end();
+    for (DOMObjectWrapperMap::const_iterator it = wrappers.begin(); it != wrappersEnd; ++it)
         removeWrapper(it->second);
 }
 
@@ -242,19 +242,10 @@ static inline DOMObjectWrapperMap& DOMObjectWrapperMapFor(JSC::ExecState* exec)
     return currentWorld(exec)->m_wrappers;
 }
 
-bool hasCachedDOMObjectWrapperUnchecked(JSGlobalData* globalData, void* objectHandle)
-{
-    for (JSGlobalDataWorldIterator worldIter(globalData); worldIter; ++worldIter) {
-        if (worldIter->m_wrappers.uncheckedGet(objectHandle))
-            return true;
-    }
-    return false;
-}
-
 bool hasCachedDOMObjectWrapper(JSGlobalData* globalData, void* objectHandle)
 {
     for (JSGlobalDataWorldIterator worldIter(globalData); worldIter; ++worldIter) {
-        if (worldIter->m_wrappers.get(objectHandle))
+        if (worldIter->m_wrappers.contains(objectHandle))
             return true;
     }
     return false;
@@ -271,14 +262,14 @@ void cacheDOMObjectWrapper(JSC::ExecState* exec, void* objectHandle, DOMObject*
     DOMObjectWrapperMapFor(exec).set(objectHandle, wrapper);
 }
 
-bool hasCachedDOMNodeWrapperUnchecked(Document* document, Node* node)
+bool hasCachedDOMNodeWrapper(Document* document, Node* node)
 {
     if (!document)
-        return hasCachedDOMObjectWrapperUnchecked(JSDOMWindow::commonJSGlobalData(), node);
+        return hasCachedDOMObjectWrapper(JSDOMWindow::commonJSGlobalData(), node);
 
     JSWrapperCacheMap& wrapperCacheMap = document->wrapperCacheMap();
     for (JSWrapperCacheMap::iterator iter = wrapperCacheMap.begin(); iter != wrapperCacheMap.end(); ++iter) {
-        if (iter->second->uncheckedGet(node))
+        if (iter->second->contains(node))
             return true;
     }
     return false;
@@ -295,13 +286,20 @@ void forgetDOMObject(DOMObject* wrapper, void* objectHandle)
 {
     JSC::JSGlobalData* globalData = Heap::heap(wrapper)->globalData();
     for (JSGlobalDataWorldIterator worldIter(globalData); worldIter; ++worldIter) {
-        if (worldIter->m_wrappers.uncheckedRemove(objectHandle, wrapper))
-            break;
+        DOMObjectWrapperMap& wrappers = worldIter->m_wrappers;
+        DOMObjectWrapperMap::iterator iter = wrappers.find(objectHandle);
+        if ((iter != wrappers.end()) && (iter->second == wrapper)) {
+            removeWrapper(wrapper);
+            wrappers.remove(iter);
+            return;
+        }
     }
-    removeWrapper(wrapper);
+
+    // If the world went away, it should have removed this wrapper from the set.
+    ASSERT(!wrapperSet().contains(wrapper));
 }
 
-void forgetDOMNode(JSNode* wrapper, Node* node, Document* document)
+void forgetDOMNode(DOMObject* wrapper, Node* node, Document* document)
 {
     if (!document) {
         forgetDOMObject(wrapper, node);
@@ -310,10 +308,17 @@ void forgetDOMNode(JSNode* wrapper, Node* node, Document* document)
 
     JSWrapperCacheMap& wrapperCacheMap = document->wrapperCacheMap();
     for (JSWrapperCacheMap::iterator wrappersIter = wrapperCacheMap.begin(); wrappersIter != wrapperCacheMap.end(); ++wrappersIter) {
-        if (wrappersIter->second->uncheckedRemove(node, wrapper))
-            break;
+        JSWrapperCache* wrappers = wrappersIter->second;
+        JSWrapperCache::iterator iter = wrappers->find(node);
+        if ((iter != wrappers->end()) && (iter->second == wrapper)) {
+            wrappers->remove(iter);
+            removeWrapper(wrapper);
+            return;
+        }
     }
-    removeWrapper(wrapper);
+
+    // If the world went away, it should have removed this wrapper from the set.
+    ASSERT(!wrapperSet().contains(wrapper));
 }
 
 void cacheDOMNodeWrapper(JSC::ExecState* exec, Document* document, Node* node, JSNode* wrapper)
@@ -374,14 +379,14 @@ static inline bool isObservableThroughDOM(JSNode* jsNode, DOMWrapperWorld* world
         // the custom markChildren functions rather than here.
         if (node->isElementNode()) {
             if (NamedNodeMap* attributes = static_cast<Element*>(node)->attributeMap()) {
-                if (DOMObject* wrapper = world->m_wrappers.uncheckedGet(attributes)) {
+                if (DOMObject* wrapper = world->m_wrappers.get(attributes)) {
                     if (wrapper->hasCustomProperties())
                         return true;
                 }
             }
             if (node->isStyledElement()) {
                 if (CSSMutableStyleDeclaration* style = static_cast<StyledElement*>(node)->inlineStyleDecl()) {
-                    if (DOMObject* wrapper = world->m_wrappers.uncheckedGet(style)) {
+                    if (DOMObject* wrapper = world->m_wrappers.get(style)) {
                         if (wrapper->hasCustomProperties())
                             return true;
                     }
@@ -389,7 +394,7 @@ static inline bool isObservableThroughDOM(JSNode* jsNode, DOMWrapperWorld* world
             }
             if (static_cast<Element*>(node)->hasTagName(canvasTag)) {
                 if (CanvasRenderingContext* context = static_cast<HTMLCanvasElement*>(node)->renderingContext()) {
-                    if (DOMObject* wrapper = world->m_wrappers.uncheckedGet(context)) {
+                    if (DOMObject* wrapper = world->m_wrappers.get(context)) {
                         if (wrapper->hasCustomProperties())
                             return true;
                     }
@@ -427,8 +432,8 @@ void markDOMNodesForDocument(MarkStack& markStack, Document* document)
         DOMWrapperWorld* world = wrappersIter->first;
         JSWrapperCache* nodeDict = wrappersIter->second;
 
-        JSWrapperCache::iterator nodeEnd = nodeDict->uncheckedEnd();
-        for (JSWrapperCache::iterator nodeIt = nodeDict->uncheckedBegin(); nodeIt != nodeEnd; ++nodeIt) {
+        JSWrapperCache::iterator nodeEnd = nodeDict->end();
+        for (JSWrapperCache::iterator nodeIt = nodeDict->begin(); nodeIt != nodeEnd; ++nodeIt) {
             JSNode* jsNode = nodeIt->second;
             if (isObservableThroughDOM(jsNode, world))
                 markStack.append(jsNode);
@@ -511,7 +516,7 @@ void markDOMObjectWrapper(MarkStack& markStack, JSGlobalData& globalData, void*
         return;
 
     for (JSGlobalDataWorldIterator worldIter(&globalData); worldIter; ++worldIter) {
-        if (DOMObject* wrapper = worldIter->m_wrappers.uncheckedGet(object))
+        if (DOMObject* wrapper = worldIter->m_wrappers.get(object))
             markStack.append(wrapper);
     }
 }
@@ -521,14 +526,14 @@ void markDOMNodeWrapper(MarkStack& markStack, Document* document, Node* node)
     if (document) {
         JSWrapperCacheMap& wrapperCacheMap = document->wrapperCacheMap();
         for (JSWrapperCacheMap::iterator iter = wrapperCacheMap.begin(); iter != wrapperCacheMap.end(); ++iter) {
-            if (JSNode* wrapper = iter->second->uncheckedGet(node))
+            if (JSNode* wrapper = iter->second->get(node))
                 markStack.append(wrapper);
         }
         return;
     }
 
     for (JSGlobalDataWorldIterator worldIter(JSDOMWindow::commonJSGlobalData()); worldIter; ++worldIter) {
-        if (DOMObject* wrapper = worldIter->m_wrappers.uncheckedGet(node))
+        if (DOMObject* wrapper = worldIter->m_wrappers.get(node))
             markStack.append(wrapper);
     }
 }
diff --git a/WebCore/bindings/js/JSDOMBinding.h b/WebCore/bindings/js/JSDOMBinding.h
index d0b6762..3982dad 100644
--- a/WebCore/bindings/js/JSDOMBinding.h
+++ b/WebCore/bindings/js/JSDOMBinding.h
@@ -23,10 +23,9 @@
 #define JSDOMBinding_h
 
 #include "JSDOMGlobalObject.h"
-#include "Document.h"
+#include "Document.h" // For DOMConstructorWithDocument
 #include <runtime/Completion.h>
 #include <runtime/Lookup.h>
-#include <runtime/WeakGCMap.h>
 #include <wtf/Noncopyable.h>
 
 namespace JSC {
@@ -140,7 +139,7 @@ namespace WebCore {
         }
     };
 
-    typedef JSC::WeakGCMap<void*, DOMObject*> DOMObjectWrapperMap;
+    typedef HashMap<void*, DOMObject*> DOMObjectWrapperMap;
 
     class DOMWrapperWorld : public RefCounted<DOMWrapperWorld> {
     public:
@@ -217,24 +216,22 @@ namespace WebCore {
         DOMWrapperWorld m_normalWorld;
     };
 
-    DOMObject* getCachedDOMObjectWrapper(JSC::ExecState*, void* objectHandle);
     bool hasCachedDOMObjectWrapper(JSC::JSGlobalData*, void* objectHandle);
+    DOMObject* getCachedDOMObjectWrapper(JSC::ExecState*, void* objectHandle);
     void cacheDOMObjectWrapper(JSC::ExecState*, void* objectHandle, DOMObject* wrapper);
-    void forgetDOMNode(JSNode* wrapper, Node* node, Document* document);
+    void forgetDOMNode(DOMObject* wrapper, Node* node, Document* document);
     void forgetDOMObject(DOMObject* wrapper, void* objectHandle);
 
+    bool hasCachedDOMNodeWrapper(Document*, Node*);
     JSNode* getCachedDOMNodeWrapper(JSC::ExecState*, Document*, Node*);
     void cacheDOMNodeWrapper(JSC::ExecState*, Document*, Node*, JSNode* wrapper);
     void forgetAllDOMNodesForDocument(Document*);
     void forgetWorldOfDOMNodesForDocument(Document*, DOMWrapperWorld*);
     void updateDOMNodeDocument(Node*, Document* oldDocument, Document* newDocument);
-
     void markDOMNodesForDocument(JSC::MarkStack&, Document*);
     void markActiveObjectsForContext(JSC::MarkStack&, JSC::JSGlobalData&, ScriptExecutionContext*);
     void markDOMObjectWrapper(JSC::MarkStack&, JSC::JSGlobalData& globalData, void* object);
     void markDOMNodeWrapper(JSC::MarkStack& markStack, Document* document, Node* node);
-    bool hasCachedDOMObjectWrapperUnchecked(JSC::JSGlobalData*, void* objectHandle);
-    bool hasCachedDOMNodeWrapperUnchecked(Document*, Node*);
 
     JSC::Structure* getCachedDOMStructure(JSDOMGlobalObject*, const JSC::ClassInfo*);
     JSC::Structure* cacheDOMStructure(JSDOMGlobalObject*, NonNullPassRefPtr<JSC::Structure>, const JSC::ClassInfo*);
diff --git a/WebCore/bindings/js/JSDocumentCustom.cpp b/WebCore/bindings/js/JSDocumentCustom.cpp
index 9366399..4aa6583 100644
--- a/WebCore/bindings/js/JSDocumentCustom.cpp
+++ b/WebCore/bindings/js/JSDocumentCustom.cpp
@@ -96,18 +96,18 @@ JSValue toJS(ExecState* exec, JSDOMGlobalObject* globalObject, Document* documen
     if (!document)
         return jsNull();
 
-    DOMObject* wrapper = getCachedDOMNodeWrapper(exec, document, document);
+    DOMObject* wrapper = getCachedDOMObjectWrapper(exec, document);
     if (wrapper)
         return wrapper;
 
     if (document->isHTMLDocument())
-        wrapper = CREATE_DOM_NODE_WRAPPER(exec, globalObject, HTMLDocument, document);
+        wrapper = CREATE_DOM_OBJECT_WRAPPER(exec, globalObject, HTMLDocument, document);
 #if ENABLE(SVG)
     else if (document->isSVGDocument())
-        wrapper = CREATE_DOM_NODE_WRAPPER(exec, globalObject, SVGDocument, document);
+        wrapper = CREATE_DOM_OBJECT_WRAPPER(exec, globalObject, SVGDocument, document);
 #endif
     else
-        wrapper = CREATE_DOM_NODE_WRAPPER(exec, globalObject, Document, document);
+        wrapper = CREATE_DOM_OBJECT_WRAPPER(exec, globalObject, Document, document);
 
     // Make sure the document is kept around by the window object, and works right with the
     // back/forward cache.
diff --git a/WebCore/bindings/js/JSInspectedObjectWrapper.cpp b/WebCore/bindings/js/JSInspectedObjectWrapper.cpp
index 60213b3..13f59b7 100644
--- a/WebCore/bindings/js/JSInspectedObjectWrapper.cpp
+++ b/WebCore/bindings/js/JSInspectedObjectWrapper.cpp
@@ -30,7 +30,6 @@
 
 #include "JSInspectorCallbackWrapper.h"
 #include <runtime/JSGlobalObject.h>
-#include <runtime/WeakGCMap.h>
 #include <wtf/StdLibExtras.h>
 
 using namespace JSC;
@@ -39,7 +38,7 @@ namespace WebCore {
 
 ASSERT_CLASS_FITS_IN_CELL(JSInspectedObjectWrapper);
 
-typedef WeakGCMap<JSObject*, JSInspectedObjectWrapper*> WrapperMap;
+typedef HashMap<JSObject*, JSInspectedObjectWrapper*> WrapperMap;
 typedef HashMap<JSGlobalObject*, WrapperMap*> GlobalObjectWrapperMap;
 
 static GlobalObjectWrapperMap& wrappers()
@@ -82,17 +81,17 @@ JSInspectedObjectWrapper::JSInspectedObjectWrapper(ExecState* unwrappedExec, JSO
         wrappers().set(unwrappedGlobalObject(), wrapperMap);
     }
 
-    pair<WrapperMap::iterator, bool> result = wrapperMap->set(unwrappedObject, this);
-    ASSERT(result.second);
-    UNUSED_PARAM(result);
+    ASSERT(!wrapperMap->contains(unwrappedObject));
+    wrapperMap->set(unwrappedObject, this);
 }
 
 JSInspectedObjectWrapper::~JSInspectedObjectWrapper()
 {
+    ASSERT(wrappers().contains(unwrappedGlobalObject()));
     WrapperMap* wrapperMap = wrappers().get(unwrappedGlobalObject());
-    ASSERT(wrapperMap);
 
-    wrapperMap->uncheckedRemove(unwrappedObject(), this);
+    ASSERT(wrapperMap->contains(unwrappedObject()));
+    wrapperMap->remove(unwrappedObject());
 
     if (wrapperMap->isEmpty()) {
         wrappers().remove(unwrappedGlobalObject());
diff --git a/WebCore/bindings/js/JSInspectorCallbackWrapper.cpp b/WebCore/bindings/js/JSInspectorCallbackWrapper.cpp
index 3a73fda..ff4fbb9 100644
--- a/WebCore/bindings/js/JSInspectorCallbackWrapper.cpp
+++ b/WebCore/bindings/js/JSInspectorCallbackWrapper.cpp
@@ -29,7 +29,6 @@
 #if ENABLE(INSPECTOR)
 
 #include "JSInspectedObjectWrapper.h"
-#include <runtime/Protect.h>
 #include <wtf/StdLibExtras.h>
 
 using namespace JSC;
diff --git a/WebCore/bindings/js/JSNodeCustom.cpp b/WebCore/bindings/js/JSNodeCustom.cpp
index 737430e..f375ae5 100644
--- a/WebCore/bindings/js/JSNodeCustom.cpp
+++ b/WebCore/bindings/js/JSNodeCustom.cpp
@@ -144,7 +144,7 @@ void JSNode::markChildren(MarkStack& markStack)
     // mark any other nodes.
     if (node->inDocument()) {
         if (Document* doc = node->ownerDocument())
-            markDOMNodeWrapper(markStack, doc, doc);
+            markDOMObjectWrapper(markStack, *Heap::heap(this)->globalData(), doc);
         return;
     }
 
@@ -154,7 +154,7 @@ void JSNode::markChildren(MarkStack& markStack)
     Node* outermostNodeWithWrapper = node;
     for (Node* current = m_impl.get(); current; current = current->parentNode()) {
         root = current;
-        if (hasCachedDOMNodeWrapperUnchecked(current->document(), current))
+        if (hasCachedDOMNodeWrapper(current->document(), current))
             outermostNodeWithWrapper = current;
     }
 
diff --git a/WebCore/bindings/js/JSSVGPODTypeWrapper.h b/WebCore/bindings/js/JSSVGPODTypeWrapper.h
index fea7a5f..51e4e9e 100644
--- a/WebCore/bindings/js/JSSVGPODTypeWrapper.h
+++ b/WebCore/bindings/js/JSSVGPODTypeWrapper.h
@@ -105,8 +105,6 @@ private:
         ASSERT(m_setter);
     }
 
-    virtual ~JSSVGDynamicPODTypeWrapper();
-
     // Update callbacks
     RefPtr<PODTypeCreator> m_creator;
     GetterMethod m_getter;
@@ -353,7 +351,6 @@ struct PODTypeWrapperCacheInfoTraits : WTF::GenericHashTraits<PODTypeWrapperCach
     }
 };
 
-// Used for dynamic read-write attributes
 template<typename PODType, typename PODTypeCreator>
 class JSSVGDynamicPODTypeWrapperCache {
 public:
@@ -365,41 +362,49 @@ public:
     typedef PODTypeWrapperCacheInfoTraits<PODType, PODTypeCreator> CacheInfoTraits;
 
     typedef JSSVGPODTypeWrapper<PODType> WrapperBase;
-    typedef JSSVGDynamicPODTypeWrapper<PODType, PODTypeCreator> Wrapper;
-    typedef HashMap<CacheInfo, Wrapper*, CacheInfoHash, CacheInfoTraits> WrapperMap;
+    typedef JSSVGDynamicPODTypeWrapper<PODType, PODTypeCreator> DynamicWrapper;
+    typedef HashMap<CacheInfo, DynamicWrapper*, CacheInfoHash, CacheInfoTraits> DynamicWrapperHashMap;
+    typedef typename DynamicWrapperHashMap::const_iterator DynamicWrapperHashMapIterator;
 
-    static WrapperMap& wrapperMap()
+    static DynamicWrapperHashMap& dynamicWrapperHashMap()
     {
-        DEFINE_STATIC_LOCAL(WrapperMap, s_wrapperMap, ());
-        return s_wrapperMap;
+        DEFINE_STATIC_LOCAL(DynamicWrapperHashMap, s_dynamicWrapperHashMap, ());
+        return s_dynamicWrapperHashMap;
     }
 
+    // Used for readwrite attributes only
     static PassRefPtr<WrapperBase> lookupOrCreateWrapper(PODTypeCreator* creator, GetterMethod getter, SetterMethod setter)
     {
+        DynamicWrapperHashMap& map(dynamicWrapperHashMap());
         CacheInfo info(creator, getter, setter);
-        pair<typename WrapperMap::iterator, bool> result = wrapperMap().add(info, 0);
-        if (!result.second) // pre-existing entry
-            return result.first->second;
 
-        RefPtr<Wrapper> wrapper = Wrapper::create(creator, getter, setter);
-        result.first->second = wrapper.get();
+        if (map.contains(info))
+            return map.get(info);
+
+        RefPtr<DynamicWrapper> wrapper = DynamicWrapper::create(creator, getter, setter);
+        map.set(info, wrapper.get());
         return wrapper.release();
     }
 
-    static void forgetWrapper(PODTypeCreator* creator, GetterMethod getter, SetterMethod setter)
+    static void forgetWrapper(WrapperBase* wrapper)
     {
-        CacheInfo info(creator, getter, setter);
-        wrapperMap().remove(info);
+        DynamicWrapperHashMap& map(dynamicWrapperHashMap());
+
+        DynamicWrapperHashMapIterator it = map.begin();
+        DynamicWrapperHashMapIterator end = map.end();
+
+        for (; it != end; ++it) {
+            if (it->second != wrapper)
+                continue;
+
+            // It's guaranteed that there's just one object we need to take care of.
+            map.remove(it->first);
+            break;
+        }
     }
 };
 
-template<typename PODType, typename PODTypeCreator>
-JSSVGDynamicPODTypeWrapper<PODType, PODTypeCreator>::~JSSVGDynamicPODTypeWrapper()
-{
-    JSSVGDynamicPODTypeWrapperCache<PODType, PODTypeCreator>::forgetWrapper(m_creator.get(), m_getter, m_setter);
-}
-
-} // namespace WebCore
+};
 
 #endif // ENABLE(SVG)
 #endif // JSSVGPODTypeWrapper_h
diff --git a/WebCore/bindings/scripts/CodeGeneratorJS.pm b/WebCore/bindings/scripts/CodeGeneratorJS.pm
index ca4b03c..6ccf739 100644
--- a/WebCore/bindings/scripts/CodeGeneratorJS.pm
+++ b/WebCore/bindings/scripts/CodeGeneratorJS.pm
@@ -566,7 +566,7 @@ sub GenerateHeader
     }
 
     # Destructor
-    push(@headerContent, "    virtual ~$className();\n") if (!$hasParent or $eventTarget or $interfaceName eq "DOMWindow");
+    push(@headerContent, "    virtual ~$className();\n") if (!$hasParent or $eventTarget or $interfaceName eq "Document" or $interfaceName eq "DOMWindow");
 
     # Prototype
     push(@headerContent, "    static JSC::JSObject* createPrototype(JSC::ExecState*, JSC::JSGlobalObject*);\n") unless ($dataNode->extendedAttributes->{"ExtendsDOMGlobalObject"});
@@ -1210,6 +1210,15 @@ sub GenerateImplementation
             if ($interfaceName eq "Node") {
                  push(@implContent, "    forgetDOMNode(this, impl(), impl()->document());\n");
             } else {
+                if ($podType) {
+                    my $animatedType = $implClassName;
+                    $animatedType =~ s/SVG/SVGAnimated/;
+
+                    # Special case for JSSVGNumber
+                    if ($codeGenerator->IsSVGAnimatedType($animatedType) and $podType ne "float") {
+                        push(@implContent, "    JSSVGDynamicPODTypeWrapperCache<$podType, $animatedType>::forgetWrapper(m_impl.get());\n");
+                    }
+                }
                 push(@implContent, "    forgetDOMObject(this, impl());\n");
             }
         }
@@ -1217,6 +1226,13 @@ sub GenerateImplementation
         push(@implContent, "}\n\n");
     }
 
+    # Document needs a special destructor because it's a special case for caching. It needs
+    # its own special handling rather than relying on the caching that Node normally does.
+    if ($interfaceName eq "Document") {
+        push(@implContent, "${className}::~$className()\n");
+        push(@implContent, "{\n    forgetDOMObject(this, static_cast<${implClassName}*>(impl()));\n}\n\n");
+    }
+
     if ($needsMarkChildren && !$dataNode->extendedAttributes->{"CustomMarkFunction"}) {
         push(@implContent, "void ${className}::markChildren(MarkStack& markStack)\n");
         push(@implContent, "{\n");
diff --git a/WebCore/dom/Document.h b/WebCore/dom/Document.h
index 7e8c5bd..0f108e9 100644
--- a/WebCore/dom/Document.h
+++ b/WebCore/dom/Document.h
@@ -35,7 +35,6 @@
 #include "DocumentMarker.h"
 #include "ScriptExecutionContext.h"
 #include "Timer.h"
-#include <runtime/WeakGCMap.h>
 #include <wtf/HashCountedSet.h>
 #include <wtf/OwnPtr.h>
 #include <wtf/PassOwnPtr.h>
@@ -830,7 +829,7 @@ public:
     virtual void scriptImported(unsigned long, const String&);
     virtual void postTask(PassOwnPtr<Task>); // Executes the task on context's thread asynchronously.
 
-    typedef JSC::WeakGCMap<WebCore::Node*, JSNode*> JSWrapperCache;
+    typedef HashMap<WebCore::Node*, JSNode*> JSWrapperCache;
     typedef HashMap<DOMWrapperWorld*, JSWrapperCache*> JSWrapperCacheMap;
     JSWrapperCacheMap& wrapperCacheMap() { return m_wrapperCacheMap; }
     JSWrapperCache* getWrapperCache(DOMWrapperWorld* world)

-- 
WebKit Debian packaging



More information about the Pkg-webkit-commits mailing list