Title: [181010] trunk/Source
Revision
181010
Author
[email protected]
Date
2015-03-04 12:00:00 -0800 (Wed, 04 Mar 2015)

Log Message

Stale entries in WeakGCMaps are keeping tons of WeakBlocks alive unnecessarily.
<https://webkit.org/b/142115>
<rdar://problem/19992268>

Reviewed by Geoffrey Garen.

Prune stale entries from WeakGCMaps as part of every full garbage collection.
This frees up tons of previously-stuck WeakBlocks that were only sitting around
with finalized handles waiting to die.

Note that WeakGCMaps register/unregister themselves with the GC heap in their
ctor/dtor, so creating one now requires passing the VM.

Average time spent in the PruningStaleEntriesFromWeakGCMaps GC phase appears
to be between 0.01ms and 0.3ms, though I've seen a few longer ones at ~1.2ms.
It seems somewhat excessive to do this on every Eden collection, so it's only
doing work in full collections for now.

* API/JSWeakObjectMapRefInternal.h:
(OpaqueJSWeakObjectMap::create):
(OpaqueJSWeakObjectMap::OpaqueJSWeakObjectMap):
* API/JSWeakObjectMapRefPrivate.cpp:
* API/JSWrapperMap.mm:
(-[JSWrapperMap initWithContext:]):
(-[JSWrapperMap jsWrapperForObject:]): Pass VM to WeakGCMap constructor.

* _javascript_Core.xcodeproj/project.pbxproj: Add WeakGCMapInlines.h and make
it project-private so WebCore clients can access it.

* heap/Heap.cpp:
(JSC::Heap::collect):
(JSC::Heap::pruneStaleEntriesFromWeakGCMaps): Added a new GC phase for pruning
stale entries from WeakGCMaps. This is only executed during full collections.

* heap/Heap.h:
* heap/HeapInlines.h:
(JSC::Heap::registerWeakGCMap):
(JSC::Heap::unregisterWeakGCMap): Added a mechanism for WeakGCMaps to register
themselves with the Heap and provide a pruning callback.

* runtime/PrototypeMap.h:
(JSC::PrototypeMap::PrototypeMap):
* runtime/Structure.cpp:
(JSC::StructureTransitionTable::add): Pass VM to WeakGCMap constructor.

* runtime/JSCInlines.h: Add "WeakGCMapInlines.h"

* runtime/JSGlobalObject.cpp: Include "WeakGCMapInlines.h" so this builds.

* runtime/VM.cpp:
(JSC::VM::VM): Pass VM to WeakGCMap constructor.

* runtime/WeakGCMap.h:
(JSC::WeakGCMap::set):
(JSC::WeakGCMap::add):
(JSC::WeakGCMap::WeakGCMap): Deleted.
(JSC::WeakGCMap::gcMap): Deleted.
(JSC::WeakGCMap::gcMapIfNeeded): Deleted.
* runtime/WeakGCMapInlines.h: Added.
(JSC::WeakGCMap::WeakGCMap):
(JSC::WeakGCMap::~WeakGCMap):
(JSC::WeakGCMap::pruneStaleEntries): Moved ctor, dtor and pruning callback
to WeakGCMapInlines.h to fix interdependent header issues. Removed code that
prunes WeakGCMap at certain growth milestones and instead rely on the GC
callback for housekeeping.

Modified Paths

Added Paths

Diff

Modified: trunk/Source/_javascript_Core/API/JSWeakObjectMapRefInternal.h (181009 => 181010)


