// Walk all methods in the class list and assign a fingerprint. // so that this part of the ConstMethod* is read only. static void calculate_fingerprints() { for (int i = 0; i < _global_klass_objects->length(); i++) { Klass* k = _global_klass_objects->at(i); if (k->oop_is_instance()) { InstanceKlass* ik = InstanceKlass::cast(k); for (int i = 0; i < ik->methods()->length(); i++) { Method* m = ik->methods()->at(i); Fingerprinter fp(m); // The side effect of this call sets method's fingerprint field. fp.fingerprint(); } } } }
// Assumes the vtable is in first slot in object. static void patch_klass_vtables(void** vtbl_list, void* new_vtable_start) { int n = _global_klass_objects->length(); for (int i = 0; i < n; i++) { Klass* obj = _global_klass_objects->at(i); // Note oop_is_instance() is a virtual call. After patching vtables // all virtual calls on the dummy vtables will restore the original! if (obj->oop_is_instance()) { InstanceKlass* ik = InstanceKlass::cast(obj); *(void**)ik = find_matching_vtbl_ptr(vtbl_list, new_vtable_start, ik); ConstantPool* cp = ik->constants(); *(void**)cp = find_matching_vtbl_ptr(vtbl_list, new_vtable_start, cp); for (int j = 0; j < ik->methods()->length(); j++) { Method* m = ik->methods()->at(j); *(void**)m = find_matching_vtbl_ptr(vtbl_list, new_vtable_start, m); } } else { // Array klasses Klass* k = obj; *(void**)k = find_matching_vtbl_ptr(vtbl_list, new_vtable_start, k); } } }
static GrowableArray<EmptyVtableSlot*>* find_empty_vtable_slots( InstanceKlass* klass, GrowableArray<Method*>* mirandas, TRAPS) { assert(klass != NULL, "Must be valid class"); GrowableArray<EmptyVtableSlot*>* slots = new GrowableArray<EmptyVtableSlot*>(); // All miranda methods are obvious candidates for (int i = 0; i < mirandas->length(); ++i) { Method* m = mirandas->at(i); if (!already_in_vtable_slots(slots, m)) { slots->append(new EmptyVtableSlot(m)); } } // Also any overpasses in our superclasses, that we haven't implemented. // (can't use the vtable because it is not guaranteed to be initialized yet) InstanceKlass* super = klass->java_super(); while (super != NULL) { for (int i = 0; i < super->methods()->length(); ++i) { Method* m = super->methods()->at(i); if (m->is_overpass() || m->is_static()) { // m is a method that would have been a miranda if not for the // default method processing that occurred on behalf of our superclass, // so it's a method we want to re-examine in this new context. That is, // unless we have a real implementation of it in the current class. Method* impl = klass->lookup_method(m->name(), m->signature()); if (impl == NULL || impl->is_overpass() || impl->is_static()) { if (!already_in_vtable_slots(slots, m)) { slots->append(new EmptyVtableSlot(m)); } } } } // also any default methods in our superclasses if (super->default_methods() != NULL) { for (int i = 0; i < super->default_methods()->length(); ++i) { Method* m = super->default_methods()->at(i); // m is a method that would have been a miranda if not for the // default method processing that occurred on behalf of our superclass, // so it's a method we want to re-examine in this new context. That is, // unless we have a real implementation of it in the current class. Method* impl = klass->lookup_method(m->name(), m->signature()); if (impl == NULL || impl->is_overpass() || impl->is_static()) { if (!already_in_vtable_slots(slots, m)) { slots->append(new EmptyVtableSlot(m)); } } } } super = super->java_super(); } #ifndef PRODUCT if (TraceDefaultMethods) { tty->print_cr("Slots that need filling:"); streamIndentor si(tty); for (int i = 0; i < slots->length(); ++i) { tty->indent(); slots->at(i)->print_on(tty); tty->cr(); } } #endif // ndef PRODUCT return slots; }