10 * This code is distributed in the hope that it will be useful, but WITHOUT
11 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
13 * version 2 for more details (a copy is included in the LICENSE file that
14 * accompanied this code).
15 *
16 * You should have received a copy of the GNU General Public License version
17 * 2 along with this work; if not, write to the Free Software Foundation,
18 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
19 *
20 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
21 * or visit www.oracle.com if you need additional information or have any
22 * questions.
23 *
24 */
25
26 #include "classfile/classLoaderData.hpp"
27 #include "gc/shared/barrierSet.hpp"
28 #include "gc/shared/barrierSetAssembler.hpp"
29 #include "gc/shared/barrierSetNMethod.hpp"
30 #include "gc/shared/collectedHeap.hpp"
31 #include "interpreter/interp_masm.hpp"
32 #include "memory/universe.hpp"
33 #include "runtime/javaThread.hpp"
34 #include "runtime/jniHandles.hpp"
35 #include "runtime/sharedRuntime.hpp"
36 #include "runtime/stubRoutines.hpp"
37 #ifdef COMPILER2
38 #include "gc/shared/c2/barrierSetC2.hpp"
39 #endif // COMPILER2
40
41 #define __ masm->
42
43 void BarrierSetAssembler::load_at(MacroAssembler* masm, DecoratorSet decorators, BasicType type,
44 Register dst, Address src, Register tmp1, Register tmp2) {
45 // RA is live. It must be saved around calls.
46
47 bool in_heap = (decorators & IN_HEAP) != 0;
48 bool in_native = (decorators & IN_NATIVE) != 0;
49 bool is_not_null = (decorators & IS_NOT_NULL) != 0;
67 }
68 break;
69 }
70 case T_BOOLEAN: __ load_unsigned_byte (dst, src); break;
71 case T_BYTE: __ load_signed_byte (dst, src); break;
72 case T_CHAR: __ load_unsigned_short(dst, src); break;
73 case T_SHORT: __ load_signed_short (dst, src); break;
74 case T_INT: __ lw (dst, src); break;
75 case T_LONG: __ ld (dst, src); break;
76 case T_ADDRESS: __ ld (dst, src); break;
77 case T_FLOAT: __ flw (f10, src); break;
78 case T_DOUBLE: __ fld (f10, src); break;
79 default: Unimplemented();
80 }
81 }
82
83 void BarrierSetAssembler::store_at(MacroAssembler* masm, DecoratorSet decorators, BasicType type,
84 Address dst, Register val, Register tmp1, Register tmp2, Register tmp3) {
85 bool in_heap = (decorators & IN_HEAP) != 0;
86 bool in_native = (decorators & IN_NATIVE) != 0;
87 switch (type) {
88 case T_OBJECT: // fall through
89 case T_ARRAY: {
90 val = val == noreg ? zr : val;
91 if (in_heap) {
92 if (UseCompressedOops) {
93 assert(!dst.uses(val), "not enough registers");
94 if (val != zr) {
95 __ encode_heap_oop(val);
96 }
97 __ sw(val, dst);
98 } else {
99 __ sd(val, dst);
100 }
101 } else {
102 assert(in_native, "why else?");
103 __ sd(val, dst);
104 }
105 break;
106 }
107 case T_BOOLEAN:
108 __ andi(val, val, 0x1); // boolean is true if LSB is 1
109 __ sb(val, dst);
110 break;
111 case T_BYTE: __ sb(val, dst); break;
112 case T_CHAR: __ sh(val, dst); break;
113 case T_SHORT: __ sh(val, dst); break;
114 case T_INT: __ sw(val, dst); break;
115 case T_LONG: __ sd(val, dst); break;
116 case T_ADDRESS: __ sd(val, dst); break;
117 case T_FLOAT: __ fsw(f10, dst); break;
118 case T_DOUBLE: __ fsd(f10, dst); break;
119 default: Unimplemented();
120 }
121
122 }
123
124 void BarrierSetAssembler::copy_load_at(MacroAssembler* masm,
125 DecoratorSet decorators,
126 BasicType type,
127 size_t bytes,
128 Register dst,
129 Address src,
130 Register tmp) {
131 if (bytes == 1) {
132 __ lbu(dst, src);
133 } else if (bytes == 2) {
134 __ lhu(dst, src);
135 } else if (bytes == 4) {
136 __ lwu(dst, src);
137 } else if (bytes == 8) {
138 __ ld(dst, src);
139 } else {
140 // Not the right size
141 ShouldNotReachHere();
142 }
143 if ((decorators & ARRAYCOPY_CHECKCAST) != 0 && UseCompressedOops) {
275 // which is stronger than needed for ordering (stronger than TSO).
276 __ srli(ra, t0, 32);
277 __ orr(t1, t1, ra);
278 }
279 // Read the global epoch value.
280 __ lwu(t1, t1);
281 // Combine the guard value (low order) with the epoch value (high order).
282 __ slli(t1, t1, 32);
283 __ orr(t0, t0, t1);
284 // Compare the global values with the thread-local values
285 Address thread_disarmed_and_epoch_addr(xthread, in_bytes(bs_nm->thread_disarmed_guard_value_offset()));
286 __ ld(t1, thread_disarmed_and_epoch_addr);
287 break;
288 }
289 default:
290 ShouldNotReachHere();
291 }
292
293 Label& barrier_target = slow_path == nullptr ? skip_barrier : *slow_path;
294 if (slow_path == nullptr) {
295 __ beq(t0, t1, barrier_target, true /* is_far */);
296 } else {
297 __ bne(t0, t1, barrier_target, true /* is_far */);
298 }
299
300 if (slow_path == nullptr) {
301 __ rt_call(StubRoutines::method_entry_barrier());
302 __ j(skip_barrier);
303
304 __ bind(local_guard);
305
306 MacroAssembler::assert_alignment(__ pc());
307 __ emit_int32(0); // nmethod guard value. Skipped over in common case.
308 } else {
309 __ bind(*continuation);
310 }
311
312 __ bind(skip_barrier);
313 }
314
315 void BarrierSetAssembler::c2i_entry_barrier(MacroAssembler* masm) {
316 Label bad_call;
317 __ beqz(xmethod, bad_call);
|
10 * This code is distributed in the hope that it will be useful, but WITHOUT
11 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
13 * version 2 for more details (a copy is included in the LICENSE file that
14 * accompanied this code).
15 *
16 * You should have received a copy of the GNU General Public License version
17 * 2 along with this work; if not, write to the Free Software Foundation,
18 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
19 *
20 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
21 * or visit www.oracle.com if you need additional information or have any
22 * questions.
23 *
24 */
25
26 #include "classfile/classLoaderData.hpp"
27 #include "gc/shared/barrierSet.hpp"
28 #include "gc/shared/barrierSetAssembler.hpp"
29 #include "gc/shared/barrierSetNMethod.hpp"
30 #include "gc/shared/barrierSetRuntime.hpp"
31 #include "gc/shared/collectedHeap.hpp"
32 #include "interpreter/interp_masm.hpp"
33 #include "memory/universe.hpp"
34 #include "runtime/javaThread.hpp"
35 #include "runtime/jniHandles.hpp"
36 #include "runtime/sharedRuntime.hpp"
37 #include "runtime/stubRoutines.hpp"
38 #ifdef COMPILER2
39 #include "gc/shared/c2/barrierSetC2.hpp"
40 #endif // COMPILER2
41
42 #define __ masm->
43
44 void BarrierSetAssembler::load_at(MacroAssembler* masm, DecoratorSet decorators, BasicType type,
45 Register dst, Address src, Register tmp1, Register tmp2) {
46 // RA is live. It must be saved around calls.
47
48 bool in_heap = (decorators & IN_HEAP) != 0;
49 bool in_native = (decorators & IN_NATIVE) != 0;
50 bool is_not_null = (decorators & IS_NOT_NULL) != 0;
68 }
69 break;
70 }
71 case T_BOOLEAN: __ load_unsigned_byte (dst, src); break;
72 case T_BYTE: __ load_signed_byte (dst, src); break;
73 case T_CHAR: __ load_unsigned_short(dst, src); break;
74 case T_SHORT: __ load_signed_short (dst, src); break;
75 case T_INT: __ lw (dst, src); break;
76 case T_LONG: __ ld (dst, src); break;
77 case T_ADDRESS: __ ld (dst, src); break;
78 case T_FLOAT: __ flw (f10, src); break;
79 case T_DOUBLE: __ fld (f10, src); break;
80 default: Unimplemented();
81 }
82 }
83
84 void BarrierSetAssembler::store_at(MacroAssembler* masm, DecoratorSet decorators, BasicType type,
85 Address dst, Register val, Register tmp1, Register tmp2, Register tmp3) {
86 bool in_heap = (decorators & IN_HEAP) != 0;
87 bool in_native = (decorators & IN_NATIVE) != 0;
88 bool is_not_null = (decorators & IS_NOT_NULL) != 0;
89
90 switch (type) {
91 case T_OBJECT: // fall through
92 case T_ARRAY: {
93 if (in_heap) {
94 if (val == noreg) {
95 assert(!is_not_null, "inconsistent access");
96 if (UseCompressedOops) {
97 __ sw(zr, dst);
98 } else {
99 __ sd(zr, dst);
100 }
101 } else {
102 if (UseCompressedOops) {
103 assert(!dst.uses(val), "not enough registers");
104 if (is_not_null) {
105 __ encode_heap_oop_not_null(val);
106 } else {
107 __ encode_heap_oop(val);
108 }
109 __ sw(val, dst);
110 } else {
111 __ sd(val, dst);
112 }
113 }
114 } else {
115 assert(in_native, "why else?");
116 assert(val != noreg, "not supported");
117 __ sd(val, dst);
118 }
119 break;
120 }
121 case T_BOOLEAN:
122 __ andi(val, val, 0x1); // boolean is true if LSB is 1
123 __ sb(val, dst);
124 break;
125 case T_BYTE: __ sb(val, dst); break;
126 case T_CHAR: __ sh(val, dst); break;
127 case T_SHORT: __ sh(val, dst); break;
128 case T_INT: __ sw(val, dst); break;
129 case T_LONG: __ sd(val, dst); break;
130 case T_ADDRESS: __ sd(val, dst); break;
131 case T_FLOAT: __ fsw(f10, dst); break;
132 case T_DOUBLE: __ fsd(f10, dst); break;
133 default: Unimplemented();
134 }
135
136 }
137
138 void BarrierSetAssembler::flat_field_copy(MacroAssembler* masm, DecoratorSet decorators,
139 Register src, Register dst, Register inline_layout_info) {
140 // flat_field_copy implementation is fairly complex, and there are not any
141 // "short-cuts" to be made from asm. What there is, appears to have the same
142 // cost in C++, so just "call_VM_leaf" for now rather than maintain hundreds
143 // of hand-rolled instructions...
144 if (decorators & IS_DEST_UNINITIALIZED) {
145 __ call_VM_leaf(CAST_FROM_FN_PTR(address, BarrierSetRuntime::value_copy_is_dest_uninitialized), src, dst, inline_layout_info);
146 } else {
147 __ call_VM_leaf(CAST_FROM_FN_PTR(address, BarrierSetRuntime::value_copy), src, dst, inline_layout_info);
148 }
149 }
150
151 void BarrierSetAssembler::copy_load_at(MacroAssembler* masm,
152 DecoratorSet decorators,
153 BasicType type,
154 size_t bytes,
155 Register dst,
156 Address src,
157 Register tmp) {
158 if (bytes == 1) {
159 __ lbu(dst, src);
160 } else if (bytes == 2) {
161 __ lhu(dst, src);
162 } else if (bytes == 4) {
163 __ lwu(dst, src);
164 } else if (bytes == 8) {
165 __ ld(dst, src);
166 } else {
167 // Not the right size
168 ShouldNotReachHere();
169 }
170 if ((decorators & ARRAYCOPY_CHECKCAST) != 0 && UseCompressedOops) {
302 // which is stronger than needed for ordering (stronger than TSO).
303 __ srli(ra, t0, 32);
304 __ orr(t1, t1, ra);
305 }
306 // Read the global epoch value.
307 __ lwu(t1, t1);
308 // Combine the guard value (low order) with the epoch value (high order).
309 __ slli(t1, t1, 32);
310 __ orr(t0, t0, t1);
311 // Compare the global values with the thread-local values
312 Address thread_disarmed_and_epoch_addr(xthread, in_bytes(bs_nm->thread_disarmed_guard_value_offset()));
313 __ ld(t1, thread_disarmed_and_epoch_addr);
314 break;
315 }
316 default:
317 ShouldNotReachHere();
318 }
319
320 Label& barrier_target = slow_path == nullptr ? skip_barrier : *slow_path;
321 if (slow_path == nullptr) {
322 __ beq(t0, t1, barrier_target, /* is_far */ true);
323 } else {
324 __ bne(t0, t1, barrier_target, /* is_far */ true);
325 }
326
327 if (slow_path == nullptr) {
328 __ rt_call(StubRoutines::method_entry_barrier());
329 __ j(skip_barrier);
330
331 __ bind(local_guard);
332
333 MacroAssembler::assert_alignment(__ pc());
334 __ emit_int32(0); // nmethod guard value. Skipped over in common case.
335 } else {
336 __ bind(*continuation);
337 }
338
339 __ bind(skip_barrier);
340 }
341
342 void BarrierSetAssembler::c2i_entry_barrier(MacroAssembler* masm) {
343 Label bad_call;
344 __ beqz(xmethod, bad_call);
|