1 /*
2 * Copyright (c) 2004, 2020, 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
25 #include "precompiled.hpp"
26 #include "asm/macroAssembler.hpp"
27 #include "memory/resourceArea.hpp"
28 #include "prims/jniFastGetField.hpp"
29 #include "prims/jvm_misc.hpp"
30 #include "prims/jvmtiExport.hpp"
31 #include "runtime/safepoint.hpp"
32
33 #define __ masm->
34
35 #define BUFFER_SIZE 30
36
37 #ifdef _WINDOWS
38 GetBooleanField_t JNI_FastGetField::jni_fast_GetBooleanField_fp;
39 GetByteField_t JNI_FastGetField::jni_fast_GetByteField_fp;
40 GetCharField_t JNI_FastGetField::jni_fast_GetCharField_fp;
41 GetShortField_t JNI_FastGetField::jni_fast_GetShortField_fp;
42 GetIntField_t JNI_FastGetField::jni_fast_GetIntField_fp;
43 GetLongField_t JNI_FastGetField::jni_fast_GetLongField_fp;
44 GetFloatField_t JNI_FastGetField::jni_fast_GetFloatField_fp;
45 GetDoubleField_t JNI_FastGetField::jni_fast_GetDoubleField_fp;
46 #endif
47
48 // Instead of issuing lfence for LoadLoad barrier, we create data dependency
49 // between loads, which is much more efficient than lfence.
50
generate_fast_get_int_field0(BasicType type)51 address JNI_FastGetField::generate_fast_get_int_field0(BasicType type) {
52 const char *name = NULL;
53 switch (type) {
54 case T_BOOLEAN: name = "jni_fast_GetBooleanField"; break;
55 case T_BYTE: name = "jni_fast_GetByteField"; break;
56 case T_CHAR: name = "jni_fast_GetCharField"; break;
57 case T_SHORT: name = "jni_fast_GetShortField"; break;
58 case T_INT: name = "jni_fast_GetIntField"; break;
59 default: ShouldNotReachHere();
60 }
61 ResourceMark rm;
62 BufferBlob* blob = BufferBlob::create(name, BUFFER_SIZE*wordSize);
63 CodeBuffer cbuf(blob);
64 MacroAssembler* masm = new MacroAssembler(&cbuf);
65 address fast_entry = __ pc();
66
67 Label slow;
68
69 // stack layout: offset from rsp (in words):
70 // return pc 0
71 // jni env 1
72 // obj 2
73 // jfieldID 3
74
75 ExternalAddress counter(SafepointSynchronize::safepoint_counter_addr());
76 __ mov32 (rcx, counter);
77 __ testb (rcx, 1);
78 __ jcc (Assembler::notZero, slow);
79
80 if (JvmtiExport::can_post_field_access()) {
81 // Check to see if a field access watch has been set before we
82 // take the fast path.
83 __ cmp32(ExternalAddress((address) JvmtiExport::get_field_access_count_addr()), 0);
84 __ jcc(Assembler::notZero, slow);
85 }
86
87 __ mov(rax, rcx);
88 __ andptr(rax, 1); // rax, must end up 0
89 __ movptr(rdx, Address(rsp, rax, Address::times_1, 2*wordSize));
90 // obj, notice rax, is 0.
91 // rdx is data dependent on rcx.
92 __ movptr(rax, Address(rsp, 3*wordSize)); // jfieldID
93
94 __ clear_jweak_tag(rdx);
95
96 __ movptr(rdx, Address(rdx, 0)); // *obj
97 __ shrptr (rax, 2); // offset
98
99 assert(count < LIST_CAPACITY, "LIST_CAPACITY too small");
100 speculative_load_pclist[count] = __ pc();
101 switch (type) {
102 case T_BOOLEAN: __ movzbl (rax, Address(rdx, rax, Address::times_1)); break;
103 case T_BYTE: __ movsbl (rax, Address(rdx, rax, Address::times_1)); break;
104 case T_CHAR: __ movzwl (rax, Address(rdx, rax, Address::times_1)); break;
105 case T_SHORT: __ movswl (rax, Address(rdx, rax, Address::times_1)); break;
106 case T_INT: __ movl (rax, Address(rdx, rax, Address::times_1)); break;
107 default: ShouldNotReachHere();
108 }
109
110 Address ca1;
111 __ lea(rdx, counter);
112 __ xorptr(rdx, rax);
113 __ xorptr(rdx, rax);
114 __ cmp32(rcx, Address(rdx, 0));
115 // ca1 is the same as ca because
116 // rax, ^ counter_addr ^ rax, = address
117 // ca1 is data dependent on rax,.
118 __ jcc (Assembler::notEqual, slow);
119
120 #ifndef _WINDOWS
121 __ ret (0);
122 #else
123 // __stdcall calling convention
124 __ ret (3*wordSize);
125 #endif
126
127 slowcase_entry_pclist[count++] = __ pc();
128 __ bind (slow);
129 address slow_case_addr = NULL;
130 switch (type) {
131 case T_BOOLEAN: slow_case_addr = jni_GetBooleanField_addr(); break;
132 case T_BYTE: slow_case_addr = jni_GetByteField_addr(); break;
133 case T_CHAR: slow_case_addr = jni_GetCharField_addr(); break;
134 case T_SHORT: slow_case_addr = jni_GetShortField_addr(); break;
135 case T_INT: slow_case_addr = jni_GetIntField_addr(); break;
136 default: ShouldNotReachHere();
137 }
138 // tail call
139 __ jump (ExternalAddress(slow_case_addr));
140
141 __ flush ();
142
143 #ifndef _WINDOWS
144 return fast_entry;
145 #else
146 switch (type) {
147 case T_BOOLEAN: jni_fast_GetBooleanField_fp = (GetBooleanField_t) fast_entry; break;
148 case T_BYTE: jni_fast_GetByteField_fp = (GetByteField_t) fast_entry; break;
149 case T_CHAR: jni_fast_GetCharField_fp = (GetCharField_t) fast_entry; break;
150 case T_SHORT: jni_fast_GetShortField_fp = (GetShortField_t) fast_entry; break;
151 case T_INT: jni_fast_GetIntField_fp = (GetIntField_t) fast_entry; break;
152 }
153 return os::win32::fast_jni_accessor_wrapper(type);
154 #endif
155 }
156
generate_fast_get_boolean_field()157 address JNI_FastGetField::generate_fast_get_boolean_field() {
158 return generate_fast_get_int_field0(T_BOOLEAN);
159 }
160
generate_fast_get_byte_field()161 address JNI_FastGetField::generate_fast_get_byte_field() {
162 return generate_fast_get_int_field0(T_BYTE);
163 }
164
generate_fast_get_char_field()165 address JNI_FastGetField::generate_fast_get_char_field() {
166 return generate_fast_get_int_field0(T_CHAR);
167 }
168
generate_fast_get_short_field()169 address JNI_FastGetField::generate_fast_get_short_field() {
170 return generate_fast_get_int_field0(T_SHORT);
171 }
172
generate_fast_get_int_field()173 address JNI_FastGetField::generate_fast_get_int_field() {
174 return generate_fast_get_int_field0(T_INT);
175 }
176
generate_fast_get_long_field()177 address JNI_FastGetField::generate_fast_get_long_field() {
178 const char *name = "jni_fast_GetLongField";
179 ResourceMark rm;
180 BufferBlob* blob = BufferBlob::create(name, BUFFER_SIZE*wordSize);
181 CodeBuffer cbuf(blob);
182 MacroAssembler* masm = new MacroAssembler(&cbuf);
183 address fast_entry = __ pc();
184
185 Label slow;
186
187 // stack layout: offset from rsp (in words):
188 // old rsi 0
189 // return pc 1
190 // jni env 2
191 // obj 3
192 // jfieldID 4
193
194 ExternalAddress counter(SafepointSynchronize::safepoint_counter_addr());
195
196 __ push (rsi);
197 __ mov32 (rcx, counter);
198 __ testb (rcx, 1);
199 __ jcc (Assembler::notZero, slow);
200
201 if (JvmtiExport::can_post_field_access()) {
202 // Check to see if a field access watch has been set before we
203 // take the fast path.
204 __ cmp32(ExternalAddress((address) JvmtiExport::get_field_access_count_addr()), 0);
205 __ jcc(Assembler::notZero, slow);
206 }
207
208 __ mov(rax, rcx);
209 __ andptr(rax, 1); // rax, must end up 0
210 __ movptr(rdx, Address(rsp, rax, Address::times_1, 3*wordSize));
211 // obj, notice rax, is 0.
212 // rdx is data dependent on rcx.
213 __ movptr(rsi, Address(rsp, 4*wordSize)); // jfieldID
214
215 __ clear_jweak_tag(rdx);
216
217 __ movptr(rdx, Address(rdx, 0)); // *obj
218 __ shrptr(rsi, 2); // offset
219
220 assert(count < LIST_CAPACITY-1, "LIST_CAPACITY too small");
221 speculative_load_pclist[count++] = __ pc();
222 __ movptr(rax, Address(rdx, rsi, Address::times_1));
223 #ifndef _LP64
224 speculative_load_pclist[count] = __ pc();
225 __ movl(rdx, Address(rdx, rsi, Address::times_1, 4));
226 #endif // _LP64
227
228 __ lea(rsi, counter);
229 __ xorptr(rsi, rdx);
230 __ xorptr(rsi, rax);
231 __ xorptr(rsi, rdx);
232 __ xorptr(rsi, rax);
233 __ cmp32(rcx, Address(rsi, 0));
234 // ca1 is the same as ca because
235 // rax, ^ rdx ^ counter_addr ^ rax, ^ rdx = address
236 // ca1 is data dependent on both rax, and rdx.
237 __ jcc (Assembler::notEqual, slow);
238
239 __ pop (rsi);
240
241 #ifndef _WINDOWS
242 __ ret (0);
243 #else
244 // __stdcall calling convention
245 __ ret (3*wordSize);
246 #endif
247
248 slowcase_entry_pclist[count-1] = __ pc();
249 slowcase_entry_pclist[count++] = __ pc();
250 __ bind (slow);
251 __ pop (rsi);
252 address slow_case_addr = jni_GetLongField_addr();;
253 // tail call
254 __ jump (ExternalAddress(slow_case_addr));
255
256 __ flush ();
257
258 #ifndef _WINDOWS
259 return fast_entry;
260 #else
261 jni_fast_GetLongField_fp = (GetLongField_t) fast_entry;
262 return os::win32::fast_jni_accessor_wrapper(T_LONG);
263 #endif
264 }
265
generate_fast_get_float_field0(BasicType type)266 address JNI_FastGetField::generate_fast_get_float_field0(BasicType type) {
267 const char *name = NULL;
268 switch (type) {
269 case T_FLOAT: name = "jni_fast_GetFloatField"; break;
270 case T_DOUBLE: name = "jni_fast_GetDoubleField"; break;
271 default: ShouldNotReachHere();
272 }
273 ResourceMark rm;
274 BufferBlob* blob = BufferBlob::create(name, BUFFER_SIZE*wordSize);
275 CodeBuffer cbuf(blob);
276 MacroAssembler* masm = new MacroAssembler(&cbuf);
277 address fast_entry = __ pc();
278
279 Label slow_with_pop, slow;
280
281 // stack layout: offset from rsp (in words):
282 // return pc 0
283 // jni env 1
284 // obj 2
285 // jfieldID 3
286
287 ExternalAddress counter(SafepointSynchronize::safepoint_counter_addr());
288
289 __ mov32 (rcx, counter);
290 __ testb (rcx, 1);
291 __ jcc (Assembler::notZero, slow);
292
293 if (JvmtiExport::can_post_field_access()) {
294 // Check to see if a field access watch has been set before we
295 // take the fast path.
296 __ cmp32(ExternalAddress((address) JvmtiExport::get_field_access_count_addr()), 0);
297 __ jcc(Assembler::notZero, slow);
298 }
299
300 __ mov(rax, rcx);
301 __ andptr(rax, 1); // rax, must end up 0
302 __ movptr(rdx, Address(rsp, rax, Address::times_1, 2*wordSize));
303 // obj, notice rax, is 0.
304 // rdx is data dependent on rcx.
305 __ movptr(rax, Address(rsp, 3*wordSize)); // jfieldID
306
307 __ clear_jweak_tag(rdx);
308
309 __ movptr(rdx, Address(rdx, 0)); // *obj
310 __ shrptr(rax, 2); // offset
311
312 assert(count < LIST_CAPACITY, "LIST_CAPACITY too small");
313 speculative_load_pclist[count] = __ pc();
314 switch (type) {
315 #ifndef _LP64
316 case T_FLOAT: __ fld_s (Address(rdx, rax, Address::times_1)); break;
317 case T_DOUBLE: __ fld_d (Address(rdx, rax, Address::times_1)); break;
318 #else
319 case T_FLOAT: __ movflt (xmm0, Address(robj, roffset, Address::times_1)); break;
320 case T_DOUBLE: __ movdbl (xmm0, Address(robj, roffset, Address::times_1)); break;
321 #endif // _LP64
322 default: ShouldNotReachHere();
323 }
324
325 Address ca1;
326 __ fst_s (Address(rsp, -4));
327 __ lea(rdx, counter);
328 __ movl (rax, Address(rsp, -4));
329 // garbage hi-order bits on 64bit are harmless.
330 __ xorptr(rdx, rax);
331 __ xorptr(rdx, rax);
332 __ cmp32(rcx, Address(rdx, 0));
333 // rax, ^ counter_addr ^ rax, = address
334 // ca1 is data dependent on the field
335 // access.
336 __ jcc (Assembler::notEqual, slow_with_pop);
337
338 #ifndef _WINDOWS
339 __ ret (0);
340 #else
341 // __stdcall calling convention
342 __ ret (3*wordSize);
343 #endif
344
345 __ bind (slow_with_pop);
346 // invalid load. pop FPU stack.
347 __ fstp_d (0);
348
349 slowcase_entry_pclist[count++] = __ pc();
350 __ bind (slow);
351 address slow_case_addr = NULL;
352 switch (type) {
353 case T_FLOAT: slow_case_addr = jni_GetFloatField_addr(); break;
354 case T_DOUBLE: slow_case_addr = jni_GetDoubleField_addr(); break;
355 default: ShouldNotReachHere();
356 }
357 // tail call
358 __ jump (ExternalAddress(slow_case_addr));
359
360 __ flush ();
361
362 #ifndef _WINDOWS
363 return fast_entry;
364 #else
365 switch (type) {
366 case T_FLOAT: jni_fast_GetFloatField_fp = (GetFloatField_t) fast_entry; break;
367 case T_DOUBLE: jni_fast_GetDoubleField_fp = (GetDoubleField_t) fast_entry; break;
368 }
369 return os::win32::fast_jni_accessor_wrapper(type);
370 #endif
371 }
372
generate_fast_get_float_field()373 address JNI_FastGetField::generate_fast_get_float_field() {
374 return generate_fast_get_float_field0(T_FLOAT);
375 }
376
generate_fast_get_double_field()377 address JNI_FastGetField::generate_fast_get_double_field() {
378 return generate_fast_get_float_field0(T_DOUBLE);
379 }
380