< prev index next >

src/hotspot/share/classfile/defaultMethods.cpp

Print this page
rev 53972 : 8219713: Reduce work in DefaultMethods::generate_default_methods
Reviewed-by: hseigel, dholmes, lfoltan, kkinnear

*** 151,184 **** InstanceKlass* next_interface() { return interface_at(interface_index()); } }; ! bool _cancelled; GrowableArray<Node*> _path; Node* current_top() const { return _path.top(); } bool has_more_nodes() const { return !_path.is_empty(); } void push(InstanceKlass* cls, void* data) { assert(cls != NULL, "Requires a valid instance class"); Node* node = new Node(cls, data, has_super(cls)); _path.push(node); } void pop() { _path.pop(); } ! void reset_iteration() { ! _cancelled = false; ! _path.clear(); ! } ! bool is_cancelled() const { return _cancelled; } ! ! // This code used to skip interface classes because their only ! // superclass was j.l.Object which would be also covered by class ! // superclass hierarchy walks. Now that the starting point can be ! // an interface, we must ensure we catch j.l.Object as the super. ! static bool has_super(InstanceKlass* cls) { ! return cls->super() != NULL; } Node* node_at_depth(int i) const { return (i >= _path.length()) ? NULL : _path.at(_path.length() - i - 1); } --- 151,181 ---- InstanceKlass* next_interface() { return interface_at(interface_index()); } }; ! bool _visited_Object; GrowableArray<Node*> _path; Node* current_top() const { return _path.top(); } bool has_more_nodes() const { return !_path.is_empty(); } void push(InstanceKlass* cls, void* data) { assert(cls != NULL, "Requires a valid instance class"); Node* node = new Node(cls, data, has_super(cls)); + if (cls == SystemDictionary::Object_klass()) { + _visited_Object = true; + } _path.push(node); } void pop() { _path.pop(); } ! // Since the starting point can be an interface, we must ensure we catch ! // j.l.Object as the super once in those cases. The _visited_Object flag ! // only ensures we don't then repeatedly enqueue Object for each interface ! // in the class hierarchy. ! bool has_super(InstanceKlass* cls) { ! return cls->super() != NULL && (!_visited_Object || !cls->is_interface()); } Node* node_at_depth(int i) const { return (i >= _path.length()) ? NULL : _path.at(_path.length() - i - 1); }
*** 198,216 **** Node* n = node_at_depth(i); return n == NULL ? NULL : n->_algorithm_data; } void* current_data() { return data_at_depth(0); } - void cancel_iteration() { _cancelled = true; } - public: void run(InstanceKlass* root) { ALGO* algo = static_cast<ALGO*>(this); - reset_iteration(); - void* algo_data = algo->new_node_data(root); push(root, algo_data); bool top_needs_visit = true; do { --- 195,209 ----
*** 240,250 **** assert(next != NULL, "Otherwise we shouldn't be here"); algo_data = algo->new_node_data(next); push(next, algo_data); top_needs_visit = true; } ! } while (!is_cancelled() && has_more_nodes()); } }; class PrintHierarchy : public HierarchyVisitor<PrintHierarchy> { private: --- 233,243 ---- assert(next != NULL, "Otherwise we shouldn't be here"); algo_data = algo->new_node_data(next); push(next, algo_data); top_needs_visit = true; } ! } while (has_more_nodes()); } }; class PrintHierarchy : public HierarchyVisitor<PrintHierarchy> { private:
*** 442,460 **** ls.cr(); } } } - bool contains_signature(Symbol* query) { - for (int i = 0; i < _members.length(); ++i) { - if (query == _members.at(i).first->signature()) { - return true; - } - } - return false; - } - void print_selected(outputStream* str, int indent) const { assert(has_target(), "Should be called otherwise"); streamIndentor si(str, indent * 2); str->indent().print("Selected method: "); print_method(str, _selected_target); --- 435,444 ----
*** 519,544 **** void set_qualification_state(QualifiedState state) { _qualification_state = state; } protected: ! MethodFamily* _method_family; public: StatefulMethodFamily() { - _method_family = new MethodFamily(); - _qualification_state = QUALIFIED; - } - - StatefulMethodFamily(MethodFamily* mf) { - _method_family = mf; _qualification_state = QUALIFIED; } ! void set_target_if_empty(Method* m) { _method_family->set_target_if_empty(m); } ! MethodFamily* get_method_family() { return _method_family; } StateRestorer* record_method_and_dq_further(Method* mo); }; class StateRestorer : public PseudoScopeMark { --- 503,522 ---- void set_qualification_state(QualifiedState state) { _qualification_state = state; } protected: ! MethodFamily _method_family; public: StatefulMethodFamily() { _qualification_state = QUALIFIED; } ! void set_target_if_empty(Method* m) { _method_family.set_target_if_empty(m); } ! MethodFamily* get_method_family() { return &_method_family; } StateRestorer* record_method_and_dq_further(Method* mo); }; class StateRestorer : public PseudoScopeMark {
*** 554,566 **** }; StateRestorer* StatefulMethodFamily::record_method_and_dq_further(Method* mo) { StateRestorer* mark = new StateRestorer(this, _qualification_state); if (_qualification_state == QUALIFIED) { ! _method_family->record_qualified_method(mo); } else { ! _method_family->record_disqualified_method(mo); } // Everything found "above"??? this method in the hierarchy walk is set to // disqualified set_qualification_state(DISQUALIFIED); return mark; --- 532,544 ---- }; StateRestorer* StatefulMethodFamily::record_method_and_dq_further(Method* mo) { StateRestorer* mark = new StateRestorer(this, _qualification_state); if (_qualification_state == QUALIFIED) { ! _method_family.record_qualified_method(mo); } else { ! _method_family.record_disqualified_method(mo); } // Everything found "above"??? this method in the hierarchy walk is set to // disqualified set_qualification_state(DISQUALIFIED); return mark;
*** 604,620 **** } } return found; } ! static GrowableArray<EmptyVtableSlot*>* find_empty_vtable_slots( InstanceKlass* klass, const 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)); --- 582,596 ---- } } return found; } ! static void find_empty_vtable_slots(GrowableArray<EmptyVtableSlot*>* slots, InstanceKlass* klass, const GrowableArray<Method*>* mirandas, TRAPS) { assert(klass != NULL, "Must be valid class"); // 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));
*** 625,642 **** // (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)); } } } } --- 601,618 ---- // (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() && !SystemDictionary::is_nonpublic_Object_method(m))) { // 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. if (!already_in_vtable_slots(slots, m)) { + Method *impl = klass->lookup_method(m->name(), m->signature()); + if (impl == NULL || impl->is_overpass() || impl->is_static()) { slots->append(new EmptyVtableSlot(m)); } } } }
*** 647,659 **** 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)); } } } } --- 623,635 ---- 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. + if (!already_in_vtable_slots(slots, m)) { Method* impl = klass->lookup_method(m->name(), m->signature()); if (impl == NULL || impl->is_overpass() || impl->is_static()) { slots->append(new EmptyVtableSlot(m)); } } } }
*** 670,681 **** ls.indent(); slots->at(i)->print_on(&ls); ls.cr(); } } - - return slots; } // Iterates over the superinterface type hierarchy looking for all methods // with a specific erased signature. class FindMethodsByErasedSig : public HierarchyVisitor<FindMethodsByErasedSig> { --- 646,655 ----
*** 747,758 **** static void create_defaults_and_exceptions( GrowableArray<EmptyVtableSlot*>* slots, InstanceKlass* klass, TRAPS); static void generate_erased_defaults( ! InstanceKlass* klass, GrowableArray<EmptyVtableSlot*>* empty_slots, ! EmptyVtableSlot* slot, bool is_intf, TRAPS) { // sets up a set of methods with the same exact erased signature FindMethodsByErasedSig visitor(slot->name(), slot->signature(), is_intf); visitor.run(klass); --- 721,731 ---- static void create_defaults_and_exceptions( GrowableArray<EmptyVtableSlot*>* slots, InstanceKlass* klass, TRAPS); static void generate_erased_defaults( ! InstanceKlass* klass, EmptyVtableSlot* slot, bool is_intf, TRAPS) { // sets up a set of methods with the same exact erased signature FindMethodsByErasedSig visitor(slot->name(), slot->signature(), is_intf); visitor.run(klass);
*** 782,791 **** --- 755,765 ---- // overpass method that throws an exception and add it to the klass methods list. // The JVM does not create bridges nor handle generic signatures here. void DefaultMethods::generate_default_methods( InstanceKlass* klass, const GrowableArray<Method*>* mirandas, TRAPS) { assert(klass != NULL, "invariant"); + assert(klass != SystemDictionary::Object_klass(), "Shouldn't be called for Object"); // This resource mark is the bound for all memory allocation that takes // place during default method processing. After this goes out of scope, // all (Resource) objects' memory will be reclaimed. Be careful if adding an // embedded resource mark under here as that memory can't be used outside
*** 807,833 **** LogStream ls(lt); PrintHierarchy printer(&ls); printer.run(klass); } ! GrowableArray<EmptyVtableSlot*>* empty_slots = ! find_empty_vtable_slots(klass, mirandas, CHECK); ! for (int i = 0; i < empty_slots->length(); ++i) { ! EmptyVtableSlot* slot = empty_slots->at(i); LogTarget(Debug, defaultmethods) lt; if (lt.is_enabled()) { LogStream ls(lt); streamIndentor si(&ls, 2); ls.indent().print("Looking for default methods for slot "); slot->print_on(&ls); ls.cr(); } ! generate_erased_defaults(klass, empty_slots, slot, klass->is_interface(), CHECK); } log_debug(defaultmethods)("Creating defaults and overpasses..."); ! create_defaults_and_exceptions(empty_slots, klass, CHECK); log_debug(defaultmethods)("Default method processing complete"); } static int assemble_method_error( BytecodeConstantPool* cp, BytecodeBuffer* buffer, Symbol* errorName, Symbol* message, TRAPS) { --- 781,809 ---- LogStream ls(lt); PrintHierarchy printer(&ls); printer.run(klass); } ! GrowableArray<EmptyVtableSlot*> empty_slots; ! find_empty_vtable_slots(&empty_slots, klass, mirandas, CHECK); ! if (empty_slots.length() > 0) { ! for (int i = 0; i < empty_slots.length(); ++i) { ! EmptyVtableSlot* slot = empty_slots.at(i); LogTarget(Debug, defaultmethods) lt; if (lt.is_enabled()) { LogStream ls(lt); streamIndentor si(&ls, 2); ls.indent().print("Looking for default methods for slot "); slot->print_on(&ls); ls.cr(); } ! generate_erased_defaults(klass, slot, klass->is_interface(), CHECK); } log_debug(defaultmethods)("Creating defaults and overpasses..."); ! create_defaults_and_exceptions(&empty_slots, klass, CHECK); ! } log_debug(defaultmethods)("Default method processing complete"); } static int assemble_method_error( BytecodeConstantPool* cp, BytecodeBuffer* buffer, Symbol* errorName, Symbol* message, TRAPS) {
*** 912,923 **** // // Note that if overpass method are ever created that are not exception // throwing methods then the loader constraint checking logic for vtable and // itable creation needs to be changed to check loader constraints for the // overpass methods that do not throw exceptions. ! static void create_defaults_and_exceptions( ! GrowableArray<EmptyVtableSlot*>* slots, InstanceKlass* klass, TRAPS) { GrowableArray<Method*> overpasses; GrowableArray<Method*> defaults; BytecodeConstantPool bpool(klass->constants()); --- 888,898 ---- // // Note that if overpass method are ever created that are not exception // throwing methods then the loader constraint checking logic for vtable and // itable creation needs to be changed to check loader constraints for the // overpass methods that do not throw exceptions. ! static void create_defaults_and_exceptions(GrowableArray<EmptyVtableSlot*>* slots, InstanceKlass* klass, TRAPS) { GrowableArray<Method*> overpasses; GrowableArray<Method*> defaults; BytecodeConstantPool bpool(klass->constants());
*** 977,987 **** if (defaults.length() > 0) { create_default_methods(klass, &defaults, CHECK); } } ! static void create_default_methods( InstanceKlass* klass, GrowableArray<Method*>* new_methods, TRAPS) { int new_size = new_methods->length(); Array<Method*>* total_default_methods = MetadataFactory::new_array<Method*>( klass->class_loader_data(), new_size, NULL, CHECK); --- 952,962 ---- if (defaults.length() > 0) { create_default_methods(klass, &defaults, CHECK); } } ! static void create_default_methods(InstanceKlass* klass, GrowableArray<Method*>* new_methods, TRAPS) { int new_size = new_methods->length(); Array<Method*>* total_default_methods = MetadataFactory::new_array<Method*>( klass->class_loader_data(), new_size, NULL, CHECK);
< prev index next >