--- trunk/Source/_javascript_Core/API/JSWeakObjectMapRefInternal.h	2015-03-04 19:56:39 UTC (rev 181009)
+++ trunk/Source/_javascript_Core/API/JSWeakObjectMapRefInternal.h	2015-03-04 20:00:00 UTC (rev 181010)
@@ -41,9 +41,9 @@
 
 struct OpaqueJSWeakObjectMap : public RefCounted<OpaqueJSWeakObjectMap> {
 public:
-    static PassRefPtr<OpaqueJSWeakObjectMap> create(void* data, JSWeakMapDestroyedCallback callback)
+    static Ref<OpaqueJSWeakObjectMap> create(JSC::VM& vm, void* data, JSWeakMapDestroyedCallback callback)
     {
-        return adoptRef(new OpaqueJSWeakObjectMap(data, callback));
+        return adoptRef(*new OpaqueJSWeakObjectMap(vm, data, callback));
     }
 
     WeakMapType& map() { return m_map; }
@@ -54,8 +54,9 @@
     }
 
 private:
-    OpaqueJSWeakObjectMap(void* data, JSWeakMapDestroyedCallback callback)
-        : m_data(data)
+    OpaqueJSWeakObjectMap(JSC::VM& vm, void* data, JSWeakMapDestroyedCallback callback)
+        : m_map(vm)
+        , m_data(data)
         , m_callback(callback)
     {
     }

Modified: trunk/Source/_javascript_Core/API/JSWeakObjectMapRefPrivate.cpp (181009 => 181010)


--- trunk/Source/_javascript_Core/API/JSWeakObjectMapRefPrivate.cpp	2015-03-04 19:56:39 UTC (rev 181009)
+++ trunk/Source/_javascript_Core/API/JSWeakObjectMapRefPrivate.cpp	2015-03-04 20:00:00 UTC (rev 181010)
@@ -32,6 +32,7 @@
 #include "JSWeakObjectMapRefInternal.h"
 #include "JSCInlines.h"
 #include "Weak.h"
+#include "WeakGCMapInlines.h"
 #include <wtf/HashMap.h>
 #include <wtf/text/StringHash.h>
 
@@ -46,7 +47,7 @@
 {
     ExecState* exec = toJS(context);
     JSLockHolder locker(exec);
-    RefPtr<OpaqueJSWeakObjectMap> map = OpaqueJSWeakObjectMap::create(privateData, callback);
+    RefPtr<OpaqueJSWeakObjectMap> map = OpaqueJSWeakObjectMap::create(exec->vm(), privateData, callback);
     exec->lexicalGlobalObject()->registerWeakMap(map.get());
     return map.get();
 }

Modified: trunk/Source/_javascript_Core/API/JSWrapperMap.mm (181009 => 181010)


--- trunk/Source/_javascript_Core/API/JSWrapperMap.mm	2015-03-04 19:56:39 UTC (rev 181009)
+++ trunk/Source/_javascript_Core/API/JSWrapperMap.mm	2015-03-04 20:00:00 UTC (rev 181010)
@@ -37,6 +37,7 @@
 #import "ObjCCallbackFunction.h"
 #import "ObjcRuntimeExtras.h"
 #import "WeakGCMap.h"
+#import "WeakGCMapInlines.h"
 #import <wtf/HashSet.h>
 #import <wtf/TCSpinLock.h>
 #import <wtf/Vector.h>
@@ -546,7 +547,7 @@
 @implementation JSWrapperMap {
     JSContext *m_context;
     NSMutableDictionary *m_classMap;
-    JSC::WeakGCMap<id, JSC::JSObject> m_cachedJSWrappers;
+    std::unique_ptr<JSC::WeakGCMap<id, JSC::JSObject>> m_cachedJSWrappers;
     NSMapTable *m_cachedObjCWrappers;
 }
 
@@ -559,7 +560,9 @@
     NSPointerFunctionsOptions keyOptions = NSPointerFunctionsOpaqueMemory | NSPointerFunctionsOpaquePersonality;
     NSPointerFunctionsOptions valueOptions = NSPointerFunctionsWeakMemory | NSPointerFunctionsObjectPersonality;
     m_cachedObjCWrappers = [[NSMapTable alloc] initWithKeyOptions:keyOptions valueOptions:valueOptions capacity:0];
