src/share/vm/oops/objArrayKlass.cpp

Thu, 13 Mar 2008 14:17:48 -0700

author
dcubed
date
Thu, 13 Mar 2008 14:17:48 -0700
changeset 487
75b0f3cb1943
parent 435
a61af66fc99e
child 548
ba764ed4b6f2
permissions
-rw-r--r--

Merge

     1 /*
     2  * Copyright 1997-2007 Sun Microsystems, Inc.  All Rights Reserved.
     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  *
    19  * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
    20  * CA 95054 USA or visit www.sun.com if you need additional information or
    21  * have any questions.
    22  *
    23  */
    25 # include "incls/_precompiled.incl"
    26 # include "incls/_objArrayKlass.cpp.incl"
    28 int objArrayKlass::oop_size(oop obj) const {
    29   assert(obj->is_objArray(), "must be object array");
    30   return objArrayOop(obj)->object_size();
    31 }
    33 objArrayOop objArrayKlass::allocate(int length, TRAPS) {
    34   if (length >= 0) {
    35     if (length <= arrayOopDesc::max_array_length(T_OBJECT)) {
    36       int size = objArrayOopDesc::object_size(length);
    37       KlassHandle h_k(THREAD, as_klassOop());
    38       objArrayOop a = (objArrayOop)CollectedHeap::array_allocate(h_k, size, length, CHECK_NULL);
    39       assert(a->is_parsable(), "Can't publish unless parsable");
    40       return a;
    41     } else {
    42       THROW_OOP_0(Universe::out_of_memory_error_array_size());
    43     }
    44   } else {
    45     THROW_0(vmSymbols::java_lang_NegativeArraySizeException());
    46   }
    47 }
    49 static int multi_alloc_counter = 0;
    51 oop objArrayKlass::multi_allocate(int rank, jint* sizes, TRAPS) {
    52   int length = *sizes;
    53   // Call to lower_dimension uses this pointer, so most be called before a
    54   // possible GC
    55   KlassHandle h_lower_dimension(THREAD, lower_dimension());
    56   // If length < 0 allocate will throw an exception.
    57   objArrayOop array = allocate(length, CHECK_NULL);
    58   assert(array->is_parsable(), "Don't handlize unless parsable");
    59   objArrayHandle h_array (THREAD, array);
    60   if (rank > 1) {
    61     if (length != 0) {
    62       for (int index = 0; index < length; index++) {
    63         arrayKlass* ak = arrayKlass::cast(h_lower_dimension());
    64         oop sub_array = ak->multi_allocate(rank-1, &sizes[1], CHECK_NULL);
    65         assert(sub_array->is_parsable(), "Don't publish until parsable");
    66         h_array->obj_at_put(index, sub_array);
    67       }
    68     } else {
    69       // Since this array dimension has zero length, nothing will be
    70       // allocated, however the lower dimension values must be checked
    71       // for illegal values.
    72       for (int i = 0; i < rank - 1; ++i) {
    73         sizes += 1;
    74         if (*sizes < 0) {
    75           THROW_0(vmSymbols::java_lang_NegativeArraySizeException());
    76         }
    77       }
    78     }
    79   }
    80   return h_array();
    81 }
    83 void objArrayKlass::copy_array(arrayOop s, int src_pos, arrayOop d,
    84                                int dst_pos, int length, TRAPS) {
    85   assert(s->is_objArray(), "must be obj array");
    87   if (!d->is_objArray()) {
    88     THROW(vmSymbols::java_lang_ArrayStoreException());
    89   }
    91   // Check is all offsets and lengths are non negative
    92   if (src_pos < 0 || dst_pos < 0 || length < 0) {
    93     THROW(vmSymbols::java_lang_ArrayIndexOutOfBoundsException());
    94   }
    95   // Check if the ranges are valid
    96   if  ( (((unsigned int) length + (unsigned int) src_pos) > (unsigned int) s->length())
    97      || (((unsigned int) length + (unsigned int) dst_pos) > (unsigned int) d->length()) ) {
    98     THROW(vmSymbols::java_lang_ArrayIndexOutOfBoundsException());
    99   }
   101   // Special case. Boundary cases must be checked first
   102   // This allows the following call: copy_array(s, s.length(), d.length(), 0).
   103   // This is correct, since the position is supposed to be an 'in between point', i.e., s.length(),
   104   // points to the right of the last element.
   105   if (length==0) {
   106     return;
   107   }
   109   oop* const src = objArrayOop(s)->obj_at_addr(src_pos);
   110   oop* const dst = objArrayOop(d)->obj_at_addr(dst_pos);
   111   const size_t word_len = length * HeapWordsPerOop;
   113   // For performance reasons, we assume we are using a card marking write
   114   // barrier. The assert will fail if this is not the case.
   115   BarrierSet* bs = Universe::heap()->barrier_set();
   116   assert(bs->has_write_ref_array_opt(), "Barrier set must have ref array opt");
   118   if (s == d) {
   119     // since source and destination are equal we do not need conversion checks.
   120     assert(length > 0, "sanity check");
   121     Copy::conjoint_oops_atomic(src, dst, length);
   122   } else {
   123     // We have to make sure all elements conform to the destination array
   124     klassOop bound = objArrayKlass::cast(d->klass())->element_klass();
   125     klassOop stype = objArrayKlass::cast(s->klass())->element_klass();
   126     if (stype == bound || Klass::cast(stype)->is_subtype_of(bound)) {
   127       // elements are guaranteed to be subtypes, so no check necessary
   128       Copy::conjoint_oops_atomic(src, dst, length);
   129     } else {
   130       // slow case: need individual subtype checks
   131       // note: don't use obj_at_put below because it includes a redundant store check
   132       oop* from = src;
   133       oop* end = from + length;
   134       for (oop* p = dst; from < end; from++, p++) {
   135         oop element = *from;
   136         if (element == NULL || Klass::cast(element->klass())->is_subtype_of(bound)) {
   137           *p = element;
   138         } else {
   139           // We must do a barrier to cover the partial copy.
   140           const size_t done_word_len = pointer_delta(p, dst, oopSize) *
   141                                        HeapWordsPerOop;
   142           bs->write_ref_array(MemRegion((HeapWord*)dst, done_word_len));
   143           THROW(vmSymbols::java_lang_ArrayStoreException());
   144           return;
   145         }
   146       }
   147     }
   148   }
   149   bs->write_ref_array(MemRegion((HeapWord*)dst, word_len));
   150 }
   153 klassOop objArrayKlass::array_klass_impl(bool or_null, int n, TRAPS) {
   154   objArrayKlassHandle h_this(THREAD, as_klassOop());
   155   return array_klass_impl(h_this, or_null, n, CHECK_NULL);
   156 }
   159 klassOop objArrayKlass::array_klass_impl(objArrayKlassHandle this_oop, bool or_null, int n, TRAPS) {
   161   assert(this_oop->dimension() <= n, "check order of chain");
   162   int dimension = this_oop->dimension();
   163   if (dimension == n)
   164     return this_oop();
   166   objArrayKlassHandle ak (THREAD, this_oop->higher_dimension());
   167   if (ak.is_null()) {
   168     if (or_null)  return NULL;
   170     ResourceMark rm;
   171     JavaThread *jt = (JavaThread *)THREAD;
   172     {
   173       MutexLocker mc(Compile_lock, THREAD);   // for vtables
   174       // Ensure atomic creation of higher dimensions
   175       MutexLocker mu(MultiArray_lock, THREAD);
   177       // Check if another thread beat us
   178       ak = objArrayKlassHandle(THREAD, this_oop->higher_dimension());
   179       if( ak.is_null() ) {
   181         // Create multi-dim klass object and link them together
   182         klassOop new_klass =
   183           objArrayKlassKlass::cast(Universe::objArrayKlassKlassObj())->
   184           allocate_objArray_klass(dimension + 1, this_oop, CHECK_NULL);
   185         ak = objArrayKlassHandle(THREAD, new_klass);
   186         this_oop->set_higher_dimension(ak());
   187         ak->set_lower_dimension(this_oop());
   188         assert(ak->oop_is_objArray(), "incorrect initialization of objArrayKlass");
   189       }
   190     }
   191   } else {
   192     CHECK_UNHANDLED_OOPS_ONLY(Thread::current()->clear_unhandled_oops());
   193   }
   195   if (or_null) {
   196     return ak->array_klass_or_null(n);
   197   }
   198   return ak->array_klass(n, CHECK_NULL);
   199 }
   201 klassOop objArrayKlass::array_klass_impl(bool or_null, TRAPS) {
   202   return array_klass_impl(or_null, dimension() +  1, CHECK_NULL);
   203 }
   205 bool objArrayKlass::can_be_primary_super_slow() const {
   206   if (!bottom_klass()->klass_part()->can_be_primary_super())
   207     // array of interfaces
   208     return false;
   209   else
   210     return Klass::can_be_primary_super_slow();
   211 }
   213 objArrayOop objArrayKlass::compute_secondary_supers(int num_extra_slots, TRAPS) {
   214   // interfaces = { cloneable_klass, serializable_klass, elemSuper[], ... };
   215   objArrayOop es = Klass::cast(element_klass())->secondary_supers();
   216   objArrayHandle elem_supers (THREAD, es);
   217   int num_elem_supers = elem_supers.is_null() ? 0 : elem_supers->length();
   218   int num_secondaries = num_extra_slots + 2 + num_elem_supers;
   219   if (num_secondaries == 2) {
   220     // Must share this for correct bootstrapping!
   221     return Universe::the_array_interfaces_array();
   222   } else {
   223     objArrayOop sec_oop = oopFactory::new_system_objArray(num_secondaries, CHECK_NULL);
   224     objArrayHandle secondaries(THREAD, sec_oop);
   225     secondaries->obj_at_put(num_extra_slots+0, SystemDictionary::cloneable_klass());
   226     secondaries->obj_at_put(num_extra_slots+1, SystemDictionary::serializable_klass());
   227     for (int i = 0; i < num_elem_supers; i++) {
   228       klassOop elem_super = (klassOop) elem_supers->obj_at(i);
   229       klassOop array_super = elem_super->klass_part()->array_klass_or_null();
   230       assert(array_super != NULL, "must already have been created");
   231       secondaries->obj_at_put(num_extra_slots+2+i, array_super);
   232     }
   233     return secondaries();
   234   }
   235 }
   237 bool objArrayKlass::compute_is_subtype_of(klassOop k) {
   238   if (!k->klass_part()->oop_is_objArray())
   239     return arrayKlass::compute_is_subtype_of(k);
   241   objArrayKlass* oak = objArrayKlass::cast(k);
   242   return element_klass()->klass_part()->is_subtype_of(oak->element_klass());
   243 }
   246 void objArrayKlass::initialize(TRAPS) {
   247   Klass::cast(bottom_klass())->initialize(THREAD);  // dispatches to either instanceKlass or typeArrayKlass
   248 }
   251 void objArrayKlass::oop_follow_contents(oop obj) {
   252   assert (obj->is_array(), "obj must be array");
   253   arrayOop a = arrayOop(obj);
   254   a->follow_header();
   255   oop* base      = (oop*)a->base(T_OBJECT);
   256   oop* const end = base + a->length();
   257   while (base < end) {
   258     if (*base != NULL)
   259       // we call mark_and_follow here to avoid excessive marking stack usage
   260       MarkSweep::mark_and_follow(base);
   261     base++;
   262   }
   263 }
   265 #ifndef SERIALGC
   266 void objArrayKlass::oop_follow_contents(ParCompactionManager* cm,
   267                                         oop obj) {
   268   assert (obj->is_array(), "obj must be array");
   269   arrayOop a = arrayOop(obj);
   270   a->follow_header(cm);
   271   oop* base      = (oop*)a->base(T_OBJECT);
   272   oop* const end = base + a->length();
   273   while (base < end) {
   274     if (*base != NULL)
   275       // we call mark_and_follow here to avoid excessive marking stack usage
   276       PSParallelCompact::mark_and_follow(cm, base);
   277     base++;
   278   }
   279 }
   280 #endif // SERIALGC
   282 #define invoke_closure_on(base, closure, nv_suffix) {                                  \
   283   if (*(base) != NULL) {                                                               \
   284     (closure)->do_oop##nv_suffix(base);                                                \
   285   }                                                                                    \
   286 }
   288 #define ObjArrayKlass_OOP_OOP_ITERATE_DEFN(OopClosureType, nv_suffix)           \
   289                                                                                 \
   290 int objArrayKlass::oop_oop_iterate##nv_suffix(oop obj,                          \
   291                                               OopClosureType* closure) {        \
   292   SpecializationStats::record_iterate_call##nv_suffix(SpecializationStats::oa); \
   293   assert (obj->is_array(), "obj must be array");                                \
   294   objArrayOop a = objArrayOop(obj);                                             \
   295   /* Get size before changing pointers. */                                      \
   296   /* Don't call size() or oop_size() since that is a virtual call. */           \
   297   int size = a->object_size();                                                  \
   298   if (closure->do_header()) {                                                   \
   299     a->oop_iterate_header(closure);                                             \
   300   }                                                                             \
   301   oop* base               = a->base();                                          \
   302   oop* const end          = base + a->length();                                 \
   303   const intx field_offset = PrefetchFieldsAhead;                                \
   304   if (field_offset > 0) {                                                       \
   305     while (base < end) {                                                        \
   306       prefetch_beyond(base, end, field_offset, closure->prefetch_style());      \
   307       invoke_closure_on(base, closure, nv_suffix);                              \
   308       base++;                                                                   \
   309     }                                                                           \
   310   } else {                                                                      \
   311     while (base < end) {                                                        \
   312       invoke_closure_on(base, closure, nv_suffix);                              \
   313       base++;                                                                   \
   314     }                                                                           \
   315   }                                                                             \
   316   return size;                                                                  \
   317 }
   319 #define ObjArrayKlass_OOP_OOP_ITERATE_DEFN_m(OopClosureType, nv_suffix)         \
   320                                                                                 \
   321 int objArrayKlass::oop_oop_iterate##nv_suffix##_m(oop obj,                      \
   322                                                   OopClosureType* closure,      \
   323                                                   MemRegion mr) {               \
   324   SpecializationStats::record_iterate_call##nv_suffix(SpecializationStats::oa); \
   325   assert(obj->is_array(), "obj must be array");                                 \
   326   objArrayOop a  = objArrayOop(obj);                                            \
   327   /* Get size before changing pointers. */                                      \
   328   /* Don't call size() or oop_size() since that is a virtual call */            \
   329   int size = a->object_size();                                                  \
   330   if (closure->do_header()) {                                                   \
   331     a->oop_iterate_header(closure, mr);                                         \
   332   }                                                                             \
   333   oop* bottom = (oop*)mr.start();                                               \
   334   oop* top    = (oop*)mr.end();                                                 \
   335   oop* base = a->base();                                                        \
   336   oop* end    = base + a->length();                                             \
   337   if (base < bottom) {                                                          \
   338     base = bottom;                                                              \
   339   }                                                                             \
   340   if (end > top) {                                                              \
   341     end = top;                                                                  \
   342   }                                                                             \
   343   const intx field_offset = PrefetchFieldsAhead;                                \
   344   if (field_offset > 0) {                                                       \
   345     while (base < end) {                                                        \
   346       prefetch_beyond(base, end, field_offset, closure->prefetch_style());      \
   347       invoke_closure_on(base, closure, nv_suffix);                              \
   348       base++;                                                                   \
   349     }                                                                           \
   350   } else {                                                                      \
   351     while (base < end) {                                                        \
   352       invoke_closure_on(base, closure, nv_suffix);                              \
   353       base++;                                                                   \
   354     }                                                                           \
   355   }                                                                             \
   356   return size;                                                                  \
   357 }
   359 ALL_OOP_OOP_ITERATE_CLOSURES_1(ObjArrayKlass_OOP_OOP_ITERATE_DEFN)
   360 ALL_OOP_OOP_ITERATE_CLOSURES_3(ObjArrayKlass_OOP_OOP_ITERATE_DEFN)
   361 ALL_OOP_OOP_ITERATE_CLOSURES_1(ObjArrayKlass_OOP_OOP_ITERATE_DEFN_m)
   362 ALL_OOP_OOP_ITERATE_CLOSURES_3(ObjArrayKlass_OOP_OOP_ITERATE_DEFN_m)
   364 int objArrayKlass::oop_adjust_pointers(oop obj) {
   365   assert(obj->is_objArray(), "obj must be obj array");
   366   objArrayOop a = objArrayOop(obj);
   367   // Get size before changing pointers.
   368   // Don't call size() or oop_size() since that is a virtual call.
   369   int size = a->object_size();
   370   a->adjust_header();
   371   oop* base      = a->base();
   372   oop* const end = base + a->length();
   373   while (base < end) {
   374     MarkSweep::adjust_pointer(base);
   375     base++;
   376   }
   377   return size;
   378 }
   380 #ifndef SERIALGC
   381 void objArrayKlass::oop_copy_contents(PSPromotionManager* pm, oop obj) {
   382   assert(!pm->depth_first(), "invariant");
   383   assert(obj->is_objArray(), "obj must be obj array");
   384   // Compute oop range
   385   oop* curr = objArrayOop(obj)->base();
   386   oop* end = curr + objArrayOop(obj)->length();
   387   //  assert(align_object_size(end - (oop*)obj) == oop_size(obj), "checking size");
   388   assert(align_object_size(pointer_delta(end, obj, sizeof(oop*)))
   389                                   == oop_size(obj), "checking size");
   391   // Iterate over oops
   392   while (curr < end) {
   393     if (PSScavenge::should_scavenge(*curr)) {
   394       pm->claim_or_forward_breadth(curr);
   395     }
   396     ++curr;
   397   }
   398 }
   400 void objArrayKlass::oop_push_contents(PSPromotionManager* pm, oop obj) {
   401   assert(pm->depth_first(), "invariant");
   402   assert(obj->is_objArray(), "obj must be obj array");
   403   // Compute oop range
   404   oop* curr = objArrayOop(obj)->base();
   405   oop* end = curr + objArrayOop(obj)->length();
   406   //  assert(align_object_size(end - (oop*)obj) == oop_size(obj), "checking size");
   407   assert(align_object_size(pointer_delta(end, obj, sizeof(oop*)))
   408                                   == oop_size(obj), "checking size");
   410   // Iterate over oops
   411   while (curr < end) {
   412     if (PSScavenge::should_scavenge(*curr)) {
   413       pm->claim_or_forward_depth(curr);
   414     }
   415     ++curr;
   416   }
   417 }
   419 int objArrayKlass::oop_update_pointers(ParCompactionManager* cm, oop obj) {
   420   assert (obj->is_objArray(), "obj must be obj array");
   421   objArrayOop a = objArrayOop(obj);
   423   oop* const base = a->base();
   424   oop* const beg_oop = base;
   425   oop* const end_oop = base + a->length();
   426   for (oop* cur_oop = beg_oop; cur_oop < end_oop; ++cur_oop) {
   427     PSParallelCompact::adjust_pointer(cur_oop);
   428   }
   429   return a->object_size();
   430 }
   432 int objArrayKlass::oop_update_pointers(ParCompactionManager* cm, oop obj,
   433                                        HeapWord* beg_addr, HeapWord* end_addr) {
   434   assert (obj->is_objArray(), "obj must be obj array");
   435   objArrayOop a = objArrayOop(obj);
   437   oop* const base = a->base();
   438   oop* const beg_oop = MAX2((oop*)beg_addr, base);
   439   oop* const end_oop = MIN2((oop*)end_addr, base + a->length());
   440   for (oop* cur_oop = beg_oop; cur_oop < end_oop; ++cur_oop) {
   441     PSParallelCompact::adjust_pointer(cur_oop);
   442   }
   443   return a->object_size();
   444 }
   445 #endif // SERIALGC
   447 // JVM support
   449 jint objArrayKlass::compute_modifier_flags(TRAPS) const {
   450   // The modifier for an objectArray is the same as its element
   451   if (element_klass() == NULL) {
   452     assert(Universe::is_bootstrapping(), "partial objArray only at startup");
   453     return JVM_ACC_ABSTRACT | JVM_ACC_FINAL | JVM_ACC_PUBLIC;
   454   }
   455   // Recurse down the element list
   456   jint element_flags = Klass::cast(element_klass())->compute_modifier_flags(CHECK_0);
   458   return (element_flags & (JVM_ACC_PUBLIC | JVM_ACC_PRIVATE | JVM_ACC_PROTECTED))
   459                         | (JVM_ACC_ABSTRACT | JVM_ACC_FINAL);
   460 }
   463 #ifndef PRODUCT
   464 // Printing
   466 void objArrayKlass::oop_print_on(oop obj, outputStream* st) {
   467   arrayKlass::oop_print_on(obj, st);
   468   assert(obj->is_objArray(), "must be objArray");
   469   objArrayOop oa = objArrayOop(obj);
   470   int print_len = MIN2((intx) oa->length(), MaxElementPrintSize);
   471   for(int index = 0; index < print_len; index++) {
   472     st->print(" - %3d : ", index);
   473     oa->obj_at(index)->print_value_on(st);
   474     st->cr();
   475   }
   476   int remaining = oa->length() - print_len;
   477   if (remaining > 0) {
   478     tty->print_cr(" - <%d more elements, increase MaxElementPrintSize to print>", remaining);
   479   }
   480 }
   483 void objArrayKlass::oop_print_value_on(oop obj, outputStream* st) {
   484   assert(obj->is_objArray(), "must be objArray");
   485   element_klass()->print_value_on(st);
   486   st->print("a [%d] ", objArrayOop(obj)->length());
   487   as_klassOop()->klass()->print_value_on(st);
   488 }
   490 #endif // PRODUCT
   492 const char* objArrayKlass::internal_name() const {
   493   return external_name();
   494 }
   496 // Verification
   498 void objArrayKlass::oop_verify_on(oop obj, outputStream* st) {
   499   arrayKlass::oop_verify_on(obj, st);
   500   guarantee(obj->is_objArray(), "must be objArray");
   501   objArrayOop oa = objArrayOop(obj);
   502   for(int index = 0; index < oa->length(); index++) {
   503     guarantee(oa->obj_at(index)->is_oop_or_null(), "should be oop");
   504   }
   505 }
   507 void objArrayKlass::oop_verify_old_oop(oop obj, oop* p, bool allow_dirty) {
   508   /* $$$ move into remembered set verification?
   509   RememberedSet::verify_old_oop(obj, p, allow_dirty, true);
   510   */
   511 }

mercurial