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