-    
+
+    m_cachedJSWrappers = std::make_unique<JSC::WeakGCMap<id, JSC::JSObject>>(toJS([context JSGlobalContextRef])->vm());
+
     m_context = context;
     m_classMap = [[NSMutableDictionary alloc] init];
     return self;
@@ -590,7 +593,7 @@
 
 - (JSValue *)jsWrapperForObject:(id)object
 {
-    JSC::JSObject* jsWrapper = m_cachedJSWrappers.get(object);
+    JSC::JSObject* jsWrapper = m_cachedJSWrappers->get(object);
     if (jsWrapper)
         return [JSValue valueWithJSValueRef:toRef(jsWrapper) inContext:m_context];
 
@@ -606,7 +609,7 @@
     // (1) For immortal objects JSValues will effectively leak and this results in error output being logged - we should avoid adding associated objects to immortal objects.
     // (2) A long lived object may rack up many JSValues. When the contexts are released these will unprotect the associated _javascript_ objects,
     //     but still, would probably nicer if we made it so that only one associated object was required, broadcasting object dealloc.
-    m_cachedJSWrappers.set(object, jsWrapper);
+    m_cachedJSWrappers->set(object, jsWrapper);
     return [JSValue valueWithJSValueRef:toRef(jsWrapper) inContext:m_context];
 }
 

Modified: trunk/Source/_javascript_Core/ChangeLog (181009 => 181010)


--- trunk/Source/_javascript_Core/ChangeLog	2015-03-04 19:56:39 UTC (rev 181009)
+++ trunk/Source/_javascript_Core/ChangeLog	2015-03-04 20:00:00 UTC (rev 181010)
@@ -1,3 +1,71 @@
+2015-03-04  Andreas Kling  <[email protected]>
+
+        Stale entries in WeakGCMaps are keeping tons of WeakBlocks alive unnecessarily.
+        <https://webkit.org/b/142115>
+        <rdar://problem/19992268>
+
+        Reviewed by Geoffrey Garen.
+
+        Prune stale entries from WeakGCMaps as part of every full garbage collection.
+        This frees up tons of previously-stuck WeakBlocks that were only sitting around
+        with finalized handles waiting to die.
+
+        Note that WeakGCMaps register/unregister themselves with the GC heap in their
+        ctor/dtor, so creating one now requires passing the VM.
+
+        Average time spent in the PruningStaleEntriesFromWeakGCMaps GC phase appears
+        to be between 0.01ms and 0.3ms, though I've seen a few longer ones at ~1.2ms.
+        It seems somewhat excessive to do this on every Eden collection, so it's only
+        doing work in full collections for now.
+
+        * API/JSWeakObjectMapRefInternal.h:
+        (OpaqueJSWeakObjectMap::create):
+        (OpaqueJSWeakObjectMap::OpaqueJSWeakObjectMap):
+        * API/JSWeakObjectMapRefPrivate.cpp:
+        * API/JSWrapperMap.mm:
+        (-[JSWrapperMap initWithContext:]):
+        (-[JSWrapperMap jsWrapperForObject:]): Pass VM to WeakGCMap constructor.
+
+        * _javascript_Core.xcodeproj/project.pbxproj: Add WeakGCMapInlines.h and make
+        it project-private so WebCore clients can access it.
+
+        * heap/Heap.cpp:
+        (JSC::Heap::collect):
+        (JSC::Heap::pruneStaleEntriesFromWeakGCMaps): Added a new GC phase for pruning
+        stale entries from WeakGCMaps. This is only executed during full collections.
+
+        * heap/Heap.h:
+        * heap/HeapInlines.h:
+        (JSC::Heap::registerWeakGCMap):
+        (JSC::Heap::unregisterWeakGCMap): Added a mechanism for WeakGCMaps to register
+        themselves with the Heap and provide a pruning callback.
+
+        * runtime/PrototypeMap.h:
+        (JSC::PrototypeMap::PrototypeMap):
+        * runtime/Structure.cpp:
+        (JSC::StructureTransitionTable::add): Pass VM to WeakGCMap constructor.
+
+        * runtime/JSCInlines.h: Add "WeakGCMapInlines.h"
+
+        * runtime/JSGlobalObject.cpp: Include "WeakGCMapInlines.h" so this builds.
+
+        * runtime/VM.cpp:
+        (JSC::VM::VM): Pass VM to WeakGCMap constructor.
+
+        * runtime/WeakGCMap.h:
+        (JSC::WeakGCMap::set):
+        (JSC::WeakGCMap::add):
+        (JSC::WeakGCMap::WeakGCMap): Deleted.
+        (JSC::WeakGCMap::gcMap): Deleted.
+        (JSC::WeakGCMap::gcMapIfNeeded): Deleted.
+        * runtime/WeakGCMapInlines.h: Added.
+        (JSC::WeakGCMap::WeakGCMap):
+        (JSC::WeakGCMap::~WeakGCMap):
+        (JSC::WeakGCMap::pruneStaleEntries): Moved ctor, dtor and pruning callback
+        to WeakGCMapInlines.h to fix interdependent header issues. Removed code that
+        prunes WeakGCMap at certain growth milestones and instead rely on the GC
+        callback for housekeeping.
+
 2015-03-03  Filip Pizlo  <[email protected]>
 
         DFG IR should refer to FunctionExecutables directly and not via the CodeBlock

