/*
 * Copyright (C) 2015 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

public class Main {

  static boolean doThrow = false;

  /*
   * Ensure an inlined static invoke explicitly triggers the
   * initialization check of the called method's declaring class, and
   * that the corresponding load class instruction does not get
   * removed before register allocation & code generation.
   */

  /// CHECK-START: void Main.invokeStaticInlined() builder (after)
  /// CHECK-DAG:     <<LoadClass:l\d+>>    LoadClass gen_clinit_check:false
  /// CHECK-DAG:     <<ClinitCheck:l\d+>>  ClinitCheck [<<LoadClass>>]
  /// CHECK-DAG:                           InvokeStaticOrDirect [{{[ij]\d+}},<<ClinitCheck>>]

  /// CHECK-START: void Main.invokeStaticInlined() inliner (after)
  /// CHECK-DAG:     <<LoadClass:l\d+>>    LoadClass gen_clinit_check:false
  /// CHECK-DAG:     <<ClinitCheck:l\d+>>  ClinitCheck [<<LoadClass>>]

  /// CHECK-START: void Main.invokeStaticInlined() inliner (after)
  /// CHECK-NOT:                           InvokeStaticOrDirect

  // The following checks ensure the clinit check instruction added by
  // the builder is pruned by the PrepareForRegisterAllocation, while
  // the load class instruction is preserved.  As the control flow
  // graph is not dumped after (nor before) this step, we check the
  // CFG as it is before the next pass (liveness analysis) instead.

  /// CHECK-START: void Main.invokeStaticInlined() liveness (before)
  /// CHECK-DAG:                           LoadClass gen_clinit_check:true

  /// CHECK-START: void Main.invokeStaticInlined() liveness (before)
  /// CHECK-NOT:                           ClinitCheck
  /// CHECK-NOT:                           InvokeStaticOrDirect

  static void invokeStaticInlined() {
    ClassWithClinit1.$opt$inline$StaticMethod();
  }

  static class ClassWithClinit1 {
    static {
      System.out.println("Main$ClassWithClinit1's static initializer");
    }

    static void $opt$inline$StaticMethod() {
    }
  }

  /*
   * Ensure a non-inlined static invoke eventually has an implicit
   * initialization check of the called method's declaring class.
   */

  /// CHECK-START: void Main.invokeStaticNotInlined() builder (after)
  /// CHECK:         <<LoadClass:l\d+>>    LoadClass gen_clinit_check:false
  /// CHECK:         <<ClinitCheck:l\d+>>  ClinitCheck [<<LoadClass>>]
  /// CHECK:                               InvokeStaticOrDirect [{{[ij]\d+}},<<ClinitCheck>>]

  /// CHECK-START: void Main.invokeStaticNotInlined() inliner (after)
  /// CHECK:         <<LoadClass:l\d+>>    LoadClass gen_clinit_check:false
  /// CHECK:         <<ClinitCheck:l\d+>>  ClinitCheck [<<LoadClass>>]
  /// CHECK:                               InvokeStaticOrDirect [{{([ij]\d+,)?}}<<ClinitCheck>>]

  // The following checks ensure the clinit check and load class
  // instructions added by the builder are pruned by the
  // PrepareForRegisterAllocation.  As the control flow graph is not
  // dumped after (nor before) this step, we check the CFG as it is
  // before the next pass (liveness analysis) instead.

  /// CHECK-START: void Main.invokeStaticNotInlined() liveness (before)
  /// CHECK:                               InvokeStaticOrDirect clinit_check:implicit

  /// CHECK-START: void Main.invokeStaticNotInlined() liveness (before)
  /// CHECK-NOT:                           LoadClass
  /// CHECK-NOT:                           ClinitCheck

  static void invokeStaticNotInlined() {
    ClassWithClinit2.$noinline$staticMethod();
  }

  static class ClassWithClinit2 {
    static {
      System.out.println("Main$ClassWithClinit2's static initializer");
    }

    static boolean doThrow = false;

    static void $noinline$staticMethod() {
      if (doThrow) {
        // Try defeating inlining.
        throw new Error();
      }
    }
  }

  /*
   * Ensure an inlined call to a static method whose declaring class
   * is statically known to have been initialized does not require an
   * explicit clinit check.
   */

  /// CHECK-START: void Main$ClassWithClinit3.invokeStaticInlined() builder (after)
  /// CHECK-DAG:                           InvokeStaticOrDirect

  /// CHECK-START: void Main$ClassWithClinit3.invokeStaticInlined() builder (after)
  /// CHECK-NOT:                           LoadClass
  /// CHECK-NOT:                           ClinitCheck

  /// CHECK-START: void Main$ClassWithClinit3.invokeStaticInlined() inliner (after)
  /// CHECK-NOT:                           LoadClass
  /// CHECK-NOT:                           ClinitCheck
  /// CHECK-NOT:                           InvokeStaticOrDirect

  static class ClassWithClinit3 {
    static void invokeStaticInlined() {
      // The invocation of invokeStaticInlined triggers the
      // initialization of ClassWithClinit3, meaning that the
      // hereinbelow call to $opt$inline$StaticMethod does not need a
      // clinit check.
      $opt$inline$StaticMethod();
    }

    static {
      System.out.println("Main$ClassWithClinit3's static initializer");
    }

    static void $opt$inline$StaticMethod() {
    }
  }

  /*
   * Ensure an non-inlined call to a static method whose declaring
   * class is statically known to have been initialized does not
   * require an explicit clinit check.
   */

  /// CHECK-START: void Main$ClassWithClinit4.invokeStaticNotInlined() builder (after)
  /// CHECK-DAG:                           InvokeStaticOrDirect

  /// CHECK-START: void Main$ClassWithClinit4.invokeStaticNotInlined() builder (after)
  /// CHECK-NOT:                           LoadClass
  /// CHECK-NOT:                           ClinitCheck

  /// CHECK-START: void Main$ClassWithClinit4.invokeStaticNotInlined() inliner (after)
  /// CHECK-DAG:                           InvokeStaticOrDirect

  /// CHECK-START: void Main$ClassWithClinit4.invokeStaticNotInlined() inliner (after)
  /// CHECK-NOT:                           LoadClass
  /// CHECK-NOT:                           ClinitCheck

  static class ClassWithClinit4 {
    static void invokeStaticNotInlined() {
      // The invocation of invokeStaticNotInlined triggers the
      // initialization of ClassWithClinit4, meaning that the
      // call to staticMethod below does not need a clinit
      // check.
      $noinline$staticMethod();
    }

    static {
      System.out.println("Main$ClassWithClinit4's static initializer");
    }

    static boolean doThrow = false;

    static void $noinline$staticMethod() {
      if (doThrow) {
        // Try defeating inlining.
        throw new Error();
      }
    }
  }

  /*
   * Ensure an inlined call to a static method whose declaring class
   * is a super class of the caller's class does not require an
   * explicit clinit check.
   */

  /// CHECK-START: void Main$SubClassOfClassWithClinit5.invokeStaticInlined() builder (after)
  /// CHECK-DAG:                           InvokeStaticOrDirect

  /// CHECK-START: void Main$SubClassOfClassWithClinit5.invokeStaticInlined() builder (after)
  /// CHECK-NOT:                           LoadClass
  /// CHECK-NOT:                           ClinitCheck

  /// CHECK-START: void Main$SubClassOfClassWithClinit5.invokeStaticInlined() inliner (after)
  /// CHECK-NOT:                           LoadClass
  /// CHECK-NOT:                           ClinitCheck
  /// CHECK-NOT:                           InvokeStaticOrDirect

  static class ClassWithClinit5 {
    static void $opt$inline$StaticMethod() {
    }

    static {
      System.out.println("Main$ClassWithClinit5's static initializer");
    }
  }

  static class SubClassOfClassWithClinit5 extends ClassWithClinit5 {
    static void invokeStaticInlined() {
      ClassWithClinit5.$opt$inline$StaticMethod();
    }
  }

  /*
   * Ensure an non-inlined call to a static method whose declaring
   * class is a super class of the caller's class does not require an
   * explicit clinit check.
   */

  /// CHECK-START: void Main$SubClassOfClassWithClinit6.invokeStaticNotInlined() builder (after)
  /// CHECK-DAG:                           InvokeStaticOrDirect

  /// CHECK-START: void Main$SubClassOfClassWithClinit6.invokeStaticNotInlined() builder (after)
  /// CHECK-NOT:                           LoadClass
  /// CHECK-NOT:                           ClinitCheck

  /// CHECK-START: void Main$SubClassOfClassWithClinit6.invokeStaticNotInlined() inliner (after)
  /// CHECK-DAG:                           InvokeStaticOrDirect

  /// CHECK-START: void Main$SubClassOfClassWithClinit6.invokeStaticNotInlined() inliner (after)
  /// CHECK-NOT:                           LoadClass
  /// CHECK-NOT:                           ClinitCheck

  static class ClassWithClinit6 {
    static boolean doThrow = false;

    static void $noinline$staticMethod() {
      if (doThrow) {
        // Try defeating inlining.
        throw new Error();
      }
    }

    static {
      System.out.println("Main$ClassWithClinit6's static initializer");
    }
  }

  static class SubClassOfClassWithClinit6 extends ClassWithClinit6 {
    static void invokeStaticNotInlined() {
      ClassWithClinit6.$noinline$staticMethod();
    }
  }


  /*
   * Verify that if we have a static call immediately after the load class
   * we don't do generate a clinit check.
   */

  /// CHECK-START: void Main.noClinitBecauseOfInvokeStatic() liveness (before)
  /// CHECK-DAG:     <<IntConstant:i\d+>>  IntConstant 0
  /// CHECK-DAG:     <<LoadClass:l\d+>>    LoadClass gen_clinit_check:false
  /// CHECK-DAG:                           InvokeStaticOrDirect clinit_check:implicit
  /// CHECK-DAG:                           StaticFieldSet [<<LoadClass>>,<<IntConstant>>]

  /// CHECK-START: void Main.noClinitBecauseOfInvokeStatic() liveness (before)
  /// CHECK-NOT:                           ClinitCheck

  static void noClinitBecauseOfInvokeStatic() {
    ClassWithClinit2.$noinline$staticMethod();
    ClassWithClinit2.doThrow = false;
  }

  /*
   * Verify that if the static call is after a field access, the load class
   * will generate a clinit check.
   */

  /// CHECK-START: void Main.clinitBecauseOfFieldAccess() liveness (before)
  /// CHECK-DAG:     <<IntConstant:i\d+>>  IntConstant 0
  /// CHECK-DAG:     <<LoadClass:l\d+>>    LoadClass gen_clinit_check:true
  /// CHECK-DAG:                           StaticFieldSet [<<LoadClass>>,<<IntConstant>>]
  /// CHECK-DAG:                           InvokeStaticOrDirect clinit_check:none

  /// CHECK-START: void Main.clinitBecauseOfFieldAccess() liveness (before)
  /// CHECK-NOT:                           ClinitCheck
  static void clinitBecauseOfFieldAccess() {
    ClassWithClinit2.doThrow = false;
    ClassWithClinit2.$noinline$staticMethod();
  }

  /*
   * Verify that LoadClass from const-class is not merged with
   * later invoke-static (or it's ClinitCheck).
   */

  /// CHECK-START: void Main.constClassAndInvokeStatic(java.lang.Iterable) liveness (before)
  /// CHECK:                               LoadClass gen_clinit_check:false
  /// CHECK:                               InvokeStaticOrDirect clinit_check:implicit

  /// CHECK-START: void Main.constClassAndInvokeStatic(java.lang.Iterable) liveness (before)
  /// CHECK-NOT:                           ClinitCheck

  static void constClassAndInvokeStatic(Iterable<?> it) {
    $opt$inline$ignoreClass(ClassWithClinit7.class);
    ClassWithClinit7.someStaticMethod(it);
  }

  static void $opt$inline$ignoreClass(Class<?> c) {
  }

  static class ClassWithClinit7 {
    static {
      System.out.println("Main$ClassWithClinit7's static initializer");
    }

    // Note: not inlined from constClassAndInvokeStatic() but fully inlined from main().
    static void someStaticMethod(Iterable<?> it) {
      // We're not inlining invoke-interface at the moment.
      it.iterator();
    }
  }

  /*
   * Verify that LoadClass from sget is not merged with later invoke-static.
   */

  /// CHECK-START: void Main.sgetAndInvokeStatic(java.lang.Iterable) liveness (before)
  /// CHECK:                               LoadClass gen_clinit_check:true
  /// CHECK:                               InvokeStaticOrDirect clinit_check:none

  /// CHECK-START: void Main.sgetAndInvokeStatic(java.lang.Iterable) liveness (before)
  /// CHECK-NOT:                           ClinitCheck

  static void sgetAndInvokeStatic(Iterable<?> it) {
    $opt$inline$ignoreInt(ClassWithClinit8.value);
    ClassWithClinit8.someStaticMethod(it);
  }

  static void $opt$inline$ignoreInt(int i) {
  }

  static class ClassWithClinit8 {
    public static int value = 0;
    static {
      System.out.println("Main$ClassWithClinit8's static initializer");
    }

    // Note: not inlined from sgetAndInvokeStatic() but fully inlined from main().
    static void someStaticMethod(Iterable<?> it) {
      // We're not inlining invoke-interface at the moment.
      it.iterator();
    }
  }

  /*
   * Verify that LoadClass from const-class, ClinitCheck from sget and
   * InvokeStaticOrDirect from invoke-static are not merged.
   */

  /// CHECK-START: void Main.constClassSgetAndInvokeStatic(java.lang.Iterable) liveness (before)
  /// CHECK:                               LoadClass gen_clinit_check:false
  /// CHECK:                               ClinitCheck
  /// CHECK:                               InvokeStaticOrDirect clinit_check:none

  static void constClassSgetAndInvokeStatic(Iterable<?> it) {
    $opt$inline$ignoreClass(ClassWithClinit9.class);
    $opt$inline$ignoreInt(ClassWithClinit9.value);
    ClassWithClinit9.someStaticMethod(it);
  }

  static class ClassWithClinit9 {
    public static int value = 0;
    static {
      System.out.println("Main$ClassWithClinit9's static initializer");
    }

    // Note: not inlined from constClassSgetAndInvokeStatic() but fully inlined from main().
    static void someStaticMethod(Iterable<?> it) {
      // We're not inlining invoke-interface at the moment.
      it.iterator();
    }
  }

  /*
   * Verify that LoadClass from a fully-inlined invoke-static is not merged
   * with InvokeStaticOrDirect from a later invoke-static to the same method.
   */

  /// CHECK-START: void Main.inlinedInvokeStaticViaNonStatic(java.lang.Iterable) liveness (before)
  /// CHECK:                               LoadClass gen_clinit_check:true
  /// CHECK:                               InvokeStaticOrDirect clinit_check:none

  /// CHECK-START: void Main.inlinedInvokeStaticViaNonStatic(java.lang.Iterable) liveness (before)
  /// CHECK-NOT:                           ClinitCheck

  static void inlinedInvokeStaticViaNonStatic(Iterable<?> it) {
    inlinedInvokeStaticViaNonStaticHelper(null);
    inlinedInvokeStaticViaNonStaticHelper(it);
  }

  static void inlinedInvokeStaticViaNonStaticHelper(Iterable<?> it) {
    ClassWithClinit10.inlinedForNull(it);
  }

  static class ClassWithClinit10 {
    public static int value = 0;
    static {
      System.out.println("Main$ClassWithClinit10's static initializer");
    }

    static void inlinedForNull(Iterable<?> it) {
      if (it != null) {
        // We're not inlining invoke-interface at the moment.
        it.iterator();
      }
    }
  }

  /*
   * Check that the LoadClass from an invoke-static C.foo() doesn't get merged with
   * an invoke-static inside C.foo(). This would mess up the stack walk in the
   * resolution trampoline where we would have to load C (if C isn't loaded yet)
   * which is not permitted there.
   *
   * Note: In case of failure, we would get an failed assertion during compilation,
   * so we wouldn't really get to the checker tests below.
   */

  /// CHECK-START: void Main.inlinedInvokeStaticViaStatic(java.lang.Iterable) liveness (before)
  /// CHECK:                               LoadClass gen_clinit_check:true
  /// CHECK:                               InvokeStaticOrDirect clinit_check:none

  /// CHECK-START: void Main.inlinedInvokeStaticViaStatic(java.lang.Iterable) liveness (before)
  /// CHECK-NOT:                           ClinitCheck

  static void inlinedInvokeStaticViaStatic(Iterable<?> it) {
    ClassWithClinit11.callInlinedForNull(it);
  }

  static class ClassWithClinit11 {
    public static int value = 0;
    static {
      System.out.println("Main$ClassWithClinit11's static initializer");
    }

    static void callInlinedForNull(Iterable<?> it) {
      inlinedForNull(it);
    }

    static void inlinedForNull(Iterable<?> it) {
      // We're not inlining invoke-interface at the moment.
      it.iterator();
    }
  }

  /*
   * A test similar to inlinedInvokeStaticViaStatic() but doing the indirect invoke
   * twice with the first one to be fully inlined.
   */

  /// CHECK-START: void Main.inlinedInvokeStaticViaStaticTwice(java.lang.Iterable) liveness (before)
  /// CHECK:                               LoadClass gen_clinit_check:true
  /// CHECK:                               InvokeStaticOrDirect clinit_check:none

  /// CHECK-START: void Main.inlinedInvokeStaticViaStaticTwice(java.lang.Iterable) liveness (before)
  /// CHECK-NOT:                           ClinitCheck

  static void inlinedInvokeStaticViaStaticTwice(Iterable<?> it) {
    ClassWithClinit12.callInlinedForNull(null);
    ClassWithClinit12.callInlinedForNull(it);
  }

  static class ClassWithClinit12 {
    public static int value = 0;
    static {
      System.out.println("Main$ClassWithClinit12's static initializer");
    }

    static void callInlinedForNull(Iterable<?> it) {
      inlinedForNull(it);
    }

    static void inlinedForNull(Iterable<?> it) {
      if (it != null) {
        // We're not inlining invoke-interface at the moment.
        it.iterator();
      }
    }
  }

  static class ClassWithClinit13 {
    static {
      System.out.println("Main$ClassWithClinit13's static initializer");
    }

    public static void $inline$forwardToGetIterator(Iterable<?> it) {
      $noinline$getIterator(it);
    }

    public static void $noinline$getIterator(Iterable<?> it) {
      // We're not inlining invoke-interface at the moment.
      it.iterator();
    }
  }

  // TODO: Write checker statements.
  static Object $noinline$testInliningAndNewInstance(Iterable<?> it) {
    if (doThrow) { throw new Error(); }
    ClassWithClinit13.$inline$forwardToGetIterator(it);
    return new ClassWithClinit13();
  }

  // TODO: Add a test for the case of a static method whose declaring
  // class type index is not available (i.e. when `storage_index`
  // equals `DexFile::kDexNoIndex` in
  // art::HGraphBuilder::BuildInvoke).

  public static void main(String[] args) {
    invokeStaticInlined();
    invokeStaticNotInlined();
    ClassWithClinit3.invokeStaticInlined();
    ClassWithClinit4.invokeStaticNotInlined();
    SubClassOfClassWithClinit5.invokeStaticInlined();
    SubClassOfClassWithClinit6.invokeStaticNotInlined();
    Iterable it = new Iterable() { public java.util.Iterator iterator() { return null; } };
    constClassAndInvokeStatic(it);
    sgetAndInvokeStatic(it);
    constClassSgetAndInvokeStatic(it);
    inlinedInvokeStaticViaNonStatic(it);
    inlinedInvokeStaticViaStatic(it);
    inlinedInvokeStaticViaStaticTwice(it);
    $noinline$testInliningAndNewInstance(it);
  }
}
