src/share/vm/classfile/defaultMethods.cpp
Index Unified diffs Context diffs Sdiffs Wdiffs Patch New Old Previous File Next File bug_8027804.2 Sdiff src/share/vm/classfile

src/share/vm/classfile/defaultMethods.cpp

Print this page




 332   Symbol* _exception_name;    // If no unique target is found
 333 
 334   bool contains_method(Method* method) {
 335     int* lookup = _member_index.get(method);
 336     return lookup != NULL;
 337   }
 338 
 339   void add_method(Method* method, QualifiedState state) {
 340     Pair<Method*,QualifiedState> entry(method, state);
 341     _member_index.put(method, _members.length());
 342     _members.append(entry);
 343   }
 344 
 345   void disqualify_method(Method* method) {
 346     int* index = _member_index.get(method);
 347     guarantee(index != NULL && *index >= 0 && *index < _members.length(), "bad index");
 348     _members.at(*index).second = DISQUALIFIED;
 349   }
 350 
 351   Symbol* generate_no_defaults_message(TRAPS) const;

 352   Symbol* generate_conflicts_message(GrowableArray<Method*>* methods, TRAPS) const;
 353 
 354  public:
 355 
 356   MethodFamily()
 357       : _selected_target(NULL), _exception_message(NULL), _exception_name(NULL) {}
 358 
 359   void set_target_if_empty(Method* m) {
 360     if (_selected_target == NULL && !m->is_overpass()) {
 361       _selected_target = m;
 362     }
 363   }
 364 
 365   void record_qualified_method(Method* m) {
 366     // If the method already exists in the set as qualified, this operation is
 367     // redundant.  If it already exists as disqualified, then we leave it as
 368     // disqualfied.  Thus we only add to the set if it's not already in the
 369     // set.
 370     if (!contains_method(m)) {
 371       add_method(m, QUALIFIED);


 397 
 398     // Qualified methods are maximally-specific methods
 399     // These include public, instance concrete (=default) and abstract methods
 400     GrowableArray<Method*> qualified_methods;
 401     int num_defaults = 0;
 402     int default_index = -1;
 403     int qualified_index = -1;
 404     for (int i = 0; i < _members.length(); ++i) {
 405       Pair<Method*,QualifiedState> entry = _members.at(i);
 406       if (entry.second == QUALIFIED) {
 407         qualified_methods.append(entry.first);
 408         qualified_index++;
 409         if (entry.first->is_default_method()) {
 410           num_defaults++;
 411           default_index = qualified_index;
 412 
 413         }
 414       }
 415     }
 416 

 417     if (qualified_methods.length() == 0) {
 418       _exception_message = generate_no_defaults_message(CHECK);




 419       _exception_name = vmSymbols::java_lang_AbstractMethodError();
 420     // If only one qualified method is default, select that
 421     } else if (num_defaults == 1) {
 422         _selected_target = qualified_methods.at(default_index);
 423     } else if (num_defaults > 1) {
 424       _exception_message = generate_conflicts_message(&qualified_methods,CHECK);
 425       _exception_name = vmSymbols::java_lang_IncompatibleClassChangeError();
 426       if (TraceDefaultMethods) {
 427         _exception_message->print_value_on(tty);
 428         tty->print_cr("");
 429       }
 430     }
 431     // leave abstract methods alone, they will be found via normal search path
 432   }
 433 
 434   bool contains_signature(Symbol* query) {
 435     for (int i = 0; i < _members.length(); ++i) {
 436       if (query == _members.at(i).first->signature()) {
 437         return true;
 438       }
 439     }
 440     return false;
 441   }
 442 
 443 #ifndef PRODUCT
 444   void print_sig_on(outputStream* str, Symbol* signature, int indent) const {
 445     streamIndentor si(str, indent * 2);
 446 
 447     str->indent().print_cr("Logical Method %s:", signature->as_C_string());
 448 
 449     streamIndentor si2(str);
 450     for (int i = 0; i < _members.length(); ++i) {
 451       str->indent();


 469     Klass* method_holder = _selected_target->method_holder();
 470     if (!method_holder->is_interface()) {
 471       tty->print(" : in superclass");
 472     }
 473     str->print_cr("");
 474   }
 475 
 476   void print_exception(outputStream* str, int indent) {
 477     assert(throws_exception(), "Should be called otherwise");
 478     assert(_exception_name != NULL, "exception_name should be set");
 479     streamIndentor si(str, indent * 2);
 480     str->indent().print_cr("%s: %s", _exception_name->as_C_string(), _exception_message->as_C_string());
 481   }
 482 #endif // ndef PRODUCT
 483 };
 484 
 485 Symbol* MethodFamily::generate_no_defaults_message(TRAPS) const {
 486   return SymbolTable::new_symbol("No qualifying defaults found", CHECK_NULL);
 487 }
 488 













 489 Symbol* MethodFamily::generate_conflicts_message(GrowableArray<Method*>* methods, TRAPS) const {
 490   stringStream ss;
 491   ss.print("Conflicting default methods:");
 492   for (int i = 0; i < methods->length(); ++i) {
 493     Method* method = methods->at(i);
 494     Symbol* klass = method->klass_name();
 495     Symbol* name = method->name();
 496     ss.print(" ");
 497     ss.write((const char*)klass->bytes(), klass->utf8_length());
 498     ss.print(".");
 499     ss.write((const char*)name->bytes(), name->utf8_length());
 500   }
 501   return SymbolTable::new_symbol(ss.base(), (int)ss.size(), CHECK_NULL);
 502 }
 503 
 504 
 505 class StateRestorer;
 506 
 507 // StatefulMethodFamily is a wrapper around a MethodFamily that maintains the
 508 // qualification state during hierarchy visitation, and applies that state




 332   Symbol* _exception_name;    // If no unique target is found
 333 
 334   bool contains_method(Method* method) {
 335     int* lookup = _member_index.get(method);
 336     return lookup != NULL;
 337   }
 338 
 339   void add_method(Method* method, QualifiedState state) {
 340     Pair<Method*,QualifiedState> entry(method, state);
 341     _member_index.put(method, _members.length());
 342     _members.append(entry);
 343   }
 344 
 345   void disqualify_method(Method* method) {
 346     int* index = _member_index.get(method);
 347     guarantee(index != NULL && *index >= 0 && *index < _members.length(), "bad index");
 348     _members.at(*index).second = DISQUALIFIED;
 349   }
 350 
 351   Symbol* generate_no_defaults_message(TRAPS) const;
 352   Symbol* generate_method_message(Symbol *klass_name, Method* method, TRAPS) const;
 353   Symbol* generate_conflicts_message(GrowableArray<Method*>* methods, TRAPS) const;
 354 
 355  public:
 356 
 357   MethodFamily()
 358       : _selected_target(NULL), _exception_message(NULL), _exception_name(NULL) {}
 359 
 360   void set_target_if_empty(Method* m) {
 361     if (_selected_target == NULL && !m->is_overpass()) {
 362       _selected_target = m;
 363     }
 364   }
 365 
 366   void record_qualified_method(Method* m) {
 367     // If the method already exists in the set as qualified, this operation is
 368     // redundant.  If it already exists as disqualified, then we leave it as
 369     // disqualfied.  Thus we only add to the set if it's not already in the
 370     // set.
 371     if (!contains_method(m)) {
 372       add_method(m, QUALIFIED);


 398 
 399     // Qualified methods are maximally-specific methods
 400     // These include public, instance concrete (=default) and abstract methods
 401     GrowableArray<Method*> qualified_methods;
 402     int num_defaults = 0;
 403     int default_index = -1;
 404     int qualified_index = -1;
 405     for (int i = 0; i < _members.length(); ++i) {
 406       Pair<Method*,QualifiedState> entry = _members.at(i);
 407       if (entry.second == QUALIFIED) {
 408         qualified_methods.append(entry.first);
 409         qualified_index++;
 410         if (entry.first->is_default_method()) {
 411           num_defaults++;
 412           default_index = qualified_index;
 413 
 414         }
 415       }
 416     }
 417 
 418     if (num_defaults == 0) {
 419       if (qualified_methods.length() == 0) {
 420         _exception_message = generate_no_defaults_message(CHECK);
 421       } else {
 422         assert(root != NULL, "Null root class");
 423         _exception_message = generate_method_message(root->name(), qualified_methods.at(0), CHECK);
 424       }
 425       _exception_name = vmSymbols::java_lang_AbstractMethodError();
 426     // If only one qualified method is default, select that
 427     } else if (num_defaults == 1) {
 428         _selected_target = qualified_methods.at(default_index);
 429     } else if (num_defaults > 1) {
 430        _exception_message = generate_conflicts_message(&qualified_methods,CHECK);
 431        _exception_name = vmSymbols::java_lang_IncompatibleClassChangeError();
 432       if (TraceDefaultMethods) {
 433         _exception_message->print_value_on(tty);
 434         tty->print_cr("");
 435       }
 436     }

 437   }
 438 
 439   bool contains_signature(Symbol* query) {
 440     for (int i = 0; i < _members.length(); ++i) {
 441       if (query == _members.at(i).first->signature()) {
 442         return true;
 443       }
 444     }
 445     return false;
 446   }
 447 
 448 #ifndef PRODUCT
 449   void print_sig_on(outputStream* str, Symbol* signature, int indent) const {
 450     streamIndentor si(str, indent * 2);
 451 
 452     str->indent().print_cr("Logical Method %s:", signature->as_C_string());
 453 
 454     streamIndentor si2(str);
 455     for (int i = 0; i < _members.length(); ++i) {
 456       str->indent();


 474     Klass* method_holder = _selected_target->method_holder();
 475     if (!method_holder->is_interface()) {
 476       tty->print(" : in superclass");
 477     }
 478     str->print_cr("");
 479   }
 480 
 481   void print_exception(outputStream* str, int indent) {
 482     assert(throws_exception(), "Should be called otherwise");
 483     assert(_exception_name != NULL, "exception_name should be set");
 484     streamIndentor si(str, indent * 2);
 485     str->indent().print_cr("%s: %s", _exception_name->as_C_string(), _exception_message->as_C_string());
 486   }
 487 #endif // ndef PRODUCT
 488 };
 489 
 490 Symbol* MethodFamily::generate_no_defaults_message(TRAPS) const {
 491   return SymbolTable::new_symbol("No qualifying defaults found", CHECK_NULL);
 492 }
 493 
 494 Symbol* MethodFamily::generate_method_message(Symbol *klass_name, Method* method, TRAPS) const {
 495   stringStream ss;
 496   ss.print("Method ");
 497   Symbol* name = method->name();
 498   Symbol* signature = method->signature();
 499   ss.write((const char*)klass_name->bytes(), klass_name->utf8_length());
 500   ss.print(".");
 501   ss.write((const char*)name->bytes(), name->utf8_length());
 502   ss.write((const char*)signature->bytes(), signature->utf8_length());
 503   ss.print(" is abstract");
 504   return SymbolTable::new_symbol(ss.base(), (int)ss.size(), CHECK_NULL);
 505 }
 506 
 507 Symbol* MethodFamily::generate_conflicts_message(GrowableArray<Method*>* methods, TRAPS) const {
 508   stringStream ss;
 509   ss.print("Conflicting default methods:");
 510   for (int i = 0; i < methods->length(); ++i) {
 511     Method* method = methods->at(i);
 512     Symbol* klass = method->klass_name();
 513     Symbol* name = method->name();
 514     ss.print(" ");
 515     ss.write((const char*)klass->bytes(), klass->utf8_length());
 516     ss.print(".");
 517     ss.write((const char*)name->bytes(), name->utf8_length());
 518   }
 519   return SymbolTable::new_symbol(ss.base(), (int)ss.size(), CHECK_NULL);
 520 }
 521 
 522 
 523 class StateRestorer;
 524 
 525 // StatefulMethodFamily is a wrapper around a MethodFamily that maintains the
 526 // qualification state during hierarchy visitation, and applies that state


src/share/vm/classfile/defaultMethods.cpp
Index Unified diffs Context diffs Sdiffs Wdiffs Patch New Old Previous File Next File