diff options
Diffstat (limited to 'test/616-cha-interface-default')
| -rw-r--r-- | test/616-cha-interface-default/build.py (renamed from test/616-cha-interface-default/build) | 7 | ||||
| -rw-r--r-- | test/616-cha-interface-default/run.py (renamed from test/616-cha-interface-default/run) | 6 | ||||
| -rw-r--r-- | test/616-cha-interface-default/src-multidex/Base.java | 40 | ||||
| -rw-r--r-- | test/616-cha-interface-default/src/Main.java | 258 |
4 files changed, 157 insertions, 154 deletions
diff --git a/test/616-cha-interface-default/build b/test/616-cha-interface-default/build.py index d9654f8d38..3e0ecd5973 100644 --- a/test/616-cha-interface-default/build +++ b/test/616-cha-interface-default/build.py @@ -1,6 +1,5 @@ -#!/bin/bash # -# Copyright 2017 The Android Open Source Project +# Copyright (C) 2022 The Android Open Source Project # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -14,4 +13,6 @@ # See the License for the specific language governing permissions and # limitations under the License. -./default-build "$@" --experimental default-methods + +def build(ctx): + ctx.default_build(api_level="default-methods") diff --git a/test/616-cha-interface-default/run b/test/616-cha-interface-default/run.py index d8b4f0d26c..1e797a8e43 100644 --- a/test/616-cha-interface-default/run +++ b/test/616-cha-interface-default/run.py @@ -14,5 +14,7 @@ # See the License for the specific language governing permissions and # limitations under the License. -# Run without an app image to prevent the classes to be loaded at startup. -exec ${RUN} "${@}" --no-app-image + +def run(ctx, args): + # Run without an app image to prevent the classes to be loaded at startup. + ctx.default_run(args, app_image=False) diff --git a/test/616-cha-interface-default/src-multidex/Base.java b/test/616-cha-interface-default/src-multidex/Base.java index 2cbcb500c4..e3222a1ab3 100644 --- a/test/616-cha-interface-default/src-multidex/Base.java +++ b/test/616-cha-interface-default/src-multidex/Base.java @@ -15,27 +15,27 @@ */ interface Base { - default public int foo(int i) { - if (i != 1) { - return -2; + default public int foo(int i) { + if (i != 1) { + return -2; + } + return i + 10; } - return i + 10; - } - // Test default method that's not inlined. - default public int $noinline$bar() { - System.out.print(""); - System.out.print(""); - System.out.print(""); - System.out.print(""); - System.out.print(""); - System.out.print(""); - System.out.print(""); - System.out.print(""); - return -1; - } + // Test default method that's not inlined. + default public int $noinline$bar() { + System.out.print(""); + System.out.print(""); + System.out.print(""); + System.out.print(""); + System.out.print(""); + System.out.print(""); + System.out.print(""); + System.out.print(""); + return -1; + } - default void printError(String msg) { - System.out.println(msg); - } + default void printError(String msg) { + System.out.println(msg); + } } diff --git a/test/616-cha-interface-default/src/Main.java b/test/616-cha-interface-default/src/Main.java index ce02cf0271..40b815ad74 100644 --- a/test/616-cha-interface-default/src/Main.java +++ b/test/616-cha-interface-default/src/Main.java @@ -18,159 +18,159 @@ class Main1 implements Base { } class Main2 extends Main1 { - public void foobar() {} + public void foobar() {} } class Main3 implements Base { - public int foo(int i) { - if (i != 3) { - printError("error3"); + public int foo(int i) { + if (i != 3) { + printError("error3"); + } + return -(i + 10); } - return -(i + 10); - } } public class Main { - static Base sMain1; - static Base sMain2; - static Base sMain3; - - static boolean sIsOptimizing = true; - static boolean sHasJIT = true; - static volatile boolean sOtherThreadStarted; - - private static void assertSingleImplementation(Class<?> clazz, String method_name, boolean b) { - if (hasSingleImplementation(clazz, method_name) != b) { - System.out.println(clazz + "." + method_name + - " doesn't have single implementation value of " + b); + static Base sMain1; + static Base sMain2; + static Base sMain3; + + static boolean sIsOptimizing = true; + static boolean sHasJIT = true; + static volatile boolean sOtherThreadStarted; + + private static void assertSingleImplementation(Class<?> clazz, String method_name, boolean b) { + if (hasSingleImplementation(clazz, method_name) != b) { + System.out.println(clazz + "." + method_name + + " doesn't have single implementation value of " + b); + } } - } - static int getValue(Class<?> cls) { - if (cls == Main1.class || cls == Main2.class) { - return 1; - } - return 3; - } - - // sMain1.foo()/sMain2.foo() will be always be Base.foo() before Main3 is loaded/linked. - // So sMain1.foo() can be devirtualized to Base.foo() and be inlined. - // After Helper.createMain3() which links in Main3, live testImplement() on stack - // should be deoptimized. - static void testImplement(boolean createMain3, boolean wait, boolean setHasJIT) { - if (setHasJIT) { - if (isInterpreted()) { - sHasJIT = false; - } - return; + static int getValue(Class<?> cls) { + if (cls == Main1.class || cls == Main2.class) { + return 1; + } + return 3; } - if (createMain3 && (sIsOptimizing || sHasJIT)) { - assertIsManaged(); - } + // sMain1.foo()/sMain2.foo() will be always be Base.foo() before Main3 is loaded/linked. + // So sMain1.foo() can be devirtualized to Base.foo() and be inlined. + // After Helper.createMain3() which links in Main3, live testImplement() on stack + // should be deoptimized. + static void testImplement(boolean createMain3, boolean wait, boolean setHasJIT) { + if (setHasJIT) { + if (isInterpreted()) { + sHasJIT = false; + } + return; + } - if (sMain1.foo(getValue(sMain1.getClass())) != 11) { - System.out.println("11 expected."); - } - if (sMain1.$noinline$bar() != -1) { - System.out.println("-1 expected."); - } - if (sMain2.foo(getValue(sMain2.getClass())) != 11) { - System.out.println("11 expected."); - } + if (createMain3 && (sIsOptimizing || sHasJIT)) { + assertIsManaged(); + } - if (createMain3) { - // Wait for the other thread to start. - while (!sOtherThreadStarted); - // Create an Main2 instance and assign it to sMain2. - // sMain1 is kept the same. - sMain3 = Helper.createMain3(); - // Wake up the other thread. - synchronized(Main.class) { - Main.class.notify(); - } - } else if (wait) { - // This is the other thread. - synchronized(Main.class) { - sOtherThreadStarted = true; - // Wait for Main2 to be linked and deoptimization is triggered. - try { - Main.class.wait(); - } catch (Exception e) { + if (sMain1.foo(getValue(sMain1.getClass())) != 11) { + System.out.println("11 expected."); + } + if (sMain1.$noinline$bar() != -1) { + System.out.println("-1 expected."); + } + if (sMain2.foo(getValue(sMain2.getClass())) != 11) { + System.out.println("11 expected."); } - } - } - // There should be a deoptimization here right after Main3 is linked by - // calling Helper.createMain3(), even though sMain1 didn't change. - // The behavior here would be different if inline-cache is used, which - // doesn't deoptimize since sMain1 still hits the type cache. - if (sMain1.foo(getValue(sMain1.getClass())) != 11) { - System.out.println("11 expected."); - } - if ((createMain3 || wait) && sHasJIT && !sIsOptimizing) { - // This method should be deoptimized right after Main3 is created. - assertIsInterpreted(); - } + if (createMain3) { + // Wait for the other thread to start. + while (!sOtherThreadStarted); + // Create an Main2 instance and assign it to sMain2. + // sMain1 is kept the same. + sMain3 = Helper.createMain3(); + // Wake up the other thread. + synchronized(Main.class) { + Main.class.notify(); + } + } else if (wait) { + // This is the other thread. + synchronized(Main.class) { + sOtherThreadStarted = true; + // Wait for Main2 to be linked and deoptimization is triggered. + try { + Main.class.wait(); + } catch (Exception e) { + } + } + } + + // There should be a deoptimization here right after Main3 is linked by + // calling Helper.createMain3(), even though sMain1 didn't change. + // The behavior here would be different if inline-cache is used, which + // doesn't deoptimize since sMain1 still hits the type cache. + if (sMain1.foo(getValue(sMain1.getClass())) != 11) { + System.out.println("11 expected."); + } + if ((createMain3 || wait) && sHasJIT && !sIsOptimizing) { + // This method should be deoptimized right after Main3 is created. + assertIsInterpreted(); + } - if (sMain3 != null) { - if (sMain3.foo(getValue(sMain3.getClass())) != -13) { - System.out.println("-13 expected."); - } + if (sMain3 != null) { + if (sMain3.foo(getValue(sMain3.getClass())) != -13) { + System.out.println("-13 expected."); + } + } } - } - // Test scenarios under which CHA-based devirtualization happens, - // and class loading that implements a method can invalidate compiled code. - public static void main(String[] args) { - System.loadLibrary(args[0]); + // Test scenarios under which CHA-based devirtualization happens, + // and class loading that implements a method can invalidate compiled code. + public static void main(String[] args) { + System.loadLibrary(args[0]); - if (isInterpreted()) { - sIsOptimizing = false; - } + if (isInterpreted()) { + sIsOptimizing = false; + } - // sMain1 is an instance of Main1. - // sMain2 is an instance of Main2. - // Neither Main1 nor Main2 override default method Base.foo(). - // Main3 hasn't bee loaded yet. - sMain1 = new Main1(); - sMain2 = new Main2(); - - ensureJitCompiled(Main.class, "testImplement"); - testImplement(false, false, true); - - if (sHasJIT && !sIsOptimizing) { - assertSingleImplementation(Base.class, "foo", true); - assertSingleImplementation(Main1.class, "foo", true); - } else { - // Main3 is verified ahead-of-time so it's linked in already. + // sMain1 is an instance of Main1. + // sMain2 is an instance of Main2. + // Neither Main1 nor Main2 override default method Base.foo(). + // Main3 hasn't bee loaded yet. + sMain1 = new Main1(); + sMain2 = new Main2(); + + ensureJitCompiled(Main.class, "testImplement"); + testImplement(false, false, true); + + if (sHasJIT && !sIsOptimizing) { + assertSingleImplementation(Base.class, "foo", true); + assertSingleImplementation(Main1.class, "foo", true); + } else { + // Main3 is verified ahead-of-time so it's linked in already. + } + + // Create another thread that also calls sMain1.foo(). + // Try to test suspend and deopt another thread. + new Thread() { + public void run() { + testImplement(false, true, false); + } + }.start(); + + // This will create Main3 instance in the middle of testImplement(). + testImplement(true, false, false); + assertSingleImplementation(Base.class, "foo", false); + assertSingleImplementation(Main1.class, "foo", true); + assertSingleImplementation(sMain3.getClass(), "foo", true); } - // Create another thread that also calls sMain1.foo(). - // Try to test suspend and deopt another thread. - new Thread() { - public void run() { - testImplement(false, true, false); - } - }.start(); - - // This will create Main3 instance in the middle of testImplement(). - testImplement(true, false, false); - assertSingleImplementation(Base.class, "foo", false); - assertSingleImplementation(Main1.class, "foo", true); - assertSingleImplementation(sMain3.getClass(), "foo", true); - } - - private static native void ensureJitCompiled(Class<?> itf, String method_name); - private static native void assertIsInterpreted(); - private static native void assertIsManaged(); - private static native boolean isInterpreted(); - private static native boolean hasSingleImplementation(Class<?> clazz, String method_name); + private static native void ensureJitCompiled(Class<?> itf, String method_name); + private static native void assertIsInterpreted(); + private static native void assertIsManaged(); + private static native boolean isInterpreted(); + private static native boolean hasSingleImplementation(Class<?> clazz, String method_name); } // Put createMain3() in another class to avoid class loading due to verifier. class Helper { - static Base createMain3() { - return new Main3(); - } + static Base createMain3() { + return new Main3(); + } } |