Beispiel #1
0
void CHA::process_interface(instanceKlassHandle r, GrowableArray<KlassHandle>* receivers, GrowableArray<methodHandle>* methods, 
                            symbolHandle name, symbolHandle signature) {
  // recursively add non-abstract implementors of interface r to receivers list
  assert(r->is_interface(), "should call process_class instead");
  
  // We only store the implementors for an interface, if there is exactly one implementor  
  klassOop k = r->implementor();
  assert(k == NULL || r->nof_implementors() == 1, "inconsistent implementor list");
  if (k != NULL && !methods->is_full()) {   
    instanceKlass* kl = instanceKlass::cast(k);
    assert(kl->oop_is_instance(), "primitive klasses don't implement interfaces");
    assert(!kl->is_interface(), "must be a real klass");
    process_class(kl, receivers, methods, name, signature);
  }

  // now process all subinterfaces
  for (Klass* s = r->subklass(); s != NULL && !methods->is_full(); s = s->next_sibling()) {
    assert(s->is_interface(), "must be an interface");
    instanceKlassHandle sub(s->as_klassOop());
    process_interface(sub, receivers, methods, name, signature);
    if (methods->is_full()) break;          // give up -- too many overriding methods
  }
}
Beispiel #2
0
void CHA::process_class(KlassHandle r, GrowableArray<KlassHandle>* receivers, GrowableArray<methodHandle>* methods, symbolHandle name, symbolHandle signature) {    
  // recursively add non-abstract subclasses of r to receivers list
  assert(!r->is_interface(), "should call process_interface instead");
  for (Klass* s = r->subklass(); s != NULL && !methods->is_full(); s = s->next_sibling()) {
    // preorder traversal, so check subclasses first
    if (s->is_interface()) {
      // can only happen if r == Object
      assert(r->superklass() == NULL, "must be klass Object");
    } else {
      process_class(s, receivers, methods, name, signature);
    }
  }
  // now check r itself (after subclasses because of preorder)
  if (!methods->is_full()) {
    // don't add abstract classes to receivers list
    // (but still consider their methods -- they may be non-abstract)
    if (!receivers->is_full() && !r->is_abstract()) receivers->push(r);
    methodOop m = NULL;
    if (r->oop_is_instance()) m = instanceKlass::cast(r())->find_method(name(), signature()); 
    if (m != NULL && !m->is_abstract()) {
      if (!methods->contains(m)) methods->push(m);
    }
  }
}
Beispiel #3
0
int
main (int argc, char** argv)
{
  JCF jcf[1];
  int argi, opt;

  /* Unlock the stdio streams.  */
  unlock_std_streams ();

  gcc_init_libintl ();

  if (argc <= 1)
    {
      fprintf (stderr, _("jcf-dump: no classes specified\n"));
      usage ();
    }

  jcf_path_init ();

  /* We use getopt_long_only to allow single `-' long options.  For
     some of our options this is more natural.  */
  while ((opt = getopt_long_only (argc, argv, "o:I:vc", options, NULL)) != -1)
    {
      switch (opt)
	{
	case 0:
	  /* Already handled.  */
	  break;

        case 'o':
	  output_file = optarg;
	  break;

	case 'I':
	  jcf_path_include_arg (optarg);
	  break;

	case 'v':
	  verbose++;
	  break;

	case 'c':
	  flag_disassemble_methods = 1;
	  break;

	case OPT_classpath:
	  jcf_path_classpath_arg (optarg);
	  break;

	case OPT_bootclasspath:
	  jcf_path_bootclasspath_arg (optarg);
	  break;

	case OPT_extdirs:
	  jcf_path_extdirs_arg (optarg);
	  break;

	case OPT_HELP:
	  help ();
	  break;

	case OPT_VERSION:
	  version ();
	  break;

	case OPT_JAVAP:
	  flag_javap_compatible++;
	  flag_print_constant_pool = 0;
	  flag_print_attributes = 0;
	  break;

	default:
	  usage ();
	}
    }

  if (verbose && ! flag_javap_compatible)
    flag_print_constant_pool = 1;

  if (optind == argc)
    {
      fprintf (stderr, _("jcf-dump: no classes specified\n"));
      usage ();
    }

  jcf_path_seal (verbose);

  if (flag_print_main)
    {
      flag_print_fields = 0;
      flag_print_methods = 0;
      flag_print_constant_pool = 0;
      flag_print_attributes = 0;
      flag_print_class_info = 0;
    }

  if (output_file)
    {
      out = fopen (output_file, "w");
      if (! out)
	{
	  fprintf (stderr, _("Cannot open '%s' for output.\n"), output_file);
	  return FATAL_EXIT_CODE;
	}
    }
  else
    out = stdout;

  if (optind >= argc)
    {
      fprintf (out, "Reading .class from <standard input>.\n");
      open_class ("<stdio>", jcf, 0, NULL);
      process_class (jcf);
    }
  else
    {
      for (argi = optind; argi < argc; argi++)
	{
	  char *arg = argv[argi];
	  const char *class_filename = find_class (arg, strlen (arg), jcf, 0);
	  if (class_filename == NULL)
	    class_filename = find_classfile (arg, jcf, NULL);
	  if (class_filename == NULL)
	    {
	      perror ("Could not find class");
	      return FATAL_EXIT_CODE;
	    }
	  JCF_FILL (jcf, 4);
	  if (GET_u4 (jcf->read_ptr) == ZIPMAGIC)
	    {
	      long compressed_size, member_size;
	      int compression_method, filename_length, extra_length;
	      int general_purpose_bits;
	      const char *filename;
	      int total_length;
	      if (flag_print_class_info)
		fprintf (out, "Reading classes from archive %s.\n",
			 class_filename);
	      for (;;)
		{
		  int skip = 0;
		  jcf_filbuf_t save_filbuf = jcf->filbuf;
		  long magic = JCF_readu4_le (jcf);
		  if (magic == 0x02014b50 || magic == 0x06054b50)
		    break;  /* got to central directory */
		  if (magic != 0x04034b50) /* ZIPMAGIC (little-endian) */
		    {
		      fprintf (stderr, _("bad format of .zip/.jar archive\n"));
		      return FATAL_EXIT_CODE;
		    }
		  JCF_FILL (jcf, 26);
		  JCF_SKIP (jcf, 2);
		  general_purpose_bits = JCF_readu2_le (jcf);
		  compression_method = JCF_readu2_le (jcf);
		  JCF_SKIP (jcf, 8);
		  compressed_size = JCF_readu4_le (jcf);
		  member_size = JCF_readu4_le (jcf);
		  filename_length = JCF_readu2_le (jcf);
		  extra_length = JCF_readu2_le (jcf);
		  total_length = filename_length + extra_length
		    + compressed_size;
		  if (jcf->read_end - jcf->read_ptr < total_length)
		    jcf_trim_old_input (jcf);
		  JCF_FILL (jcf, total_length);
		  filename = (const char *) jcf->read_ptr;
		  JCF_SKIP (jcf, filename_length);
		  JCF_SKIP (jcf, extra_length);
		  if (filename_length > 0
		      && filename[filename_length-1] == '/')
		    {
		      if (flag_print_class_info)
			fprintf (out, "[Skipping directory %.*s]\n",
				 filename_length, filename);
		      skip = 1;
		    }
		  else if (compression_method != 0)
		    {
		      if (flag_print_class_info)
			fprintf (out, "[Skipping compressed file %.*s]\n",
				 filename_length, filename);
		      skip = 1;
		    }
		  else if (member_size < 4
			   || GET_u4 (jcf->read_ptr) != 0xcafebabe)
		    {
		      if (flag_print_class_info)
			fprintf (out, "[Skipping non-.class member %.*s]\n",
				 filename_length, filename);
		      skip = 1;
		    }
		  else
		    {
		      if (flag_print_class_info)
			fprintf (out, "Reading class member: %.*s.\n",
				 filename_length, filename);
		    }
		  if (skip)
		    {
		      JCF_SKIP (jcf, compressed_size);
		    }
		  else
		    {
		      unsigned char *save_end;
		      jcf->filbuf = jcf_unexpected_eof;
		      save_end = jcf->read_end;
		      jcf->read_end = jcf->read_ptr + compressed_size;
		      process_class (jcf);
		      jcf->filbuf = save_filbuf;
		      jcf->read_end = save_end;
		    }
		}
	    }
	  else
	    {
	      if (flag_print_class_info)
		fprintf (out, "Reading .class from %s.\n", class_filename);
	      process_class (jcf);
	    }
	  JCF_FINISH(jcf);
	}
    }

  return SUCCESS_EXIT_CODE;
}
Beispiel #4
0
void report_process_update_display(void)
{
	unsigned int i, lines = 0;
	unsigned int total;

	int show_power;

	if ((!reportout.csv_report)&&(!reportout.http_report))
		return;

	sort(all_power.begin(), all_power.end(), power_cpu_sort);

	show_power = global_power_valid();

	if (reporttype){
		fprintf(reportout.http_report,
			"<div id=\"software\"><h2>%s</h2>\n <table width=\"100%%\">\n",_("Overview of Software Power Consumers"));
		if (show_power)
			fprintf(reportout.http_report,
				"<tr><th width=\"10%%\">%s</th><th width=\"10%%\">%s</th><th width=\"10%%\">%s</th><th width=\"10%%\">%s</th><th width=\"10%%\">%s</th><th width=\"10%%\">%s</th><th width=\"10%%\" class=\"process\">%s</th><th class=\"process\">%s</th></tr>\n",_("Power est."), _("Usage"), _("Wakeups/s"),_("GPU ops/s"),_("Disk IO/s"), _("GFX Wakeups/s"),_("Category"),_("Description"));
		else
			fprintf(reportout.http_report,
				"<tr><th width=\"10%%\">%s</th><th width=\"10%%\">%s</th><th width=\"10%%\">%s</th><th width=\"10%%\">%s</th><th width=\"10%%\">%s</th><th width=\"10%%\" class=\"process\">%s</th><th class=\"process\">%s</th></tr>\n",_("Usage"), _("Wakeups/s"),_("GPU ops/s"),_("Disk IO/s"), _("GFX Wakeups/s"),_("Category"),_("Description"));
	}else {
		fprintf(reportout.csv_report,"**Overview of Software Power Consumers**, \n\n");
		if (show_power)
			fprintf(reportout.csv_report,
				"Power est., Usage, Wakeups, GPU ops, Disk IO, GFX Wakeups, Category, Description, \n");
		else
			fprintf(reportout.csv_report,
				"Usage,  Wakeups, GPU ops, Disk IO, GFX Wakeups, Category, Description, \n");
	}

	total = all_power.size();

	if (total > 100)
		total = 100;

	for (i = 0; i < total; i++) {
		char power[16];
		char name[20];
		char usage[20];
		char wakes[20];
		char gpus[20];
		char disks[20];
		char xwakes[20];
		char descr[128];
		format_watts(all_power[i]->Witts(), power, 10);


		if (!show_power)
			strcpy(power, "          ");
		sprintf(name, "%s", all_power[i]->type());

		if (strcmp(name, "Device") == 0)
			continue;

		lines++;

		if (all_power[i]->events() == 0 && all_power[i]->usage() == 0 && all_power[i]->Witts() == 0)
			break;

		usage[0] = 0;
		if (all_power[i]->usage_units()) {
			if (all_power[i]->usage() < 1000)
				sprintf(usage, "%5.1f%s", all_power[i]->usage(), all_power[i]->usage_units());
			else
				sprintf(usage, "%5i%s", (int)all_power[i]->usage(), all_power[i]->usage_units());
		}
		sprintf(wakes, "%5.1f", all_power[i]->wake_ups / measurement_time);
		if (all_power[i]->wake_ups / measurement_time <= 0.3)
			sprintf(wakes, "%5.2f", all_power[i]->wake_ups / measurement_time);
		sprintf(gpus, "%5.1f", all_power[i]->gpu_ops / measurement_time);
		sprintf(disks, "%5.1f (%5.1f)", all_power[i]->hard_disk_hits / measurement_time, all_power[i]->disk_hits / measurement_time);
		sprintf(xwakes, "%5.1f", all_power[i]->xwakes / measurement_time);
		if (!all_power[i]->show_events()) {
			wakes[0] = 0;
			gpus[0] = 0;
			disks[0] = 0;
		}

		if (all_power[i]->gpu_ops == 0)
			gpus[0] = 0;
		if (all_power[i]->wake_ups == 0)
			wakes[0] = 0;
		if (all_power[i]->disk_hits == 0)
			disks[0] = 0;
		if (all_power[i]->xwakes == 0)
			xwakes[0] = 0;

		if (show_power) {
			if (reporttype)
				fprintf(reportout.http_report,"<tr class=\"%s\"><td class=\"process_power\">%s</td><td class=\"process_power\">%s</td><td class=\"process_power\">%s</td><td class=\"process_power\">%s</td><td class=\"process_power\">%s</td><td class=\"process_power\">%s</td><td>%s</td><td>%s</td></tr>\n",
					process_class(lines), power, usage, wakes, gpus, disks, xwakes, name, pretty_print(all_power[i]->description(), descr, 128));
			else
				fprintf(reportout.csv_report,"%s, %s, %s, %s, %s, %s, %s, %s,\n",
					power, usage, wakes, gpus, disks, xwakes, name,
					pretty_print(all_power[i]->description(), descr, 128));

		} else {
			if (reporttype)
				fprintf(reportout.http_report,"<tr class=\"%s\"><td class=\"process_power\">%s</td><td class=\"process_power\">%s</td><td class=\"process_power\">%s</td><td class=\"process_power\">%s</td><td class=\"process_power\">%s</td><td>%s</td><td>%s</td></tr>\n",
					process_class(lines), usage, wakes, gpus, disks, xwakes, name, pretty_print(all_power[i]->description(), descr, 128));
			else
				fprintf(reportout.csv_report,"%s, %s, %s, %s, %s, %s, %s, \n",
					usage, wakes, gpus, disks, xwakes, name,
					pretty_print(all_power[i]->description(), descr, 128));
		}
	}
	if (reporttype)
		fprintf(reportout.http_report,"</table></div>\n");
	else
		fprintf(reportout.csv_report,"\n");
}
Beispiel #5
0
void report_summary(void)
{
	unsigned int i, lines = 0;
	unsigned int total;

	int show_power;

	if ((!reportout.csv_report)&&(!reportout.http_report))
		return;

	sort(all_power.begin(), all_power.end(), power_cpu_sort);

	show_power = global_power_valid();

	if (reporttype) {
		fprintf(reportout.http_report,
			"<div id=\"summary\"><h2>%s</h2>\n",_("Power Consumption Summary"));
		fprintf(reportout.http_report,
			"<p>%3.1f %s,  %3.1f %s, %3.1f %s, %3.1f %s %3.1f%% %s</p>\n <table width=\"100%%\">\n",
			total_wakeups(), _("wakeups/second"), total_gpu_ops(),_("GPU ops/second"), total_disk_hits(),
			_("VFS ops/sec"), total_xwakes(),_("GFX wakes/sec and"), total_cpu_time()*100, _("CPU use"));

		if (show_power)
			fprintf(reportout.http_report,
			"<tr><th width=\"10%%\">%s</th><th width=\"10%%\">%s</th><th width=\"10%%\">%s</th><th width=\"10%%\" class=\"process\">%s</th><th class=\"process\">%s</th></tr>\n", _("Power est."), _("Usage"), _("Events/s"),_("Category"),_("Description"));

		else
		fprintf(reportout.http_report,
		"<tr><th width=\"10%%\">%s</th><th width=\"10%%\">%s</th><th width=\"10%%\" class=\"process\">%s</th><th class=\"process\">%s</th></tr>\n", _("Usage"), _("Events/s"),_("Category"),_("Description"));

	}else {
		fprintf(reportout.csv_report,
			"**Power Consumption Summary** \n");
		fprintf(reportout.csv_report,
			"%3.1f wakeups/second,  %3.1f GPU ops/second, %3.1f VFS ops/sec, %3.1f GFX wakes/sec and %3.1f%% CPU use \n\n",
			total_wakeups(), total_gpu_ops(), total_disk_hits(), total_xwakes(), total_cpu_time()*100);

		if (show_power)
			fprintf(reportout.csv_report,"Power est., Usage, Events/s, Category,  Description, \n");
        else
			fprintf(reportout.csv_report,"Usage, Events/s, Category, Description, \n");

	}
	total = all_power.size();
	if (total > 10)
		total = 10;

	for (i = 0; i < all_power.size(); i++) {
		char power[16];
		char name[20];
		char usage[20];
		char events[20];
		char descr[128];
		format_watts(all_power[i]->Witts(), power, 10);


		if (!show_power)
			strcpy(power, "          ");
		sprintf(name, "%s", all_power[i]->type());

		lines++;

		if (lines > total)
			break;

		if (all_power[i]->events() == 0 && all_power[i]->usage() == 0 && all_power[i]->Witts() == 0)
			break;

		usage[0] = 0;
		if (all_power[i]->usage_units()) {
			if (all_power[i]->usage() < 1000)
				sprintf(usage, "%5.1f%s", all_power[i]->usage_summary(), all_power[i]->usage_units_summary());
			else
				sprintf(usage, "%5i%s", (int)all_power[i]->usage_summary(), all_power[i]->usage_units_summary());
		}
		sprintf(events, "%5.1f", all_power[i]->events());
		if (!all_power[i]->show_events())
			events[0] = 0;
		else if (all_power[i]->events() <= 0.3)
			sprintf(events, "%5.2f", all_power[i]->events());

		if (show_power) {
			if (reporttype)
				fprintf(reportout.http_report,"<tr class=\"%s\"><td class=\"process_power\">%s</td><td class=\"process_power\">%s</td><td class=\"process_power\">%s</td><td>%s</td><td>%s</td></tr>\n",
					process_class(lines), power, usage, events, name, pretty_print(all_power[i]->description(), descr, 128));
			else
				fprintf(reportout.csv_report,"%s,%s,%s,%s,%s \n",
					power, usage, events, name, pretty_print(all_power[i]->description(), descr, 128));
		} else {
			if (reporttype)
				fprintf(reportout.http_report,
					"<tr class=\"%s\"><td class=\"process_power\">%s</td><td class=\"process_power\">%s</td><td>%s</td><td>%s</td></tr>\n",
					process_class(lines),usage, events, name, pretty_print(all_power[i]->description(), descr, 128));
			else
				fprintf(reportout.csv_report,"%s,%s,%s,%s, \n",
					usage, events, name, pretty_print(all_power[i]->description(), descr, 128));
		}
	}
	if (reporttype)
		fprintf(reportout.http_report,"</table></div>\n");
	else
		fprintf(reportout.csv_report,"\n");
}
Beispiel #6
0
 /*
  * boot_compact_db - compact specified classes
  * HEAP_CACHE_ATTRINFO structure
  *    return: error status
  *    class_oids(in): the classes list
  *    n_classes(in): the class_oids length
  * hfids(in):  the hfid list
  *    space_to_process(in): the space to process
  *    instance_lock_timeout(in): the lock timeout for instances
  *    class_lock_timeout(in): the lock timeout for instances
  *    delete_old_repr(in):  whether to delete the old class representation
  *    last_processed_class_oid(in,out): last processed class oid
  *    last_processed_oid(in,out): last processed oid
  *    total_objects(out): count processed objects for each class
  *    failed_objects(out): count failed objects for each class
  *    modified_objects(out): count modified objects for each class
  *    big_objects(out): count big objects for each class
  *    initial_last_repr_id(in, out): the list of initial last class 
  * representation
  */
