blob: f4ae3a91823de75b95ecb2574b6f1172e2bb1d3c [file] [log] [blame]
/*
* Copyright (C) 2015 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.
*/
// TODO: Add more tests after we can inline functions with calls.
class ClassWithoutFinals {
/// CHECK-START: void ClassWithoutFinals.<init>() inliner (after)
/// CHECK-NOT: ConstructorFence
public ClassWithoutFinals() {}
}
class ClassWithFinals {
public final int x;
public ClassWithFinals obj;
public static boolean doThrow = false;
public ClassWithFinals(boolean cond) {
x = 1;
throw new RuntimeException();
// should not inline this constructor
}
/// CHECK-START: void ClassWithFinals.<init>() inliner (after)
/// CHECK: ConstructorFence
/// CHECK-NOT: ConstructorFence
/*
* Check that the correct assembly instructions are selected for a Store/Store fence.
*
* - ARM variants: DMB ISHST (store-store fence for inner shareable domain)
* - Intel variants: no-op (store-store does not need a fence).
*/
/// CHECK-START-ARM64: void ClassWithFinals.<init>() disassembly (after)
/// CHECK: ConstructorFence
/// CHECK-NEXT: dmb ishst
/// CHECK-START-ARM: void ClassWithFinals.<init>() disassembly (after)
/// CHECK: ConstructorFence
/// CHECK-NEXT: dmb ishst
/// CHECK-START-X86_64: void ClassWithFinals.<init>() disassembly (after)
/// CHECK: ConstructorFence
/// CHECK-NOT: {{[slm]}}fence
/// CHECK-START-X86: void ClassWithFinals.<init>() disassembly (after)
/// CHECK: ConstructorFence
/// CHECK-NOT: {{[slm]}}fence
public ClassWithFinals() {
// Exactly one constructor barrier.
// Note: Do not store 0 as that can be eliminated together with the constructor
// barrier by the code pattern substitution in the inliner.
x = 1;
}
/// CHECK-START: void ClassWithFinals.<init>(int) inliner (after)
/// CHECK: <<This:l\d+>> ParameterValue
/// CHECK: <<NewInstance:l\d+>> NewInstance
/// CHECK-DAG: ConstructorFence [<<NewInstance>>]
/// CHECK-DAG: ConstructorFence [<<NewInstance>>]
/// CHECK-DAG: ConstructorFence [<<This>>]
/// CHECK-NOT: ConstructorFence
public ClassWithFinals(int x) {
// This should have exactly three barriers:
// - one for the new-instance
// - one for the constructor
// - one for the `new` which should be inlined.
obj = new ClassWithFinals();
this.x = x;
}
}
class InheritFromClassWithFinals extends ClassWithFinals {
/// CHECK-START: void InheritFromClassWithFinals.<init>() inliner (after)
/// CHECK: <<This:l\d+>> ParameterValue
/// CHECK: ConstructorFence [<<This>>]
/// CHECK-NOT: ConstructorFence
/// CHECK-START: void InheritFromClassWithFinals.<init>() inliner (after)
/// CHECK-NOT: InvokeStaticOrDirect
public InheritFromClassWithFinals() {
// Should inline the super constructor.
//
// Exactly one constructor barrier here.
}
/// CHECK-START: void InheritFromClassWithFinals.<init>(boolean) inliner (after)
/// CHECK: InvokeStaticOrDirect
/// CHECK-START: void InheritFromClassWithFinals.<init>(boolean) inliner (after)
/// CHECK-NOT: ConstructorFence
public InheritFromClassWithFinals(boolean cond) {
super(cond);
// should not inline the super constructor
}
/// CHECK-START: void InheritFromClassWithFinals.<init>(int) inliner (after)
/// CHECK: <<This:l\d+>> ParameterValue
/// CHECK-DAG: <<NewHere:l\d+>> NewInstance klass:InheritFromClassWithFinals
/// CHECK-DAG: ConstructorFence [<<This>>]
/// CHECK-DAG: ConstructorFence [<<NewHere>>]
/// CHECK-DAG: ConstructorFence [<<NewHere>>]
/// CHECK-NOT: ConstructorFence
/// CHECK-START: void InheritFromClassWithFinals.<init>(int) inliner (after)
/// CHECK-NOT: InvokeStaticOrDirect
public InheritFromClassWithFinals(int unused) {
// super(); // implicitly the first invoke in this constructor.
// Should inline the super constructor and insert a constructor fence there.
// Should inline the new instance call (barrier); and add another one
// because the superclass has finals.
new InheritFromClassWithFinals();
}
}
class HaveFinalsAndInheritFromClassWithFinals extends ClassWithFinals {
final int y;
/// CHECK-START: void HaveFinalsAndInheritFromClassWithFinals.<init>() inliner (after)
/// CHECK: <<This:l\d+>> ParameterValue
/// CHECK: ConstructorFence [<<This>>]
/// CHECK: ConstructorFence [<<This>>]
/// CHECK-NOT: ConstructorFence
/// CHECK-START: void HaveFinalsAndInheritFromClassWithFinals.<init>() inliner (after)
/// CHECK-NOT: InvokeStaticOrDirect
public HaveFinalsAndInheritFromClassWithFinals() {
// Should inline the super constructor and keep the memory barrier.
y = 0;
}
/// CHECK-START: void HaveFinalsAndInheritFromClassWithFinals.<init>(boolean) inliner (after)
/// CHECK: <<This:l\d+>> ParameterValue
/// CHECK: InvokeStaticOrDirect
/// CHECK: ConstructorFence [<<This>>]
/// CHECK-NOT: ConstructorFence
public HaveFinalsAndInheritFromClassWithFinals(boolean cond) {
super(cond);
// should not inline the super constructor
y = 0;
}
/// CHECK-START: void HaveFinalsAndInheritFromClassWithFinals.<init>(int) inliner (after)
/// CHECK: <<This:l\d+>> ParameterValue
/// CHECK-DAG: <<NewHF:l\d+>> NewInstance klass:HaveFinalsAndInheritFromClassWithFinals
/// CHECK-DAG: <<NewIF:l\d+>> NewInstance klass:InheritFromClassWithFinals
/// CHECK-DAG: ConstructorFence [<<This>>]
/// CHECK-DAG: ConstructorFence [<<NewHF>>]
/// CHECK-DAG: ConstructorFence [<<NewHF>>]
/// CHECK-DAG: ConstructorFence [<<NewHF>>]
/// CHECK-DAG: ConstructorFence [<<NewIF>>]
/// CHECK-DAG: ConstructorFence [<<NewIF>>]
/// CHECK-DAG: ConstructorFence [<<This>>]
/// CHECK-NOT: ConstructorFence
/// CHECK-START: void HaveFinalsAndInheritFromClassWithFinals.<init>(int) inliner (after)
/// CHECK-NOT: InvokeStaticOrDirect
public HaveFinalsAndInheritFromClassWithFinals(int unused) {
// super()
// -- Inlined super constructor, insert memory barrier here.
y = 0;
// Should inline new instance and keep both memory barriers.
// One more memory barrier for new-instance.
// (3 total for this new-instance #1)
new HaveFinalsAndInheritFromClassWithFinals();
// Should inline new instance and have exactly one barrier.
// One more barrier for new-instance.
// (2 total for this new-instance #2)
new InheritFromClassWithFinals();
// -- End of constructor, insert memory barrier here to freeze 'y'.
}
}
public class Main {
/// CHECK-START: ClassWithFinals Main.noInlineNoConstructorBarrier() inliner (after)
/// CHECK: InvokeStaticOrDirect
/// CHECK-START: ClassWithFinals Main.noInlineNoConstructorBarrier() inliner (after)
/// CHECK: <<NewInstance:l\d+>> NewInstance
/// CHECK: ConstructorFence [<<NewInstance>>]
/// CHECK-NOT: ConstructorFence
public static ClassWithFinals noInlineNoConstructorBarrier() {
// Exactly one barrier for the new-instance.
return new ClassWithFinals(false);
// should not inline the constructor
}
/// CHECK-START: void Main.inlineNew() inliner (after)
/// CHECK: <<NewInstance:l\d+>> NewInstance
/// CHECK-DAG: ConstructorFence [<<NewInstance>>]
/// CHECK-DAG: ConstructorFence [<<NewInstance>>]
/// CHECK-NOT: ConstructorFence
/// CHECK-START: void Main.inlineNew() inliner (after)
/// CHECK-NOT: InvokeStaticOrDirect
public static void inlineNew() {
// Exactly 2 barriers. One for new-instance, one for constructor with finals.
new ClassWithFinals();
}
/// CHECK-START: void Main.inlineNew1() inliner (after)
/// CHECK: <<NewInstance:l\d+>> NewInstance
/// CHECK-DAG: ConstructorFence [<<NewInstance>>]
/// CHECK-DAG: ConstructorFence [<<NewInstance>>]
/// CHECK-NOT: ConstructorFence
/// CHECK-START: void Main.inlineNew1() inliner (after)
/// CHECK-NOT: InvokeStaticOrDirect
public static void inlineNew1() {
new InheritFromClassWithFinals();
}
/// CHECK-START: void Main.inlineNew2() inliner (after)
/// CHECK: <<NewInstance:l\d+>> NewInstance
/// CHECK-DAG: ConstructorFence [<<NewInstance>>]
/// CHECK-DAG: ConstructorFence [<<NewInstance>>]
/// CHECK-DAG: ConstructorFence [<<NewInstance>>]
/// CHECK-NOT: ConstructorFence
/// CHECK-START: void Main.inlineNew2() inliner (after)
/// CHECK-NOT: InvokeStaticOrDirect
public static void inlineNew2() {
new HaveFinalsAndInheritFromClassWithFinals();
}
/// CHECK-START: void Main.inlineNew3() inliner (after)
/// CHECK: <<NewInstance:l\d+>> NewInstance
/// CHECK-DAG: ConstructorFence [<<NewInstance>>]
/// CHECK-DAG: ConstructorFence [<<NewInstance>>]
/// CHECK-DAG: ConstructorFence [<<NewInstance>>]
/// CHECK-NOT: ConstructorFence
/// CHECK: <<NewInstance2:l\d+>> NewInstance
/// CHECK-DAG: ConstructorFence [<<NewInstance2>>]
/// CHECK-DAG: ConstructorFence [<<NewInstance2>>]
/// CHECK-DAG: ConstructorFence [<<NewInstance2>>]
/// CHECK-NOT: ConstructorFence
/// CHECK-START: void Main.inlineNew3() inliner (after)
/// CHECK-NOT: InvokeStaticOrDirect
public static void inlineNew3() {
new HaveFinalsAndInheritFromClassWithFinals();
new HaveFinalsAndInheritFromClassWithFinals();
}
static int[] mCodePointsEmpty = new int[0];
/// CHECK-START: void Main.testNewString() inliner (after)
/// CHECK-NOT: ConstructorFence
/// CHECK: InvokeStaticOrDirect method_load_kind:StringInit
/// CHECK-NOT: ConstructorFence
/// CHECK-NOT: InvokeStaticOrDirect
public static void testNewString() {
// Strings are special because of StringFactory hackeries.
//
// Assume they handle their own fencing internally in the StringFactory.
int[] codePoints = null;
String some_new_string = new String(mCodePointsEmpty, 0, 0);
}
public static void main(String[] args) {}
}