Skip to content

Commit d97070b

Browse files
Do not store LazyNeverDestroyed objects as member variables
https://bugs.webkit.org/show_bug.cgi?id=298814 Reviewed by Darin Adler. Stop using LazyNeverDestroyed for member variables in StaticCSSValuePool. This triggers undefined behavior in ASSERT_ENABLED builds, since the 'm_isConstructed' member of LazyNeverDestroyed<T> is not initialized in that case. GCC 14 correctly warned about this, breaking the build on e.g. Ubuntu 25.04, where GCC 14 is default. The straightforward solution was to directly use AlignedStorage<T> as type for the pool member variables instead of LazyNeverDestroyed<T>, preserving the current performance characteristics (no dynamic allocations, etc.). The "canonical" solution of using e.g. Vector<RefPtr<CSSPrimitiveValue>> would re-introduce the memory problems which were previously migitiated by introducing std::array<LazyNeverDestroyed<...>, capacity> -- thus it is not applicable here. Covered by existing tests. * Source/WebCore/css/CSSPrimitiveValue.cpp: (WebCore::valueFromPool): * Source/WebCore/css/CSSValuePool.cpp: (WebCore::StaticCSSValuePool::StaticCSSValuePool): (WebCore::CSSValuePool::createColorValue): * Source/WebCore/css/CSSValuePool.h: (WebCore::CSSPrimitiveValue::implicitInitialValue): (WebCore::CSSPrimitiveValue::create): Canonical link: https://commits.webkit.org/299936@main
1 parent 87a5937 commit d97070b

File tree

3 files changed

+23
-25
lines changed

3 files changed

+23
-25
lines changed

Source/WebCore/css/CSSPrimitiveValue.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -423,14 +423,14 @@ Ref<CSSPrimitiveValue> CSSPrimitiveValue::create(CSSPropertyID propertyID)
423423
return adoptRef(*new CSSPrimitiveValue(propertyID));
424424
}
425425

426-
static CSSPrimitiveValue* valueFromPool(std::span<LazyNeverDestroyed<CSSPrimitiveValue>> pool, double value)
426+
static CSSPrimitiveValue* valueFromPool(std::span<AlignedStorage<CSSPrimitiveValue>> pool, double value)
427427
{
428428
// Casting to a signed integer first since casting a negative floating point value to an unsigned
429429
// integer is undefined behavior.
430430
unsigned poolIndex = static_cast<unsigned>(static_cast<int>(value));
431431
double roundTripValue = poolIndex;
432432
if (equalSpans(asByteSpan(value), asByteSpan(roundTripValue)) && poolIndex < pool.size())
433-
return &pool[poolIndex].get();
433+
return pool[poolIndex].get();
434434
return nullptr;
435435
}
436436

Source/WebCore/css/CSSValuePool.cpp

Lines changed: 11 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -37,20 +37,18 @@ DEFINE_ALLOCATOR_WITH_HEAP_IDENTIFIER(CSSValuePool);
3737
LazyNeverDestroyed<StaticCSSValuePool> staticCSSValuePool;
3838

3939
StaticCSSValuePool::StaticCSSValuePool()
40+
: m_implicitInitialValue(CSSValue::StaticCSSValue, CSSPrimitiveValue::ImplicitInitialValue)
41+
, m_transparentColor(CSSValue::StaticCSSValue, WebCore::Color::transparentBlack)
42+
, m_whiteColor(CSSValue::StaticCSSValue, WebCore::Color::white)
43+
, m_blackColor(CSSValue::StaticCSSValue, WebCore::Color::black)
4044
{
41-
m_implicitInitialValue.construct(CSSValue::StaticCSSValue, CSSPrimitiveValue::ImplicitInitialValue);
42-
43-
m_transparentColor.construct(CSSValue::StaticCSSValue, WebCore::Color::transparentBlack);
44-
m_whiteColor.construct(CSSValue::StaticCSSValue, WebCore::Color::white);
45-
m_blackColor.construct(CSSValue::StaticCSSValue, WebCore::Color::black);
46-
4745
for (auto keyword : allCSSValueKeywords())
48-
m_identifierValues[enumToUnderlyingType(keyword)].construct(CSSValue::StaticCSSValue, keyword);
46+
new (m_identifierValues[enumToUnderlyingType(keyword)].get()) CSSPrimitiveValue { CSSValue::StaticCSSValue, keyword };
4947

5048
for (unsigned i = 0; i <= maximumCacheableIntegerValue; ++i) {
51-
m_pixelValues[i].construct(CSSValue::StaticCSSValue, i, CSSUnitType::CSS_PX);
52-
m_percentageValues[i].construct(CSSValue::StaticCSSValue, i, CSSUnitType::CSS_PERCENTAGE);
53-
m_numberValues[i].construct(CSSValue::StaticCSSValue, i, CSSUnitType::CSS_NUMBER);
49+
new (m_pixelValues[i].get()) CSSPrimitiveValue(CSSValue::StaticCSSValue, i, CSSUnitType::CSS_PX);
50+
new (m_percentageValues[i].get()) CSSPrimitiveValue(CSSValue::StaticCSSValue, i, CSSUnitType::CSS_PERCENTAGE);
51+
new (m_numberValues[i].get()) CSSPrimitiveValue(CSSValue::StaticCSSValue, i, CSSUnitType::CSS_NUMBER);
5452
}
5553
}
5654

