|
1 /* |
|
2 * Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved. |
|
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
|
4 * |
|
5 * This code is free software; you can redistribute it and/or modify it |
|
6 * under the terms of the GNU General Public License version 2 only, as |
|
7 * published by the Free Software Foundation. |
|
8 * |
|
9 * This code is distributed in the hope that it will be useful, but WITHOUT |
|
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
|
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
|
12 * version 2 for more details (a copy is included in the LICENSE file that |
|
13 * accompanied this code). |
|
14 * |
|
15 * You should have received a copy of the GNU General Public License version |
|
16 * 2 along with this work; if not, write to the Free Software Foundation, |
|
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. |
|
18 * |
|
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
|
20 * or visit www.oracle.com if you need additional information or have any |
|
21 * questions. |
|
22 */ |
|
23 |
|
24 #ifndef SHARE_GC_Z_ZBARRIERSET_INLINE_HPP |
|
25 #define SHARE_GC_Z_ZBARRIERSET_INLINE_HPP |
|
26 |
|
27 #include "gc/shared/accessBarrierSupport.inline.hpp" |
|
28 #include "gc/z/zBarrier.inline.hpp" |
|
29 #include "gc/z/zBarrierSet.hpp" |
|
30 #include "utilities/debug.hpp" |
|
31 |
|
32 template <DecoratorSet decorators, typename BarrierSetT> |
|
33 template <DecoratorSet expected> |
|
34 inline void ZBarrierSet::AccessBarrier<decorators, BarrierSetT>::verify_decorators_present() { |
|
35 if ((decorators & expected) == 0) { |
|
36 fatal("Using unsupported access decorators"); |
|
37 } |
|
38 } |
|
39 |
|
40 template <DecoratorSet decorators, typename BarrierSetT> |
|
41 template <DecoratorSet expected> |
|
42 inline void ZBarrierSet::AccessBarrier<decorators, BarrierSetT>::verify_decorators_absent() { |
|
43 if ((decorators & expected) != 0) { |
|
44 fatal("Using unsupported access decorators"); |
|
45 } |
|
46 } |
|
47 |
|
48 template <DecoratorSet decorators, typename BarrierSetT> |
|
49 inline oop* ZBarrierSet::AccessBarrier<decorators, BarrierSetT>::field_addr(oop base, ptrdiff_t offset) { |
|
50 assert(base != NULL, "Invalid base"); |
|
51 return reinterpret_cast<oop*>(reinterpret_cast<intptr_t>((void*)base) + offset); |
|
52 } |
|
53 |
|
54 template <DecoratorSet decorators, typename BarrierSetT> |
|
55 template <typename T> |
|
56 inline oop ZBarrierSet::AccessBarrier<decorators, BarrierSetT>::load_barrier_on_oop_field_preloaded(T* addr, oop o) { |
|
57 verify_decorators_absent<ON_UNKNOWN_OOP_REF>(); |
|
58 |
|
59 if (HasDecorator<decorators, AS_NO_KEEPALIVE>::value) { |
|
60 if (HasDecorator<decorators, ON_STRONG_OOP_REF>::value) { |
|
61 return ZBarrier::weak_load_barrier_on_oop_field_preloaded(addr, o); |
|
62 } else if (HasDecorator<decorators, ON_WEAK_OOP_REF>::value) { |
|
63 return ZBarrier::weak_load_barrier_on_weak_oop_field_preloaded(addr, o); |
|
64 } else { |
|
65 return ZBarrier::weak_load_barrier_on_phantom_oop_field_preloaded(addr, o); |
|
66 } |
|
67 } else { |
|
68 if (HasDecorator<decorators, ON_STRONG_OOP_REF>::value) { |
|
69 return ZBarrier::load_barrier_on_oop_field_preloaded(addr, o); |
|
70 } else if (HasDecorator<decorators, ON_WEAK_OOP_REF>::value) { |
|
71 return ZBarrier::load_barrier_on_weak_oop_field_preloaded(addr, o); |
|
72 } else { |
|
73 return ZBarrier::load_barrier_on_phantom_oop_field_preloaded(addr, o); |
|
74 } |
|
75 } |
|
76 } |
|
77 |
|
78 template <DecoratorSet decorators, typename BarrierSetT> |
|
79 template <typename T> |
|
80 inline oop ZBarrierSet::AccessBarrier<decorators, BarrierSetT>::load_barrier_on_unknown_oop_field_preloaded(oop base, ptrdiff_t offset, T* addr, oop o) { |
|
81 verify_decorators_present<ON_UNKNOWN_OOP_REF>(); |
|
82 |
|
83 const DecoratorSet decorators_known_strength = |
|
84 AccessBarrierSupport::resolve_possibly_unknown_oop_ref_strength<decorators>(base, offset); |
|
85 |
|
86 if (HasDecorator<decorators, AS_NO_KEEPALIVE>::value) { |
|
87 if (decorators_known_strength & ON_STRONG_OOP_REF) { |
|
88 return ZBarrier::weak_load_barrier_on_oop_field_preloaded(addr, o); |
|
89 } else if (decorators_known_strength & ON_WEAK_OOP_REF) { |
|
90 return ZBarrier::weak_load_barrier_on_weak_oop_field_preloaded(addr, o); |
|
91 } else { |
|
92 return ZBarrier::weak_load_barrier_on_phantom_oop_field_preloaded(addr, o); |
|
93 } |
|
94 } else { |
|
95 if (decorators_known_strength & ON_STRONG_OOP_REF) { |
|
96 return ZBarrier::load_barrier_on_oop_field_preloaded(addr, o); |
|
97 } else if (decorators_known_strength & ON_WEAK_OOP_REF) { |
|
98 return ZBarrier::load_barrier_on_weak_oop_field_preloaded(addr, o); |
|
99 } else { |
|
100 return ZBarrier::load_barrier_on_phantom_oop_field_preloaded(addr, o); |
|
101 } |
|
102 } |
|
103 } |
|
104 |
|
105 // |
|
106 // In heap |
|
107 // |
|
108 template <DecoratorSet decorators, typename BarrierSetT> |
|
109 template <typename T> |
|
110 inline oop ZBarrierSet::AccessBarrier<decorators, BarrierSetT>::oop_load_in_heap(T* addr) { |
|
111 verify_decorators_absent<ON_UNKNOWN_OOP_REF>(); |
|
112 |
|
113 const oop o = Raw::oop_load_in_heap(addr); |
|
114 return load_barrier_on_oop_field_preloaded(addr, o); |
|
115 } |
|
116 |
|
117 template <DecoratorSet decorators, typename BarrierSetT> |
|
118 inline oop ZBarrierSet::AccessBarrier<decorators, BarrierSetT>::oop_load_in_heap_at(oop base, ptrdiff_t offset) { |
|
119 oop* const addr = field_addr(base, offset); |
|
120 const oop o = Raw::oop_load_in_heap(addr); |
|
121 |
|
122 if (HasDecorator<decorators, ON_UNKNOWN_OOP_REF>::value) { |
|
123 return load_barrier_on_unknown_oop_field_preloaded(base, offset, addr, o); |
|
124 } |
|
125 |
|
126 return load_barrier_on_oop_field_preloaded(addr, o); |
|
127 } |
|
128 |
|
129 template <DecoratorSet decorators, typename BarrierSetT> |
|
130 template <typename T> |
|
131 inline oop ZBarrierSet::AccessBarrier<decorators, BarrierSetT>::oop_atomic_cmpxchg_in_heap(oop new_value, T* addr, oop compare_value) { |
|
132 verify_decorators_present<ON_STRONG_OOP_REF>(); |
|
133 verify_decorators_absent<AS_NO_KEEPALIVE>(); |
|
134 |
|
135 ZBarrier::load_barrier_on_oop_field(addr); |
|
136 return Raw::oop_atomic_cmpxchg_in_heap(new_value, addr, compare_value); |
|
137 } |
|
138 |
|
139 template <DecoratorSet decorators, typename BarrierSetT> |
|
140 inline oop ZBarrierSet::AccessBarrier<decorators, BarrierSetT>::oop_atomic_cmpxchg_in_heap_at(oop new_value, oop base, ptrdiff_t offset, oop compare_value) { |
|
141 verify_decorators_present<ON_STRONG_OOP_REF | ON_UNKNOWN_OOP_REF>(); |
|
142 verify_decorators_absent<AS_NO_KEEPALIVE>(); |
|
143 |
|
144 // Through Unsafe.CompareAndExchangeObject()/CompareAndSetObject() we can recieve |
|
145 // calls with ON_UNKNOWN_OOP_REF set. However, we treat these as ON_STRONG_OOP_REF, |
|
146 // with the motivation that if you're doing Unsafe operations on a Reference.referent |
|
147 // field, then you're on your own anyway. |
|
148 ZBarrier::load_barrier_on_oop_field(field_addr(base, offset)); |
|
149 return Raw::oop_atomic_cmpxchg_in_heap_at(new_value, base, offset, compare_value); |
|
150 } |
|
151 |
|
152 template <DecoratorSet decorators, typename BarrierSetT> |
|
153 template <typename T> |
|
154 inline oop ZBarrierSet::AccessBarrier<decorators, BarrierSetT>::oop_atomic_xchg_in_heap(oop new_value, T* addr) { |
|
155 verify_decorators_present<ON_STRONG_OOP_REF>(); |
|
156 verify_decorators_absent<AS_NO_KEEPALIVE>(); |
|
157 |
|
158 const oop o = Raw::oop_atomic_xchg_in_heap(new_value, addr); |
|
159 return ZBarrier::load_barrier_on_oop(o); |
|
160 } |
|
161 |
|
162 template <DecoratorSet decorators, typename BarrierSetT> |
|
163 inline oop ZBarrierSet::AccessBarrier<decorators, BarrierSetT>::oop_atomic_xchg_in_heap_at(oop new_value, oop base, ptrdiff_t offset) { |
|
164 verify_decorators_present<ON_STRONG_OOP_REF>(); |
|
165 verify_decorators_absent<AS_NO_KEEPALIVE>(); |
|
166 |
|
167 const oop o = Raw::oop_atomic_xchg_in_heap_at(new_value, base, offset); |
|
168 return ZBarrier::load_barrier_on_oop(o); |
|
169 } |
|
170 |
|
171 template <DecoratorSet decorators, typename BarrierSetT> |
|
172 template <typename T> |
|
173 inline bool ZBarrierSet::AccessBarrier<decorators, BarrierSetT>::oop_arraycopy_in_heap(arrayOop src_obj, size_t src_offset_in_bytes, T* src_raw, |
|
174 arrayOop dst_obj, size_t dst_offset_in_bytes, T* dst_raw, |
|
175 size_t length) { |
|
176 T* src = arrayOopDesc::obj_offset_to_raw(src_obj, src_offset_in_bytes, src_raw); |
|
177 T* dst = arrayOopDesc::obj_offset_to_raw(dst_obj, dst_offset_in_bytes, dst_raw); |
|
178 |
|
179 if (!HasDecorator<decorators, ARRAYCOPY_CHECKCAST>::value) { |
|
180 // No check cast, bulk barrier and bulk copy |
|
181 ZBarrier::load_barrier_on_oop_array(src, length); |
|
182 return Raw::oop_arraycopy_in_heap(NULL, 0, src, NULL, 0, dst, length); |
|
183 } |
|
184 |
|
185 // Check cast and copy each elements |
|
186 Klass* const dst_klass = objArrayOop(dst_obj)->element_klass(); |
|
187 for (const T* const end = src + length; src < end; src++, dst++) { |
|
188 const oop elem = ZBarrier::load_barrier_on_oop_field(src); |
|
189 if (!oopDesc::is_instanceof_or_null(elem, dst_klass)) { |
|
190 // Check cast failed |
|
191 return false; |
|
192 } |
|
193 |
|
194 // Cast is safe, since we know it's never a narrowOop |
|
195 *(oop*)dst = elem; |
|
196 } |
|
197 |
|
198 return true; |
|
199 } |
|
200 |
|
201 template <DecoratorSet decorators, typename BarrierSetT> |
|
202 inline void ZBarrierSet::AccessBarrier<decorators, BarrierSetT>::clone_in_heap(oop src, oop dst, size_t size) { |
|
203 ZBarrier::load_barrier_on_oop_fields(src); |
|
204 Raw::clone_in_heap(src, dst, size); |
|
205 } |
|
206 |
|
207 // |
|
208 // Not in heap |
|
209 // |
|
210 template <DecoratorSet decorators, typename BarrierSetT> |
|
211 template <typename T> |
|
212 inline oop ZBarrierSet::AccessBarrier<decorators, BarrierSetT>::oop_load_not_in_heap(T* addr) { |
|
213 const oop o = Raw::oop_load_not_in_heap(addr); |
|
214 |
|
215 if (HasDecorator<decorators, ON_PHANTOM_OOP_REF>::value) { |
|
216 return load_barrier_on_oop_field_preloaded(addr, o); |
|
217 } |
|
218 |
|
219 verify_decorators_present<ON_STRONG_OOP_REF>(); |
|
220 verify_decorators_absent<AS_NO_KEEPALIVE>(); |
|
221 |
|
222 return o; |
|
223 } |
|
224 |
|
225 template <DecoratorSet decorators, typename BarrierSetT> |
|
226 template <typename T> |
|
227 inline oop ZBarrierSet::AccessBarrier<decorators, BarrierSetT>::oop_atomic_cmpxchg_not_in_heap(oop new_value, T* addr, oop compare_value) { |
|
228 verify_decorators_present<ON_STRONG_OOP_REF>(); |
|
229 verify_decorators_absent<AS_NO_KEEPALIVE>(); |
|
230 |
|
231 return Raw::oop_atomic_cmpxchg_not_in_heap(new_value, addr, compare_value); |
|
232 } |
|
233 |
|
234 template <DecoratorSet decorators, typename BarrierSetT> |
|
235 template <typename T> |
|
236 inline oop ZBarrierSet::AccessBarrier<decorators, BarrierSetT>::oop_atomic_xchg_not_in_heap(oop new_value, T* addr) { |
|
237 verify_decorators_present<ON_STRONG_OOP_REF>(); |
|
238 verify_decorators_absent<AS_NO_KEEPALIVE>(); |
|
239 |
|
240 return Raw::oop_atomic_xchg_not_in_heap(new_value, addr); |
|
241 } |
|
242 |
|
243 #endif // SHARE_GC_Z_ZBARRIERSET_INLINE_HPP |