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");