1 /*
2 * Copyright (c) 2016, 2020, Oracle and/or its affiliates. All rights reserved.
3 * Copyright (c) 2016 SAP SE. All rights reserved.
4 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 *
6 * This code is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License version 2 only, as
8 * published by the Free Software Foundation.
9 *
10 * This code is distributed in the hope that it will be useful, but WITHOUT
11 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
13 * version 2 for more details (a copy is included in the LICENSE file that
14 * accompanied this code).
15 *
16 * You should have received a copy of the GNU General Public License version
17 * 2 along with this work; if not, write to the Free Software Foundation,
18 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
19 *
20 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
21 * or visit www.oracle.com if you need additional information or have any
22 * questions.
23 *
24 */
25
26 #include "precompiled.hpp"
27 #include "asm/macroAssembler.inline.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 // TSO ensures that loads are blocking and ordered with respect to
37 // to earlier loads, so we don't need LoadLoad membars.
38
39 #define __ masm->
40
41 #define BUFFER_SIZE 30*sizeof(jint)
42
43 // Common register usage:
44 // Z_RET/Z_FRET: result
45 // Z_ARG1: jni env
46 // Z_ARG2: obj
47 // Z_ARG3: jfield id
48
generate_fast_get_int_field0(BasicType type)49 address JNI_FastGetField::generate_fast_get_int_field0(BasicType type) {
50 const char *name;
51 switch (type) {
52 case T_BOOLEAN: name = "jni_fast_GetBooleanField"; break;
53 case T_BYTE: name = "jni_fast_GetByteField"; break;
54 case T_CHAR: name = "jni_fast_GetCharField"; break;
55 case T_SHORT: name = "jni_fast_GetShortField"; break;
56 case T_INT: name = "jni_fast_GetIntField"; break;
57 case T_LONG: name = "jni_fast_GetLongField"; break;
58 case T_FLOAT: name = "jni_fast_GetFloatField"; break;
59 case T_DOUBLE: name = "jni_fast_GetDoubleField"; break;
60 default: ShouldNotReachHere();
61 name = NULL; // unreachable
62 }
63 ResourceMark rm;
64 BufferBlob* blob = BufferBlob::create(name, BUFFER_SIZE);
65 CodeBuffer cbuf(blob);
66 MacroAssembler* masm = new MacroAssembler(&cbuf);
67 address fast_entry = __ pc();
68
69 Label slow;
70
71 // We can only kill the remaining volatile registers.
72 const Register Rcounter = Z_ARG4,
73 Robj = Z_R1_scratch,
74 Rtmp = Z_R0_scratch;
75 __ load_const_optimized(Robj, SafepointSynchronize::safepoint_counter_addr());
76 __ z_lg(Rcounter, Address(Robj));
77 __ z_tmll(Rcounter, 1);
78 __ z_brnaz(slow);
79
80 if (JvmtiExport::can_post_field_access()) {
81 // Check to see if a field access watch has been set before we
82 // take the fast path.
83 __ load_const_optimized(Robj, JvmtiExport::get_field_access_count_addr());
84 __ z_lt(Robj, Address(Robj));
85 __ z_brne(slow);
86 }
87
88 __ z_lgr(Robj, Z_ARG2);
89 BarrierSetAssembler* bs = BarrierSet::barrier_set()->barrier_set_assembler();
90 bs->try_resolve_jobject_in_native(masm, Z_ARG1, Robj, Rtmp, slow);
91
92 __ z_srlg(Rtmp, Z_ARG3, 2); // offset
93 __ z_agr(Robj, Rtmp);
94
95 assert(count < LIST_CAPACITY, "LIST_CAPACITY too small");
96 speculative_load_pclist[count] = __ pc(); // Used by the segfault handler
97 bool is_fp = false;
98 switch (type) {
99 case T_BOOLEAN: __ z_llgc(Rtmp, Address(Robj)); break;
100 case T_BYTE: __ z_lgb( Rtmp, Address(Robj)); break;
101 case T_CHAR: __ z_llgh(Rtmp, Address(Robj)); break;
102 case T_SHORT: __ z_lgh( Rtmp, Address(Robj)); break;
103 case T_INT: __ z_lgf( Rtmp, Address(Robj)); break;
104 case T_LONG: __ z_lg( Rtmp, Address(Robj)); break;
105 case T_FLOAT: __ mem2freg_opt(Z_FRET, Address(Robj), false); is_fp = true; break;
106 case T_DOUBLE: __ mem2freg_opt(Z_FRET, Address(Robj), true ); is_fp = true; break;
107 default: ShouldNotReachHere();
108 }
109
110 __ load_const_optimized(Robj, SafepointSynchronize::safepoint_counter_addr());
111 __ z_cg(Rcounter, Address(Robj));
112 __ z_brne(slow);
113
114 if (!is_fp) {
115 __ z_lgr(Z_RET, Rtmp);
116 }
117 __ z_br(Z_R14);
118
119 slowcase_entry_pclist[count++] = __ pc();
120 __ bind(slow);
121 address slow_case_addr;
122 switch (type) {
123 case T_BOOLEAN: slow_case_addr = jni_GetBooleanField_addr(); break;
124 case T_BYTE: slow_case_addr = jni_GetByteField_addr(); break;
125 case T_CHAR: slow_case_addr = jni_GetCharField_addr(); break;
126 case T_SHORT: slow_case_addr = jni_GetShortField_addr(); break;
127 case T_INT: slow_case_addr = jni_GetIntField_addr(); break;
128 case T_LONG: slow_case_addr = jni_GetLongField_addr(); break;
129 case T_FLOAT: slow_case_addr = jni_GetFloatField_addr(); break;
130 case T_DOUBLE: slow_case_addr = jni_GetDoubleField_addr(); break;
131 default: ShouldNotReachHere();
132 slow_case_addr = NULL; // unreachable
133 }
134 __ load_const_optimized(Robj, slow_case_addr);
135 __ z_br(Robj); // tail call
136
137 __ flush();
138
139 return fast_entry;
140 }
141
generate_fast_get_boolean_field()142 address JNI_FastGetField::generate_fast_get_boolean_field() {
143 return generate_fast_get_int_field0(T_BOOLEAN);
144 }
145
generate_fast_get_byte_field()146 address JNI_FastGetField::generate_fast_get_byte_field() {
147 return generate_fast_get_int_field0(T_BYTE);
148 }
149
generate_fast_get_char_field()150 address JNI_FastGetField::generate_fast_get_char_field() {
151 return generate_fast_get_int_field0(T_CHAR);
152 }
153
generate_fast_get_short_field()154 address JNI_FastGetField::generate_fast_get_short_field() {
155 return generate_fast_get_int_field0(T_SHORT);
156 }
157
generate_fast_get_int_field()158 address JNI_FastGetField::generate_fast_get_int_field() {
159 return generate_fast_get_int_field0(T_INT);
160 }
161
generate_fast_get_long_field()162 address JNI_FastGetField::generate_fast_get_long_field() {
163 return generate_fast_get_int_field0(T_LONG);
164 }
165
generate_fast_get_float_field()166 address JNI_FastGetField::generate_fast_get_float_field() {
167 return generate_fast_get_int_field0(T_FLOAT);
168 }
169
generate_fast_get_double_field()170 address JNI_FastGetField::generate_fast_get_double_field() {
171 return generate_fast_get_int_field0(T_DOUBLE);
172 }
173