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