JDK-4803284 : Bad performance when HotSpot cannot optimize polymorphic calls
  • Type: Bug
  • Component: hotspot
  • Sub-Component: compiler
  • Affected Version: 1.4.1,1.4.2
  • Priority: P4
  • Status: Resolved
  • Resolution: Fixed
  • OS: linux,windows_2000
  • CPU: x86
  • Submitted: 2003-01-15
  • Updated: 2003-11-03
  • Resolved: 2003-11-03
The Version table provides details related to the release that this issue/RFE will be addressed.

Unresolved : Release in which this issue/RFE will be addressed.
Resolved: Release in which this issue/RFE has been resolved.
Fixed : Release in which this issue/RFE has been fixed. The release containing this fix may be available for download as an Early Access Release or a General Availability Release.

To download the current JDK release, click here.
Other
5.0 b28Fixed
Related Reports
Duplicate :  
Relates :  
Description
ln("*** Testing (Easy) ***");

    for (int i = ZERO; i < CYCLES; ++i)
      bench();
  }

  /**
   * Benchmark controller for "Easy" tests.
   */
  static void bench ()
  {
    t = new MethodEasy();
    new HelperD().polyEasyF(1);
    consume(Helper.x);

    startBench("Interface: ");
    do { t.benchInterface(); } while (!checkEnd());
    endBench();

    startBench("  TrulyPoly: ");
    do { t.benchTrulyPoly(); } while (!checkEnd());
    endBench();

    startBench("  Poly: ");
    do { t.benchPoly(); } while (!checkEnd());
    endBench();

    startBench("  Virtual: ");
    do { t.benchVirtual(); } while (!checkEnd());
    endBench();

    startBench("  Final: ");
    do { t.benchFinal(); } while (!checkEnd());
    endBench();

    startBench("  Static: ");
    do { t.benchStatic(); } while (!checkEnd());
    endBench();

    System.out.println();
  }
}
--- MethodBench.java
import java.text.DecimalFormat;
import java.text.MessageFormat;

/**
 * Benchmark for method devirtualization and inlining.
 *
 * This is technically a microbenchmark (tested code is minimal), but
 * we make a lot of effort to prevent "excessive" optimizations that
 * would make results irrelevant or hard to analyse.  The techniques
 * are apparently very successfull for the current crop of JITs.
 *
 * (c) 2002 by Osvaldo Pinali Doederlein.
 * Released to public domain.
 */
abstract public class MethodBench
{
  /**
   * Start time for the benchmark cycle.
   */
  private static long start;

  /**
   * Total time for the benchmark cycle.
   */
  private static long span;

  /**
   * Divider for the benchmark cycle, used for timer tuning.
   */
  private static int divider;

  /**
   * Formatter for timings.
   */
  private static final DecimalFormat fmt = new DecimalFormat("00.000");

  /**
   * Declare the helper here, init later, to fight dataflow optimizations.
   */
  protected static HelperC helper;

  /**
   * Consumes a value produced by the benchmark, so its calculation cannot be
   * eliminated as dead code (but it might still be computed in compilation time).
   */
  protected static void consume (int value)
  {
    System.out.print(MessageFormat.format("", new Object[]{new Integer(value)}));
  }

  /**
   * Starts one test.
   */
  protected static void startBench (String header)
  {
    System.out.print(header);
    helper = new HelperC();
    start = System.currentTimeMillis();
    divider = 1;
  }

  /**
   * Checks if the benchmark can stop (enough precision obtained).
   */
  protected static boolean checkEnd ()
  {
    span = System.currentTimeMillis() - start;

    if (span >= 1000)
      return true;
    else
    {
      ++divider;
      return false;
    }
  }

  /**
   * Ends one test.
   */
  protected static void endBench ()
  {
    consume(Helper.x);
    System.out.print(fmt.format(span / 100.0 / divider));
  }
}
--- HelperD.java
/**
 * Used only to override the polymorphic method.
 */
