// Copyright (c) 2018, 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.ir.desugar;

import com.android.tools.r8.dex.Constants;
import com.android.tools.r8.graph.AppInfo;
import com.android.tools.r8.graph.AppView;
import com.android.tools.r8.graph.ClassAccessFlags;
import com.android.tools.r8.graph.DexAnnotationSet;
import com.android.tools.r8.graph.DexApplication.Builder;
import com.android.tools.r8.graph.DexClass;
import com.android.tools.r8.graph.DexEncodedField;
import com.android.tools.r8.graph.DexEncodedMethod;
import com.android.tools.r8.graph.DexItemFactory;
import com.android.tools.r8.graph.DexMethod;
import com.android.tools.r8.graph.DexProgramClass;
import com.android.tools.r8.graph.DexProto;
import com.android.tools.r8.graph.DexString;
import com.android.tools.r8.graph.DexType;
import com.android.tools.r8.graph.DexTypeList;
import com.android.tools.r8.graph.MethodAccessFlags;
import com.android.tools.r8.graph.ParameterAnnotationsList;
import com.android.tools.r8.ir.code.IRCode;
import com.android.tools.r8.ir.code.Instruction;
import com.android.tools.r8.ir.code.InstructionIterator;
import com.android.tools.r8.ir.code.InvokeStatic;
import com.android.tools.r8.ir.conversion.IRConverter;
import com.android.tools.r8.ir.desugar.Java8MethodRewriter.RewritableMethods.MethodGenerator;
import com.android.tools.r8.ir.synthetic.TemplateMethodCode;
import com.android.tools.r8.origin.SynthesizedOrigin;
import com.android.tools.r8.utils.DescriptorUtils;
import com.android.tools.r8.utils.InternalOptions;
import com.google.common.collect.Sets;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.function.BiFunction;

public final class Java8MethodRewriter {
  public static final String UTILITY_CLASS_NAME_PREFIX = "$r8$java8methods$utility";
  private static final String UTILITY_CLASS_DESCRIPTOR_PREFIX = "L$r8$java8methods$utility";
  private final Set<DexType> holders = Sets.newConcurrentHashSet();

  private final AppView<?> appView;
  private final IRConverter converter;
  private final DexItemFactory factory;
  private final RewritableMethods rewritableMethods;

  private Map<DexMethod, MethodGenerator> methodGenerators = new ConcurrentHashMap<>();

  public Java8MethodRewriter(AppView<?> appView, IRConverter converter) {
    this.appView = appView;
    this.converter = converter;
    this.factory = appView.dexItemFactory();
    this.rewritableMethods = new RewritableMethods(factory, appView.options());
  }

  public void desugar(IRCode code) {
    if (rewritableMethods.isEmpty()) {
      return; // Nothing to do!
    }

    InstructionIterator iterator = code.instructionIterator();
    while (iterator.hasNext()) {
      Instruction instruction = iterator.next();
      if (!instruction.isInvokeStatic()) {
        continue;
      }
      InvokeStatic invoke = instruction.asInvokeStatic();

      MethodGenerator generator = getMethodGeneratorOrNull(invoke.getInvokedMethod());
      if (generator == null) {
        continue;
      }
      iterator.replaceCurrentInstruction(
            new InvokeStatic(generator.generateMethod(factory),
                invoke.outValue(), invoke.inValues()));
      methodGenerators.putIfAbsent(generator.generateMethod(factory), generator);
      holders.add(code.method.method.holder);
    }
  }

  private Collection<DexProgramClass> findSynthesizedFrom(Builder<?> builder, DexType holder) {
    for (DexProgramClass synthesizedClass : builder.getSynthesizedClasses()) {
      if (holder == synthesizedClass.getType()) {
        return synthesizedClass.getSynthesizedFrom();
      }
    }
    return null;
  }

  public static boolean hasJava8MethodRewritePrefix(DexType clazz) {
    return clazz.descriptor.toString().startsWith(UTILITY_CLASS_DESCRIPTOR_PREFIX);
  }

