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 jdk.test.lib.jittester.IRNode; 28 import jdk.test.lib.jittester.Nothing; 29 import jdk.test.lib.jittester.ProductionFailedException; 30 import jdk.test.lib.jittester.SymbolTable; 31 import jdk.test.lib.jittester.TypeList; 32 import jdk.test.lib.jittester.VariableInfo; 33 import jdk.test.lib.jittester.functions.ArgumentDeclaration; 34 import jdk.test.lib.jittester.functions.FunctionInfo; 35 import jdk.test.lib.jittester.functions.FunctionRedefinition; 36 import jdk.test.lib.jittester.functions.Return; 37 import jdk.test.lib.jittester.types.TypeKlass; 38 import jdk.test.lib.jittester.utils.PseudoRandom; 39 40 class FunctionRedefinitionFactory extends Factory<FunctionRedefinition> { 41 private final long complexityLimit; 42 private final int statementLimit; 43 private final int operatorLimit; 44 private final int level; 45 private final TypeKlass ownerClass; 46 private final FunctionInfo functionInfo; 47 48 FunctionRedefinitionFactory(FunctionInfo functionInfo, TypeKlass ownerClass, 49 long complexityLimit, int statementLimit, int operatorLimit, int level, int flags) { 50 this.ownerClass = ownerClass; 51 this.functionInfo = new FunctionInfo(functionInfo); // do deep coping 52 functionInfo.owner = ownerClass; // important! fix klass! 53 if ((functionInfo.flags & FunctionInfo.STATIC) == 0) { 54 functionInfo.argTypes.get(0).type = ownerClass; // redefine type of this 55 } 56 functionInfo.flags = flags; // apply new flags. 57 // fix the type of class where the args would be declared 58 for (VariableInfo varInfo : functionInfo.argTypes) { 59 varInfo.owner = ownerClass; 60 } 61 this.complexityLimit = complexityLimit; 62 this.statementLimit = statementLimit; 63 this.operatorLimit = operatorLimit; 64 this.level = level; 65 } 66 67 @Override 68 public FunctionRedefinition produce() throws ProductionFailedException { 69 ArrayList<VariableInfo> argumentsInfo = functionInfo.argTypes; 70 SymbolTable.push(); 71 IRNode body; 72 Return returnNode; 73 ArrayList<ArgumentDeclaration> argumentsDeclaration; 74 try { 75 if (functionInfo.isStatic()) { 76 argumentsDeclaration = new ArrayList<>(argumentsInfo.size()); 77 for (VariableInfo varInfo : argumentsInfo) { 78 argumentsDeclaration.add(new ArgumentDeclaration(varInfo)); 79 SymbolTable.add(varInfo); 80 } 81 } else { 82 argumentsDeclaration = new ArrayList<>(argumentsInfo.size() - 1); 83 SymbolTable.add(argumentsInfo.get(0)); 84 for (int i = 1; i < argumentsInfo.size(); i++) { 85 argumentsDeclaration.add(new ArgumentDeclaration(argumentsInfo.get(i))); 86 SymbolTable.add(argumentsInfo.get(i)); 87 } 88 } 89 long blockComplLimit = (long) (PseudoRandom.random() * complexityLimit); 90 IRNodeBuilder builder = new IRNodeBuilder() 91 .setOwnerKlass(ownerClass) 92 .setResultType(functionInfo.type) 93 .setStatementLimit(statementLimit) 94 .setOperatorLimit(operatorLimit); 95 body = builder.setComplexityLimit(blockComplLimit) 96 .setLevel(level) 97 .setSubBlock(true) 98 .setCanHaveBreaks(false) 99 .setCanHaveContinues(false) 100 .setCanHaveReturn(true) 101 .getBlockFactory() 102 .produce(); 103 if (!functionInfo.type.equals(TypeList.VOID)) { 104 returnNode = builder.setComplexityLimit(complexityLimit - blockComplLimit) 105 .setExceptionSafe(false) 106 .getReturnFactory() 107 .produce(); 108 } else { 109 returnNode = new Return(new Nothing()); 110 } 111 } catch (ProductionFailedException e) { 112 SymbolTable.pop(); 113 SymbolTable.add(functionInfo); 114 throw e; 115 } 116 SymbolTable.pop(); 117 if (!functionInfo.isStatic()) { 118 functionInfo.flags &= ~FunctionInfo.ABSTRACT; 119 } 120 // If it's all ok, add the function to the symbol table. 121 SymbolTable.add(functionInfo); 122 return new FunctionRedefinition(functionInfo, argumentsDeclaration, body, returnNode); 123 } 124 125 }