Mercurial > hg > graal-jvmci-8
comparison src/share/vm/jvmci/jvmciCompilerToVM.cpp @ 23347:7ae6a635fad0
8152903: [JVMCI] CompilerToVM::resolveMethod should correctly handle private methods in interfaces
author | Tom Rodriguez <tom.rodriguez@oracle.com> |
---|---|
date | Wed, 06 Apr 2016 20:02:32 -0700 |
parents | f8178417d018 |
children | 19855d029fc0 |
comparison
equal
deleted
inserted
replaced
23346:39f25354aeee | 23347:7ae6a635fad0 |
---|---|
477 } | 477 } |
478 return LinkResolver::vtable_index_of_interface_method(klass, method); | 478 return LinkResolver::vtable_index_of_interface_method(klass, method); |
479 C2V_END | 479 C2V_END |
480 | 480 |
481 C2V_VMENTRY(jobject, resolveMethod, (JNIEnv *, jobject, jobject receiver_jvmci_type, jobject jvmci_method, jobject caller_jvmci_type)) | 481 C2V_VMENTRY(jobject, resolveMethod, (JNIEnv *, jobject, jobject receiver_jvmci_type, jobject jvmci_method, jobject caller_jvmci_type)) |
482 Klass* recv_klass = CompilerToVM::asKlass(receiver_jvmci_type); | 482 KlassHandle recv_klass = CompilerToVM::asKlass(receiver_jvmci_type); |
483 Klass* caller_klass = CompilerToVM::asKlass(caller_jvmci_type); | 483 KlassHandle caller_klass = CompilerToVM::asKlass(caller_jvmci_type); |
484 Method* method = CompilerToVM::asMethod(jvmci_method); | 484 methodHandle method = CompilerToVM::asMethod(jvmci_method); |
485 | 485 |
486 if (recv_klass->oop_is_array() || (InstanceKlass::cast(recv_klass)->is_linked())) { | 486 KlassHandle h_resolved (THREAD, method->method_holder()); |
487 Klass* holder_klass = method->method_holder(); | 487 Symbol* h_name = method->name(); |
488 Symbol* method_name = method->name(); | 488 Symbol* h_signature = method->signature(); |
489 Symbol* method_signature = method->signature(); | 489 |
490 | 490 methodHandle m; |
491 | 491 // Only do exact lookup if receiver klass has been linked. Otherwise, |
492 if (holder_klass->is_interface()) { | 492 // the vtable has not been setup, and the LinkResolver will fail. |
493 // do link-time resolution to check all access rules. | 493 if (recv_klass->oop_is_array() || |
494 methodHandle resolved_method; | 494 InstanceKlass::cast(recv_klass())->is_linked() && !recv_klass->is_interface()) { |
495 LinkResolver::linktime_resolve_interface_method(resolved_method, holder_klass, method_name, method_signature, caller_klass, true, CHECK_AND_CLEAR_0); | 495 bool check_access = true; |
496 if (resolved_method->is_private()) { | 496 if (h_resolved->is_interface()) { |
497 return NULL; | 497 m = LinkResolver::resolve_interface_call_or_null(recv_klass, h_resolved, h_name, h_signature, caller_klass, check_access); |
498 } | |
499 assert(recv_klass->is_subtype_of(holder_klass), ""); | |
500 // do actual lookup | |
501 methodHandle sel_method; | |
502 LinkResolver::lookup_instance_method_in_klasses(sel_method, recv_klass, | |
503 resolved_method->name(), | |
504 resolved_method->signature(), CHECK_AND_CLEAR_0); | |
505 oop result = CompilerToVM::get_jvmci_method(sel_method, CHECK_NULL); | |
506 return JNIHandles::make_local(THREAD, result); | |
507 } else { | 498 } else { |
508 // do link-time resolution to check all access rules. | 499 m = LinkResolver::resolve_virtual_call_or_null(recv_klass, h_resolved, h_name, h_signature, caller_klass, check_access); |
509 methodHandle resolved_method; | 500 } |
510 LinkResolver::linktime_resolve_virtual_method(resolved_method, holder_klass, method_name, method_signature, caller_klass, true, CHECK_AND_CLEAR_0); | 501 } |
511 // do actual lookup (see LinkResolver::runtime_resolve_virtual_method) | 502 |
512 int vtable_index = Method::invalid_vtable_index; | 503 if (m.is_null()) { |
513 Method* selected_method; | 504 // Return NULL only if there was a problem with lookup (uninitialized class, etc.) |
514 | 505 return NULL; |
515 if (resolved_method->method_holder()->is_interface()) { // miranda method | 506 } |
516 vtable_index = LinkResolver::vtable_index_of_interface_method(holder_klass, resolved_method); | 507 |
517 assert(vtable_index >= 0 , "we should have valid vtable index at this point"); | 508 oop result = CompilerToVM::get_jvmci_method(m, CHECK_NULL); |
518 | 509 return JNIHandles::make_local(THREAD, result); |
519 InstanceKlass* inst = InstanceKlass::cast(recv_klass); | |
520 selected_method = inst->method_at_vtable(vtable_index); | |
521 } else { | |
522 // at this point we are sure that resolved_method is virtual and not | |
523 // a miranda method; therefore, it must have a valid vtable index. | |
524 assert(!resolved_method->has_itable_index(), ""); | |
525 vtable_index = resolved_method->vtable_index(); | |
526 // We could get a negative vtable_index for final methods, | |
527 // because as an optimization they are they are never put in the vtable, | |
528 // unless they override an existing method. | |
529 // If we do get a negative, it means the resolved method is the the selected | |
530 // method, and it can never be changed by an override. | |
531 if (vtable_index == Method::nonvirtual_vtable_index) { | |
532 assert(resolved_method->can_be_statically_bound(), "cannot override this method"); | |
533 selected_method = resolved_method(); | |
534 } else { | |
535 // recv_klass might be an arrayKlassOop but all vtables start at | |
536 // the same place. The cast is to avoid virtual call and assertion. | |
537 InstanceKlass* inst = (InstanceKlass*)recv_klass; | |
538 selected_method = inst->method_at_vtable(vtable_index); | |
539 } | |
540 } | |
541 oop result = CompilerToVM::get_jvmci_method(selected_method, CHECK_NULL); | |
542 return JNIHandles::make_local(THREAD, result); | |
543 } | |
544 } | |
545 return NULL; | |
546 C2V_END | 510 C2V_END |
547 | 511 |
548 C2V_VMENTRY(jboolean, hasFinalizableSubclass,(JNIEnv *, jobject, jobject jvmci_type)) | 512 C2V_VMENTRY(jboolean, hasFinalizableSubclass,(JNIEnv *, jobject, jobject jvmci_type)) |
549 Klass* klass = CompilerToVM::asKlass(jvmci_type); | 513 Klass* klass = CompilerToVM::asKlass(jvmci_type); |
550 assert(klass != NULL, "method must not be called for primitive types"); | 514 assert(klass != NULL, "method must not be called for primitive types"); |