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 __ 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 148 address JNI_FastGetField::generate_fast_get_boolean_field() { 149 return generate_fast_get_int_field0(T_BOOLEAN); 150 } 151 152 address JNI_FastGetField::generate_fast_get_byte_field() { 153 return generate_fast_get_int_field0(T_BYTE); 154 } 155 156 address JNI_FastGetField::generate_fast_get_char_field() { 157 return generate_fast_get_int_field0(T_CHAR); 158 } 159 160 address JNI_FastGetField::generate_fast_get_short_field() { 161 return generate_fast_get_int_field0(T_SHORT); 162 } 163 164 address JNI_FastGetField::generate_fast_get_int_field() { 165 return generate_fast_get_int_field0(T_INT); 166 } 167 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 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 348 address JNI_FastGetField::generate_fast_get_float_field() { 349 return generate_fast_get_float_field0(T_FLOAT); 350 } 351 352 address JNI_FastGetField::generate_fast_get_double_field() { 353 return generate_fast_get_float_field0(T_DOUBLE); 354 }