Changeset 140194 in webkit
- Timestamp:
- Jan 18, 2013 12:38:10 PM (11 years ago)
- Location:
- trunk/Source
- Files:
-
- 15 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/Source/JavaScriptCore/API/JSWeakObjectMapRefPrivate.cpp
r139541 r140194 60 60 return; 61 61 ASSERT(obj->inherits(&JSCallbackObject<JSGlobalObject>::s_info) || obj->inherits(&JSCallbackObject<JSDestructibleObject>::s_info)); 62 map->map().set( exec->globalData(),key, obj);62 map->map().set(key, obj); 63 63 } 64 64 -
trunk/Source/JavaScriptCore/ChangeLog
r140186 r140194 1 2013-01-18 Geoffrey Garen <ggaren@apple.com> 2 3 Weak GC maps should be easier to use 4 https://bugs.webkit.org/show_bug.cgi?id=107312 5 6 Reviewed by Sam Weinig. 7 8 This patch changes WeakGCMap to not use a WeakImpl finalizer to remove 9 items from the map, and to instead have the map automatically remove 10 stale items itself upon insertion. This has a few advantages: 11 12 (1) WeakGCMap is now compatible with all the specializations you would 13 use for HashMap. 14 15 (2) There's no need for clients to write special finalization munging 16 functions. 17 18 (3) Clients can specify custom value finalizers if they like. 19 20 * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCoreExports.def: Def! 21 22 * API/JSWeakObjectMapRefPrivate.cpp: Setter no longer requires a global 23 data, since we've reduced interdependency. 24 25 * heap/Handle.h: No more need to forward declare, since we've reduced 26 interdependency. 27 28 * heap/Weak.h: 29 (Weak): Use explicit so we can assign directly to a weak map iterator 30 without ambiguity between Weak<T> and PassWeak<T>. 31 32 * runtime/Structure.cpp: 33 (JSC::StructureTransitionTable::add): See above. 34 35 * runtime/Structure.h: 36 (JSC): 37 * runtime/StructureTransitionTable.h: 38 (StructureTransitionTable): Bad code goes away, programmer happy. 39 40 * runtime/WeakGCMap.h: 41 (JSC): 42 (WeakGCMap): 43 (JSC::WeakGCMap::WeakGCMap): 44 (JSC::WeakGCMap::set): 45 (JSC::WeakGCMap::add): 46 (JSC::WeakGCMap::find): 47 (JSC::WeakGCMap::contains): 48 (JSC::WeakGCMap::gcMap): 49 (JSC::WeakGCMap::gcMapIfNeeded): Inherit from HashMap and override any 50 function that might observe a Weak<T> that has died, just enough to 51 make such items appear as if they are not in the table. 52 1 53 2013-01-18 Michael Saboff <msaboff@apple.com> 2 54 -
trunk/Source/JavaScriptCore/JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCoreExports.def
r139259 r140194 115 115 ?className@JSProxy@JSC@@KA?AVString@WTF@@PBVJSObject@2@@Z 116 116 ?clear@SourceProviderCache@JSC@@QAEXXZ 117 ?clearRareData@JSGlobalObject@JSC@@CAXPAVJSCell@2@@Z118 117 ?collate@Collator@WTF@@QBE?AW4Result@12@PB_WI0I@Z 119 118 ?collectAllGarbage@Heap@JSC@@QAEXXZ -
trunk/Source/JavaScriptCore/heap/Handle.h
r127191 r140194 44 44 template <> class Handle<JSValue>; 45 45 46 // Forward declare WeakGCMap47 template<typename KeyType, typename MappedType, typename FinalizerCallback, typename HashArg, typename KeyTraitsArg> class WeakGCMap;48 49 46 class HandleBase { 50 47 template <typename T> friend class Weak; 51 48 friend class HandleSet; 52 49 friend struct JSCallbackObjectData; 53 template <typename KeyType, typename MappedType, typename FinalizerCallback, typename HashArg, typename KeyTraitsArg> friend class WeakGCMap;54 50 55 51 public: -
trunk/Source/JavaScriptCore/heap/Weak.h
r134697 r140194 41 41 42 42 Weak(); 43 Weak(std::nullptr_t);44 Weak(GetType, WeakHandleOwner* = 0, void* context = 0);43 explicit Weak(std::nullptr_t); 44 explicit Weak(GetType, WeakHandleOwner* = 0, void* context = 0); 45 45 46 46 enum HashTableDeletedValueTag { HashTableDeletedValue }; -
trunk/Source/JavaScriptCore/runtime/Structure.cpp
r139491 r140194 102 102 // When either of the parameters are bitfields, the C++ compiler will try to bind them as lvalues, which is invalid. To work around this, use unary "+" to make the parameter an rvalue. 103 103 // See https://bugs.webkit.org/show_bug.cgi?id=59261 for more details 104 map()->set( globalData,make_pair(structure->m_nameInPrevious, +structure->m_attributesInPrevious), structure);104 map()->set(make_pair(structure->m_nameInPrevious, +structure->m_attributesInPrevious), structure); 105 105 } 106 106 -
trunk/Source/JavaScriptCore/runtime/Structure.h
r139541 r140194 528 528 } 529 529 530 inline StructureTransitionTable::Hash::Key StructureTransitionTable::keyForWeakGCMapFinalizer(void*, Structure* structure)531 {532 // Newer versions of the STL have an std::make_pair function that takes rvalue references.533 // When either of the parameters are bitfields, the C++ compiler will try to bind them as lvalues, which is invalid. To work around this, use unary "+" to make the parameter an rvalue.534 // See https://bugs.webkit.org/show_bug.cgi?id=59261 for more details.535 return Hash::Key(structure->m_nameInPrevious.get(), +structure->m_attributesInPrevious);536 }537 538 530 inline bool Structure::transitivelyTransitionedFrom(Structure* structureToFind) 539 531 { -
trunk/Source/JavaScriptCore/runtime/StructureTransitionTable.h
r133953 r140194 112 112 }; 113 113 114 struct WeakGCMapFinalizerCallback { 115 static void* finalizerContextFor(Hash::Key) 116 { 117 return 0; 118 } 119 120 static inline Hash::Key keyForFinalizer(void* context, Structure* structure) 121 { 122 return keyForWeakGCMapFinalizer(context, structure); 123 } 124 }; 125 126 typedef WeakGCMap<Hash::Key, Structure, WeakGCMapFinalizerCallback, Hash> TransitionMap; 127 128 static Hash::Key keyForWeakGCMapFinalizer(void* context, Structure*); 114 typedef WeakGCMap<Hash::Key, Structure, Hash> TransitionMap; 129 115 130 116 public: -
trunk/Source/JavaScriptCore/runtime/WeakGCMap.h
r130612 r140194 27 27 #define WeakGCMap_h 28 28 29 #include "Handle.h" 30 #include "JSGlobalData.h" 29 #include "Weak.h" 31 30 #include <wtf/HashMap.h> 32 31 33 32 namespace JSC { 34 33 35 // A HashMap for GC'd values that removes entries when the associated value 36 // dies. 37 template <typename KeyType, typename MappedType> struct DefaultWeakGCMapFinalizerCallback { 38 static void* finalizerContextFor(KeyType key) 39 { 40 return reinterpret_cast<void*>(key); 41 } 34 // A HashMap with Weak<JSCell> values, which automatically removes values once they're garbage collected. 42 35 43 static KeyType keyForFinalizer(void* context, typename HandleTypes<MappedType>::ExternalType) 44 { 45 return reinterpret_cast<KeyType>(context); 46 } 47 }; 48 49 template<typename KeyType, typename MappedType, typename FinalizerCallback = DefaultWeakGCMapFinalizerCallback<KeyType, MappedType>, typename HashArg = typename DefaultHash<KeyType>::Hash, typename KeyTraitsArg = HashTraits<KeyType> > 50 class WeakGCMap : private WeakHandleOwner { 51 WTF_MAKE_FAST_ALLOCATED; 52 WTF_MAKE_NONCOPYABLE(WeakGCMap); 53 54 typedef HashMap<KeyType, WeakImpl*, HashArg, KeyTraitsArg> MapType; 55 typedef typename HandleTypes<MappedType>::ExternalType ExternalType; 36 template<typename KeyArg, typename RawMappedArg, typename HashArg = typename DefaultHash<KeyArg>::Hash, 37 typename KeyTraitsArg = HashTraits<KeyArg> > 38 class WeakGCMap : public HashMap<KeyArg, Weak<RawMappedArg>, HashArg, KeyTraitsArg> { 39 typedef Weak<RawMappedArg> MappedType; 40 typedef HashMap<KeyArg, MappedType, HashArg, KeyTraitsArg> Base; 41 typedef WeakGCMap<KeyArg, RawMappedArg, HashArg, KeyTraitsArg> Self; 42 typedef HashTraits<MappedType> MappedTraits; 43 typedef typename MappedTraits::PassInType MappedPassInType; 56 44 57 45 public: 46 using typename Base::KeyType; 47 using typename Base::AddResult; 48 using typename Base::iterator; 49 using typename Base::const_iterator; 50 using Base::begin; 51 using Base::end; 52 using Base::size; 53 using Base::remove; 54 58 55 WeakGCMap() 56 : m_gcThreshold(minGCThreshold) 59 57 { 60 58 } 61 59 62 void clear()60 AddResult set(const KeyType& key, MappedPassInType value) 63 61 { 64 typename MapType::iterator end = m_map.end(); 65 for (typename MapType::iterator ptr = m_map.begin(); ptr != end; ++ptr) 66 WeakSet::deallocate(ptr->value); 67 m_map.clear(); 62 gcMapIfNeeded(); 63 return Base::set(key, value); 68 64 } 69 65 70 ExternalType get(const KeyType& key) const66 AddResult add(const KeyType& key, MappedPassInType value) 71 67 { 72 WeakImpl* impl = m_map.get(key); 73 if (!impl || impl->state() != WeakImpl::Live) 74 return ExternalType(); 75 return HandleTypes<MappedType>::getFromSlot(const_cast<JSValue*>(&impl->jsValue())); 68 gcMapIfNeeded(); 69 AddResult addResult = Base::add(key, value); 70 if (!addResult.isNewEntry && !addResult.iterator->value) { // Found a zombie value. 71 addResult.isNewEntry = true; 72 addResult.iterator->value = value; 73 } 74 return addResult; 76 75 } 77 76 78 void set(JSGlobalData& globalData, const KeyType& key, ExternalType value)77 iterator find(const KeyType& key) 79 78 { 80 ASSERT_UNUSED(globalData, globalData.apiLock().currentThreadIsHoldingLock());81 typename MapType::AddResult result = m_map.add(key, 0);82 if ( !result.isNewEntry)83 WeakSet::deallocate(result.iterator->value);84 re sult.iterator->value = WeakSet::allocate(value, this, FinalizerCallback::finalizerContextFor(key));79 iterator it = Base::find(key); 80 iterator end = Base::end(); 81 if (it != end && !it->value) // Found a zombie value. 82 return end; 83 return it; 85 84 } 86 85 87 void remove(const KeyType& key)86 const_iterator find(const KeyType& key) const 88 87 { 89 WeakImpl* impl = m_map.take(key); 90 if (!impl) 91 return; 92 WeakSet::deallocate(impl); 88 return const_cast<Self*>(this)->find(key); 93 89 } 94 90 95 ~WeakGCMap()91 template<typename T, typename HashTranslator> bool contains(const T& key) const 96 92 { 97 clear(); 98 } 99 100 private: 101 virtual void finalize(Handle<Unknown> handle, void* context) 102 { 103 WeakImpl* impl = m_map.take(FinalizerCallback::keyForFinalizer(context, HandleTypes<MappedType>::getFromSlot(handle.slot()))); 104 ASSERT(impl); 105 WeakSet::deallocate(impl); 93 return find(key) != end(); 106 94 } 107 95 108 MapType m_map; 96 private: 97 static const int minGCThreshold; 98 99 void gcMap() 100 { 101 Vector<KeyType, 4> zombies; 102 iterator end = this->end(); 103 for (iterator it = begin(); it != end; ++it) { 104 if (!it->value) 105 zombies.append(it->key); 106 } 107 for (size_t i = 0; i < zombies.size(); ++i) 108 remove(zombies[i]); 109 } 110 111 void gcMapIfNeeded() 112 { 113 if (size() < m_gcThreshold) 114 return; 115 116 gcMap(); 117 m_gcThreshold = std::max(minGCThreshold, size() * 2 - 1); 118 } 119 120 int m_gcThreshold; 109 121 }; 122 123 template<typename KeyArg, typename RawMappedArg, typename HashArg, typename KeyTraitsArg> 124 const int WeakGCMap<KeyArg, RawMappedArg, HashArg, KeyTraitsArg>::minGCThreshold = 3; 110 125 111 126 } // namespace JSC -
trunk/Source/WebCore/ChangeLog
r140193 r140194 1 2013-01-18 Geoffrey Garen <ggaren@apple.com> 2 3 Weak GC maps should be easier to use 4 https://bugs.webkit.org/show_bug.cgi?id=107312 5 6 Reviewed by Sam Weinig. 7 8 Since weak GC maps are so easy to use now, let's use them for the DOM 9 string cache. 10 11 * WebCore.exp.in: 12 * bindings/js/DOMWrapperWorld.cpp: 13 (WebCore): 14 (WebCore::DOMWrapperWorld::DOMWrapperWorld): 15 * bindings/js/DOMWrapperWorld.h: 16 (WebCore): 17 (WebCore::DOMWrapperWorld::globalData): 18 (DOMWrapperWorld): 19 * bindings/js/JSDOMBinding.cpp: 20 (WebCore): 21 * bindings/js/JSDOMBinding.h: 22 (WebCore): 23 (WebCore::jsStringWithCache): 24 1 25 2013-01-18 Tim Volodine <timvolodine@chromium.org> 2 26 -
trunk/Source/WebCore/WebCore.exp.in
r140105 r140194 688 688 __ZN7WebCore25computeViewportAttributesENS_17ViewportArgumentsEiiifNS_7IntSizeE 689 689 __ZN7WebCore25createCanonicalUUIDStringEv 690 __ZN7WebCore25jsStringWithCacheSlowCaseEPN3JSC9ExecStateERN3WTF7HashMapIPNS3_10StringImplENS0_4WeakINS0_8JSStringEEENS3_7PtrHashIS6_EENS3_10HashTraitsIS6_EENSC_IS9_EEEES6_691 690 __ZN7WebCore26NetscapePlugInStreamLoader6createEPNS_5FrameEPNS_32NetscapePlugInStreamLoaderClientERKNS_15ResourceRequestE 692 691 __ZN7WebCore26UserTypingGestureIndicator27processingUserTypingGestureEv -
trunk/Source/WebCore/bindings/js/DOMWrapperWorld.cpp
r118483 r140194 31 31 namespace WebCore { 32 32 33 void JSStringOwner::finalize(JSC::Handle<JSC::Unknown> handle, void* context)34 {35 JSString* jsString = jsCast<JSString*>(handle.get().asCell());36 StringImpl* stringImpl = static_cast<StringImpl*>(context);37 weakRemove(m_world->m_stringCache, stringImpl, jsString);38 }39 40 33 DOMWrapperWorld::DOMWrapperWorld(JSC::JSGlobalData* globalData, bool isNormal) 41 34 : m_globalData(globalData) 42 35 , m_isNormal(isNormal) 43 , m_stringWrapperOwner(this)44 36 { 45 37 JSGlobalData::ClientData* clientData = m_globalData->clientData; -
trunk/Source/WebCore/bindings/js/DOMWrapperWorld.h
r119341 r140194 35 35 36 36 typedef HashMap<void*, JSC::Weak<JSDOMWrapper> > DOMObjectWrapperMap; 37 typedef HashMap<StringImpl*, JSC::Weak<JSC::JSString>, PtrHash<StringImpl*> > JSStringCache; 38 39 class JSStringOwner : public JSC::WeakHandleOwner { 40 public: 41 JSStringOwner(DOMWrapperWorld*); 42 virtual void finalize(JSC::Handle<JSC::Unknown>, void* context); 43 44 private: 45 DOMWrapperWorld* m_world; 46 }; 47 48 inline JSStringOwner::JSStringOwner(DOMWrapperWorld* world) 49 : m_world(world) 50 { 51 } 37 typedef JSC::WeakGCMap<StringImpl*, JSC::JSString, PtrHash<StringImpl*> > JSStringCache; 52 38 53 39 class DOMWrapperWorld : public RefCounted<DOMWrapperWorld> { … … 73 59 74 60 JSC::JSGlobalData* globalData() const { return m_globalData; } 75 JSStringOwner* stringWrapperOwner() { return &m_stringWrapperOwner; }76 61 77 62 protected: … … 82 67 HashSet<ScriptController*> m_scriptControllersWithWindowShells; 83 68 bool m_isNormal; 84 JSStringOwner m_stringWrapperOwner;85 69 }; 86 70 -
trunk/Source/WebCore/bindings/js/JSDOMBinding.cpp
r135009 r140194 51 51 } 52 52 53 JSValue jsStringWithCacheSlowCase(ExecState* exec, JSStringCache& stringCache, StringImpl* stringImpl)54 {55 JSString* wrapper = JSC::jsString(exec, String(stringImpl));56 weakAdd(stringCache, stringImpl, PassWeak<JSString>(wrapper, currentWorld(exec)->stringWrapperOwner(), stringImpl));57 return wrapper;58 }59 60 53 JSValue jsStringOrNull(ExecState* exec, const String& s) 61 54 { -
trunk/Source/WebCore/bindings/js/JSDOMBinding.h
r139541 r140194 47 47 #include <wtf/Forward.h> 48 48 #include <wtf/Noncopyable.h> 49 #include <wtf/NullPtr.h> 49 50 #include <wtf/Vector.h> 50 51 … … 270 271 271 272 JSC::JSValue jsStringWithCache(JSC::ExecState*, const String&); 272 JSC::JSValue jsStringWithCacheSlowCase(JSC::ExecState*, JSStringCache&, StringImpl*);273 273 JSC::JSValue jsString(JSC::ExecState*, const KURL&); // empty if the URL is null 274 274 inline JSC::JSValue jsStringWithCache(JSC::ExecState* exec, const AtomicString& s) … … 504 504 505 505 JSStringCache& stringCache = currentWorld(exec)->m_stringCache; 506 if (JSC::JSString* string = stringCache.get(stringImpl))507 return string;508 509 return jsStringWithCacheSlowCase(exec, stringCache, stringImpl);506 JSStringCache::AddResult addResult = stringCache.add(stringImpl, nullptr); 507 if (addResult.isNewEntry) 508 addResult.iterator->value = JSC::jsString(exec, String(stringImpl)); 509 return JSC::JSValue(addResult.iterator->value.get()); 510 510 } 511 511
Note: See TracChangeset
for help on using the changeset viewer.