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
158 ldr(disp_hdr, Address(oop, oopDesc::mark_offset_in_bytes()));
159
160 if (DiagnoseSyncOnValueBasedClasses != 0) {
161 load_klass(tmp, oop);
162 ldrb(tmp, Address(tmp, Klass::misc_flags_offset()));
163 tst(tmp, KlassFlags::_misc_is_value_based_class);
164 br(Assembler::NE, cont);
165 }
166
167 // Check for existing monitor
168 tbnz(disp_hdr, exact_log2(markWord::monitor_value), object_has_monitor);
169
170 if (LockingMode == LM_MONITOR) {
171 tst(oop, oop); // Set NE to indicate 'failure' -> take slow-path. We know that oop != 0.
172 b(cont);
173 } else {
174 assert(LockingMode == LM_LEGACY, "must be");
175 // Set tmp to be (markWord of object | UNLOCK_VALUE).
176 orr(tmp, disp_hdr, markWord::unlocked_value);
177
178 // Initialize the box. (Must happen before we update the object mark!)
179 str(tmp, Address(box, BasicLock::displaced_header_offset_in_bytes()));
180
181 // Compare object markWord with an unlocked value (tmp) and if
182 // equal exchange the stack address of our box with object markWord.
183 // On failure disp_hdr contains the possibly locked markWord.
184 cmpxchg(oop, tmp, box, Assembler::xword, /*acquire*/ true,
185 /*release*/ true, /*weak*/ false, disp_hdr);
186 br(Assembler::EQ, cont);
187
188 assert(oopDesc::mark_offset_in_bytes() == 0, "offset of _mark is not 0");
189
190 // If the compare-and-exchange succeeded, then we found an unlocked
191 // object, will have now locked it will continue at label cont
192
193 // Check if the owner is self by comparing the value in the
194 // markWord of object (disp_hdr) with the stack pointer.
195 mov(rscratch1, sp);
196 sub(disp_hdr, disp_hdr, rscratch1);
197 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
179 ldr(disp_hdr, Address(oop, oopDesc::mark_offset_in_bytes()));
180
181 if (DiagnoseSyncOnValueBasedClasses != 0) {
182 load_klass(tmp, oop);
183 ldrb(tmp, Address(tmp, Klass::misc_flags_offset()));
184 tst(tmp, KlassFlags::_misc_is_value_based_class);
185 br(Assembler::NE, cont);
186 }
187
188 // Check for existing monitor
189 tbnz(disp_hdr, exact_log2(markWord::monitor_value), object_has_monitor);
190
191 if (LockingMode == LM_MONITOR) {
192 tst(oop, oop); // Set NE to indicate 'failure' -> take slow-path. We know that oop != 0.
193 b(cont);
194 } else {
195 assert(LockingMode == LM_LEGACY, "must be");
196 // Set tmp to be (markWord of object | UNLOCK_VALUE).
197 orr(tmp, disp_hdr, markWord::unlocked_value);
198
199 if (EnableValhalla) {
200 // Mask inline_type bit such that we go to the slow path if object is an inline type
201 andr(tmp, tmp, ~((int) markWord::inline_type_bit_in_place));
202 }
203
204 // Initialize the box. (Must happen before we update the object mark!)
205 str(tmp, Address(box, BasicLock::displaced_header_offset_in_bytes()));
206
207 // Compare object markWord with an unlocked value (tmp) and if
208 // equal exchange the stack address of our box with object markWord.
209 // On failure disp_hdr contains the possibly locked markWord.
210 cmpxchg(oop, tmp, box, Assembler::xword, /*acquire*/ true,
211 /*release*/ true, /*weak*/ false, disp_hdr);
212 br(Assembler::EQ, cont);
213
214 assert(oopDesc::mark_offset_in_bytes() == 0, "offset of _mark is not 0");
215
216 // If the compare-and-exchange succeeded, then we found an unlocked
217 // object, will have now locked it will continue at label cont
218
219 // Check if the owner is self by comparing the value in the
220 // markWord of object (disp_hdr) with the stack pointer.
221 mov(rscratch1, sp);
222 sub(disp_hdr, disp_hdr, rscratch1);
223 mov(tmp, (address) (~(os::vm_page_size()-1) | markWord::lock_mask_in_place));
|