/*
 * Copyright (C) 2016 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.
 */

import java.lang.reflect.Field;

import sun.misc.Unsafe;

/**
 * Checker test on the 1.8 unsafe operations. Note, this is by no means an
 * exhaustive unit test for these CAS (compare-and-swap) and fence operations.
 * Instead, this test ensures the methods are recognized as intrinsic and behave
 * as expected.
 */
public class Main {

  private static final Unsafe unsafe = getUnsafe();

  private static Thread[] sThreads = new Thread[10];

  //
  // Fields accessed by setters and adders.
  //

  public int i = 0;
  public long l = 0;
  public Object o = null;

  //
  // Setters.
  //

  /// CHECK-START: int Main.set32(java.lang.Object, long, int) intrinsics_recognition (after)
  /// CHECK-DAG: <<Result:i\d+>> InvokeVirtual intrinsic:UnsafeGetAndSetInt
  /// CHECK-DAG:                 Return [<<Result>>]
  private static int set32(Object o, long offset, int newValue) {
    return unsafe.getAndSetInt(o, offset, newValue);
  }

  /// CHECK-START: long Main.set64(java.lang.Object, long, long) intrinsics_recognition (after)
  /// CHECK-DAG: <<Result:j\d+>> InvokeVirtual intrinsic:UnsafeGetAndSetLong
  /// CHECK-DAG:                 Return [<<Result>>]
  private static long set64(Object o, long offset, long newValue) {
    return unsafe.getAndSetLong(o, offset, newValue);
  }

  /// CHECK-START: java.lang.Object Main.setObj(java.lang.Object, long, java.lang.Object) intrinsics_recognition (after)
  /// CHECK-DAG: <<Result:l\d+>> InvokeVirtual intrinsic:UnsafeGetAndSetObject
  /// CHECK-DAG:                 Return [<<Result>>]
  private static Object setObj(Object o, long offset, Object newValue) {
    return unsafe.getAndSetObject(o, offset, newValue);
  }

  //
  // Adders.
  //

  /// CHECK-START: int Main.add32(java.lang.Object, long, int) intrinsics_recognition (after)
  /// CHECK-DAG: <<Result:i\d+>> InvokeVirtual intrinsic:UnsafeGetAndAddInt
  /// CHECK-DAG:                 Return [<<Result>>]
  private static int add32(Object o, long offset, int delta) {
    return unsafe.getAndAddInt(o, offset, delta);
  }

  /// CHECK-START: long Main.add64(java.lang.Object, long, long) intrinsics_recognition (after)
  /// CHECK-DAG: <<Result:j\d+>> InvokeVirtual intrinsic:UnsafeGetAndAddLong
  /// CHECK-DAG:                 Return [<<Result>>]
  private static long add64(Object o, long offset, long delta) {
    return unsafe.getAndAddLong(o, offset, delta);
  }

  //
  // Fences (native).
  //

  /// CHECK-START: void Main.load() intrinsics_recognition (after)
  /// CHECK-DAG: InvokeVirtual intrinsic:UnsafeLoadFence
  //
  /// CHECK-START: void Main.load() instruction_simplifier (after)
  /// CHECK-NOT: InvokeVirtual intrinsic:UnsafeLoadFence
  //
  /// CHECK-START: void Main.load() instruction_simplifier (after)
  /// CHECK-DAG: MemoryBarrier kind:LoadAny
  private static void load() {
    unsafe.loadFence();
  }

  /// CHECK-START: void Main.store() intrinsics_recognition (after)
  /// CHECK-DAG: InvokeVirtual intrinsic:UnsafeStoreFence
  //
  /// CHECK-START: void Main.store() instruction_simplifier (after)
  /// CHECK-NOT: InvokeVirtual intrinsic:UnsafeStoreFence
  //
  /// CHECK-START: void Main.store() instruction_simplifier (after)
  /// CHECK-DAG: MemoryBarrier kind:AnyStore
  private static void store() {
    unsafe.storeFence();
  }

