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