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 jdk.test.lib.jittester.factories; 25 26 import java.util.ArrayList; 27 import java.util.List; 28 import java.util.stream.Collectors; 29 import jdk.test.lib.jittester.Block; 30 import jdk.test.lib.jittester.IRNode; 31 import jdk.test.lib.jittester.ProductionFailedException; 32 import jdk.test.lib.jittester.ProductionParams; 33 import jdk.test.lib.jittester.Symbol; 34 import jdk.test.lib.jittester.SymbolTable; 35 import jdk.test.lib.jittester.Type; 36 import jdk.test.lib.jittester.TypeList; 37 import jdk.test.lib.jittester.VariableInfo; 38 import jdk.test.lib.jittester.classes.MainKlass; 39 import jdk.test.lib.jittester.functions.FunctionInfo; 40 import jdk.test.lib.jittester.types.TypeKlass; 41 import jdk.test.lib.jittester.utils.PseudoRandom; 42 43 class MainKlassFactory extends Factory<MainKlass> { 44 private final String name; 45 private final long complexityLimit; 46 private final int statementsInTestFunctionLimit; 47 private final int statementsInFunctionLimit; 48 private final int operatorLimit; 49 private final int memberFunctionsLimit; 50 private final int memberFunctionsArgLimit; 51 private TypeKlass thisKlass; 52 53 MainKlassFactory(String name, long complexityLimit, int memberFunctionsLimit, 54 int memberFunctionsArgLimit, int statementsInFunctionLimit, 55 int statementsInTestFunctionLimit, int operatorLimit) { 56 this.name = name; 57 this.complexityLimit = complexityLimit; 58 this.memberFunctionsLimit = memberFunctionsLimit; 59 this.memberFunctionsArgLimit = memberFunctionsArgLimit; 60 this.statementsInFunctionLimit = statementsInFunctionLimit; 61 this.statementsInTestFunctionLimit = statementsInTestFunctionLimit; 62 this.operatorLimit = operatorLimit; 63 } 64 65 @Override 66 public MainKlass produce() throws ProductionFailedException { 67 TypeKlass parent = TypeList.OBJECT; 68 thisKlass = new TypeKlass(name); 69 thisKlass.addParent(parent.getName()); 70 thisKlass.setParent(parent); 71 parent.addChild(name); 72 parent.addChild(thisKlass); 73 SymbolTable.add(new VariableInfo("this", thisKlass, thisKlass, 74 VariableInfo.FINAL | VariableInfo.LOCAL | VariableInfo.INITIALIZED)); 75 IRNodeBuilder builder = new IRNodeBuilder() 76 .setOwnerKlass(thisKlass) 77 .setOperatorLimit(operatorLimit) 78 .setMemberFunctionsLimit(memberFunctionsLimit) 79 .setMemberFunctionsArgLimit(memberFunctionsArgLimit) 80 .setStatementLimit(statementsInFunctionLimit) 81 .setLevel(1) 82 .setExceptionSafe(true); 83 IRNode variableDeclarations = builder 84 .setComplexityLimit((long) (complexityLimit * 0.05)) 85 .getVariableDeclarationBlockFactory().produce(); 86 IRNode functionDefinitions = null; 87 if (!ProductionParams.disableFunctions.value()) { 88 functionDefinitions = builder 89 .setComplexityLimit((long) (complexityLimit * 0.01 * PseudoRandom.random())) 90 .setFlags(FunctionInfo.NONRECURSIVE) 91 .getFunctionDefinitionBlockFactory() 92 .produce(); 93 } 94 IRNode testFunction = builder.setResultType(TypeList.VOID) 95 .setComplexityLimit(complexityLimit) 96 .setStatementLimit(statementsInTestFunctionLimit) 97 .getBlockFactory() 98 .produce(); 99 SymbolTable.remove(new Symbol("this", thisKlass, thisKlass, VariableInfo.NONE)); 100 IRNode printVariables = builder.setLevel(2) 101 .getPrintVariablesFactory() 102 .produce(); 103 List<IRNode> childs = new ArrayList<>(); 104 childs.add(variableDeclarations); 105 childs.add(functionDefinitions); 106 childs.add(testFunction); 107 childs.add(printVariables); 108 ensureMinDepth(childs, builder); 109 ensureMaxDepth(childs); 110 TypeList.add(thisKlass); 111 return new MainKlass(name, thisKlass, variableDeclarations, 112 functionDefinitions, testFunction, printVariables); 113 } 114 115 private void ensureMaxDepth(List<IRNode> childs) { 116 int maxDepth = ProductionParams.maxCfgDepth.value(); 117 List<IRNode> filtered = childs.stream() 118 .filter(c -> c.isCFDeviation() && c.countDepth() > maxDepth) 119 .collect(Collectors.toList()); 120 for (IRNode child : filtered) { 121 List<IRNode> leaves; 122 do { 123 long depth = Math.max(child.countDepth(), maxDepth + 1); 124 leaves = child.getDeviantBlocks(depth); 125 leaves.get(0).removeSelf(); 126 } while (!leaves.isEmpty() && child.countDepth() > maxDepth); 127 } 128 } 129 130 private void ensureMinDepth(List<IRNode> childs, IRNodeBuilder builder) 131 throws ProductionFailedException { 132 int minDepth = ProductionParams.minCfgDepth.value(); 133 List<IRNode> filtered = new ArrayList<>(childs); 134 addMoreChildren(filtered, minDepth, builder); 135 } 136 137 private void addMoreChildren(List<IRNode> childs, int minDepth, IRNodeBuilder builder) 138 throws ProductionFailedException { 139 while (!childs.isEmpty() && IRNode.countDepth(childs) < minDepth) { 140 IRNode randomChild = childs.get(PseudoRandom.randomNotNegative(childs.size())); 141 List<IRNode> leaves = randomChild.getStackableLeaves(); 142 if (!leaves.isEmpty()) { 143 Block randomLeaf = (Block) leaves.get(PseudoRandom.randomNotNegative(leaves.size())); 144 TypeKlass owner = randomChild.getOwner(); 145 int newLevel = randomLeaf.getLevel() + 1; 146 Type retType = randomLeaf.getResultType(); 147 IRNode newBlock = builder.setOwnerKlass(owner) 148 .setResultType(retType) 149 .setComplexityLimit(complexityLimit) 150 .setStatementLimit(statementsInFunctionLimit) 151 .setLevel(newLevel) 152 .getBlockFactory() 153 .produce(); 154 List<IRNode> siblings = randomLeaf.getChildren(); 155 // to avoid break; 156 int index = PseudoRandom.randomNotZero(siblings.size() - 1); 157 siblings.add(index, newBlock); 158 } 159 } 160 } 161 }