  public void synthesizeUtilityClass(
      Builder<?> builder, ExecutorService executorService, InternalOptions options)
      throws ExecutionException {
    if (holders.isEmpty()) {
      return;
    }
    Set<DexProgramClass> referencingClasses = Sets.newConcurrentHashSet();
    AppInfo appInfo = appView.appInfo();
    for (DexType holder : holders) {
      DexClass definitionFor = appInfo.definitionFor(holder);
      if (definitionFor == null) {
        Collection<DexProgramClass> synthesizedFrom = findSynthesizedFrom(builder, holder);
        assert synthesizedFrom != null;
        referencingClasses.addAll(synthesizedFrom);
      } else {
        referencingClasses.add(definitionFor.asProgramClass());
      }
    }
    MethodAccessFlags flags = MethodAccessFlags.fromSharedAccessFlags(
        Constants.ACC_PUBLIC | Constants.ACC_STATIC | Constants.ACC_SYNTHETIC, false);
    ClassAccessFlags classAccessFlags =
        ClassAccessFlags.fromSharedAccessFlags(Constants.ACC_PUBLIC | Constants.ACC_SYNTHETIC);

    for (MethodGenerator generator : methodGenerators.values()) {
      DexMethod method = generator.generateMethod(factory);
      TemplateMethodCode code = generator.generateTemplateMethod(options, method);
      DexEncodedMethod dexEncodedMethod= new DexEncodedMethod(method,
          flags, DexAnnotationSet.empty(), ParameterAnnotationsList.empty(), code);
      DexProgramClass utilityClass =
          new DexProgramClass(
              method.holder,
              null,
              new SynthesizedOrigin("java8 methods utility class", getClass()),
              classAccessFlags,
              factory.objectType,
              DexTypeList.empty(),
              null,
              null,
              Collections.emptyList(),
              null,
              Collections.emptyList(),
              DexAnnotationSet.empty(),
              DexEncodedField.EMPTY_ARRAY,
              DexEncodedField.EMPTY_ARRAY,
              new DexEncodedMethod[] {dexEncodedMethod},
              DexEncodedMethod.EMPTY_ARRAY,
              factory.getSkipNameValidationForTesting(),
              referencingClasses);
      code.setUpContext(utilityClass);
      boolean addToMainDexList =
          referencingClasses.stream().anyMatch(clazz -> appInfo.isInMainDexList(clazz.type));
      appInfo.addSynthesizedClass(utilityClass);
      converter.optimizeSynthesizedClass(utilityClass, executorService);
      builder.addSynthesizedClass(utilityClass, addToMainDexList);
    }
  }

  private MethodGenerator getMethodGeneratorOrNull(DexMethod method) {
    DexMethod original = appView.graphLense().getOriginalMethodSignature(method);
    assert original != null;
    return rewritableMethods.getGenerator(
        original.holder.descriptor, original.name, original.proto);
  }

  private static final class ByteMethods extends TemplateMethodCode {
    ByteMethods(InternalOptions options, DexMethod method, String methodName) {
      super(options, method, methodName, method.proto.toDescriptorString());
    }

    public static ByteMethods hashCodeCode(InternalOptions options, DexMethod method) {
      return new ByteMethods(options, method, "hashCodeImpl");
    }

    public static int hashCodeImpl(byte i) {
      return Byte.valueOf(i).hashCode();
    }
  }


  private static final class ShortMethods extends TemplateMethodCode {
    ShortMethods(InternalOptions options, DexMethod method, String methodName) {
      super(options, method, methodName, method.proto.toDescriptorString());
    }

    public static ShortMethods hashCodeCode(InternalOptions options, DexMethod method) {
      return new ShortMethods(options, method, "hashCodeImpl");
    }

    public static int hashCodeImpl(short i) {
      return Short.valueOf(i).hashCode();
    }
  }

  private static final class IntegerMethods extends TemplateMethodCode {
    IntegerMethods(InternalOptions options, DexMethod method, String methodName) {
      super(options, method, methodName, method.proto.toDescriptorString());
    }

    public static IntegerMethods hashCodeCode(InternalOptions options, DexMethod method) {
      return new IntegerMethods(options, method, "hashCodeImpl");
    }

    public static IntegerMethods maxCode(InternalOptions options, DexMethod method) {
      return new IntegerMethods(options, method, "maxImpl");
    }

