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 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 } 228