1 /* 2 * Copyright (c) 2004, 2017, Oracle and/or its affiliates. All rights reserved. 3 * Copyright (c) 2014, Red Hat Inc. All rights reserved. 4 * Copyright (c) 2015, Linaro Ltd. All rights reserved. 5 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 6 * 7 * This code is free software; you can redistribute it and/or modify it 8 * under the terms of the GNU General Public License version 2 only, as 9 * published by the Free Software Foundation. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 * 25 */ 26 27 #include "precompiled.hpp" 28 #include "asm/macroAssembler.hpp" 29 #include "gc/shared/barrierSet.hpp" 30 #include "gc/shared/barrierSetAssembler.hpp" 31 #include "memory/resourceArea.hpp" 32 #include "prims/jniFastGetField.hpp" 33 #include "prims/jvm_misc.hpp" 34 #include "runtime/safepoint.hpp" 35 36 #define __ masm-> 37 38 #define BUFFER_SIZE_ARMV7 31*wordSize 39 #define BUFFER_SIZE_ARMV6 51*wordSize 40 41 // Instead of issuing a LoadLoad barrier we create an address 42 // dependency between loads; this might be more efficient. 43 44 // Common register usage: 45 // r0/v0: result 46 // c_rarg0: jni env 47 // c_rarg1: obj 48 // c_rarg2: jfield id 49 50 address JNI_FastGetField::generate_fast_get_int_field0(BasicType type) { 51 Register result = c_rarg0; 52 Register robj = c_rarg1; 53 Register rcounter = c_rarg3; 54 int args = RegSet::of(c_rarg0, c_rarg1, c_rarg2).bits(); 55 int nargs = 3; 56 57 const char *name; 58 switch (type) { 59 case T_BOOLEAN: name = "jni_fast_GetBooleanField"; break; 60 case T_BYTE: name = "jni_fast_GetByteField"; break; 61 case T_CHAR: name = "jni_fast_GetCharField"; break; 62 case T_SHORT: name = "jni_fast_GetShortField"; break; 63 case T_INT: name = "jni_fast_GetIntField"; break; 64 case T_LONG: name = "jni_fast_GetLongField"; break; 65 case T_FLOAT: name = "jni_fast_GetFloatField"; break; 66 case T_DOUBLE: name = "jni_fast_GetDoubleField"; break; 67 default: ShouldNotReachHere(); name = ""; // unreachable 68 } 69 ResourceMark rm; 70 BufferBlob* blob = BufferBlob::create(name, 71 VM_Version::features() & FT_ARMV7 ? 72 BUFFER_SIZE_ARMV7 : 73 BUFFER_SIZE_ARMV6 ); 74 CodeBuffer cbuf(blob); 75 MacroAssembler* masm = new MacroAssembler(&cbuf); 76 address fast_entry = __ pc(); 77 78 Label slow; 79 80 __ lea(rcounter, SafepointSynchronize::safepoint_counter_addr()); 81 __ ldr(rcounter, rcounter); 82 __ tst(rcounter, 1); 83 __ b(slow, Assembler::NE); 84 __ stmdb(sp, args); 85 // doesn't change c_rarg1 but does force a dependency on rcounter before 86 // performing __ ldr(robj, ... 87 __ eor(robj, c_rarg1, rcounter); 88 __ eor(robj, robj, rcounter); 89 90 BarrierSetAssembler* bs = BarrierSet::barrier_set()->barrier_set_assembler(); 91 bs->try_resolve_jobject_in_native(masm, c_rarg0, robj, noreg, slow); 92 93 assert(count < LIST_CAPACITY, "LIST_CAPACITY too small"); 94 speculative_load_pclist[count] = __ pc(); // Used by the segfault handler 95 // c_rarg2 * 2 is offset 96 // Only ldr & ldrb support shifted loads 97 switch (type) { 98 case T_FLOAT: 99 case T_INT: __ ldr (result, Address(robj, c_rarg2, lsr(2))); break; 100 case T_BOOLEAN: __ ldrb(result, Address(robj, c_rarg2, lsr(2))); break; 101 default: { 102 __ lsr(c_rarg2, c_rarg2, 2); 103 switch(type) { 104 case T_BYTE: __ ldrsb (result, Address(robj, c_rarg2)); break; 105 case T_CHAR: __ ldrh (result, Address(robj, c_rarg2)); break; 106 case T_SHORT: __ ldrsh (result, Address(robj, c_rarg2)); break; 107 case T_DOUBLE: 108 case T_LONG: __ ldrd (result, Address(robj, c_rarg2)); break; 109 default: ShouldNotReachHere(); 110 } 111 } 112 } 113 __ lea(rscratch2, SafepointSynchronize::safepoint_counter_addr()); 114 // rscratch2 is address dependent on result. 115 // TODO Do we need to force dependency on r1 too? 116 __ eor(rscratch2, rscratch2, result); 117 __ eor(rscratch2, rscratch2, result); 118 __ ldr(rscratch2, rscratch2); 119 __ cmp(rcounter, rscratch2); 120 121 #ifdef HARD_FLOAT_CC 122 switch (type) { 123 case T_FLOAT: __ vmov_f32(d0, result, Assembler::EQ); break; 124 case T_DOUBLE: __ vmov_f64(d0, r0, r1, Assembler::EQ); break; // Change me if result changes 125 default: break; 126 } 127 #endif//HARD_FLOAT_CC 128 129 __ add(sp, sp, nargs * wordSize, Assembler::EQ); // Pop args if we don't need them. 130 __ b(lr, Assembler::EQ); 131 132 // Restore args for slowcase call into the vm 133 __ ldmia(sp, args); 134 135 // Slowcase 136 slowcase_entry_pclist[count++] = __ pc(); 137 __ bind(slow); 138 139 address slow_case_addr = NULL; 140 switch (type) { 141 case T_BOOLEAN: slow_case_addr = jni_GetBooleanField_addr(); break; 142 case T_BYTE: slow_case_addr = jni_GetByteField_addr(); break; 143 case T_CHAR: slow_case_addr = jni_GetCharField_addr(); break; 144 case T_SHORT: slow_case_addr = jni_GetShortField_addr(); break; 145 case T_INT: slow_case_addr = jni_GetIntField_addr(); break; 146 case T_LONG: slow_case_addr = jni_GetLongField_addr(); break; 147 case T_FLOAT: slow_case_addr = jni_GetFloatField_addr(); break; 148 case T_DOUBLE: slow_case_addr = jni_GetDoubleField_addr(); break; 149 default: ShouldNotReachHere(); 150 } 151 152 { 153 __ enter(); 154 __ lea(rscratch2, ExternalAddress(slow_case_addr)); 155 __ bl(rscratch2); 156 __ maybe_isb(); 157 __ leave(); 158 __ b(lr); 159 } 160 __ flush (); 161 162 return fast_entry; 163 } 164 165 address JNI_FastGetField::generate_fast_get_boolean_field() { 166 return generate_fast_get_int_field0(T_BOOLEAN); 167 } 168 169 address JNI_FastGetField::generate_fast_get_byte_field() { 170 return generate_fast_get_int_field0(T_BYTE); 171 } 172 173 address JNI_FastGetField::generate_fast_get_char_field() { 174 return generate_fast_get_int_field0(T_CHAR); 175 } 176 177 address JNI_FastGetField::generate_fast_get_short_field() { 178 return generate_fast_get_int_field0(T_SHORT); 179 } 180 181 address JNI_FastGetField::generate_fast_get_int_field() { 182 return generate_fast_get_int_field0(T_INT); 183 } 184 185 address JNI_FastGetField::generate_fast_get_long_field() { 186 return generate_fast_get_int_field0(T_LONG); 187 } 188 189 address JNI_FastGetField::generate_fast_get_float_field() { 190 return generate_fast_get_int_field0(T_FLOAT); 191 } 192 193 address JNI_FastGetField::generate_fast_get_double_field() { 194 return generate_fast_get_int_field0(T_DOUBLE); 195 }