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

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

Issue 1252683002: CSSValue Immediates: Change RefPtr<CSSValue> to store tagged pointers (Closed) Base URL: https://chromium.googlesource.com/chromium/blink.git@master
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 | « no previous file | 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 3f7b65ed10fa47ffdcee0ea063f26b3bc7687402..1820b226d24c511e3c90c80db830cb3cfecda590 100644
--- a/Source/core/css/CSSPrimitiveValue.h
+++ b/Source/core/css/CSSPrimitiveValue.h
@@ -31,6 +31,7 @@
#include "wtf/Forward.h"
#include "wtf/MathExtras.h"
#include "wtf/PassRefPtr.h"
+#include "wtf/RefCounted.h"
#include "wtf/text/StringHash.h"
namespace blink {
@@ -70,56 +71,58 @@ template<> inline float roundForImpreciseConversion(double value)
// CSSPrimitiveValues are immutable. This class has manual ref-counting
// of unioned types and does not have the code necessary
// to handle any kind of mutations.
+// In some cases, CSSPrimitiveValue is a tagged pointer. If isTaggedPtr() returns
+// true, |this| is an invalid pointer and member variables should not be accessed.
class CORE_EXPORT CSSPrimitiveValue : public CSSValue {
public:
enum UnitType {
- CSS_UNKNOWN = 0,
- CSS_NUMBER = 1,
- CSS_PERCENTAGE = 2,
- CSS_EMS = 3,
- CSS_EXS = 4,
- CSS_PX = 5,
- CSS_CM = 6,
- CSS_MM = 7,
- CSS_IN = 8,
- CSS_PT = 9,
- CSS_PC = 10,
- CSS_DEG = 11,
- CSS_RAD = 12,
- CSS_GRAD = 13,
- CSS_MS = 14,
- 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_UNKNOWN,
+ CSS_NUMBER,
+ CSS_PERCENTAGE,
+ CSS_EMS,
+ CSS_EXS,
+ CSS_PX,
+ CSS_CM,
+ CSS_MM,
+ CSS_IN,
+ CSS_PT,
+ CSS_PC,
+ CSS_DEG,
+ CSS_RAD,
+ CSS_GRAD,
+ CSS_MS,
+ CSS_S,
+ CSS_HZ,
+ CSS_KHZ,
+ CSS_CUSTOM_IDENT,
+ CSS_URI,
+ CSS_IDENT,
+ CSS_ATTR,
+ CSS_COUNTER,
+ CSS_RECT,
+ CSS_RGBCOLOR,
+ CSS_VW,
+ CSS_VH,
+ CSS_VMIN,
+ CSS_VMAX,
+ CSS_DPPX,
+ CSS_DPI,
+ CSS_DPCM,
+ CSS_FR,
+ CSS_INTEGER,
+ CSS_PAIR,
+ CSS_TURN,
+ CSS_REMS,
+ CSS_CHS,
+ CSS_SHAPE,
+ CSS_QUAD,
+ CSS_CALC,
+ CSS_CALC_PERCENTAGE_WITH_NUMBER,
+ CSS_CALC_PERCENTAGE_WITH_LENGTH,
+ CSS_STRING,
+ CSS_PROPERTY_ID,
+ CSS_VALUE_ID,
+ CSS_QEM
};
enum LengthUnitType {
@@ -138,6 +141,21 @@ public:
LengthUnitTypeCount,
};
+ union CSSPrimitiveValueData {
+ CSSPropertyID propertyID;
+ CSSValueID valueID;
+ double num;
+ StringImpl* string;
+ RGBA32 rgbcolor;
+ // FIXME: oilpan: Should be members, but no support for members in unions. Just trace the raw ptr for now.
+ CSSBasicShape* shape;
+ CSSCalcValue* calc;
+ Counter* counter;
+ Pair* pair;
+ Rect* rect;
+ Quad* quad;
+ };
+
typedef Vector<double, CSSPrimitiveValue::LengthUnitTypeCount> CSSLengthArray;
typedef BitVector CSSLengthTypeArray;
@@ -163,22 +181,22 @@ public:
bool isAngle() const
{
- return m_primitiveUnitType == CSS_DEG
- || m_primitiveUnitType == CSS_RAD
- || m_primitiveUnitType == CSS_GRAD
- || m_primitiveUnitType == CSS_TURN;
+ return type() == CSS_DEG
+ || type() == CSS_RAD
+ || type() == CSS_GRAD
+ || type() == CSS_TURN;
}
- bool isAttr() const { return m_primitiveUnitType == CSS_ATTR; }
- bool isCounter() const { return m_primitiveUnitType == CSS_COUNTER; }
- bool isCustomIdent() const { return m_primitiveUnitType == CSS_CUSTOM_IDENT; }
+ bool isAttr() const { return type() == CSS_ATTR; }
+ bool isCounter() const { return type() == CSS_COUNTER; }
+ bool isCustomIdent() const { return type() == CSS_CUSTOM_IDENT; }
bool isFontRelativeLength() const
{
- return m_primitiveUnitType == CSS_EMS
- || m_primitiveUnitType == CSS_EXS
- || m_primitiveUnitType == CSS_REMS
- || m_primitiveUnitType == CSS_CHS;
+ return type() == CSS_EMS
+ || type() == CSS_EXS
+ || type() == CSS_REMS
+ || type() == CSS_CHS;
}
- bool isViewportPercentageLength() const { return isViewportPercentageLength(static_cast<UnitType>(m_primitiveUnitType)); }
+ bool isViewportPercentageLength() const { return isViewportPercentageLength(type()); }
static bool isViewportPercentageLength(UnitType type) { return type >= CSS_VW && type <= CSS_VMAX; }
static bool isLength(UnitType type)
{
@@ -188,13 +206,13 @@ public:
bool isNumber() const { return primitiveType() == CSS_NUMBER || primitiveType() == CSS_INTEGER; }
bool isPercentage() const { return primitiveType() == CSS_PERCENTAGE; }
bool isPx() const { return primitiveType() == CSS_PX; }
- bool isRect() const { return m_primitiveUnitType == CSS_RECT; }
- bool isRGBColor() const { return m_primitiveUnitType == CSS_RGBCOLOR; }
- bool isShape() const { return m_primitiveUnitType == CSS_SHAPE; }
- bool isString() const { return m_primitiveUnitType == CSS_STRING; }
- bool isTime() const { return m_primitiveUnitType == CSS_S || m_primitiveUnitType == CSS_MS; }
- bool isURI() const { return m_primitiveUnitType == CSS_URI; }
- bool isCalculated() const { return m_primitiveUnitType == CSS_CALC; }
+ bool isRect() const { return type() == CSS_RECT; }
+ bool isRGBColor() const { return type() == CSS_RGBCOLOR; }
+ bool isShape() const { return type() == CSS_SHAPE; }
+ bool isString() const { return type() == CSS_STRING; }
+ bool isTime() const { return type() == CSS_S || type() == CSS_MS; }
+ bool isURI() const { return type() == CSS_URI; }
+ bool isCalculated() const { return type() == CSS_CALC; }
bool isCalculatedPercentageWithNumber() const { return primitiveType() == CSS_CALC_PERCENTAGE_WITH_NUMBER; }
bool isCalculatedPercentageWithLength() const { return primitiveType() == CSS_CALC_PERCENTAGE_WITH_LENGTH; }
static bool isDotsPerInch(UnitType type) { return type == CSS_DPI; }
@@ -202,24 +220,63 @@ public:
static bool isDotsPerCentimeter(UnitType type) { return type == CSS_DPCM; }
static bool isResolution(UnitType type) { return type >= CSS_DPPX && type <= CSS_DPCM; }
bool isFlex() const { return primitiveType() == CSS_FR; }
- bool isValueID() const { return m_primitiveUnitType == CSS_VALUE_ID; }
+ bool isValueID() const { return type() == CSS_VALUE_ID; }
bool colorIsDerivedFromElement() const;
static PassRefPtrWillBeRawPtr<CSSPrimitiveValue> createIdentifier(CSSValueID valueID)
{
- return adoptRefWillBeNoop(new CSSPrimitiveValue(valueID));
+ CSSTaggedPtrValue taggedPtr;
+ taggedPtr.flag = 1;
+ taggedPtr.type = static_cast<uintptr_t>(CSSPrimitiveValue::CSS_VALUE_ID);
+ taggedPtr.value = static_cast<uintptr_t>(valueID);
+ return adoptRefWillBeNoop(toPtr(taggedPtr));
}
static PassRefPtrWillBeRawPtr<CSSPrimitiveValue> createIdentifier(CSSPropertyID propertyID)
{
- return adoptRefWillBeNoop(new CSSPrimitiveValue(propertyID));
+ CSSTaggedPtrValue taggedPtr;
+ taggedPtr.flag = 1;
+ taggedPtr.type = static_cast<uintptr_t>(CSSPrimitiveValue::CSS_PROPERTY_ID);
+ taggedPtr.value = static_cast<uintptr_t>(propertyID);
+ return adoptRefWillBeNoop(toPtr(taggedPtr));
}
static PassRefPtrWillBeRawPtr<CSSPrimitiveValue> createColor(RGBA32 rgbValue)
{
- return adoptRefWillBeNoop(new CSSPrimitiveValue(rgbValue));
+ bool canFitColor;
+#if CPU(32BIT)
+ canFitColor = alphaChannel(rgbValue) == 0 || alphaChannel(rgbValue) == 255;
+#elif CPU(64BIT)
+ canFitColor = true;
+#endif
+ if (!canFitColor)
+ return adoptRefWillBeNoop(new CSSPrimitiveValue(rgbValue));
+
+ CSSTaggedPtrValue taggedPtr;
+ taggedPtr.flag = 1;
+ taggedPtr.type = static_cast<uintptr_t>(CSSPrimitiveValue::CSS_RGBCOLOR);
+
+ packedColor colorToStore;
+ colorToStore.red = static_cast<uintptr_t>(redChannel(rgbValue));
+ colorToStore.green = static_cast<uintptr_t>(greenChannel(rgbValue));
+ colorToStore.blue = static_cast<uintptr_t>(blueChannel(rgbValue));
+#if CPU(32BIT)
+ colorToStore.alpha = static_cast<uintptr_t>(alphaChannel(rgbValue) == 255 ? 1 : 0);
+#elif CPU(64BIT)
+ colorToStore.alpha = static_cast<uintptr_t>(alphaChannel(rgbValue));
+#endif
+ taggedPtr.value = *reinterpret_cast<uintptr_t*>(&colorToStore);
+ return adoptRefWillBeNoop(toPtr(taggedPtr));
}
static PassRefPtrWillBeRawPtr<CSSPrimitiveValue> create(double value, UnitType type)
{
- return adoptRefWillBeNoop(new CSSPrimitiveValue(value, type));
+ uint64_t& doubleAsBits = reinterpret_cast<uint64_t&>(value);
+ if ((doubleAsBits & mantissaTruncationMask) != 0)
+ return adoptRefWillBeNoop(new CSSPrimitiveValue(value, type));
+
+ CSSTaggedPtrValue taggedPtr;
+ taggedPtr.flag = 1;
+ taggedPtr.type = static_cast<uintptr_t>(type);
+ taggedPtr.value = doubleAsBits >> doubleShiftAmount;
+ return adoptRefWillBeNoop(toPtr(taggedPtr));
}
static PassRefPtrWillBeRawPtr<CSSPrimitiveValue> create(const String& value, UnitType type)
{
@@ -264,36 +321,49 @@ public:
// Converts to a Length (Fixed, Percent or Calculated)
Length convertToLength(const CSSToLengthConversionData&);
- double getDoubleValue() const;
+ double getDoubleValue() const
+ {
+ if (type() == CSS_CALC)
+ return getCalcDoubleValue();
+ return value().num;
+ }
+
+ double getCalcDoubleValue() const;
+
float getFloatValue() const { return getValue<float>(); }
int getIntValue() const { return getValue<int>(); }
template<typename T> inline T getValue() const { return clampTo<T>(getDoubleValue()); }
String getStringValue() const;
- Counter* getCounterValue() const { return m_primitiveUnitType != CSS_COUNTER ? 0 : m_value.counter; }
+ Counter* getCounterValue() const { return type() != CSS_COUNTER ? 0 : value().counter; }
- Rect* getRectValue() const { return m_primitiveUnitType != CSS_RECT ? 0 : m_value.rect; }
+ Rect* getRectValue() const { return type() != CSS_RECT ? 0 : value().rect; }
- Quad* getQuadValue() const { return m_primitiveUnitType != CSS_QUAD ? 0 : m_value.quad; }
+ Quad* getQuadValue() const { return type() != CSS_QUAD ? 0 : value().quad; }
- RGBA32 getRGBA32Value() const { return m_primitiveUnitType != CSS_RGBCOLOR ? 0 : m_value.rgbcolor; }
+ RGBA32 getRGBA32Value() const { return type() != CSS_RGBCOLOR ? 0 : value().rgbcolor; }
- Pair* getPairValue() const { return m_primitiveUnitType != CSS_PAIR ? 0 : m_value.pair; }
+ Pair* getPairValue() const { return type() != CSS_PAIR ? 0 : value().pair; }
- CSSBasicShape* getShapeValue() const { return m_primitiveUnitType != CSS_SHAPE ? 0 : m_value.shape; }
+ CSSBasicShape* getShapeValue() const { return type() != CSS_SHAPE ? 0 : value().shape; }
- CSSCalcValue* cssCalcValue() const { return m_primitiveUnitType != CSS_CALC ? 0 : m_value.calc; }
+ CSSCalcValue* cssCalcValue() const { return type() != CSS_CALC ? 0 : value().calc; }
- CSSPropertyID getPropertyID() const { return m_primitiveUnitType == CSS_PROPERTY_ID ? m_value.propertyID : CSSPropertyInvalid; }
- CSSValueID getValueID() const { return m_primitiveUnitType == CSS_VALUE_ID ? m_value.valueID : CSSValueInvalid; }
+ CSSPropertyID getPropertyID() const { return type() == CSS_PROPERTY_ID ? value().propertyID : CSSPropertyInvalid; }
+ CSSValueID getValueID() const { return type() == CSS_VALUE_ID ? value().valueID : CSSValueInvalid; }
template<typename T> inline operator T() const; // Defined in CSSPrimitiveValueMappings.h
static const char* unitTypeToString(UnitType);
String customCSSText() const;
- bool isQuirkValue() { return m_isQuirkValue; }
+ inline bool isQuirkValue() const
+ {
+ if (isTaggedPtr())
+ return false;
+ return m_isQuirkValue;
+ }
bool equals(const CSSPrimitiveValue&) const;
@@ -343,20 +413,86 @@ private:
double computeLengthDouble(const CSSToLengthConversionData&);
- union {
- CSSPropertyID propertyID;
- CSSValueID valueID;
- double num;
- StringImpl* string;
- RGBA32 rgbcolor;
- // FIXME: oilpan: Should be members, but no support for members in unions. Just trace the raw ptr for now.
- CSSBasicShape* shape;
- CSSCalcValue* calc;
- Counter* counter;
- Pair* pair;
- Rect* rect;
- Quad* quad;
- } m_value;
+ // Useful bit masks for dealing with tagged pointer doubles.
+#if CPU(32BIT)
+ static const unsigned doubleShiftAmount = 32 + 7;
+ static const uint64_t mantissaTruncationMask = 0x7fffffffff;
+#elif CPU(64BIT)
+ static const unsigned doubleShiftAmount = 7;
+ static const uint64_t mantissaTruncationMask = 0x7f;
+#endif
+
+ // Struct for storing RGB values.
+ 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;
+
+ // Getter/setter functions that account for tagged pointer optimization.
+ inline bool isTaggedPtr() const
+ {
+ return reinterpret_cast<uintptr_t>(this) & 1;
+ }
+
+ static inline CSSPrimitiveValue* toPtr(CSSTaggedPtrValue taggedPtr)
+ {
+ return reinterpret_cast<CSSPrimitiveValue*&>(taggedPtr);
+ }
+
+ inline CSSTaggedPtrValue toTaggedPtr() const
+ {
+ CSSPrimitiveValue* nonConstThis = const_cast<CSSPrimitiveValue*>(this);
+ return reinterpret_cast<CSSTaggedPtrValue&&>(nonConstThis);
+ }
+
+ inline UnitType type() const
+ {
+ if (!isTaggedPtr())
+ return static_cast<UnitType>(m_primitiveUnitType);
+ return static_cast<UnitType>(toTaggedPtr().type);
+ }
+
+ inline CSSPrimitiveValueData value() const
+ {
+ if (!isTaggedPtr())
+ return m_value;
+
+ CSSPrimitiveValueData data;
+ switch (type()) {
+ case CSSPrimitiveValue::CSS_PROPERTY_ID:
+ data.propertyID = static_cast<CSSPropertyID>(toTaggedPtr().value);
+ break;
+ case CSSPrimitiveValue::CSS_VALUE_ID:
+ data.valueID = static_cast<CSSValueID>(toTaggedPtr().value);
+ break;
+ case CSSPrimitiveValue::CSS_RGBCOLOR: {
+ uintptr_t valueRawVar = toTaggedPtr().value;
+ packedColor color = *reinterpret_cast<packedColor*>(&valueRawVar);
+ unsigned alpha;
+#if CPU(32BIT)
+ alpha = color.alpha == 1 ? 255 : 0;
+#elif CPU(64BIT)
+ alpha = color.alpha;
+#endif
+ data.rgbcolor = makeRGBA(color.red, color.green, color.blue, alpha);
+ break;
+ }
+ default:
+ uint64_t shiftedValue = toTaggedPtr().value;
+ shiftedValue = shiftedValue << doubleShiftAmount;
+ data.num = *reinterpret_cast<double*>(&shiftedValue);
+ break;
+ }
+ return data;
+ }
+
+ CSSPrimitiveValueData m_value;
};
typedef CSSPrimitiveValue::CSSLengthArray CSSLengthArray;
@@ -366,4 +502,19 @@ DEFINE_CSS_VALUE_TYPE_CASTS(CSSPrimitiveValue, isPrimitiveValue());
} // namespace blink
+namespace WTF {
+
+#if !ENABLE(OILPAN)
+// Must be defined *after* CSSPrimitiveValue to compile with the correct adopted() method.
+template<> inline PassRefPtr<blink::CSSPrimitiveValue> adoptRef<blink::CSSPrimitiveValue>(blink::CSSPrimitiveValue* p)
+{
+ // Immediates (non-pointers) end in a 1.
+ if (!(reinterpret_cast<uintptr_t>(p) & 1))
+ adopted(p);
+ return PassRefPtr<blink::CSSPrimitiveValue>(p, PassRefPtr<blink::CSSPrimitiveValue>::AdoptRef);
+}
+#endif
+
+} // namespace WTF
+
#endif // CSSPrimitiveValue_h
« no previous file with comments | « no previous file | Source/core/css/CSSPrimitiveValue.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698