1014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch// Copyright 2015 the V8 project authors. All rights reserved.
2014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch// Use of this source code is governed by a BSD-style license that can be
3014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch// found in the LICENSE file.
4014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
5014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#ifndef V8_ATOMIC_UTILS_H_
6014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#define V8_ATOMIC_UTILS_H_
7014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
8014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#include <limits.h>
9014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
10014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#include "src/base/atomicops.h"
11014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#include "src/base/macros.h"
12014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
13014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochnamespace v8 {
14bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdochnamespace base {
15014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
16014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochtemplate <class T>
17014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochclass AtomicNumber {
18014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch public:
19014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  AtomicNumber() : value_(0) {}
20014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  explicit AtomicNumber(T initial) : value_(initial) {}
21014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
22f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  // Returns the value after incrementing.
23014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  V8_INLINE T Increment(T increment) {
24014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    return static_cast<T>(base::Barrier_AtomicIncrement(
25014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        &value_, static_cast<base::AtomicWord>(increment)));
26014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
27014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
28f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  // Returns the value after decrementing.
29f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  V8_INLINE T Decrement(T decrement) {
30f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    return static_cast<T>(base::Barrier_AtomicIncrement(
31f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch        &value_, -static_cast<base::AtomicWord>(decrement)));
32f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  }
33f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
3462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  V8_INLINE T Value() const {
3562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    return static_cast<T>(base::Acquire_Load(&value_));
3662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  }
37014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
38014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  V8_INLINE void SetValue(T new_value) {
39014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    base::Release_Store(&value_, static_cast<base::AtomicWord>(new_value));
40014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
41014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
42014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  V8_INLINE T operator=(T value) {
43014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    SetValue(value);
44014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    return value;
45014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
46014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
47f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  V8_INLINE T operator+=(T value) { return Increment(value); }
48f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  V8_INLINE T operator-=(T value) { return Decrement(value); }
49f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
50014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch private:
51014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  STATIC_ASSERT(sizeof(T) <= sizeof(base::AtomicWord));
52014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
53014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  base::AtomicWord value_;
54014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch};
55014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
56c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch// This type uses no barrier accessors to change atomic word. Be careful with
57c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch// data races.
58c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdochtemplate <typename T>
59c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdochclass NoBarrierAtomicValue {
60c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch public:
61c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  NoBarrierAtomicValue() : value_(0) {}
62c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch
63c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  explicit NoBarrierAtomicValue(T initial)
64c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch      : value_(cast_helper<T>::to_storage_type(initial)) {}
65c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch
66c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  static NoBarrierAtomicValue* FromAddress(void* address) {
67c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    return reinterpret_cast<base::NoBarrierAtomicValue<T>*>(address);
68c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  }
69c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch
70c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  V8_INLINE bool TrySetValue(T old_value, T new_value) {
71c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    return base::NoBarrier_CompareAndSwap(
72c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch               &value_, cast_helper<T>::to_storage_type(old_value),
73c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch               cast_helper<T>::to_storage_type(new_value)) ==
74c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch           cast_helper<T>::to_storage_type(old_value);
75c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  }
76c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch
77c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  V8_INLINE T Value() const {
78c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    return cast_helper<T>::to_return_type(base::NoBarrier_Load(&value_));
79c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  }
80c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch
81c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  V8_INLINE void SetValue(T new_value) {
82c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    base::NoBarrier_Store(&value_, cast_helper<T>::to_storage_type(new_value));
83c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  }
84c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch
85c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch private:
86c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  STATIC_ASSERT(sizeof(T) <= sizeof(base::AtomicWord));
87c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch
88c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  template <typename S>
89c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  struct cast_helper {
90c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    static base::AtomicWord to_storage_type(S value) {
91c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch      return static_cast<base::AtomicWord>(value);
92c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    }
93c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    static S to_return_type(base::AtomicWord value) {
94c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch      return static_cast<S>(value);
95c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    }
96c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  };
97c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch
98c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  template <typename S>
99c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  struct cast_helper<S*> {
100c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    static base::AtomicWord to_storage_type(S* value) {
101c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch      return reinterpret_cast<base::AtomicWord>(value);
102c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    }
103c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    static S* to_return_type(base::AtomicWord value) {
104c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch      return reinterpret_cast<S*>(value);
105c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    }
106c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  };
107c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch
108c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  base::AtomicWord value_;
109c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch};
110014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
111014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch// Flag using T atomically. Also accepts void* as T.
112014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochtemplate <typename T>
113014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochclass AtomicValue {
114014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch public:
115014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  AtomicValue() : value_(0) {}
116014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
117014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  explicit AtomicValue(T initial)
118014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      : value_(cast_helper<T>::to_storage_type(initial)) {}
119014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
120f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  V8_INLINE T Value() const {
121014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    return cast_helper<T>::to_return_type(base::Acquire_Load(&value_));
122014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
123014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
124014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  V8_INLINE bool TrySetValue(T old_value, T new_value) {
125014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    return base::Release_CompareAndSwap(
126014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch               &value_, cast_helper<T>::to_storage_type(old_value),
127014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch               cast_helper<T>::to_storage_type(new_value)) ==
128014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch           cast_helper<T>::to_storage_type(old_value);
129014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
130014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
131f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  V8_INLINE void SetBits(T bits, T mask) {
132c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    DCHECK_EQ(bits & ~mask, static_cast<T>(0));
133f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch    T old_value;
134f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch    T new_value;
135f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch    do {
136f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch      old_value = Value();
137f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch      new_value = (old_value & ~mask) | bits;
138f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch    } while (!TrySetValue(old_value, new_value));
139f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  }
140f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch
141f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  V8_INLINE void SetBit(int bit) {
142f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch    SetBits(static_cast<T>(1) << bit, static_cast<T>(1) << bit);
143f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  }
144f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch
145f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  V8_INLINE void ClearBit(int bit) { SetBits(0, 1 << bit); }
146f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch
147014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  V8_INLINE void SetValue(T new_value) {
148014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    base::Release_Store(&value_, cast_helper<T>::to_storage_type(new_value));
149014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
150014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
151014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch private:
152014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  STATIC_ASSERT(sizeof(T) <= sizeof(base::AtomicWord));
153014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
154014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  template <typename S>
155014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  struct cast_helper {
156014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    static base::AtomicWord to_storage_type(S value) {
157014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      return static_cast<base::AtomicWord>(value);
158014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    }
159014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    static S to_return_type(base::AtomicWord value) {
160014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      return static_cast<S>(value);
161014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    }
162014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  };
163014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
164014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  template <typename S>
165014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  struct cast_helper<S*> {
166014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    static base::AtomicWord to_storage_type(S* value) {
167014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      return reinterpret_cast<base::AtomicWord>(value);
168014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    }
169014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    static S* to_return_type(base::AtomicWord value) {
170014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      return reinterpret_cast<S*>(value);
171014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    }
172014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  };
173014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
174014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  base::AtomicWord value_;
175014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch};
176014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
177014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
178014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch// See utils.h for EnumSet. Storage is always base::AtomicWord.
179014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch// Requirements on E:
180014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch// - No explicit values.
181014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch// - E::kLastValue defined to be the last actually used value.
182014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch//
183014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch// Example:
184014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch// enum E { kA, kB, kC, kLastValue = kC };
185014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochtemplate <class E>
186014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochclass AtomicEnumSet {
187014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch public:
188014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  explicit AtomicEnumSet(base::AtomicWord bits = 0) : bits_(bits) {}
189014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
190014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  bool IsEmpty() const { return ToIntegral() == 0; }
191014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
192014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  bool Contains(E element) const { return (ToIntegral() & Mask(element)) != 0; }
193014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  bool ContainsAnyOf(const AtomicEnumSet& set) const {
194014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    return (ToIntegral() & set.ToIntegral()) != 0;
195014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
196014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
197014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void RemoveAll() { base::Release_Store(&bits_, 0); }
198014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
199014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  bool operator==(const AtomicEnumSet& set) const {
200014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    return ToIntegral() == set.ToIntegral();
201014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
202014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
203014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  bool operator!=(const AtomicEnumSet& set) const {
204014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    return ToIntegral() != set.ToIntegral();
205014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
206014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
207014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  AtomicEnumSet<E> operator|(const AtomicEnumSet& set) const {
208014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    return AtomicEnumSet<E>(ToIntegral() | set.ToIntegral());
209014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
210014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
211014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch// The following operations modify the underlying storage.
212014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
213014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#define ATOMIC_SET_WRITE(OP, NEW_VAL)                                     \
214014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  do {                                                                    \
215014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    base::AtomicWord old;                                                 \
216014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    do {                                                                  \
217014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      old = base::Acquire_Load(&bits_);                                   \
218014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    } while (base::Release_CompareAndSwap(&bits_, old, old OP NEW_VAL) != \
219014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch             old);                                                        \
220014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  } while (false)
221014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
222014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void Add(E element) { ATOMIC_SET_WRITE(|, Mask(element)); }
223014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
224014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void Add(const AtomicEnumSet& set) { ATOMIC_SET_WRITE(|, set.ToIntegral()); }
225014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
226014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void Remove(E element) { ATOMIC_SET_WRITE(&, ~Mask(element)); }
227014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
228014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void Remove(const AtomicEnumSet& set) {
229014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    ATOMIC_SET_WRITE(&, ~set.ToIntegral());
230014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
231014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
232014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void Intersect(const AtomicEnumSet& set) {
233014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    ATOMIC_SET_WRITE(&, set.ToIntegral());
234014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
235014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
236014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#undef ATOMIC_SET_OP
237014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
238014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch private:
239014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // Check whether there's enough storage to hold E.
240014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  STATIC_ASSERT(E::kLastValue < (sizeof(base::AtomicWord) * CHAR_BIT));
241014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
242014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  V8_INLINE base::AtomicWord ToIntegral() const {
243014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    return base::Acquire_Load(&bits_);
244014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
245014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
246014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  V8_INLINE base::AtomicWord Mask(E element) const {
247014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    return static_cast<base::AtomicWord>(1) << element;
248014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
249014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
250014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  base::AtomicWord bits_;
251014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch};
252014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
253bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch}  // namespace base
254014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}  // namespace v8
255014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
256014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#endif  // #define V8_ATOMIC_UTILS_H_
257