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