23 */ |
23 */ |
24 |
24 |
25 #ifndef SHARE_VM_GC_SHARED_BARRIERSET_HPP |
25 #ifndef SHARE_VM_GC_SHARED_BARRIERSET_HPP |
26 #define SHARE_VM_GC_SHARED_BARRIERSET_HPP |
26 #define SHARE_VM_GC_SHARED_BARRIERSET_HPP |
27 |
27 |
|
28 #include "gc/shared/barrierSetConfig.hpp" |
28 #include "memory/memRegion.hpp" |
29 #include "memory/memRegion.hpp" |
|
30 #include "oops/access.hpp" |
|
31 #include "oops/accessBackend.hpp" |
29 #include "oops/oopsHierarchy.hpp" |
32 #include "oops/oopsHierarchy.hpp" |
30 #include "utilities/fakeRttiSupport.hpp" |
33 #include "utilities/fakeRttiSupport.hpp" |
31 |
34 |
32 // This class provides the interface between a barrier implementation and |
35 // This class provides the interface between a barrier implementation and |
33 // the rest of the system. |
36 // the rest of the system. |
34 |
37 |
35 class BarrierSet: public CHeapObj<mtGC> { |
38 class BarrierSet: public CHeapObj<mtGC> { |
36 friend class VMStructs; |
39 friend class VMStructs; |
37 public: |
40 |
|
41 static BarrierSet* _bs; |
|
42 |
|
43 public: |
|
44 enum Name { |
|
45 #define BARRIER_SET_DECLARE_BS_ENUM(bs_name) bs_name , |
|
46 FOR_EACH_BARRIER_SET_DO(BARRIER_SET_DECLARE_BS_ENUM) |
|
47 #undef BARRIER_SET_DECLARE_BS_ENUM |
|
48 UnknownBS |
|
49 }; |
|
50 |
|
51 static BarrierSet* barrier_set() { return _bs; } |
|
52 |
|
53 protected: |
38 // Fake RTTI support. For a derived class T to participate |
54 // Fake RTTI support. For a derived class T to participate |
39 // - T must have a corresponding Name entry. |
55 // - T must have a corresponding Name entry. |
40 // - GetName<T> must be specialized to return the corresponding Name |
56 // - GetName<T> must be specialized to return the corresponding Name |
41 // entry. |
57 // entry. |
42 // - If T is a base class, the constructor must have a FakeRtti |
58 // - If T is a base class, the constructor must have a FakeRtti |
43 // parameter and pass it up to its base class, with the tag set |
59 // parameter and pass it up to its base class, with the tag set |
44 // augmented with the corresponding Name entry. |
60 // augmented with the corresponding Name entry. |
45 // - If T is a concrete class, the constructor must create a |
61 // - If T is a concrete class, the constructor must create a |
46 // FakeRtti object whose tag set includes the corresponding Name |
62 // FakeRtti object whose tag set includes the corresponding Name |
47 // entry, and pass it up to its base class. |
63 // entry, and pass it up to its base class. |
48 |
|
49 enum Name { // associated class |
|
50 ModRef, // ModRefBarrierSet |
|
51 CardTableModRef, // CardTableModRefBS |
|
52 CardTableForRS, // CardTableModRefBSForCTRS |
|
53 CardTableExtension, // CardTableExtension |
|
54 G1SATBCT, // G1SATBCardTableModRefBS |
|
55 G1SATBCTLogging // G1SATBCardTableLoggingModRefBS |
|
56 }; |
|
57 |
|
58 protected: |
|
59 typedef FakeRttiSupport<BarrierSet, Name> FakeRtti; |
64 typedef FakeRttiSupport<BarrierSet, Name> FakeRtti; |
60 |
65 |
61 private: |
66 private: |
62 FakeRtti _fake_rtti; |
67 FakeRtti _fake_rtti; |
63 |
68 |
|
69 public: |
64 // Metafunction mapping a class derived from BarrierSet to the |
70 // Metafunction mapping a class derived from BarrierSet to the |
65 // corresponding Name enum tag. |
71 // corresponding Name enum tag. |
66 template<typename T> struct GetName; |
72 template<typename T> struct GetName; |
67 |
73 |
68 // Downcast argument to a derived barrier set type. |
74 // Metafunction mapping a Name enum type to the corresponding |
69 // The cast is checked in a debug build. |
75 // lass derived from BarrierSet. |
70 // T must have a specialization for BarrierSet::GetName<T>. |
76 template<BarrierSet::Name T> struct GetType; |
71 template<typename T> friend T* barrier_set_cast(BarrierSet* bs); |
77 |
72 |
|
73 public: |
|
74 // Note: This is not presently the Name corresponding to the |
78 // Note: This is not presently the Name corresponding to the |
75 // concrete class of this object. |
79 // concrete class of this object. |
76 BarrierSet::Name kind() const { return _fake_rtti.concrete_tag(); } |
80 BarrierSet::Name kind() const { return _fake_rtti.concrete_tag(); } |
77 |
81 |
78 // Test whether this object is of the type corresponding to bsn. |
82 // Test whether this object is of the type corresponding to bsn. |
81 // End of fake RTTI support. |
85 // End of fake RTTI support. |
82 |
86 |
83 protected: |
87 protected: |
84 BarrierSet(const FakeRtti& fake_rtti) : _fake_rtti(fake_rtti) { } |
88 BarrierSet(const FakeRtti& fake_rtti) : _fake_rtti(fake_rtti) { } |
85 ~BarrierSet() { } |
89 ~BarrierSet() { } |
86 |
|
87 public: |
|
88 // Invoke the barrier, if any, necessary when writing "new_val" into the |
|
89 // ref field at "offset" in "obj". |
|
90 // (For efficiency reasons, this operation is specialized for certain |
|
91 // barrier types. Semantically, it should be thought of as a call to the |
|
92 // virtual "_work" function below, which must implement the barrier.) |
|
93 // First the pre-write versions... |
|
94 template <class T> inline void write_ref_field_pre(T* field, oop new_val); |
|
95 |
|
96 // ...then the post-write version. |
|
97 inline void write_ref_field(void* field, oop new_val, bool release = false); |
|
98 |
|
99 protected: |
|
100 virtual void write_ref_field_pre_work( oop* field, oop new_val) {}; |
|
101 virtual void write_ref_field_pre_work(narrowOop* field, oop new_val) {}; |
|
102 virtual void write_ref_field_work(void* field, oop new_val, bool release) = 0; |
|
103 |
90 |
104 public: |
91 public: |
105 // Operations on arrays, or general regions (e.g., for "clone") may be |
92 // Operations on arrays, or general regions (e.g., for "clone") may be |
106 // optimized by some barriers. |
93 // optimized by some barriers. |
107 |
94 |
142 // within the heap, this function tells whether they are met. |
129 // within the heap, this function tells whether they are met. |
143 virtual bool is_aligned(HeapWord* addr) = 0; |
130 virtual bool is_aligned(HeapWord* addr) = 0; |
144 |
131 |
145 // Print a description of the memory for the barrier set |
132 // Print a description of the memory for the barrier set |
146 virtual void print_on(outputStream* st) const = 0; |
133 virtual void print_on(outputStream* st) const = 0; |
|
134 |
|
135 static void set_bs(BarrierSet* bs) { _bs = bs; } |
|
136 |
|
137 // The AccessBarrier of a BarrierSet subclass is called by the Access API |
|
138 // (cf. oops/access.hpp) to perform decorated accesses. GC implementations |
|
139 // may override these default access operations by declaring an |
|
140 // AccessBarrier class in its BarrierSet. Its accessors will then be |
|
141 // automatically resolved at runtime. |
|
142 // |
|
143 // In order to register a new FooBarrierSet::AccessBarrier with the Access API, |
|
144 // the following steps should be taken: |
|
145 // 1) Provide an enum "name" for the BarrierSet in barrierSetConfig.hpp |
|
146 // 2) Make sure the barrier set headers are included from barrierSetConfig.inline.hpp |
|
147 // 3) Provide specializations for BarrierSet::GetName and BarrierSet::GetType. |
|
148 template <DecoratorSet decorators, typename BarrierSetT> |
|
149 class AccessBarrier: protected RawAccessBarrier<decorators> { |
|
150 protected: |
|
151 typedef RawAccessBarrier<decorators> Raw; |
|
152 typedef typename BarrierSetT::template AccessBarrier<decorators> CRTPAccessBarrier; |
|
153 |
|
154 public: |
|
155 // Primitive heap accesses. These accessors get resolved when |
|
156 // IN_HEAP is set (e.g. when using the HeapAccess API), it is |
|
157 // not an oop_* overload, and the barrier strength is AS_NORMAL. |
|
158 template <typename T> |
|
159 static T load_in_heap(T* addr) { |
|
160 return Raw::template load<T>(addr); |
|
161 } |
|
162 |
|
163 template <typename T> |
|
164 static T load_in_heap_at(oop base, ptrdiff_t offset) { |
|
165 return Raw::template load_at<T>(base, offset); |
|
166 } |
|
167 |
|
168 template <typename T> |
|
169 static void store_in_heap(T* addr, T value) { |
|
170 Raw::store(addr, value); |
|
171 } |
|
172 |
|
173 template <typename T> |
|
174 static void store_in_heap_at(oop base, ptrdiff_t offset, T value) { |
|
175 Raw::store_at(base, offset, value); |
|
176 } |
|
177 |
|
178 template <typename T> |
|
179 static T atomic_cmpxchg_in_heap(T new_value, T* addr, T compare_value) { |
|
180 return Raw::atomic_cmpxchg(new_value, addr, compare_value); |
|
181 } |
|
182 |
|
183 template <typename T> |
|
184 static T atomic_cmpxchg_in_heap_at(T new_value, oop base, ptrdiff_t offset, T compare_value) { |
|
185 return Raw::oop_atomic_cmpxchg_at(new_value, base, offset, compare_value); |
|
186 } |
|
187 |
|
188 template <typename T> |
|
189 static T atomic_xchg_in_heap(T new_value, T* addr) { |
|
190 return Raw::atomic_xchg(new_value, addr); |
|
191 } |
|
192 |
|
193 template <typename T> |
|
194 static T atomic_xchg_in_heap_at(T new_value, oop base, ptrdiff_t offset) { |
|
195 return Raw::atomic_xchg_at(new_value, base, offset); |
|
196 } |
|
197 |
|
198 template <typename T> |
|
199 static bool arraycopy_in_heap(arrayOop src_obj, arrayOop dst_obj, T* src, T* dst, size_t length) { |
|
200 return Raw::arraycopy(src_obj, dst_obj, src, dst, length); |
|
201 } |
|
202 |
|
203 // Heap oop accesses. These accessors get resolved when |
|
204 // IN_HEAP is set (e.g. when using the HeapAccess API), it is |
|
205 // an oop_* overload, and the barrier strength is AS_NORMAL. |
|
206 template <typename T> |
|
207 static oop oop_load_in_heap(T* addr) { |
|
208 return Raw::template oop_load<oop>(addr); |
|
209 } |
|
210 |
|
211 static oop oop_load_in_heap_at(oop base, ptrdiff_t offset) { |
|
212 return Raw::template oop_load_at<oop>(base, offset); |
|
213 } |
|
214 |
|
215 template <typename T> |
|
216 static void oop_store_in_heap(T* addr, oop value) { |
|
217 Raw::oop_store(addr, value); |
|
218 } |
|
219 |
|
220 static void oop_store_in_heap_at(oop base, ptrdiff_t offset, oop value) { |
|
221 Raw::oop_store_at(base, offset, value); |
|
222 } |
|
223 |
|
224 template <typename T> |
|
225 static oop oop_atomic_cmpxchg_in_heap(oop new_value, T* addr, oop compare_value) { |
|
226 return Raw::oop_atomic_cmpxchg(new_value, addr, compare_value); |
|
227 } |
|
228 |
|
229 static oop oop_atomic_cmpxchg_in_heap_at(oop new_value, oop base, ptrdiff_t offset, oop compare_value) { |
|
230 return Raw::oop_atomic_cmpxchg_at(new_value, base, offset, compare_value); |
|
231 } |
|
232 |
|
233 template <typename T> |
|
234 static oop oop_atomic_xchg_in_heap(oop new_value, T* addr) { |
|
235 return Raw::oop_atomic_xchg(new_value, addr); |
|
236 } |
|
237 |
|
238 static oop oop_atomic_xchg_in_heap_at(oop new_value, oop base, ptrdiff_t offset) { |
|
239 return Raw::oop_atomic_xchg_at(new_value, base, offset); |
|
240 } |
|
241 |
|
242 template <typename T> |
|
243 static bool oop_arraycopy_in_heap(arrayOop src_obj, arrayOop dst_obj, T* src, T* dst, size_t length) { |
|
244 return Raw::oop_arraycopy(src_obj, dst_obj, src, dst, length); |
|
245 } |
|
246 |
|
247 // Off-heap oop accesses. These accessors get resolved when |
|
248 // IN_HEAP is not set (e.g. when using the RootAccess API), it is |
|
249 // an oop* overload, and the barrier strength is AS_NORMAL. |
|
250 template <typename T> |
|
251 static oop oop_load_not_in_heap(T* addr) { |
|
252 return Raw::template oop_load<oop>(addr); |
|
253 } |
|
254 |
|
255 template <typename T> |
|
256 static void oop_store_not_in_heap(T* addr, oop value) { |
|
257 Raw::oop_store(addr, value); |
|
258 } |
|
259 |
|
260 template <typename T> |
|
261 static oop oop_atomic_cmpxchg_not_in_heap(oop new_value, T* addr, oop compare_value) { |
|
262 return Raw::oop_atomic_cmpxchg(new_value, addr, compare_value); |
|
263 } |
|
264 |
|
265 template <typename T> |
|
266 static oop oop_atomic_xchg_not_in_heap(oop new_value, T* addr) { |
|
267 return Raw::oop_atomic_xchg(new_value, addr); |
|
268 } |
|
269 |
|
270 // Clone barrier support |
|
271 static void clone_in_heap(oop src, oop dst, size_t size) { |
|
272 Raw::clone(src, dst, size); |
|
273 } |
|
274 }; |
147 }; |
275 }; |
148 |
276 |
149 template<typename T> |
277 template<typename T> |
150 inline T* barrier_set_cast(BarrierSet* bs) { |
278 inline T* barrier_set_cast(BarrierSet* bs) { |
151 assert(bs->is_a(BarrierSet::GetName<T>::value), "wrong type of barrier set"); |
279 assert(bs->is_a(BarrierSet::GetName<T>::value), "wrong type of barrier set"); |