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