Mercurial > hg > graal-compiler
comparison src/share/vm/oops/klassVtable.cpp @ 6934:4735d2c84362
7200776: Implement default methods in interfaces
Summary: Add generic type analysis and default method selection algorithms
Reviewed-by: coleenp, acorn
author | kamg |
---|---|
date | Thu, 11 Oct 2012 12:25:42 -0400 |
parents | d8ce2825b193 |
children | 18fb7da42534 |
comparison
equal
deleted
inserted
replaced
6921:a1b8cf9cf970 | 6934:4735d2c84362 |
---|---|
52 // interface I. Let's say there is a method m in I that neither C nor any | 52 // interface I. Let's say there is a method m in I that neither C nor any |
53 // of its super classes implement (i.e there is no method of any access, with | 53 // of its super classes implement (i.e there is no method of any access, with |
54 // the same name and signature as m), then m is a Miranda method which is | 54 // the same name and signature as m), then m is a Miranda method which is |
55 // entered as a public abstract method in C's vtable. From then on it should | 55 // entered as a public abstract method in C's vtable. From then on it should |
56 // treated as any other public method in C for method over-ride purposes. | 56 // treated as any other public method in C for method over-ride purposes. |
57 void klassVtable::compute_vtable_size_and_num_mirandas(int &vtable_length, | 57 void klassVtable::compute_vtable_size_and_num_mirandas( |
58 int &num_miranda_methods, | 58 int* vtable_length_ret, int* num_new_mirandas, |
59 Klass* super, | 59 GrowableArray<Method*>* all_mirandas, Klass* super, |
60 Array<Method*>* methods, | 60 Array<Method*>* methods, AccessFlags class_flags, |
61 AccessFlags class_flags, | 61 Handle classloader, Symbol* classname, Array<Klass*>* local_interfaces, |
62 Handle classloader, | 62 TRAPS) { |
63 Symbol* classname, | |
64 Array<Klass*>* local_interfaces, | |
65 TRAPS | |
66 ) { | |
67 | |
68 No_Safepoint_Verifier nsv; | 63 No_Safepoint_Verifier nsv; |
69 | 64 |
70 // set up default result values | 65 // set up default result values |
71 vtable_length = 0; | 66 int vtable_length = 0; |
72 num_miranda_methods = 0; | |
73 | 67 |
74 // start off with super's vtable length | 68 // start off with super's vtable length |
75 InstanceKlass* sk = (InstanceKlass*)super; | 69 InstanceKlass* sk = (InstanceKlass*)super; |
76 vtable_length = super == NULL ? 0 : sk->vtable_length(); | 70 vtable_length = super == NULL ? 0 : sk->vtable_length(); |
77 | 71 |
84 if (needs_new_vtable_entry(mh, super, classloader, classname, class_flags, THREAD)) { | 78 if (needs_new_vtable_entry(mh, super, classloader, classname, class_flags, THREAD)) { |
85 vtable_length += vtableEntry::size(); // we need a new entry | 79 vtable_length += vtableEntry::size(); // we need a new entry |
86 } | 80 } |
87 } | 81 } |
88 | 82 |
83 GrowableArray<Method*> new_mirandas(20); | |
89 // compute the number of mirandas methods that must be added to the end | 84 // compute the number of mirandas methods that must be added to the end |
90 num_miranda_methods = get_num_mirandas(super, methods, local_interfaces); | 85 get_mirandas(&new_mirandas, all_mirandas, super, methods, local_interfaces); |
91 vtable_length += (num_miranda_methods * vtableEntry::size()); | 86 *num_new_mirandas = new_mirandas.length(); |
87 | |
88 vtable_length += *num_new_mirandas * vtableEntry::size(); | |
92 | 89 |
93 if (Universe::is_bootstrapping() && vtable_length == 0) { | 90 if (Universe::is_bootstrapping() && vtable_length == 0) { |
94 // array classes don't have their superclass set correctly during | 91 // array classes don't have their superclass set correctly during |
95 // bootstrapping | 92 // bootstrapping |
96 vtable_length = Universe::base_vtable_size(); | 93 vtable_length = Universe::base_vtable_size(); |
107 } | 104 } |
108 assert(super != NULL || vtable_length == Universe::base_vtable_size(), | 105 assert(super != NULL || vtable_length == Universe::base_vtable_size(), |
109 "bad vtable size for class Object"); | 106 "bad vtable size for class Object"); |
110 assert(vtable_length % vtableEntry::size() == 0, "bad vtable length"); | 107 assert(vtable_length % vtableEntry::size() == 0, "bad vtable length"); |
111 assert(vtable_length >= Universe::base_vtable_size(), "vtable too small"); | 108 assert(vtable_length >= Universe::base_vtable_size(), "vtable too small"); |
109 | |
110 *vtable_length_ret = vtable_length; | |
112 } | 111 } |
113 | 112 |
114 int klassVtable::index_of(Method* m, int len) const { | 113 int klassVtable::index_of(Method* m, int len) const { |
115 assert(m->vtable_index() >= 0, "do not ask this of non-vtable methods"); | 114 assert(m->vtable_index() >= 0, "do not ask this of non-vtable methods"); |
116 return m->vtable_index(); | 115 return m->vtable_index(); |
189 initialized++; | 188 initialized++; |
190 } | 189 } |
191 } | 190 } |
192 | 191 |
193 // add miranda methods; it will also update the value of initialized | 192 // add miranda methods; it will also update the value of initialized |
194 fill_in_mirandas(initialized); | 193 fill_in_mirandas(&initialized); |
195 | 194 |
196 // In class hierarchies where the accessibility is not increasing (i.e., going from private -> | 195 // In class hierarchies where the accessibility is not increasing (i.e., going from private -> |
197 // package_private -> publicprotected), the vtable might actually be smaller than our initial | 196 // package_private -> publicprotected), the vtable might actually be smaller than our initial |
198 // calculation. | 197 // calculation. |
199 assert(initialized <= _length, "vtable initialization failed"); | 198 assert(initialized <= _length, "vtable initialization failed"); |
247 } | 246 } |
248 | 247 |
249 return superk; | 248 return superk; |
250 } | 249 } |
251 | 250 |
251 // Methods that are "effectively" final don't need vtable entries. | |
252 bool method_is_effectively_final( | |
253 AccessFlags klass_flags, methodHandle target) { | |
254 return target->is_final() || klass_flags.is_final() && !target->is_overpass(); | |
255 } | |
252 | 256 |
253 // Update child's copy of super vtable for overrides | 257 // Update child's copy of super vtable for overrides |
254 // OR return true if a new vtable entry is required | 258 // OR return true if a new vtable entry is required |
255 // Only called for InstanceKlass's, i.e. not for arrays | 259 // Only called for InstanceKlass's, i.e. not for arrays |
256 // If that changed, could not use _klass as handle for klass | 260 // If that changed, could not use _klass as handle for klass |
267 // Static and <init> methods are never in | 271 // Static and <init> methods are never in |
268 if (target_method()->is_static() || target_method()->name() == vmSymbols::object_initializer_name()) { | 272 if (target_method()->is_static() || target_method()->name() == vmSymbols::object_initializer_name()) { |
269 return false; | 273 return false; |
270 } | 274 } |
271 | 275 |
272 if (klass->is_final() || target_method()->is_final()) { | 276 if (method_is_effectively_final(klass->access_flags(), target_method)) { |
273 // a final method never needs a new entry; final methods can be statically | 277 // a final method never needs a new entry; final methods can be statically |
274 // resolved and they have to be present in the vtable only if they override | 278 // resolved and they have to be present in the vtable only if they override |
275 // a super's method, in which case they re-use its entry | 279 // a super's method, in which case they re-use its entry |
276 allocate_new = false; | 280 allocate_new = false; |
277 } | 281 } |
404 Klass* super, | 408 Klass* super, |
405 Handle classloader, | 409 Handle classloader, |
406 Symbol* classname, | 410 Symbol* classname, |
407 AccessFlags class_flags, | 411 AccessFlags class_flags, |
408 TRAPS) { | 412 TRAPS) { |
409 if ((class_flags.is_final() || target_method()->is_final()) || | 413 |
414 if (method_is_effectively_final(class_flags, target_method) || | |
410 // a final method never needs a new entry; final methods can be statically | 415 // a final method never needs a new entry; final methods can be statically |
411 // resolved and they have to be present in the vtable only if they override | 416 // resolved and they have to be present in the vtable only if they override |
412 // a super's method, in which case they re-use its entry | 417 // a super's method, in which case they re-use its entry |
413 (target_method()->is_static()) || | 418 (target_method()->is_static()) || |
414 // static methods don't need to be in vtable | 419 // static methods don't need to be in vtable |
500 Klass* method_holder = m->method_holder(); | 505 Klass* method_holder = m->method_holder(); |
501 InstanceKlass *mhk = InstanceKlass::cast(method_holder); | 506 InstanceKlass *mhk = InstanceKlass::cast(method_holder); |
502 | 507 |
503 // miranda methods are interface methods in a class's vtable | 508 // miranda methods are interface methods in a class's vtable |
504 if (mhk->is_interface()) { | 509 if (mhk->is_interface()) { |
505 assert(m->is_public() && m->is_abstract(), "should be public and abstract"); | 510 assert(m->is_public(), "should be public"); |
506 assert(ik()->implements_interface(method_holder) , "this class should implement the interface"); | 511 assert(ik()->implements_interface(method_holder) , "this class should implement the interface"); |
507 assert(is_miranda(m, ik()->methods(), ik()->super()), "should be a miranda_method"); | 512 assert(is_miranda(m, ik()->methods(), ik()->super()), "should be a miranda_method"); |
508 return true; | 513 return true; |
509 } | 514 } |
510 return false; | 515 return false; |
530 } | 535 } |
531 | 536 |
532 return false; | 537 return false; |
533 } | 538 } |
534 | 539 |
535 void klassVtable::add_new_mirandas_to_list(GrowableArray<Method*>* list_of_current_mirandas, | 540 void klassVtable::add_new_mirandas_to_lists( |
536 Array<Method*>* current_interface_methods, | 541 GrowableArray<Method*>* new_mirandas, GrowableArray<Method*>* all_mirandas, |
537 Array<Method*>* class_methods, | 542 Array<Method*>* current_interface_methods, Array<Method*>* class_methods, |
538 Klass* super) { | 543 Klass* super) { |
539 // iterate thru the current interface's method to see if it a miranda | 544 // iterate thru the current interface's method to see if it a miranda |
540 int num_methods = current_interface_methods->length(); | 545 int num_methods = current_interface_methods->length(); |
541 for (int i = 0; i < num_methods; i++) { | 546 for (int i = 0; i < num_methods; i++) { |
542 Method* im = current_interface_methods->at(i); | 547 Method* im = current_interface_methods->at(i); |
543 bool is_duplicate = false; | 548 bool is_duplicate = false; |
544 int num_of_current_mirandas = list_of_current_mirandas->length(); | 549 int num_of_current_mirandas = new_mirandas->length(); |
545 // check for duplicate mirandas in different interfaces we implement | 550 // check for duplicate mirandas in different interfaces we implement |
546 for (int j = 0; j < num_of_current_mirandas; j++) { | 551 for (int j = 0; j < num_of_current_mirandas; j++) { |
547 Method* miranda = list_of_current_mirandas->at(j); | 552 Method* miranda = new_mirandas->at(j); |
548 if ((im->name() == miranda->name()) && | 553 if ((im->name() == miranda->name()) && |
549 (im->signature() == miranda->signature())) { | 554 (im->signature() == miranda->signature())) { |
550 is_duplicate = true; | 555 is_duplicate = true; |
551 break; | 556 break; |
552 } | 557 } |
555 if (!is_duplicate) { // we don't want duplicate miranda entries in the vtable | 560 if (!is_duplicate) { // we don't want duplicate miranda entries in the vtable |
556 if (is_miranda(im, class_methods, super)) { // is it a miranda at all? | 561 if (is_miranda(im, class_methods, super)) { // is it a miranda at all? |
557 InstanceKlass *sk = InstanceKlass::cast(super); | 562 InstanceKlass *sk = InstanceKlass::cast(super); |
558 // check if it is a duplicate of a super's miranda | 563 // check if it is a duplicate of a super's miranda |
559 if (sk->lookup_method_in_all_interfaces(im->name(), im->signature()) == NULL) { | 564 if (sk->lookup_method_in_all_interfaces(im->name(), im->signature()) == NULL) { |
560 list_of_current_mirandas->append(im); | 565 new_mirandas->append(im); |
566 } | |
567 if (all_mirandas != NULL) { | |
568 all_mirandas->append(im); | |
561 } | 569 } |
562 } | 570 } |
563 } | 571 } |
564 } | 572 } |
565 } | 573 } |
566 | 574 |
567 void klassVtable::get_mirandas(GrowableArray<Method*>* mirandas, | 575 void klassVtable::get_mirandas(GrowableArray<Method*>* new_mirandas, |
576 GrowableArray<Method*>* all_mirandas, | |
568 Klass* super, Array<Method*>* class_methods, | 577 Klass* super, Array<Method*>* class_methods, |
569 Array<Klass*>* local_interfaces) { | 578 Array<Klass*>* local_interfaces) { |
570 assert((mirandas->length() == 0) , "current mirandas must be 0"); | 579 assert((new_mirandas->length() == 0) , "current mirandas must be 0"); |
571 | 580 |
572 // iterate thru the local interfaces looking for a miranda | 581 // iterate thru the local interfaces looking for a miranda |
573 int num_local_ifs = local_interfaces->length(); | 582 int num_local_ifs = local_interfaces->length(); |
574 for (int i = 0; i < num_local_ifs; i++) { | 583 for (int i = 0; i < num_local_ifs; i++) { |
575 InstanceKlass *ik = InstanceKlass::cast(local_interfaces->at(i)); | 584 InstanceKlass *ik = InstanceKlass::cast(local_interfaces->at(i)); |
576 add_new_mirandas_to_list(mirandas, ik->methods(), class_methods, super); | 585 add_new_mirandas_to_lists(new_mirandas, all_mirandas, |
586 ik->methods(), class_methods, super); | |
577 // iterate thru each local's super interfaces | 587 // iterate thru each local's super interfaces |
578 Array<Klass*>* super_ifs = ik->transitive_interfaces(); | 588 Array<Klass*>* super_ifs = ik->transitive_interfaces(); |
579 int num_super_ifs = super_ifs->length(); | 589 int num_super_ifs = super_ifs->length(); |
580 for (int j = 0; j < num_super_ifs; j++) { | 590 for (int j = 0; j < num_super_ifs; j++) { |
581 InstanceKlass *sik = InstanceKlass::cast(super_ifs->at(j)); | 591 InstanceKlass *sik = InstanceKlass::cast(super_ifs->at(j)); |
582 add_new_mirandas_to_list(mirandas, sik->methods(), class_methods, super); | 592 add_new_mirandas_to_lists(new_mirandas, all_mirandas, |
583 } | 593 sik->methods(), class_methods, super); |
584 } | 594 } |
585 } | 595 } |
586 | |
587 // get number of mirandas | |
588 int klassVtable::get_num_mirandas(Klass* super, Array<Method*>* class_methods, Array<Klass*>* local_interfaces) { | |
589 ResourceMark rm; | |
590 GrowableArray<Method*>* mirandas = new GrowableArray<Method*>(20); | |
591 get_mirandas(mirandas, super, class_methods, local_interfaces); | |
592 return mirandas->length(); | |
593 } | 596 } |
594 | 597 |
595 // fill in mirandas | 598 // fill in mirandas |
596 void klassVtable::fill_in_mirandas(int& initialized) { | 599 void klassVtable::fill_in_mirandas(int* initialized) { |
597 ResourceMark rm; | 600 GrowableArray<Method*> mirandas(20); |
598 GrowableArray<Method*>* mirandas = new GrowableArray<Method*>(20); | 601 get_mirandas(&mirandas, NULL, ik()->super(), ik()->methods(), |
599 InstanceKlass *this_ik = ik(); | 602 ik()->local_interfaces()); |
600 get_mirandas(mirandas, this_ik->super(), this_ik->methods(), this_ik->local_interfaces()); | 603 for (int i = 0; i < mirandas.length(); i++) { |
601 int num_mirandas = mirandas->length(); | 604 put_method_at(mirandas.at(i), *initialized); |
602 for (int i = 0; i < num_mirandas; i++) { | 605 ++(*initialized); |
603 put_method_at(mirandas->at(i), initialized); | |
604 initialized++; | |
605 } | 606 } |
606 } | 607 } |
607 | 608 |
608 void klassVtable::copy_vtable_to(vtableEntry* start) { | 609 void klassVtable::copy_vtable_to(vtableEntry* start) { |
609 Copy::disjoint_words((HeapWord*)table(), (HeapWord*)start, _length * vtableEntry::size()); | 610 Copy::disjoint_words((HeapWord*)table(), (HeapWord*)start, _length * vtableEntry::size()); |