    public static IntegerMethods minCode(InternalOptions options, DexMethod method) {
      return new IntegerMethods(options, method, "minImpl");
    }

    public static IntegerMethods sumCode(InternalOptions options, DexMethod method) {
      return new IntegerMethods(options, method, "sumImpl");
    }

    public static IntegerMethods divideUnsignedCode(InternalOptions options, DexMethod method) {
      return new IntegerMethods(options, method, "divideUnsignedImpl");
    }

    public static IntegerMethods remainderUnsignedCode(InternalOptions options, DexMethod method) {
      return new IntegerMethods(options, method, "remainderUnsignedImpl");
    }

    public static IntegerMethods compareUnsignedCode(InternalOptions options, DexMethod method) {
      return new IntegerMethods(options, method, "compareUnsignedImpl");
    }

    public static int hashCodeImpl(int i) {
      return Integer.valueOf(i).hashCode();
    }

    public static int maxImpl(int a, int b) {
      return java.lang.Math.max(a, b);
    }

    public static int minImpl(int a, int b) {
      return java.lang.Math.min(a, b);
    }

    public static int sumImpl(int a, int b) {
      return a + b;
    }

    public static int divideUnsignedImpl(int dividend, int divisor) {
      long dividendLong = dividend & 0xffffffffL;
      long divisorLong = divisor & 0xffffffffL;
      return (int) (dividendLong / divisorLong);
    }

    public static int remainderUnsignedImpl(int dividend, int divisor) {
      long dividendLong = dividend & 0xffffffffL;
      long divisorLong = divisor & 0xffffffffL;
      return (int) (dividendLong % divisorLong);
    }

    public static int compareUnsignedImpl(int a, int b) {
      int aFlipped = a ^ Integer.MIN_VALUE;
      int bFlipped = b ^ Integer.MIN_VALUE;
      return (aFlipped < bFlipped) ? -1 : ((aFlipped > bFlipped) ? 1 : 0);
    }
  }

  private static final class DoubleMethods extends TemplateMethodCode {
    DoubleMethods(InternalOptions options, DexMethod method, String methodName) {
      super(options, method, methodName, method.proto.toDescriptorString());
    }

    public static DoubleMethods hashCodeCode(InternalOptions options, DexMethod method) {
      return new DoubleMethods(options, method, "hashCodeImpl");
    }

    public static DoubleMethods maxCode(InternalOptions options, DexMethod method) {
      return new DoubleMethods(options, method, "maxImpl");
    }

    public static DoubleMethods minCode(InternalOptions options, DexMethod method) {
      return new DoubleMethods(options, method, "minImpl");
    }

    public static DoubleMethods sumCode(InternalOptions options, DexMethod method) {
      return new DoubleMethods(options, method, "sumImpl");
    }

    public static DoubleMethods isFiniteCode(InternalOptions options, DexMethod method) {
      return new DoubleMethods(options, method, "isFiniteImpl");
    }

    public static int hashCodeImpl(double d) {
      return Double.valueOf(d).hashCode();
    }

    public static double maxImpl(double a, double b) {
      return java.lang.Math.max(a, b);
    }

    public static double minImpl(double a, double b) {
      return java.lang.Math.min(a, b);
    }

    public static double sumImpl(double a, double b) {
      return a + b;
    }

    public static boolean isFiniteImpl(double d) {
      Double boxed = Double.valueOf(d);
      return !boxed.isInfinite() && !boxed.isNaN();
    }
  }

  private static final class FloatMethods extends TemplateMethodCode {
    FloatMethods(InternalOptions options, DexMethod method, String methodName) {
      super(options, method, methodName, method.proto.toDescriptorString());
    }

    public static FloatMethods hashCodeCode(InternalOptions options, DexMethod method) {
      return new FloatMethods(options, method, "hashCodeImpl");
    }

    public static FloatMethods maxCode(InternalOptions options, DexMethod method) {
      return new FloatMethods(options, method, "maxImpl");
    }

    public static FloatMethods minCode(InternalOptions options, DexMethod method) {
      return new FloatMethods(options, method, "minImpl");
    }

