src/cpu/x86/vm/jniFastGetField_x86_32.cpp

Wed, 27 Apr 2016 01:25:04 +0800

author
aoqi
date
Wed, 27 Apr 2016 01:25:04 +0800
changeset 0
f90c822e73f8
child 6876
710a3c8b516e
permissions
-rw-r--r--

Initial load
http://hg.openjdk.java.net/jdk8u/jdk8u/hotspot/
changeset: 6782:28b50d07f6f8
tag: jdk8u25-b17

aoqi@0 1 /*
aoqi@0 2 * Copyright (c) 2004, 2010, Oracle and/or its affiliates. All rights reserved.
aoqi@0 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
aoqi@0 4 *
aoqi@0 5 * This code is free software; you can redistribute it and/or modify it
aoqi@0 6 * under the terms of the GNU General Public License version 2 only, as
aoqi@0 7 * published by the Free Software Foundation.
aoqi@0 8 *
aoqi@0 9 * This code is distributed in the hope that it will be useful, but WITHOUT
aoqi@0 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
aoqi@0 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
aoqi@0 12 * version 2 for more details (a copy is included in the LICENSE file that
aoqi@0 13 * accompanied this code).
aoqi@0 14 *
aoqi@0 15 * You should have received a copy of the GNU General Public License version
aoqi@0 16 * 2 along with this work; if not, write to the Free Software Foundation,
aoqi@0 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
aoqi@0 18 *
aoqi@0 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
aoqi@0 20 * or visit www.oracle.com if you need additional information or have any
aoqi@0 21 * questions.
aoqi@0 22 *
aoqi@0 23 */
aoqi@0 24
aoqi@0 25 #include "precompiled.hpp"
aoqi@0 26 #include "asm/macroAssembler.hpp"
aoqi@0 27 #include "memory/resourceArea.hpp"
aoqi@0 28 #include "prims/jniFastGetField.hpp"
aoqi@0 29 #include "prims/jvm_misc.hpp"
aoqi@0 30 #include "runtime/safepoint.hpp"
aoqi@0 31
aoqi@0 32 #define __ masm->
aoqi@0 33
aoqi@0 34 #define BUFFER_SIZE 30
aoqi@0 35
aoqi@0 36 #ifdef _WINDOWS
aoqi@0 37 GetBooleanField_t JNI_FastGetField::jni_fast_GetBooleanField_fp;
aoqi@0 38 GetByteField_t JNI_FastGetField::jni_fast_GetByteField_fp;
aoqi@0 39 GetCharField_t JNI_FastGetField::jni_fast_GetCharField_fp;
aoqi@0 40 GetShortField_t JNI_FastGetField::jni_fast_GetShortField_fp;
aoqi@0 41 GetIntField_t JNI_FastGetField::jni_fast_GetIntField_fp;
aoqi@0 42 GetLongField_t JNI_FastGetField::jni_fast_GetLongField_fp;
aoqi@0 43 GetFloatField_t JNI_FastGetField::jni_fast_GetFloatField_fp;
aoqi@0 44 GetDoubleField_t JNI_FastGetField::jni_fast_GetDoubleField_fp;
aoqi@0 45 #endif
aoqi@0 46
aoqi@0 47 // Instead of issuing lfence for LoadLoad barrier, we create data dependency
aoqi@0 48 // between loads, which is much more efficient than lfence.
aoqi@0 49
aoqi@0 50 address JNI_FastGetField::generate_fast_get_int_field0(BasicType type) {
aoqi@0 51 const char *name;
aoqi@0 52 switch (type) {
aoqi@0 53 case T_BOOLEAN: name = "jni_fast_GetBooleanField"; break;
aoqi@0 54 case T_BYTE: name = "jni_fast_GetByteField"; break;
aoqi@0 55 case T_CHAR: name = "jni_fast_GetCharField"; break;
aoqi@0 56 case T_SHORT: name = "jni_fast_GetShortField"; break;
aoqi@0 57 case T_INT: name = "jni_fast_GetIntField"; break;
aoqi@0 58 default: ShouldNotReachHere();
aoqi@0 59 }
aoqi@0 60 ResourceMark rm;
aoqi@0 61 BufferBlob* blob = BufferBlob::create(name, BUFFER_SIZE*wordSize);
aoqi@0 62 CodeBuffer cbuf(blob);
aoqi@0 63 MacroAssembler* masm = new MacroAssembler(&cbuf);
aoqi@0 64 address fast_entry = __ pc();
aoqi@0 65
aoqi@0 66 Label slow;
aoqi@0 67
aoqi@0 68 // stack layout: offset from rsp (in words):
aoqi@0 69 // return pc 0
aoqi@0 70 // jni env 1
aoqi@0 71 // obj 2
aoqi@0 72 // jfieldID 3
aoqi@0 73
aoqi@0 74 ExternalAddress counter(SafepointSynchronize::safepoint_counter_addr());
aoqi@0 75 __ mov32 (rcx, counter);
aoqi@0 76 __ testb (rcx, 1);
aoqi@0 77 __ jcc (Assembler::notZero, slow);
aoqi@0 78 if (os::is_MP()) {
aoqi@0 79 __ mov(rax, rcx);
aoqi@0 80 __ andptr(rax, 1); // rax, must end up 0
aoqi@0 81 __ movptr(rdx, Address(rsp, rax, Address::times_1, 2*wordSize));
aoqi@0 82 // obj, notice rax, is 0.
aoqi@0 83 // rdx is data dependent on rcx.
aoqi@0 84 } else {
aoqi@0 85 __ movptr (rdx, Address(rsp, 2*wordSize)); // obj
aoqi@0 86 }
aoqi@0 87 __ movptr(rax, Address(rsp, 3*wordSize)); // jfieldID
aoqi@0 88 __ movptr(rdx, Address(rdx, 0)); // *obj
aoqi@0 89 __ shrptr (rax, 2); // offset
aoqi@0 90
aoqi@0 91 assert(count < LIST_CAPACITY, "LIST_CAPACITY too small");
aoqi@0 92 speculative_load_pclist[count] = __ pc();
aoqi@0 93 switch (type) {
aoqi@0 94 case T_BOOLEAN: __ movzbl (rax, Address(rdx, rax, Address::times_1)); break;
aoqi@0 95 case T_BYTE: __ movsbl (rax, Address(rdx, rax, Address::times_1)); break;
aoqi@0 96 case T_CHAR: __ movzwl (rax, Address(rdx, rax, Address::times_1)); break;
aoqi@0 97 case T_SHORT: __ movswl (rax, Address(rdx, rax, Address::times_1)); break;
aoqi@0 98 case T_INT: __ movl (rax, Address(rdx, rax, Address::times_1)); break;
aoqi@0 99 default: ShouldNotReachHere();
aoqi@0 100 }
aoqi@0 101
aoqi@0 102 Address ca1;
aoqi@0 103 if (os::is_MP()) {
aoqi@0 104 __ lea(rdx, counter);
aoqi@0 105 __ xorptr(rdx, rax);
aoqi@0 106 __ xorptr(rdx, rax);
aoqi@0 107 __ cmp32(rcx, Address(rdx, 0));
aoqi@0 108 // ca1 is the same as ca because
aoqi@0 109 // rax, ^ counter_addr ^ rax, = address
aoqi@0 110 // ca1 is data dependent on rax,.
aoqi@0 111 } else {
aoqi@0 112 __ cmp32(rcx, counter);
aoqi@0 113 }
aoqi@0 114 __ jcc (Assembler::notEqual, slow);
aoqi@0 115
aoqi@0 116 #ifndef _WINDOWS
aoqi@0 117 __ ret (0);
aoqi@0 118 #else
aoqi@0 119 // __stdcall calling convention
aoqi@0 120 __ ret (3*wordSize);
aoqi@0 121 #endif
aoqi@0 122
aoqi@0 123 slowcase_entry_pclist[count++] = __ pc();
aoqi@0 124 __ bind (slow);
aoqi@0 125 address slow_case_addr;
aoqi@0 126 switch (type) {
aoqi@0 127 case T_BOOLEAN: slow_case_addr = jni_GetBooleanField_addr(); break;
aoqi@0 128 case T_BYTE: slow_case_addr = jni_GetByteField_addr(); break;
aoqi@0 129 case T_CHAR: slow_case_addr = jni_GetCharField_addr(); break;
aoqi@0 130 case T_SHORT: slow_case_addr = jni_GetShortField_addr(); break;
aoqi@0 131 case T_INT: slow_case_addr = jni_GetIntField_addr();
aoqi@0 132 }
aoqi@0 133 // tail call
aoqi@0 134 __ jump (ExternalAddress(slow_case_addr));
aoqi@0 135
aoqi@0 136 __ flush ();
aoqi@0 137
aoqi@0 138 #ifndef _WINDOWS
aoqi@0 139 return fast_entry;
aoqi@0 140 #else
aoqi@0 141 switch (type) {
aoqi@0 142 case T_BOOLEAN: jni_fast_GetBooleanField_fp = (GetBooleanField_t) fast_entry; break;
aoqi@0 143 case T_BYTE: jni_fast_GetByteField_fp = (GetByteField_t) fast_entry; break;
aoqi@0 144 case T_CHAR: jni_fast_GetCharField_fp = (GetCharField_t) fast_entry; break;
aoqi@0 145 case T_SHORT: jni_fast_GetShortField_fp = (GetShortField_t) fast_entry; break;
aoqi@0 146 case T_INT: jni_fast_GetIntField_fp = (GetIntField_t) fast_entry; break;
aoqi@0 147 }
aoqi@0 148 return os::win32::fast_jni_accessor_wrapper(type);
aoqi@0 149 #endif
aoqi@0 150 }
aoqi@0 151
aoqi@0 152 address JNI_FastGetField::generate_fast_get_boolean_field() {
aoqi@0 153 return generate_fast_get_int_field0(T_BOOLEAN);
aoqi@0 154 }
aoqi@0 155
aoqi@0 156 address JNI_FastGetField::generate_fast_get_byte_field() {
aoqi@0 157 return generate_fast_get_int_field0(T_BYTE);
aoqi@0 158 }
aoqi@0 159
aoqi@0 160 address JNI_FastGetField::generate_fast_get_char_field() {
aoqi@0 161 return generate_fast_get_int_field0(T_CHAR);
aoqi@0 162 }
aoqi@0 163
aoqi@0 164 address JNI_FastGetField::generate_fast_get_short_field() {
aoqi@0 165 return generate_fast_get_int_field0(T_SHORT);
aoqi@0 166 }
aoqi@0 167
aoqi@0 168 address JNI_FastGetField::generate_fast_get_int_field() {
aoqi@0 169 return generate_fast_get_int_field0(T_INT);
aoqi@0 170 }
aoqi@0 171
aoqi@0 172 address JNI_FastGetField::generate_fast_get_long_field() {
aoqi@0 173 const char *name = "jni_fast_GetLongField";
aoqi@0 174 ResourceMark rm;
aoqi@0 175 BufferBlob* blob = BufferBlob::create(name, BUFFER_SIZE*wordSize);
aoqi@0 176 CodeBuffer cbuf(blob);
aoqi@0 177 MacroAssembler* masm = new MacroAssembler(&cbuf);
aoqi@0 178 address fast_entry = __ pc();
aoqi@0 179
aoqi@0 180 Label slow;
aoqi@0 181
aoqi@0 182 // stack layout: offset from rsp (in words):
aoqi@0 183 // old rsi 0
aoqi@0 184 // return pc 1
aoqi@0 185 // jni env 2
aoqi@0 186 // obj 3
aoqi@0 187 // jfieldID 4
aoqi@0 188
aoqi@0 189 ExternalAddress counter(SafepointSynchronize::safepoint_counter_addr());
aoqi@0 190
aoqi@0 191 __ push (rsi);
aoqi@0 192 __ mov32 (rcx, counter);
aoqi@0 193 __ testb (rcx, 1);
aoqi@0 194 __ jcc (Assembler::notZero, slow);
aoqi@0 195 if (os::is_MP()) {
aoqi@0 196 __ mov(rax, rcx);
aoqi@0 197 __ andptr(rax, 1); // rax, must end up 0
aoqi@0 198 __ movptr(rdx, Address(rsp, rax, Address::times_1, 3*wordSize));
aoqi@0 199 // obj, notice rax, is 0.
aoqi@0 200 // rdx is data dependent on rcx.
aoqi@0 201 } else {
aoqi@0 202 __ movptr(rdx, Address(rsp, 3*wordSize)); // obj
aoqi@0 203 }
aoqi@0 204 __ movptr(rsi, Address(rsp, 4*wordSize)); // jfieldID
aoqi@0 205 __ movptr(rdx, Address(rdx, 0)); // *obj
aoqi@0 206 __ shrptr(rsi, 2); // offset
aoqi@0 207
aoqi@0 208 assert(count < LIST_CAPACITY-1, "LIST_CAPACITY too small");
aoqi@0 209 speculative_load_pclist[count++] = __ pc();
aoqi@0 210 __ movptr(rax, Address(rdx, rsi, Address::times_1));
aoqi@0 211 #ifndef _LP64
aoqi@0 212 speculative_load_pclist[count] = __ pc();
aoqi@0 213 __ movl(rdx, Address(rdx, rsi, Address::times_1, 4));
aoqi@0 214 #endif // _LP64
aoqi@0 215
aoqi@0 216 if (os::is_MP()) {
aoqi@0 217 __ lea(rsi, counter);
aoqi@0 218 __ xorptr(rsi, rdx);
aoqi@0 219 __ xorptr(rsi, rax);
aoqi@0 220 __ xorptr(rsi, rdx);
aoqi@0 221 __ xorptr(rsi, rax);
aoqi@0 222 __ cmp32(rcx, Address(rsi, 0));
aoqi@0 223 // ca1 is the same as ca because
aoqi@0 224 // rax, ^ rdx ^ counter_addr ^ rax, ^ rdx = address
aoqi@0 225 // ca1 is data dependent on both rax, and rdx.
aoqi@0 226 } else {
aoqi@0 227 __ cmp32(rcx, counter);
aoqi@0 228 }
aoqi@0 229 __ jcc (Assembler::notEqual, slow);
aoqi@0 230
aoqi@0 231 __ pop (rsi);
aoqi@0 232
aoqi@0 233 #ifndef _WINDOWS
aoqi@0 234 __ ret (0);
aoqi@0 235 #else
aoqi@0 236 // __stdcall calling convention
aoqi@0 237 __ ret (3*wordSize);
aoqi@0 238 #endif
aoqi@0 239
aoqi@0 240 slowcase_entry_pclist[count-1] = __ pc();
aoqi@0 241 slowcase_entry_pclist[count++] = __ pc();
aoqi@0 242 __ bind (slow);
aoqi@0 243 __ pop (rsi);
aoqi@0 244 address slow_case_addr = jni_GetLongField_addr();;
aoqi@0 245 // tail call
aoqi@0 246 __ jump (ExternalAddress(slow_case_addr));
aoqi@0 247
aoqi@0 248 __ flush ();
aoqi@0 249
aoqi@0 250 #ifndef _WINDOWS
aoqi@0 251 return fast_entry;
aoqi@0 252 #else
aoqi@0 253 jni_fast_GetLongField_fp = (GetLongField_t) fast_entry;
aoqi@0 254 return os::win32::fast_jni_accessor_wrapper(T_LONG);
aoqi@0 255 #endif
aoqi@0 256 }
aoqi@0 257
aoqi@0 258 address JNI_FastGetField::generate_fast_get_float_field0(BasicType type) {
aoqi@0 259 const char *name;
aoqi@0 260 switch (type) {
aoqi@0 261 case T_FLOAT: name = "jni_fast_GetFloatField"; break;
aoqi@0 262 case T_DOUBLE: name = "jni_fast_GetDoubleField"; break;
aoqi@0 263 default: ShouldNotReachHere();
aoqi@0 264 }
aoqi@0 265 ResourceMark rm;
aoqi@0 266 BufferBlob* blob = BufferBlob::create(name, BUFFER_SIZE*wordSize);
aoqi@0 267 CodeBuffer cbuf(blob);
aoqi@0 268 MacroAssembler* masm = new MacroAssembler(&cbuf);
aoqi@0 269 address fast_entry = __ pc();
aoqi@0 270
aoqi@0 271 Label slow_with_pop, slow;
aoqi@0 272
aoqi@0 273 // stack layout: offset from rsp (in words):
aoqi@0 274 // return pc 0
aoqi@0 275 // jni env 1
aoqi@0 276 // obj 2
aoqi@0 277 // jfieldID 3
aoqi@0 278
aoqi@0 279 ExternalAddress counter(SafepointSynchronize::safepoint_counter_addr());
aoqi@0 280
aoqi@0 281 __ mov32 (rcx, counter);
aoqi@0 282 __ testb (rcx, 1);
aoqi@0 283 __ jcc (Assembler::notZero, slow);
aoqi@0 284 if (os::is_MP()) {
aoqi@0 285 __ mov(rax, rcx);
aoqi@0 286 __ andptr(rax, 1); // rax, must end up 0
aoqi@0 287 __ movptr(rdx, Address(rsp, rax, Address::times_1, 2*wordSize));
aoqi@0 288 // obj, notice rax, is 0.
aoqi@0 289 // rdx is data dependent on rcx.
aoqi@0 290 } else {
aoqi@0 291 __ movptr(rdx, Address(rsp, 2*wordSize)); // obj
aoqi@0 292 }
aoqi@0 293 __ movptr(rax, Address(rsp, 3*wordSize)); // jfieldID
aoqi@0 294 __ movptr(rdx, Address(rdx, 0)); // *obj
aoqi@0 295 __ shrptr(rax, 2); // offset
aoqi@0 296
aoqi@0 297 assert(count < LIST_CAPACITY, "LIST_CAPACITY too small");
aoqi@0 298 speculative_load_pclist[count] = __ pc();
aoqi@0 299 switch (type) {
aoqi@0 300 #ifndef _LP64
aoqi@0 301 case T_FLOAT: __ fld_s (Address(rdx, rax, Address::times_1)); break;
aoqi@0 302 case T_DOUBLE: __ fld_d (Address(rdx, rax, Address::times_1)); break;
aoqi@0 303 #else
aoqi@0 304 case T_FLOAT: __ movflt (xmm0, Address(robj, roffset, Address::times_1)); break;
aoqi@0 305 case T_DOUBLE: __ movdbl (xmm0, Address(robj, roffset, Address::times_1)); break;
aoqi@0 306 #endif // _LP64
aoqi@0 307 default: ShouldNotReachHere();
aoqi@0 308 }
aoqi@0 309
aoqi@0 310 Address ca1;
aoqi@0 311 if (os::is_MP()) {
aoqi@0 312 __ fst_s (Address(rsp, -4));
aoqi@0 313 __ lea(rdx, counter);
aoqi@0 314 __ movl (rax, Address(rsp, -4));
aoqi@0 315 // garbage hi-order bits on 64bit are harmless.
aoqi@0 316 __ xorptr(rdx, rax);
aoqi@0 317 __ xorptr(rdx, rax);
aoqi@0 318 __ cmp32(rcx, Address(rdx, 0));
aoqi@0 319 // rax, ^ counter_addr ^ rax, = address
aoqi@0 320 // ca1 is data dependent on the field
aoqi@0 321 // access.
aoqi@0 322 } else {
aoqi@0 323 __ cmp32(rcx, counter);
aoqi@0 324 }
aoqi@0 325 __ jcc (Assembler::notEqual, slow_with_pop);
aoqi@0 326
aoqi@0 327 #ifndef _WINDOWS
aoqi@0 328 __ ret (0);
aoqi@0 329 #else
aoqi@0 330 // __stdcall calling convention
aoqi@0 331 __ ret (3*wordSize);
aoqi@0 332 #endif
aoqi@0 333
aoqi@0 334 __ bind (slow_with_pop);
aoqi@0 335 // invalid load. pop FPU stack.
aoqi@0 336 __ fstp_d (0);
aoqi@0 337
aoqi@0 338 slowcase_entry_pclist[count++] = __ pc();
aoqi@0 339 __ bind (slow);
aoqi@0 340 address slow_case_addr;
aoqi@0 341 switch (type) {
aoqi@0 342 case T_FLOAT: slow_case_addr = jni_GetFloatField_addr(); break;
aoqi@0 343 case T_DOUBLE: slow_case_addr = jni_GetDoubleField_addr(); break;
aoqi@0 344 default: ShouldNotReachHere();
aoqi@0 345 }
aoqi@0 346 // tail call
aoqi@0 347 __ jump (ExternalAddress(slow_case_addr));
aoqi@0 348
aoqi@0 349 __ flush ();
aoqi@0 350
aoqi@0 351 #ifndef _WINDOWS
aoqi@0 352 return fast_entry;
aoqi@0 353 #else
aoqi@0 354 switch (type) {
aoqi@0 355 case T_FLOAT: jni_fast_GetFloatField_fp = (GetFloatField_t) fast_entry; break;
aoqi@0 356 case T_DOUBLE: jni_fast_GetDoubleField_fp = (GetDoubleField_t) fast_entry; break;
aoqi@0 357 }
aoqi@0 358 return os::win32::fast_jni_accessor_wrapper(type);
aoqi@0 359 #endif
aoqi@0 360 }
aoqi@0 361
aoqi@0 362 address JNI_FastGetField::generate_fast_get_float_field() {
aoqi@0 363 return generate_fast_get_float_field0(T_FLOAT);
aoqi@0 364 }
aoqi@0 365
aoqi@0 366 address JNI_FastGetField::generate_fast_get_double_field() {
aoqi@0 367 return generate_fast_get_float_field0(T_DOUBLE);
aoqi@0 368 }

mercurial