annotate src/share/vm/oops/objArrayKlass.cpp @ 1091:6aa7255741f3

6906727: UseCompressedOops: some card-marking fixes related to object arrays Summary: Introduced a new write_ref_array(HeapWords* start, size_t count) method that does the requisite MemRegion range calculation so (some of the) clients of the erstwhile write_ref_array(MemRegion mr) do not need to worry. This removed all external uses of array_size(), which was also simplified and made private. Asserts were added to catch other possible issues. Further, less essential, fixes stemming from this investigation are deferred to CR 6904516 (to follow shortly in hs17). Reviewed-by: kvn, coleenp, jmasa
author ysr
date Thu, 03 Dec 2009 15:01:57 -0800
parents 494244ae0171
children 4ce7240d622c
rev   line source
duke@0 1 /*
jrose@665 2 * Copyright 1997-2009 Sun Microsystems, Inc. All Rights Reserved.
duke@0 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
duke@0 4 *
duke@0 5 * This code is free software; you can redistribute it and/or modify it
duke@0 6 * under the terms of the GNU General Public License version 2 only, as
duke@0 7 * published by the Free Software Foundation.
duke@0 8 *
duke@0 9 * This code is distributed in the hope that it will be useful, but WITHOUT
duke@0 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
duke@0 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
duke@0 12 * version 2 for more details (a copy is included in the LICENSE file that
duke@0 13 * accompanied this code).
duke@0 14 *
duke@0 15 * You should have received a copy of the GNU General Public License version
duke@0 16 * 2 along with this work; if not, write to the Free Software Foundation,
duke@0 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
duke@0 18 *
duke@0 19 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
duke@0 20 * CA 95054 USA or visit www.sun.com if you need additional information or
duke@0 21 * have any questions.
duke@0 22 *
duke@0 23 */
duke@0 24
duke@0 25 # include "incls/_precompiled.incl"
duke@0 26 # include "incls/_objArrayKlass.cpp.incl"
duke@0 27
duke@0 28 int objArrayKlass::oop_size(oop obj) const {
duke@0 29 assert(obj->is_objArray(), "must be object array");
duke@0 30 return objArrayOop(obj)->object_size();
duke@0 31 }
duke@0 32
duke@0 33 objArrayOop objArrayKlass::allocate(int length, TRAPS) {
duke@0 34 if (length >= 0) {
duke@0 35 if (length <= arrayOopDesc::max_array_length(T_OBJECT)) {
duke@0 36 int size = objArrayOopDesc::object_size(length);
duke@0 37 KlassHandle h_k(THREAD, as_klassOop());
duke@0 38 objArrayOop a = (objArrayOop)CollectedHeap::array_allocate(h_k, size, length, CHECK_NULL);
duke@0 39 assert(a->is_parsable(), "Can't publish unless parsable");
duke@0 40 return a;
duke@0 41 } else {
martin@876 42 report_java_out_of_memory("Requested array size exceeds VM limit");
duke@0 43 THROW_OOP_0(Universe::out_of_memory_error_array_size());
duke@0 44 }
duke@0 45 } else {
duke@0 46 THROW_0(vmSymbols::java_lang_NegativeArraySizeException());
duke@0 47 }
duke@0 48 }
duke@0 49
duke@0 50 static int multi_alloc_counter = 0;
duke@0 51
duke@0 52 oop objArrayKlass::multi_allocate(int rank, jint* sizes, TRAPS) {
duke@0 53 int length = *sizes;
duke@0 54 // Call to lower_dimension uses this pointer, so most be called before a
duke@0 55 // possible GC
duke@0 56 KlassHandle h_lower_dimension(THREAD, lower_dimension());
duke@0 57 // If length < 0 allocate will throw an exception.
duke@0 58 objArrayOop array = allocate(length, CHECK_NULL);
duke@0 59 assert(array->is_parsable(), "Don't handlize unless parsable");
duke@0 60 objArrayHandle h_array (THREAD, array);
duke@0 61 if (rank > 1) {
duke@0 62 if (length != 0) {
duke@0 63 for (int index = 0; index < length; index++) {
duke@0 64 arrayKlass* ak = arrayKlass::cast(h_lower_dimension());
duke@0 65 oop sub_array = ak->multi_allocate(rank-1, &sizes[1], CHECK_NULL);
duke@0 66 assert(sub_array->is_parsable(), "Don't publish until parsable");
duke@0 67 h_array->obj_at_put(index, sub_array);
duke@0 68 }
duke@0 69 } else {
duke@0 70 // Since this array dimension has zero length, nothing will be
duke@0 71 // allocated, however the lower dimension values must be checked
duke@0 72 // for illegal values.
duke@0 73 for (int i = 0; i < rank - 1; ++i) {
duke@0 74 sizes += 1;
duke@0 75 if (*sizes < 0) {
duke@0 76 THROW_0(vmSymbols::java_lang_NegativeArraySizeException());
duke@0 77 }
duke@0 78 }
duke@0 79 }
duke@0 80 }
duke@0 81 return h_array();
duke@0 82 }
duke@0 83
coleenp@113 84 // Either oop or narrowOop depending on UseCompressedOops.
coleenp@113 85 template <class T> void objArrayKlass::do_copy(arrayOop s, T* src,
coleenp@113 86 arrayOop d, T* dst, int length, TRAPS) {
coleenp@113 87
coleenp@113 88 BarrierSet* bs = Universe::heap()->barrier_set();
ysr@342 89 // For performance reasons, we assume we are that the write barrier we
ysr@342 90 // are using has optimized modes for arrays of references. At least one
ysr@342 91 // of the asserts below will fail if this is not the case.
coleenp@113 92 assert(bs->has_write_ref_array_opt(), "Barrier set must have ref array opt");
ysr@342 93 assert(bs->has_write_ref_array_pre_opt(), "For pre-barrier as well.");
coleenp@113 94
coleenp@113 95 if (s == d) {
coleenp@113 96 // since source and destination are equal we do not need conversion checks.
coleenp@113 97 assert(length > 0, "sanity check");
ysr@845 98 bs->write_ref_array_pre(dst, length);
coleenp@113 99 Copy::conjoint_oops_atomic(src, dst, length);
coleenp@113 100 } else {
coleenp@113 101 // We have to make sure all elements conform to the destination array
coleenp@113 102 klassOop bound = objArrayKlass::cast(d->klass())->element_klass();
coleenp@113 103 klassOop stype = objArrayKlass::cast(s->klass())->element_klass();
coleenp@113 104 if (stype == bound || Klass::cast(stype)->is_subtype_of(bound)) {
coleenp@113 105 // elements are guaranteed to be subtypes, so no check necessary
ysr@845 106 bs->write_ref_array_pre(dst, length);
coleenp@113 107 Copy::conjoint_oops_atomic(src, dst, length);
coleenp@113 108 } else {
coleenp@113 109 // slow case: need individual subtype checks
coleenp@113 110 // note: don't use obj_at_put below because it includes a redundant store check
coleenp@113 111 T* from = src;
coleenp@113 112 T* end = from + length;
coleenp@113 113 for (T* p = dst; from < end; from++, p++) {
coleenp@113 114 // XXX this is going to be slow.
coleenp@113 115 T element = *from;
ysr@342 116 // even slower now
ysr@342 117 bool element_is_null = oopDesc::is_null(element);
ysr@342 118 oop new_val = element_is_null ? oop(NULL)
ysr@342 119 : oopDesc::decode_heap_oop_not_null(element);
ysr@342 120 if (element_is_null ||
ysr@342 121 Klass::cast((new_val->klass()))->is_subtype_of(bound)) {
ysr@342 122 bs->write_ref_field_pre(p, new_val);
coleenp@113 123 *p = *from;
coleenp@113 124 } else {
coleenp@113 125 // We must do a barrier to cover the partial copy.
coleenp@113 126 const size_t pd = pointer_delta(p, dst, (size_t)heapOopSize);
coleenp@113 127 // pointer delta is scaled to number of elements (length field in
coleenp@113 128 // objArrayOop) which we assume is 32 bit.
coleenp@113 129 assert(pd == (size_t)(int)pd, "length field overflow");
ysr@1091 130 bs->write_ref_array((HeapWord*)dst, pd);
coleenp@113 131 THROW(vmSymbols::java_lang_ArrayStoreException());
coleenp@113 132 return;
coleenp@113 133 }
coleenp@113 134 }
coleenp@113 135 }
coleenp@113 136 }
ysr@1091 137 bs->write_ref_array((HeapWord*)dst, length);
coleenp@113 138 }
coleenp@113 139
duke@0 140 void objArrayKlass::copy_array(arrayOop s, int src_pos, arrayOop d,
duke@0 141 int dst_pos, int length, TRAPS) {
duke@0 142 assert(s->is_objArray(), "must be obj array");
duke@0 143
duke@0 144 if (!d->is_objArray()) {
duke@0 145 THROW(vmSymbols::java_lang_ArrayStoreException());
duke@0 146 }
duke@0 147
duke@0 148 // Check is all offsets and lengths are non negative
duke@0 149 if (src_pos < 0 || dst_pos < 0 || length < 0) {
duke@0 150 THROW(vmSymbols::java_lang_ArrayIndexOutOfBoundsException());
duke@0 151 }
duke@0 152 // Check if the ranges are valid
duke@0 153 if ( (((unsigned int) length + (unsigned int) src_pos) > (unsigned int) s->length())
duke@0 154 || (((unsigned int) length + (unsigned int) dst_pos) > (unsigned int) d->length()) ) {
duke@0 155 THROW(vmSymbols::java_lang_ArrayIndexOutOfBoundsException());
duke@0 156 }
duke@0 157
duke@0 158 // Special case. Boundary cases must be checked first
duke@0 159 // This allows the following call: copy_array(s, s.length(), d.length(), 0).
duke@0 160 // This is correct, since the position is supposed to be an 'in between point', i.e., s.length(),
duke@0 161 // points to the right of the last element.
duke@0 162 if (length==0) {
duke@0 163 return;
duke@0 164 }
coleenp@113 165 if (UseCompressedOops) {
coleenp@113 166 narrowOop* const src = objArrayOop(s)->obj_at_addr<narrowOop>(src_pos);
coleenp@113 167 narrowOop* const dst = objArrayOop(d)->obj_at_addr<narrowOop>(dst_pos);
coleenp@113 168 do_copy<narrowOop>(s, src, d, dst, length, CHECK);
duke@0 169 } else {
coleenp@113 170 oop* const src = objArrayOop(s)->obj_at_addr<oop>(src_pos);
coleenp@113 171 oop* const dst = objArrayOop(d)->obj_at_addr<oop>(dst_pos);
coleenp@113 172 do_copy<oop> (s, src, d, dst, length, CHECK);
duke@0 173 }
duke@0 174 }
duke@0 175
duke@0 176
duke@0 177 klassOop objArrayKlass::array_klass_impl(bool or_null, int n, TRAPS) {
duke@0 178 objArrayKlassHandle h_this(THREAD, as_klassOop());
duke@0 179 return array_klass_impl(h_this, or_null, n, CHECK_NULL);
duke@0 180 }
duke@0 181
duke@0 182
duke@0 183 klassOop objArrayKlass::array_klass_impl(objArrayKlassHandle this_oop, bool or_null, int n, TRAPS) {
duke@0 184
duke@0 185 assert(this_oop->dimension() <= n, "check order of chain");
duke@0 186 int dimension = this_oop->dimension();
duke@0 187 if (dimension == n)
duke@0 188 return this_oop();
duke@0 189
duke@0 190 objArrayKlassHandle ak (THREAD, this_oop->higher_dimension());
duke@0 191 if (ak.is_null()) {
duke@0 192 if (or_null) return NULL;
duke@0 193
duke@0 194 ResourceMark rm;
duke@0 195 JavaThread *jt = (JavaThread *)THREAD;
duke@0 196 {
duke@0 197 MutexLocker mc(Compile_lock, THREAD); // for vtables
duke@0 198 // Ensure atomic creation of higher dimensions
duke@0 199 MutexLocker mu(MultiArray_lock, THREAD);
duke@0 200
duke@0 201 // Check if another thread beat us
duke@0 202 ak = objArrayKlassHandle(THREAD, this_oop->higher_dimension());
duke@0 203 if( ak.is_null() ) {
duke@0 204
duke@0 205 // Create multi-dim klass object and link them together
duke@0 206 klassOop new_klass =
duke@0 207 objArrayKlassKlass::cast(Universe::objArrayKlassKlassObj())->
duke@0 208 allocate_objArray_klass(dimension + 1, this_oop, CHECK_NULL);
duke@0 209 ak = objArrayKlassHandle(THREAD, new_klass);
duke@0 210 this_oop->set_higher_dimension(ak());
duke@0 211 ak->set_lower_dimension(this_oop());
duke@0 212 assert(ak->oop_is_objArray(), "incorrect initialization of objArrayKlass");
duke@0 213 }
duke@0 214 }
duke@0 215 } else {
duke@0 216 CHECK_UNHANDLED_OOPS_ONLY(Thread::current()->clear_unhandled_oops());
duke@0 217 }
duke@0 218
duke@0 219 if (or_null) {
duke@0 220 return ak->array_klass_or_null(n);
duke@0 221 }
duke@0 222 return ak->array_klass(n, CHECK_NULL);
duke@0 223 }
duke@0 224
duke@0 225 klassOop objArrayKlass::array_klass_impl(bool or_null, TRAPS) {
duke@0 226 return array_klass_impl(or_null, dimension() + 1, CHECK_NULL);
duke@0 227 }
duke@0 228
duke@0 229 bool objArrayKlass::can_be_primary_super_slow() const {
duke@0 230 if (!bottom_klass()->klass_part()->can_be_primary_super())
duke@0 231 // array of interfaces
duke@0 232 return false;
duke@0 233 else
duke@0 234 return Klass::can_be_primary_super_slow();
duke@0 235 }
duke@0 236
duke@0 237 objArrayOop objArrayKlass::compute_secondary_supers(int num_extra_slots, TRAPS) {
duke@0 238 // interfaces = { cloneable_klass, serializable_klass, elemSuper[], ... };
duke@0 239 objArrayOop es = Klass::cast(element_klass())->secondary_supers();
duke@0 240 objArrayHandle elem_supers (THREAD, es);
duke@0 241 int num_elem_supers = elem_supers.is_null() ? 0 : elem_supers->length();
duke@0 242 int num_secondaries = num_extra_slots + 2 + num_elem_supers;
duke@0 243 if (num_secondaries == 2) {
duke@0 244 // Must share this for correct bootstrapping!
duke@0 245 return Universe::the_array_interfaces_array();
duke@0 246 } else {
duke@0 247 objArrayOop sec_oop = oopFactory::new_system_objArray(num_secondaries, CHECK_NULL);
duke@0 248 objArrayHandle secondaries(THREAD, sec_oop);
duke@0 249 secondaries->obj_at_put(num_extra_slots+0, SystemDictionary::cloneable_klass());
duke@0 250 secondaries->obj_at_put(num_extra_slots+1, SystemDictionary::serializable_klass());
duke@0 251 for (int i = 0; i < num_elem_supers; i++) {
duke@0 252 klassOop elem_super = (klassOop) elem_supers->obj_at(i);
duke@0 253 klassOop array_super = elem_super->klass_part()->array_klass_or_null();
duke@0 254 assert(array_super != NULL, "must already have been created");
duke@0 255 secondaries->obj_at_put(num_extra_slots+2+i, array_super);
duke@0 256 }
duke@0 257 return secondaries();
duke@0 258 }
duke@0 259 }
duke@0 260
duke@0 261 bool objArrayKlass::compute_is_subtype_of(klassOop k) {
duke@0 262 if (!k->klass_part()->oop_is_objArray())
duke@0 263 return arrayKlass::compute_is_subtype_of(k);
duke@0 264
duke@0 265 objArrayKlass* oak = objArrayKlass::cast(k);
duke@0 266 return element_klass()->klass_part()->is_subtype_of(oak->element_klass());
duke@0 267 }
duke@0 268
duke@0 269 void objArrayKlass::initialize(TRAPS) {
duke@0 270 Klass::cast(bottom_klass())->initialize(THREAD); // dispatches to either instanceKlass or typeArrayKlass
duke@0 271 }
duke@0 272
coleenp@113 273 #define ObjArrayKlass_SPECIALIZED_OOP_ITERATE(T, a, p, do_oop) \
coleenp@113 274 { \
coleenp@113 275 T* p = (T*)(a)->base(); \
coleenp@113 276 T* const end = p + (a)->length(); \
coleenp@113 277 while (p < end) { \
coleenp@113 278 do_oop; \
coleenp@113 279 p++; \
coleenp@113 280 } \
coleenp@113 281 }
coleenp@113 282
coleenp@113 283 #define ObjArrayKlass_SPECIALIZED_BOUNDED_OOP_ITERATE(T, a, p, low, high, do_oop) \
coleenp@113 284 { \
coleenp@113 285 T* const l = (T*)(low); \
coleenp@113 286 T* const h = (T*)(high); \
coleenp@113 287 T* p = (T*)(a)->base(); \
coleenp@113 288 T* end = p + (a)->length(); \
coleenp@113 289 if (p < l) p = l; \
coleenp@113 290 if (end > h) end = h; \
coleenp@113 291 while (p < end) { \
coleenp@113 292 do_oop; \
coleenp@113 293 ++p; \
coleenp@113 294 } \
coleenp@113 295 }
coleenp@113 296
coleenp@113 297 #define ObjArrayKlass_OOP_ITERATE(a, p, do_oop) \
coleenp@113 298 if (UseCompressedOops) { \
coleenp@113 299 ObjArrayKlass_SPECIALIZED_OOP_ITERATE(narrowOop, \
coleenp@113 300 a, p, do_oop) \
coleenp@113 301 } else { \
coleenp@113 302 ObjArrayKlass_SPECIALIZED_OOP_ITERATE(oop, \
coleenp@113 303 a, p, do_oop) \
coleenp@113 304 }
coleenp@113 305
coleenp@113 306 #define ObjArrayKlass_BOUNDED_OOP_ITERATE(a, p, low, high, do_oop) \
coleenp@113 307 if (UseCompressedOops) { \
coleenp@113 308 ObjArrayKlass_SPECIALIZED_BOUNDED_OOP_ITERATE(narrowOop, \
coleenp@113 309 a, p, low, high, do_oop) \
coleenp@113 310 } else { \
coleenp@113 311 ObjArrayKlass_SPECIALIZED_BOUNDED_OOP_ITERATE(oop, \
coleenp@113 312 a, p, low, high, do_oop) \
coleenp@113 313 }
duke@0 314
duke@0 315 void objArrayKlass::oop_follow_contents(oop obj) {
duke@0 316 assert (obj->is_array(), "obj must be array");
coleenp@113 317 objArrayOop a = objArrayOop(obj);
duke@0 318 a->follow_header();
coleenp@113 319 ObjArrayKlass_OOP_ITERATE( \
coleenp@113 320 a, p, \
coleenp@113 321 /* we call mark_and_follow here to avoid excessive marking stack usage */ \
coleenp@113 322 MarkSweep::mark_and_follow(p))
duke@0 323 }
duke@0 324
duke@0 325 #ifndef SERIALGC
duke@0 326 void objArrayKlass::oop_follow_contents(ParCompactionManager* cm,
duke@0 327 oop obj) {
duke@0 328 assert (obj->is_array(), "obj must be array");
coleenp@113 329 objArrayOop a = objArrayOop(obj);
duke@0 330 a->follow_header(cm);
coleenp@113 331 ObjArrayKlass_OOP_ITERATE( \
coleenp@113 332 a, p, \
coleenp@113 333 /* we call mark_and_follow here to avoid excessive marking stack usage */ \
coleenp@113 334 PSParallelCompact::mark_and_follow(cm, p))
duke@0 335 }
duke@0 336 #endif // SERIALGC
duke@0 337
duke@0 338 #define ObjArrayKlass_OOP_OOP_ITERATE_DEFN(OopClosureType, nv_suffix) \
duke@0 339 \
duke@0 340 int objArrayKlass::oop_oop_iterate##nv_suffix(oop obj, \
duke@0 341 OopClosureType* closure) { \
duke@0 342 SpecializationStats::record_iterate_call##nv_suffix(SpecializationStats::oa); \
duke@0 343 assert (obj->is_array(), "obj must be array"); \
duke@0 344 objArrayOop a = objArrayOop(obj); \
duke@0 345 /* Get size before changing pointers. */ \
duke@0 346 /* Don't call size() or oop_size() since that is a virtual call. */ \
duke@0 347 int size = a->object_size(); \
duke@0 348 if (closure->do_header()) { \
duke@0 349 a->oop_iterate_header(closure); \
duke@0 350 } \
coleenp@113 351 ObjArrayKlass_OOP_ITERATE(a, p, (closure)->do_oop##nv_suffix(p)) \
duke@0 352 return size; \
duke@0 353 }
duke@0 354
duke@0 355 #define ObjArrayKlass_OOP_OOP_ITERATE_DEFN_m(OopClosureType, nv_suffix) \
duke@0 356 \
duke@0 357 int objArrayKlass::oop_oop_iterate##nv_suffix##_m(oop obj, \
duke@0 358 OopClosureType* closure, \
duke@0 359 MemRegion mr) { \
duke@0 360 SpecializationStats::record_iterate_call##nv_suffix(SpecializationStats::oa); \
duke@0 361 assert(obj->is_array(), "obj must be array"); \
duke@0 362 objArrayOop a = objArrayOop(obj); \
duke@0 363 /* Get size before changing pointers. */ \
duke@0 364 /* Don't call size() or oop_size() since that is a virtual call */ \
duke@0 365 int size = a->object_size(); \
duke@0 366 if (closure->do_header()) { \
duke@0 367 a->oop_iterate_header(closure, mr); \
duke@0 368 } \
coleenp@113 369 ObjArrayKlass_BOUNDED_OOP_ITERATE( \
coleenp@113 370 a, p, mr.start(), mr.end(), (closure)->do_oop##nv_suffix(p)) \
coleenp@113 371 return size; \
coleenp@113 372 }
coleenp@113 373
coleenp@113 374 // Like oop_oop_iterate but only iterates over a specified range and only used
coleenp@113 375 // for objArrayOops.
coleenp@113 376 #define ObjArrayKlass_OOP_OOP_ITERATE_DEFN_r(OopClosureType, nv_suffix) \
coleenp@113 377 \
coleenp@113 378 int objArrayKlass::oop_oop_iterate_range##nv_suffix(oop obj, \
coleenp@113 379 OopClosureType* closure, \
coleenp@113 380 int start, int end) { \
coleenp@113 381 SpecializationStats::record_iterate_call##nv_suffix(SpecializationStats::oa); \
coleenp@113 382 assert(obj->is_array(), "obj must be array"); \
coleenp@113 383 objArrayOop a = objArrayOop(obj); \
coleenp@113 384 /* Get size before changing pointers. */ \
coleenp@113 385 /* Don't call size() or oop_size() since that is a virtual call */ \
coleenp@113 386 int size = a->object_size(); \
coleenp@113 387 if (UseCompressedOops) { \
coleenp@113 388 HeapWord* low = start == 0 ? (HeapWord*)a : (HeapWord*)a->obj_at_addr<narrowOop>(start);\
coleenp@113 389 /* this might be wierd if end needs to be aligned on HeapWord boundary */ \
coleenp@113 390 HeapWord* high = (HeapWord*)((narrowOop*)a->base() + end); \
coleenp@113 391 MemRegion mr(low, high); \
coleenp@113 392 if (closure->do_header()) { \
coleenp@113 393 a->oop_iterate_header(closure, mr); \
duke@0 394 } \
coleenp@113 395 ObjArrayKlass_SPECIALIZED_BOUNDED_OOP_ITERATE(narrowOop, \
coleenp@113 396 a, p, low, high, (closure)->do_oop##nv_suffix(p)) \
duke@0 397 } else { \
coleenp@113 398 HeapWord* low = start == 0 ? (HeapWord*)a : (HeapWord*)a->obj_at_addr<oop>(start); \
coleenp@113 399 HeapWord* high = (HeapWord*)((oop*)a->base() + end); \
coleenp@113 400 MemRegion mr(low, high); \
coleenp@113 401 if (closure->do_header()) { \
coleenp@113 402 a->oop_iterate_header(closure, mr); \
duke@0 403 } \
coleenp@113 404 ObjArrayKlass_SPECIALIZED_BOUNDED_OOP_ITERATE(oop, \
coleenp@113 405 a, p, low, high, (closure)->do_oop##nv_suffix(p)) \
duke@0 406 } \
duke@0 407 return size; \
duke@0 408 }
duke@0 409
duke@0 410 ALL_OOP_OOP_ITERATE_CLOSURES_1(ObjArrayKlass_OOP_OOP_ITERATE_DEFN)
ysr@342 411 ALL_OOP_OOP_ITERATE_CLOSURES_2(ObjArrayKlass_OOP_OOP_ITERATE_DEFN)
duke@0 412 ALL_OOP_OOP_ITERATE_CLOSURES_1(ObjArrayKlass_OOP_OOP_ITERATE_DEFN_m)
ysr@342 413 ALL_OOP_OOP_ITERATE_CLOSURES_2(ObjArrayKlass_OOP_OOP_ITERATE_DEFN_m)
coleenp@113 414 ALL_OOP_OOP_ITERATE_CLOSURES_1(ObjArrayKlass_OOP_OOP_ITERATE_DEFN_r)
ysr@342 415 ALL_OOP_OOP_ITERATE_CLOSURES_2(ObjArrayKlass_OOP_OOP_ITERATE_DEFN_r)
duke@0 416
duke@0 417 int objArrayKlass::oop_adjust_pointers(oop obj) {
duke@0 418 assert(obj->is_objArray(), "obj must be obj array");
duke@0 419 objArrayOop a = objArrayOop(obj);
duke@0 420 // Get size before changing pointers.
duke@0 421 // Don't call size() or oop_size() since that is a virtual call.
duke@0 422 int size = a->object_size();
duke@0 423 a->adjust_header();
coleenp@113 424 ObjArrayKlass_OOP_ITERATE(a, p, MarkSweep::adjust_pointer(p))
duke@0 425 return size;
duke@0 426 }
duke@0 427
duke@0 428 #ifndef SERIALGC
duke@0 429 void objArrayKlass::oop_copy_contents(PSPromotionManager* pm, oop obj) {
duke@0 430 assert(!pm->depth_first(), "invariant");
duke@0 431 assert(obj->is_objArray(), "obj must be obj array");
coleenp@113 432 ObjArrayKlass_OOP_ITERATE( \
coleenp@113 433 objArrayOop(obj), p, \
coleenp@113 434 if (PSScavenge::should_scavenge(p)) { \
coleenp@113 435 pm->claim_or_forward_breadth(p); \
coleenp@113 436 })
duke@0 437 }
duke@0 438
duke@0 439 void objArrayKlass::oop_push_contents(PSPromotionManager* pm, oop obj) {
duke@0 440 assert(pm->depth_first(), "invariant");
duke@0 441 assert(obj->is_objArray(), "obj must be obj array");
coleenp@113 442 ObjArrayKlass_OOP_ITERATE( \
coleenp@113 443 objArrayOop(obj), p, \
coleenp@113 444 if (PSScavenge::should_scavenge(p)) { \
coleenp@113 445 pm->claim_or_forward_depth(p); \
coleenp@113 446 })
duke@0 447 }
duke@0 448
duke@0 449 int objArrayKlass::oop_update_pointers(ParCompactionManager* cm, oop obj) {
duke@0 450 assert (obj->is_objArray(), "obj must be obj array");
duke@0 451 objArrayOop a = objArrayOop(obj);
coleenp@113 452 ObjArrayKlass_OOP_ITERATE(a, p, PSParallelCompact::adjust_pointer(p))
duke@0 453 return a->object_size();
duke@0 454 }
duke@0 455
duke@0 456 int objArrayKlass::oop_update_pointers(ParCompactionManager* cm, oop obj,
duke@0 457 HeapWord* beg_addr, HeapWord* end_addr) {
duke@0 458 assert (obj->is_objArray(), "obj must be obj array");
duke@0 459 objArrayOop a = objArrayOop(obj);
coleenp@113 460 ObjArrayKlass_BOUNDED_OOP_ITERATE( \
coleenp@113 461 a, p, beg_addr, end_addr, \
coleenp@113 462 PSParallelCompact::adjust_pointer(p))
duke@0 463 return a->object_size();
duke@0 464 }
duke@0 465 #endif // SERIALGC
duke@0 466
duke@0 467 // JVM support
duke@0 468
duke@0 469 jint objArrayKlass::compute_modifier_flags(TRAPS) const {
duke@0 470 // The modifier for an objectArray is the same as its element
duke@0 471 if (element_klass() == NULL) {
duke@0 472 assert(Universe::is_bootstrapping(), "partial objArray only at startup");
duke@0 473 return JVM_ACC_ABSTRACT | JVM_ACC_FINAL | JVM_ACC_PUBLIC;
duke@0 474 }
coleenp@398 475 // Return the flags of the bottom element type.
coleenp@398 476 jint element_flags = Klass::cast(bottom_klass())->compute_modifier_flags(CHECK_0);
duke@0 477
duke@0 478 return (element_flags & (JVM_ACC_PUBLIC | JVM_ACC_PRIVATE | JVM_ACC_PROTECTED))
duke@0 479 | (JVM_ACC_ABSTRACT | JVM_ACC_FINAL);
duke@0 480 }
duke@0 481
duke@0 482
duke@0 483 #ifndef PRODUCT
duke@0 484 // Printing
duke@0 485
duke@0 486 void objArrayKlass::oop_print_on(oop obj, outputStream* st) {
duke@0 487 arrayKlass::oop_print_on(obj, st);
duke@0 488 assert(obj->is_objArray(), "must be objArray");
duke@0 489 objArrayOop oa = objArrayOop(obj);
duke@0 490 int print_len = MIN2((intx) oa->length(), MaxElementPrintSize);
duke@0 491 for(int index = 0; index < print_len; index++) {
duke@0 492 st->print(" - %3d : ", index);
duke@0 493 oa->obj_at(index)->print_value_on(st);
duke@0 494 st->cr();
duke@0 495 }
duke@0 496 int remaining = oa->length() - print_len;
duke@0 497 if (remaining > 0) {
duke@0 498 tty->print_cr(" - <%d more elements, increase MaxElementPrintSize to print>", remaining);
duke@0 499 }
duke@0 500 }
duke@0 501
jrose@665 502 static int max_objArray_print_length = 4;
duke@0 503
duke@0 504 void objArrayKlass::oop_print_value_on(oop obj, outputStream* st) {
duke@0 505 assert(obj->is_objArray(), "must be objArray");
jrose@665 506 st->print("a ");
duke@0 507 element_klass()->print_value_on(st);
jrose@665 508 int len = objArrayOop(obj)->length();
jrose@665 509 st->print("[%d] ", len);
jrose@665 510 obj->print_address_on(st);
jrose@665 511 if (PrintOopAddress || PrintMiscellaneous && (WizardMode || Verbose)) {
jrose@665 512 st->print("{");
jrose@665 513 for (int i = 0; i < len; i++) {
jrose@665 514 if (i > max_objArray_print_length) {
jrose@665 515 st->print("..."); break;
jrose@665 516 }
jrose@665 517 st->print(" "INTPTR_FORMAT, (intptr_t)(void*)objArrayOop(obj)->obj_at(i));
jrose@665 518 }
jrose@665 519 st->print(" }");
jrose@665 520 }
duke@0 521 }
duke@0 522
duke@0 523 #endif // PRODUCT
duke@0 524
duke@0 525 const char* objArrayKlass::internal_name() const {
duke@0 526 return external_name();
duke@0 527 }
duke@0 528
duke@0 529 // Verification
duke@0 530
duke@0 531 void objArrayKlass::oop_verify_on(oop obj, outputStream* st) {
duke@0 532 arrayKlass::oop_verify_on(obj, st);
duke@0 533 guarantee(obj->is_objArray(), "must be objArray");
duke@0 534 objArrayOop oa = objArrayOop(obj);
duke@0 535 for(int index = 0; index < oa->length(); index++) {
duke@0 536 guarantee(oa->obj_at(index)->is_oop_or_null(), "should be oop");
duke@0 537 }
duke@0 538 }
duke@0 539
duke@0 540 void objArrayKlass::oop_verify_old_oop(oop obj, oop* p, bool allow_dirty) {
duke@0 541 /* $$$ move into remembered set verification?
duke@0 542 RememberedSet::verify_old_oop(obj, p, allow_dirty, true);
duke@0 543 */
duke@0 544 }
coleenp@113 545 void objArrayKlass::oop_verify_old_oop(oop obj, narrowOop* p, bool allow_dirty) {}