blob: 574556f3469e243256b6c7c9d8c88ae40fedb45e [file] [log] [blame]
Mads Ager418d1ca2017-05-22 09:35:49 +02001// 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
8package throwing;
9
10import java.util.Collections;
11import java.util.List;
12
13class Throwing {
14
15 static int[] used = new int[10];
16
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
95 public static int magicNumber(int value) {
96 if (value < 0) {
97 return magicNumber(value++);
98 }
99 return value;
100 }
101
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.
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.
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.
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
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.
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.
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.
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.
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
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
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
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.
206 void doSomethingUseless() {
207 Throwing.used[9] = 11;
208 }
209
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
218 int aMethod(int value) {
219 if (value > 10) {
220 return aMethod(value - 1);
221 } else {
222 return value;
223 }
224 }
225 }
226
227}