changeset 1438:e953411d3d5e

7902096: State order DAG does not work correctly with mixed Scope-d state objects
author shade
date Wed, 17 Jan 2018 11:53:49 +0100
parents a0c4f5e23278
children 6d51e8e924d0
files jmh-core-it/src/test/java/org/openjdk/jmh/it/dagorder/MixedBGTIterationDagOrderTest.java jmh-core-it/src/test/java/org/openjdk/jmh/it/dagorder/MixedBGTTrialDagOrderTest.java jmh-core-it/src/test/java/org/openjdk/jmh/it/dagorder/MixedBTGIterationDagOrderTest.java jmh-core-it/src/test/java/org/openjdk/jmh/it/dagorder/MixedBTGTrialDagOrderTest.java jmh-core-it/src/test/java/org/openjdk/jmh/it/dagorder/MixedGBTIterationDagOrderTest.java jmh-core-it/src/test/java/org/openjdk/jmh/it/dagorder/MixedGBTTrialDagOrderTest.java jmh-core-it/src/test/java/org/openjdk/jmh/it/dagorder/MixedGTBIterationDagOrderTest.java jmh-core-it/src/test/java/org/openjdk/jmh/it/dagorder/MixedGTBTrialDagOrderTest.java jmh-core-it/src/test/java/org/openjdk/jmh/it/dagorder/MixedTBGIterationDagOrderTest.java jmh-core-it/src/test/java/org/openjdk/jmh/it/dagorder/MixedTBGTrialDagOrderTest.java jmh-core-it/src/test/java/org/openjdk/jmh/it/dagorder/MixedTGBIterationDagOrderTest.java jmh-core-it/src/test/java/org/openjdk/jmh/it/dagorder/MixedTGBTrialDagOrderTest.java jmh-core/src/main/java/org/openjdk/jmh/generators/core/StateObjectHandler.java
diffstat 13 files changed, 1506 insertions(+), 23 deletions(-) [+]
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jmh-core-it/src/test/java/org/openjdk/jmh/it/dagorder/MixedBGTIterationDagOrderTest.java	Wed Jan 17 11:53:49 2018 +0100
@@ -0,0 +1,124 @@
+/*
+ * Copyright (c) 2005, 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package org.openjdk.jmh.it.dagorder;
+
+import junit.framework.Assert;
+import org.junit.Test;
+import org.openjdk.jmh.annotations.*;
+import org.openjdk.jmh.it.Fixtures;
+import org.openjdk.jmh.runner.Runner;
+import org.openjdk.jmh.runner.RunnerException;
+import org.openjdk.jmh.runner.options.Options;
+import org.openjdk.jmh.runner.options.OptionsBuilder;
+
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicInteger;
+
+/**
+ * Tests global setup -> run -> tearDown sequence.
+ */
+public class MixedBGTIterationDagOrderTest {
+
+    public static final AtomicInteger TICKER = new AtomicInteger();
+
+    private static volatile int s1setup, s1teardown;
+    private static volatile int s2setup, s2teardown;
+    private static volatile int s3setup, s3teardown;
+    private static volatile int run;
+
+    @State(Scope.Thread)
+    public static class S3 {
+
+        @Setup(Level.Iteration)
+        public void setupInstance() {
+            s3setup = TICKER.incrementAndGet();
+        }
+
+        @TearDown(Level.Iteration)
+        public void tearDownInstance() {
+            s3teardown = TICKER.incrementAndGet();
+        }
+    }
+
+    @State(Scope.Group)
+    public static class S2 {
+
+        @Setup(Level.Iteration)
+        public void setupInstance(S3 s3) {
+            s2setup = TICKER.incrementAndGet();
+        }
+
+        @TearDown(Level.Iteration)
+        public void tearDownInstance() {
+            s2teardown = TICKER.incrementAndGet();
+        }
+    }
+
+    @State(Scope.Benchmark)
+    public static class S1 {
+
+        @Setup(Level.Iteration)
+        public void setupInstance(S2 s2) {
+            s1setup = TICKER.incrementAndGet();
+        }
+
+        @TearDown(Level.Iteration)
+        public void tearDownInstance() {
+            s1teardown = TICKER.incrementAndGet();
+        }
+    }
+
+    @Benchmark
+    @BenchmarkMode(Mode.All)
+    @Warmup(iterations = 0)
+    @Measurement(iterations = 1, time = 100, timeUnit = TimeUnit.MILLISECONDS)
+    @Fork(0)
+    @Threads(1)
+    public void test(S1 state) {
+        run = TICKER.incrementAndGet();
+        Fixtures.work();
+    }
+
+    @Test
+    public void invokeAPI() throws RunnerException {
+        for (int c = 0; c < Fixtures.repetitionCount(); c++) {
+            Options opt = new OptionsBuilder()
+                    .include(Fixtures.getTestMask(this.getClass()))
+                    .shouldFailOnError(true)
+                    .syncIterations(false)
+                    .build();
+            new Runner(opt).run();
+
+
+            Assert.assertTrue(s3setup + " < " + s2setup, s3setup < s2setup);
+            Assert.assertTrue(s2setup + " < " + s1setup, s2setup < s1setup);
+            Assert.assertTrue(s1setup + " < " + run, s1setup < run);
+
+            Assert.assertTrue(run + " < " + s1teardown, run < s1teardown);
+            Assert.assertTrue(s1teardown + " < " + s2teardown, s1teardown < s2teardown);
+            Assert.assertTrue(s2teardown + " < " + s3teardown, s2teardown < s3teardown);
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jmh-core-it/src/test/java/org/openjdk/jmh/it/dagorder/MixedBGTTrialDagOrderTest.java	Wed Jan 17 11:53:49 2018 +0100
@@ -0,0 +1,124 @@
+/*
+ * Copyright (c) 2005, 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package org.openjdk.jmh.it.dagorder;
+
+import junit.framework.Assert;
+import org.junit.Test;
+import org.openjdk.jmh.annotations.*;
+import org.openjdk.jmh.it.Fixtures;
+import org.openjdk.jmh.runner.Runner;
+import org.openjdk.jmh.runner.RunnerException;
+import org.openjdk.jmh.runner.options.Options;
+import org.openjdk.jmh.runner.options.OptionsBuilder;
+
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicInteger;
+
+/**
+ * Tests global setup -> run -> tearDown sequence.
+ */
+public class MixedBGTTrialDagOrderTest {
+
+    public static final AtomicInteger TICKER = new AtomicInteger();
+
+    private static volatile int s1setup, s1teardown;
+    private static volatile int s2setup, s2teardown;
+    private static volatile int s3setup, s3teardown;
+    private static volatile int run;
+
+    @State(Scope.Thread)
+    public static class S3 {
+
+        @Setup(Level.Trial)
+        public void setupInstance() {
+            s3setup = TICKER.incrementAndGet();
+        }
+
+        @TearDown(Level.Trial)
+        public void tearDownInstance() {
+            s3teardown = TICKER.incrementAndGet();
+        }
+    }
+
+    @State(Scope.Group)
+    public static class S2 {
+
+        @Setup(Level.Trial)
+        public void setupInstance(S3 s3) {
+            s2setup = TICKER.incrementAndGet();
+        }
+
+        @TearDown(Level.Trial)
+        public void tearDownInstance() {
+            s2teardown = TICKER.incrementAndGet();
+        }
+    }
+
+    @State(Scope.Benchmark)
+    public static class S1 {
+
+        @Setup(Level.Trial)
+        public void setupInstance(S2 s2) {
+            s1setup = TICKER.incrementAndGet();
+        }
+
+        @TearDown(Level.Trial)
+        public void tearDownInstance() {
+            s1teardown = TICKER.incrementAndGet();
+        }
+    }
+
+    @Benchmark
+    @BenchmarkMode(Mode.All)
+    @Warmup(iterations = 0)
+    @Measurement(iterations = 1, time = 100, timeUnit = TimeUnit.MILLISECONDS)
+    @Fork(0)
+    @Threads(1)
+    public void test(S1 state) {
+        run = TICKER.incrementAndGet();
+        Fixtures.work();
+    }
+
+    @Test
+    public void invokeAPI() throws RunnerException {
+        for (int c = 0; c < Fixtures.repetitionCount(); c++) {
+            Options opt = new OptionsBuilder()
+                    .include(Fixtures.getTestMask(this.getClass()))
+                    .shouldFailOnError(true)
+                    .syncIterations(false)
+                    .build();
+            new Runner(opt).run();
+
+
+            Assert.assertTrue(s3setup + " < " + s2setup, s3setup < s2setup);
+            Assert.assertTrue(s2setup + " < " + s1setup, s2setup < s1setup);
+            Assert.assertTrue(s1setup + " < " + run, s1setup < run);
+
+            Assert.assertTrue(run + " < " + s1teardown, run < s1teardown);
+            Assert.assertTrue(s1teardown + " < " + s2teardown, s1teardown < s2teardown);
+            Assert.assertTrue(s2teardown + " < " + s3teardown, s2teardown < s3teardown);
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jmh-core-it/src/test/java/org/openjdk/jmh/it/dagorder/MixedBTGIterationDagOrderTest.java	Wed Jan 17 11:53:49 2018 +0100
@@ -0,0 +1,124 @@
+/*
+ * Copyright (c) 2005, 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package org.openjdk.jmh.it.dagorder;
+
+import junit.framework.Assert;
+import org.junit.Test;
+import org.openjdk.jmh.annotations.*;
+import org.openjdk.jmh.it.Fixtures;
+import org.openjdk.jmh.runner.Runner;
+import org.openjdk.jmh.runner.RunnerException;
+import org.openjdk.jmh.runner.options.Options;
+import org.openjdk.jmh.runner.options.OptionsBuilder;
+
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicInteger;
+
+/**
+ * Tests global setup -> run -> tearDown sequence.
+ */
+public class MixedBTGIterationDagOrderTest {
+
+    public static final AtomicInteger TICKER = new AtomicInteger();
+
+    private static volatile int s1setup, s1teardown;
+    private static volatile int s2setup, s2teardown;
+    private static volatile int s3setup, s3teardown;
+    private static volatile int run;
+
+    @State(Scope.Group)
+    public static class S3 {
+
+        @Setup(Level.Iteration)
+        public void setupInstance() {
+            s3setup = TICKER.incrementAndGet();
+        }
+
+        @TearDown(Level.Iteration)
+        public void tearDownInstance() {
+            s3teardown = TICKER.incrementAndGet();
+        }
+    }
+
+    @State(Scope.Thread)
+    public static class S2 {
+
+        @Setup(Level.Iteration)
+        public void setupInstance(S3 s3) {
+            s2setup = TICKER.incrementAndGet();
+        }
+
+        @TearDown(Level.Iteration)
+        public void tearDownInstance() {
+            s2teardown = TICKER.incrementAndGet();
+        }
+    }
+
+    @State(Scope.Benchmark)
+    public static class S1 {
+
+        @Setup(Level.Iteration)
+        public void setupInstance(S2 s2) {
+            s1setup = TICKER.incrementAndGet();
+        }
+
+        @TearDown(Level.Iteration)
+        public void tearDownInstance() {
+            s1teardown = TICKER.incrementAndGet();
+        }
+    }
+
+    @Benchmark
+    @BenchmarkMode(Mode.All)
+    @Warmup(iterations = 0)
+    @Measurement(iterations = 1, time = 100, timeUnit = TimeUnit.MILLISECONDS)
+    @Fork(0)
+    @Threads(1)
+    public void test(S1 state) {
+        run = TICKER.incrementAndGet();
+        Fixtures.work();
+    }
+
+    @Test
+    public void invokeAPI() throws RunnerException {
+        for (int c = 0; c < Fixtures.repetitionCount(); c++) {
+            Options opt = new OptionsBuilder()
+                    .include(Fixtures.getTestMask(this.getClass()))
+                    .shouldFailOnError(true)
+                    .syncIterations(false)
+                    .build();
+            new Runner(opt).run();
+
+
+            Assert.assertTrue(s3setup + " < " + s2setup, s3setup < s2setup);
+            Assert.assertTrue(s2setup + " < " + s1setup, s2setup < s1setup);
+            Assert.assertTrue(s1setup + " < " + run, s1setup < run);
+
+            Assert.assertTrue(run + " < " + s1teardown, run < s1teardown);
+            Assert.assertTrue(s1teardown + " < " + s2teardown, s1teardown < s2teardown);
+            Assert.assertTrue(s2teardown + " < " + s3teardown, s2teardown < s3teardown);
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jmh-core-it/src/test/java/org/openjdk/jmh/it/dagorder/MixedBTGTrialDagOrderTest.java	Wed Jan 17 11:53:49 2018 +0100
@@ -0,0 +1,124 @@
+/*
+ * Copyright (c) 2005, 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package org.openjdk.jmh.it.dagorder;
+
+import junit.framework.Assert;
+import org.junit.Test;
+import org.openjdk.jmh.annotations.*;
+import org.openjdk.jmh.it.Fixtures;
+import org.openjdk.jmh.runner.Runner;
+import org.openjdk.jmh.runner.RunnerException;
+import org.openjdk.jmh.runner.options.Options;
+import org.openjdk.jmh.runner.options.OptionsBuilder;
+
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicInteger;
+
+/**
+ * Tests global setup -> run -> tearDown sequence.
+ */
+public class MixedBTGTrialDagOrderTest {
+
+    public static final AtomicInteger TICKER = new AtomicInteger();
+
+    private static volatile int s1setup, s1teardown;
+    private static volatile int s2setup, s2teardown;
+    private static volatile int s3setup, s3teardown;
+    private static volatile int run;
+
+    @State(Scope.Group)
+    public static class S3 {
+
+        @Setup(Level.Trial)
+        public void setupInstance() {
+            s3setup = TICKER.incrementAndGet();
+        }
+
+        @TearDown(Level.Trial)
+        public void tearDownInstance() {
+            s3teardown = TICKER.incrementAndGet();
+        }
+    }
+
+    @State(Scope.Thread)
+    public static class S2 {
+
+        @Setup(Level.Trial)
+        public void setupInstance(S3 s3) {
+            s2setup = TICKER.incrementAndGet();
+        }
+
+        @TearDown(Level.Trial)
+        public void tearDownInstance() {
+            s2teardown = TICKER.incrementAndGet();
+        }
+    }
+
+    @State(Scope.Benchmark)
+    public static class S1 {
+
+        @Setup(Level.Trial)
+        public void setupInstance(S2 s2) {
+            s1setup = TICKER.incrementAndGet();
+        }
+
+        @TearDown(Level.Trial)
+        public void tearDownInstance() {
+            s1teardown = TICKER.incrementAndGet();
+        }
+    }
+
+    @Benchmark
+    @BenchmarkMode(Mode.All)
+    @Warmup(iterations = 0)
+    @Measurement(iterations = 1, time = 100, timeUnit = TimeUnit.MILLISECONDS)
+    @Fork(0)
+    @Threads(1)
+    public void test(S1 state) {
+        run = TICKER.incrementAndGet();
+        Fixtures.work();
+    }
+
+    @Test
+    public void invokeAPI() throws RunnerException {
+        for (int c = 0; c < Fixtures.repetitionCount(); c++) {
+            Options opt = new OptionsBuilder()
+                    .include(Fixtures.getTestMask(this.getClass()))
+                    .shouldFailOnError(true)
+                    .syncIterations(false)
+                    .build();
+            new Runner(opt).run();
+
+
+            Assert.assertTrue(s3setup + " < " + s2setup, s3setup < s2setup);
+            Assert.assertTrue(s2setup + " < " + s1setup, s2setup < s1setup);
+            Assert.assertTrue(s1setup + " < " + run, s1setup < run);
+
+            Assert.assertTrue(run + " < " + s1teardown, run < s1teardown);
+            Assert.assertTrue(s1teardown + " < " + s2teardown, s1teardown < s2teardown);
+            Assert.assertTrue(s2teardown + " < " + s3teardown, s2teardown < s3teardown);
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jmh-core-it/src/test/java/org/openjdk/jmh/it/dagorder/MixedGBTIterationDagOrderTest.java	Wed Jan 17 11:53:49 2018 +0100
@@ -0,0 +1,125 @@
+/*
+ * Copyright (c) 2005, 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package org.openjdk.jmh.it.dagorder;
+
+import junit.framework.Assert;
+import org.junit.Test;
+import org.openjdk.jmh.annotations.*;
+import org.openjdk.jmh.it.Fixtures;
+import org.openjdk.jmh.runner.Runner;
+import org.openjdk.jmh.runner.RunnerException;
+import org.openjdk.jmh.runner.options.Options;
+import org.openjdk.jmh.runner.options.OptionsBuilder;
+
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicInteger;
+
+/**
+ * Tests global setup -> run -> tearDown sequence.
+ */
+public class MixedGBTIterationDagOrderTest {
+
+    public static final AtomicInteger TICKER = new AtomicInteger();
+
+    private static volatile int s1setup, s1teardown;
+    private static volatile int s2setup, s2teardown;
+    private static volatile int s3setup, s3teardown;
+    private static volatile int run;
+
+    @State(Scope.Thread)
+    public static class S3 {
+
+        @Setup(Level.Iteration)
+        public void setupInstance() {
+            s3setup = TICKER.incrementAndGet();
+        }
+
+        @TearDown(Level.Iteration)
+        public void tearDownInstance() {
+            s3teardown = TICKER.incrementAndGet();
+        }
+    }
+
+    @State(Scope.Benchmark)
+    public static class S2 {
+
+        @Setup(Level.Iteration)
+        public void setupInstance(S3 s3) {
+            s2setup = TICKER.incrementAndGet();
+        }
+
+        @TearDown(Level.Iteration)
+        public void tearDownInstance() {
+            s2teardown = TICKER.incrementAndGet();
+        }
+    }
+
+    @State(Scope.Group)
+    public static class S1 {
+
+        @Setup(Level.Iteration)
+        public void setupInstance(S2 s2) {
+            s1setup = TICKER.incrementAndGet();
+        }
+
+        @TearDown(Level.Iteration)
+        public void tearDownInstance() {
+            s1teardown = TICKER.incrementAndGet();
+        }
+    }
+
+    @Benchmark
+    @BenchmarkMode(Mode.All)
+    @Warmup(iterations = 0)
+    @Measurement(iterations = 1, time = 100, timeUnit = TimeUnit.MILLISECONDS)
+    @Fork(0)
+    @GroupThreads(1)
+    @Group
+    public void test(S1 state) {
+        run = TICKER.incrementAndGet();
+        Fixtures.work();
+    }
+
+    @Test
+    public void invokeAPI() throws RunnerException {
+        for (int c = 0; c < Fixtures.repetitionCount(); c++) {
+            Options opt = new OptionsBuilder()
+                    .include(Fixtures.getTestMask(this.getClass()))
+                    .shouldFailOnError(true)
+                    .syncIterations(false)
+                    .build();
+            new Runner(opt).run();
+
+
+            Assert.assertTrue(s3setup + " < " + s2setup, s3setup < s2setup);
+            Assert.assertTrue(s2setup + " < " + s1setup, s2setup < s1setup);
+            Assert.assertTrue(s1setup + " < " + run, s1setup < run);
+
+            Assert.assertTrue(run + " < " + s1teardown, run < s1teardown);
+            Assert.assertTrue(s1teardown + " < " + s2teardown, s1teardown < s2teardown);
+            Assert.assertTrue(s2teardown + " < " + s3teardown, s2teardown < s3teardown);
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jmh-core-it/src/test/java/org/openjdk/jmh/it/dagorder/MixedGBTTrialDagOrderTest.java	Wed Jan 17 11:53:49 2018 +0100
@@ -0,0 +1,125 @@
+/*
+ * Copyright (c) 2005, 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package org.openjdk.jmh.it.dagorder;
+
+import junit.framework.Assert;
+import org.junit.Test;
+import org.openjdk.jmh.annotations.*;
+import org.openjdk.jmh.it.Fixtures;
+import org.openjdk.jmh.runner.Runner;
+import org.openjdk.jmh.runner.RunnerException;
+import org.openjdk.jmh.runner.options.Options;
+import org.openjdk.jmh.runner.options.OptionsBuilder;
+
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicInteger;
+
+/**
+ * Tests global setup -> run -> tearDown sequence.
+ */
+public class MixedGBTTrialDagOrderTest {
+
+    public static final AtomicInteger TICKER = new AtomicInteger();
+
+    private static volatile int s1setup, s1teardown;
+    private static volatile int s2setup, s2teardown;
+    private static volatile int s3setup, s3teardown;
+    private static volatile int run;
+
+    @State(Scope.Thread)
+    public static class S3 {
+
+        @Setup(Level.Trial)
+        public void setupInstance() {
+            s3setup = TICKER.incrementAndGet();
+        }
+
+        @TearDown(Level.Trial)
+        public void tearDownInstance() {
+            s3teardown = TICKER.incrementAndGet();
+        }
+    }
+
+    @State(Scope.Benchmark)
+    public static class S2 {
+
+        @Setup(Level.Trial)
+        public void setupInstance(S3 s3) {
+            s2setup = TICKER.incrementAndGet();
+        }
+
+        @TearDown(Level.Trial)
+        public void tearDownInstance() {
+            s2teardown = TICKER.incrementAndGet();
+        }
+    }
+
+    @State(Scope.Group)
+    public static class S1 {
+
+        @Setup(Level.Trial)
+        public void setupInstance(S2 s2) {
+            s1setup = TICKER.incrementAndGet();
+        }
+
+        @TearDown(Level.Trial)
+        public void tearDownInstance() {
+            s1teardown = TICKER.incrementAndGet();
+        }
+    }
+
+    @Benchmark
+    @BenchmarkMode(Mode.All)
+    @Warmup(iterations = 0)
+    @Measurement(iterations = 1, time = 100, timeUnit = TimeUnit.MILLISECONDS)
+    @Fork(0)
+    @GroupThreads(1)
+    @Group
+    public void test(S1 state) {
+        run = TICKER.incrementAndGet();
+        Fixtures.work();
+    }
+
+    @Test
+    public void invokeAPI() throws RunnerException {
+        for (int c = 0; c < Fixtures.repetitionCount(); c++) {
+            Options opt = new OptionsBuilder()
+                    .include(Fixtures.getTestMask(this.getClass()))
+                    .shouldFailOnError(true)
+                    .syncIterations(false)
+                    .build();
+            new Runner(opt).run();
+
+
+            Assert.assertTrue(s3setup + " < " + s2setup, s3setup < s2setup);
+            Assert.assertTrue(s2setup + " < " + s1setup, s2setup < s1setup);
+            Assert.assertTrue(s1setup + " < " + run, s1setup < run);
+
+            Assert.assertTrue(run + " < " + s1teardown, run < s1teardown);
+            Assert.assertTrue(s1teardown + " < " + s2teardown, s1teardown < s2teardown);
+            Assert.assertTrue(s2teardown + " < " + s3teardown, s2teardown < s3teardown);
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jmh-core-it/src/test/java/org/openjdk/jmh/it/dagorder/MixedGTBIterationDagOrderTest.java	Wed Jan 17 11:53:49 2018 +0100
@@ -0,0 +1,125 @@
+/*
+ * Copyright (c) 2005, 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package org.openjdk.jmh.it.dagorder;
+
+import junit.framework.Assert;
+import org.junit.Test;
+import org.openjdk.jmh.annotations.*;
+import org.openjdk.jmh.it.Fixtures;
+import org.openjdk.jmh.runner.Runner;
+import org.openjdk.jmh.runner.RunnerException;
+import org.openjdk.jmh.runner.options.Options;
+import org.openjdk.jmh.runner.options.OptionsBuilder;
+
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicInteger;
+
+/**
+ * Tests global setup -> run -> tearDown sequence.
+ */
+public class MixedGTBIterationDagOrderTest {
+
+    public static final AtomicInteger TICKER = new AtomicInteger();
+
+    private static volatile int s1setup, s1teardown;
+    private static volatile int s2setup, s2teardown;
+    private static volatile int s3setup, s3teardown;
+    private static volatile int run;
+
+    @State(Scope.Benchmark)
+    public static class S3 {
+
+        @Setup(Level.Iteration)
+        public void setupInstance() {
+            s3setup = TICKER.incrementAndGet();
+        }
+
+        @TearDown(Level.Iteration)
+        public void tearDownInstance() {
+            s3teardown = TICKER.incrementAndGet();
+        }
+    }
+
+    @State(Scope.Thread)
+    public static class S2 {
+
+        @Setup(Level.Iteration)
+        public void setupInstance(S3 s3) {
+            s2setup = TICKER.incrementAndGet();
+        }
+
+        @TearDown(Level.Iteration)
+        public void tearDownInstance() {
+            s2teardown = TICKER.incrementAndGet();
+        }
+    }
+
+    @State(Scope.Group)
+    public static class S1 {
+
+        @Setup(Level.Iteration)
+        public void setupInstance(S2 s2) {
+            s1setup = TICKER.incrementAndGet();
+        }
+
+        @TearDown(Level.Iteration)
+        public void tearDownInstance() {
+            s1teardown = TICKER.incrementAndGet();
+        }
+    }
+
+    @Benchmark
+    @BenchmarkMode(Mode.All)
+    @Warmup(iterations = 0)
+    @Measurement(iterations = 1, time = 100, timeUnit = TimeUnit.MILLISECONDS)
+    @Fork(0)
+    @GroupThreads(1)
+    @Group
+    public void test(S1 state) {
+        run = TICKER.incrementAndGet();
+        Fixtures.work();
+    }
+
+    @Test
+    public void invokeAPI() throws RunnerException {
+        for (int c = 0; c < Fixtures.repetitionCount(); c++) {
+            Options opt = new OptionsBuilder()
+                    .include(Fixtures.getTestMask(this.getClass()))
+                    .shouldFailOnError(true)
+                    .syncIterations(false)
+                    .build();
+            new Runner(opt).run();
+
+
+            Assert.assertTrue(s3setup + " < " + s2setup, s3setup < s2setup);
+            Assert.assertTrue(s2setup + " < " + s1setup, s2setup < s1setup);
+            Assert.assertTrue(s1setup + " < " + run, s1setup < run);
+
+            Assert.assertTrue(run + " < " + s1teardown, run < s1teardown);
+            Assert.assertTrue(s1teardown + " < " + s2teardown, s1teardown < s2teardown);
+            Assert.assertTrue(s2teardown + " < " + s3teardown, s2teardown < s3teardown);
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jmh-core-it/src/test/java/org/openjdk/jmh/it/dagorder/MixedGTBTrialDagOrderTest.java	Wed Jan 17 11:53:49 2018 +0100
@@ -0,0 +1,125 @@
+/*
+ * Copyright (c) 2005, 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package org.openjdk.jmh.it.dagorder;
+
+import junit.framework.Assert;
+import org.junit.Test;
+import org.openjdk.jmh.annotations.*;
+import org.openjdk.jmh.it.Fixtures;
+import org.openjdk.jmh.runner.Runner;
+import org.openjdk.jmh.runner.RunnerException;
+import org.openjdk.jmh.runner.options.Options;
+import org.openjdk.jmh.runner.options.OptionsBuilder;
+
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicInteger;
+
+/**
+ * Tests global setup -> run -> tearDown sequence.
+ */
+public class MixedGTBTrialDagOrderTest {
+
+    public static final AtomicInteger TICKER = new AtomicInteger();
+
+    private static volatile int s1setup, s1teardown;
+    private static volatile int s2setup, s2teardown;
+    private static volatile int s3setup, s3teardown;
+    private static volatile int run;
+
+    @State(Scope.Benchmark)
+    public static class S3 {
+
+        @Setup(Level.Trial)
+        public void setupInstance() {
+            s3setup = TICKER.incrementAndGet();
+        }
+
+        @TearDown(Level.Trial)
+        public void tearDownInstance() {
+            s3teardown = TICKER.incrementAndGet();
+        }
+    }
+
+    @State(Scope.Thread)
+    public static class S2 {
+
+        @Setup(Level.Trial)
+        public void setupInstance(S3 s3) {
+            s2setup = TICKER.incrementAndGet();
+        }
+
+        @TearDown(Level.Trial)
+        public void tearDownInstance() {
+            s2teardown = TICKER.incrementAndGet();
+        }
+    }
+
+    @State(Scope.Group)
+    public static class S1 {
+
+        @Setup(Level.Trial)
+        public void setupInstance(S2 s2) {
+            s1setup = TICKER.incrementAndGet();
+        }
+
+        @TearDown(Level.Trial)
+        public void tearDownInstance() {
+            s1teardown = TICKER.incrementAndGet();
+        }
+    }
+
+    @Benchmark
+    @BenchmarkMode(Mode.All)
+    @Warmup(iterations = 0)
+    @Measurement(iterations = 1, time = 100, timeUnit = TimeUnit.MILLISECONDS)
+    @Fork(0)
+    @GroupThreads(1)
+    @Group
+    public void test(S1 state) {
+        run = TICKER.incrementAndGet();
+        Fixtures.work();
+    }
+
+    @Test
+    public void invokeAPI() throws RunnerException {
+        for (int c = 0; c < Fixtures.repetitionCount(); c++) {
+            Options opt = new OptionsBuilder()
+                    .include(Fixtures.getTestMask(this.getClass()))
+                    .shouldFailOnError(true)
+                    .syncIterations(false)
+                    .build();
+            new Runner(opt).run();
+
+
+            Assert.assertTrue(s3setup + " < " + s2setup, s3setup < s2setup);
+            Assert.assertTrue(s2setup + " < " + s1setup, s2setup < s1setup);
+            Assert.assertTrue(s1setup + " < " + run, s1setup < run);
+
+            Assert.assertTrue(run + " < " + s1teardown, run < s1teardown);
+            Assert.assertTrue(s1teardown + " < " + s2teardown, s1teardown < s2teardown);
+            Assert.assertTrue(s2teardown + " < " + s3teardown, s2teardown < s3teardown);
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jmh-core-it/src/test/java/org/openjdk/jmh/it/dagorder/MixedTBGIterationDagOrderTest.java	Wed Jan 17 11:53:49 2018 +0100
@@ -0,0 +1,124 @@
+/*
+ * Copyright (c) 2005, 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package org.openjdk.jmh.it.dagorder;
+
+import junit.framework.Assert;
+import org.junit.Test;
+import org.openjdk.jmh.annotations.*;
+import org.openjdk.jmh.it.Fixtures;
+import org.openjdk.jmh.runner.Runner;
+import org.openjdk.jmh.runner.RunnerException;
+import org.openjdk.jmh.runner.options.Options;
+import org.openjdk.jmh.runner.options.OptionsBuilder;
+
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicInteger;
+
+/**
+ * Tests global setup -> run -> tearDown sequence.
+ */
+public class MixedTBGIterationDagOrderTest {
+
+    public static final AtomicInteger TICKER = new AtomicInteger();
+
+    private static volatile int s1setup, s1teardown;
+    private static volatile int s2setup, s2teardown;
+    private static volatile int s3setup, s3teardown;
+    private static volatile int run;
+
+    @State(Scope.Group)
+    public static class S3 {
+
+        @Setup(Level.Iteration)
+        public void setupInstance() {
+            s3setup = TICKER.incrementAndGet();
+        }
+
+        @TearDown(Level.Iteration)
+        public void tearDownInstance() {
+            s3teardown = TICKER.incrementAndGet();
+        }
+    }
+
+    @State(Scope.Benchmark)
+    public static class S2 {
+
+        @Setup(Level.Iteration)
+        public void setupInstance(S3 s3) {
+            s2setup = TICKER.incrementAndGet();
+        }
+
+        @TearDown(Level.Iteration)
+        public void tearDownInstance() {
+            s2teardown = TICKER.incrementAndGet();
+        }
+    }
+
+    @State(Scope.Thread)
+    public static class S1 {
+
+        @Setup(Level.Iteration)
+        public void setupInstance(S2 s2) {
+            s1setup = TICKER.incrementAndGet();
+        }
+
+        @TearDown(Level.Iteration)
+        public void tearDownInstance() {
+            s1teardown = TICKER.incrementAndGet();
+        }
+    }
+
+    @Benchmark
+    @BenchmarkMode(Mode.All)
+    @Warmup(iterations = 0)
+    @Measurement(iterations = 1, time = 100, timeUnit = TimeUnit.MILLISECONDS)
+    @Fork(0)
+    @Threads(1)
+    public void test(S1 state) {
+        run = TICKER.incrementAndGet();
+        Fixtures.work();
+    }
+
+    @Test
+    public void invokeAPI() throws RunnerException {
+        for (int c = 0; c < Fixtures.repetitionCount(); c++) {
+            Options opt = new OptionsBuilder()
+                    .include(Fixtures.getTestMask(this.getClass()))
+                    .shouldFailOnError(true)
+                    .syncIterations(false)
+                    .build();
+            new Runner(opt).run();
+
+
+            Assert.assertTrue(s3setup + " < " + s2setup, s3setup < s2setup);
+            Assert.assertTrue(s2setup + " < " + s1setup, s2setup < s1setup);
+            Assert.assertTrue(s1setup + " < " + run, s1setup < run);
+
+            Assert.assertTrue(run + " < " + s1teardown, run < s1teardown);
+            Assert.assertTrue(s1teardown + " < " + s2teardown, s1teardown < s2teardown);
+            Assert.assertTrue(s2teardown + " < " + s3teardown, s2teardown < s3teardown);
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jmh-core-it/src/test/java/org/openjdk/jmh/it/dagorder/MixedTBGTrialDagOrderTest.java	Wed Jan 17 11:53:49 2018 +0100
@@ -0,0 +1,124 @@
+/*
+ * Copyright (c) 2005, 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package org.openjdk.jmh.it.dagorder;
+
+import junit.framework.Assert;
+import org.junit.Test;
+import org.openjdk.jmh.annotations.*;
+import org.openjdk.jmh.it.Fixtures;
+import org.openjdk.jmh.runner.Runner;
+import org.openjdk.jmh.runner.RunnerException;
+import org.openjdk.jmh.runner.options.Options;
+import org.openjdk.jmh.runner.options.OptionsBuilder;
+
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicInteger;
+
+/**
+ * Tests global setup -> run -> tearDown sequence.
+ */
+public class MixedTBGTrialDagOrderTest {
+
+    public static final AtomicInteger TICKER = new AtomicInteger();
+
+    private static volatile int s1setup, s1teardown;
+    private static volatile int s2setup, s2teardown;
+    private static volatile int s3setup, s3teardown;
+    private static volatile int run;
+
+    @State(Scope.Group)
+    public static class S3 {
+
+        @Setup(Level.Trial)
+        public void setupInstance() {
+            s3setup = TICKER.incrementAndGet();
+        }
+
+        @TearDown(Level.Trial)
+        public void tearDownInstance() {
+            s3teardown = TICKER.incrementAndGet();
+        }
+    }
+
+    @State(Scope.Benchmark)
+    public static class S2 {
+
+        @Setup(Level.Trial)
+        public void setupInstance(S3 s3) {
+            s2setup = TICKER.incrementAndGet();
+        }
+
+        @TearDown(Level.Trial)
+        public void tearDownInstance() {
+            s2teardown = TICKER.incrementAndGet();
+        }
+    }
+
+    @State(Scope.Thread)
+    public static class S1 {
+
+        @Setup(Level.Trial)
+        public void setupInstance(S2 s2) {
+            s1setup = TICKER.incrementAndGet();
+        }
+
+        @TearDown(Level.Trial)
+        public void tearDownInstance() {
+            s1teardown = TICKER.incrementAndGet();
+        }
+    }
+
+    @Benchmark
+    @BenchmarkMode(Mode.All)
+    @Warmup(iterations = 0)
+    @Measurement(iterations = 1, time = 100, timeUnit = TimeUnit.MILLISECONDS)
+    @Fork(0)
+    @Threads(1)
+    public void test(S1 state) {
+        run = TICKER.incrementAndGet();
+        Fixtures.work();
+    }
+
+    @Test
+    public void invokeAPI() throws RunnerException {
+        for (int c = 0; c < Fixtures.repetitionCount(); c++) {
+            Options opt = new OptionsBuilder()
+                    .include(Fixtures.getTestMask(this.getClass()))
+                    .shouldFailOnError(true)
+                    .syncIterations(false)
+                    .build();
+            new Runner(opt).run();
+
+
+            Assert.assertTrue(s3setup + " < " + s2setup, s3setup < s2setup);
+            Assert.assertTrue(s2setup + " < " + s1setup, s2setup < s1setup);
+            Assert.assertTrue(s1setup + " < " + run, s1setup < run);
+
+            Assert.assertTrue(run + " < " + s1teardown, run < s1teardown);
+            Assert.assertTrue(s1teardown + " < " + s2teardown, s1teardown < s2teardown);
+            Assert.assertTrue(s2teardown + " < " + s3teardown, s2teardown < s3teardown);
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jmh-core-it/src/test/java/org/openjdk/jmh/it/dagorder/MixedTGBIterationDagOrderTest.java	Wed Jan 17 11:53:49 2018 +0100
@@ -0,0 +1,124 @@
+/*
+ * Copyright (c) 2005, 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package org.openjdk.jmh.it.dagorder;
+
+import junit.framework.Assert;
+import org.junit.Test;
+import org.openjdk.jmh.annotations.*;
+import org.openjdk.jmh.it.Fixtures;
+import org.openjdk.jmh.runner.Runner;
+import org.openjdk.jmh.runner.RunnerException;
+import org.openjdk.jmh.runner.options.Options;
+import org.openjdk.jmh.runner.options.OptionsBuilder;
+
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicInteger;
+
+/**
+ * Tests global setup -> run -> tearDown sequence.
+ */
+public class MixedTGBIterationDagOrderTest {
+
+    public static final AtomicInteger TICKER = new AtomicInteger();
+
+    private static volatile int s1setup, s1teardown;
+    private static volatile int s2setup, s2teardown;
+    private static volatile int s3setup, s3teardown;
+    private static volatile int run;
+
+    @State(Scope.Benchmark)
+    public static class S3 {
+
+        @Setup(Level.Iteration)
+        public void setupInstance() {
+            s3setup = TICKER.incrementAndGet();
+        }
+
+        @TearDown(Level.Iteration)
+        public void tearDownInstance() {
+            s3teardown = TICKER.incrementAndGet();
+        }
+    }
+
+    @State(Scope.Group)
+    public static class S2 {
+
+        @Setup(Level.Iteration)
+        public void setupInstance(S3 s3) {
+            s2setup = TICKER.incrementAndGet();
+        }
+
+        @TearDown(Level.Iteration)
+        public void tearDownInstance() {
+            s2teardown = TICKER.incrementAndGet();
+        }
+    }
+
+    @State(Scope.Thread)
+    public static class S1 {
+
+        @Setup(Level.Iteration)
+        public void setupInstance(S2 s2) {
+            s1setup = TICKER.incrementAndGet();
+        }
+
+        @TearDown(Level.Iteration)
+        public void tearDownInstance() {
+            s1teardown = TICKER.incrementAndGet();
+        }
+    }
+
+    @Benchmark
+    @BenchmarkMode(Mode.All)
+    @Warmup(iterations = 0)
+    @Measurement(iterations = 1, time = 100, timeUnit = TimeUnit.MILLISECONDS)
+    @Fork(0)
+    @Threads(1)
+    public void test(S1 state) {
+        run = TICKER.incrementAndGet();
+        Fixtures.work();
+    }
+
+    @Test
+    public void invokeAPI() throws RunnerException {
+        for (int c = 0; c < Fixtures.repetitionCount(); c++) {
+            Options opt = new OptionsBuilder()
+                    .include(Fixtures.getTestMask(this.getClass()))
+                    .shouldFailOnError(true)
+                    .syncIterations(false)
+                    .build();
+            new Runner(opt).run();
+
+
+            Assert.assertTrue(s3setup + " < " + s2setup, s3setup < s2setup);
+            Assert.assertTrue(s2setup + " < " + s1setup, s2setup < s1setup);
+            Assert.assertTrue(s1setup + " < " + run, s1setup < run);
+
+            Assert.assertTrue(run + " < " + s1teardown, run < s1teardown);
+            Assert.assertTrue(s1teardown + " < " + s2teardown, s1teardown < s2teardown);
+            Assert.assertTrue(s2teardown + " < " + s3teardown, s2teardown < s3teardown);
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jmh-core-it/src/test/java/org/openjdk/jmh/it/dagorder/MixedTGBTrialDagOrderTest.java	Wed Jan 17 11:53:49 2018 +0100
@@ -0,0 +1,124 @@
+/*
+ * Copyright (c) 2005, 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package org.openjdk.jmh.it.dagorder;
+
+import junit.framework.Assert;
+import org.junit.Test;
+import org.openjdk.jmh.annotations.*;
+import org.openjdk.jmh.it.Fixtures;
+import org.openjdk.jmh.runner.Runner;
+import org.openjdk.jmh.runner.RunnerException;
+import org.openjdk.jmh.runner.options.Options;
+import org.openjdk.jmh.runner.options.OptionsBuilder;
+
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicInteger;
+
+/**
+ * Tests global setup -> run -> tearDown sequence.
+ */
+public class MixedTGBTrialDagOrderTest {
+
+    public static final AtomicInteger TICKER = new AtomicInteger();
+
+    private static volatile int s1setup, s1teardown;
+    private static volatile int s2setup, s2teardown;
+    private static volatile int s3setup, s3teardown;
+    private static volatile int run;
+
+    @State(Scope.Benchmark)
+    public static class S3 {
+
+        @Setup(Level.Trial)
+        public void setupInstance() {
+            s3setup = TICKER.incrementAndGet();
+        }
+
+        @TearDown(Level.Trial)
+        public void tearDownInstance() {
+            s3teardown = TICKER.incrementAndGet();
+        }
+    }
+
+    @State(Scope.Group)
+    public static class S2 {
+
+        @Setup(Level.Trial)
+        public void setupInstance(S3 s3) {
+            s2setup = TICKER.incrementAndGet();
+        }
+
+        @TearDown(Level.Trial)
+        public void tearDownInstance() {
+            s2teardown = TICKER.incrementAndGet();
+        }
+    }
+
+    @State(Scope.Thread)
+    public static class S1 {
+
+        @Setup(Level.Trial)
+        public void setupInstance(S2 s2) {
+            s1setup = TICKER.incrementAndGet();
+        }
+
+        @TearDown(Level.Trial)
+        public void tearDownInstance() {
+            s1teardown = TICKER.incrementAndGet();
+        }
+    }
+
+    @Benchmark
+    @BenchmarkMode(Mode.All)
+    @Warmup(iterations = 0)
+    @Measurement(iterations = 1, time = 100, timeUnit = TimeUnit.MILLISECONDS)
+    @Fork(0)
+    @Threads(1)
+    public void test(S1 state) {
+        run = TICKER.incrementAndGet();
+        Fixtures.work();
+    }
+
+    @Test
+    public void invokeAPI() throws RunnerException {
+        for (int c = 0; c < Fixtures.repetitionCount(); c++) {
+            Options opt = new OptionsBuilder()
+                    .include(Fixtures.getTestMask(this.getClass()))
+                    .shouldFailOnError(true)
+                    .syncIterations(false)
+                    .build();
+            new Runner(opt).run();
+
+
+            Assert.assertTrue(s3setup + " < " + s2setup, s3setup < s2setup);
+            Assert.assertTrue(s2setup + " < " + s1setup, s2setup < s1setup);
+            Assert.assertTrue(s1setup + " < " + run, s1setup < run);
+
+            Assert.assertTrue(run + " < " + s1teardown, run < s1teardown);
+            Assert.assertTrue(s1teardown + " < " + s2teardown, s1teardown < s2teardown);
+            Assert.assertTrue(s2teardown + " < " + s3teardown, s2teardown < s3teardown);
+        }
+    }
+}
--- a/jmh-core/src/main/java/org/openjdk/jmh/generators/core/StateObjectHandler.java	Tue Jan 16 12:13:36 2018 +0100
+++ b/jmh-core/src/main/java/org/openjdk/jmh/generators/core/StateObjectHandler.java	Wed Jan 17 11:53:49 2018 +0100
@@ -588,9 +588,9 @@
 
         // Handle Thread object helpers
         for (StateObject so : statesForward) {
-            if (so.scope != Scope.Thread) continue;
+            if (type != HelperType.SETUP) continue;
 
-            if (type == HelperType.SETUP) {
+            if (so.scope == Scope.Thread) {
                 for (HelperMethodInvocation mi : so.getHelpers()) {
                     if (mi.helperLevel == helperLevel && mi.type == HelperType.SETUP) {
                         Collection<String> args = so.helperArgs.get(mi.method.getQualifiedName());
@@ -598,26 +598,8 @@
                     }
                 }
             }
-        }
 
-        for (StateObject so : statesReverse) {
-            if (so.scope != Scope.Thread) continue;
-
-            if (type == HelperType.TEARDOWN) {
-                for (HelperMethodInvocation mi : so.getHelpers()) {
-                    if (mi.helperLevel == helperLevel && mi.type == HelperType.TEARDOWN) {
-                        Collection<String> args = so.helperArgs.get(mi.method.getQualifiedName());
-                        result.add(so.localIdentifier + "." + mi.method.getName() + "(" + Utils.join(args, ",") + ");");
-                    }
-                }
-            }
-        }
-
-        // Handle Benchmark/Group object helpers
-        for (StateObject so : statesForward) {
-            if (so.scope != Scope.Benchmark && so.scope != Scope.Group) continue;
-
-            if (type == HelperType.SETUP) {
+            if (so.scope == Scope.Benchmark || so.scope == Scope.Group) {
                 result.add("if (" + so.type + ".setup" + helperLevel + "MutexUpdater.compareAndSet(" + so.localIdentifier + ", 0, 1)) {");
                 result.add("    try {");
                 result.add("        if (control.isFailing) throw new FailureAssistException();");
@@ -646,9 +628,18 @@
         }
 
         for (StateObject so : statesReverse) {
-            if (so.scope != Scope.Benchmark && so.scope != Scope.Group) continue;
+            if (type != HelperType.TEARDOWN) continue;
 
-            if (type == HelperType.TEARDOWN) {
+            if (so.scope == Scope.Thread) {
+                for (HelperMethodInvocation mi : so.getHelpers()) {
+                    if (mi.helperLevel == helperLevel && mi.type == HelperType.TEARDOWN) {
+                        Collection<String> args = so.helperArgs.get(mi.method.getQualifiedName());
+                        result.add(so.localIdentifier + "." + mi.method.getName() + "(" + Utils.join(args, ",") + ");");
+                    }
+                }
+            }
+
+            if (so.scope == Scope.Benchmark || so.scope == Scope.Group) {
                 result.add("if (" + so.type + ".tear" + helperLevel + "MutexUpdater.compareAndSet(" + so.localIdentifier + ", 0, 1)) {");
                 result.add("    try {");
                 result.add("        if (control.isFailing) throw new FailureAssistException();");