Modified: trunk/Source/_javascript_Core/_javascript_Core.xcodeproj/project.pbxproj (181009 => 181010)


--- trunk/Source/_javascript_Core/_javascript_Core.xcodeproj/project.pbxproj	2015-03-04 19:56:39 UTC (rev 181009)
+++ trunk/Source/_javascript_Core/_javascript_Core.xcodeproj/project.pbxproj	2015-03-04 20:00:00 UTC (rev 181010)
@@ -1427,6 +1427,7 @@
 		A7FB61001040C38B0017A286 /* PropertyDescriptor.h in Headers */ = {isa = PBXBuildFile; fileRef = A7FB604B103F5EAB0017A286 /* PropertyDescriptor.h */; settings = {ATTRIBUTES = (Private, ); }; };
 		A7FCC26D17A0B6AA00786D1A /* FTLSwitchCase.h in Headers */ = {isa = PBXBuildFile; fileRef = A7FCC26C17A0B6AA00786D1A /* FTLSwitchCase.h */; settings = {ATTRIBUTES = (Private, ); }; };
 		A8A4748E151A8306004123FF /* libWTF.a in Frameworks */ = {isa = PBXBuildFile; fileRef = A8A4748D151A8306004123FF /* libWTF.a */; };
+		AD86A93E1AA4D88D002FE77F /* WeakGCMapInlines.h in Headers */ = {isa = PBXBuildFile; fileRef = AD86A93D1AA4D87C002FE77F /* WeakGCMapInlines.h */; settings = {ATTRIBUTES = (Private, ); }; };
 		ADDB1F6318D77DBE009B58A8 /* OpaqueRootSet.h in Headers */ = {isa = PBXBuildFile; fileRef = ADDB1F6218D77DB7009B58A8 /* OpaqueRootSet.h */; settings = {ATTRIBUTES = (Private, ); }; };
 		ADE39FFF16DD144B0003CD4A /* PropertyTable.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AD1CF06816DCAB2D00B97123 /* PropertyTable.cpp */; };
 		B59F89391891F29F00D5CCDC /* UnlinkedInstructionStream.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B59F89381891ADB500D5CCDC /* UnlinkedInstructionStream.cpp */; };
