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