changeset 17871:665bbe93823f

8039499: Add all common classes used by tests on RTM support to testlibrary Reviewed-by: kvn, iignatyev Contributed-by: filipp.zhinkin@oracle.com
author iignatyev
date Mon, 14 Apr 2014 19:29:34 +0400
parents a0eb3f61d34a
children 100f2b109432
files test/compiler/testlibrary/rtm/AbortProvoker.java test/compiler/testlibrary/rtm/AbortType.java test/compiler/testlibrary/rtm/BufferOverflowProvoker.java test/compiler/testlibrary/rtm/BusyLock.java test/compiler/testlibrary/rtm/CompilableTest.java test/compiler/testlibrary/rtm/MemoryConflictProvoker.java test/compiler/testlibrary/rtm/NestedAbortProvoker.java test/compiler/testlibrary/rtm/RTMLockingStatistics.java test/compiler/testlibrary/rtm/RTMTestBase.java test/compiler/testlibrary/rtm/XAbortProvoker.java test/compiler/testlibrary/rtm/predicate/SupportedCPU.java test/compiler/testlibrary/rtm/predicate/SupportedVM.java test/testlibrary/com/oracle/java/testlibrary/cli/CPUSpecificCommandLineOptionTest.java test/testlibrary/com/oracle/java/testlibrary/cli/CommandLineOptionTest.java test/testlibrary/com/oracle/java/testlibrary/cli/predicate/AndPredicate.java test/testlibrary/com/oracle/java/testlibrary/cli/predicate/CPUSpecificPredicate.java test/testlibrary/com/oracle/java/testlibrary/cli/predicate/NotPredicate.java test/testlibrary/com/oracle/java/testlibrary/cli/predicate/OrPredicate.java
diffstat 18 files changed, 1730 insertions(+), 122 deletions(-) [+]
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/compiler/testlibrary/rtm/AbortProvoker.java	Mon Apr 14 19:29:34 2014 +0400
@@ -0,0 +1,172 @@
+/*
+ * Copyright (c) 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.
+ *
+ * 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 rtm;
+
+import java.util.Objects;
+import java.util.concurrent.BrokenBarrierException;
+import java.util.concurrent.CyclicBarrier;
+
+import com.oracle.java.testlibrary.Asserts;
+import com.oracle.java.testlibrary.Utils;
+import sun.misc.Unsafe;
+
+/**
+ * Base class for different transactional execution abortion
+ * provokers aimed to force abort due to specified reason.
+ */
+public abstract class AbortProvoker implements CompilableTest {
+    public static final long DEFAULT_ITERATIONS = 10000L;
+    /**
+     * Inflates monitor associated with object {@code monitor}.
+     * Inflation is forced by entering the same monitor from
+     * two different threads.
+     *
+     * @param monitor monitor to be inflated.
+     * @return inflated monitor.
+     * @throws Exception if something went wrong.
+     */
+    public static Object inflateMonitor(Object monitor) throws Exception {
+        Unsafe unsafe = Utils.getUnsafe();
+        CyclicBarrier barrier = new CyclicBarrier(2);
+
+        Runnable inflatingRunnable = () -> {
+            unsafe.monitorEnter(monitor);
+            try {
+                barrier.await();
+                barrier.await();
+            } catch (InterruptedException | BrokenBarrierException e) {
+                throw new RuntimeException(
+                        "Synchronization issue occurred.", e);
+            } finally {
+                unsafe.monitorExit(monitor);
+            }
+        };
+
+        Thread t = new Thread(inflatingRunnable);
+        t.start();
+        // Wait until thread t enters the monitor.
+        barrier.await();
+        // At this point monitor will be owned by thread t,
+        // so our attempt to enter the same monitor will force
+        // monitor inflation.
+        Asserts.assertFalse(unsafe.tryMonitorEnter(monitor),
+                            "Not supposed to enter the monitor first");
+        barrier.await();
+        t.join();
+        return monitor;
+    }
+
+
+    /**
+     * Get instance of specified AbortProvoker, inflate associated monitor
+     * if needed and then invoke forceAbort method in a loop.
+     *
+     * Usage:
+     * AbortProvoker <AbortType name> [<inflate monitor&gt
+     * [<iterations> [ <delay>]]]
+     *
+     *  Default parameters are:
+     *  <ul>
+     *  <li>inflate monitor = <b>true</b></li>
+     *  <li>iterations = {@code AbortProvoker.DEFAULT_ITERATIONS}</li>
+     *  <li>delay = <b>0</b></li>
+     *  </ul>
+     */
+    public static void main(String args[]) throws Throwable {
+        Asserts.assertGT(args.length, 0, "At least one argument is required.");
+
+        AbortType abortType = AbortType.lookup(Integer.valueOf(args[0]));
+        boolean monitorShouldBeInflated = true;
+        long iterations = AbortProvoker.DEFAULT_ITERATIONS;
+
+        if (args.length > 1) {
+            monitorShouldBeInflated = Boolean.valueOf(args[1]);
+
+            if (args.length > 2) {
+                iterations = Long.valueOf(args[2]);
+
+                if (args.length > 3) {
+                    Thread.sleep(Integer.valueOf(args[3]));
+                }
+            }
+        }
+
+        AbortProvoker provoker = abortType.provoker();
+
+        if (monitorShouldBeInflated) {
+            provoker.inflateMonitor();
+        }
+
+        for (long i = 0; i < iterations; i++) {
+            provoker.forceAbort();
+        }
+    }
+
+    protected final Object monitor;
+
+    protected AbortProvoker() {
+        this(new Object());
+    }
+
+    protected AbortProvoker(Object monitor) {
+        this.monitor = Objects.requireNonNull(monitor);
+    }
+
+    /**
+     * Inflates monitor used by this AbortProvoker instance.
+     * @throws Exception
+     */
+    public void inflateMonitor() throws Exception {
+        AbortProvoker.inflateMonitor(monitor);
+    }
+
+    /**
+     * Forces transactional execution abortion.
+     */
+    public abstract void forceAbort();
+
+    /**
+     * Returns names of all methods that have to be compiled
+     * in order to successfully force transactional execution
+     * abortion.
+     *
+     * @return array with methods' names that have to be compiled.
+     */
+    @Override
+    public String[] getMethodsToCompileNames() {
+        return new String[] { getMethodWithLockName() };
+    }
+
+    /**
+     * Returns name of the method that will contain monitor whose locking
+     * will be elided using transactional execution.
+     *
+     * @return name of the method that will contain elided lock.
+     */
+    @Override
+    public String getMethodWithLockName() {
+        return this.getClass().getName() + "::forceAbort";
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/compiler/testlibrary/rtm/AbortType.java	Mon Apr 14 19:29:34 2014 +0400
@@ -0,0 +1,103 @@
+/*
+ * Copyright (c) 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.
+ *
+ * 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 rtm;
+
+import com.oracle.java.testlibrary.Asserts;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * Type of transactional execution abort.
+ * For more details on different abort types please see
+ * shared/vm/runtime/rtmLocking.hpp
+ */
+public enum AbortType {
+    XABORT(0),
+    RETRIABLE(1),
+    MEM_CONFLICT(2),
+    BUF_OVERFLOW(3),
+    DEBUG_BREAKPOINT(4),
+    NESTED_ABORT(5);
+
+    private final int type;
+    private static final Map<Integer, AbortType> LOOKUP_MAP = new HashMap<>();
+
+    static {
+        for (AbortType abortType : AbortType.values()) {
+            Asserts.assertFalse(LOOKUP_MAP.containsKey(abortType.type),
+                    "Abort type values should be unique.");
+            LOOKUP_MAP.put(abortType.type, abortType);
+        }
+    }
+
+    private AbortType(int type) {
+        this.type = type;
+    }
+
+    /**
+     * Returns AbortProvoker for aborts represented by this abort type.
+     *
+     * @return an AbortProvoker instance
+     */
+    public AbortProvoker provoker() {
+        return AbortType.createNewProvoker(this);
+    }
+
+    public static AbortType lookup(int type) {
+        Asserts.assertLT(type, AbortType.values().length,
+                "Unknown abort type.");
+        return LOOKUP_MAP.get(type);
+    }
+
+    /**
+     * Returns transaction execution abort provoker for specified abortion type.
+     *
+     * @param type a type of abort which will be forced by returned
+     *             AbortProvoker instance.
+     * @return AbortProvoker instance that will force abort of specified type
+     * @throws RuntimeException if there is no provoker for specified type
+     */
+    private static AbortProvoker createNewProvoker(AbortType type) {
+        switch (type) {
+            case XABORT:
+                return new XAbortProvoker();
+            case MEM_CONFLICT:
+                return new MemoryConflictProvoker();
+            case BUF_OVERFLOW:
+                return new BufferOverflowProvoker();
+            case NESTED_ABORT:
+                return new NestedAbortProvoker();
+            default:
+                throw new RuntimeException("No provoker exists for type "
+                        + type.name());
+        }
+    }
+
+    @Override
+    public String toString() {
+        return Integer.toString(type);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/compiler/testlibrary/rtm/BufferOverflowProvoker.java	Mon Apr 14 19:29:34 2014 +0400
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 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.
+ *
+ * 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 rtm;
+
+/**
+ * In order to provoke transactional execution abort due to
+ * internal's buffer overflow BufferOverflowProvoker modifies
+ * 1MB of BYTES during single transaction.
+ */
+class BufferOverflowProvoker extends AbortProvoker {
+    /**
+     * To force buffer overflow abort we modify memory region with
+     * size more then L1d cache size.
+     */
+    private static final int MORE_THAN_L1D_SIZE = 1024 * 1024;
+    private static final byte[] DATA = new byte[MORE_THAN_L1D_SIZE];
+
+    @Override
+    public void forceAbort() {
+        synchronized(monitor) {
+            for (int i = 0; i < BufferOverflowProvoker.DATA.length; i++) {
+                BufferOverflowProvoker.DATA[i]++;
+            }
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/compiler/testlibrary/rtm/BusyLock.java	Mon Apr 14 19:29:34 2014 +0400
@@ -0,0 +1,136 @@
+/*
+ * Copyright (c) 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.
+ *
+ * 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 rtm;
+
+import com.oracle.java.testlibrary.Utils;
+import sun.misc.Unsafe;
+
+import java.util.concurrent.BrokenBarrierException;
+import java.util.concurrent.CyclicBarrier;
+
+/**
+ * Test case for busy lock scenario.
+ * One thread enters the monitor and sleep for a while.
+ * Another thread is blocked on the same monitor.
+ */
+public class BusyLock implements CompilableTest, Runnable {
+    private static final int DEFAULT_TIMEOUT = 1000;
+    private final CyclicBarrier barrier;
+
+    // Following field have to be static in order to avoid escape analysis.
+    @SuppressWarnings("UnsuedDeclaration")
+    private static int field = 0;
+    private static final Unsafe UNSAFE = Utils.getUnsafe();
+    protected final Object monitor;
+    protected final int timeout;
+
+    public BusyLock() {
+        this(BusyLock.DEFAULT_TIMEOUT);
+    }
+
+    public BusyLock(int timeout) {
+        this.timeout = timeout;
+        this.monitor = new Object();
+        this.barrier = new CyclicBarrier(2);
+    }
+
+    @Override
+    public void run() {
+        try {
+            // wait until forceAbort leave monitor
+            barrier.await();
+            if (UNSAFE.tryMonitorEnter(monitor)) {
+                try {
+                    barrier.await();
+                    Thread.sleep(timeout);
+                } finally {
+                    UNSAFE.monitorExit(monitor);
+                }
+            } else {
+                throw new RuntimeException("Monitor should be entered by " +
+                                           "::run() first.");
+            }
+        } catch (InterruptedException | BrokenBarrierException e) {
+            throw new RuntimeException("Synchronization error happened.", e);
+        }
+    }
+
+    public void test() {
+        try {
+            barrier.await();
+            // wait until monitor is locked by a ::run method
+            barrier.await();
+        } catch (InterruptedException | BrokenBarrierException e) {
+            throw new RuntimeException("Synchronization error happened.", e);
+        }
+        synchronized(monitor) {
+            BusyLock.field++;
+        }
+    }
+
+    @Override
+    public String getMethodWithLockName() {
+        return this.getClass().getName() + "::test";
+    }
+
+    @Override
+    public String[] getMethodsToCompileNames() {
+        return new String[] { getMethodWithLockName() };
+    }
+
+    /**
+     * Usage:
+     * BusyLock [ &lt;inflate monitor&gt; [ &lt;timeout&gt; ] ]
+     *
+     * Default values are:
+     * <ul>
+     *     <li>inflate monitor = {@code true}</li>
+     *     <li>timeout = {@code BusyLock.DEFAULT_TIMEOUT}</li>
+     * </ul>
+     */
+    public static void main(String args[]) throws Exception {
+        int timeoutValue = BusyLock.DEFAULT_TIMEOUT;
+        boolean inflateMonitor = true;
+
+        if (args.length > 0 ) {
+            inflateMonitor = Boolean.valueOf(args[0]);
+
+            if (args.length > 1) {
+                timeoutValue = Integer.valueOf(args[1]);
+            }
+        }
+
+        BusyLock busyLock = new BusyLock(timeoutValue);
+
+        if (inflateMonitor) {
+            AbortProvoker.inflateMonitor(busyLock.monitor);
+        }
+
+        Thread t = new Thread(busyLock);
+        t.start();
+        busyLock.test();
+        t.join();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/compiler/testlibrary/rtm/CompilableTest.java	Mon Apr 14 19:29:34 2014 +0400
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 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.
+ *
+ * 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 rtm;
+
+/**
+ * Interface for test scenarios that contain methods
+ * that should be compiled.
+ */
+public interface CompilableTest {
+    /**
+     * @return array with methods' names that should be compiled.
+     */
+    String[] getMethodsToCompileNames();
+
+    /**
+     * @return name of method with RTM-elided lock.
+     */
+    String getMethodWithLockName();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/compiler/testlibrary/rtm/MemoryConflictProvoker.java	Mon Apr 14 19:29:34 2014 +0400
@@ -0,0 +1,100 @@
+/*
+ * Copyright (c) 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.
+ *
+ * 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 rtm;
+
+import java.util.concurrent.BrokenBarrierException;
+import java.util.concurrent.CyclicBarrier;
+
+/**
+ * To force transactional execution abort due to memory conflict
+ * one thread should access memory region from transactional region
+ * while another thread should modify the same memory region.
+ * Since this scenario is based on the race condition between threads
+ * you should not expect some particular amount of aborts.
+ */
+class MemoryConflictProvoker extends AbortProvoker {
+    // Following field have to be static in order to avoid escape analysis.
+    @SuppressWarnings("UnsuedDeclaration")
+    private static int field = 0;
+    private static final int INNER_ITERATIONS = 10000;
+    private final CyclicBarrier barrier;
+    /**
+     * This thread will access and modify memory region
+     * from outside of the transaction.
+     */
+    private final Runnable conflictingThread;
+
+    public MemoryConflictProvoker() {
+        this(new Object());
+    }
+
+    public MemoryConflictProvoker(Object monitor) {
+        super(monitor);
+        barrier = new CyclicBarrier(2);
+        conflictingThread = () -> {
+            try {
+                barrier.await();
+            } catch (Exception e) {
+                throw new RuntimeException(e);
+            }
+            for (int i = 0; i < MemoryConflictProvoker.INNER_ITERATIONS; i++) {
+                MemoryConflictProvoker.field++;
+            }
+        };
+    }
+
+    /**
+     * Accesses and modifies memory region from within the transaction.
+     */
+    public void transactionalRegion() {
+        try {
+            barrier.await();
+        } catch (InterruptedException | BrokenBarrierException e) {
+            throw new RuntimeException(e);
+        }
+        for (int i = 0; i < MemoryConflictProvoker.INNER_ITERATIONS; i++) {
+            synchronized(monitor) {
+                MemoryConflictProvoker.field--;
+            }
+        }
+    }
+
+    @Override
+    public void forceAbort() {
+        try {
+            Thread t = new Thread(conflictingThread);
+            t.start();
+            transactionalRegion();
+            t.join();
+        } catch (Exception e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    @Override
+    public String getMethodWithLockName() {
+        return this.getClass().getName() + "::transactionalRegion";
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/compiler/testlibrary/rtm/NestedAbortProvoker.java	Mon Apr 14 19:29:34 2014 +0400
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 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.
+ *
+ * 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 rtm;
+
+import java.util.Arrays;
+
+/**
+ * In order to force nested transaction abort NestedAbortProvoker
+ * invoke BufferOverflowProvoker from transactional region.
+ */
+class NestedAbortProvoker extends AbortProvoker {
+    // Following field have to be static in order to avoid escape analysis.
+    @SuppressWarnings("UnsuedDeclaration")
+    private static int field = 0;
+    private final AbortProvoker nestedAbortProvoker;
+
+    public NestedAbortProvoker() {
+        this.nestedAbortProvoker = new XAbortProvoker(monitor);
+    }
+
+    @Override
+    public void forceAbort() {
+        synchronized(monitor) {
+            NestedAbortProvoker.field++;
+            nestedAbortProvoker.forceAbort();
+            NestedAbortProvoker.field--;
+        }
+    }
+
+    @Override
+    public String[] getMethodsToCompileNames() {
+        String nestedProvokerMethods[]
+                = nestedAbortProvoker.getMethodsToCompileNames();
+        String methods[] = Arrays.copyOf(nestedProvokerMethods,
+                nestedProvokerMethods.length + 1);
+        methods[methods.length - 1] = getMethodWithLockName();
+        return methods;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/compiler/testlibrary/rtm/RTMLockingStatistics.java	Mon Apr 14 19:29:34 2014 +0400
@@ -0,0 +1,227 @@
+/*
+ * Copyright (c) 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.
+ *
+ * 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 rtm;
+
+import java.util.EnumMap;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.regex.Pattern;
+import java.util.regex.Matcher;
+
+/**
+ * Wrapper for +UsePreciseRTMLockingStatistics output.
+ *
+ * Example of locking statistics:
+ *
+ * java/lang/ClassLoader.loadClass@7
+ * # rtm locks total (estimated): 0
+ * # rtm lock aborts  : 13
+ * # rtm lock aborts 0: 12
+ * # rtm lock aborts 1: 0
+ * # rtm lock aborts 2: 0
+ * # rtm lock aborts 3: 0
+ * # rtm lock aborts 4: 0
+ * # rtm lock aborts 5: 0
+ */
+public class RTMLockingStatistics {
+    /**
+     * Pattern for aborts per abort type entries.
+     */
+    private static final Pattern ABORT_PATTERN;
+
+    /**
+     * Pattern for whole statistics.
+     */
+    private static final Pattern RTM_LOCKING_STATISTICS_PATTERN;
+
+    static {
+        String abortRe
+                = "# rtm lock aborts\\s+(?<type>[0-9]+):\\s(?<count>[0-9]+)";
+
+        ABORT_PATTERN = Pattern.compile(abortRe);
+        RTM_LOCKING_STATISTICS_PATTERN = Pattern.compile(
+                "(?<className>[^.\n]+)\\." +
+                "(?<methodName>[^@\n]+)@(?<bci>[0-9]+)\n" +
+                "# rtm locks total \\(estimated\\):\\s*" +
+                "(?<totalLocks>[0-9]+)\n" +
+                "# rtm lock aborts\\s+:\\s*(?<totalAborts>[0-9]+)\n" +
+                "(?<abortStats>(" + abortRe + "\n)+)");
+    }
+
+    private final long totalLocks;
+    private final long totalAborts;
+    private final String className;
+    private final String methodName;
+    private final int bci;
+    private final Map<AbortType, Long> aborts = new EnumMap<>(AbortType.class);
+
+    /**
+     * Constructs RTMLockingStatistics from matcher captured statistics entry.
+     * @param matcher Matcher captured statistics entry.
+     */
+    private RTMLockingStatistics(Matcher matcher) {
+        className = matcher.group("className");
+        methodName = matcher.group("methodName");
+        bci = Integer.valueOf(matcher.group("bci"));
+        totalLocks = Long.valueOf(matcher.group("totalLocks"));
+        totalAborts = Long.valueOf(matcher.group("totalAborts"));
+
+        Matcher abortMatcher = ABORT_PATTERN.matcher(matcher.
+                group("abortStats"));
+
+        while (abortMatcher.find()) {
+            int type = Integer.valueOf(abortMatcher.group("type"));
+            long count = Long.valueOf(abortMatcher.group("count"));
+            setAborts(AbortType.lookup(type), count);
+        }
+    }
+
+
+    /**
+     * Parses string and return all founded RTM locking statistics entries.
+     *
+     * @param str the string to be parsed.
+     * @return list with all founded RTM locking statistics entries or
+     *         empty list if nothing was found.
+     */
+    public static List<RTMLockingStatistics> fromString(String str) {
+        List<RTMLockingStatistics> statistics = new LinkedList<>();
+        Matcher matcher = RTM_LOCKING_STATISTICS_PATTERN.matcher(str);
+
+        while (matcher.find()) {
+            RTMLockingStatistics lock = new RTMLockingStatistics(matcher);
+            statistics.add(lock);
+        }
+
+        return statistics;
+    }
+
+    /**
+     * Parses string and return all founded RTM locking statistics entries
+     * for locks in method {@code methodName}.
+     *
+     * @param methodName a name of the method for locks from which statistics
+     *                   should be gathered.
+     * @param str the string to be parsed.
+     * @return list with all founded RTM locking statistics entries or
+     *         empty list if nothing was found.
+     */
+    public static List<RTMLockingStatistics> fromString(String methodName,
+            String str) {
+        String formattedMethodName = formatMethodName(methodName);
+
+        List<RTMLockingStatistics> statisticsForMethod = new LinkedList<>();
+        for (RTMLockingStatistics statistics : fromString(str)) {
+            if (statistics.getLockName().startsWith(formattedMethodName)) {
+                statisticsForMethod.add(statistics);
+            }
+        }
+        return statisticsForMethod;
+    }
+
+    /**
+     * Formats method's name so it will have the same format as
+     * in rtm locking statistics.
+     *
+     * <pre>
+     * Example:
+     * com/example/Klass::method =&gt; com/example/Klass.method
+     * com/example/Klass.method  =&gt; com/example/Klass.method
+     * com.example.Klass::method =&gt; com/example/Klass.method
+     * com.example.Klass.method  =&gt; com/example/Klass.method
+     * </pre>
+     *
+     * @param methodName method's name that should be formatted.
+     * @return formatted method's name.
+     */
+    private static String formatMethodName(String methodName) {
+        String m[];
+        if (methodName.contains("::")) {
+            m = methodName.split("::");
+        } else {
+            int splitAt = methodName.lastIndexOf('.');
+            m = new String[2];
+            m[0] = methodName.substring(0, splitAt);
+            m[1] = methodName.substring(splitAt + 1);
+        }
+        return String.format("%s.%s", m[0].replaceAll("\\.", "/"), m[1]);
+    }
+
+    /**
+     * Returns name of lock for which this statistics was collected.
+     * Lock name has following format:
+     * &lt;class name&gt;.&lt;method name&gt;@&lt;bci&gt;
+     *
+     * @return name of lock.
+     */
+    public String getLockName() {
+        return String.format("%s.%s@%d", className, methodName, bci);
+    }
+
+    /**
+     * Returns aborts count for specified abort type.
+     *
+     * @param type an abort type.
+     * @return count of aborts.
+     */
+    public long getAborts(AbortType type) {
+        return aborts.getOrDefault(type, 0L);
+    }
+
+    /**
+     * Sets aborts count for specified abort type.
+     *
+     * @param type an abort type.
+     * @param count count of aborts.
+     */
+    public void setAborts(AbortType type, long count) {
+        aborts.put(type, count);
+    }
+
+    public long getTotalLocks() {
+        return totalLocks;
+    }
+
+    public long getTotalAborts() {
+        return totalAborts;
+    }
+
+    @Override
+    public String toString() {
+        StringBuilder builder = new StringBuilder();
+        builder.append(getLockName()).append('\n');
+        builder.append(String.format("# rtm locks total (estimated): %d\n",
+                getTotalLocks()));
+        builder.append(String.format("# rtm lock aborts: %d\n",
+                getTotalLocks()));
+
+        for (AbortType type : AbortType.values()) {
+            builder.append(String.format("# rtm lock aborts %s %d\n",
+                    type.toString(), getAborts(type)));
+        }
+        return builder.toString();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/compiler/testlibrary/rtm/RTMTestBase.java	Mon Apr 14 19:29:34 2014 +0400
@@ -0,0 +1,280 @@
+/*
+ * Copyright (c) 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.
+ *
+ * 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 rtm;
+
+import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.Paths;
+import java.util.List;
+import java.util.LinkedList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import com.oracle.java.testlibrary.OutputAnalyzer;
+import com.oracle.java.testlibrary.ProcessTools;
+import com.oracle.java.testlibrary.Utils;
+import com.oracle.java.testlibrary.cli.CommandLineOptionTest;
+
+/**
+ * Auxiliary methods used for RTM testing.
+ */
+public class RTMTestBase {
+    private static final String RTM_STATE_CHANGE_REASON = "rtm_state_change";
+    /**
+     * We don't parse compilation log as XML-document and use regular
+     * expressions instead, because in some cases it could be
+     * malformed.
+     */
+    private static final String FIRED_UNCOMMON_TRAP_PATTERN_TEMPLATE
+            = "<uncommon_trap thread='[0-9]+' reason='%s'";
+    private static final String INSTALLED_UNCOMMON_TRAP_PATTERN_TEMPLATE
+            = "<uncommon_trap bci='[0-9]+' reason='%s'";
+
+    /**
+     * Executes RTM test in a new JVM started with {@code options} cli options.
+     *
+     * @param test test case to execute.
+     * @param options additional options for VM
+     * @throws Exception when something went wrong.
+     */
+    public static OutputAnalyzer executeRTMTest(CompilableTest test,
+            String... options) throws Exception {
+        ProcessBuilder processBuilder
+                = ProcessTools.createJavaProcessBuilder(
+                RTMTestBase.prepareTestOptions(test, options));
+        OutputAnalyzer outputAnalyzer
+                = new OutputAnalyzer(processBuilder.start());
+        System.out.println(outputAnalyzer.getOutput());
+        return outputAnalyzer;
+    }
+
+    /**
+     * Executes test case and save compilation log to {@code logFileName}.
+     *
+     * @param logFileName a name of compilation log file
+     * @param test a test case to execute case to execute
+     * @param options additional options to VM
+     * @return OutputAnalyzer for started test case
+     * @throws Exception when something went wrong
+     */
+    public static OutputAnalyzer executeRTMTest(String logFileName,
+            CompilableTest test, String... options) throws Exception {
+        ProcessBuilder processBuilder
+                = ProcessTools.createJavaProcessBuilder(
+                RTMTestBase.prepareTestOptions(logFileName, test, options));
+        OutputAnalyzer outputAnalyzer
+                = new OutputAnalyzer(processBuilder.start());
+
+        System.out.println(outputAnalyzer.getOutput());
+
+        return outputAnalyzer;
+    }
+
+    /**
+     * Finds count of uncommon traps with reason {@code reason} installed
+     * during compilation.
+     *
+     * @param compilationLogFile a path to file with LogCompilation output.
+     * @param reason reason of installed uncommon traps.
+     * @return count of installed uncommon traps with reason {@code reason}.
+     * @throws IOException
+     */
+    public static int installedUncommonTraps(String compilationLogFile,
+            String reason)throws IOException {
+        String pattern = String.format(
+                RTMTestBase.INSTALLED_UNCOMMON_TRAP_PATTERN_TEMPLATE,
+                reason);
+        return RTMTestBase.findTraps(compilationLogFile, pattern);
+    }
+
+    /**
+     * Finds count of uncommon traps with reason <i>rtm_state_change</i>
+     * installed during compilation.
+     *
+     * @param compilationLogFile a path to file with LogCompilation output.
+     * @return count of installed uncommon traps with reason
+     *         <i>rtm_state_change</i>.
+     * @throws IOException
+     */
+    public static int installedRTMStateChangeTraps(String compilationLogFile)
+            throws IOException {
+        return RTMTestBase.installedUncommonTraps(compilationLogFile,
+                RTMTestBase.RTM_STATE_CHANGE_REASON);
+    }
+
+    /**
+     * Finds count of fired uncommon traps with reason {@code reason}.
+     *
+     * @param compilationLogFile a path to file with LogCompilation output.
+     * @param reason a reason of fired uncommon traps.
+     * @return count of fired uncommon traps with reason {@code reason}.
+     * @throws IOException
+     */
+    public static int firedUncommonTraps(String compilationLogFile,
+            String reason) throws IOException {
+        String pattern = String.format(
+                RTMTestBase.FIRED_UNCOMMON_TRAP_PATTERN_TEMPLATE,
+                reason);
+        return RTMTestBase.findTraps(compilationLogFile, pattern);
+    }
+
+    /**
+     * Finds count of fired uncommon traps with reason <i>rtm_state_change</i>.
+     *
+     * @param compilationLogFile a path to file with LogCompilation output.
+     * @return count of fired uncommon traps with reason
+     *         <i>rtm_state_change</i>.
+     * @throws IOException
+     */
+    public static int firedRTMStateChangeTraps(String compilationLogFile)
+            throws IOException {
+        return RTMTestBase.firedUncommonTraps(compilationLogFile,
+                RTMTestBase.RTM_STATE_CHANGE_REASON);
+    }
+
+    /**
+     * Finds count of uncommon traps that matches regular
+     * expression in {@code re}.
+     *
+     * @param compilationLogFile a path to file with LogCompilation output.
+     * @param re regular expression to match uncommon traps.
+     * @throws IOException
+     */
+    private static int findTraps(String compilationLogFile, String re)
+            throws IOException {
+        String compilationLog = RTMTestBase.fileAsString(compilationLogFile);
+        Pattern pattern = Pattern.compile(re);
+        Matcher matcher = pattern.matcher(compilationLog);
+        int traps = 0;
+        while (matcher.find()) {
+            traps++;
+        }
+        return traps;
+    }
+
+    /**
+     * Returns file's content as a string.
+     *
+     * @param path a path to file to operate on.
+     * @return string with content of file.
+     * @throws IOException
+     */
+    private static String fileAsString(String path) throws IOException {
+        byte[] fileAsBytes = Files.readAllBytes(Paths.get(path));
+        return new String(fileAsBytes);
+    }
+
+    /**
+     * Prepares VM options for test execution.
+     * This method get test java options, filter out all RTM-related options,
+     * adds CompileCommand=compileonly,method_name options for each method
+     * from {@code methodToCompile} and finally appends all {@code vmOpts}.
+     *
+     * @param test test case whose methods that should be compiled.
+     *             If {@code null} then no additional <i>compileonly</i>
+     *             commands will be added to VM options.
+     * @param vmOpts additional options to pass to VM.
+     * @return Array with VM options.
+     */
+    private static String[] prepareTestOptions(CompilableTest test,
+            String... vmOpts) {
+        return RTMTestBase.prepareFilteredTestOptions(test, null, vmOpts);
+    }
+
+    /**
+     * Prepares VM options for test execution.
+     * This method get test java options, filter out all RTM-related options
+     * and all options that matches regexps in {@code additionalFilters},
+     * adds CompileCommand=compileonly,method_name options for each method
+     * from {@code methodToCompile} and finally appends all {@code vmOpts}.
+     *
+     * @param test test case whose methods that should be compiled.
+     *             If {@code null} then no additional <i>compileonly</i>
+     *             commands will be added to VM options.
+     * @param additionalFilters array with regular expression that will be
+     *                          used to filter out test java options.
+     *                          If {@code null} then no additional filters
+     *                          will be used.
+     * @param vmOpts additional options to pass to VM.
+     * @return array with VM options.
+     */
+    private static String[] prepareFilteredTestOptions(CompilableTest test,
+            String[] additionalFilters, String... vmOpts) {
+        List<String> finalVMOpts = new LinkedList<>();
+        String[] filters;
+
+        if (additionalFilters != null) {
+            filters = Arrays.copyOf(additionalFilters,
+                    additionalFilters.length + 1);
+        } else {
+            filters = new String[1];
+        }
+
+        filters[filters.length - 1] = "RTM";
+        String[] filteredVMOpts = Utils.getFilteredTestJavaOpts(filters);
+        Collections.addAll(finalVMOpts, filteredVMOpts);
+        Collections.addAll(finalVMOpts, "-Xcomp", "-server",
+                "-XX:-TieredCompilation",
+                CommandLineOptionTest.UNLOCK_DIAGNOSTIC_VM_OPTIONS,
+                CommandLineOptionTest.UNLOCK_EXPERIMENTAL_VM_OPTIONS,
+                "-XX:+UseRTMLocking");
+
+        if (test != null) {
+            for (String method : test.getMethodsToCompileNames()) {
+                finalVMOpts.add("-XX:CompileCommand=compileonly," + method);
+            }
+        }
+        Collections.addAll(finalVMOpts, vmOpts);
+        return finalVMOpts.toArray(new String[finalVMOpts.size()]);
+    }
+
+    /**
+     * Adds additional options for VM required for successful execution of test.
+     *
+     * @param logFileName a name of compilation log file
+     * @param test a test case to execute
+     * @param options additional options to VM
+     * @return an array with VM options
+     */
+    private static String[] prepareTestOptions(String logFileName,
+            CompilableTest test, String... options) {
+        String[] preparedOptions = RTMTestBase.prepareFilteredTestOptions(
+                test,
+                new String[] {
+                        "LogCompilation",
+                        "LogFile"
+                });
+        List<String> updatedOptions = new LinkedList<>();
+        Collections.addAll(updatedOptions, preparedOptions);
+        Collections.addAll(updatedOptions,
+                "-XX:+LogCompilation",
+                "-XX:LogFile=" + logFileName);
+        Collections.addAll(updatedOptions, options);
+
+        return updatedOptions.toArray(new String[updatedOptions.size()]);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/compiler/testlibrary/rtm/XAbortProvoker.java	Mon Apr 14 19:29:34 2014 +0400
@@ -0,0 +1,62 @@
+/*
+ * Copyright (c) 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.
+ *
+ * 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 rtm;
+
+import com.oracle.java.testlibrary.Utils;
+import sun.misc.Unsafe;
+
+/**
+ * Current RTM locking implementation force transaction abort
+ * before native method call by explicit xabort(0) call.
+ */
+class XAbortProvoker extends AbortProvoker {
+    // Following field have to be static in order to avoid escape analysis.
+    @SuppressWarnings("UnsuedDeclaration")
+    private static int field = 0;
+    private static final Unsafe UNSAFE = Utils.getUnsafe();
+
+    public XAbortProvoker() {
+        this(new Object());
+    }
+
+    public XAbortProvoker(Object monitor) {
+        super(monitor);
+    }
+
+    @Override
+    public void forceAbort() {
+        synchronized(monitor) {
+            XAbortProvoker.field = UNSAFE.addressSize();
+        }
+    }
+
+    @Override
+    public String[] getMethodsToCompileNames() {
+        return new String[] {
+                getMethodWithLockName(),
+                Unsafe.class.getName() + "::addressSize"
+        };
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/compiler/testlibrary/rtm/predicate/SupportedCPU.java	Mon Apr 14 19:29:34 2014 +0400
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 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.
+ *
+ * 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 rtm.predicate;
+
+import sun.hotspot.cpuinfo.CPUInfo;
+
+import java.util.function.BooleanSupplier;
+
+public class SupportedCPU implements BooleanSupplier {
+    @Override
+    public boolean getAsBoolean() {
+        return CPUInfo.hasFeature("rtm");
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/compiler/testlibrary/rtm/predicate/SupportedVM.java	Mon Apr 14 19:29:34 2014 +0400
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 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.
+ *
+ * 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 rtm.predicate;
+
+import com.oracle.java.testlibrary.Platform;
+
+import java.util.function.BooleanSupplier;
+
+public class SupportedVM implements BooleanSupplier {
+    @Override
+    public boolean getAsBoolean() {
+        return Platform.isServer() && !Platform.isEmbedded();
+    }
+}
--- a/test/testlibrary/com/oracle/java/testlibrary/cli/CPUSpecificCommandLineOptionTest.java	Fri Apr 11 00:34:56 2014 +0400
+++ b/test/testlibrary/com/oracle/java/testlibrary/cli/CPUSpecificCommandLineOptionTest.java	Mon Apr 14 19:29:34 2014 +0400
@@ -23,22 +23,16 @@
 
 package com.oracle.java.testlibrary.cli;
 
-import sun.hotspot.cpuinfo.CPUInfo;
-import com.oracle.java.testlibrary.*;
+import com.oracle.java.testlibrary.cli.predicate.CPUSpecificPredicate;
 
 /**
  * Base class for command line options tests that
  * requires specific CPU arch or specific CPU features.
  */
 public abstract class CPUSpecificCommandLineOptionTest
-              extends CommandLineOptionTest {
-
-    private String cpuArchPattern;
-    private String supportedCPUFeatures[];
-    private String unsupportedCPUFeatures[];
-
+        extends CommandLineOptionTest {
     /**
-     * Create new CPU specific test instance that does not
+     * Creates new CPU specific test instance that does not
      * require any CPU features.
      *
      * @param cpuArchPattern Regular expression that should
@@ -49,62 +43,23 @@
     }
 
     /**
-     * Create new CPU specific test instance that does not
+     * Creates new CPU specific test instance that does not
      * require from CPU support of {@code supportedCPUFeatures} features
      * and no support of {@code unsupportedCPUFeatures}.
      *
      * @param cpuArchPattern Regular expression that should
      *                       match os.arch.
      * @param supportedCPUFeatures Array with names of features that
-     *                             should be supported by CPU. If <b>null</b>,
+     *                             should be supported by CPU. If {@code null},
      *                             then no features have to be supported.
      * @param unsupportedCPUFeatures Array with names of features that
      *                               should not be supported by CPU.
-     *                               If <b>null</b>, then CPU may support any
+     *                               If {@code null}, then CPU may support any
      *                               features.
      */
     public CPUSpecificCommandLineOptionTest(String cpuArchPattern,
-                                            String supportedCPUFeatures[],
-                                            String unsupportedCPUFeatures[]) {
-        this.cpuArchPattern = cpuArchPattern;
-        this.supportedCPUFeatures = supportedCPUFeatures;
-        this.unsupportedCPUFeatures = unsupportedCPUFeatures;
-    }
-
-    /**
-     * Check that CPU on test box has appropriate architecture, support all
-     * required features and does not support all features that should not be
-     * supported.
-     *
-     * @return <b>true</b> if CPU on test box fulfill all requirements.
-     */
-    @Override
-    public boolean checkPreconditions() {
-        if (!Platform.getOsArch().matches(cpuArchPattern)) {
-            System.out.println("CPU arch does not match " + cpuArchPattern);
-            return false;
-        }
-
-        if (supportedCPUFeatures != null) {
-            for (String feature : supportedCPUFeatures) {
-                if (!CPUInfo.hasFeature(feature)) {
-                    System.out.println("CPU does not support " + feature +
-                                       " feature");
-                    return false;
-                }
-            }
-        }
-
-        if (unsupportedCPUFeatures != null) {
-            for (String feature : unsupportedCPUFeatures) {
-                if (CPUInfo.hasFeature(feature)) {
-                    System.out.println("CPU support " + feature + " feature");
-                    return false;
-                }
-            }
-        }
-
-        return true;
+            String supportedCPUFeatures[], String unsupportedCPUFeatures[]) {
+        super(new CPUSpecificPredicate(cpuArchPattern, supportedCPUFeatures,
+                unsupportedCPUFeatures));
     }
 }
-
--- a/test/testlibrary/com/oracle/java/testlibrary/cli/CommandLineOptionTest.java	Fri Apr 11 00:34:56 2014 +0400
+++ b/test/testlibrary/com/oracle/java/testlibrary/cli/CommandLineOptionTest.java	Mon Apr 14 19:29:34 2014 +0400
@@ -26,6 +26,7 @@
 import java.util.List;
 import java.util.ArrayList;
 import java.util.Collections;
+import java.util.function.BooleanSupplier;
 
 import com.oracle.java.testlibrary.*;
 
@@ -33,34 +34,71 @@
  * Base class for command line option tests.
  */
 public abstract class CommandLineOptionTest {
-
-    public static final String UNRECOGNIZED_OPTION_ERROR_FORMAT =
-        "Unrecognized VM option '[+-]?%s'";
-
-    public static final String printFlagsFinalFormat = "%s\\s*:?=\\s*%s";
+    public static final String UNLOCK_DIAGNOSTIC_VM_OPTIONS
+            = "-XX:+UnlockDiagnosticVMOptions";
+    public static final String UNLOCK_EXPERIMENTAL_VM_OPTIONS
+            = "-XX:+UnlockExperimentalVMOptions";
+    protected static final String UNRECOGNIZED_OPTION_ERROR_FORMAT
+            = "Unrecognized VM option '[+-]?%s(=.*)?'";
+    protected static final String EXPERIMENTAL_OPTION_ERROR_FORMAT
+            = "VM option '%s' is experimental and must be enabled via "
+            + "-XX:\\+UnlockExperimentalVMOptions.";
+    protected static final String DIAGNOSTIC_OPTION_ERROR_FORMAT
+            = " VM option '%s' is diagnostic and must be enabled via "
+            + "-XX:\\+UnlockDiagnosticVMOptions.";
+    private static final String PRINT_FLAGS_FINAL_FORMAT = "%s\\s*:?=\\s*%s";
 
     /**
-     * Verify that JVM startup behaviour matches our expectations.
+     * Verifies that JVM startup behaviour matches our expectations.
      *
-     * @param option The option that should be passed to JVM
-     * @param excpectedMessages Array of patterns that should occur
-     *                          in JVM output. If <b>null</b> then
+     * @param option an option that should be passed to JVM
+     * @param expectedMessages an array of patterns that should occur
+     *                          in JVM output. If {@code null} then
      *                          JVM output could be empty.
-     * @param unexpectedMessages Array of patterns that should not
-     *                           occur in JVM output. If <b>null</b> then
-     *                          JVM output could be empty.
+     * @param unexpectedMessages an array of patterns that should not
+     *                           occur in JVM output. If {@code null} then
+     *                           JVM output could be empty.
      * @param exitCode expected exit code.
      * @throws Throwable if verification fails or some other issues occur.
      */
     public static void verifyJVMStartup(String option,
-                                        String expectedMessages[],
-                                        String unexpectedMessages[],
-                                        ExitCode exitCode)
-                                 throws Throwable {
+            String expectedMessages[], String unexpectedMessages[],
+            ExitCode exitCode) throws Throwable {
+        CommandLineOptionTest.verifyJVMStartup(expectedMessages,
+                unexpectedMessages, exitCode, false, option);
+    }
 
-        OutputAnalyzer outputAnalyzer =
-            ProcessTools.executeTestJvm(option, "-version");
+    /**
+     * Verifies that JVM startup behaviour matches our expectations.
+     *
+     * @param expectedMessages an array of patterns that should occur
+     *                         in JVM output. If {@code null} then
+     *                         JVM output could be empty.
+     * @param unexpectedMessages an array of patterns that should not
+     *                           occur in JVM output. If {@code null} then
+     *                           JVM output could be empty.
+     * @param exitCode expected exit code.
+     * @param addTestVMOptions if {@code true} then test VM options will be
+     *                         passed to VM.
+     * @param options options that should be passed to VM in addition to mode
+     *                flag.
+     * @throws Throwable if verification fails or some other issues occur.
+     */
+    public static void verifyJVMStartup(String expectedMessages[],
+            String unexpectedMessages[], ExitCode exitCode,
+            boolean addTestVMOptions, String... options) throws Throwable {
+        List<String> finalOptions = new ArrayList<>();
+        if (addTestVMOptions) {
+            Collections.addAll(finalOptions, Utils.getTestJavaOpts());
+        }
+        Collections.addAll(finalOptions, options);
+        finalOptions.add("-version");
 
+        ProcessBuilder processBuilder
+                = ProcessTools.createJavaProcessBuilder(finalOptions.toArray(
+                new String[finalOptions.size()]));
+        OutputAnalyzer outputAnalyzer
+                = new OutputAnalyzer(processBuilder.start());
         outputAnalyzer.shouldHaveExitValue(exitCode.value);
 
         if (expectedMessages != null) {
@@ -77,97 +115,216 @@
     }
 
     /**
-     * Verify that value of specified JVM option is the same as
+     * Verifies that JVM startup behaviour matches our expectations when type
+     * of newly started VM is the same as the type of current.
+     *
+     * @param expectedMessages an array of patterns that should occur
+     *                         in JVM output. If {@code null} then
+     *                         JVM output could be empty.
+     * @param unexpectedMessages an array of patterns that should not
+     *                           occur in JVM output. If {@code null} then
+     *                           JVM output could be empty.
+     * @param exitCode expected exit code.
+     * @param options options that should be passed to VM in addition to mode
+     *                flag.
+     * @throws Throwable if verification fails or some other issues occur.
+     */
+    public static void verifySameJVMStartup(String expectedMessages[],
+            String unexpectedMessages[], ExitCode exitCode, String... options)
+            throws  Throwable {
+        List<String> finalOptions = new ArrayList<>();
+        finalOptions.add(CommandLineOptionTest.getVMTypeOption());
+        Collections.addAll(finalOptions, options);
+
+        CommandLineOptionTest.verifyJVMStartup(expectedMessages,
+                unexpectedMessages, exitCode, false,
+                finalOptions.toArray(new String[finalOptions.size()]));
+    }
+
+    /**
+     * Verifies that value of specified JVM option is the same as
      * expected value.
      * This method filter out option with {@code optionName}
      * name from test java options.
      *
-     * @param optionName Name of tested option.
-     * @param expectedValue Expected value of tested option.
-     * @param additionalVMOpts Additonal options that should be
+     * @param optionName a name of tested option.
+     * @param expectedValue expected value of tested option.
+     * @param additionalVMOpts additional options that should be
      *                         passed to JVM.
      * @throws Throwable if verification fails or some other issues occur.
      */
     public static void verifyOptionValue(String optionName,
-                                         String expectedValue,
-                                         String... additionalVMOpts)
-                                  throws Throwable {
+            String expectedValue, String... additionalVMOpts) throws Throwable {
         verifyOptionValue(optionName, expectedValue, true, additionalVMOpts);
     }
 
     /**
-     * Verify that value of specified JVM option is the same as
+     * Verifies that value of specified JVM option is the same as
      * expected value.
      * This method filter out option with {@code optionName}
      * name from test java options.
      *
-     * @param optionName Name of tested option.
-     * @param expectedValue Expected value of tested option.
-     * @param addTestVmOptions If <b>true</b>, then test VM options
+     * @param optionName a name of tested option.
+     * @param expectedValue expected value of tested option.
+     * @param addTestVmOptions if {@code true}, then test VM options
      *                         will be used.
-     * @param additionalVMOpts Additonal options that should be
+     * @param additionalVMOpts additional options that should be
      *                         passed to JVM.
-     * @throws Throwable if verification fails or some other issues occur.
+     * @throws Throwable if verification fails or some other issues
+     *                          occur.
      */
     public static void verifyOptionValue(String optionName,
-                                         String expectedValue,
-                                         boolean addTestVmOptions,
-                                         String... additionalVMOpts)
-                                  throws Throwable {
-
-        List<String> vmOpts = new ArrayList<String>();
+            String expectedValue, boolean addTestVmOptions,
+            String... additionalVMOpts) throws Throwable {
+        List<String> vmOpts = new ArrayList<>();
 
         if (addTestVmOptions) {
             Collections.addAll(vmOpts,
                                Utils.getFilteredTestJavaOpts(optionName));
         }
         Collections.addAll(vmOpts, additionalVMOpts);
-        Collections.addAll(vmOpts, new String[] {
-                "-XX:+PrintFlagsFinal",
-                "-version"
-            });
+        Collections.addAll(vmOpts, "-XX:+PrintFlagsFinal", "-version");
 
-        ProcessBuilder processBuilder =
-            ProcessTools.
-            createJavaProcessBuilder(vmOpts.
-                                     toArray(new String[vmOpts.size()]));
+        ProcessBuilder processBuilder = ProcessTools.createJavaProcessBuilder(
+                vmOpts.toArray(new String[vmOpts.size()]));
 
-        OutputAnalyzer outputAnalyzer =
-            new OutputAnalyzer(processBuilder.start());
+        OutputAnalyzer outputAnalyzer
+                = new OutputAnalyzer(processBuilder.start());
 
         outputAnalyzer.shouldHaveExitValue(0);
-        outputAnalyzer.shouldMatch(String.
-                                   format(printFlagsFinalFormat,
-                                          optionName,
-                                          expectedValue));
+        outputAnalyzer.shouldMatch(String.format(
+                CommandLineOptionTest.PRINT_FLAGS_FINAL_FORMAT,
+                optionName, expectedValue));
+    }
+
+    /**
+     * Verifies that value of specified JVM when type of newly started VM
+     * is the same as the type of current.
+     * This method filter out option with {@code optionName}
+     * name from test java options.
+     * Only mode flag will be passed to VM in addition to
+     * {@code additionalVMOpts}
+     *
+     * @param optionName name of tested option.
+     * @param expectedValue expected value of tested option.
+     * @param additionalVMOpts additional options that should be
+     *                         passed to JVM.
+     * @throws Throwable if verification fails or some other issues occur.
+     */
+    public static void verifyOptionValueForSameVM(String optionName,
+            String expectedValue, String... additionalVMOpts) throws Throwable {
+        List<String> finalOptions = new ArrayList<>();
+        finalOptions.add(CommandLineOptionTest.getVMTypeOption());
+        Collections.addAll(finalOptions, additionalVMOpts);
+
+        CommandLineOptionTest.verifyOptionValue(optionName, expectedValue,
+                false, finalOptions.toArray(new String[finalOptions.size()]));
+    }
+
+    /**
+     * Prepares boolean command line flag with name {@code name} according
+     * to it's {@code value}.
+     *
+     * @param name the name of option to be prepared
+     * @param value the value of option
+     * @return prepared command line flag
+     */
+    public static String prepareBooleanFlag(String name, boolean value) {
+        return String.format("-XX:%c%s", (value ? '+' : '-'), name);
+    }
+
+    /**
+     * Prepares numeric command line flag with name {@code name} by setting
+     * it's value to {@code value}.
+     *
+     * @param name the name of option to be prepared
+     * @param value the value of option
+     * @return prepared command line flag
+     */
+    public static String prepareNumericFlag(String name, Number value) {
+        return String.format("-XX:%s=%s", name, value.toString());
     }
 
+    /**
+     * Returns message that should occur in VM output if option
+     * {@code optionName} if unrecognized.
+     *
+     * @param optionName the name of option for which message should be returned
+     * @return message saying that option {@code optionName} is unrecognized
+     */
+    public static String getUnrecognizedOptionErrorMessage(String optionName) {
+        return String.format(
+                CommandLineOptionTest.UNRECOGNIZED_OPTION_ERROR_FORMAT,
+                optionName);
+    }
+
+    /**
+     * Returns message that should occur in VM output if option
+     * {@code optionName} is experimental and
+     * -XX:+UnlockExperimentalVMOptions was not passed to VM.
+     *
+     * @param optionName the name of option for which message should be returned
+     * @return message saying that option {@code optionName} is experimental
+     */
+    public static String getExperimentalOptionErrorMessage(String optionName) {
+        return String.format(
+                CommandLineOptionTest.EXPERIMENTAL_OPTION_ERROR_FORMAT,
+                optionName);
+    }
 
     /**
-     * Run command line option test.
+     * Returns message that should occur in VM output if option
+     * {@code optionName} is diagnostic and -XX:+UnlockDiagnosticVMOptions
+     * was not passed to VM.
      *
-     * @throws Throwable if test failed.
+     * @param optionName the name of option for which message should be returned
+     * @return message saying that option {@code optionName} is diganostic
+     */
+    public static String getDiagnosticOptionErrorMessage(String optionName) {
+        return String.format(
+                CommandLineOptionTest.DIAGNOSTIC_OPTION_ERROR_FORMAT,
+                optionName);
+    }
+
+    /**
+     * @return option required to start a new VM with the same type as current.
+     * @throws RuntimeException when VM type is unknown.
+     */
+    private static String getVMTypeOption() {
+        if (Platform.isServer()) {
+            return "-server";
+        } else if (Platform.isClient()) {
+            return "-client";
+        } else if (Platform.isMinimal()) {
+            return "-minimal";
+        } else if (Platform.isGraal()) {
+            return "-graal";
+        }
+        throw new RuntimeException("Unknown VM mode.");
+    }
+
+    private final BooleanSupplier predicate;
+
+    /**
+     * Constructs new CommandLineOptionTest that will be executed only if
+     * predicate {@code predicate} return {@code true}.
+     * @param predicate a predicate responsible for test's preconditions check.
+     */
+    public CommandLineOptionTest(BooleanSupplier predicate) {
+        this.predicate = predicate;
+    }
+
+    /**
+     * Runs command line option test.
      */
     public final void test() throws Throwable {
-        if (checkPreconditions()) {
+        if (predicate.getAsBoolean()) {
             runTestCases();
         }
     }
 
     /**
-     * Check that all preconditions for test execution are met.
-     *
-     * @return <b>true</b> if test could be executed.
+     * @throws Throwable if some issue happened during test cases execution.
      */
-    public boolean checkPreconditions() {
-        return true;
-    }
-
-    /**
-     * Run test cases.
-     *
-     * @throws Throwable if test failed.
-     */
-    public abstract void runTestCases() throws Throwable;
+    protected abstract void runTestCases() throws Throwable;
 }
-
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/testlibrary/com/oracle/java/testlibrary/cli/predicate/AndPredicate.java	Mon Apr 14 19:29:34 2014 +0400
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 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.
+ *
+ * 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 com.oracle.java.testlibrary.cli.predicate;
+
+import java.util.function.BooleanSupplier;
+
+public class AndPredicate implements BooleanSupplier {
+    private final BooleanSupplier a;
+    private final BooleanSupplier b;
+
+    public AndPredicate(BooleanSupplier a, BooleanSupplier b) {
+        this.a = a;
+        this.b = b;
+    }
+
+    @Override
+    public boolean getAsBoolean() {
+        return a.getAsBoolean() && b.getAsBoolean();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/testlibrary/com/oracle/java/testlibrary/cli/predicate/CPUSpecificPredicate.java	Mon Apr 14 19:29:34 2014 +0400
@@ -0,0 +1,71 @@
+/*
+ * Copyright (c) 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.
+ *
+ * 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 com.oracle.java.testlibrary.cli.predicate;
+
+import com.oracle.java.testlibrary.Platform;
+import sun.hotspot.cpuinfo.CPUInfo;
+
+import java.util.function.BooleanSupplier;
+
+public class CPUSpecificPredicate implements BooleanSupplier {
+    private final String cpuArchPattern;
+    private final String supportedCPUFeatures[];
+    private final String unsupportedCPUFeatures[];
+
+    public CPUSpecificPredicate(String cpuArchPattern,
+            String supportedCPUFeatures[],
+            String unsupportedCPUFeatures[]) {
+        this.cpuArchPattern = cpuArchPattern;
+        this.supportedCPUFeatures = supportedCPUFeatures;
+        this.unsupportedCPUFeatures = unsupportedCPUFeatures;
+    }
+
+    @Override
+    public boolean getAsBoolean() {
+        if (!Platform.getOsArch().matches(cpuArchPattern)) {
+            System.out.println("CPU arch does not match " + cpuArchPattern);
+            return false;
+        }
+
+        if (supportedCPUFeatures != null) {
+            for (String feature : supportedCPUFeatures) {
+                if (!CPUInfo.hasFeature(feature)) {
+                    System.out.println("CPU does not support " + feature
+                            + " feature");
+                    return false;
+                }
+            }
+        }
+
+        if (unsupportedCPUFeatures != null) {
+            for (String feature : unsupportedCPUFeatures) {
+                if (CPUInfo.hasFeature(feature)) {
+                    System.out.println("CPU support " + feature + " feature");
+                    return false;
+                }
+            }
+        }
+        return true;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/testlibrary/com/oracle/java/testlibrary/cli/predicate/NotPredicate.java	Mon Apr 14 19:29:34 2014 +0400
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 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.
+ *
+ * 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 com.oracle.java.testlibrary.cli.predicate;
+
+import java.util.function.BooleanSupplier;
+
+public class NotPredicate implements BooleanSupplier {
+    private final BooleanSupplier s;
+
+    public NotPredicate(BooleanSupplier s) {
+        this.s = s;
+    }
+
+    @Override
+    public boolean getAsBoolean() {
+        return !s.getAsBoolean();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/testlibrary/com/oracle/java/testlibrary/cli/predicate/OrPredicate.java	Mon Apr 14 19:29:34 2014 +0400
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 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.
+ *
+ * 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 com.oracle.java.testlibrary.cli.predicate;
+
+import java.util.function.BooleanSupplier;
+
+public class OrPredicate implements BooleanSupplier {
+    private final BooleanSupplier a;
+    private final BooleanSupplier b;
+
+    public OrPredicate(BooleanSupplier a, BooleanSupplier b) {
+        this.a = a;
+        this.b = b;
+    }
+
+    @Override
+    public boolean getAsBoolean() {
+        return a.getAsBoolean() || b.getAsBoolean();
+    }
+}