public class HelperD extends HelperC implements HelperInterface
{
  /**
   * Makes Helper.polyHardF() even more polymorphic.
   */
  public void polyHardF (int value) { x ^= value; }
}
--- Helper.java
/**
 * Invoked methods are in a different class, to make optimizations
 * harder (compilers may special-case for "local" calls).
 * Method bodies are minimal because we are only interested in the call.
 */
public class Helper
{
  /**
   * Holds computed data, with non-optimizable initial value.
   */
  public static int x = Integer.parseInt("0");

  /**
   * The polymorphic virtual method (Hard).
   */
  public void polyHardF (int value) { x += value; }

  /**
   * The virtual method (Hard).
   */
  public void virtualHardF (int value) { x += value; }

  /**
   * The non-virtual method (Hard).
   */
  public final void finalHardF (int value) { x += value; }

  /**
   * The static method (Hard).
   */
  public static void staticHardF (int value) { x += value; }

  /**
   * The polymorphic virtual method (Easy).
   */
  public void polyEasyF (int value) { x++; }

  /**
   * The virtual method (Easy).
   */
  public void virtualEasyF (int value) { x++; }

  /**
   * The non-virtual method (Easy).
   */
  public final void finalEasyF (int value) { x++; }

  /**
   * The static method (Easy).
   */
  public static void staticEasyF (int value) { x++; }
}
--- HelperInterface.java
/**
 * Enables the interface test.
 */
public interface HelperInterface
{
  /**
   * Makes polyHardF() interface-callable.
   */
  void polyHardF (int value);
}
--- HelperC.java
/**
 * Used only to override the polymorphic method.
 */
public class HelperC extends HelperA
{
  /**
   * Makes Helper.polyHardF() even more polymorphic.
   */
  public void polyHardF (int value) { x |= value; }
}
--- HelperB.java
/**
 * Used only to override the polymorphic method.
 */
public class HelperB extends Helper implements HelperInterface
{
  /**
   * Makes Helper.polyHardF() even more polymorphic.
   */
  public void polyHardF (int value) { x &= value; }
}
--- HelperA.java
/**
 * Used only to override the polymorphic method.
 */
public class HelperA extends Helper
{
  /**
   * Makes Helper.polyHardF() polymorphic.
   */
  public void polyHardF (int value) { x -= value; }

  /**
   * Makes Helper.polyEasyF() polymorphic.
   */
  public void polyEasyF (int value) { x--; }
}
--- MethodHard.java
/**
 * "Hard" test: Uses values not compilt-time computable for loop bounds, making
 * things harder for loop optimizations (favors profile-driven compilers).
 *
 * (c) 2002 by Osvaldo Pinali Doederlein.
 * Released to public domain.
 */
public class MethodHard extends MethodBench
{
  /**
   * Declare the benchmark instance here, init later, to fight dataflow
optimizations.
   */
  static MethodHard t;

  /**
   * Optimizer-friendly constant for the loop's max bound.
   */
  static final int CALLS = Integer.parseInt("100000000");

  /**
   * Optimizer-friendly constant for the loops' lower bounds.
   */
  static final int ZERO = Integer.parseInt("0");

  /**
   * Optimizer-friendly constant for the benchmark controller's loop.
   */
  static final int CYCLES = Integer.parseInt("5");

  /**
   * Tests interface method.
   */
  final void benchInterface ()
  {
    int calls = CALLS / 1000;
    HelperInterface helper = null, h1 = new HelperB(), h2 = new HelperD();

    for (int i = 0; i < 1000; ++i)
    {
      switch (i % 500)
      {
        case 0: helper = h1; break;
        case 1: helper = h2; break;
      }

      for (int j = ZERO; j < calls; ++j)
        helper.polyHardF(i);
    }
  }