    public static FloatMethods sumCode(InternalOptions options, DexMethod method) {
      return new FloatMethods(options, method, "sumImpl");
    }

    public static FloatMethods isFiniteCode(InternalOptions options, DexMethod method) {
      return new FloatMethods(options, method, "isFiniteImpl");
    }

    public static int hashCodeImpl(float d) {
      return Float.valueOf(d).hashCode();
    }

    public static float maxImpl(float a, float b) {
      return java.lang.Math.max(a, b);
    }

    public static float minImpl(float a, float b) {
      return java.lang.Math.min(a, b);
    }

    public static float sumImpl(float a, float b) {
      return a + b;
    }

    public static boolean isFiniteImpl(float d) {
      Float boxed = Float.valueOf(d);
      return !boxed.isInfinite() && !boxed.isNaN();
    }
  }

  private static final class BooleanMethods extends TemplateMethodCode {
    BooleanMethods(InternalOptions options, DexMethod method, String methodName) {
      super(options, method, methodName, method.proto.toDescriptorString());
    }

    public static BooleanMethods hashCodeCode(InternalOptions options, DexMethod method) {
      return new BooleanMethods(options, method, "hashCodeImpl");
    }

    public static BooleanMethods logicalAndCode(InternalOptions options, DexMethod method) {
      return new BooleanMethods(options, method, "logicalAndImpl");
    }

    public static BooleanMethods logicalOrCode(InternalOptions options, DexMethod method) {
      return new BooleanMethods(options, method, "logicalOrImpl");
    }

    public static BooleanMethods logicalXorCode(InternalOptions options, DexMethod method) {
      return new BooleanMethods(options, method, "logicalXorImpl");
    }

    public static int hashCodeImpl(boolean b) {
      return Boolean.valueOf(b).hashCode();
    }

    public static boolean logicalAndImpl(boolean a, boolean b) {
      return a && b;
    }

    public static boolean logicalOrImpl(boolean a, boolean b) {
      return a || b;
    }

    public static boolean logicalXorImpl(boolean a, boolean b) {
      return a ^ b;
    }
  }

  private static final class LongMethods extends TemplateMethodCode {
    LongMethods(InternalOptions options, DexMethod method, String methodName) {
      super(options, method, methodName, method.proto.toDescriptorString());
    }

    public static LongMethods hashCodeCode(InternalOptions options, DexMethod method) {
      return new LongMethods(options, method, "hashCodeImpl");
    }

    public static LongMethods maxCode(InternalOptions options, DexMethod method) {
      return new LongMethods(options, method, "maxImpl");
    }

    public static LongMethods minCode(InternalOptions options, DexMethod method) {
      return new LongMethods(options, method, "minImpl");
    }

    public static LongMethods sumCode(InternalOptions options, DexMethod method) {
      return new LongMethods(options, method, "sumImpl");
    }

    public static LongMethods divideUnsignedCode(InternalOptions options, DexMethod method) {
      return new LongMethods(options, method, "divideUnsignedImpl");
    }

    public static LongMethods remainderUnsignedCode(InternalOptions options, DexMethod method) {
      return new LongMethods(options, method, "remainderUnsignedImpl");
    }

    public static LongMethods compareUnsignedCode(InternalOptions options, DexMethod method) {
      return new LongMethods(options, method, "compareUnsignedImpl");
    }

    public static int hashCodeImpl(long i) {
      return Long.valueOf(i).hashCode();
    }

    public static long maxImpl(long a, long b) {
      return java.lang.Math.max(a, b);
    }

    public static long minImpl(long a, long b) {
      return java.lang.Math.min(a, b);
    }

    public static long sumImpl(long a, long b) {
      return a + b;
    }

