src/share/vm/oops/objArrayKlass.cpp

Thu, 07 Apr 2011 09:53:20 -0700

author
johnc
date
Thu, 07 Apr 2011 09:53:20 -0700
changeset 2781
e1162778c1c8
parent 2534
e5383553fd4e
child 3638
a735aec54ea4
permissions
-rw-r--r--

7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
Summary: A referent object that is only weakly reachable at the start of concurrent marking but is re-attached to the strongly reachable object graph during marking may not be marked as live. This can cause the reference object to be processed prematurely and leave dangling pointers to the referent object. Implement a read barrier for the java.lang.ref.Reference::referent field by intrinsifying the Reference.get() method, and intercepting accesses though JNI, reflection, and Unsafe, so that when a non-null referent object is read it is also logged in an SATB buffer.
Reviewed-by: kvn, iveresov, never, tonyp, dholmes

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

mercurial