@@ -3144,6 +3145,7 @@
 		A8E894310CD0602400367179 /* JSCallbackObjectFunctions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSCallbackObjectFunctions.h; sourceTree = "<group>"; };
 		A8E894330CD0603F00367179 /* JSGlobalObject.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSGlobalObject.h; sourceTree = "<group>"; };
 		AD1CF06816DCAB2D00B97123 /* PropertyTable.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = PropertyTable.cpp; sourceTree = "<group>"; };
+		AD86A93D1AA4D87C002FE77F /* WeakGCMapInlines.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WeakGCMapInlines.h; sourceTree = "<group>"; };
 		ADDB1F6218D77DB7009B58A8 /* OpaqueRootSet.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OpaqueRootSet.h; sourceTree = "<group>"; };
 		B59F89371891AD3300D5CCDC /* UnlinkedInstructionStream.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = UnlinkedInstructionStream.h; sourceTree = "<group>"; };
 		B59F89381891ADB500D5CCDC /* UnlinkedInstructionStream.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = UnlinkedInstructionStream.cpp; sourceTree = "<group>"; };
@@ -4626,6 +4628,7 @@
 				FED94F2C171E3E2300BE77A4 /* Watchdog.h */,
 				FED94F2D171E3E2300BE77A4 /* WatchdogMac.cpp */,
 				14BFCE6810CDB1FC00364CCE /* WeakGCMap.h */,
+				AD86A93D1AA4D87C002FE77F /* WeakGCMapInlines.h */,
 				A7CA3ADD17DA41AE006538AF /* WeakMapConstructor.cpp */,
 				A7CA3ADE17DA41AE006538AF /* WeakMapConstructor.h */,
 				A7CA3AE917DA5168006538AF /* WeakMapData.cpp */,
@@ -5521,6 +5524,7 @@
 				0F885E111849A3BE00F1E3FA /* BytecodeUseDef.h in Headers */,
 				0F8023EA1613832B00A0BA45 /* ByValInfo.h in Headers */,
 				BC18C3ED0E16F5CD00B34460 /* CallData.h in Headers */,
+				AD86A93E1AA4D88D002FE77F /* WeakGCMapInlines.h in Headers */,
 				1429D8DE0ED2205B00B89619 /* CallFrame.h in Headers */,
 				A7C1EAEF17987AB600299DB2 /* CallFrameInlines.h in Headers */,
 				95E3BC050E1AE68200B2D1C1 /* CallIdentifier.h in Headers */,

Modified: trunk/Source/_javascript_Core/heap/Heap.cpp (181009 => 181010)


--- trunk/Source/_javascript_Core/heap/Heap.cpp	2015-03-04 19:56:39 UTC (rev 181009)
+++ trunk/Source/_javascript_Core/heap/Heap.cpp	2015-03-04 20:00:00 UTC (rev 181010)
@@ -1060,6 +1060,7 @@
         vm()->typeProfiler()->invalidateTypeSetCache();
 
     reapWeakHandles();
+    pruneStaleEntriesFromWeakGCMaps();
     sweepArrayBuffers();
     snapshotMarkedSpace();
 
@@ -1173,6 +1174,15 @@
     m_objectSpace.reapWeakSets();
 }
 
+void Heap::pruneStaleEntriesFromWeakGCMaps()
+{
+    GCPHASE(PruningStaleEntriesFromWeakGCMaps);
+    if (m_operationInProgress != FullCollection)
+        return;
+    for (auto& pruneCallback : m_weakGCMaps.values())
+        pruneCallback();
+}
+
 void Heap::sweepArrayBuffers()
 {
     GCPHASE(SweepingArrayBuffers);

Modified: trunk/Source/_javascript_Core/heap/Heap.h (181009 => 181010)


--- trunk/Source/_javascript_Core/heap/Heap.h	2015-03-04 19:56:39 UTC (rev 181009)
+++ trunk/Source/_javascript_Core/heap/Heap.h	2015-03-04 20:00:00 UTC (rev 181010)
@@ -227,6 +227,9 @@
 
     static bool isZombified(JSCell* cell) { return *(void**)cell == zombifiedBits; }
 
+    void registerWeakGCMap(void* weakGCMap, std::function<void()> pruningCallback);
+    void unregisterWeakGCMap(void* weakGCMap);
+
 private:
     friend class CodeBlock;
     friend class CopiedBlock;
@@ -298,6 +301,7 @@
     void resetVisitors();
 
     void reapWeakHandles();
+    void pruneStaleEntriesFromWeakGCMaps();
     void sweepArrayBuffers();
     void snapshotMarkedSpace();
     void deleteSourceProviderCaches();
@@ -391,6 +395,8 @@
     Vector<RetainPtr<CFTypeRef>> m_delayedReleaseObjects;
     unsigned m_delayedReleaseRecursionCount;
 #endif
+
+    HashMap<void*, std::function<void()>> m_weakGCMaps;
 };
 
 } // namespace JSC

