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