1 /*
2  * Copyright (c) 2013, 2018, Oracle and/or its affiliates. All rights reserved.
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * This code is free software; you can redistribute it and/or modify it
6  * under the terms of the GNU General Public License version 2 only, as
7  * published by the Free Software Foundation.
8  *
9  * This code is distributed in the hope that it will be useful, but WITHOUT
10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
12  * version 2 for more details (a copy is included in the LICENSE file that
13  * accompanied this code).
14  *
15  * You should have received a copy of the GNU General Public License version
16  * 2 along with this work; if not, write to the Free Software Foundation,
17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18  *
19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20  * or visit www.oracle.com if you need additional information or have any
21  * questions.
22  */
23 package vm.compiler.complog.uninit;
24 
25 import java.util.*;
26 import java.util.regex.*;
27 import java.io.*;
28 
29 import nsk.share.TestFailure;
30 import vm.compiler.complog.share.LogCompilationParser;
31 
32 /**
33  * Parser that finds uninitialized traps for each method and throws
34  * and exception if there are more then 1 uninitialized trap for at least 1 method.
35  *
36  * Parser supports following options:
37  * <ul>
38  * <li>-classFilter=<comma separated list> - list of classes for which uncommon traps will be checked. If option is not presented or list is empty then all uncommon traps for all classes will be checked.
39  * <li>-methodFilter=<comma separated list> - list of methods for which uncommon traps will be checked. If option is not presented or list is empty then all uncommon traps for all methods will be checked.
40  * </ul>
41  * If compilation log contains uncommon trap with reason uninialized that was fired for method M in class K, then it will be checked only if classFilter contains K and methodFilter contains M.
42  */
43 public class UninitializedTrapCounter extends LogCompilationParser {
44     private Map<String,Integer> methods = new LinkedHashMap<String,Integer>();
45 
46     private static final String JVMS_ELEMENT = "<jvms [^>]*>";
47     private static final String METHOD_INFO = "method='(([^ ']+) ([^ ']+) [^']+)'.*uninitialized_traps='([0-9]+)'";
48     private static final String CLASS_FILTER = "-classFilter=([^ ]+)";
49     private static final String METHOD_FILTER = "-methodFilter=([^ ]+)";
50     private static Pattern pattern = Pattern.compile(METHOD_INFO);
51 
52     private List<String> classFilter = new ArrayList<String>();
53     private List<String> methodFilter = new ArrayList<String>();
54 
setOptions(String optionString)55     public void setOptions(String optionString) {
56         if(optionString == null) return;
57         Matcher methodFilterMatcher = Pattern.compile(METHOD_FILTER).matcher(optionString);
58         Matcher classFilterMatcher = Pattern.compile(CLASS_FILTER).matcher(optionString);
59         if(methodFilterMatcher.find()) {
60             methodFilter = Arrays.asList(methodFilterMatcher.group(1).split(","));
61         }
62         if(classFilterMatcher.find()) {
63             classFilter = Arrays.asList(classFilterMatcher.group(1).split(","));
64         }
65     }
66 
67     /**
68      * Find uninitialized traps count.
69      */
parse(File logFile)70     public void parse(File logFile) throws Throwable {
71         Scanner scanner = new Scanner(logFile);
72         String jvms = scanner.findWithinHorizon(JVMS_ELEMENT,0);
73         while(jvms != null) {
74             parseJVMSElement(jvms);
75             jvms = scanner.findWithinHorizon(JVMS_ELEMENT,0);
76         }
77 
78         boolean failed = false;
79         for(Map.Entry<String,Integer> method : methods.entrySet()) {
80             if(method.getValue() > 1) {
81                 failed = true;
82                 log.error(method.getValue() +
83                           " uninitizlied traps found for method '" +
84                           method.getKey() + "'.");
85 
86             }
87         }
88         if(failed) {
89             throw new TestFailure("More than 1 uncommon trap with reason 'uninitialized'"+
90                                   " occurred at least for 1 method.");
91         }
92     }
93 
parseJVMSElement(String jvms)94     private void parseJVMSElement(String jvms) {
95         Matcher matcher = pattern.matcher(jvms);
96         if(!matcher.find()) return;
97 
98         String methodID = matcher.group(1);
99         String trapsCountStr = matcher.group(4);
100         Integer trapsCount = 0;
101         Integer oldTrapsCount = 0;
102         String className = matcher.group(2);
103         String methodName = matcher.group(3);
104 
105         if((classFilter.size() > 0 && !findMatches(classFilter,className)) ||
106            (methodFilter.size() > 0 && !findMatches(methodFilter,methodName))) {
107             //filtering out uncommon trap we are not interested in
108             return;
109         }
110 
111         try {
112             trapsCount = Integer.valueOf(trapsCountStr);
113         } catch (NumberFormatException nfe) {
114             trapsCount = 0;
115         }
116 
117         oldTrapsCount = methods.get(methodID);
118         if(oldTrapsCount == null) oldTrapsCount = -1;
119 
120         methods.put(methodID, Math.max(trapsCount, oldTrapsCount));
121     }
122 
findMatches(List<String> patterns, String str)123     private static boolean findMatches(List<String> patterns, String str) {
124         for(String pattern : patterns) {
125             if(Pattern.matches(pattern,str)) {
126                 return true;
127             }
128         }
129         return false;
130     }
131 
132 }
133