Mercurial > hg > truffle
annotate src/cpu/x86/vm/jniFastGetField_x86_64.cpp @ 2007:5ddfcf4b079e
7003554: (tiered) assert(is_null_object() || handle() != NULL) failed: cannot embed null pointer
Summary: C1 with profiling doesn't check whether the MDO has been really allocated, which can silently fail if the perm gen is full. The solution is to check if the allocation failed and bailout out of inlining or compilation.
Reviewed-by: kvn, never
author | iveresov |
---|---|
date | Thu, 02 Dec 2010 17:21:12 -0800 |
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*wordSize | |
35 | |
36 // Instead of issuing lfence for LoadLoad barrier, we create data dependency | |
37 // between loads, which is more efficient than lfence. | |
38 | |
39 // Common register usage: | |
40 // rax/xmm0: result | |
41 // c_rarg0: jni env | |
42 // c_rarg1: obj | |
43 // c_rarg2: jfield id | |
44 | |
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; | |
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; | |
1748 | 65 BufferBlob* blob = BufferBlob::create(name, BUFFER_SIZE); |
66 CodeBuffer cbuf(blob); | |
0 | 67 MacroAssembler* masm = new MacroAssembler(&cbuf); |
1748 | 68 address fast_entry = __ pc(); |
0 | 69 |
70 Label slow; | |
71 | |
72 ExternalAddress counter(SafepointSynchronize::safepoint_counter_addr()); | |
73 __ mov32 (rcounter, counter); | |
304 | 74 __ mov (robj, c_rarg1); |
0 | 75 __ testb (rcounter, 1); |
76 __ jcc (Assembler::notZero, slow); | |
77 if (os::is_MP()) { | |
304 | 78 __ xorptr(robj, rcounter); |
79 __ xorptr(robj, rcounter); // obj, since | |
0 | 80 // robj ^ rcounter ^ rcounter == robj |
81 // robj is data dependent on rcounter. | |
82 } | |
304 | 83 __ movptr(robj, Address(robj, 0)); // *obj |
84 __ mov (roffset, c_rarg2); | |
85 __ shrptr(roffset, 2); // offset | |
0 | 86 |
87 assert(count < LIST_CAPACITY, "LIST_CAPACITY too small"); | |
88 speculative_load_pclist[count] = __ pc(); | |
89 switch (type) { | |
90 case T_BOOLEAN: __ movzbl (rax, Address(robj, roffset, Address::times_1)); break; | |
91 case T_BYTE: __ movsbl (rax, Address(robj, roffset, Address::times_1)); break; | |
92 case T_CHAR: __ movzwl (rax, Address(robj, roffset, Address::times_1)); break; | |
93 case T_SHORT: __ movswl (rax, Address(robj, roffset, Address::times_1)); break; | |
94 case T_INT: __ movl (rax, Address(robj, roffset, Address::times_1)); break; | |
95 case T_LONG: __ movq (rax, Address(robj, roffset, Address::times_1)); break; | |
96 default: ShouldNotReachHere(); | |
97 } | |
98 | |
99 if (os::is_MP()) { | |
100 __ lea(rcounter_addr, counter); | |
101 // ca is data dependent on rax. | |
304 | 102 __ xorptr(rcounter_addr, rax); |
103 __ xorptr(rcounter_addr, rax); | |
0 | 104 __ cmpl (rcounter, Address(rcounter_addr, 0)); |
105 } else { | |
106 __ cmp32 (rcounter, counter); | |
107 } | |
108 __ jcc (Assembler::notEqual, slow); | |
109 | |
110 __ ret (0); | |
111 | |
112 slowcase_entry_pclist[count++] = __ pc(); | |
113 __ bind (slow); | |
114 address slow_case_addr; | |
115 switch (type) { | |
116 case T_BOOLEAN: slow_case_addr = jni_GetBooleanField_addr(); break; | |
117 case T_BYTE: slow_case_addr = jni_GetByteField_addr(); break; | |
118 case T_CHAR: slow_case_addr = jni_GetCharField_addr(); break; | |
119 case T_SHORT: slow_case_addr = jni_GetShortField_addr(); break; | |
120 case T_INT: slow_case_addr = jni_GetIntField_addr(); break; | |
121 case T_LONG: slow_case_addr = jni_GetLongField_addr(); | |
122 } | |
123 // tail call | |
124 __ jump (ExternalAddress(slow_case_addr)); | |
125 | |
126 __ flush (); | |
127 | |
128 return fast_entry; | |
129 } | |
130 | |
131 address JNI_FastGetField::generate_fast_get_boolean_field() { | |
132 return generate_fast_get_int_field0(T_BOOLEAN); | |
133 } | |
134 | |
135 address JNI_FastGetField::generate_fast_get_byte_field() { | |
136 return generate_fast_get_int_field0(T_BYTE); | |
137 } | |
138 | |
139 address JNI_FastGetField::generate_fast_get_char_field() { | |
140 return generate_fast_get_int_field0(T_CHAR); | |
141 } | |
142 | |
143 address JNI_FastGetField::generate_fast_get_short_field() { | |
144 return generate_fast_get_int_field0(T_SHORT); | |
145 } | |
146 | |
147 address JNI_FastGetField::generate_fast_get_int_field() { | |
148 return generate_fast_get_int_field0(T_INT); | |
149 } | |
150 | |
151 address JNI_FastGetField::generate_fast_get_long_field() { | |
152 return generate_fast_get_int_field0(T_LONG); | |
153 } | |
154 | |
155 address JNI_FastGetField::generate_fast_get_float_field0(BasicType type) { | |
156 const char *name; | |
157 switch (type) { | |
158 case T_FLOAT: name = "jni_fast_GetFloatField"; break; | |
159 case T_DOUBLE: name = "jni_fast_GetDoubleField"; break; | |
160 default: ShouldNotReachHere(); | |
161 } | |
162 ResourceMark rm; | |
1748 | 163 BufferBlob* blob = BufferBlob::create(name, BUFFER_SIZE); |
164 CodeBuffer cbuf(blob); | |
0 | 165 MacroAssembler* masm = new MacroAssembler(&cbuf); |
1748 | 166 address fast_entry = __ pc(); |
0 | 167 |
168 Label slow; | |
169 | |
170 ExternalAddress counter(SafepointSynchronize::safepoint_counter_addr()); | |
171 __ mov32 (rcounter, counter); | |
304 | 172 __ mov (robj, c_rarg1); |
0 | 173 __ testb (rcounter, 1); |
174 __ jcc (Assembler::notZero, slow); | |
175 if (os::is_MP()) { | |
304 | 176 __ xorptr(robj, rcounter); |
177 __ xorptr(robj, rcounter); // obj, since | |
0 | 178 // robj ^ rcounter ^ rcounter == robj |
179 // robj is data dependent on rcounter. | |
180 } | |
304 | 181 __ movptr(robj, Address(robj, 0)); // *obj |
182 __ mov (roffset, c_rarg2); | |
183 __ shrptr(roffset, 2); // offset | |
0 | 184 |
185 assert(count < LIST_CAPACITY, "LIST_CAPACITY too small"); | |
186 speculative_load_pclist[count] = __ pc(); | |
187 switch (type) { | |
188 case T_FLOAT: __ movflt (xmm0, Address(robj, roffset, Address::times_1)); break; | |
189 case T_DOUBLE: __ movdbl (xmm0, Address(robj, roffset, Address::times_1)); break; | |
190 default: ShouldNotReachHere(); | |
191 } | |
192 | |
193 if (os::is_MP()) { | |
194 __ lea(rcounter_addr, counter); | |
195 __ movdq (rax, xmm0); | |
196 // counter address is data dependent on xmm0. | |
304 | 197 __ xorptr(rcounter_addr, rax); |
198 __ xorptr(rcounter_addr, rax); | |
0 | 199 __ cmpl (rcounter, Address(rcounter_addr, 0)); |
200 } else { | |
201 __ cmp32 (rcounter, counter); | |
202 } | |
203 __ jcc (Assembler::notEqual, slow); | |
204 | |
205 __ ret (0); | |
206 | |
207 slowcase_entry_pclist[count++] = __ pc(); | |
208 __ bind (slow); | |
209 address slow_case_addr; | |
210 switch (type) { | |
211 case T_FLOAT: slow_case_addr = jni_GetFloatField_addr(); break; | |
212 case T_DOUBLE: slow_case_addr = jni_GetDoubleField_addr(); | |
213 } | |
214 // tail call | |
215 __ jump (ExternalAddress(slow_case_addr)); | |
216 | |
217 __ flush (); | |
218 | |
219 return fast_entry; | |
220 } | |
221 | |
222 address JNI_FastGetField::generate_fast_get_float_field() { | |
223 return generate_fast_get_float_field0(T_FLOAT); | |
224 } | |
225 | |
226 address JNI_FastGetField::generate_fast_get_double_field() { | |
227 return generate_fast_get_float_field0(T_DOUBLE); | |
228 } |