// 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.regress.b111250398;

import static com.android.tools.r8.utils.codeinspector.Matchers.isPresent;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.junit.Assert.assertEquals;

import com.android.tools.r8.TestBase;
import com.android.tools.r8.code.Iget;
import com.android.tools.r8.code.IgetObject;
import com.android.tools.r8.code.Sget;
import com.android.tools.r8.graph.DexCode;
import com.android.tools.r8.graph.DexField;
import com.android.tools.r8.utils.AndroidApp;
import com.android.tools.r8.utils.InternalOptions;
import com.android.tools.r8.utils.codeinspector.ClassSubject;
import com.android.tools.r8.utils.codeinspector.CodeInspector;
import com.android.tools.r8.utils.codeinspector.FieldSubject;
import com.android.tools.r8.utils.codeinspector.MethodSubject;
import com.google.common.collect.ImmutableList;
import java.util.Arrays;
import org.junit.Test;

// Copy of javax.inject.Provider.
interface Provider<T> {
  T get();
}

// Copy of dagger.internal.SingleClass.
final class SingleCheck<T> implements Provider<T> {
  private static final Object UNINITIALIZED = new Object();

  private volatile Provider<T> provider;
  private volatile Object instance = UNINITIALIZED;

  private SingleCheck(Provider<T> provider) {
    assert provider != null;
    this.provider = provider;
  }

  @SuppressWarnings("unchecked") // cast only happens when result comes from the delegate provider
  @Override
  public T get() {
    Object local = instance;
    if (local == UNINITIALIZED) {
      // provider is volatile and might become null after the check, so retrieve the provider first
      Provider<T> providerReference = provider;
      if (providerReference == null) {
        // The provider was null, so the instance must already be set
        local = instance;
      } else {
        local = providerReference.get();
        instance = local;

        // Null out the reference to the provider. We are never going to need it again, so we can
        // make it eligible for GC.
        provider = null;
      }
    }
    return (T) local;
  }

  // This method is not relevant for the test.
  /*
  public static <P extends Provider<T>, T> Provider<T> provider(P provider) {
    // If a scoped @Binds delegates to a scoped binding, don't cache the value again.
    if (provider instanceof SingleCheck || provider instanceof DoubleCheck) {
      return provider;
    }
    return new SingleCheck<T>(checkNotNull(provider));
  }
  */
}

// Several field gets on non-volatile and volatile fields on the same class.
class A {
  int t;
  int f;
  static int sf;
  volatile int v;
  static volatile int sv;

  public void mf() {
    t = f;
    t = f;
    t = f;
    t = f;
    t = f;
  }

  public void mfWithMonitor() {
    t = f;
    synchronized (this) {
      t = f;
      t = f;
    }
    t = f;
    t = f;
  }

  public void msf() {
    t = sf;
    t = sf;
    t = sf;
    t = sf;
    t = sf;
  }

  public void mv() {
    t = v;
    t = v;
    t = v;
    t = v;
    t = v;
  }

  public void msv() {
    t = sv;
    t = sv;
    t = sv;
    t = sv;
    t = sv;
  }
}

// Several field gets on non-volatile and volatile fields on different class.
class B {
  int t;

  public void mf(A a) {
    t = a.f;
    t = a.f;
    t = a.f;
    t = a.f;
    t = a.f;
  }

  public void msf() {
    t = A.sf;
    t = A.sf;
    t = A.sf;
    t = A.sf;
    t = A.sf;
  }

  public void mv(A a) {
    t = a.v;
    t = a.v;
    t = a.v;
    t = a.v;
    t = a.v;
  }

  public void msv() {
    t = A.sv;
    t = A.sv;
    t = A.sv;
    t = A.sv;
    t = A.sv;
  }
}

// Modified sample from http://tutorials.jenkov.com/java-concurrency/volatile.html.
class C {
  private int years;
  private int months;
  private volatile int days;

  public int totalDays() {
    int total = this.days;
    total += months * 30;
    total += years * 365;
    return total;
  }