  /**
   * Tests "truly" polymorphic virtual method.
   */
  final void benchTrulyPoly ()
  {
    int calls = CALLS / 1000;
    Helper helper = null, h1 = new Helper(), h2 = new HelperA();
    Helper h3 = new HelperB(), h4 = new HelperC(), h5 = new HelperD();

    for (int i = 0; i < 1000; ++i)
    {
      switch (i % 200)
      {
        case 0: helper = h1; break;
        case 1: helper = h2; break;
        case 2: helper = h3; break;
        case 3: helper = h4; break;
        case 4: helper = h5; break;
      }

      for (int j = ZERO; j < calls; ++j)
        helper.polyHardF(i);
    }
  }

  /**
   * Tests polymorphic virtual method.
   */
  final void benchPoly ()
  {
    for (int i = ZERO; i < CALLS; ++i)
      helper.polyHardF(i);
  }

  /**
   * Tests virtual method.
   */
  final void benchVirtual ()
  {
    for (int i = ZERO; i < CALLS; ++i)
      helper.virtualHardF(i);
  }

  /**
   * Tests non-virtual method.
   */
  final void benchFinal ()
  {
    for (int i = ZERO; i < CALLS; ++i)
      helper.finalHardF(i);
  }

  /**
   * Tests static method.
   */
  final void benchStatic ()
  {
    for (int i = ZERO; i < CALLS; ++i)
      Helper.staticHardF(i);
  }

  /**
   * Benchmark startup.
   */
  public static void main (String[] args)
  {
    System.out.println("*** Testing (Hard) ***");

    for (int i = ZERO; i < CYCLES; ++i)
      bench();
  }

  /**
   * Benchmark controller for "Hard" tests.
   */
  static void bench ()
  {
    t = new MethodHard();
    new HelperD().polyHardF(1);
    consume(Helper.x);

    startBench("Interface: ");
    do { t.benchInterface(); } while (!checkEnd());
    endBench();

    startBench("  TrulyPoly: ");
    do { t.benchTrulyPoly(); } while (!checkEnd());
    endBench();

    startBench("  Poly: ");
    do { t.benchPoly(); } while (!checkEnd());
    endBench();

    startBench("  Virtual: ");
    do { t.benchVirtual(); } while (!checkEnd());
    endBench();

    startBench("  Final: ");
    do { t.benchFinal(); } while (!checkEnd());
    endBench();

    startBench("  Static: ");
    do { t.benchStatic(); } while (!checkEnd());
    endBench();

    System.out.println();
  }
}

---------- END SOURCE ----------

CUSTOMER WORKAROUND :
Use older VMs, then losing important performance and API
enhancements of JDK 1.4.x.

This perf bug is important because in real world OO code,
there are lots of interface calls and virtual calls that are
really polymorphic and cannot be optimized by HotSpot's
devirtualization tricks.  In these cases, HotSpot should be
smart enough to not attempt any optimization and be happy
with the standard dynamic dispatch code and no inlining.
(Review ID: 179170) 
======================================================================


Name: jl125535			Date: 01/14/2003


FULL PRODUCT VERSION :
java version "1.4.1_01"
Java(TM) 2 Runtime Environment, Standard Edition (build 1.4.1_01-b01)
Java HotSpot(TM) Client VM (build 1.4.1_01-b01, mixed mode)

FULL OPERATING SYSTEM VERSION :
Microsoft Windows 2000 [Version 5.00.2195]

A DESCRIPTION OF THE PROBLEM :
I designed the MethodBench benchmark to measure how
effectively Java VMs optimize method invocations, with a
focus on devirtualization and inlining.  The first version
of the benchmark was published here:
http://javalobby.org/members/jpr/methodopt.jsp and the
results are outrageously good for Sun JDK 1.4.1's HotSpot
VMs.  My motivation is that existing syntethic benchmarks of
this kind (e.g. JGF's) are obsoleted by current optimizers;
MethodBench applies every technique I know to prevent the
"wrong" optimizations from invalidating the benchmark, and
uses multiple variations of the tests to analyse the
optimizer's behavior in all important scenarios (see
article; this version contains a few additional tricks).  (I
have yet to fix my use of Math.random() but it's just a
minor issue.)

