blob: e32f2cae88a3a063087b13a4f3490839235a4fde [file] [log] [blame]
// Copyright (c) 2017, the R8 project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
public class Locals {
private static void noLocals() {
System.out.println("There's no local here");
}
private static void unusedLocals() {
int i = Integer.MAX_VALUE;
System.out.println("Not using local variable");
}
private static void constantLocals(int p) {
int c = 5;
int v = c + p;
System.out.println("c=" + c + ", v=" + v);
}
private static void zeroLocals() {
int i = 0;
float f = 0.0f;
System.out.println("zeroLocals");
}
private static void noFlowOptimization() {
int i = 0;
if (i == 0) {
System.out.println("i == 0");
} else {
System.out.println("i != 0");
}
}
private static void manyLocals() {
int i1 = 1;
int i2 = 2;
int i3 = 3;
int i4 = 4;
int i5 = 5;
int i6 = 6;
int i7 = 7;
int i8 = 8;
int i9 = 9;
int i10 = 10;
int i11 = 11;
int i12 = 12;
invokeRange(i6, i5, i4, i3, i2, i1, invokeRange(i12, i11, i10, i9, i8, i7, 0));
}
private static int reverseRange(int a, int b, int c, int d, int e, int f, int g) {
return invokeRange(g, f, e, d, c, b, a);
}
private static int invokeRange(int a, int b, int c, int d, int e, int f, int g) {
System.out.println(a + b + c + d + e + f + g);
return a + b + c + d + e + f + g;
}
private void lotsOfArrayLength() {
int lengthOfArray1 = 0;
int lengthOfArray2 = 0;
int lengthOfArray3 = 0;
int lengthOfArray4 = 0;
int lengthOfArray5 = 0;
int lengthOfArray6 = 0;
int lengthOfArray7 = 0;
int lengthOfArray8 = 0;
int lengthOfArray9 = 0;
int lengthOfArray10 = 0;
int lengthOfArray11 = 0;
int lengthOfArray12 = 0;
int lengthOfArray13 = 0;
int lengthOfArray14 = 0;
int lengthOfArray15 = 0;
int lengthOfArray16 = 0;
// These statements are compiled into new-array in DEX which stores the result in a 4bit
// register (0..15).
boolean[] array1 = new boolean[1];
byte[] array2 = new byte[1];
char[] array3 = new char[1];
short[] array4 = new short[1];
int[] array5 = new int[1];
long[] array6 = new long[1];
float[] array7 = new float[1];
double[] array8 = new double[1];
Object[] array9 = new Object[1];
String[] array10 = new String[1];
String[] array11 = new String[1];
String[] array12 = new String[1];
String[] array13 = new String[1];
String[] array14 = new String[1];
String[] array15 = new String[1];
String[] array16 = new String[1];
// 1st breakpoint to capture the IDs of each array.
breakpoint();
// Breakpoint at line below. In DEX, the array-length instruction expects a 4bit register
// (0..15). By creating >16 locals, we should cause an intermediate move instruction to
// copy/move a high register (>= 16) into a lower register (< 16).
// A test should step instruction by instruction and make sure all locals have the correct
// value.
lengthOfArray1 = array1.length;
lengthOfArray2 = array2.length;
lengthOfArray3 = array3.length;
lengthOfArray4 = array4.length;
lengthOfArray5 = array5.length;
lengthOfArray6 = array6.length;
lengthOfArray7 = array7.length;
lengthOfArray8 = array8.length;
lengthOfArray9 = array9.length;
lengthOfArray10 = array10.length;
lengthOfArray11 = array11.length;
lengthOfArray12 = array12.length;
lengthOfArray13 = array13.length;
lengthOfArray14 = array14.length;
lengthOfArray15 = array15.length;
lengthOfArray16 = array16.length;
// Use all locals
System.out.println(array1);
System.out.println(array2);
System.out.println(array3);
System.out.println(array4);
System.out.println(array5);
System.out.println(array6);
System.out.println(array7);
System.out.println(array8);
System.out.println(array9);
System.out.println(array10);
System.out.println(array11);
System.out.println(array12);
System.out.println(array13);
System.out.println(array14);
System.out.println(array15);
System.out.println(array16);
System.out.println(lengthOfArray1);
System.out.println(lengthOfArray2);
System.out.println(lengthOfArray3);
System.out.println(lengthOfArray4);
System.out.println(lengthOfArray5);
System.out.println(lengthOfArray6);
System.out.println(lengthOfArray7);
System.out.println(lengthOfArray8);
System.out.println(lengthOfArray9);
System.out.println(lengthOfArray10);
System.out.println(lengthOfArray11);
System.out.println(lengthOfArray12);
System.out.println(lengthOfArray13);
System.out.println(lengthOfArray14);
System.out.println(lengthOfArray15);
System.out.println(lengthOfArray16);
}
// Utility method to set a breakpoint and inspect the stack.
private static void breakpoint() {
}
public void foo(int x) {
Integer obj = new Integer(x + x);
long l = obj.longValue();
try {
l = obj.longValue();
x = (int) l / x;
invokerangeLong(l, l, l, l, l, l);
sout(x);
} catch (ArithmeticException e) {
sout(l);
} catch (RuntimeException e) {
sout(l); // We should not attempt to read the previous definition of 'e' here or below.
} catch (Throwable e) {
sout(l);
}
}
private void sout(long l) {
System.out.print(l);
}
private void invokerangeLong(long a, long b, long c, long d, long e, long f) {
if (a != d) {
throw new RuntimeException("unexpected");
}
}
public static int stepEmptyForLoopBody1(int n) {
int i;
for (i = 0; i < n; i++) ;
return i;
}
public static int stepEmptyForLoopBody2(int n) {
int i;
for (i = 0; i < n; i++) {
// has a line but still empty...
}
return i;
}
public static int stepNonEmptyForLoopBody(int n) {
int i;
for (i = 0; i < n; i++)
nop();
return i;
}
public static void nop() {}
public static int tempInCase(int x) {
int res = 0;
for (int i = 0; i < x; ++i) {
int rem = x - i;
switch (rem) {
case 1:
return res;
case 5:
int tmp = res + x + i;
res += tmp;
break;
case 10:
i++;
break;
default:
res += rem;
}
res += rem % 2;
}
res *= x;
return res;
}
public static int localSwap(int x, int y) {
int sum = x + y;
{
int t = x;
x = y;
y = t;
}
return sum + x + y;
}
public static int argumentLiveAtReturn(int x) {
switch (x) {
case 0:
return 0;
case 1:
return 0;
case 2:
return 0;
case 100:
return 1;
case 101:
return 1;
case 102:
return 1;
}
return -1;
}
public static int switchRewriteToIfs(int x) {
{
int t = x + 1;
x = t;
x = x + x;
}
switch (x) {
case 0:
return 0;
case 100:
return 1;
}
return -1;
}
public static int switchRewriteToSwitches(int x) {
{
int t = x + 1;
x = t;
x = x + x;
}
switch (x) {
case 0:
return 0;
case 1:
return 0;
case 2:
return 0;
case 100:
return 1;
case 101:
return 1;
case 102:
return 1;
}
return -1;
}
public static String regression65039701(boolean createIntNotLong) {
Object a = createIntNotLong ? new int[1] : new long[1];
if (a instanceof int []) {
((int [])a)[0] = 0;
}
return "OK";
}
public static void regression65066975(boolean bit) {
nop();
if (bit) {
nop();
} else {
nop();
}
nop();
}
public static int localConstant(boolean b) {
if (b) {
int result1 = 1;
return result1;
} else {
int result2 = 2;
return result2;
}
}
public static int localConstantBis(boolean b) {
int result = 0;
if (b) {
result = 1;
} else {
result = 2;
}
return result;
}
public static int localTriggeringCSE() {
int a = 1;
int b = 3;
int c = a + b;
int d = a + b;
return c + d;
}
public static int intAddition(int a, int b, int c) {
a += b;
b += c;
c = a + b;
return c;
}
public static void localVisibilityIntoLoop(double B[][], double A[][]) {
int i;
int length = 1;
for (i = 0; i < length; i++) {
double Bi[] = B[i];
double Ai[] = A[i];
for (int j = 0; j < 1; j += 4) {
Bi[j] = Ai[j];
}
}
}
public static void main(String[] args) {
noLocals();
unusedLocals();
constantLocals(10);
zeroLocals();
noFlowOptimization();
manyLocals();
reverseRange(1,2,3,4,5,6,7);
new Locals().lotsOfArrayLength();
new Locals().foo(21);
stepEmptyForLoopBody1(3);
stepEmptyForLoopBody2(3);
stepNonEmptyForLoopBody(3);
tempInCase(42);
localSwap(1, 2);
argumentLiveAtReturn(-1);
switchRewriteToIfs(1);
switchRewriteToSwitches(1);
regression65039701(true);
regression65066975(false);
System.out.println(localConstant(true));
System.out.println(localConstantBis(true));
System.out.println(localTriggeringCSE());
System.out.println(intAddition(1, 2, 6));
localVisibilityIntoLoop(new double[1][1], new double[1][1]);
}
}