< prev index next >

src/hotspot/share/oops/objArrayKlass.cpp

Print this page




  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  *
  19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  20  * or visit www.oracle.com if you need additional information or have any
  21  * questions.
  22  *
  23  */
  24 
  25 #include "precompiled.hpp"
  26 #include "classfile/moduleEntry.hpp"
  27 #include "classfile/packageEntry.hpp"
  28 #include "classfile/symbolTable.hpp"
  29 #include "classfile/systemDictionary.hpp"
  30 #include "classfile/vmSymbols.hpp"
  31 #include "gc/shared/collectedHeap.inline.hpp"
  32 #include "memory/iterator.inline.hpp"
  33 #include "memory/metadataFactory.hpp"
  34 #include "memory/metaspaceClosure.hpp"

  35 #include "memory/resourceArea.hpp"
  36 #include "memory/universe.hpp"
  37 #include "oops/arrayKlass.inline.hpp"
  38 #include "oops/instanceKlass.hpp"
  39 #include "oops/klass.inline.hpp"
  40 #include "oops/objArrayKlass.inline.hpp"
  41 #include "oops/objArrayOop.inline.hpp"
  42 #include "oops/oop.inline.hpp"
  43 #include "oops/symbol.hpp"
  44 #include "runtime/handles.inline.hpp"
  45 #include "runtime/mutexLocker.hpp"
  46 #include "utilities/macros.hpp"
  47 
  48 ObjArrayKlass* ObjArrayKlass::allocate(ClassLoaderData* loader_data, int n, Klass* k, Symbol* name, TRAPS) {
  49   assert(ObjArrayKlass::header_size() <= InstanceKlass::header_size(),
  50       "array klasses must be same size as InstanceKlass");
  51 
  52   int size = ArrayKlass::static_size(ObjArrayKlass::header_size());
  53 
  54   return new (loader_data, size, THREAD) ObjArrayKlass(n, k, name);


  80         Klass* ek = NULL;
  81         {
  82           MutexUnlocker mu(MultiArray_lock);
  83           super_klass = element_super->array_klass(CHECK_0);
  84           for( int i = element_supers->length()-1; i >= 0; i-- ) {
  85             Klass* elem_super = element_supers->at(i);
  86             elem_super->array_klass(CHECK_0);
  87           }
  88           // Now retry from the beginning
  89           ek = element_klass->array_klass(n, CHECK_0);
  90         }  // re-lock
  91         return ek;
  92       }
  93     } else {
  94       // The element type is already Object.  Object[] has direct super of Object.
  95       super_klass = SystemDictionary::Object_klass();
  96     }
  97   }
  98 
  99   // Create type name for klass.
 100   Symbol* name = NULL;
 101   if (!element_klass->is_instance_klass() ||
 102       (name = InstanceKlass::cast(element_klass)->array_name()) == NULL) {
 103 
 104     ResourceMark rm(THREAD);
 105     char *name_str = element_klass->name()->as_C_string();
 106     int len = element_klass->name()->utf8_length();
 107     char *new_str = NEW_RESOURCE_ARRAY(char, len + 4);
 108     int idx = 0;
 109     new_str[idx++] = '[';
 110     if (element_klass->is_instance_klass()) { // it could be an array or simple type
 111       new_str[idx++] = 'L';
 112     }
 113     memcpy(&new_str[idx], name_str, len * sizeof(char));
 114     idx += len;
 115     if (element_klass->is_instance_klass()) {
 116       new_str[idx++] = ';';
 117     }
 118     new_str[idx++] = '\0';
 119     name = SymbolTable::new_permanent_symbol(new_str, CHECK_0);
 120     if (element_klass->is_instance_klass()) {
 121       InstanceKlass* ik = InstanceKlass::cast(element_klass);
 122       ik->set_array_name(name);
 123     }
 124   }
 125 
 126   // Initialize instance variables
 127   ObjArrayKlass* oak = ObjArrayKlass::allocate(loader_data, n, element_klass, name, CHECK_0);
 128 
 129   // Add all classes to our internal class loader list here,
 130   // including classes in the bootstrap (NULL) class loader.
 131   // GC walks these as strong roots.
 132   loader_data->add_class(oak);
 133 
 134   ModuleEntry* module = oak->module();
 135   assert(module != NULL, "No module entry for array");
 136 
 137   // Call complete_create_array_klass after all instance variables has been initialized.
 138   ArrayKlass::complete_create_array_klass(oak, super_klass, module, CHECK_0);
 139 
 140   return oak;
 141 }
 142 
 143 ObjArrayKlass::ObjArrayKlass(int n, Klass* element_klass, Symbol* name) : ArrayKlass(name, ID) {
 144   this->set_dimension(n);
 145   this->set_element_klass(element_klass);
 146   // decrement refcount because object arrays are not explicitly freed.  The
 147   // InstanceKlass array_name() keeps the name counted while the klass is
 148   // loaded.
 149   name->decrement_refcount();
 150 
 151   Klass* bk;
 152   if (element_klass->is_objArray_klass()) {
 153     bk = ObjArrayKlass::cast(element_klass)->bottom_klass();


 154   } else {
 155     bk = element_klass;
 156   }
 157   assert(bk != NULL && (bk->is_instance_klass() || bk->is_typeArray_klass()), "invalid bottom klass");

 158   this->set_bottom_klass(bk);
 159   this->set_class_loader_data(bk->class_loader_data());
 160 
 161   this->set_layout_helper(array_layout_helper(T_OBJECT));
 162   assert(this->is_array_klass(), "sanity");
 163   assert(this->is_objArray_klass(), "sanity");
 164 }
 165 
 166 int ObjArrayKlass::oop_size(oop obj) const {
 167   assert(obj->is_objArray(), "must be object array");
 168   return objArrayOop(obj)->object_size();
 169 }
 170 
 171 objArrayOop ObjArrayKlass::allocate(int length, TRAPS) {
 172   check_array_allocation_length(length, arrayOopDesc::max_array_length(T_OBJECT), CHECK_0);
 173   int size = objArrayOopDesc::object_size(length);
 174   return (objArrayOop)Universe::heap()->array_allocate(this, size, length,
 175                                                        /* do_zero */ true, THREAD);
 176 }
 177 
 178 static int multi_alloc_counter = 0;
 179 
 180 oop ObjArrayKlass::multi_allocate(int rank, jint* sizes, TRAPS) {
 181   int length = *sizes;




 182   // Call to lower_dimension uses this pointer, so most be called before a
 183   // possible GC
 184   Klass* ld_klass = lower_dimension();
 185   // If length < 0 allocate will throw an exception.
 186   objArrayOop array = allocate(length, CHECK_NULL);
 187   objArrayHandle h_array (THREAD, array);
 188   if (rank > 1) {
 189     if (length != 0) {
 190       for (int index = 0; index < length; index++) {
 191         ArrayKlass* ak = ArrayKlass::cast(ld_klass);
 192         oop sub_array = ak->multi_allocate(rank-1, &sizes[1], CHECK_NULL);
 193         h_array->obj_at_put(index, sub_array);
 194       }
 195     } else {
 196       // Since this array dimension has zero length, nothing will be
 197       // allocated, however the lower dimension values must be checked
 198       // for illegal values.
 199       for (int i = 0; i < rank - 1; ++i) {
 200         sizes += 1;
 201         if (*sizes < 0) {
 202           THROW_MSG_0(vmSymbols::java_lang_NegativeArraySizeException(), err_msg("%d", *sizes));
 203         }
 204       }
 205     }
 206   }
 207   return h_array();
 208 }
 209 
 210 // Either oop or narrowOop depending on UseCompressedOops.
 211 void ObjArrayKlass::do_copy(arrayOop s, size_t src_offset,
 212                             arrayOop d, size_t dst_offset, int length, TRAPS) {
 213   if (oopDesc::equals(s, d)) {
 214     // since source and destination are equal we do not need conversion checks.
 215     assert(length > 0, "sanity check");
 216     ArrayAccess<>::oop_arraycopy(s, src_offset, d, dst_offset, length);
 217   } else {
 218     // We have to make sure all elements conform to the destination array
 219     Klass* bound = ObjArrayKlass::cast(d->klass())->element_klass();
 220     Klass* stype = ObjArrayKlass::cast(s->klass())->element_klass();
 221     if (stype == bound || stype->is_subtype_of(bound)) {
 222       // elements are guaranteed to be subtypes, so no check necessary
 223       ArrayAccess<ARRAYCOPY_DISJOINT>::oop_arraycopy(s, src_offset, d, dst_offset, length);
 224     } else {
 225       // slow case: need individual subtype checks
 226       // note: don't use obj_at_put below because it includes a redundant store check


 230         if (!bound->is_subtype_of(stype)) {
 231           ss.print("arraycopy: type mismatch: can not copy %s[] into %s[]",
 232                    stype->external_name(), bound->external_name());
 233         } else {
 234           // oop_arraycopy should return the index in the source array that
 235           // contains the problematic oop.
 236           ss.print("arraycopy: element type mismatch: can not cast one of the elements"
 237                    " of %s[] to the type of the destination array, %s",
 238                    stype->external_name(), bound->external_name());
 239         }
 240         THROW_MSG(vmSymbols::java_lang_ArrayStoreException(), ss.as_string());
 241       }
 242     }
 243   }
 244 }
 245 
 246 void ObjArrayKlass::copy_array(arrayOop s, int src_pos, arrayOop d,
 247                                int dst_pos, int length, TRAPS) {
 248   assert(s->is_objArray(), "must be obj array");
 249 







 250   if (!d->is_objArray()) {
 251     ResourceMark rm(THREAD);
 252     stringStream ss;
 253     if (d->is_typeArray()) {
 254       ss.print("arraycopy: type mismatch: can not copy object array[] into %s[]",
 255                type2name_tab[ArrayKlass::cast(d->klass())->element_type()]);
 256     } else {
 257       ss.print("arraycopy: destination type %s is not an array", d->klass()->external_name());
 258     }
 259     THROW_MSG(vmSymbols::java_lang_ArrayStoreException(), ss.as_string());
 260   }
 261 
 262   // Check is all offsets and lengths are non negative
 263   if (src_pos < 0 || dst_pos < 0 || length < 0) {
 264     // Pass specific exception reason.
 265     ResourceMark rm(THREAD);
 266     stringStream ss;
 267     if (src_pos < 0) {
 268       ss.print("arraycopy: source index %d out of bounds for object array[%d]",
 269                src_pos, s->length());


 281     // Pass specific exception reason.
 282     ResourceMark rm(THREAD);
 283     stringStream ss;
 284     if (((unsigned int) length + (unsigned int) src_pos) > (unsigned int) s->length()) {
 285       ss.print("arraycopy: last source index %u out of bounds for object array[%d]",
 286                (unsigned int) length + (unsigned int) src_pos, s->length());
 287     } else {
 288       ss.print("arraycopy: last destination index %u out of bounds for object array[%d]",
 289                (unsigned int) length + (unsigned int) dst_pos, d->length());
 290     }
 291     THROW_MSG(vmSymbols::java_lang_ArrayIndexOutOfBoundsException(), ss.as_string());
 292   }
 293 
 294   // Special case. Boundary cases must be checked first
 295   // This allows the following call: copy_array(s, s.length(), d.length(), 0).
 296   // This is correct, since the position is supposed to be an 'in between point', i.e., s.length(),
 297   // points to the right of the last element.
 298   if (length==0) {
 299     return;
 300   }
 301   if (UseCompressedOops) {



















 302     size_t src_offset = (size_t) objArrayOopDesc::obj_at_offset<narrowOop>(src_pos);
 303     size_t dst_offset = (size_t) objArrayOopDesc::obj_at_offset<narrowOop>(dst_pos);
 304     assert(arrayOopDesc::obj_offset_to_raw<narrowOop>(s, src_offset, NULL) ==
 305            objArrayOop(s)->obj_at_addr_raw<narrowOop>(src_pos), "sanity");
 306     assert(arrayOopDesc::obj_offset_to_raw<narrowOop>(d, dst_offset, NULL) ==
 307            objArrayOop(d)->obj_at_addr_raw<narrowOop>(dst_pos), "sanity");
 308     do_copy(s, src_offset, d, dst_offset, length, CHECK);
 309   } else {
 310     size_t src_offset = (size_t) objArrayOopDesc::obj_at_offset<oop>(src_pos);
 311     size_t dst_offset = (size_t) objArrayOopDesc::obj_at_offset<oop>(dst_pos);
 312     assert(arrayOopDesc::obj_offset_to_raw<oop>(s, src_offset, NULL) ==
 313            objArrayOop(s)->obj_at_addr_raw<oop>(src_pos), "sanity");
 314     assert(arrayOopDesc::obj_offset_to_raw<oop>(d, dst_offset, NULL) ==
 315            objArrayOop(d)->obj_at_addr_raw<oop>(dst_pos), "sanity");
 316     do_copy(s, src_offset, d, dst_offset, length, CHECK);
 317   }
 318 }
 319 
 320 
 321 Klass* ObjArrayKlass::array_klass_impl(bool or_null, int n, TRAPS) {


 419   return (element_flags & (JVM_ACC_PUBLIC | JVM_ACC_PRIVATE | JVM_ACC_PROTECTED))
 420                         | (JVM_ACC_ABSTRACT | JVM_ACC_FINAL);
 421 }
 422 
 423 ModuleEntry* ObjArrayKlass::module() const {
 424   assert(bottom_klass() != NULL, "ObjArrayKlass returned unexpected NULL bottom_klass");
 425   // The array is defined in the module of its bottom class
 426   return bottom_klass()->module();
 427 }
 428 
 429 PackageEntry* ObjArrayKlass::package() const {
 430   assert(bottom_klass() != NULL, "ObjArrayKlass returned unexpected NULL bottom_klass");
 431   return bottom_klass()->package();
 432 }
 433 
 434 // Printing
 435 
 436 void ObjArrayKlass::print_on(outputStream* st) const {
 437 #ifndef PRODUCT
 438   Klass::print_on(st);
 439   st->print(" - instance klass: ");
 440   element_klass()->print_value_on(st);
 441   st->cr();
 442 #endif //PRODUCT
 443 }
 444 
 445 void ObjArrayKlass::print_value_on(outputStream* st) const {
 446   assert(is_klass(), "must be klass");
 447 
 448   element_klass()->print_value_on(st);
 449   st->print("[]");
 450 }
 451 
 452 #ifndef PRODUCT
 453 
 454 void ObjArrayKlass::oop_print_on(oop obj, outputStream* st) {
 455   ArrayKlass::oop_print_on(obj, st);
 456   assert(obj->is_objArray(), "must be objArray");
 457   objArrayOop oa = objArrayOop(obj);
 458   int print_len = MIN2((intx) oa->length(), MaxElementPrintSize);
 459   for(int index = 0; index < print_len; index++) {


 481   st->print("[%d] ", len);
 482   if (obj != NULL) {
 483     obj->print_address_on(st);
 484   } else {
 485     st->print_cr("NULL");
 486   }
 487 }
 488 
 489 const char* ObjArrayKlass::internal_name() const {
 490   return external_name();
 491 }
 492 
 493 
 494 // Verification
 495 
 496 void ObjArrayKlass::verify_on(outputStream* st) {
 497   ArrayKlass::verify_on(st);
 498   guarantee(element_klass()->is_klass(), "should be klass");
 499   guarantee(bottom_klass()->is_klass(), "should be klass");
 500   Klass* bk = bottom_klass();
 501   guarantee(bk->is_instance_klass() || bk->is_typeArray_klass(),  "invalid bottom klass");

 502 }
 503 
 504 void ObjArrayKlass::oop_verify_on(oop obj, outputStream* st) {
 505   ArrayKlass::oop_verify_on(obj, st);
 506   guarantee(obj->is_objArray(), "must be objArray");
 507   objArrayOop oa = objArrayOop(obj);
 508   for(int index = 0; index < oa->length(); index++) {
 509     guarantee(oopDesc::is_oop_or_null(oa->obj_at(index)), "should be oop");
 510   }
 511 }


  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  *
  19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  20  * or visit www.oracle.com if you need additional information or have any
  21  * questions.
  22  *
  23  */
  24 
  25 #include "precompiled.hpp"
  26 #include "classfile/moduleEntry.hpp"
  27 #include "classfile/packageEntry.hpp"
  28 #include "classfile/symbolTable.hpp"
  29 #include "classfile/systemDictionary.hpp"
  30 #include "classfile/vmSymbols.hpp"
  31 #include "gc/shared/collectedHeap.inline.hpp"
  32 #include "memory/iterator.inline.hpp"
  33 #include "memory/metadataFactory.hpp"
  34 #include "memory/metaspaceClosure.hpp"
  35 #include "memory/oopFactory.hpp"
  36 #include "memory/resourceArea.hpp"
  37 #include "memory/universe.hpp"
  38 #include "oops/arrayKlass.inline.hpp"
  39 #include "oops/instanceKlass.hpp"
  40 #include "oops/klass.inline.hpp"
  41 #include "oops/objArrayKlass.inline.hpp"
  42 #include "oops/objArrayOop.inline.hpp"
  43 #include "oops/oop.inline.hpp"
  44 #include "oops/symbol.hpp"
  45 #include "runtime/handles.inline.hpp"
  46 #include "runtime/mutexLocker.hpp"
  47 #include "utilities/macros.hpp"
  48 
  49 ObjArrayKlass* ObjArrayKlass::allocate(ClassLoaderData* loader_data, int n, Klass* k, Symbol* name, TRAPS) {
  50   assert(ObjArrayKlass::header_size() <= InstanceKlass::header_size(),
  51       "array klasses must be same size as InstanceKlass");
  52 
  53   int size = ArrayKlass::static_size(ObjArrayKlass::header_size());
  54 
  55   return new (loader_data, size, THREAD) ObjArrayKlass(n, k, name);


  81         Klass* ek = NULL;
  82         {
  83           MutexUnlocker mu(MultiArray_lock);
  84           super_klass = element_super->array_klass(CHECK_0);
  85           for( int i = element_supers->length()-1; i >= 0; i-- ) {
  86             Klass* elem_super = element_supers->at(i);
  87             elem_super->array_klass(CHECK_0);
  88           }
  89           // Now retry from the beginning
  90           ek = element_klass->array_klass(n, CHECK_0);
  91         }  // re-lock
  92         return ek;
  93       }
  94     } else {
  95       // The element type is already Object.  Object[] has direct super of Object.
  96       super_klass = SystemDictionary::Object_klass();
  97     }
  98   }
  99 
 100   // Create type name for klass.
 101   Symbol* name = ArrayKlass::create_element_klass_array_name(element_klass, CHECK_NULL);
























 102 
 103   // Initialize instance variables
 104   ObjArrayKlass* oak = ObjArrayKlass::allocate(loader_data, n, element_klass, name, CHECK_0);
 105 
 106   // Add all classes to our internal class loader list here,
 107   // including classes in the bootstrap (NULL) class loader.
 108   // GC walks these as strong roots.
 109   loader_data->add_class(oak);
 110 
 111   ModuleEntry* module = oak->module();
 112   assert(module != NULL, "No module entry for array");
 113 
 114   // Call complete_create_array_klass after all instance variables has been initialized.
 115   ArrayKlass::complete_create_array_klass(oak, super_klass, module, CHECK_0);
 116 
 117   return oak;
 118 }
 119 
 120 ObjArrayKlass::ObjArrayKlass(int n, Klass* element_klass, Symbol* name) : ArrayKlass(name, ID) {
 121   this->set_dimension(n);
 122   this->set_element_klass(element_klass);
 123   // decrement refcount because object arrays are not explicitly freed.  The
 124   // InstanceKlass array_name() keeps the name counted while the klass is
 125   // loaded.
 126   name->decrement_refcount();
 127 
 128   Klass* bk;
 129   if (element_klass->is_objArray_klass()) {
 130     bk = ObjArrayKlass::cast(element_klass)->bottom_klass();
 131   } else if (element_klass->is_valueArray_klass()) {
 132     bk = ValueArrayKlass::cast(element_klass)->element_klass();
 133   } else {
 134     bk = element_klass;
 135   }
 136   assert(bk != NULL && (bk->is_instance_klass()
 137       || bk->is_typeArray_klass()), "invalid bottom klass");
 138   this->set_bottom_klass(bk);
 139   this->set_class_loader_data(bk->class_loader_data());
 140 
 141   this->set_layout_helper(array_layout_helper(T_OBJECT));
 142   assert(this->is_array_klass(), "sanity");
 143   assert(this->is_objArray_klass(), "sanity");
 144 }
 145 
 146 int ObjArrayKlass::oop_size(oop obj) const {
 147   assert(obj->is_objArray(), "must be object array");
 148   return objArrayOop(obj)->object_size();
 149 }
 150 
 151 objArrayOop ObjArrayKlass::allocate(int length, TRAPS) {
 152   check_array_allocation_length(length, arrayOopDesc::max_array_length(T_OBJECT), CHECK_0);
 153   int size = objArrayOopDesc::object_size(length);
 154   return (objArrayOop)Universe::heap()->array_allocate(this, size, length,
 155                                                        /* do_zero */ true, THREAD);
 156 }
 157 
 158 static int multi_alloc_counter = 0;
 159 
 160 oop ObjArrayKlass::multi_allocate(int rank, jint* sizes, TRAPS) {
 161   int length = *sizes;
 162   if (rank == 1) { // last dim may be valueArray
 163     return oopFactory::new_array(element_klass(), length, CHECK_NULL);
 164   }
 165   guarantee(rank > 1, "Rank below 1");
 166   // Call to lower_dimension uses this pointer, so most be called before a
 167   // possible GC
 168   Klass* ld_klass = lower_dimension();
 169   // If length < 0 allocate will throw an exception.
 170   objArrayOop array = allocate(length, CHECK_NULL);
 171   objArrayHandle h_array (THREAD, array);

 172   if (length != 0) {
 173     for (int index = 0; index < length; index++) {
 174       ArrayKlass* ak = ArrayKlass::cast(ld_klass);
 175       oop sub_array = ak->multi_allocate(rank-1, &sizes[1], CHECK_NULL);
 176       h_array->obj_at_put(index, sub_array);
 177     }
 178   } else {
 179     // Since this array dimension has zero length, nothing will be
 180     // allocated, however the lower dimension values must be checked
 181     // for illegal values.
 182     for (int i = 0; i < rank - 1; ++i) {
 183       sizes += 1;
 184       if (*sizes < 0) {
 185         THROW_MSG_0(vmSymbols::java_lang_NegativeArraySizeException(), err_msg("%d", *sizes));
 186       }
 187     }
 188   }

 189   return h_array();
 190 }
 191 
 192 // Either oop or narrowOop depending on UseCompressedOops.
 193 void ObjArrayKlass::do_copy(arrayOop s, size_t src_offset,
 194                             arrayOop d, size_t dst_offset, int length, TRAPS) {
 195   if (oopDesc::equals(s, d)) {
 196     // since source and destination are equal we do not need conversion checks.
 197     assert(length > 0, "sanity check");
 198     ArrayAccess<>::oop_arraycopy(s, src_offset, d, dst_offset, length);
 199   } else {
 200     // We have to make sure all elements conform to the destination array
 201     Klass* bound = ObjArrayKlass::cast(d->klass())->element_klass();
 202     Klass* stype = ObjArrayKlass::cast(s->klass())->element_klass();
 203     if (stype == bound || stype->is_subtype_of(bound)) {
 204       // elements are guaranteed to be subtypes, so no check necessary
 205       ArrayAccess<ARRAYCOPY_DISJOINT>::oop_arraycopy(s, src_offset, d, dst_offset, length);
 206     } else {
 207       // slow case: need individual subtype checks
 208       // note: don't use obj_at_put below because it includes a redundant store check


 212         if (!bound->is_subtype_of(stype)) {
 213           ss.print("arraycopy: type mismatch: can not copy %s[] into %s[]",
 214                    stype->external_name(), bound->external_name());
 215         } else {
 216           // oop_arraycopy should return the index in the source array that
 217           // contains the problematic oop.
 218           ss.print("arraycopy: element type mismatch: can not cast one of the elements"
 219                    " of %s[] to the type of the destination array, %s",
 220                    stype->external_name(), bound->external_name());
 221         }
 222         THROW_MSG(vmSymbols::java_lang_ArrayStoreException(), ss.as_string());
 223       }
 224     }
 225   }
 226 }
 227 
 228 void ObjArrayKlass::copy_array(arrayOop s, int src_pos, arrayOop d,
 229                                int dst_pos, int length, TRAPS) {
 230   assert(s->is_objArray(), "must be obj array");
 231 
 232   if (EnableValhalla) {
 233     if (d->is_valueArray()) {
 234       ValueArrayKlass::cast(d->klass())->copy_array(s, src_pos, d, dst_pos, length, THREAD);
 235       return;
 236     }
 237   }
 238 
 239   if (!d->is_objArray()) {
 240     ResourceMark rm(THREAD);
 241     stringStream ss;
 242     if (d->is_typeArray()) {
 243       ss.print("arraycopy: type mismatch: can not copy object array[] into %s[]",
 244                type2name_tab[ArrayKlass::cast(d->klass())->element_type()]);
 245     } else {
 246       ss.print("arraycopy: destination type %s is not an array", d->klass()->external_name());
 247     }
 248     THROW_MSG(vmSymbols::java_lang_ArrayStoreException(), ss.as_string());
 249   }
 250 
 251   // Check is all offsets and lengths are non negative
 252   if (src_pos < 0 || dst_pos < 0 || length < 0) {
 253     // Pass specific exception reason.
 254     ResourceMark rm(THREAD);
 255     stringStream ss;
 256     if (src_pos < 0) {
 257       ss.print("arraycopy: source index %d out of bounds for object array[%d]",
 258                src_pos, s->length());


 270     // Pass specific exception reason.
 271     ResourceMark rm(THREAD);
 272     stringStream ss;
 273     if (((unsigned int) length + (unsigned int) src_pos) > (unsigned int) s->length()) {
 274       ss.print("arraycopy: last source index %u out of bounds for object array[%d]",
 275                (unsigned int) length + (unsigned int) src_pos, s->length());
 276     } else {
 277       ss.print("arraycopy: last destination index %u out of bounds for object array[%d]",
 278                (unsigned int) length + (unsigned int) dst_pos, d->length());
 279     }
 280     THROW_MSG(vmSymbols::java_lang_ArrayIndexOutOfBoundsException(), ss.as_string());
 281   }
 282 
 283   // Special case. Boundary cases must be checked first
 284   // This allows the following call: copy_array(s, s.length(), d.length(), 0).
 285   // This is correct, since the position is supposed to be an 'in between point', i.e., s.length(),
 286   // points to the right of the last element.
 287   if (length==0) {
 288     return;
 289   }
 290   if (EnableValhalla && ArrayKlass::cast(d->klass())->element_klass()->is_value()) {
 291     assert(d->is_objArray(), "Expected objArray");
 292     ValueKlass* d_elem_vklass = ValueKlass::cast(ArrayKlass::cast(d->klass())->element_klass());
 293     objArrayOop da = objArrayOop(d);
 294     objArrayOop sa = objArrayOop(s);
 295     int src_end = src_pos + length;
 296     while (src_pos < src_end) {
 297       oop se = sa->obj_at(src_pos);
 298       if (se == NULL) {
 299         THROW(vmSymbols::java_lang_NullPointerException());
 300       }
 301       // Check exact type per element
 302       if (se->klass() != d_elem_vklass) {
 303         THROW(vmSymbols::java_lang_ArrayStoreException());
 304       }
 305       da->obj_at_put(dst_pos, se);  // TODO: review with ValueArrayKlass::copy_array and Access API
 306       dst_pos++;
 307       src_pos++;
 308     }
 309   } else if (UseCompressedOops) {
 310     size_t src_offset = (size_t) objArrayOopDesc::obj_at_offset<narrowOop>(src_pos);
 311     size_t dst_offset = (size_t) objArrayOopDesc::obj_at_offset<narrowOop>(dst_pos);
 312     assert(arrayOopDesc::obj_offset_to_raw<narrowOop>(s, src_offset, NULL) ==
 313            objArrayOop(s)->obj_at_addr_raw<narrowOop>(src_pos), "sanity");
 314     assert(arrayOopDesc::obj_offset_to_raw<narrowOop>(d, dst_offset, NULL) ==
 315            objArrayOop(d)->obj_at_addr_raw<narrowOop>(dst_pos), "sanity");
 316     do_copy(s, src_offset, d, dst_offset, length, CHECK);
 317   } else {
 318     size_t src_offset = (size_t) objArrayOopDesc::obj_at_offset<oop>(src_pos);
 319     size_t dst_offset = (size_t) objArrayOopDesc::obj_at_offset<oop>(dst_pos);
 320     assert(arrayOopDesc::obj_offset_to_raw<oop>(s, src_offset, NULL) ==
 321            objArrayOop(s)->obj_at_addr_raw<oop>(src_pos), "sanity");
 322     assert(arrayOopDesc::obj_offset_to_raw<oop>(d, dst_offset, NULL) ==
 323            objArrayOop(d)->obj_at_addr_raw<oop>(dst_pos), "sanity");
 324     do_copy(s, src_offset, d, dst_offset, length, CHECK);
 325   }
 326 }
 327 
 328 
 329 Klass* ObjArrayKlass::array_klass_impl(bool or_null, int n, TRAPS) {


 427   return (element_flags & (JVM_ACC_PUBLIC | JVM_ACC_PRIVATE | JVM_ACC_PROTECTED))
 428                         | (JVM_ACC_ABSTRACT | JVM_ACC_FINAL);
 429 }
 430 
 431 ModuleEntry* ObjArrayKlass::module() const {
 432   assert(bottom_klass() != NULL, "ObjArrayKlass returned unexpected NULL bottom_klass");
 433   // The array is defined in the module of its bottom class
 434   return bottom_klass()->module();
 435 }
 436 
 437 PackageEntry* ObjArrayKlass::package() const {
 438   assert(bottom_klass() != NULL, "ObjArrayKlass returned unexpected NULL bottom_klass");
 439   return bottom_klass()->package();
 440 }
 441 
 442 // Printing
 443 
 444 void ObjArrayKlass::print_on(outputStream* st) const {
 445 #ifndef PRODUCT
 446   Klass::print_on(st);
 447   st->print(" - element klass: ");
 448   element_klass()->print_value_on(st);
 449   st->cr();
 450 #endif //PRODUCT
 451 }
 452 
 453 void ObjArrayKlass::print_value_on(outputStream* st) const {
 454   assert(is_klass(), "must be klass");
 455 
 456   element_klass()->print_value_on(st);
 457   st->print("[]");
 458 }
 459 
 460 #ifndef PRODUCT
 461 
 462 void ObjArrayKlass::oop_print_on(oop obj, outputStream* st) {
 463   ArrayKlass::oop_print_on(obj, st);
 464   assert(obj->is_objArray(), "must be objArray");
 465   objArrayOop oa = objArrayOop(obj);
 466   int print_len = MIN2((intx) oa->length(), MaxElementPrintSize);
 467   for(int index = 0; index < print_len; index++) {


 489   st->print("[%d] ", len);
 490   if (obj != NULL) {
 491     obj->print_address_on(st);
 492   } else {
 493     st->print_cr("NULL");
 494   }
 495 }
 496 
 497 const char* ObjArrayKlass::internal_name() const {
 498   return external_name();
 499 }
 500 
 501 
 502 // Verification
 503 
 504 void ObjArrayKlass::verify_on(outputStream* st) {
 505   ArrayKlass::verify_on(st);
 506   guarantee(element_klass()->is_klass(), "should be klass");
 507   guarantee(bottom_klass()->is_klass(), "should be klass");
 508   Klass* bk = bottom_klass();
 509   guarantee(bk->is_instance_klass() || bk->is_typeArray_klass() || bk->is_valueArray_klass(),
 510             "invalid bottom klass");
 511 }
 512 
 513 void ObjArrayKlass::oop_verify_on(oop obj, outputStream* st) {
 514   ArrayKlass::oop_verify_on(obj, st);
 515   guarantee(obj->is_objArray(), "must be objArray");
 516   objArrayOop oa = objArrayOop(obj);
 517   for(int index = 0; index < oa->length(); index++) {
 518     guarantee(oopDesc::is_oop_or_null(oa->obj_at(index)), "should be oop");
 519   }
 520 }
< prev index next >