Updating the benchmark to contemplate harder scenarios --
call sites that cannot be devirtualized, and interface calls
-- the initial scores reveal severely bad performance in the
latest HotSpot VMs, that consistently produce results up to
5X slower that other compilers (including Sun's but also
IBM's, one static compiler, and two .NET implementations).
It seems that HotSpot is desperately trying to apply
aggressive optimizations that cannot deliver any benefit in
the new, worst-case call sites, with the results below. Look
at "Polymorphic", "TrulyPoly" and "Poly" scores; all these
exhibit variable degrees of degenerated performance (i.e.,
substantially worse than older Sun VMs) for HotSpot 1.4.0
(Server) and HotSpot 1.4.1 (both Client and Server).

HotSpot Client 1.3.1_06:
*** Testing (Hard) ***
Interface: 15,160  TrulyPoly: 13,120  Poly: 11,720  Virtual:
11,720  Final: 05,310  Static: 03,960
Interface: 14,680  TrulyPoly: 12,810  Poly: 11,870  Virtual:
11,570  Final: 08,670  Static: 03,853
Interface: 35,780  TrulyPoly: 12,810  Poly: 12,030  Virtual:
11,720  Final: 05,235  Static: 03,853
Interface: 14,530  TrulyPoly: 12,810  Poly: 12,190  Virtual:
12,190  Final: 05,155  Static: 03,853
Interface: 14,380  TrulyPoly: 12,970  Poly: 12,180  Virtual:
12,030  Final: 05,160  Static: 03,853
*** Testing (Easy) ***
Interface: 11,880  TrulyPoly: 13,120  Poly: 11,880  Virtual:
11,870  Final: 05,235  Static: 04,427
Interface: 11,560  TrulyPoly: 12,820  Poly: 11,870  Virtual:
11,880  Final: 05,230  Static: 03,857
Interface: 12,030  TrulyPoly: 12,960  Poly: 11,880  Virtual:
12,030  Final: 05,390  Static: 03,853
Interface: 14,530  TrulyPoly: 12,970  Poly: 12,030  Virtual:
12,190  Final: 05,235  Static: 03,853
Interface: 14,220  TrulyPoly: 12,970  Poly: 12,030  Virtual:
12,030  Final: 05,235  Static: 03,800
HotSpot Server 1.3.1_06:
*** Testing (Hard) ***
Interface: 14,220  TrulyPoly: 10,620  Poly: 09,065  Virtual:
00,500  Final: 00,491  Static: 00,357
Interface: 13,750  TrulyPoly: 10,310  Poly: 08,985  Virtual:
00,370  Final: 00,376  Static: 00,357
Interface: 12,970  TrulyPoly: 10,470  Poly: 09,840  Virtual:
00,376  Final: 00,385  Static: 00,350
Interface: 12,960  TrulyPoly: 10,630  Poly: 08,905  Virtual:
00,430  Final: 00,430  Static: 00,423
Interface: 13,130  TrulyPoly: 10,460  Poly: 08,910  Virtual:
00,441  Final: 00,430  Static: 00,435
*** Testing (Easy) ***
Interface: 10,470  TrulyPoly: 00,391  Poly: 00,323  Virtual:
00,217  Final: 00,208  Static: 00,161
Interface: 11,560  TrulyPoly: 00,267  Poly: 00,267  Virtual:
00,159  Final: 00,159  Static: 00,164
Interface: 08,985  TrulyPoly: 00,238  Poly: 00,244  Virtual:
00,156  Final: 00,161  Static: 00,161
Interface: 13,430  TrulyPoly: 00,242  Poly: 00,238  Virtual:
00,161  Final: 00,159  Static: 00,161
Interface: 12,970  TrulyPoly: 00,242  Poly: 00,242  Virtual:
00,159  Final: 00,159  Static: 00,161
HotSpot Client 1.4.0_03:
*** Testing (Hard) ***
Interface: 14,850  TrulyPoly: 12,970  Poly: 11,720  Virtual:
05,155  Final: 05,155  Static: 02,695
Interface: 14,690  TrulyPoly: 12,970  Poly: 11,870  Virtual:
05,155  Final: 05,160  Static: 02,615
Interface: 14,380  TrulyPoly: 12,970  Poly: 12,030  Virtual:
05,155  Final: 05,080  Static: 02,655
Interface: 14,380  TrulyPoly: 13,120  Poly: 12,030  Virtual:
05,080  Final: 05,155  Static: 02,578
Interface: 14,530  TrulyPoly: 13,130  Poly: 11,870  Virtual:
05,155  Final: 05,155  Static: 02,618
*** Testing (Easy) ***
Interface: 11,880  TrulyPoly: 04,427  Poly: 05,465  Virtual:
05,550  Final: 05,235  Static: 03,800
Interface: 12,810  TrulyPoly: 04,167  Poly: 05,390  Virtual:
05,315  Final: 05,310  Static: 03,853
Interface: 11,720  TrulyPoly: 04,167  Poly: 05,235  Virtual:
05,310  Final: 05,315  Static: 03,853
Interface: 11,870  TrulyPoly: 04,167  Poly: 05,235  Virtual:
05,390  Final: 05,315  Static: 03,800
Interface: 15,310  TrulyPoly: 04,167  Poly: 05,315  Virtual:
05,390  Final: 05,310  Static: 03,857
HotSpot Server 1.4.0_03:
*** Testing (Hard) ***
Interface: 30,150  TrulyPoly: 30,630  Poly: 00,634  Virtual:
00,350  Final: 00,363  Static: 00,350
Interface: 29,060  TrulyPoly: 30,940  Poly: 00,598  Virtual:
00,357  Final: 00,350  Static: 00,357
Interface: 27,970  TrulyPoly: 29,060  Poly: 00,588  Virtual:
00,350  Final: 00,350  Static: 00,357
Interface: 28,910  TrulyPoly: 29,060  Poly: 00,588  Virtual:
00,350  Final: 00,357  Static: 00,345
Interface: 28,910  TrulyPoly: 29,060  Poly: 00,606  Virtual:
00,345  Final: 00,357  Static: 00,345
*** Testing (Easy) ***
Interface: 13,830  TrulyPoly: 00,132  Poly: 00,147  Virtual:
00,128  Final: 00,127  Static: 00,128
Interface: 24,210  TrulyPoly: 00,125  Poly: 00,164  Virtual:
00,125  Final: 00,127  Static: 00,125
Interface: 24,530  TrulyPoly: 00,125  Poly: 00,164  Virtual:
00,128  Final: 00,125  Static: 00,128
Interface: 24,530  TrulyPoly: 00,127  Poly: 00,161  Virtual:
00,127  Final: 00,127  Static: 00,127
Interface: 24,530  TrulyPoly: 00,127  Poly: 00,164  Virtual:
00,125  Final: 00,127  Static: 00,125
HotSpot Client 1.4.1_01:
*** Testing (Hard) ***
Interface: 47,970  TrulyPoly: 40,160  Poly: 35,780  Virtual:
03,903  Final: 03,960  Static: 04,530
Interface: 47,810  TrulyPoly: 40,630  Poly: 35,930  Virtual:
03,853  Final: 03,907  Static: 05,080
Interface: 48,750  TrulyPoly: 39,840  Poly: 35,930  Virtual:
03,857  Final: 03,853  Static: 05,155
Interface: 48,590  TrulyPoly: 39,840  Poly: 35,780  Virtual:
03,907  Final: 03,853  Static: 05,390
Interface: 48,590  TrulyPoly: 40,000  Poly: 35,940  Virtual:
03,853  Final: 03,853  Static: 05,000
*** Testing (Easy) ***
Interface: 39,380  TrulyPoly: 04,273  Poly: 05,230  Virtual:
05,160  Final: 05,075  Static: 03,853
Interface: 39,380  TrulyPoly: 03,907  Poly: 05,075  Virtual:
05,155  Final: 05,160  Static: 03,853
Interface: 58,750  TrulyPoly: 03,903  Poly: 05,080  Virtual:
05,155  Final: 05,080  Static: 03,853
Interface: 58,900  TrulyPoly: 03,857  Poly: 05,155  Virtual:
05,075  Final: 05,160  Static: 03,853
Interface: 57,970  TrulyPoly: 03,957  Poly: 05,155  Virtual:
05,080  Final: 05,155  Static: 03,853
HotSpot Server 1.4.1_01:
*** Testing (Hard) ***
Interface: 46,720  TrulyPoly: 47,960  Poly: 01,111  Virtual:
00,350  Final: 00,363  Static: 00,357
Interface: 47,490  TrulyPoly: 47,810  Poly: 01,063  Virtual:
00,350  Final: 00,350  Static: 00,350
Interface: 47,650  TrulyPoly: 47,660  Poly: 01,046  Virtual:
00,357  Final: 00,356  Static: 00,350
Interface: 47,340  TrulyPoly: 47,660  Poly: 01,032  Virtual:
00,357  Final: 00,350  Static: 00,357
Interface: 47,970  TrulyPoly: 47,500  Poly: 01,046  Virtual:
00,356  Final: 00,350  Static: 00,357
*** Testing (Easy) ***
Interface: 18,907  TrulyPoly: 00,196  Poly: 00,196  Virtual:
00,127  Final: 00,128  Static: 00,125
Interface: 51,400  TrulyPoly: 00,189  Poly: 00,192  Virtual:
00,127  Final: 00,123  Static: 00,123
Interface: 55,150  TrulyPoly: 00,189  Poly: 00,192  Virtual:
00,127  Final: 00,125  Static: 00,125
Interface: 55,150  TrulyPoly: 00,189  Poly: 00,192  Virtual:
00,128  Final: 00,123  Static: 00,127
Interface: 55,160  TrulyPoly: 00,189  Poly: 00,192  Virtual:
00,125  Final: 00,123  Static: 00,127
IBM JDK 1.3.1 (20020821):
*** Testing (Hard) ***
Interface: 09,300  TrulyPoly: 09,065  Poly: 10,310  Virtual:
02,540  Final: 01,308  Static: 01,270
Interface: 09,060  TrulyPoly: 08,985  Poly: 10,470  Virtual:
02,312  Final: 01,328  Static: 01,270
Interface: 09,140  TrulyPoly: 09,060  Poly: 10,320  Virtual:
02,406  Final: 01,329  Static: 01,289
Interface: 09,060  TrulyPoly: 08,985  Poly: 10,310  Virtual:
02,500  Final: 01,328  Static: 01,270
Interface: 09,060  TrulyPoly: 09,065  Poly: 10,310  Virtual:
02,468  Final: 01,429  Static: 01,289
*** Testing (Easy) ***
Interface: 09,145  TrulyPoly: 02,280  Poly: 02,406  Virtual:
02,344  Final: 00,005  Static: 00,000
Interface: 09,375  TrulyPoly: 02,374  Poly: 02,500  Virtual:
02,126  Final: 00,000  Static: 00,000
Interface: 09,140  TrulyPoly: 02,438  Poly: 02,436  Virtual:
02,000  Final: 00,000  Static: 00,000
Interface: 09,140  TrulyPoly: 02,188  Poly: 02,540  Virtual:
02,280  Final: 00,000  Static: 00,000
Interface: 09,215  TrulyPoly: 02,250  Poly: 02,282  Virtual:
02,188  Final: 00,000  Static: 00,000
Excelsior JET 3.0:
*** Testing (Hard) ***
Interface: 10,940  TrulyPoly: 10,310  Poly: 11,560  Virtual:
11,560  Final: 01,047  Static: 01,016
Interface: 11,250  TrulyPoly: 10,310  Poly: 11,400  Virtual:
11,570  Final: 01,146  Static: 01,047
Interface: 11,400  TrulyPoly: 10,470  Poly: 11,560  Virtual:
11,720  Final: 01,063  Static: 01,015
Interface: 11,410  TrulyPoly: 10,310  Poly: 11,560  Virtual:
11,560  Final: 01,063  Static: 01,062
Interface: 11,100  TrulyPoly: 10,310  Poly: 11,400  Virtual:
11,560  Final: 01,000  Static: 01,146
*** Testing (Easy) ***
Interface: 10,940  TrulyPoly: 10,940  Poly: 10,930  Virtual:
10,780  Final: 00,645  Static: 00,644
Interface: 10,940  TrulyPoly: 10,930  Poly: 10,780  Virtual:
10,940  Final: 00,644  Static: 00,635
Interface: 10,940  TrulyPoly: 11,090  Poly: 10,780  Virtual:
10,940  Final: 00,634  Static: 00,644
Interface: 11,100  TrulyPoly: 10,930  Poly: 10,940  Virtual:
10,940  Final: 00,635  Static: 00,644
Interface: 10,780  TrulyPoly: 11,090  Poly: 10,940  Virtual:
10,780  Final: 00,644  Static: 00,644
Microsoft .NET 1.1beta:
*** Testing (Hard) ***
Interface: 10,150  TrulyPoly: 08,980  Poly: 10,310  Virtual:
10,460  Final: 03,853  Static: 03,123
Interface: 10,150  TrulyPoly: 08,980  Poly: 10,310  Virtual:
10,310  Final: 03,853  Static: 03,045
Interface: 10,310  TrulyPoly: 08,980  Poly: 10,310  Virtual:
10,150  Final: 03,853  Static: 03,123
Interface: 10,310  TrulyPoly: 08,905  Poly: 10,310  Virtual:
10,460  Final: 03,853  Static: 03,593
Interface: 10,150  TrulyPoly: 09,060  Poly: 10,310  Virtual:
10,620  Final: 03,853  Static: 03,203
*** Testing (Easy) ***
Interface: 10,310  TrulyPoly: 08,980  Poly: 10,310  Virtual:
10,310  Final: 03,853  Static: 05,700
Interface: 10,310  TrulyPoly: 08,905  Poly: 10,310  Virtual:
10,310  Final: 03,853  Static: 05,545
Interface: 10,310  TrulyPoly: 08,980  Poly: 10,460  Virtual:
10,620  Final: 03,853  Static: 05,230
Interface: 10,150  TrulyPoly: 08,980  Poly: 10,310  Virtual:
10,460  Final: 03,853  Static: 05,545
Interface: 10,150  TrulyPoly: 08,980  Poly: 10,310  Virtual:
10,310  Final: 03,800  Static: 05,620
Mono 0.17:
*** Testing (Hard) ***
Interface: 14,84  TrulyPoly: 13,91  Poly: 14,69  Virtual:
15,15  Final: 3,96  Static: 5,075
Interface: 14,22  TrulyPoly: 13,59  Poly: 15  Virtual: 14,69
 Final: 3,95666666666667  Static: 5,47
Interface: 14,38  TrulyPoly: 13,43  Poly: 15,16  Virtual:
14,84  Final: 4,06333333333333  Static: 6,25
Interface: 14,06  TrulyPoly: 13,59  Poly: 14,85  Virtual: 15
 Final: 3,90333333333333  Static: 5,16
Interface: 14,53  TrulyPoly: 13,43  Poly: 14,85  Virtual:
14,37  Final: 4,11333333333333  Static: 5,705
*** Testing (Easy) ***
Interface: 13,59  TrulyPoly: 15,78  Poly: 17,66  Virtual:
17,5  Final: 13,12  Static: 12,35
Interface: 13,28  TrulyPoly: 15,93  Poly: 17,5  Virtual:
17,66  Final: 13,12  Static: 11,88
Interface: 13,43  TrulyPoly: 16,41  Poly: 17,5  Virtual:
17,34  Final: 13,75  Static: 12,19
Interface: 13,28  TrulyPoly: 15,93  Poly: 17,5  Virtual:
17,81  Final: 13,6  Static: 12,18
Interface: 13,13  TrulyPoly: 16,25  Poly: 17,18  Virtual:
17,82  Final: 13,43  Static: 11,88


REGRESSION.  Last worked in version 1.3

STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
1. javac *.java
2. java [-server] -Xbatch MethodEasy
3. java [-server] -Xbatch MethodHard


REPRODUCIBILITY :
This bug can be reproduced always.

---------- BEGIN SOURCE ----------
(Several public classes, save to proper individual .java files)
(Ask me if you want the full sources and scripts, but this is
enough for the Java platform tests)

--- MethodEasy.java
/**
 * "Easy" test: Uses only compile-time constants for loop bounds, making
 * things easier for loop optimizations reliant on static analysis.
 *
 * (c) 2002 by Osvaldo Pinali Doederlein.
 * Released to public domain.
 */
public class MethodEasy extends MethodBench
{
  /**
   * Declare the benchmark instance here, init later, to fight dataflow
optimizations.
   */
  static MethodEasy t;

  /**
   * Optimizer-friendly constant for the loop's max bound.
   */
  static final int CALLS = 100000000;

  /**
   * Optimizer-friendly constant for the loops' lower bounds.
   */
  static final int ZERO = 0;

  /**
   * Optimizer-friendly constant for the benchmark controller's loop.
   */
  static final int CYCLES = 5;

  /**
   * Tests interface method.
   */
  final void benchInterface ()
  {
    HelperInterface helper = (Math.random() < 0.5) ?
      (HelperInterface)new HelperB() : (HelperInterface)new HelperD();

    for (int i = ZERO; i < CALLS; ++i)
      helper.polyHardF(i);
  }

  /**
   * Tests "truly" polymorphic virtual method.
   */
  final void benchTrulyPoly ()
  {
    final int calls = CALLS / 1000;
    HelperC helper = null, h1 = new HelperC(), h2 = new HelperD();

    for (int i = 0; i < 1000; ++i)
    {
      switch (i % 500)
      {
        case 0: helper = h1; break;
        case 1: helper = h2; break;
      }

      for (int j = ZERO; j < calls; ++j)
        helper.polyEasyF(i);
    }
  }

  /**
   * Tests polymorphic virtual method.
   */
  final void benchPoly ()
  {
    for (int i = ZERO; i < CALLS; ++i)
      helper.polyEasyF(i);
  }

  /**
   * Tests virtual method.
   */
  final void benchVirtual ()
  {
    for (int i = ZERO; i < CALLS; ++i)
      helper.virtualEasyF(i);
  }

  /**
   * Tests non-virtual method.
   */
  final void benchFinal ()
  {
    for (int i = ZERO; i < CALLS; ++i)
      helper.finalEasyF(i);
  }

  /**
   * Tests static method.
   */
  final void benchStatic ()
  {
    for (int i = ZERO; i < CALLS; ++i)
      Helper.staticEasyF(i);
  }

  /**
   * Benchmark startup.
   */
  public static void main (String[] args)
  {
    System.out.print

Comments
CONVERTED DATA BugTraq+ Release Management Values COMMIT TO FIX: tiger FIXED IN: tiger-beta INTEGRATED IN: tiger-b28 tiger-beta
14-06-2004

SUGGESTED FIX ###@###.### 2003-10-30 1. Inline both virtual methods when the profiling shows only 2 receivers and second method called more then 10% of all calls. 2. To improve performance of micro-leaf calls: Don't generate stack overflow check when a compiled method doesn't have java calls and has frame size < vm_page_size/8.
11-06-2004

EVALUATION ###@###.### 2003-01-22 Improve performance of micro-leaf calls in next major release. ----- -----
22-01-2003