Changeset 181297 in webkit


Ignore:
Timestamp:
Mar 9, 2015 5:09:39 PM (9 years ago)
Author:
akling@apple.com
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.

Because the GC may now mutate WeakGCMap below object allocation, I've made it
so that the classic HashMap::add() optimization can't be used with WeakGCMap.
This caused intermittent test failures when originally landed due to having
an invalid iterator on the stack after add() inserted a new entry and we
proceeded to allocate the new object, triggering GC.

  • API/JSWeakObjectMapRefInternal.h:

(OpaqueJSWeakObjectMap::create):
(OpaqueJSWeakObjectMap::OpaqueJSWeakObjectMap):

  • API/JSWeakObjectMapRefPrivate.cpp:
  • API/JSWrapperMap.mm:

(-[JSWrapperMap initWithContext:]):
(-[JSWrapperMap jsWrapperForObject:]): Pass VM to WeakGCMap constructor.

  • JavaScriptCore.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/JSString.cpp:

(JSC::jsStringWithCacheSlowCase):

  • runtime/PrototypeMap.cpp:

(JSC::PrototypeMap::addPrototype):
(JSC::PrototypeMap::emptyObjectStructureForPrototype): Remove HashMap add()
optimization since it's not safe in the GC-managed WeakGCMap world.

  • 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.

Location:
trunk/Source
Files:
1 added
17 edited
1 copied

Legend:

