201 ArrayKlass* ak = ArrayKlass::cast(ld_klass);
202 oop sub_array = ak->multi_allocate(rank-1, &sizes[1], CHECK_NULL);
203 h_array->obj_at_put(index, sub_array);
204 }
205 } else {
206 // Since this array dimension has zero length, nothing will be
207 // allocated, however the lower dimension values must be checked
208 // for illegal values.
209 for (int i = 0; i < rank - 1; ++i) {
210 sizes += 1;
211 if (*sizes < 0) {
212 THROW_0(vmSymbols::java_lang_NegativeArraySizeException());
213 }
214 }
215 }
216 }
217 return h_array();
218 }
219
220 // Either oop or narrowOop depending on UseCompressedOops.
221 template <class T> void ObjArrayKlass::do_copy(arrayOop s, T* src,
222 arrayOop d, T* dst, int length, TRAPS) {
223 if (oopDesc::equals(s, d)) {
224 // since source and destination are equal we do not need conversion checks.
225 assert(length > 0, "sanity check");
226 HeapAccess<>::oop_arraycopy(s, d, src, dst, length);
227 } else {
228 // We have to make sure all elements conform to the destination array
229 Klass* bound = ObjArrayKlass::cast(d->klass())->element_klass();
230 Klass* stype = ObjArrayKlass::cast(s->klass())->element_klass();
231 if (stype == bound || stype->is_subtype_of(bound)) {
232 // elements are guaranteed to be subtypes, so no check necessary
233 HeapAccess<ARRAYCOPY_DISJOINT>::oop_arraycopy(s, d, src, dst, length);
234 } else {
235 // slow case: need individual subtype checks
236 // note: don't use obj_at_put below because it includes a redundant store check
237 if (!HeapAccess<ARRAYCOPY_DISJOINT | ARRAYCOPY_CHECKCAST>::oop_arraycopy(s, d, src, dst, length)) {
238 THROW(vmSymbols::java_lang_ArrayStoreException());
239 }
240 }
241 }
242 }
243
244 void ObjArrayKlass::copy_array(arrayOop s, int src_pos, arrayOop d,
245 int dst_pos, int length, TRAPS) {
246 assert(s->is_objArray(), "must be obj array");
247
248 if (!d->is_objArray()) {
249 THROW(vmSymbols::java_lang_ArrayStoreException());
250 }
251
252 // Check is all offsets and lengths are non negative
253 if (src_pos < 0 || dst_pos < 0 || length < 0) {
254 THROW(vmSymbols::java_lang_ArrayIndexOutOfBoundsException());
255 }
256 // Check if the ranges are valid
257 if ( (((unsigned int) length + (unsigned int) src_pos) > (unsigned int) s->length())
258 || (((unsigned int) length + (unsigned int) dst_pos) > (unsigned int) d->length()) ) {
259 THROW(vmSymbols::java_lang_ArrayIndexOutOfBoundsException());
260 }
261
262 // Special case. Boundary cases must be checked first
263 // This allows the following call: copy_array(s, s.length(), d.length(), 0).
264 // This is correct, since the position is supposed to be an 'in between point', i.e., s.length(),
265 // points to the right of the last element.
266 if (length==0) {
267 return;
268 }
269 if (UseCompressedOops) {
270 narrowOop* const src = objArrayOop(s)->obj_at_addr<narrowOop>(src_pos);
271 narrowOop* const dst = objArrayOop(d)->obj_at_addr<narrowOop>(dst_pos);
272 do_copy<narrowOop>(s, src, d, dst, length, CHECK);
273 } else {
274 oop* const src = objArrayOop(s)->obj_at_addr<oop>(src_pos);
275 oop* const dst = objArrayOop(d)->obj_at_addr<oop>(dst_pos);
276 do_copy<oop> (s, src, d, dst, length, CHECK);
277 }
278 }
279
280
281 Klass* ObjArrayKlass::array_klass_impl(bool or_null, int n, TRAPS) {
282
283 assert(dimension() <= n, "check order of chain");
284 int dim = dimension();
285 if (dim == n) return this;
286
287 // lock-free read needs acquire semantics
288 if (higher_dimension_acquire() == NULL) {
289 if (or_null) return NULL;
290
291 ResourceMark rm;
292 JavaThread *jt = (JavaThread *)THREAD;
293 {
294 MutexLocker mc(Compile_lock, THREAD); // for vtables
295 // Ensure atomic creation of higher dimensions
296 MutexLocker mu(MultiArray_lock, THREAD);
|
201 ArrayKlass* ak = ArrayKlass::cast(ld_klass);
202 oop sub_array = ak->multi_allocate(rank-1, &sizes[1], CHECK_NULL);
203 h_array->obj_at_put(index, sub_array);
204 }
205 } else {
206 // Since this array dimension has zero length, nothing will be
207 // allocated, however the lower dimension values must be checked
208 // for illegal values.
209 for (int i = 0; i < rank - 1; ++i) {
210 sizes += 1;
211 if (*sizes < 0) {
212 THROW_0(vmSymbols::java_lang_NegativeArraySizeException());
213 }
214 }
215 }
216 }
217 return h_array();
218 }
219
220 // Either oop or narrowOop depending on UseCompressedOops.
221 template <class T> void ObjArrayKlass::do_copy(arrayOop s, size_t src_offset,
222 arrayOop d, size_t dst_offset, int length, TRAPS) {
223 if (oopDesc::equals(s, d)) {
224 // since source and destination are equal we do not need conversion checks.
225 assert(length > 0, "sanity check");
226 HeapAccess<>::oop_arraycopy<T>(s, src_offset, NULL, d, dst_offset, NULL, length);
227 } else {
228 // We have to make sure all elements conform to the destination array
229 Klass* bound = ObjArrayKlass::cast(d->klass())->element_klass();
230 Klass* stype = ObjArrayKlass::cast(s->klass())->element_klass();
231 if (stype == bound || stype->is_subtype_of(bound)) {
232 // elements are guaranteed to be subtypes, so no check necessary
233 HeapAccess<ARRAYCOPY_DISJOINT>::oop_arraycopy<T>(s, src_offset, NULL, d, dst_offset, NULL, length);
234 } else {
235 // slow case: need individual subtype checks
236 // note: don't use obj_at_put below because it includes a redundant store check
237 if (!HeapAccess<ARRAYCOPY_DISJOINT | ARRAYCOPY_CHECKCAST>::oop_arraycopy<T>(s, src_offset, NULL, d, dst_offset, NULL, length)) {
238 THROW(vmSymbols::java_lang_ArrayStoreException());
239 }
240 }
241 }
242 }
243
244 void ObjArrayKlass::copy_array(arrayOop s, int src_pos, arrayOop d,
245 int dst_pos, int length, TRAPS) {
246 assert(s->is_objArray(), "must be obj array");
247
248 if (!d->is_objArray()) {
249 THROW(vmSymbols::java_lang_ArrayStoreException());
250 }
251
252 // Check is all offsets and lengths are non negative
253 if (src_pos < 0 || dst_pos < 0 || length < 0) {
254 THROW(vmSymbols::java_lang_ArrayIndexOutOfBoundsException());
255 }
256 // Check if the ranges are valid
257 if ( (((unsigned int) length + (unsigned int) src_pos) > (unsigned int) s->length())
258 || (((unsigned int) length + (unsigned int) dst_pos) > (unsigned int) d->length()) ) {
259 THROW(vmSymbols::java_lang_ArrayIndexOutOfBoundsException());
260 }
261
262 // Special case. Boundary cases must be checked first
263 // This allows the following call: copy_array(s, s.length(), d.length(), 0).
264 // This is correct, since the position is supposed to be an 'in between point', i.e., s.length(),
265 // points to the right of the last element.
266 if (length==0) {
267 return;
268 }
269 if (UseCompressedOops) {
270 size_t src_offset = (size_t) objArrayOopDesc::obj_at_offset<narrowOop>(src_pos);
271 size_t dst_offset = (size_t) objArrayOopDesc::obj_at_offset<narrowOop>(dst_pos);
272 assert(arrayOopDesc::obj_offset_to_raw<narrowOop>(s, src_offset, NULL) == objArrayOop(s)->obj_at_addr<narrowOop>(src_pos), "sanity");
273 assert(arrayOopDesc::obj_offset_to_raw<narrowOop>(d, dst_offset, NULL) == objArrayOop(d)->obj_at_addr<narrowOop>(dst_pos), "sanity");
274 do_copy<narrowOop>(s, src_offset, d, dst_offset, length, CHECK);
275 } else {
276 size_t src_offset = (size_t) objArrayOopDesc::obj_at_offset<oop>(src_pos);
277 size_t dst_offset = (size_t) objArrayOopDesc::obj_at_offset<oop>(dst_pos);
278 assert(arrayOopDesc::obj_offset_to_raw<oop>(s, src_offset, NULL) == objArrayOop(s)->obj_at_addr<oop>(src_pos), "sanity");
279 assert(arrayOopDesc::obj_offset_to_raw<oop>(d, dst_offset, NULL) == objArrayOop(d)->obj_at_addr<oop>(dst_pos), "sanity");
280 do_copy<oop> (s, src_offset, d, dst_offset, length, CHECK);
281 }
282 }
283
284
285 Klass* ObjArrayKlass::array_klass_impl(bool or_null, int n, TRAPS) {
286
287 assert(dimension() <= n, "check order of chain");
288 int dim = dimension();
289 if (dim == n) return this;
290
291 // lock-free read needs acquire semantics
292 if (higher_dimension_acquire() == NULL) {
293 if (or_null) return NULL;
294
295 ResourceMark rm;
296 JavaThread *jt = (JavaThread *)THREAD;
297 {
298 MutexLocker mc(Compile_lock, THREAD); // for vtables
299 // Ensure atomic creation of higher dimensions
300 MutexLocker mu(MultiArray_lock, THREAD);
|