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 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 156 address JNI_FastGetField::generate_fast_get_boolean_field() { 157 return generate_fast_get_int_field0(T_BOOLEAN); 158 } 159 160 address JNI_FastGetField::generate_fast_get_byte_field() { 161 return generate_fast_get_int_field0(T_BYTE); 162 } 163 164 address JNI_FastGetField::generate_fast_get_char_field() { 165 return generate_fast_get_int_field0(T_CHAR); 166 } 167 168 address JNI_FastGetField::generate_fast_get_short_field() { 169 return generate_fast_get_int_field0(T_SHORT); 170 } 171 172 address JNI_FastGetField::generate_fast_get_int_field() { 173 return generate_fast_get_int_field0(T_INT); 174 } 175 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 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 372 address JNI_FastGetField::generate_fast_get_float_field() { 373 return generate_fast_get_float_field0(T_FLOAT); 374 } 375 376 address JNI_FastGetField::generate_fast_get_double_field() { 377 return generate_fast_get_float_field0(T_DOUBLE); 378 }