1 /* 2 * Copyright (C) 2015 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 public class Main { Main()18 public Main() { 19 } 20 $noinline$testLiveArgument(int arg1, Integer arg2)21 static int $noinline$testLiveArgument(int arg1, Integer arg2) { 22 doStaticNativeCallLiveVreg(); 23 return arg1 + arg2.intValue(); 24 } 25 moveArgToCalleeSave()26 static void moveArgToCalleeSave() { 27 try { 28 Thread.sleep(0); 29 } catch (Exception e) { 30 throw new Error(e); 31 } 32 } 33 $noinline$testIntervalHole(int arg, boolean test)34 static void $noinline$testIntervalHole(int arg, boolean test) { 35 // Move the argument to callee save to ensure it is in 36 // a readable register. 37 moveArgToCalleeSave(); 38 if (test) { 39 staticField1 = arg; 40 // The environment use of `arg` should not make it live. 41 doStaticNativeCallLiveVreg(); 42 } else { 43 staticField2 = arg; 44 // The environment use of `arg` should not make it live. 45 doStaticNativeCallLiveVreg(); 46 } 47 if (staticField1 == 2) { 48 throw new Error(""); 49 } 50 } 51 doStaticNativeCallLiveVreg()52 static native void doStaticNativeCallLiveVreg(); 53 main(String[] args)54 public static void main(String[] args) { 55 System.loadLibrary(args[0]); 56 if ($noinline$testLiveArgument(staticField3, Integer.valueOf(1)) != staticField3 + 1) { 57 throw new Error("Expected " + staticField3 + 1); 58 } 59 60 if ($noinline$testLiveArgument(staticField3,Integer.valueOf(1)) != staticField3 + 1) { 61 throw new Error("Expected " + staticField3 + 1); 62 } 63 64 testWrapperIntervalHole(1, true); 65 testWrapperIntervalHole(1, false); 66 67 $noinline$testCodeSinking(1); 68 } 69 70 // Wrapper method to avoid inlining, which affects liveness 71 // of dex registers. testWrapperIntervalHole(int arg, boolean test)72 static void testWrapperIntervalHole(int arg, boolean test) { 73 try { 74 Thread.sleep(0); 75 $noinline$testIntervalHole(arg, test); 76 } catch (Exception e) { 77 throw new Error(e); 78 } 79 } 80 81 // The value of dex register which originally holded "Object[] o = new Object[1];" will not be 82 // live at the call to doStaticNativeCallLiveVreg after code sinking optimizizaion. $noinline$testCodeSinking(int x)83 static void $noinline$testCodeSinking(int x) { 84 Object[] o = new Object[1]; 85 o[0] = o; 86 doStaticNativeCallLiveVreg(); 87 if (doThrow) { 88 throw new Error(o.toString()); 89 } 90 } 91 92 static boolean doThrow; 93 94 static int staticField1; 95 static int staticField2; 96 static int staticField3 = 42; 97 } 98