29 #include "opto/intrinsicnode.hpp"
30 #include "opto/matcher.hpp"
31 #include "opto/output.hpp"
32 #include "opto/subnode.hpp"
33 #include "runtime/stubRoutines.hpp"
34 #include "utilities/globalDefinitions.hpp"
35 #include "utilities/powerOfTwo.hpp"
36
37 #ifdef PRODUCT
38 #define BLOCK_COMMENT(str) /* nothing */
39 #define STOP(error) stop(error)
40 #else
41 #define BLOCK_COMMENT(str) block_comment(str)
42 #define STOP(error) block_comment(error); stop(error)
43 #endif
44
45 #define BIND(label) bind(label); BLOCK_COMMENT(#label ":")
46
47 typedef void (MacroAssembler::* chr_insn)(Register Rt, const Address &adr);
48
49 // jdk.internal.util.ArraysSupport.vectorizedHashCode
50 address C2_MacroAssembler::arrays_hashcode(Register ary, Register cnt, Register result,
51 FloatRegister vdata0, FloatRegister vdata1,
52 FloatRegister vdata2, FloatRegister vdata3,
53 FloatRegister vmul0, FloatRegister vmul1,
54 FloatRegister vmul2, FloatRegister vmul3,
55 FloatRegister vpow, FloatRegister vpowm,
56 BasicType eltype) {
57 ARRAYS_HASHCODE_REGISTERS;
58
59 Register tmp1 = rscratch1, tmp2 = rscratch2;
60
61 Label TAIL, STUB_SWITCH, STUB_SWITCH_OUT, LOOP, BR_BASE, LARGE, DONE;
62
63 // Vectorization factor. Number of array elements loaded to one SIMD&FP registers by the stubs. We
64 // use 8H load arrangements for chars and shorts and 8B for booleans and bytes. It's possible to
65 // use 4H for chars and shorts instead, but using 8H gives better performance.
66 const size_t vf = eltype == T_BOOLEAN || eltype == T_BYTE ? 8
67 : eltype == T_CHAR || eltype == T_SHORT ? 8
68 : eltype == T_INT ? 4
164 ldr(disp_hdr, Address(oop, oopDesc::mark_offset_in_bytes()));
165
166 if (DiagnoseSyncOnValueBasedClasses != 0) {
167 load_klass(tmp, oop);
168 ldrb(tmp, Address(tmp, Klass::misc_flags_offset()));
169 tst(tmp, KlassFlags::_misc_is_value_based_class);
170 br(Assembler::NE, cont);
171 }
172
173 // Check for existing monitor
174 tbnz(disp_hdr, exact_log2(markWord::monitor_value), object_has_monitor);
175
176 if (LockingMode == LM_MONITOR) {
177 tst(oop, oop); // Set NE to indicate 'failure' -> take slow-path. We know that oop != 0.
178 b(cont);
179 } else {
180 assert(LockingMode == LM_LEGACY, "must be");
181 // Set tmp to be (markWord of object | UNLOCK_VALUE).
182 orr(tmp, disp_hdr, markWord::unlocked_value);
183
184 // Initialize the box. (Must happen before we update the object mark!)
185 str(tmp, Address(box, BasicLock::displaced_header_offset_in_bytes()));
186
187 // Compare object markWord with an unlocked value (tmp) and if
188 // equal exchange the stack address of our box with object markWord.
189 // On failure disp_hdr contains the possibly locked markWord.
190 cmpxchg(oop, tmp, box, Assembler::xword, /*acquire*/ true,
191 /*release*/ true, /*weak*/ false, disp_hdr);
192 br(Assembler::EQ, cont);
193
194 assert(oopDesc::mark_offset_in_bytes() == 0, "offset of _mark is not 0");
195
196 // If the compare-and-exchange succeeded, then we found an unlocked
197 // object, will have now locked it will continue at label cont
198
199 // Check if the owner is self by comparing the value in the
200 // markWord of object (disp_hdr) with the stack pointer.
201 mov(rscratch1, sp);
202 sub(disp_hdr, disp_hdr, rscratch1);
203 mov(tmp, (address) (~(os::vm_page_size()-1) | markWord::lock_mask_in_place));
|
29 #include "opto/intrinsicnode.hpp"
30 #include "opto/matcher.hpp"
31 #include "opto/output.hpp"
32 #include "opto/subnode.hpp"
33 #include "runtime/stubRoutines.hpp"
34 #include "utilities/globalDefinitions.hpp"
35 #include "utilities/powerOfTwo.hpp"
36
37 #ifdef PRODUCT
38 #define BLOCK_COMMENT(str) /* nothing */
39 #define STOP(error) stop(error)
40 #else
41 #define BLOCK_COMMENT(str) block_comment(str)
42 #define STOP(error) block_comment(error); stop(error)
43 #endif
44
45 #define BIND(label) bind(label); BLOCK_COMMENT(#label ":")
46
47 typedef void (MacroAssembler::* chr_insn)(Register Rt, const Address &adr);
48
49 void C2_MacroAssembler::entry_barrier() {
50 BarrierSetAssembler* bs = BarrierSet::barrier_set()->barrier_set_assembler();
51 // Dummy labels for just measuring the code size
52 Label dummy_slow_path;
53 Label dummy_continuation;
54 Label dummy_guard;
55 Label* slow_path = &dummy_slow_path;
56 Label* continuation = &dummy_continuation;
57 Label* guard = &dummy_guard;
58 if (!Compile::current()->output()->in_scratch_emit_size()) {
59 // Use real labels from actual stub when not emitting code for the purpose of measuring its size
60 C2EntryBarrierStub* stub = new (Compile::current()->comp_arena()) C2EntryBarrierStub();
61 Compile::current()->output()->add_stub(stub);
62 slow_path = &stub->entry();
63 continuation = &stub->continuation();
64 guard = &stub->guard();
65 }
66 // In the C2 code, we move the non-hot part of nmethod entry barriers out-of-line to a stub.
67 bs->nmethod_entry_barrier(this, slow_path, continuation, guard);
68 }
69
70 // jdk.internal.util.ArraysSupport.vectorizedHashCode
71 address C2_MacroAssembler::arrays_hashcode(Register ary, Register cnt, Register result,
72 FloatRegister vdata0, FloatRegister vdata1,
73 FloatRegister vdata2, FloatRegister vdata3,
74 FloatRegister vmul0, FloatRegister vmul1,
75 FloatRegister vmul2, FloatRegister vmul3,
76 FloatRegister vpow, FloatRegister vpowm,
77 BasicType eltype) {
78 ARRAYS_HASHCODE_REGISTERS;
79
80 Register tmp1 = rscratch1, tmp2 = rscratch2;
81
82 Label TAIL, STUB_SWITCH, STUB_SWITCH_OUT, LOOP, BR_BASE, LARGE, DONE;
83
84 // Vectorization factor. Number of array elements loaded to one SIMD&FP registers by the stubs. We
85 // use 8H load arrangements for chars and shorts and 8B for booleans and bytes. It's possible to
86 // use 4H for chars and shorts instead, but using 8H gives better performance.
87 const size_t vf = eltype == T_BOOLEAN || eltype == T_BYTE ? 8
88 : eltype == T_CHAR || eltype == T_SHORT ? 8
89 : eltype == T_INT ? 4
185 ldr(disp_hdr, Address(oop, oopDesc::mark_offset_in_bytes()));
186
187 if (DiagnoseSyncOnValueBasedClasses != 0) {
188 load_klass(tmp, oop);
189 ldrb(tmp, Address(tmp, Klass::misc_flags_offset()));
190 tst(tmp, KlassFlags::_misc_is_value_based_class);
191 br(Assembler::NE, cont);
192 }
193
194 // Check for existing monitor
195 tbnz(disp_hdr, exact_log2(markWord::monitor_value), object_has_monitor);
196
197 if (LockingMode == LM_MONITOR) {
198 tst(oop, oop); // Set NE to indicate 'failure' -> take slow-path. We know that oop != 0.
199 b(cont);
200 } else {
201 assert(LockingMode == LM_LEGACY, "must be");
202 // Set tmp to be (markWord of object | UNLOCK_VALUE).
203 orr(tmp, disp_hdr, markWord::unlocked_value);
204
205 if (EnableValhalla) {
206 // Mask inline_type bit such that we go to the slow path if object is an inline type
207 andr(tmp, tmp, ~((int) markWord::inline_type_bit_in_place));
208 }
209
210 // Initialize the box. (Must happen before we update the object mark!)
211 str(tmp, Address(box, BasicLock::displaced_header_offset_in_bytes()));
212
213 // Compare object markWord with an unlocked value (tmp) and if
214 // equal exchange the stack address of our box with object markWord.
215 // On failure disp_hdr contains the possibly locked markWord.
216 cmpxchg(oop, tmp, box, Assembler::xword, /*acquire*/ true,
217 /*release*/ true, /*weak*/ false, disp_hdr);
218 br(Assembler::EQ, cont);
219
220 assert(oopDesc::mark_offset_in_bytes() == 0, "offset of _mark is not 0");
221
222 // If the compare-and-exchange succeeded, then we found an unlocked
223 // object, will have now locked it will continue at label cont
224
225 // Check if the owner is self by comparing the value in the
226 // markWord of object (disp_hdr) with the stack pointer.
227 mov(rscratch1, sp);
228 sub(disp_hdr, disp_hdr, rscratch1);
229 mov(tmp, (address) (~(os::vm_page_size()-1) | markWord::lock_mask_in_place));
|