66
77namespace Memory
88{
9+ class Recycler ;
10+ class RecyclerNonLeafAllocator ;
11+
12+ // Dummy tag classes to mark yes/no write barrier policy
13+ //
14+ struct _write_barrier_policy {};
15+ struct _no_write_barrier_policy {};
16+
17+ // Type write barrier policy
18+ //
19+ // By default following potentially contains GC pointers and use write barrier policy:
20+ // pointer, WriteBarrierPtr, _write_barrier_policy
21+ //
22+ template <class T >
23+ struct TypeWriteBarrierPolicy { typedef _no_write_barrier_policy Policy; };
24+ template <class T >
25+ struct TypeWriteBarrierPolicy <T*> { typedef _write_barrier_policy Policy; };
26+ template <class T >
27+ struct TypeWriteBarrierPolicy <WriteBarrierPtr<T>> { typedef _write_barrier_policy Policy; };
28+ template <>
29+ struct TypeWriteBarrierPolicy <_write_barrier_policy> { typedef _write_barrier_policy Policy; };
30+
31+ // AllocatorType write barrier policy
32+ //
33+ // Recycler allocator type => _write_barrier_policy
34+ // Note that Recycler allocator type consists of multiple allocators:
35+ // Recycler, RecyclerNonLeafAllocator, RecyclerLeafAllocator
36+ //
37+ template <class AllocatorType >
38+ struct _AllocatorTypeWriteBarrierPolicy { typedef _no_write_barrier_policy Policy; };
39+ template <>
40+ struct _AllocatorTypeWriteBarrierPolicy <Recycler> { typedef _write_barrier_policy Policy; };
41+
42+ template <class Policy1 , class Policy2 >
43+ struct _AndWriteBarrierPolicy { typedef _no_write_barrier_policy Policy; };
44+ template <>
45+ struct _AndWriteBarrierPolicy <_write_barrier_policy, _write_barrier_policy>
46+ {
47+ typedef _write_barrier_policy Policy;
48+ };
49+
50+ // Combine Allocator + Data => write barrier policy
51+ // Specialize RecyclerNonLeafAllocator
52+ //
53+ template <class Allocator , class T >
54+ struct AllocatorWriteBarrierPolicy
55+ {
56+ typedef typename AllocatorInfo<Allocator, void >::AllocatorType AllocatorType;
57+ typedef typename _AndWriteBarrierPolicy<
58+ typename _AllocatorTypeWriteBarrierPolicy<AllocatorType>::Policy,
59+ typename TypeWriteBarrierPolicy<T>::Policy>::Policy Policy;
60+ };
61+ template <class T >
62+ struct AllocatorWriteBarrierPolicy <RecyclerNonLeafAllocator, T> { typedef _write_barrier_policy Policy; };
63+ template <>
64+ struct AllocatorWriteBarrierPolicy <RecyclerNonLeafAllocator, int > { typedef _no_write_barrier_policy Policy; };
65+
66+ // Choose WriteBarrierPtr or NoWriteBarrierPtr based on Policy
67+ //
68+ template <class T , class Policy >
69+ struct _WriteBarrierPtrPolicy { typedef NoWriteBarrierPtr<T> Ptr; };
70+ template <class T >
71+ struct _WriteBarrierPtrPolicy <T, _write_barrier_policy> { typedef WriteBarrierPtr<T> Ptr; };
72+
73+ // Choose WriteBarrierPtr or NoWriteBarrierPtr based on Allocator and T* type
74+ //
75+ template <class T ,
76+ class Allocator = Recycler,
77+ class Policy = typename AllocatorWriteBarrierPolicy<Allocator, T*>::Policy>
78+ struct WriteBarrierPtrTraits { typedef typename _WriteBarrierPtrPolicy<T, Policy>::Ptr Ptr; };
79+
80+ // ArrayWriteBarrier behavior
81+ //
82+ template <class Policy >
83+ struct _ArrayWriteBarrier
84+ {
85+ template <class T >
86+ static void WriteBarrier (T * address, size_t count) {}
87+ };
88+
89+ #ifdef RECYCLER_WRITE_BARRIER
90+ template <>
91+ struct _ArrayWriteBarrier <_write_barrier_policy>
92+ {
93+ template <class T >
94+ static void WriteBarrier (T * address, size_t count)
95+ {
96+ RecyclerWriteBarrierManager::WriteBarrier (address, sizeof (T) * count);
97+ }
98+ };
99+ #endif
100+
101+ // Trigger write barrier on changing array content if Allocator and element type
102+ // determines write barrier is needed. Ignore otherwise.
103+ //
104+ template <class T , class Allocator = Recycler, class PolicyType = T>
105+ void WriteBarrier (T * address, size_t count)
106+ {
107+ typedef typename AllocatorWriteBarrierPolicy<Allocator, PolicyType>::Policy Policy;
108+ return _ArrayWriteBarrier<Policy>::WriteBarrier (address, count);
109+ }
110+
111+ // Copy array content. Triggers write barrier on the dst array content if if
112+ // Allocator and element type determines write barrier is needed.
113+ //
114+ template <class Allocator , class T , class PolicyType = T>
115+ void CopyArray (T* dst, size_t dstCount, const T* src, size_t srcCount)
116+ {
117+ js_memcpy_s (dst, sizeof (T) * dstCount, src, sizeof (T) * srcCount);
118+ WriteBarrier<T, Allocator, PolicyType>(dst, dstCount);
119+ }
120+ template <class Allocator , class T , class PolicyType = T>
121+ void CopyArray (NoWriteBarrierPtr<T>& dst, size_t dstCount, const NoWriteBarrierPtr<T>& src, size_t srcCount)
122+ {
123+ return CopyArray<Allocator, T, PolicyType>((T*)dst, dstCount, (const T*)src, srcCount);
124+ }
125+ template <class Allocator , class T , class PolicyType = T>
126+ void CopyArray (WriteBarrierPtr<T>& dst, size_t dstCount, const WriteBarrierPtr<T>& src, size_t srcCount)
127+ {
128+ return CopyArray<Allocator, T, PolicyType>((T*)dst, dstCount, (const T*)src, srcCount);
129+ }
130+
131+
9132template <typename T>
10133class NoWriteBarrierField
11134{
12135public:
13136 NoWriteBarrierField () {}
14- NoWriteBarrierField (T const & value) : value(value) {}
137+ explicit NoWriteBarrierField (T const & value) : value(value) {}
15138
16139 // Getters
17140 operator T const &() const { return value; }
@@ -136,23 +259,17 @@ class WriteBarrierPtr
136259 static void MoveArray (WriteBarrierPtr * dst, WriteBarrierPtr * src, size_t count)
137260 {
138261 memmove ((void *)dst, src, sizeof (WriteBarrierPtr) * count);
139- #ifdef RECYCLER_WRITE_BARRIER
140- RecyclerWriteBarrierManager::WriteBarrier (dst, count);
141- #endif
262+ WriteBarrier (dst, count);
142263 }
143264 static void CopyArray (WriteBarrierPtr * dst, size_t dstCount, T const * src, size_t srcCount)
144265 {
145266 js_memcpy_s ((void *)dst, sizeof (WriteBarrierPtr) * dstCount, src, sizeof (T *) * srcCount);
146- #ifdef RECYCLER_WRITE_BARRIER
147- RecyclerWriteBarrierManager::WriteBarrier (dst, dstCount);
148- #endif
267+ WriteBarrier (dst, dstCount);
149268 }
150269 static void CopyArray (WriteBarrierPtr * dst, size_t dstCount, WriteBarrierPtr const * src, size_t srcCount)
151270 {
152271 js_memcpy_s ((void *)dst, sizeof (WriteBarrierPtr) * dstCount, src, sizeof (WriteBarrierPtr) * srcCount);
153- #ifdef RECYCLER_WRITE_BARRIER
154- RecyclerWriteBarrierManager::WriteBarrier (dst, dstCount);
155- #endif
272+ WriteBarrier (dst, dstCount);
156273 }
157274 static void ClearArray (WriteBarrierPtr * dst, size_t count)
158275 {
@@ -162,7 +279,7 @@ class WriteBarrierPtr
162279private:
163280 T * ptr;
164281};
165- }
282+ } // namespace Memory
166283
167284
168285template <class T > inline
0 commit comments