Line data Source code
1 : // Copyright 2018 the V8 project authors. All rights reserved.
2 : // Use of this source code is governed by a BSD-style license that can be
3 : // found in the LICENSE file.
4 :
5 : #ifndef V8_OBJECTS_SLOTS_ATOMIC_INL_H_
6 : #define V8_OBJECTS_SLOTS_ATOMIC_INL_H_
7 :
8 : #include "src/base/atomic-utils.h"
9 : #include "src/objects/compressed-slots.h"
10 : #include "src/objects/slots.h"
11 :
12 : namespace v8 {
13 : namespace internal {
14 :
15 : // This class is intended to be used as a wrapper for elements of an array
16 : // that is passed in to STL functions such as std::sort. It ensures that
17 : // elements accesses are atomic.
18 : // Usage example:
19 : // FixedArray array;
20 : // AtomicSlot start(array->GetFirstElementAddress());
21 : // std::sort(start, start + given_length,
22 : // [](Tagged_t a, Tagged_t b) {
23 : // // Decompress a and b if necessary.
24 : // return my_comparison(a, b);
25 : // });
26 : // Note how the comparator operates on Tagged_t values, representing the raw
27 : // data found at the given heap location, so you probably want to construct
28 : // an Object from it.
29 : class AtomicSlot : public SlotBase<AtomicSlot, Tagged_t> {
30 : public:
31 : // This class is a stand-in for "Address&" that uses custom atomic
32 : // read/write operations for the actual memory accesses.
33 : class Reference {
34 : public:
35 : explicit Reference(Tagged_t* address) : address_(address) {}
36 : Reference(const Reference&) V8_NOEXCEPT = default;
37 :
38 39677610 : Reference& operator=(const Reference& other) V8_NOEXCEPT {
39 39677610 : AsAtomicTagged::Relaxed_Store(
40 39677610 : address_, AsAtomicTagged::Relaxed_Load(other.address_));
41 39677610 : return *this;
42 : }
43 : Reference& operator=(Tagged_t value) {
44 : AsAtomicTagged::Relaxed_Store(address_, value);
45 : return *this;
46 : }
47 :
48 : // Values of type AtomicSlot::reference must be implicitly convertible
49 : // to AtomicSlot::value_type.
50 : operator Tagged_t() const { return AsAtomicTagged::Relaxed_Load(address_); }
51 :
52 17396274 : void swap(Reference& other) {
53 : Tagged_t tmp = value();
54 17396274 : AsAtomicTagged::Relaxed_Store(address_, other.value());
55 17396274 : AsAtomicTagged::Relaxed_Store(other.address_, tmp);
56 17396274 : }
57 :
58 : bool operator<(const Reference& other) const {
59 : return value() < other.value();
60 : }
61 :
62 : bool operator==(const Reference& other) const {
63 : return value() == other.value();
64 : }
65 :
66 : private:
67 34792548 : Tagged_t value() const { return AsAtomicTagged::Relaxed_Load(address_); }
68 :
69 : Tagged_t* address_;
70 : };
71 :
72 : // The rest of this class follows C++'s "RandomAccessIterator" requirements.
73 : // Most of the heavy lifting is inherited from SlotBase.
74 : using difference_type = int;
75 : using value_type = Tagged_t;
76 : using reference = Reference;
77 : using pointer = void*; // Must be present, but should not be used.
78 : using iterator_category = std::random_access_iterator_tag;
79 :
80 : AtomicSlot() : SlotBase(kNullAddress) {}
81 : explicit AtomicSlot(Address address) : SlotBase(address) {}
82 : explicit AtomicSlot(ObjectSlot slot) : SlotBase(slot.address()) {}
83 :
84 : Reference operator*() const {
85 368319633 : return Reference(reinterpret_cast<Tagged_t*>(address()));
86 : }
87 : Reference operator[](difference_type i) const {
88 : return Reference(reinterpret_cast<Tagged_t*>(address() + i * kTaggedSize));
89 : }
90 :
91 17396290 : friend void swap(Reference lhs, Reference rhs) { lhs.swap(rhs); }
92 :
93 : friend difference_type operator-(AtomicSlot a, AtomicSlot b) {
94 6054205 : return static_cast<int>(a.address() - b.address()) / kTaggedSize;
95 : }
96 : };
97 :
98 : } // namespace internal
99 : } // namespace v8
100 :
101 : #endif // V8_OBJECTS_SLOTS_ATOMIC_INL_H_
|