test/hotspot/jtreg/runtime/exceptionMsgs/AbstractMethodError/AbstractMethodErrorTest.java
changeset 49368 2ed1c37df3a5
child 49399 e0fec3292f00
equal deleted inserted replaced
49366:f95ef5511e1f 49368:2ed1c37df3a5
       
     1 /*
       
     2  * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
       
     3  * Copyright (c) 2018 SAP SE. All rights reserved.
       
     4  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
       
     5  *
       
     6  * This code is free software; you can redistribute it and/or modify it
       
     7  * under the terms of the GNU General Public License version 2 only, as
       
     8  * published by the Free Software Foundation.
       
     9  *
       
    10  * This code is distributed in the hope that it will be useful, but WITHOUT
       
    11  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
       
    12  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
       
    13  * version 2 for more details (a copy is included in the LICENSE file that
       
    14  * accompanied this code).
       
    15  *
       
    16  * You should have received a copy of the GNU General Public License version
       
    17  * 2 along with this work; if not, write to the Free Software Foundation,
       
    18  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
       
    19  *
       
    20  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
       
    21  * or visit www.oracle.com if you need additional information or have any
       
    22  * questions.
       
    23  */
       
    24 
       
    25 /**
       
    26  * @test
       
    27  * @summary Check that the verbose message of the AME is printed correctly.
       
    28  * @requires !(os.arch=="arm")
       
    29  * @library /test/lib /
       
    30  * @build sun.hotspot.WhiteBox
       
    31  * @run driver ClassFileInstaller sun.hotspot.WhiteBox sun.hotspot.WhiteBox$WhiteBoxPermission
       
    32  * @compile AbstractMethodErrorTest.java
       
    33  * @compile AME1_E.jasm AME2_C.jasm AME3_C.jasm AME4_E.jasm AME5_B.jasm AME6_B.jasm
       
    34  * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI
       
    35  *                   -XX:-BackgroundCompilation -XX:-Inline
       
    36  *                   -XX:CompileCommand=exclude,AbstractMethodErrorTest::test_ame1
       
    37  *                   AbstractMethodErrorTest
       
    38  */
       
    39 
       
    40 import sun.hotspot.WhiteBox;
       
    41 import compiler.whitebox.CompilerWhiteBoxTest;
       
    42 import java.lang.reflect.Method;
       
    43 
       
    44 // This test assembles an errorneous installation of classes.
       
    45 // First, compile the test by @compile. This results in a legal set
       
    46 // of classes.
       
    47 // Then, with jasm, generate incompatible classes that overwrite
       
    48 // the class files in the build directory.
       
    49 // Last, call the real test throwing an AbstractMethodError and
       
    50 // check the message generated.
       
    51 public class AbstractMethodErrorTest {
       
    52 
       
    53     private static final WhiteBox WHITE_BOX = WhiteBox.getWhiteBox();
       
    54 
       
    55     private static boolean enableChecks = true;
       
    56 
       
    57     public static void setup_test() {
       
    58         // Assure all exceptions are loaded.
       
    59         new AbstractMethodError();
       
    60         new IncompatibleClassChangeError();
       
    61 
       
    62         enableChecks = false;
       
    63         // Warmup
       
    64         System.out.println("warmup:");
       
    65         test_ame5_compiled_vtable_stub();
       
    66         test_ame6_compiled_itable_stub();
       
    67         enableChecks = true;
       
    68 
       
    69         // Compile
       
    70         try {
       
    71             Method method = AbstractMethodErrorTest.class.getMethod("test_ame5_compiled_vtable_stub");
       
    72             WHITE_BOX.enqueueMethodForCompilation(method, CompilerWhiteBoxTest.COMP_LEVEL_FULL_OPTIMIZATION);
       
    73             if (!WHITE_BOX.isMethodCompiled(method)) {
       
    74                 throw new RuntimeException(method.getName() + " is not compiled");
       
    75             }
       
    76             method = AbstractMethodErrorTest.class.getMethod("test_ame6_compiled_itable_stub");
       
    77             WHITE_BOX.enqueueMethodForCompilation(method, CompilerWhiteBoxTest.COMP_LEVEL_FULL_OPTIMIZATION);
       
    78             if (!WHITE_BOX.isMethodCompiled(method)) {
       
    79                 throw new RuntimeException(method.getName() + " is not compiled");
       
    80             }
       
    81             method = AME5_C.class.getMethod("c");
       
    82             WHITE_BOX.enqueueMethodForCompilation(method, CompilerWhiteBoxTest.COMP_LEVEL_FULL_OPTIMIZATION);
       
    83             if (!WHITE_BOX.isMethodCompiled(method)) {
       
    84                 throw new RuntimeException("AME5_C." + method.getName() + " is not compiled");
       
    85             }
       
    86             method = AME5_D.class.getMethod("c");
       
    87             WHITE_BOX.enqueueMethodForCompilation(method, CompilerWhiteBoxTest.COMP_LEVEL_FULL_OPTIMIZATION);
       
    88             if (!WHITE_BOX.isMethodCompiled(method)) {
       
    89                 throw new RuntimeException("AME5_D." + method.getName() + " is not compiled");
       
    90             }
       
    91             method = AME5_E.class.getMethod("c");
       
    92             WHITE_BOX.enqueueMethodForCompilation(method, CompilerWhiteBoxTest.COMP_LEVEL_FULL_OPTIMIZATION);
       
    93             if (!WHITE_BOX.isMethodCompiled(method)) {
       
    94                 throw new RuntimeException("AME5_E." + method.getName() + " is not compiled");
       
    95             }
       
    96             method = AME6_C.class.getMethod("c");
       
    97             WHITE_BOX.enqueueMethodForCompilation(method, CompilerWhiteBoxTest.COMP_LEVEL_FULL_OPTIMIZATION);
       
    98             if (!WHITE_BOX.isMethodCompiled(method)) {
       
    99                 throw new RuntimeException("AME6_C." + method.getName() + " is not compiled");
       
   100             }
       
   101             method = AME6_D.class.getMethod("c");
       
   102             WHITE_BOX.enqueueMethodForCompilation(method, CompilerWhiteBoxTest.COMP_LEVEL_FULL_OPTIMIZATION);
       
   103             if (!WHITE_BOX.isMethodCompiled(method)) {
       
   104                 throw new RuntimeException("AME6_D." + method.getName() + " is not compiled");
       
   105             }
       
   106             method = AME6_E.class.getMethod("c");
       
   107             WHITE_BOX.enqueueMethodForCompilation(method, CompilerWhiteBoxTest.COMP_LEVEL_FULL_OPTIMIZATION);
       
   108             if (!WHITE_BOX.isMethodCompiled(method)) {
       
   109                 throw new RuntimeException("AME6_E." + method.getName() + " is not compiled");
       
   110             }
       
   111         } catch (NoSuchMethodException e) { }
       
   112     }
       
   113 
       
   114     private static String expectedErrorMessageAME1_1 =
       
   115         "Missing implementation of resolved method abstract " +
       
   116         "anAbstractMethod()Ljava/lang/String; of abstract class AME1_B.";
       
   117     private static String expectedErrorMessageAME1_2 =
       
   118         "Receiver class AME1_E does not define or inherit an implementation of the " +
       
   119         "resolved method abstract aFunctionOfMyInterface()Ljava/lang/String; of " +
       
   120         "interface AME1_C.";
       
   121 
       
   122     public static void test_ame1() {
       
   123         AME1_B objectAbstract = new AME1_D();
       
   124         AME1_C objectInterface = new AME1_D();
       
   125         objectInterface.secondFunctionOfMyInterface();
       
   126         objectAbstract.anAbstractMethod();
       
   127         objectInterface.aFunctionOfMyInterface();
       
   128 
       
   129         try {
       
   130             objectAbstract = new AME1_E();
       
   131             // AbstractMethodError gets thrown in the interpreter at:
       
   132             // InterpreterGenerator::generate_abstract_entry
       
   133             objectAbstract.anAbstractMethod();
       
   134             throw new RuntimeException("Expected AbstractRuntimeError was not thrown.");
       
   135         } catch (AbstractMethodError e) {
       
   136             String errorMsg = e.getMessage();
       
   137             if (errorMsg == null) {
       
   138                 throw new RuntimeException("Caught AbstractMethodError with empty message.");
       
   139             } else if (!errorMsg.equals(expectedErrorMessageAME1_1)) {
       
   140                 System.out.println("Expected: " + expectedErrorMessageAME1_1 + "\n" +
       
   141                                    "but got:  " + errorMsg);
       
   142                 throw new RuntimeException("Wrong error message of AbstractMethodError.");
       
   143             }
       
   144         } catch (RuntimeException e) {
       
   145             throw e;
       
   146         } catch (Throwable e) {
       
   147             throw new RuntimeException("Caught unexpected exception: " + e);
       
   148         }
       
   149 
       
   150         try {
       
   151             objectInterface = new AME1_E();
       
   152             // AbstractMethodError gets thrown in:
       
   153             // TemplateTable::invokeinterface or C-Interpreter loop
       
   154             objectInterface.aFunctionOfMyInterface();
       
   155             throw new RuntimeException("Expected AbstractRuntimeError was not thrown.");
       
   156         } catch (AbstractMethodError e) {
       
   157             String errorMsg = e.getMessage();
       
   158             if (errorMsg == null) {
       
   159                 throw new RuntimeException("Caught AbstractMethodError with empty message.");
       
   160             } else if (!errorMsg.equals(expectedErrorMessageAME1_2)) {
       
   161                 // Thrown via InterpreterRuntime::throw_AbstractMethodErrorVerbose().
       
   162                 System.out.println("Expected: " + expectedErrorMessageAME1_2 + "\n" +
       
   163                                    "but got:  " + errorMsg);
       
   164                 throw new RuntimeException("Wrong error message of AbstractMethodError.");
       
   165             }
       
   166         } catch (Throwable e) {
       
   167             throw new RuntimeException("Caught unexpected exception: " + e);
       
   168         }
       
   169     }
       
   170 
       
   171     private static String expectedErrorMessageAME2_Interpreted =
       
   172         "Missing implementation of resolved method abstract " +
       
   173         "aFunctionOfMyInterface()V of interface AME2_A.";
       
   174     private static String expectedErrorMessageAME2_Compiled =
       
   175         "Receiver class AME2_C does not define or inherit an implementation of the resolved method " +
       
   176         "abstract aFunctionOfMyInterface()V of interface AME2_A.";
       
   177 
       
   178     public AbstractMethodErrorTest() throws InstantiationException, IllegalAccessException {
       
   179         try {
       
   180             AME2_B myAbstract = new ImplementsAllFunctions();
       
   181             myAbstract.fun2();
       
   182             myAbstract.aFunctionOfMyInterface();
       
   183 
       
   184             // AME2_C does not implement the method
       
   185             // aFunctionOfMyInterface(). Expected runtime behavior is
       
   186             // throwing an AbstractMethodError.
       
   187             // The error will be thrown via throw_AbstractMethodErrorWithMethod()
       
   188             // if the template interpreter calls an abstract method by
       
   189             // entering the abstract method entry.
       
   190             myAbstract = new AME2_C();
       
   191             myAbstract.fun2();
       
   192             myAbstract.aFunctionOfMyInterface();
       
   193         } catch (SecurityException e) {
       
   194             e.printStackTrace();
       
   195         }
       
   196     }
       
   197 
       
   198     // Loop so that method gets eventually compiled/osred.
       
   199     public static void test_ame2() throws Exception {
       
   200         boolean seenInterpreted = false;
       
   201         boolean seenCompiled = false;
       
   202 
       
   203         // Loop to test both, the interpreted and the compiled case.
       
   204         for (int i = 0; i < 10000 && !(seenInterpreted && seenCompiled); ++i) {
       
   205             try {
       
   206                 // Supposed to throw AME with verbose message.
       
   207                 new AbstractMethodErrorTest();
       
   208 
       
   209                 throw new RuntimeException("Expected AbstractMethodError was not thrown.");
       
   210             } catch (AbstractMethodError e) {
       
   211                 String errorMsg = e.getMessage();
       
   212 
       
   213                 // Check the message obtained.
       
   214                 if (errorMsg == null) {
       
   215                     throw new RuntimeException("Caught AbstractMethodError with empty message.");
       
   216                 } else if (errorMsg.equals(expectedErrorMessageAME2_Interpreted)) {
       
   217                     seenInterpreted = true;
       
   218                 } else if (errorMsg.equals(expectedErrorMessageAME2_Compiled)) {
       
   219                     // Sparc and the other platforms behave differently here:
       
   220                     // Sparc throws the exception via SharedRuntime::handle_wrong_method_abstract(),
       
   221                     // x86, ppc and s390 via LinkResolver::runtime_resolve_virtual_method(). Thus,
       
   222                     // sparc misses the test case for LinkResolver::runtime_resolve_virtual_method().
       
   223                     seenCompiled = true;
       
   224                 } else {
       
   225                     System.out.println("Expected: " + expectedErrorMessageAME2_Interpreted + "\n" +
       
   226                                        "or:       " + expectedErrorMessageAME2_Compiled + "\n" +
       
   227                                        "but got:  " + errorMsg);
       
   228                     throw new RuntimeException("Wrong error message of AbstractMethodError.");
       
   229                 }
       
   230             }
       
   231         }
       
   232         if (!(seenInterpreted && seenCompiled)) {
       
   233             if (seenInterpreted) { System.out.println("Saw interpreted message."); }
       
   234             if (seenCompiled)    { System.out.println("Saw compiled message."); }
       
   235             throw new RuntimeException("Test did not produce wrong error messages for AbstractMethodError, " +
       
   236                                        "but it did not test both cases (interpreted and compiled).");
       
   237         }
       
   238     }
       
   239 
       
   240     private static String expectedErrorMessageAME3_1 =
       
   241         "Receiver class AME3_C does not define or inherit an implementation of the resolved method " +
       
   242         "ma()V of class AME3_A. Selected method is abstract AME3_B.ma()V.";
       
   243 
       
   244     // Testing abstract class that extends a class that has an implementation.
       
   245     // Loop so that method gets eventually compiled/osred.
       
   246     public static void test_ame3_1() throws Exception {
       
   247         AME3_A c = new AME3_C();
       
   248 
       
   249         try {
       
   250             // Supposed to throw AME with verbose message.
       
   251             c.ma();
       
   252 
       
   253             throw new RuntimeException("Expected AbstractMethodError was not thrown.");
       
   254         } catch (AbstractMethodError e) {
       
   255             String errorMsg = e.getMessage();
       
   256 
       
   257             // Check the message obtained.
       
   258             if (errorMsg == null) {
       
   259                 throw new RuntimeException("Caught AbstractMethodError with empty message.");
       
   260             } else if (errorMsg.equals(expectedErrorMessageAME3_1)) {
       
   261                 // Expected test case thrown via LinkResolver::runtime_resolve_virtual_method().
       
   262             } else {
       
   263                 System.out.println("Expected: " + expectedErrorMessageAME3_1 + "\n" +
       
   264                                    "but got:  " + errorMsg);
       
   265                 throw new RuntimeException("Wrong error message of AbstractMethodError.");
       
   266             }
       
   267         }
       
   268     }
       
   269 
       
   270     private static String expectedErrorMessageAME3_2 =
       
   271         "Receiver class AME3_C does not define or inherit an implementation of " +
       
   272         "the resolved method abstract ma()V of abstract class AME3_B.";
       
   273 
       
   274     // Testing abstract class that extends a class that has an implementation.
       
   275     // Loop so that method gets eventually compiled/osred.
       
   276     public static void test_ame3_2() throws Exception {
       
   277         AME3_C c = new AME3_C();
       
   278 
       
   279         try {
       
   280             // Supposed to throw AME with verbose message.
       
   281             c.ma();
       
   282 
       
   283             throw new RuntimeException("Expected AbstractMethodError was not thrown.");
       
   284         } catch (AbstractMethodError e) {
       
   285             String errorMsg = e.getMessage();
       
   286 
       
   287             // Check the message obtained.
       
   288             if (errorMsg == null) {
       
   289                 throw new RuntimeException("Caught AbstractMethodError with empty message.");
       
   290             } else if (errorMsg.equals(expectedErrorMessageAME3_2)) {
       
   291                 // Expected test case thrown via LinkResolver::runtime_resolve_virtual_method().
       
   292             } else {
       
   293                 System.out.println("Expected: " + expectedErrorMessageAME3_2 + "\n" +
       
   294                                    "but got:  " + errorMsg);
       
   295                 throw new RuntimeException("Wrong error message of AbstractMethodError.");
       
   296             }
       
   297         }
       
   298     }
       
   299 
       
   300     private static String expectedErrorMessageAME4 =
       
   301         "Missing implementation of resolved method abstract ma()V of " +
       
   302         "abstract class AME4_B.";
       
   303 
       
   304     // Testing abstract class that extends a class that has an implementation.
       
   305     public static void test_ame4() throws Exception {
       
   306         AME4_C c = new AME4_C();
       
   307         AME4_D d = new AME4_D();
       
   308         AME4_E e = new AME4_E();  // Errorneous.
       
   309 
       
   310         AME4_A a;
       
   311         try {
       
   312             // Test: calls errorneous e.ma() in the last iteration.
       
   313             final int iterations = 10;
       
   314             for (int i = 0; i < iterations; i++) {
       
   315                 a = e;
       
   316                 if (i % 2 == 0 && i < iterations - 1) {
       
   317                     a = c;
       
   318                 }
       
   319                 if (i % 2 == 1 && i < iterations - 1) {
       
   320                     a = d;
       
   321                 }
       
   322 
       
   323                 // AbstractMethodError gets thrown in the interpreter at:
       
   324                 // InterpreterGenerator::generate_abstract_entry
       
   325                 a.ma();
       
   326             }
       
   327 
       
   328             throw new RuntimeException("Expected AbstractMethodError was not thrown.");
       
   329         } catch (AbstractMethodError exc) {
       
   330             System.out.println();
       
   331             String errorMsg = exc.getMessage();
       
   332 
       
   333                 // Check the message obtained.
       
   334             if (enableChecks && errorMsg == null) {
       
   335                 throw new RuntimeException("Caught AbstractMethodError with empty message.");
       
   336             } else if (errorMsg.equals(expectedErrorMessageAME4)) {
       
   337                 // Expected test case.
       
   338             } else if (enableChecks) {
       
   339                 System.out.println("Expected: " + expectedErrorMessageAME4 + "\n" +
       
   340                                    "but got:  " + errorMsg);
       
   341                 throw new RuntimeException("Wrong error message of AbstractMethodError.");
       
   342             }
       
   343         }
       
   344     }
       
   345 
       
   346     private static String expectedErrorMessageAME5_VtableStub =
       
   347         "Receiver class AME5_B does not define or inherit an implementation of the resolved method abstract mc()V " +
       
   348         "of abstract class AME5_A.";
       
   349 
       
   350     // AbstractMethodErrors detected in vtable stubs.
       
   351     // Note: How can we verify that we really stepped through the vtable stub?
       
   352     // - Bimorphic inlining should not happen since we have no profiling data when
       
   353     //   we compile the method
       
   354     // - As a result, an inline cache call should be generated
       
   355     // - This inline cache call is patched into a real vtable call at the first
       
   356     //   re-resolve, which happens constantly during the first 10 iterations of the loop.
       
   357     // => we should be fine! :-)
       
   358     public static void test_ame5_compiled_vtable_stub() {
       
   359         // Allocated the objects we need and call a valid method.
       
   360         boolean caught_ame = false;
       
   361         AME5_B b = new AME5_B();
       
   362         AME5_C c = new AME5_C();
       
   363         AME5_D d = new AME5_D();
       
   364         AME5_E e = new AME5_E();
       
   365         b.ma();
       
   366         c.ma();
       
   367         d.ma();
       
   368         e.ma();
       
   369 
       
   370         try {
       
   371             final int iterations = 10;
       
   372             // Test: calls b.c() in the last iteration.
       
   373             for (int i = 0; i < iterations; i++) {
       
   374                 AME5_A a = b;
       
   375                 if (i % 3 == 0 && i < iterations - 1) {
       
   376                     a = c;
       
   377                 }
       
   378                 if (i % 3 == 1 && i < iterations - 1) {
       
   379                     a = d;
       
   380                 }
       
   381                 if (i % 3 == 2 && i < iterations - 1) {
       
   382                     a = e;
       
   383                 }
       
   384 
       
   385               a.mc();
       
   386             }
       
   387             System.out.println();
       
   388         } catch (AbstractMethodError exc) {
       
   389             caught_ame = true;
       
   390             System.out.println();
       
   391             String errorMsg = exc.getMessage();
       
   392             if (enableChecks && errorMsg == null) {
       
   393                 System.out.println(exc);
       
   394                 throw new RuntimeException("Empty error message of AbstractMethodError.");
       
   395             }
       
   396             if (enableChecks &&
       
   397                 !errorMsg.equals(expectedErrorMessageAME5_VtableStub)) {
       
   398                 // Thrown via SharedRuntime::handle_wrong_method_abstract().
       
   399                 System.out.println("Expected: " + expectedErrorMessageAME5_VtableStub + "\n" +
       
   400                                    "but got:  " + errorMsg);
       
   401                 System.out.println(exc);
       
   402                 throw new RuntimeException("Wrong error message of AbstractMethodError.");
       
   403             }
       
   404             if (enableChecks) {
       
   405                 System.out.println("Passed with message: " + errorMsg);
       
   406             }
       
   407         } catch (Throwable exc) {
       
   408 
       
   409         throw exc;
       
   410         }
       
   411 
       
   412         // Check that we got the exception at some point.
       
   413         if (enableChecks && !caught_ame) {
       
   414             throw new RuntimeException("Expected AbstractMethodError was not thrown.");
       
   415         }
       
   416     }
       
   417 
       
   418     private static String expectedErrorMessageAME6_ItableStub =
       
   419         "Receiver class AME6_B does not define or inherit an implementation of the resolved" +
       
   420         " method abstract mc()V of interface AME6_A.";
       
   421 
       
   422     // -------------------------------------------------------------------------
       
   423     // AbstractMethodErrors detected in itable stubs.
       
   424     // Note: How can we verify that we really stepped through the itable stub?
       
   425     // - Bimorphic inlining should not happen since we have no profiling data when
       
   426     //   we compile the method
       
   427     // - As a result, an inline cache call should be generated
       
   428     // - This inline cache call is patched into a real vtable call at the first
       
   429     //   re-resolve, which happens constantly during the first 10 iterations of the loop.
       
   430     // => we should be fine! :-)
       
   431     public static void test_ame6_compiled_itable_stub() {
       
   432         // Allocated the objects we need and call a valid method.
       
   433         boolean caught_ame = false;
       
   434         AME6_B b = new AME6_B();
       
   435         AME6_C c = new AME6_C();
       
   436         AME6_D d = new AME6_D();
       
   437         AME6_E e = new AME6_E();
       
   438         b.ma();
       
   439         c.ma();
       
   440         d.ma();
       
   441         e.ma();
       
   442 
       
   443         try {
       
   444             final int iterations = 10;
       
   445             // Test: calls b.c() in the last iteration.
       
   446             for (int i = 0; i < iterations; i++) {
       
   447                 AME6_A a = b;
       
   448                 if (i % 3 == 0 && i < iterations - 1) {
       
   449                     a = c;
       
   450                 }
       
   451                 if (i % 3 == 1 && i < iterations - 1) {
       
   452                     a = d;
       
   453                 }
       
   454                 if (i % 3 == 2 && i < iterations - 1) {
       
   455                     a = e;
       
   456                 }
       
   457                 a.mc();
       
   458             }
       
   459             System.out.println();
       
   460         } catch (AbstractMethodError exc) {
       
   461             caught_ame = true;
       
   462             System.out.println();
       
   463             String errorMsg = exc.getMessage();
       
   464             if (enableChecks && errorMsg == null) {
       
   465                 System.out.println(exc);
       
   466                 throw new RuntimeException("Empty error message of AbstractMethodError.");
       
   467             }
       
   468             if (enableChecks &&
       
   469                 !errorMsg.equals(expectedErrorMessageAME6_ItableStub)) {
       
   470                 // Thrown via LinkResolver::runtime_resolve_interface_method().
       
   471                 System.out.println("Expected: " + expectedErrorMessageAME6_ItableStub + "\n" +
       
   472                                    "but got:  " + errorMsg);
       
   473                 System.out.println(exc);
       
   474                 throw new RuntimeException("Wrong error message of AbstractMethodError.");
       
   475             }
       
   476             if (enableChecks) {
       
   477                 System.out.println("Passed with message: " + errorMsg);
       
   478             }
       
   479         } catch (Throwable exc) {
       
   480             throw exc;
       
   481         }
       
   482 
       
   483         // Check that we got the exception at some point.
       
   484         if (enableChecks && !caught_ame) {
       
   485             throw new RuntimeException("Expected AbstractMethodError was not thrown.");
       
   486         }
       
   487     }
       
   488 
       
   489 
       
   490     public static void main(String[] args) throws Exception {
       
   491         setup_test();
       
   492         test_ame1();
       
   493         test_ame2();
       
   494         test_ame3_1();
       
   495         test_ame3_2();
       
   496         test_ame4();
       
   497         test_ame5_compiled_vtable_stub();
       
   498         test_ame6_compiled_itable_stub();
       
   499     }
       
   500 }
       
   501 
       
   502 // Helper classes to test abstract method error.
       
   503 //
       
   504 // Errorneous versions of these classes are implemented in java
       
   505 // assembler.
       
   506 
       
   507 
       
   508 // -------------------------------------------------------------------------
       
   509 // This error should be detected interpreted.
       
   510 //
       
   511 // Class hierachy:
       
   512 //
       
   513 //            C     // interface, defines aFunctionOfMyInterface()
       
   514 //            |
       
   515 //      A     |     // interface
       
   516 //      |     |
       
   517 //      B     |     // abstract class, defines anAbstractMethod()
       
   518 //       \   /
       
   519 //         E        // errorneous class implementation lacks methods C::aFunctionOfMyInterface()
       
   520 //                                                                   B::anAbstractMethod()
       
   521 interface AME1_A {
       
   522 
       
   523     public String firstFunctionOfMyInterface0();
       
   524 
       
   525     public String secondFunctionOfMyInterface0();
       
   526 }
       
   527 
       
   528 abstract class AME1_B implements AME1_A {
       
   529 
       
   530     abstract public String firstAbstractMethod();
       
   531 
       
   532     abstract public String secondAbstractMethod();
       
   533 
       
   534     abstract public String anAbstractMethod();
       
   535 }
       
   536 
       
   537 interface AME1_C {
       
   538 
       
   539     public String firstFunctionOfMyInterface();
       
   540 
       
   541     public String secondFunctionOfMyInterface();
       
   542 
       
   543     public String aFunctionOfMyInterface();
       
   544 }
       
   545 
       
   546 class AME1_D extends AME1_B implements AME1_C {
       
   547 
       
   548     public AME1_D() {
       
   549     }
       
   550 
       
   551     public String firstAbstractMethod() {
       
   552         return this.getClass().getName();
       
   553     }
       
   554 
       
   555     public String secondAbstractMethod() {
       
   556         return this.getClass().getName();
       
   557     }
       
   558 
       
   559     public String anAbstractMethod() {
       
   560         return this.getClass().getName();
       
   561     }
       
   562 
       
   563     public String firstFunctionOfMyInterface0() {
       
   564         return this.getClass().getName();
       
   565     }
       
   566 
       
   567     public String secondFunctionOfMyInterface0() {
       
   568         return this.getClass().getName();
       
   569     }
       
   570 
       
   571     public String firstFunctionOfMyInterface() {
       
   572         return this.getClass().getName();
       
   573     }
       
   574 
       
   575     public String secondFunctionOfMyInterface() {
       
   576         return this.getClass().getName();
       
   577     }
       
   578 
       
   579     public String aFunctionOfMyInterface() {
       
   580         return this.getClass().getName();
       
   581     }
       
   582 }
       
   583 
       
   584 class AME1_E extends AME1_B implements AME1_C {
       
   585 
       
   586     public AME1_E() {
       
   587     }
       
   588 
       
   589     public String firstAbstractMethod() {
       
   590         return this.getClass().getName();
       
   591     }
       
   592 
       
   593     public String secondAbstractMethod() {
       
   594         return this.getClass().getName();
       
   595     }
       
   596 
       
   597     // This method is missing in the .jasm implementation.
       
   598     public String anAbstractMethod() {
       
   599         return this.getClass().getName();
       
   600     }
       
   601 
       
   602     public String firstFunctionOfMyInterface0() {
       
   603         return this.getClass().getName();
       
   604     }
       
   605 
       
   606     public String secondFunctionOfMyInterface0() {
       
   607         return this.getClass().getName();
       
   608     }
       
   609 
       
   610     public String firstFunctionOfMyInterface() {
       
   611         return this.getClass().getName();
       
   612     }
       
   613 
       
   614     public String secondFunctionOfMyInterface() {
       
   615         return this.getClass().getName();
       
   616     }
       
   617 
       
   618     // This method is missing in the .jasm implementation.
       
   619     public String aFunctionOfMyInterface() {
       
   620         return this.getClass().getName();
       
   621     }
       
   622 }
       
   623 
       
   624 // -------------------------------------------------------------------------
       
   625 // This error should be detected interpreted.
       
   626 //
       
   627 // Class hierachy:
       
   628 //
       
   629 //      A   // an interface declaring aFunctionOfMyInterface()
       
   630 //      |
       
   631 //      B   // an abstract class
       
   632 //      |
       
   633 //      C   // errorneous implementation lacks method A::aFunctionOfMyInterface()
       
   634 //
       
   635 interface AME2_A {
       
   636     public void aFunctionOfMyInterface();
       
   637 }
       
   638 
       
   639 abstract class AME2_B implements AME2_A {
       
   640     abstract public void fun2();
       
   641 }
       
   642 
       
   643 class ImplementsAllFunctions extends AME2_B {
       
   644 
       
   645     public ImplementsAllFunctions() {}
       
   646 
       
   647     public void fun2() {
       
   648         //System.out.print("You called public void ImplementsAllFunctions::fun2().\n");
       
   649     }
       
   650 
       
   651     public void aFunctionOfMyInterface() {
       
   652         //System.out.print("You called public void ImplementsAllFunctions::aFunctionOfMyInterface()\n");
       
   653     }
       
   654 }
       
   655 
       
   656 class AME2_C extends AME2_B {
       
   657 
       
   658     public AME2_C() {}
       
   659 
       
   660     public void fun2() {
       
   661         //System.out.print("You called public void AME2_C::fun2().\n");
       
   662     }
       
   663 
       
   664     // This method is missing in the .jasm implementation.
       
   665     public void aFunctionOfMyInterface() {
       
   666         //System.out.print("You called public void AME2_C::aFunctionOfMyInterface()\n");
       
   667     }
       
   668 }
       
   669 
       
   670 // -----------------------------------------------------------------------
       
   671 // Test AbstractMethod error shadowing existing implementation.
       
   672 //
       
   673 // Class hierachy:
       
   674 //
       
   675 //           A           // a class implementing m()
       
   676 //           |
       
   677 //           B           // an abstract class defining m() abstract
       
   678 //           |
       
   679 //           C           // an errorneous class lacking an implementation of m()
       
   680 //
       
   681 class AME3_A {
       
   682     public void ma() {
       
   683         System.out.print("A.ma() ");
       
   684     }
       
   685 }
       
   686 
       
   687 abstract class AME3_B extends AME3_A {
       
   688     public abstract void ma();
       
   689 }
       
   690 
       
   691 class AME3_C extends AME3_B {
       
   692     // This method is missing in the .jasm implementation.
       
   693     public void ma() {
       
   694         System.out.print("C.ma() ");
       
   695     }
       
   696 }
       
   697 
       
   698 // -----------------------------------------------------------------------
       
   699 // Test AbstractMethod error shadowing existing implementation. In
       
   700 // this test there are several subclasses of the abstract class.
       
   701 //
       
   702 // Class hierachy:
       
   703 //
       
   704 //           A           // A: a class implementing ma()
       
   705 //           |
       
   706 //           B           // B: an abstract class defining ma() abstract
       
   707 //        /  | \
       
   708 //       C   D  E        // E: an errorneous class lacking an implementation of ma()
       
   709 //
       
   710 class AME4_A {
       
   711     public void ma() {
       
   712         System.out.print("A.ma() ");
       
   713     }
       
   714 }
       
   715 
       
   716 abstract class AME4_B extends AME4_A {
       
   717     public abstract void ma();
       
   718 }
       
   719 
       
   720 class AME4_C extends AME4_B {
       
   721     public void ma() {
       
   722         System.out.print("C.ma() ");
       
   723     }
       
   724 }
       
   725 
       
   726 class AME4_D extends AME4_B {
       
   727     public void ma() {
       
   728         System.out.print("D.ma() ");
       
   729     }
       
   730 }
       
   731 
       
   732 class AME4_E extends AME4_B {
       
   733     // This method is missing in the .jasm implementation.
       
   734     public void ma() {
       
   735         System.out.print("E.ma() ");
       
   736     }
       
   737 }
       
   738 
       
   739 // -------------------------------------------------------------------------
       
   740 // This error should be detected while processing the vtable stub.
       
   741 //
       
   742 // Class hierachy:
       
   743 //
       
   744 //              A__     // abstract
       
   745 //             /|\ \
       
   746 //            C D E \
       
   747 //                   B  // Bad class, missing method implementation.
       
   748 //
       
   749 // Test:
       
   750 // - Call D.mc() / E.mc() / F.mc() several times to force real vtable call constrution
       
   751 // - Call errorneous B.mc() in the end to raise the AbstraceMethodError
       
   752 
       
   753 abstract class AME5_A {
       
   754     abstract void ma();
       
   755     abstract void mb();
       
   756     abstract void mc();
       
   757 }
       
   758 
       
   759 class AME5_B extends AME5_A {
       
   760     void ma() {
       
   761         System.out.print("B.ma() ");
       
   762     }
       
   763 
       
   764     void mb() {
       
   765         System.out.print("B.mb() ");
       
   766     }
       
   767 
       
   768     // This method is missing in the .jasm implementation.
       
   769     void mc() {
       
   770         System.out.print("B.mc() ");
       
   771     }
       
   772 }
       
   773 
       
   774 class AME5_C extends AME5_A {
       
   775     void ma() {
       
   776         System.out.print("C.ma() ");
       
   777     }
       
   778 
       
   779     void mb() {
       
   780         System.out.print("C.mb() ");
       
   781     }
       
   782 
       
   783     void mc() {
       
   784         System.out.print("C.mc() ");
       
   785     }
       
   786 }
       
   787 
       
   788 class AME5_D extends AME5_A {
       
   789     void ma() {
       
   790         System.out.print("D.ma() ");
       
   791     }
       
   792 
       
   793     void mb() {
       
   794         System.out.print("D.mb() ");
       
   795     }
       
   796 
       
   797     void mc() {
       
   798         System.out.print("D.mc() ");
       
   799     }
       
   800 }
       
   801 
       
   802 class AME5_E extends AME5_A {
       
   803     void ma() {
       
   804        System.out.print("E.ma() ");
       
   805    }
       
   806 
       
   807    void mb() {
       
   808        System.out.print("E.mb() ");
       
   809    }
       
   810 
       
   811    void mc() {
       
   812        System.out.print("E.mc() ");
       
   813    }
       
   814 }
       
   815 
       
   816 //-------------------------------------------------------------------------
       
   817 // Test AbstractMethod error detected while processing
       
   818 // the itable stub.
       
   819 //
       
   820 // Class hierachy:
       
   821 //
       
   822 //           A__   (interface)
       
   823 //          /|\ \
       
   824 //         C D E \
       
   825 //                B (bad class, missing method)
       
   826 //
       
   827 // Test:
       
   828 // - Call D.mc() / E.mc() / F.mc() several times to force real itable call constrution
       
   829 // - Call errorneous B.mc() in the end to raise the AbstraceMethodError
       
   830 
       
   831 interface AME6_A {
       
   832     abstract void ma();
       
   833     abstract void mb();
       
   834     abstract void mc();
       
   835 }
       
   836 
       
   837 class AME6_B implements AME6_A {
       
   838     public void ma() {
       
   839         System.out.print("B.ma() ");
       
   840     }
       
   841 
       
   842     public void mb() {
       
   843         System.out.print("B.mb() ");
       
   844     }
       
   845 
       
   846     // This method is missing in the .jasm implementation.
       
   847     public void mc() {
       
   848         System.out.print("B.mc() ");
       
   849     }
       
   850 }
       
   851 
       
   852 class AME6_C implements AME6_A {
       
   853     public void ma() {
       
   854         System.out.print("C.ma() ");
       
   855     }
       
   856 
       
   857     public void mb() {
       
   858         System.out.print("C.mb() ");
       
   859     }
       
   860 
       
   861     public void mc() {
       
   862         System.out.print("C.mc() ");
       
   863     }
       
   864 }
       
   865 
       
   866 class AME6_D implements AME6_A {
       
   867     public void ma() {
       
   868         System.out.print("D.ma() ");
       
   869     }
       
   870 
       
   871     public void mb() {
       
   872         System.out.print("D.mb() ");
       
   873     }
       
   874 
       
   875     public void mc() {
       
   876         System.out.print("D.mc() ");
       
   877     }
       
   878 }
       
   879 
       
   880 class AME6_E implements AME6_A {
       
   881     public void ma() {
       
   882         System.out.print("E.ma() ");
       
   883     }
       
   884 
       
   885     public void mb() {
       
   886         System.out.print("E.mb() ");
       
   887     }
       
   888 
       
   889     public void mc() {
       
   890         System.out.print("E.mc() ");
       
   891     }
       
   892 }