1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/src/cpu/x86/vm/jniFastGetField_x86_64.cpp Wed Apr 27 01:25:04 2016 +0800 1.3 @@ -0,0 +1,228 @@ 1.4 +/* 1.5 + * Copyright (c) 2004, 2010, Oracle and/or its affiliates. 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 1.23 + * or visit www.oracle.com if you need additional information or have any 1.24 + * questions. 1.25 + * 1.26 + */ 1.27 + 1.28 +#include "precompiled.hpp" 1.29 +#include "asm/macroAssembler.hpp" 1.30 +#include "memory/resourceArea.hpp" 1.31 +#include "prims/jniFastGetField.hpp" 1.32 +#include "prims/jvm_misc.hpp" 1.33 +#include "runtime/safepoint.hpp" 1.34 + 1.35 +#define __ masm-> 1.36 + 1.37 +#define BUFFER_SIZE 30*wordSize 1.38 + 1.39 +// Instead of issuing lfence for LoadLoad barrier, we create data dependency 1.40 +// between loads, which is more efficient than lfence. 1.41 + 1.42 +// Common register usage: 1.43 +// rax/xmm0: result 1.44 +// c_rarg0: jni env 1.45 +// c_rarg1: obj 1.46 +// c_rarg2: jfield id 1.47 + 1.48 +static const Register robj = r9; 1.49 +static const Register rcounter = r10; 1.50 +static const Register roffset = r11; 1.51 +static const Register rcounter_addr = r11; 1.52 + 1.53 +// Warning: do not use rip relative addressing after the first counter load 1.54 +// since that may scratch r10! 1.55 + 1.56 +address JNI_FastGetField::generate_fast_get_int_field0(BasicType type) { 1.57 + const char *name; 1.58 + switch (type) { 1.59 + case T_BOOLEAN: name = "jni_fast_GetBooleanField"; break; 1.60 + case T_BYTE: name = "jni_fast_GetByteField"; break; 1.61 + case T_CHAR: name = "jni_fast_GetCharField"; break; 1.62 + case T_SHORT: name = "jni_fast_GetShortField"; break; 1.63 + case T_INT: name = "jni_fast_GetIntField"; break; 1.64 + case T_LONG: name = "jni_fast_GetLongField"; break; 1.65 + default: ShouldNotReachHere(); 1.66 + } 1.67 + ResourceMark rm; 1.68 + BufferBlob* blob = BufferBlob::create(name, BUFFER_SIZE); 1.69 + CodeBuffer cbuf(blob); 1.70 + MacroAssembler* masm = new MacroAssembler(&cbuf); 1.71 + address fast_entry = __ pc(); 1.72 + 1.73 + Label slow; 1.74 + 1.75 + ExternalAddress counter(SafepointSynchronize::safepoint_counter_addr()); 1.76 + __ mov32 (rcounter, counter); 1.77 + __ mov (robj, c_rarg1); 1.78 + __ testb (rcounter, 1); 1.79 + __ jcc (Assembler::notZero, slow); 1.80 + if (os::is_MP()) { 1.81 + __ xorptr(robj, rcounter); 1.82 + __ xorptr(robj, rcounter); // obj, since 1.83 + // robj ^ rcounter ^ rcounter == robj 1.84 + // robj is data dependent on rcounter. 1.85 + } 1.86 + __ movptr(robj, Address(robj, 0)); // *obj 1.87 + __ mov (roffset, c_rarg2); 1.88 + __ shrptr(roffset, 2); // offset 1.89 + 1.90 + assert(count < LIST_CAPACITY, "LIST_CAPACITY too small"); 1.91 + speculative_load_pclist[count] = __ pc(); 1.92 + switch (type) { 1.93 + case T_BOOLEAN: __ movzbl (rax, Address(robj, roffset, Address::times_1)); break; 1.94 + case T_BYTE: __ movsbl (rax, Address(robj, roffset, Address::times_1)); break; 1.95 + case T_CHAR: __ movzwl (rax, Address(robj, roffset, Address::times_1)); break; 1.96 + case T_SHORT: __ movswl (rax, Address(robj, roffset, Address::times_1)); break; 1.97 + case T_INT: __ movl (rax, Address(robj, roffset, Address::times_1)); break; 1.98 + case T_LONG: __ movq (rax, Address(robj, roffset, Address::times_1)); break; 1.99 + default: ShouldNotReachHere(); 1.100 + } 1.101 + 1.102 + if (os::is_MP()) { 1.103 + __ lea(rcounter_addr, counter); 1.104 + // ca is data dependent on rax. 1.105 + __ xorptr(rcounter_addr, rax); 1.106 + __ xorptr(rcounter_addr, rax); 1.107 + __ cmpl (rcounter, Address(rcounter_addr, 0)); 1.108 + } else { 1.109 + __ cmp32 (rcounter, counter); 1.110 + } 1.111 + __ jcc (Assembler::notEqual, slow); 1.112 + 1.113 + __ ret (0); 1.114 + 1.115 + slowcase_entry_pclist[count++] = __ pc(); 1.116 + __ bind (slow); 1.117 + address slow_case_addr; 1.118 + switch (type) { 1.119 + case T_BOOLEAN: slow_case_addr = jni_GetBooleanField_addr(); break; 1.120 + case T_BYTE: slow_case_addr = jni_GetByteField_addr(); break; 1.121 + case T_CHAR: slow_case_addr = jni_GetCharField_addr(); break; 1.122 + case T_SHORT: slow_case_addr = jni_GetShortField_addr(); break; 1.123 + case T_INT: slow_case_addr = jni_GetIntField_addr(); break; 1.124 + case T_LONG: slow_case_addr = jni_GetLongField_addr(); 1.125 + } 1.126 + // tail call 1.127 + __ jump (ExternalAddress(slow_case_addr)); 1.128 + 1.129 + __ flush (); 1.130 + 1.131 + return fast_entry; 1.132 +} 1.133 + 1.134 +address JNI_FastGetField::generate_fast_get_boolean_field() { 1.135 + return generate_fast_get_int_field0(T_BOOLEAN); 1.136 +} 1.137 + 1.138 +address JNI_FastGetField::generate_fast_get_byte_field() { 1.139 + return generate_fast_get_int_field0(T_BYTE); 1.140 +} 1.141 + 1.142 +address JNI_FastGetField::generate_fast_get_char_field() { 1.143 + return generate_fast_get_int_field0(T_CHAR); 1.144 +} 1.145 + 1.146 +address JNI_FastGetField::generate_fast_get_short_field() { 1.147 + return generate_fast_get_int_field0(T_SHORT); 1.148 +} 1.149 + 1.150 +address JNI_FastGetField::generate_fast_get_int_field() { 1.151 + return generate_fast_get_int_field0(T_INT); 1.152 +} 1.153 + 1.154 +address JNI_FastGetField::generate_fast_get_long_field() { 1.155 + return generate_fast_get_int_field0(T_LONG); 1.156 +} 1.157 + 1.158 +address JNI_FastGetField::generate_fast_get_float_field0(BasicType type) { 1.159 + const char *name; 1.160 + switch (type) { 1.161 + case T_FLOAT: name = "jni_fast_GetFloatField"; break; 1.162 + case T_DOUBLE: name = "jni_fast_GetDoubleField"; break; 1.163 + default: ShouldNotReachHere(); 1.164 + } 1.165 + ResourceMark rm; 1.166 + BufferBlob* blob = BufferBlob::create(name, BUFFER_SIZE); 1.167 + CodeBuffer cbuf(blob); 1.168 + MacroAssembler* masm = new MacroAssembler(&cbuf); 1.169 + address fast_entry = __ pc(); 1.170 + 1.171 + Label slow; 1.172 + 1.173 + ExternalAddress counter(SafepointSynchronize::safepoint_counter_addr()); 1.174 + __ mov32 (rcounter, counter); 1.175 + __ mov (robj, c_rarg1); 1.176 + __ testb (rcounter, 1); 1.177 + __ jcc (Assembler::notZero, slow); 1.178 + if (os::is_MP()) { 1.179 + __ xorptr(robj, rcounter); 1.180 + __ xorptr(robj, rcounter); // obj, since 1.181 + // robj ^ rcounter ^ rcounter == robj 1.182 + // robj is data dependent on rcounter. 1.183 + } 1.184 + __ movptr(robj, Address(robj, 0)); // *obj 1.185 + __ mov (roffset, c_rarg2); 1.186 + __ shrptr(roffset, 2); // offset 1.187 + 1.188 + assert(count < LIST_CAPACITY, "LIST_CAPACITY too small"); 1.189 + speculative_load_pclist[count] = __ pc(); 1.190 + switch (type) { 1.191 + case T_FLOAT: __ movflt (xmm0, Address(robj, roffset, Address::times_1)); break; 1.192 + case T_DOUBLE: __ movdbl (xmm0, Address(robj, roffset, Address::times_1)); break; 1.193 + default: ShouldNotReachHere(); 1.194 + } 1.195 + 1.196 + if (os::is_MP()) { 1.197 + __ lea(rcounter_addr, counter); 1.198 + __ movdq (rax, xmm0); 1.199 + // counter address is data dependent on xmm0. 1.200 + __ xorptr(rcounter_addr, rax); 1.201 + __ xorptr(rcounter_addr, rax); 1.202 + __ cmpl (rcounter, Address(rcounter_addr, 0)); 1.203 + } else { 1.204 + __ cmp32 (rcounter, counter); 1.205 + } 1.206 + __ jcc (Assembler::notEqual, slow); 1.207 + 1.208 + __ ret (0); 1.209 + 1.210 + slowcase_entry_pclist[count++] = __ pc(); 1.211 + __ bind (slow); 1.212 + address slow_case_addr; 1.213 + switch (type) { 1.214 + case T_FLOAT: slow_case_addr = jni_GetFloatField_addr(); break; 1.215 + case T_DOUBLE: slow_case_addr = jni_GetDoubleField_addr(); 1.216 + } 1.217 + // tail call 1.218 + __ jump (ExternalAddress(slow_case_addr)); 1.219 + 1.220 + __ flush (); 1.221 + 1.222 + return fast_entry; 1.223 +} 1.224 + 1.225 +address JNI_FastGetField::generate_fast_get_float_field() { 1.226 + return generate_fast_get_float_field0(T_FLOAT); 1.227 +} 1.228 + 1.229 +address JNI_FastGetField::generate_fast_get_double_field() { 1.230 + return generate_fast_get_float_field0(T_DOUBLE); 1.231 +}