42 #include "oops/objArrayOop.inline.hpp" |
42 #include "oops/objArrayOop.inline.hpp" |
43 #include "oops/oop.inline.hpp" |
43 #include "oops/oop.inline.hpp" |
44 #include "oops/symbol.hpp" |
44 #include "oops/symbol.hpp" |
45 #include "runtime/handles.inline.hpp" |
45 #include "runtime/handles.inline.hpp" |
46 #include "runtime/mutexLocker.hpp" |
46 #include "runtime/mutexLocker.hpp" |
47 #include "utilities/copy.hpp" |
|
48 #include "utilities/macros.hpp" |
47 #include "utilities/macros.hpp" |
49 |
48 |
50 ObjArrayKlass* ObjArrayKlass::allocate(ClassLoaderData* loader_data, int n, Klass* k, Symbol* name, TRAPS) { |
49 ObjArrayKlass* ObjArrayKlass::allocate(ClassLoaderData* loader_data, int n, Klass* k, Symbol* name, TRAPS) { |
51 assert(ObjArrayKlass::header_size() <= InstanceKlass::header_size(), |
50 assert(ObjArrayKlass::header_size() <= InstanceKlass::header_size(), |
52 "array klasses must be same size as InstanceKlass"); |
51 "array klasses must be same size as InstanceKlass"); |
219 } |
218 } |
220 |
219 |
221 // Either oop or narrowOop depending on UseCompressedOops. |
220 // Either oop or narrowOop depending on UseCompressedOops. |
222 template <class T> void ObjArrayKlass::do_copy(arrayOop s, T* src, |
221 template <class T> void ObjArrayKlass::do_copy(arrayOop s, T* src, |
223 arrayOop d, T* dst, int length, TRAPS) { |
222 arrayOop d, T* dst, int length, TRAPS) { |
224 |
|
225 BarrierSet* bs = Universe::heap()->barrier_set(); |
|
226 // For performance reasons, we assume we are that the write barrier we |
|
227 // are using has optimized modes for arrays of references. At least one |
|
228 // of the asserts below will fail if this is not the case. |
|
229 |
|
230 if (s == d) { |
223 if (s == d) { |
231 // since source and destination are equal we do not need conversion checks. |
224 // since source and destination are equal we do not need conversion checks. |
232 assert(length > 0, "sanity check"); |
225 assert(length > 0, "sanity check"); |
233 bs->write_ref_array_pre(dst, length); |
226 HeapAccess<>::oop_arraycopy(s, d, src, dst, length); |
234 Copy::conjoint_oops_atomic(src, dst, length); |
|
235 } else { |
227 } else { |
236 // We have to make sure all elements conform to the destination array |
228 // We have to make sure all elements conform to the destination array |
237 Klass* bound = ObjArrayKlass::cast(d->klass())->element_klass(); |
229 Klass* bound = ObjArrayKlass::cast(d->klass())->element_klass(); |
238 Klass* stype = ObjArrayKlass::cast(s->klass())->element_klass(); |
230 Klass* stype = ObjArrayKlass::cast(s->klass())->element_klass(); |
239 if (stype == bound || stype->is_subtype_of(bound)) { |
231 if (stype == bound || stype->is_subtype_of(bound)) { |
240 // elements are guaranteed to be subtypes, so no check necessary |
232 // elements are guaranteed to be subtypes, so no check necessary |
241 bs->write_ref_array_pre(dst, length); |
233 HeapAccess<ARRAYCOPY_DISJOINT>::oop_arraycopy(s, d, src, dst, length); |
242 Copy::conjoint_oops_atomic(src, dst, length); |
|
243 } else { |
234 } else { |
244 // slow case: need individual subtype checks |
235 // slow case: need individual subtype checks |
245 // note: don't use obj_at_put below because it includes a redundant store check |
236 // note: don't use obj_at_put below because it includes a redundant store check |
246 T* from = src; |
237 if (!HeapAccess<ARRAYCOPY_DISJOINT | ARRAYCOPY_CHECKCAST>::oop_arraycopy(s, d, src, dst, length)) { |
247 T* end = from + length; |
238 THROW(vmSymbols::java_lang_ArrayStoreException()); |
248 for (T* p = dst; from < end; from++, p++) { |
239 } |
249 // XXX this is going to be slow. |
240 } |
250 T element = *from; |
241 } |
251 // even slower now |
|
252 bool element_is_null = oopDesc::is_null(element); |
|
253 oop new_val = element_is_null ? oop(NULL) |
|
254 : oopDesc::decode_heap_oop_not_null(element); |
|
255 if (element_is_null || |
|
256 (new_val->klass())->is_subtype_of(bound)) { |
|
257 bs->write_ref_field_pre(p, new_val); |
|
258 *p = element; |
|
259 } else { |
|
260 // We must do a barrier to cover the partial copy. |
|
261 const size_t pd = pointer_delta(p, dst, (size_t)heapOopSize); |
|
262 // pointer delta is scaled to number of elements (length field in |
|
263 // objArrayOop) which we assume is 32 bit. |
|
264 assert(pd == (size_t)(int)pd, "length field overflow"); |
|
265 bs->write_ref_array((HeapWord*)dst, pd); |
|
266 THROW(vmSymbols::java_lang_ArrayStoreException()); |
|
267 return; |
|
268 } |
|
269 } |
|
270 } |
|
271 } |
|
272 bs->write_ref_array((HeapWord*)dst, length); |
|
273 } |
242 } |
274 |
243 |
275 void ObjArrayKlass::copy_array(arrayOop s, int src_pos, arrayOop d, |
244 void ObjArrayKlass::copy_array(arrayOop s, int src_pos, arrayOop d, |
276 int dst_pos, int length, TRAPS) { |
245 int dst_pos, int length, TRAPS) { |
277 assert(s->is_objArray(), "must be obj array"); |
246 assert(s->is_objArray(), "must be obj array"); |