    public static long divideUnsignedImpl(long dividend, long divisor) {
      // This implementation is adapted from Guava's UnsignedLongs.java and Longs.java.

      if (divisor < 0) { // i.e., divisor >= 2^63:
        // Reference implementation calls UnsignedLongs.compare(dividend, divisor) whose
        // implementation is Longs.compare(UnsignedLong.flip(a), UnsignedLong.flip(b)). The
        // implementations of flip() and compare() are inlined here instead.
        long dividendFlipped = dividend ^ Long.MIN_VALUE;
        long divisorFlipped = divisor ^ Long.MIN_VALUE;
        if (dividendFlipped < divisorFlipped) {
          return 0; // dividend < divisor
        } else {
          return 1; // dividend >= divisor
        }
      }

      // Optimization - use signed division if dividend < 2^63
      if (dividend >= 0) {
        return dividend / divisor;
      }

      // Otherwise, approximate the quotient, check, and correct if necessary. Our approximation is
      // guaranteed to be either exact or one less than the correct value. This follows from the
      // fact that floor(floor(x)/i) == floor(x/i) for any real x and integer i != 0. The proof is
      // not quite trivial.
      long quotient = ((dividend >>> 1) / divisor) << 1;
      long rem = dividend - quotient * divisor;

      // Reference implementation calls UnsignedLongs.compare(rem, divisor) whose
      // implementation is Longs.compare(UnsignedLong.flip(a), UnsignedLong.flip(b)). The
      // implementations of flip() and compare() are inlined here instead.
      long remFlipped = rem ^ Long.MIN_VALUE;
      long divisorFlipped = divisor ^ Long.MIN_VALUE;
      return quotient + (remFlipped >= divisorFlipped ? 1 : 0);
    }

    public static long remainderUnsignedImpl(long dividend, long divisor) {
      // This implementation is adapted from Guava's UnsignedLongs.java and Longs.java.

      if (divisor < 0) { // i.e., divisor >= 2^63:
        // Reference implementation calls UnsignedLongs.compare(dividend, divisor) whose
        // implementation is Longs.compare(UnsignedLong.flip(a), UnsignedLong.flip(b)). The
        // implementations of flip() and compare() are inlined here instead.
        long dividendFlipped = dividend ^ Long.MIN_VALUE;
        long divisorFlipped = divisor ^ Long.MIN_VALUE;
        if (dividendFlipped < divisorFlipped) {
          return dividend; // dividend < divisor
        } else {
          return dividend - divisor; // dividend >= divisor
        }
      }

      // Optimization - use signed modulus if dividend < 2^63
      if (dividend >= 0) {
        return dividend % divisor;
      }

      // Otherwise, approximate the quotient, check, and correct if necessary. Our approximation is
      // guaranteed to be either exact or one less than the correct value. This follows from the
      // fact that floor(floor(x)/i) == floor(x/i) for any real x and integer i != 0. The proof is
      // not quite trivial.
      long quotient = ((dividend >>> 1) / divisor) << 1;
      long rem = dividend - quotient * divisor;

      // Reference implementation calls UnsignedLongs.compare(rem, divisor) whose
      // implementation is Longs.compare(UnsignedLong.flip(a), UnsignedLong.flip(b)). The
      // implementations of flip() and compare() are inlined here instead.
      long remFlipped = rem ^ Long.MIN_VALUE;
      long divisorFlipped = divisor ^ Long.MIN_VALUE;
      return rem - (remFlipped >= divisorFlipped ? divisor : 0);
    }

    public static int compareUnsignedImpl(long a, long b) {
      long aFlipped = a ^ Long.MIN_VALUE;
      long bFlipped = b ^ Long.MIN_VALUE;
      return (aFlipped < bFlipped) ? -1 : ((aFlipped > bFlipped) ? 1 : 0);
    }
  }

  private static final class CharacterMethods extends TemplateMethodCode {
    CharacterMethods(InternalOptions options, DexMethod method, String methodName) {
      super(options, method, methodName, method.proto.toDescriptorString());
    }

    public static CharacterMethods hashCodeCode(InternalOptions options, DexMethod method) {
      return new CharacterMethods(options, method, "hashCodeImpl");
    }

    public static int hashCodeImpl(char i) {
      return Character.valueOf(i).hashCode();
    }
  }

  public static final class RewritableMethods {
    // Map class, method, proto to a generator for creating the code and method.
    private final Map<DexString, Map<DexString, Map<DexProto, MethodGenerator>>> rewritable =
        new HashMap<>();

