66
77namespace Memory
88{
9+ // Dummy tag classes to mark yes/no write barrier policy
10+ struct _write_barrier_policy {};
11+ struct _no_write_barrier_policy {};
12+
13+ // Type write barrier policy
14+ //
15+ // By default following potentially contains GC pointers and use write barrier policy:
16+ // pointer, WriteBarrierPtr, _write_barrier_policy
17+ //
18+ template <class T >
19+ struct TypeWriteBarrierPolicy { typedef _no_write_barrier_policy Policy; };
20+ template <class T >
21+ struct TypeWriteBarrierPolicy <T*> { typedef _write_barrier_policy Policy; };
22+ template <class T >
23+ struct TypeWriteBarrierPolicy <WriteBarrierPtr<T>> { typedef _write_barrier_policy Policy; };
24+ template <>
25+ struct TypeWriteBarrierPolicy <_write_barrier_policy> { typedef _write_barrier_policy Policy; };
26+
27+ // Combine AllocatorType and data type write barrier policy
28+ // Recycler allocator type + _write_barrier_policy data type => _write_barrier_policy
29+ //
30+ template <class AllocatorType , class TPolicy >
31+ struct AllocatorTypeWriteBarrierPolicy { typedef _no_write_barrier_policy Policy; };
32+ template <>
33+ struct AllocatorTypeWriteBarrierPolicy <Recycler, _write_barrier_policy>
34+ {
35+ typedef _write_barrier_policy Policy;
36+ };
37+
38+ // Combine Allocator + Data write barrier policy
39+ // RecyclerNonLeafAllocator, * => _write_barrier_policy
40+ //
41+ template <class Allocator , class T >
42+ struct AllocatorWriteBarrierPolicy
43+ {
44+ typedef typename AllocatorInfo<Allocator, void >::AllocatorType AllocatorType;
45+ typedef typename TypeWriteBarrierPolicy<T>::Policy TPolicy;
46+ typedef typename AllocatorTypeWriteBarrierPolicy<AllocatorType, TPolicy>::Policy Policy;
47+ };
48+ template <class T >
49+ struct AllocatorWriteBarrierPolicy <RecyclerNonLeafAllocator, T>
50+ {
51+ typedef _write_barrier_policy Policy;
52+ };
53+
54+ // Actual WriteBarrierPolicy behavior
55+ //
56+ template <class Policy >
57+ struct WriteBarrierPolicy
58+ {
59+ template <class Allocator , class T >
60+ static void WriteBarrier (WriteBarrierPtr<T, Allocator> * address) {}
61+
62+ template <class T >
63+ static void WriteBarrier (T * address, size_t count) {}
64+ };
65+
66+ #ifdef RECYCLER_WRITE_BARRIER
67+ template <>
68+ struct WriteBarrierPolicy <_write_barrier_policy>
69+ {
70+ template <class Allocator , class T >
71+ static void WriteBarrier (WriteBarrierPtr<T, Allocator> * address)
72+ {
73+ RecyclerWriteBarrierManager::WriteBarrier (address);
74+ }
75+
76+ template <class T >
77+ static void WriteBarrier (T * address, size_t count)
78+ {
79+ RecyclerWriteBarrierManager::WriteBarrier (address, sizeof (T) * count);
80+ }
81+ };
82+ #endif
83+
84+ // Check if "operator&" is allowed on given WriteBarrierPtr type at compile time.
85+ // Not allowed on WriteBarrierPtr<T, RecyclerFamilyAllocator>.
86+ //
87+ template <class Policy >
88+ void CheckAddressOperator ()
89+ {
90+ static_assert (false , " Might need to set barrier for this operation, and use AddressOf instead." );
91+ }
92+ template <>
93+ inline void CheckAddressOperator<_no_write_barrier_policy>()
94+ {
95+ }
96+ template <class Allocator , class T , class PolicyType = WriteBarrierPtr<T, Allocator>>
97+ void CheckAddressOperator (WriteBarrierPtr<T, Allocator> * p)
98+ {
99+ typedef typename AllocatorWriteBarrierPolicy<Allocator, PolicyType>::Policy Policy;
100+ CheckAddressOperator<Policy>();
101+ }
102+
103+ // Trigger write barrier on changing a WriteBarrierPtr if Allocator type is one of
104+ // recycler allocators. Ignore otherwise.
105+ //
106+ template <class Allocator , class T , class PolicyType = WriteBarrierPtr<T, Allocator>>
107+ void WriteBarrier (WriteBarrierPtr<T, Allocator> * address)
108+ {
109+ typedef typename AllocatorWriteBarrierPolicy<Allocator, PolicyType>::Policy Policy;
110+ return WriteBarrierPolicy<Policy>::WriteBarrier (address);
111+ }
112+
113+ // Trigger write barrier on changing array content if Allocator and element type
114+ // determines write barrier is needed. Ignore otherwise.
115+ //
116+ template <class Allocator , class T , class PolicyType = T>
117+ void WriteBarrier (T * address, size_t count)
118+ {
119+ typedef typename AllocatorWriteBarrierPolicy<Allocator, PolicyType>::Policy Policy;
120+ return WriteBarrierPolicy<Policy>::WriteBarrier (address, count);
121+ }
122+
123+ // Set an array field (naked pointer or NoWriteBarrierPtr) to an allocated array.
124+ // Used when the field does not use write barrier. Will not trigger write barrier
125+ // on the array content.
126+ //
127+ template <class Allocator , class T , class PolicyType = T>
128+ void SetArray (T*& dst, T* src, size_t srcCount)
129+ {
130+ dst = src;
131+ }
132+
133+ // Set an array field (WriteBarrierPtr) to an allocated array.
134+ // Used when the field uses write barrier. Will trigger write barrier on the array
135+ // content if Allocator and element type determines write barrier is needed.
136+ //
137+ template <class Allocator , class T , class PolicyType = T>
138+ void SetArray (WriteBarrierPtr<T, Allocator>& dst, T* src, size_t srcCount)
139+ {
140+ dst = src;
141+ WriteBarrier<Allocator, T, PolicyType>(dst, srcCount);
142+ }
143+
144+
9145template <typename T>
10146class NoWriteBarrierField
11147{
@@ -31,7 +167,7 @@ class NoWriteBarrierField
31167 T value;
32168};
33169
34- template <typename T>
170+ template <typename T, class Allocator >
35171class NoWriteBarrierPtr
36172{
37173public:
@@ -80,7 +216,7 @@ class WriteBarrierObjectConstructorTrigger
80216 Recycler* recycler;
81217};
82218
83- template <typename T>
219+ template <typename T, class Allocator >
84220class WriteBarrierPtr
85221{
86222public:
@@ -100,12 +236,12 @@ class WriteBarrierPtr
100236
101237 T const ** operator &() const
102238 {
103- static_assert ( false , " Might need to set barrier for this operation, and use AddressOf instead. " );
239+ CheckAddressOperator ( this );
104240 return &ptr;
105241 }
106242 T** operator &()
107243 {
108- static_assert ( false , " Might need to set barrier for this operation, and use AddressOf instead. " );
244+ CheckAddressOperator ( this );
109245 return &ptr;
110246 }
111247
@@ -122,9 +258,7 @@ class WriteBarrierPtr
122258 void WriteBarrierSet (T * ptr)
123259 {
124260 NoWriteBarrierSet (ptr);
125- #ifdef RECYCLER_WRITE_BARRIER
126- RecyclerWriteBarrierManager::WriteBarrier (this );
127- #endif
261+ WriteBarrier (this );
128262 }
129263
130264 WriteBarrierPtr& operator =(WriteBarrierPtr const & other)
@@ -136,23 +270,17 @@ class WriteBarrierPtr
136270 static void MoveArray (WriteBarrierPtr * dst, WriteBarrierPtr * src, size_t count)
137271 {
138272 memmove ((void *)dst, src, sizeof (WriteBarrierPtr) * count);
139- #ifdef RECYCLER_WRITE_BARRIER
140- RecyclerWriteBarrierManager::WriteBarrier (dst, count);
141- #endif
273+ WriteBarrier<Allocator>(dst, count);
142274 }
143275 static void CopyArray (WriteBarrierPtr * dst, size_t dstCount, T const * src, size_t srcCount)
144276 {
145277 js_memcpy_s ((void *)dst, sizeof (WriteBarrierPtr) * dstCount, src, sizeof (T *) * srcCount);
146- #ifdef RECYCLER_WRITE_BARRIER
147- RecyclerWriteBarrierManager::WriteBarrier (dst, dstCount);
148- #endif
278+ WriteBarrier<Allocator>(dst, dstCount);
149279 }
150280 static void CopyArray (WriteBarrierPtr * dst, size_t dstCount, WriteBarrierPtr const * src, size_t srcCount)
151281 {
152282 js_memcpy_s ((void *)dst, sizeof (WriteBarrierPtr) * dstCount, src, sizeof (WriteBarrierPtr) * srcCount);
153- #ifdef RECYCLER_WRITE_BARRIER
154- RecyclerWriteBarrierManager::WriteBarrier (dst, dstCount);
155- #endif
283+ WriteBarrier<Allocator>(dst, dstCount);
156284 }
157285 static void ClearArray (WriteBarrierPtr * dst, size_t count)
158286 {
@@ -162,7 +290,7 @@ class WriteBarrierPtr
162290private:
163291 T * ptr;
164292};
165- }
293+ } // namespace Memory
166294
167295
168296template <class T > inline
0 commit comments