Example #1
0
CHAResult* CHA::analyze_call(KlassHandle calling_klass, KlassHandle static_receiver, KlassHandle actual_receiver, 
                             symbolHandle name, symbolHandle signature) {
  assert(static_receiver->oop_is_instance(), "must be instance klass");
  
  methodHandle m;
  // Only do exact lookup if receiver klass has been linked.  Otherwise,
  // the vtables has not been setup, and the LinkResolver will fail.
  if (instanceKlass::cast(static_receiver())->is_linked() && instanceKlass::cast(actual_receiver())->is_linked()) {    
    if (static_receiver->is_interface()) {
      // no point trying to resolve unless actual receiver is a klass
      if (!actual_receiver->is_interface()) {
        m = LinkResolver::resolve_interface_call_or_null(actual_receiver, static_receiver, name, signature, calling_klass);
      }
    } else {
      m = LinkResolver::resolve_virtual_call_or_null(actual_receiver, static_receiver, name, signature, calling_klass);
    }

    if (m.is_null()) {
      // didn't find method (e.g., could be abstract method)
      return new CHAResult(actual_receiver, name, signature, NULL, NULL, m, false);
    } 
    if( Klass::can_be_statically_bound(m()) ||
        m()->is_private() || 
        actual_receiver->subklass() == NULL ) {
      // always optimize final methods, private methods or methods with no
      // subclasses.
      return new CHAResult(actual_receiver, name, signature, NULL, NULL, m);
    } 
    if (!UseCHA) {
      // don't optimize this call
      return new CHAResult(actual_receiver, name, signature, NULL, NULL, m, false);
    }
  }

  // If the method is abstract then each non-abstract subclass must implement 
  // the method and inlining is not possible.  If there is exactly 1 subclass
  // then there can be only 1 implementation and we are OK.  
  if( !m.is_null() && m()->is_abstract() ) {// Method is abstract?
    Klass *sr = Klass::cast(static_receiver());
    if( sr == sr->up_cast_abstract() )
      return new CHAResult(actual_receiver, name, signature, NULL, NULL, m, false);
    // Fall into the next code; it will find the one implementation
    // and that implementation is correct.
  }

  _used = true;
  GrowableArray<methodHandle>* methods  = new GrowableArray<methodHandle>(CHA::max_result());
  GrowableArray<KlassHandle>* receivers = new GrowableArray<KlassHandle>(CHA::max_result());

  // Since 'm' is visible from the actual receiver we can call it if the
  // runtime receiver class does not override 'm'.  
  if( !m.is_null() && m()->method_holder() != actual_receiver() &&
      !m->is_abstract() ) {
    receivers->push(actual_receiver);
    methods->push(m);
  }
  if (static_receiver->is_interface()) {
    instanceKlassHandle sr = static_receiver();
    process_interface(sr, receivers, methods, name, signature);
  } else {
    process_class(static_receiver, receivers, methods, name, signature);
  }

  methodHandle dummy;
  CHAResult* res = new CHAResult(actual_receiver, name, signature, receivers, methods, dummy);

  //res->print();
  return res;
}