1 /* 2 * Copyright (c) 2004, 2024, 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 "precompiled.hpp" 26 #include "asm/macroAssembler.hpp" 27 #include "code/codeBlob.hpp" 28 #include "gc/shared/barrierSet.hpp" 29 #include "gc/shared/barrierSetAssembler.hpp" 30 #include "memory/resourceArea.hpp" 31 #include "prims/jniFastGetField.hpp" 32 #include "prims/jvm_misc.hpp" 33 #include "prims/jvmtiExport.hpp" 34 #include "runtime/safepoint.hpp" 35 36 #define __ masm-> 37 38 #define BUFFER_SIZE 40*wordSize 39 40 // Common register usage: 41 // rax/xmm0: result 42 // c_rarg0: jni env 43 // c_rarg1: obj 44 // c_rarg2: jfield id 45 46 static const Register rtmp = rax; // r8 == c_rarg2 on Windows 47 static const Register robj = r9; 48 static const Register roffset = r10; 49 static const Register rcounter = r11; 50 51 address JNI_FastGetField::generate_fast_get_int_field0(BasicType type) { 52 const char *name = nullptr; 53 switch (type) { 54 case T_BOOLEAN: name = "jni_fast_GetBooleanField"; break; 55 case T_BYTE: name = "jni_fast_GetByteField"; break; 56 case T_CHAR: name = "jni_fast_GetCharField"; break; 57 case T_SHORT: name = "jni_fast_GetShortField"; break; 58 case T_INT: name = "jni_fast_GetIntField"; break; 59 case T_LONG: name = "jni_fast_GetLongField"; break; 60 default: ShouldNotReachHere(); 61 } 62 ResourceMark rm; 63 BufferBlob* blob = BufferBlob::create(name, BUFFER_SIZE); 64 CodeBuffer cbuf(blob); 65 MacroAssembler* masm = new MacroAssembler(&cbuf); 66 address fast_entry = __ pc(); 67 68 Label slow; 69 70 ExternalAddress counter(SafepointSynchronize::safepoint_counter_addr()); 71 __ mov32 (rcounter, counter); 72 __ mov (robj, c_rarg1); 73 __ testb (rcounter, 1); 74 __ jcc (Assembler::notZero, slow); 75 76 if (JvmtiExport::can_post_field_access()) { 77 // Check to see if a field access watch has been set before we take the fast path. 78 assert_different_registers(rscratch1, robj, rcounter); 79 __ cmp32(ExternalAddress(JvmtiExport::get_field_access_count_addr()), 0, rscratch1); 80 __ jcc(Assembler::notZero, slow); 81 } 82 83 __ mov (roffset, c_rarg2); 84 __ shrptr(roffset, 2); // offset 85 86 // Both robj and rtmp are clobbered by try_resolve_jobject_in_native. 87 BarrierSetAssembler* bs = BarrierSet::barrier_set()->barrier_set_assembler(); 88 bs->try_resolve_jobject_in_native(masm, /* jni_env */ c_rarg0, robj, rtmp, slow); 89 DEBUG_ONLY(__ movl(rtmp, 0xDEADC0DE);) 90 91 assert(count < LIST_CAPACITY, "LIST_CAPACITY too small"); 92 speculative_load_pclist[count] = __ pc(); 93 switch (type) { 94 case T_BOOLEAN: __ movzbl (rax, Address(robj, roffset, Address::times_1)); break; 95 case T_BYTE: __ movsbl (rax, Address(robj, roffset, Address::times_1)); break; 96 case T_CHAR: __ movzwl (rax, Address(robj, roffset, Address::times_1)); break; 97 case T_SHORT: __ movswl (rax, Address(robj, roffset, Address::times_1)); break; 98 case T_INT: __ movl (rax, Address(robj, roffset, Address::times_1)); break; 99 case T_LONG: __ movq (rax, Address(robj, roffset, Address::times_1)); break; 100 default: ShouldNotReachHere(); 101 } 102 103 __ cmp32 (rcounter, counter, rscratch1); 104 __ jcc (Assembler::notEqual, slow); 105 106 __ ret (0); 107 108 slowcase_entry_pclist[count++] = __ pc(); 109 __ bind (slow); 110 address slow_case_addr = nullptr; 111 switch (type) { 112 case T_BOOLEAN: slow_case_addr = jni_GetBooleanField_addr(); break; 113 case T_BYTE: slow_case_addr = jni_GetByteField_addr(); break; 114 case T_CHAR: slow_case_addr = jni_GetCharField_addr(); break; 115 case T_SHORT: slow_case_addr = jni_GetShortField_addr(); break; 116 case T_INT: slow_case_addr = jni_GetIntField_addr(); break; 117 case T_LONG: slow_case_addr = jni_GetLongField_addr(); break; 118 default: break; 119 } 120 // tail call 121 __ jump (RuntimeAddress(slow_case_addr), rscratch1); 122 123 __ flush (); 124 125 return fast_entry; 126 } 127 128 address JNI_FastGetField::generate_fast_get_boolean_field() { 129 return generate_fast_get_int_field0(T_BOOLEAN); 130 } 131 132 address JNI_FastGetField::generate_fast_get_byte_field() { 133 return generate_fast_get_int_field0(T_BYTE); 134 } 135 136 address JNI_FastGetField::generate_fast_get_char_field() { 137 return generate_fast_get_int_field0(T_CHAR); 138 } 139 140 address JNI_FastGetField::generate_fast_get_short_field() { 141 return generate_fast_get_int_field0(T_SHORT); 142 } 143 144 address JNI_FastGetField::generate_fast_get_int_field() { 145 return generate_fast_get_int_field0(T_INT); 146 } 147 148 address JNI_FastGetField::generate_fast_get_long_field() { 149 return generate_fast_get_int_field0(T_LONG); 150 } 151 152 address JNI_FastGetField::generate_fast_get_float_field0(BasicType type) { 153 const char *name = nullptr; 154 switch (type) { 155 case T_FLOAT: name = "jni_fast_GetFloatField"; break; 156 case T_DOUBLE: name = "jni_fast_GetDoubleField"; break; 157 default: ShouldNotReachHere(); 158 } 159 ResourceMark rm; 160 BufferBlob* blob = BufferBlob::create(name, BUFFER_SIZE); 161 CodeBuffer cbuf(blob); 162 MacroAssembler* masm = new MacroAssembler(&cbuf); 163 address fast_entry = __ pc(); 164 165 Label slow; 166 167 ExternalAddress counter(SafepointSynchronize::safepoint_counter_addr()); 168 __ mov32 (rcounter, counter); 169 __ mov (robj, c_rarg1); 170 __ testb (rcounter, 1); 171 __ jcc (Assembler::notZero, slow); 172 173 if (JvmtiExport::can_post_field_access()) { 174 // Check to see if a field access watch has been set before we 175 // take the fast path. 176 __ cmp32(ExternalAddress(JvmtiExport::get_field_access_count_addr()), 0, rscratch1); 177 __ jcc(Assembler::notZero, slow); 178 } 179 180 // Both robj and rtmp are clobbered by try_resolve_jobject_in_native. 181 BarrierSetAssembler* bs = BarrierSet::barrier_set()->barrier_set_assembler(); 182 bs->try_resolve_jobject_in_native(masm, /* jni_env */ c_rarg0, robj, rtmp, slow); 183 DEBUG_ONLY(__ movl(rtmp, 0xDEADC0DE);) 184 185 __ mov (roffset, c_rarg2); 186 __ shrptr(roffset, 2); // offset 187 188 assert(count < LIST_CAPACITY, "LIST_CAPACITY too small"); 189 speculative_load_pclist[count] = __ pc(); 190 switch (type) { 191 case T_FLOAT: __ movflt (xmm0, Address(robj, roffset, Address::times_1)); break; 192 case T_DOUBLE: __ movdbl (xmm0, Address(robj, roffset, Address::times_1)); break; 193 default: ShouldNotReachHere(); 194 } 195 __ cmp32 (rcounter, counter, rscratch1); 196 __ jcc (Assembler::notEqual, slow); 197 198 __ ret (0); 199 200 slowcase_entry_pclist[count++] = __ pc(); 201 __ bind (slow); 202 address slow_case_addr = nullptr; 203 switch (type) { 204 case T_FLOAT: slow_case_addr = jni_GetFloatField_addr(); break; 205 case T_DOUBLE: slow_case_addr = jni_GetDoubleField_addr(); break; 206 default: break; 207 } 208 // tail call 209 __ jump (RuntimeAddress(slow_case_addr), rscratch1); 210 211 __ flush (); 212 213 return fast_entry; 214 } 215 216 address JNI_FastGetField::generate_fast_get_float_field() { 217 return generate_fast_get_float_field0(T_FLOAT); 218 } 219 220 address JNI_FastGetField::generate_fast_get_double_field() { 221 return generate_fast_get_float_field0(T_DOUBLE); 222 }