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.pool.PoolHelper; 28 import jdk.test.lib.Pair; 29 30 import java.lang.reflect.Executable; 31 import java.util.ArrayList; 32 import java.util.Collections; 33 import java.util.HashMap; 34 import java.util.List; 35 import java.util.Map; 36 import java.util.concurrent.Callable; 37 38 /** 39 * An abstract class that builds states by applying 40 * commands one after another 41 */ 42 public abstract class AbstractCommandBuilder 43 implements StateBuilder<CompileCommand> { 44 protected static final List<Pair<Executable, Callable<?>>> METHODS 45 = new PoolHelper().getAllMethods(); 46 protected final List<CompileCommand> compileCommands = new ArrayList<>(); 47 48 @Override 49 public void add(CompileCommand command) { 50 compileCommands.add(command); 51 CommandStateBuilder.getInstance().add(command); 52 } 53 54 @Override 55 public Map<Executable, State> getStates() { 56 return CommandStateBuilder.getInstance().getStates(); 57 } 58 59 @Override 60 public List<CompileCommand> getCompileCommands() { 61 return Collections.unmodifiableList(compileCommands); 62 } 63 64 @Override 65 public boolean isValid() { 66 // -XX:CompileCommand(File) ignores invalid items 67 return true; 68 } 69 70 /* 71 * This is an internal class used to build states for commands given from 72 * options and a file. As all commands are added into a single set in 73 * CompilerOracle, we need a class that builds states in the same manner 74 */ 75 private static class CommandStateBuilder { 76 private static final CommandStateBuilder INSTANCE 77 = new CommandStateBuilder(); 78 private final List<CompileCommand> optionCommands = new ArrayList<>(); 79 private final List<CompileCommand> fileCommands = new ArrayList<>(); 80 81 private CommandStateBuilder() { } 82 83 public static CommandStateBuilder getInstance() { 84 return INSTANCE; 85 } 86 87 public void add(CompileCommand command) { 88 switch (command.type) { 89 case OPTION: 90 optionCommands.add(command); 91 break; 92 case FILE: 93 fileCommands.add(command); 94 break; 95 default: 96 throw new Error("TESTBUG: wrong type: " + command.type); 97 } 98 } 99 100 public Map<Executable, State> getStates() { 101 List<CompileCommand> commandList = new ArrayList<>(); 102 commandList.addAll(optionCommands); 103 commandList.addAll(fileCommands); 104 Map<Executable, State> states = new HashMap<>(); 105 for (Pair<Executable, Callable<?>> pair : METHODS) { 106 Executable exec = pair.first; 107 State state = getState(commandList, exec); 108 states.put(exec, state); 109 } 110 return states; 111 } 112 113 private State getState(List<CompileCommand> commandList, 114 Executable exec) { 115 State state = new State(); 116 MethodDescriptor execDesc = new MethodDescriptor(exec); 117 for (CompileCommand compileCommand : commandList) { 118 if (compileCommand.isValid()) { 119 // Create a copy without compiler set 120 CompileCommand cc = new CompileCommand( 121 compileCommand.command, 122 compileCommand.methodDescriptor, 123 /* CompileCommand option and file doesn't support 124 compiler setting */ 125 null, 126 compileCommand.type); 127 MethodDescriptor md = cc.methodDescriptor; 128 // if executable matches regex then apply the state 129 if (execDesc.getCanonicalString().matches(md.getRegexp())) { 130 if (cc.command == Command.COMPILEONLY 131 && !state.isCompilable()) { 132 /* if the method was already excluded it will not 133 be compilable again */ 134 } else { 135 state.apply(cc); 136 } 137 } 138 } 139 } 140 141 /* 142 * Set compilation states for methods that don't match 143 * any compileonly command. Such methods should be excluded 144 * from compilation 145 */ 146 for (CompileCommand compileCommand : commandList) { 147 if (compileCommand.isValid() 148 && (compileCommand.command == Command.COMPILEONLY)) { 149 MethodDescriptor md = compileCommand.methodDescriptor; 150 if (!execDesc.getCanonicalString().matches(md.getRegexp()) 151 // if compilation state wasn't set before 152 && (!state.getCompilableOptional( 153 // no matter C1, C2 or both 154 Scenario.Compiler.C2).isPresent())) { 155 /* compileonly excludes only methods that haven't been 156 already set to be compilable or excluded */ 157 state.setC1Compilable(false); 158 state.setC2Compilable(false); 159 } 160 } 161 } 162 return state; 163 } 164 } 165 }