1 # Copyright (C) 2017 The Android Open Source Project 2 # 3 # Licensed under the Apache License, Version 2.0 (the "License"); 4 # you may not use this file except in compliance with the License. 5 # You may obtain a copy of the License at 6 # 7 # http://www.apache.org/licenses/LICENSE-2.0 8 # 9 # Unless required by applicable law or agreed to in writing, software 10 # distributed under the License is distributed on an "AS IS" BASIS, 11 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 # See the License for the specific language governing permissions and 13 # limitations under the License. 14 15 .class public LSmaliTests; 16 .super Ljava/lang/Object; 17 18 ## CHECK-START: void SmaliTests.bar() load_store_elimination (after) 19 ## CHECK-DAG: <<Null:l\d+>> NullConstant 20 ## CHECK-DAG: <<BoundType:l\d+>> BoundType [<<Null>>] 21 ## CHECK-DAG: <<CheckL:l\d+>> NullCheck [<<BoundType>>] 22 ## CHECK-DAG: <<GetL0:l\d+>> ArrayGet [<<CheckL>>,{{i\d+}}] 23 ## CHECK-DAG: <<GetL1:l\d+>> ArrayGet [<<CheckL>>,{{i\d+}}] 24 ## CHECK-DAG: <<GetL2:l\d+>> ArrayGet [<<CheckL>>,{{i\d+}}] 25 ## CHECK-DAG: <<GetL3:l\d+>> ArrayGet [<<CheckL>>,{{i\d+}}] 26 ## CHECK-DAG: <<CheckJ:l\d+>> NullCheck [<<Null>>] 27 ## CHECK-DAG: <<GetJ0:j\d+>> ArrayGet [<<CheckJ>>,{{i\d+}}] 28 ## CHECK-DAG: <<GetJ1:j\d+>> ArrayGet [<<CheckJ>>,{{i\d+}}] 29 ## CHECK-DAG: <<GetJ2:j\d+>> ArrayGet [<<CheckJ>>,{{i\d+}}] 30 ## CHECK-DAG: <<GetJ3:j\d+>> ArrayGet [<<CheckJ>>,{{i\d+}}] 31 .method public static bar()V 32 .registers 7 33 34 .prologue 35 const/4 v6, 0x3 36 const/4 v5, 0x2 37 const/4 v4, 0x1 38 const/4 v3, 0x0 39 40 # We create multiple accesses that will lead the bounds check 41 # elimination pass to add a HDeoptimize. Not having the bounds check helped 42 # the load store elimination think it could merge two ArrayGet with different 43 # types. 44 45 # String[] array = (String[])getNull(); 46 invoke-static {}, LMain;->getNull()Ljava/lang/Object; 47 move-result-object v0 48 check-cast v0, [Ljava/lang/String; 49 50 # objectField = array[0]; 51 aget-object v2, v0, v3 52 sput-object v2, LMain;->objectField:Ljava/lang/Object; 53 # objectField = array[1]; 54 aget-object v2, v0, v4 55 sput-object v2, LMain;->objectField:Ljava/lang/Object; 56 # objectField = array[2]; 57 aget-object v2, v0, v5 58 sput-object v2, LMain;->objectField:Ljava/lang/Object; 59 # objectField = array[3]; 60 aget-object v2, v0, v6 61 sput-object v2, LMain;->objectField:Ljava/lang/Object; 62 63 # long[] longArray = getLongArray(); 64 invoke-static {}, LMain;->getLongArray()[J 65 move-result-object v1 66 67 # longField = longArray[0]; 68 aget-wide v2, v1, v3 69 sput-wide v2, LMain;->longField:J 70 # longField = longArray[1]; 71 aget-wide v2, v1, v4 72 sput-wide v2, LMain;->longField:J 73 # longField = longArray[2]; 74 aget-wide v2, v1, v5 75 sput-wide v2, LMain;->longField:J 76 # longField = longArray[3]; 77 aget-wide v2, v1, v6 78 sput-wide v2, LMain;->longField:J 79 80 return-void 81 .end method 82 83 # This is indentical to bar() except that it has two check-casts 84 # that DX tends to generate. 85 86 ## CHECK-START: void SmaliTests.bar2() load_store_elimination (after) 87 ## CHECK-DAG: <<Null:l\d+>> NullConstant 88 ## CHECK-DAG: <<BoundFirst:l\d+>> BoundType [<<Null>>] 89 ## CHECK-DAG: <<BoundType:l\d+>> BoundType [<<BoundFirst>>] 90 ## CHECK-DAG: <<CheckL:l\d+>> NullCheck [<<BoundType>>] 91 ## CHECK-DAG: <<GetL0:l\d+>> ArrayGet [<<CheckL>>,{{i\d+}}] 92 ## CHECK-DAG: <<GetL1:l\d+>> ArrayGet [<<CheckL>>,{{i\d+}}] 93 ## CHECK-DAG: <<GetL2:l\d+>> ArrayGet [<<CheckL>>,{{i\d+}}] 94 ## CHECK-DAG: <<GetL3:l\d+>> ArrayGet [<<CheckL>>,{{i\d+}}] 95 ## CHECK-DAG: <<CheckJ:l\d+>> NullCheck [<<Null>>] 96 ## CHECK-DAG: <<GetJ0:j\d+>> ArrayGet [<<CheckJ>>,{{i\d+}}] 97 ## CHECK-DAG: <<GetJ1:j\d+>> ArrayGet [<<CheckJ>>,{{i\d+}}] 98 ## CHECK-DAG: <<GetJ2:j\d+>> ArrayGet [<<CheckJ>>,{{i\d+}}] 99 ## CHECK-DAG: <<GetJ3:j\d+>> ArrayGet [<<CheckJ>>,{{i\d+}}] 100 .method public static bar2()V 101 .registers 7 102 103 .prologue 104 const/4 v6, 0x3 105 const/4 v5, 0x2 106 const/4 v4, 0x1 107 const/4 v3, 0x0 108 109 # We create multiple accesses that will lead the bounds check 110 # elimination pass to add a HDeoptimize. Not having the bounds check helped 111 # the load store elimination think it could merge two ArrayGet with different 112 # types. 113 114 # String[] array = (String[])getNull(); 115 invoke-static {}, LMain;->getNull()Ljava/lang/Object; 116 move-result-object v2 117 check-cast v2, [Ljava/lang/String; 118 119 move-object v0, v2 120 check-cast v0, [Ljava/lang/String; 121 122 # objectField = array[0]; 123 aget-object v2, v0, v3 124 sput-object v2, LMain;->objectField:Ljava/lang/Object; 125 # objectField = array[1]; 126 aget-object v2, v0, v4 127 sput-object v2, LMain;->objectField:Ljava/lang/Object; 128 # objectField = array[2]; 129 aget-object v2, v0, v5 130 sput-object v2, LMain;->objectField:Ljava/lang/Object; 131 # objectField = array[3]; 132 aget-object v2, v0, v6 133 sput-object v2, LMain;->objectField:Ljava/lang/Object; 134 135 # long[] longArray = getLongArray(); 136 invoke-static {}, LMain;->getLongArray()[J 137 move-result-object v1 138 139 # longField = longArray[0]; 140 aget-wide v2, v1, v3 141 sput-wide v2, LMain;->longField:J 142 # longField = longArray[1]; 143 aget-wide v2, v1, v4 144 sput-wide v2, LMain;->longField:J 145 # longField = longArray[2]; 146 aget-wide v2, v1, v5 147 sput-wide v2, LMain;->longField:J 148 # longField = longArray[3]; 149 aget-wide v2, v1, v6 150 sput-wide v2, LMain;->longField:J 151 152 return-void 153 .end method 154 155 # static fields 156 .field static doThrow:Z # boolean 157 158 # direct methods 159 .method static constructor <clinit>()V 160 .registers 1 161 162 .prologue 163 # doThrow = false 164 const/4 v0, 0x0 165 sput-boolean v0, LSmaliTests;->doThrow:Z 166 return-void 167 .end method 168