Modified: trunk/Source/_javascript_Core/heap/HeapInlines.h (181009 => 181010)


--- trunk/Source/_javascript_Core/heap/HeapInlines.h	2015-03-04 19:56:39 UTC (rev 181009)
+++ trunk/Source/_javascript_Core/heap/HeapInlines.h	2015-03-04 20:00:00 UTC (rev 181010)
@@ -289,6 +289,16 @@
         m_markListSet = std::make_unique<HashSet<MarkedArgumentBuffer*>>();
     return *m_markListSet;
 }
+
+inline void Heap::registerWeakGCMap(void* weakGCMap, std::function<void()> pruningCallback)
+{
+    m_weakGCMaps.add(weakGCMap, WTF::move(pruningCallback));
+}
+
+inline void Heap::unregisterWeakGCMap(void* weakGCMap)
+{
+    m_weakGCMaps.remove(weakGCMap);
+}
     
 } // namespace JSC
 

Modified: trunk/Source/_javascript_Core/runtime/JSCInlines.h (181009 => 181010)


--- trunk/Source/_javascript_Core/runtime/JSCInlines.h	2015-03-04 19:56:39 UTC (rev 181009)
+++ trunk/Source/_javascript_Core/runtime/JSCInlines.h	2015-03-04 20:00:00 UTC (rev 181010)
@@ -51,5 +51,6 @@
 #include "Operations.h"
 #include "SlotVisitorInlines.h"
 #include "StructureInlines.h"
+#include "WeakGCMapInlines.h"
 
 #endif // JSCInlines_h

Modified: trunk/Source/_javascript_Core/runtime/JSGlobalObject.cpp (181009 => 181010)


--- trunk/Source/_javascript_Core/runtime/JSGlobalObject.cpp	2015-03-04 19:56:39 UTC (rev 181009)
+++ trunk/Source/_javascript_Core/runtime/JSGlobalObject.cpp	2015-03-04 20:00:00 UTC (rev 181010)
@@ -120,6 +120,7 @@
 #include "SymbolConstructor.h"
 #include "SymbolPrototype.h"
 #include "VariableWatchpointSetInlines.h"
+#include "WeakGCMapInlines.h"
 #include "WeakMapConstructor.h"
 #include "WeakMapPrototype.h"
 

Modified: trunk/Source/_javascript_Core/runtime/PrototypeMap.h (181009 => 181010)


--- trunk/Source/_javascript_Core/runtime/PrototypeMap.h	2015-03-04 19:56:39 UTC (rev 181009)
+++ trunk/Source/_javascript_Core/runtime/PrototypeMap.h	2015-03-04 20:00:00 UTC (rev 181010)
@@ -33,10 +33,17 @@
 
 class JSObject;
 class Structure;