Unmodified
Added
Removed
  • trunk/Source/JavaScriptCore/API/JSWeakObjectMapRefInternal.h

    r181214 r181297  
    4242struct OpaqueJSWeakObjectMap : public RefCounted<OpaqueJSWeakObjectMap> {
    4343public:
    44     static PassRefPtr<OpaqueJSWeakObjectMap> create(void* data, JSWeakMapDestroyedCallback callback)
     44    static Ref<OpaqueJSWeakObjectMap> create(JSC::VM& vm, void* data, JSWeakMapDestroyedCallback callback)
    4545    {
    46         return adoptRef(new OpaqueJSWeakObjectMap(data, callback));
     46        return adoptRef(*new OpaqueJSWeakObjectMap(vm, data, callback));
    4747    }
    4848
     
    5555
    5656private:
    57     OpaqueJSWeakObjectMap(void* data, JSWeakMapDestroyedCallback callback)
    58         : m_data(data)
     57    OpaqueJSWeakObjectMap(JSC::VM& vm, void* data, JSWeakMapDestroyedCallback callback)
     58        : m_map(vm)
     59        , m_data(data)
    5960        , m_callback(callback)
    6061    {
  • trunk/Source/JavaScriptCore/API/JSWeakObjectMapRefPrivate.cpp

    r181214 r181297  
    3333#include "JSCInlines.h"
    3434#include "Weak.h"
     35#include "WeakGCMapInlines.h"
    3536#include <wtf/HashMap.h>
    3637#include <wtf/text/StringHash.h>
     
    4748    ExecState* exec = toJS(context);
    4849    JSLockHolder locker(exec);
    49     RefPtr<OpaqueJSWeakObjectMap> map = OpaqueJSWeakObjectMap::create(privateData, callback);
     50    RefPtr<OpaqueJSWeakObjectMap> map = OpaqueJSWeakObjectMap::create(exec->vm(), privateData, callback);
    5051    exec->lexicalGlobalObject()->registerWeakMap(map.get());
    5152    return map.get();
  • trunk/Source/JavaScriptCore/API/JSWrapperMap.mm

    r181214 r181297  
    3838#import "ObjcRuntimeExtras.h"
    3939#import "WeakGCMap.h"
     40#import "WeakGCMapInlines.h"
    4041#import <wtf/HashSet.h>
    4142#import <wtf/TCSpinLock.h>
     
    547548    JSContext *m_context;
    548549    NSMutableDictionary *m_classMap;
    549     JSC::WeakGCMap<id, JSC::JSObject> m_cachedJSWrappers;
     550    std::unique_ptr<JSC::WeakGCMap<id, JSC::JSObject>> m_cachedJSWrappers;
    550551    NSMapTable *m_cachedObjCWrappers;
    551552}
     
    560561    NSPointerFunctionsOptions valueOptions = NSPointerFunctionsWeakMemory | NSPointerFunctionsObjectPersonality;
    561562    m_cachedObjCWrappers = [[NSMapTable alloc] initWithKeyOptions:keyOptions valueOptions:valueOptions capacity:0];
    562    
     563
     564    m_cachedJSWrappers = std::make_unique<JSC::WeakGCMap<id, JSC::JSObject>>(toJS([context JSGlobalContextRef])->vm());
     565
    563566    m_context = context;
    564567    m_classMap = [[NSMutableDictionary alloc] init];
     
    591594- (JSValue *)jsWrapperForObject:(id)object
    592595{
    593     JSC::JSObject* jsWrapper = m_cachedJSWrappers.get(object);
     596    JSC::JSObject* jsWrapper = m_cachedJSWrappers->get(object);
    594597    if (jsWrapper)
    595598        return [JSValue valueWithJSValueRef:toRef(jsWrapper) inContext:m_context];
     
    607610    // (2) A long lived object may rack up many JSValues. When the contexts are released these will unprotect the associated JavaScript objects,
    608611    //     but still, would probably nicer if we made it so that only one associated object was required, broadcasting object dealloc.
    609     m_cachedJSWrappers.set(object, jsWrapper);
     612    m_cachedJSWrappers->set(object, jsWrapper);
    610613    return [JSValue valueWithJSValueRef:toRef(jsWrapper) inContext:m_context];
    611614}
  • trunk/Source/JavaScriptCore/ChangeLog

    r181293 r181297  
     12015-03-09  Andreas Kling  <akling@apple.com>
     2
     3        Stale entries in WeakGCMaps are keeping tons of WeakBlocks alive unnecessarily.
     4        <https://webkit.org/b/142115>
     5        <rdar://problem/19992268>
     6
     7        Reviewed by Geoffrey Garen.
     8
     9        Prune stale entries from WeakGCMaps as part of every full garbage collection.
     10        This frees up tons of previously-stuck WeakBlocks that were only sitting around
     11        with finalized handles waiting to die.
     12
     13        Note that WeakGCMaps register/unregister themselves with the GC heap in their
     14        ctor/dtor, so creating one now requires passing the VM.
     15
     16        Average time spent in the PruningStaleEntriesFromWeakGCMaps GC phase appears
     17        to be between 0.01ms and 0.3ms, though I've seen a few longer ones at ~1.2ms.
     18        It seems somewhat excessive to do this on every Eden collection, so it's only
     19        doing work in full collections for now.
     20
     21        Because the GC may now mutate WeakGCMap below object allocation, I've made it
     22        so that the classic HashMap::add() optimization can't be used with WeakGCMap.
     23        This caused intermittent test failures when originally landed due to having
     24        an invalid iterator on the stack after add() inserted a new entry and we
     25        proceeded to allocate the new object, triggering GC.
     26
     27        * API/JSWeakObjectMapRefInternal.h:
     28        (OpaqueJSWeakObjectMap::create):
     29        (OpaqueJSWeakObjectMap::OpaqueJSWeakObjectMap):
     30        * API/JSWeakObjectMapRefPrivate.cpp:
     31        * API/JSWrapperMap.mm:
     32        (-[JSWrapperMap initWithContext:]):
     33        (-[JSWrapperMap jsWrapperForObject:]): Pass VM to WeakGCMap constructor.
     34
     35        * JavaScriptCore.xcodeproj/project.pbxproj: Add WeakGCMapInlines.h and make
     36        it project-private so WebCore clients can access it.
     37
     38        * heap/Heap.cpp:
     39        (JSC::Heap::collect):
     40        (JSC::Heap::pruneStaleEntriesFromWeakGCMaps): Added a new GC phase for pruning
     41        stale entries from WeakGCMaps. This is only executed during full collections.
     42
     43        * heap/Heap.h:
     44        * heap/HeapInlines.h:
     45        (JSC::Heap::registerWeakGCMap):
     46        (JSC::Heap::unregisterWeakGCMap): Added a mechanism for WeakGCMaps to register
     47        themselves with the Heap and provide a pruning callback.
     48
     49        * runtime/PrototypeMap.h:
     50        (JSC::PrototypeMap::PrototypeMap):
     51        * runtime/Structure.cpp:
     52        (JSC::StructureTransitionTable::add): Pass VM to WeakGCMap constructor.
     53
     54        * runtime/JSCInlines.h: Add "WeakGCMapInlines.h"
     55
     56        * runtime/JSGlobalObject.cpp: Include "WeakGCMapInlines.h" so this builds.
     57
     58        * runtime/JSString.cpp:
     59        (JSC::jsStringWithCacheSlowCase):
     60        * runtime/PrototypeMap.cpp:
     61        (JSC::PrototypeMap::addPrototype):
     62        (JSC::PrototypeMap::emptyObjectStructureForPrototype): Remove HashMap add()
     63        optimization since it's not safe in the GC-managed WeakGCMap world.
     64
     65        * runtime/VM.cpp:
     66        (JSC::VM::VM): Pass VM to WeakGCMap constructor.
     67
     68        * runtime/WeakGCMap.h:
     69        (JSC::WeakGCMap::set):
     70        (JSC::WeakGCMap::add):
     71        (JSC::WeakGCMap::WeakGCMap): Deleted.
     72        (JSC::WeakGCMap::gcMap): Deleted.
     73        (JSC::WeakGCMap::gcMapIfNeeded): Deleted.
     74        * runtime/WeakGCMapInlines.h: Added.
     75        (JSC::WeakGCMap::WeakGCMap):
     76        (JSC::WeakGCMap::~WeakGCMap):
     77        (JSC::WeakGCMap::pruneStaleEntries): Moved ctor, dtor and pruning callback
     78        to WeakGCMapInlines.h to fix interdependent header issues. Removed code that
     79        prunes WeakGCMap at certain growth milestones and instead rely on the GC
     80        callback for housekeeping.
     81
    1822015-03-09  Ryosuke Niwa  <rniwa@webkit.org>
    283
  • trunk/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj

    r181215 r181297  
    14341434                A7FCC26D17A0B6AA00786D1A /* FTLSwitchCase.h in Headers */ = {isa = PBXBuildFile; fileRef = A7FCC26C17A0B6AA00786D1A /* FTLSwitchCase.h */; settings = {ATTRIBUTES = (Private, ); }; };
    14351435                A8A4748E151A8306004123FF /* libWTF.a in Frameworks */ = {isa = PBXBuildFile; fileRef = A8A4748D151A8306004123FF /* libWTF.a */; };
     1436                AD86A93E1AA4D88D002FE77F /* WeakGCMapInlines.h in Headers */ = {isa = PBXBuildFile; fileRef = AD86A93D1AA4D87C002FE77F /* WeakGCMapInlines.h */; settings = {ATTRIBUTES = (Private, ); }; };
    14361437                ADDB1F6318D77DBE009B58A8 /* OpaqueRootSet.h in Headers */ = {isa = PBXBuildFile; fileRef = ADDB1F6218D77DB7009B58A8 /* OpaqueRootSet.h */; settings = {ATTRIBUTES = (Private, ); }; };
    14371438                ADE39FFF16DD144B0003CD4A /* PropertyTable.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AD1CF06816DCAB2D00B97123 /* PropertyTable.cpp */; };
     
    31543155                A8E894330CD0603F00367179 /* JSGlobalObject.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSGlobalObject.h; sourceTree = "<group>"; };
    31553156                AD1CF06816DCAB2D00B97123 /* PropertyTable.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = PropertyTable.cpp; sourceTree = "<group>"; };
     3157                AD86A93D1AA4D87C002FE77F /* WeakGCMapInlines.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WeakGCMapInlines.h; sourceTree = "<group>"; };
    31563158                ADDB1F6218D77DB7009B58A8 /* OpaqueRootSet.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OpaqueRootSet.h; sourceTree = "<group>"; };
    31573159                B59F89371891AD3300D5CCDC /* UnlinkedInstructionStream.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = UnlinkedInstructionStream.h; sourceTree = "<group>"; };
     
    46364638                                FED94F2D171E3E2300BE77A4 /* WatchdogMac.cpp */,
    46374639                                14BFCE6810CDB1FC00364CCE /* WeakGCMap.h */,
     4640                                AD86A93D1AA4D87C002FE77F /* WeakGCMapInlines.h */,
    46384641                                A7CA3ADD17DA41AE006538AF /* WeakMapConstructor.cpp */,
    46394642                                A7CA3ADE17DA41AE006538AF /* WeakMapConstructor.h */,
     
    55305533                                0F8023EA1613832B00A0BA45 /* ByValInfo.h in Headers */,
    55315534                                BC18C3ED0E16F5CD00B34460 /* CallData.h in Headers */,
     5535                                AD86A93E1AA4D88D002FE77F /* WeakGCMapInlines.h in Headers */,
    55325536                                1429D8DE0ED2205B00B89619 /* CallFrame.h in Headers */,
    55335537                                A7C1EAEF17987AB600299DB2 /* CallFrameInlines.h in Headers */,
  • trunk/Source/JavaScriptCore/heap/Heap.cpp

    r181215 r181297  
    10661066
    10671067    reapWeakHandles();
     1068    pruneStaleEntriesFromWeakGCMaps();
    10681069    sweepArrayBuffers();
    10691070    snapshotMarkedSpace();
     
    11771178    GCPHASE(ReapingWeakHandles);
    11781179    m_objectSpace.reapWeakSets();
     1180}
     1181
     1182void Heap::pruneStaleEntriesFromWeakGCMaps()
     1183{
     1184    GCPHASE(PruningStaleEntriesFromWeakGCMaps);
     1185    if (m_operationInProgress != FullCollection)
     1186        return;
     1187    for (auto& pruneCallback : m_weakGCMaps.values())
     1188        pruneCallback();
    11791189}
    11801190
  • trunk/Source/JavaScriptCore/heap/Heap.h

    r181215 r181297  
    227227
    228228    static bool isZombified(JSCell* cell) { return *(void**)cell == zombifiedBits; }
     229
     230    void registerWeakGCMap(void* weakGCMap, std::function<void()> pruningCallback);
     231    void unregisterWeakGCMap(void* weakGCMap);
    229232
    230233private:
     
    302305
    303306    void reapWeakHandles();
     307    void pruneStaleEntriesFromWeakGCMaps();
    304308    void sweepArrayBuffers();
    305309    void snapshotMarkedSpace();
     
    394398    unsigned m_delayedReleaseRecursionCount;
    395399#endif
     400
     401    HashMap<void*, std::function<void()>> m_weakGCMaps;
    396402};
    397403
  • trunk/Source/JavaScriptCore/heap/HeapInlines.h

    r181215 r181297  
    315315    return *m_markListSet;
    316316}
     317
     318inline void Heap::registerWeakGCMap(void* weakGCMap, std::function<void()> pruningCallback)
     319{
     320    m_weakGCMaps.add(weakGCMap, WTF::move(pruningCallback));
     321}
     322
     323inline void Heap::unregisterWeakGCMap(void* weakGCMap)
     324{
     325    m_weakGCMaps.remove(weakGCMap);
     326}
    317327   
    318328} // namespace JSC
  • trunk/Source/JavaScriptCore/runtime/JSCInlines.h

    r181214 r181297  
    5252#include "SlotVisitorInlines.h"
    5353#include "StructureInlines.h"
     54#include "WeakGCMapInlines.h"
    5455
    5556#endif // JSCInlines_h
  • trunk/Source/JavaScriptCore/runtime/JSGlobalObject.cpp

    r181214 r181297  
    124124#include "SymbolPrototype.h"
    125125#include "VariableWatchpointSetInlines.h"
     126#include "WeakGCMapInlines.h"
    126127#include "WeakMapConstructor.h"
    127128#include "WeakMapPrototype.h"
  • trunk/Source/JavaScriptCore/runtime/JSString.cpp

    r178928 r181297  
    438438JSString* jsStringWithCacheSlowCase(VM& vm, StringImpl& stringImpl)
    439439{
    440     auto addResult = vm.stringCache.add(&stringImpl, nullptr);
    441     if (addResult.isNewEntry)
    442         addResult.iterator->value = jsString(&vm, String(stringImpl));
    443     vm.lastCachedString.set(vm, addResult.iterator->value.get());
    444     return addResult.iterator->value.get();
     440    if (JSString* string = vm.stringCache.get(&stringImpl))
     441        return string;
     442
     443    JSString* string = jsString(&vm, String(stringImpl));
     444    vm.lastCachedString.set(vm, string);
     445    return string;
    445446}
    446447
  • trunk/Source/JavaScriptCore/runtime/PrototypeMap.cpp

    r163844 r181297  
    3434void PrototypeMap::addPrototype(JSObject* object)
    3535{
    36     m_prototypes.add(object, object);
     36    m_prototypes.set(object, object);
    3737
    3838    // Note that this method makes the somewhat odd decision to not check if this
     
    5555Structure* PrototypeMap::emptyObjectStructureForPrototype(JSObject* prototype, unsigned inlineCapacity)
    5656{
    57     StructureMap::AddResult addResult = m_structures.add(std::make_pair(prototype, inlineCapacity), nullptr);
    58     if (!addResult.isNewEntry) {
     57    auto key = std::make_pair(prototype, inlineCapacity);
     58    if (Structure* structure = m_structures.get(key)) {
    5959        ASSERT(isPrototype(prototype));
    60         return addResult.iterator->value.get();
     60        return structure;
    6161    }
    6262
     
    6464    Structure* structure = JSFinalObject::createStructure(
    6565        prototype->globalObject()->vm(), prototype->globalObject(), prototype, inlineCapacity);
    66     addResult.iterator->value = Weak<Structure>(structure);
     66    m_structures.set(key, Weak<Structure>(structure));
    6767    return structure;
    6868}
  • trunk/Source/JavaScriptCore/runtime/PrototypeMap.h

    r181214 r181297  
    3434class JSObject;
    3535class Structure;
     36class VM;
    3637
    3738// Tracks the canonical structure an object should be allocated with when inheriting from a given prototype.
    3839class PrototypeMap {
    3940public:
     41    explicit PrototypeMap(VM& vm)
     42        : m_prototypes(vm)
     43        , m_structures(vm)
     44    {
     45    }
     46
    4047    JS_EXPORT_PRIVATE Structure* emptyObjectStructureForPrototype(JSObject*, unsigned inlineCapacity);
    4148    void clearEmptyObjectStructureForPrototype(JSObject*, unsigned inlineCapacity);
  • trunk/Source/JavaScriptCore/runtime/Structure.cpp

    r181214 r181297  
    3737#include "StructureChain.h"
    3838#include "StructureRareDataInlines.h"
     39#include "WeakGCMapInlines.h"
    3940#include <wtf/CommaPrinter.h>
    4041#include <wtf/ProcessID.h>
     
    9192        // This handles the second transition being added
    9293        // (or the first transition being despecified!)
    93         setMap(new TransitionMap());
     94        setMap(new TransitionMap(vm));
    9495        add(vm, existingTransition);
    9596    }
  • trunk/Source/JavaScriptCore/runtime/VM.cpp

    r181214 r181297  
    8484#include "TypeProfilerLog.h"
    8585#include "UnlinkedCodeBlock.h"
     86#include "WeakGCMapInlines.h"
    8687#include "WeakMapData.h"
    8788#include <wtf/ProcessID.h>
     
    154155    , propertyNames(nullptr)
    155156    , emptyList(new MarkedArgumentBuffer)
     157    , stringCache(*this)
     158    , prototypeMap(*this)
    156159    , keywords(std::make_unique<Keywords>(*this))
    157160    , interpreter(0)
  • trunk/Source/JavaScriptCore/runtime/WeakGCMap.h

    r181214 r181297  
    11/*
    2  * Copyright (C) 2009 Apple Inc. All rights reserved.
     2 * Copyright (C) 2009, 2015 Apple Inc. All rights reserved.
    33 *
    44 * Redistribution and use in source and binary forms, with or without
     
    4848    typedef typename HashMapType::const_iterator const_iterator;
    4949
    50     WeakGCMap()
    51         : m_gcThreshold(minGCThreshold)
    52     {
    53     }
     50    explicit WeakGCMap(VM&);
     51    ~WeakGCMap();
    5452
    5553    ValueArg* get(const KeyType& key) const
     
    6058    AddResult set(const KeyType& key, ValueType value)
    6159    {
    62         gcMapIfNeeded();
    6360        return m_map.set(key, WTF::move(value));
    64     }
    65 
    66     ALWAYS_INLINE AddResult add(const KeyType& key, ValueType value)
    67     {
    68         gcMapIfNeeded();
    69         AddResult addResult = m_map.fastAdd(key, nullptr);
    70         if (!addResult.iterator->value) { // New value or found a zombie value.
    71             addResult.isNewEntry = true;
    72             addResult.iterator->value = WTF::move(value);
    73         }
    74         return addResult;
    7561    }
    7662
     
    10490    }
    10591
     92    void pruneStaleEntries();
     93
    10694private:
    107     static const int minGCThreshold = 3;
    108 
    109     NEVER_INLINE void gcMap()
    110     {
    111         Vector<KeyType, 4> zombies;
    112 
    113         for (iterator it = m_map.begin(), end = m_map.end(); it != end; ++it) {
    114             if (!it->value)
    115                 zombies.append(it->key);
    116         }
    117 
    118         for (size_t i = 0; i < zombies.size(); ++i)
    119             m_map.remove(zombies[i]);
    120     }
    121 
    122     void gcMapIfNeeded()
    123     {
    124         if (m_map.size() < m_gcThreshold)
    125             return;
    126 
    127         gcMap();
    128         m_gcThreshold = std::max(minGCThreshold, m_map.size() * 2 - 1);
    129     }
    130 
    13195    HashMapType m_map;
    132     int m_gcThreshold;
     96    VM& m_vm;
    13397};
    134 
    135 template<typename KeyArg, typename RawMappedArg, typename HashArg, typename KeyTraitsArg>
    136 const int WeakGCMap<KeyArg, RawMappedArg, HashArg, KeyTraitsArg>::minGCThreshold;
    13798
    13899} // namespace JSC
  • trunk/Source/JavaScriptCore/runtime/WeakGCMapInlines.h

    r181293 r181297  
    11/*
    2  * Copyright (C) 2010 Apple Inc. All rights reserved.
     2 * Copyright (C) 2015 Apple Inc. All rights reserved.
    33 *
    44 * Redistribution and use in source and binary forms, with or without
     
    2424 */
    2525
    26 #ifndef JSWeakObjectMapRefInternal_h
    27 #define JSWeakObjectMapRefInternal_h
     26#ifndef WeakGCMapInlines_h
     27#define WeakGCMapInlines_h
    2828
     29#include "HeapInlines.h"
    2930#include "WeakGCMap.h"
    30 #include <wtf/RefCounted.h>
    3131
    3232namespace JSC {
    3333
    34 class JSObject;
    35 
     34template<typename KeyArg, typename ValueArg, typename HashArg, typename KeyTraitsArg>
     35inline WeakGCMap<KeyArg, ValueArg, HashArg, KeyTraitsArg>::WeakGCMap(VM& vm)
     36    : m_vm(vm)
     37{
     38    vm.heap.registerWeakGCMap(this, [this]() {
     39        pruneStaleEntries();
     40    });
    3641}
    3742
    38 typedef void (*JSWeakMapDestroyedCallback)(struct OpaqueJSWeakObjectMap*, void*);
     43template<typename KeyArg, typename ValueArg, typename HashArg, typename KeyTraitsArg>
     44inline WeakGCMap<KeyArg, ValueArg, HashArg, KeyTraitsArg>::~WeakGCMap()
     45{
     46    m_vm.heap.unregisterWeakGCMap(this);
     47}
    3948
    40 typedef JSC::WeakGCMap<void*, JSC::JSObject> WeakMapType;
     49template<typename KeyArg, typename ValueArg, typename HashArg, typename KeyTraitsArg>
     50NEVER_INLINE void WeakGCMap<KeyArg, ValueArg, HashArg, KeyTraitsArg>::pruneStaleEntries()
     51{
     52    m_map.removeIf([](typename HashMapType::KeyValuePairType& entry) {
     53        return !entry.value;
     54    });
     55}
    4156
    42 struct OpaqueJSWeakObjectMap : public RefCounted<OpaqueJSWeakObjectMap> {
    43 public:
    44     static PassRefPtr<OpaqueJSWeakObjectMap> create(void* data, JSWeakMapDestroyedCallback callback)
    45     {
    46         return adoptRef(new OpaqueJSWeakObjectMap(data, callback));
    47     }
     57} // namespace JSC
    4858
    49     WeakMapType& map() { return m_map; }
    50    
    51     ~OpaqueJSWeakObjectMap()
    52     {
    53         m_callback(this, m_data);
    54     }
    55 
    56 private:
    57     OpaqueJSWeakObjectMap(void* data, JSWeakMapDestroyedCallback callback)
    58         : m_data(data)
    59         , m_callback(callback)
    60     {
    61     }
    62     WeakMapType m_map;
    63     void* m_data;
    64     JSWeakMapDestroyedCallback m_callback;
    65 };
    66 
    67 
    68 #endif // JSWeakObjectMapInternal_h
     59#endif // WeakGCMapInlines_h
  • trunk/Source/WebCore/bindings/js/ScriptCachedFrameData.cpp

    r181214 r181297  
    3939#include "PageConsoleClient.h"
    4040#include "PageGroup.h"
     41#include "ScriptController.h"
    4142#include <heap/StrongInlines.h>
    4243#include <profiler/Profile.h>
    4344#include <runtime/JSLock.h>
    44 #include "ScriptController.h"
     45#include <runtime/WeakGCMapInlines.h>
    4546
    4647using namespace JSC;
Note: See TracChangeset for help on using the changeset viewer.