• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright (c) 2016, the R8 project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file.
4 
5 // This code is not run directly. It needs to be compiled to dex code.
6 // 'throwing.dex' is what is run.
7 
8 package throwing;
9 
10 import java.util.Collections;
11 import java.util.List;
12 
13 class Throwing {
14 
15   static int[] used = new int[10];
16 
main(String[] args)17   public static void main(String[] args) {
18     try {
19       used[0] = throwAtFistLine(42);
20     } catch (Exception e) {
21       printFrameHead(e);
22     }
23     try {
24       used[1] = throwInMiddle(42);
25     } catch (Exception e) {
26       printFrameHead(e);
27     }
28     try {
29       used[2] = throwAfterMultiInline(42);
30     } catch (Exception e) {
31       printFrameHead(e);
32     }
33     try {
34       int value = magicNumber(42);
35       // This throws after an inline, on the top-level.
36       used[6] = value * 10;
37       used[7] = anotherInlinedFunction(value);
38       //
39       // Some space to increase line numbers...
40       //
41       used[8] = value / (value & 0x0);
42     } catch (Exception e) {
43       printFrameHead(e);
44     }
45 
46     Nested nested = new Nested();
47 
48     try {
49       used[3] = nested.justThrow(42);
50     } catch (Exception e) {
51       printFrameHead(e);
52     }
53 
54     nested.doSomethingUseless();
55 
56     used[0] += Nested.callAMethod(nested, 11);
57     used[0] += Nested.callAMethod(nested, 42);
58 
59     RenamedClass aInstance = RenamedClass.create();
60     aInstance.takeThingsForASpin(42);
61 
62     System.out.print(used[0]);
63 
64     try {
65       throwInAFunctionThatIsNotInlinedAndCalledTwice();
66     } catch (Exception e) {
67       printFrameHead(e);
68     }
69 
70     try {
71       throwInAFunctionThatIsNotInlinedAndCalledTwice();
72     } catch (Exception e) {
73       printFrameHead(e);
74     }
75 
76     try {
77       aFunctionThatCallsAnInlinedMethodThatThrows(Collections.emptyList());
78     } catch (Exception e) {
79       printFrameHead(e);
80     }
81 
82     try {
83       anotherFunctionThatCallsAnInlinedMethodThatThrows("string");
84     } catch (Exception e) {
85       printFrameHead(e);
86     }
87 
88     try {
89       aFunctionsThatThrowsBeforeAnInlinedMethod(magicNumber(42));
90     } catch (Exception e) {
91       printFrameHead(e);
92     }
93   }
94 
magicNumber(int value)95   public static int magicNumber(int value) {
96     if (value < 0) {
97       return magicNumber(value++);
98     }
99     return value;
100   }
101 
printFrameHead(Exception e)102   public static void printFrameHead(Exception e) {
103     for (StackTraceElement element : e.getStackTrace()) {
104       System.out.println("FRAME: " + element);
105     }
106   }
107 
108   // This throws in the first line of the method.
throwAtFistLine(int value)109   public static int throwAtFistLine(int value) {
110     int aValue = value * 2 / (value & 0x0);
111     return aValue;
112   }
113 
114   // This throws a little further down.
throwInMiddle(int value)115   public static int throwInMiddle(int value) {
116     used[2] = value * 10;
117     used[3] = value >> 3;
118     used[4] = value / (value & 0x0);
119     used[5] = value * 20;
120     return value >> 5;
121   }
122 
123   // This throws after another inlined function.
throwAfterMultiInline(int value)124   public static int throwAfterMultiInline(int value) {
125     used[6] = value * 10;
126     used[7] = anotherInlinedFunction(value);
127     //
128     // Some space to increase line numbers...
129     //
130     used[8] = value / (value & 0x0);
131     return value >> 5;
132   }
133 
throwInAFunctionThatIsNotInlinedAndCalledTwice()134   public static int throwInAFunctionThatIsNotInlinedAndCalledTwice() {
135     for (int i = 0; i < 10; i++) {
136       used[9] += i;
137       System.out.println("Increment by one!");
138     }
139     System.out.println("Incremented by 10.");
140     used[9] = used[9] / (used[9] & 0x0);
141     return used[9];
142   }
143 
144   // Small method that throws and can be inlined.
anotherThrowingMethodToInline(int value)145   private static int anotherThrowingMethodToInline(int value) {
146     used[4] = value / (value & 0x0);
147     return value >> 5;
148   }
149 
150   // It is important that this function uses an argument type that is otherwise unused, so it gets
151   // the same minified name.
aFunctionThatCallsAnInlinedMethodThatThrows(List aList)152   public static int aFunctionThatCallsAnInlinedMethodThatThrows(List aList) {
153     used[9] = aList.size();
154     for (int i = 0; i < 10; i++) {
155       used[9] += i;
156       System.out.println("Increment by one!");
157     }
158     System.out.println("Incremented by 10.");
159     used[9] = anotherThrowingMethodToInline(used[9]);
160     return used[9];
161   }
162 
163   // Small method that throws and can be inlined.
yetAnotherThrowingMethodToInline(int value)164   private static int yetAnotherThrowingMethodToInline(int value) {
165     used[5] = value / (value & 0x0);
166     return value >> 5;
167   }
168 
169   // It is important that this function uses an argument type that is otherwise unused, so it gets
170   // the same minified name.
anotherFunctionThatCallsAnInlinedMethodThatThrows(String aString)171   public static int anotherFunctionThatCallsAnInlinedMethodThatThrows(String aString) {
172     used[0] = aString.length();
173     for (int i = 0; i < 10; i++) {
174       used[8] += i;
175       System.out.println("Increment by one!");
176     }
177     System.out.println("Incremented by 10.");
178     used[8] = yetAnotherThrowingMethodToInline(used[8]);
179     return used[8];
180   }
181 
aFunctionsThatThrowsBeforeAnInlinedMethod(int value)182   public static int aFunctionsThatThrowsBeforeAnInlinedMethod(int value) {
183     used[1] = value / (value & 0x0);
184     anotherInlinedFunction(used[1]);
185     return used[1];
186   }
187 
188   // This will be inlined above but does not throw
anotherInlinedFunction(int value)189   public static int anotherInlinedFunction(int value) {
190     return value / (value & 0xff);
191   }
192 
193   /**
194    * A nested class with different kind of methods to have inlining from a nested class and also
195    * renamings of a nested class in the mapping file.
196    *
197    * <p>Some methods are recursive to avoid inlining.
198    */
199   static class Nested {
200 
justThrow(int value)201     int justThrow(int value) {
202       return used[8] = value / (value & 0x0);
203     }
204 
205     // This will also be inlined. Not used in test but for generating interesting mapping files.
doSomethingUseless()206     void doSomethingUseless() {
207       Throwing.used[9] = 11;
208     }
209 
callAMethod(Nested on, int value)210     static int callAMethod(Nested on, int value) {
211       if (value > 20) {
212         return callAMethod(on, value - 1);
213       } else {
214         return on.aMethod(value);
215       }
216     }
217 
aMethod(int value)218     int aMethod(int value) {
219       if (value > 10) {
220         return aMethod(value - 1);
221       } else {
222         return value;
223       }
224     }
225   }
226 
227 }
228