objArrayKlass.cpp revision 356:1ee8caae33af
1214501Srpaulo/*
2214501Srpaulo * Copyright 1997-2008 Sun Microsystems, Inc.  All Rights Reserved.
3214501Srpaulo * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4214501Srpaulo *
5252726Srpaulo * This code is free software; you can redistribute it and/or modify it
6252726Srpaulo * under the terms of the GNU General Public License version 2 only, as
7214501Srpaulo * published by the Free Software Foundation.
8214501Srpaulo *
9214501Srpaulo * This code is distributed in the hope that it will be useful, but WITHOUT
10214501Srpaulo * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11214501Srpaulo * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
12214501Srpaulo * version 2 for more details (a copy is included in the LICENSE file that
13214501Srpaulo * accompanied this code).
14214501Srpaulo *
15252726Srpaulo * You should have received a copy of the GNU General Public License version
16214501Srpaulo * 2 along with this work; if not, write to the Free Software Foundation,
17214501Srpaulo * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18214501Srpaulo *
19214501Srpaulo * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
20214501Srpaulo * CA 95054 USA or visit www.sun.com if you need additional information or
21214501Srpaulo * have any questions.
22214501Srpaulo *
23214501Srpaulo */
24214501Srpaulo
25214501Srpaulo# include "incls/_precompiled.incl"
26214501Srpaulo# include "incls/_objArrayKlass.cpp.incl"
27214501Srpaulo
28214501Srpauloint objArrayKlass::oop_size(oop obj) const {
29214501Srpaulo  assert(obj->is_objArray(), "must be object array");
30214501Srpaulo  return objArrayOop(obj)->object_size();
31214501Srpaulo}
32214501Srpaulo
33214501SrpauloobjArrayOop objArrayKlass::allocate(int length, TRAPS) {
34214501Srpaulo  if (length >= 0) {
35214501Srpaulo    if (length <= arrayOopDesc::max_array_length(T_OBJECT)) {
36214501Srpaulo      int size = objArrayOopDesc::object_size(length);
37214501Srpaulo      KlassHandle h_k(THREAD, as_klassOop());
38214501Srpaulo      objArrayOop a = (objArrayOop)CollectedHeap::array_allocate(h_k, size, length, CHECK_NULL);
39214501Srpaulo      assert(a->is_parsable(), "Can't publish unless parsable");
40214501Srpaulo      return a;
41214501Srpaulo    } else {
42214501Srpaulo      THROW_OOP_0(Universe::out_of_memory_error_array_size());
43214501Srpaulo    }
44214501Srpaulo  } else {
45214501Srpaulo    THROW_0(vmSymbols::java_lang_NegativeArraySizeException());
46214501Srpaulo  }
47214501Srpaulo}
48214501Srpaulo
49214501Srpaulostatic int multi_alloc_counter = 0;
50214501Srpaulo
51214501Srpaulooop objArrayKlass::multi_allocate(int rank, jint* sizes, TRAPS) {
52214501Srpaulo  int length = *sizes;
53214501Srpaulo  // Call to lower_dimension uses this pointer, so most be called before a
54214501Srpaulo  // possible GC
55214501Srpaulo  KlassHandle h_lower_dimension(THREAD, lower_dimension());
56214501Srpaulo  // If length < 0 allocate will throw an exception.
57214501Srpaulo  objArrayOop array = allocate(length, CHECK_NULL);
58214501Srpaulo  assert(array->is_parsable(), "Don't handlize unless parsable");
59214501Srpaulo  objArrayHandle h_array (THREAD, array);
60214501Srpaulo  if (rank > 1) {
61214501Srpaulo    if (length != 0) {
62214501Srpaulo      for (int index = 0; index < length; index++) {
63214501Srpaulo        arrayKlass* ak = arrayKlass::cast(h_lower_dimension());
64214501Srpaulo        oop sub_array = ak->multi_allocate(rank-1, &sizes[1], CHECK_NULL);
65214501Srpaulo        assert(sub_array->is_parsable(), "Don't publish until parsable");
66214501Srpaulo        h_array->obj_at_put(index, sub_array);
67214501Srpaulo      }
68214501Srpaulo    } else {
69214501Srpaulo      // Since this array dimension has zero length, nothing will be
70214501Srpaulo      // allocated, however the lower dimension values must be checked
71214501Srpaulo      // for illegal values.
72214501Srpaulo      for (int i = 0; i < rank - 1; ++i) {
73214501Srpaulo        sizes += 1;
74214501Srpaulo        if (*sizes < 0) {
75214501Srpaulo          THROW_0(vmSymbols::java_lang_NegativeArraySizeException());
76214501Srpaulo        }
77214501Srpaulo      }
78214501Srpaulo    }
79214501Srpaulo  }
80214501Srpaulo  return h_array();
81214501Srpaulo}
82214501Srpaulo
83214501Srpaulo// Either oop or narrowOop depending on UseCompressedOops.
84214501Srpaulotemplate <class T> void objArrayKlass::do_copy(arrayOop s, T* src,
85214501Srpaulo                               arrayOop d, T* dst, int length, TRAPS) {
86214501Srpaulo
87214501Srpaulo  const size_t word_len = objArrayOopDesc::array_size(length);
88214501Srpaulo
89214501Srpaulo  BarrierSet* bs = Universe::heap()->barrier_set();
90214501Srpaulo  // For performance reasons, we assume we are that the write barrier we
91214501Srpaulo  // are using has optimized modes for arrays of references.  At least one
92214501Srpaulo  // of the asserts below will fail if this is not the case.
93214501Srpaulo  assert(bs->has_write_ref_array_opt(), "Barrier set must have ref array opt");
94214501Srpaulo  assert(bs->has_write_ref_array_pre_opt(), "For pre-barrier as well.");
95214501Srpaulo
96214501Srpaulo  MemRegion dst_mr = MemRegion((HeapWord*)dst, word_len);
97214501Srpaulo  if (s == d) {
98214501Srpaulo    // since source and destination are equal we do not need conversion checks.
99214501Srpaulo    assert(length > 0, "sanity check");
100214501Srpaulo    bs->write_ref_array_pre(dst_mr);
101214501Srpaulo    Copy::conjoint_oops_atomic(src, dst, length);
102214501Srpaulo  } else {
103214501Srpaulo    // We have to make sure all elements conform to the destination array
104214501Srpaulo    klassOop bound = objArrayKlass::cast(d->klass())->element_klass();
105214501Srpaulo    klassOop stype = objArrayKlass::cast(s->klass())->element_klass();
106214501Srpaulo    if (stype == bound || Klass::cast(stype)->is_subtype_of(bound)) {
107214501Srpaulo      // elements are guaranteed to be subtypes, so no check necessary
108214501Srpaulo      bs->write_ref_array_pre(dst_mr);
109214501Srpaulo      Copy::conjoint_oops_atomic(src, dst, length);
110214501Srpaulo    } else {
111214501Srpaulo      // slow case: need individual subtype checks
112214501Srpaulo      // note: don't use obj_at_put below because it includes a redundant store check
113214501Srpaulo      T* from = src;
114214501Srpaulo      T* end = from + length;
115214501Srpaulo      for (T* p = dst; from < end; from++, p++) {
116214501Srpaulo        // XXX this is going to be slow.
117214501Srpaulo        T element = *from;
118214501Srpaulo        // even slower now
119214501Srpaulo        bool element_is_null = oopDesc::is_null(element);
120214501Srpaulo        oop new_val = element_is_null ? oop(NULL)
121214501Srpaulo                                      : oopDesc::decode_heap_oop_not_null(element);
122214501Srpaulo        if (element_is_null ||
123214501Srpaulo            Klass::cast((new_val->klass()))->is_subtype_of(bound)) {
124214501Srpaulo          bs->write_ref_field_pre(p, new_val);
125214501Srpaulo          *p = *from;
126214501Srpaulo        } else {
127214501Srpaulo          // We must do a barrier to cover the partial copy.
128214501Srpaulo          const size_t pd = pointer_delta(p, dst, (size_t)heapOopSize);
129214501Srpaulo          // pointer delta is scaled to number of elements (length field in
130214501Srpaulo          // objArrayOop) which we assume is 32 bit.
131214501Srpaulo          assert(pd == (size_t)(int)pd, "length field overflow");
132214501Srpaulo          const size_t done_word_len = objArrayOopDesc::array_size((int)pd);
133214501Srpaulo          bs->write_ref_array(MemRegion((HeapWord*)dst, done_word_len));
134214501Srpaulo          THROW(vmSymbols::java_lang_ArrayStoreException());
135214501Srpaulo          return;
136214501Srpaulo        }
137214501Srpaulo      }
138214501Srpaulo    }
139214501Srpaulo  }
140214501Srpaulo  bs->write_ref_array(MemRegion((HeapWord*)dst, word_len));
141214501Srpaulo}
142214501Srpaulo
143214501Srpaulovoid objArrayKlass::copy_array(arrayOop s, int src_pos, arrayOop d,
144214501Srpaulo                               int dst_pos, int length, TRAPS) {
145214501Srpaulo  assert(s->is_objArray(), "must be obj array");
146214501Srpaulo
147214501Srpaulo  if (!d->is_objArray()) {
148214501Srpaulo    THROW(vmSymbols::java_lang_ArrayStoreException());
149214501Srpaulo  }
150214501Srpaulo
151214501Srpaulo  // Check is all offsets and lengths are non negative
152214501Srpaulo  if (src_pos < 0 || dst_pos < 0 || length < 0) {
153214501Srpaulo    THROW(vmSymbols::java_lang_ArrayIndexOutOfBoundsException());
154214501Srpaulo  }
155214501Srpaulo  // Check if the ranges are valid
156214501Srpaulo  if  ( (((unsigned int) length + (unsigned int) src_pos) > (unsigned int) s->length())
157214501Srpaulo     || (((unsigned int) length + (unsigned int) dst_pos) > (unsigned int) d->length()) ) {
158214501Srpaulo    THROW(vmSymbols::java_lang_ArrayIndexOutOfBoundsException());
159214501Srpaulo  }
160214501Srpaulo
161214501Srpaulo  // Special case. Boundary cases must be checked first
162214501Srpaulo  // This allows the following call: copy_array(s, s.length(), d.length(), 0).
163214501Srpaulo  // This is correct, since the position is supposed to be an 'in between point', i.e., s.length(),
164214501Srpaulo  // points to the right of the last element.
165214501Srpaulo  if (length==0) {
166214501Srpaulo    return;
167214501Srpaulo  }
168214501Srpaulo  if (UseCompressedOops) {
169214501Srpaulo    narrowOop* const src = objArrayOop(s)->obj_at_addr<narrowOop>(src_pos);
170214501Srpaulo    narrowOop* const dst = objArrayOop(d)->obj_at_addr<narrowOop>(dst_pos);
171214501Srpaulo    do_copy<narrowOop>(s, src, d, dst, length, CHECK);
172214501Srpaulo  } else {
173214501Srpaulo    oop* const src = objArrayOop(s)->obj_at_addr<oop>(src_pos);
174214501Srpaulo    oop* const dst = objArrayOop(d)->obj_at_addr<oop>(dst_pos);
175214501Srpaulo    do_copy<oop> (s, src, d, dst, length, CHECK);
176214501Srpaulo  }
177214501Srpaulo}
178214501Srpaulo
179214501Srpaulo
180214501SrpauloklassOop objArrayKlass::array_klass_impl(bool or_null, int n, TRAPS) {
181214501Srpaulo  objArrayKlassHandle h_this(THREAD, as_klassOop());
182214501Srpaulo  return array_klass_impl(h_this, or_null, n, CHECK_NULL);
183214501Srpaulo}
184214501Srpaulo
185214501Srpaulo
186214501SrpauloklassOop objArrayKlass::array_klass_impl(objArrayKlassHandle this_oop, bool or_null, int n, TRAPS) {
187214501Srpaulo
188214501Srpaulo  assert(this_oop->dimension() <= n, "check order of chain");
189214501Srpaulo  int dimension = this_oop->dimension();
190214501Srpaulo  if (dimension == n)
191214501Srpaulo    return this_oop();
192214501Srpaulo
193214501Srpaulo  objArrayKlassHandle ak (THREAD, this_oop->higher_dimension());
194214501Srpaulo  if (ak.is_null()) {
195214501Srpaulo    if (or_null)  return NULL;
196214501Srpaulo
197214501Srpaulo    ResourceMark rm;
198214501Srpaulo    JavaThread *jt = (JavaThread *)THREAD;
199214501Srpaulo    {
200214501Srpaulo      MutexLocker mc(Compile_lock, THREAD);   // for vtables
201214501Srpaulo      // Ensure atomic creation of higher dimensions
202214501Srpaulo      MutexLocker mu(MultiArray_lock, THREAD);
203214501Srpaulo
204214501Srpaulo      // Check if another thread beat us
205214501Srpaulo      ak = objArrayKlassHandle(THREAD, this_oop->higher_dimension());
206214501Srpaulo      if( ak.is_null() ) {
207214501Srpaulo
208214501Srpaulo        // Create multi-dim klass object and link them together
209214501Srpaulo        klassOop new_klass =
210214501Srpaulo          objArrayKlassKlass::cast(Universe::objArrayKlassKlassObj())->
211214501Srpaulo          allocate_objArray_klass(dimension + 1, this_oop, CHECK_NULL);
212214501Srpaulo        ak = objArrayKlassHandle(THREAD, new_klass);
213214501Srpaulo        this_oop->set_higher_dimension(ak());
214214501Srpaulo        ak->set_lower_dimension(this_oop());
215214501Srpaulo        assert(ak->oop_is_objArray(), "incorrect initialization of objArrayKlass");
216214501Srpaulo      }
217214501Srpaulo    }
218214501Srpaulo  } else {
219214501Srpaulo    CHECK_UNHANDLED_OOPS_ONLY(Thread::current()->clear_unhandled_oops());
220214501Srpaulo  }
221214501Srpaulo
222214501Srpaulo  if (or_null) {
223214501Srpaulo    return ak->array_klass_or_null(n);
224214501Srpaulo  }
225214501Srpaulo  return ak->array_klass(n, CHECK_NULL);
226214501Srpaulo}
227214501Srpaulo
228214501SrpauloklassOop objArrayKlass::array_klass_impl(bool or_null, TRAPS) {
229214501Srpaulo  return array_klass_impl(or_null, dimension() +  1, CHECK_NULL);
230214501Srpaulo}
231214501Srpaulo
232214501Srpaulobool objArrayKlass::can_be_primary_super_slow() const {
233214501Srpaulo  if (!bottom_klass()->klass_part()->can_be_primary_super())
234214501Srpaulo    // array of interfaces
235214501Srpaulo    return false;
236214501Srpaulo  else
237214501Srpaulo    return Klass::can_be_primary_super_slow();
238214501Srpaulo}
239214501Srpaulo
240214501SrpauloobjArrayOop objArrayKlass::compute_secondary_supers(int num_extra_slots, TRAPS) {
241214501Srpaulo  // interfaces = { cloneable_klass, serializable_klass, elemSuper[], ... };
242214501Srpaulo  objArrayOop es = Klass::cast(element_klass())->secondary_supers();
243214501Srpaulo  objArrayHandle elem_supers (THREAD, es);
244214501Srpaulo  int num_elem_supers = elem_supers.is_null() ? 0 : elem_supers->length();
245214501Srpaulo  int num_secondaries = num_extra_slots + 2 + num_elem_supers;
246214501Srpaulo  if (num_secondaries == 2) {
247214501Srpaulo    // Must share this for correct bootstrapping!
248214501Srpaulo    return Universe::the_array_interfaces_array();
249214501Srpaulo  } else {
250214501Srpaulo    objArrayOop sec_oop = oopFactory::new_system_objArray(num_secondaries, CHECK_NULL);
251214501Srpaulo    objArrayHandle secondaries(THREAD, sec_oop);
252214501Srpaulo    secondaries->obj_at_put(num_extra_slots+0, SystemDictionary::cloneable_klass());
253214501Srpaulo    secondaries->obj_at_put(num_extra_slots+1, SystemDictionary::serializable_klass());
254214501Srpaulo    for (int i = 0; i < num_elem_supers; i++) {
255214501Srpaulo      klassOop elem_super = (klassOop) elem_supers->obj_at(i);
256214501Srpaulo      klassOop array_super = elem_super->klass_part()->array_klass_or_null();
257214501Srpaulo      assert(array_super != NULL, "must already have been created");
258214501Srpaulo      secondaries->obj_at_put(num_extra_slots+2+i, array_super);
259214501Srpaulo    }
260214501Srpaulo    return secondaries();
261214501Srpaulo  }
262214501Srpaulo}
263214501Srpaulo
264214501Srpaulobool objArrayKlass::compute_is_subtype_of(klassOop k) {
265214501Srpaulo  if (!k->klass_part()->oop_is_objArray())
266214501Srpaulo    return arrayKlass::compute_is_subtype_of(k);
267214501Srpaulo
268214501Srpaulo  objArrayKlass* oak = objArrayKlass::cast(k);
269214501Srpaulo  return element_klass()->klass_part()->is_subtype_of(oak->element_klass());
270214501Srpaulo}
271214501Srpaulo
272214501Srpaulovoid objArrayKlass::initialize(TRAPS) {
273214501Srpaulo  Klass::cast(bottom_klass())->initialize(THREAD);  // dispatches to either instanceKlass or typeArrayKlass
274214501Srpaulo}
275214501Srpaulo
276214501Srpaulo#define ObjArrayKlass_SPECIALIZED_OOP_ITERATE(T, a, p, do_oop) \
277214501Srpaulo{                                   \
278214501Srpaulo  T* p         = (T*)(a)->base();   \
279214501Srpaulo  T* const end = p + (a)->length(); \
280214501Srpaulo  while (p < end) {                 \
281214501Srpaulo    do_oop;                         \
282214501Srpaulo    p++;                            \
283214501Srpaulo  }                                 \
284214501Srpaulo}
285214501Srpaulo
286214501Srpaulo#define ObjArrayKlass_SPECIALIZED_BOUNDED_OOP_ITERATE(T, a, p, low, high, do_oop) \
287214501Srpaulo{                                   \
288214501Srpaulo  T* const l = (T*)(low);           \
289214501Srpaulo  T* const h = (T*)(high);          \
290214501Srpaulo  T* p       = (T*)(a)->base();     \
291214501Srpaulo  T* end     = p + (a)->length();   \
292252726Srpaulo  if (p < l) p = l;                 \
293214501Srpaulo  if (end > h) end = h;             \
294214501Srpaulo  while (p < end) {                 \
295214501Srpaulo    do_oop;                         \
296214501Srpaulo    ++p;                            \
297214501Srpaulo  }                                 \
298214501Srpaulo}
299214501Srpaulo
300214501Srpaulo#define ObjArrayKlass_OOP_ITERATE(a, p, do_oop)      \
301214501Srpaulo  if (UseCompressedOops) {                           \
302214501Srpaulo    ObjArrayKlass_SPECIALIZED_OOP_ITERATE(narrowOop, \
303214501Srpaulo      a, p, do_oop)                                  \
304214501Srpaulo  } else {                                           \
305214501Srpaulo    ObjArrayKlass_SPECIALIZED_OOP_ITERATE(oop,       \
306214501Srpaulo      a, p, do_oop)                                  \
307214501Srpaulo  }
308214501Srpaulo
309214501Srpaulo#define ObjArrayKlass_BOUNDED_OOP_ITERATE(a, p, low, high, do_oop) \
310214501Srpaulo  if (UseCompressedOops) {                                   \
311214501Srpaulo    ObjArrayKlass_SPECIALIZED_BOUNDED_OOP_ITERATE(narrowOop, \
312214501Srpaulo      a, p, low, high, do_oop)                               \
313214501Srpaulo  } else {                                                   \
314214501Srpaulo    ObjArrayKlass_SPECIALIZED_BOUNDED_OOP_ITERATE(oop,       \
315214501Srpaulo      a, p, low, high, do_oop)                               \
316214501Srpaulo  }
317214501Srpaulo
318214501Srpaulovoid objArrayKlass::oop_follow_contents(oop obj) {
319214501Srpaulo  assert (obj->is_array(), "obj must be array");
320214501Srpaulo  objArrayOop a = objArrayOop(obj);
321214501Srpaulo  a->follow_header();
322214501Srpaulo  ObjArrayKlass_OOP_ITERATE( \
323214501Srpaulo    a, p, \
324214501Srpaulo    /* we call mark_and_follow here to avoid excessive marking stack usage */ \
325214501Srpaulo    MarkSweep::mark_and_follow(p))
326214501Srpaulo}
327214501Srpaulo
328214501Srpaulo#ifndef SERIALGC
329214501Srpaulovoid objArrayKlass::oop_follow_contents(ParCompactionManager* cm,
330214501Srpaulo                                        oop obj) {
331214501Srpaulo  assert (obj->is_array(), "obj must be array");
332214501Srpaulo  objArrayOop a = objArrayOop(obj);
333214501Srpaulo  a->follow_header(cm);
334214501Srpaulo  ObjArrayKlass_OOP_ITERATE( \
335214501Srpaulo    a, p, \
336214501Srpaulo    /* we call mark_and_follow here to avoid excessive marking stack usage */ \
337214501Srpaulo    PSParallelCompact::mark_and_follow(cm, p))
338214501Srpaulo}
339214501Srpaulo#endif // SERIALGC
340214501Srpaulo
341214501Srpaulo#define ObjArrayKlass_OOP_OOP_ITERATE_DEFN(OopClosureType, nv_suffix)           \
342214501Srpaulo                                                                                \
343214501Srpauloint objArrayKlass::oop_oop_iterate##nv_suffix(oop obj,                          \
344214501Srpaulo                                              OopClosureType* closure) {        \
345214501Srpaulo  SpecializationStats::record_iterate_call##nv_suffix(SpecializationStats::oa); \
346214501Srpaulo  assert (obj->is_array(), "obj must be array");                                \
347214501Srpaulo  objArrayOop a = objArrayOop(obj);                                             \
348214501Srpaulo  /* Get size before changing pointers. */                                      \
349214501Srpaulo  /* Don't call size() or oop_size() since that is a virtual call. */           \
350214501Srpaulo  int size = a->object_size();                                                  \
351214501Srpaulo  if (closure->do_header()) {                                                   \
352214501Srpaulo    a->oop_iterate_header(closure);                                             \
353214501Srpaulo  }                                                                             \
354214501Srpaulo  ObjArrayKlass_OOP_ITERATE(a, p, (closure)->do_oop##nv_suffix(p))              \
355214501Srpaulo  return size;                                                                  \
356214501Srpaulo}
357214501Srpaulo
358214501Srpaulo#define ObjArrayKlass_OOP_OOP_ITERATE_DEFN_m(OopClosureType, nv_suffix)         \
359214501Srpaulo                                                                                \
360214501Srpauloint objArrayKlass::oop_oop_iterate##nv_suffix##_m(oop obj,                      \
361214501Srpaulo                                                  OopClosureType* closure,      \
362214501Srpaulo                                                  MemRegion mr) {               \
363214501Srpaulo  SpecializationStats::record_iterate_call##nv_suffix(SpecializationStats::oa); \
364214501Srpaulo  assert(obj->is_array(), "obj must be array");                                 \
365214501Srpaulo  objArrayOop a  = objArrayOop(obj);                                            \
366214501Srpaulo  /* Get size before changing pointers. */                                      \
367214501Srpaulo  /* Don't call size() or oop_size() since that is a virtual call */            \
368214501Srpaulo  int size = a->object_size();                                                  \
369214501Srpaulo  if (closure->do_header()) {                                                   \
370214501Srpaulo    a->oop_iterate_header(closure, mr);                                         \
371214501Srpaulo  }                                                                             \
372214501Srpaulo  ObjArrayKlass_BOUNDED_OOP_ITERATE(                                            \
373214501Srpaulo    a, p, mr.start(), mr.end(), (closure)->do_oop##nv_suffix(p))                \
374214501Srpaulo  return size;                                                                  \
375214501Srpaulo}
376214501Srpaulo
377214501Srpaulo// Like oop_oop_iterate but only iterates over a specified range and only used
378214501Srpaulo// for objArrayOops.
379214501Srpaulo#define ObjArrayKlass_OOP_OOP_ITERATE_DEFN_r(OopClosureType, nv_suffix)         \
380214501Srpaulo                                                                                \
381214501Srpauloint objArrayKlass::oop_oop_iterate_range##nv_suffix(oop obj,                    \
382214501Srpaulo                                                  OopClosureType* closure,      \
383214501Srpaulo                                                  int start, int end) {         \
384214501Srpaulo  SpecializationStats::record_iterate_call##nv_suffix(SpecializationStats::oa); \
385214501Srpaulo  assert(obj->is_array(), "obj must be array");                                 \
386214501Srpaulo  objArrayOop a  = objArrayOop(obj);                                            \
387214501Srpaulo  /* Get size before changing pointers. */                                      \
388214501Srpaulo  /* Don't call size() or oop_size() since that is a virtual call */            \
389214501Srpaulo  int size = a->object_size();                                                  \
390214501Srpaulo  if (UseCompressedOops) {                                                      \
391214501Srpaulo    HeapWord* low = start == 0 ? (HeapWord*)a : (HeapWord*)a->obj_at_addr<narrowOop>(start);\
392214501Srpaulo    /* this might be wierd if end needs to be aligned on HeapWord boundary */   \
393214501Srpaulo    HeapWord* high = (HeapWord*)((narrowOop*)a->base() + end);                  \
394214501Srpaulo    MemRegion mr(low, high);                                                    \
395214501Srpaulo    if (closure->do_header()) {                                                 \
396214501Srpaulo      a->oop_iterate_header(closure, mr);                                       \
397    }                                                                           \
398    ObjArrayKlass_SPECIALIZED_BOUNDED_OOP_ITERATE(narrowOop,                    \
399      a, p, low, high, (closure)->do_oop##nv_suffix(p))                         \
400  } else {                                                                      \
401    HeapWord* low = start == 0 ? (HeapWord*)a : (HeapWord*)a->obj_at_addr<oop>(start);  \
402    HeapWord* high = (HeapWord*)((oop*)a->base() + end);                        \
403    MemRegion mr(low, high);                                                    \
404    if (closure->do_header()) {                                                 \
405      a->oop_iterate_header(closure, mr);                                       \
406    }                                                                           \
407    ObjArrayKlass_SPECIALIZED_BOUNDED_OOP_ITERATE(oop,                          \
408      a, p, low, high, (closure)->do_oop##nv_suffix(p))                         \
409  }                                                                             \
410  return size;                                                                  \
411}
412
413ALL_OOP_OOP_ITERATE_CLOSURES_1(ObjArrayKlass_OOP_OOP_ITERATE_DEFN)
414ALL_OOP_OOP_ITERATE_CLOSURES_2(ObjArrayKlass_OOP_OOP_ITERATE_DEFN)
415ALL_OOP_OOP_ITERATE_CLOSURES_1(ObjArrayKlass_OOP_OOP_ITERATE_DEFN_m)
416ALL_OOP_OOP_ITERATE_CLOSURES_2(ObjArrayKlass_OOP_OOP_ITERATE_DEFN_m)
417ALL_OOP_OOP_ITERATE_CLOSURES_1(ObjArrayKlass_OOP_OOP_ITERATE_DEFN_r)
418ALL_OOP_OOP_ITERATE_CLOSURES_2(ObjArrayKlass_OOP_OOP_ITERATE_DEFN_r)
419
420int objArrayKlass::oop_adjust_pointers(oop obj) {
421  assert(obj->is_objArray(), "obj must be obj array");
422  objArrayOop a = objArrayOop(obj);
423  // Get size before changing pointers.
424  // Don't call size() or oop_size() since that is a virtual call.
425  int size = a->object_size();
426  a->adjust_header();
427  ObjArrayKlass_OOP_ITERATE(a, p, MarkSweep::adjust_pointer(p))
428  return size;
429}
430
431#ifndef SERIALGC
432void objArrayKlass::oop_copy_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_breadth(p); \
439    })
440}
441
442void objArrayKlass::oop_push_contents(PSPromotionManager* pm, oop obj) {
443  assert(pm->depth_first(), "invariant");
444  assert(obj->is_objArray(), "obj must be obj array");
445  ObjArrayKlass_OOP_ITERATE( \
446    objArrayOop(obj), p, \
447    if (PSScavenge::should_scavenge(p)) { \
448      pm->claim_or_forward_depth(p); \
449    })
450}
451
452int objArrayKlass::oop_update_pointers(ParCompactionManager* cm, oop obj) {
453  assert (obj->is_objArray(), "obj must be obj array");
454  objArrayOop a = objArrayOop(obj);
455  ObjArrayKlass_OOP_ITERATE(a, p, PSParallelCompact::adjust_pointer(p))
456  return a->object_size();
457}
458
459int objArrayKlass::oop_update_pointers(ParCompactionManager* cm, oop obj,
460                                       HeapWord* beg_addr, HeapWord* end_addr) {
461  assert (obj->is_objArray(), "obj must be obj array");
462  objArrayOop a = objArrayOop(obj);
463  ObjArrayKlass_BOUNDED_OOP_ITERATE( \
464     a, p, beg_addr, end_addr, \
465     PSParallelCompact::adjust_pointer(p))
466  return a->object_size();
467}
468#endif // SERIALGC
469
470// JVM support
471
472jint objArrayKlass::compute_modifier_flags(TRAPS) const {
473  // The modifier for an objectArray is the same as its element
474  if (element_klass() == NULL) {
475    assert(Universe::is_bootstrapping(), "partial objArray only at startup");
476    return JVM_ACC_ABSTRACT | JVM_ACC_FINAL | JVM_ACC_PUBLIC;
477  }
478  // Recurse down the element list
479  jint element_flags = Klass::cast(element_klass())->compute_modifier_flags(CHECK_0);
480
481  return (element_flags & (JVM_ACC_PUBLIC | JVM_ACC_PRIVATE | JVM_ACC_PROTECTED))
482                        | (JVM_ACC_ABSTRACT | JVM_ACC_FINAL);
483}
484
485
486#ifndef PRODUCT
487// Printing
488
489void objArrayKlass::oop_print_on(oop obj, outputStream* st) {
490  arrayKlass::oop_print_on(obj, st);
491  assert(obj->is_objArray(), "must be objArray");
492  objArrayOop oa = objArrayOop(obj);
493  int print_len = MIN2((intx) oa->length(), MaxElementPrintSize);
494  for(int index = 0; index < print_len; index++) {
495    st->print(" - %3d : ", index);
496    oa->obj_at(index)->print_value_on(st);
497    st->cr();
498  }
499  int remaining = oa->length() - print_len;
500  if (remaining > 0) {
501    tty->print_cr(" - <%d more elements, increase MaxElementPrintSize to print>", remaining);
502  }
503}
504
505
506void objArrayKlass::oop_print_value_on(oop obj, outputStream* st) {
507  assert(obj->is_objArray(), "must be objArray");
508  element_klass()->print_value_on(st);
509  st->print("a [%d] ", objArrayOop(obj)->length());
510  as_klassOop()->klass()->print_value_on(st);
511}
512
513#endif // PRODUCT
514
515const char* objArrayKlass::internal_name() const {
516  return external_name();
517}
518
519// Verification
520
521void objArrayKlass::oop_verify_on(oop obj, outputStream* st) {
522  arrayKlass::oop_verify_on(obj, st);
523  guarantee(obj->is_objArray(), "must be objArray");
524  objArrayOop oa = objArrayOop(obj);
525  for(int index = 0; index < oa->length(); index++) {
526    guarantee(oa->obj_at(index)->is_oop_or_null(), "should be oop");
527  }
528}
529
530void objArrayKlass::oop_verify_old_oop(oop obj, oop* p, bool allow_dirty) {
531  /* $$$ move into remembered set verification?
532  RememberedSet::verify_old_oop(obj, p, allow_dirty, true);
533  */
534}
535void objArrayKlass::oop_verify_old_oop(oop obj, narrowOop* p, bool allow_dirty) {}
536