    public RewritableMethods(DexItemFactory factory, InternalOptions options) {
      if (!options.canUseJava8SignedOperations()) {
        initializeJava8SignedOperations(factory);
      }
      if (!options.canUseJava8UnsignedOperations()) {
        initializeJava8UnsignedOperations(factory);
      }
    }

    boolean isEmpty() {
      return rewritable.isEmpty();
    }

    private void initializeJava8SignedOperations(DexItemFactory factory) {
      // Byte
      DexString clazz = factory.boxedByteDescriptor;
      // int Byte.hashCode(byte i)
      DexString method = factory.createString("hashCode");
      DexProto proto = factory.createProto(factory.intType, factory.byteType);
      addOrGetMethod(clazz, method)
          .put(proto, new MethodGenerator(ByteMethods::hashCodeCode, clazz, method, proto));

      // Short
      clazz = factory.boxedShortDescriptor;
      // int Short.hashCode(short i)
      method = factory.createString("hashCode");
      proto = factory.createProto(factory.intType, factory.shortType);
      addOrGetMethod(clazz, method)
          .put(proto, new MethodGenerator(ShortMethods::hashCodeCode, clazz, method, proto));

      // Integer
      clazz = factory.boxedIntDescriptor;

      // int Integer.hashCode(int i)
      method = factory.createString("hashCode");
      proto = factory.createProto(factory.intType, factory.intType);
      addOrGetMethod(clazz, method)
          .put(proto, new MethodGenerator(IntegerMethods::hashCodeCode, clazz, method, proto));

      // int Integer.max(int a, int b)
      method = factory.createString("max");
      proto = factory.createProto(factory.intType, factory.intType, factory.intType);
      addOrGetMethod(clazz, method)
          .put(proto, new MethodGenerator(IntegerMethods::maxCode, clazz, method, proto));

      // int Integer.min(int a, int b)
      method = factory.createString("min");
      proto = factory.createProto(factory.intType, factory.intType, factory.intType);
      addOrGetMethod(clazz, method)
          .put(proto, new MethodGenerator(IntegerMethods::minCode, clazz, method, proto));

      // int Integer.sum(int a, int b)
      method = factory.createString("sum");
      proto = factory.createProto(factory.intType, factory.intType, factory.intType);
      addOrGetMethod(clazz, method)
          .put(proto, new MethodGenerator(IntegerMethods::sumCode, clazz, method, proto));

      // Double
      clazz = factory.boxedDoubleDescriptor;

      // int Double.hashCode(double d)
      method = factory.createString("hashCode");
      proto = factory.createProto(factory.intType, factory.doubleType);
      addOrGetMethod(clazz, method)
          .put(proto, new MethodGenerator(DoubleMethods::hashCodeCode, clazz, method, proto));

      // double Double.max(double a, double b)
      method = factory.createString("max");
      proto = factory.createProto(factory.doubleType, factory.doubleType, factory.doubleType);
      addOrGetMethod(clazz, method)
          .put(proto, new MethodGenerator(DoubleMethods::maxCode, clazz, method, proto));

      // double Double.min(double a, double b)
      method = factory.createString("min");
      proto = factory.createProto(factory.doubleType, factory.doubleType, factory.doubleType);
      addOrGetMethod(clazz, method)
          .put(proto, new MethodGenerator(DoubleMethods::minCode, clazz, method, proto));

      // double Double.sum(double a, double b)
      method = factory.createString("sum");
      proto = factory.createProto(factory.doubleType, factory.doubleType, factory.doubleType);
      addOrGetMethod(clazz, method)
          .put(proto, new MethodGenerator(DoubleMethods::sumCode, clazz, method, proto));

      // boolean Double.isFinite(double a)
      method = factory.createString("isFinite");
      proto = factory.createProto(factory.booleanType, factory.doubleType);
      addOrGetMethod(clazz, method)
          .put(proto, new MethodGenerator(DoubleMethods::isFiniteCode, clazz, method, proto));

      // Float
      clazz = factory.boxedFloatDescriptor;

      // int Float.hashCode(float d)
      method = factory.createString("hashCode");
      proto = factory.createProto(factory.intType, factory.floatType);
      addOrGetMethod(clazz, method)
          .put(proto, new MethodGenerator(FloatMethods::hashCodeCode, clazz, method, proto));

      // float Float.max(float a, float b)
      method = factory.createString("max");
      proto = factory.createProto(factory.floatType, factory.floatType, factory.floatType);
      addOrGetMethod(clazz, method)
          .put(proto, new MethodGenerator(FloatMethods::maxCode, clazz, method, proto));

      // float Float.min(float a, float b)
      method = factory.createString("min");
      proto = factory.createProto(factory.floatType, factory.floatType, factory.floatType);
      addOrGetMethod(clazz, method)
          .put(proto, new MethodGenerator(FloatMethods::minCode, clazz, method, proto));

      // float Float.sum(float a, float b)
      method = factory.createString("sum");
      proto = factory.createProto(factory.floatType, factory.floatType, factory.floatType);
      addOrGetMethod(clazz, method)
          .put(proto, new MethodGenerator(FloatMethods::sumCode, clazz, method, proto));

      // boolean Float.isFinite(float a)
      method = factory.createString("isFinite");
      proto = factory.createProto(factory.booleanType, factory.floatType);
      addOrGetMethod(clazz, method)
          .put(proto, new MethodGenerator(FloatMethods::isFiniteCode, clazz, method, proto));

      // Boolean
      clazz = factory.boxedBooleanDescriptor;

      // int Boolean.hashCode(boolean b)
      method = factory.createString("hashCode");
      proto = factory.createProto(factory.intType, factory.booleanType);
      addOrGetMethod(clazz, method)
          .put(proto, new MethodGenerator(BooleanMethods::hashCodeCode, clazz, method, proto));

      // boolean Boolean.logicalAnd(boolean a, boolean b)
      method = factory.createString("logicalAnd");
      proto = factory.createProto(factory.booleanType, factory.booleanType, factory.booleanType);
      addOrGetMethod(clazz, method)
          .put(proto, new MethodGenerator(BooleanMethods::logicalAndCode, clazz, method, proto));

      // boolean Boolean.logicalOr(boolean a, boolean b)
      method = factory.createString("logicalOr");
      proto = factory.createProto(factory.booleanType, factory.booleanType, factory.booleanType);
      addOrGetMethod(clazz, method)
          .put(proto, new MethodGenerator(BooleanMethods::logicalOrCode, clazz, method, proto));

      // boolean Boolean.logicalXor(boolean a, boolean b)
      method = factory.createString("logicalXor");
      proto = factory.createProto(factory.booleanType, factory.booleanType, factory.booleanType);
      addOrGetMethod(clazz, method)
          .put(proto, new MethodGenerator(BooleanMethods::logicalXorCode, clazz, method, proto));

      // Long
      clazz = factory.boxedLongDescriptor;

      // int Long.hashCode(long i)
      method = factory.createString("hashCode");
      proto = factory.createProto(factory.intType, factory.longType);
      addOrGetMethod(clazz, method)
          .put(proto, new MethodGenerator(LongMethods::hashCodeCode, clazz, method, proto));

      // long Long.max(long a, long b)
      method = factory.createString("max");
      proto = factory.createProto(factory.longType, factory.longType, factory.longType);
      addOrGetMethod(clazz, method)
          .put(proto, new MethodGenerator(LongMethods::maxCode, clazz, method, proto));

      // long Long.min(long a, long b)
      method = factory.createString("min");
      proto = factory.createProto(factory.longType, factory.longType, factory.longType);
      addOrGetMethod(clazz, method)
          .put(proto, new MethodGenerator(LongMethods::minCode, clazz, method, proto));

      // long Long.sum(long a, long b)
      method = factory.createString("sum");
      proto = factory.createProto(factory.longType, factory.longType, factory.longType);
      addOrGetMethod(clazz, method)
          .put(proto, new MethodGenerator(LongMethods::sumCode, clazz, method, proto));

      // Character
      clazz = factory.boxedCharDescriptor;

      // int Character.hashCode(char i)
      method = factory.createString("hashCode");
      proto = factory.createProto(factory.intType, factory.charType);
      addOrGetMethod(clazz, method)
          .put(proto, new MethodGenerator(CharacterMethods::hashCodeCode, clazz, method, proto));
    }

