/*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*
*/
#include "precompiled.hpp"
#include "classfile/systemDictionary.hpp"
#include "classfile/vmSymbols.hpp"
#include "gc_implementation/shared/markSweep.inline.hpp"
#include "memory/gcLocker.hpp"
#include "memory/resourceArea.hpp"
#include "memory/universe.inline.hpp"
#include "oops/instanceKlass.hpp"
#include "oops/klassOop.hpp"
#include "oops/klassVtable.hpp"
#include "oops/methodOop.hpp"
#include "oops/objArrayOop.hpp"
#include "oops/oop.inline.hpp"
#include "prims/jvmtiRedefineClassesTrace.hpp"
#include "runtime/arguments.hpp"
#include "runtime/handles.inline.hpp"
return (instanceKlass*)k;
}
// this function computes the vtable size (including the size needed for miranda
// methods) and the number of miranda methods in this class
// Note on Miranda methods: Let's say there is a class C that implements
// interface I. Let's say there is a method m in I that neither C nor any
// of its super classes implement (i.e there is no method of any access, with
// the same name and signature as m), then m is a Miranda method which is
// entered as a public abstract method in C's vtable. From then on it should
// treated as any other public method in C for method over-ride purposes.
int &num_miranda_methods,
) {
// set up default result values
vtable_length = 0;
num_miranda_methods = 0;
// start off with super's vtable length
// go thru each method in the methods table to see if it needs a new entry
for (int i = 0; i < len; i++) {
}
}
// compute the number of mirandas methods that must be added to the end
// array classes don't have their superclass set correctly during
// bootstrapping
}
// Someone is attempting to redefine java.lang.Object incorrectly. The
// only way this should happen is from
// SystemDictionary::resolve_from_stream(), which will detect this later
// and throw a security exception. So don't assert here to let
// the exception occur.
}
"bad vtable size for class Object");
}
return m->vtable_index();
}
return 0;
} else {
// copy methods from superKlass
// can't inherit from array class, so must be instanceKlass
#ifdef ASSERT
#endif
#ifndef PRODUCT
if (PrintVtables && Verbose) {
tty->print_cr("copy vtable from %s to %s size %d", sk->internal_name(), klass()->internal_name(), _length);
}
#endif
return superVtable->length();
}
}
// Revised lookup semantics introduced 1.3 (Kestral beta)
// Note: Arrays can have intermediate array supers. Use java_super to skip them.
int nofNewEntries = 0;
}
#ifdef ASSERT
#endif
if (Universe::is_bootstrapping()) {
// just clear everything
return;
}
if (klass()->oop_is_array()) {
} else {
// update_inherited_vtable can stop for gc - ensure using handles
for (int i = 0; i < len; i++) {
bool needs_new_entry = update_inherited_vtable(ik(), mh, super_vtable_len, checkconstraints, CHECK);
if (needs_new_entry) {
initialized++;
}
}
// add miranda methods; it will also update the value of initialized
// In class hierarchies where the accessibility is not increasing (i.e., going from private ->
// package_private -> publicprotected), the vtable might actually be smaller than our initial
// calculation.
}
}
}
// Called for cases where a method does not override its superclass' vtable entry
// For bytecodes not produced by javac together it is possible that a method does not override
// the superclass's method, but might indirectly override a super-super class's vtable entry
// If none found, return a null superk, else return the superk of the method this does override
instanceKlass* klassVtable::find_transitive_override(instanceKlass* initialsuper, methodHandle target_method,
#ifndef PRODUCT
assert(super_method->name() == name && super_method->signature() == signature, "vtable entry name/sig mismatch");
#endif
#ifndef PRODUCT
if (PrintVtables && Verbose) {
}
#endif /*PRODUCT*/
break; // return found superk
}
} else {
// super class has no vtable entry here, stop transitive search
break;
}
// if no override found yet, continue to search up
}
return superk;
}
// Update child's copy of super vtable for overrides
// OR return true if a new vtable entry is required
// Only called for instanceKlass's, i.e. not for arrays
// If that changed, could not use _klass as handle for klass
bool klassVtable::update_inherited_vtable(instanceKlass* klass, methodHandle target_method, int super_vtable_len,
bool checkconstraints, TRAPS) {
bool allocate_new = true;
// Initialize the method's vtable index to "nonvirtual".
// If we allocate a vtable entry, we will update it to a non-negative number.
// Static and <init> methods are never in
if (target_method()->is_static() || target_method()->name() == vmSymbols::object_initializer_name()) {
return false;
}
// a final method never needs a new entry; final methods can be statically
// resolved and they have to be present in the vtable only if they override
// a super's method, in which case they re-use its entry
allocate_new = false;
}
// we need a new entry if there is no superclass
return allocate_new;
}
// private methods always have a new entry in the vtable
// specification interpretation since classic has
// private methods not overriding
if (target_method()->is_private()) {
return allocate_new;
}
// search through the vtable and update overridden entries
// Since check_signature_loaders acquires SystemDictionary_lock
// which can block for gc, once we are in this loop, use handles
// For classfiles built with >= jdk7, we now look for transitive overrides
for(int i = 0; i < super_vtable_len; i++) {
// Check if method name matches
// get super_klass for method_holder for the found method
// overriding, so no new entry
allocate_new = false;
if (checkconstraints) {
// Override vtable entry if passes loader constraint check
// if loader constraint checking requested
// No need to visit his super, since he and his super
// have already made any needed loader constraints.
// Since loader constraints are transitive, it is enough
// to link to the first super, and we get all the others.
if (target_loader() != super_loader()) {
char* failed_type_name =
super_loader, true,
CHECK_(false));
if (failed_type_name != NULL) {
"overridden method \"%s\" the class loader (instance"
" of %s) of the current class, %s, and its superclass loader "
"(instance of %s), have different Class objects for the type "
"%s used in the signature";
}
}
}
put_method_at(target_method(), i);
target_method()->set_vtable_index(i);
#ifndef PRODUCT
if (PrintVtables && Verbose) {
}
#endif /*PRODUCT*/
} else {
// allocate_new = true; default. We might override one entry,
// but not override another. Once we override one, not need new
#ifndef PRODUCT
if (PrintVtables && Verbose) {
}
#endif /*PRODUCT*/
}
}
}
return allocate_new;
}
#ifndef PRODUCT
if (PrintVtables && Verbose) {
}
#endif
}
// Find out if a method "m" with superclass "super", loader "classloader" and
// name "classname" needs a new vtable entry. Let P be a class package defined
// by "classloader" and "classname".
// NOTE: The logic used here is very similar to the one used for computing
// the vtables indices for a method. We cannot directly use that function because,
// we allocate the instanceKlass at load time, and that requires that the
// superclass has been loaded.
// However, the vtable entries are filled in at link time, and therefore
// the superclass' vtable may not yet have been filled in.
TRAPS) {
// a final method never needs a new entry; final methods can be statically
// resolved and they have to be present in the vtable only if they override
// a super's method, in which case they re-use its entry
(target_method()->is_static()) ||
// static methods don't need to be in vtable
// <init> is never called dynamically-bound
) {
return false;
}
// we need a new entry if there is no superclass
return true;
}
// private methods always have a new entry in the vtable
// specification interpretation since classic has
// private methods not overriding
if (target_method()->is_private()) {
return true;
}
// search through the super class hierarchy to see if we need
// a new entry
while (k != NULL) {
// lookup through the hierarchy for a method with matching name and sign.
if (super_method == NULL) {
break; // we still have to search for a matching miranda method
}
// get the class holding the matching method
// make sure you use that class for is_override
// we want only instance method matches
// pretend private methods are not in the super vtable
// ignore private, c.m pub does override a.m pub
// For classes that were not javac'd together, we also do transitive overriding around
// methods that have less accessibility
if ((!super_method->is_static()) &&
(!super_method->is_private())) {
return false;
// else keep looking for transitive overrides
}
}
// Start with lookup result and continue to search up
}
// if the target method is public or protected it may have a matching
// miranda method in the super, whose entry it should re-use.
// Actually, to handle cases that javac would not generate, we need
// this check for all access permissions.
if (sk->has_miranda_methods()) {
return false; // found a matching miranda; we do not need a new entry
}
}
return true; // found no match; we need a new entry
}
// Support for miranda methods
// get the vtable index of a miranda method with matching "name" and "signature"
// search from the bottom, might be faster
for (int i = (length() - 1); i >= 0; i--) {
if (is_miranda_entry_at(i) &&
return i;
}
}
return methodOopDesc::invalid_vtable_index;
}
// check if an entry is miranda
// miranda methods are interface methods in a class's vtable
if (mhk->is_interface()) {
return true;
}
return false;
}
// check if a method is a miranda method, given a class's methods table and it's super
// the caller must make sure that the method belongs to an interface implemented by the class
// did not find it in the method table of the current class
// super doesn't exist
return true;
}
// super class hierarchy does not implement it or protection is different
return true;
}
}
return false;
}
// iterate thru the current interface's method to see if it a miranda
for (int i = 0; i < num_methods; i++) {
bool is_duplicate = false;
// check for duplicate mirandas in different interfaces we implement
for (int j = 0; j < num_of_current_mirandas; j++) {
is_duplicate = true;
break;
}
}
if (!is_duplicate) { // we don't want duplicate miranda entries in the vtable
// check if it is a duplicate of a super's miranda
}
}
}
}
}
// iterate thru the local interfaces looking for a miranda
for (int i = 0; i < num_local_ifs; i++) {
// iterate thru each local's super interfaces
for (int j = 0; j < num_super_ifs; j++) {
}
}
}
// get number of mirandas
int klassVtable::get_num_mirandas(klassOop super, objArrayOop class_methods, objArrayOop local_interfaces) {
}
// fill in mirandas
for (int i = 0; i < num_mirandas; i++) {
initialized++;
}
}
}
int methods_length, bool * trace_name_printed) {
// search the vtable for uses of either obsolete or EMCP methods
for (int j = 0; j < methods_length; j++) {
// In the vast majority of cases we could get the vtable index
// by using: old_method->vtable_index()
// However, there are rare cases, eg. sun.awt.X11.XDecoratedPeer.getX()
// in sun.awt.X11.XFramePeer where methods occur more than once in the
// vtable, so, alas, we must do an exhaustive search.
if (!(*trace_name_printed)) {
// RC_TRACE_MESG macro has an embedded ResourceMark
RC_TRACE_MESG(("adjust: name=%s",
*trace_name_printed = true;
}
// RC_TRACE macro has an embedded ResourceMark
}
// cannot 'break' here; see for-loop comment above.
}
}
}
}
// a vtable should never contain old or obsolete methods
for (int i = 0; i < length(); i++) {
methodOop m = unchecked_method_at(i);
return false;
}
}
return true;
}
for (int i = 0; i < length(); i++) {
methodOop m = unchecked_method_at(i);
if (m != NULL) {
m->print_name(tty);
}
}
}
// CDS/RedefineClasses support - clear vtables so they can be reinitialized
}
}
// Garbage collection
for (int i = 0; i < len; i++) {
}
}
#ifndef SERIALGC
for (int i = 0; i < len; i++) {
}
}
#endif // SERIALGC
for (int i = 0; i < len; i++) {
}
}
#ifndef SERIALGC
const int n = length();
for (int i = 0; i < n; i++) {
}
}
#endif // SERIALGC
// Iterators
for (int i = 0; i < len; i++) {
}
}
int i;
for (i = 0; i < len; i++) {
}
for (; i < len; i++) {
}
}
//-----------------------------------------------------------------------------------------
// Itable code
// Initialize a itableMethodEntry
if (m == NULL) return;
_method = m;
}
if (klass->itable_length() > 0) {
if (offset_entry != NULL && offset_entry->interface_klass() != NULL) { // Check that itable is initialized
// First offset entry points to the first method_entry
assert(_table_offset >= 0 && _size_offset_table >= 0 && _size_method_table >= 0, "wrong computation");
return;
}
}
// The length of the itable was either zero, or it has not yet been initialized.
_table_offset = 0;
_size_offset_table = 0;
_size_method_table = 0;
}
// Garbage Collection
// offset table
for(int i = 0; i < _size_offset_table; i++) {
ioe++;
}
// method table
for(int j = 0; j < _size_method_table; j++) {
ime++;
}
}
#ifndef SERIALGC
// offset table
for(int i = 0; i < _size_offset_table; i++) {
ioe++;
}
// method table
for(int j = 0; j < _size_method_table; j++) {
ime++;
}
}
#endif // SERIALGC
// offset table
for(int i = 0; i < _size_offset_table; i++) {
ioe++;
}
// method table
for(int j = 0; j < _size_method_table; j++) {
ime++;
}
}
#ifndef SERIALGC
// offset table
for(int i = 0; i < _size_offset_table; i++) {
ioe++;
}
// method table
for(int j = 0; j < _size_method_table; j++) {
ime++;
}
}
#endif // SERIALGC
// Iterators
// offset table
for(int i = 0; i < _size_offset_table; i++) {
ioe++;
}
// method table
for(int j = 0; j < _size_method_table; j++) {
ime++;
}
}
// offset table
for(int i = 0; i < _size_offset_table; i++) {
ioe++;
}
// method table
for(int j = 0; j < _size_method_table; j++) {
ime++;
}
}
static int initialize_count = 0;
// Initialization
// Cannot be setup doing bootstrapping, interfaces don't have
// itables, and klass with only ones entry have empty itables
if (Universe::is_bootstrapping() ||
_klass->is_interface() ||
// There's alway an extra itable entry so we can null-terminate it.
if (num_interfaces > 0) {
// Iterate through all interfaces
int i;
for(i = 0; i < num_interfaces; i++) {
}
}
// Check that the last entry is empty
}
void klassItable::initialize_itable_for_interface(int method_table_offset, KlassHandle interf_h, bool checkconstraints, TRAPS) {
int ime_num = 0;
// Skip first methodOop if it is a class initializer
// m, method_name, method_signature, klass reset each loop so they
// don't need preserving across check_signature_loaders call
// methods needs a handle in case of gc from check_signature_loaders
for(; i < nof_methods; i++) {
// This is same code as in Linkresolver::lookup_instance_method_in_klasses
// continue with recursive lookup through the superclass
target = (super == NULL) ? methodOop(NULL) : Klass::cast(super)->uncached_lookup_method(method_name, method_signature);
}
// Entry do not resolve. Leave it empty
} else {
// Entry did resolve, check loader constraints before initializing
// if checkconstraints requested
if (checkconstraints) {
if (method_holder_loader() != interface_loader()) {
char* failed_type_name =
true, CHECK);
if (failed_type_name != NULL) {
"itable initialization: when resolving method \"%s\" the class"
" loader (instance of %s) of the current class, %s, "
"and the class loader (instance of %s) for interface "
"%s have different Class objects for the type %s "
"used in the signature";
}
}
}
// ime may have moved during GC so recalculate address
}
// Progress to next entry
ime_num++;
}
}
// Update entry for specific methodOop
for(int i = 0; i < _size_method_table; i++) {
ime->initialize(m);
}
ime++;
}
}
int methods_length, bool * trace_name_printed) {
// search the itable for uses of either obsolete or EMCP methods
for (int j = 0; j < methods_length; j++) {
// The itable can describe more than one interface and the same
// method signature can be specified by more than one interface.
// This means we have to do an exhaustive search to find all the
// old_method references.
for (int i = 0; i < _size_method_table; i++) {
if (!(*trace_name_printed)) {
// RC_TRACE_MESG macro has an embedded ResourceMark
RC_TRACE_MESG(("adjust: name=%s",
*trace_name_printed = true;
}
// RC_TRACE macro has an embedded ResourceMark
}
// cannot 'break' here; see for-loop comment above.
}
ime++;
}
}
}
// an itable should never contain old or obsolete methods
for (int i = 0; i < _size_method_table; i++) {
return false;
}
ime++;
}
return true;
}
for (int i = 0; i < _size_method_table; i++) {
if (m != NULL) {
m->print_name(tty);
}
ime++;
}
}
// Setup
public:
};
// Visit all interfaces with at-least one method (excluding <clinit>)
// Handle array argument
for(int i = 0; i < transitive_intf->length(); i++) {
// Find no. of methods excluding a <clinit>
if (method_count > 0) {
method_count--;
}
}
// Only count interfaces with at least one method
if (method_count > 0) {
}
}
}
private:
int _nof_methods;
int _nof_interfaces;
public:
};
private:
public:
SetupItableClosure(address klass_begin, itableOffsetEntry* offset_entry, itableMethodEntry* method_entry) {
}
}
};
// Count no of interfaces and total number of interface methods
// There's alway an extra itable entry so we can null-terminate it.
// Statistics
return itable_size;
}
// Fill out offset table and interface klasses into the itable space
if (klass->itable_length() == 0) return;
// Count no of interfaces and total number of interface methods
// Add one extra entry so we can null-terminate the table
"mismatch calculation of itable size");
// Fill-out offset table
assert((oop*)(ime + nof_methods) <= (oop*)klass->start_of_nonstatic_oop_maps(), "wrong offset calculation (1)");
// Visit all interfaces and initialize itable offset table
#ifdef ASSERT
#endif
}
// m must be a method in an interface
int index = 0;
index++;
}
// Adjust for <clinit>, which is left out of table if first method
index--;
}
return index;
}
// inverse to compute_itable_index
// Adjust for <clinit>, which is left out of table if first method
index++;
}
return NULL; // help caller defend against bad indexes
return m;
}
// make sure table is initialized
if (!Universe::is_fully_initialized()) return;
#ifndef PRODUCT
// avoid redundant verifies
#endif
if (end_of_vtable > end_of_obj) {
}
// verify consistency with superKlass vtable
}
}
}
}
}
#ifndef PRODUCT
for (int i = 0; i < length(); i++) {
}
}
#endif
// we sub_type, because it could be a miranda method
#ifndef PRODUCT
print();
#endif
}
}
#ifndef PRODUCT
if (Verbose) {
}
}
public:
no_klasses++;
if (kl->oop_is_instance()) {
}
if (kl->oop_is_array()) {
}
}
static void compute() {
// filler size is a conservative approximation
filler = oopSize * (no_klasses - no_instance_klasses) * (sizeof(instanceKlass) - sizeof(arrayKlass) - 1);
}
};
VtableStats::compute();
tty->print_cr("%6d classes (%d instance, %d array)", VtableStats::no_klasses, VtableStats::no_instance_klasses, VtableStats::no_array_klasses);
tty->print_cr("%6d bytes for vtable entries (%d for arrays)", VtableStats::entries, VtableStats::array_entries);
}
tty->print_cr("%6d K uses for itables (average by class: %d bytes)", _total_size / K, _total_size / _total_classes);
}
#endif // PRODUCT