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