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