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 "incls/_precompiled.incl" 26 # include "incls/_jniFastGetField_x86_32.cpp.incl" 27 28 #define __ masm-> 29 30 #define BUFFER_SIZE 30 31 32 #ifdef _WINDOWS 33 GetBooleanField_t JNI_FastGetField::jni_fast_GetBooleanField_fp; 34 GetByteField_t JNI_FastGetField::jni_fast_GetByteField_fp; 35 GetCharField_t JNI_FastGetField::jni_fast_GetCharField_fp; 36 GetShortField_t JNI_FastGetField::jni_fast_GetShortField_fp; 37 GetIntField_t JNI_FastGetField::jni_fast_GetIntField_fp; 38 GetLongField_t JNI_FastGetField::jni_fast_GetLongField_fp; 39 GetFloatField_t JNI_FastGetField::jni_fast_GetFloatField_fp; 40 GetDoubleField_t JNI_FastGetField::jni_fast_GetDoubleField_fp; 41 #endif 42 43 // Instead of issuing lfence for LoadLoad barrier, we create data dependency 44 // between loads, which is much more efficient than lfence. 45 46 address JNI_FastGetField::generate_fast_get_int_field0(BasicType type) { 47 const char *name; 48 switch (type) { 49 case T_BOOLEAN: name = "jni_fast_GetBooleanField"; break; 50 case T_BYTE: name = "jni_fast_GetByteField"; break; 51 case T_CHAR: name = "jni_fast_GetCharField"; break; 52 case T_SHORT: name = "jni_fast_GetShortField"; break; 53 case T_INT: name = "jni_fast_GetIntField"; break; 54 default: ShouldNotReachHere(); 55 } 56 ResourceMark rm; 57 BufferBlob* blob = BufferBlob::create(name, BUFFER_SIZE*wordSize); 58 CodeBuffer cbuf(blob); 59 MacroAssembler* masm = new MacroAssembler(&cbuf); 60 address fast_entry = __ pc(); 61 62 Label slow; 63 64 // stack layout: offset from rsp (in words): 65 // return pc 0 66 // jni env 1 67 // obj 2 68 // jfieldID 3 69 70 ExternalAddress counter(SafepointSynchronize::safepoint_counter_addr()); 71 __ mov32 (rcx, counter); 72 __ testb (rcx, 1); 73 __ jcc (Assembler::notZero, slow); 74 if (os::is_MP()) { 75 __ mov(rax, rcx); 76 __ andptr(rax, 1); // rax, must end up 0 77 __ movptr(rdx, Address(rsp, rax, Address::times_1, 2*wordSize)); 78 // obj, notice rax, is 0. 79 // rdx is data dependent on rcx. 80 } else { 81 __ movptr (rdx, Address(rsp, 2*wordSize)); // obj 82 } 83 __ movptr(rax, Address(rsp, 3*wordSize)); // jfieldID 84 __ movptr(rdx, Address(rdx, 0)); // *obj 85 __ shrptr (rax, 2); // offset 86 87 assert(count < LIST_CAPACITY, "LIST_CAPACITY too small"); 88 speculative_load_pclist[count] = __ pc(); 89 switch (type) { 90 case T_BOOLEAN: __ movzbl (rax, Address(rdx, rax, Address::times_1)); break; 91 case T_BYTE: __ movsbl (rax, Address(rdx, rax, Address::times_1)); break; 92 case T_CHAR: __ movzwl (rax, Address(rdx, rax, Address::times_1)); break; 93 case T_SHORT: __ movswl (rax, Address(rdx, rax, Address::times_1)); break; 94 case T_INT: __ movl (rax, Address(rdx, rax, Address::times_1)); break; 95 default: ShouldNotReachHere(); 96 } 97 98 Address ca1; 99 if (os::is_MP()) { 100 __ lea(rdx, counter); 101 __ xorptr(rdx, rax); 102 __ xorptr(rdx, rax); 103 __ cmp32(rcx, Address(rdx, 0)); 104 // ca1 is the same as ca because 105 // rax, ^ counter_addr ^ rax, = address 106 // ca1 is data dependent on rax,. 107 } else { 108 __ cmp32(rcx, counter); 109 } 110 __ jcc (Assembler::notEqual, slow); 111 112 #ifndef _WINDOWS 113 __ ret (0); 114 #else 115 // __stdcall calling convention 116 __ ret (3*wordSize); 117 #endif 118 119 slowcase_entry_pclist[count++] = __ pc(); 120 __ bind (slow); 121 address slow_case_addr; 122 switch (type) { 123 case T_BOOLEAN: slow_case_addr = jni_GetBooleanField_addr(); break; 124 case T_BYTE: slow_case_addr = jni_GetByteField_addr(); break; 125 case T_CHAR: slow_case_addr = jni_GetCharField_addr(); break; 126 case T_SHORT: slow_case_addr = jni_GetShortField_addr(); break; 127 case T_INT: slow_case_addr = jni_GetIntField_addr(); 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 if (os::is_MP()) { 192 __ mov(rax, rcx); 193 __ andptr(rax, 1); // rax, must end up 0 194 __ movptr(rdx, Address(rsp, rax, Address::times_1, 3*wordSize)); 195 // obj, notice rax, is 0. 196 // rdx is data dependent on rcx. 197 } else { 198 __ movptr(rdx, Address(rsp, 3*wordSize)); // obj 199 } 200 __ movptr(rsi, Address(rsp, 4*wordSize)); // jfieldID 201 __ movptr(rdx, Address(rdx, 0)); // *obj 202 __ shrptr(rsi, 2); // offset 203 204 assert(count < LIST_CAPACITY-1, "LIST_CAPACITY too small"); 205 speculative_load_pclist[count++] = __ pc(); 206 __ movptr(rax, Address(rdx, rsi, Address::times_1)); 207 #ifndef _LP64 208 speculative_load_pclist[count] = __ pc(); 209 __ movl(rdx, Address(rdx, rsi, Address::times_1, 4)); 210 #endif // _LP64 211 212 if (os::is_MP()) { 213 __ lea(rsi, counter); 214 __ xorptr(rsi, rdx); 215 __ xorptr(rsi, rax); 216 __ xorptr(rsi, rdx); 217 __ xorptr(rsi, rax); 218 __ cmp32(rcx, Address(rsi, 0)); 219 // ca1 is the same as ca because 220 // rax, ^ rdx ^ counter_addr ^ rax, ^ rdx = address 221 // ca1 is data dependent on both rax, and rdx. 222 } else { 223 __ cmp32(rcx, counter); 224 } 225 __ jcc (Assembler::notEqual, slow); 226 227 __ pop (rsi); 228 229 #ifndef _WINDOWS 230 __ ret (0); 231 #else 232 // __stdcall calling convention 233 __ ret (3*wordSize); 234 #endif 235 236 slowcase_entry_pclist[count-1] = __ pc(); 237 slowcase_entry_pclist[count++] = __ pc(); 238 __ bind (slow); 239 __ pop (rsi); 240 address slow_case_addr = jni_GetLongField_addr();; 241 // tail call 242 __ jump (ExternalAddress(slow_case_addr)); 243 244 __ flush (); 245 246 #ifndef _WINDOWS 247 return fast_entry; 248 #else 249 jni_fast_GetLongField_fp = (GetLongField_t) fast_entry; 250 return os::win32::fast_jni_accessor_wrapper(T_LONG); 251 #endif 252 } 253 254 address JNI_FastGetField::generate_fast_get_float_field0(BasicType type) { 255 const char *name; 256 switch (type) { 257 case T_FLOAT: name = "jni_fast_GetFloatField"; break; 258 case T_DOUBLE: name = "jni_fast_GetDoubleField"; break; 259 default: ShouldNotReachHere(); 260 } 261 ResourceMark rm; 262 BufferBlob* blob = BufferBlob::create(name, BUFFER_SIZE*wordSize); 263 CodeBuffer cbuf(blob); 264 MacroAssembler* masm = new MacroAssembler(&cbuf); 265 address fast_entry = __ pc(); 266 267 Label slow_with_pop, slow; 268 269 // stack layout: offset from rsp (in words): 270 // return pc 0 271 // jni env 1 272 // obj 2 273 // jfieldID 3 274 275 ExternalAddress counter(SafepointSynchronize::safepoint_counter_addr()); 276 277 __ mov32 (rcx, counter); 278 __ testb (rcx, 1); 279 __ jcc (Assembler::notZero, slow); 280 if (os::is_MP()) { 281 __ mov(rax, rcx); 282 __ andptr(rax, 1); // rax, must end up 0 283 __ movptr(rdx, Address(rsp, rax, Address::times_1, 2*wordSize)); 284 // obj, notice rax, is 0. 285 // rdx is data dependent on rcx. 286 } else { 287 __ movptr(rdx, Address(rsp, 2*wordSize)); // obj 288 } 289 __ movptr(rax, Address(rsp, 3*wordSize)); // jfieldID 290 __ movptr(rdx, Address(rdx, 0)); // *obj 291 __ shrptr(rax, 2); // offset 292 293 assert(count < LIST_CAPACITY, "LIST_CAPACITY too small"); 294 speculative_load_pclist[count] = __ pc(); 295 switch (type) { 296 #ifndef _LP64 297 case T_FLOAT: __ fld_s (Address(rdx, rax, Address::times_1)); break; 298 case T_DOUBLE: __ fld_d (Address(rdx, rax, Address::times_1)); break; 299 #else 300 case T_FLOAT: __ movflt (xmm0, Address(robj, roffset, Address::times_1)); break; 301 case T_DOUBLE: __ movdbl (xmm0, Address(robj, roffset, Address::times_1)); break; 302 #endif // _LP64 303 default: ShouldNotReachHere(); 304 } 305 306 Address ca1; 307 if (os::is_MP()) { 308 __ fst_s (Address(rsp, -4)); 309 __ lea(rdx, counter); 310 __ movl (rax, Address(rsp, -4)); 311 // garbage hi-order bits on 64bit are harmless. 312 __ xorptr(rdx, rax); 313 __ xorptr(rdx, rax); 314 __ cmp32(rcx, Address(rdx, 0)); 315 // rax, ^ counter_addr ^ rax, = address 316 // ca1 is data dependent on the field 317 // access. 318 } else { 319 __ cmp32(rcx, counter); 320 } 321 __ jcc (Assembler::notEqual, slow_with_pop); 322 323 #ifndef _WINDOWS 324 __ ret (0); 325 #else 326 // __stdcall calling convention 327 __ ret (3*wordSize); 328 #endif 329 330 __ bind (slow_with_pop); 331 // invalid load. pop FPU stack. 332 __ fstp_d (0); 333 334 slowcase_entry_pclist[count++] = __ pc(); 335 __ bind (slow); 336 address slow_case_addr; 337 switch (type) { 338 case T_FLOAT: slow_case_addr = jni_GetFloatField_addr(); break; 339 case T_DOUBLE: slow_case_addr = jni_GetDoubleField_addr(); break; 340 default: ShouldNotReachHere(); 341 } 342 // tail call 343 __ jump (ExternalAddress(slow_case_addr)); 344 345 __ flush (); 346 347 #ifndef _WINDOWS 348 return fast_entry; 349 #else 350 switch (type) { 351 case T_FLOAT: jni_fast_GetFloatField_fp = (GetFloatField_t) fast_entry; break; 352 case T_DOUBLE: jni_fast_GetDoubleField_fp = (GetDoubleField_t) fast_entry; break; 353 } 354 return os::win32::fast_jni_accessor_wrapper(type); 355 #endif 356 } 357 358 address JNI_FastGetField::generate_fast_get_float_field() { 359 return generate_fast_get_float_field0(T_FLOAT); 360 } 361 362 address JNI_FastGetField::generate_fast_get_double_field() { 363 return generate_fast_get_float_field0(T_DOUBLE); 364 }