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