Mercurial > hg > truffle
annotate src/cpu/x86/vm/jniFastGetField_x86_32.cpp @ 3096:8073f5ad1d87
IdealGraphVisualizer: Rename predecessors to "Nodes Above" and successors to "Nodes Below" and actions "Expand Predecessors" and "Expand Successors" to "Expand Above" and "Expand Below" to avoid ambiguity with the Graal concept of successors and predecessors
author | Peter Hofer <peter.hofer@jku.at> |
---|---|
date | Wed, 29 Jun 2011 18:27:14 +0200 |
parents | f95d63e2154a |
children | cd3d6a6b95d9 |
rev | line source |
---|---|
0 | 1 /* |
1748 | 2 * Copyright (c) 2004, 2010, Oracle and/or its affiliates. All rights reserved. |
0 | 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 * | |
1552
c18cbe5936b8
6941466: Oracle rebranding changes for Hotspot repositories
trims
parents:
337
diff
changeset
|
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
c18cbe5936b8
6941466: Oracle rebranding changes for Hotspot repositories
trims
parents:
337
diff
changeset
|
20 * or visit www.oracle.com if you need additional information or have any |
c18cbe5936b8
6941466: Oracle rebranding changes for Hotspot repositories
trims
parents:
337
diff
changeset
|
21 * questions. |
0 | 22 * |
23 */ | |
24 | |
1972 | 25 #include "precompiled.hpp" |
26 #include "assembler_x86.inline.hpp" | |
27 #include "memory/resourceArea.hpp" | |
28 #include "prims/jniFastGetField.hpp" | |
29 #include "prims/jvm_misc.hpp" | |
30 #include "runtime/safepoint.hpp" | |
0 | 31 |
32 #define __ masm-> | |
33 | |
34 #define BUFFER_SIZE 30 | |
35 | |
36 #ifdef _WINDOWS | |
37 GetBooleanField_t JNI_FastGetField::jni_fast_GetBooleanField_fp; | |
38 GetByteField_t JNI_FastGetField::jni_fast_GetByteField_fp; | |
39 GetCharField_t JNI_FastGetField::jni_fast_GetCharField_fp; | |
40 GetShortField_t JNI_FastGetField::jni_fast_GetShortField_fp; | |
41 GetIntField_t JNI_FastGetField::jni_fast_GetIntField_fp; | |
42 GetLongField_t JNI_FastGetField::jni_fast_GetLongField_fp; | |
43 GetFloatField_t JNI_FastGetField::jni_fast_GetFloatField_fp; | |
44 GetDoubleField_t JNI_FastGetField::jni_fast_GetDoubleField_fp; | |
45 #endif | |
46 | |
47 // Instead of issuing lfence for LoadLoad barrier, we create data dependency | |
48 // between loads, which is much more efficient than lfence. | |
49 | |
50 address JNI_FastGetField::generate_fast_get_int_field0(BasicType type) { | |
51 const char *name; | |
52 switch (type) { | |
53 case T_BOOLEAN: name = "jni_fast_GetBooleanField"; break; | |
54 case T_BYTE: name = "jni_fast_GetByteField"; break; | |
55 case T_CHAR: name = "jni_fast_GetCharField"; break; | |
56 case T_SHORT: name = "jni_fast_GetShortField"; break; | |
57 case T_INT: name = "jni_fast_GetIntField"; break; | |
58 default: ShouldNotReachHere(); | |
59 } | |
60 ResourceMark rm; | |
1748 | 61 BufferBlob* blob = BufferBlob::create(name, BUFFER_SIZE*wordSize); |
62 CodeBuffer cbuf(blob); | |
0 | 63 MacroAssembler* masm = new MacroAssembler(&cbuf); |
1748 | 64 address fast_entry = __ pc(); |
0 | 65 |
66 Label slow; | |
67 | |
68 // stack layout: offset from rsp (in words): | |
69 // return pc 0 | |
70 // jni env 1 | |
71 // obj 2 | |
72 // jfieldID 3 | |
73 | |
74 ExternalAddress counter(SafepointSynchronize::safepoint_counter_addr()); | |
75 __ mov32 (rcx, counter); | |
76 __ testb (rcx, 1); | |
77 __ jcc (Assembler::notZero, slow); | |
78 if (os::is_MP()) { | |
304 | 79 __ mov(rax, rcx); |
80 __ andptr(rax, 1); // rax, must end up 0 | |
81 __ movptr(rdx, Address(rsp, rax, Address::times_1, 2*wordSize)); | |
0 | 82 // obj, notice rax, is 0. |
83 // rdx is data dependent on rcx. | |
84 } else { | |
304 | 85 __ movptr (rdx, Address(rsp, 2*wordSize)); // obj |
0 | 86 } |
304 | 87 __ movptr(rax, Address(rsp, 3*wordSize)); // jfieldID |
88 __ movptr(rdx, Address(rdx, 0)); // *obj | |
89 __ shrptr (rax, 2); // offset | |
0 | 90 |
91 assert(count < LIST_CAPACITY, "LIST_CAPACITY too small"); | |
92 speculative_load_pclist[count] = __ pc(); | |
93 switch (type) { | |
304 | 94 case T_BOOLEAN: __ movzbl (rax, Address(rdx, rax, Address::times_1)); break; |
95 case T_BYTE: __ movsbl (rax, Address(rdx, rax, Address::times_1)); break; | |
96 case T_CHAR: __ movzwl (rax, Address(rdx, rax, Address::times_1)); break; | |
97 case T_SHORT: __ movswl (rax, Address(rdx, rax, Address::times_1)); break; | |
0 | 98 case T_INT: __ movl (rax, Address(rdx, rax, Address::times_1)); break; |
99 default: ShouldNotReachHere(); | |
100 } | |
101 | |
102 Address ca1; | |
103 if (os::is_MP()) { | |
104 __ lea(rdx, counter); | |
304 | 105 __ xorptr(rdx, rax); |
106 __ xorptr(rdx, rax); | |
0 | 107 __ cmp32(rcx, Address(rdx, 0)); |
108 // ca1 is the same as ca because | |
109 // rax, ^ counter_addr ^ rax, = address | |
110 // ca1 is data dependent on rax,. | |
111 } else { | |
112 __ cmp32(rcx, counter); | |
113 } | |
114 __ jcc (Assembler::notEqual, slow); | |
115 | |
116 #ifndef _WINDOWS | |
117 __ ret (0); | |
118 #else | |
119 // __stdcall calling convention | |
120 __ ret (3*wordSize); | |
121 #endif | |
122 | |
123 slowcase_entry_pclist[count++] = __ pc(); | |
124 __ bind (slow); | |
125 address slow_case_addr; | |
126 switch (type) { | |
127 case T_BOOLEAN: slow_case_addr = jni_GetBooleanField_addr(); break; | |
128 case T_BYTE: slow_case_addr = jni_GetByteField_addr(); break; | |
129 case T_CHAR: slow_case_addr = jni_GetCharField_addr(); break; | |
130 case T_SHORT: slow_case_addr = jni_GetShortField_addr(); break; | |
131 case T_INT: slow_case_addr = jni_GetIntField_addr(); | |
132 } | |
133 // tail call | |
134 __ jump (ExternalAddress(slow_case_addr)); | |
135 | |
136 __ flush (); | |
137 | |
138 #ifndef _WINDOWS | |
139 return fast_entry; | |
140 #else | |
141 switch (type) { | |
1748 | 142 case T_BOOLEAN: jni_fast_GetBooleanField_fp = (GetBooleanField_t) fast_entry; break; |
143 case T_BYTE: jni_fast_GetByteField_fp = (GetByteField_t) fast_entry; break; | |
144 case T_CHAR: jni_fast_GetCharField_fp = (GetCharField_t) fast_entry; break; | |
145 case T_SHORT: jni_fast_GetShortField_fp = (GetShortField_t) fast_entry; break; | |
146 case T_INT: jni_fast_GetIntField_fp = (GetIntField_t) fast_entry; break; | |
0 | 147 } |
148 return os::win32::fast_jni_accessor_wrapper(type); | |
149 #endif | |
150 } | |
151 | |
152 address JNI_FastGetField::generate_fast_get_boolean_field() { | |
153 return generate_fast_get_int_field0(T_BOOLEAN); | |
154 } | |
155 | |
156 address JNI_FastGetField::generate_fast_get_byte_field() { | |
157 return generate_fast_get_int_field0(T_BYTE); | |
158 } | |
159 | |
160 address JNI_FastGetField::generate_fast_get_char_field() { | |
161 return generate_fast_get_int_field0(T_CHAR); | |
162 } | |
163 | |
164 address JNI_FastGetField::generate_fast_get_short_field() { | |
165 return generate_fast_get_int_field0(T_SHORT); | |
166 } | |
167 | |
168 address JNI_FastGetField::generate_fast_get_int_field() { | |
169 return generate_fast_get_int_field0(T_INT); | |
170 } | |
171 | |
172 address JNI_FastGetField::generate_fast_get_long_field() { | |
173 const char *name = "jni_fast_GetLongField"; | |
174 ResourceMark rm; | |
1748 | 175 BufferBlob* blob = BufferBlob::create(name, BUFFER_SIZE*wordSize); |
176 CodeBuffer cbuf(blob); | |
0 | 177 MacroAssembler* masm = new MacroAssembler(&cbuf); |
1748 | 178 address fast_entry = __ pc(); |
0 | 179 |
180 Label slow; | |
181 | |
182 // stack layout: offset from rsp (in words): | |
183 // old rsi 0 | |
184 // return pc 1 | |
185 // jni env 2 | |
186 // obj 3 | |
187 // jfieldID 4 | |
188 | |
189 ExternalAddress counter(SafepointSynchronize::safepoint_counter_addr()); | |
190 | |
304 | 191 __ push (rsi); |
0 | 192 __ mov32 (rcx, counter); |
193 __ testb (rcx, 1); | |
194 __ jcc (Assembler::notZero, slow); | |
195 if (os::is_MP()) { | |
304 | 196 __ mov(rax, rcx); |
197 __ andptr(rax, 1); // rax, must end up 0 | |
198 __ movptr(rdx, Address(rsp, rax, Address::times_1, 3*wordSize)); | |
0 | 199 // obj, notice rax, is 0. |
200 // rdx is data dependent on rcx. | |
201 } else { | |
304 | 202 __ movptr(rdx, Address(rsp, 3*wordSize)); // obj |
0 | 203 } |
304 | 204 __ movptr(rsi, Address(rsp, 4*wordSize)); // jfieldID |
205 __ movptr(rdx, Address(rdx, 0)); // *obj | |
206 __ shrptr(rsi, 2); // offset | |
0 | 207 |
208 assert(count < LIST_CAPACITY-1, "LIST_CAPACITY too small"); | |
209 speculative_load_pclist[count++] = __ pc(); | |
304 | 210 __ movptr(rax, Address(rdx, rsi, Address::times_1)); |
211 #ifndef _LP64 | |
0 | 212 speculative_load_pclist[count] = __ pc(); |
304 | 213 __ movl(rdx, Address(rdx, rsi, Address::times_1, 4)); |
214 #endif // _LP64 | |
0 | 215 |
216 if (os::is_MP()) { | |
304 | 217 __ lea(rsi, counter); |
218 __ xorptr(rsi, rdx); | |
219 __ xorptr(rsi, rax); | |
220 __ xorptr(rsi, rdx); | |
221 __ xorptr(rsi, rax); | |
0 | 222 __ cmp32(rcx, Address(rsi, 0)); |
223 // ca1 is the same as ca because | |
224 // rax, ^ rdx ^ counter_addr ^ rax, ^ rdx = address | |
225 // ca1 is data dependent on both rax, and rdx. | |
226 } else { | |
227 __ cmp32(rcx, counter); | |
228 } | |
229 __ jcc (Assembler::notEqual, slow); | |
230 | |
304 | 231 __ pop (rsi); |
0 | 232 |
233 #ifndef _WINDOWS | |
234 __ ret (0); | |
235 #else | |
236 // __stdcall calling convention | |
237 __ ret (3*wordSize); | |
238 #endif | |
239 | |
240 slowcase_entry_pclist[count-1] = __ pc(); | |
241 slowcase_entry_pclist[count++] = __ pc(); | |
242 __ bind (slow); | |
304 | 243 __ pop (rsi); |
0 | 244 address slow_case_addr = jni_GetLongField_addr();; |
245 // tail call | |
246 __ jump (ExternalAddress(slow_case_addr)); | |
247 | |
248 __ flush (); | |
249 | |
250 #ifndef _WINDOWS | |
251 return fast_entry; | |
252 #else | |
1748 | 253 jni_fast_GetLongField_fp = (GetLongField_t) fast_entry; |
0 | 254 return os::win32::fast_jni_accessor_wrapper(T_LONG); |
255 #endif | |
256 } | |
257 | |
258 address JNI_FastGetField::generate_fast_get_float_field0(BasicType type) { | |
259 const char *name; | |
260 switch (type) { | |
261 case T_FLOAT: name = "jni_fast_GetFloatField"; break; | |
262 case T_DOUBLE: name = "jni_fast_GetDoubleField"; break; | |
263 default: ShouldNotReachHere(); | |
264 } | |
265 ResourceMark rm; | |
1748 | 266 BufferBlob* blob = BufferBlob::create(name, BUFFER_SIZE*wordSize); |
267 CodeBuffer cbuf(blob); | |
0 | 268 MacroAssembler* masm = new MacroAssembler(&cbuf); |
1748 | 269 address fast_entry = __ pc(); |
0 | 270 |
271 Label slow_with_pop, slow; | |
272 | |
273 // stack layout: offset from rsp (in words): | |
274 // return pc 0 | |
275 // jni env 1 | |
276 // obj 2 | |
277 // jfieldID 3 | |
278 | |
279 ExternalAddress counter(SafepointSynchronize::safepoint_counter_addr()); | |
280 | |
281 __ mov32 (rcx, counter); | |
282 __ testb (rcx, 1); | |
283 __ jcc (Assembler::notZero, slow); | |
284 if (os::is_MP()) { | |
304 | 285 __ mov(rax, rcx); |
286 __ andptr(rax, 1); // rax, must end up 0 | |
287 __ movptr(rdx, Address(rsp, rax, Address::times_1, 2*wordSize)); | |
0 | 288 // obj, notice rax, is 0. |
289 // rdx is data dependent on rcx. | |
290 } else { | |
304 | 291 __ movptr(rdx, Address(rsp, 2*wordSize)); // obj |
0 | 292 } |
304 | 293 __ movptr(rax, Address(rsp, 3*wordSize)); // jfieldID |
294 __ movptr(rdx, Address(rdx, 0)); // *obj | |
295 __ shrptr(rax, 2); // offset | |
0 | 296 |
297 assert(count < LIST_CAPACITY, "LIST_CAPACITY too small"); | |
298 speculative_load_pclist[count] = __ pc(); | |
299 switch (type) { | |
304 | 300 #ifndef _LP64 |
0 | 301 case T_FLOAT: __ fld_s (Address(rdx, rax, Address::times_1)); break; |
302 case T_DOUBLE: __ fld_d (Address(rdx, rax, Address::times_1)); break; | |
304 | 303 #else |
304 case T_FLOAT: __ movflt (xmm0, Address(robj, roffset, Address::times_1)); break; | |
305 case T_DOUBLE: __ movdbl (xmm0, Address(robj, roffset, Address::times_1)); break; | |
306 #endif // _LP64 | |
0 | 307 default: ShouldNotReachHere(); |
308 } | |
309 | |
310 Address ca1; | |
311 if (os::is_MP()) { | |
312 __ fst_s (Address(rsp, -4)); | |
313 __ lea(rdx, counter); | |
314 __ movl (rax, Address(rsp, -4)); | |
304 | 315 // garbage hi-order bits on 64bit are harmless. |
316 __ xorptr(rdx, rax); | |
317 __ xorptr(rdx, rax); | |
0 | 318 __ cmp32(rcx, Address(rdx, 0)); |
319 // rax, ^ counter_addr ^ rax, = address | |
320 // ca1 is data dependent on the field | |
321 // access. | |
322 } else { | |
323 __ cmp32(rcx, counter); | |
324 } | |
325 __ jcc (Assembler::notEqual, slow_with_pop); | |
326 | |
327 #ifndef _WINDOWS | |
328 __ ret (0); | |
329 #else | |
330 // __stdcall calling convention | |
331 __ ret (3*wordSize); | |
332 #endif | |
333 | |
334 __ bind (slow_with_pop); | |
335 // invalid load. pop FPU stack. | |
336 __ fstp_d (0); | |
337 | |
338 slowcase_entry_pclist[count++] = __ pc(); | |
339 __ bind (slow); | |
340 address slow_case_addr; | |
341 switch (type) { | |
342 case T_FLOAT: slow_case_addr = jni_GetFloatField_addr(); break; | |
343 case T_DOUBLE: slow_case_addr = jni_GetDoubleField_addr(); break; | |
344 default: ShouldNotReachHere(); | |
345 } | |
346 // tail call | |
347 __ jump (ExternalAddress(slow_case_addr)); | |
348 | |
349 __ flush (); | |
350 | |
351 #ifndef _WINDOWS | |
352 return fast_entry; | |
353 #else | |
354 switch (type) { | |
1748 | 355 case T_FLOAT: jni_fast_GetFloatField_fp = (GetFloatField_t) fast_entry; break; |
356 case T_DOUBLE: jni_fast_GetDoubleField_fp = (GetDoubleField_t) fast_entry; break; | |
0 | 357 } |
358 return os::win32::fast_jni_accessor_wrapper(type); | |
359 #endif | |
360 } | |
361 | |
362 address JNI_FastGetField::generate_fast_get_float_field() { | |
363 return generate_fast_get_float_field0(T_FLOAT); | |
364 } | |
365 | |
366 address JNI_FastGetField::generate_fast_get_double_field() { | |
367 return generate_fast_get_float_field0(T_DOUBLE); | |
368 } |