@@ -76,12 +74,12 @@ Ref<CSSColorValue> CSSValuePool::createColorValue(const WebCore::Color& color)
7674
{
7775
// These are the empty and deleted values of the hash table.
7876
if (color == WebCore::Color::transparentBlack)
79-
return staticCSSValuePool->m_transparentColor.get();
77+
return staticCSSValuePool->m_transparentColor;
8078
if (color == WebCore::Color::white)
81-
return staticCSSValuePool->m_whiteColor.get();
79+
return staticCSSValuePool->m_whiteColor;
8280
// Just because it is common.
8381
if (color == WebCore::Color::black)
84-
return staticCSSValuePool->m_blackColor.get();
82+
return staticCSSValuePool->m_blackColor;
8583

8684
// Remove one entry at random if the cache grows too large.
8785
// FIXME: Use TinyLRUCache instead?

Source/WebCore/css/CSSValuePool.h

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -48,18 +48,18 @@ class StaticCSSValuePool {
4848
private:
4949
StaticCSSValuePool();
5050

51-
LazyNeverDestroyed<CSSPrimitiveValue> m_implicitInitialValue;
51+
CSSPrimitiveValue m_implicitInitialValue;
5252

53-
LazyNeverDestroyed<CSSColorValue> m_transparentColor;
54-
LazyNeverDestroyed<CSSColorValue> m_whiteColor;
55-
LazyNeverDestroyed<CSSColorValue> m_blackColor;
53+
CSSColorValue m_transparentColor;
54+
CSSColorValue m_whiteColor;
55+
CSSColorValue m_blackColor;
5656

5757
static constexpr int maximumCacheableIntegerValue = 255;
5858

59-
std::array<LazyNeverDestroyed<CSSPrimitiveValue>, maximumCacheableIntegerValue + 1> m_pixelValues;
60-
std::array<LazyNeverDestroyed<CSSPrimitiveValue>, maximumCacheableIntegerValue + 1> m_percentageValues;
61-
std::array<LazyNeverDestroyed<CSSPrimitiveValue>, maximumCacheableIntegerValue + 1> m_numberValues;
62-
std::array<LazyNeverDestroyed<CSSPrimitiveValue>, numCSSValueKeywords> m_identifierValues;
59+
std::array<AlignedStorage<CSSPrimitiveValue>, maximumCacheableIntegerValue + 1> m_pixelValues;
60+
std::array<AlignedStorage<CSSPrimitiveValue>, maximumCacheableIntegerValue + 1> m_percentageValues;
61+
std::array<AlignedStorage<CSSPrimitiveValue>, maximumCacheableIntegerValue + 1> m_numberValues;
62+
std::array<AlignedStorage<CSSPrimitiveValue>, numCSSValueKeywords> m_identifierValues;
6363
};
6464

6565
WEBCORE_EXPORT extern LazyNeverDestroyed<StaticCSSValuePool> staticCSSValuePool;
@@ -85,13 +85,13 @@ class CSSValuePool {
8585

8686
inline CSSPrimitiveValue& CSSPrimitiveValue::implicitInitialValue()
8787
{
88-
return staticCSSValuePool->m_implicitInitialValue.get();
88+
return staticCSSValuePool->m_implicitInitialValue;
8989
}
9090

9191
inline Ref<CSSPrimitiveValue> CSSPrimitiveValue::create(CSSValueID identifier)
9292
{
9393
RELEASE_ASSERT(identifier < numCSSValueKeywords);
94-
return staticCSSValuePool->m_identifierValues[identifier].get();
94+
return *staticCSSValuePool->m_identifierValues[identifier];
9595
}
9696

9797
} // namespace WebCore

0 commit comments

Comments
 (0)