Flutter Engine
The Flutter Engine
Loading...
Searching...
No Matches
bitfield.h
Go to the documentation of this file.
1// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
2// for details. All rights reserved. Use of this source code is governed by a
3// BSD-style license that can be found in the LICENSE file.
4
5#ifndef RUNTIME_VM_BITFIELD_H_
6#define RUNTIME_VM_BITFIELD_H_
7
8#include <type_traits>
9
10#include "platform/assert.h"
11#include "platform/atomic.h"
12#include "platform/globals.h"
14
15namespace dart {
16
18 private:
19 AtomicBitFieldContainerBase() = delete; // Only used for std::is_base_of.
20};
21
22template <typename T>
24 static_assert(sizeof(std::atomic<T>) == sizeof(T),
25 "Size of type changes when made atomic");
26
27 public:
29
30 AtomicBitFieldContainer() : field_(0) {}
31
32 operator T() const { return field_.load(std::memory_order_relaxed); }
33 T operator=(T tags) {
34 field_.store(tags, std::memory_order_relaxed);
35 return tags;
36 }
37
38 T load(std::memory_order order) const { return field_.load(order); }
39 void store(T value, std::memory_order order) { field_.store(value, order); }
40
41 bool compare_exchange_weak(T old_tags, T new_tags, std::memory_order order) {
42 return field_.compare_exchange_weak(old_tags, new_tags, order);
43 }
44
45 template <class TargetBitField,
46 std::memory_order order = std::memory_order_relaxed>
47 typename TargetBitField::Type Read() const {
48 return TargetBitField::decode(field_.load(order));
49 }
50
51 template <class TargetBitField>
52 NO_SANITIZE_THREAD typename TargetBitField::Type ReadIgnoreRace() const {
53 return TargetBitField::decode(*reinterpret_cast<const T*>(&field_));
54 }
55
56 template <class TargetBitField,
57 std::memory_order order = std::memory_order_relaxed>
58 void UpdateBool(bool value) {
59 if (value) {
60 field_.fetch_or(TargetBitField::encode(true), order);
61 } else {
62 field_.fetch_and(~TargetBitField::encode(true), order);
63 }
64 }
65
66 template <class TargetBitField>
67 void FetchOr(typename TargetBitField::Type value) {
68 field_.fetch_or(TargetBitField::encode(value), std::memory_order_relaxed);
69 }
70
71 template <class TargetBitField>
72 void Update(typename TargetBitField::Type value) {
73 T old_field = field_.load(std::memory_order_relaxed);
74 T new_field;
75 do {
76 new_field = TargetBitField::update(value, old_field);
77 } while (!field_.compare_exchange_weak(old_field, new_field,
78 std::memory_order_relaxed));
79 }
80
81 template <class TargetBitField>
82 void UpdateUnsynchronized(typename TargetBitField::Type value) {
83 field_.store(
84 TargetBitField::update(value, field_.load(std::memory_order_relaxed)),
85 std::memory_order_relaxed);
86 }
87
88 template <class TargetBitField>
89 typename TargetBitField::Type UpdateConditional(
90 typename TargetBitField::Type value_to_be_set,
91 typename TargetBitField::Type conditional_old_value) {
92 T old_field = field_.load(std::memory_order_relaxed);
93 while (true) {
94 // This operation is only performed if the condition is met.
95 auto old_value = TargetBitField::decode(old_field);
96 if (old_value != conditional_old_value) {
97 return old_value;
98 }
99 T new_tags = TargetBitField::update(value_to_be_set, old_field);
100 if (field_.compare_exchange_weak(old_field, new_tags,
101 std::memory_order_relaxed)) {
102 return value_to_be_set;
103 }
104 // [old_tags] was updated to it's current value.
105 }
106 }
107
108 template <class TargetBitField>
109 bool TryAcquire() {
110 T mask = TargetBitField::encode(true);
111 T old_field = field_.fetch_or(mask, std::memory_order_relaxed);
112 return !TargetBitField::decode(old_field);
113 }
114
115 template <class TargetBitField>
116 bool TryClear() {
117 T mask = ~TargetBitField::encode(true);
118 T old_field = field_.fetch_and(mask, std::memory_order_relaxed);
119 return TargetBitField::decode(old_field);
120 }
121
122 private:
123 std::atomic<T> field_;
124};
125
126static constexpr uword kUwordOne = 1U;
127
128// BitField is a template for encoding and decoding a value of type T
129// inside a storage of type S.
130template <typename S,
131 typename T,
132 int position,
133 int size = (sizeof(S) * kBitsPerByte) - position,
134 bool sign_extend = false,
135 typename Enable = void>
136class BitField {
137 public:
138 typedef T Type;
139
140 static_assert((sizeof(S) * kBitsPerByte) >= (position + size),
141 "BitField does not fit into the type.");
142 static_assert(!sign_extend || std::is_signed<T>::value,
143 "Should only sign extend signed bitfield types");
144
145 static constexpr intptr_t kNextBit = position + size;
146
147 // Tells whether the provided value fits into the bit field.
148 static constexpr bool is_valid(T value) {
149 return decode(encode_unchecked(value)) == value;
150 }
151
152 // Returns a S mask of the bit field.
153 static constexpr S mask() { return (kUwordOne << size) - 1; }
154
155 // Returns a S mask of the bit field which can be applied directly to
156 // to the raw unshifted bits.
157 static constexpr S mask_in_place() { return mask() << position; }
158
159 // Returns the shift count needed to right-shift the bit field to
160 // the least-significant bits.
161 static constexpr int shift() { return position; }
162
163 // Returns the size of the bit field.
164 static constexpr int bitsize() { return size; }
165
166 // Returns an S with the bit field value encoded.
167 static constexpr S encode(T value) {
169 return encode_unchecked(value);
170 }
171
172 // Extracts the bit field from the value.
173 static constexpr T decode(S value) {
174 // Ensure we slide down the sign bit if the value in the bit field is signed
175 // and negative. We use 64-bit ints inside the expression since we can have
176 // both cases: sizeof(S) > sizeof(T) or sizeof(S) < sizeof(T).
177 if constexpr (sign_extend) {
178 auto const u = static_cast<uint64_t>(value);
179 return static_cast<T>((static_cast<int64_t>(u << (64 - kNextBit))) >>
180 (64 - size));
181 } else {
182 auto const u = static_cast<typename std::make_unsigned<S>::type>(value);
183 return static_cast<T>((u >> position) & mask());
184 }
185 }
186
187 // Returns an S with the bit field value encoded based on the
188 // original value. Only the bits corresponding to this bit field
189 // will be changed.
190 static constexpr S update(T value, S original) {
191 return encode(value) | (~mask_in_place() & original);
192 }
193
194 private:
195 // Returns an S with the bit field value encoded.
196 static constexpr S encode_unchecked(T value) {
197 auto const u = static_cast<typename std::make_unsigned<S>::type>(value);
198 return (u & mask()) << position;
199 }
200};
201
202// Partial instantiations to avoid having to change BitField declarations if
203// S is decltype(field_) and the type of field_ is changed to be wrapped in an
204// AtomicBitFieldContainer.
205template <typename S, typename T, int position, int size, bool sign_extend>
207 T,
208 position,
209 size,
211 typename std::enable_if<
212 std::is_base_of<AtomicBitFieldContainerBase, S>::value,
213 void>::type> : public BitField<typename S::ContainedType,
214 T,
215 position,
216 size,
217 sign_extend> {};
218
219template <typename S, typename T, int position, int size>
221 T,
222 position,
223 size,
224 false,
225 typename std::enable_if<
226 std::is_base_of<AtomicBitFieldContainerBase, S>::value,
227 void>::type>
228 : public BitField<typename S::ContainedType, T, position, size, false> {};
229
230} // namespace dart
231
232#endif // RUNTIME_VM_BITFIELD_H_
static void encode(uint8_t output[16], const uint32_t input[4])
Definition SkMD5.cpp:240
void UpdateBool(bool value)
Definition bitfield.h:58
void FetchOr(typename TargetBitField::Type value)
Definition bitfield.h:67
TargetBitField::Type UpdateConditional(typename TargetBitField::Type value_to_be_set, typename TargetBitField::Type conditional_old_value)
Definition bitfield.h:89
void UpdateUnsynchronized(typename TargetBitField::Type value)
Definition bitfield.h:82
bool compare_exchange_weak(T old_tags, T new_tags, std::memory_order order)
Definition bitfield.h:41
void store(T value, std::memory_order order)
Definition bitfield.h:39
void Update(typename TargetBitField::Type value)
Definition bitfield.h:72
T load(std::memory_order order) const
Definition bitfield.h:38
NO_SANITIZE_THREAD TargetBitField::Type ReadIgnoreRace() const
Definition bitfield.h:52
TargetBitField::Type Read() const
Definition bitfield.h:47
static constexpr int bitsize()
Definition bitfield.h:164
static constexpr intptr_t kNextBit
Definition bitfield.h:145
static constexpr T decode(S value)
Definition bitfield.h:173
static constexpr S update(T value, S original)
Definition bitfield.h:190
static constexpr S mask_in_place()
Definition bitfield.h:157
static constexpr S mask()
Definition bitfield.h:153
static constexpr S encode(T value)
Definition bitfield.h:167
static constexpr bool is_valid(T value)
Definition bitfield.h:148
static constexpr int shift()
Definition bitfield.h:161
#define ASSERT(E)
uint8_t value
constexpr intptr_t kBitsPerByte
Definition globals.h:463
uintptr_t uword
Definition globals.h:501
intx_t sign_extend(int32_t x)
static constexpr uword kUwordOne
Definition bitfield.h:126
Definition ref_ptr.h:256
#define T
#define NO_SANITIZE_THREAD