Mercurial > hg > graal-compiler
view src/share/vm/oops/instanceKlassKlass.cpp @ 477:24fda36852ce
6727377: VM stack guard pages on Windows should PAGE_READWRITE not PAGE_EXECUTE_READWRITE
Summary: Make reguard_stack change access to RW, not execute and use os::protect_memory with the new parameter when change needed to X.
Reviewed-by: acorn, jcoomes
author | coleenp |
---|---|
date | Wed, 10 Dec 2008 15:14:29 -0800 |
parents | a45484ea312d |
children | c89f86385056 |
line wrap: on
line source
/* * Copyright 1997-2008 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_host_klass()); 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_host_klass()); 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_host_klass()); 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_host_klass(); 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_host_klass()); 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* hk_addr = ik->adr_host_klass(); if (PSScavenge::should_scavenge(hk_addr)) { pm->claim_or_forward_breadth(hk_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* hk_addr = ik->adr_host_klass(); if (PSScavenge::should_scavenge(hk_addr)) { pm->claim_or_forward_depth(hk_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_host_klass(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(" - host class: "); ik->host_klass()->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() + heapOopSize*(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 { protected: template <class T> void do_oop_work(T* p) { guarantee(Universe::heap()->is_in(p), "should be in heap"); oop obj = oopDesc::load_decode_heap_oop(p); guarantee(obj->is_oop_or_null(), "should be in heap"); } public: virtual void do_oop(oop* p) { VerifyFieldClosure::do_oop_work(p); } virtual void do_oop(narrowOop* p) { VerifyFieldClosure::do_oop_work(p); } }; 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() && !ik->is_anonymous()) { 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->host_klass() != NULL) { guarantee(ik->host_klass()->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 }