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 __ mov32(rax, ExternalAddress((address) JvmtiExport::get_field_access_count_addr())); 83 __ testl(rax, rax); 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 157 address JNI_FastGetField::generate_fast_get_boolean_field() { 158 return generate_fast_get_int_field0(T_BOOLEAN); 159 } 160 161 address JNI_FastGetField::generate_fast_get_byte_field() { 162 return generate_fast_get_int_field0(T_BYTE); 163 } 164 165 address JNI_FastGetField::generate_fast_get_char_field() { 166 return generate_fast_get_int_field0(T_CHAR); 167 } 168 169 address JNI_FastGetField::generate_fast_get_short_field() { 170 return generate_fast_get_int_field0(T_SHORT); 171 } 172 173 address JNI_FastGetField::generate_fast_get_int_field() { 174 return generate_fast_get_int_field0(T_INT); 175 } 176 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 __ mov32(rax, ExternalAddress((address) JvmtiExport::get_field_access_count_addr())); 205 __ testl(rax, rax); 206 __ jcc(Assembler::notZero, slow); 207 } 208 209 __ mov(rax, rcx); 210 __ andptr(rax, 1); // rax, must end up 0 211 __ movptr(rdx, Address(rsp, rax, Address::times_1, 3*wordSize)); 212 // obj, notice rax, is 0. 213 // rdx is data dependent on rcx. 214 __ movptr(rsi, Address(rsp, 4*wordSize)); // jfieldID 215 216 __ clear_jweak_tag(rdx); 217 218 __ movptr(rdx, Address(rdx, 0)); // *obj 219 __ shrptr(rsi, 2); // offset 220 221 assert(count < LIST_CAPACITY-1, "LIST_CAPACITY too small"); 222 speculative_load_pclist[count++] = __ pc(); 223 __ movptr(rax, Address(rdx, rsi, Address::times_1)); 224 #ifndef _LP64 225 speculative_load_pclist[count] = __ pc(); 226 __ movl(rdx, Address(rdx, rsi, Address::times_1, 4)); 227 #endif // _LP64 228 229 __ lea(rsi, counter); 230 __ xorptr(rsi, rdx); 231 __ xorptr(rsi, rax); 232 __ xorptr(rsi, rdx); 233 __ xorptr(rsi, rax); 234 __ cmp32(rcx, Address(rsi, 0)); 235 // ca1 is the same as ca because 236 // rax, ^ rdx ^ counter_addr ^ rax, ^ rdx = address 237 // ca1 is data dependent on both rax, and rdx. 238 __ jcc (Assembler::notEqual, slow); 239 240 __ pop (rsi); 241 242 #ifndef _WINDOWS 243 __ ret (0); 244 #else 245 // __stdcall calling convention 246 __ ret (3*wordSize); 247 #endif 248 249 slowcase_entry_pclist[count-1] = __ pc(); 250 slowcase_entry_pclist[count++] = __ pc(); 251 __ bind (slow); 252 __ pop (rsi); 253 address slow_case_addr = jni_GetLongField_addr();; 254 // tail call 255 __ jump (ExternalAddress(slow_case_addr)); 256 257 __ flush (); 258 259 #ifndef _WINDOWS 260 return fast_entry; 261 #else 262 jni_fast_GetLongField_fp = (GetLongField_t) fast_entry; 263 return os::win32::fast_jni_accessor_wrapper(T_LONG); 264 #endif 265 } 266 267 address JNI_FastGetField::generate_fast_get_float_field0(BasicType type) { 268 const char *name = NULL; 269 switch (type) { 270 case T_FLOAT: name = "jni_fast_GetFloatField"; break; 271 case T_DOUBLE: name = "jni_fast_GetDoubleField"; break; 272 default: ShouldNotReachHere(); 273 } 274 ResourceMark rm; 275 BufferBlob* blob = BufferBlob::create(name, BUFFER_SIZE*wordSize); 276 CodeBuffer cbuf(blob); 277 MacroAssembler* masm = new MacroAssembler(&cbuf); 278 address fast_entry = __ pc(); 279 280 Label slow_with_pop, slow; 281 282 // stack layout: offset from rsp (in words): 283 // return pc 0 284 // jni env 1 285 // obj 2 286 // jfieldID 3 287 288 ExternalAddress counter(SafepointSynchronize::safepoint_counter_addr()); 289 290 __ mov32 (rcx, counter); 291 __ testb (rcx, 1); 292 __ jcc (Assembler::notZero, slow); 293 294 if (JvmtiExport::can_post_field_access()) { 295 // Check to see if a field access watch has been set before we 296 // take the fast path. 297 __ mov32(rax, ExternalAddress((address) JvmtiExport::get_field_access_count_addr())); 298 __ testl(rax, rax); 299 __ jcc(Assembler::notZero, slow); 300 } 301 302 __ mov(rax, rcx); 303 __ andptr(rax, 1); // rax, must end up 0 304 __ movptr(rdx, Address(rsp, rax, Address::times_1, 2*wordSize)); 305 // obj, notice rax, is 0. 306 // rdx is data dependent on rcx. 307 __ movptr(rax, Address(rsp, 3*wordSize)); // jfieldID 308 309 __ clear_jweak_tag(rdx); 310 311 __ movptr(rdx, Address(rdx, 0)); // *obj 312 __ shrptr(rax, 2); // offset 313 314 assert(count < LIST_CAPACITY, "LIST_CAPACITY too small"); 315 speculative_load_pclist[count] = __ pc(); 316 switch (type) { 317 #ifndef _LP64 318 case T_FLOAT: __ fld_s (Address(rdx, rax, Address::times_1)); break; 319 case T_DOUBLE: __ fld_d (Address(rdx, rax, Address::times_1)); break; 320 #else 321 case T_FLOAT: __ movflt (xmm0, Address(robj, roffset, Address::times_1)); break; 322 case T_DOUBLE: __ movdbl (xmm0, Address(robj, roffset, Address::times_1)); break; 323 #endif // _LP64 324 default: ShouldNotReachHere(); 325 } 326 327 Address ca1; 328 __ fst_s (Address(rsp, -4)); 329 __ lea(rdx, counter); 330 __ movl (rax, Address(rsp, -4)); 331 // garbage hi-order bits on 64bit are harmless. 332 __ xorptr(rdx, rax); 333 __ xorptr(rdx, rax); 334 __ cmp32(rcx, Address(rdx, 0)); 335 // rax, ^ counter_addr ^ rax, = address 336 // ca1 is data dependent on the field 337 // access. 338 __ jcc (Assembler::notEqual, slow_with_pop); 339 340 #ifndef _WINDOWS 341 __ ret (0); 342 #else 343 // __stdcall calling convention 344 __ ret (3*wordSize); 345 #endif 346 347 __ bind (slow_with_pop); 348 // invalid load. pop FPU stack. 349 __ fstp_d (0); 350 351 slowcase_entry_pclist[count++] = __ pc(); 352 __ bind (slow); 353 address slow_case_addr = NULL; 354 switch (type) { 355 case T_FLOAT: slow_case_addr = jni_GetFloatField_addr(); break; 356 case T_DOUBLE: slow_case_addr = jni_GetDoubleField_addr(); break; 357 default: ShouldNotReachHere(); 358 } 359 // tail call 360 __ jump (ExternalAddress(slow_case_addr)); 361 362 __ flush (); 363 364 #ifndef _WINDOWS 365 return fast_entry; 366 #else 367 switch (type) { 368 case T_FLOAT: jni_fast_GetFloatField_fp = (GetFloatField_t) fast_entry; break; 369 case T_DOUBLE: jni_fast_GetDoubleField_fp = (GetDoubleField_t) fast_entry; break; 370 } 371 return os::win32::fast_jni_accessor_wrapper(type); 372 #endif 373 } 374 375 address JNI_FastGetField::generate_fast_get_float_field() { 376 return generate_fast_get_float_field0(T_FLOAT); 377 } 378 379 address JNI_FastGetField::generate_fast_get_double_field() { 380 return generate_fast_get_float_field0(T_DOUBLE); 381 }