+class VM;
 
 // Tracks the canonical structure an object should be allocated with when inheriting from a given prototype.
 class PrototypeMap {
 public:
+    explicit PrototypeMap(VM& vm)
+        : m_prototypes(vm)
+        , m_structures(vm)
+    {
+    }
+
     JS_EXPORT_PRIVATE Structure* emptyObjectStructureForPrototype(JSObject*, unsigned inlineCapacity);
     void clearEmptyObjectStructureForPrototype(JSObject*, unsigned inlineCapacity);
     void addPrototype(JSObject*);

Modified: trunk/Source/_javascript_Core/runtime/Structure.cpp (181009 => 181010)


--- trunk/Source/_javascript_Core/runtime/Structure.cpp	2015-03-04 19:56:39 UTC (rev 181009)
+++ trunk/Source/_javascript_Core/runtime/Structure.cpp	2015-03-04 20:00:00 UTC (rev 181010)
@@ -36,6 +36,7 @@
 #include "PropertyNameArray.h"
 #include "StructureChain.h"
 #include "StructureRareDataInlines.h"
+#include "WeakGCMapInlines.h"
 #include <wtf/CommaPrinter.h>
 #include <wtf/ProcessID.h>
 #include <wtf/RefCountedLeakCounter.h>
@@ -90,7 +91,7 @@
 
         // This handles the second transition being added
         // (or the first transition being despecified!)
-        setMap(new TransitionMap());
+        setMap(new TransitionMap(vm));
         add(vm, existingTransition);
     }
 

Modified: trunk/Source/_javascript_Core/runtime/VM.cpp (181009 => 181010)


--- trunk/Source/_javascript_Core/runtime/VM.cpp	2015-03-04 19:56:39 UTC (rev 181009)
+++ trunk/Source/_javascript_Core/runtime/VM.cpp	2015-03-04 20:00:00 UTC (rev 181010)
@@ -83,6 +83,7 @@
 #include "TypeProfiler.h"
 #include "TypeProfilerLog.h"
 #include "UnlinkedCodeBlock.h"
+#include "WeakGCMapInlines.h"
 #include "WeakMapData.h"
 #include <wtf/ProcessID.h>
 #include <wtf/RetainPtr.h>
@@ -153,6 +154,8 @@
     , m_atomicStringTable(vmType == Default ? wtfThreadData().atomicStringTable() : new AtomicStringTable)
     , propertyNames(nullptr)
     , emptyList(new MarkedArgumentBuffer)
+    , stringCache(*this)
+    , prototypeMap(*this)
     , keywords(std::make_unique<Keywords>(*this))
     , interpreter(0)
     , jsArrayClassInfo(JSArray::info())

Modified: trunk/Source/_javascript_Core/runtime/WeakGCMap.h (181009 => 181010)


--- trunk/Source/_javascript_Core/runtime/WeakGCMap.h	2015-03-04 19:56:39 UTC (rev 181009)
+++ trunk/Source/_javascript_Core/runtime/WeakGCMap.h	2015-03-04 20:00:00 UTC (rev 181010)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2009 Apple Inc. All rights reserved.
+ * Copyright (C) 2009, 2015 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -47,10 +47,8 @@
     typedef typename HashMapType::iterator iterator;
     typedef typename HashMapType::const_iterator const_iterator;
 
-    WeakGCMap()
-        : m_gcThreshold(minGCThreshold)
-    {
-    }
+    explicit WeakGCMap(VM&);
+    ~WeakGCMap();
 
     ValueArg* get(const KeyType& key) const
     {
@@ -59,13 +57,11 @@
 
     AddResult set(const KeyType& key, ValueType value)
     {
-        gcMapIfNeeded();
         return m_map.set(key, WTF::move(value));
     }
 
     ALWAYS_INLINE AddResult add(const KeyType& key, ValueType value)
     {
-        gcMapIfNeeded();
         AddResult addResult = m_map.fastAdd(key, nullptr);
         if (!addResult.iterator->value) { // New value or found a zombie value.
             addResult.isNewEntry = true;
@@ -103,38 +99,13 @@
         return find(key) != m_map.end();
     }
 
-private:
-    static const int minGCThreshold = 3;
+    void pruneStaleEntries();
 
-    NEVER_INLINE void gcMap()
-    {
-        Vector<KeyType, 4> zombies;
-
-        for (iterator it = m_map.begin(), end = m_map.end(); it != end; ++it) {
-            if (!it->value)
-                zombies.append(it->key);
-        }
-
-        for (size_t i = 0; i < zombies.size(); ++i)
-            m_map.remove(zombies[i]);
-    }
-
-    void gcMapIfNeeded()
-    {
-        if (m_map.size() < m_gcThreshold)
-            return;
-
-        gcMap();
-        m_gcThreshold = std::max(minGCThreshold, m_map.size() * 2 - 1);
-    }
-
+private:
     HashMapType m_map;
-    int m_gcThreshold;
+    VM& m_vm;
 };
 
-template<typename KeyArg, typename RawMappedArg, typename HashArg, typename KeyTraitsArg>
-const int WeakGCMap<KeyArg, RawMappedArg, HashArg, KeyTraitsArg>::minGCThreshold;
-
 } // namespace JSC
 
 #endif // WeakGCMap_h

