8066157: JEP-JDK-8046155: Test task: method matcher
authorppunegov
Thu, 24 Sep 2015 20:13:04 +0300
changeset 33081 71794b149055
parent 33080 73c9bbe40ff8
child 33082 c3e302e8e429
8066157: JEP-JDK-8046155: Test task: method matcher Summary: MethodMatcher test and framework Reviewed-by: iignatyev, neliasso
hotspot/test/compiler/compilercontrol/matcher/MethodMatcherTest.java
hotspot/test/compiler/compilercontrol/share/method/ClassType.java
hotspot/test/compiler/compilercontrol/share/method/MethodDescriptor.java
hotspot/test/compiler/compilercontrol/share/method/MethodElementType.java
hotspot/test/compiler/compilercontrol/share/method/MethodGenerator.java
hotspot/test/compiler/compilercontrol/share/method/MethodType.java
hotspot/test/compiler/compilercontrol/share/method/SignatureType.java
hotspot/test/compiler/compilercontrol/share/pool/MethodHolder.java
hotspot/test/compiler/compilercontrol/share/pool/PoolHelper.java
hotspot/test/compiler/compilercontrol/share/pool/sub/Klass.java
hotspot/test/compiler/compilercontrol/share/pool/sub/KlassDup.java
hotspot/test/compiler/compilercontrol/share/pool/subpack/Klass.java
hotspot/test/compiler/compilercontrol/share/pool/subpack/KlassDup.java
hotspot/test/testlibrary/jdk/test/lib/Pair.java
hotspot/test/testlibrary/jdk/test/lib/Triple.java
hotspot/test/testlibrary/jdk/test/lib/Utils.java
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/compilercontrol/matcher/MethodMatcherTest.java	Thu Sep 24 20:13:04 2015 +0300
@@ -0,0 +1,152 @@
+/*
+ * Copyright (c) 2015, 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 compiler.compilercontrol.matcher;
+
+import jdk.test.lib.Pair;
+import compiler.compilercontrol.share.method.MethodDescriptor;
+import compiler.compilercontrol.share.method.MethodGenerator;
+import pool.PoolHelper;
+import sun.hotspot.WhiteBox;
+
+import java.lang.reflect.Executable;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.Callable;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+/*
+ * @test
+ * @bug 8135068
+ * @summary Tests CompilerCommand's method matcher
+ * @library /testlibrary /../../test/lib /compiler/whitebox ../share /
+ * @build MethodMatcherTest
+ * @run main ClassFileInstaller sun.hotspot.WhiteBox
+ *                              sun.hotspot.WhiteBox$WhiteBoxPermission
+ * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions
+ *           -XX:+WhiteBoxAPI compiler.compilercontrol.matcher.MethodMatcherTest
+ */
+public class MethodMatcherTest {
+    private static final WhiteBox WB = WhiteBox.getWhiteBox();
+    private static final PoolHelper POOL = new PoolHelper();
+    private static final List<Pair<Executable, Callable<?>>> METHODS =
+            POOL.getAllMethods();
+    private static final int AMOUNT = Integer.parseInt(System
+            .getProperty("test.amount", "25"));
+
+    public static void main(String[] args) {
+        MethodGenerator gen = new MethodGenerator();
+        List<Pair<Executable, Callable<?>>> testMethods =
+                POOL.getAllMethods(PoolHelper.METHOD_FILTER);
+        for (Pair<Executable, Callable<?>> pair : testMethods) {
+            for (int i = 0; i < AMOUNT; i++) {
+                MethodDescriptor md = gen.generateRandomDescriptor(pair.first);
+                check(md);
+            }
+        }
+    }
+
+    /**
+     * Check method matcher with given test case
+     *
+     * @param methodDescriptor method descriptor to check matcher's pattern
+     */
+    private static void check(MethodDescriptor methodDescriptor) {
+        System.out.println("Test case: " + methodDescriptor.getString());
+        System.out.println("Regex: " + methodDescriptor.getRegexp());
+        Pattern pattern = Pattern.compile(methodDescriptor.getRegexp());
+        boolean isValidDesc = methodDescriptor.isValid();
+        List<MethodDescriptor> failList = new ArrayList<>();
+        // walk through all methods in pool to check match with test pattern
+        for (Pair<Executable, Callable<?>> pair : METHODS) {
+            MethodDescriptor m = MethodGenerator.commandDescriptor(pair.first);
+            Matcher matcher = pattern.matcher(m.getCanonicalString());
+            // get expected result
+            MatcherResult expected;
+            if (isValidDesc) {
+                expected = matcher.matches() ?
+                        MatcherResult.MATCH : MatcherResult.NO_MATCH;
+            } else {
+                expected = MatcherResult.PARSING_FAILURE;
+            }
+            // get MethodMatcher's result
+            MatcherResult matchResult = MatcherResult.fromCode(WB.matchesMethod(
+                    pair.first, methodDescriptor.getString()));
+            // compare
+            if (matchResult != expected) {
+                System.out.printf("- Method: %s%n-- FAILED: result: %s, " +
+                                "but expected: %s%n", m.getCanonicalString(),
+                        matchResult, expected);
+                failList.add(m);
+            }
+        }
+        int size = failList.size();
+        if (size != 0) {
+            System.err.println("FAILED test case: " + methodDescriptor
+                    .getString());
+            if (size == METHODS.size()) {
+                System.err.println("-- All methods failed to match");
+            } else {
+                for (MethodDescriptor md : failList) {
+                    System.err.println("-- FAILED match: " + md.getString());
+                }
+            }
+            throw new AssertionError("FAIL: " + methodDescriptor.getString());
+        }
+        System.out.println("--PASSED");
+    }
+
+    /**
+     * Represents MethodMatcher's matching result
+     */
+    public enum MatcherResult {
+        PARSING_FAILURE(-1, "Parsing failed"),
+        NO_MATCH(0, "No match"),
+        MATCH(1, "Match");
+
+        public final int code;
+        private final String message;
+
+        private MatcherResult(int code, String message) {
+            this.code = code;
+            this.message = message;
+        }
+
+        public static MatcherResult fromCode(int code) {
+            switch (code) {
+                case -1: return PARSING_FAILURE;
+                case  0: return NO_MATCH;
+                case  1: return MATCH;
+                default:
+                    throw new IllegalArgumentException("MATCHER FAILURE:"
+                            + "Wrong code: " + code);
+            }
+        }
+
+        @Override
+        public String toString() {
+            return message;
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/compilercontrol/share/method/ClassType.java	Thu Sep 24 20:13:04 2015 +0300
@@ -0,0 +1,175 @@
+/*
+ * Copyright (c) 2015, 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 compiler.compilercontrol.share.method;
+
+import java.lang.reflect.Executable;
+import java.util.Arrays;
+import java.util.stream.Collectors;
+
+/**
+ * Element represents class in method descriptor
+ * that consist from class package and class itself
+ */
+public class ClassType extends MethodElementType {
+    private final String[] packageDirs;
+    private final Class<?> aClass;
+    private boolean setPackage;
+
+    public ClassType(Executable method) {
+        // Use pack/subpack/Class::method separators style
+        super(MethodDescriptor.Separator.SLASH);
+        // Get package
+        aClass = method.getDeclaringClass();
+        Package aPackage = method.getDeclaringClass().getPackage();
+        if (aPackage != null) {
+            // split into directories
+            packageDirs = aPackage.getName().split("\\.");
+        } else {
+            packageDirs = null;
+        }
+        setPackage = true;
+        buildElement(setPackage);
+    }
+
+    @Override
+    public boolean isValid() {
+        if (element.isEmpty()) {
+            return false;
+        }
+        boolean separatorMet = false;
+        char separatorChar = 0;
+        char[] charArray = element.toCharArray();
+        for (int i = 0; i < charArray.length; i++) {
+            char ch = charArray[i];
+            switch (ch) {
+                case '/':
+                case '.':
+                    if (separatorMet) {
+                        if (ch != separatorChar) {
+                            // there are two different separators
+                            return false;
+                        }
+                    } else {
+                        separatorChar = ch;
+                        separatorMet = true;
+                    }
+                    break;
+                case ':':
+                    if (++i != charArray.length) {
+                        if (charArray[i] == ':') {
+                            // :: is invalid separator
+                            separator = MethodDescriptor.Separator.DOUBLECOLON;
+                            return false;
+                        }
+                    }
+                    break;
+                // Invalid separators
+                case ',':
+                case ' ':
+                    return false;
+            }
+        }
+        // set correct separator
+        switch (separatorChar) {
+            case '.':
+                separator = MethodDescriptor.Separator.DOT;
+                break;
+            case '/':
+                separator = MethodDescriptor.Separator.SLASH;
+                break;
+            default:
+                separator = MethodDescriptor.Separator.NONE;
+                break;
+        }
+        return super.isValid();
+    }
+
+    @Override
+    public void setSeparator(MethodDescriptor.Separator separator) {
+        this.separator = separator;
+        buildElement(setPackage);
+    }
+
+    @Override
+    public void setPattern(MethodDescriptor.PatternType patternType) {
+        switch (patternType) {
+            case EXACT:
+                break;
+            case PREFIX:
+                // For prefix pattern use only class name without package
+                buildElement(false);
+                regexp = ".*" + regexp;
+                element = "*" + element;
+                break;
+            case ANY:
+                regexp = ".*";
+                element = "*";
+                break;
+            case SUFFIX:
+                regexp = regexp + ".*";
+                element = element + "*";
+                break;
+            case SUBSTRING:
+                setPattern(MethodDescriptor.PatternType.PREFIX);
+                setPattern(MethodDescriptor.PatternType.SUFFIX);
+                break;
+            default:
+                throw new IllegalArgumentException("ERROR: wrong pattern type "
+                        + patternType);
+        }
+    }
+
+    /**
+     * Builds element string and regexp.
+     *
+     * @param setPackage shows that element should have a package name
+     */
+    private void buildElement(boolean setPackage) {
+        this.setPackage = setPackage;
+        StringBuilder elementBuilder = new StringBuilder();
+        if (packageDirs != null && setPackage) {
+            elementBuilder.append(Arrays.stream(packageDirs)
+                    .collect(Collectors.joining(separator.symbol)));
+            elementBuilder.append(separator.symbol);
+        }
+        String className = aClass.getSimpleName();
+        if (setPackage) {
+            // Add outer classes if any
+            Class<?> enclosingClass = aClass.getEnclosingClass();
+            while (enclosingClass != null) {
+                className = enclosingClass.getSimpleName() + "$" + className;
+                enclosingClass = enclosingClass.getEnclosingClass();
+            }
+        }
+        elementBuilder.append(className);
+        element = elementBuilder.toString();
+        if (separator == MethodDescriptor.Separator.DOT) {
+            // Replace . with / to make regexp look like CommandSignature
+            regexp = element.replace(".", "/");
+        } else {
+            regexp = element;
+        }
+        regexp = regexp.replace("$", "\\$");
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/compilercontrol/share/method/MethodDescriptor.java	Thu Sep 24 20:13:04 2015 +0300
@@ -0,0 +1,207 @@
+/*
+ * Copyright (c) 2015, 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 compiler.compilercontrol.share.method;
+
+import jdk.test.lib.Triple;
+
+import java.lang.reflect.Executable;
+import java.util.function.Function;
+import java.util.regex.Pattern;
+
+/**
+ * Method descriptor for Compiler Control commands.
+ * It represents method pattern used for matching in Compiler Control
+ * and CompileCommand option
+ */
+public class MethodDescriptor {
+    public final ClassType aClass;         // Represents class and package
+    public final MethodType aMethod;       // Represents method
+    public final SignatureType aSignature; // Represents signature
+
+    /**
+     * Constructor
+     *
+     * @param method executable to build method descriptor from
+     */
+    public MethodDescriptor(Executable method) {
+        aClass = new ClassType(method);
+        aMethod = new MethodType(method);
+        aSignature = new SignatureType(method);
+    }
+
+    /**
+     * Sets signature separators for all elements
+     */
+    public void setSeparators(
+            Triple<Separator, Separator, Separator> separators) {
+        aClass.setSeparator(separators.getFirst());
+        aMethod.setSeparator(separators.getSecond());
+        aSignature.setSeparator(separators.getThird());
+    }
+
+    /**
+     * Sets custom strings for each element
+     */
+    public void setStrings(Triple<String, String, String> strings) {
+        aClass.setElement(strings.getFirst());
+        aMethod.setElement(strings.getSecond());
+        aSignature.setElement(strings.getThird());
+    }
+
+    /**
+     * Sets patterns for all elements
+     */
+    public void setPatterns(
+            Triple<PatternType, PatternType, PatternType> patterns) {
+        aClass.setPattern(patterns.getFirst());
+        aMethod.setPattern(patterns.getSecond());
+        aSignature.setPattern(patterns.getThird());
+    }
+
+    /**
+     * Separates elements in the MethodDescriptor
+     */
+    public static enum Separator {
+        SLASH("/"),
+        DOT("."),
+        COMMA(","),
+        DOUBLECOLON("::"),
+        SPACE(" "),
+        NONE("");
+
+        public final String symbol;
+
+        Separator(String symbol) {
+            this.symbol = symbol;
+        }
+
+        /**
+         * Validates method descriptor separators
+         *
+         * @param md method descriptor to validate
+         * @return true if descriptor's separators are valid
+         */
+        public static boolean isValid(MethodDescriptor md) {
+            Separator cls = md.getClassSeparator();
+            Separator method = md.getMethodSeparator();
+            Separator sign = md.getSignatureSeparator();
+            if (sign == SPACE || sign == NONE || sign == COMMA) {
+                // if it looks like java/lang/String.indexOf
+                if ((cls == SLASH || cls == NONE)
+                        // allow space and comma instead of dot
+                        && (method == DOT || method == SPACE
+                        || method == COMMA)) {
+                    return true;
+                }
+                // if it looks like java.lang.String::indexOf
+                if ((cls == DOT || cls == NONE) && method == DOUBLECOLON) {
+                    return true;
+                }
+            }
+            return false;
+        }
+    }
+
+    /**
+     * Type of the pattern
+     */
+    public static enum PatternType {
+        PREFIX,
+        ANY,
+        SUFFIX,
+        SUBSTRING,
+        EXACT
+    }
+
+    public Separator getClassSeparator() {
+        return aClass.getSeparator();
+    }
+
+    public Separator getMethodSeparator() {
+        return aMethod.getSeparator();
+    }
+
+    public Separator getSignatureSeparator() {
+        return aSignature.getSeparator();
+    }
+
+    /**
+     * Gets regular expression to match methods
+     *
+     * @return string representation of the regular expression
+     */
+    public String getRegexp() {
+        // regexp should have a . as a method separator
+        // and / as a package/class separator
+        return aClass.getRegexp().replaceAll("\\.", "/")
+                .replaceAll("/\\*", ".*")
+                + Pattern.quote(Separator.DOT.symbol)
+                + aMethod.getRegexp() + aSignature.getRegexp();
+    }
+
+    /**
+     * Gets method descriptor string representation.
+     * This string is used as a pattern in CompilerControl and CompileCommand
+     */
+    public String getString() {
+        return aClass.getElement() + getMethodSeparator().symbol
+                + aMethod.getElement() + getSignatureSeparator().symbol
+                + aSignature.getElement();
+    }
+
+    /**
+     * Convert method descriptor to be regexp-compatible
+     *
+     * @return string representation of the method signature
+     */
+    public String getCanonicalString() {
+        return aClass.getElement().replaceAll("\\.", "/") + Separator.DOT.symbol
+                + aMethod.getElement() + aSignature.getElement();
+    }
+
+    /**
+     * Shows if this descriptor is a valid pattern for CompilerControl
+     *
+     * @return true, if descriptor is valid, false otherwise
+     */
+    public boolean isValid() {
+        return aClass.isValid() && aMethod.isValid() && aSignature.isValid()
+                && Separator.isValid(this);
+    }
+
+    /**
+     * Sets custom string from element mutate function
+     * to the appropriate element of method descriptor
+     */
+    public void applyMutates(Triple<Function<String, String>,
+                             Function<String, String>,
+                             Function<String, String>> mutators) {
+        String elementString = aClass.getElement();
+        aClass.setElement(mutators.getFirst().apply(elementString));
+        elementString = aMethod.getElement();
+        aMethod.setElement(mutators.getSecond().apply(elementString));
+        elementString = aSignature.getElement();
+        aSignature.setElement(mutators.getThird().apply(elementString));
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/compilercontrol/share/method/MethodElementType.java	Thu Sep 24 20:13:04 2015 +0300
@@ -0,0 +1,147 @@
+/*
+ * Copyright (c) 2015, 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 compiler.compilercontrol.share.method;
+
+import java.util.regex.Pattern;
+
+/**
+ * Class represents an element of the MethodDescriptor
+ * used as pattern for CompilerCommand method strings
+ */
+public abstract class MethodElementType {
+    private static final char[] INVALID_CHARS = { ';', '[', '(', ')', ']',
+            '<', '>'};
+    protected String element;
+    protected String regexp;
+    protected MethodDescriptor.Separator separator;
+
+    /**
+     * Constructor
+     */
+    protected MethodElementType(MethodDescriptor.Separator separator) {
+        this.separator = separator;
+    }
+
+    /**
+     * Gets element's separator
+     *
+     * @return separator instance
+     */
+    public MethodDescriptor.Separator getSeparator() {
+        return separator;
+    }
+
+    /**
+     * Sets separator for this element
+     *
+     * @param separator separator type
+     */
+    public void setSeparator(MethodDescriptor.Separator separator) {
+        this.separator = separator;
+    }
+
+    /**
+     * Gets String representation of the element
+     *
+     * @return element string
+     */
+    public String getElement() {
+        return element;
+    }
+
+    /**
+     * Sets String representation of the element
+     *
+     * @param element custom string to be used as an element
+     */
+    public void setElement(String element) {
+        this.element = element;
+        this.regexp = Pattern.quote(element);
+    }
+
+    /**
+     * Shows that the element is valid according to CompilerControl and JVMS specs
+     *
+     * @return true, if the element is a valid string
+     */
+    public boolean isValid() {
+        for (char ch : INVALID_CHARS) {
+            if (element.indexOf(ch) != -1) {
+                return false;
+            }
+        }
+        // Check for * usage
+        if (element.equals("**")) {
+            return false;
+        }
+        for (int i = 0; i < element.length(); i++) {
+            char c = element.charAt(i);
+            if (c == '*' && i > 0 && i < element.length() - 1) {
+                // Embedded * isn't allowed
+                return false;
+            }
+        }
+        return true;
+    }
+
+    /**
+     * Creates pattern of a given type
+     *
+     * @param patternType type of the pattern
+     */
+    public void setPattern(MethodDescriptor.PatternType patternType) {
+        switch (patternType) {
+            case EXACT:
+                break;
+            case PREFIX:
+                regexp = ".*" + regexp;
+                element = "*" + element;
+                break;
+            case ANY:
+                regexp = ".*";
+                element = "*";
+                break;
+            case SUFFIX:
+                regexp = regexp + ".*";
+                element = element + "*";
+                break;
+            case SUBSTRING:
+                setPattern(MethodDescriptor.PatternType.PREFIX);
+                setPattern(MethodDescriptor.PatternType.SUFFIX);
+                break;
+            default:
+                throw new IllegalArgumentException("ERROR: wrong pattern type"
+                        + patternType);
+        }
+    }
+
+    /**
+     * Gets regular expression of this element
+     *
+     * @return string representation of regexp
+     */
+    public String getRegexp() {
+        return regexp;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/compilercontrol/share/method/MethodGenerator.java	Thu Sep 24 20:13:04 2015 +0300
@@ -0,0 +1,263 @@
+/*
+ * Copyright (c) 2015, 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 compiler.compilercontrol.share.method;
+
+import compiler.compilercontrol.share.method.MethodDescriptor.PatternType;
+import compiler.compilercontrol.share.method.MethodDescriptor.Separator;
+import jdk.test.lib.Pair;
+import jdk.test.lib.Triple;
+import jdk.test.lib.Utils;
+import pool.PoolHelper;
+
+import java.lang.reflect.Executable;
+import java.util.ArrayList;
+import java.util.EnumSet;
+import java.util.List;
+import java.util.concurrent.Callable;
+import java.util.function.Function;
+
+/**
+ * Generates combinations of method descriptors from the pool of methods
+ */
+public class MethodGenerator {
+    private static final List<Pair<Executable, Callable<?>>> METHODS =
+            new PoolHelper().getAllMethods(PoolHelper.METHOD_FILTER);
+    // Different combinations of patterns
+    private static final List<Combination<PatternType>> PATTERNS_LIST;
+    // Different combinations of separators
+    private static final List<Combination<Separator>> SEPARATORS_LIST;
+    // List of functions that modify elements
+    private static final List<Function<String, String>> ELEMENT_MUTATORS;
+
+    static {
+        PATTERNS_LIST =
+                generate(EnumSet.allOf(PatternType.class),
+                        EnumSet.allOf(PatternType.class),
+                        EnumSet.of(PatternType.ANY, PatternType.EXACT));
+        SEPARATORS_LIST =
+                generate(EnumSet.of(Separator.SLASH, Separator.DOT),
+                        EnumSet.complementOf(EnumSet.of(Separator.NONE)),
+                        EnumSet.of(Separator.COMMA, Separator.SPACE,
+                                Separator.NONE));
+        ELEMENT_MUTATORS = generateMutators();
+    }
+
+    // Test method
+    public static void main(String[] args) {
+        MethodGenerator methodGenerator = new MethodGenerator();
+        List<MethodDescriptor> tests = methodGenerator.getTests();
+        tests.forEach(System.out::println);
+    }
+
+    /**
+     * Generates random method descriptor
+     *
+     * @param executable executable used to generate descriptor
+     * @return MethodDescriptor instance
+     */
+    public MethodDescriptor generateRandomDescriptor(Executable executable) {
+        Combination<PatternType> patterns =
+                Utils.getRandomElement(PATTERNS_LIST);
+        Combination<Separator> separators =
+                Utils.getRandomElement(SEPARATORS_LIST);
+        // Create simple mutators for signature generation
+        List<Function<String, String>> signMutators = new ArrayList<>();
+        signMutators.add(input -> input);
+        signMutators.add(input -> "");
+        Combination<Function<String, String>> mutators = new Combination<>(
+                Utils.getRandomElement(ELEMENT_MUTATORS),
+                Utils.getRandomElement(ELEMENT_MUTATORS),
+                // use only this type of mutators
+                Utils.getRandomElement(signMutators));
+        return makeMethodDescriptor(executable, patterns,
+                separators, mutators);
+    }
+
+    /**
+     * Compile command signature that looks like java/lang/String.indexOf
+     * http://docs.oracle.com/javase/8/docs/technotes/tools/unix/java.html#BABDDFII
+     *
+     * @param executable executable used to generate descriptor
+     * @return MethodDescriptor instance
+     */
+    public static MethodDescriptor commandDescriptor(Executable executable) {
+        MethodDescriptor md = new MethodDescriptor(executable);
+        md.aClass.setSeparator(Separator.SLASH);
+        md.aMethod.setSeparator(Separator.DOT);
+        md.aSignature.setSeparator(Separator.NONE);
+        return md;
+    }
+
+    /**
+     * Compile command signature that looks like java.lang.String::indexOf
+     *
+     * @param executable executable used to generate descriptor
+     * @return MethodDescriptor instance
+     */
+    public static MethodDescriptor logDescriptor(Executable executable) {
+        MethodDescriptor md = new MethodDescriptor(executable);
+        md.aClass.setSeparator(Separator.DOT);
+        md.aMethod.setSeparator(Separator.DOUBLECOLON);
+        md.aSignature.setSeparator(Separator.NONE);
+        return md;
+    }
+
+    /**
+     * Generates a list of method patterns from the pool of methods
+     *
+     * @return a list of test cases
+     */
+    public List<MethodDescriptor> getTests() {
+        List<MethodDescriptor> list = new ArrayList<>();
+        METHODS.forEach(pair -> list.addAll(getTests(pair.first)));
+        return list;
+    }
+
+    /**
+     * Generates all combinations of method descriptors for a given executable
+     *
+     * @param executable executable for which the different combination is built
+     * @return list of method descriptors
+     */
+    public List<MethodDescriptor> getTests(Executable executable) {
+        List<MethodDescriptor> list = new ArrayList<>();
+        for (Combination<PatternType> patterns : PATTERNS_LIST) {
+            for (Combination<Separator> separators : SEPARATORS_LIST) {
+                for (Function<String, String> classGen : ELEMENT_MUTATORS) {
+                    for (Function<String, String> methodGen :
+                            ELEMENT_MUTATORS) {
+                        for (Function<String, String> signatureGen :
+                                ELEMENT_MUTATORS) {
+                            list.add(makeMethodDescriptor(executable,
+                                    patterns, separators,
+                                    new Combination<>(classGen, methodGen,
+                                        signatureGen)));
+                        }
+                    }
+                }
+            }
+        }
+        return list;
+    }
+
+    /**
+     * Creates method descriptor from the given executable,
+     * patterns and separators for its elements
+     */
+    private MethodDescriptor makeMethodDescriptor(
+            Executable executable,
+            Combination<PatternType> patterns,
+            Combination<Separator> separators,
+            Combination<Function<String, String>> mutators) {
+        MethodDescriptor methodDescriptor = new MethodDescriptor(executable);
+        methodDescriptor.setSeparators(separators);
+        methodDescriptor.applyMutates(mutators);
+        methodDescriptor.setPatterns(patterns);
+        return methodDescriptor;
+    }
+
+    /**
+     * Creates a list of functions that change given string
+     */
+    private static List<Function<String, String>> generateMutators() {
+        List<Function<String, String>> elements = new ArrayList<>();
+        // Use the input itself
+        elements.add(input -> input);
+        // Use half of the input string
+        elements.add(input -> input.substring(input.length() / 2));
+        // Add nonexistent element
+        elements.add(input -> "nonexistent");
+        // Use left and right angle brackets
+        elements.add(input -> "<" + input + ">");
+        // Embed * inside
+        elements.add(input -> embed(input, "*"));
+        // ** as a whole element
+        elements.add(input -> "**");
+        // Embed JLS-invalid letters
+        elements.add(input -> embed(input, "@%"));
+        elements.add(input -> embed(input, "]"));
+        // Use JLS-invalid letters
+        elements.add(input -> "-");
+        elements.add(input -> "+");
+        elements.add(input -> ")" + input);
+        elements.add(input -> "{" + input + "}");
+        // Add valid Java identifier start char
+        elements.add(input -> "_" + input);
+        elements.add(input -> "$" + input);
+        elements.add(input -> "0" + input);
+        // Unicode characters
+        elements.add(input -> embed(input, "\u0001"));
+        elements.add(input -> embed(input, "\u007F"));
+        // Combining character
+        elements.add(input -> embed(input, "\u0300"));
+        elements.add(input -> embed(input, "\u0306"));
+        // Supplementary character
+        elements.add(input -> new String(Character.toChars(0x1F64C)));
+        return elements;
+    }
+
+    /**
+     * Embeds one string inside another one
+     *
+     * @param target  target source string
+     * @param element string to be embedded into target string
+     * @return result string
+     */
+    private static String embed(String target, String element) {
+        int mid = target.length() / 2;
+        String begin = target.substring(0, mid);
+        String end = target.substring(mid);
+        return begin + element + end;
+    }
+
+    /**
+     * Generates triples from the given enum sets
+     * for each of the method elements
+     *
+     * @param classSet  set of allowed elements for class
+     * @param methodSet set of allowed elements for method
+     * @param signSet   set of allowed elements for signature
+     * @param <E>       type of generated triples
+     * @return list of triples
+     */
+    private static <E extends Enum<E>> List<Combination<E>> generate(
+            EnumSet<E> classSet, EnumSet<E> methodSet, EnumSet<E> signSet) {
+        List<Combination<E>> list = new ArrayList<>();
+        classSet.forEach(clsElement ->
+            methodSet.forEach(methodElement ->
+                signSet.forEach(signElement ->
+                    list.add(new Combination<>(clsElement, methodElement,
+                            signElement))
+                )
+            )
+        );
+        return list;
+    }
+
+    private static class Combination<T> extends Triple<T, T, T> {
+        public Combination(T first, T second, T third) {
+            super(first, second, third);
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/compilercontrol/share/method/MethodType.java	Thu Sep 24 20:13:04 2015 +0300
@@ -0,0 +1,89 @@
+/*
+ * Copyright (c) 2015, 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 compiler.compilercontrol.share.method;
+
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Executable;
+
+/**
+ * Represents a method in CompileControl method signature
+ */
+public class MethodType extends MethodElementType {
+    private static final char[] INVALID_CHARS = { '.', '/' };
+
+    public MethodType(Executable method) {
+        // Use pack/subpack/Class::method separators style
+        super(MethodDescriptor.Separator.DOT);
+        if (method instanceof Constructor) {
+            element = "<init>";
+        } else {
+            element = method.getName();
+        }
+        regexp = element;
+    }
+
+    @Override
+    public boolean isValid() {
+        for (char ch : INVALID_CHARS) {
+            if (element.indexOf(ch) != -1) {
+                return false;
+            }
+        }
+        if (element.isEmpty()) {
+            // Shouldn't be empty
+            return false;
+        }
+        if (element.contains("<") || element.contains(">")) {
+            return element.matches("(\\*)?<(cl)?init>(\\*)?");
+        }
+        return super.isValid();
+    }
+
+    @Override
+    public void setPattern(MethodDescriptor.PatternType patternType) {
+        switch (patternType) {
+            case EXACT:
+                break;
+            case PREFIX:
+                regexp = ".*" + regexp;
+                element = "*" + element;
+                break;
+            case ANY:
+                regexp = "[^(]*";
+                element = "*";
+                break;
+            case SUFFIX:
+                regexp = regexp + "[^(]*";
+                element = element + "*";
+                break;
+            case SUBSTRING:
+                setPattern(MethodDescriptor.PatternType.PREFIX);
+                setPattern(MethodDescriptor.PatternType.SUFFIX);
+                break;
+            default:
+                throw new IllegalArgumentException("ERROR: wrong pattern type "
+                        + patternType);
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/compilercontrol/share/method/SignatureType.java	Thu Sep 24 20:13:04 2015 +0300
@@ -0,0 +1,151 @@
+/*
+ * Copyright (c) 2015, 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 compiler.compilercontrol.share.method;
+
+import jdk.test.lib.Utils;
+
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Executable;
+import java.lang.reflect.Method;
+import java.util.Arrays;
+
+/**
+ * This class represents a signature of the method
+ */
+public class SignatureType extends MethodElementType {
+    public SignatureType(Executable method) {
+        super(MethodDescriptor.Separator.NONE);
+        // Get parameters
+        Class<?>[] types = method.getParameterTypes();
+        String[] parameterTypes = new String[types.length];
+        for (int i = 0; i < types.length; i++) {
+            parameterTypes[i] = Utils.toJVMTypeSignature(types[i]);
+        }
+        // Get return value
+        String returnType;
+        if (method instanceof Method) {
+            returnType = Utils.toJVMTypeSignature(((Method) method)
+                    .getReturnType());
+        } else if (method instanceof Constructor) {
+            // Constructor returns void in VM
+            returnType = Utils.toJVMTypeSignature(void.class);
+        } else {
+            throw new Error(String.format("TESTBUG: wrong type of executable "
+                    + "%s of class %s", method, method.getClass()));
+        }
+        // Create signature
+        setElement("(" + String.join("", parameterTypes)+ ")" + returnType);
+        regexp = element;
+        setPattern(MethodDescriptor.PatternType.EXACT);
+        separator = MethodDescriptor.Separator.NONE;
+    }
+
+    @Override
+    public void setElement(String element) {
+        if (element.isEmpty()) {
+            setPattern(MethodDescriptor.PatternType.ANY);
+        } else {
+            super.setElement(element);
+        }
+    }
+
+    @Override
+    public boolean isValid() {
+        if (element.isEmpty()) {
+            return true;
+        }
+        // Allowed primitive types
+        char[] baseTypes = {'B', 'C', 'D', 'F', 'I', 'J', 'S', 'Z'};  // sorted
+        // Parsing states
+        boolean isArray = false;
+        boolean isInsideSig = false;
+        boolean isClass = false;
+
+        for (char ch : element.toCharArray()) {
+            if (ch == '(') {
+                if (isInsideSig) {
+                    // Met another ( inside
+                    return false;
+                }
+                isInsideSig = true;
+            } else if (ch == ')') {
+                if (!isInsideSig) {
+                    // met another ) outside
+                    return false;
+                }
+                isInsideSig = false;
+            } else if (ch == 'V') {
+                if (isInsideSig) {
+                    // void type is allowed only as a return value
+                    return false;
+                }
+            } else if (ch == 'L') {
+                // this is a beginning of class/interface
+                isClass = true;
+                // met actual type of array
+                isArray = false;
+            } else if (ch == '[') {
+                isArray = true;
+            } else if (isClass) {
+                if (!Character.isJavaIdentifierPart(ch)) {
+                    if (ch == '/' || ch == '.') {
+                        // separator met
+                    } else if (ch == ';') {
+                        // end of class/interface
+                        isClass = false;
+                    } else {
+                        return false;
+                    }
+                }
+            } else if (Arrays.binarySearch(baseTypes, ch) < 0) {
+                // if it doesn't belong to base types
+                return false;
+            } else {
+                // array of a base type
+                isArray = false;
+            }
+        }
+        return !(isArray || isInsideSig || isClass);
+    }
+
+    @Override
+    public void setPattern(MethodDescriptor.PatternType patternType) {
+        switch (patternType) {
+            case PREFIX:
+            case SUFFIX:
+            case SUBSTRING:
+                // These patterns are not supported in Compiler Control
+                // Just use ANY pattern instead
+            case ANY:
+                regexp = "\\(.*\\).*";
+                element = "";
+                break;
+            case EXACT:
+                break;
+            default:
+                throw new IllegalArgumentException("ERROR: wrong pattern type "
+                        + patternType);
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/compilercontrol/share/pool/MethodHolder.java	Thu Sep 24 20:13:04 2015 +0300
@@ -0,0 +1,122 @@
+/*
+ * Copyright (c) 2015, 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 pool;
+
+import jdk.test.lib.Pair;
+
+import java.lang.reflect.Executable;
+import java.lang.reflect.Method;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.Callable;
+
+/**
+ * Represents a holder that contains test methods
+ */
+public abstract class MethodHolder {
+    /**
+     * Helper method to get executable for the specified method
+     *
+     * @param holder class that holds specified method
+     * @param name method name
+     * @param parameterTypes parameter types of the specified method
+     * @return {@link Method} instance
+     */
+    public Method getMethod(MethodHolder holder,
+                             String name,
+                             Class<?>... parameterTypes) {
+        try {
+            return holder.getClass().getDeclaredMethod(name, parameterTypes);
+        } catch (NoSuchMethodException e) {
+            throw new Error("TESTBUG: Can't get method " + name, e);
+        }
+    }
+
+    /**
+     * Gets all test methods
+     *
+     * @return pairs of Executable and appropriate Callable
+     */
+    public List<Pair<Executable, Callable<?>>> getAllMethods() {
+        Class<?> aClass = this.getClass();
+        Object classInstance;
+        try {
+            classInstance = aClass.newInstance();
+        } catch (ReflectiveOperationException e) {
+            throw new Error("TESTBUG: unable to get new instance", e);
+        }
+        List<Pair<Executable, Callable<?>>> pairs = new ArrayList<>();
+        {
+            Method method = getMethod(this, "method", int.class, String[].class,
+                    Integer.class, byte[].class, double[][].class);
+            Pair<Executable, Callable<?>> pair = new Pair<>(method,
+                    () -> {
+                        // Make args
+                        int a = 0;
+                        String[] ss = {"a", "b", "c", "d"};
+                        Integer i = 1;
+                        byte[] bb = {1, 2};
+                        double[][] dd = {
+                                {1.618033, 3.141592},
+                                {2.718281, 0.007874}
+                        };
+                        // Invoke method
+                        method.invoke(classInstance, a, ss, i, bb, dd);
+                        return true;
+                    });
+            pairs.add(pair);
+        }
+        {
+            Method method = getMethod(this, "method");
+            Pair<Executable, Callable<?>> pair = new Pair<>(method,
+                    () -> {
+                        method.invoke(classInstance);
+                        return true;
+                    });
+            pairs.add(pair);
+        }
+        {
+            Method method = getMethod(this, "smethod");
+            Pair<Executable, Callable<?>> pair = new Pair<>(method,
+                    () -> method.invoke(classInstance));
+            pairs.add(pair);
+        }
+        {
+            Method method = getMethod(this, "smethod", int.class, int[].class);
+            Pair<Executable, Callable<?>> pair = new Pair<>(method,
+                    () -> {
+                        int[] array = {1, 2, 3};
+                        return method.invoke(classInstance, 42, array);
+                    });
+            pairs.add(pair);
+        }
+        {
+            Method method = getMethod(this, "smethod", Integer.class);
+            Pair<Executable, Callable<?>> pair = new Pair<>(method,
+                    () -> method.invoke(classInstance, 100));
+            pairs.add(pair);
+        }
+        return pairs;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/compilercontrol/share/pool/PoolHelper.java	Thu Sep 24 20:13:04 2015 +0300
@@ -0,0 +1,89 @@
+/*
+ * Copyright (c) 2015, 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 pool;
+
+import jdk.test.lib.Pair;
+import pool.MethodHolder;
+import java.lang.reflect.Executable;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.Callable;
+import java.util.function.Predicate;
+import java.util.stream.Collectors;
+
+/**
+ * This is a helper class that provides tests with methods
+ */
+public class PoolHelper extends MethodHolder {
+    private static final List<Pair<Executable, Callable<?>>> METHODS;
+
+    /**
+     * Filters only those methods who belong to Klass or its internal class
+     * Internal and named as "method" or is a constructor
+     */
+    public static final Predicate<Executable> METHOD_FILTER = executable -> {
+        String methodName = executable.getName();
+        String className = executable.getDeclaringClass().getName();
+        return className.matches(".*(Klass)(\\$Internal)?") &&
+                (methodName.equals("method") ||
+                        methodName.equals(className)); // if method is <init>
+    };
+
+    static {
+        METHODS = new ArrayList<>();
+        List<MethodHolder> holders = new ArrayList<>();
+        holders.add(new pool.sub.Klass());
+        holders.add(new pool.sub.KlassDup());
+        holders.add(new pool.subpack.Klass());
+        holders.add(new pool.subpack.KlassDup());
+        holders.add(new pool.sub.Klass.Internal());
+        holders.add(new pool.subpack.KlassDup.Internal());
+        for (MethodHolder holder : holders) {
+            METHODS.addAll(holder.getAllMethods());
+        }
+    }
+
+    /**
+     * Gets all methods from the pool using specified filter
+     *
+     * @param filter method filter
+     * @return pairs of Executable and appropriate Callable
+     */
+    public List<Pair<Executable, Callable<?>>> getAllMethods(
+            Predicate<Executable> filter) {
+        return getAllMethods().stream()
+                .filter(pair -> filter.test(pair.first))
+                .collect(Collectors.toList());
+    }
+
+    /**
+     * Gets all methods from the pool
+     *
+     * @return pairs of Executable and appropriate Callable
+     */
+    @Override
+    public List<Pair<Executable, Callable<?>>> getAllMethods() {
+        return METHODS;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/compilercontrol/share/pool/sub/Klass.java	Thu Sep 24 20:13:04 2015 +0300
@@ -0,0 +1,92 @@
+/*
+ * Copyright (c) 2015, 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 pool.sub;
+
+import jdk.test.lib.Pair;
+import pool.MethodHolder;
+
+import java.lang.reflect.Executable;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.Callable;
+
+/**
+ * Simple class with methods to test signatures
+ */
+public class Klass extends MethodHolder {
+    public void method(int a, String[] ss, Integer i, byte[] bb, double[][] dd) { }
+
+    public void method() { }
+
+    public static String smethod() {
+        return "ABC";
+    }
+
+    public static String smethod(int iarg, int[] aarg) {
+        return "ABC";
+    }
+
+    public static Integer smethod(Integer arg) {
+        Integer var = 1024;
+        return arg + var;
+    }
+
+    // Internal class and constructor
+    public static class Internal extends MethodHolder {
+        public Internal() { }
+
+        public Double method(Float fl) { return Double.valueOf(fl); }
+
+        public Double methodDup() {
+            return Math.exp(1.0);
+        }
+
+        public static Integer smethod(Integer arg) {
+            Integer var = 1024;
+            return arg + var;
+        }
+
+        @Override
+        public List<Pair<Executable, Callable<?>>> getAllMethods() {
+            List<Pair<Executable, Callable<?>>> pairs = new ArrayList<>();
+            Pair<Executable, Callable<?>> pair = new Pair<>
+                    (getMethod(this, "method", Float.class),
+                            () -> this.method(3.141592f));
+            pairs.add(pair);
+            pair = new Pair<>(getMethod(this, "methodDup"), this::methodDup);
+            pairs.add(pair);
+            pair = new Pair<>(getMethod(this, "smethod", Integer.class),
+                    () -> smethod(1024));
+            pairs.add(pair);
+            try {
+                pair = new Pair<>(this.getClass().getConstructor(),
+                        Internal::new);
+                pairs.add(pair);
+            } catch (NoSuchMethodException e) {
+                throw new Error("TESTBUG: unable to get constructor");
+            }
+            return pairs;
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/compilercontrol/share/pool/sub/KlassDup.java	Thu Sep 24 20:13:04 2015 +0300
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2015, 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 pool.sub;
+
+import pool.MethodHolder;
+
+/**
+ * Simple class with methods to test signatures
+ * This class has Dup suffix in the name to test suffix patterns like Klass*.
+ * Such patterns should match both Klass and KlassDup
+ */
+public class KlassDup extends MethodHolder {
+    public void method(int a, String[] ss, Integer i, byte[] bb, double[][] dd) { }
+
+    public void method() { }
+
+    public static String smethod() {
+        return "ABC";
+    }
+
+    public static String smethod(int iarg, int[] aarg) {
+        return "ABC";
+    }
+
+    public static Integer smethod(Integer arg) {
+        Integer var = 1024;
+        return arg + var;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/compilercontrol/share/pool/subpack/Klass.java	Thu Sep 24 20:13:04 2015 +0300
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2015, 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 pool.subpack;
+
+import pool.MethodHolder;
+
+/**
+ * Simple class with methods to test signatures
+ * This is a clone of the pool.sub.Klass, but without inner class
+ * This class has different package name to test prefix patterns like *Klass.
+ * *Klass patern should match both pool.sub.Klass and pool.subpack.Klass
+ */
+public class Klass extends MethodHolder {
+    public void method(int a, String[] ss, Integer i, byte[] bb, double[][] dd) { }
+
+    public void method() { }
+
+    public static String smethod() {
+        return "ABC";
+    }
+
+    public static String smethod(int iarg, int[] aarg) {
+        return "ABC";
+    }
+
+    public static Integer smethod(Integer arg) {
+        Integer var = 1024;
+        return arg + var;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/compilercontrol/share/pool/subpack/KlassDup.java	Thu Sep 24 20:13:04 2015 +0300
@@ -0,0 +1,93 @@
+/*
+ * Copyright (c) 2015, 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 pool.subpack;
+
+import jdk.test.lib.Pair;
+import pool.MethodHolder;
+
+import java.lang.reflect.Executable;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.Callable;
+
+/**
+ * This is a clone of the pool.sub.Klass used to test pattern matching
+ * Full class name contains both suffix (Dup) and prefix (pool.subpack)
+ */
+public class KlassDup extends MethodHolder {
+    public void method(int a, String[] ss, Integer i, byte[] bb, double[][] dd) { }
+
+    public void method() { }
+
+    public static String smethod() {
+        return "ABC";
+    }
+
+    public static String smethod(int iarg, int[] aarg) {
+        return "ABC";
+    }
+
+    public static Integer smethod(Integer arg) {
+        Integer var = 1024;
+        return arg + var;
+    }
+
+    // Internal class and constructor
+    public static class Internal extends MethodHolder {
+        public Internal() { }
+
+        public Double method(Float fl) { return Double.valueOf(fl); }
+
+        public Double methodDup() {
+            return Math.exp(1.0);
+        }
+
+        public static Integer smethod(Integer arg) {
+            Integer var = 1024;
+            return arg + var;
+        }
+
+        @Override
+        public List<Pair<Executable, Callable<?>>> getAllMethods() {
+            List<Pair<Executable, Callable<?>>> pairs = new ArrayList<>();
+            Pair<Executable, Callable<?>> pair = new Pair<>
+                    (getMethod(this, "method", Float.class),
+                            () -> this.method(3.141592f));
+            pairs.add(pair);
+            pair = new Pair<>(getMethod(this, "methodDup"), this::methodDup);
+            pairs.add(pair);
+            pair = new Pair<>(getMethod(this, "smethod", Integer.class),
+                    () -> smethod(1024));
+            pairs.add(pair);
+            try {
+                pair = new Pair<>(this.getClass().getConstructor(),
+                        Internal::new);
+                pairs.add(pair);
+            } catch (NoSuchMethodException e) {
+                throw new Error("TESTBUG: unable to get constructor");
+            }
+            return pairs;
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/testlibrary/jdk/test/lib/Pair.java	Thu Sep 24 20:13:04 2015 +0300
@@ -0,0 +1,68 @@
+/*
+ * Copyright (c) 2015, 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 jdk.test.lib;
+
+import java.util.Objects;
+
+/**
+ * Pair - a two element tuple
+ *
+ * @param <F> first type
+ * @param <S> second type
+ */
+public class Pair<F, S> {
+    public final F first;
+    public final S second;
+
+    public Pair(F first, S second) {
+        this.first = first;
+        this.second = second;
+    }
+
+    @Override
+    public String toString() {
+        return "(" + first + ":" + second + ")";
+    }
+
+    @Override
+    public boolean equals(Object other) {
+        if (other instanceof Pair<?, ?>) {
+            Pair<?, ?> otherPair = (Pair<?, ?>) other;
+            return Objects.equals(first, otherPair.first) &&
+                    Objects.equals(second, otherPair.second);
+        }
+        return false;
+    }
+
+    @Override
+    public int hashCode() {
+        if (first == null) {
+            return (second == null) ? 0 : second.hashCode();
+        } else if (second == null) {
+            return first.hashCode();
+        } else {
+            return first.hashCode() * 17 + second.hashCode();
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/testlibrary/jdk/test/lib/Triple.java	Thu Sep 24 20:13:04 2015 +0300
@@ -0,0 +1,90 @@
+/*
+ * Copyright (c) 2015, 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 jdk.test.lib;
+
+import java.util.Objects;
+
+/**
+ * Triple - a three element tuple
+ *
+ * @param <F> first element type
+ * @param <S> second element type
+ * @param <T> third element type
+ */
+public class Triple<F, S, T> {
+    private final Pair<F, Pair<S, T>> container;
+
+    /**
+     * Constructor
+     *
+     * @param first  first element of the triple
+     * @param second second element of the triple
+     * @param third  third element of the triple
+     */
+    public Triple(F first, S second, T third) {
+        container = new Pair<>(first, new Pair<>(second, third));
+    }
+
+    /**
+     * Gets first element of the triple
+     */
+    public F getFirst() {
+        return container.first;
+    }
+
+    /**
+     * Gets second element of the triple
+     */
+    public S getSecond() {
+        return container.second.first;
+    }
+
+    /**
+     * Gets third element of the triple
+     */
+    public T getThird() {
+        return container.second.second;
+    }
+
+    @Override
+    public int hashCode() {
+        return container.hashCode();
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (obj instanceof Triple<?, ?, ?>) {
+            Triple<?, ?, ?> objTriple = (Triple<?, ?, ?>) obj;
+            return Objects.equals(container.first, objTriple.container.first)
+                    && Objects.equals(container.second,
+                    objTriple.container.second);
+        }
+        return false;
+    }
+
+    @Override
+    public String toString() {
+        return "(" + getFirst() + " : " + getSecond() + " : " + getThird() + ")";
+    }
+}
--- a/hotspot/test/testlibrary/jdk/test/lib/Utils.java	Thu Sep 24 18:24:10 2015 +0300
+++ b/hotspot/test/testlibrary/jdk/test/lib/Utils.java	Thu Sep 24 20:13:04 2015 +0300
@@ -34,7 +34,9 @@
 import java.nio.file.Paths;
 import java.util.ArrayList;
 import java.util.Arrays;
+import java.util.Collection;
 import java.util.Collections;
+import java.util.Iterator;
 import java.util.List;
 import java.util.Random;
 import java.util.function.BooleanSupplier;
@@ -379,6 +381,28 @@
     }
 
     /**
+     * Returns random element of non empty collection
+     *
+     * @param <T> a type of collection element
+     * @param collection collection of elements
+     * @return random element of collection
+     * @throws IllegalArgumentException if collection is empty
+     */
+    public static <T> T getRandomElement(Collection<T> collection)
+            throws IllegalArgumentException {
+        if (collection.isEmpty()) {
+            throw new IllegalArgumentException("Empty collection");
+        }
+        Random random = getRandomInstance();
+        int elementIndex = 1 + random.nextInt(collection.size() - 1);
+        Iterator<T> iterator = collection.iterator();
+        while (--elementIndex != 0) {
+            iterator.next();
+        }
+        return iterator.next();
+    }
+
+    /**
      * Wait for condition to be true
      *
      * @param condition, a condition to wait for
@@ -461,5 +485,41 @@
         }
     }
 
+    /**
+     * Converts to VM type signature
+     *
+     * @param type Java type to convert
+     * @return string representation of VM type
+     */
+    public static String toJVMTypeSignature(Class<?> type) {
+        if (type.isPrimitive()) {
+            if (type == boolean.class) {
+                return "Z";
+            } else if (type == byte.class) {
+                return "B";
+            } else if (type == char.class) {
+                return "C";
+            } else if (type == double.class) {
+                return "D";
+            } else if (type == float.class) {
+                return "F";
+            } else if (type == int.class) {
+                return "I";
+            } else if (type == long.class) {
+                return "J";
+            } else if (type == short.class) {
+                return "S";
+            } else if (type == void.class) {
+                return "V";
+            } else {
+                throw new Error("Unsupported type: " + type);
+            }
+        }
+        String result = type.getName().replaceAll("\\.", "/");
+        if (!type.isArray()) {
+            return "L" + result + ";";
+        }
+        return result;
+    }
 }