void CHA::process_interface(instanceKlassHandle r, GrowableArray<KlassHandle>* receivers, GrowableArray<methodHandle>* methods, symbolHandle name, symbolHandle signature) { // recursively add non-abstract implementors of interface r to receivers list assert(r->is_interface(), "should call process_class instead"); // We only store the implementors for an interface, if there is exactly one implementor klassOop k = r->implementor(); assert(k == NULL || r->nof_implementors() == 1, "inconsistent implementor list"); if (k != NULL && !methods->is_full()) { instanceKlass* kl = instanceKlass::cast(k); assert(kl->oop_is_instance(), "primitive klasses don't implement interfaces"); assert(!kl->is_interface(), "must be a real klass"); process_class(kl, receivers, methods, name, signature); } // now process all subinterfaces for (Klass* s = r->subklass(); s != NULL && !methods->is_full(); s = s->next_sibling()) { assert(s->is_interface(), "must be an interface"); instanceKlassHandle sub(s->as_klassOop()); process_interface(sub, receivers, methods, name, signature); if (methods->is_full()) break; // give up -- too many overriding methods } }
void CHA::process_class(KlassHandle r, GrowableArray<KlassHandle>* receivers, GrowableArray<methodHandle>* methods, symbolHandle name, symbolHandle signature) { // recursively add non-abstract subclasses of r to receivers list assert(!r->is_interface(), "should call process_interface instead"); for (Klass* s = r->subklass(); s != NULL && !methods->is_full(); s = s->next_sibling()) { // preorder traversal, so check subclasses first if (s->is_interface()) { // can only happen if r == Object assert(r->superklass() == NULL, "must be klass Object"); } else { process_class(s, receivers, methods, name, signature); } } // now check r itself (after subclasses because of preorder) if (!methods->is_full()) { // don't add abstract classes to receivers list // (but still consider their methods -- they may be non-abstract) if (!receivers->is_full() && !r->is_abstract()) receivers->push(r); methodOop m = NULL; if (r->oop_is_instance()) m = instanceKlass::cast(r())->find_method(name(), signature()); if (m != NULL && !m->is_abstract()) { if (!methods->contains(m)) methods->push(m); } } }