// Path: impl/src/main/java/io/perfmark/impl/Generator.java
// @NotThreadSafe
// public abstract class Generator {
//   /**
//    * This field is here as a hack. This class is a shared dependency of both {@link
//    * SecretPerfMarkImpl} and {@link Storage}. The impl needs to record the first time an event
//    * occurs, but doesn't call Storage#clinit until PerfMark is enabled. This leads to the timings
//    * being off in the trace event viewer, since the "start" time is since it was enabled, rather
//    * than when the first PerfMark call happens.
//    */
//   static final long INIT_NANO_TIME = System.nanoTime();
// 
//   /**
//    * The number of reserved bits at the bottom of the generation. All generations should be
//    * left-shifted by this amount.
//    */
//   public static final int GEN_OFFSET = 8;
//   /**
//    * Represents a failure to enable PerfMark library. This can be used by subclasses to indicate a
//    * previous failure to set the generation. It can also be used to indicate the generation count
//    * has overflowed.
//    */
//   public static final long FAILURE = -2L << GEN_OFFSET;
// 
//   protected Generator() {}
// 
//   /**
//    * Sets the current generation count. This should be eventually noticeable for callers of {@link
//    * #getGeneration()}. An odd number means the library is enabled, while an even number means the
//    * library is disabled.
//    *
//    * @param generation the generation id, shifted left by {@link #GEN_OFFSET}.
//    */
//   public abstract void setGeneration(long generation);
// 
//   /**
//    * Gets the current generation, shifted left by {@link #GEN_OFFSET}. An odd number means the
//    * library is enabled, while an even number means the library is disabled.
//    *
//    * @return the current generation or {@link #FAILURE}.
//    */
//   public abstract long getGeneration();
// 
//   /**
//    * Returns the approximate cost to change the generation.
//    *
//    * @return an approximate number of nanoseconds needed to change the generator value.
//    */
//   public long costOfSetNanos() {
//     return 1000000;
//   }
// 
//   /**
//    * Returns the approximate cost to read the generation.
//    *
//    * @return an approximate number of nanoseconds needed to read the generator value.
//    */
//   public long costOfGetNanos() {
//     return 10;
//   }
// }
// 
// Path: testing/src/main/java/io/perfmark/testing/GeneratorBenchmark.java
// @State(Scope.Benchmark)
// public class GeneratorBenchmark {
// 
//   private Generator generator;
// 
//   @Setup(Level.Trial)
//   public void setUp() {
//     generator = getGenerator();
//     generator.setGeneration(Generator.FAILURE);
//   }
// 
//   protected Generator getGenerator() {
//     throw new UnsupportedOperationException();
//   }
// 
//   @Benchmark
//   @BenchmarkMode(Mode.AverageTime)
//   @OutputTimeUnit(TimeUnit.NANOSECONDS)
//   public void ifEnabled() {
//     if (isEnabled(getGeneration())) {
//       Blackhole.consumeCPU(1000);
//     }
//   }
// 
//   @Benchmark
//   @BenchmarkMode(Mode.AverageTime)
//   @OutputTimeUnit(TimeUnit.NANOSECONDS)
//   public long getGeneration() {
//     return generator.getGeneration();
//   }
// 
//   @Benchmark
//   @BenchmarkMode(Mode.AverageTime)
//   @OutputTimeUnit(TimeUnit.NANOSECONDS)
//   public long getAndSetAndGetGeneration() {
//     long oldGeneration = generator.getGeneration();
//     generator.setGeneration(oldGeneration + 1);
//     return generator.getGeneration();
//   }
// 
//   @Benchmark
//   @BenchmarkMode(Mode.AverageTime)
//   @OutputTimeUnit(TimeUnit.NANOSECONDS)
//   @GroupThreads(3)
//   public long racyGetAndSetAndGetGeneration() {
//     long oldGeneration = generator.getGeneration();
//     generator.setGeneration(oldGeneration + 1);
//     return generator.getGeneration();
//   }
// 
//   protected static boolean isEnabled(long gen) {
//     return ((gen >>> Generator.GEN_OFFSET) & 0x1L) != 0L;
//   }
// }


