Ignore:
Timestamp:
Mar 4, 2015, 12:00:00 PM (10 years ago)
Author:
[email protected]
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.

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

File:
1 copied

Legend:

Unmodified
Added
Removed
  • trunk/Source/JavaScriptCore/runtime/WeakGCMapInlines.h

    r181008 r181010  
    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
Note: See TracChangeset for help on using the changeset viewer.