int
boot_compact_db (THREAD_ENTRY * thread_p, OID * class_oids, int n_classes,
		 int space_to_process,
		 int instance_lock_timeout,
		 int class_lock_timeout,
		 bool delete_old_repr,
		 OID * last_processed_class_oid,
		 OID * last_processed_oid,
		 int *total_objects, int *failed_objects,
		 int *modified_objects, int *big_objects,
		 int *initial_last_repr_id)
{
  int result = NO_ERROR;
  int i, j, start_index = -1;
  int max_space_to_process, current_tran_index = -1;
  int lock_ret;
  HFID hfid;

  if (boot_can_compact (thread_p) == false)
    {
      return ER_COMPACTDB_ALREADY_STARTED;
    }

  if (class_oids == NULL || n_classes <= 0 ||
      space_to_process <= 0 || last_processed_class_oid == NULL ||
      last_processed_oid == NULL || total_objects == NULL ||
      failed_objects == NULL || modified_objects == NULL ||
      big_objects == NULL || initial_last_repr_id == NULL)
    {
      return ER_QPROC_INVALID_PARAMETER;
    }

  for (start_index = 0; start_index < n_classes; start_index++)
    {
      if (OID_EQ (class_oids + start_index, last_processed_class_oid))
	{
	  break;
	}
    }

  if (start_index == n_classes)
    {
      return ER_QPROC_INVALID_PARAMETER;
    }

  for (i = 0; i < n_classes; i++)
    {
      total_objects[i] = 0;
      failed_objects[i] = 0;
      modified_objects[i] = 0;
      big_objects[i] = 0;
    }

  max_space_to_process = space_to_process;
  for (i = start_index; i < n_classes; i++)
    {
      lock_ret = lock_object_waitsecs (thread_p, class_oids + i,
				       oid_Root_class_oid, IX_LOCK,
				       LK_UNCOND_LOCK, class_lock_timeout);

      if (lock_ret != LK_GRANTED)
	{
	  total_objects[i] = COMPACTDB_LOCKED_CLASS;
	  OID_SET_NULL (last_processed_oid);
	  continue;
	}

      if (heap_get_hfid_from_class_oid (thread_p, class_oids + i, &hfid) !=
	  NO_ERROR)
	{
	  lock_unlock_object (thread_p, class_oids + i, oid_Root_class_oid,
			      IX_LOCK, true);
	  OID_SET_NULL (last_processed_oid);
	  total_objects[i] = COMPACTDB_INVALID_CLASS;
	  continue;
	}

      if (HFID_IS_NULL (&hfid))
	{
	  lock_unlock_object (thread_p, class_oids + i, oid_Root_class_oid,
			      IX_LOCK, true);
	  OID_SET_NULL (last_processed_oid);
	  total_objects[i] = COMPACTDB_INVALID_CLASS;
	  continue;
	}

      if (OID_ISNULL (last_processed_oid))
	{
	  initial_last_repr_id[i] =
	    heap_get_class_repr_id (thread_p, class_oids + i);
	  if (initial_last_repr_id[i] <= 0)
	    {
	      lock_unlock_object (thread_p, class_oids + i,
				  oid_Root_class_oid, IX_LOCK, true);
	      total_objects[i] = COMPACTDB_INVALID_CLASS;
	      continue;
	    }
	}

      if (process_class
	  (thread_p, class_oids + i, &hfid, max_space_to_process,
	   &instance_lock_timeout, &space_to_process,
	   last_processed_oid, total_objects + i,
	   failed_objects + i, modified_objects + i, big_objects + i) !=
	  NO_ERROR)
	{
	  OID_SET_NULL (last_processed_oid);
	  for (j = start_index; j <= i; j++)
	    {
	      total_objects[j] = COMPACTDB_UNPROCESSED_CLASS;
	      failed_objects[j] = 0;
	      modified_objects[j] = 0;
	      big_objects[j] = 0;
	    }

	  result = ER_FAILED;
	  break;
	}

      if (delete_old_repr &&
	  OID_ISNULL (last_processed_oid) && failed_objects[i] == 0 &&
	  heap_get_class_repr_id (thread_p, class_oids + i) ==
	  initial_last_repr_id[i])
	{
	  lock_ret = lock_object_waitsecs (thread_p, class_oids + i,
					   oid_Root_class_oid, X_LOCK,
					   LK_UNCOND_LOCK,
					   class_lock_timeout);
	  if (lock_ret == LK_GRANTED)
	    {
	      if (catalog_drop_old_representations (thread_p, class_oids + i)
		  != NO_ERROR)
		{
		  for (j = start_index; j <= i; j++)
		    {
		      total_objects[j] = COMPACTDB_UNPROCESSED_CLASS;
		      failed_objects[j] = 0;
		      modified_objects[j] = 0;
		      big_objects[j] = 0;
		    }

		  result = ER_FAILED;
		}
	      else
		{
		  initial_last_repr_id[i] = COMPACTDB_REPR_DELETED;
		}

	      break;
	    }
	}

      if (space_to_process == 0)
	{
	  break;
	}
    }

  if (OID_ISNULL (last_processed_oid))
    {
      if (i < n_classes - 1)
	{
	  COPY_OID (last_processed_class_oid, class_oids + i + 1);
	}
      else
	{
	  OID_SET_NULL (last_processed_class_oid);
	}
    }
  else
    {
      COPY_OID (last_processed_class_oid, class_oids + i);
    }

  return result;
}
Beispiel #7
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;
}