// 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.ir.optimize.library;

import com.android.tools.r8.graph.AppView;
import com.android.tools.r8.graph.DexItemFactory;
import com.android.tools.r8.graph.DexMethod;
import com.android.tools.r8.graph.LibraryMethod;
import com.android.tools.r8.ir.code.InvokeMethod;
import com.android.tools.r8.ir.code.Value;
import com.android.tools.r8.ir.optimize.library.sideeffects.JavaLangObjectsSideEffectCollection;
import com.android.tools.r8.utils.BiPredicateUtils;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.function.BiPredicate;
import java.util.function.Consumer;

public class LibraryMethodSideEffectModelCollection {

  private final Map<DexMethod, BiPredicate<DexMethod, List<Value>>> finalMethodsWithoutSideEffects;
  private final Set<DexMethod> unconditionalFinalMethodsWithoutSideEffects;

  private final Set<DexMethod> nonFinalMethodsWithoutSideEffects;

  public LibraryMethodSideEffectModelCollection(AppView<?> appView) {
    DexItemFactory dexItemFactory = appView.dexItemFactory();
    finalMethodsWithoutSideEffects = buildFinalMethodsWithoutSideEffects(appView, dexItemFactory);
    unconditionalFinalMethodsWithoutSideEffects =
        buildUnconditionalFinalMethodsWithoutSideEffects(dexItemFactory);
    nonFinalMethodsWithoutSideEffects = buildNonFinalMethodsWithoutSideEffects(dexItemFactory);
  }

  private static Map<DexMethod, BiPredicate<DexMethod, List<Value>>>
      buildFinalMethodsWithoutSideEffects(AppView<?> appView, DexItemFactory dexItemFactory) {
    ImmutableMap.Builder<DexMethod, BiPredicate<DexMethod, List<Value>>> builder =
        ImmutableMap.<DexMethod, BiPredicate<DexMethod, List<Value>>>builder()
            .put(
                dexItemFactory.byteMembers.byteValue,
                (method, arguments) -> arguments.get(0).isNeverNull())
            .put(
                dexItemFactory.objectsMethods.toStringWithObject,
                (method, arguments) ->
                    !JavaLangObjectsSideEffectCollection.toStringMayHaveSideEffects(
                        appView, arguments))
            .put(
                dexItemFactory.stringMembers.constructor,
                (method, arguments) -> arguments.get(1).isNeverNull())
            .put(
                dexItemFactory.stringMembers.valueOf,
                (method, arguments) ->
                    !JavaLangObjectsSideEffectCollection.toStringMayHaveSideEffects(
                        appView, arguments));
    putAll(
        builder,
        dexItemFactory.stringBufferMethods.constructorMethods,
        dexItemFactory.stringBufferMethods::constructorInvokeIsSideEffectFree);
    putAll(
        builder,
        dexItemFactory.stringBuilderMethods.constructorMethods,
        dexItemFactory.stringBuilderMethods::constructorInvokeIsSideEffectFree);
    return builder.build();
  }

  private static Set<DexMethod> buildUnconditionalFinalMethodsWithoutSideEffects(
      DexItemFactory dexItemFactory) {
    return ImmutableSet.<DexMethod>builder()
        .add(dexItemFactory.booleanMembers.toString)
        .add(dexItemFactory.byteMembers.toString)
        .add(dexItemFactory.byteMembers.valueOf)
        .add(dexItemFactory.classMethods.desiredAssertionStatus)
        .add(dexItemFactory.charMembers.toString)
        .add(dexItemFactory.doubleMembers.toString)
        .add(dexItemFactory.enumMembers.constructor)
        .add(dexItemFactory.floatMembers.toString)
        .add(dexItemFactory.integerMembers.toString)
        .add(dexItemFactory.longMembers.toString)
        .add(dexItemFactory.npeMethods.init)
        .add(dexItemFactory.npeMethods.initWithMessage)
        .add(dexItemFactory.recordMembers.constructor)
        .add(dexItemFactory.objectMembers.constructor)
        .add(dexItemFactory.objectMembers.getClass)
        .add(dexItemFactory.shortMembers.toString)
        .add(dexItemFactory.stringBufferMethods.toString)
        .add(dexItemFactory.stringBuilderMethods.toString)
        .add(dexItemFactory.stringMembers.length)
        .add(dexItemFactory.stringMembers.hashCode)
        .add(dexItemFactory.stringMembers.isEmpty)
        .add(dexItemFactory.stringMembers.toString)
        .add(dexItemFactory.stringMembers.trim)
        .addAll(dexItemFactory.classMethods.getNames)
        .addAll(dexItemFactory.boxedValueOfMethods())
        .build();
  }

  private static Set<DexMethod> buildNonFinalMethodsWithoutSideEffects(
      DexItemFactory dexItemFactory) {
    return ImmutableSet.of(
        dexItemFactory.objectMembers.equals,
        dexItemFactory.objectMembers.hashCode,
        dexItemFactory.objectMembers.toString);
  }

  private static <K, V> void putAll(ImmutableMap.Builder<K, V> builder, Iterable<K> keys, V value) {
    for (K key : keys) {
      builder.put(key, value);
    }
  }

  public void forEachSideEffectFreeFinalMethod(Consumer<DexMethod> consumer) {
    unconditionalFinalMethodsWithoutSideEffects.forEach(consumer);
  }

  public boolean isCallToSideEffectFreeFinalMethod(InvokeMethod invoke) {
    return isSideEffectFreeFinalMethod(invoke.getInvokedMethod(), invoke.arguments());
  }

  public boolean isSideEffectFreeFinalMethod(DexMethod method, List<Value> arguments) {
    return unconditionalFinalMethodsWithoutSideEffects.contains(method)
        || finalMethodsWithoutSideEffects
            .getOrDefault(method, BiPredicateUtils.alwaysFalse())
            .test(method, arguments);
  }

  // This intentionally takes the invoke instruction since the determination of whether a library
  // method has side effects may depend on the arguments.
  public boolean isSideEffectFree(InvokeMethod invoke, LibraryMethod singleTarget) {
    return isSideEffectFreeFinalMethod(singleTarget.getReference(), invoke.arguments())
        || nonFinalMethodsWithoutSideEffects.contains(singleTarget.getReference());
  }
}
