src/cpu/x86/vm/jniFastGetField_x86_64.cpp

Thu, 24 May 2018 17:06:56 +0800

author
aoqi
date
Thu, 24 May 2018 17:06:56 +0800
changeset 8604
04d83ba48607
parent 8316
626f594dffa6
parent 6876
710a3c8b516e
child 9703
2fdf635bcf28
permissions
-rw-r--r--

Merge

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*wordSize
aoqi@0 35
aoqi@0 36 // Instead of issuing lfence for LoadLoad barrier, we create data dependency
aoqi@0 37 // between loads, which is more efficient than lfence.
aoqi@0 38
aoqi@0 39 // Common register usage:
aoqi@0 40 // rax/xmm0: result
aoqi@0 41 // c_rarg0: jni env
aoqi@0 42 // c_rarg1: obj
aoqi@0 43 // c_rarg2: jfield id
aoqi@0 44
aoqi@0 45 static const Register robj = r9;
aoqi@0 46 static const Register rcounter = r10;
aoqi@0 47 static const Register roffset = r11;
aoqi@0 48 static const Register rcounter_addr = r11;
aoqi@0 49
aoqi@0 50 // Warning: do not use rip relative addressing after the first counter load
aoqi@0 51 // since that may scratch r10!
aoqi@0 52
aoqi@0 53 address JNI_FastGetField::generate_fast_get_int_field0(BasicType type) {
csahu@8316 54 const char *name = NULL;
aoqi@0 55 switch (type) {
aoqi@0 56 case T_BOOLEAN: name = "jni_fast_GetBooleanField"; break;
aoqi@0 57 case T_BYTE: name = "jni_fast_GetByteField"; break;
aoqi@0 58 case T_CHAR: name = "jni_fast_GetCharField"; break;
aoqi@0 59 case T_SHORT: name = "jni_fast_GetShortField"; break;
aoqi@0 60 case T_INT: name = "jni_fast_GetIntField"; break;
aoqi@0 61 case T_LONG: name = "jni_fast_GetLongField"; break;
aoqi@0 62 default: ShouldNotReachHere();
aoqi@0 63 }
aoqi@0 64 ResourceMark rm;
aoqi@0 65 BufferBlob* blob = BufferBlob::create(name, BUFFER_SIZE);
aoqi@0 66 CodeBuffer cbuf(blob);
aoqi@0 67 MacroAssembler* masm = new MacroAssembler(&cbuf);
aoqi@0 68 address fast_entry = __ pc();
aoqi@0 69
aoqi@0 70 Label slow;
aoqi@0 71
aoqi@0 72 ExternalAddress counter(SafepointSynchronize::safepoint_counter_addr());
aoqi@0 73 __ mov32 (rcounter, counter);
aoqi@0 74 __ mov (robj, c_rarg1);
aoqi@0 75 __ testb (rcounter, 1);
aoqi@0 76 __ jcc (Assembler::notZero, slow);
aoqi@0 77 if (os::is_MP()) {
aoqi@0 78 __ xorptr(robj, rcounter);
aoqi@0 79 __ xorptr(robj, rcounter); // obj, since
aoqi@0 80 // robj ^ rcounter ^ rcounter == robj
aoqi@0 81 // robj is data dependent on rcounter.
aoqi@0 82 }
aoqi@0 83 __ movptr(robj, Address(robj, 0)); // *obj
aoqi@0 84 __ mov (roffset, c_rarg2);
aoqi@0 85 __ shrptr(roffset, 2); // offset
aoqi@0 86
aoqi@0 87 assert(count < LIST_CAPACITY, "LIST_CAPACITY too small");
aoqi@0 88 speculative_load_pclist[count] = __ pc();
aoqi@0 89 switch (type) {
aoqi@0 90 case T_BOOLEAN: __ movzbl (rax, Address(robj, roffset, Address::times_1)); break;
aoqi@0 91 case T_BYTE: __ movsbl (rax, Address(robj, roffset, Address::times_1)); break;
aoqi@0 92 case T_CHAR: __ movzwl (rax, Address(robj, roffset, Address::times_1)); break;
aoqi@0 93 case T_SHORT: __ movswl (rax, Address(robj, roffset, Address::times_1)); break;
aoqi@0 94 case T_INT: __ movl (rax, Address(robj, roffset, Address::times_1)); break;
aoqi@0 95 case T_LONG: __ movq (rax, Address(robj, roffset, Address::times_1)); break;
aoqi@0 96 default: ShouldNotReachHere();
aoqi@0 97 }
aoqi@0 98
aoqi@0 99 if (os::is_MP()) {
aoqi@0 100 __ lea(rcounter_addr, counter);
aoqi@0 101 // ca is data dependent on rax.
aoqi@0 102 __ xorptr(rcounter_addr, rax);
aoqi@0 103 __ xorptr(rcounter_addr, rax);
aoqi@0 104 __ cmpl (rcounter, Address(rcounter_addr, 0));
aoqi@0 105 } else {
aoqi@0 106 __ cmp32 (rcounter, counter);
aoqi@0 107 }
aoqi@0 108 __ jcc (Assembler::notEqual, slow);
aoqi@0 109
aoqi@0 110 __ ret (0);
aoqi@0 111
aoqi@0 112 slowcase_entry_pclist[count++] = __ pc();
aoqi@0 113 __ bind (slow);
csahu@8316 114 address slow_case_addr = NULL;
aoqi@0 115 switch (type) {
aoqi@0 116 case T_BOOLEAN: slow_case_addr = jni_GetBooleanField_addr(); break;
aoqi@0 117 case T_BYTE: slow_case_addr = jni_GetByteField_addr(); break;
aoqi@0 118 case T_CHAR: slow_case_addr = jni_GetCharField_addr(); break;
aoqi@0 119 case T_SHORT: slow_case_addr = jni_GetShortField_addr(); break;
aoqi@0 120 case T_INT: slow_case_addr = jni_GetIntField_addr(); break;
aoqi@0 121 case T_LONG: slow_case_addr = jni_GetLongField_addr();
aoqi@0 122 }
aoqi@0 123 // tail call
aoqi@0 124 __ jump (ExternalAddress(slow_case_addr));
aoqi@0 125
aoqi@0 126 __ flush ();
aoqi@0 127
aoqi@0 128 return fast_entry;
aoqi@0 129 }
aoqi@0 130
aoqi@0 131 address JNI_FastGetField::generate_fast_get_boolean_field() {
aoqi@0 132 return generate_fast_get_int_field0(T_BOOLEAN);
aoqi@0 133 }
aoqi@0 134
aoqi@0 135 address JNI_FastGetField::generate_fast_get_byte_field() {
aoqi@0 136 return generate_fast_get_int_field0(T_BYTE);
aoqi@0 137 }
aoqi@0 138
aoqi@0 139 address JNI_FastGetField::generate_fast_get_char_field() {
aoqi@0 140 return generate_fast_get_int_field0(T_CHAR);
aoqi@0 141 }
aoqi@0 142
aoqi@0 143 address JNI_FastGetField::generate_fast_get_short_field() {
aoqi@0 144 return generate_fast_get_int_field0(T_SHORT);
aoqi@0 145 }
aoqi@0 146
aoqi@0 147 address JNI_FastGetField::generate_fast_get_int_field() {
aoqi@0 148 return generate_fast_get_int_field0(T_INT);
aoqi@0 149 }
aoqi@0 150
aoqi@0 151 address JNI_FastGetField::generate_fast_get_long_field() {
aoqi@0 152 return generate_fast_get_int_field0(T_LONG);
aoqi@0 153 }
aoqi@0 154
aoqi@0 155 address JNI_FastGetField::generate_fast_get_float_field0(BasicType type) {
csahu@8316 156 const char *name = NULL;
aoqi@0 157 switch (type) {
aoqi@0 158 case T_FLOAT: name = "jni_fast_GetFloatField"; break;
aoqi@0 159 case T_DOUBLE: name = "jni_fast_GetDoubleField"; break;
aoqi@0 160 default: ShouldNotReachHere();
aoqi@0 161 }
aoqi@0 162 ResourceMark rm;
aoqi@0 163 BufferBlob* blob = BufferBlob::create(name, BUFFER_SIZE);
aoqi@0 164 CodeBuffer cbuf(blob);
aoqi@0 165 MacroAssembler* masm = new MacroAssembler(&cbuf);
aoqi@0 166 address fast_entry = __ pc();
aoqi@0 167
aoqi@0 168 Label slow;
aoqi@0 169
aoqi@0 170 ExternalAddress counter(SafepointSynchronize::safepoint_counter_addr());
aoqi@0 171 __ mov32 (rcounter, counter);
aoqi@0 172 __ mov (robj, c_rarg1);
aoqi@0 173 __ testb (rcounter, 1);
aoqi@0 174 __ jcc (Assembler::notZero, slow);
aoqi@0 175 if (os::is_MP()) {
aoqi@0 176 __ xorptr(robj, rcounter);
aoqi@0 177 __ xorptr(robj, rcounter); // obj, since
aoqi@0 178 // robj ^ rcounter ^ rcounter == robj
aoqi@0 179 // robj is data dependent on rcounter.
aoqi@0 180 }
aoqi@0 181 __ movptr(robj, Address(robj, 0)); // *obj
aoqi@0 182 __ mov (roffset, c_rarg2);
aoqi@0 183 __ shrptr(roffset, 2); // offset
aoqi@0 184
aoqi@0 185 assert(count < LIST_CAPACITY, "LIST_CAPACITY too small");
aoqi@0 186 speculative_load_pclist[count] = __ pc();
aoqi@0 187 switch (type) {
aoqi@0 188 case T_FLOAT: __ movflt (xmm0, Address(robj, roffset, Address::times_1)); break;
aoqi@0 189 case T_DOUBLE: __ movdbl (xmm0, Address(robj, roffset, Address::times_1)); break;
aoqi@0 190 default: ShouldNotReachHere();
aoqi@0 191 }
aoqi@0 192
aoqi@0 193 if (os::is_MP()) {
aoqi@0 194 __ lea(rcounter_addr, counter);
aoqi@0 195 __ movdq (rax, xmm0);
aoqi@0 196 // counter address is data dependent on xmm0.
aoqi@0 197 __ xorptr(rcounter_addr, rax);
aoqi@0 198 __ xorptr(rcounter_addr, rax);
aoqi@0 199 __ cmpl (rcounter, Address(rcounter_addr, 0));
aoqi@0 200 } else {
aoqi@0 201 __ cmp32 (rcounter, counter);
aoqi@0 202 }
aoqi@0 203 __ jcc (Assembler::notEqual, slow);
aoqi@0 204
aoqi@0 205 __ ret (0);
aoqi@0 206
aoqi@0 207 slowcase_entry_pclist[count++] = __ pc();
aoqi@0 208 __ bind (slow);
csahu@8316 209 address slow_case_addr = NULL;
aoqi@0 210 switch (type) {
aoqi@0 211 case T_FLOAT: slow_case_addr = jni_GetFloatField_addr(); break;
aoqi@0 212 case T_DOUBLE: slow_case_addr = jni_GetDoubleField_addr();
aoqi@0 213 }
aoqi@0 214 // tail call
aoqi@0 215 __ jump (ExternalAddress(slow_case_addr));
aoqi@0 216
aoqi@0 217 __ flush ();
aoqi@0 218
aoqi@0 219 return fast_entry;
aoqi@0 220 }
aoqi@0 221
aoqi@0 222 address JNI_FastGetField::generate_fast_get_float_field() {
aoqi@0 223 return generate_fast_get_float_field0(T_FLOAT);
aoqi@0 224 }
aoqi@0 225
aoqi@0 226 address JNI_FastGetField::generate_fast_get_double_field() {
aoqi@0 227 return generate_fast_get_float_field0(T_DOUBLE);
aoqi@0 228 }

mercurial