Mercurial > hg > truffle
diff src/share/vm/oops/instanceKlassKlass.cpp @ 0:a61af66fc99e jdk7-b24
Initial load
author | duke |
---|---|
date | Sat, 01 Dec 2007 00:00:00 +0000 |
parents | |
children | ba764ed4b6f2 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/vm/oops/instanceKlassKlass.cpp Sat Dec 01 00:00:00 2007 +0000 @@ -0,0 +1,809 @@ +/* + * Copyright 1997-2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + * + */ + +# include "incls/_precompiled.incl" +# include "incls/_instanceKlassKlass.cpp.incl" + +klassOop instanceKlassKlass::create_klass(TRAPS) { + instanceKlassKlass o; + KlassHandle h_this_klass(THREAD, Universe::klassKlassObj()); + KlassHandle k = base_create_klass(h_this_klass, header_size(), o.vtbl_value(), CHECK_NULL); + // Make sure size calculation is right + assert(k()->size() == align_object_size(header_size()), "wrong size for object"); + java_lang_Class::create_mirror(k, CHECK_NULL); // Allocate mirror + return k(); +} + +int instanceKlassKlass::oop_size(oop obj) const { + assert(obj->is_klass(), "must be klass"); + return instanceKlass::cast(klassOop(obj))->object_size(); +} + +bool instanceKlassKlass::oop_is_parsable(oop obj) const { + assert(obj->is_klass(), "must be klass"); + instanceKlass* ik = instanceKlass::cast(klassOop(obj)); + return (!ik->null_vtbl()) && ik->object_is_parsable(); +} + +void instanceKlassKlass::iterate_c_heap_oops(instanceKlass* ik, + OopClosure* closure) { + if (ik->oop_map_cache() != NULL) { + ik->oop_map_cache()->oop_iterate(closure); + } + + if (ik->jni_ids() != NULL) { + ik->jni_ids()->oops_do(closure); + } +} + +void instanceKlassKlass::oop_follow_contents(oop obj) { + assert(obj->is_klass(),"must be a klass"); + assert(klassOop(obj)->klass_part()->oop_is_instance_slow(), "must be instance klass"); + + instanceKlass* ik = instanceKlass::cast(klassOop(obj)); + ik->follow_static_fields(); + { + HandleMark hm; + ik->vtable()->oop_follow_contents(); + ik->itable()->oop_follow_contents(); + } + + MarkSweep::mark_and_push(ik->adr_array_klasses()); + MarkSweep::mark_and_push(ik->adr_methods()); + MarkSweep::mark_and_push(ik->adr_method_ordering()); + MarkSweep::mark_and_push(ik->adr_local_interfaces()); + MarkSweep::mark_and_push(ik->adr_transitive_interfaces()); + MarkSweep::mark_and_push(ik->adr_fields()); + MarkSweep::mark_and_push(ik->adr_constants()); + MarkSweep::mark_and_push(ik->adr_class_loader()); + MarkSweep::mark_and_push(ik->adr_source_file_name()); + MarkSweep::mark_and_push(ik->adr_source_debug_extension()); + MarkSweep::mark_and_push(ik->adr_inner_classes()); + MarkSweep::mark_and_push(ik->adr_protection_domain()); + MarkSweep::mark_and_push(ik->adr_signers()); + MarkSweep::mark_and_push(ik->adr_generic_signature()); + MarkSweep::mark_and_push(ik->adr_class_annotations()); + MarkSweep::mark_and_push(ik->adr_fields_annotations()); + MarkSweep::mark_and_push(ik->adr_methods_annotations()); + MarkSweep::mark_and_push(ik->adr_methods_parameter_annotations()); + MarkSweep::mark_and_push(ik->adr_methods_default_annotations()); + + // We do not follow adr_implementors() here. It is followed later + // in instanceKlass::follow_weak_klass_links() + + klassKlass::oop_follow_contents(obj); + + iterate_c_heap_oops(ik, &MarkSweep::mark_and_push_closure); +} + +#ifndef SERIALGC +void instanceKlassKlass::oop_follow_contents(ParCompactionManager* cm, + oop obj) { + assert(obj->is_klass(),"must be a klass"); + assert(klassOop(obj)->klass_part()->oop_is_instance_slow(), "must be instance klass"); + + instanceKlass* ik = instanceKlass::cast(klassOop(obj)); + ik->follow_static_fields(cm); + ik->vtable()->oop_follow_contents(cm); + ik->itable()->oop_follow_contents(cm); + + PSParallelCompact::mark_and_push(cm, ik->adr_array_klasses()); + PSParallelCompact::mark_and_push(cm, ik->adr_methods()); + PSParallelCompact::mark_and_push(cm, ik->adr_method_ordering()); + PSParallelCompact::mark_and_push(cm, ik->adr_local_interfaces()); + PSParallelCompact::mark_and_push(cm, ik->adr_transitive_interfaces()); + PSParallelCompact::mark_and_push(cm, ik->adr_fields()); + PSParallelCompact::mark_and_push(cm, ik->adr_constants()); + PSParallelCompact::mark_and_push(cm, ik->adr_class_loader()); + PSParallelCompact::mark_and_push(cm, ik->adr_source_file_name()); + PSParallelCompact::mark_and_push(cm, ik->adr_source_debug_extension()); + PSParallelCompact::mark_and_push(cm, ik->adr_inner_classes()); + PSParallelCompact::mark_and_push(cm, ik->adr_protection_domain()); + PSParallelCompact::mark_and_push(cm, ik->adr_signers()); + PSParallelCompact::mark_and_push(cm, ik->adr_generic_signature()); + PSParallelCompact::mark_and_push(cm, ik->adr_class_annotations()); + PSParallelCompact::mark_and_push(cm, ik->adr_fields_annotations()); + PSParallelCompact::mark_and_push(cm, ik->adr_methods_annotations()); + PSParallelCompact::mark_and_push(cm, ik->adr_methods_parameter_annotations()); + PSParallelCompact::mark_and_push(cm, ik->adr_methods_default_annotations()); + + // We do not follow adr_implementor() here. It is followed later + // in instanceKlass::follow_weak_klass_links() + + klassKlass::oop_follow_contents(cm, obj); + + PSParallelCompact::MarkAndPushClosure mark_and_push_closure(cm); + iterate_c_heap_oops(ik, &mark_and_push_closure); +} +#endif // SERIALGC + +int instanceKlassKlass::oop_oop_iterate(oop obj, OopClosure* blk) { + assert(obj->is_klass(),"must be a klass"); + assert(klassOop(obj)->klass_part()->oop_is_instance_slow(), "must be instance klass"); + instanceKlass* ik = instanceKlass::cast(klassOop(obj)); + // Get size before changing pointers. + // Don't call size() or oop_size() since that is a virtual call. + int size = ik->object_size(); + + ik->iterate_static_fields(blk); + ik->vtable()->oop_oop_iterate(blk); + ik->itable()->oop_oop_iterate(blk); + + blk->do_oop(ik->adr_array_klasses()); + blk->do_oop(ik->adr_methods()); + blk->do_oop(ik->adr_method_ordering()); + blk->do_oop(ik->adr_local_interfaces()); + blk->do_oop(ik->adr_transitive_interfaces()); + blk->do_oop(ik->adr_fields()); + blk->do_oop(ik->adr_constants()); + blk->do_oop(ik->adr_class_loader()); + blk->do_oop(ik->adr_protection_domain()); + blk->do_oop(ik->adr_signers()); + blk->do_oop(ik->adr_source_file_name()); + blk->do_oop(ik->adr_source_debug_extension()); + blk->do_oop(ik->adr_inner_classes()); + for (int i = 0; i < instanceKlass::implementors_limit; i++) { + blk->do_oop(&ik->adr_implementors()[i]); + } + blk->do_oop(ik->adr_generic_signature()); + blk->do_oop(ik->adr_class_annotations()); + blk->do_oop(ik->adr_fields_annotations()); + blk->do_oop(ik->adr_methods_annotations()); + blk->do_oop(ik->adr_methods_parameter_annotations()); + blk->do_oop(ik->adr_methods_default_annotations()); + + klassKlass::oop_oop_iterate(obj, blk); + + if(ik->oop_map_cache() != NULL) ik->oop_map_cache()->oop_iterate(blk); + return size; +} + +int instanceKlassKlass::oop_oop_iterate_m(oop obj, OopClosure* blk, + MemRegion mr) { + assert(obj->is_klass(),"must be a klass"); + assert(klassOop(obj)->klass_part()->oop_is_instance_slow(), "must be instance klass"); + instanceKlass* ik = instanceKlass::cast(klassOop(obj)); + // Get size before changing pointers. + // Don't call size() or oop_size() since that is a virtual call. + int size = ik->object_size(); + + ik->iterate_static_fields(blk, mr); + ik->vtable()->oop_oop_iterate_m(blk, mr); + ik->itable()->oop_oop_iterate_m(blk, mr); + + oop* adr; + adr = ik->adr_array_klasses(); + if (mr.contains(adr)) blk->do_oop(adr); + adr = ik->adr_methods(); + if (mr.contains(adr)) blk->do_oop(adr); + adr = ik->adr_method_ordering(); + if (mr.contains(adr)) blk->do_oop(adr); + adr = ik->adr_local_interfaces(); + if (mr.contains(adr)) blk->do_oop(adr); + adr = ik->adr_transitive_interfaces(); + if (mr.contains(adr)) blk->do_oop(adr); + adr = ik->adr_fields(); + if (mr.contains(adr)) blk->do_oop(adr); + adr = ik->adr_constants(); + if (mr.contains(adr)) blk->do_oop(adr); + adr = ik->adr_class_loader(); + if (mr.contains(adr)) blk->do_oop(adr); + adr = ik->adr_protection_domain(); + if (mr.contains(adr)) blk->do_oop(adr); + adr = ik->adr_signers(); + if (mr.contains(adr)) blk->do_oop(adr); + adr = ik->adr_source_file_name(); + if (mr.contains(adr)) blk->do_oop(adr); + adr = ik->adr_source_debug_extension(); + if (mr.contains(adr)) blk->do_oop(adr); + adr = ik->adr_inner_classes(); + if (mr.contains(adr)) blk->do_oop(adr); + adr = ik->adr_implementors(); + for (int i = 0; i < instanceKlass::implementors_limit; i++) { + if (mr.contains(&adr[i])) blk->do_oop(&adr[i]); + } + adr = ik->adr_generic_signature(); + if (mr.contains(adr)) blk->do_oop(adr); + adr = ik->adr_class_annotations(); + if (mr.contains(adr)) blk->do_oop(adr); + adr = ik->adr_fields_annotations(); + if (mr.contains(adr)) blk->do_oop(adr); + adr = ik->adr_methods_annotations(); + if (mr.contains(adr)) blk->do_oop(adr); + adr = ik->adr_methods_parameter_annotations(); + if (mr.contains(adr)) blk->do_oop(adr); + adr = ik->adr_methods_default_annotations(); + if (mr.contains(adr)) blk->do_oop(adr); + + klassKlass::oop_oop_iterate_m(obj, blk, mr); + + if(ik->oop_map_cache() != NULL) ik->oop_map_cache()->oop_iterate(blk, mr); + return size; +} + +int instanceKlassKlass::oop_adjust_pointers(oop obj) { + assert(obj->is_klass(),"must be a klass"); + assert(klassOop(obj)->klass_part()->oop_is_instance_slow(), "must be instance klass"); + + instanceKlass* ik = instanceKlass::cast(klassOop(obj)); + ik->adjust_static_fields(); + ik->vtable()->oop_adjust_pointers(); + ik->itable()->oop_adjust_pointers(); + + MarkSweep::adjust_pointer(ik->adr_array_klasses()); + MarkSweep::adjust_pointer(ik->adr_methods()); + MarkSweep::adjust_pointer(ik->adr_method_ordering()); + MarkSweep::adjust_pointer(ik->adr_local_interfaces()); + MarkSweep::adjust_pointer(ik->adr_transitive_interfaces()); + MarkSweep::adjust_pointer(ik->adr_fields()); + MarkSweep::adjust_pointer(ik->adr_constants()); + MarkSweep::adjust_pointer(ik->adr_class_loader()); + MarkSweep::adjust_pointer(ik->adr_protection_domain()); + MarkSweep::adjust_pointer(ik->adr_signers()); + MarkSweep::adjust_pointer(ik->adr_source_file_name()); + MarkSweep::adjust_pointer(ik->adr_source_debug_extension()); + MarkSweep::adjust_pointer(ik->adr_inner_classes()); + for (int i = 0; i < instanceKlass::implementors_limit; i++) { + MarkSweep::adjust_pointer(&ik->adr_implementors()[i]); + } + MarkSweep::adjust_pointer(ik->adr_generic_signature()); + MarkSweep::adjust_pointer(ik->adr_class_annotations()); + MarkSweep::adjust_pointer(ik->adr_fields_annotations()); + MarkSweep::adjust_pointer(ik->adr_methods_annotations()); + MarkSweep::adjust_pointer(ik->adr_methods_parameter_annotations()); + MarkSweep::adjust_pointer(ik->adr_methods_default_annotations()); + + iterate_c_heap_oops(ik, &MarkSweep::adjust_root_pointer_closure); + + return klassKlass::oop_adjust_pointers(obj); +} + +#ifndef SERIALGC +void instanceKlassKlass::oop_copy_contents(PSPromotionManager* pm, oop obj) { + assert(!pm->depth_first(), "invariant"); + instanceKlass* ik = instanceKlass::cast(klassOop(obj)); + ik->copy_static_fields(pm); + + oop* loader_addr = ik->adr_class_loader(); + if (PSScavenge::should_scavenge(*loader_addr)) { + pm->claim_or_forward_breadth(loader_addr); + } + + oop* pd_addr = ik->adr_protection_domain(); + if (PSScavenge::should_scavenge(*pd_addr)) { + pm->claim_or_forward_breadth(pd_addr); + } + + oop* sg_addr = ik->adr_signers(); + if (PSScavenge::should_scavenge(*sg_addr)) { + pm->claim_or_forward_breadth(sg_addr); + } + + klassKlass::oop_copy_contents(pm, obj); +} + +void instanceKlassKlass::oop_push_contents(PSPromotionManager* pm, oop obj) { + assert(pm->depth_first(), "invariant"); + instanceKlass* ik = instanceKlass::cast(klassOop(obj)); + ik->push_static_fields(pm); + + oop* loader_addr = ik->adr_class_loader(); + if (PSScavenge::should_scavenge(*loader_addr)) { + pm->claim_or_forward_depth(loader_addr); + } + + oop* pd_addr = ik->adr_protection_domain(); + if (PSScavenge::should_scavenge(*pd_addr)) { + pm->claim_or_forward_depth(pd_addr); + } + + oop* sg_addr = ik->adr_signers(); + if (PSScavenge::should_scavenge(*sg_addr)) { + pm->claim_or_forward_depth(sg_addr); + } + + klassKlass::oop_copy_contents(pm, obj); +} + +int instanceKlassKlass::oop_update_pointers(ParCompactionManager* cm, oop obj) { + assert(obj->is_klass(),"must be a klass"); + assert(klassOop(obj)->klass_part()->oop_is_instance_slow(), + "must be instance klass"); + + instanceKlass* ik = instanceKlass::cast(klassOop(obj)); + ik->update_static_fields(); + ik->vtable()->oop_update_pointers(cm); + ik->itable()->oop_update_pointers(cm); + + oop* const beg_oop = ik->oop_block_beg(); + oop* const end_oop = ik->oop_block_end(); + for (oop* cur_oop = beg_oop; cur_oop < end_oop; ++cur_oop) { + PSParallelCompact::adjust_pointer(cur_oop); + } + + OopClosure* closure = PSParallelCompact::adjust_root_pointer_closure(); + iterate_c_heap_oops(ik, closure); + + klassKlass::oop_update_pointers(cm, obj); + return ik->object_size(); +} + +int instanceKlassKlass::oop_update_pointers(ParCompactionManager* cm, oop obj, + HeapWord* beg_addr, + HeapWord* end_addr) { + assert(obj->is_klass(),"must be a klass"); + assert(klassOop(obj)->klass_part()->oop_is_instance_slow(), + "must be instance klass"); + + instanceKlass* ik = instanceKlass::cast(klassOop(obj)); + ik->update_static_fields(beg_addr, end_addr); + ik->vtable()->oop_update_pointers(cm, beg_addr, end_addr); + ik->itable()->oop_update_pointers(cm, beg_addr, end_addr); + + oop* const beg_oop = MAX2((oop*)beg_addr, ik->oop_block_beg()); + oop* const end_oop = MIN2((oop*)end_addr, ik->oop_block_end()); + for (oop* cur_oop = beg_oop; cur_oop < end_oop; ++cur_oop) { + PSParallelCompact::adjust_pointer(cur_oop); + } + + // The oop_map_cache, jni_ids and jni_id_map are allocated from the C heap, + // and so don't lie within any 'Chunk' boundaries. Update them when the + // lowest addressed oop in the instanceKlass 'oop_block' is updated. + if (beg_oop == ik->oop_block_beg()) { + OopClosure* closure = PSParallelCompact::adjust_root_pointer_closure(); + iterate_c_heap_oops(ik, closure); + } + + klassKlass::oop_update_pointers(cm, obj, beg_addr, end_addr); + return ik->object_size(); +} +#endif // SERIALGC + +klassOop instanceKlassKlass::allocate_instance_klass(int vtable_len, int itable_len, int static_field_size, + int nonstatic_oop_map_size, ReferenceType rt, TRAPS) { + + int size = instanceKlass::object_size(align_object_offset(vtable_len) + align_object_offset(itable_len) + static_field_size + nonstatic_oop_map_size); + + // Allocation + KlassHandle h_this_klass(THREAD, as_klassOop()); + KlassHandle k; + if (rt == REF_NONE) { + // regular klass + instanceKlass o; + k = base_create_klass(h_this_klass, size, o.vtbl_value(), CHECK_NULL); + } else { + // reference klass + instanceRefKlass o; + k = base_create_klass(h_this_klass, size, o.vtbl_value(), CHECK_NULL); + } + { + No_Safepoint_Verifier no_safepoint; // until k becomes parsable + instanceKlass* ik = (instanceKlass*) k()->klass_part(); + assert(!k()->is_parsable(), "not expecting parsability yet."); + + // The sizes of these these three variables are used for determining the + // size of the instanceKlassOop. It is critical that these are set to the right + // sizes before the first GC, i.e., when we allocate the mirror. + ik->set_vtable_length(vtable_len); + ik->set_itable_length(itable_len); + ik->set_static_field_size(static_field_size); + ik->set_nonstatic_oop_map_size(nonstatic_oop_map_size); + assert(k()->size() == size, "wrong size for object"); + + ik->set_array_klasses(NULL); + ik->set_methods(NULL); + ik->set_method_ordering(NULL); + ik->set_local_interfaces(NULL); + ik->set_transitive_interfaces(NULL); + ik->init_implementor(); + ik->set_fields(NULL); + ik->set_constants(NULL); + ik->set_class_loader(NULL); + ik->set_protection_domain(NULL); + ik->set_signers(NULL); + ik->set_source_file_name(NULL); + ik->set_source_debug_extension(NULL); + ik->set_inner_classes(NULL); + ik->set_static_oop_field_size(0); + ik->set_nonstatic_field_size(0); + ik->set_is_marked_dependent(false); + ik->set_init_state(instanceKlass::allocated); + ik->set_init_thread(NULL); + ik->set_reference_type(rt); + ik->set_oop_map_cache(NULL); + ik->set_jni_ids(NULL); + ik->set_osr_nmethods_head(NULL); + ik->set_breakpoints(NULL); + ik->init_previous_versions(); + ik->set_generic_signature(NULL); + ik->release_set_methods_jmethod_ids(NULL); + ik->release_set_methods_cached_itable_indices(NULL); + ik->set_class_annotations(NULL); + ik->set_fields_annotations(NULL); + ik->set_methods_annotations(NULL); + ik->set_methods_parameter_annotations(NULL); + ik->set_methods_default_annotations(NULL); + ik->set_enclosing_method_indices(0, 0); + ik->set_jvmti_cached_class_field_map(NULL); + ik->set_initial_method_idnum(0); + assert(k()->is_parsable(), "should be parsable here."); + + // initialize the non-header words to zero + intptr_t* p = (intptr_t*)k(); + for (int index = instanceKlass::header_size(); index < size; index++) { + p[index] = NULL_WORD; + } + + // To get verify to work - must be set to partial loaded before first GC point. + k()->set_partially_loaded(); + } + + // GC can happen here + java_lang_Class::create_mirror(k, CHECK_NULL); // Allocate mirror + return k(); +} + + + +#ifndef PRODUCT + +// Printing + +static const char* state_names[] = { + "unparseable_by_gc", "allocated", "loaded", "linked", "being_initialized", "fully_initialized", "initialization_error" +}; + + +void instanceKlassKlass::oop_print_on(oop obj, outputStream* st) { + assert(obj->is_klass(), "must be klass"); + instanceKlass* ik = instanceKlass::cast(klassOop(obj)); + klassKlass::oop_print_on(obj, st); + + st->print(" - instance size: %d", ik->size_helper()); st->cr(); + st->print(" - klass size: %d", ik->object_size()); st->cr(); + st->print(" - access: "); ik->access_flags().print_on(st); st->cr(); + st->print(" - state: "); st->print_cr(state_names[ik->_init_state]); + st->print(" - name: "); ik->name()->print_value_on(st); st->cr(); + st->print(" - super: "); ik->super()->print_value_on(st); st->cr(); + st->print(" - sub: "); + Klass* sub = ik->subklass(); + int n; + for (n = 0; sub != NULL; n++, sub = sub->next_sibling()) { + if (n < MaxSubklassPrintSize) { + sub->as_klassOop()->print_value_on(st); + st->print(" "); + } + } + if (n >= MaxSubklassPrintSize) st->print("(%d more klasses...)", n - MaxSubklassPrintSize); + st->cr(); + + if (ik->is_interface()) { + st->print_cr(" - nof implementors: %d", ik->nof_implementors()); + int print_impl = 0; + for (int i = 0; i < instanceKlass::implementors_limit; i++) { + if (ik->implementor(i) != NULL) { + if (++print_impl == 1) + st->print_cr(" - implementor: "); + st->print(" "); + ik->implementor(i)->print_value_on(st); + } + } + if (print_impl > 0) st->cr(); + } + + st->print(" - arrays: "); ik->array_klasses()->print_value_on(st); st->cr(); + st->print(" - methods: "); ik->methods()->print_value_on(st); st->cr(); + if (Verbose) { + objArrayOop methods = ik->methods(); + for(int i = 0; i < methods->length(); i++) { + tty->print("%d : ", i); methods->obj_at(i)->print_value(); tty->cr(); + } + } + st->print(" - method ordering: "); ik->method_ordering()->print_value_on(st); st->cr(); + st->print(" - local interfaces: "); ik->local_interfaces()->print_value_on(st); st->cr(); + st->print(" - trans. interfaces: "); ik->transitive_interfaces()->print_value_on(st); st->cr(); + st->print(" - constants: "); ik->constants()->print_value_on(st); st->cr(); + st->print(" - class loader: "); ik->class_loader()->print_value_on(st); st->cr(); + st->print(" - protection domain: "); ik->protection_domain()->print_value_on(st); st->cr(); + st->print(" - signers: "); ik->signers()->print_value_on(st); st->cr(); + if (ik->source_file_name() != NULL) { + st->print(" - source file: "); + ik->source_file_name()->print_value_on(st); + st->cr(); + } + if (ik->source_debug_extension() != NULL) { + st->print(" - source debug extension: "); + ik->source_debug_extension()->print_value_on(st); + st->cr(); + } + + st->print_cr(" - previous version: "); + { + ResourceMark rm; + // PreviousVersionInfo objects returned via PreviousVersionWalker + // contain a GrowableArray of handles. We have to clean up the + // GrowableArray _after_ the PreviousVersionWalker destructor + // has destroyed the handles. + { + PreviousVersionWalker pvw(ik); + for (PreviousVersionInfo * pv_info = pvw.next_previous_version(); + pv_info != NULL; pv_info = pvw.next_previous_version()) { + pv_info->prev_constant_pool_handle()()->print_value_on(st); + } + st->cr(); + } // pvw is cleaned up + } // rm is cleaned up + + if (ik->generic_signature() != NULL) { + st->print(" - generic signature: "); + ik->generic_signature()->print_value_on(st); + } + st->print(" - inner classes: "); ik->inner_classes()->print_value_on(st); st->cr(); + st->print(" - java mirror: "); ik->java_mirror()->print_value_on(st); st->cr(); + st->print(" - vtable length %d (start addr: " INTPTR_FORMAT ")", ik->vtable_length(), ik->start_of_vtable()); st->cr(); + st->print(" - itable length %d (start addr: " INTPTR_FORMAT ")", ik->itable_length(), ik->start_of_itable()); st->cr(); + st->print_cr(" - static fields:"); + FieldPrinter print_static_field(st); + ik->do_local_static_fields(&print_static_field); + st->print_cr(" - non-static fields:"); + FieldPrinter print_nonstatic_field(st, obj); + ik->do_nonstatic_fields(&print_nonstatic_field); + + st->print(" - static oop maps: "); + if (ik->static_oop_field_size() > 0) { + int first_offset = ik->offset_of_static_fields(); + st->print("%d-%d", first_offset, first_offset + ik->static_oop_field_size() - 1); + } + st->cr(); + + st->print(" - non-static oop maps: "); + OopMapBlock* map = ik->start_of_nonstatic_oop_maps(); + OopMapBlock* end_map = map + ik->nonstatic_oop_map_size(); + while (map < end_map) { + st->print("%d-%d ", map->offset(), map->offset() + oopSize*(map->length() - 1)); + map++; + } + st->cr(); +} + + +void instanceKlassKlass::oop_print_value_on(oop obj, outputStream* st) { + assert(obj->is_klass(), "must be klass"); + instanceKlass* ik = instanceKlass::cast(klassOop(obj)); + ik->name()->print_value_on(st); +} + +#endif // PRODUCT + +const char* instanceKlassKlass::internal_name() const { + return "{instance class}"; +} + +// Verification + + +class VerifyFieldClosure: public OopClosure { + public: + void do_oop(oop* p) { + guarantee(Universe::heap()->is_in(p), "should be in heap"); + guarantee((*p)->is_oop_or_null(), "should be in heap"); + } +}; + + +void instanceKlassKlass::oop_verify_on(oop obj, outputStream* st) { + klassKlass::oop_verify_on(obj, st); + if (!obj->partially_loaded()) { + Thread *thread = Thread::current(); + instanceKlass* ik = instanceKlass::cast(klassOop(obj)); + +#ifndef PRODUCT + // Avoid redundant verifies + if (ik->_verify_count == Universe::verify_count()) return; + ik->_verify_count = Universe::verify_count(); +#endif + // Verify that klass is present in SystemDictionary + if (ik->is_loaded()) { + symbolHandle h_name (thread, ik->name()); + Handle h_loader (thread, ik->class_loader()); + Handle h_obj(thread, obj); + SystemDictionary::verify_obj_klass_present(h_obj, h_name, h_loader); + } + + // Verify static fields + VerifyFieldClosure blk; + ik->iterate_static_fields(&blk); + + // Verify vtables + if (ik->is_linked()) { + ResourceMark rm(thread); + // $$$ This used to be done only for m/s collections. Doing it + // always seemed a valid generalization. (DLD -- 6/00) + ik->vtable()->verify(st); + } + + // Verify oop map cache + if (ik->oop_map_cache() != NULL) { + ik->oop_map_cache()->verify(); + } + + // Verify first subklass + if (ik->subklass_oop() != NULL) { + guarantee(ik->subklass_oop()->is_perm(), "should be in permspace"); + guarantee(ik->subklass_oop()->is_klass(), "should be klass"); + } + + // Verify siblings + klassOop super = ik->super(); + Klass* sib = ik->next_sibling(); + int sib_count = 0; + while (sib != NULL) { + if (sib == ik) { + fatal1("subclass cycle of length %d", sib_count); + } + if (sib_count >= 100000) { + fatal1("suspiciously long subclass list %d", sib_count); + } + guarantee(sib->as_klassOop()->is_klass(), "should be klass"); + guarantee(sib->as_klassOop()->is_perm(), "should be in permspace"); + guarantee(sib->super() == super, "siblings should have same superklass"); + sib = sib->next_sibling(); + } + + // Verify implementor fields + bool saw_null_impl = false; + for (int i = 0; i < instanceKlass::implementors_limit; i++) { + klassOop im = ik->implementor(i); + if (im == NULL) { saw_null_impl = true; continue; } + guarantee(!saw_null_impl, "non-nulls must preceded all nulls"); + guarantee(ik->is_interface(), "only interfaces should have implementor set"); + guarantee(i < ik->nof_implementors(), "should only have one implementor"); + guarantee(im->is_perm(), "should be in permspace"); + guarantee(im->is_klass(), "should be klass"); + guarantee(!Klass::cast(klassOop(im))->is_interface(), "implementors cannot be interfaces"); + } + + // Verify local interfaces + objArrayOop local_interfaces = ik->local_interfaces(); + guarantee(local_interfaces->is_perm(), "should be in permspace"); + guarantee(local_interfaces->is_objArray(), "should be obj array"); + int j; + for (j = 0; j < local_interfaces->length(); j++) { + oop e = local_interfaces->obj_at(j); + guarantee(e->is_klass() && Klass::cast(klassOop(e))->is_interface(), "invalid local interface"); + } + + // Verify transitive interfaces + objArrayOop transitive_interfaces = ik->transitive_interfaces(); + guarantee(transitive_interfaces->is_perm(), "should be in permspace"); + guarantee(transitive_interfaces->is_objArray(), "should be obj array"); + for (j = 0; j < transitive_interfaces->length(); j++) { + oop e = transitive_interfaces->obj_at(j); + guarantee(e->is_klass() && Klass::cast(klassOop(e))->is_interface(), "invalid transitive interface"); + } + + // Verify methods + objArrayOop methods = ik->methods(); + guarantee(methods->is_perm(), "should be in permspace"); + guarantee(methods->is_objArray(), "should be obj array"); + for (j = 0; j < methods->length(); j++) { + guarantee(methods->obj_at(j)->is_method(), "non-method in methods array"); + } + for (j = 0; j < methods->length() - 1; j++) { + methodOop m1 = methodOop(methods->obj_at(j)); + methodOop m2 = methodOop(methods->obj_at(j + 1)); + guarantee(m1->name()->fast_compare(m2->name()) <= 0, "methods not sorted correctly"); + } + + // Verify method ordering + typeArrayOop method_ordering = ik->method_ordering(); + guarantee(method_ordering->is_perm(), "should be in permspace"); + guarantee(method_ordering->is_typeArray(), "should be type array"); + int length = method_ordering->length(); + if (JvmtiExport::can_maintain_original_method_order()) { + guarantee(length == methods->length(), "invalid method ordering length"); + jlong sum = 0; + for (j = 0; j < length; j++) { + int original_index = method_ordering->int_at(j); + guarantee(original_index >= 0 && original_index < length, "invalid method ordering index"); + sum += original_index; + } + // Verify sum of indices 0,1,...,length-1 + guarantee(sum == ((jlong)length*(length-1))/2, "invalid method ordering sum"); + } else { + guarantee(length == 0, "invalid method ordering length"); + } + + // Verify JNI static field identifiers + if (ik->jni_ids() != NULL) { + ik->jni_ids()->verify(ik->as_klassOop()); + } + + // Verify other fields + if (ik->array_klasses() != NULL) { + guarantee(ik->array_klasses()->is_perm(), "should be in permspace"); + guarantee(ik->array_klasses()->is_klass(), "should be klass"); + } + guarantee(ik->fields()->is_perm(), "should be in permspace"); + guarantee(ik->fields()->is_typeArray(), "should be type array"); + guarantee(ik->constants()->is_perm(), "should be in permspace"); + guarantee(ik->constants()->is_constantPool(), "should be constant pool"); + guarantee(ik->inner_classes()->is_perm(), "should be in permspace"); + guarantee(ik->inner_classes()->is_typeArray(), "should be type array"); + if (ik->source_file_name() != NULL) { + guarantee(ik->source_file_name()->is_perm(), "should be in permspace"); + guarantee(ik->source_file_name()->is_symbol(), "should be symbol"); + } + if (ik->source_debug_extension() != NULL) { + guarantee(ik->source_debug_extension()->is_perm(), "should be in permspace"); + guarantee(ik->source_debug_extension()->is_symbol(), "should be symbol"); + } + if (ik->protection_domain() != NULL) { + guarantee(ik->protection_domain()->is_oop(), "should be oop"); + } + if (ik->signers() != NULL) { + guarantee(ik->signers()->is_objArray(), "should be obj array"); + } + if (ik->generic_signature() != NULL) { + guarantee(ik->generic_signature()->is_perm(), "should be in permspace"); + guarantee(ik->generic_signature()->is_symbol(), "should be symbol"); + } + if (ik->class_annotations() != NULL) { + guarantee(ik->class_annotations()->is_typeArray(), "should be type array"); + } + if (ik->fields_annotations() != NULL) { + guarantee(ik->fields_annotations()->is_objArray(), "should be obj array"); + } + if (ik->methods_annotations() != NULL) { + guarantee(ik->methods_annotations()->is_objArray(), "should be obj array"); + } + if (ik->methods_parameter_annotations() != NULL) { + guarantee(ik->methods_parameter_annotations()->is_objArray(), "should be obj array"); + } + if (ik->methods_default_annotations() != NULL) { + guarantee(ik->methods_default_annotations()->is_objArray(), "should be obj array"); + } + } +} + + +bool instanceKlassKlass::oop_partially_loaded(oop obj) const { + assert(obj->is_klass(), "object must be klass"); + instanceKlass* ik = instanceKlass::cast(klassOop(obj)); + assert(ik->oop_is_instance(), "object must be instanceKlass"); + return ik->transitive_interfaces() == (objArrayOop) obj; // Check whether transitive_interfaces points to self +} + + +// The transitive_interfaces is the last field set when loading an object. +void instanceKlassKlass::oop_set_partially_loaded(oop obj) { + assert(obj->is_klass(), "object must be klass"); + instanceKlass* ik = instanceKlass::cast(klassOop(obj)); + // Set the layout helper to a place-holder value, until fuller initialization. + // (This allows asserts in oop_is_instance to succeed.) + ik->set_layout_helper(Klass::instance_layout_helper(0, true)); + assert(ik->oop_is_instance(), "object must be instanceKlass"); + assert(ik->transitive_interfaces() == NULL, "just checking"); + ik->set_transitive_interfaces((objArrayOop) obj); // Temporarily set transitive_interfaces to point to self +}