1 /*
2 * Copyright (c) 2016, 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 "runtime/safepoint.hpp"
34
35 // TSO ensures that loads are blocking and ordered with respect to
36 // to earlier loads, so we don't need LoadLoad membars.
37
38 #define __ masm->
39
40 #define BUFFER_SIZE 30*sizeof(jint)
41
42 // Common register usage:
43 // Z_RET/Z_FRET: result
44 // Z_ARG1: jni env
45 // Z_ARG2: obj
46 // Z_ARG3: jfield id
47
generate_fast_get_int_field0(BasicType type)48 address JNI_FastGetField::generate_fast_get_int_field0(BasicType type) {
49 const char *name;
50 switch (type) {
51 case T_BOOLEAN: name = "jni_fast_GetBooleanField"; break;
52 case T_BYTE: name = "jni_fast_GetByteField"; break;
53 case T_CHAR: name = "jni_fast_GetCharField"; break;
54 case T_SHORT: name = "jni_fast_GetShortField"; break;
55 case T_INT: name = "jni_fast_GetIntField"; break;
56 case T_LONG: name = "jni_fast_GetLongField"; break;
57 case T_FLOAT: name = "jni_fast_GetFloatField"; break;
58 case T_DOUBLE: name = "jni_fast_GetDoubleField"; break;
59 default: ShouldNotReachHere();
60 name = NULL; // unreachable
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 // We can only kill the remaining volatile registers.
71 const Register Rcounter = Z_ARG4,
72 Robj = Z_R1_scratch,
73 Rtmp = Z_R0_scratch;
74 __ load_const_optimized(Robj, SafepointSynchronize::safepoint_counter_addr());
75 __ z_lg(Rcounter, Address(Robj));
76 __ z_tmll(Rcounter, 1);
77 __ z_brnaz(slow);
78
79 if (JvmtiExport::can_post_field_access()) {
80 // Check to see if a field access watch has been set before we
81 // take the fast path.
82 __ load_const_optimized(Robj, JvmtiExport::get_field_access_count_addr());
83 __ z_lt(Robj, Address(Robj));
84 __ z_brne(slow);
85 }
86
87 __ z_lgr(Robj, Z_ARG2);
88 BarrierSetAssembler* bs = BarrierSet::barrier_set()->barrier_set_assembler();
89 bs->try_resolve_jobject_in_native(masm, Z_ARG1, Robj, Rtmp, slow);
90
91 __ z_srlg(Rtmp, Z_ARG3, 2); // offset
92 __ z_agr(Robj, Rtmp);
93
94 assert(count < LIST_CAPACITY, "LIST_CAPACITY too small");
95 speculative_load_pclist[count] = __ pc(); // Used by the segfault handler
96 bool is_fp = false;
97 switch (type) {
98 case T_BOOLEAN: __ z_llgc(Rtmp, Address(Robj)); break;
99 case T_BYTE: __ z_lgb( Rtmp, Address(Robj)); break;
100 case T_CHAR: __ z_llgh(Rtmp, Address(Robj)); break;
101 case T_SHORT: __ z_lgh( Rtmp, Address(Robj)); break;
102 case T_INT: __ z_lgf( Rtmp, Address(Robj)); break;
103 case T_LONG: __ z_lg( Rtmp, Address(Robj)); break;
104 case T_FLOAT: __ mem2freg_opt(Z_FRET, Address(Robj), false); is_fp = true; break;
105 case T_DOUBLE: __ mem2freg_opt(Z_FRET, Address(Robj), true ); is_fp = true; break;
106 default: ShouldNotReachHere();
107 }
108
109 __ load_const_optimized(Robj, SafepointSynchronize::safepoint_counter_addr());
110 __ z_cg(Rcounter, Address(Robj));
111 __ z_brne(slow);
112
113 if (!is_fp) {
114 __ z_lgr(Z_RET, Rtmp);
115 }
116 __ z_br(Z_R14);
117
118 slowcase_entry_pclist[count++] = __ pc();
119 __ bind(slow);
120 address slow_case_addr;
121 switch (type) {
122 case T_BOOLEAN: slow_case_addr = jni_GetBooleanField_addr(); break;
123 case T_BYTE: slow_case_addr = jni_GetByteField_addr(); break;
124 case T_CHAR: slow_case_addr = jni_GetCharField_addr(); break;
125 case T_SHORT: slow_case_addr = jni_GetShortField_addr(); break;
126 case T_INT: slow_case_addr = jni_GetIntField_addr(); break;
127 case T_LONG: slow_case_addr = jni_GetLongField_addr(); break;
128 case T_FLOAT: slow_case_addr = jni_GetFloatField_addr(); break;
129 case T_DOUBLE: slow_case_addr = jni_GetDoubleField_addr(); break;
130 default: ShouldNotReachHere();
131 slow_case_addr = NULL; // unreachable
132 }
133 __ load_const_optimized(Robj, slow_case_addr);
134 __ z_br(Robj); // tail call
135
136 __ flush();
137
138 return fast_entry;
139 }
140
generate_fast_get_boolean_field()141 address JNI_FastGetField::generate_fast_get_boolean_field() {
142 return generate_fast_get_int_field0(T_BOOLEAN);
143 }
144
generate_fast_get_byte_field()145 address JNI_FastGetField::generate_fast_get_byte_field() {
146 return generate_fast_get_int_field0(T_BYTE);
147 }
148
generate_fast_get_char_field()149 address JNI_FastGetField::generate_fast_get_char_field() {
150 return generate_fast_get_int_field0(T_CHAR);
151 }
152
generate_fast_get_short_field()153 address JNI_FastGetField::generate_fast_get_short_field() {
154 return generate_fast_get_int_field0(T_SHORT);
155 }
156
generate_fast_get_int_field()157 address JNI_FastGetField::generate_fast_get_int_field() {
158 return generate_fast_get_int_field0(T_INT);
159 }
160
generate_fast_get_long_field()161 address JNI_FastGetField::generate_fast_get_long_field() {
162 return generate_fast_get_int_field0(T_LONG);
163 }
164
generate_fast_get_float_field()165 address JNI_FastGetField::generate_fast_get_float_field() {
166 return generate_fast_get_int_field0(T_FLOAT);
167 }
168
generate_fast_get_double_field()169 address JNI_FastGetField::generate_fast_get_double_field() {
170 return generate_fast_get_int_field0(T_DOUBLE);
171 }
172