    private void initializeJava8UnsignedOperations(DexItemFactory factory) {
      DexString clazz = factory.boxedIntDescriptor;

      // int Integer.divideUnsigned(int a, int b)
      DexString method = factory.createString("divideUnsigned");
      DexProto proto = factory.createProto(factory.intType, factory.intType, factory.intType);
      addOrGetMethod(clazz, method).put(proto,
          new MethodGenerator(IntegerMethods::divideUnsignedCode, clazz, method, proto));

      // int Integer.remainderUnsigned(int a, int b)
      method = factory.createString("remainderUnsigned");
      proto = factory.createProto(factory.intType, factory.intType, factory.intType);
      addOrGetMethod(clazz, method).put(proto,
          new MethodGenerator(IntegerMethods::remainderUnsignedCode, clazz, method, proto));

      // int Integer.compareUnsigned(int a, int b)
      method = factory.createString("compareUnsigned");
      proto = factory.createProto(factory.intType, factory.intType, factory.intType);
      addOrGetMethod(clazz, method).put(proto,
          new MethodGenerator(IntegerMethods::compareUnsignedCode, clazz, method, proto));

      clazz = factory.boxedLongDescriptor;

      // long Long.divideUnsigned(long a, long b)
      method = factory.createString("divideUnsigned");
      proto = factory.createProto(factory.longType, factory.longType, factory.longType);
      addOrGetMethod(clazz, method).put(proto,
          new MethodGenerator(LongMethods::divideUnsignedCode, clazz, method, proto));

      // long Long.remainderUnsigned(long a, long b)
      method = factory.createString("remainderUnsigned");
      proto = factory.createProto(factory.longType, factory.longType, factory.longType);
      addOrGetMethod(clazz, method).put(proto,
          new MethodGenerator(LongMethods::remainderUnsignedCode, clazz, method, proto));

      // int Long.compareUnsigned(long a, long b)
      method = factory.createString("compareUnsigned");
      proto = factory.createProto(factory.intType, factory.longType, factory.longType);
      addOrGetMethod(clazz, method).put(proto,
          new MethodGenerator(LongMethods::compareUnsignedCode, clazz, method, proto));
    }