  /// CHECK-START: void Main.full() intrinsics_recognition (after)
  /// CHECK-DAG: InvokeVirtual intrinsic:UnsafeFullFence
  //
  /// CHECK-START: void Main.full() instruction_simplifier (after)
  /// CHECK-NOT: InvokeVirtual intrinsic:UnsafeFullFence
  //
  /// CHECK-START: void Main.full() instruction_simplifier (after)
  /// CHECK-DAG: MemoryBarrier kind:AnyAny
  private static void full() {
    unsafe.fullFence();
  }

  //
  // Thread fork/join.
  //

  private static void fork(Runnable r) {
    for (int i = 0; i < 10; i++) {
      sThreads[i] = new Thread(r);
      sThreads[i].start();
    }
  }

  private static void join() {
    try {
      for (int i = 0; i < 10; i++) {
        sThreads[i].join();
      }
    } catch (InterruptedException e) {
      throw new Error("Failed join: " + e);
    }
  }

  //
  // Driver.
  //

  public static void main(String[] args) {
    System.out.println("starting");

    final Main m = new Main();

    // Get the offsets.

    final long intOffset, longOffset, objOffset;
    try {
      Field intField = Main.class.getDeclaredField("i");
      Field longField = Main.class.getDeclaredField("l");
      Field objField = Main.class.getDeclaredField("o");

      intOffset = unsafe.objectFieldOffset(intField);
      longOffset = unsafe.objectFieldOffset(longField);
      objOffset = unsafe.objectFieldOffset(objField);

    } catch (NoSuchFieldException e) {
      throw new Error("No offset: " + e);
    }

    // Some sanity within same thread.

    set32(m, intOffset, 3);
    expectEquals32(3, m.i);

    set64(m, longOffset, 7L);
    expectEquals64(7L, m.l);

    setObj(m, objOffset, m);
    expectEqualsObj(m, m.o);

    add32(m, intOffset, 11);
    expectEquals32(14, m.i);

    add64(m, longOffset, 13L);
    expectEquals64(20L, m.l);

    // Some sanity on setters within different threads.

    fork(new Runnable() {
      public void run() {
        for (int i = 0; i < 10; i++)
          set32(m, intOffset, i);
      }
    });
    join();
    expectEquals32(9, m.i);  // one thread's last value wins

    fork(new Runnable() {
      public void run() {
        for (int i = 0; i < 10; i++)
          set64(m, longOffset, (long) (100 + i));
      }
    });
    join();
    expectEquals64(109L, m.l);  // one thread's last value wins

    fork(new Runnable() {
      public void run() {
        for (int i = 0; i < 10; i++)
          setObj(m, objOffset, sThreads[i]);
      }
    });
    join();
    expectEqualsObj(sThreads[9], m.o);  // one thread's last value wins

    // Some sanity on adders within different threads.

    fork(new Runnable() {
      public void run() {
        for (int i = 0; i < 10; i++)
          add32(m, intOffset, i + 1);
      }
    });
    join();
    expectEquals32(559, m.i);  // all values accounted for

    fork(new Runnable() {
      public void run() {
        for (int i = 0; i < 10; i++)
          add64(m, longOffset, (long) (i + 1));
      }
    });
    join();
    expectEquals64(659L, m.l);  // all values accounted for

    // TODO: the fences

    System.out.println("passed");
  }

  // Use reflection to implement "Unsafe.getUnsafe()";
  private static Unsafe getUnsafe() {
    try {
      Class<?> unsafeClass = Unsafe.class;
      Field f = unsafeClass.getDeclaredField("theUnsafe");
      f.setAccessible(true);
      return (Unsafe) f.get(null);
    } catch (Exception e) {
      throw new Error("Cannot get Unsafe instance");
    }
  }

  private static void expectEquals32(int expected, int result) {
    if (expected != result) {
      throw new Error("Expected: " + expected + ", found: " + result);
    }
  }

  private static void expectEquals64(long expected, long result) {
    if (expected != result) {
      throw new Error("Expected: " + expected + ", found: " + result);
    }
  }

  private static void expectEqualsObj(Object expected, Object result) {
    if (expected != result) {
      throw new Error("Expected: " + expected + ", found: " + result);
    }
  }
}
