Mercurial > hg > truffle
annotate src/share/vm/oops/typeArrayKlass.cpp @ 3762:5c0a3c1858b1
7048782: CMS: assert(last_chunk_index_to_check<= last_chunk_index) failed: parCardTableModRefBS.cpp:359
Summary: The LNC array is sized before the start of a scavenge, while the heap may expand during a scavenge. With CMS, the last block of an arbitrary suffice of the LNC array may expand due to coalition with the expansion delta. We now take care not to attempt access past the end of the LNC array. LNC array code will be cleaned up and suitably encapsulated as part of the forthcoming performance RFE 7043675.
Reviewed-by: brutisso
author | ysr |
---|---|
date | Thu, 02 Jun 2011 10:23:36 -0700 |
parents | e5383553fd4e |
children | c9ca3f51cf41 |
rev | line source |
---|---|
0 | 1 /* |
2119 | 2 * Copyright (c) 1997, 2011, 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:
1334
diff
changeset
|
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
c18cbe5936b8
6941466: Oracle rebranding changes for Hotspot repositories
trims
parents:
1334
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:
1334
diff
changeset
|
21 * questions. |
0 | 22 * |
23 */ | |
24 | |
1972 | 25 #include "precompiled.hpp" |
26 #include "classfile/systemDictionary.hpp" | |
27 #include "classfile/vmSymbols.hpp" | |
28 #include "gc_interface/collectedHeap.hpp" | |
29 #include "gc_interface/collectedHeap.inline.hpp" | |
30 #include "memory/resourceArea.hpp" | |
31 #include "memory/universe.hpp" | |
32 #include "memory/universe.inline.hpp" | |
33 #include "oops/instanceKlass.hpp" | |
34 #include "oops/klassOop.hpp" | |
35 #include "oops/objArrayKlassKlass.hpp" | |
36 #include "oops/oop.inline.hpp" | |
37 #include "oops/typeArrayKlass.hpp" | |
38 #include "oops/typeArrayOop.hpp" | |
39 #include "runtime/handles.inline.hpp" | |
0 | 40 |
41 bool typeArrayKlass::compute_is_subtype_of(klassOop k) { | |
42 if (!k->klass_part()->oop_is_typeArray()) { | |
43 return arrayKlass::compute_is_subtype_of(k); | |
44 } | |
45 | |
46 typeArrayKlass* tak = typeArrayKlass::cast(k); | |
47 if (dimension() != tak->dimension()) return false; | |
48 | |
49 return element_type() == tak->element_type(); | |
50 } | |
51 | |
481
7d7a7c599c17
6578152: fill_region_with_object has usability and safety issues
jcoomes
parents:
0
diff
changeset
|
52 klassOop typeArrayKlass::create_klass(BasicType type, int scale, |
7d7a7c599c17
6578152: fill_region_with_object has usability and safety issues
jcoomes
parents:
0
diff
changeset
|
53 const char* name_str, TRAPS) { |
0 | 54 typeArrayKlass o; |
55 | |
2177
3582bf76420e
6990754: Use native memory and reference counting to implement SymbolTable
coleenp
parents:
2119
diff
changeset
|
56 Symbol* sym = NULL; |
3582bf76420e
6990754: Use native memory and reference counting to implement SymbolTable
coleenp
parents:
2119
diff
changeset
|
57 if (name_str != NULL) { |
3582bf76420e
6990754: Use native memory and reference counting to implement SymbolTable
coleenp
parents:
2119
diff
changeset
|
58 sym = SymbolTable::new_symbol(name_str, CHECK_NULL); |
0 | 59 } |
60 KlassHandle klassklass (THREAD, Universe::typeArrayKlassKlassObj()); | |
61 | |
62 arrayKlassHandle k = base_create_array_klass(o.vtbl_value(), header_size(), klassklass, CHECK_NULL); | |
63 typeArrayKlass* ak = typeArrayKlass::cast(k()); | |
2177
3582bf76420e
6990754: Use native memory and reference counting to implement SymbolTable
coleenp
parents:
2119
diff
changeset
|
64 ak->set_name(sym); |
0 | 65 ak->set_layout_helper(array_layout_helper(type)); |
66 assert(scale == (1 << ak->log2_element_size()), "scale must check out"); | |
67 assert(ak->oop_is_javaArray(), "sanity"); | |
68 assert(ak->oop_is_typeArray(), "sanity"); | |
69 ak->set_max_length(arrayOopDesc::max_array_length(type)); | |
70 assert(k()->size() > header_size(), "bad size"); | |
71 | |
72 // Call complete_create_array_klass after all instance variables have been initialized. | |
73 KlassHandle super (THREAD, k->super()); | |
74 complete_create_array_klass(k, super, CHECK_NULL); | |
75 | |
76 return k(); | |
77 } | |
78 | |
79 typeArrayOop typeArrayKlass::allocate(int length, TRAPS) { | |
80 assert(log2_element_size() >= 0, "bad scale"); | |
81 if (length >= 0) { | |
82 if (length <= max_length()) { | |
83 size_t size = typeArrayOopDesc::object_size(layout_helper(), length); | |
84 KlassHandle h_k(THREAD, as_klassOop()); | |
85 typeArrayOop t; | |
86 CollectedHeap* ch = Universe::heap(); | |
87 if (size < ch->large_typearray_limit()) { | |
88 t = (typeArrayOop)CollectedHeap::array_allocate(h_k, (int)size, length, CHECK_NULL); | |
89 } else { | |
90 t = (typeArrayOop)CollectedHeap::large_typearray_allocate(h_k, (int)size, length, CHECK_NULL); | |
91 } | |
92 assert(t->is_parsable(), "Don't publish unless parsable"); | |
93 return t; | |
94 } else { | |
876
1413494da700
6850957: Honor -XX:OnOutOfMemoryError when array size exceeds VM limit
martin
parents:
579
diff
changeset
|
95 report_java_out_of_memory("Requested array size exceeds VM limit"); |
0 | 96 THROW_OOP_0(Universe::out_of_memory_error_array_size()); |
97 } | |
98 } else { | |
99 THROW_0(vmSymbols::java_lang_NegativeArraySizeException()); | |
100 } | |
101 } | |
102 | |
103 typeArrayOop typeArrayKlass::allocate_permanent(int length, TRAPS) { | |
104 if (length < 0) THROW_0(vmSymbols::java_lang_NegativeArraySizeException()); | |
105 int size = typeArrayOopDesc::object_size(layout_helper(), length); | |
106 KlassHandle h_k(THREAD, as_klassOop()); | |
107 typeArrayOop t = (typeArrayOop) | |
108 CollectedHeap::permanent_array_allocate(h_k, size, length, CHECK_NULL); | |
109 assert(t->is_parsable(), "Can't publish until parsable"); | |
110 return t; | |
111 } | |
112 | |
113 oop typeArrayKlass::multi_allocate(int rank, jint* last_size, TRAPS) { | |
114 // For typeArrays this is only called for the last dimension | |
115 assert(rank == 1, "just checking"); | |
116 int length = *last_size; | |
117 return allocate(length, THREAD); | |
118 } | |
119 | |
120 | |
121 void typeArrayKlass::copy_array(arrayOop s, int src_pos, arrayOop d, int dst_pos, int length, TRAPS) { | |
122 assert(s->is_typeArray(), "must be type array"); | |
123 | |
124 // Check destination | |
125 if (!d->is_typeArray() || element_type() != typeArrayKlass::cast(d->klass())->element_type()) { | |
126 THROW(vmSymbols::java_lang_ArrayStoreException()); | |
127 } | |
128 | |
129 // Check is all offsets and lengths are non negative | |
130 if (src_pos < 0 || dst_pos < 0 || length < 0) { | |
131 THROW(vmSymbols::java_lang_ArrayIndexOutOfBoundsException()); | |
132 } | |
133 // Check if the ranges are valid | |
134 if ( (((unsigned int) length + (unsigned int) src_pos) > (unsigned int) s->length()) | |
135 || (((unsigned int) length + (unsigned int) dst_pos) > (unsigned int) d->length()) ) { | |
136 THROW(vmSymbols::java_lang_ArrayIndexOutOfBoundsException()); | |
137 } | |
1334
b5d78a3b8843
6892265: System.arraycopy unable to reference elements beyond Integer.MAX_VALUE bytes
kvn
parents:
876
diff
changeset
|
138 // Check zero copy |
b5d78a3b8843
6892265: System.arraycopy unable to reference elements beyond Integer.MAX_VALUE bytes
kvn
parents:
876
diff
changeset
|
139 if (length == 0) |
b5d78a3b8843
6892265: System.arraycopy unable to reference elements beyond Integer.MAX_VALUE bytes
kvn
parents:
876
diff
changeset
|
140 return; |
0 | 141 |
142 // This is an attempt to make the copy_array fast. | |
143 int l2es = log2_element_size(); | |
144 int ihs = array_header_in_bytes() / wordSize; | |
1334
b5d78a3b8843
6892265: System.arraycopy unable to reference elements beyond Integer.MAX_VALUE bytes
kvn
parents:
876
diff
changeset
|
145 char* src = (char*) ((oop*)s + ihs) + ((size_t)src_pos << l2es); |
b5d78a3b8843
6892265: System.arraycopy unable to reference elements beyond Integer.MAX_VALUE bytes
kvn
parents:
876
diff
changeset
|
146 char* dst = (char*) ((oop*)d + ihs) + ((size_t)dst_pos << l2es); |
b5d78a3b8843
6892265: System.arraycopy unable to reference elements beyond Integer.MAX_VALUE bytes
kvn
parents:
876
diff
changeset
|
147 Copy::conjoint_memory_atomic(src, dst, (size_t)length << l2es); |
0 | 148 } |
149 | |
150 | |
151 // create a klass of array holding typeArrays | |
152 klassOop typeArrayKlass::array_klass_impl(bool or_null, int n, TRAPS) { | |
153 typeArrayKlassHandle h_this(THREAD, as_klassOop()); | |
154 return array_klass_impl(h_this, or_null, n, THREAD); | |
155 } | |
156 | |
157 klassOop typeArrayKlass::array_klass_impl(typeArrayKlassHandle h_this, bool or_null, int n, TRAPS) { | |
158 int dimension = h_this->dimension(); | |
159 assert(dimension <= n, "check order of chain"); | |
160 if (dimension == n) | |
161 return h_this(); | |
162 | |
163 objArrayKlassHandle h_ak(THREAD, h_this->higher_dimension()); | |
164 if (h_ak.is_null()) { | |
165 if (or_null) return NULL; | |
166 | |
167 ResourceMark rm; | |
168 JavaThread *jt = (JavaThread *)THREAD; | |
169 { | |
170 MutexLocker mc(Compile_lock, THREAD); // for vtables | |
171 // Atomic create higher dimension and link into list | |
172 MutexLocker mu(MultiArray_lock, THREAD); | |
173 | |
174 h_ak = objArrayKlassHandle(THREAD, h_this->higher_dimension()); | |
175 if (h_ak.is_null()) { | |
176 klassOop oak = objArrayKlassKlass::cast( | |
177 Universe::objArrayKlassKlassObj())->allocate_objArray_klass( | |
178 dimension + 1, h_this, CHECK_NULL); | |
179 h_ak = objArrayKlassHandle(THREAD, oak); | |
180 h_ak->set_lower_dimension(h_this()); | |
2119 | 181 OrderAccess::storestore(); |
0 | 182 h_this->set_higher_dimension(h_ak()); |
183 assert(h_ak->oop_is_objArray(), "incorrect initialization of objArrayKlass"); | |
184 } | |
185 } | |
186 } else { | |
187 CHECK_UNHANDLED_OOPS_ONLY(Thread::current()->clear_unhandled_oops()); | |
188 } | |
189 if (or_null) { | |
190 return h_ak->array_klass_or_null(n); | |
191 } | |
192 return h_ak->array_klass(n, CHECK_NULL); | |
193 } | |
194 | |
195 klassOop typeArrayKlass::array_klass_impl(bool or_null, TRAPS) { | |
196 return array_klass_impl(or_null, dimension() + 1, THREAD); | |
197 } | |
198 | |
199 int typeArrayKlass::oop_size(oop obj) const { | |
200 assert(obj->is_typeArray(),"must be a type array"); | |
201 typeArrayOop t = typeArrayOop(obj); | |
202 return t->object_size(); | |
203 } | |
204 | |
205 void typeArrayKlass::oop_follow_contents(oop obj) { | |
206 assert(obj->is_typeArray(),"must be a type array"); | |
207 // Performance tweak: We skip iterating over the klass pointer since we | |
208 // know that Universe::typeArrayKlass never moves. | |
209 } | |
210 | |
211 #ifndef SERIALGC | |
212 void typeArrayKlass::oop_follow_contents(ParCompactionManager* cm, oop obj) { | |
213 assert(obj->is_typeArray(),"must be a type array"); | |
214 // Performance tweak: We skip iterating over the klass pointer since we | |
215 // know that Universe::typeArrayKlass never moves. | |
216 } | |
217 #endif // SERIALGC | |
218 | |
219 int typeArrayKlass::oop_adjust_pointers(oop obj) { | |
220 assert(obj->is_typeArray(),"must be a type array"); | |
221 typeArrayOop t = typeArrayOop(obj); | |
222 // Performance tweak: We skip iterating over the klass pointer since we | |
223 // know that Universe::typeArrayKlass never moves. | |
224 return t->object_size(); | |
225 } | |
226 | |
227 int typeArrayKlass::oop_oop_iterate(oop obj, OopClosure* blk) { | |
228 assert(obj->is_typeArray(),"must be a type array"); | |
229 typeArrayOop t = typeArrayOop(obj); | |
230 // Performance tweak: We skip iterating over the klass pointer since we | |
231 // know that Universe::typeArrayKlass never moves. | |
232 return t->object_size(); | |
233 } | |
234 | |
235 int typeArrayKlass::oop_oop_iterate_m(oop obj, OopClosure* blk, MemRegion mr) { | |
236 assert(obj->is_typeArray(),"must be a type array"); | |
237 typeArrayOop t = typeArrayOop(obj); | |
238 // Performance tweak: We skip iterating over the klass pointer since we | |
239 // know that Universe::typeArrayKlass never moves. | |
240 return t->object_size(); | |
241 } | |
242 | |
243 #ifndef SERIALGC | |
244 void typeArrayKlass::oop_push_contents(PSPromotionManager* pm, oop obj) { | |
245 assert(obj->is_typeArray(),"must be a type array"); | |
246 } | |
247 | |
248 int | |
249 typeArrayKlass::oop_update_pointers(ParCompactionManager* cm, oop obj) { | |
250 assert(obj->is_typeArray(),"must be a type array"); | |
251 return typeArrayOop(obj)->object_size(); | |
252 } | |
253 #endif // SERIALGC | |
254 | |
255 void typeArrayKlass::initialize(TRAPS) { | |
256 // Nothing to do. Having this function is handy since objArrayKlasses can be | |
257 // initialized by calling initialize on their bottom_klass, see objArrayKlass::initialize | |
258 } | |
259 | |
260 const char* typeArrayKlass::external_name(BasicType type) { | |
261 switch (type) { | |
262 case T_BOOLEAN: return "[Z"; | |
263 case T_CHAR: return "[C"; | |
264 case T_FLOAT: return "[F"; | |
265 case T_DOUBLE: return "[D"; | |
266 case T_BYTE: return "[B"; | |
267 case T_SHORT: return "[S"; | |
268 case T_INT: return "[I"; | |
269 case T_LONG: return "[J"; | |
270 default: ShouldNotReachHere(); | |
271 } | |
272 return NULL; | |
273 } | |
274 | |
275 #ifndef PRODUCT | |
276 // Printing | |
277 | |
278 static void print_boolean_array(typeArrayOop ta, int print_len, outputStream* st) { | |
279 for (int index = 0; index < print_len; index++) { | |
280 st->print_cr(" - %3d: %s", index, (ta->bool_at(index) == 0) ? "false" : "true"); | |
281 } | |
282 } | |
283 | |
284 | |
285 static void print_char_array(typeArrayOop ta, int print_len, outputStream* st) { | |
286 for (int index = 0; index < print_len; index++) { | |
287 jchar c = ta->char_at(index); | |
288 st->print_cr(" - %3d: %x %c", index, c, isprint(c) ? c : ' '); | |
289 } | |
290 } | |
291 | |
292 | |
293 static void print_float_array(typeArrayOop ta, int print_len, outputStream* st) { | |
294 for (int index = 0; index < print_len; index++) { | |
295 st->print_cr(" - %3d: %g", index, ta->float_at(index)); | |
296 } | |
297 } | |
298 | |
299 | |
300 static void print_double_array(typeArrayOop ta, int print_len, outputStream* st) { | |
301 for (int index = 0; index < print_len; index++) { | |
302 st->print_cr(" - %3d: %g", index, ta->double_at(index)); | |
303 } | |
304 } | |
305 | |
306 | |
307 static void print_byte_array(typeArrayOop ta, int print_len, outputStream* st) { | |
308 for (int index = 0; index < print_len; index++) { | |
309 jbyte c = ta->byte_at(index); | |
310 st->print_cr(" - %3d: %x %c", index, c, isprint(c) ? c : ' '); | |
311 } | |
312 } | |
313 | |
314 | |
315 static void print_short_array(typeArrayOop ta, int print_len, outputStream* st) { | |
316 for (int index = 0; index < print_len; index++) { | |
317 int v = ta->ushort_at(index); | |
318 st->print_cr(" - %3d: 0x%x\t %d", index, v, v); | |
319 } | |
320 } | |
321 | |
322 | |
323 static void print_int_array(typeArrayOop ta, int print_len, outputStream* st) { | |
324 for (int index = 0; index < print_len; index++) { | |
325 jint v = ta->int_at(index); | |
326 st->print_cr(" - %3d: 0x%x %d", index, v, v); | |
327 } | |
328 } | |
329 | |
330 | |
331 static void print_long_array(typeArrayOop ta, int print_len, outputStream* st) { | |
332 for (int index = 0; index < print_len; index++) { | |
333 jlong v = ta->long_at(index); | |
334 st->print_cr(" - %3d: 0x%x 0x%x", index, high(v), low(v)); | |
335 } | |
336 } | |
337 | |
338 | |
339 void typeArrayKlass::oop_print_on(oop obj, outputStream* st) { | |
340 arrayKlass::oop_print_on(obj, st); | |
341 typeArrayOop ta = typeArrayOop(obj); | |
342 int print_len = MIN2((intx) ta->length(), MaxElementPrintSize); | |
343 switch (element_type()) { | |
344 case T_BOOLEAN: print_boolean_array(ta, print_len, st); break; | |
345 case T_CHAR: print_char_array(ta, print_len, st); break; | |
346 case T_FLOAT: print_float_array(ta, print_len, st); break; | |
347 case T_DOUBLE: print_double_array(ta, print_len, st); break; | |
348 case T_BYTE: print_byte_array(ta, print_len, st); break; | |
349 case T_SHORT: print_short_array(ta, print_len, st); break; | |
350 case T_INT: print_int_array(ta, print_len, st); break; | |
351 case T_LONG: print_long_array(ta, print_len, st); break; | |
352 default: ShouldNotReachHere(); | |
353 } | |
354 int remaining = ta->length() - print_len; | |
355 if (remaining > 0) { | |
356 tty->print_cr(" - <%d more elements, increase MaxElementPrintSize to print>", remaining); | |
357 } | |
358 } | |
359 | |
360 #endif // PRODUCT | |
361 | |
362 const char* typeArrayKlass::internal_name() const { | |
363 return Klass::external_name(); | |
364 } |