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