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