1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/src/cpu/x86/vm/jniFastGetField_x86_64.cpp Sat Dec 01 00:00:00 2007 +0000 1.3 @@ -0,0 +1,224 @@ 1.4 +/* 1.5 + * Copyright 2004-2006 Sun Microsystems, Inc. All Rights Reserved. 1.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 1.7 + * 1.8 + * This code is free software; you can redistribute it and/or modify it 1.9 + * under the terms of the GNU General Public License version 2 only, as 1.10 + * published by the Free Software Foundation. 1.11 + * 1.12 + * This code is distributed in the hope that it will be useful, but WITHOUT 1.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 1.14 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 1.15 + * version 2 for more details (a copy is included in the LICENSE file that 1.16 + * accompanied this code). 1.17 + * 1.18 + * You should have received a copy of the GNU General Public License version 1.19 + * 2 along with this work; if not, write to the Free Software Foundation, 1.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 1.21 + * 1.22 + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, 1.23 + * CA 95054 USA or visit www.sun.com if you need additional information or 1.24 + * have any questions. 1.25 + * 1.26 + */ 1.27 + 1.28 +# include "incls/_precompiled.incl" 1.29 +# include "incls/_jniFastGetField_x86_64.cpp.incl" 1.30 + 1.31 +#define __ masm-> 1.32 + 1.33 +#define BUFFER_SIZE 30*wordSize 1.34 + 1.35 +// Instead of issuing lfence for LoadLoad barrier, we create data dependency 1.36 +// between loads, which is more efficient than lfence. 1.37 + 1.38 +// Common register usage: 1.39 +// rax/xmm0: result 1.40 +// c_rarg0: jni env 1.41 +// c_rarg1: obj 1.42 +// c_rarg2: jfield id 1.43 + 1.44 +static const Register robj = r9; 1.45 +static const Register rcounter = r10; 1.46 +static const Register roffset = r11; 1.47 +static const Register rcounter_addr = r11; 1.48 + 1.49 +// Warning: do not use rip relative addressing after the first counter load 1.50 +// since that may scratch r10! 1.51 + 1.52 +address JNI_FastGetField::generate_fast_get_int_field0(BasicType type) { 1.53 + const char *name; 1.54 + switch (type) { 1.55 + case T_BOOLEAN: name = "jni_fast_GetBooleanField"; break; 1.56 + case T_BYTE: name = "jni_fast_GetByteField"; break; 1.57 + case T_CHAR: name = "jni_fast_GetCharField"; break; 1.58 + case T_SHORT: name = "jni_fast_GetShortField"; break; 1.59 + case T_INT: name = "jni_fast_GetIntField"; break; 1.60 + case T_LONG: name = "jni_fast_GetLongField"; break; 1.61 + default: ShouldNotReachHere(); 1.62 + } 1.63 + ResourceMark rm; 1.64 + BufferBlob* b = BufferBlob::create(name, BUFFER_SIZE); 1.65 + address fast_entry = b->instructions_begin(); 1.66 + CodeBuffer cbuf(fast_entry, b->instructions_size()); 1.67 + MacroAssembler* masm = new MacroAssembler(&cbuf); 1.68 + 1.69 + Label slow; 1.70 + 1.71 + ExternalAddress counter(SafepointSynchronize::safepoint_counter_addr()); 1.72 + __ mov32 (rcounter, counter); 1.73 + __ movq (robj, c_rarg1); 1.74 + __ testb (rcounter, 1); 1.75 + __ jcc (Assembler::notZero, slow); 1.76 + if (os::is_MP()) { 1.77 + __ xorq (robj, rcounter); 1.78 + __ xorq (robj, rcounter); // obj, since 1.79 + // robj ^ rcounter ^ rcounter == robj 1.80 + // robj is data dependent on rcounter. 1.81 + } 1.82 + __ movq (robj, Address(robj, 0)); // *obj 1.83 + __ movq (roffset, c_rarg2); 1.84 + __ shrq (roffset, 2); // offset 1.85 + 1.86 + assert(count < LIST_CAPACITY, "LIST_CAPACITY too small"); 1.87 + speculative_load_pclist[count] = __ pc(); 1.88 + switch (type) { 1.89 + case T_BOOLEAN: __ movzbl (rax, Address(robj, roffset, Address::times_1)); break; 1.90 + case T_BYTE: __ movsbl (rax, Address(robj, roffset, Address::times_1)); break; 1.91 + case T_CHAR: __ movzwl (rax, Address(robj, roffset, Address::times_1)); break; 1.92 + case T_SHORT: __ movswl (rax, Address(robj, roffset, Address::times_1)); break; 1.93 + case T_INT: __ movl (rax, Address(robj, roffset, Address::times_1)); break; 1.94 + case T_LONG: __ movq (rax, Address(robj, roffset, Address::times_1)); break; 1.95 + default: ShouldNotReachHere(); 1.96 + } 1.97 + 1.98 + if (os::is_MP()) { 1.99 + __ lea(rcounter_addr, counter); 1.100 + // ca is data dependent on rax. 1.101 + __ xorq (rcounter_addr, rax); 1.102 + __ xorq (rcounter_addr, rax); 1.103 + __ cmpl (rcounter, Address(rcounter_addr, 0)); 1.104 + } else { 1.105 + __ cmp32 (rcounter, counter); 1.106 + } 1.107 + __ jcc (Assembler::notEqual, slow); 1.108 + 1.109 + __ ret (0); 1.110 + 1.111 + slowcase_entry_pclist[count++] = __ pc(); 1.112 + __ bind (slow); 1.113 + address slow_case_addr; 1.114 + switch (type) { 1.115 + case T_BOOLEAN: slow_case_addr = jni_GetBooleanField_addr(); break; 1.116 + case T_BYTE: slow_case_addr = jni_GetByteField_addr(); break; 1.117 + case T_CHAR: slow_case_addr = jni_GetCharField_addr(); break; 1.118 + case T_SHORT: slow_case_addr = jni_GetShortField_addr(); break; 1.119 + case T_INT: slow_case_addr = jni_GetIntField_addr(); break; 1.120 + case T_LONG: slow_case_addr = jni_GetLongField_addr(); 1.121 + } 1.122 + // tail call 1.123 + __ jump (ExternalAddress(slow_case_addr)); 1.124 + 1.125 + __ flush (); 1.126 + 1.127 + return fast_entry; 1.128 +} 1.129 + 1.130 +address JNI_FastGetField::generate_fast_get_boolean_field() { 1.131 + return generate_fast_get_int_field0(T_BOOLEAN); 1.132 +} 1.133 + 1.134 +address JNI_FastGetField::generate_fast_get_byte_field() { 1.135 + return generate_fast_get_int_field0(T_BYTE); 1.136 +} 1.137 + 1.138 +address JNI_FastGetField::generate_fast_get_char_field() { 1.139 + return generate_fast_get_int_field0(T_CHAR); 1.140 +} 1.141 + 1.142 +address JNI_FastGetField::generate_fast_get_short_field() { 1.143 + return generate_fast_get_int_field0(T_SHORT); 1.144 +} 1.145 + 1.146 +address JNI_FastGetField::generate_fast_get_int_field() { 1.147 + return generate_fast_get_int_field0(T_INT); 1.148 +} 1.149 + 1.150 +address JNI_FastGetField::generate_fast_get_long_field() { 1.151 + return generate_fast_get_int_field0(T_LONG); 1.152 +} 1.153 + 1.154 +address JNI_FastGetField::generate_fast_get_float_field0(BasicType type) { 1.155 + const char *name; 1.156 + switch (type) { 1.157 + case T_FLOAT: name = "jni_fast_GetFloatField"; break; 1.158 + case T_DOUBLE: name = "jni_fast_GetDoubleField"; break; 1.159 + default: ShouldNotReachHere(); 1.160 + } 1.161 + ResourceMark rm; 1.162 + BufferBlob* b = BufferBlob::create(name, BUFFER_SIZE); 1.163 + address fast_entry = b->instructions_begin(); 1.164 + CodeBuffer cbuf(fast_entry, b->instructions_size()); 1.165 + MacroAssembler* masm = new MacroAssembler(&cbuf); 1.166 + 1.167 + Label slow; 1.168 + 1.169 + ExternalAddress counter(SafepointSynchronize::safepoint_counter_addr()); 1.170 + __ mov32 (rcounter, counter); 1.171 + __ movq (robj, c_rarg1); 1.172 + __ testb (rcounter, 1); 1.173 + __ jcc (Assembler::notZero, slow); 1.174 + if (os::is_MP()) { 1.175 + __ xorq (robj, rcounter); 1.176 + __ xorq (robj, rcounter); // obj, since 1.177 + // robj ^ rcounter ^ rcounter == robj 1.178 + // robj is data dependent on rcounter. 1.179 + } 1.180 + __ movq (robj, Address(robj, 0)); // *obj 1.181 + __ movq (roffset, c_rarg2); 1.182 + __ shrq (roffset, 2); // offset 1.183 + 1.184 + assert(count < LIST_CAPACITY, "LIST_CAPACITY too small"); 1.185 + speculative_load_pclist[count] = __ pc(); 1.186 + switch (type) { 1.187 + case T_FLOAT: __ movflt (xmm0, Address(robj, roffset, Address::times_1)); break; 1.188 + case T_DOUBLE: __ movdbl (xmm0, Address(robj, roffset, Address::times_1)); break; 1.189 + default: ShouldNotReachHere(); 1.190 + } 1.191 + 1.192 + if (os::is_MP()) { 1.193 + __ lea(rcounter_addr, counter); 1.194 + __ movdq (rax, xmm0); 1.195 + // counter address is data dependent on xmm0. 1.196 + __ xorq (rcounter_addr, rax); 1.197 + __ xorq (rcounter_addr, rax); 1.198 + __ cmpl (rcounter, Address(rcounter_addr, 0)); 1.199 + } else { 1.200 + __ cmp32 (rcounter, counter); 1.201 + } 1.202 + __ jcc (Assembler::notEqual, slow); 1.203 + 1.204 + __ ret (0); 1.205 + 1.206 + slowcase_entry_pclist[count++] = __ pc(); 1.207 + __ bind (slow); 1.208 + address slow_case_addr; 1.209 + switch (type) { 1.210 + case T_FLOAT: slow_case_addr = jni_GetFloatField_addr(); break; 1.211 + case T_DOUBLE: slow_case_addr = jni_GetDoubleField_addr(); 1.212 + } 1.213 + // tail call 1.214 + __ jump (ExternalAddress(slow_case_addr)); 1.215 + 1.216 + __ flush (); 1.217 + 1.218 + return fast_entry; 1.219 +} 1.220 + 1.221 +address JNI_FastGetField::generate_fast_get_float_field() { 1.222 + return generate_fast_get_float_field0(T_FLOAT); 1.223 +} 1.224 + 1.225 +address JNI_FastGetField::generate_fast_get_double_field() { 1.226 + return generate_fast_get_float_field0(T_DOUBLE); 1.227 +}