/*
 * 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.
 */

package art;

import java.lang.ref.PhantomReference;
import java.lang.ref.ReferenceQueue;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.function.BiConsumer;

public class Test905 {
  private static final boolean DALVIK_RUN = "Dalvik".equals(System.getProperty("java.vm.name"));

  // Taken from jdwp tests.
  public static class MarkerObj {
    public static int cnt = 0;
    public void finalize() { cnt++; }
  }
  public static class GcMarker {
    private final ReferenceQueue mQueue;
    private final ArrayList<PhantomReference> mList;
    public GcMarker() {
      mQueue = new ReferenceQueue();
      mList = new ArrayList<PhantomReference>(3);
    }
    public void add(Object referent) {
      mList.add(new PhantomReference(referent, mQueue));
    }
    public void waitForGc() {
      waitForGc(mList.size());
    }
    public void waitForGc(int numberOfExpectedFinalizations) {
      if (numberOfExpectedFinalizations > mList.size()) {
        throw new IllegalArgumentException("wait condition will never be met");
      }
      // Request finalization of objects, and subsequent reference enqueueing.
      // Repeat until reference queue reaches expected size.
      do {
          System.runFinalization();
          Runtime.getRuntime().gc();
          try { Thread.sleep(10); } catch (Exception e) {}
      } while (isLive(numberOfExpectedFinalizations));
    }
    private boolean isLive(int numberOfExpectedFinalizations) {
      int numberFinalized = 0;
      for (int i = 0, n = mList.size(); i < n; i++) {
        if (mList.get(i).isEnqueued()) {
          numberFinalized++;
        }
      }
      return numberFinalized < numberOfExpectedFinalizations;
    }
  }

  public static void run() throws Exception {
    doTest();
  }

  public static void doTest() throws Exception {
    // Use a list to ensure objects must be allocated.
    ArrayList<Object> l = new ArrayList<>(100);

    setupObjectFreeCallback();

    enableFreeTracking(true);
    run(l);

    enableFreeTracking(false);
    run(l);

    enableFreeTracking(true);
    if (DALVIK_RUN) {
      stress(400000);
    } else {
      // For JVM the JVMTI tag handling is not running as expected for the stress test
      // (b/252990223).
      stress(10000);
    }
  }

  private static void run(ArrayList<Object> l) {
    allocate(l, 1);
    l.clear();

    gcAndWait();

    getAndPrintTags();
    System.out.println("---");

    // Note: the reporting will not depend on the heap layout (which could be unstable). Walking
    //       the tag table should give us a stable output order.
    for (int i = 10; i <= 1000; i *= 10) {
      allocate(l, i);
    }
    l.clear();

    gcAndWait();

    getAndPrintTags();
    System.out.println("---");

    gcAndWait();

    getAndPrintTags();
    System.out.println("---");
  }

  private static int errors = 0;

  private static void stressAllocate(int i, BiConsumer<Integer, Object> saver) {
    Object obj = new Object();
    Main.setTag(obj, i);
    setTag2(obj, i + 1);
    saver.accept(i, obj);
  }

  private static void stress(int allocations) {
    getCollectedTags(0);
    getCollectedTags(1);
    final int num_obj = allocations;
    final Object[] saved = new Object[num_obj/2];
    // Allocate objects, Save every other one. We want to be sure that it's only the deleted objects
    // that get their tags cleared and non-deleted objects correctly keep track of their tags.
    for (int i = 1; i <= num_obj; ++i) {
      stressAllocate(i, (idx, obj) -> {
        if ((idx.intValue() - 1) % 2 == 0) {
          saved[(idx.intValue() - 1)/2] = obj;
        }
      });
    }
    gcAndWait();
    long[] freedTags1 = getCollectedTags(0);
    long[] freedTags2 = getCollectedTags(1);
    // Sort the freedtags
    Arrays.sort(freedTags1);
    Arrays.sort(freedTags2);
    // Make sure we freed all the ones we expect to and both envs agree on this.
    if (freedTags1.length == num_obj / 2 && freedTags2.length == num_obj / 2) {
      System.out.println("Free counts as expected");
    } else {
      System.out.println("Free counts " + freedTags1.length + " " + freedTags2.length);
    }
    for (int i = 0; i < freedTags1.length; ++i) {
      if (freedTags1[i] + 1 != freedTags2[i]) {
        System.out.println("Mismatched tags " + (freedTags1[i] + 1) + " " + freedTags2[i]);
        break;
      }
    }
    // Make sure the saved-tags aren't present.
    for (int i = 0; i < saved.length; i++) {
      // index = (tag - 1)/2 --> (index * 2) + 1 = tag
      long expectedTag1 = (i * 2) + 1;
      if (Main.getTag(saved[i]) != expectedTag1) {
        System.out.println("Saved object has unexpected tag in env 1. Expected "
                           + expectedTag1 + " got " + Main.getTag(saved[i]));
      }
      if (getTag2(saved[i]) != 1 + expectedTag1) {
        System.out.println("Saved object has unexpected tag in env 2. Expected "
                           + (expectedTag1 + 1) + " got " + getTag2(saved[i]));
      }
      if (Arrays.binarySearch(freedTags1, expectedTag1) >= 0) {
        System.out.println("Saved object was marked as deleted in env 1. Object was "
                           + expectedTag1);
      }
      if (Arrays.binarySearch(freedTags2, expectedTag1 + 1) >= 0) {
        System.out.println("Saved object was marked as deleted in env 2. Object was "
                           + (expectedTag1 + 1));
      }
    }
  }

  private static void allocate(ArrayList<Object> l, long tag) {
    Object obj = new Object();
    l.add(obj);
    Main.setTag(obj, tag);
  }

  private static void getAndPrintTags() {
    long[] freedTags = getCollectedTags(0);
    Arrays.sort(freedTags);
    System.out.println(Arrays.toString(freedTags));
  }

  private static GcMarker getMarker() {
    GcMarker m = new GcMarker();
    m.add(new MarkerObj());
    return m;
  }

  private static void gcAndWait() {
    GcMarker marker = getMarker();
    marker.waitForGc();
  }

  private static native void setupObjectFreeCallback();
  private static native void enableFreeTracking(boolean enable);
  private static native long[] getCollectedTags(int index);
  private static native void setTag2(Object o, long tag);
  private static native long getTag2(Object o);
}
