blob: c683e6b2ab611c8f4d690a6baa1e50f954d80a58 [file] [log] [blame]
/*
* Copyright (C) 2021 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.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
interface Itf {
// We make the methods below directly throw instead of using the $noinline$
// directive to get the inliner actually try to inline but decide not to.
// This will then make the compiler try to generate an HInvokeVirtual instead
// of an HInvokeInterface.
public default void m() throws Exception {
throw new Exception("Don't inline me");
}
public default void mConflict() throws Exception {
throw new Exception("Don't inline me");
}
}
// This is redefined in src2 with a mConflict method.
interface Itf2 {
}
interface Itf3 extends Itf, Itf2 {
}
class Itf3Impl implements Itf3 {
}
interface Itf4 extends Itf, Itf2 {
public default void m() throws Exception {
throw new Exception("Don't inline me");
}
}
class Itf4Impl implements Itf4 {
}
public class Main implements Itf, Itf2 {
public static void main(String[] args) {
System.loadLibrary(args[0]);
// Execute enough time to populate inline caches.
for (int i = 0; i < 100000; ++i) {
try {
$noinline$doCallDefault();
} catch (Exception e) {
// Expected.
}
}
ensureJitCompiled(Main.class, "$noinline$doCallDefault");
try {
$noinline$doCallDefault();
throw new Error("Expected exception");
} catch (Exception e) {
// Expected.
}
ensureJitCompiled(Main.class, "$noinline$doCallDefaultConflict");
try {
$noinline$doCallDefaultConflict();
throw new Error("Expected IncompatibleClassChangeError");
} catch (Exception e) {
throw new Error("Unexpected exception");
} catch (IncompatibleClassChangeError e) {
// Expected.
}
// Execute enough time to populate inline caches.
for (int i = 0; i < 100000; ++i) {
try {
$noinline$doCallDefaultConflictItf3();
} catch (Throwable t) {
// Expected.
}
}
ensureJitCompiled(Main.class, "$noinline$doCallDefaultConflictItf3");
try {
$noinline$doCallDefaultConflictItf3();
throw new Error("Expected IncompatibleClassChangeError");
} catch (Exception e) {
throw new Error("Unexpected exception " + e);
} catch (IncompatibleClassChangeError e) {
// Expected.
}
ensureJitCompiled(Main.class, "$noinline$doCallDefaultConflictItf4");
try {
$noinline$doCallDefaultConflictItf4();
throw new Error("Expected IncompatibleClassChangeError");
} catch (Exception e) {
throw new Error("Unexpected exception");
} catch (IncompatibleClassChangeError e) {
// Expected.
}
}
public static void $noinline$doCallDefault() throws Exception {
itf.m();
}
public static void $noinline$doCallDefaultConflict() throws Exception {
itf.mConflict();
}
public static void $noinline$doCallDefaultConflictItf3() throws Exception {
itf3.mConflict();
}
public static void $noinline$doCallDefaultConflictItf4() throws Exception {
itf4.mConflict();
}
static Itf itf = new Main();
static Itf3 itf3 = new Itf3Impl();
static Itf4 itf4 = new Itf4Impl();
private static native void ensureJitCompiled(Class<?> cls, String methodName);
}