/*
|
* 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.
|
*/
|
|
interface SuperInterface {
|
void superInterfaceMethod();
|
}
|
|
interface OtherInterface extends SuperInterface {
|
}
|
|
interface Interface extends SuperInterface {
|
void $noinline$f();
|
}
|
|
class Super implements Interface {
|
public void superInterfaceMethod() {}
|
public void $noinline$f() {
|
throw new RuntimeException();
|
}
|
|
public int $inline$h(boolean cond) {
|
Super obj = (cond ? this : null);
|
return obj.hashCode();
|
}
|
}
|
|
class SubclassA extends Super {
|
public void $noinline$f() {
|
throw new RuntimeException();
|
}
|
|
public String $noinline$h() {
|
throw new RuntimeException();
|
}
|
|
void $noinline$g() {
|
throw new RuntimeException();
|
}
|
}
|
|
class SubclassC extends SubclassA {
|
}
|
|
class SubclassB extends Super {
|
public void $noinline$f() {
|
throw new RuntimeException();
|
}
|
|
void $noinline$g() {
|
throw new RuntimeException();
|
}
|
}
|
|
class Generic<A> {
|
private A a = null;
|
public A get() {
|
return a;
|
}
|
}
|
|
final class Final {}
|
|
final class FinalException extends Exception {}
|
|
public class Main {
|
|
/// CHECK-START: void Main.testSimpleRemove() instruction_simplifier (before)
|
/// CHECK: CheckCast
|
|
/// CHECK-START: void Main.testSimpleRemove() instruction_simplifier (after)
|
/// CHECK-NOT: CheckCast
|
public void testSimpleRemove() {
|
Super s = new SubclassA();
|
((SubclassA)s).$noinline$g();
|
}
|
|
/// CHECK-START: void Main.testSimpleKeep(Super) instruction_simplifier (before)
|
/// CHECK: CheckCast
|
|
/// CHECK-START: void Main.testSimpleKeep(Super) instruction_simplifier (after)
|
/// CHECK: CheckCast
|
public void testSimpleKeep(Super s) {
|
((SubclassA)s).$noinline$f();
|
}
|
|
/// CHECK-START: java.lang.String Main.testClassRemove() instruction_simplifier (before)
|
/// CHECK: CheckCast
|
|
/// CHECK-START: java.lang.String Main.testClassRemove() instruction_simplifier (after)
|
/// CHECK-NOT: CheckCast
|
public String testClassRemove() {
|
Object s = SubclassA.class;
|
return ((Class<?>)s).getName();
|
}
|
|
/// CHECK-START: java.lang.String Main.testClassKeep() instruction_simplifier (before)
|
/// CHECK: CheckCast
|
|
/// CHECK-START: java.lang.String Main.testClassKeep() instruction_simplifier (after)
|
/// CHECK: CheckCast
|
public String testClassKeep() {
|
Object s = SubclassA.class;
|
return ((SubclassA)s).$noinline$h();
|
}
|
|
/// CHECK-START: void Main.testIfRemove(int) instruction_simplifier (before)
|
/// CHECK: CheckCast
|
|
/// CHECK-START: void Main.testIfRemove(int) instruction_simplifier (after)
|
/// CHECK-NOT: CheckCast
|
public void testIfRemove(int x) {
|
Super s;
|
if (x % 2 == 0) {
|
s = new SubclassA();
|
} else {
|
s = new SubclassC();
|
}
|
((SubclassA)s).$noinline$g();
|
}
|
|
/// CHECK-START: void Main.testIfKeep(int) instruction_simplifier (before)
|
/// CHECK: CheckCast
|
|
/// CHECK-START: void Main.testIfKeep(int) instruction_simplifier (after)
|
/// CHECK: CheckCast
|
public void testIfKeep(int x) {
|
Super s;
|
if (x % 2 == 0) {
|
s = new SubclassA();
|
} else {
|
s = new SubclassB();
|
}
|
((SubclassA)s).$noinline$g();
|
}
|
|
/// CHECK-START: void Main.testForRemove(int) instruction_simplifier (before)
|
/// CHECK: CheckCast
|
|
/// CHECK-START: void Main.testForRemove(int) instruction_simplifier (after)
|
/// CHECK-NOT: CheckCast
|
public void testForRemove(int x) {
|
Super s = new SubclassA();
|
for (int i = 0 ; i < x; i++) {
|
if (x % 2 == 0) {
|
s = new SubclassC();
|
}
|
}
|
((SubclassA)s).$noinline$g();
|
}
|
|
/// CHECK-START: void Main.testForKeep(int) instruction_simplifier (before)
|
/// CHECK: CheckCast
|
|
/// CHECK-START: void Main.testForKeep(int) instruction_simplifier (after)
|
/// CHECK: CheckCast
|
public void testForKeep(int x) {
|
Super s = new SubclassA();
|
for (int i = 0 ; i < x; i++) {
|
if (x % 2 == 0) {
|
s = new SubclassC();
|
}
|
}
|
((SubclassC)s).$noinline$g();
|
}
|
|
/// CHECK-START: void Main.testPhiFromCall(int) instruction_simplifier (before)
|
/// CHECK: CheckCast
|
|
/// CHECK-START: void Main.testPhiFromCall(int) instruction_simplifier (after)
|
/// CHECK: CheckCast
|
public void testPhiFromCall(int i) {
|
Object x;
|
if (i % 2 == 0) {
|
x = new SubclassC();
|
} else {
|
x = newObject(); // this one will have an unknown type.
|
}
|
((SubclassC)x).$noinline$g();
|
}
|
|
/// CHECK-START: void Main.testInstanceOf(java.lang.Object) instruction_simplifier (before)
|
/// CHECK: CheckCast
|
/// CHECK: CheckCast
|
/// CHECK-NOT: CheckCast
|
|
/// CHECK-START: void Main.testInstanceOf(java.lang.Object) instruction_simplifier (after)
|
/// CHECK-NOT: CheckCast
|
public void testInstanceOf(Object o) {
|
if (o instanceof SubclassC) {
|
((SubclassC)o).$noinline$g();
|
}
|
if (o instanceof SubclassB) {
|
((SubclassB)o).$noinline$g();
|
}
|
}
|
|
public static boolean $inline$InstanceofSubclassB(Object o) { return o instanceof SubclassB; }
|
public static boolean $inline$InstanceofSubclassC(Object o) { return o instanceof SubclassC; }
|
|
/// CHECK-START: void Main.testInstanceOf_NotInlined(java.lang.Object) builder (after)
|
/// CHECK-DAG: <<Cst0:i\d+>> IntConstant 0
|
/// CHECK-DAG: <<Cst1:i\d+>> IntConstant 1
|
/// CHECK-DAG: <<IOf1:z\d+>> InstanceOf
|
/// CHECK-DAG: NotEqual [<<IOf1>>,<<Cst1>>]
|
/// CHECK-DAG: <<IOf2:z\d+>> InstanceOf
|
/// CHECK-DAG: Equal [<<IOf2>>,<<Cst0>>]
|
|
/// CHECK-START: void Main.testInstanceOf_NotInlined(java.lang.Object) instruction_simplifier (before)
|
/// CHECK: CheckCast
|
/// CHECK: CheckCast
|
/// CHECK-NOT: CheckCast
|
|
/// CHECK-START: void Main.testInstanceOf_NotInlined(java.lang.Object) instruction_simplifier (after)
|
/// CHECK-NOT: CheckCast
|
public void testInstanceOf_NotInlined(Object o) {
|
if ((o instanceof SubclassC) == true) {
|
((SubclassC)o).$noinline$g();
|
}
|
if ((o instanceof SubclassB) != false) {
|
((SubclassB)o).$noinline$g();
|
}
|
}
|
|
/// CHECK-START: void Main.testNotInstanceOf_NotInlined(java.lang.Object) builder (after)
|
/// CHECK-DAG: <<Cst0:i\d+>> IntConstant 0
|
/// CHECK-DAG: <<Cst1:i\d+>> IntConstant 1
|
/// CHECK-DAG: <<IOf1:z\d+>> InstanceOf
|
/// CHECK-DAG: Equal [<<IOf1>>,<<Cst1>>]
|
/// CHECK-DAG: <<IOf2:z\d+>> InstanceOf
|
/// CHECK-DAG: NotEqual [<<IOf2>>,<<Cst0>>]
|
|
/// CHECK-START: void Main.testNotInstanceOf_NotInlined(java.lang.Object) instruction_simplifier (before)
|
/// CHECK: CheckCast
|
/// CHECK: CheckCast
|
/// CHECK-NOT: CheckCast
|
|
/// CHECK-START: void Main.testNotInstanceOf_NotInlined(java.lang.Object) instruction_simplifier (after)
|
/// CHECK-NOT: CheckCast
|
public void testNotInstanceOf_NotInlined(Object o) {
|
if ((o instanceof SubclassC) != true) {
|
// Empty branch to flip the condition.
|
} else {
|
((SubclassC)o).$noinline$g();
|
}
|
if ((o instanceof SubclassB) == false) {
|
// Empty branch to flip the condition.
|
} else {
|
((SubclassB)o).$noinline$g();
|
}
|
}
|
|
/// CHECK-START: void Main.testInstanceOf_Inlined(java.lang.Object) inliner (after)
|
/// CHECK-DAG: <<IOf:z\d+>> InstanceOf
|
/// CHECK-DAG: If [<<IOf>>]
|
|
/// CHECK-START: void Main.testInstanceOf_Inlined(java.lang.Object) instruction_simplifier$after_inlining (before)
|
/// CHECK: CheckCast
|
/// CHECK-NOT: CheckCast
|
|
/// CHECK-START: void Main.testInstanceOf_Inlined(java.lang.Object) instruction_simplifier$after_inlining (after)
|
/// CHECK-NOT: CheckCast
|
public void testInstanceOf_Inlined(Object o) {
|
if (!$inline$InstanceofSubclassC(o)) {
|
// Empty branch to flip the condition.
|
} else {
|
((SubclassC)o).$noinline$g();
|
}
|
}
|
|
/// CHECK-START: void Main.testInstanceOfKeep(java.lang.Object) instruction_simplifier (before)
|
/// CHECK: CheckCast
|
/// CHECK: CheckCast
|
|
/// CHECK-START: void Main.testInstanceOfKeep(java.lang.Object) instruction_simplifier (after)
|
/// CHECK: CheckCast
|
/// CHECK: CheckCast
|
public void testInstanceOfKeep(Object o) {
|
if (o instanceof SubclassC) {
|
((SubclassB)o).$noinline$g();
|
}
|
if (o instanceof SubclassB) {
|
((SubclassA)o).$noinline$g();
|
}
|
}
|
|
/// CHECK-START: void Main.testInstanceOfNested(java.lang.Object) instruction_simplifier (before)
|
/// CHECK: CheckCast
|
/// CHECK: CheckCast
|
|
/// CHECK-START: void Main.testInstanceOfNested(java.lang.Object) instruction_simplifier (after)
|
/// CHECK-NOT: CheckCast
|
public void testInstanceOfNested(Object o) {
|
if (o instanceof SubclassC) {
|
if (o instanceof SubclassB) {
|
((SubclassB)o).$noinline$g();
|
} else {
|
((SubclassC)o).$noinline$g();
|
}
|
}
|
}
|
|
/// CHECK-START: void Main.testInstanceOfWithPhi(int) instruction_simplifier (before)
|
/// CHECK: CheckCast
|
|
/// CHECK-START: void Main.testInstanceOfWithPhi(int) instruction_simplifier (after)
|
/// CHECK-NOT: CheckCast
|
public void testInstanceOfWithPhi(int i) {
|
Object o;
|
if (i == 0) {
|
o = new SubclassA();
|
} else {
|
o = new SubclassB();
|
}
|
|
if (o instanceof SubclassB) {
|
((SubclassB)o).$noinline$g();
|
}
|
}
|
|
/// CHECK-START: void Main.testInstanceOfInFor(int) instruction_simplifier (before)
|
/// CHECK: CheckCast
|
|
/// CHECK-START: void Main.testInstanceOfInFor(int) instruction_simplifier (after)
|
/// CHECK-NOT: CheckCast
|
public void testInstanceOfInFor(int n) {
|
Object o = new SubclassA();
|
for (int i = 0; i < n; i++) {
|
if (i / 2 == 0) {
|
o = new SubclassB();
|
}
|
if (o instanceof SubclassB) {
|
((SubclassB)o).$noinline$g();
|
}
|
}
|
}
|
|
/// CHECK-START: void Main.testInstanceOfSubclass() instruction_simplifier (before)
|
/// CHECK: CheckCast
|
|
/// CHECK-START: void Main.testInstanceOfSubclass() instruction_simplifier (after)
|
/// CHECK-NOT: CheckCast
|
public void testInstanceOfSubclass() {
|
Object o = new SubclassA();
|
if (o instanceof Super) {
|
((SubclassA)o).$noinline$g();
|
}
|
}
|
|
/// CHECK-START: void Main.testInstanceOfWithPhiSubclass(int) instruction_simplifier (before)
|
/// CHECK: CheckCast
|
|
/// CHECK-START: void Main.testInstanceOfWithPhiSubclass(int) instruction_simplifier (after)
|
/// CHECK-NOT: CheckCast
|
public void testInstanceOfWithPhiSubclass(int i) {
|
Object o;
|
if (i == 0) {
|
o = new SubclassA();
|
} else {
|
o = new SubclassC();
|
}
|
|
if (o instanceof Super) {
|
((SubclassA)o).$noinline$g();
|
}
|
}
|
|
/// CHECK-START: void Main.testInstanceOfWithPhiTop(int) instruction_simplifier (before)
|
/// CHECK: CheckCast
|
|
/// CHECK-START: void Main.testInstanceOfWithPhiTop(int) instruction_simplifier (after)
|
/// CHECK-NOT: CheckCast
|
public void testInstanceOfWithPhiTop(int i) {
|
Object o;
|
if (i == 0) {
|
o = new Object();
|
} else {
|
o = new SubclassC();
|
}
|
|
if (o instanceof Super) {
|
((Super)o).$noinline$f();
|
}
|
}
|
|
/// CHECK-START: void Main.testInstanceOfSubclassInFor(int) instruction_simplifier (before)
|
/// CHECK: CheckCast
|
|
/// CHECK-START: void Main.testInstanceOfSubclassInFor(int) instruction_simplifier (after)
|
/// CHECK-NOT: CheckCast
|
public void testInstanceOfSubclassInFor(int n) {
|
Object o = new SubclassA();
|
for (int i = 0; i < n; i++) {
|
if (o instanceof Super) {
|
((SubclassA)o).$noinline$g();
|
}
|
if (i / 2 == 0) {
|
o = new SubclassC();
|
}
|
}
|
}
|
|
/// CHECK-START: void Main.testInstanceOfTopInFor(int) instruction_simplifier (before)
|
/// CHECK: CheckCast
|
|
/// CHECK-START: void Main.testInstanceOfTopInFor(int) instruction_simplifier (after)
|
/// CHECK-NOT: CheckCast
|
public void testInstanceOfTopInFor(int n) {
|
Object o = new SubclassA();
|
for (int i = 0; i < n; i++) {
|
if (o instanceof Super) {
|
((Super)o).$noinline$f();
|
}
|
if (i / 2 == 0) {
|
o = new Object();
|
}
|
}
|
}
|
|
public Object newObject() {
|
try {
|
return Object.class.newInstance();
|
} catch (Exception e) {
|
return null;
|
}
|
}
|
|
public SubclassA a = new SubclassA();
|
public static SubclassA b = new SubclassA();
|
|
/// CHECK-START: void Main.testInstanceFieldGetSimpleRemove() instruction_simplifier (before)
|
/// CHECK: CheckCast
|
|
/// CHECK-START: void Main.testInstanceFieldGetSimpleRemove() instruction_simplifier (after)
|
/// CHECK-NOT: CheckCast
|
public void testInstanceFieldGetSimpleRemove() {
|
Main m = new Main();
|
Super a = m.a;
|
((SubclassA)a).$noinline$g();
|
}
|
|
/// CHECK-START: void Main.testStaticFieldGetSimpleRemove() instruction_simplifier (before)
|
/// CHECK: CheckCast
|
|
/// CHECK-START: void Main.testStaticFieldGetSimpleRemove() instruction_simplifier (after)
|
/// CHECK-NOT: CheckCast
|
public void testStaticFieldGetSimpleRemove() {
|
Super b = Main.b;
|
((SubclassA)b).$noinline$g();
|
}
|
|
public SubclassA $noinline$getSubclass() { throw new RuntimeException(); }
|
|
/// CHECK-START: void Main.testInvokeSimpleRemove() instruction_simplifier (before)
|
/// CHECK: CheckCast
|
|
/// CHECK-START: void Main.testInvokeSimpleRemove() instruction_simplifier (after)
|
/// CHECK-NOT: CheckCast
|
public void testInvokeSimpleRemove() {
|
Super b = $noinline$getSubclass();
|
((SubclassA)b).$noinline$g();
|
}
|
/// CHECK-START: void Main.testArrayGetSimpleRemove() instruction_simplifier (before)
|
/// CHECK: CheckCast
|
|
/// CHECK-START: void Main.testArrayGetSimpleRemove() instruction_simplifier (after)
|
/// CHECK-NOT: CheckCast
|
public void testArrayGetSimpleRemove() {
|
Super[] a = new SubclassA[10];
|
((SubclassA)a[0]).$noinline$g();
|
}
|
|
/// CHECK-START: int Main.testLoadExceptionInCatchNonExact(int, int) builder (after)
|
/// CHECK: LoadException klass:java.lang.ArithmeticException can_be_null:false exact:false
|
public int testLoadExceptionInCatchNonExact(int x, int y) {
|
try {
|
return x / y;
|
} catch (ArithmeticException ex) {
|
return ex.hashCode();
|
}
|
}
|
|
/// CHECK-START: int Main.testLoadExceptionInCatchExact(int) builder (after)
|
/// CHECK: LoadException klass:FinalException can_be_null:false exact:true
|
public int testLoadExceptionInCatchExact(int x) {
|
try {
|
if (x == 42) {
|
throw new FinalException();
|
} else {
|
return x;
|
}
|
} catch (FinalException ex) {
|
return ex.hashCode();
|
}
|
}
|
|
/// CHECK-START: int Main.testLoadExceptionInCatchAll(int, int) builder (after)
|
/// CHECK: LoadException klass:java.lang.Throwable can_be_null:false exact:false
|
public int testLoadExceptionInCatchAll(int x, int y) {
|
try {
|
x = x / y;
|
} finally {
|
return x;
|
}
|
}
|
|
private Generic<SubclassC> genericC = new Generic<SubclassC>();
|
private Generic<Final> genericFinal = new Generic<Final>();
|
|
private SubclassC get() {
|
return genericC.get();
|
}
|
|
private Final getFinal() {
|
return genericFinal.get();
|
}
|
|
/// CHECK-START: SubclassC Main.inlineGenerics() builder (after)
|
/// CHECK: <<Invoke:l\d+>> InvokeStaticOrDirect klass:SubclassC exact:false
|
/// CHECK-NEXT: Return [<<Invoke>>]
|
|
/// CHECK-START: SubclassC Main.inlineGenerics() inliner (after)
|
/// CHECK: <<BoundType:l\d+>> BoundType klass:SubclassC exact:false
|
/// CHECK: Return [<<BoundType>>]
|
private SubclassC inlineGenerics() {
|
SubclassC c = get();
|
return c;
|
}
|
|
/// CHECK-START: Final Main.inlineGenericsFinal() builder (after)
|
/// CHECK: <<Invoke:l\d+>> InvokeStaticOrDirect klass:Final exact:true
|
/// CHECK-NEXT: Return [<<Invoke>>]
|
|
/// CHECK-START: Final Main.inlineGenericsFinal() inliner (after)
|
/// CHECK: <<BoundType:l\d+>> BoundType klass:Final exact:true
|
/// CHECK: Return [<<BoundType>>]
|
private Final inlineGenericsFinal() {
|
Final f = getFinal();
|
return f;
|
}
|
|
/// CHECK-START: void Main.boundOnlyOnceIfNotNull(java.lang.Object) inliner (after)
|
/// CHECK: BoundType
|
/// CHECK-NOT: BoundType
|
private void boundOnlyOnceIfNotNull(Object o) {
|
if (o != null) {
|
o.toString();
|
}
|
}
|
|
/// CHECK-START: void Main.boundOnlyOnceIfInstanceOf(java.lang.Object) inliner (after)
|
/// CHECK: BoundType
|
/// CHECK-NOT: BoundType
|
private void boundOnlyOnceIfInstanceOf(Object o) {
|
if (o instanceof Main) {
|
o.toString();
|
}
|
}
|
|
/// CHECK-START: Final Main.boundOnlyOnceCheckCast(Generic) inliner (after)
|
/// CHECK: BoundType
|
/// CHECK-NOT: BoundType
|
private Final boundOnlyOnceCheckCast(Generic<Final> o) {
|
Final f = o.get();
|
return f;
|
}
|
|
private Super getSuper() {
|
return new SubclassA();
|
}
|
|
/// CHECK-START: void Main.updateNodesInTheSameBlockAsPhi(boolean) builder (after)
|
/// CHECK: <<Phi:l\d+>> Phi klass:Super
|
/// CHECK: NullCheck [<<Phi>>] klass:Super
|
|
/// CHECK-START: void Main.updateNodesInTheSameBlockAsPhi(boolean) inliner (after)
|
/// CHECK: <<Phi:l\d+>> Phi klass:SubclassA
|
/// CHECK: NullCheck [<<Phi>>] klass:SubclassA
|
private void updateNodesInTheSameBlockAsPhi(boolean cond) {
|
Super s = getSuper();
|
if (cond) {
|
s = new SubclassA();
|
}
|
s.$noinline$f();
|
}
|
|
/// CHECK-START: java.lang.String Main.checkcastPreserveNullCheck(java.lang.Object) inliner (after)
|
/// CHECK: <<This:l\d+>> ParameterValue
|
/// CHECK: <<Param:l\d+>> ParameterValue
|
/// CHECK: <<Clazz:l\d+>> LoadClass
|
/// CHECK: CheckCast [<<Param>>,<<Clazz>>]
|
/// CHECK: BoundType [<<Param>>] can_be_null:true
|
|
/// CHECK-START: java.lang.String Main.checkcastPreserveNullCheck(java.lang.Object) instruction_simplifier (after)
|
/// CHECK: <<This:l\d+>> ParameterValue
|
/// CHECK: <<Param:l\d+>> ParameterValue
|
/// CHECK: <<Clazz:l\d+>> LoadClass
|
/// CHECK: CheckCast [<<Param>>,<<Clazz>>]
|
/// CHECK: <<Bound:l\d+>> BoundType [<<Param>>]
|
/// CHECK: NullCheck [<<Bound>>]
|
public String checkcastPreserveNullCheck(Object a) {
|
return ((SubclassA)a).toString();
|
}
|
|
|
/// CHECK-START: void Main.argumentCheck(Super, double, SubclassA, Final) builder (after)
|
/// CHECK: ParameterValue klass:Main can_be_null:false exact:false
|
/// CHECK: ParameterValue klass:Super can_be_null:true exact:false
|
/// CHECK: ParameterValue
|
/// CHECK: ParameterValue klass:SubclassA can_be_null:true exact:false
|
/// CHECK: ParameterValue klass:Final can_be_null:true exact:true
|
/// CHECK-NOT: ParameterValue
|
private void argumentCheck(Super s, double d, SubclassA a, Final f) {
|
}
|
|
private Main getNull() {
|
return null;
|
}
|
|
private int mainField = 0;
|
|
/// CHECK-START: SuperInterface Main.getWiderType(boolean, Interface, OtherInterface) builder (after)
|
/// CHECK: <<Phi:l\d+>> Phi klass:java.lang.Object
|
/// CHECK: Return [<<Phi>>]
|
private SuperInterface getWiderType(boolean cond, Interface a, OtherInterface b) {
|
return cond ? a : b;
|
}
|
|
/// CHECK-START: void Main.testInlinerWidensReturnType(boolean, Interface, OtherInterface) inliner (before)
|
/// CHECK: <<Invoke:l\d+>> InvokeStaticOrDirect klass:SuperInterface
|
/// CHECK: <<NullCheck:l\d+>> NullCheck [<<Invoke>>] klass:SuperInterface exact:false
|
/// CHECK: InvokeInterface [<<NullCheck>>]
|
|
/// CHECK-START: void Main.testInlinerWidensReturnType(boolean, Interface, OtherInterface) inliner (after)
|
/// CHECK: <<Phi:l\d+>> Phi klass:java.lang.Object
|
/// CHECK: <<NullCheck:l\d+>> NullCheck [<<Phi>>] klass:SuperInterface exact:false
|
/// CHECK: InvokeInterface [<<NullCheck>>]
|
private void testInlinerWidensReturnType(boolean cond, Interface a, OtherInterface b) {
|
getWiderType(cond, a, b).superInterfaceMethod();
|
}
|
|
/// CHECK-START: void Main.testInlinerReturnsNull() inliner (before)
|
/// CHECK: <<Int:i\d+>> IntConstant 0
|
/// CHECK: <<Invoke:l\d+>> InvokeStaticOrDirect klass:Main
|
/// CHECK: <<NullCheck:l\d+>> NullCheck [<<Invoke>>] klass:Main exact:false
|
/// CHECK: InstanceFieldSet [<<NullCheck>>,<<Int>>]
|
|
/// CHECK-START: void Main.testInlinerReturnsNull() inliner (after)
|
/// CHECK: <<Int:i\d+>> IntConstant 0
|
/// CHECK: <<Null:l\d+>> NullConstant klass:java.lang.Object
|
/// CHECK: <<NullCheck:l\d+>> NullCheck [<<Null>>] klass:Main exact:false
|
/// CHECK: InstanceFieldSet [<<NullCheck>>,<<Int>>]
|
private void testInlinerReturnsNull() {
|
Main o = getNull();
|
o.mainField = 0;
|
}
|
|
/// CHECK-START: void Main.testThisArgumentMoreSpecific(boolean) inliner (before)
|
/// CHECK-DAG: <<Arg:l\d+>> NewInstance
|
/// CHECK-DAG: InvokeVirtual [<<Arg>>,{{z\d+}}] method_name:Super.$inline$h
|
|
/// CHECK-START: void Main.testThisArgumentMoreSpecific(boolean) inliner (after)
|
/// CHECK-DAG: <<Arg:l\d+>> NewInstance
|
/// CHECK-DAG: <<Null:l\d+>> NullConstant
|
/// CHECK-DAG: <<Phi:l\d+>> Phi [<<Arg>>,<<Null>>] klass:SubclassA
|
/// CHECK-DAG: <<NCPhi:l\d+>> NullCheck [<<Phi>>]
|
/// CHECK-DAG: InvokeVirtual [<<NCPhi>>] method_name:java.lang.Object.hashCode
|
|
public void testThisArgumentMoreSpecific(boolean cond) {
|
// Inlining method from Super will build it with `this` typed as Super.
|
// Running RTP will sharpen it to SubclassA.
|
SubclassA obj = new SubclassA();
|
((Super) obj).$inline$h(cond);
|
}
|
|
public static int $inline$hashCode(Super obj) {
|
return obj.hashCode();
|
}
|
|
/// CHECK-START: void Main.testExplicitArgumentMoreSpecific(SubclassA) inliner (before)
|
/// CHECK-DAG: <<Arg:l\d+>> ParameterValue klass:SubclassA
|
// Note: The ArtMethod* (typed as int or long) is optional after sharpening.
|
/// CHECK-DAG: InvokeStaticOrDirect [<<Arg>>{{(,[ij]\d+)?}}] method_name:Main.$inline$hashCode
|
|
/// CHECK-START: void Main.testExplicitArgumentMoreSpecific(SubclassA) inliner (after)
|
/// CHECK-DAG: <<Arg:l\d+>> ParameterValue klass:SubclassA
|
/// CHECK-DAG: <<NCArg:l\d+>> NullCheck [<<Arg>>] klass:SubclassA
|
/// CHECK-DAG: InvokeVirtual [<<NCArg>>] method_name:java.lang.Object.hashCode
|
|
public static void testExplicitArgumentMoreSpecific(SubclassA obj) {
|
// Inlining a method will build it with reference types from its signature,
|
// here the callee graph is built with Super as the type of its only argument.
|
// Running RTP after its ParameterValue instructions are replaced with actual
|
// arguments will type the inner graph more precisely.
|
$inline$hashCode(obj);
|
}
|
|
/// CHECK-START: void Main.testPhiHasOnlyNullInputs(boolean) inliner (before)
|
/// CHECK: <<Int:i\d+>> IntConstant 0
|
/// CHECK: <<Phi:l\d+>> Phi klass:Main exact:false
|
/// CHECK: <<NullCheck:l\d+>> NullCheck [<<Phi>>] klass:Main exact:false
|
/// CHECK: InstanceFieldSet [<<NullCheck>>,<<Int>>]
|
|
/// CHECK-START: void Main.testPhiHasOnlyNullInputs(boolean) inliner (after)
|
/// CHECK: <<Int:i\d+>> IntConstant 0
|
/// CHECK: <<Null:l\d+>> NullConstant klass:java.lang.Object
|
/// CHECK: <<Phi:l\d+>> Phi [<<Null>>,<<Null>>] klass:java.lang.Object exact:false
|
/// CHECK: <<NullCheck:l\d+>> NullCheck [<<Phi>>] klass:java.lang.Object exact:false
|
/// CHECK: InstanceFieldSet [<<NullCheck>>,<<Int>>]
|
private void testPhiHasOnlyNullInputs(boolean cond) {
|
Main o = cond ? null : getNull();
|
o.mainField = 0;
|
// getSuper() will force a type propagation after inlining
|
// because returns a more precise type.
|
getSuper();
|
}
|
|
/// CHECK-START: void Main.testLoopPhiWithNullFirstInput(boolean) builder (after)
|
/// CHECK-DAG: <<Null:l\d+>> NullConstant
|
/// CHECK-DAG: <<Main:l\d+>> NewInstance klass:Main exact:true
|
/// CHECK-DAG: <<LoopPhi:l\d+>> Phi [<<Null>>,<<LoopPhi>>,<<Main>>] klass:Main exact:true
|
private void testLoopPhiWithNullFirstInput(boolean cond) {
|
Main a = null;
|
while (a == null) {
|
if (cond) {
|
a = new Main();
|
}
|
}
|
}
|
|
/// CHECK-START: java.lang.Object[] Main.testInstructionsWithUntypedParent() builder (after)
|
/// CHECK-DAG: <<Null:l\d+>> NullConstant
|
/// CHECK-DAG: <<LoopPhi:l\d+>> Phi [<<Null>>,<<Phi:l\d+>>] klass:java.lang.Object[] exact:true
|
/// CHECK-DAG: <<Array:l\d+>> NewArray klass:java.lang.Object[] exact:true
|
/// CHECK-DAG: <<Phi>> Phi [<<Array>>,<<LoopPhi>>] klass:java.lang.Object[] exact:true
|
/// CHECK-DAG: <<NC:l\d+>> NullCheck [<<LoopPhi>>] klass:java.lang.Object[] exact:true
|
/// CHECK-DAG: ArrayGet [<<NC>>,{{i\d+}}] klass:java.lang.Object exact:false
|
private Object[] testInstructionsWithUntypedParent() {
|
Object[] array = null;
|
boolean cond = true;
|
for (int i = 0; i < 10; ++i) {
|
if (cond) {
|
array = new Object[10];
|
array[0] = new Object();
|
cond = false;
|
} else {
|
array[i] = array[0];
|
}
|
}
|
return array;
|
}
|
|
public static void main(String[] args) {
|
}
|
}
|