1 /* 2 * Copyright (c) 2015, 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 24 package compiler.compilercontrol.share.scenario; 25 26 import compiler.compilercontrol.share.method.MethodDescriptor; 27 import compiler.compilercontrol.share.method.MethodGenerator; 28 import pool.PoolHelper; 29 import jdk.test.lib.Pair; 30 31 import java.lang.reflect.Executable; 32 import java.util.ArrayList; 33 import java.util.HashMap; 34 import java.util.Iterator; 35 import java.util.LinkedHashMap; 36 import java.util.List; 37 import java.util.Map; 38 import java.util.concurrent.Callable; 39 import java.util.stream.Collectors; 40 41 public class JcmdStateBuilder implements StateBuilder<JcmdCommand> { 42 private static final List<Pair<Executable, Callable<?>>> METHODS 43 = new PoolHelper().getAllMethods(); 44 private final Map<Executable, State> stateMap = new HashMap<>(); 45 private final DirectiveBuilder directiveBuilder; 46 private Map<MethodDescriptor, List<CompileCommand>> matchBlocks 47 = new LinkedHashMap<>(); 48 private boolean isFileValid = true; 49 50 public JcmdStateBuilder(String fileName) { 51 directiveBuilder = new DirectiveBuilder(fileName); 52 } 53 54 @Override 55 public void add(JcmdCommand compileCommand) { 56 switch (compileCommand.jcmdType) { 57 case ADD: 58 directiveBuilder.add(compileCommand); 59 addCommand(compileCommand); 60 break; 61 case PRINT: 62 // doesn't change the state 63 break; 64 case CLEAR: 65 matchBlocks.clear(); 66 break; 67 case REMOVE: 68 removeDirective(); 69 break; 70 } 71 } 72 73 private void addCommand(JcmdCommand compileCommand) { 74 isFileValid &= compileCommand.isValid(); 75 for (MethodDescriptor md: matchBlocks.keySet()) { 76 if (compileCommand.methodDescriptor.getCanonicalString() 77 .matches(md.getRegexp())) { 78 matchBlocks.get(md).add(compileCommand); 79 } 80 } 81 List<CompileCommand> commands = new ArrayList<>(); 82 commands.add(compileCommand); 83 matchBlocks.put(compileCommand.methodDescriptor, commands); 84 } 85 86 private void removeDirective() { 87 Iterator<MethodDescriptor> iterator = matchBlocks.keySet().iterator(); 88 if (iterator.hasNext()) { 89 MethodDescriptor md = iterator.next(); 90 matchBlocks.remove(md); 91 } 92 } 93 94 @Override 95 public boolean isValid() { 96 // VM skips invalid directive file added via jcmd command 97 return true; 98 } 99 100 @Override 101 public Map<Executable, State> getStates() { 102 directiveBuilder.getStates(); 103 // Build states for each method according to match blocks 104 for (Pair<Executable, Callable<?>> pair : METHODS) { 105 State state = getState(pair); 106 if (state != null) { 107 stateMap.put(pair.first, state); 108 } 109 } 110 if (isFileValid) { 111 return stateMap; 112 } else { 113 // return empty map because invalid file doesn't change states 114 return new HashMap<>(); 115 } 116 } 117 118 private State getState(Pair<Executable, Callable<?>> pair) { 119 State state = null; 120 MethodDescriptor execDesc = MethodGenerator.commandDescriptor( 121 pair.first); 122 boolean isMatchFound = false; 123 124 if (stateMap.containsKey(pair.first)) { 125 state = stateMap.get(pair.first); 126 } 127 for (MethodDescriptor matchDesc : matchBlocks.keySet()) { 128 if (execDesc.getCanonicalString().matches(matchDesc.getRegexp())) { 129 /* 130 * if executable matches regex 131 * then apply commands from this match to the state 132 */ 133 for (CompileCommand cc : matchBlocks.get(matchDesc)) { 134 state = new State(); 135 if (!isMatchFound) { 136 // this is a first found match, apply all commands 137 state.apply(cc); 138 } else { 139 // apply only inline directives 140 switch (cc.command) { 141 case INLINE: 142 case DONTINLINE: 143 state.apply(cc); 144 break; 145 } 146 } 147 } 148 isMatchFound = true; 149 } 150 } 151 return state; 152 } 153 154 @Override 155 public List<String> getOptions() { 156 return new ArrayList<>(); 157 } 158 159 @Override 160 public List<JcmdCommand> getCompileCommands() { 161 if (isFileValid) { 162 return matchBlocks.keySet().stream() 163 /* only method descriptor is required 164 to check print_directives */ 165 .map(md -> new JcmdCommand(null, md, null, null, 166 Scenario.JcmdType.ADD)) 167 .collect(Collectors.toList()); 168 } else { 169 return new ArrayList<>(); 170 } 171 } 172 }