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