Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(422)

Unified Diff: Source/core/css/CSSPrimitiveValue.h

Issue 1226273002: CSSValue Immediates: Make CSSPrimitiveValue store a tagged pointer (Closed) Base URL: https://chromium.googlesource.com/chromium/blink.git@cssvalue_patch_2_attempt_2
Patch Set: Rebase Created 5 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « Source/core/core.gypi ('k') | Source/core/css/CSSPrimitiveValue.cpp » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: Source/core/css/CSSPrimitiveValue.h
diff --git a/Source/core/css/CSSPrimitiveValue.h b/Source/core/css/CSSPrimitiveValue.h
index a810b39136c13da67a088033ce8e128cc5ad6347..9f84a36b9bf1b567c16b5a5a641ccb56570fc337 100644
--- a/Source/core/css/CSSPrimitiveValue.h
+++ b/Source/core/css/CSSPrimitiveValue.h
@@ -109,35 +109,35 @@ public:
CSS_S = 15,
CSS_HZ = 16,
CSS_KHZ = 17,
- CSS_CUSTOM_IDENT = 19,
- CSS_URI = 20,
- CSS_IDENT = 21,
- CSS_ATTR = 22,
- CSS_COUNTER = 23,
- CSS_RECT = 24,
- CSS_RGBCOLOR = 25,
- CSS_VW = 26,
- CSS_VH = 27,
- CSS_VMIN = 28,
- CSS_VMAX = 29,
- CSS_DPPX = 30,
- CSS_DPI = 31,
- CSS_DPCM = 32,
- CSS_FR = 33,
- CSS_INTEGER = 34,
- CSS_PAIR = 100,
- CSS_TURN = 107,
- CSS_REMS = 108,
- CSS_CHS = 109,
- CSS_SHAPE = 111,
- CSS_QUAD = 112,
- CSS_CALC = 113,
- CSS_CALC_PERCENTAGE_WITH_NUMBER = 114,
- CSS_CALC_PERCENTAGE_WITH_LENGTH = 115,
- CSS_STRING = 116,
- CSS_PROPERTY_ID = 117,
- CSS_VALUE_ID = 118,
- CSS_QEM = 119
+ CSS_CUSTOM_IDENT = 18,
+ CSS_URI = 19,
+ CSS_IDENT = 20,
+ CSS_ATTR = 21,
+ CSS_COUNTER = 22,
+ CSS_RECT = 23,
+ CSS_RGBCOLOR = 24,
+ CSS_VW = 25,
+ CSS_VH = 26,
+ CSS_VMIN = 27,
+ CSS_VMAX = 28,
+ CSS_DPPX = 29,
+ CSS_DPI = 30,
+ CSS_DPCM = 31,
+ CSS_FR = 32,
+ CSS_INTEGER = 33,
+ CSS_PAIR = 34,
+ CSS_TURN = 35,
+ CSS_REMS = 36,
+ CSS_CHS = 37,
+ CSS_SHAPE = 38,
+ CSS_QUAD = 39,
+ CSS_CALC = 40,
+ CSS_CALC_PERCENTAGE_WITH_NUMBER = 41,
+ CSS_CALC_PERCENTAGE_WITH_LENGTH = 42,
+ CSS_STRING = 43,
+ CSS_PROPERTY_ID = 44,
+ CSS_VALUE_ID = 45,
+ CSS_QEM = 46
};
enum LengthUnitType {
@@ -159,6 +159,123 @@ public:
typedef Vector<double, CSSPrimitiveValue::LengthUnitTypeCount> CSSLengthArray;
typedef BitVector CSSLengthTypeArray;
+ struct CSSTaggedPtrValue {
+ // Variables for accessing parts of the tagged pointer.
+ // 32 bits = <value 25 bits><type 6 bits><tag 1 bit>
+ // 64 bits = <value 57 bits><type 6 bits><tag 1 bit>
+#if CPU(32BIT)
+ static const uint doubleShiftAmount = 32 + 7;
+ static const uint64_t mantissaTruncationMask = 0x7fffffffff;
+#elif CPU(64BIT)
+ static const uint doubleShiftAmount = 7;
+ static const uint64_t mantissaTruncationMask = 0x7f;
+#endif
+
+ unsigned flag : 1;
+ unsigned type : 6;
+#if CPU(32BIT)
+ unsigned long long valueRaw : 25;
+#elif CPU(64BIT)
+ unsigned long long valueRaw : 57;
+#endif
+
+ typedef struct {
+ unsigned red : 8;
+ unsigned green : 8;
+ unsigned blue : 8;
+#if CPU(32BIT)
+ unsigned alpha : 1;
+#elif CPU(64BIT)
+ unsigned alpha : 8;
+#endif
+ } packedColor;
+
+
+ // Returns true if value can be stored in the value field of the tagged pointer
+ // without losing information.
+ inline static bool fitsWithoutDataLoss(double value)
+ {
+ union {
+ double asDouble;
+ uint64_t asBits;
+ } interpretableValue;
+ interpretableValue.asDouble = value;
+ return (interpretableValue.asBits & mantissaTruncationMask) == 0;
+ }
+
+ inline static bool fitsWithoutDataLoss(RGBA32 color)
+ {
+#if CPU(32BIT)
+ return alphaChannel(color) == 0 || alphaChannel(color) == 255;
+#elif CPU(64BIT)
+ return true;
+#endif
+ }
+
+ // Convenience methods for getting/setting the value field, which is truncated.
+ inline double getValue() const
+ {
+ uint64_t shiftedValue = valueRaw;
+ shiftedValue = shiftedValue << doubleShiftAmount;
+ return *reinterpret_cast<double*>(&shiftedValue);
+ }
+
+ inline RGBA32 getColorValue() const
+ {
+ uintptr_t valueRawVar = valueRaw;
+ packedColor color = *reinterpret_cast<packedColor*>(&valueRawVar);
+ int alpha = color.alpha;
+#if CPU(32BIT)
+ alpha = color.alpha == 1 ? 255 : 0;
+#endif
+ return makeRGBA(color.red, color.green, color.blue, alpha);
+ }
+
+ inline CSSPropertyID getPropertyIDValue() const
+ {
+ return static_cast<CSSPropertyID>(valueRaw);
+ }
+
+ inline CSSValueID getValueIDValue() const
+ {
+ return static_cast<CSSValueID>(valueRaw);
+ }
+
+ inline void setValue(double value)
+ {
+ union {
+ double asDouble;
+ uint64_t asBits;
+ } interpretableValue;
+ interpretableValue.asDouble = value;
+ valueRaw = interpretableValue.asBits >> doubleShiftAmount;
+ }
+
+ inline void setValue(RGBA32 value)
+ {
+ packedColor color;
+ color.red = static_cast<uintptr_t>(redChannel(value));
+ color.green = static_cast<uintptr_t>(greenChannel(value));
+ color.blue = static_cast<uintptr_t>(blueChannel(value));
+#if CPU(32BIT)
+ color.alpha = static_cast<uintptr_t>(alphaChannel(value) == 255 ? 1 : 0);
+#elif CPU(64BIT)
+ color.alpha = static_cast<uintptr_t>(alphaChannel(value));
+#endif
+ valueRaw = *reinterpret_cast<uintptr_t*>(&color);
+ }
+
+ inline void setValue(CSSPropertyID propertyID)
+ {
+ valueRaw = static_cast<uintptr_t>(propertyID);
+ }
+
+ inline void setValue(CSSValueID valueID)
+ {
+ valueRaw = static_cast<uintptr_t>(valueID);
+ }
+ };
+
// No methods here, don't use this. It's just for large value storage.
// IMPORTANT: You should never actually make one of these outside the parser.
class CSSLargePrimitiveValue final : public CSSValueObject {
@@ -206,6 +323,12 @@ public:
CSSPrimitiveValueData m_value;
};
+ explicit CSSPrimitiveValue(CSSTaggedPtrValue taggedPtr)
+ : m_rawValue(taggedPtr)
+ {
+ ASSERT(!isObject());
+ }
+
explicit CSSPrimitiveValue(const CSSLargePrimitiveValue* object)
: m_rawValue(const_cast<CSSLargePrimitiveValue*>(object))
{
@@ -219,7 +342,7 @@ public:
CSSPrimitiveValue(const CSSPrimitiveValue& other)
- : m_rawValue(other.m_rawValue)
+ : m_rawValue(other.m_rawValue.asPtr)
{
ref();
}
@@ -240,7 +363,7 @@ public:
CSSLargePrimitiveValue* get() const
{
- return m_rawValue;
+ return m_rawValue.asPtr;
}
void accumulateLengthArray(CSSLengthArray&, double multiplier = 1) const;
@@ -309,18 +432,41 @@ public:
static CSSPrimitiveValue createIdentifier(CSSValueID valueID)
{
- return CSSPrimitiveValue(adoptRefWillBeNoop(new CSSLargePrimitiveValue(valueID)));
+ CSSTaggedPtrValue taggedPointer;
+ taggedPointer.flag = 1;
+ taggedPointer.type = CSS_VALUE_ID;
+ taggedPointer.setValue(valueID);
+ return CSSPrimitiveValue(taggedPointer);
}
+
static CSSPrimitiveValue createIdentifier(CSSPropertyID propertyID)
{
- return CSSPrimitiveValue(adoptRefWillBeNoop(new CSSLargePrimitiveValue(propertyID)));
+ CSSTaggedPtrValue taggedPointer;
+ taggedPointer.flag = 1;
+ taggedPointer.type = CSS_PROPERTY_ID;
+ taggedPointer.setValue(propertyID);
+ return CSSPrimitiveValue(taggedPointer);
}
static CSSPrimitiveValue createColor(RGBA32 rgbValue)
{
+ if (CSSTaggedPtrValue::fitsWithoutDataLoss(rgbValue)) {
+ CSSTaggedPtrValue taggedPointer;
+ taggedPointer.flag = 1;
+ taggedPointer.type = CSS_RGBCOLOR;
+ taggedPointer.setValue(rgbValue);
+ return CSSPrimitiveValue(taggedPointer);
+ }
return CSSPrimitiveValue(adoptRefWillBeNoop(new CSSLargePrimitiveValue(rgbValue)));
}
static CSSPrimitiveValue create(double value, UnitType type)
{
+ if (CSSTaggedPtrValue::fitsWithoutDataLoss(value)) {
+ CSSTaggedPtrValue taggedPointer;
+ taggedPointer.flag = 1;
+ taggedPointer.type = type;
+ taggedPointer.setValue(value);
+ return CSSPrimitiveValue(taggedPointer);
+ }
return CSSPrimitiveValue(adoptRefWillBeNoop(new CSSLargePrimitiveValue(value, type)));
}
static CSSPrimitiveValue create(const String& value, UnitType type)
@@ -391,7 +537,12 @@ public:
String customCSSText() const;
String cssText() const { return customCSSText(); }
- bool isQuirkValue() const { return m_rawValue->m_isQuirkValue; }
+ bool isQuirkValue() const
+ {
+ if (!isObject())
+ return false;
+ return m_rawValue.asPtr->m_isQuirkValue;
+ }
bool equals(const CSSPrimitiveValue) const;
@@ -405,21 +556,22 @@ public:
DEFINE_INLINE_TRACE()
{
visitor->trace(m_rawValue);
- m_rawValue->traceAfterDispatch(visitor);
}
private:
void ref() const
{
#if !ENABLE(OILPAN)
- m_rawValue->ref();
+ if (isObject())
+ m_rawValue.asPtr->ref();
#endif
}
void deref() const
{
#if !ENABLE(OILPAN)
- m_rawValue->deref();
+ if (isObject())
+ m_rawValue.asPtr->deref();
#endif
}
@@ -429,22 +581,59 @@ private:
double computeLengthDouble(const CSSToLengthConversionData&);
- RawPtrWillBeMember<CSSLargePrimitiveValue> m_rawValue;
+ union CSSPrimitivePointerValue {
+ CSSTaggedPtrValue asTaggedPtr;
+ RawPtrWillBeMember<CSSLargePrimitiveValue> asPtr;
+
+ CSSPrimitivePointerValue(CSSLargePrimitiveValue* ptr) : asPtr(ptr) { }
+ CSSPrimitivePointerValue(CSSTaggedPtrValue taggedPtr) : asTaggedPtr(taggedPtr) { }
+
+ DEFINE_INLINE_TRACE()
+ {
+ if (!(reinterpret_cast<uintptr_t>(asPtr.get()) & 1)) {
+ visitor->trace(asPtr);
+ asPtr->traceAfterDispatch(visitor);
+ }
+ }
+ } m_rawValue;
+ static_assert(sizeof(m_rawValue) == sizeof(void*), "The tagged pointer field in CSSPrimitiveValue must be the size of a pointer");
+
+ bool isObject() const
+ {
+ return m_rawValue.asTaggedPtr.flag == 0;
+ }
// Getters/setters for inner class.
- CSSPrimitiveValueData value() const { return m_rawValue->m_value; }
- UnitType type() const { return static_cast<UnitType>(m_rawValue->m_primitiveUnitType); }
- bool hasCachedCSSText() const { return m_rawValue->m_hasCachedCSSText; }
-
- void setValue(CSSPrimitiveValueData value) { m_rawValue->m_value = value; }
- void setType(UnitType primitiveUnitType) { m_rawValue->m_primitiveUnitType = static_cast<unsigned>(primitiveUnitType); }
- void setHasCachedCSSText(bool hasCachedCSSText) const { m_rawValue->m_hasCachedCSSText = hasCachedCSSText; }
- void setIsQuirkValue(bool isQuirkValue) { m_rawValue->m_isQuirkValue = isQuirkValue; }
+ CSSPrimitiveValueData value() const
+ {
+ if (isObject())
+ return m_rawValue.asPtr->m_value;
+
+ CSSPrimitiveValueData result;
+ if (m_rawValue.asTaggedPtr.type == CSS_RGBCOLOR)
+ result.rgbcolor = m_rawValue.asTaggedPtr.getColorValue();
+ else if (m_rawValue.asTaggedPtr.type == CSS_PROPERTY_ID)
+ result.propertyID = m_rawValue.asTaggedPtr.getPropertyIDValue();
+ else if (m_rawValue.asTaggedPtr.type == CSS_VALUE_ID)
+ result.valueID = m_rawValue.asTaggedPtr.getValueIDValue();
+ else
+ result.num = m_rawValue.asTaggedPtr.getValue();
+ return result;
+ }
+
+ UnitType type() const
+ {
+ if (isObject())
+ return static_cast<UnitType>(m_rawValue.asPtr->m_primitiveUnitType);
+ return static_cast<UnitType>(m_rawValue.asTaggedPtr.type);
+ }
};
typedef CSSPrimitiveValue::CSSLengthArray CSSLengthArray;
typedef CSSPrimitiveValue::CSSLengthTypeArray CSSLengthTypeArray;
+static_assert(sizeof(CSSPrimitiveValue) == sizeof(void*), "CSSPrimitiveValue must be the size of a pointer");
+
} // namespace blink
#endif // CSSPrimitiveValue_h
« no previous file with comments | « Source/core/core.gypi ('k') | Source/core/css/CSSPrimitiveValue.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698