    private Map<DexString, Map<DexProto, MethodGenerator>> addOrGetClass(DexString clazz) {
      return rewritable.computeIfAbsent(clazz, k -> new HashMap<>());
    }

    private Map<DexProto, MethodGenerator> addOrGetMethod(
        DexString clazz, DexString method) {
      return addOrGetClass(clazz).computeIfAbsent(method, k -> new HashMap<>());
    }

    public MethodGenerator getGenerator(DexString clazz, DexString method, DexProto proto) {
      Map<DexString, Map<DexProto, MethodGenerator>> classMap = rewritable.get(clazz);
      if (classMap != null) {
        Map<DexProto, MethodGenerator> methodMap = classMap.get(method);
        if (methodMap != null) {
          return methodMap.get(proto);
        }
      }
      return null;
    }

    public static class MethodGenerator {
      private final BiFunction<InternalOptions, DexMethod, TemplateMethodCode> generator;
      private final DexString clazz;
      private final DexString method;
      private final DexProto proto;
      private DexMethod dexMethod;

      public MethodGenerator(
          BiFunction<InternalOptions, DexMethod, TemplateMethodCode> generator,
          DexString clazz, DexString method, DexProto proto) {
        this.generator = generator;
        this.clazz = clazz;
        this.method = method;
        this.proto = proto;
      }

      public DexMethod generateMethod(DexItemFactory factory) {
        if (dexMethod != null) {
          return dexMethod;
        }
        String unqualifiedName =
            DescriptorUtils.getUnqualifiedClassNameFromDescriptor(clazz.toString());
        String postFix = "$" + unqualifiedName + "$" + method + "$" + proto.shorty.toString();
        DexType clazz = factory.createType(UTILITY_CLASS_DESCRIPTOR_PREFIX + postFix + ";");
        dexMethod = factory.createMethod(clazz, proto, method);
        return dexMethod;
      }

      public TemplateMethodCode generateTemplateMethod(InternalOptions options, DexMethod method) {
        return generator.apply(options, method);
      }
    }
  }
}
