src/hotspot/share/oops/objArrayKlass.cpp
changeset 47998 fb0275c320a0
parent 47658 c2b7fb8e5144
child 49359 59f6547e151f
equal deleted inserted replaced
47997:55c43e677ded 47998:fb0275c320a0
    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");