0

Streamline CSSPropertyID set testing.

It turns out that CSSBitSet _can_ be made compile-time statically
initialized without resorting to lots of precomputed uint64_t values,
as long as we hold Clang just right. So change kKnownExposedProperties
to using that (giving slightly less complex Jinja code), and convert
the CSSParserFastPath tests from switches (which create jump tables,
which are generally larger) to using bitsets.

Change-Id: I2ddd18ca093611580adf4daeb99fdb5bcf066284
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4014121
Commit-Queue: Steinar H Gunderson <sesse@chromium.org>
Reviewed-by: Anders Hartvoll Ruud <andruud@chromium.org>
Cr-Commit-Position: refs/heads/main@{#1069137}
This commit is contained in:
Steinar H. Gunderson
2022-11-09 14:37:42 +00:00
committed by Chromium LUCI CQ
parent b7aabf1d0c
commit 603cb301d4
5 changed files with 252 additions and 241 deletions
third_party/blink/renderer

@ -16,28 +16,24 @@ class KnownExposedPropertiesWriter(json5_generator.Writer):
properties = (
css_properties.CSSProperties(json5_file_paths)).properties_including_aliases
bitmask = []
known_exposed_properties = []
for property in properties:
if not property['is_internal'] and \
not property['runtime_flag'] and \
not property['in_origin_trial']:
bit_idx = property['enum_value']
chunk = int(bit_idx / 64)
while chunk >= len(bitmask):
bitmask.append(0)
bitmask[chunk] = bitmask[chunk] | (1 << (bit_idx % 64))
known_exposed_properties.append(property['enum_key'])
self._known_exposed_properties_bitmask = bitmask
self._known_exposed_properties = known_exposed_properties
self._outputs = {
'known_exposed_properties.cc': self.generate_bitmap,
'known_exposed_properties.cc': self.generate_list,
}
@template_expander.use_jinja('core/css/properties/templates/known_exposed_properties.cc.tmpl')
def generate_bitmap(self):
def generate_list(self):
return {
'input_files': self._input_files,
'known_exposed_properties_bitmask': self._known_exposed_properties_bitmask,
'known_exposed_properties': self._known_exposed_properties,
}

@ -12,10 +12,10 @@
namespace blink {
const CSSBitset kKnownExposedProperties{std::array<uint64_t, CSSBitset::kChunks>{
{% for chunk in known_exposed_properties_bitmask %}
0x{{ '%016x' % chunk }}ULL,
const CSSBitset kKnownExposedProperties{ {
{% for property in known_exposed_properties %}
CSSPropertyID::{{ property }},
{% endfor %}
}};
} };
} // namespace blink

@ -19,6 +19,7 @@
#include "third_party/blink/renderer/core/css/css_value_clamping_utils.h"
#include "third_party/blink/renderer/core/css/parser/css_parser_idioms.h"
#include "third_party/blink/renderer/core/css/parser/css_property_parser.h"
#include "third_party/blink/renderer/core/css/properties/css_bitset.h"
#include "third_party/blink/renderer/core/css/properties/css_property.h"
#include "third_party/blink/renderer/core/css/style_color.h"
#include "third_party/blink/renderer/core/html/parser/html_parser_idioms.h"
@ -31,60 +32,70 @@ namespace blink {
static inline bool IsSimpleLengthPropertyID(CSSPropertyID property_id,
bool& accepts_negative_numbers) {
switch (property_id) {
case CSSPropertyID::kBlockSize:
case CSSPropertyID::kInlineSize:
case CSSPropertyID::kMinBlockSize:
case CSSPropertyID::kMinInlineSize:
case CSSPropertyID::kFontSize:
case CSSPropertyID::kHeight:
case CSSPropertyID::kWidth:
case CSSPropertyID::kMinHeight:
case CSSPropertyID::kMinWidth:
case CSSPropertyID::kPaddingBottom:
case CSSPropertyID::kPaddingLeft:
case CSSPropertyID::kPaddingRight:
case CSSPropertyID::kPaddingTop:
case CSSPropertyID::kScrollPaddingBlockEnd:
case CSSPropertyID::kScrollPaddingBlockStart:
case CSSPropertyID::kScrollPaddingBottom:
case CSSPropertyID::kScrollPaddingInlineEnd:
case CSSPropertyID::kScrollPaddingInlineStart:
case CSSPropertyID::kScrollPaddingLeft:
case CSSPropertyID::kScrollPaddingRight:
case CSSPropertyID::kScrollPaddingTop:
case CSSPropertyID::kPaddingBlockEnd:
case CSSPropertyID::kPaddingBlockStart:
case CSSPropertyID::kPaddingInlineEnd:
case CSSPropertyID::kPaddingInlineStart:
case CSSPropertyID::kShapeMargin:
case CSSPropertyID::kR:
case CSSPropertyID::kRx:
case CSSPropertyID::kRy:
accepts_negative_numbers = false;
return true;
case CSSPropertyID::kBottom:
case CSSPropertyID::kCx:
case CSSPropertyID::kCy:
case CSSPropertyID::kLeft:
case CSSPropertyID::kMarginBottom:
case CSSPropertyID::kMarginLeft:
case CSSPropertyID::kMarginRight:
case CSSPropertyID::kMarginTop:
case CSSPropertyID::kOffsetDistance:
case CSSPropertyID::kRight:
case CSSPropertyID::kTop:
case CSSPropertyID::kMarginBlockEnd:
case CSSPropertyID::kMarginBlockStart:
case CSSPropertyID::kMarginInlineEnd:
case CSSPropertyID::kMarginInlineStart:
case CSSPropertyID::kX:
case CSSPropertyID::kY:
accepts_negative_numbers = true;
return true;
default:
return false;
static CSSBitset properties{{
CSSPropertyID::kBlockSize,
CSSPropertyID::kInlineSize,
CSSPropertyID::kMinBlockSize,
CSSPropertyID::kMinInlineSize,
CSSPropertyID::kFontSize,
CSSPropertyID::kHeight,
CSSPropertyID::kWidth,
CSSPropertyID::kMinHeight,
CSSPropertyID::kMinWidth,
CSSPropertyID::kPaddingBottom,
CSSPropertyID::kPaddingLeft,
CSSPropertyID::kPaddingRight,
CSSPropertyID::kPaddingTop,
CSSPropertyID::kScrollPaddingBlockEnd,
CSSPropertyID::kScrollPaddingBlockStart,
CSSPropertyID::kScrollPaddingBottom,
CSSPropertyID::kScrollPaddingInlineEnd,
CSSPropertyID::kScrollPaddingInlineStart,
CSSPropertyID::kScrollPaddingLeft,
CSSPropertyID::kScrollPaddingRight,
CSSPropertyID::kScrollPaddingTop,
CSSPropertyID::kPaddingBlockEnd,
CSSPropertyID::kPaddingBlockStart,
CSSPropertyID::kPaddingInlineEnd,
CSSPropertyID::kPaddingInlineStart,
CSSPropertyID::kShapeMargin,
CSSPropertyID::kR,
CSSPropertyID::kRx,
CSSPropertyID::kRy,
CSSPropertyID::kBottom,
CSSPropertyID::kCx,
CSSPropertyID::kCy,
CSSPropertyID::kLeft,
CSSPropertyID::kMarginBottom,
CSSPropertyID::kMarginLeft,
CSSPropertyID::kMarginRight,
CSSPropertyID::kMarginTop,
CSSPropertyID::kOffsetDistance,
CSSPropertyID::kRight,
CSSPropertyID::kTop,
CSSPropertyID::kMarginBlockEnd,
CSSPropertyID::kMarginBlockStart,
CSSPropertyID::kMarginInlineEnd,
CSSPropertyID::kMarginInlineStart,
CSSPropertyID::kX,
CSSPropertyID::kY,
}};
// A subset of the above.
static CSSBitset accept_negative{
{CSSPropertyID::kBottom, CSSPropertyID::kCx, CSSPropertyID::kCy,
CSSPropertyID::kLeft, CSSPropertyID::kMarginBottom,
CSSPropertyID::kMarginLeft, CSSPropertyID::kMarginRight,
CSSPropertyID::kMarginTop, CSSPropertyID::kOffsetDistance,
CSSPropertyID::kRight, CSSPropertyID::kTop,
CSSPropertyID::kMarginBlockEnd, CSSPropertyID::kMarginBlockStart,
CSSPropertyID::kMarginInlineEnd, CSSPropertyID::kMarginInlineStart,
CSSPropertyID::kX, CSSPropertyID::kY}};
accepts_negative_numbers = accept_negative.Has(property_id);
if (accepts_negative_numbers) {
DCHECK(properties.Has(property_id));
}
return properties.Has(property_id);
}
template <typename CharacterType>
@ -194,49 +205,44 @@ static inline bool ParseSimpleAngle(const CharacterType* characters,
}
static inline bool IsColorPropertyID(CSSPropertyID property_id) {
switch (property_id) {
case CSSPropertyID::kCaretColor:
case CSSPropertyID::kColor:
case CSSPropertyID::kBackgroundColor:
case CSSPropertyID::kBorderBottomColor:
case CSSPropertyID::kBorderLeftColor:
case CSSPropertyID::kBorderRightColor:
case CSSPropertyID::kBorderTopColor:
case CSSPropertyID::kFill:
case CSSPropertyID::kFloodColor:
case CSSPropertyID::kLightingColor:
case CSSPropertyID::kOutlineColor:
case CSSPropertyID::kStopColor:
case CSSPropertyID::kStroke:
case CSSPropertyID::kBorderBlockEndColor:
case CSSPropertyID::kBorderBlockStartColor:
case CSSPropertyID::kBorderInlineEndColor:
case CSSPropertyID::kBorderInlineStartColor:
case CSSPropertyID::kColumnRuleColor:
case CSSPropertyID::kTextEmphasisColor:
case CSSPropertyID::kWebkitTextFillColor:
case CSSPropertyID::kWebkitTextStrokeColor:
case CSSPropertyID::kTextDecorationColor:
return true;
default:
return false;
}
static CSSBitset properties{{
CSSPropertyID::kCaretColor,
CSSPropertyID::kColor,
CSSPropertyID::kBackgroundColor,
CSSPropertyID::kBorderBottomColor,
CSSPropertyID::kBorderLeftColor,
CSSPropertyID::kBorderRightColor,
CSSPropertyID::kBorderTopColor,
CSSPropertyID::kFill,
CSSPropertyID::kFloodColor,
CSSPropertyID::kLightingColor,
CSSPropertyID::kOutlineColor,
CSSPropertyID::kStopColor,
CSSPropertyID::kStroke,
CSSPropertyID::kBorderBlockEndColor,
CSSPropertyID::kBorderBlockStartColor,
CSSPropertyID::kBorderInlineEndColor,
CSSPropertyID::kBorderInlineStartColor,
CSSPropertyID::kColumnRuleColor,
CSSPropertyID::kTextEmphasisColor,
CSSPropertyID::kWebkitTextFillColor,
CSSPropertyID::kWebkitTextStrokeColor,
CSSPropertyID::kTextDecorationColor,
}};
return properties.Has(property_id);
}
// https://quirks.spec.whatwg.org/#the-hashless-hex-color-quirk
static inline bool ColorPropertyAllowsQuirkyColor(CSSPropertyID property_id) {
switch (property_id) {
case CSSPropertyID::kColor:
case CSSPropertyID::kBackgroundColor:
case CSSPropertyID::kBorderBottomColor:
case CSSPropertyID::kBorderLeftColor:
case CSSPropertyID::kBorderRightColor:
case CSSPropertyID::kBorderTopColor:
return true;
default:
DCHECK(IsColorPropertyID(property_id));
return false;
}
static CSSBitset properties{{
CSSPropertyID::kColor,
CSSPropertyID::kBackgroundColor,
CSSPropertyID::kBorderBottomColor,
CSSPropertyID::kBorderLeftColor,
CSSPropertyID::kBorderRightColor,
CSSPropertyID::kBorderTopColor,
}};
return properties.Has(property_id);
}
// Returns the number of initial characters which form a valid double.
@ -1268,126 +1274,121 @@ bool CSSParserFastPaths::IsValidKeywordPropertyAndValue(
}
}
bool CSSParserFastPaths::IsHandledByKeywordFastPath(CSSPropertyID property_id) {
// NOTE: This list must match exactly those properties handled by
// IsValidKeywordPropertyAndValue().
switch (property_id) {
case CSSPropertyID::kAlignmentBaseline:
case CSSPropertyID::kAll:
case CSSPropertyID::kMixBlendMode:
case CSSPropertyID::kIsolation:
case CSSPropertyID::kBackgroundRepeatX:
case CSSPropertyID::kBackgroundRepeatY:
case CSSPropertyID::kBorderBottomStyle:
case CSSPropertyID::kBorderCollapse:
case CSSPropertyID::kBorderLeftStyle:
case CSSPropertyID::kBorderRightStyle:
case CSSPropertyID::kBorderTopStyle:
case CSSPropertyID::kBoxSizing:
case CSSPropertyID::kBufferedRendering:
case CSSPropertyID::kCaptionSide:
case CSSPropertyID::kClear:
case CSSPropertyID::kClipRule:
case CSSPropertyID::kColorInterpolation:
case CSSPropertyID::kColorInterpolationFilters:
case CSSPropertyID::kColorRendering:
case CSSPropertyID::kDirection:
case CSSPropertyID::kDominantBaseline:
case CSSPropertyID::kEmptyCells:
case CSSPropertyID::kFillRule:
case CSSPropertyID::kFloat:
case CSSPropertyID::kForcedColorAdjust:
case CSSPropertyID::kHyphens:
case CSSPropertyID::kImageRendering:
case CSSPropertyID::kListStylePosition:
case CSSPropertyID::kMaskType:
case CSSPropertyID::kMathShift:
case CSSPropertyID::kMathStyle:
case CSSPropertyID::kObjectFit:
case CSSPropertyID::kOutlineStyle:
case CSSPropertyID::kOverflowAnchor:
case CSSPropertyID::kOverflowBlock:
case CSSPropertyID::kOverflowInline:
case CSSPropertyID::kOverflowWrap:
case CSSPropertyID::kOverflowX:
case CSSPropertyID::kOverflowY:
case CSSPropertyID::kBreakAfter:
case CSSPropertyID::kBreakBefore:
case CSSPropertyID::kBreakInside:
case CSSPropertyID::kPageOrientation:
case CSSPropertyID::kPointerEvents:
case CSSPropertyID::kPosition:
case CSSPropertyID::kResize:
case CSSPropertyID::kScrollBehavior:
case CSSPropertyID::kOverscrollBehaviorInline:
case CSSPropertyID::kOverscrollBehaviorBlock:
case CSSPropertyID::kOverscrollBehaviorX:
case CSSPropertyID::kOverscrollBehaviorY:
case CSSPropertyID::kRubyPosition:
case CSSPropertyID::kShapeRendering:
case CSSPropertyID::kSpeak:
case CSSPropertyID::kStrokeLinecap:
case CSSPropertyID::kStrokeLinejoin:
case CSSPropertyID::kTableLayout:
case CSSPropertyID::kTextAlign:
case CSSPropertyID::kTextAlignLast:
case CSSPropertyID::kTextAnchor:
case CSSPropertyID::kTextCombineUpright:
case CSSPropertyID::kTextDecorationStyle:
case CSSPropertyID::kTextDecorationSkipInk:
case CSSPropertyID::kTextOrientation:
case CSSPropertyID::kWebkitTextOrientation:
case CSSPropertyID::kTextOverflow:
case CSSPropertyID::kTextRendering:
case CSSPropertyID::kTextTransform:
case CSSPropertyID::kUnicodeBidi:
case CSSPropertyID::kVectorEffect:
case CSSPropertyID::kVisibility:
case CSSPropertyID::kAppRegion:
case CSSPropertyID::kBackfaceVisibility:
case CSSPropertyID::kBorderBlockEndStyle:
case CSSPropertyID::kBorderBlockStartStyle:
case CSSPropertyID::kBorderInlineEndStyle:
case CSSPropertyID::kBorderInlineStartStyle:
case CSSPropertyID::kWebkitBoxAlign:
case CSSPropertyID::kWebkitBoxDecorationBreak:
case CSSPropertyID::kWebkitBoxDirection:
case CSSPropertyID::kWebkitBoxOrient:
case CSSPropertyID::kWebkitBoxPack:
case CSSPropertyID::kColumnFill:
case CSSPropertyID::kColumnRuleStyle:
case CSSPropertyID::kFlexDirection:
case CSSPropertyID::kFlexWrap:
case CSSPropertyID::kFontKerning:
case CSSPropertyID::kFontOpticalSizing:
case CSSPropertyID::kFontSynthesisWeight:
case CSSPropertyID::kFontSynthesisStyle:
case CSSPropertyID::kFontSynthesisSmallCaps:
case CSSPropertyID::kWebkitFontSmoothing:
case CSSPropertyID::kLineBreak:
case CSSPropertyID::kWebkitLineBreak:
case CSSPropertyID::kWebkitPrintColorAdjust:
case CSSPropertyID::kWebkitRtlOrdering:
case CSSPropertyID::kWebkitRubyPosition:
case CSSPropertyID::kWebkitTextCombine:
case CSSPropertyID::kWebkitTextSecurity:
case CSSPropertyID::kTransformBox:
case CSSPropertyID::kTransformStyle:
case CSSPropertyID::kWebkitUserDrag:
case CSSPropertyID::kWebkitUserModify:
case CSSPropertyID::kUserSelect:
case CSSPropertyID::kWebkitWritingMode:
case CSSPropertyID::kWhiteSpace:
case CSSPropertyID::kWordBreak:
case CSSPropertyID::kWritingMode:
case CSSPropertyID::kScrollbarWidth:
case CSSPropertyID::kScrollSnapStop:
case CSSPropertyID::kOriginTrialTestProperty:
return true;
default:
return false;
}
}
// NOTE: This list must match exactly those properties handled by
// IsValidKeywordPropertyAndValue().
CSSBitset CSSParserFastPaths::handled_by_keyword_fast_paths_properties_{{
CSSPropertyID::kAlignmentBaseline,
CSSPropertyID::kAll,
CSSPropertyID::kMixBlendMode,
CSSPropertyID::kIsolation,
CSSPropertyID::kBackgroundRepeatX,
CSSPropertyID::kBackgroundRepeatY,
CSSPropertyID::kBorderBottomStyle,
CSSPropertyID::kBorderCollapse,
CSSPropertyID::kBorderLeftStyle,
CSSPropertyID::kBorderRightStyle,
CSSPropertyID::kBorderTopStyle,
CSSPropertyID::kBoxSizing,
CSSPropertyID::kBufferedRendering,
CSSPropertyID::kCaptionSide,
CSSPropertyID::kClear,
CSSPropertyID::kClipRule,
CSSPropertyID::kColorInterpolation,
CSSPropertyID::kColorInterpolationFilters,
CSSPropertyID::kColorRendering,
CSSPropertyID::kDirection,
CSSPropertyID::kDominantBaseline,
CSSPropertyID::kEmptyCells,
CSSPropertyID::kFillRule,
CSSPropertyID::kFloat,
CSSPropertyID::kForcedColorAdjust,
CSSPropertyID::kHyphens,
CSSPropertyID::kImageRendering,
CSSPropertyID::kListStylePosition,
CSSPropertyID::kMaskType,
CSSPropertyID::kMathShift,
CSSPropertyID::kMathStyle,
CSSPropertyID::kObjectFit,
CSSPropertyID::kOutlineStyle,
CSSPropertyID::kOverflowAnchor,
CSSPropertyID::kOverflowBlock,
CSSPropertyID::kOverflowInline,
CSSPropertyID::kOverflowWrap,
CSSPropertyID::kOverflowX,
CSSPropertyID::kOverflowY,
CSSPropertyID::kBreakAfter,
CSSPropertyID::kBreakBefore,
CSSPropertyID::kBreakInside,
CSSPropertyID::kPageOrientation,
CSSPropertyID::kPointerEvents,
CSSPropertyID::kPosition,
CSSPropertyID::kResize,
CSSPropertyID::kScrollBehavior,
CSSPropertyID::kOverscrollBehaviorInline,
CSSPropertyID::kOverscrollBehaviorBlock,
CSSPropertyID::kOverscrollBehaviorX,
CSSPropertyID::kOverscrollBehaviorY,
CSSPropertyID::kRubyPosition,
CSSPropertyID::kShapeRendering,
CSSPropertyID::kSpeak,
CSSPropertyID::kStrokeLinecap,
CSSPropertyID::kStrokeLinejoin,
CSSPropertyID::kTableLayout,
CSSPropertyID::kTextAlign,
CSSPropertyID::kTextAlignLast,
CSSPropertyID::kTextAnchor,
CSSPropertyID::kTextCombineUpright,
CSSPropertyID::kTextDecorationStyle,
CSSPropertyID::kTextDecorationSkipInk,
CSSPropertyID::kTextOrientation,
CSSPropertyID::kWebkitTextOrientation,
CSSPropertyID::kTextOverflow,
CSSPropertyID::kTextRendering,
CSSPropertyID::kTextTransform,
CSSPropertyID::kUnicodeBidi,
CSSPropertyID::kVectorEffect,
CSSPropertyID::kVisibility,
CSSPropertyID::kAppRegion,
CSSPropertyID::kBackfaceVisibility,
CSSPropertyID::kBorderBlockEndStyle,
CSSPropertyID::kBorderBlockStartStyle,
CSSPropertyID::kBorderInlineEndStyle,
CSSPropertyID::kBorderInlineStartStyle,
CSSPropertyID::kWebkitBoxAlign,
CSSPropertyID::kWebkitBoxDecorationBreak,
CSSPropertyID::kWebkitBoxDirection,
CSSPropertyID::kWebkitBoxOrient,
CSSPropertyID::kWebkitBoxPack,
CSSPropertyID::kColumnFill,
CSSPropertyID::kColumnRuleStyle,
CSSPropertyID::kFlexDirection,
CSSPropertyID::kFlexWrap,
CSSPropertyID::kFontKerning,
CSSPropertyID::kFontOpticalSizing,
CSSPropertyID::kFontSynthesisWeight,
CSSPropertyID::kFontSynthesisStyle,
CSSPropertyID::kFontSynthesisSmallCaps,
CSSPropertyID::kWebkitFontSmoothing,
CSSPropertyID::kLineBreak,
CSSPropertyID::kWebkitLineBreak,
CSSPropertyID::kWebkitPrintColorAdjust,
CSSPropertyID::kWebkitRtlOrdering,
CSSPropertyID::kWebkitRubyPosition,
CSSPropertyID::kWebkitTextCombine,
CSSPropertyID::kWebkitTextSecurity,
CSSPropertyID::kTransformBox,
CSSPropertyID::kTransformStyle,
CSSPropertyID::kWebkitUserDrag,
CSSPropertyID::kWebkitUserModify,
CSSPropertyID::kUserSelect,
CSSPropertyID::kWebkitWritingMode,
CSSPropertyID::kWhiteSpace,
CSSPropertyID::kWordBreak,
CSSPropertyID::kWritingMode,
CSSPropertyID::kScrollbarWidth,
CSSPropertyID::kScrollSnapStop,
CSSPropertyID::kOriginTrialTestProperty,
}};
bool CSSParserFastPaths::IsValidSystemFont(CSSValueID value_id) {
return value_id >= CSSValueID::kCaption && value_id <= CSSValueID::kStatusBar;

@ -7,6 +7,7 @@
#include "third_party/blink/renderer/core/core_export.h"
#include "third_party/blink/renderer/core/css/css_property_names.h"
#include "third_party/blink/renderer/core/css/properties/css_bitset.h"
#include "third_party/blink/renderer/core/css_value_keywords.h"
#include "third_party/blink/renderer/platform/graphics/color.h"
#include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"
@ -26,7 +27,9 @@ class CORE_EXPORT CSSParserFastPaths {
// NOTE: Properties handled here shouldn't be explicitly handled in
// CSSPropertyParser, so if this returns true, the fast path is the only path.
static bool IsHandledByKeywordFastPath(CSSPropertyID);
static bool IsHandledByKeywordFastPath(CSSPropertyID property_id) {
return handled_by_keyword_fast_paths_properties_.Has(property_id);
}
static bool IsValidKeywordPropertyAndValue(CSSPropertyID,
CSSValueID,
@ -35,6 +38,9 @@ class CORE_EXPORT CSSParserFastPaths {
static bool IsValidSystemFont(CSSValueID);
static CSSValue* ParseColor(const String&, CSSParserMode);
private:
static CSSBitset handled_by_keyword_fast_paths_properties_;
};
} // namespace blink

@ -38,15 +38,12 @@ class CORE_EXPORT CSSBitsetBase {
CSSBitsetBase() : chunks_() {}
CSSBitsetBase(const CSSBitsetBase<kBits>& o) { *this = o; }
CSSBitsetBase(std::initializer_list<CSSPropertyID> list) : chunks_() {
for (CSSPropertyID id : list)
Set(id);
}
// This exists really only for generated code to be able to create global
// (const) objects without requiring global constructors.
explicit constexpr CSSBitsetBase(const std::array<uint64_t, kChunks>& chunks)
: chunks_{chunks} {}
// This slightly weird construction helps Clang make an actual
// compile-time static value, until we have constinit.
template <int N>
explicit constexpr CSSBitsetBase(const CSSPropertyID (&list)[N])
: chunks_(CreateChunks(list)) {}
CSSBitsetBase& operator=(const CSSBitsetBase& o) = default;
@ -54,21 +51,21 @@ class CORE_EXPORT CSSBitsetBase {
bool operator!=(const CSSBitsetBase& o) const { return !(*this == o); }
inline void Set(CSSPropertyID id) {
size_t bit = static_cast<size_t>(id);
size_t bit = static_cast<size_t>(static_cast<unsigned>(id));
DCHECK_LT(bit, kBits);
chunks_[bit / 64] |= (1ull << (bit % 64));
chunks_.data()[bit / 64] |= (1ull << (bit % 64));
}
inline void Or(CSSPropertyID id, bool v) {
size_t bit = static_cast<size_t>(id);
size_t bit = static_cast<size_t>(static_cast<unsigned>(id));
DCHECK_LT(bit, kBits);
chunks_[bit / 64] |= (static_cast<uint64_t>(v) << (bit % 64));
chunks_.data()[bit / 64] |= (static_cast<uint64_t>(v) << (bit % 64));
}
inline bool Has(CSSPropertyID id) const {
size_t bit = static_cast<size_t>(id);
size_t bit = static_cast<size_t>(static_cast<unsigned>(id));
DCHECK_LT(bit, kBits);
return chunks_[bit / 64] & (1ull << (bit % 64));
return chunks_.data()[bit / 64] & (1ull << (bit % 64));
}
inline bool HasAny() const {
@ -144,6 +141,17 @@ class CORE_EXPORT CSSBitsetBase {
private:
std::array<uint64_t, kChunks> chunks_;
template <int N>
static constexpr std::array<uint64_t, kChunks> CreateChunks(
const CSSPropertyID (&list)[N]) {
std::array<uint64_t, kChunks> chunks{};
for (CSSPropertyID id : list) {
unsigned bit = static_cast<unsigned>(id);
chunks[bit / 64] |= uint64_t{1} << (bit % 64);
}
return chunks;
}
};
using CSSBitset = CSSBitsetBase<kNumCSSPropertyIDs>;