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