  public int totalDaysTimes2() {
    int total = this.days;
    total += months * 30;
    total += years * 365;
    total += this.days;
    total += months * 30;
    total += years * 365;
    return total;
  }

  public int totalDaysTimes3() {
    int total = this.days;
    total += months * 30;
    total += years * 365;
    total += this.days;
    total += months * 30;
    total += years * 365;
    total += this.days;
    total += months * 30;
    total += years * 365;
    return total;
  }

  public void update(int years, int months, int days){
    this.years  = years;
    this.months = months;
    this.days   = days;
  }
}

public class B111250398 extends TestBase {

  private void releaseMode(InternalOptions options) {
    options.debug = false;
  }

  private long countIget(DexCode code, DexField field) {
    return Arrays.stream(code.instructions)
        .filter(instruction -> instruction instanceof Iget)
        .map(instruction -> (Iget) instruction)
        .filter(get -> get.getField() == field)
        .count();
  }

  private long countSget(DexCode code, DexField field) {
    return Arrays.stream(code.instructions)
        .filter(instruction -> instruction instanceof Sget)
        .map(instruction -> (Sget) instruction)
        .filter(get -> get.getField() == field)
        .count();
  }

  private long countIgetObject(MethodSubject method, FieldSubject field) {
    return Arrays.stream(method.getMethod().getCode().asDexCode().instructions)
        .filter(instruction -> instruction instanceof IgetObject)
        .map(instruction -> (IgetObject) instruction)
        .filter(get -> get.getField() == field.getField().field)
        .count();
  }

  private void check(CodeInspector inspector, int mfOnBGets, int msfOnBGets) {
    ClassSubject classA = inspector.clazz(A.class);
    assertThat(classA, isPresent());
    MethodSubject mfOnA = classA.method("void", "mf", ImmutableList.of());
    assertThat(mfOnA, isPresent());
    MethodSubject mfWithMonitorOnA = classA.method("void", "mfWithMonitor", ImmutableList.of());
    assertThat(mfWithMonitorOnA, isPresent());
    MethodSubject msfOnA = classA.method("void", "msf", ImmutableList.of());
    assertThat(msfOnA, isPresent());
    MethodSubject mvOnA = classA.method("void", "mv", ImmutableList.of());
    assertThat(mvOnA, isPresent());
    MethodSubject msvOnA = classA.method("void", "msv", ImmutableList.of());
    assertThat(msvOnA, isPresent());
    FieldSubject fOnA = classA.field("int", "f");
    assertThat(fOnA, isPresent());
    FieldSubject sfOnA = classA.field("int", "sf");
    assertThat(sfOnA, isPresent());
    FieldSubject vOnA = classA.field("int", "v");
    assertThat(vOnA, isPresent());
    FieldSubject svOnA = classA.field("int", "sv");
    assertThat(svOnA, isPresent());
    ClassSubject classB = inspector.clazz(B.class);
    assertThat(classB, isPresent());
    MethodSubject mfOnB = classB.method("void", "mf", ImmutableList.of(classA.getOriginalName()));
    assertThat(mfOnB, isPresent());
    MethodSubject msfOnB = classB.method("void", "msf", ImmutableList.of());
    assertThat(msfOnB, isPresent());
    MethodSubject mvOnB = classB.method("void", "mv", ImmutableList.of(classA.getOriginalName()));
    assertThat(mvOnB, isPresent());
    MethodSubject msvOnB = classB.method("void", "msv", ImmutableList.of());
    assertThat(msvOnB, isPresent());
    // Field load of volatile fields are never eliminated.
    assertEquals(5, countIget(mvOnA.getMethod().getCode().asDexCode(), vOnA.getField().field));
    assertEquals(5, countSget(msvOnA.getMethod().getCode().asDexCode(), svOnA.getField().field));
    assertEquals(5, countIget(mvOnB.getMethod().getCode().asDexCode(), vOnA.getField().field));
    assertEquals(5, countSget(msvOnB.getMethod().getCode().asDexCode(), svOnA.getField().field));
    // For fields on the same class both separate compilation (D8) and whole program
    // compilation (R8) will eliminate field loads on non-volatile fields.
    assertEquals(1, countIget(mfOnA.getMethod().getCode().asDexCode(), fOnA.getField().field));
    assertEquals(1, countSget(msfOnA.getMethod().getCode().asDexCode(), sfOnA.getField().field));
    // TODO(111380066). This could be 2 in stead of 4, but right now the optimization tracks the
    // combined set of fields for all successors, and for synchronized code all blocks have
    // exceptional edges for ensuring monitor exit causing the active load to be invalidated for
    // both normal and exceptional successors.
    assertEquals(4,
        countIget(mfWithMonitorOnA.getMethod().getCode().asDexCode(), fOnA.getField().field));

    // For fields on other class both separate compilation (D8) and whole program
    // compilation (R8) will differ in the eliminated field loads of non-volatile fields.
    assertEquals(mfOnBGets,
        countIget(mfOnB.getMethod().getCode().asDexCode(), fOnA.getField().field));
    assertEquals(msfOnBGets,
        countSget(msfOnB.getMethod().getCode().asDexCode(), sfOnA.getField().field));
  }

