Mercurial > hg > truffle
comparison src/cpu/x86/vm/jniFastGetField_x86_32.cpp @ 0:a61af66fc99e jdk7-b24
Initial load
author | duke |
---|---|
date | Sat, 01 Dec 2007 00:00:00 +0000 |
parents | |
children | dc7f315e41f7 |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:a61af66fc99e |
---|---|
1 /* | |
2 * Copyright 2004-2006 Sun Microsystems, Inc. All Rights Reserved. | |
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 * | |
19 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, | |
20 * CA 95054 USA or visit www.sun.com if you need additional information or | |
21 * have any questions. | |
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; | |
57 BufferBlob* b = BufferBlob::create(name, BUFFER_SIZE*wordSize); | |
58 address fast_entry = b->instructions_begin(); | |
59 CodeBuffer cbuf(fast_entry, b->instructions_size()); | |
60 MacroAssembler* masm = new MacroAssembler(&cbuf); | |
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()) { | |
75 __ movl (rax, rcx); | |
76 __ andl (rax, 1); // rax, must end up 0 | |
77 __ movl (rdx, Address(rsp, rax, Address::times_1, 2*wordSize)); | |
78 // obj, notice rax, is 0. | |
79 // rdx is data dependent on rcx. | |
80 } else { | |
81 __ movl (rdx, Address(rsp, 2*wordSize)); // obj | |
82 } | |
83 __ movl (rax, Address(rsp, 3*wordSize)); // jfieldID | |
84 __ movl (rdx, Address(rdx, 0)); // *obj | |
85 __ shrl (rax, 2); // offset | |
86 | |
87 assert(count < LIST_CAPACITY, "LIST_CAPACITY too small"); | |
88 speculative_load_pclist[count] = __ pc(); | |
89 switch (type) { | |
90 case T_BOOLEAN: __ movzxb (rax, Address(rdx, rax, Address::times_1)); break; | |
91 case T_BYTE: __ movsxb (rax, Address(rdx, rax, Address::times_1)); break; | |
92 case T_CHAR: __ movzxw (rax, Address(rdx, rax, Address::times_1)); break; | |
93 case T_SHORT: __ movsxw (rax, Address(rdx, rax, Address::times_1)); break; | |
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); | |
101 __ xorl(rdx, rax); | |
102 __ xorl(rdx, rax); | |
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) { | |
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; | |
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; | |
171 BufferBlob* b = BufferBlob::create(name, BUFFER_SIZE*wordSize); | |
172 address fast_entry = b->instructions_begin(); | |
173 CodeBuffer cbuf(fast_entry, b->instructions_size()); | |
174 MacroAssembler* masm = new MacroAssembler(&cbuf); | |
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 | |
187 __ pushl (rsi); | |
188 __ mov32 (rcx, counter); | |
189 __ testb (rcx, 1); | |
190 __ jcc (Assembler::notZero, slow); | |
191 if (os::is_MP()) { | |
192 __ movl (rax, rcx); | |
193 __ andl (rax, 1); // rax, must end up 0 | |
194 __ movl (rdx, Address(rsp, rax, Address::times_1, 3*wordSize)); | |
195 // obj, notice rax, is 0. | |
196 // rdx is data dependent on rcx. | |
197 } else { | |
198 __ movl (rdx, Address(rsp, 3*wordSize)); // obj | |
199 } | |
200 __ movl (rsi, Address(rsp, 4*wordSize)); // jfieldID | |
201 __ movl (rdx, Address(rdx, 0)); // *obj | |
202 __ shrl (rsi, 2); // offset | |
203 | |
204 assert(count < LIST_CAPACITY-1, "LIST_CAPACITY too small"); | |
205 speculative_load_pclist[count++] = __ pc(); | |
206 __ movl (rax, Address(rdx, rsi, Address::times_1)); | |
207 speculative_load_pclist[count] = __ pc(); | |
208 __ movl (rdx, Address(rdx, rsi, Address::times_1, 4)); | |
209 | |
210 if (os::is_MP()) { | |
211 __ lea (rsi, counter); | |
212 __ xorl (rsi, rdx); | |
213 __ xorl (rsi, rax); | |
214 __ xorl (rsi, rdx); | |
215 __ xorl (rsi, rax); | |
216 __ cmp32(rcx, Address(rsi, 0)); | |
217 // ca1 is the same as ca because | |
218 // rax, ^ rdx ^ counter_addr ^ rax, ^ rdx = address | |
219 // ca1 is data dependent on both rax, and rdx. | |
220 } else { | |
221 __ cmp32(rcx, counter); | |
222 } | |
223 __ jcc (Assembler::notEqual, slow); | |
224 | |
225 __ popl (rsi); | |
226 | |
227 #ifndef _WINDOWS | |
228 __ ret (0); | |
229 #else | |
230 // __stdcall calling convention | |
231 __ ret (3*wordSize); | |
232 #endif | |
233 | |
234 slowcase_entry_pclist[count-1] = __ pc(); | |
235 slowcase_entry_pclist[count++] = __ pc(); | |
236 __ bind (slow); | |
237 __ popl (rsi); | |
238 address slow_case_addr = jni_GetLongField_addr();; | |
239 // tail call | |
240 __ jump (ExternalAddress(slow_case_addr)); | |
241 | |
242 __ flush (); | |
243 | |
244 #ifndef _WINDOWS | |
245 return fast_entry; | |
246 #else | |
247 jni_fast_GetLongField_fp = (GetLongField_t)fast_entry; | |
248 return os::win32::fast_jni_accessor_wrapper(T_LONG); | |
249 #endif | |
250 } | |
251 | |
252 address JNI_FastGetField::generate_fast_get_float_field0(BasicType type) { | |
253 const char *name; | |
254 switch (type) { | |
255 case T_FLOAT: name = "jni_fast_GetFloatField"; break; | |
256 case T_DOUBLE: name = "jni_fast_GetDoubleField"; break; | |
257 default: ShouldNotReachHere(); | |
258 } | |
259 ResourceMark rm; | |
260 BufferBlob* b = BufferBlob::create(name, BUFFER_SIZE*wordSize); | |
261 address fast_entry = b->instructions_begin(); | |
262 CodeBuffer cbuf(fast_entry, b->instructions_size()); | |
263 MacroAssembler* masm = new MacroAssembler(&cbuf); | |
264 | |
265 Label slow_with_pop, slow; | |
266 | |
267 // stack layout: offset from rsp (in words): | |
268 // return pc 0 | |
269 // jni env 1 | |
270 // obj 2 | |
271 // jfieldID 3 | |
272 | |
273 ExternalAddress counter(SafepointSynchronize::safepoint_counter_addr()); | |
274 | |
275 __ mov32 (rcx, counter); | |
276 __ testb (rcx, 1); | |
277 __ jcc (Assembler::notZero, slow); | |
278 if (os::is_MP()) { | |
279 __ movl (rax, rcx); | |
280 __ andl (rax, 1); // rax, must end up 0 | |
281 __ movl (rdx, Address(rsp, rax, Address::times_1, 2*wordSize)); | |
282 // obj, notice rax, is 0. | |
283 // rdx is data dependent on rcx. | |
284 } else { | |
285 __ movl (rdx, Address(rsp, 2*wordSize)); // obj | |
286 } | |
287 __ movl (rax, Address(rsp, 3*wordSize)); // jfieldID | |
288 __ movl (rdx, Address(rdx, 0)); // *obj | |
289 __ shrl (rax, 2); // offset | |
290 | |
291 assert(count < LIST_CAPACITY, "LIST_CAPACITY too small"); | |
292 speculative_load_pclist[count] = __ pc(); | |
293 switch (type) { | |
294 case T_FLOAT: __ fld_s (Address(rdx, rax, Address::times_1)); break; | |
295 case T_DOUBLE: __ fld_d (Address(rdx, rax, Address::times_1)); break; | |
296 default: ShouldNotReachHere(); | |
297 } | |
298 | |
299 Address ca1; | |
300 if (os::is_MP()) { | |
301 __ fst_s (Address(rsp, -4)); | |
302 __ lea(rdx, counter); | |
303 __ movl (rax, Address(rsp, -4)); | |
304 __ xorl(rdx, rax); | |
305 __ xorl(rdx, rax); | |
306 __ cmp32(rcx, Address(rdx, 0)); | |
307 // rax, ^ counter_addr ^ rax, = address | |
308 // ca1 is data dependent on the field | |
309 // access. | |
310 } else { | |
311 __ cmp32(rcx, counter); | |
312 } | |
313 __ jcc (Assembler::notEqual, slow_with_pop); | |
314 | |
315 #ifndef _WINDOWS | |
316 __ ret (0); | |
317 #else | |
318 // __stdcall calling convention | |
319 __ ret (3*wordSize); | |
320 #endif | |
321 | |
322 __ bind (slow_with_pop); | |
323 // invalid load. pop FPU stack. | |
324 __ fstp_d (0); | |
325 | |
326 slowcase_entry_pclist[count++] = __ pc(); | |
327 __ bind (slow); | |
328 address slow_case_addr; | |
329 switch (type) { | |
330 case T_FLOAT: slow_case_addr = jni_GetFloatField_addr(); break; | |
331 case T_DOUBLE: slow_case_addr = jni_GetDoubleField_addr(); break; | |
332 default: ShouldNotReachHere(); | |
333 } | |
334 // tail call | |
335 __ jump (ExternalAddress(slow_case_addr)); | |
336 | |
337 __ flush (); | |
338 | |
339 #ifndef _WINDOWS | |
340 return fast_entry; | |
341 #else | |
342 switch (type) { | |
343 case T_FLOAT: jni_fast_GetFloatField_fp = (GetFloatField_t)fast_entry; break; | |
344 case T_DOUBLE: jni_fast_GetDoubleField_fp = (GetDoubleField_t)fast_entry; | |
345 } | |
346 return os::win32::fast_jni_accessor_wrapper(type); | |
347 #endif | |
348 } | |
349 | |
350 address JNI_FastGetField::generate_fast_get_float_field() { | |
351 return generate_fast_get_float_field0(T_FLOAT); | |
352 } | |
353 | |
354 address JNI_FastGetField::generate_fast_get_double_field() { | |
355 return generate_fast_get_float_field0(T_DOUBLE); | |
356 } |