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
24package jdk.test.lib.jittester.factories;
25
26import jdk.test.lib.jittester.Block;
27import jdk.test.lib.jittester.Literal;
28import jdk.test.lib.jittester.LocalVariable;
29import jdk.test.lib.jittester.ProductionFailedException;
30import jdk.test.lib.jittester.SymbolTable;
31import jdk.test.lib.jittester.Type;
32import jdk.test.lib.jittester.TypeList;
33import jdk.test.lib.jittester.loops.DoWhile;
34import jdk.test.lib.jittester.loops.Loop;
35import jdk.test.lib.jittester.types.TypeKlass;
36import jdk.test.lib.jittester.utils.PseudoRandom;
37
38import java.util.LinkedList;
39
40class DoWhileFactory extends SafeFactory<DoWhile> {
41    private final Loop loop;
42    private final long complexityLimit;
43    private final int statementLimit;
44    private final int operatorLimit;
45    private boolean canHaveReturn = false;
46    private final TypeKlass ownerClass;
47    private final int level;
48    private final Type returnType;
49    private long thisLoopIterLimit;
50
51    DoWhileFactory(TypeKlass ownerClass, Type returnType, long complexityLimit, int statementLimit,
52            int operatorLimit, int level, boolean canHaveReturn) {
53        loop = new Loop();
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        this.canHaveReturn = canHaveReturn;
61        thisLoopIterLimit = 0;
62    }
63
64    @Override
65    protected DoWhile sproduce() throws ProductionFailedException {
66        Block emptyBlock = new Block(ownerClass, returnType, new LinkedList<>(), level - 1);
67        if (statementLimit > 0 && complexityLimit > 0) {
68            long complexity = complexityLimit;
69            // Loop header parameters
70            long headerComplLimit = (long) (0.005 * complexity * PseudoRandom.random());
71            complexity -= headerComplLimit;
72            int headerStatementLimit = PseudoRandom.randomNotZero((int) (statementLimit / 3.0));
73            // Loop body parameters
74            thisLoopIterLimit = (long) (0.0001 * complexity * PseudoRandom.random());
75            if (thisLoopIterLimit > Integer.MAX_VALUE || thisLoopIterLimit == 0) {
76                throw new ProductionFailedException();
77            }
78            complexity = thisLoopIterLimit > 0 ? complexity / thisLoopIterLimit : 0;
79            long condComplLimit = (long) (complexity * PseudoRandom.random());
80            complexity -= condComplLimit;
81            long body1ComplLimit = (long) (complexity * PseudoRandom.random());
82            complexity -= body1ComplLimit;
83            int body1StatementLimit = PseudoRandom.randomNotZero((int) (statementLimit / 3.0));
84            long body2ComplLimit = (long) (complexity * PseudoRandom.random());
85            complexity -= body2ComplLimit;
86            int body2StatementLimit = PseudoRandom.randomNotZero((int) (statementLimit / 3.0));
87            // Production
88            IRNodeBuilder builder = new IRNodeBuilder()
89                    .setOwnerKlass(ownerClass)
90                    .setResultType(returnType)
91                    .setOperatorLimit(operatorLimit);
92            loop.initialization = builder.getCounterInitializerFactory(0).produce();
93            Block header;
94            try {
95                header = builder.setComplexityLimit(headerComplLimit)
96                        .setStatementLimit(headerStatementLimit)
97                        .setLevel(level - 1)
98                        .setSubBlock(true)
99                        .setCanHaveBreaks(false)
100                        .setCanHaveContinues(false)
101                        .setCanHaveReturn(false)
102                        .getBlockFactory()
103                        .produce();
104            } catch (ProductionFailedException e) {
105                header = emptyBlock;
106            }
107            // getChildren().set(DoWhile.DoWhilePart.HEADER.ordinal(), header);
108            LocalVariable counter = new LocalVariable(loop.initialization.getVariableInfo());
109            Literal limiter = new Literal((int) thisLoopIterLimit, TypeList.INT);
110            loop.condition = builder.setComplexityLimit(condComplLimit)
111                    .setLocalVariable(counter)
112                    .getLoopingConditionFactory(limiter)
113                    .produce();
114            SymbolTable.push();
115            Block body1;
116            try {
117                body1 = builder.setComplexityLimit(body1ComplLimit)
118                        .setStatementLimit(body1StatementLimit)
119                        .setLevel(level)
120                        .setSubBlock(true)
121                        .setCanHaveBreaks(true)
122                        .setCanHaveContinues(false)
123                        .setCanHaveReturn(false)
124                        .getBlockFactory()
125                        .produce();
126            } catch (ProductionFailedException e) {
127                body1 = emptyBlock;
128            }
129            // getChildren().set(DoWhile.DoWhilePart.BODY1.ordinal(), body1);
130            loop.manipulator = builder.setLocalVariable(counter).getCounterManipulatorFactory().produce();
131            Block body2;
132            try {
133                body2 = builder.setComplexityLimit(body2ComplLimit)
134                        .setStatementLimit(body2StatementLimit)
135                        .setLevel(level)
136                        .setSubBlock(true)
137                        .setCanHaveBreaks(true)
138                        .setCanHaveContinues(false)
139                        .setCanHaveReturn(canHaveReturn)
140                        .getBlockFactory()
141                        .produce();
142            } catch (ProductionFailedException e) {
143                body2 = emptyBlock;
144            }
145            // getChildren().set(DoWhile.DoWhilePart.BODY2.ordinal(), body2);
146            SymbolTable.pop();
147            return new DoWhile(level, loop, thisLoopIterLimit, header, body1, body2);
148        }
149        throw new ProductionFailedException();
150    }
151}
152