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 jdk.test.lib.jittester.Block; 27 import jdk.test.lib.jittester.IRNode; 28 import jdk.test.lib.jittester.Literal; 29 import jdk.test.lib.jittester.LocalVariable; 30 import jdk.test.lib.jittester.Nothing; 31 import jdk.test.lib.jittester.ProductionFailedException; 32 import jdk.test.lib.jittester.Rule; 33 import jdk.test.lib.jittester.Statement; 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.loops.For; 38 import jdk.test.lib.jittester.loops.Loop; 39 import jdk.test.lib.jittester.types.TypeKlass; 40 import jdk.test.lib.jittester.utils.PseudoRandom; 41 42 import java.util.LinkedList; 43 44 class ForFactory extends SafeFactory<For> { 45 private final Loop loop; 46 private final long complexityLimit; 47 private final int statementLimit; 48 private final int operatorLimit; 49 private final TypeKlass ownerClass; 50 private final Type returnType; 51 private final int level; 52 private final boolean canHaveReturn; 53 54 ForFactory(TypeKlass ownerClass, Type returnType, long complexityLimit, int statementLimit, 55 int operatorLimit, int level, boolean canHaveReturn) { 56 this.ownerClass = ownerClass; 57 this.returnType = returnType; 58 this.complexityLimit = complexityLimit; 59 this.statementLimit = statementLimit; 60 this.operatorLimit = operatorLimit; 61 this.level = level; 62 loop = new Loop(); 63 this.canHaveReturn = canHaveReturn; 64 } 65 66 @Override 67 protected For sproduce() throws ProductionFailedException { 68 Block emptyBlock = new Block(ownerClass, returnType, new LinkedList<>(), level - 1); 69 if (statementLimit <= 0 || complexityLimit <= 0) { 70 throw new ProductionFailedException(); 71 } 72 IRNodeBuilder builder = new IRNodeBuilder() 73 .setOwnerKlass(ownerClass) 74 .setResultType(returnType) 75 .setOperatorLimit(operatorLimit) 76 .setSemicolon(false) 77 .setExceptionSafe(false) 78 .setNoConsts(false); 79 long complexity = complexityLimit; 80 // Loop header parameters 81 long headerComplLimit = (long) (0.005 * complexity * PseudoRandom.random()); 82 complexity -= headerComplLimit; 83 int headerStatementLimit = PseudoRandom.randomNotZero((int) (statementLimit / 4.0)); 84 long statement1ComplLimit = (long) (0.005 * complexity * PseudoRandom.random()); 85 complexity -= statement1ComplLimit; 86 // Loop body parameters 87 long thisLoopIterLimit = (long) (0.0001 * complexity * PseudoRandom.random()); 88 if (thisLoopIterLimit > Integer.MAX_VALUE || thisLoopIterLimit == 0) { 89 throw new ProductionFailedException(); 90 } 91 complexity = thisLoopIterLimit > 0 ? complexity / thisLoopIterLimit : 0; 92 long condComplLimit = (long) (complexity * PseudoRandom.random()); 93 complexity -= condComplLimit; 94 long statement2ComplLimit = (long) (complexity * PseudoRandom.random()); 95 complexity -= statement2ComplLimit; 96 long body1ComplLimit = (long) (complexity * PseudoRandom.random()); 97 complexity -= body1ComplLimit; 98 int body1StatementLimit = PseudoRandom.randomNotZero((int) (statementLimit / 4.0)); 99 long body2ComplLimit = (long) (complexity * PseudoRandom.random()); 100 complexity -= body2ComplLimit; 101 int body2StatementLimit = PseudoRandom.randomNotZero((int) (statementLimit / 4.0)); 102 long body3ComplLimit = complexity; 103 int body3StatementLimit = PseudoRandom.randomNotZero((int) (statementLimit / 4.0)); 104 // Production 105 loop.initialization = builder.getCounterInitializerFactory(0).produce(); 106 Block header; 107 try { 108 header = builder.setComplexityLimit(headerComplLimit) 109 .setStatementLimit(headerStatementLimit) 110 .setLevel(level - 1) 111 .setSubBlock(true) 112 .setCanHaveBreaks(false) 113 .setCanHaveContinues(false) 114 .setCanHaveReturn(false) 115 .getBlockFactory() 116 .produce(); 117 } catch (ProductionFailedException e) { 118 header = emptyBlock; 119 } 120 SymbolTable.push(); 121 IRNode statement1; 122 try { 123 Rule<IRNode> rule = new Rule<>("statement1"); 124 builder.setComplexityLimit(statement1ComplLimit); 125 rule.add("assignment", builder.getAssignmentOperatorFactory()); 126 rule.add("function", builder.getFunctionFactory(), 0.1); 127 rule.add("initialization", builder.setIsConstant(false) 128 .setIsStatic(false) 129 .setIsLocal(true) 130 .getVariableInitializationFactory()); 131 statement1 = rule.produce(); 132 } catch (ProductionFailedException e) { 133 statement1 = new Nothing(); 134 } 135 LocalVariable counter = new LocalVariable(loop.initialization.getVariableInfo()); 136 Literal limiter = new Literal((int) thisLoopIterLimit, TypeList.INT); 137 loop.condition = builder.setComplexityLimit(condComplLimit) 138 .setLocalVariable(counter) 139 .getLoopingConditionFactory(limiter) 140 .produce(); 141 IRNode statement2; 142 try { 143 statement2 = builder.setComplexityLimit(statement2ComplLimit) 144 .getAssignmentOperatorFactory().produce(); 145 } catch (ProductionFailedException e) { 146 statement2 = new Nothing(); 147 } 148 Block body1; 149 try { 150 body1 = builder.setComplexityLimit(body1ComplLimit) 151 .setStatementLimit(body1StatementLimit) 152 .setLevel(level) 153 .setSubBlock(true) 154 .setCanHaveBreaks(true) 155 .setCanHaveContinues(false) 156 .setCanHaveReturn(false) 157 .getBlockFactory() 158 .produce(); 159 } catch (ProductionFailedException e) { 160 body1 = emptyBlock; 161 } 162 loop.manipulator = builder.setLocalVariable(counter).getCounterManipulatorFactory().produce(); 163 Block body2; 164 try { 165 body2 = builder.setComplexityLimit(body2ComplLimit) 166 .setStatementLimit(body2StatementLimit) 167 .setLevel(level) 168 .setSubBlock(true) 169 .setCanHaveBreaks(true) 170 .setCanHaveContinues(true) 171 .setCanHaveReturn(false) 172 .getBlockFactory() 173 .produce(); 174 } catch (ProductionFailedException e) { 175 body2 = emptyBlock; 176 } 177 Block body3; 178 try { 179 body3 = builder.setComplexityLimit(body3ComplLimit) 180 .setStatementLimit(body3StatementLimit) 181 .setLevel(level) 182 .setSubBlock(true) 183 .setCanHaveBreaks(true) 184 .setCanHaveContinues(false) 185 .setCanHaveReturn(canHaveReturn) 186 .getBlockFactory() 187 .produce(); 188 } catch (ProductionFailedException e) { 189 body3 = emptyBlock; 190 } 191 SymbolTable.pop(); 192 return new For(level, loop, thisLoopIterLimit, header, 193 new Statement(statement1, false), 194 new Statement(statement2, false), 195 body1, 196 body2, body3); 197 } 198 }