|  | // Copyright (c) 2020, 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. | 
|  | package com.android.tools.r8.enumunboxing; | 
|  |  | 
|  | // This class implements support methods for enum unboxing. The enum unboxing optimization may | 
|  | // rewrite any call to an enum method into one of the following methods. | 
|  | // The methods Enum#name, Enum#toString and MyEnum#valueOf cannot be implemented here since they | 
|  | // are different on each Enum implementation. | 
|  | public class EnumUnboxingMethods { | 
|  |  | 
|  | // An enum is unboxed to ordinal + 1. | 
|  | // For example, enum E {A,B}, is unboxed to null -> 0, A -> 1, B-> 2. | 
|  | // Computing the ordinal of an unboxed enum throws a null pointer exception on 0, | 
|  | // else answers the value - 1. | 
|  | public static int ordinal(int unboxedEnum) { | 
|  | if (unboxedEnum == 0) { | 
|  | throw new NullPointerException(); | 
|  | } | 
|  | return unboxedEnum - 1; | 
|  | } | 
|  |  | 
|  | // The values methods normally reads the $VALUES field, then clones and returns it. | 
|  | // In our case we just create a new instance each time. | 
|  | // Note: This can replace a MyEnum#values() call, but not a MyEnum#$VALUES static get. | 
|  | // numEnums is the number of elements in the enum. | 
|  | public static int[] values(int numEnums) { | 
|  | int[] ints = new int[numEnums]; | 
|  | for (int i = 0; i < ints.length; i++) { | 
|  | ints[i] = i + 1; | 
|  | } | 
|  | return ints; | 
|  | } | 
|  |  | 
|  | // We assume the enum could be unboxed only if both parameters were proven to be of the same | 
|  | // enum types, so we do not check they belong to the same Enum type. | 
|  | // We need the 0 checks for null pointer exception. | 
|  | public static int compareTo(int unboxedEnum1, int unboxedEnum2) { | 
|  | if (unboxedEnum1 == 0 || unboxedEnum2 == 0) { | 
|  | throw new NullPointerException(); | 
|  | } | 
|  | // Formula: unboxedEnum1 - 1 - (unboxedEnum2 - 1), simplified as follow: | 
|  | return unboxedEnum1 - unboxedEnum2; | 
|  | } | 
|  |  | 
|  | // Equals on Enum is implemented using directly ==. The invoke raises a NPE if the | 
|  | // receiver is null, but returns false if the parameter is null. | 
|  | public static boolean equals(int unboxedEnum1, int unboxedEnum2) { | 
|  | if (unboxedEnum1 == 0) { | 
|  | throw new NullPointerException(); | 
|  | } | 
|  | return unboxedEnum1 == unboxedEnum2; | 
|  | } | 
|  |  | 
|  | // Methods zeroCheck and zeroCheckMessage are used to replace null checks on unboxed enums. | 
|  | public static void zeroCheck(int unboxedEnum) { | 
|  | if (unboxedEnum == 0) { | 
|  | throw new NullPointerException(); | 
|  | } | 
|  | } | 
|  |  | 
|  | public static void zeroCheckMessage(int unboxedEnum, String message) { | 
|  | if (unboxedEnum == 0) { | 
|  | throw new NullPointerException(message); | 
|  | } | 
|  | } | 
|  | } |