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