Changeset 256494 in webkit
- Timestamp:
- Feb 12, 2020 5:11:08 PM (4 years ago)
- Location:
- trunk/Source/WebCore
- Files:
-
- 11 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/Source/WebCore/ChangeLog
r256493 r256494 1 2020-02-12 Yusuke Suzuki <ysuzuki@apple.com> 2 3 CSSValuePool's constant CSS values should not be allocated dynamically (and same for Vectors) 4 https://bugs.webkit.org/show_bug.cgi?id=207666 5 6 Reviewed by Mark Lam. 7 8 r252785 changes contents (CSSValues and Vectors) of CSSValuePool from static ones to 9 dynamically allocated ones. This was done since we would like to use static CSSValues 10 even in the other threads (workers etc.) for OffscreenCanvas feature. 11 12 But this causes memory regression in Membuster since we allocates many CSSValues and 13 large Vectors, and they are kept persistently. 14 15 This patch removes dynamic allocation part of r252785 to recover memory regression. 16 The key of this patch is introducing Static CSSValue feature. When incrementing / decrementing 17 m_refCount of CSSValue, we add / subtract by 0x2. And we put 0x1 as a static-flag. So, even if 18 this CSSValue is used by multiple threads, we never see that CSSValue gets 0 m_refCount if 19 it is marked as static (having 0x1). This is the same design to our static StringImpl. 20 21 No behavior change. 22 23 * css/CSSInheritedValue.h: 24 * css/CSSInitialValue.h: 25 * css/CSSPrimitiveValue.cpp: 26 (WebCore::CSSPrimitiveValue::CSSPrimitiveValue): 27 * css/CSSPrimitiveValue.h: 28 * css/CSSRevertValue.h: 29 * css/CSSUnsetValue.h: 30 * css/CSSValue.cpp: 31 * css/CSSValue.h: 32 (WebCore::CSSValue::ref const): 33 (WebCore::CSSValue::hasOneRef const): 34 (WebCore::CSSValue::refCount const): 35 (WebCore::CSSValue::hasAtLeastOneRef const): 36 (WebCore::CSSValue::deref): 37 (WebCore::CSSValue::makeStatic): 38 * css/CSSValuePool.cpp: 39 (WebCore::StaticCSSValuePool::StaticCSSValuePool): 40 (WebCore::StaticCSSValuePool::init): 41 (WebCore::CSSValuePool::CSSValuePool): 42 (WebCore::CSSValuePool::singleton): 43 (WebCore::CSSValuePool::createIdentifierValue): 44 (WebCore::CSSValuePool::createColorValue): 45 (WebCore::CSSValuePool::createValue): 46 * css/CSSValuePool.h: 47 (WebCore::CSSValuePool::createInheritedValue): 48 (WebCore::CSSValuePool::createImplicitInitialValue): 49 (WebCore::CSSValuePool::createExplicitInitialValue): 50 (WebCore::CSSValuePool::createUnsetValue): 51 (WebCore::CSSValuePool::createRevertValue): 52 1 53 2020-02-12 Ryan Haddad <ryanhaddad@apple.com> 2 54 -
trunk/Source/WebCore/css/CSSInheritedValue.h
r252785 r256494 27 27 class CSSInheritedValue final : public CSSValue { 28 28 public: 29 static Ref<CSSInheritedValue> create() { return adoptRef(*new CSSInheritedValue()); }30 31 29 String customCSSText() const; 32 30 … … 34 32 35 33 private: 36 CSSInheritedValue() 34 friend LazyNeverDestroyed<CSSInheritedValue>; 35 CSSInheritedValue(StaticCSSValueTag) 37 36 : CSSValue(InheritedClass) 38 37 { 38 makeStatic(); 39 39 } 40 40 }; -
trunk/Source/WebCore/css/CSSInitialValue.h
r235986 r256494 27 27 class CSSInitialValue final : public CSSValue { 28 28 public: 29 static Ref<CSSInitialValue> createExplicit()30 {31 return adoptRef(*new CSSInitialValue(/* implicit */ false));32 }33 static Ref<CSSInitialValue> createImplicit()34 {35 return adoptRef(*new CSSInitialValue(/* implicit */ true));36 }37 38 29 String customCSSText() const; 39 30 … … 44 35 private: 45 36 friend LazyNeverDestroyed<CSSInitialValue>; 46 CSSInitialValue( bool implicit)37 CSSInitialValue(StaticCSSValueTag, bool implicit) 47 38 : CSSValue(InitialClass) 48 39 , m_isImplicit(implicit) 49 40 { 41 makeStatic(); 50 42 } 51 43 -
trunk/Source/WebCore/css/CSSPrimitiveValue.cpp
r255785 r256494 305 305 { 306 306 init(lengthSize, style); 307 } 308 309 CSSPrimitiveValue::CSSPrimitiveValue(StaticCSSValueTag, CSSValueID valueID) 310 : CSSPrimitiveValue(valueID) 311 { 312 makeStatic(); 313 } 314 315 CSSPrimitiveValue::CSSPrimitiveValue(StaticCSSValueTag, const Color& color) 316 : CSSPrimitiveValue(color) 317 { 318 makeStatic(); 319 } 320 321 CSSPrimitiveValue::CSSPrimitiveValue(StaticCSSValueTag, double num, CSSUnitType type) 322 : CSSPrimitiveValue(num, type) 323 { 324 makeStatic(); 307 325 } 308 326 -
trunk/Source/WebCore/css/CSSPrimitiveValue.h
r255785 r256494 219 219 CSSPrimitiveValue(double, CSSUnitType); 220 220 221 CSSPrimitiveValue(StaticCSSValueTag, CSSValueID); 222 CSSPrimitiveValue(StaticCSSValueTag, const Color&); 223 CSSPrimitiveValue(StaticCSSValueTag, double, CSSUnitType); 224 221 225 template<typename T> CSSPrimitiveValue(T); // Defined in CSSPrimitiveValueMappings.h 222 226 template<typename T> CSSPrimitiveValue(RefPtr<T>&&); -
trunk/Source/WebCore/css/CSSRevertValue.h
r252785 r256494 32 32 class CSSRevertValue final : public CSSValue { 33 33 public: 34 static Ref<CSSRevertValue> create() { return adoptRef(*new CSSRevertValue()); }35 36 34 String customCSSText() const; 37 35 … … 39 37 40 38 private: 41 CSSRevertValue() 39 friend LazyNeverDestroyed<CSSRevertValue>; 40 CSSRevertValue(StaticCSSValueTag) 42 41 : CSSValue(RevertClass) 43 42 { 43 makeStatic(); 44 44 } 45 45 }; -
trunk/Source/WebCore/css/CSSUnsetValue.h
r252785 r256494 32 32 class CSSUnsetValue final : public CSSValue { 33 33 public: 34 static Ref<CSSUnsetValue> create() { return adoptRef(*new CSSUnsetValue()); }35 36 34 String customCSSText() const; 37 35 … … 39 37 40 38 private: 41 CSSUnsetValue() 39 friend LazyNeverDestroyed<CSSUnsetValue>; 40 CSSUnsetValue(StaticCSSValueTag) 42 41 : CSSValue(UnsetClass) 43 42 { 43 makeStatic(); 44 44 } 45 45 }; -
trunk/Source/WebCore/css/CSSValue.cpp
r253987 r256494 75 75 namespace WebCore { 76 76 77 struct SameSizeAsCSSValue : public RefCounted<SameSizeAsCSSValue> { 77 struct SameSizeAsCSSValue { 78 uint32_t refCount; 78 79 uint32_t bitfields; 79 80 }; -
trunk/Source/WebCore/css/CSSValue.h
r253987 r256494 40 40 41 41 DECLARE_ALLOCATOR_WITH_HEAP_IDENTIFIER(CSSValue); 42 class CSSValue : public RefCounted<CSSValue> { 42 class CSSValue { 43 WTF_MAKE_NONCOPYABLE(CSSValue); 43 44 WTF_MAKE_FAST_ALLOCATED_WITH_HEAP_IDENTIFIER(CSSValue); 44 45 public: … … 53 54 }; 54 55 55 // Override RefCounted's deref() to ensure operator delete is called on 56 // the appropriate subclass type. 56 static constexpr unsigned refCountFlagIsStatic = 0x1; 57 static constexpr unsigned refCountIncrement = 0x2; // This allows us to ref / deref without disturbing the static CSSValue flag. 58 void ref() const 59 { 60 m_refCount += refCountIncrement; 61 } 62 bool hasOneRef() const { return m_refCount == refCountIncrement; } 63 unsigned refCount() const { return m_refCount / refCountIncrement; } 64 bool hasAtLeastOneRef() const { return m_refCount; } 65 57 66 void deref() 58 67 { 59 if (derefBase()) 68 // Customized deref() to ensure operator delete is called on 69 // the appropriate subclass type. 70 unsigned tempRefCount = m_refCount - refCountIncrement; 71 if (!tempRefCount) { 60 72 destroy(); 73 return; 74 } 75 m_refCount = tempRefCount; 61 76 } 62 77 … … 215 230 SlashSeparator 216 231 }; 232 enum StaticCSSValueTag { StaticCSSValue }; 217 233 218 234 protected: … … 228 244 } 229 245 246 void makeStatic() 247 { 248 m_refCount |= refCountFlagIsStatic; 249 } 250 230 251 // NOTE: This class is non-virtual for memory and performance reasons. 231 252 // Don't go making it virtual again unless you know exactly what you're doing! … … 236 257 WEBCORE_EXPORT void destroy(); 237 258 259 mutable unsigned m_refCount { refCountIncrement }; 238 260 protected: 239 261 // The bits in this section are only used by specific subclasses but kept here 240 262 // to maximize struct packing. 241 242 263 // CSSPrimitiveValue bits: 243 264 unsigned m_primitiveUnitType : 7; // CSSUnitType -
trunk/Source/WebCore/css/CSSValuePool.cpp
r254703 r256494 35 35 namespace WebCore { 36 36 37 LazyNeverDestroyed<StaticCSSValuePool> staticCSSValuePool; 38 39 StaticCSSValuePool::StaticCSSValuePool() 40 { 41 m_inheritedValue.construct(CSSValue::StaticCSSValue); 42 m_implicitInitialValue.construct(CSSValue::StaticCSSValue, true); 43 m_explicitInitialValue.construct(CSSValue::StaticCSSValue, false); 44 m_unsetValue.construct(CSSValue::StaticCSSValue); 45 m_revertValue.construct(CSSValue::StaticCSSValue); 46 47 m_transparentColor.construct(CSSValue::StaticCSSValue, Color(Color::transparent)); 48 m_whiteColor.construct(CSSValue::StaticCSSValue, Color(Color::white)); 49 m_blackColor.construct(CSSValue::StaticCSSValue, Color(Color::black)); 50 51 for (unsigned i = firstCSSValueKeyword; i <= lastCSSValueKeyword; ++i) 52 m_identifierValues[i].construct(CSSValue::StaticCSSValue, static_cast<CSSValueID>(i)); 53 54 for (unsigned i = 0; i < (maximumCacheableIntegerValue + 1); ++i) { 55 m_pixelValues[i].construct(CSSValue::StaticCSSValue, i, CSSUnitType::CSS_PX); 56 m_percentValues[i].construct(CSSValue::StaticCSSValue, i, CSSUnitType::CSS_PERCENTAGE); 57 m_numberValues[i].construct(CSSValue::StaticCSSValue, i, CSSUnitType::CSS_NUMBER); 58 } 59 } 60 61 void StaticCSSValuePool::init() 62 { 63 static std::once_flag onceKey; 64 std::call_once(onceKey, []() { 65 staticCSSValuePool.construct(); 66 }); 67 } 68 69 CSSValuePool::CSSValuePool() 70 { 71 StaticCSSValuePool::init(); 72 } 73 37 74 CSSValuePool& CSSValuePool::singleton() 38 75 { … … 42 79 } 43 80 44 CSSValuePool::CSSValuePool()45 : m_inheritedValue(CSSInheritedValue::create())46 , m_implicitInitialValue(CSSInitialValue::createImplicit())47 , m_explicitInitialValue(CSSInitialValue::createExplicit())48 , m_unsetValue(CSSUnsetValue::create())49 , m_revertValue(CSSRevertValue::create())50 , m_transparentColor(CSSPrimitiveValue::create(Color(Color::transparent)))51 , m_whiteColor(CSSPrimitiveValue::create(Color(Color::white)))52 , m_blackColor(CSSPrimitiveValue::create(Color(Color::black)))53 {54 m_identifierValues.reserveInitialCapacity(numCSSValueKeywords);55 for (unsigned i = 0; i < numCSSValueKeywords; ++i)56 m_identifierValues.uncheckedAppend(CSSPrimitiveValue::create(static_cast<CSSValueID>(i)));57 58 m_pixelValues.reserveInitialCapacity(maximumCacheableIntegerValue + 1);59 m_percentValues.reserveInitialCapacity(maximumCacheableIntegerValue + 1);60 m_numberValues.reserveInitialCapacity(maximumCacheableIntegerValue + 1);61 for (unsigned i = 0; i < (maximumCacheableIntegerValue + 1); ++i) {62 m_pixelValues.uncheckedAppend(CSSPrimitiveValue::create(i, CSSUnitType::CSS_PX));63 m_percentValues.uncheckedAppend(CSSPrimitiveValue::create(i, CSSUnitType::CSS_PERCENTAGE));64 m_numberValues.uncheckedAppend(CSSPrimitiveValue::create(i, CSSUnitType::CSS_NUMBER));65 }66 }67 68 81 Ref<CSSPrimitiveValue> CSSValuePool::createIdentifierValue(CSSValueID ident) 69 82 { 70 83 RELEASE_ASSERT(ident >= firstCSSValueKeyword && ident <= lastCSSValueKeyword); 71 return m_identifierValues[ident].get();84 return staticCSSValuePool->m_identifierValues[ident].get(); 72 85 } 73 86 … … 81 94 // These are the empty and deleted values of the hash table. 82 95 if (color == Color::transparent) 83 return m_transparentColor.get();96 return staticCSSValuePool->m_transparentColor.get(); 84 97 if (color == Color::white) 85 return m_whiteColor.get();98 return staticCSSValuePool->m_whiteColor.get(); 86 99 // Just because it is common. 87 100 if (color == Color::black) 88 return m_blackColor.get();101 return staticCSSValuePool->m_blackColor.get(); 89 102 90 103 // Remove one entry at random if the cache grows too large. … … 103 116 ASSERT(std::isfinite(value)); 104 117 105 if (value < 0 || value > maximumCacheableIntegerValue)118 if (value < 0 || value > StaticCSSValuePool::maximumCacheableIntegerValue) 106 119 return CSSPrimitiveValue::create(value, type); 107 120 … … 112 125 switch (type) { 113 126 case CSSUnitType::CSS_PX: 114 return m_pixelValues[intValue].get();127 return staticCSSValuePool->m_pixelValues[intValue].get(); 115 128 case CSSUnitType::CSS_PERCENTAGE: 116 return m_percentValues[intValue].get();129 return staticCSSValuePool->m_percentValues[intValue].get(); 117 130 case CSSUnitType::CSS_NUMBER: 118 return m_numberValues[intValue].get();131 return staticCSSValuePool->m_numberValues[intValue].get(); 119 132 default: 120 133 return CSSPrimitiveValue::create(value, type); -
trunk/Source/WebCore/css/CSSValuePool.h
r252785 r256494 38 38 #include <wtf/NeverDestroyed.h> 39 39 #include <wtf/RefPtr.h> 40 #include <wtf/Vector.h>41 40 #include <wtf/text/AtomStringHash.h> 42 41 … … 44 43 45 44 class CSSValueList; 45 class CSSValuePool; 46 46 47 47 enum class FromSystemFontID { No, Yes }; 48 49 class StaticCSSValuePool { 50 friend class CSSValuePool; 51 friend class LazyNeverDestroyed<StaticCSSValuePool>; 52 public: 53 static void init(); 54 55 private: 56 StaticCSSValuePool(); 57 58 LazyNeverDestroyed<CSSInheritedValue> m_inheritedValue; 59 LazyNeverDestroyed<CSSInitialValue> m_implicitInitialValue; 60 LazyNeverDestroyed<CSSInitialValue> m_explicitInitialValue; 61 LazyNeverDestroyed<CSSUnsetValue> m_unsetValue; 62 LazyNeverDestroyed<CSSRevertValue> m_revertValue; 63 64 LazyNeverDestroyed<CSSPrimitiveValue> m_transparentColor; 65 LazyNeverDestroyed<CSSPrimitiveValue> m_whiteColor; 66 LazyNeverDestroyed<CSSPrimitiveValue> m_blackColor; 67 68 static constexpr int maximumCacheableIntegerValue = 255; 69 70 LazyNeverDestroyed<CSSPrimitiveValue> m_pixelValues[maximumCacheableIntegerValue + 1]; 71 LazyNeverDestroyed<CSSPrimitiveValue> m_percentValues[maximumCacheableIntegerValue + 1]; 72 LazyNeverDestroyed<CSSPrimitiveValue> m_numberValues[maximumCacheableIntegerValue + 1]; 73 LazyNeverDestroyed<CSSPrimitiveValue> m_identifierValues[numCSSValueKeywords]; 74 }; 75 76 WEBCORE_EXPORT extern LazyNeverDestroyed<StaticCSSValuePool> staticCSSValuePool; 48 77 49 78 class CSSValuePool { … … 56 85 RefPtr<CSSValueList> createFontFaceValue(const AtomString&); 57 86 Ref<CSSPrimitiveValue> createFontFamilyValue(const String&, FromSystemFontID = FromSystemFontID::No); 58 Ref<CSSInheritedValue> createInheritedValue() { return m_inheritedValue.get(); }59 Ref<CSSInitialValue> createImplicitInitialValue() { return m_implicitInitialValue.get(); }60 Ref<CSSInitialValue> createExplicitInitialValue() { return m_explicitInitialValue.get(); }61 Ref<CSSUnsetValue> createUnsetValue() { return m_unsetValue.get(); }62 Ref<CSSRevertValue> createRevertValue() { return m_revertValue.get(); }87 Ref<CSSInheritedValue> createInheritedValue() { return staticCSSValuePool->m_inheritedValue.get(); } 88 Ref<CSSInitialValue> createImplicitInitialValue() { return staticCSSValuePool->m_implicitInitialValue.get(); } 89 Ref<CSSInitialValue> createExplicitInitialValue() { return staticCSSValuePool->m_explicitInitialValue.get(); } 90 Ref<CSSUnsetValue> createUnsetValue() { return staticCSSValuePool->m_unsetValue.get(); } 91 Ref<CSSRevertValue> createRevertValue() { return staticCSSValuePool->m_revertValue.get(); } 63 92 Ref<CSSPrimitiveValue> createIdentifierValue(CSSValueID identifier); 64 93 Ref<CSSPrimitiveValue> createIdentifierValue(CSSPropertyID identifier); … … 82 111 FontFamilyValueCache m_fontFamilyValueCache; 83 112 84 friend class WTF::NeverDestroyed<CSSValuePool>; 85 86 Ref<CSSInheritedValue> m_inheritedValue; 87 Ref<CSSInitialValue> m_implicitInitialValue; 88 Ref<CSSInitialValue> m_explicitInitialValue; 89 Ref<CSSUnsetValue> m_unsetValue; 90 Ref<CSSRevertValue> m_revertValue; 91 92 Ref<CSSPrimitiveValue> m_transparentColor; 93 Ref<CSSPrimitiveValue> m_whiteColor; 94 Ref<CSSPrimitiveValue> m_blackColor; 95 96 static const int maximumCacheableIntegerValue = 255; 97 98 Vector<Ref<CSSPrimitiveValue>> m_pixelValues; 99 Vector<Ref<CSSPrimitiveValue>> m_percentValues; 100 Vector<Ref<CSSPrimitiveValue>> m_numberValues; 101 Vector<Ref<CSSPrimitiveValue>> m_identifierValues; 113 friend class NeverDestroyed<CSSValuePool>; 102 114 }; 103 115
Note: See TracChangeset
for help on using the changeset viewer.