Copied: trunk/Source/_javascript_Core/runtime/WeakGCMapInlines.h (from rev 181008, trunk/Source/_javascript_Core/API/JSWeakObjectMapRefInternal.h) (0 => 181010)


--- trunk/Source/_javascript_Core/runtime/WeakGCMapInlines.h	                        (rev 0)
+++ trunk/Source/_javascript_Core/runtime/WeakGCMapInlines.h	2015-03-04 20:00:00 UTC (rev 181010)
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2015 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 WeakGCMapInlines_h
+#define WeakGCMapInlines_h
+
+#include "HeapInlines.h"
+#include "WeakGCMap.h"
+
+namespace JSC {
+
+template<typename KeyArg, typename ValueArg, typename HashArg, typename KeyTraitsArg>
+inline WeakGCMap<KeyArg, ValueArg, HashArg, KeyTraitsArg>::WeakGCMap(VM& vm)
+    : m_vm(vm)
+{
+    vm.heap.registerWeakGCMap(this, [this]() {
+        pruneStaleEntries();
+    });
+}
+
+template<typename KeyArg, typename ValueArg, typename HashArg, typename KeyTraitsArg>
+inline WeakGCMap<KeyArg, ValueArg, HashArg, KeyTraitsArg>::~WeakGCMap()
+{
+    m_vm.heap.unregisterWeakGCMap(this);
+}
+
+template<typename KeyArg, typename ValueArg, typename HashArg, typename KeyTraitsArg>
+NEVER_INLINE void WeakGCMap<KeyArg, ValueArg, HashArg, KeyTraitsArg>::pruneStaleEntries()
+{
+    m_map.removeIf([](typename HashMapType::KeyValuePairType& entry) {
+        return !entry.value;
+    });
+}
+
+} // namespace JSC
+
+#endif // WeakGCMapInlines_h

Added: trunk/Source/WebCore/ForwardingHeaders/runtime/WeakGCMapInlines.h (0 => 181010)


--- trunk/Source/WebCore/ForwardingHeaders/runtime/WeakGCMapInlines.h	                        (rev 0)
+++ trunk/Source/WebCore/ForwardingHeaders/runtime/WeakGCMapInlines.h	2015-03-04 20:00:00 UTC (rev 181010)
@@ -0,0 +1,4 @@
+#ifndef WebCore_FWD_WeakGCMapInlines_h
+#define WebCore_FWD_WeakGCMapInlines_h
+#include <_javascript_Core/WeakGCMapInlines.h>
+#endif

Modified: trunk/Source/WebCore/bindings/js/ScriptCachedFrameData.cpp (181009 => 181010)


--- trunk/Source/WebCore/bindings/js/ScriptCachedFrameData.cpp	2015-03-04 19:56:39 UTC (rev 181009)
+++ trunk/Source/WebCore/bindings/js/ScriptCachedFrameData.cpp	2015-03-04 20:00:00 UTC (rev 181010)
@@ -38,10 +38,11 @@
 #include "Page.h"
 #include "PageConsoleClient.h"
 #include "PageGroup.h"
+#include "ScriptController.h"
 #include <heap/StrongInlines.h>
 #include <profiler/Profile.h>
 #include <runtime/JSLock.h>
-#include "ScriptController.h"
+#include <runtime/WeakGCMapInlines.h>
 
 using namespace JSC;
 
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to