// Unevolving classes may point to methods of the evolving class directly // from their constantpool caches and vtables/itables. Fix this. void VM_RedefineClasses::adjust_cpool_cache_and_vtable(klassOop k_oop, oop loader) { Klass *k = k_oop->klass_part(); if (k->oop_is_instance()) { instanceKlass *ik = (instanceKlass *) k; bool previous_version; // By this time we have already replaced the constantpool pointer in the evolving // class itself. However, we need to fix the entries in the old constantpool, which // is still referenced by active old methods of this class. constantPoolCacheOop cp_cache = (k_oop == _evolving_koop) ? _old_constants->cache() : ik->constants()->cache(); do { if (cp_cache != NULL) { cp_cache->adjust_method_entries(_old_methods, _new_methods); } // Fix vtable (this is needed for the evolving class itself and its subclasses). if (ik->vtable_length() > 0 && ik->is_subclass_of(_evolving_koop)) { ik->vtable()->adjust_entries(_old_methods, _new_methods); } // Fix itable, if it exists. if (ik->itable_length() > 0) { ik->itable()->adjust_method_entries(_old_methods, _new_methods); } // Previous version methods could be still on stack so adjust entries // in all previous versions. if (ik->has_previous_version()) { ik = (instanceKlass *)(ik->previous_version())->klass_part(); cp_cache = ik->constants()->cache(); previous_version = true; } else { previous_version = false; } } while (previous_version); } }
// ------------------------------------------------------------------ // ciFieldLayout::fill_in_instance_fields // // Set up the instance fields in this ciFieldLayout. void ciFieldLayout::fill_in_instance_fields(GrowableArray<BasicType>* fieldtypes, GrowableArray<int>* fieldoffsets, GrowableArray<int>* aflags, int& pos, klassOop current) { Klass* k = current->klass_part(); assert(k->oop_is_instance(), "must be instanceKlass"); instanceKlass* ik = (instanceKlass*)k; klassOop super = k->super(); if (super) { fill_in_instance_fields(fieldtypes, fieldoffsets, aflags, pos, super); } // Fill in this klass's instance fields. typeArrayOop field_list = ik->fields(); constantPoolOop cpool = ik->constants(); uint num_fields = field_list->length(); for (uint i = 0; i < num_fields; i += instanceKlass::next_offset) { AccessFlags flags; flags.set_flags(field_list->short_at(i + instanceKlass::access_flags_offset)); if (!flags.is_static()) { // This is an instance field. Add it to our list. int field_offset = ik->offset_from_fields( i ); // Add the type to our list. symbolOop type_sym = cpool->symbol_at(field_list->short_at(i+ instanceKlass::signature_index_offset)); BasicType field_type; field_type = type2field[FieldType::basic_type(type_sym)]; fieldtypes->at_put_grow(pos, field_type, T_VOID); aflags->at_put_grow(pos, flags.as_int(), 0); // The field offset we set here includes the header_size fieldoffsets->at_put_grow(pos, field_offset, 0); pos++; } } }
void Klass::initialize_supers(klassOop k, TRAPS) { if (FastSuperclassLimit == 0) { // None of the other machinery matters. set_super(k); return; } if (k == NULL) { set_super(NULL); oop_store_without_check((oop*) &_primary_supers[0], (oop) this->as_klassOop()); assert(super_depth() == 0, "Object must already be initialized properly"); } else if (k != super() || k == SystemDictionary::Object_klass()) { assert(super() == NULL || super() == SystemDictionary::Object_klass(), "initialize this only once to a non-trivial value"); set_super(k); Klass* sup = k->klass_part(); int sup_depth = sup->super_depth(); juint my_depth = MIN2(sup_depth + 1, (int)primary_super_limit()); if (!can_be_primary_super_slow()) my_depth = primary_super_limit(); for (juint i = 0; i < my_depth; i++) { oop_store_without_check((oop*) &_primary_supers[i], (oop) sup->_primary_supers[i]); } klassOop *super_check_cell; if (my_depth < primary_super_limit()) { oop_store_without_check((oop*) &_primary_supers[my_depth], (oop) this->as_klassOop()); super_check_cell = &_primary_supers[my_depth]; } else { // Overflow of the primary_supers array forces me to be secondary. super_check_cell = &_secondary_super_cache; } set_super_check_offset((address)super_check_cell - (address) this->as_klassOop()); #ifdef ASSERT { juint j = super_depth(); assert(j == my_depth, "computed accessor gets right answer"); klassOop t = as_klassOop(); while (!Klass::cast(t)->can_be_primary_super()) { t = Klass::cast(t)->super(); j = Klass::cast(t)->super_depth(); } for (juint j1 = j+1; j1 < primary_super_limit(); j1++) { assert(primary_super_of_depth(j1) == NULL, "super list padding"); } while (t != NULL) { assert(primary_super_of_depth(j) == t, "super list initialization"); t = Klass::cast(t)->super(); --j; } assert(j == (juint)-1, "correct depth count"); } #endif } if (secondary_supers() == NULL) { KlassHandle this_kh (THREAD, this); // Now compute the list of secondary supertypes. // Secondaries can occasionally be on the super chain, // if the inline "_primary_supers" array overflows. int extras = 0; klassOop p; for (p = super(); !(p == NULL || p->klass_part()->can_be_primary_super()); p = p->klass_part()->super()) { ++extras; } // Compute the "real" non-extra secondaries. objArrayOop secondary_oops = compute_secondary_supers(extras, CHECK); objArrayHandle secondaries (THREAD, secondary_oops); // Store the extra secondaries in the first array positions: int fillp = extras; for (p = this_kh->super(); !(p == NULL || p->klass_part()->can_be_primary_super()); p = p->klass_part()->super()) { int i; // Scan for overflow primaries being duplicates of 2nd'arys // This happens frequently for very deeply nested arrays: the // primary superclass chain overflows into the secondary. The // secondary list contains the element_klass's secondaries with // an extra array dimension added. If the element_klass's // secondary list already contains some primary overflows, they // (with the extra level of array-ness) will collide with the // normal primary superclass overflows. for( i = extras; i < secondaries->length(); i++ ) if( secondaries->obj_at(i) == p ) break; if( i < secondaries->length() ) continue; // It's a dup, don't put it in secondaries->obj_at_put(--fillp, p); } // See if we had some dup's, so the array has holes in it. if( fillp > 0 ) { // Pack the array. Drop the old secondaries array on the floor // and let GC reclaim it. objArrayOop s2 = oopFactory::new_system_objArray(secondaries->length() - fillp, CHECK); for( int i = 0; i < s2->length(); i++ ) s2->obj_at_put( i, secondaries->obj_at(i+fillp) ); secondaries = objArrayHandle(THREAD, s2); } #ifdef ASSERT if (secondaries() != Universe::the_array_interfaces_array()) { // We must not copy any NULL placeholders left over from bootstrap. for (int j = 0; j < secondaries->length(); j++) { assert(secondaries->obj_at(j) != NULL, "correct bootstrapping order"); } } #endif this_kh->set_secondary_supers(secondaries()); } }
void Klass_vtbl::post_new_init_klass(KlassHandle& klass, klassOop new_klass) const { assert(!new_klass->klass_part()->null_vtbl(), "Not a complete klass"); CollectedHeap::post_allocation_install_obj_klass(klass, new_klass); }
void AllocationProfiler::add_classes_to_array(klassOop k) { // Iterate over klass and all array klasses for klass k->klass_part()->with_array_klasses_do(&AllocationProfiler::add_class_to_array); }
TESTF(ByteArrayKlassTests, allocateShouldNotFailWhenNotAllowedAndNoSpace) { eden_top = eden_end; ASSERT_TRUE(Universe::new_gen.eden()->free() < 4 * oopSize); ASSERT_TRUE(Universe::new_gen.contains(theClass->klass_part()->allocateObjectSize(100, true))); }
TESTF(ByteArrayKlassTests, allocateShouldAllocateTenuredWhenRequired) { ASSERT_TRUE(Universe::old_gen.contains(theClass->klass_part()->allocateObjectSize(100, false, true))); }
TESTF(ByteArrayKlassTests, allocateShouldFailWhenAllowedAndNoSpace) { eden_top = eden_end; ASSERT_EQUALS((int)NULL, (int)(theClass->klass_part()->allocateObjectSize(100, false))); }
TESTF(ByteArrayKlassTests, shouldBeDoubleByteArray) { eden_top = eden_end; ASSERT_TRUE(theClass->klass_part()->oop_is_byteArray()); }
TESTF(ContextKlassTests, allocateShouldAllocateTenuredWhenRequired) { ASSERT_TRUE(Universe::old_gen.contains(theClass->klass_part()->allocateObject(false, true))); }
TESTF(ContextKlassTests, allocateShouldFailWhenAllowedAndNoSpace) { eden_top = eden_end; ASSERT_EQUALS((int)NULL, (int)(theClass->klass_part()->allocateObject(false))); }
// Do not expose internal implementation specific classes bool is_visible_klass(klassOop k) { return k->klass_part()->oop_is_instance() || (k->klass_part()->oop_is_array() && k != Universe::systemObjArrayKlassObj()); }