import io.perfmark.impl.Generator;
import io.perfmark.testing.GeneratorBenchmark;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;
import org.openjdk.jmh.annotations.Scope;
import org.openjdk.jmh.annotations.State;
import org.openjdk.jmh.runner.Runner;
import org.openjdk.jmh.runner.options.Options;
import org.openjdk.jmh.runner.options.OptionsBuilder;
import org.openjdk.jmh.runner.options.TimeValue;
import org.openjdk.jmh.runner.options.VerboseMode;
/*
 * Copyright 2021 Carl Mastrangelo
 *
 * 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 io.perfmark.java7;


@RunWith(JUnit4.class)
public class MethodHandleGeneratorBenchmarkTest {

  @Test
  public void generatorBenchmark() throws Exception {
    Options options = new OptionsBuilder()
        .include(MethodHandleGeneratorBenchmark.class.getCanonicalName())
        .measurementIterations(5)
        .warmupIterations(10)
        .forks(1)
        .verbosity(VerboseMode.EXTRA)
        .warmupTime(TimeValue.seconds(1))
        .measurementTime(TimeValue.seconds(1))
        .shouldFailOnError(true)
        // This is necessary to run in the IDE, otherwise it would inherit the VM args.
        .jvmArgs("-da")
        .build();

    new Runner(options).run();
  }

  @State(Scope.Benchmark)
// Path: impl/src/main/java/io/perfmark/impl/Generator.java
// @NotThreadSafe
// public abstract class Generator {
//   /**
//    * This field is here as a hack. This class is a shared dependency of both {@link
//    * SecretPerfMarkImpl} and {@link Storage}. The impl needs to record the first time an event
//    * occurs, but doesn't call Storage#clinit until PerfMark is enabled. This leads to the timings
//    * being off in the trace event viewer, since the "start" time is since it was enabled, rather
//    * than when the first PerfMark call happens.
//    */
//   static final long INIT_NANO_TIME = System.nanoTime();
// 
//   /**
//    * The number of reserved bits at the bottom of the generation. All generations should be
//    * left-shifted by this amount.
//    */
//   public static final int GEN_OFFSET = 8;
//   /**
//    * Represents a failure to enable PerfMark library. This can be used by subclasses to indicate a
//    * previous failure to set the generation. It can also be used to indicate the generation count
//    * has overflowed.
//    */
//   public static final long FAILURE = -2L << GEN_OFFSET;
// 
//   protected Generator() {}
// 
//   /**
//    * Sets the current generation count. This should be eventually noticeable for callers of {@link
//    * #getGeneration()}. An odd number means the library is enabled, while an even number means the
//    * library is disabled.
//    *
//    * @param generation the generation id, shifted left by {@link #GEN_OFFSET}.
//    */
//   public abstract void setGeneration(long generation);
// 
//   /**
//    * Gets the current generation, shifted left by {@link #GEN_OFFSET}. An odd number means the
//    * library is enabled, while an even number means the library is disabled.
//    *
//    * @return the current generation or {@link #FAILURE}.
//    */
//   public abstract long getGeneration();
// 
//   /**
//    * Returns the approximate cost to change the generation.
//    *
//    * @return an approximate number of nanoseconds needed to change the generator value.
//    */
//   public long costOfSetNanos() {
//     return 1000000;
//   }
// 
//   /**
//    * Returns the approximate cost to read the generation.
//    *
//    * @return an approximate number of nanoseconds needed to read the generator value.
//    */
//   public long costOfGetNanos() {
//     return 10;
//   }
// }
// 
// Path: testing/src/main/java/io/perfmark/testing/GeneratorBenchmark.java
// @State(Scope.Benchmark)
// public class GeneratorBenchmark {
// 
//   private Generator generator;
// 
//   @Setup(Level.Trial)
//   public void setUp() {
//     generator = getGenerator();
//     generator.setGeneration(Generator.FAILURE);
//   }
// 
//   protected Generator getGenerator() {
//     throw new UnsupportedOperationException();
//   }
// 
//   @Benchmark
//   @BenchmarkMode(Mode.AverageTime)
//   @OutputTimeUnit(TimeUnit.NANOSECONDS)
//   public void ifEnabled() {
//     if (isEnabled(getGeneration())) {
//       Blackhole.consumeCPU(1000);
//     }
//   }
// 
//   @Benchmark
//   @BenchmarkMode(Mode.AverageTime)
//   @OutputTimeUnit(TimeUnit.NANOSECONDS)
//   public long getGeneration() {
//     return generator.getGeneration();
//   }
// 
//   @Benchmark
//   @BenchmarkMode(Mode.AverageTime)
//   @OutputTimeUnit(TimeUnit.NANOSECONDS)
//   public long getAndSetAndGetGeneration() {
//     long oldGeneration = generator.getGeneration();
//     generator.setGeneration(oldGeneration + 1);
//     return generator.getGeneration();
//   }
// 
//   @Benchmark
//   @BenchmarkMode(Mode.AverageTime)
//   @OutputTimeUnit(TimeUnit.NANOSECONDS)
//   @GroupThreads(3)
//   public long racyGetAndSetAndGetGeneration() {
//     long oldGeneration = generator.getGeneration();
//     generator.setGeneration(oldGeneration + 1);
//     return generator.getGeneration();
//   }
// 
//   protected static boolean isEnabled(long gen) {
//     return ((gen >>> Generator.GEN_OFFSET) & 0x1L) != 0L;
//   }
// }


// Path: java7/src/jmh/java/io/perfmark/java7/MethodHandleGeneratorBenchmarkTest.java
import io.perfmark.impl.Generator;
import io.perfmark.testing.GeneratorBenchmark;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;
import org.openjdk.jmh.annotations.Scope;
import org.openjdk.jmh.annotations.State;
import org.openjdk.jmh.runner.Runner;
import org.openjdk.jmh.runner.options.Options;
import org.openjdk.jmh.runner.options.OptionsBuilder;
import org.openjdk.jmh.runner.options.TimeValue;
import org.openjdk.jmh.runner.options.VerboseMode;

/*
 * Copyright 2021 Carl Mastrangelo
 *
 * 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 io.perfmark.java7;


@RunWith(JUnit4.class)
public class MethodHandleGeneratorBenchmarkTest {

  @Test
  public void generatorBenchmark() throws Exception {
    Options options = new OptionsBuilder()
        .include(MethodHandleGeneratorBenchmark.class.getCanonicalName())
        .measurementIterations(5)
        .warmupIterations(10)
        .forks(1)
        .verbosity(VerboseMode.EXTRA)
        .warmupTime(TimeValue.seconds(1))
        .measurementTime(TimeValue.seconds(1))
        .shouldFailOnError(true)
        // This is necessary to run in the IDE, otherwise it would inherit the VM args.
        .jvmArgs("-da")
        .build();

    new Runner(options).run();
  }

  @State(Scope.Benchmark)
  public static class MethodHandleGeneratorBenchmark extends GeneratorBenchmark {