Path: blob/master/test/hotspot/jtreg/compiler/compilercontrol/share/scenario/DirectiveBuilder.java
41161 views
/*1* Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation.7*8* This code is distributed in the hope that it will be useful, but WITHOUT9* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or10* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License11* version 2 for more details (a copy is included in the LICENSE file that12* accompanied this code).13*14* You should have received a copy of the GNU General Public License version15* 2 along with this work; if not, write to the Free Software Foundation,16* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.17*18* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA19* or visit www.oracle.com if you need additional information or have any20* questions.21*/2223package compiler.compilercontrol.share.scenario;2425import compiler.compilercontrol.share.JSONFile;26import compiler.compilercontrol.share.method.MethodDescriptor;27import compiler.compilercontrol.share.method.MethodGenerator;28import compiler.compilercontrol.share.pool.PoolHelper;29import jdk.test.lib.util.Pair;3031import java.lang.reflect.Executable;32import java.util.ArrayList;33import java.util.HashMap;34import java.util.LinkedHashMap;35import java.util.List;36import java.util.Map;37import java.util.concurrent.Callable;38import java.util.stream.Collectors;3940/**41* Directive file and state builder class42*/43public class DirectiveBuilder implements StateBuilder<CompileCommand> {44private static final List<Pair<Executable, Callable<?>>> METHODS45= new PoolHelper().getAllMethods();46private final Map<Executable, State> stateMap = new HashMap<>();47private final String fileName;48private final Map<MethodDescriptor, List<CompileCommand>> matchBlocks49= new LinkedHashMap<>();50private final List<CompileCommand> inlines = new ArrayList<>();51private boolean isFileValid = true;5253public DirectiveBuilder(String fileName) {54this.fileName = fileName;55}5657@Override58public List<String> getOptions() {59List<String> options = new ArrayList<>();60if (!matchBlocks.isEmpty()) {61// add option only if there are any directive available62options.add("-XX:CompilerDirectivesFile=" + fileName);63}64return options;65}6667@Override68public List<CompileCommand> getCompileCommands() {69return matchBlocks.keySet().stream()70// only method descriptor is required to check print_directives71.map(md -> new CompileCommand(null, md, null, null))72.collect(Collectors.toList());73}7475@Override76public boolean isValid() {77// Invalid directives file makes VM exit with error code78return isFileValid;79}8081@Override82public Map<Executable, State> getStates() {83writeDirectiveFile();84if (isFileValid) {85// Build states for each method according to match blocks86for (Pair<Executable, Callable<?>> pair : METHODS) {87State state = getState(pair);88if (state != null) {89stateMap.put(pair.first, state);90}91}92return stateMap;93} else {94// return empty map because invalid file doesn't change states95return new HashMap<>();96}97}9899private void writeDirectiveFile() {100try (DirectiveWriter dirFile = new DirectiveWriter(fileName)) {101for (MethodDescriptor matchDescriptor : matchBlocks.keySet()) {102// Write match block with all options converted from commands103dirFile.match(matchDescriptor);104for (CompileCommand compileCommand :105matchBlocks.get(matchDescriptor)) {106handleCommand(dirFile, compileCommand);107}108if ("Inlinee.caller()".matches(matchDescriptor.getRegexp())109&& !inlines.isEmpty()) {110// Got a *.* match block, where inline would be written111writeInlines(dirFile);112inlines.clear();113}114dirFile.end(); // ends match block115}116117/*118* Write inline directive in the end to the latest match block119* if we didn't do this before120* Inlinee caller methods should match this block only121*/122if (!inlines.isEmpty()) {123Pair<Executable, Callable<?>> pair = METHODS.get(0);124MethodDescriptor md = MethodGenerator.anyMatchDescriptor(125pair.first);126CompileCommand cc = new CompileCommand(Command.QUIET, md,127null, Scenario.Type.DIRECTIVE);128List<CompileCommand> commands = new ArrayList<>();129130// Add appropriate "*.*" match block131commands.add(cc);132matchBlocks.put(md, commands);133// Add match block for this descriptor with inlines134dirFile.match(md);135writeInlines(dirFile);136dirFile.end();137}138if (!matchBlocks.isEmpty()) {139// terminates file140dirFile.end();141}142143}144}145146private State getState(Pair<Executable, Callable<?>> pair) {147State state = null;148MethodDescriptor execDesc = MethodGenerator.commandDescriptor(149pair.first);150boolean isMatchFound = false;151152if (stateMap.containsKey(pair.first)) {153state = stateMap.get(pair.first);154}155for (MethodDescriptor matchDesc : matchBlocks.keySet()) {156if (execDesc.getCanonicalString().matches(matchDesc.getRegexp())) {157/*158* if executable matches regex159* then apply commands from this match to the state160*/161for (CompileCommand cc : matchBlocks.get(matchDesc)) {162if (state == null) {163state = new State();164}165if (!isMatchFound) {166// this is a first found match, apply all commands167state.apply(cc);168} else {169// apply only inline directives170switch (cc.command) {171case INLINE:172case DONTINLINE:173state.apply(cc);174break;175}176}177}178isMatchFound = true;179}180}181return state;182}183184private void handleCommand(DirectiveWriter dirFile, CompileCommand cmd) {185Command command = cmd.command;186187switch (command) {188case COMPILEONLY:189dirFile.excludeCompile(cmd.compiler, false);190break;191case EXCLUDE:192dirFile.excludeCompile(cmd.compiler, true);193break;194case QUIET:195/* there are no appropriate directive for this, just make196match be enabled */197case INLINE:198case DONTINLINE:199/* Inline commands will be written later.200Just make this match be enabled */201dirFile.emitCompiler(Scenario.Compiler.C1);202dirFile.option(DirectiveWriter.Option.ENABLE, true);203dirFile.end();204dirFile.emitCompiler(Scenario.Compiler.C2);205dirFile.option(DirectiveWriter.Option.ENABLE, true);206dirFile.end();207break;208case LOG:209dirFile.option(DirectiveWriter.Option.LOG, true);210break;211case PRINT:212dirFile.option(DirectiveWriter.Option.PRINT_ASSEMBLY, true);213break;214case INTRINSIC:215dirFile.option(DirectiveWriter.Option.INTRINSIC, "\"" + cmd.argument + "\"");216break;217case NONEXISTENT:218dirFile.write(JSONFile.Element.PAIR, command.name);219dirFile.write(JSONFile.Element.OBJECT);220dirFile.write(JSONFile.Element.PAIR, command.name);221dirFile.write(JSONFile.Element.VALUE,222cmd.methodDescriptor.getString());223dirFile.end(); // ends object224break;225default:226throw new Error("TESTBUG: wrong command: " + command);227}228}229230private void writeInlines(DirectiveWriter dirFile) {231List<String> c1Block = new ArrayList<>();232List<String> c2Block = new ArrayList<>();233List<String> allBlock = new ArrayList<>();234for (CompileCommand cc : inlines) {235String inlineMethodPattern;236switch (cc.command) {237case INLINE:238inlineMethodPattern = "+" + cc.methodDescriptor.getString();239break;240case DONTINLINE:241inlineMethodPattern = "-" + cc.methodDescriptor.getString();242break;243default:244throw new Error("TESTBUG: incorrect command got in "245+ "the list: " + cc.command);246}247if (cc.compiler == Scenario.Compiler.C1) {248c1Block.add(inlineMethodPattern);249} else if (cc.compiler == Scenario.Compiler.C2) {250c2Block.add(inlineMethodPattern);251} else {252allBlock.add(inlineMethodPattern);253}254}255dirFile.emitCompiler(Scenario.Compiler.C1);256if (!c1Block.isEmpty()) {257dirFile.inline(c1Block);258} else {259dirFile.option(DirectiveWriter.Option.ENABLE, true);260}261dirFile.end();262dirFile.emitCompiler(Scenario.Compiler.C2);263if (!c2Block.isEmpty()) {264dirFile.inline(c2Block);265} else {266dirFile.option(DirectiveWriter.Option.ENABLE, true);267}268dirFile.end();269if (!allBlock.isEmpty()) {270dirFile.inline(allBlock);271}272}273274@Override275public void add(CompileCommand compileCommand) {276isFileValid &= compileCommand.isValid();277MethodDescriptor methodDescriptor = compileCommand.methodDescriptor;278279switch (compileCommand.command) {280case INLINE:281case DONTINLINE:282inlines.add(compileCommand);283break;284}285for (MethodDescriptor md: matchBlocks.keySet()) {286if (methodDescriptor.getCanonicalString().matches(md.getRegexp())) {287matchBlocks.get(md).add(compileCommand);288}289}290if (!matchBlocks.containsKey(compileCommand.methodDescriptor)) {291List<CompileCommand> commands = new ArrayList<>();292commands.add(compileCommand);293matchBlocks.put(compileCommand.methodDescriptor, commands);294}295}296}297298299