objArrayKlass.cpp revision 196:d1605aabd0a1
1/*
2 * Copyright 1997-2008 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 */
24
25# include "incls/_precompiled.incl"
26# include "incls/_objArrayKlass.cpp.incl"
27
28int objArrayKlass::oop_size(oop obj) const {
29  assert(obj->is_objArray(), "must be object array");
30  return objArrayOop(obj)->object_size();
31}
32
33objArrayOop 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}
48
49static int multi_alloc_counter = 0;
50
51oop 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}
82
83// Either oop or narrowOop depending on UseCompressedOops.
84template <class T> void objArrayKlass::do_copy(arrayOop s, T* src,
85                               arrayOop d, T* dst, int length, TRAPS) {
86
87  const size_t word_len = objArrayOopDesc::array_size(length);
88
89  // For performance reasons, we assume we are using a card marking write
90  // barrier. The assert will fail if this is not the case.
91  BarrierSet* bs = Universe::heap()->barrier_set();
92  assert(bs->has_write_ref_array_opt(), "Barrier set must have ref array opt");
93
94  if (s == d) {
95    // since source and destination are equal we do not need conversion checks.
96    assert(length > 0, "sanity check");
97    Copy::conjoint_oops_atomic(src, dst, length);
98  } else {
99    // We have to make sure all elements conform to the destination array
100    klassOop bound = objArrayKlass::cast(d->klass())->element_klass();
101    klassOop stype = objArrayKlass::cast(s->klass())->element_klass();
102    if (stype == bound || Klass::cast(stype)->is_subtype_of(bound)) {
103      // elements are guaranteed to be subtypes, so no check necessary
104      Copy::conjoint_oops_atomic(src, dst, length);
105    } else {
106      // slow case: need individual subtype checks
107      // note: don't use obj_at_put below because it includes a redundant store check
108      T* from = src;
109      T* end = from + length;
110      for (T* p = dst; from < end; from++, p++) {
111        // XXX this is going to be slow.
112        T element = *from;
113        if (oopDesc::is_null(element) ||
114            Klass::cast(oopDesc::decode_heap_oop_not_null(element)->klass())->is_subtype_of(bound)) {
115          *p = *from;
116        } else {
117          // We must do a barrier to cover the partial copy.
118          const size_t pd = pointer_delta(p, dst, (size_t)heapOopSize);
119          // pointer delta is scaled to number of elements (length field in
120          // objArrayOop) which we assume is 32 bit.
121          assert(pd == (size_t)(int)pd, "length field overflow");
122          const size_t done_word_len = objArrayOopDesc::array_size((int)pd);
123          bs->write_ref_array(MemRegion((HeapWord*)dst, done_word_len));
124          THROW(vmSymbols::java_lang_ArrayStoreException());
125          return;
126        }
127      }
128    }
129  }
130  bs->write_ref_array(MemRegion((HeapWord*)dst, word_len));
131}
132
133void objArrayKlass::copy_array(arrayOop s, int src_pos, arrayOop d,
134                               int dst_pos, int length, TRAPS) {
135  assert(s->is_objArray(), "must be obj array");
136
137  if (!d->is_objArray()) {
138    THROW(vmSymbols::java_lang_ArrayStoreException());
139  }
140
141  // Check is all offsets and lengths are non negative
142  if (src_pos < 0 || dst_pos < 0 || length < 0) {
143    THROW(vmSymbols::java_lang_ArrayIndexOutOfBoundsException());
144  }
145  // Check if the ranges are valid
146  if  ( (((unsigned int) length + (unsigned int) src_pos) > (unsigned int) s->length())
147     || (((unsigned int) length + (unsigned int) dst_pos) > (unsigned int) d->length()) ) {
148    THROW(vmSymbols::java_lang_ArrayIndexOutOfBoundsException());
149  }
150
151  // Special case. Boundary cases must be checked first
152  // This allows the following call: copy_array(s, s.length(), d.length(), 0).
153  // This is correct, since the position is supposed to be an 'in between point', i.e., s.length(),
154  // points to the right of the last element.
155  if (length==0) {
156    return;
157  }
158  if (UseCompressedOops) {
159    narrowOop* const src = objArrayOop(s)->obj_at_addr<narrowOop>(src_pos);
160    narrowOop* const dst = objArrayOop(d)->obj_at_addr<narrowOop>(dst_pos);
161    do_copy<narrowOop>(s, src, d, dst, length, CHECK);
162  } else {
163    oop* const src = objArrayOop(s)->obj_at_addr<oop>(src_pos);
164    oop* const dst = objArrayOop(d)->obj_at_addr<oop>(dst_pos);
165    do_copy<oop> (s, src, d, dst, length, CHECK);
166  }
167}
168
169
170klassOop objArrayKlass::array_klass_impl(bool or_null, int n, TRAPS) {
171  objArrayKlassHandle h_this(THREAD, as_klassOop());
172  return array_klass_impl(h_this, or_null, n, CHECK_NULL);
173}
174
175
176klassOop objArrayKlass::array_klass_impl(objArrayKlassHandle this_oop, bool or_null, int n, TRAPS) {
177
178  assert(this_oop->dimension() <= n, "check order of chain");
179  int dimension = this_oop->dimension();
180  if (dimension == n)
181    return this_oop();
182
183  objArrayKlassHandle ak (THREAD, this_oop->higher_dimension());
184  if (ak.is_null()) {
185    if (or_null)  return NULL;
186
187    ResourceMark rm;
188    JavaThread *jt = (JavaThread *)THREAD;
189    {
190      MutexLocker mc(Compile_lock, THREAD);   // for vtables
191      // Ensure atomic creation of higher dimensions
192      MutexLocker mu(MultiArray_lock, THREAD);
193
194      // Check if another thread beat us
195      ak = objArrayKlassHandle(THREAD, this_oop->higher_dimension());
196      if( ak.is_null() ) {
197
198        // Create multi-dim klass object and link them together
199        klassOop new_klass =
200          objArrayKlassKlass::cast(Universe::objArrayKlassKlassObj())->
201          allocate_objArray_klass(dimension + 1, this_oop, CHECK_NULL);
202        ak = objArrayKlassHandle(THREAD, new_klass);
203        this_oop->set_higher_dimension(ak());
204        ak->set_lower_dimension(this_oop());
205        assert(ak->oop_is_objArray(), "incorrect initialization of objArrayKlass");
206      }
207    }
208  } else {
209    CHECK_UNHANDLED_OOPS_ONLY(Thread::current()->clear_unhandled_oops());
210  }
211
212  if (or_null) {
213    return ak->array_klass_or_null(n);
214  }
215  return ak->array_klass(n, CHECK_NULL);
216}
217
218klassOop objArrayKlass::array_klass_impl(bool or_null, TRAPS) {
219  return array_klass_impl(or_null, dimension() +  1, CHECK_NULL);
220}
221
222bool objArrayKlass::can_be_primary_super_slow() const {
223  if (!bottom_klass()->klass_part()->can_be_primary_super())
224    // array of interfaces
225    return false;
226  else
227    return Klass::can_be_primary_super_slow();
228}
229
230objArrayOop objArrayKlass::compute_secondary_supers(int num_extra_slots, TRAPS) {
231  // interfaces = { cloneable_klass, serializable_klass, elemSuper[], ... };
232  objArrayOop es = Klass::cast(element_klass())->secondary_supers();
233  objArrayHandle elem_supers (THREAD, es);
234  int num_elem_supers = elem_supers.is_null() ? 0 : elem_supers->length();
235  int num_secondaries = num_extra_slots + 2 + num_elem_supers;
236  if (num_secondaries == 2) {
237    // Must share this for correct bootstrapping!
238    return Universe::the_array_interfaces_array();
239  } else {
240    objArrayOop sec_oop = oopFactory::new_system_objArray(num_secondaries, CHECK_NULL);
241    objArrayHandle secondaries(THREAD, sec_oop);
242    secondaries->obj_at_put(num_extra_slots+0, SystemDictionary::cloneable_klass());
243    secondaries->obj_at_put(num_extra_slots+1, SystemDictionary::serializable_klass());
244    for (int i = 0; i < num_elem_supers; i++) {
245      klassOop elem_super = (klassOop) elem_supers->obj_at(i);
246      klassOop array_super = elem_super->klass_part()->array_klass_or_null();
247      assert(array_super != NULL, "must already have been created");
248      secondaries->obj_at_put(num_extra_slots+2+i, array_super);
249    }
250    return secondaries();
251  }
252}
253
254bool objArrayKlass::compute_is_subtype_of(klassOop k) {
255  if (!k->klass_part()->oop_is_objArray())
256    return arrayKlass::compute_is_subtype_of(k);
257
258  objArrayKlass* oak = objArrayKlass::cast(k);
259  return element_klass()->klass_part()->is_subtype_of(oak->element_klass());
260}
261
262void objArrayKlass::initialize(TRAPS) {
263  Klass::cast(bottom_klass())->initialize(THREAD);  // dispatches to either instanceKlass or typeArrayKlass
264}
265
266#define ObjArrayKlass_SPECIALIZED_OOP_ITERATE(T, a, p, do_oop) \
267{                                   \
268  T* p         = (T*)(a)->base();   \
269  T* const end = p + (a)->length(); \
270  while (p < end) {                 \
271    do_oop;                         \
272    p++;                            \
273  }                                 \
274}
275
276#define ObjArrayKlass_SPECIALIZED_BOUNDED_OOP_ITERATE(T, a, p, low, high, do_oop) \
277{                                   \
278  T* const l = (T*)(low);           \
279  T* const h = (T*)(high);          \
280  T* p       = (T*)(a)->base();     \
281  T* end     = p + (a)->length();   \
282  if (p < l) p = l;                 \
283  if (end > h) end = h;             \
284  while (p < end) {                 \
285    do_oop;                         \
286    ++p;                            \
287  }                                 \
288}
289
290#define ObjArrayKlass_OOP_ITERATE(a, p, do_oop)      \
291  if (UseCompressedOops) {                           \
292    ObjArrayKlass_SPECIALIZED_OOP_ITERATE(narrowOop, \
293      a, p, do_oop)                                  \
294  } else {                                           \
295    ObjArrayKlass_SPECIALIZED_OOP_ITERATE(oop,       \
296      a, p, do_oop)                                  \
297  }
298
299#define ObjArrayKlass_BOUNDED_OOP_ITERATE(a, p, low, high, do_oop) \
300  if (UseCompressedOops) {                                   \
301    ObjArrayKlass_SPECIALIZED_BOUNDED_OOP_ITERATE(narrowOop, \
302      a, p, low, high, do_oop)                               \
303  } else {                                                   \
304    ObjArrayKlass_SPECIALIZED_BOUNDED_OOP_ITERATE(oop,       \
305      a, p, low, high, do_oop)                               \
306  }
307
308void objArrayKlass::oop_follow_contents(oop obj) {
309  assert (obj->is_array(), "obj must be array");
310  objArrayOop a = objArrayOop(obj);
311  a->follow_header();
312  ObjArrayKlass_OOP_ITERATE( \
313    a, p, \
314    /* we call mark_and_follow here to avoid excessive marking stack usage */ \
315    MarkSweep::mark_and_follow(p))
316}
317
318#ifndef SERIALGC
319void objArrayKlass::oop_follow_contents(ParCompactionManager* cm,
320                                        oop obj) {
321  assert (obj->is_array(), "obj must be array");
322  objArrayOop a = objArrayOop(obj);
323  a->follow_header(cm);
324  ObjArrayKlass_OOP_ITERATE( \
325    a, p, \
326    /* we call mark_and_follow here to avoid excessive marking stack usage */ \
327    PSParallelCompact::mark_and_follow(cm, p))
328}
329#endif // SERIALGC
330
331#define ObjArrayKlass_OOP_OOP_ITERATE_DEFN(OopClosureType, nv_suffix)           \
332                                                                                \
333int objArrayKlass::oop_oop_iterate##nv_suffix(oop obj,                          \
334                                              OopClosureType* closure) {        \
335  SpecializationStats::record_iterate_call##nv_suffix(SpecializationStats::oa); \
336  assert (obj->is_array(), "obj must be array");                                \
337  objArrayOop a = objArrayOop(obj);                                             \
338  /* Get size before changing pointers. */                                      \
339  /* Don't call size() or oop_size() since that is a virtual call. */           \
340  int size = a->object_size();                                                  \
341  if (closure->do_header()) {                                                   \
342    a->oop_iterate_header(closure);                                             \
343  }                                                                             \
344  ObjArrayKlass_OOP_ITERATE(a, p, (closure)->do_oop##nv_suffix(p))              \
345  return size;                                                                  \
346}
347
348#define ObjArrayKlass_OOP_OOP_ITERATE_DEFN_m(OopClosureType, nv_suffix)         \
349                                                                                \
350int objArrayKlass::oop_oop_iterate##nv_suffix##_m(oop obj,                      \
351                                                  OopClosureType* closure,      \
352                                                  MemRegion mr) {               \
353  SpecializationStats::record_iterate_call##nv_suffix(SpecializationStats::oa); \
354  assert(obj->is_array(), "obj must be array");                                 \
355  objArrayOop a  = objArrayOop(obj);                                            \
356  /* Get size before changing pointers. */                                      \
357  /* Don't call size() or oop_size() since that is a virtual call */            \
358  int size = a->object_size();                                                  \
359  if (closure->do_header()) {                                                   \
360    a->oop_iterate_header(closure, mr);                                         \
361  }                                                                             \
362  ObjArrayKlass_BOUNDED_OOP_ITERATE(                                            \
363    a, p, mr.start(), mr.end(), (closure)->do_oop##nv_suffix(p))                \
364  return size;                                                                  \
365}
366
367// Like oop_oop_iterate but only iterates over a specified range and only used
368// for objArrayOops.
369#define ObjArrayKlass_OOP_OOP_ITERATE_DEFN_r(OopClosureType, nv_suffix)         \
370                                                                                \
371int objArrayKlass::oop_oop_iterate_range##nv_suffix(oop obj,                    \
372                                                  OopClosureType* closure,      \
373                                                  int start, int end) {         \
374  SpecializationStats::record_iterate_call##nv_suffix(SpecializationStats::oa); \
375  assert(obj->is_array(), "obj must be array");                                 \
376  objArrayOop a  = objArrayOop(obj);                                            \
377  /* Get size before changing pointers. */                                      \
378  /* Don't call size() or oop_size() since that is a virtual call */            \
379  int size = a->object_size();                                                  \
380  if (UseCompressedOops) {                                                      \
381    HeapWord* low = start == 0 ? (HeapWord*)a : (HeapWord*)a->obj_at_addr<narrowOop>(start);\
382    /* this might be wierd if end needs to be aligned on HeapWord boundary */   \
383    HeapWord* high = (HeapWord*)((narrowOop*)a->base() + end);                  \
384    MemRegion mr(low, high);                                                    \
385    if (closure->do_header()) {                                                 \
386      a->oop_iterate_header(closure, mr);                                       \
387    }                                                                           \
388    ObjArrayKlass_SPECIALIZED_BOUNDED_OOP_ITERATE(narrowOop,                    \
389      a, p, low, high, (closure)->do_oop##nv_suffix(p))                         \
390  } else {                                                                      \
391    HeapWord* low = start == 0 ? (HeapWord*)a : (HeapWord*)a->obj_at_addr<oop>(start);  \
392    HeapWord* high = (HeapWord*)((oop*)a->base() + end);                        \
393    MemRegion mr(low, high);                                                    \
394    if (closure->do_header()) {                                                 \
395      a->oop_iterate_header(closure, mr);                                       \
396    }                                                                           \
397    ObjArrayKlass_SPECIALIZED_BOUNDED_OOP_ITERATE(oop,                          \
398      a, p, low, high, (closure)->do_oop##nv_suffix(p))                         \
399  }                                                                             \
400  return size;                                                                  \
401}
402
403ALL_OOP_OOP_ITERATE_CLOSURES_1(ObjArrayKlass_OOP_OOP_ITERATE_DEFN)
404ALL_OOP_OOP_ITERATE_CLOSURES_3(ObjArrayKlass_OOP_OOP_ITERATE_DEFN)
405ALL_OOP_OOP_ITERATE_CLOSURES_1(ObjArrayKlass_OOP_OOP_ITERATE_DEFN_m)
406ALL_OOP_OOP_ITERATE_CLOSURES_3(ObjArrayKlass_OOP_OOP_ITERATE_DEFN_m)
407ALL_OOP_OOP_ITERATE_CLOSURES_1(ObjArrayKlass_OOP_OOP_ITERATE_DEFN_r)
408ALL_OOP_OOP_ITERATE_CLOSURES_3(ObjArrayKlass_OOP_OOP_ITERATE_DEFN_r)
409
410int objArrayKlass::oop_adjust_pointers(oop obj) {
411  assert(obj->is_objArray(), "obj must be obj array");
412  objArrayOop a = objArrayOop(obj);
413  // Get size before changing pointers.
414  // Don't call size() or oop_size() since that is a virtual call.
415  int size = a->object_size();
416  a->adjust_header();
417  ObjArrayKlass_OOP_ITERATE(a, p, MarkSweep::adjust_pointer(p))
418  return size;
419}
420
421#ifndef SERIALGC
422void objArrayKlass::oop_copy_contents(PSPromotionManager* pm, oop obj) {
423  assert(!pm->depth_first(), "invariant");
424  assert(obj->is_objArray(), "obj must be obj array");
425  ObjArrayKlass_OOP_ITERATE( \
426    objArrayOop(obj), p, \
427    if (PSScavenge::should_scavenge(p)) { \
428      pm->claim_or_forward_breadth(p); \
429    })
430}
431
432void objArrayKlass::oop_push_contents(PSPromotionManager* pm, oop obj) {
433  assert(pm->depth_first(), "invariant");
434  assert(obj->is_objArray(), "obj must be obj array");
435  ObjArrayKlass_OOP_ITERATE( \
436    objArrayOop(obj), p, \
437    if (PSScavenge::should_scavenge(p)) { \
438      pm->claim_or_forward_depth(p); \
439    })
440}
441
442int objArrayKlass::oop_update_pointers(ParCompactionManager* cm, oop obj) {
443  assert (obj->is_objArray(), "obj must be obj array");
444  objArrayOop a = objArrayOop(obj);
445  ObjArrayKlass_OOP_ITERATE(a, p, PSParallelCompact::adjust_pointer(p))
446  return a->object_size();
447}
448
449int objArrayKlass::oop_update_pointers(ParCompactionManager* cm, oop obj,
450                                       HeapWord* beg_addr, HeapWord* end_addr) {
451  assert (obj->is_objArray(), "obj must be obj array");
452  objArrayOop a = objArrayOop(obj);
453  ObjArrayKlass_BOUNDED_OOP_ITERATE( \
454     a, p, beg_addr, end_addr, \
455     PSParallelCompact::adjust_pointer(p))
456  return a->object_size();
457}
458#endif // SERIALGC
459
460// JVM support
461
462jint objArrayKlass::compute_modifier_flags(TRAPS) const {
463  // The modifier for an objectArray is the same as its element
464  if (element_klass() == NULL) {
465    assert(Universe::is_bootstrapping(), "partial objArray only at startup");
466    return JVM_ACC_ABSTRACT | JVM_ACC_FINAL | JVM_ACC_PUBLIC;
467  }
468  // Recurse down the element list
469  jint element_flags = Klass::cast(element_klass())->compute_modifier_flags(CHECK_0);
470
471  return (element_flags & (JVM_ACC_PUBLIC | JVM_ACC_PRIVATE | JVM_ACC_PROTECTED))
472                        | (JVM_ACC_ABSTRACT | JVM_ACC_FINAL);
473}
474
475
476#ifndef PRODUCT
477// Printing
478
479void objArrayKlass::oop_print_on(oop obj, outputStream* st) {
480  arrayKlass::oop_print_on(obj, st);
481  assert(obj->is_objArray(), "must be objArray");
482  objArrayOop oa = objArrayOop(obj);
483  int print_len = MIN2((intx) oa->length(), MaxElementPrintSize);
484  for(int index = 0; index < print_len; index++) {
485    st->print(" - %3d : ", index);
486    oa->obj_at(index)->print_value_on(st);
487    st->cr();
488  }
489  int remaining = oa->length() - print_len;
490  if (remaining > 0) {
491    tty->print_cr(" - <%d more elements, increase MaxElementPrintSize to print>", remaining);
492  }
493}
494
495
496void objArrayKlass::oop_print_value_on(oop obj, outputStream* st) {
497  assert(obj->is_objArray(), "must be objArray");
498  element_klass()->print_value_on(st);
499  st->print("a [%d] ", objArrayOop(obj)->length());
500  as_klassOop()->klass()->print_value_on(st);
501}
502
503#endif // PRODUCT
504
505const char* objArrayKlass::internal_name() const {
506  return external_name();
507}
508
509// Verification
510
511void objArrayKlass::oop_verify_on(oop obj, outputStream* st) {
512  arrayKlass::oop_verify_on(obj, st);
513  guarantee(obj->is_objArray(), "must be objArray");
514  objArrayOop oa = objArrayOop(obj);
515  for(int index = 0; index < oa->length(); index++) {
516    guarantee(oa->obj_at(index)->is_oop_or_null(), "should be oop");
517  }
518}
519
520void objArrayKlass::oop_verify_old_oop(oop obj, oop* p, bool allow_dirty) {
521  /* $$$ move into remembered set verification?
522  RememberedSet::verify_old_oop(obj, p, allow_dirty, true);
523  */
524}
525void objArrayKlass::oop_verify_old_oop(oop obj, narrowOop* p, bool allow_dirty) {}
526