| // Copyright (c) 2016, 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. | |
| // This code is not run directly. It needs to be compiled to dex code. | |
| // 'throwing.dex' is what is run. | |
| package throwing; | |
| import java.util.Collections; | |
| import java.util.List; | |
| class Throwing { | |
| static int[] used = new int[10]; | |
| public static void main(String[] args) { | |
| try { | |
| used[0] = throwAtFistLine(42); | |
| } catch (Exception e) { | |
| printFrameHead(e); | |
| } | |
| try { | |
| used[1] = throwInMiddle(42); | |
| } catch (Exception e) { | |
| printFrameHead(e); | |
| } | |
| try { | |
| used[2] = throwAfterMultiInline(42); | |
| } catch (Exception e) { | |
| printFrameHead(e); | |
| } | |
| try { | |
| int value = magicNumber(42); | |
| // This throws after an inline, on the top-level. | |
| used[6] = value * 10; | |
| used[7] = anotherInlinedFunction(value); | |
| // | |
| // Some space to increase line numbers... | |
| // | |
| used[8] = value / (value & 0x0); | |
| } catch (Exception e) { | |
| printFrameHead(e); | |
| } | |
| Nested nested = new Nested(); | |
| try { | |
| used[3] = nested.justThrow(42); | |
| } catch (Exception e) { | |
| printFrameHead(e); | |
| } | |
| nested.doSomethingUseless(); | |
| used[0] += Nested.callAMethod(nested, 11); | |
| used[0] += Nested.callAMethod(nested, 42); | |
| RenamedClass aInstance = RenamedClass.create(); | |
| aInstance.takeThingsForASpin(42); | |
| System.out.print(used[0]); | |
| try { | |
| throwInAFunctionThatIsNotInlinedAndCalledTwice(); | |
| } catch (Exception e) { | |
| printFrameHead(e); | |
| } | |
| try { | |
| throwInAFunctionThatIsNotInlinedAndCalledTwice(); | |
| } catch (Exception e) { | |
| printFrameHead(e); | |
| } | |
| try { | |
| aFunctionThatCallsAnInlinedMethodThatThrows(Collections.emptyList()); | |
| } catch (Exception e) { | |
| printFrameHead(e); | |
| } | |
| try { | |
| anotherFunctionThatCallsAnInlinedMethodThatThrows("string"); | |
| } catch (Exception e) { | |
| printFrameHead(e); | |
| } | |
| try { | |
| aFunctionsThatThrowsBeforeAnInlinedMethod(magicNumber(42)); | |
| } catch (Exception e) { | |
| printFrameHead(e); | |
| } | |
| } | |
| public static int magicNumber(int value) { | |
| if (value < 0) { | |
| return magicNumber(value++); | |
| } | |
| return value; | |
| } | |
| public static void printFrameHead(Exception e) { | |
| for (StackTraceElement element : e.getStackTrace()) { | |
| System.out.println("FRAME: " + element); | |
| } | |
| } | |
| // This throws in the first line of the method. | |
| public static int throwAtFistLine(int value) { | |
| int aValue = value * 2 / (value & 0x0); | |
| return aValue; | |
| } | |
| // This throws a little further down. | |
| public static int throwInMiddle(int value) { | |
| used[2] = value * 10; | |
| used[3] = value >> 3; | |
| used[4] = value / (value & 0x0); | |
| used[5] = value * 20; | |
| return value >> 5; | |
| } | |
| // This throws after another inlined function. | |
| public static int throwAfterMultiInline(int value) { | |
| used[6] = value * 10; | |
| used[7] = anotherInlinedFunction(value); | |
| // | |
| // Some space to increase line numbers... | |
| // | |
| used[8] = value / (value & 0x0); | |
| return value >> 5; | |
| } | |
| public static int throwInAFunctionThatIsNotInlinedAndCalledTwice() { | |
| for (int i = 0; i < 10; i++) { | |
| used[9] += i; | |
| System.out.println("Increment by one!"); | |
| } | |
| System.out.println("Incremented by 10."); | |
| used[9] = used[9] / (used[9] & 0x0); | |
| return used[9]; | |
| } | |
| // Small method that throws and can be inlined. | |
| private static int anotherThrowingMethodToInline(int value) { | |
| used[4] = value / (value & 0x0); | |
| return value >> 5; | |
| } | |
| // It is important that this function uses an argument type that is otherwise unused, so it gets | |
| // the same minified name. | |
| public static int aFunctionThatCallsAnInlinedMethodThatThrows(List aList) { | |
| used[9] = aList.size(); | |
| for (int i = 0; i < 10; i++) { | |
| used[9] += i; | |
| System.out.println("Increment by one!"); | |
| } | |
| System.out.println("Incremented by 10."); | |
| used[9] = anotherThrowingMethodToInline(used[9]); | |
| return used[9]; | |
| } | |
| // Small method that throws and can be inlined. | |
| private static int yetAnotherThrowingMethodToInline(int value) { | |
| used[5] = value / (value & 0x0); | |
| return value >> 5; | |
| } | |
| // It is important that this function uses an argument type that is otherwise unused, so it gets | |
| // the same minified name. | |
| public static int anotherFunctionThatCallsAnInlinedMethodThatThrows(String aString) { | |
| used[0] = aString.length(); | |
| for (int i = 0; i < 10; i++) { | |
| used[8] += i; | |
| System.out.println("Increment by one!"); | |
| } | |
| System.out.println("Incremented by 10."); | |
| used[8] = yetAnotherThrowingMethodToInline(used[8]); | |
| return used[8]; | |
| } | |
| public static int aFunctionsThatThrowsBeforeAnInlinedMethod(int value) { | |
| used[1] = value / (value & 0x0); | |
| anotherInlinedFunction(used[1]); | |
| return used[1]; | |
| } | |
| // This will be inlined above but does not throw | |
| public static int anotherInlinedFunction(int value) { | |
| return value / (value & 0xff); | |
| } | |
| /** | |
| * A nested class with different kind of methods to have inlining from a nested class and also | |
| * renamings of a nested class in the mapping file. | |
| * | |
| * <p>Some methods are recursive to avoid inlining. | |
| */ | |
| static class Nested { | |
| int justThrow(int value) { | |
| return used[8] = value / (value & 0x0); | |
| } | |
| // This will also be inlined. Not used in test but for generating interesting mapping files. | |
| void doSomethingUseless() { | |
| Throwing.used[9] = 11; | |
| } | |
| static int callAMethod(Nested on, int value) { | |
| if (value > 20) { | |
| return callAMethod(on, value - 1); | |
| } else { | |
| return on.aMethod(value); | |
| } | |
| } | |
| int aMethod(int value) { | |
| if (value > 10) { | |
| return aMethod(value - 1); | |
| } else { | |
| return value; | |
| } | |
| } | |
| } | |
| } |