  @Test
  public void testSeparateCompilation() throws Exception {
    CodeInspector inspector =
        new CodeInspector(compileWithD8(readClasses(A.class, B.class), this::releaseMode));
    check(inspector, 5, 5);
  }

  @Test
  public void testWholeProgram() throws Exception {
    CodeInspector inspector =
        new CodeInspector(compileWithR8(readClasses(A.class, B.class), this::releaseMode));
    check(inspector, 1, 1);
  }

  private void checkMixed(AndroidApp app) throws Exception{
    CodeInspector inspector = new CodeInspector(app);
    ClassSubject classC = inspector.clazz(C.class);
    assertThat(classC, isPresent());
    MethodSubject totalDays = classC.method("int", "totalDays", ImmutableList.of());
    assertThat(totalDays, isPresent());
    MethodSubject totalDaysTimes2 = classC.method("int", "totalDaysTimes2", ImmutableList.of());
    assertThat(totalDaysTimes2, isPresent());
    MethodSubject totalDaysTimes3 = classC.method("int", "totalDaysTimes3", ImmutableList.of());
    assertThat(totalDaysTimes3, isPresent());
    FieldSubject years = classC.field("int", "years");
    assertThat(years, isPresent());
    FieldSubject months = classC.field("int", "months");
    assertThat(months, isPresent());
    FieldSubject days = classC.field("int", "days");
    assertThat(days, isPresent());


    for (FieldSubject field : new FieldSubject[]{years, months, days}) {
      assertEquals(1,
          countIget(totalDays.getMethod().getCode().asDexCode(), field.getField().field));
      assertEquals(2,
          countIget(totalDaysTimes2.getMethod().getCode().asDexCode(), field.getField().field));
      assertEquals(3,
          countIget(totalDaysTimes3.getMethod().getCode().asDexCode(), field.getField().field));
    }
  }

  @Test
  public void testMixedVolatileNonVolatile() throws Exception {
    AndroidApp app = readClasses(C.class);
    checkMixed(compileWithD8(app, this::releaseMode));
    checkMixed(compileWithR8(app, this::releaseMode));
  }

  private void checkDaggerSingleProviderGet(AndroidApp app) throws Exception {
    CodeInspector inspector = new CodeInspector(app);
    MethodSubject get =
        inspector.clazz(SingleCheck.class).method("java.lang.Object", "get", ImmutableList.of());
    assertThat(get, isPresent());
    FieldSubject instance =
        inspector.clazz(SingleCheck.class).field("java.lang.Object", "instance");
    assertEquals(2, countIgetObject(get, instance));
  }

  @Test
  public void testDaggerSingleProvider() throws Exception {
    AndroidApp app = readClasses(Provider.class, SingleCheck.class);
    checkDaggerSingleProviderGet(compileWithD8(app, this::releaseMode));
    checkDaggerSingleProviderGet(compileWithR8(app, this::releaseMode));
  }
}
