< prev index next >

src/share/vm/oops/klassVtable.cpp

Print this page

        

*** 38,48 **** #include "runtime/arguments.hpp" #include "runtime/handles.inline.hpp" #include "utilities/copy.hpp" inline InstanceKlass* klassVtable::ik() const { ! return InstanceKlass::cast(_klass()); } bool klassVtable::is_preinitialized_vtable() { return _klass->is_shared() && !MetaspaceShared::remapped_readwrite(); } --- 38,48 ---- #include "runtime/arguments.hpp" #include "runtime/handles.inline.hpp" #include "utilities/copy.hpp" inline InstanceKlass* klassVtable::ik() const { ! return InstanceKlass::cast(_klass); } bool klassVtable::is_preinitialized_vtable() { return _klass->is_shared() && !MetaspaceShared::remapped_readwrite(); }
*** 126,137 **** } // Copy super class's vtable to the first part (prefix) of this class's vtable, // and return the number of entries copied. Expects that 'super' is the Java // super class (arrays can have "array" super classes that must be skipped). ! int klassVtable::initialize_from_super(KlassHandle super) { ! if (super.is_null()) { return 0; } else if (is_preinitialized_vtable()) { // A shared class' vtable is preinitialized at dump time. No need to copy // methods from super class for shared class, as that was already done // during archiving time. However, if Jvmti has redefined a class, --- 126,137 ---- } // Copy super class's vtable to the first part (prefix) of this class's vtable, // and return the number of entries copied. Expects that 'super' is the Java // super class (arrays can have "array" super classes that must be skipped). ! int klassVtable::initialize_from_super(Klass* super) { ! if (super == NULL) { return 0; } else if (is_preinitialized_vtable()) { // A shared class' vtable is preinitialized at dump time. No need to copy // methods from super class for shared class, as that was already done // during archiving time. However, if Jvmti has redefined a class,
*** 158,179 **** // // Revised lookup semantics introduced 1.3 (Kestrel beta) void klassVtable::initialize_vtable(bool checkconstraints, TRAPS) { // Note: Arrays can have intermediate array supers. Use java_super to skip them. ! KlassHandle super (THREAD, klass()->java_super()); int nofNewEntries = 0; bool is_shared = _klass->is_shared(); ! if (!klass()->is_array_klass()) { ResourceMark rm(THREAD); log_develop_debug(vtables)("Initializing: %s", _klass->name()->as_C_string()); } #ifdef ASSERT ! oop* end_of_obj = (oop*)_klass() + _klass()->size(); oop* end_of_vtable = (oop*)&table()[_length]; assert(end_of_vtable <= end_of_obj, "vtable extends beyond end"); #endif if (Universe::is_bootstrapping()) { --- 158,179 ---- // // Revised lookup semantics introduced 1.3 (Kestrel beta) void klassVtable::initialize_vtable(bool checkconstraints, TRAPS) { // Note: Arrays can have intermediate array supers. Use java_super to skip them. ! Klass* super = _klass->java_super(); int nofNewEntries = 0; bool is_shared = _klass->is_shared(); ! if (!_klass->is_array_klass()) { ResourceMark rm(THREAD); log_develop_debug(vtables)("Initializing: %s", _klass->name()->as_C_string()); } #ifdef ASSERT ! oop* end_of_obj = (oop*)_klass + _klass->size(); oop* end_of_vtable = (oop*)&table()[_length]; assert(end_of_vtable <= end_of_obj, "vtable extends beyond end"); #endif if (Universe::is_bootstrapping()) {
*** 182,192 **** for (int i = 0; i < _length; i++) table()[i].clear(); return; } int super_vtable_len = initialize_from_super(super); ! if (klass()->is_array_klass()) { assert(super_vtable_len == _length, "arrays shouldn't introduce new methods"); } else { assert(_klass->is_instance_klass(), "must be InstanceKlass"); Array<Method*>* methods = ik()->methods(); --- 182,192 ---- for (int i = 0; i < _length; i++) table()[i].clear(); return; } int super_vtable_len = initialize_from_super(super); ! if (_klass->is_array_klass()) { assert(super_vtable_len == _length, "arrays shouldn't introduce new methods"); } else { assert(_klass->is_instance_klass(), "must be InstanceKlass"); Array<Method*>* methods = ik()->methods();
*** 325,335 **** return superk; } static void log_vtables(int i, bool overrides, methodHandle target_method, ! KlassHandle target_klass, Method* super_method, Thread* thread) { #ifndef PRODUCT if (log_develop_is_enabled(Trace, vtables)) { ResourceMark rm(thread); outputStream* logst = Log(vtables)::trace_stream(); --- 325,335 ---- return superk; } static void log_vtables(int i, bool overrides, methodHandle target_method, ! Klass* target_klass, Method* super_method, Thread* thread) { #ifndef PRODUCT if (log_develop_is_enabled(Trace, vtables)) { ResourceMark rm(thread); outputStream* logst = Log(vtables)::trace_stream();
*** 430,440 **** // For classfiles built with >= jdk7, we now look for transitive overrides Symbol* name = target_method()->name(); Symbol* signature = target_method()->signature(); ! KlassHandle target_klass(THREAD, target_method()->method_holder()); if (target_klass == NULL) { target_klass = _klass; } Handle target_loader(THREAD, target_klass->class_loader()); --- 430,440 ---- // For classfiles built with >= jdk7, we now look for transitive overrides Symbol* name = target_method()->name(); Symbol* signature = target_method()->signature(); ! Klass* target_klass = target_method()->method_holder(); if (target_klass == NULL) { target_klass = _klass; } Handle target_loader(THREAD, target_klass->class_loader());
*** 953,963 **** if (log_is_enabled(Info, redefine, class, update)) { ResourceMark rm; if (!(*trace_name_printed)) { log_info(redefine, class, update) ("adjust: klassname=%s for methods from name=%s", ! klass()->external_name(), old_method->method_holder()->external_name()); *trace_name_printed = true; } log_debug(redefine, class, update, vtables) ("vtable method update: %s(%s), updated default = %s", new_method->name()->as_C_string(), new_method->signature()->as_C_string(), updated_default ? "true" : "false"); --- 953,963 ---- if (log_is_enabled(Info, redefine, class, update)) { ResourceMark rm; if (!(*trace_name_printed)) { log_info(redefine, class, update) ("adjust: klassname=%s for methods from name=%s", ! _klass->external_name(), old_method->method_holder()->external_name()); *trace_name_printed = true; } log_debug(redefine, class, update, vtables) ("vtable method update: %s(%s), updated default = %s", new_method->name()->as_C_string(), new_method->signature()->as_C_string(), updated_default ? "true" : "false");
*** 1023,1043 **** } else { _method = m; } } ! klassItable::klassItable(instanceKlassHandle klass) { _klass = klass; if (klass->itable_length() > 0) { itableOffsetEntry* offset_entry = (itableOffsetEntry*)klass->start_of_itable(); if (offset_entry != NULL && offset_entry->interface_klass() != NULL) { // Check that itable is initialized // First offset entry points to the first method_entry ! intptr_t* method_entry = (intptr_t *)(((address)klass()) + offset_entry->offset()); intptr_t* end = klass->end_of_itable(); ! _table_offset = (intptr_t*)offset_entry - (intptr_t*)klass(); _size_offset_table = (method_entry - ((intptr_t*)offset_entry)) / itableOffsetEntry::size(); _size_method_table = (end - method_entry) / itableMethodEntry::size(); assert(_table_offset >= 0 && _size_offset_table >= 0 && _size_method_table >= 0, "wrong computation"); return; } --- 1023,1043 ---- } else { _method = m; } } ! klassItable::klassItable(InstanceKlass* klass) { _klass = klass; if (klass->itable_length() > 0) { itableOffsetEntry* offset_entry = (itableOffsetEntry*)klass->start_of_itable(); if (offset_entry != NULL && offset_entry->interface_klass() != NULL) { // Check that itable is initialized // First offset entry points to the first method_entry ! intptr_t* method_entry = (intptr_t *)(((address)klass) + offset_entry->offset()); intptr_t* end = klass->end_of_itable(); ! _table_offset = (intptr_t*)offset_entry - (intptr_t*)klass; _size_offset_table = (method_entry - ((intptr_t*)offset_entry)) / itableOffsetEntry::size(); _size_method_table = (end - method_entry) / itableMethodEntry::size(); assert(_table_offset >= 0 && _size_offset_table >= 0 && _size_method_table >= 0, "wrong computation"); return; }
*** 1054,1064 **** // Initialization void klassItable::initialize_itable(bool checkconstraints, TRAPS) { if (_klass->is_interface()) { // This needs to go after vtable indices are assigned but // before implementors need to know the number of itable indices. ! assign_itable_indices_for_interface(_klass()); } // Cannot be setup doing bootstrapping, interfaces don't have // itables, and klass with only ones entry have empty itables if (Universe::is_bootstrapping() || --- 1054,1064 ---- // Initialization void klassItable::initialize_itable(bool checkconstraints, TRAPS) { if (_klass->is_interface()) { // This needs to go after vtable indices are assigned but // before implementors need to know the number of itable indices. ! assign_itable_indices_for_interface(_klass); } // Cannot be setup doing bootstrapping, interfaces don't have // itables, and klass with only ones entry have empty itables if (Universe::is_bootstrapping() ||
*** 1076,1088 **** // Iterate through all interfaces int i; for(i = 0; i < num_interfaces; i++) { itableOffsetEntry* ioe = offset_entry(i); HandleMark hm(THREAD); ! KlassHandle interf_h (THREAD, ioe->interface_klass()); ! assert(interf_h() != NULL && ioe->offset() != 0, "bad offset entry in itable"); ! initialize_itable_for_interface(ioe->offset(), interf_h, checkconstraints, CHECK); } } // Check that the last entry is empty itableOffsetEntry* ioe = offset_entry(size_offset_table() - 1); --- 1076,1088 ---- // Iterate through all interfaces int i; for(i = 0; i < num_interfaces; i++) { itableOffsetEntry* ioe = offset_entry(i); HandleMark hm(THREAD); ! Klass* interf = ioe->interface_klass(); ! assert(interf != NULL && ioe->offset() != 0, "bad offset entry in itable"); ! initialize_itable_for_interface(ioe->offset(), interf, checkconstraints, CHECK); } } // Check that the last entry is empty itableOffsetEntry* ioe = offset_entry(size_offset_table() - 1);
*** 1167,1184 **** // itable indices return length; } ! void klassItable::initialize_itable_for_interface(int method_table_offset, KlassHandle interf_h, bool checkconstraints, TRAPS) { ! Array<Method*>* methods = InstanceKlass::cast(interf_h())->methods(); int nof_methods = methods->length(); HandleMark hm; assert(nof_methods > 0, "at least one method must exist for interface to be in vtable"); ! Handle interface_loader (THREAD, InstanceKlass::cast(interf_h())->class_loader()); ! int ime_count = method_count_for_interface(interf_h()); for (int i = 0; i < nof_methods; i++) { Method* m = methods->at(i); methodHandle target; if (m->has_itable_index()) { // This search must match the runtime resolution, i.e. selection search for invokeinterface --- 1167,1184 ---- // itable indices return length; } ! void klassItable::initialize_itable_for_interface(int method_table_offset, Klass* interf, bool checkconstraints, TRAPS) { ! Array<Method*>* methods = InstanceKlass::cast(interf)->methods(); int nof_methods = methods->length(); HandleMark hm; assert(nof_methods > 0, "at least one method must exist for interface to be in vtable"); ! Handle interface_loader (THREAD, InstanceKlass::cast(interf)->class_loader()); ! int ime_count = method_count_for_interface(interf); for (int i = 0; i < nof_methods; i++) { Method* m = methods->at(i); methodHandle target; if (m->has_itable_index()) { // This search must match the runtime resolution, i.e. selection search for invokeinterface
*** 1187,1197 **** } if (target == NULL || !target->is_public() || target->is_abstract()) { // Entry does not resolve. Leave it empty for AbstractMethodError. if (!(target == NULL) && !target->is_public()) { // Stuff an IllegalAccessError throwing method in there instead. ! itableOffsetEntry::method_entry(_klass(), method_table_offset)[m->itable_index()]. initialize(Universe::throw_illegal_access_error()); } } else { // Entry did resolve, check loader constraints before initializing // if checkconstraints requested --- 1187,1197 ---- } if (target == NULL || !target->is_public() || target->is_abstract()) { // Entry does not resolve. Leave it empty for AbstractMethodError. if (!(target == NULL) && !target->is_public()) { // Stuff an IllegalAccessError throwing method in there instead. ! itableOffsetEntry::method_entry(_klass, method_table_offset)[m->itable_index()]. initialize(Universe::throw_illegal_access_error()); } } else { // Entry did resolve, check loader constraints before initializing // if checkconstraints requested
*** 1213,1223 **** "used in the signature"; char* sig = target()->name_and_sig_as_C_string(); const char* loader1 = SystemDictionary::loader_name(method_holder_loader()); char* current = _klass->name()->as_C_string(); const char* loader2 = SystemDictionary::loader_name(interface_loader()); ! char* iface = InstanceKlass::cast(interf_h())->name()->as_C_string(); char* failed_type_name = failed_type_symbol->as_C_string(); size_t buflen = strlen(msg) + strlen(sig) + strlen(loader1) + strlen(current) + strlen(loader2) + strlen(iface) + strlen(failed_type_name); char* buf = NEW_RESOURCE_ARRAY_IN_THREAD(THREAD, char, buflen); --- 1213,1223 ---- "used in the signature"; char* sig = target()->name_and_sig_as_C_string(); const char* loader1 = SystemDictionary::loader_name(method_holder_loader()); char* current = _klass->name()->as_C_string(); const char* loader2 = SystemDictionary::loader_name(interface_loader()); ! char* iface = InstanceKlass::cast(interf)->name()->as_C_string(); char* failed_type_name = failed_type_symbol->as_C_string(); size_t buflen = strlen(msg) + strlen(sig) + strlen(loader1) + strlen(current) + strlen(loader2) + strlen(iface) + strlen(failed_type_name); char* buf = NEW_RESOURCE_ARRAY_IN_THREAD(THREAD, char, buflen);
*** 1229,1246 **** } // ime may have moved during GC so recalculate address int ime_num = m->itable_index(); assert(ime_num < ime_count, "oob"); ! itableOffsetEntry::method_entry(_klass(), method_table_offset)[ime_num].initialize(target()); if (log_develop_is_enabled(Trace, itables)) { ResourceMark rm(THREAD); if (target() != NULL) { outputStream* logst = Log(itables)::trace_stream(); char* sig = target()->name_and_sig_as_C_string(); logst->print("interface: %s, ime_num: %d, target: %s, method_holder: %s ", ! interf_h()->internal_name(), ime_num, sig, target()->method_holder()->internal_name()); logst->print("target_method flags: "); target()->print_linkage_flags(logst); logst->cr(); } --- 1229,1246 ---- } // ime may have moved during GC so recalculate address int ime_num = m->itable_index(); assert(ime_num < ime_count, "oob"); ! itableOffsetEntry::method_entry(_klass, method_table_offset)[ime_num].initialize(target()); if (log_develop_is_enabled(Trace, itables)) { ResourceMark rm(THREAD); if (target() != NULL) { outputStream* logst = Log(itables)::trace_stream(); char* sig = target()->name_and_sig_as_C_string(); logst->print("interface: %s, ime_num: %d, target: %s, method_holder: %s ", ! interf->internal_name(), ime_num, sig, target()->method_holder()->internal_name()); logst->print("target_method flags: "); target()->print_linkage_flags(logst); logst->cr(); }
*** 1406,1416 **** return itable_size; } // Fill out offset table and interface klasses into the itable space ! void klassItable::setup_itable_offset_table(instanceKlassHandle klass) { if (klass->itable_length() == 0) return; assert(!klass->is_interface(), "Should have zero length itable"); // Count no of interfaces and total number of interface methods CountInterfacesClosure cic; --- 1406,1416 ---- return itable_size; } // Fill out offset table and interface klasses into the itable space ! void klassItable::setup_itable_offset_table(InstanceKlass* klass) { if (klass->itable_length() == 0) return; assert(!klass->is_interface(), "Should have zero length itable"); // Count no of interfaces and total number of interface methods CountInterfacesClosure cic;
*** 1431,1441 **** intptr_t* end = klass->end_of_itable(); assert((oop*)(ime + nof_methods) <= (oop*)klass->start_of_nonstatic_oop_maps(), "wrong offset calculation (1)"); assert((oop*)(end) == (oop*)(ime + nof_methods), "wrong offset calculation (2)"); // Visit all interfaces and initialize itable offset table ! SetupItableClosure sic((address)klass(), ioe, ime); visit_all_interfaces(klass->transitive_interfaces(), &sic); #ifdef ASSERT ime = sic.method_entry(); oop* v = (oop*) klass->end_of_itable(); --- 1431,1441 ---- intptr_t* end = klass->end_of_itable(); assert((oop*)(ime + nof_methods) <= (oop*)klass->start_of_nonstatic_oop_maps(), "wrong offset calculation (1)"); assert((oop*)(end) == (oop*)(ime + nof_methods), "wrong offset calculation (2)"); // Visit all interfaces and initialize itable offset table ! SetupItableClosure sic((address)klass, ioe, ime); visit_all_interfaces(klass->transitive_interfaces(), &sic); #ifdef ASSERT ime = sic.method_entry(); oop* v = (oop*) klass->end_of_itable();
*** 1474,1484 **** #ifndef PRODUCT // avoid redundant verifies if (!forced && _verify_count == Universe::verify_count()) return; _verify_count = Universe::verify_count(); #endif ! oop* end_of_obj = (oop*)_klass() + _klass()->size(); oop* end_of_vtable = (oop *)&table()[_length]; if (end_of_vtable > end_of_obj) { fatal("klass %s: klass object too short (vtable extends beyond end)", _klass->internal_name()); } --- 1474,1484 ---- #ifndef PRODUCT // avoid redundant verifies if (!forced && _verify_count == Universe::verify_count()) return; _verify_count = Universe::verify_count(); #endif ! oop* end_of_obj = (oop*)_klass + _klass->size(); oop* end_of_vtable = (oop *)&table()[_length]; if (end_of_vtable > end_of_obj) { fatal("klass %s: klass object too short (vtable extends beyond end)", _klass->internal_name()); }
*** 1514,1533 **** } #endif void vtableEntry::verify(klassVtable* vt, outputStream* st) { NOT_PRODUCT(FlagSetting fs(IgnoreLockingAssertions, true)); ! KlassHandle vtklass_h = vt->klass(); ! Klass* vtklass = vtklass_h(); if (vtklass->is_instance_klass() && (InstanceKlass::cast(vtklass)->major_version() >= klassVtable::VTABLE_TRANSITIVE_OVERRIDE_VERSION)) { assert(method() != NULL, "must have set method"); } if (method() != NULL) { method()->verify(); // we sub_type, because it could be a miranda method ! if (!vtklass_h->is_subtype_of(method()->method_holder())) { #ifndef PRODUCT print(); #endif fatal("vtableEntry " PTR_FORMAT ": method is from subclass", p2i(this)); } --- 1514,1532 ---- } #endif void vtableEntry::verify(klassVtable* vt, outputStream* st) { NOT_PRODUCT(FlagSetting fs(IgnoreLockingAssertions, true)); ! Klass* vtklass = vt->klass(); if (vtklass->is_instance_klass() && (InstanceKlass::cast(vtklass)->major_version() >= klassVtable::VTABLE_TRANSITIVE_OVERRIDE_VERSION)) { assert(method() != NULL, "must have set method"); } if (method() != NULL) { method()->verify(); // we sub_type, because it could be a miranda method ! if (!vtklass->is_subtype_of(method()->method_holder())) { #ifndef PRODUCT print(); #endif fatal("vtableEntry " PTR_FORMAT ": method is from subclass", p2i(this)); }
< prev index next >