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

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

Issue 1164573002: CSSValue Immediates: Change CSSValue to an object instead of a pointer (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 | « Source/core/css/CSSUnsetValue.h ('k') | Source/core/css/CSSValue.cpp » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: Source/core/css/CSSValue.h
diff --git a/Source/core/css/CSSValue.h b/Source/core/css/CSSValue.h
index 7bec2acc42b668100407563f551f0c63e2ee7c00..609dcbc85afcae15a768dc5b5debdca568aa6112 100644
--- a/Source/core/css/CSSValue.h
+++ b/Source/core/css/CSSValue.h
@@ -22,231 +22,335 @@
#define CSSValue_h
#include "core/CoreExport.h"
+#include "core/css/CSSValueObject.h"
#include "platform/heap/Handle.h"
-#include "platform/weborigin/KURL.h"
-#include "wtf/HashMap.h"
-#include "wtf/ListHashSet.h"
#include "wtf/RefCounted.h"
#include "wtf/RefPtr.h"
namespace blink {
-class CORE_EXPORT CSSValue : public RefCountedWillBeGarbageCollectedFinalized<CSSValue> {
+// A non-nullable container for CSSValueObject. Takes ownership of the passed
+// CSSValueObject.
+class CORE_EXPORT CSSValue {
+ ALLOW_ONLY_INLINE_ALLOCATION();
+ friend class NullableCSSValue;
public:
-#if ENABLE(OILPAN)
- // Override operator new to allocate CSSValue subtype objects onto
- // a dedicated heap.
- GC_PLUGIN_IGNORE("crbug.com/443854")
- void* operator new(size_t size)
- {
- return allocateObject(size, false);
- }
- static void* allocateObject(size_t size, bool isEager)
- {
- ThreadState* state = ThreadStateFor<ThreadingTrait<CSSValue>::Affinity>::state();
- return Heap::allocateOnHeapIndex(state, size, isEager ? ThreadState::EagerSweepHeapIndex : ThreadState::CSSValueHeapIndex, GCInfoTrait<CSSValue>::index());
- }
-#else
- // Override RefCounted's deref() to ensure operator delete is called on
- // the appropriate subclass type.
- void deref()
- {
- if (derefBase())
- destroy();
- }
-#endif // !ENABLE(OILPAN)
-
- String cssText() const;
-
- bool isPrimitiveValue() const { return m_classType == PrimitiveClass; }
- bool isValueList() const { return m_classType >= ValueListClass; }
-
- bool isBaseValueList() const { return m_classType == ValueListClass; }
-
- bool isBorderImageSliceValue() const { return m_classType == BorderImageSliceClass; }
- bool isCanvasValue() const { return m_classType == CanvasClass; }
- bool isCursorImageValue() const { return m_classType == CursorImageClass; }
- bool isCrossfadeValue() const { return m_classType == CrossfadeClass; }
- bool isFontFeatureValue() const { return m_classType == FontFeatureClass; }
- bool isFontFaceSrcValue() const { return m_classType == FontFaceSrcClass; }
- bool isFunctionValue() const { return m_classType == FunctionClass; }
- bool isImageGeneratorValue() const { return m_classType >= CanvasClass && m_classType <= RadialGradientClass; }
- bool isGradientValue() const { return m_classType >= LinearGradientClass && m_classType <= RadialGradientClass; }
- bool isImageSetValue() const { return m_classType == ImageSetClass; }
- bool isImageValue() const { return m_classType == ImageClass; }
- bool isImplicitInitialValue() const;
- bool isInheritedValue() const { return m_classType == InheritedClass; }
- bool isInitialValue() const { return m_classType == InitialClass; }
- bool isUnsetValue() const { return m_classType == UnsetClass; }
- bool isCSSWideKeyword() const { return m_classType >= InheritedClass && m_classType <= UnsetClass; }
- bool isLinearGradientValue() const { return m_classType == LinearGradientClass; }
- bool isPathValue() const { return m_classType == PathClass; }
- bool isRadialGradientValue() const { return m_classType == RadialGradientClass; }
- bool isReflectValue() const { return m_classType == ReflectClass; }
- bool isShadowValue() const { return m_classType == ShadowClass; }
- bool isCubicBezierTimingFunctionValue() const { return m_classType == CubicBezierTimingFunctionClass; }
- bool isStepsTimingFunctionValue() const { return m_classType == StepsTimingFunctionClass; }
- bool isLineBoxContainValue() const { return m_classType == LineBoxContainClass; }
- bool isCalcValue() const {return m_classType == CalculationClass; }
- bool isGridTemplateAreasValue() const { return m_classType == GridTemplateAreasClass; }
- bool isSVGDocumentValue() const { return m_classType == CSSSVGDocumentClass; }
- bool isContentDistributionValue() const { return m_classType == CSSContentDistributionClass; }
- bool isUnicodeRangeValue() const { return m_classType == UnicodeRangeClass; }
- bool isGridLineNamesValue() const { return m_classType == GridLineNamesClass; }
-
- bool hasFailedOrCanceledSubresources() const;
-
- bool equals(const CSSValue&) const;
-
- void finalizeGarbageCollectedObject();
- DEFINE_INLINE_TRACE_AFTER_DISPATCH() { }
- DECLARE_TRACE();
-
- // ~CSSValue should be public, because non-public ~CSSValue causes C2248
- // error: 'blink::CSSValue::~CSSValue' : cannot access protected member
- // declared in class 'blink::CSSValue' when compiling
- // 'source\wtf\refcounted.h' by using msvc.
- ~CSSValue() { }
-
-protected:
-
- static const size_t ClassTypeBits = 6;
- enum ClassType {
- PrimitiveClass,
-
- // Image classes.
- ImageClass,
- CursorImageClass,
-
- // Image generator classes.
- CanvasClass,
- CrossfadeClass,
- LinearGradientClass,
- RadialGradientClass,
-
- // Timing function classes.
- CubicBezierTimingFunctionClass,
- StepsTimingFunctionClass,
-
- // Other class types.
- BorderImageSliceClass,
- FontFeatureClass,
- FontFaceSrcClass,
-
- InheritedClass,
- InitialClass,
- UnsetClass,
-
- ReflectClass,
- ShadowClass,
- UnicodeRangeClass,
- LineBoxContainClass,
- CalculationClass,
- GridTemplateAreasClass,
- PathClass,
-
- // SVG classes.
- CSSSVGDocumentClass,
-
- CSSContentDistributionClass,
-
- // List class types must appear after ValueListClass.
- ValueListClass,
- FunctionClass,
- ImageSetClass,
- GridLineNamesClass,
- // Do not append non-list class types here.
- };
+ // Not explicit to allow for casting.
+ CSSValue(const CSSValueObject& cssValueObject)
+ : m_data(const_cast<CSSValueObject*>(&cssValueObject))
+ {
+ ASSERT(m_data);
+ ref();
+ }
- static const size_t ValueListSeparatorBits = 2;
- enum ValueListSeparator {
- SpaceSeparator,
- CommaSeparator,
- SlashSeparator
- };
+ // TODO(sashab): Remove these; construction should only be available with
+ // CSSValueObject&.
+ template<class T> CSSValue(PassRefPtrWillBeRawPtr<T> cssValueObject)
+ : m_data(cssValueObject.leakRef())
+ {
+ static_assert(WTF::IsSubclass<T, CSSValueObject>::value, "Parameter must be a container for CSSValueObject");
+ ASSERT(m_data);
+ }
+
+#if !ENABLE(OILPAN)
+ template<class T> CSSValue(RefPtrWillBeRawPtr<T> cssValueObject)
+ : m_data(cssValueObject.release().leakRef())
+ {
+ static_assert(WTF::IsSubclass<T, CSSValueObject>::value, "Parameter must be a container for CSSValueObject");
+ ASSERT(m_data);
+ }
+#endif
+
+ CSSValue(const CSSValue& cssValue)
+ : m_data(cssValue.m_data)
+ {
+ ref();
+ }
+
+ ~CSSValue()
+ {
+ deref();
+ }
+
+ CSSValue& operator=(const CSSValue& rhs)
+ {
+ rhs.ref();
+ deref();
+ m_data = rhs.m_data;
+ return *this;
+ }
+
+ bool operator==(const CSSValue& other) const
+ {
+ return m_data->equals(*other.m_data);
+ }
- ClassType classType() const { return static_cast<ClassType>(m_classType); }
+ // TODO: Remove this and update callsites to use operator== instead.
+ bool equals(const CSSValue& other) const
+ {
+ return m_data->equals(*other.m_data);
+ }
- explicit CSSValue(ClassType classType)
- : m_primitiveUnitType(0)
- , m_hasCachedCSSText(false)
- , m_isQuirkValue(false)
- , m_valueListSeparator(SpaceSeparator)
- , m_classType(classType)
+ bool ptrEquals(const CSSValue& other) const
{
+ return m_data == other.m_data;
}
- // NOTE: This class is non-virtual for memory and performance reasons.
- // Don't go making it virtual again unless you know exactly what you're doing!
+ // Methods that proxy to CSSValueObject.
+ String cssText() const { return m_data->cssText(); }
+ bool hasFailedOrCanceledSubresources() const { return m_data->hasFailedOrCanceledSubresources(); };
+ bool isPrimitiveValue() const { return m_data->isPrimitiveValue(); }
+ bool isValueList() const { return m_data->isValueList(); }
+ bool isBaseValueList() const { return m_data->isBaseValueList(); }
+ bool isBorderImageSliceValue() const { return m_data->isBorderImageSliceValue(); }
+ bool isCanvasValue() const { return m_data->isCanvasValue(); }
+ bool isCursorImageValue() const { return m_data->isCursorImageValue(); }
+ bool isCrossfadeValue() const { return m_data->isCrossfadeValue(); }
+ bool isFontFeatureValue() const { return m_data->isFontFeatureValue(); }
+ bool isFontFaceSrcValue() const { return m_data->isFontFaceSrcValue(); }
+ bool isFunctionValue() const { return m_data->isFunctionValue(); }
+ bool isImageGeneratorValue() const { return m_data->isImageGeneratorValue(); }
+ bool isGradientValue() const { return m_data->isGradientValue(); }
+ bool isImageSetValue() const { return m_data->isImageSetValue(); }
+ bool isImageValue() const { return m_data->isImageValue(); }
+ bool isImplicitInitialValue() const { return m_data->isImplicitInitialValue(); };
+ bool isInheritedValue() const { return m_data->isInheritedValue(); };
+ bool isInitialValue() const { return m_data->isInitialValue(); };
+ bool isUnsetValue() const { return m_data->isUnsetValue(); };
+ bool isCSSWideKeyword() const { return m_data->isCSSWideKeyword(); };
+ bool isLinearGradientValue() const { return m_data->isLinearGradientValue(); };
+ bool isPathValue() const { return m_data->isPathValue(); };
+ bool isRadialGradientValue() const { return m_data->isRadialGradientValue(); };
+ bool isReflectValue() const { return m_data->isReflectValue(); };
+ bool isShadowValue() const { return m_data->isShadowValue(); };
+ bool isCubicBezierTimingFunctionValue() const { return m_data->isCubicBezierTimingFunctionValue(); };
+ bool isStepsTimingFunctionValue() const { return m_data->isStepsTimingFunctionValue(); };
+ bool isLineBoxContainValue() const { return m_data->isLineBoxContainValue(); };
+ bool isCalcValue() const { return m_data->isCalcValue(); };
+ bool isGridTemplateAreasValue() const { return m_data->isGridTemplateAreasValue(); };
+ bool isSVGDocumentValue() const { return m_data->isSVGDocumentValue(); };
+ bool isContentDistributionValue() const { return m_data->isContentDistributionValue(); };
+ bool isUnicodeRangeValue() const { return m_data->isUnicodeRangeValue(); };
+ bool isGridLineNamesValue() const { return m_data->isGridLineNamesValue(); };
+
+ DEFINE_INLINE_TRACE()
+ {
+ ASSERT(m_data);
+ visitor->trace(m_data);
+ }
+
+ // Only for use by the toFooCSSValue() macros. Don't use this.
+ // TODO(sashab): Remove this and use value.to<Type> and value.isValid<Type>
+ // like WebNode.
+ CSSValueObject* get() const
+ {
+ return m_data.get();
+ }
private:
- void destroy();
+ CSSValue() = delete; // compile-time guard
+ CSSValue(std::nullptr_t) = delete; // compile-time guard
+
+ void ref() const
+ {
+#if !ENABLE(OILPAN)
+ if (m_data)
+ m_data->ref();
+#endif
+ }
+
+ void deref() const
+ {
+#if !ENABLE(OILPAN)
+ if (m_data)
+ m_data->deref();
+#endif
+ }
+
+ RawPtrWillBeMember<CSSValueObject> m_data;
+};
+
+// A nullable container for CSSValueObject. Contents are the same as CSSValue.
+// Behavior is similar to a CSSValue*.
+class CORE_EXPORT NullableCSSValue {
+ ALLOW_ONLY_INLINE_ALLOCATION();
+public:
+ // Not explicit to allow for casting.
+ NullableCSSValue()
+ : m_data(nullptr)
+ {
+ }
+
+ NullableCSSValue(const CSSValueObject* cssValueObject)
+ : m_data(const_cast<CSSValueObject*>(cssValueObject))
+ {
+ ref();
+ }
+
+ NullableCSSValue(const CSSValueObject& cssValueObject)
+ : m_data(const_cast<CSSValueObject*>(&cssValueObject))
+ {
+ ref();
+ }
+
+ // TODO(sashab): Remove these; construction should only be available with
+ // CSSValueObject& or CSSValueObject*.
+ template <class T> NullableCSSValue(PassRefPtrWillBeRawPtr<T> cssValueObject)
+ : m_data(cssValueObject.leakRef())
+ {
+ static_assert(WTF::IsSubclass<T, CSSValueObject>::value, "Parameter must be a container for CSSValueObject");
+ }
+
+#if !ENABLE(OILPAN)
+ template <class T> NullableCSSValue(RefPtrWillBeRawPtr<T> cssValueObject)
+ : m_data(cssValueObject.release().leakRef())
+ {
+ static_assert(WTF::IsSubclass<T, CSSValueObject>::value, "Parameter must be a container for CSSValueObject");
+ }
+#endif
+
+ NullableCSSValue(const NullableCSSValue& cssValue)
+ : m_data(cssValue.m_data)
+ {
+ ref();
+ }
+
+ NullableCSSValue(const CSSValue& cssValue)
+ : m_data(cssValue.m_data)
+ {
+ ref();
+ }
+
+ ~NullableCSSValue()
+ {
+ deref();
+ };
+
+ operator bool() const
+ {
+ return m_data;
+ }
+
+ NullableCSSValue& operator=(const NullableCSSValue& rhs)
+ {
+ rhs.ref();
+ deref();
+ m_data = rhs.m_data;
+ return *this;
+ }
+
+ bool operator==(const NullableCSSValue& rhs)
+ {
+ return m_data ? rhs.m_data && m_data->equals(*rhs.m_data) : !bool(rhs.m_data);
+ }
+
+ bool operator!=(const NullableCSSValue& rhs)
+ {
+ return !(*this == rhs);
+ }
+
+ CSSValue& operator*()
+ {
+ ASSERT(m_data);
+ // reinterpret_casts used to avoid ref-churn.
+ return *reinterpret_cast<CSSValue*>(this);
+ }
+
+ const CSSValue& operator*() const
+ {
+ ASSERT(m_data);
+ return *reinterpret_cast<const CSSValue*>(this);
+ }
+
+ CSSValue* operator->()
+ {
+ ASSERT(m_data);
+ return reinterpret_cast<CSSValue*>(this);
+ }
+
+ const CSSValue* operator->() const
+ {
+ ASSERT(m_data);
+ return reinterpret_cast<const CSSValue*>(this);
+ }
-protected:
- // The bits in this section are only used by specific subclasses but kept here
- // to maximize struct packing.
+ void swap(NullableCSSValue& rhs)
+ {
+ std::swap(this->m_data, rhs.m_data);
+ }
- // CSSPrimitiveValue bits:
- unsigned m_primitiveUnitType : 7; // CSSPrimitiveValue::UnitType
- mutable unsigned m_hasCachedCSSText : 1;
- unsigned m_isQuirkValue : 1;
+ DEFINE_INLINE_TRACE()
+ {
+ visitor->trace(m_data);
+ }
- unsigned m_valueListSeparator : ValueListSeparatorBits;
+ // Only for use by the toFooCSSValue() macros. Don't use this.
+ // TODO(sashab): Remove this and use value.to<Type> and value.isValid<Type>
+ // like WebNode.
+ CSSValueObject* get() const
+ {
+ return m_data.get();
+ }
private:
- unsigned m_classType : ClassTypeBits; // ClassType
+ void ref() const
+ {
+#if !ENABLE(OILPAN)
+ if (m_data)
+ m_data->ref();
+#endif
+ }
+
+ void deref() const
+ {
+#if !ENABLE(OILPAN)
+ if (m_data)
+ m_data->deref();
+#endif
+ }
+
+ RawPtrWillBeMember<CSSValueObject> m_data;
};
-template<typename CSSValueType, size_t inlineCapacity>
-inline bool compareCSSValueVector(const WillBeHeapVector<RefPtrWillBeMember<CSSValueType>, inlineCapacity>& firstVector, const WillBeHeapVector<RefPtrWillBeMember<CSSValueType>, inlineCapacity>& secondVector)
+static_assert(sizeof(CSSValue) == sizeof(void*), "CSSValue should be pointer-sized");
+static_assert(sizeof(NullableCSSValue) == sizeof(void*), "CSSValue should be pointer-sized");
+static_assert(sizeof(CSSValue) == sizeof(NullableCSSValue), "Both CSSValue containers must contain the same data");
+
+template<size_t inlineCapacity>
+inline bool compareCSSValueVector(const WillBeHeapVector<CSSValue, inlineCapacity>& firstVector, const WillBeHeapVector<CSSValue, inlineCapacity>& secondVector)
{
size_t size = firstVector.size();
if (size != secondVector.size())
return false;
for (size_t i = 0; i < size; i++) {
- const RefPtrWillBeMember<CSSValueType>& firstPtr = firstVector[i];
- const RefPtrWillBeMember<CSSValueType>& secondPtr = secondVector[i];
- if (firstPtr == secondPtr || (firstPtr && secondPtr && firstPtr->equals(*secondPtr)))
+ const CSSValue& firstPtr = firstVector[i];
+ const CSSValue& secondPtr = secondVector[i];
+ if (firstPtr.ptrEquals(secondPtr) || firstPtr.equals(secondPtr))
continue;
return false;
}
return true;
}
-template<typename CSSValueType>
-inline bool compareCSSValuePtr(const RefPtr<CSSValueType>& first, const RefPtr<CSSValueType>& second)
-{
- if (first == second)
- return true;
- if (!first || !second)
- return false;
- return first->equals(*second);
-}
-
-template<typename CSSValueType>
-inline bool compareCSSValuePtr(const RawPtr<CSSValueType>& first, const RawPtr<CSSValueType>& second)
-{
- if (first == second)
- return true;
- if (!first || !second)
- return false;
- return first->equals(*second);
-}
-
-template<typename CSSValueType>
-inline bool compareCSSValuePtr(const Member<CSSValueType>& first, const Member<CSSValueType>& second)
-{
- if (first == second)
- return true;
- if (!first || !second)
- return false;
- return first->equals(*second);
-}
-
#define DEFINE_CSS_VALUE_TYPE_CASTS(thisType, predicate) \
- DEFINE_TYPE_CASTS(thisType, CSSValue, value, value->predicate, value.predicate)
+ DEFINE_TYPE_CASTS(thisType, CSSValueObject, value, value->predicate, value.predicate); \
+ inline thisType& to##thisType(const CSSValue& value) \
+ { \
+ ASSERT_WITH_SECURITY_IMPLICATION(value.predicate); \
+ return *static_cast<thisType*>(value.get()); \
+ } \
+ inline thisType* to##thisType(const NullableCSSValue& value) \
+ { \
+ if (!value) \
+ return nullptr; \
+ ASSERT_WITH_SECURITY_IMPLICATION(value->predicate); \
+ return static_cast<thisType*>(value.get()); \
+ }
} // namespace blink
+WTF_ALLOW_CLEAR_UNUSED_SLOTS_WITH_MEM_FUNCTIONS(blink::CSSValue);
+WTF_ALLOW_CLEAR_UNUSED_SLOTS_WITH_MEM_FUNCTIONS(blink::NullableCSSValue);
+
#endif // CSSValue_h
« no previous file with comments | « Source/core/css/CSSUnsetValue.h ('k') | Source/core/css/CSSValue.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698