Mercurial > hg > truffle
comparison src/share/vm/classfile/defaultMethods.cpp @ 14518:d8041d695d19
Merged with jdk9/dev/hotspot changeset 3812c088b945
author | twisti |
---|---|
date | Tue, 11 Mar 2014 18:45:59 -0700 |
parents | 02f27ecb4f3a 78468e5dc6fc |
children | 4ca6dc0799b6 |
comparison
equal
deleted
inserted
replaced
14141:f97c5ec83832 | 14518:d8041d695d19 |
---|---|
1 /* | 1 /* |
2 * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved. | 2 * Copyright (c) 2012, 2014, Oracle and/or its affiliates. All rights reserved. |
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. | 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
4 * | 4 * |
5 * This code is free software; you can redistribute it and/or modify it | 5 * This code is free software; you can redistribute it and/or modify it |
6 * under the terms of the GNU General Public License version 2 only, as | 6 * under the terms of the GNU General Public License version 2 only, as |
7 * published by the Free Software Foundation. | 7 * published by the Free Software Foundation. |
347 guarantee(index != NULL && *index >= 0 && *index < _members.length(), "bad index"); | 347 guarantee(index != NULL && *index >= 0 && *index < _members.length(), "bad index"); |
348 _members.at(*index).second = DISQUALIFIED; | 348 _members.at(*index).second = DISQUALIFIED; |
349 } | 349 } |
350 | 350 |
351 Symbol* generate_no_defaults_message(TRAPS) const; | 351 Symbol* generate_no_defaults_message(TRAPS) const; |
352 Symbol* generate_method_message(Symbol *klass_name, Method* method, TRAPS) const; | |
352 Symbol* generate_conflicts_message(GrowableArray<Method*>* methods, TRAPS) const; | 353 Symbol* generate_conflicts_message(GrowableArray<Method*>* methods, TRAPS) const; |
353 | 354 |
354 public: | 355 public: |
355 | 356 |
356 MethodFamily() | 357 MethodFamily() |
386 bool throws_exception() { return _exception_message != NULL; } | 387 bool throws_exception() { return _exception_message != NULL; } |
387 | 388 |
388 Method* get_selected_target() { return _selected_target; } | 389 Method* get_selected_target() { return _selected_target; } |
389 Symbol* get_exception_message() { return _exception_message; } | 390 Symbol* get_exception_message() { return _exception_message; } |
390 Symbol* get_exception_name() { return _exception_name; } | 391 Symbol* get_exception_name() { return _exception_name; } |
392 | |
393 // Return true if the specified klass has a static method that matches | |
394 // the name and signature of the target method. | |
395 bool has_matching_static(InstanceKlass* root) { | |
396 if (_members.length() > 0) { | |
397 Pair<Method*,QualifiedState> entry = _members.at(0); | |
398 Method* impl = root->find_method(entry.first->name(), | |
399 entry.first->signature()); | |
400 if ((impl != NULL) && impl->is_static()) { | |
401 return true; | |
402 } | |
403 } | |
404 return false; | |
405 } | |
391 | 406 |
392 // Either sets the target or the exception error message | 407 // Either sets the target or the exception error message |
393 void determine_target(InstanceKlass* root, TRAPS) { | 408 void determine_target(InstanceKlass* root, TRAPS) { |
394 if (has_target() || throws_exception()) { | 409 if (has_target() || throws_exception()) { |
395 return; | 410 return; |
412 | 427 |
413 } | 428 } |
414 } | 429 } |
415 } | 430 } |
416 | 431 |
417 if (qualified_methods.length() == 0) { | 432 if (num_defaults == 0) { |
418 _exception_message = generate_no_defaults_message(CHECK); | 433 // If the root klass has a static method with matching name and signature |
419 _exception_name = vmSymbols::java_lang_AbstractMethodError(); | 434 // then do not generate an overpass method because it will hide the |
435 // static method during resolution. | |
436 if (!has_matching_static(root)) { | |
437 if (qualified_methods.length() == 0) { | |
438 _exception_message = generate_no_defaults_message(CHECK); | |
439 } else { | |
440 assert(root != NULL, "Null root class"); | |
441 _exception_message = generate_method_message(root->name(), qualified_methods.at(0), CHECK); | |
442 } | |
443 _exception_name = vmSymbols::java_lang_AbstractMethodError(); | |
444 } | |
445 | |
420 // If only one qualified method is default, select that | 446 // If only one qualified method is default, select that |
421 } else if (num_defaults == 1) { | 447 } else if (num_defaults == 1) { |
422 _selected_target = qualified_methods.at(default_index); | 448 _selected_target = qualified_methods.at(default_index); |
423 } else if (num_defaults > 1) { | 449 |
450 } else if (num_defaults > 1 && !has_matching_static(root)) { | |
424 _exception_message = generate_conflicts_message(&qualified_methods,CHECK); | 451 _exception_message = generate_conflicts_message(&qualified_methods,CHECK); |
425 _exception_name = vmSymbols::java_lang_IncompatibleClassChangeError(); | 452 _exception_name = vmSymbols::java_lang_IncompatibleClassChangeError(); |
426 if (TraceDefaultMethods) { | 453 if (TraceDefaultMethods) { |
427 _exception_message->print_value_on(tty); | 454 _exception_message->print_value_on(tty); |
428 tty->print_cr(""); | 455 tty->print_cr(""); |
429 } | 456 } |
430 } | 457 } |
431 // leave abstract methods alone, they will be found via normal search path | |
432 } | 458 } |
433 | 459 |
434 bool contains_signature(Symbol* query) { | 460 bool contains_signature(Symbol* query) { |
435 for (int i = 0; i < _members.length(); ++i) { | 461 for (int i = 0; i < _members.length(); ++i) { |
436 if (query == _members.at(i).first->signature()) { | 462 if (query == _members.at(i).first->signature()) { |
482 #endif // ndef PRODUCT | 508 #endif // ndef PRODUCT |
483 }; | 509 }; |
484 | 510 |
485 Symbol* MethodFamily::generate_no_defaults_message(TRAPS) const { | 511 Symbol* MethodFamily::generate_no_defaults_message(TRAPS) const { |
486 return SymbolTable::new_symbol("No qualifying defaults found", CHECK_NULL); | 512 return SymbolTable::new_symbol("No qualifying defaults found", CHECK_NULL); |
513 } | |
514 | |
515 Symbol* MethodFamily::generate_method_message(Symbol *klass_name, Method* method, TRAPS) const { | |
516 stringStream ss; | |
517 ss.print("Method "); | |
518 Symbol* name = method->name(); | |
519 Symbol* signature = method->signature(); | |
520 ss.write((const char*)klass_name->bytes(), klass_name->utf8_length()); | |
521 ss.print("."); | |
522 ss.write((const char*)name->bytes(), name->utf8_length()); | |
523 ss.write((const char*)signature->bytes(), signature->utf8_length()); | |
524 ss.print(" is abstract"); | |
525 return SymbolTable::new_symbol(ss.base(), (int)ss.size(), CHECK_NULL); | |
487 } | 526 } |
488 | 527 |
489 Symbol* MethodFamily::generate_conflicts_message(GrowableArray<Method*>* methods, TRAPS) const { | 528 Symbol* MethodFamily::generate_conflicts_message(GrowableArray<Method*>* methods, TRAPS) const { |
490 stringStream ss; | 529 stringStream ss; |
491 ss.print("Conflicting default methods:"); | 530 ss.print("Conflicting default methods:"); |
1024 int new_size = klass->methods()->length() + new_methods->length(); | 1063 int new_size = klass->methods()->length() + new_methods->length(); |
1025 | 1064 |
1026 Array<Method*>* merged_methods = MetadataFactory::new_array<Method*>( | 1065 Array<Method*>* merged_methods = MetadataFactory::new_array<Method*>( |
1027 klass->class_loader_data(), new_size, NULL, CHECK); | 1066 klass->class_loader_data(), new_size, NULL, CHECK); |
1028 | 1067 |
1029 if (original_ordering != NULL && original_ordering->length() > 0) { | 1068 // original_ordering might be empty if this class has no methods of its own |
1069 if (JvmtiExport::can_maintain_original_method_order() || DumpSharedSpaces) { | |
1030 merged_ordering = MetadataFactory::new_array<int>( | 1070 merged_ordering = MetadataFactory::new_array<int>( |
1031 klass->class_loader_data(), new_size, CHECK); | 1071 klass->class_loader_data(), new_size, CHECK); |
1032 } | 1072 } |
1033 int method_order_index = klass->methods()->length(); | 1073 int method_order_index = klass->methods()->length(); |
1034 | 1074 |
1051 if (orig_method != NULL && | 1091 if (orig_method != NULL && |
1052 (new_method == NULL || orig_method->name() < new_method->name())) { | 1092 (new_method == NULL || orig_method->name() < new_method->name())) { |
1053 merged_methods->at_put(i, orig_method); | 1093 merged_methods->at_put(i, orig_method); |
1054 original_methods->at_put(orig_idx, NULL); | 1094 original_methods->at_put(orig_idx, NULL); |
1055 if (merged_ordering->length() > 0) { | 1095 if (merged_ordering->length() > 0) { |
1096 assert(original_ordering != NULL && original_ordering->length() > 0, | |
1097 "should have original order information for this method"); | |
1056 merged_ordering->at_put(i, original_ordering->at(orig_idx)); | 1098 merged_ordering->at_put(i, original_ordering->at(orig_idx)); |
1057 } | 1099 } |
1058 ++orig_idx; | 1100 ++orig_idx; |
1059 } else { | 1101 } else { |
1060 merged_methods->at_put(i, new_method); | 1102 merged_methods->at_put(i, new_method); |
1079 #endif | 1121 #endif |
1080 | 1122 |
1081 // Replace klass methods with new merged lists | 1123 // Replace klass methods with new merged lists |
1082 klass->set_methods(merged_methods); | 1124 klass->set_methods(merged_methods); |
1083 klass->set_initial_method_idnum(new_size); | 1125 klass->set_initial_method_idnum(new_size); |
1084 | 1126 klass->set_method_ordering(merged_ordering); |
1127 | |
1128 // Free metadata | |
1085 ClassLoaderData* cld = klass->class_loader_data(); | 1129 ClassLoaderData* cld = klass->class_loader_data(); |
1086 if (original_methods ->length() > 0) { | 1130 if (original_methods->length() > 0) { |
1087 MetadataFactory::free_array(cld, original_methods); | 1131 MetadataFactory::free_array(cld, original_methods); |
1088 } | 1132 } |
1089 if (original_ordering->length() > 0) { | 1133 if (original_ordering != NULL && original_ordering->length() > 0) { |
1090 klass->set_method_ordering(merged_ordering); | |
1091 MetadataFactory::free_array(cld, original_ordering); | 1134 MetadataFactory::free_array(cld, original_ordering); |
1092 } | 1135 } |
1093 } | 1136 } |