changeset 38693:9b68b18ad248

8141149: [jittester] create Visitor for generating bytecode 8149463: [jittester] rarely generates tests with compile error Reviewed-by: iignatyev, iveresov Contributed-by: dmitrij.pochepko@oracle.com, igor.ignatyev@oracle.com, pavel.punegov@oracle.com, tatiana.pivovarova@oracle.com
author tpivovarova
date Wed, 18 May 2016 20:19:23 +0300
parents a2c52cff500d
children 7be3816c7642
files hotspot/test/testlibrary/jittester/Makefile hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/Automatic.java hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/BinaryOperator.java hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/Block.java hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/Break.java hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/BuiltInType.java hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/ByteCodeGenerator.java hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/CastOperator.java hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/CatchBlock.java hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/Continue.java hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/Declaration.java hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/IRNode.java hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/If.java hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/Initialization.java hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/JavaCodeGenerator.java hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/Literal.java hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/LocalVariable.java hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/LogicOperator.java hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/NonStaticMemberVariable.java hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/Nothing.java hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/Operator.java hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/OperatorKind.java hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/PrintVariables.java hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/ProductionParams.java hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/Rule.java hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/Statement.java hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/StaticMemberVariable.java hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/Switch.java hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/Symbol.java hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/SymbolTable.java hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/TernaryOperator.java hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/Throw.java hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/TryCatchBlock.java hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/Type.java hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/TypeList.java hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/TypesParser.java hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/UnaryOperator.java hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/VariableBase.java hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/VariableDeclaration.java hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/VariableDeclarationBlock.java hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/VariableInfo.java hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/arrays/ArrayCreation.java hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/arrays/ArrayElement.java hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/arrays/ArrayExtraction.java hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/classes/ClassDefinitionBlock.java hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/classes/Interface.java hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/classes/Klass.java hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/classes/MainKlass.java hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/factories/ArgumentDeclarationFactory.java hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/factories/ArithmeticOperatorFactory.java hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/factories/ArrayCreationFactory.java hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/factories/ArrayElementFactory.java hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/factories/ArrayExtractionFactory.java hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/factories/AssignmentOperatorFactory.java hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/factories/AssignmentOperatorImplFactory.java hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/factories/BinaryArithmeticOperatorFactory.java hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/factories/BinaryBitwiseOperatorFactory.java hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/factories/BinaryComparisonOperatorFactory.java hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/factories/BinaryEqualityOperatorFactory.java hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/factories/BinaryLogicOperatorFactory.java hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/factories/BinaryOperatorFactory.java hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/factories/BinaryShiftOperatorFactory.java hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/factories/BinaryStringPlusFactory.java hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/factories/BitwiseInversionOperatorFactory.java hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/factories/BitwiseOperatorFactory.java hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/factories/BlockFactory.java hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/factories/BreakFactory.java hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/factories/CastOperatorFactory.java hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/factories/ClassDefinitionBlockFactory.java hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/factories/CompoundArithmeticAssignmentOperatorFactory.java hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/factories/CompoundBitwiseAssignmentOperatorFactory.java hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/factories/CompoundShiftAssignmentOperatorFactory.java hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/factories/ConstructorDefinitionBlockFactory.java hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/factories/ConstructorDefinitionFactory.java hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/factories/ContinueFactory.java hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/factories/CounterInitializerFactory.java hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/factories/CounterManipulatorFactory.java hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/factories/DeclarationFactory.java hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/factories/DoWhileFactory.java hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/factories/ExpressionFactory.java hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/factories/Factory.java hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/factories/ForFactory.java hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/factories/FunctionDeclarationBlockFactory.java hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/factories/FunctionDeclarationFactory.java hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/factories/FunctionDefinitionBlockFactory.java hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/factories/FunctionDefinitionFactory.java hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/factories/FunctionFactory.java hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/factories/FunctionRedefinitionBlockFactory.java hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/factories/FunctionRedefinitionFactory.java hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/factories/IRNodeBuilder.java hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/factories/IfFactory.java hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/factories/IncDecOperatorFactory.java hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/factories/InterfaceFactory.java hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/factories/KlassFactory.java hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/factories/LiteralFactory.java hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/factories/LocalVariableFactory.java hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/factories/LogicOperatorFactory.java hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/factories/LogicalInversionOperatorFactory.java hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/factories/LoopingConditionFactory.java hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/factories/MainKlassFactory.java hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/factories/NonStaticMemberVariableFactory.java hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/factories/NothingFactory.java hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/factories/OperatorFactory.java hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/factories/PrintVariablesFactory.java hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/factories/ReturnFactory.java hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/factories/SafeFactory.java hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/factories/StatementFactory.java hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/factories/StaticConstructorDefinitionFactory.java hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/factories/StaticMemberVariableFactory.java hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/factories/SwitchFactory.java hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/factories/TernaryOperatorFactory.java hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/factories/ThrowFactory.java hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/factories/TryCatchBlockFactory.java hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/factories/UnaryOperatorFactory.java hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/factories/UnaryPlusMinusOperatorFactory.java hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/factories/VariableDeclarationBlockFactory.java hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/factories/VariableDeclarationFactory.java hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/factories/VariableFactory.java hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/factories/VariableInitializationFactory.java hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/factories/WhileFactory.java hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/functions/ArgumentDeclaration.java hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/functions/ConstructorDefinition.java hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/functions/ConstructorDefinitionBlock.java hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/functions/Function.java hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/functions/FunctionDeclaration.java hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/functions/FunctionDeclarationBlock.java hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/functions/FunctionDefinition.java hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/functions/FunctionDefinitionBlock.java hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/functions/FunctionInfo.java hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/functions/FunctionRedefinition.java hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/functions/FunctionRedefinitionBlock.java hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/functions/Return.java hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/functions/StaticConstructorDefinition.java hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/jtreg/Printer.java hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/loops/CounterManipulator.java hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/loops/DoWhile.java hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/loops/For.java hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/loops/Loop.java hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/loops/LoopingCondition.java hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/loops/While.java hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/types/TypeArray.java hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/types/TypeKlass.java hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/utils/FixedTrees.java hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/utils/OptionResolver.java hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/utils/PseudoRandom.java hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/visitors/ByteCodeVisitor.java hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/visitors/JavaCodeVisitor.java hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/visitors/Visitor.java
diffstat 148 files changed, 3699 insertions(+), 1345 deletions(-) [+]
line wrap: on
line diff
--- a/hotspot/test/testlibrary/jittester/Makefile	Mon May 16 17:01:53 2016 +0300
+++ b/hotspot/test/testlibrary/jittester/Makefile	Wed May 18 20:19:23 2016 +0300
@@ -91,10 +91,10 @@
 	@echo 'Main-Class: jdk.test.lib.jittester.Automatic' >> $(MANIFEST)
 
 compile_testlib: INIT
-	$(JAVAC) -XDignore.symbol.file -Xlint $(TESTLIBRARY_SRC_FILES) -d $(CLASSES_DIR) -source 1.8
+	$(JAVAC) -XDignore.symbol.file -XaddExports:java.base/jdk.internal.misc=ALL-UNNAMED -XaddExports:java.base/jdk.internal.org.objectweb.asm=ALL-UNNAMED -Xlint $(TESTLIBRARY_SRC_FILES) -d $(CLASSES_DIR)
 
 COMPILE: INIT filelist compile_testlib
-	$(JAVAC) -cp $(CLASSES_DIR) -XDignore.symbol.file -Xlint -sourcepath $(SRC_DIR) -d $(CLASSES_DIR) -source 1.8 @filelist
+	$(JAVAC) -cp $(CLASSES_DIR) -XDignore.symbol.file -XaddExports:java.base/jdk.internal.misc=ALL-UNNAMED -XaddExports:java.base/jdk.internal.org.objectweb.asm=ALL-UNNAMED -Xlint -sourcepath $(SRC_DIR) -d $(CLASSES_DIR) @filelist
 
 filelist: $(SRC_FILES)
 		@rm -f $@
@@ -104,7 +104,7 @@
 	$(shell if [ ! -d $(CLASSES_DIR) ]; then mkdir -p $(CLASSES_DIR); fi)
 
 install: clean_testbase testgroup testroot copytestlibrary JAR cleantmp
-	$(JAVA) -jar $(DIST_JAR) $(APPLICATION_ARGS)
+	$(JAVA) -XaddExports:java.base/jdk.internal.org.objectweb.asm=ALL-UNNAMED -ea -jar $(DIST_JAR) $(APPLICATION_ARGS)
 
 clean_testbase:
 	@rm -rf $(TESTBASE_DIR)
--- a/hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/Automatic.java	Mon May 16 17:01:53 2016 +0300
+++ b/hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/Automatic.java	Wed May 18 20:19:23 2016 +0300
@@ -23,125 +23,165 @@
 
 package jdk.test.lib.jittester;
 
-import java.io.File;
-import java.io.FileWriter;
-import java.io.IOException;
-import java.util.HashSet;
-import java.util.Iterator;
-import java.util.concurrent.TimeUnit;
-import java.util.logging.Level;
-import java.util.logging.Logger;
-import jdk.test.lib.jittester.IRNode;
-import jdk.test.lib.jittester.ProductionParams;
-import jdk.test.lib.jittester.SymbolTable;
-import jdk.test.lib.jittester.TypeList;
+import jdk.test.lib.Pair;
 import jdk.test.lib.jittester.factories.IRNodeBuilder;
-import jdk.test.lib.jittester.TypesParser;
+import jdk.test.lib.jittester.jtreg.Printer;
 import jdk.test.lib.jittester.types.TypeKlass;
-import jdk.test.lib.jittester.visitors.JavaCodeVisitor;
+import jdk.test.lib.jittester.utils.FixedTrees;
 import jdk.test.lib.jittester.utils.OptionResolver;
 import jdk.test.lib.jittester.utils.OptionResolver.Option;
 import jdk.test.lib.jittester.utils.PseudoRandom;
 
+import java.io.File;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.time.LocalTime;
+import java.util.concurrent.TimeUnit;
+import java.util.stream.Collectors;
+
 public class Automatic {
-    public static final int minutesToWait = 3;
+    private static final int MINUTES_TO_WAIT = Integer.getInteger("jdk.test.lib.jittester", 3);
 
-    private static String makeTestCase(String name) {
+    static String getJtregHeader(String mainClass, boolean addCompile) {
+        String synopsis = "seed = '" + ProductionParams.seed.value() + "'"
+                + ", specificSeed = '" + PseudoRandom.getCurrentSeed() + "'";
+        StringBuilder header = new StringBuilder();
+        header.append("/*\n * @test\n * @summary ")
+                .append(synopsis)
+                .append(" \n* @library / ../\n");
+        if (addCompile) {
+            header.append("\n * @compile ")
+                    .append(mainClass)
+                    .append(".java\n");
+        }
+        header.append(" * @run build jdk.test.lib.jittester.jtreg.JitTesterDriver "
+                        + "jdk.test.lib.jittester.jtreg.Printer\n")
+                .append(" * @run driver jdk.test.lib.jittester.jtreg.JitTesterDriver ")
+                .append(mainClass)
+                .append("\n */\n\n");
+        if (ProductionParams.printHierarchy.value()) {
+            header.append("/*\n")
+                .append(Automatic.printHierarchy())
+                .append("*/\n");
+        }
+        return header.toString();
+    }
+
+    private static Pair<IRNode, IRNode> generateIRTree(String name) {
         SymbolTable.removeAll();
         TypeList.removeAll();
-        StringBuilder resultVis = new StringBuilder();
-        StringBuilder headerBuilder = new StringBuilder();
-        try {
-            IRNodeBuilder builder = new IRNodeBuilder()
-                    .setPrefix(name)
-                    .setName(name)
-                    .setLevel(0);
 
-            JavaCodeVisitor vis = new JavaCodeVisitor();
-            String synopsis = "seed = '" + ProductionParams.seed.value() + "'";
-            String pathPrefix = ProductionParams.testbaseDir.value()
-                    .replaceAll("([^/]+)", "..");
-            headerBuilder
-                    .append("/*\n")
-                    .append(" * @test\n")
-                    .append(" * @summary ")
-                        .append(synopsis)
-                        .append("\n")
-                    .append(" * @compile ")
-                        .append(name)
-                        .append(".java\n")
-                    .append(" * @run build jdk.test.lib.jittester.jtreg.JitTesterDriver\n")
-                    .append(" * @run driver jdk.test.lib.jittester.jtreg.JitTesterDriver ")
-                        .append(name)
-                        .append("\n")
-                    .append(" */\n\n");
+        IRNodeBuilder builder = new IRNodeBuilder()
+                .setPrefix(name)
+                .setName(name)
+                .setLevel(0);
 
-
-            if (!ProductionParams.disableClasses.value()) {
-                long comlexityLimit = (long) (ProductionParams.complexityLimit.value()
-                        * PseudoRandom.random());
-                IRNode privateClasses = builder.setComplexityLimit(comlexityLimit)
+        Long complexityLimit = ProductionParams.complexityLimit.value();
+        IRNode privateClasses = null;
+        if (!ProductionParams.disableClasses.value()) {
+            long privateClassComlexity = (long) (complexityLimit * PseudoRandom.random());
+            try {
+                privateClasses = builder.setComplexityLimit(privateClassComlexity)
                         .getClassDefinitionBlockFactory()
                         .produce();
-                if (privateClasses != null) {
-                    resultVis.append(privateClasses.accept(vis));
-                }
+            } catch (ProductionFailedException ex) {
+                ex.printStackTrace(System.out);
             }
-            long mainComplexityLimit = (long) (ProductionParams.complexityLimit.value()
-                    * PseudoRandom.random());
-            IRNode mainClass = builder.setComplexityLimit(mainComplexityLimit)
+        }
+        long mainClassComplexity = (long) (complexityLimit * PseudoRandom.random());
+        IRNode mainClass = null;
+        try {
+            mainClass = builder.setComplexityLimit(mainClassComplexity)
                     .getMainKlassFactory()
                     .produce();
-            resultVis.append(mainClass.accept(vis));
-
-            if (ProductionParams.printHierarchy.value()) {
-                headerBuilder
-                        .append("/*\n")
-                        .append(Automatic.printHierarchy())
-                        .append("*/\n");
-            }
-        } catch (Exception e) {
-            e.printStackTrace(System.out);
+            TypeKlass aClass = new TypeKlass(name);
+            mainClass.getChild(1).addChild(FixedTrees.generateMainOrExecuteMethod(aClass, true));
+            mainClass.getChild(1).addChild(FixedTrees.generateMainOrExecuteMethod(aClass, false));
+        } catch (ProductionFailedException ex) {
+            ex.printStackTrace(System.out);
         }
-        return headerBuilder.append(resultVis).toString();
+        return new Pair<>(mainClass, privateClasses);
     }
 
     private static void initializeTestGenerator(String[] params) {
         OptionResolver parser = new OptionResolver();
-        Option<String> propertyFileOpt = parser.addStringOption('p', "property-file", "",
-                "File to read properties from");
+        Option<String> propertyFileOpt = parser.addStringOption('p', "property-file",
+                "conf/default.properties", "File to read properties from");
         ProductionParams.register(parser);
         parser.parse(params, propertyFileOpt);
-        jdk.test.lib.jittester.utils.PseudoRandom.reset(ProductionParams.seed.value());
-        TypesParser.parseTypesAndMethods(ProductionParams.classesFile.value(), ProductionParams.excludeMethodsFile.value());
+        PseudoRandom.reset(ProductionParams.seed.value());
+        TypesParser.parseTypesAndMethods(ProductionParams.classesFile.value(),
+                ProductionParams.excludeMethodsFile.value());
+        if (ProductionParams.specificSeed.isSet()) {
+            PseudoRandom.setCurrentSeed(ProductionParams.specificSeed.value());
+        }
     }
 
     public static void main(String[] args) {
         initializeTestGenerator(args);
         int counter = 0;
         try {
-            String testbaseDir = ProductionParams.testbaseDir.value();
+            Path testbaseDir = Paths.get(ProductionParams.testbaseDir.value());
+            System.out.printf(" %13s | %8s | %8s | %8s |%n", "start time", "count", "generat",
+                              "running");
+            System.out.printf(" %13s | %8s | %8s | %8s |%n", "---", "---", "---","---");
+            String path = getJavaPath();
+            String javacPath = Paths.get(path, "javac").toString();
+            String javaPath = Paths.get(path, "java").toString();
+
+            // compile Printer class first. A common one for all tests
+            ensureExisting(testbaseDir);
+            ProcessBuilder pbPrinter = new ProcessBuilder(javacPath,
+                    Paths.get(testbaseDir.toString(), "jdk", "test", "lib", "jittester",
+                            "jtreg", "Printer.java").toString());
+            runProcess(pbPrinter, testbaseDir.resolve("Printer").toString());
             do {
                 double start = System.currentTimeMillis();
+                System.out.print("[" + LocalTime.now() + "] |");
                 String name = "Test_" + counter;
-                generateTestFile(name);
+                Pair<IRNode, IRNode> irTree = generateIRTree(name);
+                System.out.printf(" %8d |", counter);
                 double generationTime = System.currentTimeMillis() - start;
-                String path = getJavaPath();
-                ProcessBuilder pb = new ProcessBuilder(path + "javac", testbaseDir + "/" + name + ".java");
-                runProcess(pb, testbaseDir + "/" + name);
+                System.out.printf(" %8.0f |", generationTime);
+                if (!ProductionParams.disableJavacodeGeneration.value()) {
+                    JavaCodeGenerator generator = new JavaCodeGenerator();
+                    String javaFile = generator.apply(irTree.first, irTree.second);
+                    ProcessBuilder pb = new ProcessBuilder(javacPath, "-cp", testbaseDir.toString()
+                            + ":" + generator.getTestbase().toString(), javaFile);
+                    runProcess(pb, generator.getTestbase().resolve(name).toString());
+                    start = System.currentTimeMillis();
 
-                start = System.currentTimeMillis();
-                pb = new ProcessBuilder(path + "java", "-Xint", "-cp", testbaseDir, name);
-                name = name + ".gold";
-                runProcess(pb, testbaseDir + "/" + name);
+                    // Run compiled class files
+                    pb = new ProcessBuilder(javaPath, "-Xint", "-cp", testbaseDir.toString()
+                            + ":" + generator.getTestbase().toString(), name);
+                    String goldFile = name + ".gold";
+                    runProcess(pb, generator.getTestbase().resolve(goldFile).toString());
+                }
+
+                if (!ProductionParams.disableBytecodeGeneration.value()) {
+                    ByteCodeGenerator generator = new ByteCodeGenerator();
+                    generator.apply(irTree.first, irTree.second);
+                    generator.writeJtregBytecodeRunner(name);
+                    // Run generated bytecode
+                    ProcessBuilder pb = new ProcessBuilder(javaPath, "-Xint", "-Xverify", "-cp",
+                            testbaseDir.toString() + ":" + generator.getTestbase().toString(),
+                            name);
+                    String goldFile = name + ".gold";
+                    start = System.currentTimeMillis();
+                    runProcess(pb, generator.getTestbase().resolve(goldFile).toString());
+                }
+
                 double runningTime = System.currentTimeMillis() - start;
-                System.out.printf("%4d : generation time (ms) : %8.0f running time (ms) : %8.0f\n",
-                                  counter, generationTime, runningTime);
-                if (runningTime < TimeUnit.MINUTES.toMillis(minutesToWait))
-                ++counter;
+                System.out.printf(" %8.0f |%n", runningTime);
+                if (runningTime < TimeUnit.MINUTES.toMillis(MINUTES_TO_WAIT)) {
+                    ++counter;
+                }
             } while (counter < ProductionParams.numberOfTests.value());
         } catch (IOException | InterruptedException ex) {
-            Logger.getLogger(Automatic.class.getName()).log(Level.SEVERE, null, ex);
+            ex.printStackTrace();
         }
     }
 
@@ -156,65 +196,47 @@
         return "";
     }
 
-    private static void runProcess(ProcessBuilder pb, String name)
+    private static int runProcess(ProcessBuilder pb, String name)
             throws IOException, InterruptedException {
         pb.redirectError(new File(name + ".err"));
         pb.redirectOutput(new File(name + ".out"));
         Process process = pb.start();
-        if (process.waitFor(minutesToWait, TimeUnit.MINUTES)) {
+        if (process.waitFor(MINUTES_TO_WAIT, TimeUnit.MINUTES)) {
             try (FileWriter file = new FileWriter(name + ".exit")) {
                 file.write(Integer.toString(process.exitValue()));
             }
+            return process.exitValue();
         } else {
             process.destroyForcibly();
-        }
-        TimeUnit.MILLISECONDS.sleep(300);
-    }
-
-    private static void generateTestFile(String testName) {
-        String code = makeTestCase(testName);
-        String testbaseDir = ProductionParams.testbaseDir.value();
-        String fileName = testbaseDir + "/" + testName + ".java";
-        try (FileWriter file = new FileWriter(fileName)) {
-            file.write(code);
-            //file.close();
-        } catch (IOException ex) {
-            Logger.getLogger(Automatic.class.getName())
-                  .log(Level.SEVERE, " Cannot write to file " + fileName, ex);
+            return -1;
         }
     }
 
     private static String printHierarchy() {
-        String r = "CLASS HIERARCHY:\n";
-        for (Type t : TypeList.getAll()) {
-            if (t instanceof TypeKlass) {
-                TypeKlass k = (TypeKlass) t;
-                if (k.isAbstract()) {
-                    r += "abstract ";
-                }
-                if (k.isFinal()) {
-                    r += "final ";
-                }
-                if (k.isInterface()) {
-                    r += "interface ";
-                } else {
-                    r += "class ";
-                }
-                r += k.getName() + ": ";
-                HashSet<String> parents = k.getParentsNames();
-                if (parents != null) {
-                    Iterator<String> n = parents.iterator();
-                    int size = parents.size();
-                    for (int i = 0; n.hasNext() && i < size - 1; i++) {
-                        r += n.next() + ", ";
-                    }
-                    if (n.hasNext()) {
-                        r += n.next();
-                    }
-                }
-                r += "\n";
+        return TypeList.getAll().stream()
+                .filter(t -> t instanceof TypeKlass)
+                .map(t -> typeDescription((TypeKlass) t))
+                .collect(Collectors.joining("\n","CLASS HIERARCHY:\n", "\n"));
+    }
+
+    private static String typeDescription(TypeKlass type) {
+        StringBuilder result = new StringBuilder();
+        String parents = type.getParentsNames().stream().collect(Collectors.joining(","));
+        result.append(type.isAbstract() ? "abstract " : "")
+              .append(type.isFinal() ? "final " : "")
+              .append(type.isInterface() ? "interface " : "class ")
+              .append(type.getName())
+              .append(parents.isEmpty() ? "" : ": " + parents);
+        return result.toString();
+    }
+
+    static void ensureExisting(Path path) {
+        if (Files.notExists(path)) {
+            try {
+                Files.createDirectories(path);
+            } catch (IOException ex) {
+                ex.printStackTrace();
             }
         }
-        return r;
     }
 }
--- a/hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/BinaryOperator.java	Mon May 16 17:01:53 2016 +0300
+++ b/hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/BinaryOperator.java	Wed May 18 20:19:23 2016 +0300
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2005, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -26,12 +26,8 @@
 import jdk.test.lib.jittester.visitors.Visitor;
 
 public class BinaryOperator extends Operator {
-    protected String operationCode;
-    protected Type resultType;
-
-    public BinaryOperator(OperatorKind opKind, IRNode leftOperand, IRNode rightOperand) {
-        super(opKind.priority);
-        operationCode = opKind.text;
+    public BinaryOperator(OperatorKind opKind, Type resultType, IRNode leftOperand, IRNode rightOperand) {
+        super(opKind, resultType);
         addChild(leftOperand);
         addChild(rightOperand);
     }
@@ -47,10 +43,6 @@
         }
     }
 
-    public String getOperationCode() {
-        return operationCode;
-    }
-
     @Override
     public<T> T accept(Visitor<T> v) {
         return v.visit(this);
--- a/hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/Block.java	Mon May 16 17:01:53 2016 +0300
+++ b/hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/Block.java	Wed May 18 20:19:23 2016 +0300
@@ -28,17 +28,12 @@
 import jdk.test.lib.jittester.visitors.Visitor;
 
 public class Block extends IRNode {
-    private final Type returnType;
 
-    public Block(TypeKlass klass, Type returnType, List<IRNode> content, int level) {
-        setKlass(klass);
+    public Block(TypeKlass owner, Type returnType, List<? extends IRNode> content, int level) {
+        super(returnType);
+        setOwner(owner);
         addChildren(content);
         this.level = level;
-        this.returnType = returnType;
-    }
-
-    public Type getReturnType() {
-        return returnType;
     }
 
     protected int size() {
--- a/hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/Break.java	Mon May 16 17:01:53 2016 +0300
+++ b/hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/Break.java	Wed May 18 20:19:23 2016 +0300
@@ -27,6 +27,10 @@
 
 public class Break extends IRNode {
 
+    public Break() {
+        super(TypeList.VOID);
+    }
+
     @Override
     public<T> T accept(Visitor<T> v) {
         return v.visit(this);
--- a/hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/BuiltInType.java	Mon May 16 17:01:53 2016 +0300
+++ b/hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/BuiltInType.java	Wed May 18 20:19:23 2016 +0300
@@ -27,9 +27,9 @@
 
     private static class BuiltInTypeCapacityHelper {
 
-        static String builtInTypes[] = {"boolean", "byte", "short", "char", "int", "long", "float", "double"};
+        private static final String builtInTypes[] = {"boolean", "byte", "short", "char", "int", "long", "float", "double"};
 
-        static private int getIndexFor(String typeName) {
+        private static int getIndexFor(String typeName) {
             for (int i = 0; i < builtInTypes.length; i++) {
                 if (typeName.compareTo(builtInTypes[i]) == 0) {
                     return i;
@@ -38,7 +38,7 @@
             return -1;
         }
 
-        static public int compare(String typeName1, String typeName2) {
+        public static int compare(String typeName1, String typeName2) {
             int i1 = getIndexFor(typeName1);
             int i2 = getIndexFor(typeName2);
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/ByteCodeGenerator.java	Wed May 18 20:19:23 2016 +0300
@@ -0,0 +1,96 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package jdk.test.lib.jittester;
+
+import jdk.test.lib.jittester.visitors.ByteCodeVisitor;
+
+import java.io.FileOutputStream;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.nio.file.StandardOpenOption;
+import java.util.function.BiFunction;
+
+/**
+ * Generates class files from bytecode
+ */
+class ByteCodeGenerator implements BiFunction<IRNode, IRNode, String> {
+    private final Path testbase = Paths.get(ProductionParams.testbaseDir.value(),
+            "bytecode_tests");
+
+    public void writeJtregBytecodeRunner(String name) {
+        try (FileWriter file = new FileWriter(testbase.resolve(name + ".java").toFile())) {
+            file.write(Automatic.getJtregHeader(name, false));
+        } catch (IOException e) {
+            e.printStackTrace();
+        }
+    }
+
+    public String apply(IRNode mainClass, IRNode privateClasses) {
+        Automatic.ensureExisting(testbase);
+        try {
+            ByteCodeVisitor vis = new ByteCodeVisitor();
+            if (privateClasses != null) {
+                privateClasses.accept(vis);
+            }
+            mainClass.accept(vis);
+
+            Path mainClassPath = testbase.resolve(mainClass.getName() + ".class");
+            writeToClassFile(mainClassPath, vis.getByteCode(mainClass.getName()));
+            if (privateClasses != null) {
+                privateClasses.getChildren().forEach(c -> {
+                    String name = c.getName();
+                    Path classPath = testbase.resolve(name + ".class");
+                    writeToClassFile(classPath, vis.getByteCode(name));
+                });
+            }
+            return mainClassPath.toString();
+        } catch (Throwable t) {
+            Path errFile = testbase.resolve(mainClass.getName() + ".err");
+            try (PrintWriter pw = new PrintWriter(Files.newOutputStream(errFile,
+                    StandardOpenOption.CREATE_NEW))) {
+                t.printStackTrace(pw);
+            } catch (IOException e) {
+                t.printStackTrace();
+                throw new Error("can't write error to error file " + errFile, e);
+            }
+            return null;
+        }
+    }
+
+    public Path getTestbase() {
+        return testbase;
+    }
+
+    private void writeToClassFile(Path path, byte[] bytecode) {
+        try (FileOutputStream file = new FileOutputStream(path.toString())) {
+            file.write(bytecode);
+        } catch (IOException ex) {
+            ex.printStackTrace();
+        }
+    }
+}
--- a/hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/CastOperator.java	Mon May 16 17:01:53 2016 +0300
+++ b/hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/CastOperator.java	Wed May 18 20:19:23 2016 +0300
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2005, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -26,11 +26,9 @@
 import jdk.test.lib.jittester.visitors.Visitor;
 
 public class CastOperator extends Operator {
-    private final Type resultType;
 
     public CastOperator(Type resultType, IRNode casted) {
-        super(13);
-        this.resultType = resultType;
+        super(null, 13, resultType);
         addChild(casted);
     }
 
@@ -43,8 +41,4 @@
     public<T> T accept(Visitor<T> v) {
         return v.visit(this);
     }
-
-    public Type getResultType() {
-        return resultType;
-    }
 }
--- a/hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/CatchBlock.java	Mon May 16 17:01:53 2016 +0300
+++ b/hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/CatchBlock.java	Wed May 18 20:19:23 2016 +0300
@@ -31,6 +31,7 @@
     public final List<Type> throwables;
 
     public CatchBlock(IRNode body, List<Type> throwables, int level) {
+        super(body.getResultType());
         this.level = level;
         this.throwables = Collections.unmodifiableList(throwables);
         addChild(body);
--- a/hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/Continue.java	Mon May 16 17:01:53 2016 +0300
+++ b/hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/Continue.java	Wed May 18 20:19:23 2016 +0300
@@ -27,6 +27,10 @@
 
 public class Continue extends IRNode {
 
+    public Continue() {
+        super(TypeList.VOID);
+    }
+
     @Override
     public<T> T accept(Visitor<T> v) {
         return v.visit(this);
--- a/hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/Declaration.java	Mon May 16 17:01:53 2016 +0300
+++ b/hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/Declaration.java	Wed May 18 20:19:23 2016 +0300
@@ -27,6 +27,7 @@
 
 public class Declaration extends IRNode {
     public Declaration(IRNode declarationExpr) {
+        super(declarationExpr.getResultType());
         addChild(declarationExpr);
     }
 
--- a/hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/IRNode.java	Mon May 16 17:01:53 2016 +0300
+++ b/hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/IRNode.java	Wed May 18 20:19:23 2016 +0300
@@ -37,16 +37,26 @@
 public abstract class IRNode {
     private IRNode parent;
     private final List<IRNode> children = new ArrayList<>();
-    protected IRNode klass;
+    protected TypeKlass owner;
     protected int level;
+    private final Type resultType;
+
+    protected IRNode(Type resultType) {
+        this.resultType = resultType;
+    }
+
+    public Type getResultType() {
+        return resultType;
+    }
+
     //TODO
     //private boolean isCFDeviation;
 
     public abstract <T> T accept(Visitor<T> v);
 
-    public void setKlass(TypeKlass klass) {
-        this.klass = klass;
-        if (Objects.isNull(klass)) {
+    public void setOwner(TypeKlass owner) {
+        this.owner = owner;
+        if (Objects.isNull(owner)) {
             System.out.println(getClass().getName() + " null");
             for (StackTraceElement s : Thread.currentThread().getStackTrace()) {
                 System.out.println(s.toString());
@@ -55,20 +65,17 @@
     }
 
     public void addChild(IRNode child) {
-        children.add(child);
-        if (!Objects.isNull(child)) {
+        if (Objects.nonNull(child)) {
+            children.add(child);
             child.parent = this;
         }
     }
 
     public void addChildren(List<? extends IRNode> ch) {
-        if (!Objects.isNull(ch)) {
-            children.addAll(ch);
-            for (IRNode c : ch) {
-                if (!Objects.isNull(c)) {
-                    c.parent = this;
-                }
-            }
+        if (Objects.nonNull(ch)) {
+            ch.stream()
+                .filter(c -> c != null)
+                .forEach(this::addChild);
         }
     }
 
@@ -80,8 +87,8 @@
         return i < children.size() ? children.get(i) : null;
     }
 
-    public IRNode getKlass() {
-        return klass;
+    public TypeKlass getOwner() {
+        return owner;
     }
 
     public IRNode getParent() {
@@ -90,7 +97,7 @@
 
     public void setChild(int index, IRNode child) {
         children.set(index, child);
-        if (!Objects.isNull(child)) {
+        if (Objects.nonNull(child)) {
             child.parent = this;
         }
     }
@@ -145,7 +152,7 @@
 
     @Override
     public final String toString() {
-        throw new Error("Should be toJavaCode");
+        return getName();
     }
 
     public String getName() {
@@ -154,7 +161,7 @@
 
     public static long countDepth(Collection<IRNode> input) {
         return input.stream()
-                .filter(c -> !Objects.isNull(c))
+                .filter(Objects::nonNull)
                 .mapToLong(IRNode::countDepth)
                 .max().orElse(0L);
     }
@@ -166,7 +173,7 @@
     public List<IRNode> getStackableLeaves() {
         List<IRNode> result = new ArrayList<>();
         children.stream()
-                .filter(c -> !Objects.isNull(c))
+                .filter(Objects::nonNull)
                 .forEach(c -> {
                     if (countDepth() == c.level && (c instanceof Block)) {
                         result.add(c);
--- a/hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/If.java	Mon May 16 17:01:53 2016 +0300
+++ b/hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/If.java	Wed May 18 20:19:23 2016 +0300
@@ -30,9 +30,10 @@
         CONDITION,
         THEN,
         ELSE,
-    };
+    }
 
-    public If(IRNode condition, IRNode thenBlock, IRNode elseBlock, int level) {
+    public If(IRNode condition, Block thenBlock, Block elseBlock, int level) {
+        super(thenBlock.getResultType());
         this.level = level;
         resizeUpChildren(IfPart.values().length);
         setChild(IfPart.CONDITION.ordinal(), condition);
@@ -43,7 +44,7 @@
     @Override
     public long complexity() {
         IRNode condition = getChild(IfPart.CONDITION.ordinal());
-        IRNode thenBlock=  getChild(IfPart.THEN.ordinal());
+        IRNode thenBlock = getChild(IfPart.THEN.ordinal());
         IRNode elseBlock = getChild(IfPart.ELSE.ordinal());
         return (condition != null ? condition.complexity() : 0)
             + Math.max(thenBlock != null ? thenBlock.complexity() : 0,
--- a/hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/Initialization.java	Mon May 16 17:01:53 2016 +0300
+++ b/hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/Initialization.java	Wed May 18 20:19:23 2016 +0300
@@ -26,20 +26,14 @@
 import jdk.test.lib.jittester.visitors.Visitor;
 
 public abstract class Initialization extends IRNode {
-    protected VariableInfo variableInfo = new VariableInfo();
-
-    protected Initialization() {
-    }
+    private final VariableInfo variableInfo;
 
     protected Initialization(VariableInfo varInfo, IRNode initExpr) {
+        super(varInfo.type);
         variableInfo = varInfo;
         addChild(initExpr);
     }
 
-    public VariableInfo get() {
-        return variableInfo;
-    }
-
     @Override
     public long complexity() {
         return getChild(0).complexity() + 1;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/JavaCodeGenerator.java	Wed May 18 20:19:23 2016 +0300
@@ -0,0 +1,70 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package jdk.test.lib.jittester;
+
+import jdk.test.lib.jittester.visitors.JavaCodeVisitor;
+
+import java.io.FileWriter;
+import java.io.IOException;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.function.BiFunction;
+
+/**
+ * Generates class files from java source code
+ */
+class JavaCodeGenerator implements BiFunction<IRNode, IRNode, String> {
+    private final Path testbase = Paths.get(ProductionParams.testbaseDir.value(), "java_tests");
+
+    private String generateJavaCode(IRNode mainClass, IRNode privateClasses) {
+        StringBuilder code = new StringBuilder();
+        JavaCodeVisitor vis = new JavaCodeVisitor();
+
+        code.append(Automatic.getJtregHeader(mainClass.getName(), true));
+        if (privateClasses != null) {
+            code.append(privateClasses.accept(vis));
+        }
+        code.append(mainClass.accept(vis));
+
+        return code.toString();
+    }
+
+    public Path getTestbase() {
+        return testbase;
+    }
+
+    @Override
+    public String apply(IRNode mainClass, IRNode privateClasses) {
+        String code = generateJavaCode(mainClass, privateClasses);
+        Automatic.ensureExisting(testbase);
+        Path fileName = testbase.resolve(mainClass.getName() + ".java");
+        try (FileWriter file = new FileWriter(fileName.toFile())) {
+            file.write(code);
+            return fileName.toString();
+        } catch (IOException ex) {
+            ex.printStackTrace();
+        }
+        return "";
+    }
+}
--- a/hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/Literal.java	Mon May 16 17:01:53 2016 +0300
+++ b/hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/Literal.java	Wed May 18 20:19:23 2016 +0300
@@ -27,11 +27,10 @@
 
 public class Literal extends IRNode {
     public final Object value;
-    protected final Type resultType;
 
     public Literal(Object v, Type t) {
+        super(t);
         value = v;
-        resultType = t;
     }
 
     @Override
@@ -44,10 +43,6 @@
         return v.visit(this);
     }
 
-    public Type getResultType() {
-        return resultType;
-    }
-
     public Object getValue() {
         return value;
     }
--- a/hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/LocalVariable.java	Mon May 16 17:01:53 2016 +0300
+++ b/hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/LocalVariable.java	Wed May 18 20:19:23 2016 +0300
@@ -25,16 +25,9 @@
 
 import jdk.test.lib.jittester.visitors.Visitor;
 
-public class LocalVariable extends IRNode implements VariableBase {
-    private VariableInfo value = new VariableInfo();
-
+public class LocalVariable extends VariableBase {
     public LocalVariable(VariableInfo value) {
-        this.value = value;
-    }
-
-    @Override
-    public VariableInfo get() {
-        return value;
+        super(value);
     }
 
     @Override
--- a/hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/LogicOperator.java	Mon May 16 17:01:53 2016 +0300
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,37 +0,0 @@
-/*
- * Copyright (c) 2005, 2015, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package jdk.test.lib.jittester;
-
-import jdk.test.lib.jittester.visitors.Visitor;
-
-public class LogicOperator extends IRNode {
-
-    protected LogicOperator() {
-    }
-
-    @Override
-    public<T> T accept(Visitor<T> v) {
-        return v.visit(this);
-    }
-}
--- a/hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/NonStaticMemberVariable.java	Mon May 16 17:01:53 2016 +0300
+++ b/hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/NonStaticMemberVariable.java	Wed May 18 20:19:23 2016 +0300
@@ -25,20 +25,14 @@
 
 import jdk.test.lib.jittester.visitors.Visitor;
 
-public class NonStaticMemberVariable extends IRNode implements VariableBase {
-    private final VariableInfo value;
+public class NonStaticMemberVariable extends VariableBase {
 
     public NonStaticMemberVariable(IRNode object, VariableInfo value) {
-        this.value = value;
+        super(value);
         addChild(object);
     }
 
     @Override
-    public VariableInfo get() {
-        return value;
-    }
-
-    @Override
     public long complexity() {
         return getChild(0).complexity();
     }
@@ -47,8 +41,4 @@
     public<T> T accept(Visitor<T> v) {
         return v.visit(this);
     }
-
-    public VariableInfo getValue() {
-        return value;
-    }
 }
--- a/hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/Nothing.java	Mon May 16 17:01:53 2016 +0300
+++ b/hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/Nothing.java	Wed May 18 20:19:23 2016 +0300
@@ -27,6 +27,10 @@
 
 public class Nothing extends IRNode {
 
+    public Nothing() {
+        super(TypeList.VOID);
+    }
+
     @Override
     public long complexity() {
         return 0;
--- a/hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/Operator.java	Mon May 16 17:01:53 2016 +0300
+++ b/hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/Operator.java	Wed May 18 20:19:23 2016 +0300
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2005, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -24,18 +24,28 @@
 package jdk.test.lib.jittester;
 
 public abstract class Operator extends IRNode {
-    protected int operatorPriority;
+    protected final OperatorKind opKind;
+    private final int priority;
 
     public int getPriority() {
-        return operatorPriority;
+        return priority;
+    }
+
+    public OperatorKind getOperationKind() {
+        return opKind;
     }
 
     public enum Order {
         LEFT, RIGHT
-    };
+    }
 
-    // This constructor is called to construct an IR-tree node.
-    protected Operator(int operatorPriority) {
-        this.operatorPriority = operatorPriority;
+    protected Operator(OperatorKind opKind, Type resultType) {
+        this(opKind, opKind.priority, resultType);
+    }
+
+    protected Operator(OperatorKind opKind, int operatorPriority, Type resultType) {
+        super(resultType);
+        this.opKind = opKind;
+        this.priority = operatorPriority;
     }
 }
--- a/hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/OperatorKind.java	Mon May 16 17:01:53 2016 +0300
+++ b/hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/OperatorKind.java	Wed May 18 20:19:23 2016 +0300
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -25,58 +25,96 @@
 
 // all unary and binary operator kinds
 public enum OperatorKind {
-    COMPOUND_ADD("+=",   1),
-    COMPOUND_SUB("-=",   1),
-    COMPOUND_MUL("*=",   1),
-    COMPOUND_DIV("-=",   1),
-    COMPOUND_MOD("%=",   1),
-    COMPOUND_AND("&=",   1),
-    COMPOUND_OR ("|=",   1),
-    COMPOUND_XOR("^=",   1),
-    COMPOUND_SHR(">>=",  1),
-    COMPOUND_SHL("<<=",  1),
-    COMPOUND_SAR(">>>=", 1),
-    ASSIGN      ("=",    1),
-    OR          ("||",   3),
-    BIT_OR      ("|",    5),
-    BIT_XOR     ("^",    6),
-    AND         ("&&",   7),
-    BIT_AND     ("&",    7),
-    EQ          ("==",   8),
-    NE          ("!=",   8),
-    GT          (">",    9),
-    LT          ("<",    9),
-    GE          (">=",   9),
-    LE          ("<=",   9),
-    SHR         (">>",  10),
-    SHL         ("<<",  10),
-    SAR         (">>>", 10),
-    ADD         ("+",   11),
-    STRADD      ("+",   11),
-    SUB         ("-",   11),
-    MUL         ("*",   12),
-    DIV         ("/",   12),
-    MOD         ("%",   12),
-    NOT         ("!",   14),
-    BIT_NOT     ("~",   14),
-    UNARY_PLUS  ("+",   14),
-    UNARY_MINUS ("-",   14),
-    PRE_DEC     ("--",  15, true),
-    POST_DEC    ("--",  15, false),
-    PRE_INC     ("++",  16, true),
-    POST_INC    ("++",  16, false),
+    /** a += b */
+    COMPOUND_ADD(1),
+    /** a -= b */
+    COMPOUND_SUB(1),
+    /** a *= b */
+    COMPOUND_MUL(1),
+    /** a /= b */
+    COMPOUND_DIV(1),
+    /** a %= b */
+    COMPOUND_MOD(1),
+    /** a &= b */
+    COMPOUND_AND(1),
+    /** a |= b */
+    COMPOUND_OR (1),
+    /** a ^= b */
+    COMPOUND_XOR(1),
+    /** a >>= b */
+    COMPOUND_SHR(1),
+    /** a <<= b */
+    COMPOUND_SHL(1),
+    /** a >>>= b */
+    COMPOUND_SAR(1),
+    /** a = b */
+    ASSIGN      (1),
+    /**  a || b */
+    OR          (3),
+    /** a | b */
+    BIT_OR      (5),
+    /** a ^ b */
+    BIT_XOR     (6),
+    /** a && b */
+    AND         (7),
+    /** a & b */
+    BIT_AND     (7),
+    /** a == b */
+    EQ          (8),
+    /** a != b */
+    NE          (8),
+    /** a > b */
+    GT          (9),
+    /** a < b */
+    LT          (9),
+    /** a >= b */
+    GE          (9),
+    /** a <= b */
+    LE          (9),
+    /** a >> b */
+    SHR         (10),
+    /** a << b */
+    SHL         (10),
+    /** a >>> b */
+    SAR         (10),
+    /** a + b */
+    ADD         (11),
+    /** a.toString() + b */
+    STRADD      (11),
+    /** a - b */
+    SUB         (11),
+    /** a * b */
+    MUL         (12),
+    /** a / b */
+    DIV         (12),
+    /** a % b */
+    MOD         (12),
+    /** !a */
+    NOT         (14),
+    /** ~a */
+    BIT_NOT     (14),
+    /** +a */
+    UNARY_PLUS  (14),
+    /** -a */
+    UNARY_MINUS (14),
+    /** --a */
+    PRE_DEC     (15, true),
+    /** a-- */
+    POST_DEC    (15, false),
+    /** ++a */
+    PRE_INC     (16, true),
+    /** a++ */
+    POST_INC    (16, false),
     ;
 
-    public final String text;
     public final int priority;
     public final boolean isPrefix; // used for unary operators
 
-    private OperatorKind(String text, int priority) {
-        this(text, priority, true);
+    private OperatorKind(int priority) {
+        this(priority, true);
     }
 
-    private OperatorKind(String text, int priority, boolean isPrefix) {
-        this.text = text;
+    private OperatorKind(int priority, boolean isPrefix) {
         this.priority = priority;
         this.isPrefix = isPrefix;
     }
--- a/hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/PrintVariables.java	Mon May 16 17:01:53 2016 +0300
+++ b/hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/PrintVariables.java	Wed May 18 20:19:23 2016 +0300
@@ -25,15 +25,16 @@
 
 import java.util.ArrayList;
 import java.util.List;
+import jdk.test.lib.jittester.types.TypeKlass;
 import jdk.test.lib.jittester.visitors.Visitor;
 
 public class PrintVariables extends IRNode {
-    private final String printerName;
     private final ArrayList<Symbol> vars;
 
-    public PrintVariables(String printerName, ArrayList<Symbol> vars, int level) {
-        this.printerName = printerName;
-        this.vars = vars;
+    public PrintVariables(TypeKlass owner, int level) {
+        super(TypeList.VOID);
+        this.owner = owner;
+        this.vars = SymbolTable.getAllCombined(owner, VariableInfo.class);
         this.level = level;
     }
 
@@ -45,8 +46,4 @@
     public List<Symbol> getVars() {
         return vars;
     }
-
-    public String getPrinterName() {
-        return printerName;
-    }
 }
--- a/hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/ProductionParams.java	Mon May 16 17:01:53 2016 +0300
+++ b/hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/ProductionParams.java	Wed May 18 20:19:23 2016 +0300
@@ -68,11 +68,14 @@
     public static Option<Boolean> disableNestedBlocks = null;
     public static Option<Boolean> disableArrays = null;
     public static Option<Boolean> enableFinalizers = null;
+    public static Option<Boolean> disableBytecodeGeneration = null;
+    public static Option<Boolean> disableJavacodeGeneration = null;
     // workaraound: to reduce chance throwing ArrayIndexOutOfBoundsException
     public static Option<Integer> chanceExpressionIndex = null;
     public static Option<String> testbaseDir = null;
     public static Option<Integer> numberOfTests = null;
     public static Option<String> seed = null;
+    public static Option<Long> specificSeed = null;
     public static Option<String> classesFile = null;
     public static Option<String> excludeMethodsFile = null;
 
@@ -117,11 +120,14 @@
         disableNestedBlocks = optionResolver.addBooleanOption("disable-nested-blocks", "Disable generation of nested blocks");
         disableArrays = optionResolver.addBooleanOption("disable-arrays", "Disable generation of arrays");
         enableFinalizers = optionResolver.addBooleanOption("enable-finalizers", "Enable finalizers (for stress testing)");
+        disableBytecodeGeneration = optionResolver.addBooleanOption("disable-bytecode-generation", "Disable generation of bytecode output");
+        disableJavacodeGeneration = optionResolver.addBooleanOption("disable-javacode-generation", "Disable generation of java source code output");
         chanceExpressionIndex = optionResolver.addIntegerOption("chance-expression-index", 0, "A non negative decimal integer used to restrict chane of generating expression in array index while creating or accessing by index");
         testbaseDir = optionResolver.addStringOption("testbase-dir", ".", "Testbase dir");
         numberOfTests = optionResolver.addIntegerOption('n', "number-of-tests", 0, "Number of test classes to generate");
         seed = optionResolver.addStringOption("seed", "", "Random seed");
-        classesFile = optionResolver.addStringOption('f', "classes-file", "", "File to read classes from");
-        excludeMethodsFile = optionResolver.addStringOption('r', "exclude-methods-file", "", "File to read excluded methods from");
+        specificSeed = optionResolver.addLongOption('z', "specificSeed", 0L, "A seed to be set for specific test generation(regular seed still needed for initialization)");
+        classesFile = optionResolver.addStringOption('f', "classes-file", "conf/classes.lst", "File to read classes from");
+        excludeMethodsFile = optionResolver.addStringOption('r', "exclude-methods-file", "conf/exclude.methods.lst", "File to read excluded methods from");
     }
 }
--- a/hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/Rule.java	Mon May 16 17:01:53 2016 +0300
+++ b/hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/Rule.java	Wed May 18 20:19:23 2016 +0300
@@ -32,27 +32,26 @@
 /**
  * The Rule. A helper to perform production.
  */
-public class Rule extends Factory implements Comparable<Rule> {
-    private String name;
+public class Rule<T extends IRNode> extends Factory<T> implements Comparable<Rule<T>> {
+    private final String name;
+    private final TreeSet<RuleEntry> variants;
     private Integer limit = -1;
 
     @Override
-    public int compareTo(Rule rule) {
+    public int compareTo(Rule<T> rule) {
         return name.compareTo(rule.name);
     }
 
-    private TreeSet<RuleEntry> variants;
-
     public Rule(String name) {
         this.name = name;
         variants = new TreeSet<>();
     }
 
-    public void add(String ruleName, Factory factory) {
+    public void add(String ruleName, Factory<? extends T> factory) {
         add(ruleName, factory, 1.0);
     }
 
-    public void add(String ruleName, Factory factory, double weight) {
+    public void add(String ruleName, Factory<? extends T> factory, double weight) {
         variants.add(new RuleEntry(ruleName, factory, weight));
     }
 
@@ -61,7 +60,7 @@
     }
 
     @Override
-    public IRNode produce() throws ProductionFailedException {
+    public T produce() throws ProductionFailedException {
         if (!variants.isEmpty()) {
             // Begin production.
             LinkedList<RuleEntry> rulesList = new LinkedList<>(variants);
@@ -98,19 +97,19 @@
         throw new ProductionFailedException();
     }
 
-    private class RuleEntry extends Factory implements Comparable<RuleEntry> {
+    private class RuleEntry extends Factory<T> implements Comparable<RuleEntry> {
         private final double weight;
-        private final Factory factory;
+        private final Factory<? extends T> factory;
         private final String name;
 
-        private RuleEntry(String name, Factory factory, double weight) {
+        private RuleEntry(String name, Factory<? extends T> factory, double weight) {
             this.name = name;
             this.weight = weight;
             this.factory = factory;
         }
 
         @Override
-        public IRNode produce() throws ProductionFailedException {
+        public T produce() throws ProductionFailedException {
             return factory.produce();
         }
 
--- a/hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/Statement.java	Mon May 16 17:01:53 2016 +0300
+++ b/hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/Statement.java	Wed May 18 20:19:23 2016 +0300
@@ -29,6 +29,7 @@
     private final boolean needSemicolon;
 
     public Statement(IRNode statementBody, boolean needSemicolon) {
+        super(statementBody.getResultType());
         this.needSemicolon = needSemicolon;
         addChild(statementBody);
     }
--- a/hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/StaticMemberVariable.java	Mon May 16 17:01:53 2016 +0300
+++ b/hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/StaticMemberVariable.java	Wed May 18 20:19:23 2016 +0300
@@ -26,17 +26,11 @@
 import jdk.test.lib.jittester.types.TypeKlass;
 import jdk.test.lib.jittester.visitors.Visitor;
 
-public class StaticMemberVariable extends IRNode implements VariableBase {
-    private final VariableInfo varInfo;
+public class StaticMemberVariable extends VariableBase {
 
     public StaticMemberVariable(TypeKlass owner, VariableInfo varInfo) {
-        setKlass(owner);
-        this.varInfo = varInfo;
-    }
-
-    @Override
-    public VariableInfo get() {
-        return varInfo;
+        super(varInfo);
+        setOwner(owner);
     }
 
     @Override
--- a/hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/Switch.java	Mon May 16 17:01:53 2016 +0300
+++ b/hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/Switch.java	Wed May 18 20:19:23 2016 +0300
@@ -30,6 +30,7 @@
     private final int caseBlockIdx;
 
     public Switch(int level, List<IRNode> chldrn, int caseBlockIdx) {
+        super(chldrn.get(caseBlockIdx).getResultType());
         this.level = level;
         addChildren(chldrn);
         this.caseBlockIdx = caseBlockIdx;
--- a/hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/Symbol.java	Mon May 16 17:01:53 2016 +0300
+++ b/hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/Symbol.java	Wed May 18 20:19:23 2016 +0300
@@ -29,7 +29,7 @@
 
     public String name;
     public Type type;
-    public TypeKlass klass;
+    public TypeKlass owner;
     public static final int NONE = 0x00;
     public static final int PRIVATE = 0x01;
     public static final int DEFAULT = 0x02;
@@ -47,16 +47,16 @@
         this.name = name;
     }
 
-    public Symbol(String name, TypeKlass klass, Type type, int flags) {
+    public Symbol(String name, TypeKlass owner, Type type, int flags) {
         this.name = name;
-        this.klass = klass;
+        this.owner = owner;
         this.type = type;
         this.flags = flags;
     }
 
     protected Symbol(Symbol value) {
         this.name = value.name;
-        this.klass = value.klass;
+        this.owner = value.owner;
         this.type = value.type;
         this.flags = value.flags;
     }
@@ -71,7 +71,7 @@
         }
         try {
             Symbol s = (Symbol) o;
-            return klass.equals(s.klass) && name.equals(s.name);
+            return owner.equals(s.owner) && name.equals(s.name);
         } catch (Exception e) {
             return false;
         }
@@ -110,4 +110,9 @@
     public Symbol deepCopy() {
         return new Symbol(this);
     }
+
+
+    public TypeKlass getOwner() {
+        return owner;
+    }
 }
--- a/hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/SymbolTable.java	Mon May 16 17:01:53 2016 +0300
+++ b/hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/SymbolTable.java	Wed May 18 20:19:23 2016 +0300
@@ -28,6 +28,7 @@
 import java.util.HashMap;
 import java.util.Map;
 import java.util.Stack;
+import java.util.stream.Collectors;
 import jdk.test.lib.jittester.types.TypeKlass;
 
 
@@ -42,9 +43,8 @@
 
         String classList = ProductionParams.addExternalSymbols.value();
         if (classList.equals("all")) {
-            for (Type type : TypeList.getReferenceTypes()) {
-                type.exportSymbols();
-            }
+            TypeList.getReferenceTypes()
+                    .forEach(Type::exportSymbols);
         } else {
             String[] splittedList = classList.split(",");
             for (Type type : TypeList.getReferenceTypes()) {
@@ -96,13 +96,9 @@
     public static Collection<Symbol> get(Type type, Class<?> classToCheck) {
         HashMap<Type, ArrayList<Symbol>> vars = SYMBOL_STACK.peek();
         if (vars.containsKey(type)) {
-            ArrayList<Symbol> result = new ArrayList<>();
-            for (Symbol symbol : vars.get(type)) {
-                if (classToCheck.isInstance(symbol)) {
-                    result.add(symbol);
-                }
-            }
-            return result;
+            return vars.get(type).stream()
+                .filter(classToCheck::isInstance)
+                .collect(Collectors.toList());
         }
         return new ArrayList<>();
     }
@@ -113,7 +109,7 @@
         if (vars.containsKey(type)) {
             ArrayList<Symbol> result = new ArrayList<>();
             for (Symbol symbol : vars.get(type)) {
-                if (classToCheck.isInstance(symbol) && typeKlass.equals(symbol.klass)) {
+                if (classToCheck.isInstance(symbol) && typeKlass.equals(symbol.owner)) {
                     result.add(symbol);
                 }
             }
@@ -150,7 +146,7 @@
         for (Type type : SYMBOL_STACK.peek().keySet()) {
             ArrayList<Symbol> symbolsOfType =  SYMBOL_STACK.peek().get(type);
             for (Symbol symbol : symbolsOfType) {
-                if (classToCheck.isInstance(symbol) && typeKlass.equals(symbol.klass)) {
+                if (classToCheck.isInstance(symbol) && typeKlass.equals(symbol.owner)) {
                     if (!result.containsKey(type)) {
                         result.put(type, new ArrayList<>());
                     }
@@ -193,7 +189,7 @@
         for (Type type : SYMBOL_STACK.peek().keySet()) {
             ArrayList<Symbol> symbolsOfType = SYMBOL_STACK.peek().get(type);
             for (Symbol symbol : symbolsOfType) {
-                if (classToCheck.isInstance(symbol) && typeKlass.equals(symbol.klass)) {
+                if (classToCheck.isInstance(symbol) && typeKlass.equals(symbol.owner)) {
                     result.add(symbol);
                 }
             }
@@ -207,7 +203,7 @@
         for (Type t : SYMBOL_STACK.peek().keySet()) {
             ArrayList<Symbol> symbolsOfType = SYMBOL_STACK.peek().get(t);
             for (Symbol symbol : symbolsOfType) {
-                if (typeKlass.equals(symbol.klass)) {
+                if (typeKlass.equals(symbol.owner)) {
                     result.add(symbol);
                 }
             }
--- a/hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/TernaryOperator.java	Mon May 16 17:01:53 2016 +0300
+++ b/hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/TernaryOperator.java	Wed May 18 20:19:23 2016 +0300
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2005, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -30,12 +30,11 @@
         CONDITION,
         TRUE,
         FALSE,
-    };
+    }
     //protected Production conditionalExpression, leftExpression, rightExpression;
-    protected Type resultType;
 
     public TernaryOperator(IRNode condition, IRNode trueBranch, IRNode falseBranch) {
-        super(2);
+        super(null, 2, trueBranch.getResultType());
         resizeUpChildren(TernaryPart.values().length);
         setChild(TernaryPart.CONDITION.ordinal(), condition);
         setChild(TernaryPart.TRUE.ordinal(), trueBranch);
--- a/hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/Throw.java	Mon May 16 17:01:53 2016 +0300
+++ b/hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/Throw.java	Wed May 18 20:19:23 2016 +0300
@@ -27,6 +27,7 @@
 
 public class Throw extends IRNode {
     public Throw(IRNode throwable) {
+        super(throwable.getResultType());
         addChild(throwable);
     }
 
--- a/hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/TryCatchBlock.java	Mon May 16 17:01:53 2016 +0300
+++ b/hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/TryCatchBlock.java	Wed May 18 20:19:23 2016 +0300
@@ -29,6 +29,7 @@
 
 public class TryCatchBlock extends IRNode {
     public TryCatchBlock(IRNode body, IRNode finallyBlock, List<CatchBlock> catchBlocks, int level) {
+        super(body.getResultType());
         this.level = level;
         addChild(body);
         addChild(finallyBlock);
--- a/hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/Type.java	Mon May 16 17:01:53 2016 +0300
+++ b/hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/Type.java	Wed May 18 20:19:23 2016 +0300
@@ -33,10 +33,16 @@
     private final String typeName;
 
     protected Type(String typeName) {
+        super(null);
         this.typeName = typeName;
     }
 
     @Override
+    public Type getResultType() {
+        return this;
+    }
+
+    @Override
     public boolean equals(Object t) {
         if (this == t) {
             return true;
--- a/hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/TypeList.java	Mon May 16 17:01:53 2016 +0300
+++ b/hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/TypeList.java	Wed May 18 20:19:23 2016 +0300
@@ -27,19 +27,31 @@
 import java.util.Collection;
 import java.util.List;
 import java.util.function.Predicate;
-import jdk.test.lib.jittester.types.TypeArray;
+
 import jdk.test.lib.jittester.types.TypeBoolean;
 import jdk.test.lib.jittester.types.TypeByte;
 import jdk.test.lib.jittester.types.TypeChar;
 import jdk.test.lib.jittester.types.TypeDouble;
 import jdk.test.lib.jittester.types.TypeFloat;
 import jdk.test.lib.jittester.types.TypeInt;
+import jdk.test.lib.jittester.types.TypeKlass;
 import jdk.test.lib.jittester.types.TypeLong;
 import jdk.test.lib.jittester.types.TypeShort;
 import jdk.test.lib.jittester.types.TypeVoid;
 
 public class TypeList {
-    private static final TypeVoid TYPE_VOID = new TypeVoid();
+    public static final TypeVoid VOID = new TypeVoid();
+    public static final TypeBoolean BOOLEAN = new TypeBoolean();
+    public static final TypeByte BYTE = new TypeByte();
+    public static final TypeChar CHAR = new TypeChar();
+    public static final TypeShort SHORT = new TypeShort();
+    public static final TypeInt INT = new TypeInt();
+    public static final TypeLong LONG = new TypeLong();
+    public static final TypeFloat FLOAT = new TypeFloat();
+    public static final TypeDouble DOUBLE = new TypeDouble();
+    public static final TypeKlass OBJECT = new TypeKlass("java.lang.Object");
+    public static final TypeKlass STRING = new TypeKlass("java.lang.String", TypeKlass.FINAL);
+
     private static final List<Type> TYPES = new ArrayList<>();
     private static final List<Type> BUILTIN_TYPES = new ArrayList<>();
     private static final List<Type> BUILTIN_INT_TYPES = new ArrayList<>();
@@ -47,14 +59,14 @@
     private static final List<Type> REFERENCE_TYPES = new ArrayList<>();
 
     static {
-        BUILTIN_INT_TYPES.add(new TypeBoolean());
-        BUILTIN_INT_TYPES.add(new TypeByte());
-        BUILTIN_INT_TYPES.add(new TypeChar());
-        BUILTIN_INT_TYPES.add(new TypeShort());
-        BUILTIN_INT_TYPES.add(new TypeInt());
-        BUILTIN_INT_TYPES.add(new TypeLong());
-        BUILTIN_FP_TYPES.add(new TypeFloat());
-        BUILTIN_FP_TYPES.add(new TypeDouble());
+        BUILTIN_INT_TYPES.add(BOOLEAN);
+        BUILTIN_INT_TYPES.add(BYTE);
+        BUILTIN_INT_TYPES.add(CHAR);
+        BUILTIN_INT_TYPES.add(SHORT);
+        BUILTIN_INT_TYPES.add(INT);
+        BUILTIN_INT_TYPES.add(LONG);
+        BUILTIN_FP_TYPES.add(FLOAT);
+        BUILTIN_FP_TYPES.add(DOUBLE);
 
         BUILTIN_TYPES.addAll(BUILTIN_INT_TYPES);
         BUILTIN_TYPES.addAll(BUILTIN_FP_TYPES);
@@ -62,13 +74,13 @@
         TYPES.addAll(BUILTIN_TYPES);
 
         if (!ProductionParams.disableArrays.value()) {
-            REFERENCE_TYPES.add(new TypeArray().produce());
             TYPES.addAll(REFERENCE_TYPES);
         }
-    }
 
-    public static TypeVoid getVoid() {
-        return TYPE_VOID;
+        STRING.addParent(OBJECT.getName());
+        STRING.setParent(OBJECT);
+        add(STRING);
+        add(OBJECT);
     }
 
     public static Collection<Type> getAll() {
@@ -100,14 +112,14 @@
     }
 
     public static boolean isBuiltIn(Type t) {
-        return isBuiltInInt(t) || isBuiltInFP(t);
+        return isBuiltInInt(t) || isBuiltInFP(t) || t.equals(VOID);
     }
 
     protected static boolean isIn(Type t) {
         return TYPES.contains(t);
     }
 
-    protected static boolean isReferenceType(Type t) {
+    public static boolean isReferenceType(Type t) {
         return REFERENCE_TYPES.contains(t);
     }
 
--- a/hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/TypesParser.java	Mon May 16 17:01:53 2016 +0300
+++ b/hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/TypesParser.java	Wed May 18 20:19:23 2016 +0300
@@ -42,7 +42,6 @@
 import jdk.test.lib.jittester.functions.FunctionInfo;
 import jdk.test.lib.jittester.types.TypeArray;
 import jdk.test.lib.jittester.types.TypeKlass;
-import jdk.test.lib.jittester.types.TypeVoid;
 
 /**
  * Class used for parsing included classes file and excluded methods file
@@ -62,7 +61,7 @@
     public static void parseTypesAndMethods(String klassesFileName, String exMethodsFileName) {
         Asserts.assertNotNull(klassesFileName, "Classes input file name is null");
         Asserts.assertFalse(klassesFileName.isEmpty(), "Classes input file name is empty");
-        Set<Class<?>> klasses = parseKlasses(klassesFileName);
+        List<Class<?>> klasses = parseKlasses(klassesFileName);
         Set<Executable> methodsToExclude;
         if (exMethodsFileName != null && !exMethodsFileName.isEmpty()) {
             methodsToExclude = parseMethods(exMethodsFileName);
@@ -119,15 +118,18 @@
         }
         if (klass.isPrimitive()) {
             if (klass.equals(void.class)) {
-                type = new TypeVoid();
+                type = TypeList.VOID;
             } else {
                 type = TypeList.find(klass.getName());
             }
         } else {
             int flags = getKlassFlags(klass);
             if (klass.isArray()) {
-                TypeKlass elementType
-                        = new TypeKlass(klass.getCanonicalName().replaceAll("\\[\\]", ""), flags);
+                Class<?> elementKlass  = klass.getComponentType();
+                while (elementKlass.isArray()) {
+                    elementKlass = elementKlass.getComponentType();
+                }
+                Type elementType = getType(elementKlass);
                 int dim = getArrayClassDimension(klass);
                 type = new TypeArray(elementType, dim);
             } else {
@@ -138,10 +140,14 @@
                 type = new TypeKlass(canonicalName, flags);
             }
             Class<?> parentKlass = klass.getSuperclass();
+            TypeKlass typeKlass = (TypeKlass) type;
             if (parentKlass != null) {
                 TypeKlass parentTypeKlass = (TypeKlass) getType(parentKlass);
-                ((TypeKlass) type).addParent(parentTypeKlass.getName());
-                ((TypeKlass) type).setParent(parentTypeKlass);
+                typeKlass.addParent(parentTypeKlass.getName());
+                typeKlass.setParent(parentTypeKlass);
+            }
+            for (Class<?> iface : klass.getInterfaces()) {
+                typeKlass.addParent(getType(iface).getName());
             }
         }
         TYPE_CACHE.put(klass, type);
@@ -197,10 +203,10 @@
         return flags;
     }
 
-    private static Set<Class<?>> parseKlasses(String klassesFileName) {
+    private static List<Class<?>> parseKlasses(String klassesFileName) {
         Asserts.assertNotNull(klassesFileName, "Classes input file name is null");
         Asserts.assertFalse(klassesFileName.isEmpty(), "Classes input file name is empty");
-        Set<String> klassNamesSet = new HashSet<>();
+        List<String> klassNamesList = new ArrayList<>();
         Path klassesFilePath = (new File(klassesFileName)).toPath();
         try {
             Files.lines(klassesFilePath).forEach(line -> {
@@ -211,20 +217,20 @@
                 String msg = String.format("Format of the classes input file \"%s\" is incorrect,"
                         + " line \"%s\" has wrong format", klassesFileName, line);
                 Asserts.assertTrue(line.matches("\\w[\\w\\.$]*"), msg);
-                klassNamesSet.add(line.replaceAll(";", ""));
+                klassNamesList.add(line.replaceAll(";", ""));
             });
         } catch (IOException ex) {
             throw new Error("Error reading klasses file", ex);
         }
-        Set<Class<?>> klassesSet = new HashSet<>();
-        klassNamesSet.stream().forEach(klassName -> {
+        List<Class<?>> klassesList = new ArrayList<>();
+        klassNamesList.stream().forEach(klassName -> {
             try {
-                klassesSet.add(Class.forName(klassName));
+                klassesList.add(Class.forName(klassName));
             } catch (ClassNotFoundException ex) {
                 throw new Error("Unexpected exception while parsing klasses file", ex);
             }
         });
-        return klassesSet;
+        return klassesList;
     }
 
     private static Set<Executable> parseMethods(String methodsFileName) {
--- a/hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/UnaryOperator.java	Mon May 16 17:01:53 2016 +0300
+++ b/hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/UnaryOperator.java	Wed May 18 20:19:23 2016 +0300
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2005, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -26,12 +26,8 @@
 import jdk.test.lib.jittester.visitors.Visitor;
 
 public class UnaryOperator extends Operator {
-    protected OperatorKind opKind;
-    protected Type resultType;
-
     public UnaryOperator(OperatorKind opKind, IRNode expression) {
-        super(opKind.priority);
-        this.opKind = opKind;
+        super(opKind, expression.getResultType());
         addChild(expression);
     }
 
@@ -49,8 +45,4 @@
     public boolean isPrefix() {
         return opKind.isPrefix;
     }
-
-    public String getOperatorText() {
-        return opKind.text;
-    }
 }
--- a/hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/VariableBase.java	Mon May 16 17:01:53 2016 +0300
+++ b/hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/VariableBase.java	Wed May 18 20:19:23 2016 +0300
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2005, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -23,7 +23,14 @@
 
 package jdk.test.lib.jittester;
 
-public interface VariableBase {
+public abstract class VariableBase extends IRNode {
+    private final VariableInfo variableInfo;
+    protected VariableBase(VariableInfo variableInfo) {
+        super(variableInfo.type);
+        this.variableInfo = variableInfo;
+    }
 
-    VariableInfo get();
+    public VariableInfo getVariableInfo() {
+        return variableInfo;
+    }
 }
--- a/hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/VariableDeclaration.java	Mon May 16 17:01:53 2016 +0300
+++ b/hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/VariableDeclaration.java	Wed May 18 20:19:23 2016 +0300
@@ -26,9 +26,10 @@
 import jdk.test.lib.jittester.visitors.Visitor;
 
 public class VariableDeclaration extends IRNode {
-    protected final VariableInfo variableInfo;
+    private final VariableInfo variableInfo;
 
     public VariableDeclaration(VariableInfo value) {
+        super(value.type);
         variableInfo = value;
     }
 
--- a/hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/VariableDeclarationBlock.java	Mon May 16 17:01:53 2016 +0300
+++ b/hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/VariableDeclarationBlock.java	Wed May 18 20:19:23 2016 +0300
@@ -24,10 +24,12 @@
 package jdk.test.lib.jittester;
 
 import java.util.ArrayList;
+
 import jdk.test.lib.jittester.visitors.Visitor;
 
 public class VariableDeclarationBlock extends IRNode {
-    public VariableDeclarationBlock(ArrayList<IRNode> content, int level) {
+    public VariableDeclarationBlock(ArrayList<? extends Declaration> content, int level) {
+        super(TypeList.VOID);
         addChildren(content);
         this.level = level;
     }
@@ -40,10 +42,6 @@
                 .sum();
     }
 
-    protected int size() {
-        return getChildren() != null ? getChildren().size() : 0;
-    }
-
     @Override
     public<T> T accept(Visitor<T> v) {
         return v.visit(this);
--- a/hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/VariableInfo.java	Mon May 16 17:01:53 2016 +0300
+++ b/hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/VariableInfo.java	Wed May 18 20:19:23 2016 +0300
@@ -55,4 +55,8 @@
     public Symbol deepCopy() {
         return new VariableInfo(this);
     }
+
+    public boolean isLocal() {
+        return (flags & LOCAL) != 0;
+    }
 }
--- a/hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/arrays/ArrayCreation.java	Mon May 16 17:01:53 2016 +0300
+++ b/hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/arrays/ArrayCreation.java	Wed May 18 20:19:23 2016 +0300
@@ -28,7 +28,6 @@
 import java.util.stream.Collectors;
 import jdk.test.lib.jittester.IRNode;
 import jdk.test.lib.jittester.Literal;
-import jdk.test.lib.jittester.Type;
 import jdk.test.lib.jittester.VariableDeclaration;
 import jdk.test.lib.jittester.types.TypeArray;
 import jdk.test.lib.jittester.visitors.Visitor;
@@ -39,6 +38,7 @@
     private final List<Byte> dims;
 
     public ArrayCreation(VariableDeclaration var, TypeArray array, ArrayList<IRNode> dimensionSizeExpressions) {
+        super(array);
         this.variable = var;
         this.array = array;
         addChildren(dimensionSizeExpressions);
@@ -55,8 +55,8 @@
         type.setDimentions(dims);
     }
 
-    public Type getArrayType() {
-        return array.type;
+    public TypeArray getArrayType() {
+        return array;
     }
 
     @Override
--- a/hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/arrays/ArrayElement.java	Mon May 16 17:01:53 2016 +0300
+++ b/hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/arrays/ArrayElement.java	Wed May 18 20:19:23 2016 +0300
@@ -25,10 +25,12 @@
 
 import java.util.ArrayList;
 import jdk.test.lib.jittester.IRNode;
+import jdk.test.lib.jittester.types.TypeArray;
 import jdk.test.lib.jittester.visitors.Visitor;
 
 public class ArrayElement extends IRNode {
     public ArrayElement(IRNode array, ArrayList<IRNode> dimensionExpressions) {
+        super(((TypeArray) array.getResultType()).type);
         addChild(array);
         addChildren(dimensionExpressions);
     }
--- a/hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/arrays/ArrayExtraction.java	Mon May 16 17:01:53 2016 +0300
+++ b/hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/arrays/ArrayExtraction.java	Wed May 18 20:19:23 2016 +0300
@@ -40,6 +40,7 @@
 public class ArrayExtraction extends IRNode {
     private final List<Byte> dims;
     public ArrayExtraction(IRNode array, ArrayList<IRNode> dimensionExpressions) {
+        super(array.getResultType());
         addChild(array);
         addChildren(dimensionExpressions);
         if (array instanceof ArrayCreation) {
@@ -56,7 +57,7 @@
             }
         } else if (array instanceof LocalVariable) {
             LocalVariable loc = (LocalVariable) array;
-            TypeArray type = (TypeArray) loc.get().type;
+            TypeArray type = (TypeArray) loc.getVariableInfo().type;
             dims = type.getDims();
             for (int i = dimensionExpressions.size(); i < type.dimensions; ++i) {
                 dims.add(type.getDims().get(i));
--- a/hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/classes/ClassDefinitionBlock.java	Mon May 16 17:01:53 2016 +0300
+++ b/hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/classes/ClassDefinitionBlock.java	Wed May 18 20:19:23 2016 +0300
@@ -25,10 +25,12 @@
 
 import java.util.ArrayList;
 import jdk.test.lib.jittester.IRNode;
+import jdk.test.lib.jittester.TypeList;
 import jdk.test.lib.jittester.visitors.Visitor;
 
 public class ClassDefinitionBlock extends IRNode {
     public ClassDefinitionBlock(ArrayList<IRNode> content, int level) {
+        super(TypeList.VOID);
         this.level = level;
         addChildren(content);
     }
--- a/hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/classes/Interface.java	Mon May 16 17:01:53 2016 +0300
+++ b/hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/classes/Interface.java	Wed May 18 20:19:23 2016 +0300
@@ -24,6 +24,7 @@
 package jdk.test.lib.jittester.classes;
 
 import jdk.test.lib.jittester.IRNode;
+import jdk.test.lib.jittester.TypeList;
 import jdk.test.lib.jittester.types.TypeKlass;
 import jdk.test.lib.jittester.visitors.Visitor;
 
@@ -32,6 +33,7 @@
     private TypeKlass parent = null;
 
     public Interface(TypeKlass parent, String name, int level, IRNode functionDeclaraionBlock) {
+        super(TypeList.find(functionDeclaraionBlock.getOwner().getName()));
         this.parent = parent;
         this.name = name;
         this.level = level;
--- a/hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/classes/Klass.java	Mon May 16 17:01:53 2016 +0300
+++ b/hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/classes/Klass.java	Wed May 18 20:19:23 2016 +0300
@@ -70,19 +70,21 @@
             IRNode functionDefinitions, IRNode abstractFunctionRedefinitions,
             IRNode overridenFunctionRedefitions, IRNode functionDeclarations,
             IRNode printVariablesBlock) {
+        super(thisKlass);
         this.thisKlass = thisKlass;
-        klass = thisKlass;
+        owner = thisKlass;
         this.parentKlass = parent;
         this.interfaces = interfaces;
         this.name = name;
         this.level = level;
-        addChild(variableDeclarations);
-        addChild(constructorDefinitions);
-        addChild(abstractFunctionRedefinitions);
-        addChild(overridenFunctionRedefitions);
-        addChild(functionDefinitions);
-        addChild(functionDeclarations);
-        addChild(printVariablesBlock);
+        resizeUpChildren(KlassPart.values().length);
+        setChild(KlassPart.DATA_MEMBERS.ordinal(), variableDeclarations);
+        setChild(KlassPart.CONSTRUCTORS.ordinal(), constructorDefinitions);
+        setChild(KlassPart.REDEFINED_FUNCTIONS.ordinal(), abstractFunctionRedefinitions);
+        setChild(KlassPart.OVERRIDEN_FUNCTIONS.ordinal(), overridenFunctionRedefitions);
+        setChild(KlassPart.MEMBER_FUNCTIONS.ordinal(), functionDefinitions);
+        setChild(KlassPart.MEMBER_FUNCTIONS_DECLARATIONS.ordinal(), functionDeclarations);
+        setChild(KlassPart.PRINT_VARIABLES.ordinal(), printVariablesBlock);
     }
 
     @Override
--- a/hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/classes/MainKlass.java	Mon May 16 17:01:53 2016 +0300
+++ b/hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/classes/MainKlass.java	Wed May 18 20:19:23 2016 +0300
@@ -40,6 +40,7 @@
 
     public MainKlass(String name, TypeKlass thisKlass, IRNode variableDeclarations,
             IRNode functionDefinitions, IRNode testFunction, IRNode printVariables) {
+        super(thisKlass);
         addChild(variableDeclarations);
         addChild(functionDefinitions);
         addChild(testFunction);
@@ -64,4 +65,8 @@
     public String getName() {
         return name;
     }
+
+    public TypeKlass getThisKlass() {
+        return thisKlass;
+    }
 }
--- a/hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/factories/ArgumentDeclarationFactory.java	Mon May 16 17:01:53 2016 +0300
+++ b/hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/factories/ArgumentDeclarationFactory.java	Wed May 18 20:19:23 2016 +0300
@@ -33,7 +33,7 @@
 import jdk.test.lib.jittester.types.TypeKlass;
 import jdk.test.lib.jittester.utils.PseudoRandom;
 
-class ArgumentDeclarationFactory extends Factory {
+class ArgumentDeclarationFactory extends Factory<ArgumentDeclaration> {
     private final int argumentNumber;
     private final TypeKlass ownerClass;
 
--- a/hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/factories/ArithmeticOperatorFactory.java	Mon May 16 17:01:53 2016 +0300
+++ b/hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/factories/ArithmeticOperatorFactory.java	Wed May 18 20:19:23 2016 +0300
@@ -23,15 +23,15 @@
 
 package jdk.test.lib.jittester.factories;
 
-import jdk.test.lib.jittester.IRNode;
+import jdk.test.lib.jittester.Operator;
 import jdk.test.lib.jittester.OperatorKind;
 import jdk.test.lib.jittester.ProductionFailedException;
 import jdk.test.lib.jittester.Rule;
 import jdk.test.lib.jittester.Type;
 import jdk.test.lib.jittester.types.TypeKlass;
 
-class ArithmeticOperatorFactory extends Factory {
-    private final Rule rule;
+class ArithmeticOperatorFactory extends Factory<Operator> {
+    private final Rule<Operator> rule;
 
     ArithmeticOperatorFactory(long complexityLimit, int operatorLimit, TypeKlass ownerClass,
             Type resultType, boolean exceptionSafe, boolean noconsts) throws ProductionFailedException {
@@ -42,7 +42,7 @@
                 .setResultType(resultType)
                 .setExceptionSafe(exceptionSafe)
                 .setNoConsts(noconsts);
-        rule = new Rule("arithmetic");
+        rule = new Rule<>("arithmetic");
         rule.add("add", builder.setOperatorKind(OperatorKind.ADD).getBinaryOperatorFactory());
         rule.add("sub", builder.setOperatorKind(OperatorKind.SUB).getBinaryOperatorFactory());
         rule.add("mul", builder.setOperatorKind(OperatorKind.MUL).getBinaryOperatorFactory());
@@ -55,7 +55,7 @@
     }
 
     @Override
-    public IRNode produce() throws ProductionFailedException {
+    public Operator produce() throws ProductionFailedException {
         return rule.produce();
     }
 }
--- a/hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/factories/ArrayCreationFactory.java	Mon May 16 17:01:53 2016 +0300
+++ b/hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/factories/ArrayCreationFactory.java	Wed May 18 20:19:23 2016 +0300
@@ -29,15 +29,14 @@
 import jdk.test.lib.jittester.ProductionFailedException;
 import jdk.test.lib.jittester.ProductionParams;
 import jdk.test.lib.jittester.Type;
+import jdk.test.lib.jittester.TypeList;
 import jdk.test.lib.jittester.VariableDeclaration;
 import jdk.test.lib.jittester.arrays.ArrayCreation;
 import jdk.test.lib.jittester.types.TypeArray;
 import jdk.test.lib.jittester.types.TypeKlass;
-import jdk.test.lib.jittester.types.TypeByte;
-import jdk.test.lib.jittester.types.TypeVoid;
 import jdk.test.lib.jittester.utils.PseudoRandom;
 
-class ArrayCreationFactory extends SafeFactory {
+class ArrayCreationFactory extends SafeFactory<ArrayCreation> {
     private final long complexityLimit;
     private final int operatorLimit;
     private final Type resultType;
@@ -56,16 +55,16 @@
     }
 
     @Override
-    protected IRNode sproduce() throws ProductionFailedException {
+    protected ArrayCreation sproduce() throws ProductionFailedException {
         if (resultType instanceof TypeArray) {
             TypeArray arrayResultType = (TypeArray) resultType;
-            if (arrayResultType.type.equals(new TypeVoid())) {
+            if (arrayResultType.type.equals(TypeList.VOID)) {
                 arrayResultType = arrayResultType.produce();
             }
             IRNodeBuilder builder = new IRNodeBuilder()
                     .setComplexityLimit(complexityLimit)
                     .setOwnerKlass(ownerClass)
-                    .setResultType(new TypeByte())
+                    .setResultType(TypeList.BYTE)
                     .setExceptionSafe(exceptionSafe)
                     .setNoConsts(noconsts);
             double chanceExpression = ProductionParams.chanceExpressionIndex.value() / 100;
@@ -77,14 +76,14 @@
                             .getExpressionFactory()
                             .produce());
                 } else {
-                    Literal dimension = (Literal)builder.getLiteralFactory().produce();
+                    Literal dimension = builder.getLiteralFactory().produce();
                     while (Integer.valueOf(dimension.getValue().toString()) < 1) {
-                        dimension = (Literal)builder.getLiteralFactory().produce();
+                        dimension = builder.getLiteralFactory().produce();
                     }
                     dims.add(dimension);
                 }
             }
-            VariableDeclaration var =  (VariableDeclaration) builder
+            VariableDeclaration var = builder
                     .setOwnerKlass(ownerClass)
                     .setResultType(arrayResultType)
                     .setIsLocal(true)
--- a/hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/factories/ArrayElementFactory.java	Mon May 16 17:01:53 2016 +0300
+++ b/hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/factories/ArrayElementFactory.java	Wed May 18 20:19:23 2016 +0300
@@ -29,15 +29,15 @@
 import jdk.test.lib.jittester.ProductionFailedException;
 import jdk.test.lib.jittester.ProductionParams;
 import jdk.test.lib.jittester.Type;
+import jdk.test.lib.jittester.TypeList;
 import jdk.test.lib.jittester.arrays.ArrayCreation;
 import jdk.test.lib.jittester.arrays.ArrayElement;
 import jdk.test.lib.jittester.arrays.ArrayExtraction;
 import jdk.test.lib.jittester.types.TypeArray;
 import jdk.test.lib.jittester.types.TypeKlass;
-import jdk.test.lib.jittester.types.TypeByte;
 import jdk.test.lib.jittester.utils.PseudoRandom;
 
-class ArrayElementFactory extends SafeFactory {
+class ArrayElementFactory extends SafeFactory<ArrayElement> {
     private final long complexityLimit;
     private final int operatorLimit;
     private final Type resultType;
@@ -56,7 +56,7 @@
     }
 
     @Override
-    protected IRNode sproduce() throws ProductionFailedException {
+    protected ArrayElement sproduce() throws ProductionFailedException {
         if (resultType instanceof TypeArray) {
             throw new ProductionFailedException();
         }
@@ -76,10 +76,10 @@
                 .setResultType(new TypeArray(resultType, dimensionsCount))
                 .getExpressionFactory()
                 .produce();
-        ExpressionFactory expressionFactory = builder
+        Factory<IRNode> expressionFactory = builder
                 .setComplexityLimit(complexityPerDimension)
                 .setOperatorLimit(operatorLimitPerDimension)
-                .setResultType(new TypeByte())
+                .setResultType(TypeList.BYTE)
                 .getExpressionFactory();
         double chanceExpression = ProductionParams.chanceExpressionIndex.value() / 100.;
         ArrayList<IRNode> perDimensionExpressions = new ArrayList<>(dimensionsCount);
@@ -96,7 +96,7 @@
                     if (i < arrayExtraction.getDimsNumber())
                         dimLimit = arrayExtraction.getDim(i);
                 }
-                perDimensionExpressions.add(new Literal(PseudoRandom.randomNotNegative(dimLimit), new TypeByte()));
+                perDimensionExpressions.add(new Literal((byte)PseudoRandom.randomNotNegative(dimLimit), TypeList.BYTE));
             }
         }
         return new ArrayElement(arrayReturningExpression, perDimensionExpressions);
--- a/hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/factories/ArrayExtractionFactory.java	Mon May 16 17:01:53 2016 +0300
+++ b/hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/factories/ArrayExtractionFactory.java	Wed May 18 20:19:23 2016 +0300
@@ -29,14 +29,14 @@
 import jdk.test.lib.jittester.ProductionFailedException;
 import jdk.test.lib.jittester.ProductionParams;
 import jdk.test.lib.jittester.Type;
+import jdk.test.lib.jittester.TypeList;
 import jdk.test.lib.jittester.arrays.ArrayCreation;
 import jdk.test.lib.jittester.arrays.ArrayExtraction;
 import jdk.test.lib.jittester.types.TypeArray;
 import jdk.test.lib.jittester.types.TypeKlass;
-import jdk.test.lib.jittester.types.TypeByte;
 import jdk.test.lib.jittester.utils.PseudoRandom;
 
-class ArrayExtractionFactory extends SafeFactory {
+class ArrayExtractionFactory extends SafeFactory<ArrayExtraction> {
     private final long complexityLimit;
     private final int operatorLimit;
     private final Type resultType;
@@ -55,7 +55,7 @@
     }
 
     @Override
-    public IRNode sproduce() throws ProductionFailedException {
+    public ArrayExtraction sproduce() throws ProductionFailedException {
         if (resultType instanceof TypeArray) {
             TypeArray arrayType = (TypeArray) resultType;
             int delta = PseudoRandom.randomNotZero(ProductionParams.dimensionsLimit.value()
@@ -79,7 +79,7 @@
                 double chanceExpression = ProductionParams.chanceExpressionIndex.value() / 100.;
                 for (int i = 0; i < delta; i++) {
                     if (PseudoRandom.randomBoolean(chanceExpression)) {
-                        perDimensionExpression.add(builder.setResultType(new TypeByte())
+                        perDimensionExpression.add(builder.setResultType(TypeList.BYTE)
                                 .setComplexityLimit(dimComplLimit)
                                 .setOperatorLimit(dimOpLimit)
                                 .getExpressionFactory()
@@ -94,7 +94,7 @@
                             if (i < arrayExtraction.getDimsNumber())
                                 dimLimit = arrayExtraction.getDim(i);
                         }
-                        perDimensionExpression.add(new Literal(PseudoRandom.randomNotNegative(dimLimit), new TypeByte()));
+                        perDimensionExpression.add(new Literal((byte)PseudoRandom.randomNotNegative(dimLimit), TypeList.BYTE));
                     }
                 }
                 return new ArrayExtraction(arrayReturningExpression, perDimensionExpression);
--- a/hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/factories/AssignmentOperatorFactory.java	Mon May 16 17:01:53 2016 +0300
+++ b/hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/factories/AssignmentOperatorFactory.java	Wed May 18 20:19:23 2016 +0300
@@ -24,7 +24,8 @@
 package jdk.test.lib.jittester.factories;
 
 import java.util.ArrayList;
-import jdk.test.lib.jittester.IRNode;
+
+import jdk.test.lib.jittester.Operator;
 import jdk.test.lib.jittester.OperatorKind;
 import jdk.test.lib.jittester.ProductionFailedException;
 import jdk.test.lib.jittester.Rule;
@@ -34,7 +35,7 @@
 import jdk.test.lib.jittester.types.TypeKlass;
 import jdk.test.lib.jittester.utils.PseudoRandom;
 
-class AssignmentOperatorFactory extends Factory {
+class AssignmentOperatorFactory extends Factory<Operator> {
     private final int operatorLimit;
     private final long complexityLimit;
     private final Type resultType;
@@ -42,8 +43,8 @@
     private final boolean noconsts;
     private final TypeKlass ownerClass;
 
-    private Rule fillRule(Type resultType) throws ProductionFailedException {
-        Rule rule = new Rule("assignment");
+    private Rule<Operator> fillRule(Type resultType) throws ProductionFailedException {
+        Rule<Operator> rule = new Rule<>("assignment");
         IRNodeBuilder builder = new IRNodeBuilder()
                 .setComplexityLimit(complexityLimit)
                 .setOperatorLimit(operatorLimit)
@@ -84,14 +85,14 @@
     }
 
     @Override
-    public IRNode produce() throws ProductionFailedException {
+    public Operator produce() throws ProductionFailedException {
         if (resultType == null) { // if no result type is given - choose any.
             ArrayList<Type> allTypes = new ArrayList<>(TypeList.getAll());
             PseudoRandom.shuffle(allTypes);
             for (Type type : allTypes) {
                 SymbolTable.push();
                 try {
-                    IRNode result =  fillRule(type).produce();
+                    Operator result =  fillRule(type).produce();
                     SymbolTable.merge();
                     return result;
                 } catch (ProductionFailedException e) {
--- a/hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/factories/AssignmentOperatorImplFactory.java	Mon May 16 17:01:53 2016 +0300
+++ b/hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/factories/AssignmentOperatorImplFactory.java	Wed May 18 20:19:23 2016 +0300
@@ -31,8 +31,8 @@
 import jdk.test.lib.jittester.Rule;
 import jdk.test.lib.jittester.Type;
 import jdk.test.lib.jittester.TypeList;
+import jdk.test.lib.jittester.VariableBase;
 import jdk.test.lib.jittester.utils.TypeUtil;
-import jdk.test.lib.jittester.VariableBase;
 import jdk.test.lib.jittester.VariableInfo;
 import jdk.test.lib.jittester.types.TypeKlass;
 import jdk.test.lib.jittester.utils.PseudoRandom;
@@ -49,7 +49,7 @@
     }
 
     @Override
-    protected Pair<Type, Type> generateTypes() throws ProductionFailedException {
+    protected Pair<Type, Type> generateTypes() {
         return new Pair<>(resultType, PseudoRandom.randomElement(
                 TypeUtil.getImplicitlyCastable(TypeList.getAll(), resultType)));
     }
@@ -68,23 +68,22 @@
                 .setOperatorLimit(leftOperatorLimit)
                 .setResultType(leftOperandType)
                 .setIsConstant(false);
-        Rule rule = new Rule("assignment");
+        Rule<VariableBase> rule = new Rule<>("assignment");
         rule.add("initialized_nonconst_var", builder.setIsInitialized(true).getVariableFactory());
         rule.add("uninitialized_nonconst_var", builder.setIsInitialized(false).getVariableFactory());
-        IRNode leftOperandValue = rule.produce();
+        VariableBase leftOperandValue = rule.produce();
         IRNode rightOperandValue = builder.setComplexityLimit(rightComplexityLimit)
                 .setOperatorLimit(rightOperatorLimit)
                 .setResultType(rightOperandType)
                 .getExpressionFactory()
                 .produce();
         try {
-            VariableBase v = (VariableBase) leftOperandValue;
-            if ((v.get().flags & VariableInfo.INITIALIZED) == 0) {
-                v.get().flags |= VariableInfo.INITIALIZED;
+            if ((leftOperandValue.getVariableInfo().flags & VariableInfo.INITIALIZED) == 0) {
+                leftOperandValue.getVariableInfo().flags |= VariableInfo.INITIALIZED;
             }
         } catch (Exception e) {
             throw new ProductionFailedException(e.getMessage());
         }
-        return new BinaryOperator(opKind, leftOperandValue, rightOperandValue);
+        return new BinaryOperator(opKind, resultType, leftOperandValue, rightOperandValue);
     }
 }
--- a/hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/factories/BinaryArithmeticOperatorFactory.java	Mon May 16 17:01:53 2016 +0300
+++ b/hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/factories/BinaryArithmeticOperatorFactory.java	Wed May 18 20:19:23 2016 +0300
@@ -30,7 +30,6 @@
 import jdk.test.lib.jittester.Type;
 import jdk.test.lib.jittester.TypeList;
 import jdk.test.lib.jittester.utils.TypeUtil;
-import jdk.test.lib.jittester.types.TypeInt;
 import jdk.test.lib.jittester.types.TypeKlass;
 import jdk.test.lib.jittester.utils.PseudoRandom;
 
@@ -47,18 +46,18 @@
         // arithmetic for built-in types less capacious than "int" is not supported.
         if (TypeList.isBuiltIn(resultType)) {
             BuiltInType builtInType = (BuiltInType) resultType;
-            return builtInType.equals(new TypeInt()) || builtInType.isMoreCapaciousThan(new TypeInt());
+            return builtInType.equals(TypeList.INT) || builtInType.isMoreCapaciousThan(TypeList.INT);
         } else {
             return false;
         }
     }
 
     @Override
-    protected Pair<Type, Type> generateTypes() throws ProductionFailedException {
+    protected Pair<Type, Type> generateTypes() {
         Collection<Type> castableFromResultType = TypeUtil.getImplicitlyCastable(TypeList.getBuiltIn(), resultType);
         // built-in types less capacious than int are automatically casted to int in arithmetic.
         final Type leftType = PseudoRandom.randomElement(castableFromResultType);
-        final Type rightType = resultType.equals(new TypeInt()) ?
+        final Type rightType = resultType.equals(TypeList.INT) ?
                 PseudoRandom.randomElement(castableFromResultType) : resultType;
         //TODO: is there sense to swap them randomly as it was done in original code?
         return PseudoRandom.randomBoolean() ? new Pair<>(leftType, rightType) : new Pair<>(rightType, leftType);
--- a/hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/factories/BinaryBitwiseOperatorFactory.java	Mon May 16 17:01:53 2016 +0300
+++ b/hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/factories/BinaryBitwiseOperatorFactory.java	Wed May 18 20:19:23 2016 +0300
@@ -29,10 +29,7 @@
 import jdk.test.lib.jittester.Type;
 import jdk.test.lib.jittester.TypeList;
 import jdk.test.lib.jittester.utils.TypeUtil;
-import jdk.test.lib.jittester.types.TypeBoolean;
-import jdk.test.lib.jittester.types.TypeInt;
 import jdk.test.lib.jittester.types.TypeKlass;
-import jdk.test.lib.jittester.types.TypeLong;
 import jdk.test.lib.jittester.utils.PseudoRandom;
 
 import java.util.Collection;
@@ -45,15 +42,15 @@
 
     @Override
     protected boolean isApplicable(Type resultType) {
-        return resultType.equals(new TypeInt()) || resultType.equals(new TypeLong()) || resultType.equals(new TypeBoolean());
+        return resultType.equals(TypeList.INT) || resultType.equals(TypeList.LONG) || resultType.equals(TypeList.BOOLEAN);
     }
 
     @Override
-    protected Pair<Type, Type> generateTypes() throws ProductionFailedException {
+    protected Pair<Type, Type> generateTypes() {
         Collection<Type> castableFromResult = TypeUtil.getImplicitlyCastable(TypeList.getBuiltIn(), resultType);
         // built-in types less capacious than int are automatically casted to int in arithmetic.
         final Type leftType = PseudoRandom.randomElement(castableFromResult);
-        final Type rightType = resultType.equals(new TypeInt()) ? PseudoRandom.randomElement(castableFromResult) : resultType;
+        final Type rightType = resultType.equals(TypeList.INT) ? PseudoRandom.randomElement(castableFromResult) : resultType;
         //TODO: is there sense to swap them randomly as it was done in original code?
         return PseudoRandom.randomBoolean() ? new Pair<>(leftType, rightType) : new Pair<>(rightType, leftType);
     }
--- a/hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/factories/BinaryComparisonOperatorFactory.java	Mon May 16 17:01:53 2016 +0300
+++ b/hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/factories/BinaryComparisonOperatorFactory.java	Wed May 18 20:19:23 2016 +0300
@@ -28,7 +28,6 @@
 import jdk.test.lib.jittester.ProductionFailedException;
 import jdk.test.lib.jittester.Type;
 import jdk.test.lib.jittester.TypeList;
-import jdk.test.lib.jittester.types.TypeBoolean;
 import jdk.test.lib.jittester.types.TypeKlass;
 import jdk.test.lib.jittester.utils.PseudoRandom;
 
@@ -43,13 +42,13 @@
 
     @Override
     protected boolean isApplicable(Type resultType) {
-        return resultType.equals(new TypeBoolean());
+        return resultType.equals(TypeList.BOOLEAN);
     }
 
     @Override
-    protected Pair<Type, Type> generateTypes() throws ProductionFailedException {
+    protected Pair<Type, Type> generateTypes() {
         final List<Type> builtInExceptBoolean = new ArrayList<>(TypeList.getBuiltIn());
-        builtInExceptBoolean.remove(new TypeBoolean());
+        builtInExceptBoolean.remove(TypeList.BOOLEAN);
         return new Pair<>(PseudoRandom.randomElement(builtInExceptBoolean),
                 PseudoRandom.randomElement(builtInExceptBoolean));
     }
--- a/hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/factories/BinaryEqualityOperatorFactory.java	Mon May 16 17:01:53 2016 +0300
+++ b/hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/factories/BinaryEqualityOperatorFactory.java	Wed May 18 20:19:23 2016 +0300
@@ -28,7 +28,6 @@
 import jdk.test.lib.jittester.ProductionFailedException;
 import jdk.test.lib.jittester.Type;
 import jdk.test.lib.jittester.TypeList;
-import jdk.test.lib.jittester.types.TypeBoolean;
 import jdk.test.lib.jittester.types.TypeKlass;
 import jdk.test.lib.jittester.utils.PseudoRandom;
 
@@ -43,13 +42,13 @@
 
     @Override
     protected boolean isApplicable(Type resultType) {
-        return resultType.equals(new TypeBoolean());
+        return resultType.equals(TypeList.BOOLEAN);
     }
 
     @Override
-    protected Pair<Type, Type> generateTypes() throws ProductionFailedException {
+    protected Pair<Type, Type> generateTypes() {
         final List<Type> builtInExceptBoolean = new ArrayList<>(TypeList.getBuiltIn());
-        builtInExceptBoolean.remove(new TypeBoolean());
+        builtInExceptBoolean.remove(TypeList.BOOLEAN);
         return new Pair<>(PseudoRandom.randomElement(builtInExceptBoolean), PseudoRandom.randomElement(builtInExceptBoolean));
     }
 }
--- a/hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/factories/BinaryLogicOperatorFactory.java	Mon May 16 17:01:53 2016 +0300
+++ b/hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/factories/BinaryLogicOperatorFactory.java	Wed May 18 20:19:23 2016 +0300
@@ -30,7 +30,7 @@
 import jdk.test.lib.jittester.ProductionFailedException;
 import jdk.test.lib.jittester.SymbolTable;
 import jdk.test.lib.jittester.Type;
-import jdk.test.lib.jittester.types.TypeBoolean;
+import jdk.test.lib.jittester.TypeList;
 import jdk.test.lib.jittester.types.TypeKlass;
 import jdk.test.lib.jittester.utils.PseudoRandom;
 
@@ -42,11 +42,11 @@
 
     @Override
     protected boolean isApplicable(Type resultType) {
-        return resultType.equals(new TypeBoolean());
+        return resultType.equals(TypeList.BOOLEAN);
     }
 
     @Override
-    protected Pair<Type, Type> generateTypes() throws ProductionFailedException {
+    protected Pair<Type, Type> generateTypes() {
         return new Pair<>(resultType, resultType);
     }
 
@@ -81,6 +81,6 @@
         } finally {
             SymbolTable.pop();
         }
-        return new BinaryOperator(opKind, leftOperand, rightOperand);
+        return new BinaryOperator(opKind, resultType, leftOperand, rightOperand);
     }
 }
--- a/hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/factories/BinaryOperatorFactory.java	Mon May 16 17:01:53 2016 +0300
+++ b/hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/factories/BinaryOperatorFactory.java	Wed May 18 20:19:23 2016 +0300
@@ -33,7 +33,7 @@
 import jdk.test.lib.jittester.types.TypeKlass;
 import jdk.test.lib.jittester.utils.PseudoRandom;
 
-abstract class BinaryOperatorFactory extends OperatorFactory {
+abstract class BinaryOperatorFactory extends OperatorFactory<BinaryOperator> {
     protected final OperatorKind opKind;
     protected final Type resultType;
     protected final Type ownerClass;
@@ -48,7 +48,7 @@
 
     protected abstract boolean isApplicable(Type resultType);
 
-    protected abstract Pair<Type, Type> generateTypes() throws ProductionFailedException;
+    protected abstract Pair<Type, Type> generateTypes();
 
     protected BinaryOperator generateProduction(Type leftType, Type rightType) throws ProductionFailedException {
         int leftOpLimit = (int) (PseudoRandom.random() * (operatorLimit - 1));
@@ -72,11 +72,11 @@
                 .setResultType(rightType)
                 .getExpressionFactory()
                 .produce();
-        return new BinaryOperator(opKind, leftExpr, rightExpr);
+        return new BinaryOperator(opKind, resultType, leftExpr, rightExpr);
     }
 
     @Override
-    public final IRNode produce() throws ProductionFailedException {
+    public final BinaryOperator produce() throws ProductionFailedException {
         if (!isApplicable(resultType)) {
             //avoid implicit use of resultType.toString()
             throw new ProductionFailedException("Type " + resultType.getName() + " is not applicable by " + getClass().getName());
@@ -91,7 +91,7 @@
 
         try {
             SymbolTable.push();
-            IRNode p = generateProduction(types.first, types.second);
+            BinaryOperator p = generateProduction(types.first, types.second);
             SymbolTable.merge();
             return p;
         } catch (ProductionFailedException e) {
--- a/hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/factories/BinaryShiftOperatorFactory.java	Mon May 16 17:01:53 2016 +0300
+++ b/hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/factories/BinaryShiftOperatorFactory.java	Wed May 18 20:19:23 2016 +0300
@@ -28,9 +28,7 @@
 import jdk.test.lib.jittester.ProductionFailedException;
 import jdk.test.lib.jittester.Type;
 import jdk.test.lib.jittester.TypeList;
-import jdk.test.lib.jittester.types.TypeInt;
 import jdk.test.lib.jittester.types.TypeKlass;
-import jdk.test.lib.jittester.types.TypeLong;
 import jdk.test.lib.jittester.utils.PseudoRandom;
 import jdk.test.lib.jittester.utils.TypeUtil;
 
@@ -42,13 +40,13 @@
 
     @Override
     protected boolean isApplicable(Type resultType) {
-        return resultType.equals(new TypeInt()) || resultType.equals(new TypeLong());
+        return resultType.equals(TypeList.INT) || resultType.equals(TypeList.LONG);
     }
 
     @Override
-    protected Pair<Type, Type> generateTypes() throws ProductionFailedException {
-        Type leftType = resultType.equals(new TypeInt()) ? PseudoRandom.randomElement(TypeUtil.getImplicitlyCastable(TypeList.getBuiltInInt(), resultType)) : resultType;
-        Type rightType = PseudoRandom.randomElement(TypeUtil.getImplicitlyCastable(TypeList.getBuiltInInt(), new TypeLong()));
+    protected Pair<Type, Type> generateTypes() {
+        Type leftType = resultType.equals(TypeList.INT) ? PseudoRandom.randomElement(TypeUtil.getImplicitlyCastable(TypeList.getBuiltInInt(), resultType)) : resultType;
+        Type rightType = PseudoRandom.randomElement(TypeUtil.getImplicitlyCastable(TypeList.getBuiltInInt(), TypeList.LONG));
         return new Pair<>(leftType, rightType);
     }
 }
--- a/hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/factories/BinaryStringPlusFactory.java	Mon May 16 17:01:53 2016 +0300
+++ b/hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/factories/BinaryStringPlusFactory.java	Wed May 18 20:19:23 2016 +0300
@@ -38,11 +38,11 @@
 
     @Override
     protected boolean isApplicable(Type resultType) {
-        return resultType.equals(TypeList.find("java.lang.String"));
-        }
+        return resultType.equals(TypeList.STRING);
+    }
 
     @Override
-    protected Pair<Type, Type> generateTypes() throws ProductionFailedException {
+    protected Pair<Type, Type> generateTypes() {
         return new Pair<>(resultType, resultType);
     }
 }
--- a/hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/factories/BitwiseInversionOperatorFactory.java	Mon May 16 17:01:53 2016 +0300
+++ b/hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/factories/BitwiseInversionOperatorFactory.java	Wed May 18 20:19:23 2016 +0300
@@ -23,7 +23,6 @@
 
 package jdk.test.lib.jittester.factories;
 
-import jdk.test.lib.jittester.IRNode;
 import jdk.test.lib.jittester.OperatorKind;
 import jdk.test.lib.jittester.ProductionFailedException;
 import jdk.test.lib.jittester.Type;
@@ -31,8 +30,6 @@
 import jdk.test.lib.jittester.utils.TypeUtil;
 import jdk.test.lib.jittester.UnaryOperator;
 import jdk.test.lib.jittester.types.TypeKlass;
-import jdk.test.lib.jittester.types.TypeInt;
-import jdk.test.lib.jittester.types.TypeLong;
 import jdk.test.lib.jittester.utils.PseudoRandom;
 
 class BitwiseInversionOperatorFactory extends UnaryOperatorFactory {
@@ -43,12 +40,12 @@
 
     @Override
     protected boolean isApplicable(Type resultType) {
-        return resultType.equals(new TypeInt()) || resultType.equals(new TypeLong());
+        return resultType.equals(TypeList.INT) || resultType.equals(TypeList.LONG);
     }
 
     @Override
-    protected Type generateType() throws ProductionFailedException {
-        if (resultType.equals(new TypeInt())) {
+    protected Type generateType() {
+        if (resultType.equals(TypeList.INT)) {
             return PseudoRandom.randomElement(TypeUtil.getImplicitlyCastable(TypeList.getBuiltIn(), resultType));
         } else {
             return resultType;
@@ -56,7 +53,7 @@
     }
 
     @Override
-    protected IRNode generateProduction(Type resultType) throws ProductionFailedException {
+    protected UnaryOperator generateProduction(Type resultType) throws ProductionFailedException {
         return new UnaryOperator(opKind, new IRNodeBuilder().setComplexityLimit(complexityLimit - 1)
                 .setOperatorLimit(operatorLimit - 1)
                 .setOwnerKlass((TypeKlass) ownerClass)
--- a/hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/factories/BitwiseOperatorFactory.java	Mon May 16 17:01:53 2016 +0300
+++ b/hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/factories/BitwiseOperatorFactory.java	Wed May 18 20:19:23 2016 +0300
@@ -23,15 +23,15 @@
 
 package jdk.test.lib.jittester.factories;
 
-import jdk.test.lib.jittester.IRNode;
+import jdk.test.lib.jittester.Operator;
 import jdk.test.lib.jittester.OperatorKind;
 import jdk.test.lib.jittester.ProductionFailedException;
 import jdk.test.lib.jittester.Rule;
 import jdk.test.lib.jittester.Type;
 import jdk.test.lib.jittester.types.TypeKlass;
 
-class BitwiseOperatorFactory extends Factory {
-    private final Rule rule;
+class BitwiseOperatorFactory extends Factory<Operator> {
+    private final Rule<Operator> rule;
 
     BitwiseOperatorFactory(long complexityLimit, int operatorLimit, TypeKlass ownerClass,
             Type resultType, boolean exceptionSafe, boolean noconsts) throws ProductionFailedException {
@@ -42,7 +42,7 @@
                 .setResultType(resultType)
                 .setExceptionSafe(exceptionSafe)
                 .setNoConsts(noconsts);
-        rule = new Rule("bitwise");
+        rule = new Rule<>("bitwise");
         rule.add("and", builder.setOperatorKind(OperatorKind.BIT_AND).getBinaryOperatorFactory());
         rule.add("or", builder.setOperatorKind(OperatorKind.BIT_OR).getBinaryOperatorFactory());
         rule.add("xor", builder.setOperatorKind(OperatorKind.BIT_XOR).getBinaryOperatorFactory());
@@ -53,7 +53,7 @@
     }
 
     @Override
-    public IRNode produce() throws ProductionFailedException {
+    public Operator produce() throws ProductionFailedException {
         return rule.produce();
     }
 }
--- a/hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/factories/BlockFactory.java	Mon May 16 17:01:53 2016 +0300
+++ b/hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/factories/BlockFactory.java	Wed May 18 20:19:23 2016 +0300
@@ -38,13 +38,12 @@
 import jdk.test.lib.jittester.loops.For;
 import jdk.test.lib.jittester.loops.While;
 import jdk.test.lib.jittester.types.TypeKlass;
-import jdk.test.lib.jittester.types.TypeVoid;
 import jdk.test.lib.jittester.utils.PseudoRandom;
 
 import java.util.ArrayList;
 import java.util.List;
 
-class BlockFactory extends Factory {
+class BlockFactory extends Factory<Block> {
     private final Type returnType;
     private final long complexityLimit;
     private final int statementLimit;
@@ -74,7 +73,7 @@
     }
 
     @Override
-    public IRNode produce() throws ProductionFailedException {
+    public Block produce() throws ProductionFailedException {
         if (statementLimit > 0 && complexityLimit > 0) {
             List<IRNode> content = new ArrayList<>();
             int slimit = PseudoRandom.randomNotZero(statementLimit);
@@ -89,12 +88,12 @@
                     .setCanHaveContinues(canHaveContinues)
                     .setExceptionSafe(false)
                     .setNoConsts(false);
-            Rule rule;
+            Rule<IRNode> rule;
             SymbolTable.push();
             for (int i = 0; i < slimit && climit > 0; ) {
                 int subLimit = (int) (PseudoRandom.random() * (slimit - i - 1));
                 builder.setComplexityLimit((long) (PseudoRandom.random() * climit));
-                rule = new Rule("block");
+                rule = new Rule<>("block");
                 rule.add("statement", builder.getStatementFactory(), 5);
                 if (!ProductionParams.disableVarsInBlock.value()) {
                     rule.add("decl", builder.setIsLocal(true).getDeclarationFactory());
@@ -131,14 +130,14 @@
                 }
             }
             // Ok, if the block can end with break and continue. Generate the appropriate productions.
-            rule = new Rule("block_ending");
+            rule = new Rule<>("block_ending");
             if (canHaveBreaks && !subBlock) {
                 rule.add("break", builder.getBreakFactory());
             }
             if (canHaveContinues && !subBlock) {
                 rule.add("continue", builder.getContinueFactory());
             }
-            if (canHaveReturn && !subBlock && !returnType.equals(new TypeVoid())) {
+            if (canHaveReturn && !subBlock && !returnType.equals(TypeList.VOID)) {
                 rule.add("return", builder.setComplexityLimit(climit).getReturnFactory());
             }
             if (canHaveThrow && !subBlock) {
@@ -166,7 +165,7 @@
         throw new ProductionFailedException();
     }
 
-    private void addControlFlowDeviation(Rule rule, IRNodeBuilder builder) {
+    private void addControlFlowDeviation(Rule<IRNode> rule, IRNodeBuilder builder) {
         if (!ProductionParams.disableIf.value()) {
             rule.add("if", builder.getIfFactory());
         }
--- a/hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/factories/BreakFactory.java	Mon May 16 17:01:53 2016 +0300
+++ b/hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/factories/BreakFactory.java	Wed May 18 20:19:23 2016 +0300
@@ -24,12 +24,11 @@
 package jdk.test.lib.jittester.factories;
 
 import jdk.test.lib.jittester.Break;
-import jdk.test.lib.jittester.IRNode;
 import jdk.test.lib.jittester.ProductionFailedException;
 
-class BreakFactory extends Factory {
+class BreakFactory extends Factory<Break> {
     @Override
-    public IRNode produce() throws ProductionFailedException {
+    public Break produce() throws ProductionFailedException {
         return new Break();
     }
 }
--- a/hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/factories/CastOperatorFactory.java	Mon May 16 17:01:53 2016 +0300
+++ b/hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/factories/CastOperatorFactory.java	Wed May 18 20:19:23 2016 +0300
@@ -33,7 +33,7 @@
 import jdk.test.lib.jittester.types.TypeKlass;
 import jdk.test.lib.jittester.utils.PseudoRandom;
 
-class CastOperatorFactory extends OperatorFactory {
+class CastOperatorFactory extends OperatorFactory<CastOperator> {
     private final Type resultType;
     private final Type ownerClass;
 
@@ -45,12 +45,12 @@
     }
 
     @Override
-    public IRNode produce() throws ProductionFailedException {
+    public CastOperator produce() throws ProductionFailedException {
         ArrayList<Type> argType = new ArrayList<>(TypeList.getAll());
         PseudoRandom.shuffle(argType);
         for (Type type : argType) {
             try {
-                ExpressionFactory expressionFactory = new IRNodeBuilder()
+                Factory<IRNode> expressionFactory = new IRNodeBuilder()
                         .setComplexityLimit(complexityLimit - 1)
                         .setOperatorLimit(operatorLimit - 1)
                         .setOwnerKlass((TypeKlass) ownerClass)
@@ -59,14 +59,11 @@
                         .setResultType(type)
                         .getExpressionFactory();
                 SymbolTable.push();
-                if (type.equals(resultType)) {
-                    IRNode expr = expressionFactory.produce();
-                    SymbolTable.merge();
-                    return expr;
-                } else if ((!exceptionSafe || exceptionSafe && !(type instanceof TypeKlass))
-                        && type.canExplicitlyCastTo(resultType)) {
+                if (type.equals(resultType) ||
+                        ((!exceptionSafe || exceptionSafe && !(type instanceof TypeKlass))
+                            && type.canExplicitlyCastTo(resultType))) {
                     // In safe mode we cannot explicitly cast an object, because it may throw.
-                    IRNode castOperator = new CastOperator(resultType, expressionFactory.produce());
+                    CastOperator castOperator = new CastOperator(resultType, expressionFactory.produce());
                     SymbolTable.merge();
                     return castOperator;
                 }
--- a/hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/factories/ClassDefinitionBlockFactory.java	Mon May 16 17:01:53 2016 +0300
+++ b/hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/factories/ClassDefinitionBlockFactory.java	Wed May 18 20:19:23 2016 +0300
@@ -38,7 +38,7 @@
 import jdk.test.lib.jittester.types.TypeKlass;
 import jdk.test.lib.jittester.utils.PseudoRandom;
 
-class ClassDefinitionBlockFactory extends Factory {
+class ClassDefinitionBlockFactory extends Factory<ClassDefinitionBlock> {
     private final String prefix;
     private final long complexityLimit;
     private final int classesLimit;
@@ -62,7 +62,7 @@
     }
 
     @Override
-    public IRNode produce() throws ProductionFailedException {
+    public ClassDefinitionBlock produce() throws ProductionFailedException {
         ArrayList<IRNode> content = new ArrayList<>();
         int limit = (int) Math.ceil(PseudoRandom.random() * classesLimit);
         if (limit > 0) {
@@ -74,9 +74,8 @@
                     .setComplexityLimit(classCompl);
             for (int i = 0; i < limit; i++) {
                 try {
-                    Rule rule = new Rule("class");
+                    Rule<IRNode> rule = new Rule<>("class");
                     rule.add("basic_class", builder.setName(prefix + "_Class_" + i)
-                            .setPrinterName(prefix + ".Printer")
                             .setMemberFunctionsLimit(memberFunctionsLimit)
                             .getKlassFactory());
                     if (!ProductionParams.disableInterfaces.value()) {
@@ -110,13 +109,12 @@
             IRNode randomChild = childs.get(0);
             List<IRNode> leaves = randomChild.getStackableLeaves();
             if (!leaves.isEmpty()) {
-                PseudoRandom.shuffle(leaves);
-                Block randomLeaf = (Block) leaves.get(0);
-                TypeKlass klass = (TypeKlass) randomChild.getKlass();
+                Block randomLeaf = (Block) leaves.get(PseudoRandom.randomNotNegative(leaves.size()));
+                TypeKlass owner = randomChild.getOwner();
                 int newLevel = randomLeaf.getLevel() + 1;
-                Type retType = randomLeaf.getReturnType();
+                Type retType = randomLeaf.getResultType();
                 IRNodeBuilder b = new IRNodeBuilder()
-                        .setOwnerKlass(klass)
+                        .setOwnerKlass(owner)
                         .setResultType(retType)
                         .setComplexityLimit(complexityLimit)
                         .setStatementLimit(statementLimit)
@@ -137,7 +135,7 @@
                 .filter(c -> c instanceof Klass && c.countDepth() > maxDepth)
                 .collect(Collectors.toList());
         for (IRNode ch : childs) {
-            List<IRNode> leaves = null;
+            List<IRNode> leaves;
             do {
                 long depth = Math.max(ch.countDepth(), maxDepth + 1);
                 leaves = ch.getDeviantBlocks(depth);
--- a/hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/factories/CompoundArithmeticAssignmentOperatorFactory.java	Mon May 16 17:01:53 2016 +0300
+++ b/hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/factories/CompoundArithmeticAssignmentOperatorFactory.java	Wed May 18 20:19:23 2016 +0300
@@ -30,8 +30,8 @@
 import jdk.test.lib.jittester.ProductionFailedException;
 import jdk.test.lib.jittester.Type;
 import jdk.test.lib.jittester.TypeList;
+import jdk.test.lib.jittester.VariableBase;
 import jdk.test.lib.jittester.utils.TypeUtil;
-import jdk.test.lib.jittester.types.TypeBoolean;
 import jdk.test.lib.jittester.types.TypeKlass;
 import jdk.test.lib.jittester.utils.PseudoRandom;
 
@@ -43,11 +43,11 @@
 
     @Override
     protected boolean isApplicable(Type resultType) {
-        return TypeList.isBuiltIn(resultType) && !resultType.equals(new TypeBoolean());
+        return TypeList.isBuiltIn(resultType) && !resultType.equals(TypeList.BOOLEAN);
     }
 
     @Override
-    protected Pair<Type, Type> generateTypes() throws ProductionFailedException {
+    protected Pair<Type, Type> generateTypes() {
         return new Pair<>(resultType, PseudoRandom.randomElement(
                 TypeUtil.getExplicitlyCastable(TypeList.getBuiltIn(), resultType)));
     }
@@ -66,13 +66,13 @@
                 .setResultType(rightType)
                 .getExpressionFactory()
                 .produce();
-        IRNode leftExpr = builder.setComplexityLimit(leftComplexityLimit)
+        VariableBase leftExpr = builder.setComplexityLimit(leftComplexityLimit)
                 .setOperatorLimit(leftOperatorLimit)
                 .setResultType(leftType)
                 .setIsConstant(false)
                 .setIsInitialized(true)
                 .getVariableFactory()
                 .produce();
-        return new BinaryOperator(opKind, leftExpr, rightExpr);
+        return new BinaryOperator(opKind, resultType, leftExpr, rightExpr);
     }
 }
--- a/hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/factories/CompoundBitwiseAssignmentOperatorFactory.java	Mon May 16 17:01:53 2016 +0300
+++ b/hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/factories/CompoundBitwiseAssignmentOperatorFactory.java	Wed May 18 20:19:23 2016 +0300
@@ -46,7 +46,7 @@
     }
 
     @Override
-    protected Pair<Type, Type> generateTypes() throws ProductionFailedException {
+    protected Pair<Type, Type> generateTypes() {
         return new Pair<>(resultType, PseudoRandom.randomElement(TypeUtil.getExplicitlyCastable(TypeList.getBuiltInInt(), resultType)));
     }
 
@@ -71,6 +71,6 @@
                 .setResultType(rightType)
                 .getExpressionFactory()
                 .produce();
-        return new BinaryOperator(opKind, leftExpr, rightExpr);
+        return new BinaryOperator(opKind, resultType, leftExpr, rightExpr);
     }
 }
--- a/hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/factories/CompoundShiftAssignmentOperatorFactory.java	Mon May 16 17:01:53 2016 +0300
+++ b/hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/factories/CompoundShiftAssignmentOperatorFactory.java	Wed May 18 20:19:23 2016 +0300
@@ -32,7 +32,6 @@
 import jdk.test.lib.jittester.TypeList;
 import jdk.test.lib.jittester.utils.TypeUtil;
 import jdk.test.lib.jittester.types.TypeKlass;
-import jdk.test.lib.jittester.types.TypeBoolean;
 import jdk.test.lib.jittester.utils.PseudoRandom;
 
 class CompoundShiftAssignmentOperatorFactory extends BinaryOperatorFactory {
@@ -43,11 +42,11 @@
 
     @Override
     protected boolean isApplicable(Type resultType) {
-        return TypeList.isBuiltInInt(resultType) && !resultType.equals(new TypeBoolean());
+        return TypeList.isBuiltInInt(resultType) && !resultType.equals(TypeList.BOOLEAN);
     }
 
     @Override
-    protected Pair<Type, Type> generateTypes() throws ProductionFailedException {
+    protected Pair<Type, Type> generateTypes() {
         return new Pair<>(resultType, PseudoRandom.randomElement(
                 TypeUtil.getExplicitlyCastable(TypeList.getBuiltInInt(), resultType)));
     }
@@ -73,6 +72,6 @@
                 .setResultType(rightType)
                 .getExpressionFactory()
                 .produce();
-        return new BinaryOperator(opKind, leftExpr, rightExpr);
+        return new BinaryOperator(opKind, resultType, leftExpr, rightExpr);
     }
 }
--- a/hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/factories/ConstructorDefinitionBlockFactory.java	Mon May 16 17:01:53 2016 +0300
+++ b/hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/factories/ConstructorDefinitionBlockFactory.java	Wed May 18 20:19:23 2016 +0300
@@ -31,7 +31,7 @@
 import jdk.test.lib.jittester.types.TypeKlass;
 import jdk.test.lib.jittester.utils.PseudoRandom;
 
-class ConstructorDefinitionBlockFactory extends Factory {
+class ConstructorDefinitionBlockFactory extends Factory<ConstructorDefinitionBlock> {
     private final long complexityLimit;
     private final int statementLimit;
     private final int operatorLimit;
@@ -53,7 +53,7 @@
     }
 
     @Override
-    public IRNode produce() throws ProductionFailedException {
+    public ConstructorDefinitionBlock produce() throws ProductionFailedException {
         IRNodeBuilder builder = new IRNodeBuilder()
                 .setOwnerKlass(ownerClass)
                 .setStatementLimit(statementLimit)
--- a/hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/factories/ConstructorDefinitionFactory.java	Mon May 16 17:01:53 2016 +0300
+++ b/hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/factories/ConstructorDefinitionFactory.java	Wed May 18 20:19:23 2016 +0300
@@ -28,15 +28,15 @@
 import jdk.test.lib.jittester.ProductionFailedException;
 import jdk.test.lib.jittester.Symbol;
 import jdk.test.lib.jittester.SymbolTable;
+import jdk.test.lib.jittester.TypeList;
 import jdk.test.lib.jittester.VariableInfo;
 import jdk.test.lib.jittester.functions.ArgumentDeclaration;
 import jdk.test.lib.jittester.functions.ConstructorDefinition;
 import jdk.test.lib.jittester.functions.FunctionInfo;
 import jdk.test.lib.jittester.types.TypeKlass;
-import jdk.test.lib.jittester.types.TypeVoid;
 import jdk.test.lib.jittester.utils.PseudoRandom;
 
-class ConstructorDefinitionFactory extends Factory {
+class ConstructorDefinitionFactory extends Factory<ConstructorDefinition> {
     private final long complexityLimit;
     private final int statementLimit;
     private final int operatorLimit;
@@ -55,7 +55,7 @@
     }
 
     @Override
-    public IRNode produce() throws ProductionFailedException {
+    public ConstructorDefinition produce() throws ProductionFailedException {
         int argNumber = (int) (PseudoRandom.random() * memberFunctionsArgLimit);
         ArrayList<VariableInfo> argumentsInfo = new ArrayList<>(argNumber);
         ArrayList<ArgumentDeclaration> argumentsDeclaration = new ArrayList<>(argNumber);
@@ -90,7 +90,7 @@
             }
             long blockComplLimit = (long) (PseudoRandom.random() * complexityLimit);
             try {
-                body = builder.setResultType(new TypeVoid())
+                body = builder.setResultType(TypeList.VOID)
                         .setComplexityLimit(blockComplLimit)
                         .setStatementLimit(statementLimit)
                         .setOperatorLimit(operatorLimit)
--- a/hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/factories/ContinueFactory.java	Mon May 16 17:01:53 2016 +0300
+++ b/hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/factories/ContinueFactory.java	Wed May 18 20:19:23 2016 +0300
@@ -24,12 +24,11 @@
 package jdk.test.lib.jittester.factories;
 
 import jdk.test.lib.jittester.Continue;
-import jdk.test.lib.jittester.IRNode;
 import jdk.test.lib.jittester.ProductionFailedException;
 
-class ContinueFactory extends Factory {
+class ContinueFactory extends Factory<Continue> {
     @Override
-    public IRNode produce() throws ProductionFailedException {
+    public Continue produce() throws ProductionFailedException {
         return new Continue();
     }
 }
--- a/hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/factories/CounterInitializerFactory.java	Mon May 16 17:01:53 2016 +0300
+++ b/hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/factories/CounterInitializerFactory.java	Wed May 18 20:19:23 2016 +0300
@@ -24,20 +24,20 @@
 package jdk.test.lib.jittester.factories;
 
 import java.util.List;
+
 import jdk.test.lib.jittester.IRNode;
 import jdk.test.lib.jittester.LiteralInitializer;
 import jdk.test.lib.jittester.ProductionFailedException;
 import jdk.test.lib.jittester.SymbolTable;
 import jdk.test.lib.jittester.Type;
 import jdk.test.lib.jittester.TypeList;
+import jdk.test.lib.jittester.VariableInfo;
 import jdk.test.lib.jittester.utils.TypeUtil;
-import jdk.test.lib.jittester.VariableInfo;
 import jdk.test.lib.jittester.loops.CounterInitializer;
 import jdk.test.lib.jittester.types.TypeKlass;
-import jdk.test.lib.jittester.types.TypeInt;
 import jdk.test.lib.jittester.utils.PseudoRandom;
 
-class CounterInitializerFactory extends SafeFactory {
+class CounterInitializerFactory extends SafeFactory<CounterInitializer> {
     private final int counterValue;
     private final TypeKlass ownerClass;
 
@@ -47,9 +47,9 @@
     }
 
     @Override
-    protected IRNode sproduce() throws ProductionFailedException {
-        List<Type> types = TypeUtil.getMoreCapaciousThan(TypeList.getBuiltIn(), new TypeInt());
-        types.add(new TypeInt());
+    protected CounterInitializer sproduce() throws ProductionFailedException {
+        List<Type> types = TypeUtil.getMoreCapaciousThan(TypeList.getBuiltIn(), TypeList.INT);
+        types.add(TypeList.INT);
         final Type selectedType = PseudoRandom.randomElement(types);
         IRNode init = new LiteralInitializer(counterValue, selectedType);
         String resultName = "var_" + SymbolTable.getNextVariableNumber();
--- a/hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/factories/CounterManipulatorFactory.java	Mon May 16 17:01:53 2016 +0300
+++ b/hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/factories/CounterManipulatorFactory.java	Wed May 18 20:19:23 2016 +0300
@@ -27,10 +27,11 @@
 import jdk.test.lib.jittester.LocalVariable;
 import jdk.test.lib.jittester.OperatorKind;
 import jdk.test.lib.jittester.ProductionFailedException;
+import jdk.test.lib.jittester.Statement;
 import jdk.test.lib.jittester.UnaryOperator;
 import jdk.test.lib.jittester.loops.CounterManipulator;
 
-class CounterManipulatorFactory extends Factory {
+class CounterManipulatorFactory extends Factory<CounterManipulator> {
     private final LocalVariable counter;
 
     CounterManipulatorFactory(LocalVariable counter) {
@@ -38,9 +39,9 @@
     }
 
     @Override
-    public IRNode produce() throws ProductionFailedException {
+    public CounterManipulator produce() throws ProductionFailedException {
         // We'll keep it simple for the time being..
         IRNode manipulator = new UnaryOperator(OperatorKind.POST_DEC, counter);
-        return new CounterManipulator(manipulator);
+        return new CounterManipulator(new Statement(manipulator, false));
     }
 }
--- a/hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/factories/DeclarationFactory.java	Mon May 16 17:01:53 2016 +0300
+++ b/hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/factories/DeclarationFactory.java	Wed May 18 20:19:23 2016 +0300
@@ -31,7 +31,7 @@
 import jdk.test.lib.jittester.TypeList;
 import jdk.test.lib.jittester.types.TypeKlass;
 
-class DeclarationFactory extends Factory {
+class DeclarationFactory extends Factory<Declaration> {
     private final int operatorLimit;
     private final long complexityLimit;
     private final boolean isLocal;
@@ -48,29 +48,42 @@
     }
 
     @Override
-    public IRNode produce() throws ProductionFailedException {
-        Rule rule = new Rule("declaration");
+    public Declaration produce() throws ProductionFailedException {
+        Rule<IRNode> rule = new Rule<>("declaration");
         IRNodeBuilder builder = new IRNodeBuilder().setOwnerKlass(ownerClass)
-                .setResultType(TypeList.getVoid())
+                .setResultType(TypeList.VOID)
                 .setIsLocal(isLocal)
                 .setComplexityLimit(complexityLimit)
                 .setOperatorLimit(operatorLimit)
                 .setIsLocal(isLocal)
                 .setExceptionSafe(exceptionSafe);
-        rule.add("decl", builder.setIsStatic(false).getVariableDeclarationFactory());
-        rule.add("decl_and_init", builder.setIsConstant(false)
-                .setIsStatic(false).getVariableInitializationFactory());
+        rule.add("decl", builder
+                .setIsStatic(false)
+                .getVariableDeclarationFactory());
+        rule.add("decl_and_init", builder
+                .setIsConstant(false)
+                .setIsStatic(false)
+                .getVariableInitializationFactory());
         if (!ProductionParams.disableFinalVariables.value()) {
-            rule.add("const_decl_and_init", builder.setIsConstant(true)
-                    .setIsStatic(false).getVariableInitializationFactory());
+            rule.add("const_decl_and_init", builder
+                    .setIsConstant(true)
+                    .setIsStatic(false)
+                    .getVariableInitializationFactory());
         }
         if (!isLocal && !ProductionParams.disableStatic.value()) {
-            rule.add("static_decl", builder.setIsStatic(true).getVariableDeclarationFactory());
-            rule.add("static_decl_and_init", builder.setIsConstant(false)
-                    .setIsStatic(true).getVariableInitializationFactory());
+            rule.add("static_decl", builder
+                    .setIsConstant(false)
+                    .setIsStatic(true)
+                    .getVariableDeclarationFactory());
+            rule.add("static_decl_and_init", builder
+                    .setIsConstant(false)
+                    .setIsStatic(true)
+                    .getVariableInitializationFactory());
             if (!ProductionParams.disableFinalVariables.value()) {
-                rule.add("static_const_decl_and_init", builder.setIsConstant(true)
-                        .setIsStatic(true).getVariableInitializationFactory());
+                rule.add("static_const_decl_and_init", builder
+                        .setIsConstant(true)
+                        .setIsStatic(true)
+                        .getVariableInitializationFactory());
             }
         }
         return new Declaration(rule.produce());
--- a/hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/factories/DoWhileFactory.java	Mon May 16 17:01:53 2016 +0300
+++ b/hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/factories/DoWhileFactory.java	Wed May 18 20:19:23 2016 +0300
@@ -23,21 +23,21 @@
 
 package jdk.test.lib.jittester.factories;
 
-import jdk.test.lib.jittester.IRNode;
-import jdk.test.lib.jittester.Initialization;
+import jdk.test.lib.jittester.Block;
 import jdk.test.lib.jittester.Literal;
 import jdk.test.lib.jittester.LocalVariable;
-import jdk.test.lib.jittester.Nothing;
 import jdk.test.lib.jittester.ProductionFailedException;
 import jdk.test.lib.jittester.SymbolTable;
 import jdk.test.lib.jittester.Type;
+import jdk.test.lib.jittester.TypeList;
 import jdk.test.lib.jittester.loops.DoWhile;
 import jdk.test.lib.jittester.loops.Loop;
 import jdk.test.lib.jittester.types.TypeKlass;
-import jdk.test.lib.jittester.types.TypeInt;
 import jdk.test.lib.jittester.utils.PseudoRandom;
 
-class DoWhileFactory extends SafeFactory {
+import java.util.LinkedList;
+
+class DoWhileFactory extends SafeFactory<DoWhile> {
     private final Loop loop;
     private final long complexityLimit;
     private final int statementLimit;
@@ -62,7 +62,8 @@
     }
 
     @Override
-    protected IRNode sproduce() throws ProductionFailedException {
+    protected DoWhile sproduce() throws ProductionFailedException {
+        Block emptyBlock = new Block(ownerClass, returnType, new LinkedList<>(), level - 1);
         if (statementLimit > 0 && complexityLimit > 0) {
             long complexity = complexityLimit;
             // Loop header parameters
@@ -89,7 +90,7 @@
                     .setResultType(returnType)
                     .setOperatorLimit(operatorLimit);
             loop.initialization = builder.getCounterInitializerFactory(0).produce();
-            IRNode header;
+            Block header;
             try {
                 header = builder.setComplexityLimit(headerComplLimit)
                         .setStatementLimit(headerStatementLimit)
@@ -101,17 +102,17 @@
                         .getBlockFactory()
                         .produce();
             } catch (ProductionFailedException e) {
-                header = new Nothing();
+                header = emptyBlock;
             }
             // getChildren().set(DoWhile.DoWhilePart.HEADER.ordinal(), header);
-            LocalVariable counter = new LocalVariable(((Initialization) loop.initialization).get());
-            Literal limiter = new Literal(Integer.valueOf((int) thisLoopIterLimit), new TypeInt());
+            LocalVariable counter = new LocalVariable(loop.initialization.getVariableInfo());
+            Literal limiter = new Literal((int) thisLoopIterLimit, TypeList.INT);
             loop.condition = builder.setComplexityLimit(condComplLimit)
                     .setLocalVariable(counter)
                     .getLoopingConditionFactory(limiter)
                     .produce();
             SymbolTable.push();
-            IRNode body1;
+            Block body1;
             try {
                 body1 = builder.setComplexityLimit(body1ComplLimit)
                         .setStatementLimit(body1StatementLimit)
@@ -123,11 +124,11 @@
                         .getBlockFactory()
                         .produce();
             } catch (ProductionFailedException e) {
-                body1 = new Nothing();
+                body1 = emptyBlock;
             }
             // getChildren().set(DoWhile.DoWhilePart.BODY1.ordinal(), body1);
             loop.manipulator = builder.setLocalVariable(counter).getCounterManipulatorFactory().produce();
-            IRNode body2;
+            Block body2;
             try {
                 body2 = builder.setComplexityLimit(body2ComplLimit)
                         .setStatementLimit(body2StatementLimit)
@@ -139,7 +140,7 @@
                         .getBlockFactory()
                         .produce();
             } catch (ProductionFailedException e) {
-                body2 = new Nothing();
+                body2 = emptyBlock;
             }
             // getChildren().set(DoWhile.DoWhilePart.BODY2.ordinal(), body2);
             SymbolTable.pop();
--- a/hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/factories/ExpressionFactory.java	Mon May 16 17:01:53 2016 +0300
+++ b/hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/factories/ExpressionFactory.java	Wed May 18 20:19:23 2016 +0300
@@ -29,11 +29,11 @@
 import jdk.test.lib.jittester.ProductionLimiter;
 import jdk.test.lib.jittester.ProductionParams;
 import jdk.test.lib.jittester.Rule;
-import jdk.test.lib.jittester.Type;;
+import jdk.test.lib.jittester.Type;
 import jdk.test.lib.jittester.types.TypeKlass;
 
-class ExpressionFactory extends SafeFactory {
-    private final Rule rule;
+class ExpressionFactory extends SafeFactory<IRNode> {
+    private final Rule<IRNode> rule;
 
     ExpressionFactory(long complexityLimit, int operatorLimit, TypeKlass ownerClass, Type resultType,
             boolean exceptionSafe, boolean noconsts) throws ProductionFailedException {
@@ -44,7 +44,7 @@
                 .setResultType(resultType)
                 .setExceptionSafe(exceptionSafe)
                 .setNoConsts(noconsts);
-        rule = new Rule("expression");
+        rule = new Rule<>("expression");
         if (!noconsts) {
             rule.add("literal", builder.getLiteralFactory());
             rule.add("constant", builder.setIsConstant(true)
--- a/hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/factories/Factory.java	Mon May 16 17:01:53 2016 +0300
+++ b/hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/factories/Factory.java	Wed May 18 20:19:23 2016 +0300
@@ -26,6 +26,6 @@
 import jdk.test.lib.jittester.IRNode;
 import jdk.test.lib.jittester.ProductionFailedException;
 
-public abstract class Factory {
-    public abstract IRNode produce() throws ProductionFailedException;
+public abstract class Factory<T extends IRNode> {
+    public abstract T produce() throws ProductionFailedException;
 }
--- a/hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/factories/ForFactory.java	Mon May 16 17:01:53 2016 +0300
+++ b/hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/factories/ForFactory.java	Wed May 18 20:19:23 2016 +0300
@@ -23,22 +23,25 @@
 
 package jdk.test.lib.jittester.factories;
 
+import jdk.test.lib.jittester.Block;
 import jdk.test.lib.jittester.IRNode;
-import jdk.test.lib.jittester.Initialization;
 import jdk.test.lib.jittester.Literal;
 import jdk.test.lib.jittester.LocalVariable;
 import jdk.test.lib.jittester.Nothing;
 import jdk.test.lib.jittester.ProductionFailedException;
 import jdk.test.lib.jittester.Rule;
+import jdk.test.lib.jittester.Statement;
 import jdk.test.lib.jittester.SymbolTable;
 import jdk.test.lib.jittester.Type;
+import jdk.test.lib.jittester.TypeList;
 import jdk.test.lib.jittester.loops.For;
 import jdk.test.lib.jittester.loops.Loop;
 import jdk.test.lib.jittester.types.TypeKlass;
-import jdk.test.lib.jittester.types.TypeInt;
 import jdk.test.lib.jittester.utils.PseudoRandom;
 
-class ForFactory extends SafeFactory {
+import java.util.LinkedList;
+
+class ForFactory extends SafeFactory<For> {
     private final Loop loop;
     private final long complexityLimit;
     private final int statementLimit;
@@ -46,7 +49,6 @@
     private final TypeKlass ownerClass;
     private final Type returnType;
     private final int level;
-    private long thisLoopIterLimit = 0;
     private final boolean canHaveReturn;
 
     ForFactory(TypeKlass ownerClass, Type returnType, long complexityLimit, int statementLimit,
@@ -62,7 +64,8 @@
     }
 
     @Override
-    protected IRNode sproduce() throws ProductionFailedException {
+    protected For sproduce() throws ProductionFailedException {
+        Block emptyBlock = new Block(ownerClass, returnType, new LinkedList<>(), level - 1);
         if (statementLimit <= 0 || complexityLimit <= 0) {
             throw new ProductionFailedException();
         }
@@ -81,7 +84,7 @@
         long statement1ComplLimit = (long) (0.005 * complexity * PseudoRandom.random());
         complexity -= statement1ComplLimit;
         // Loop body parameters
-        thisLoopIterLimit = (long) (0.0001 * complexity * PseudoRandom.random());
+        long thisLoopIterLimit = (long) (0.0001 * complexity * PseudoRandom.random());
         if (thisLoopIterLimit > Integer.MAX_VALUE || thisLoopIterLimit == 0) {
             throw new ProductionFailedException();
         }
@@ -100,7 +103,7 @@
         int body3StatementLimit = PseudoRandom.randomNotZero((int) (statementLimit / 4.0));
         // Production
         loop.initialization = builder.getCounterInitializerFactory(0).produce();
-        IRNode header;
+        Block header;
         try {
             header = builder.setComplexityLimit(headerComplLimit)
                     .setStatementLimit(headerStatementLimit)
@@ -112,12 +115,12 @@
                     .getBlockFactory()
                     .produce();
         } catch (ProductionFailedException e) {
-            header = new Nothing();
+            header = emptyBlock;
         }
         SymbolTable.push();
         IRNode statement1;
         try {
-            Rule rule = new Rule("statement1");
+            Rule<IRNode> rule = new Rule<>("statement1");
             builder.setComplexityLimit(statement1ComplLimit);
             rule.add("assignment", builder.getAssignmentOperatorFactory());
             rule.add("function", builder.getFunctionFactory(), 0.1);
@@ -129,20 +132,20 @@
         } catch (ProductionFailedException e) {
             statement1 = new Nothing();
         }
-        LocalVariable counter = new LocalVariable(((Initialization) loop.initialization).get());
-        Literal limiter = new Literal(Integer.valueOf((int) thisLoopIterLimit), new TypeInt());
+        LocalVariable counter = new LocalVariable(loop.initialization.getVariableInfo());
+        Literal limiter = new Literal((int) thisLoopIterLimit, TypeList.INT);
         loop.condition = builder.setComplexityLimit(condComplLimit)
                 .setLocalVariable(counter)
                 .getLoopingConditionFactory(limiter)
                 .produce();
         IRNode statement2;
         try {
-            statement2 =  builder.setComplexityLimit(statement2ComplLimit)
+            statement2 = builder.setComplexityLimit(statement2ComplLimit)
                     .getAssignmentOperatorFactory().produce();
         } catch (ProductionFailedException e) {
             statement2 = new Nothing();
         }
-        IRNode body1;
+        Block body1;
         try {
             body1 = builder.setComplexityLimit(body1ComplLimit)
                     .setStatementLimit(body1StatementLimit)
@@ -154,10 +157,10 @@
                     .getBlockFactory()
                     .produce();
         } catch (ProductionFailedException e) {
-            body1 = new Nothing();
+            body1 = emptyBlock;
         }
         loop.manipulator = builder.setLocalVariable(counter).getCounterManipulatorFactory().produce();
-        IRNode body2;
+        Block body2;
         try {
             body2 = builder.setComplexityLimit(body2ComplLimit)
                     .setStatementLimit(body2StatementLimit)
@@ -169,9 +172,9 @@
                     .getBlockFactory()
                     .produce();
         } catch (ProductionFailedException e) {
-            body2 = new Nothing();
+            body2 = emptyBlock;
         }
-        IRNode body3;
+        Block body3;
         try {
             body3 = builder.setComplexityLimit(body3ComplLimit)
                     .setStatementLimit(body3StatementLimit)
@@ -183,10 +186,13 @@
                     .getBlockFactory()
                     .produce();
         } catch (ProductionFailedException e) {
-            body3 = new Nothing();
+            body3 = emptyBlock;
         }
         SymbolTable.pop();
-        return new For(level, loop, thisLoopIterLimit, header, statement1, statement2, body1,
+        return new For(level, loop, thisLoopIterLimit, header,
+                new Statement(statement1, false),
+                new Statement(statement2, false),
+                body1,
                 body2, body3);
     }
 }
--- a/hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/factories/FunctionDeclarationBlockFactory.java	Mon May 16 17:01:53 2016 +0300
+++ b/hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/factories/FunctionDeclarationBlockFactory.java	Wed May 18 20:19:23 2016 +0300
@@ -31,7 +31,7 @@
 import jdk.test.lib.jittester.types.TypeKlass;
 import jdk.test.lib.jittester.utils.PseudoRandom;
 
-class FunctionDeclarationBlockFactory extends Factory {
+class FunctionDeclarationBlockFactory extends Factory<FunctionDeclarationBlock> {
     private final int memberFunctionsLimit;
     private final int memberFunctionsArgLimit;
     private final int level;
@@ -46,7 +46,7 @@
     }
 
     @Override
-    public IRNode produce() throws ProductionFailedException {
+    public FunctionDeclarationBlock produce() throws ProductionFailedException {
         ArrayList<IRNode> content = new ArrayList<>();
         int memFunLimit = (int) (PseudoRandom.random() * memberFunctionsLimit);
         if (memFunLimit > 0) {
--- a/hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/factories/FunctionDeclarationFactory.java	Mon May 16 17:01:53 2016 +0300
+++ b/hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/factories/FunctionDeclarationFactory.java	Wed May 18 20:19:23 2016 +0300
@@ -27,7 +27,6 @@
 import java.util.Collection;
 import java.util.List;
 
-import jdk.test.lib.jittester.IRNode;
 import jdk.test.lib.jittester.ProductionFailedException;
 import jdk.test.lib.jittester.Symbol;
 import jdk.test.lib.jittester.SymbolTable;
@@ -39,10 +38,9 @@
 import jdk.test.lib.jittester.functions.FunctionDefinition;
 import jdk.test.lib.jittester.functions.FunctionInfo;
 import jdk.test.lib.jittester.types.TypeKlass;
-import jdk.test.lib.jittester.types.TypeVoid;
 import jdk.test.lib.jittester.utils.PseudoRandom;
 
-class FunctionDeclarationFactory extends Factory {
+class FunctionDeclarationFactory extends Factory<FunctionDeclaration> {
     private final Type resultType;
     private final TypeKlass ownerClass;
     private final String name;
@@ -59,11 +57,11 @@
     }
 
     @Override
-    public IRNode produce() throws ProductionFailedException {
+    public FunctionDeclaration produce() throws ProductionFailedException {
         Type resType = resultType;
         if (resType == null) {
             List<Type> types = new ArrayList<>(TypeList.getAll());
-            types.add(new TypeVoid());
+            types.add(TypeList.VOID);
             resType = PseudoRandom.randomElement(types);
         }
         int argNumber = (int) (PseudoRandom.random() * memberFunctionsArgLimit);
--- a/hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/factories/FunctionDefinitionBlockFactory.java	Mon May 16 17:01:53 2016 +0300
+++ b/hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/factories/FunctionDefinitionBlockFactory.java	Wed May 18 20:19:23 2016 +0300
@@ -35,7 +35,7 @@
 import jdk.test.lib.jittester.types.TypeKlass;
 import jdk.test.lib.jittester.utils.PseudoRandom;
 
-class FunctionDefinitionBlockFactory extends Factory {
+class FunctionDefinitionBlockFactory extends Factory<FunctionDefinitionBlock> {
     private final long complexityLimit;
     private final int statementLimit;
     private final int operatorLimit;
@@ -59,7 +59,7 @@
     }
 
     @Override
-    public IRNode produce() throws ProductionFailedException {
+    public FunctionDefinitionBlock produce() throws ProductionFailedException {
         ArrayList<IRNode> content = new ArrayList<>();
         int memFunLimit = (int) (PseudoRandom.random() * memberFunctionsLimit);
         if (memFunLimit > 0) {
--- a/hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/factories/FunctionDefinitionFactory.java	Mon May 16 17:01:53 2016 +0300
+++ b/hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/factories/FunctionDefinitionFactory.java	Wed May 18 20:19:23 2016 +0300
@@ -28,6 +28,7 @@
 import java.util.List;
 
 import jdk.test.lib.jittester.IRNode;
+import jdk.test.lib.jittester.Nothing;
 import jdk.test.lib.jittester.ProductionFailedException;
 import jdk.test.lib.jittester.Symbol;
 import jdk.test.lib.jittester.SymbolTable;
@@ -37,11 +38,11 @@
 import jdk.test.lib.jittester.functions.ArgumentDeclaration;
 import jdk.test.lib.jittester.functions.FunctionDefinition;
 import jdk.test.lib.jittester.functions.FunctionInfo;
+import jdk.test.lib.jittester.functions.Return;
 import jdk.test.lib.jittester.types.TypeKlass;
-import jdk.test.lib.jittester.types.TypeVoid;
 import jdk.test.lib.jittester.utils.PseudoRandom;
 
-class FunctionDefinitionFactory extends Factory {
+class FunctionDefinitionFactory extends Factory<FunctionDefinition> {
     private final Type resultType;
     private final String name;
     private final long complexityLimit;
@@ -67,11 +68,11 @@
     }
 
     @Override
-    public IRNode produce() throws ProductionFailedException {
+    public FunctionDefinition produce() throws ProductionFailedException {
         Type resType = resultType;
         if (resType == null) {
             List<Type> types = new ArrayList<>(TypeList.getAll());
-            types.add(new TypeVoid());
+            types.add(TypeList.VOID);
             resType = PseudoRandom.randomElement(types);
         }
         int argNumber = (int) (PseudoRandom.random() * memberFunctionsArgLimit);
@@ -86,7 +87,7 @@
         ArrayList<ArgumentDeclaration> argumentsDeclaration = new ArrayList<>(argNumber);
         SymbolTable.push();
         IRNode body;
-        IRNode returnNode;
+        Return returnNode;
         FunctionInfo functionInfo;
         try {
             IRNodeBuilder builder = new IRNodeBuilder().setArgumentType(ownerClass);
@@ -127,13 +128,13 @@
                     .setCanHaveReturn(true)
                     .getBlockFactory()
                     .produce();
-            if (!resType.equals(new TypeVoid())) {
+            if (!resType.equals(TypeList.VOID)) {
                 returnNode = builder.setComplexityLimit(complexityLimit - blockComplLimit)
                         .setExceptionSafe(false)
                         .getReturnFactory()
                         .produce();
             } else {
-                returnNode = null;
+                returnNode = new Return(new Nothing());
             }
         } finally {
             SymbolTable.pop();
--- a/hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/factories/FunctionFactory.java	Mon May 16 17:01:53 2016 +0300
+++ b/hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/factories/FunctionFactory.java	Wed May 18 20:19:23 2016 +0300
@@ -37,7 +37,7 @@
 import jdk.test.lib.jittester.types.TypeKlass;
 import jdk.test.lib.jittester.utils.PseudoRandom;
 
-class FunctionFactory extends SafeFactory {
+class FunctionFactory extends SafeFactory<Function> {
     private final FunctionInfo functionInfo;
     private final int operatorLimit;
     private final long complexityLimit;
@@ -55,7 +55,7 @@
     }
 
     @Override
-    protected IRNode sproduce() throws ProductionFailedException {
+    protected Function sproduce() throws ProductionFailedException {
         // Currently no function is exception-safe
         if (exceptionSafe) {
             throw new ProductionFailedException();
@@ -72,7 +72,7 @@
             for (Symbol function : allFunctions) {
                 FunctionInfo functionInfo = (FunctionInfo) function;
                 // Don't try to construct abstract classes.
-                if (functionInfo.isConstructor() && functionInfo.klass.isAbstract()) {
+                if (functionInfo.isConstructor() && functionInfo.owner.isAbstract()) {
                     continue;
                 }
                 // We don't call methods from the same class which are not final, because if we
@@ -94,7 +94,7 @@
 
                 // If it's a local call.. or it's a call using some variable to some object of some type in our hierarchy
                 boolean inHierarchy = false;
-                if (ownerClass.equals(functionInfo.klass) || (inHierarchy = klassHierarchy.contains(functionInfo.klass))) {
+                if (ownerClass.equals(functionInfo.owner) || (inHierarchy = klassHierarchy.contains(functionInfo.owner))) {
                     if ((functionInfo.flags & FunctionInfo.FINAL) == 0 && (functionInfo.flags & FunctionInfo.STATIC) == 0
                             && (functionInfo.flags & FunctionInfo.NONRECURSIVE) == 0) {
                         continue;
@@ -121,7 +121,7 @@
                             // If there are function with a same name and same number of args,
                             // then disable usage of foldable expressions in the args.
                             boolean noconsts = false;
-                            Collection<Symbol> allFuncsInKlass = SymbolTable.getAllCombined(functionInfo.klass,
+                            Collection<Symbol> allFuncsInKlass = SymbolTable.getAllCombined(functionInfo.owner,
                                     FunctionInfo.class);
                             for (Symbol s2 : allFuncsInKlass) {
                                 FunctionInfo i2 = (FunctionInfo) function;
--- a/hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/factories/FunctionRedefinitionBlockFactory.java	Mon May 16 17:01:53 2016 +0300
+++ b/hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/factories/FunctionRedefinitionBlockFactory.java	Wed May 18 20:19:23 2016 +0300
@@ -34,7 +34,7 @@
 import jdk.test.lib.jittester.functions.FunctionRedefinitionBlock;
 import jdk.test.lib.jittester.types.TypeKlass;
 
-class FunctionRedefinitionBlockFactory extends Factory {
+class FunctionRedefinitionBlockFactory extends Factory<FunctionRedefinitionBlock> {
     private final int statementLimit;
     private final int operatorLimit;
     private final long complexityLimit;
@@ -53,7 +53,7 @@
     }
 
     @Override
-    public IRNode produce() throws ProductionFailedException {
+    public FunctionRedefinitionBlock produce() throws ProductionFailedException {
         ArrayList<IRNode> content = new ArrayList<>();
         if (functionSet.size() > 0) {
             long funcComplexity = complexityLimit / functionSet.size();
--- a/hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/factories/FunctionRedefinitionFactory.java	Mon May 16 17:01:53 2016 +0300
+++ b/hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/factories/FunctionRedefinitionFactory.java	Wed May 18 20:19:23 2016 +0300
@@ -25,17 +25,19 @@
 
 import java.util.ArrayList;
 import jdk.test.lib.jittester.IRNode;
+import jdk.test.lib.jittester.Nothing;
 import jdk.test.lib.jittester.ProductionFailedException;
 import jdk.test.lib.jittester.SymbolTable;
+import jdk.test.lib.jittester.TypeList;
 import jdk.test.lib.jittester.VariableInfo;
 import jdk.test.lib.jittester.functions.ArgumentDeclaration;
-import jdk.test.lib.jittester.functions.FunctionDefinition;
 import jdk.test.lib.jittester.functions.FunctionInfo;
+import jdk.test.lib.jittester.functions.FunctionRedefinition;
+import jdk.test.lib.jittester.functions.Return;
 import jdk.test.lib.jittester.types.TypeKlass;
-import jdk.test.lib.jittester.types.TypeVoid;
 import jdk.test.lib.jittester.utils.PseudoRandom;
 
-class FunctionRedefinitionFactory extends Factory {
+class FunctionRedefinitionFactory extends Factory<FunctionRedefinition> {
     private final long complexityLimit;
     private final int statementLimit;
     private final int operatorLimit;
@@ -47,14 +49,14 @@
             long complexityLimit, int statementLimit, int operatorLimit, int level, int flags) {
         this.ownerClass = ownerClass;
         this.functionInfo = new FunctionInfo(functionInfo); // do deep coping
-        functionInfo.klass = ownerClass; // important! fix klass!
+        functionInfo.owner = ownerClass; // important! fix klass!
         if ((functionInfo.flags & FunctionInfo.STATIC) == 0) {
             functionInfo.argTypes.get(0).type = ownerClass; // redefine type of this
         }
         functionInfo.flags = flags; // apply new flags.
         // fix the type of class where the args would be declared
         for (VariableInfo varInfo : functionInfo.argTypes) {
-            varInfo.klass = ownerClass;
+            varInfo.owner = ownerClass;
         }
         this.complexityLimit = complexityLimit;
         this.statementLimit = statementLimit;
@@ -63,14 +65,14 @@
     }
 
     @Override
-    public IRNode produce() throws ProductionFailedException {
+    public FunctionRedefinition produce() throws ProductionFailedException {
         ArrayList<VariableInfo> argumentsInfo = functionInfo.argTypes;
         SymbolTable.push();
         IRNode body;
-        IRNode returnNode;
+        Return returnNode;
         ArrayList<ArgumentDeclaration> argumentsDeclaration;
         try {
-            if ((functionInfo.flags & FunctionInfo.STATIC) > 0) {
+            if (functionInfo.isStatic()) {
                 argumentsDeclaration = new ArrayList<>(argumentsInfo.size());
                 for (VariableInfo varInfo : argumentsInfo) {
                     argumentsDeclaration.add(new ArgumentDeclaration(varInfo));
@@ -98,13 +100,13 @@
                     .setCanHaveReturn(true)
                     .getBlockFactory()
                     .produce();
-            if (!functionInfo.type.equals(new TypeVoid())) {
+            if (!functionInfo.type.equals(TypeList.VOID)) {
                 returnNode = builder.setComplexityLimit(complexityLimit - blockComplLimit)
                         .setExceptionSafe(false)
                         .getReturnFactory()
                         .produce();
             } else {
-                returnNode = null;
+                returnNode = new Return(new Nothing());
             }
         } catch (ProductionFailedException e) {
             SymbolTable.pop();
@@ -112,12 +114,12 @@
             throw e;
         }
         SymbolTable.pop();
-        if ((functionInfo.flags & FunctionInfo.STATIC) == 0) {
+        if (!functionInfo.isStatic()) {
             functionInfo.flags &= ~FunctionInfo.ABSTRACT;
         }
         // If it's all ok, add the function to the symbol table.
         SymbolTable.add(functionInfo);
-        return new FunctionDefinition(functionInfo, argumentsDeclaration, body, returnNode);
+        return new FunctionRedefinition(functionInfo, argumentsDeclaration, body, returnNode);
     }
 
 }
--- a/hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/factories/IRNodeBuilder.java	Mon May 16 17:01:53 2016 +0300
+++ b/hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/factories/IRNodeBuilder.java	Wed May 18 20:19:23 2016 +0300
@@ -25,14 +25,64 @@
 
 import java.util.Collection;
 import java.util.Optional;
+
+import jdk.test.lib.jittester.BinaryOperator;
+import jdk.test.lib.jittester.Block;
+import jdk.test.lib.jittester.Break;
+import jdk.test.lib.jittester.CastOperator;
+import jdk.test.lib.jittester.Continue;
+import jdk.test.lib.jittester.Declaration;
+import jdk.test.lib.jittester.IRNode;
+import jdk.test.lib.jittester.If;
 import jdk.test.lib.jittester.Literal;
 import jdk.test.lib.jittester.LocalVariable;
+import jdk.test.lib.jittester.NonStaticMemberVariable;
+import jdk.test.lib.jittester.Nothing;
+import jdk.test.lib.jittester.Operator;
 import jdk.test.lib.jittester.OperatorKind;
+import jdk.test.lib.jittester.PrintVariables;
 import jdk.test.lib.jittester.ProductionFailedException;
 import jdk.test.lib.jittester.ProductionParams;
+import jdk.test.lib.jittester.Statement;
+import jdk.test.lib.jittester.StaticMemberVariable;
+import jdk.test.lib.jittester.Switch;
 import jdk.test.lib.jittester.Symbol;
+import jdk.test.lib.jittester.TernaryOperator;
+import jdk.test.lib.jittester.Throw;
+import jdk.test.lib.jittester.TryCatchBlock;
 import jdk.test.lib.jittester.Type;
+import jdk.test.lib.jittester.TypeList;
+import jdk.test.lib.jittester.UnaryOperator;
+import jdk.test.lib.jittester.VariableBase;
+import jdk.test.lib.jittester.VariableDeclaration;
+import jdk.test.lib.jittester.VariableDeclarationBlock;
+import jdk.test.lib.jittester.VariableInitialization;
+import jdk.test.lib.jittester.arrays.ArrayCreation;
+import jdk.test.lib.jittester.arrays.ArrayElement;
+import jdk.test.lib.jittester.arrays.ArrayExtraction;
+import jdk.test.lib.jittester.classes.ClassDefinitionBlock;
+import jdk.test.lib.jittester.classes.Interface;
+import jdk.test.lib.jittester.classes.Klass;
+import jdk.test.lib.jittester.classes.MainKlass;
+import jdk.test.lib.jittester.functions.ArgumentDeclaration;
+import jdk.test.lib.jittester.functions.ConstructorDefinition;
+import jdk.test.lib.jittester.functions.ConstructorDefinitionBlock;
+import jdk.test.lib.jittester.functions.Function;
+import jdk.test.lib.jittester.functions.FunctionDeclaration;
+import jdk.test.lib.jittester.functions.FunctionDeclarationBlock;
+import jdk.test.lib.jittester.functions.FunctionDefinition;
+import jdk.test.lib.jittester.functions.FunctionDefinitionBlock;
 import jdk.test.lib.jittester.functions.FunctionInfo;
+import jdk.test.lib.jittester.functions.FunctionRedefinition;
+import jdk.test.lib.jittester.functions.FunctionRedefinitionBlock;
+import jdk.test.lib.jittester.functions.Return;
+import jdk.test.lib.jittester.functions.StaticConstructorDefinition;
+import jdk.test.lib.jittester.loops.CounterInitializer;
+import jdk.test.lib.jittester.loops.CounterManipulator;
+import jdk.test.lib.jittester.loops.DoWhile;
+import jdk.test.lib.jittester.loops.For;
+import jdk.test.lib.jittester.loops.LoopingCondition;
+import jdk.test.lib.jittester.loops.While;
 import jdk.test.lib.jittester.types.TypeKlass;
 
 public class IRNodeBuilder {
@@ -63,41 +113,40 @@
     private Optional<Boolean> isConstant = Optional.empty();
     private Optional<Boolean> isInitialized = Optional.empty();
     private Optional<String> name = Optional.empty();
-    private Optional<String> printerName = Optional.empty();
     private Optional<Integer> flags = Optional.empty();
     private Optional<FunctionInfo> functionInfo = Optional.empty();
     private Optional<Boolean> semicolon = Optional.empty();
 
-    public ArgumentDeclarationFactory getArgumentDeclarationFactory() {
+    public Factory<ArgumentDeclaration> getArgumentDeclarationFactory() {
         return new ArgumentDeclarationFactory(getArgumentType(), getVariableNumber());
     }
 
-    public Factory getArithmeticOperatorFactory() throws ProductionFailedException {
+    public Factory<Operator> getArithmeticOperatorFactory() throws ProductionFailedException {
         return new ArithmeticOperatorFactory(getComplexityLimit(), getOperatorLimit(),
                 getOwnerClass(), getResultType(), getExceptionSafe(), getNoConsts());
     }
 
-    public ArrayCreationFactory getArrayCreationFactory() {
+    public Factory<ArrayCreation> getArrayCreationFactory() {
         return new ArrayCreationFactory(getComplexityLimit(), getOperatorLimit(), getOwnerClass(),
                 getResultType(), getExceptionSafe(), getNoConsts());
     }
 
-    public ArrayElementFactory getArrayElementFactory() {
+    public Factory<ArrayElement> getArrayElementFactory() {
         return new ArrayElementFactory(getComplexityLimit(), getOperatorLimit(), getOwnerClass(),
                 getResultType(), getExceptionSafe(), getNoConsts());
     }
 
-    public ArrayExtractionFactory getArrayExtractionFactory() {
+    public Factory<ArrayExtraction> getArrayExtractionFactory() {
         return new ArrayExtractionFactory(getComplexityLimit(), getOperatorLimit(), getOwnerClass(),
                 getResultType(), getExceptionSafe(), getNoConsts());
     }
 
-    public AssignmentOperatorFactory getAssignmentOperatorFactory() {
+    public Factory<Operator> getAssignmentOperatorFactory() {
         return new AssignmentOperatorFactory(getComplexityLimit(), getOperatorLimit(),
                 getOwnerClass(), resultType.orElse(null), getExceptionSafe(), getNoConsts());
     }
 
-    public BinaryOperatorFactory getBinaryOperatorFactory() throws ProductionFailedException {
+    public Factory<BinaryOperator> getBinaryOperatorFactory() throws ProductionFailedException {
         OperatorKind o = getOperatorKind();
         switch (o) {
             case ASSIGN:
@@ -166,7 +215,7 @@
         }
     }
 
-    public UnaryOperatorFactory getUnaryOperatorFactory() throws ProductionFailedException {
+    public Factory<UnaryOperator> getUnaryOperatorFactory() throws ProductionFailedException {
         OperatorKind o = getOperatorKind();
         switch (o) {
             case NOT:
@@ -193,24 +242,24 @@
         }
     }
 
-    public BlockFactory getBlockFactory() throws ProductionFailedException {
+    public Factory<Block> getBlockFactory() {
         return new BlockFactory(getOwnerClass(), getResultType(), getComplexityLimit(),
-            getStatementLimit(), getOperatorLimit(), getLevel(), subBlock.orElse(false),
-            canHaveBreaks.orElse(false), canHaveContinues.orElse(false),
+                getStatementLimit(), getOperatorLimit(), getLevel(), subBlock.orElse(false),
+                canHaveBreaks.orElse(false), canHaveContinues.orElse(false),
                 canHaveReturn.orElse(false), canHaveReturn.orElse(false));
-                //now 'throw' can be placed only in the same positions as 'return'
+        //now 'throw' can be placed only in the same positions as 'return'
     }
 
-    public BreakFactory getBreakFactory() {
+    public Factory<Break> getBreakFactory() {
         return new BreakFactory();
     }
 
-    public CastOperatorFactory getCastOperatorFactory() {
+    public Factory<CastOperator> getCastOperatorFactory() {
         return new CastOperatorFactory(getComplexityLimit(), getOperatorLimit(), getOwnerClass(),
                 getResultType(), getExceptionSafe(), getNoConsts());
     }
 
-    public Factory getClassDefinitionBlockFactory() {
+    public Factory<ClassDefinitionBlock> getClassDefinitionBlockFactory() {
         return new ClassDefinitionBlockFactory(getPrefix(),
                 ProductionParams.classesLimit.value(),
                 ProductionParams.memberFunctionsLimit.value(),
@@ -221,7 +270,7 @@
                 getLevel());
     }
 
-    public Factory getMainKlassFactory() {
+    public Factory<MainKlass> getMainKlassFactory() {
         return new MainKlassFactory(getName(), getComplexityLimit(),
                 ProductionParams.memberFunctionsLimit.value(),
                 ProductionParams.memberFunctionsArgLimit.value(),
@@ -230,200 +279,200 @@
                 ProductionParams.operatorLimit.value());
     }
 
-    public ConstructorDefinitionBlockFactory getConstructorDefinitionBlockFactory() {
+    public Factory<ConstructorDefinitionBlock> getConstructorDefinitionBlockFactory() {
         return new ConstructorDefinitionBlockFactory(getOwnerClass(), getMemberFunctionsLimit(),
                 ProductionParams.memberFunctionsArgLimit.value(), getComplexityLimit(),
                 getStatementLimit(), getOperatorLimit(), getLevel());
     }
 
-    public ConstructorDefinitionFactory getConstructorDefinitionFactory() {
+    public Factory<ConstructorDefinition> getConstructorDefinitionFactory() {
         return new ConstructorDefinitionFactory(getOwnerClass(), getComplexityLimit(),
                 getStatementLimit(), getOperatorLimit(),
                 getMemberFunctionsArgLimit(), getLevel());
     }
 
-    public ContinueFactory getContinueFactory() {
+    public Factory<Continue> getContinueFactory() {
         return new ContinueFactory();
     }
 
-    public CounterInitializerFactory getCounterInitializerFactory(int counterValue) {
+    public Factory<CounterInitializer> getCounterInitializerFactory(int counterValue) {
         return new CounterInitializerFactory(getOwnerClass(), counterValue);
     }
 
-    public CounterManipulatorFactory getCounterManipulatorFactory() {
+    public Factory<CounterManipulator> getCounterManipulatorFactory() {
         return new CounterManipulatorFactory(getLocalVariable());
     }
 
-    public DeclarationFactory getDeclarationFactory() {
+    public Factory<Declaration> getDeclarationFactory() {
         return new DeclarationFactory(getOwnerClass(), getComplexityLimit(), getOperatorLimit(),
-            getIsLocal(), getExceptionSafe());
+                getIsLocal(), getExceptionSafe());
     }
 
-    public DoWhileFactory getDoWhileFactory() {
+    public Factory<DoWhile> getDoWhileFactory() {
         return new DoWhileFactory(getOwnerClass(), getResultType(), getComplexityLimit(),
                 getStatementLimit(), getOperatorLimit(), getLevel(), getCanHaveReturn());
     }
 
-    public WhileFactory getWhileFactory() {
+    public Factory<While> getWhileFactory() {
         return new WhileFactory(getOwnerClass(), getResultType(), getComplexityLimit(),
                 getStatementLimit(), getOperatorLimit(), getLevel(), getCanHaveReturn());
     }
 
-    public IfFactory getIfFactory() {
+    public Factory<If> getIfFactory() {
         return new IfFactory(getOwnerClass(), getResultType(), getComplexityLimit(),
-        getStatementLimit(), getOperatorLimit(), getLevel(), getCanHaveBreaks(),
+                getStatementLimit(), getOperatorLimit(), getLevel(), getCanHaveBreaks(),
                 getCanHaveContinues(), getCanHaveReturn());
     }
 
-    public ForFactory getForFactory() {
+    public Factory<For> getForFactory() {
         return new ForFactory(getOwnerClass(), getResultType(), getComplexityLimit(),
                 getStatementLimit(), getOperatorLimit(), getLevel(), getCanHaveReturn());
     }
 
-    public SwitchFactory getSwitchFactory() { // TODO: switch is not used now
+    public Factory<Switch> getSwitchFactory() { // TODO: switch is not used now
         return new SwitchFactory(getOwnerClass(), getComplexityLimit(), getStatementLimit(),
                 getOperatorLimit(), getLevel(), getCanHaveReturn());
     }
 
-    public ExpressionFactory getExpressionFactory() throws ProductionFailedException {
+    public Factory<IRNode> getExpressionFactory() throws ProductionFailedException {
         return new ExpressionFactory(getComplexityLimit(), getOperatorLimit(), getOwnerClass(),
                 getResultType(), getExceptionSafe(), getNoConsts());
     }
 
-    public FunctionDeclarationBlockFactory getFunctionDeclarationBlockFactory() {
+    public Factory<FunctionDeclarationBlock> getFunctionDeclarationBlockFactory() {
         return new FunctionDeclarationBlockFactory(getOwnerClass(), getMemberFunctionsLimit(),
                 getMemberFunctionsArgLimit(), getLevel());
     }
 
-    public FunctionDeclarationFactory getFunctionDeclarationFactory() {
-        return new FunctionDeclarationFactory(getName(), getOwnerClass(),resultType.orElse(null),
+    public Factory<FunctionDeclaration> getFunctionDeclarationFactory() {
+        return new FunctionDeclarationFactory(getName(), getOwnerClass(),resultType.orElse(TypeList.VOID),
                 getMemberFunctionsArgLimit(), getFlags());
     }
 
-    public FunctionDefinitionBlockFactory getFunctionDefinitionBlockFactory() {
+    public Factory<FunctionDefinitionBlock> getFunctionDefinitionBlockFactory() {
         return new FunctionDefinitionBlockFactory(getOwnerClass(), getMemberFunctionsLimit(),
                 getMemberFunctionsArgLimit(), getComplexityLimit(), getStatementLimit(),
                 getOperatorLimit(), getLevel(), getFlags());
     }
 
-    public FunctionDefinitionFactory getFunctionDefinitionFactory() {
-        return new FunctionDefinitionFactory(getName(), getOwnerClass(), resultType.orElse(null),
+    public Factory<FunctionDefinition> getFunctionDefinitionFactory() {
+        return new FunctionDefinitionFactory(getName(), getOwnerClass(), resultType.orElse(TypeList.VOID),
                 getComplexityLimit(), getStatementLimit(), getOperatorLimit(),
                 getMemberFunctionsArgLimit(), getLevel(), getFlags());
     }
 
-    public FunctionFactory getFunctionFactory() {
+    public Factory<Function> getFunctionFactory() {
         return new FunctionFactory(getComplexityLimit(), getOperatorLimit(), getOwnerClass(),
                 resultType.orElse(null), getExceptionSafe());
     }
 
-    public FunctionRedefinitionBlockFactory getFunctionRedefinitionBlockFactory(Collection<Symbol>
-            functionSet) {
+    public Factory<FunctionRedefinitionBlock> getFunctionRedefinitionBlockFactory(Collection<Symbol>
+                                                                                        functionSet) {
         return new FunctionRedefinitionBlockFactory(functionSet, getOwnerClass(),
                 getComplexityLimit(), getStatementLimit(), getOperatorLimit(), getLevel());
     }
 
-    public FunctionRedefinitionFactory getFunctionRedefinitionFactory() {
+    public Factory<FunctionRedefinition> getFunctionRedefinitionFactory() {
         return new FunctionRedefinitionFactory(getFunctionInfo(), getOwnerClass(),
                 getComplexityLimit(), getStatementLimit(), getOperatorLimit(), getLevel(),
                 getFlags());
     }
 
-    public InterfaceFactory getInterfaceFactory() {
+    public Factory<Interface> getInterfaceFactory() {
         return new InterfaceFactory(getName(), getMemberFunctionsLimit(),
                 getMemberFunctionsArgLimit(), getLevel());
     }
 
-    public KlassFactory getKlassFactory() {
-        return new KlassFactory(getName(), getPrinterName(), getComplexityLimit(),
+    public Factory<Klass> getKlassFactory() {
+        return new KlassFactory(getName(), getComplexityLimit(),
                 getMemberFunctionsLimit(), getMemberFunctionsArgLimit(), getStatementLimit(),
                 getOperatorLimit(), getLevel());
     }
 
-    public LimitedExpressionFactory getLimitedExpressionFactory() throws ProductionFailedException {
+    public Factory<IRNode> getLimitedExpressionFactory() throws ProductionFailedException {
         return new LimitedExpressionFactory(getComplexityLimit(), getOperatorLimit(),
                 getOwnerClass(), getResultType(), getExceptionSafe(), getNoConsts());
     }
 
-    public LiteralFactory getLiteralFactory() {
+    public Factory<Literal> getLiteralFactory() {
         return new LiteralFactory(getResultType());
     }
 
-    public LocalVariableFactory getLocalVariableFactory() {
+    public Factory<LocalVariable> getLocalVariableFactory() {
         return new LocalVariableFactory(/*getVariableType()*/getResultType(), getFlags());
     }
 
-    public LogicOperatorFactory getLogicOperatorFactory() throws ProductionFailedException {
+    public Factory<Operator> getLogicOperatorFactory() throws ProductionFailedException {
         return new LogicOperatorFactory(getComplexityLimit(), getOperatorLimit(), getOwnerClass(),
                 getResultType(), getExceptionSafe(), getNoConsts());
     }
 
-    public LoopingConditionFactory getLoopingConditionFactory(Literal _limiter) {
+    public Factory<LoopingCondition> getLoopingConditionFactory(Literal _limiter) {
         return new LoopingConditionFactory(getComplexityLimit(), getOperatorLimit(), getOwnerClass(),
                 getLocalVariable(), _limiter);
     }
 
-    public NonStaticMemberVariableFactory getNonStaticMemberVariableFactory() {
+    public Factory<NonStaticMemberVariable> getNonStaticMemberVariableFactory() {
         return new NonStaticMemberVariableFactory(getComplexityLimit(), getOperatorLimit(),
                 getOwnerClass(), /*getVariableType()*/getResultType(), getFlags(), getExceptionSafe());
     }
 
-    public NothingFactory getNothingFactory() {
+    public Factory<Nothing> getNothingFactory() {
         return new NothingFactory();
     }
 
-    public PrintVariablesFactory getPrintVariablesFactory() {
-        return new PrintVariablesFactory(getPrinterName(), getOwnerClass(), getLevel());
+    public Factory<PrintVariables> getPrintVariablesFactory() {
+        return new PrintVariablesFactory(getOwnerClass(), getLevel());
     }
 
-    public ReturnFactory getReturnFactory() {
+    public Factory<Return> getReturnFactory() {
         return new ReturnFactory(getComplexityLimit(), getOperatorLimit(), getOwnerClass(),
                 getResultType(), getExceptionSafe());
     }
 
-    public ThrowFactory getThrowFactory() {
+    public Factory<Throw> getThrowFactory() {
         return new ThrowFactory(getComplexityLimit(), getOperatorLimit(), getOwnerClass(), getResultType(), getExceptionSafe());
     }
 
-    public StatementFactory getStatementFactory() {
+    public Factory<Statement> getStatementFactory() {
         return new StatementFactory(getComplexityLimit(), getOperatorLimit(), getOwnerClass(),
                 getExceptionSafe(), getNoConsts(), semicolon.orElse(true));
     }
 
-    public StaticConstructorDefinitionFactory getStaticConstructorDefinitionFactory() {
+    public Factory<StaticConstructorDefinition> getStaticConstructorDefinitionFactory() {
         return new StaticConstructorDefinitionFactory(getOwnerClass(), getComplexityLimit(),
                 getStatementLimit(), getOperatorLimit(), getLevel());
     }
 
-    public StaticMemberVariableFactory getStaticMemberVariableFactory() {
+    public Factory<StaticMemberVariable> getStaticMemberVariableFactory() {
         return new StaticMemberVariableFactory(getOwnerClass(), /*getVariableType()*/getResultType(), getFlags());
     }
 
-    public TernaryOperatorFactory getTernaryOperatorFactory() {
+    public Factory<TernaryOperator> getTernaryOperatorFactory() {
         return new TernaryOperatorFactory(getComplexityLimit(), getOperatorLimit(), getOwnerClass(),
                 getResultType(), getExceptionSafe(), getNoConsts());
     }
 
-    public VariableDeclarationBlockFactory getVariableDeclarationBlockFactory() {
+    public Factory<VariableDeclarationBlock> getVariableDeclarationBlockFactory() {
         return new VariableDeclarationBlockFactory(getOwnerClass(), getComplexityLimit(),
                 getOperatorLimit(), getLevel(), getExceptionSafe());
     }
 
-    public VariableDeclarationFactory getVariableDeclarationFactory() {
+    public Factory<VariableDeclaration> getVariableDeclarationFactory() {
         return new VariableDeclarationFactory(getOwnerClass(), getIsStatic(), getIsLocal(), getResultType());
     }
 
-    public VariableFactory getVariableFactory() {
+    public Factory<VariableBase> getVariableFactory() {
         return new VariableFactory(getComplexityLimit(), getOperatorLimit(), getOwnerClass(),
                 /*getVariableType()*/getResultType(), getIsConstant(), getIsInitialized(), getExceptionSafe(), getNoConsts());
     }
 
-    public VariableInitializationFactory getVariableInitializationFactory() {
-            return new VariableInitializationFactory(getOwnerClass(), getIsConstant(), getIsStatic(),
-                    getIsLocal(), getComplexityLimit(), getOperatorLimit(), getExceptionSafe());
+    public Factory<VariableInitialization> getVariableInitializationFactory() {
+        return new VariableInitializationFactory(getOwnerClass(), getIsConstant(), getIsStatic(),
+                getIsLocal(), getComplexityLimit(), getOperatorLimit(), getExceptionSafe());
     }
 
-    public TryCatchBlockFactory getTryCatchBlockFactory() {
+    public Factory<TryCatchBlock> getTryCatchBlockFactory() {
         return new TryCatchBlockFactory(getOwnerClass(), getResultType(),
                 getComplexityLimit(), getStatementLimit(), getOperatorLimit(),
                 getLevel(), subBlock.orElse(false), getCanHaveBreaks(),
@@ -570,11 +619,6 @@
         return this;
     }
 
-    public IRNodeBuilder setPrinterName(String value) {
-        printerName = Optional.of(value);
-        return this;
-    }
-
     public IRNodeBuilder setSemicolon(boolean value) {
         semicolon = Optional.of(value);
         return this;
@@ -698,9 +742,4 @@
         return functionInfo.orElseThrow(() -> new IllegalArgumentException(
                 "FunctionInfo wasn't set"));
     }
-
-    private String getPrinterName() {
-        return printerName.orElseThrow(() -> new IllegalArgumentException(
-                "printerName wasn't set"));
-    }
 }
--- a/hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/factories/IfFactory.java	Mon May 16 17:01:53 2016 +0300
+++ b/hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/factories/IfFactory.java	Wed May 18 20:19:23 2016 +0300
@@ -23,21 +23,22 @@
 
 package jdk.test.lib.jittester.factories;
 
+import jdk.test.lib.jittester.Block;
 import jdk.test.lib.jittester.IRNode;
 import jdk.test.lib.jittester.If;
 import jdk.test.lib.jittester.ProductionFailedException;
 import jdk.test.lib.jittester.Type;
+import jdk.test.lib.jittester.TypeList;
 import jdk.test.lib.jittester.types.TypeKlass;
-import jdk.test.lib.jittester.types.TypeBoolean;
 import jdk.test.lib.jittester.utils.PseudoRandom;
 
-class IfFactory extends SafeFactory {
-    protected long complexityLimit;
-    protected int statementLimit;
-    protected int operatorLimit;
-    protected boolean canHaveBreaks;
-    protected boolean canHaveContinues;
-    protected boolean canHaveReturn;
+class IfFactory extends SafeFactory<If> {
+    protected final long complexityLimit;
+    protected final int statementLimit;
+    protected final int operatorLimit;
+    protected final boolean canHaveBreaks;
+    protected final boolean canHaveContinues;
+    protected final boolean canHaveReturn;
     protected final TypeKlass ownerClass;
     protected final Type returnType;
     protected final int level;
@@ -57,7 +58,7 @@
     }
 
     @Override
-    public IRNode sproduce() throws ProductionFailedException {
+    public If sproduce() throws ProductionFailedException {
         // resizeUpChildren(If.IfPart.values().length);
         if (statementLimit > 0 && complexityLimit > 0) {
             long conditionComplLimit = (long) (0.01 * PseudoRandom.random() * (complexityLimit - 1));
@@ -65,7 +66,7 @@
                     .setOwnerKlass(ownerClass)
                     .setOperatorLimit(operatorLimit);
             IRNode condition = builder.setComplexityLimit(conditionComplLimit)
-                    .setResultType(new TypeBoolean())
+                    .setResultType(TypeList.BOOLEAN)
                     .setExceptionSafe(false)
                     .setNoConsts(false)
                     .getLimitedExpressionFactory()
@@ -83,7 +84,7 @@
                 controlDeviation = PseudoRandom.randomBoolean() ? If.IfPart.THEN : If.IfPart.ELSE;
             }
             if (ifBlockLimit > 0 && ifBlockComplLimit > 0) {
-                IRNode thenBlock = null;
+                Block thenBlock;
                 builder.setResultType(returnType)
                         .setLevel(level)
                         .setComplexityLimit(ifBlockComplLimit)
@@ -104,7 +105,7 @@
                             .produce();
                 }
                 // setChild(If.IfPart.THEN.ordinal(), thenBlock);
-                IRNode elseBlock = null;
+                Block elseBlock = null;
                 if (elseBlockLimit > 0 && elseBlockComplLimit > 0) {
                     builder.setComplexityLimit(elseBlockComplLimit)
                             .setStatementLimit(elseBlockLimit);
--- a/hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/factories/IncDecOperatorFactory.java	Mon May 16 17:01:53 2016 +0300
+++ b/hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/factories/IncDecOperatorFactory.java	Wed May 18 20:19:23 2016 +0300
@@ -23,14 +23,12 @@
 
 package jdk.test.lib.jittester.factories;
 
-import jdk.test.lib.jittester.IRNode;
 import jdk.test.lib.jittester.OperatorKind;
 import jdk.test.lib.jittester.ProductionFailedException;
 import jdk.test.lib.jittester.Type;
 import jdk.test.lib.jittester.TypeList;
 import jdk.test.lib.jittester.UnaryOperator;
 import jdk.test.lib.jittester.types.TypeKlass;
-import jdk.test.lib.jittester.types.TypeBoolean;
 
 class IncDecOperatorFactory extends UnaryOperatorFactory {
     IncDecOperatorFactory(OperatorKind opKind, long complexityLimit, int operatorLimit,
@@ -40,11 +38,11 @@
 
     @Override
     protected boolean isApplicable(Type resultType) {
-        return TypeList.isBuiltInInt(resultType) && !resultType.equals(new TypeBoolean());
+        return TypeList.isBuiltInInt(resultType) && !resultType.equals(TypeList.BOOLEAN);
     }
 
     @Override
-    protected IRNode generateProduction(Type l) throws ProductionFailedException {
+    protected UnaryOperator generateProduction(Type l) throws ProductionFailedException {
         return new UnaryOperator(opKind, new IRNodeBuilder().setComplexityLimit(complexityLimit - 1)
                 .setOperatorLimit(operatorLimit - 1)
                 .setOwnerKlass((TypeKlass) ownerClass)
--- a/hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/factories/InterfaceFactory.java	Mon May 16 17:01:53 2016 +0300
+++ b/hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/factories/InterfaceFactory.java	Wed May 18 20:19:23 2016 +0300
@@ -37,7 +37,7 @@
 import jdk.test.lib.jittester.types.TypeKlass;
 import jdk.test.lib.jittester.utils.PseudoRandom;
 
-class InterfaceFactory extends Factory {
+class InterfaceFactory extends Factory<Interface> {
     private final String name;
     private final int memberFunctionsLimit;
     private final int memberFunctionsArgLimit;
@@ -52,7 +52,7 @@
     }
 
     @Override
-    public IRNode produce() throws ProductionFailedException {
+    public Interface produce() throws ProductionFailedException {
         TypeKlass thisKlass;
         // Do we want to inherit something?
         if (!ProductionParams.disableInheritance.value()) {
@@ -76,7 +76,7 @@
             parent.addChild(name);
             for (Symbol symbol : SymbolTable.getAllCombined(parent, FunctionInfo.class)) {
                 FunctionInfo functionInfo = (FunctionInfo) symbol.deepCopy();
-                functionInfo.klass = thisKlass;
+                functionInfo.owner = thisKlass;
                 functionInfo.argTypes.get(0).type = thisKlass;
                 SymbolTable.add(functionInfo);
             }
--- a/hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/factories/KlassFactory.java	Mon May 16 17:01:53 2016 +0300
+++ b/hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/factories/KlassFactory.java	Wed May 18 20:19:23 2016 +0300
@@ -42,9 +42,8 @@
 import jdk.test.lib.jittester.types.TypeKlass;
 import jdk.test.lib.jittester.utils.PseudoRandom;
 
-class KlassFactory extends Factory {
+class KlassFactory extends Factory<Klass> {
     private final String name;
-    private final String printerName;
     private final long complexityLimit;
     private final int statementsInFunctionLimit;
     private final int operatorLimit;
@@ -55,11 +54,10 @@
     private TypeKlass parent;
     private int memberFunctionsLimit;
 
-    KlassFactory(String name, String printerName, long complexityLimit,
+    KlassFactory(String name, long complexityLimit,
             int memberFunctionsLimit, int memberFunctionsArgLimit, int statementsInFunctionLimit,
             int operatorLimit, int level) {
         this.name = name;
-        this.printerName = printerName;
         this.complexityLimit = complexityLimit;
         this.memberFunctionsLimit = memberFunctionsLimit;
         this.memberFunctionsArgLimit = memberFunctionsArgLimit;
@@ -70,7 +68,7 @@
     }
 
     @Override
-    public IRNode produce() throws ProductionFailedException {
+    public Klass produce() throws ProductionFailedException {
         HashSet<Symbol> abstractSet = new HashSet<>();
         HashSet<Symbol> overrideSet = new HashSet<>();
         thisKlass = new TypeKlass(name);
@@ -135,15 +133,11 @@
                 SymbolTable.remove(symbol);
             }
         } else {
-            parent = (TypeKlass) TypeList.find("java.lang.Object");
+            parent = TypeList.OBJECT;
             thisKlass.addParent(parent.getName());
             thisKlass.setParent(parent);
             parent.addChild(name);
         }
-        // Just don't print it. It's assumed that we at least are inherited from Object.
-        if (parent.getName().equals("java.lang.Object")) {
-            parent = null;
-        }
         SymbolTable.add(new VariableInfo("this", thisKlass, thisKlass,
                 VariableInfo.FINAL | VariableInfo.LOCAL | VariableInfo.INITIALIZED));
         IRNode variableDeclarations = null;
@@ -152,8 +146,7 @@
         IRNode functionDeclarations = null;
         IRNode abstractFunctionsRedefinitions = null;
         IRNode overridenFunctionsRedefinitions = null;
-        IRNodeBuilder builder = new IRNodeBuilder().setPrinterName(printerName)
-                .setOwnerKlass(thisKlass)
+        IRNodeBuilder builder = new IRNodeBuilder().setOwnerKlass(thisKlass)
                 .setExceptionSafe(true);
         try {
             builder.setLevel(level + 1)
@@ -227,7 +220,7 @@
             }
         }
         if (probableParents.isEmpty()) {
-            parent = (TypeKlass) TypeList.find("java.lang.Object");
+            parent = TypeList.OBJECT;
         } else {
             parent = (TypeKlass) PseudoRandom.randomElement(probableParents);
         }
@@ -246,7 +239,7 @@
                         functionInfo.argTypes.get(0).type = thisKlass;
                     }
                 }
-                symbolCopy.klass = thisKlass;
+                symbolCopy.owner = thisKlass;
                 SymbolTable.add(symbolCopy);
             }
         }
@@ -276,10 +269,9 @@
             interfaces.add(iface);
             iface.addChild(name);
             thisKlass.addParent(iface.getName());
-            thisKlass.setParent(iface);
             for (Symbol symbol : SymbolTable.getAllCombined(iface, FunctionInfo.class)) {
                 FunctionInfo functionInfo = (FunctionInfo) symbol.deepCopy();
-                functionInfo.klass = thisKlass;
+                functionInfo.owner = thisKlass;
                 functionInfo.argTypes.get(0).type = thisKlass;
                 SymbolTable.add(functionInfo);
             }
--- a/hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/factories/LiteralFactory.java	Mon May 16 17:01:53 2016 +0300
+++ b/hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/factories/LiteralFactory.java	Wed May 18 20:19:23 2016 +0300
@@ -23,23 +23,16 @@
 
 package jdk.test.lib.jittester.factories;
 
-import jdk.test.lib.jittester.IRNode;
 import jdk.test.lib.jittester.Literal;
 import jdk.test.lib.jittester.ProductionFailedException;
 import jdk.test.lib.jittester.ProductionParams;
 import jdk.test.lib.jittester.Type;
 import jdk.test.lib.jittester.TypeList;
-import jdk.test.lib.jittester.types.TypeBoolean;
-import jdk.test.lib.jittester.types.TypeByte;
-import jdk.test.lib.jittester.types.TypeChar;
-import jdk.test.lib.jittester.types.TypeDouble;
-import jdk.test.lib.jittester.types.TypeFloat;
-import jdk.test.lib.jittester.types.TypeInt;
-import jdk.test.lib.jittester.types.TypeLong;
-import jdk.test.lib.jittester.types.TypeShort;
 import jdk.test.lib.jittester.utils.PseudoRandom;
 
-class LiteralFactory extends Factory {
+import java.util.Locale;
+
+class LiteralFactory extends Factory<Literal> {
     protected final Type resultType;
 
     LiteralFactory(Type resultType) {
@@ -47,31 +40,39 @@
     }
 
     @Override
-    public IRNode produce() throws ProductionFailedException {
+    public Literal produce() throws ProductionFailedException {
         Literal literal;
-        if (resultType.equals(new TypeBoolean())) {
-            literal = new Literal(PseudoRandom.randomBoolean(), new TypeBoolean());
-        } else if (resultType.equals(new TypeChar())) {
-            literal = new Literal((char) ((char) (PseudoRandom.random() * ('z' - 'A')) + 'A'), new TypeChar());
-        } else if (resultType.equals(new TypeInt())) {
-            literal = new Literal((int) (PseudoRandom.random() * Integer.MAX_VALUE), new TypeInt());
-        } else if (resultType.equals(new TypeLong())) {
-            literal = new Literal((long) (PseudoRandom.random() * Long.MAX_VALUE), new TypeLong());
-        } else if (resultType.equals(new TypeFloat())) {
-            literal = new Literal((float) (PseudoRandom.random() * Float.MAX_VALUE), new TypeFloat());
-        } else if (resultType.equals(new TypeDouble())) {
-            literal = new Literal(PseudoRandom.random() * Double.MAX_VALUE, new TypeDouble());
-        } else if (resultType.equals(new TypeByte())) {
-            literal = new Literal((byte)(PseudoRandom.random() * Byte.MAX_VALUE),new TypeByte());
-        } else if (resultType.equals(new TypeShort())) {
-            literal = new Literal((short)(PseudoRandom.random() * Short.MAX_VALUE), new TypeShort());
-        } else if (resultType.equals(TypeList.find("java.lang.String"))) {
+        if (resultType.equals(TypeList.BOOLEAN)) {
+            literal = new Literal(PseudoRandom.randomBoolean(), TypeList.BOOLEAN);
+        } else if (resultType.equals(TypeList.CHAR)) {
+            literal = new Literal((char) ((char) (PseudoRandom.random() * ('z' - 'A')) + 'A'), TypeList.CHAR);
+        } else if (resultType.equals(TypeList.INT)) {
+            literal = new Literal((int) (PseudoRandom.random() * Integer.MAX_VALUE), TypeList.INT);
+        } else if (resultType.equals(TypeList.LONG)) {
+            literal = new Literal((long) (PseudoRandom.random() * Long.MAX_VALUE), TypeList.LONG);
+        } else if (resultType.equals(TypeList.FLOAT)) {
+            literal = new Literal(new Float(String.format(
+                    (Locale) null,
+                    "%." + ProductionParams.floatingPointPrecision.value() + "EF",
+                    (float) PseudoRandom.random() * Float.MAX_VALUE)),
+                    TypeList.FLOAT);
+        } else if (resultType.equals(TypeList.DOUBLE)) {
+            literal = new Literal(new Double(String.format(
+                    (Locale) null,
+                    "%." + 2 * ProductionParams.floatingPointPrecision.value() + "E",
+                    PseudoRandom.random() * Double.MAX_VALUE)),
+                    TypeList.DOUBLE);
+        } else if (resultType.equals(TypeList.BYTE)) {
+            literal = new Literal((byte)(PseudoRandom.random() * Byte.MAX_VALUE), TypeList.BYTE);
+        } else if (resultType.equals(TypeList.SHORT)) {
+            literal = new Literal((short)(PseudoRandom.random() * Short.MAX_VALUE), TypeList.SHORT);
+        } else if (resultType.equals(TypeList.STRING)) {
             int size = (int) (PseudoRandom.random() * ProductionParams.stringLiteralSizeLimit.value());
             byte[] str = new byte[size];
             for (int i = 0; i < size; i++) {
                 str[i] = (byte) ((int) (('z' - 'a') * PseudoRandom.random()) + 'a');
             }
-            literal = new Literal("\"" + new String(str) + "\"", TypeList.find("java.lang.String"));
+            literal = new Literal(new String(str), TypeList.STRING);
         } else {
             throw new ProductionFailedException();
         }
--- a/hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/factories/LocalVariableFactory.java	Mon May 16 17:01:53 2016 +0300
+++ b/hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/factories/LocalVariableFactory.java	Wed May 18 20:19:23 2016 +0300
@@ -24,7 +24,7 @@
 package jdk.test.lib.jittester.factories;
 
 import java.util.ArrayList;
-import jdk.test.lib.jittester.IRNode;
+
 import jdk.test.lib.jittester.LocalVariable;
 import jdk.test.lib.jittester.ProductionFailedException;
 import jdk.test.lib.jittester.Symbol;
@@ -33,7 +33,7 @@
 import jdk.test.lib.jittester.VariableInfo;
 import jdk.test.lib.jittester.utils.PseudoRandom;
 
-class LocalVariableFactory extends Factory {
+class LocalVariableFactory extends Factory<LocalVariable> {
     private final Type type;
     private final int flags;
 
@@ -43,7 +43,7 @@
     }
 
     @Override
-    public IRNode produce() throws ProductionFailedException {
+    public LocalVariable produce() throws ProductionFailedException {
         // Get the variables of the requested type from SymbolTable
         ArrayList<Symbol> allVariables = new ArrayList<>(SymbolTable.get(type, VariableInfo.class));
         if (!allVariables.isEmpty()) {
--- a/hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/factories/LogicOperatorFactory.java	Mon May 16 17:01:53 2016 +0300
+++ b/hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/factories/LogicOperatorFactory.java	Wed May 18 20:19:23 2016 +0300
@@ -23,15 +23,15 @@
 
 package jdk.test.lib.jittester.factories;
 
-import jdk.test.lib.jittester.IRNode;
+import jdk.test.lib.jittester.Operator;
 import jdk.test.lib.jittester.OperatorKind;
 import jdk.test.lib.jittester.ProductionFailedException;
 import jdk.test.lib.jittester.Rule;
 import jdk.test.lib.jittester.Type;
 import jdk.test.lib.jittester.types.TypeKlass;
 
-class LogicOperatorFactory extends Factory {
-    private final Rule rule;
+class LogicOperatorFactory extends Factory<Operator> {
+    private final Rule<Operator> rule;
 
     LogicOperatorFactory(long complexityLimit, int operatorLimit, TypeKlass ownerClass, Type resultType,
             boolean exceptionSafe, boolean noconsts) throws ProductionFailedException {
@@ -42,7 +42,7 @@
                 .setResultType(resultType)
                 .setExceptionSafe(exceptionSafe)
                 .setNoConsts(noconsts);
-        rule = new Rule("arithmetic");
+        rule = new Rule<>("arithmetic");
         rule.add("land", builder.setOperatorKind(OperatorKind.AND).getBinaryOperatorFactory());
         rule.add("lor", builder.setOperatorKind(OperatorKind.OR).getBinaryOperatorFactory());
         rule.add("greater", builder.setOperatorKind(OperatorKind.GT).getBinaryOperatorFactory());
@@ -55,7 +55,7 @@
     }
 
     @Override
-    public IRNode produce() throws ProductionFailedException {
+    public Operator produce() throws ProductionFailedException {
         return rule.produce();
     }
 }
--- a/hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/factories/LogicalInversionOperatorFactory.java	Mon May 16 17:01:53 2016 +0300
+++ b/hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/factories/LogicalInversionOperatorFactory.java	Wed May 18 20:19:23 2016 +0300
@@ -23,12 +23,11 @@
 
 package jdk.test.lib.jittester.factories;
 
-import jdk.test.lib.jittester.IRNode;
 import jdk.test.lib.jittester.OperatorKind;
 import jdk.test.lib.jittester.ProductionFailedException;
 import jdk.test.lib.jittester.Type;
+import jdk.test.lib.jittester.TypeList;
 import jdk.test.lib.jittester.UnaryOperator;
-import jdk.test.lib.jittester.types.TypeBoolean;
 import jdk.test.lib.jittester.types.TypeKlass;
 
 class LogicalInversionOperatorFactory extends UnaryOperatorFactory {
@@ -39,11 +38,11 @@
 
     @Override
     protected boolean isApplicable(Type resultType) {
-        return resultType.equals(new TypeBoolean());
+        return resultType.equals(TypeList.BOOLEAN);
     }
 
     @Override
-    protected IRNode generateProduction(Type resultType) throws ProductionFailedException {
+    protected UnaryOperator generateProduction(Type resultType) throws ProductionFailedException {
         return new UnaryOperator(opKind, new ExpressionFactory(complexityLimit - 1,
                 operatorLimit - 1, (TypeKlass) ownerClass, resultType, exceptionSafe, noconsts).produce());
     }
--- a/hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/factories/LoopingConditionFactory.java	Mon May 16 17:01:53 2016 +0300
+++ b/hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/factories/LoopingConditionFactory.java	Wed May 18 20:19:23 2016 +0300
@@ -29,12 +29,12 @@
 import jdk.test.lib.jittester.LocalVariable;
 import jdk.test.lib.jittester.OperatorKind;
 import jdk.test.lib.jittester.ProductionFailedException;
+import jdk.test.lib.jittester.TypeList;
 import jdk.test.lib.jittester.loops.LoopingCondition;
 import jdk.test.lib.jittester.types.TypeKlass;
-import jdk.test.lib.jittester.types.TypeBoolean;
 import jdk.test.lib.jittester.utils.PseudoRandom;
 
-class LoopingConditionFactory extends Factory {
+class LoopingConditionFactory extends Factory<LoopingCondition> {
     private final LocalVariable counter;
     private final Literal limiter;
     private final int operatorLimit;
@@ -51,11 +51,11 @@
     }
 
     @Override
-    public IRNode produce() throws ProductionFailedException {
+    public LoopingCondition produce() throws ProductionFailedException {
         IRNode leftExpression = null;
         IRNode rightExpression = null;
-        LimitedExpressionFactory exprFactory = new IRNodeBuilder()
-                .setResultType(new TypeBoolean())
+        Factory<IRNode> exprFactory = new IRNodeBuilder()
+                .setResultType(TypeList.BOOLEAN)
                 .setComplexityLimit((complexityLimit - 1) / 2)
                 .setOperatorLimit((operatorLimit - 1) / 2)
                 .setOwnerKlass(ownerClass)
@@ -75,10 +75,10 @@
         // Just as a temporary solution we'll assume that the counter is monotonically increasing.
         // And use counter < n condition to limit the loop.
         // In future we may introduce other equivalent relations as well.
-        IRNode condition = new BinaryOperator(OperatorKind.LT, counter, limiter);
-        condition = (rightExpression != null) ? new BinaryOperator(OperatorKind.AND, condition,
+        BinaryOperator condition = new BinaryOperator(OperatorKind.LT, TypeList.BOOLEAN, counter, limiter);
+        condition = (rightExpression != null) ? new BinaryOperator(OperatorKind.AND, TypeList.BOOLEAN, condition,
                 rightExpression) : condition;
-        condition = (leftExpression != null) ? new BinaryOperator(OperatorKind.AND, leftExpression,
+        condition = (leftExpression != null) ? new BinaryOperator(OperatorKind.AND, TypeList.BOOLEAN, leftExpression,
                 condition) : condition;
         return new LoopingCondition(condition);
     }
--- a/hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/factories/MainKlassFactory.java	Mon May 16 17:01:53 2016 +0300
+++ b/hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/factories/MainKlassFactory.java	Wed May 18 20:19:23 2016 +0300
@@ -38,10 +38,9 @@
 import jdk.test.lib.jittester.classes.MainKlass;
 import jdk.test.lib.jittester.functions.FunctionInfo;
 import jdk.test.lib.jittester.types.TypeKlass;
-import jdk.test.lib.jittester.types.TypeVoid;
 import jdk.test.lib.jittester.utils.PseudoRandom;
 
-class MainKlassFactory extends Factory {
+class MainKlassFactory extends Factory<MainKlass> {
     private final String name;
     private final long complexityLimit;
     private final int statementsInTestFunctionLimit;
@@ -64,8 +63,8 @@
     }
 
     @Override
-    public IRNode produce() throws ProductionFailedException {
-        TypeKlass parent = (TypeKlass) TypeList.find("java.lang.Object");
+    public MainKlass produce() throws ProductionFailedException {
+        TypeKlass parent = TypeList.OBJECT;
         thisKlass = new TypeKlass(name);
         thisKlass.addParent(parent.getName());
         thisKlass.setParent(parent);
@@ -80,8 +79,7 @@
                 .setMemberFunctionsArgLimit(memberFunctionsArgLimit)
                 .setStatementLimit(statementsInFunctionLimit)
                 .setLevel(1)
-                .setExceptionSafe(true)
-                .setPrinterName("Printer");
+                .setExceptionSafe(true);
         IRNode variableDeclarations = builder
                 .setComplexityLimit((long) (complexityLimit * 0.05))
                 .getVariableDeclarationBlockFactory().produce();
@@ -93,7 +91,7 @@
                     .getFunctionDefinitionBlockFactory()
                     .produce();
         }
-        IRNode testFunction = builder.setResultType(new TypeVoid())
+        IRNode testFunction = builder.setResultType(TypeList.VOID)
                 .setComplexityLimit(complexityLimit)
                 .setStatementLimit(statementsInTestFunctionLimit)
                 .getBlockFactory()
@@ -109,6 +107,7 @@
         childs.add(printVariables);
         ensureMinDepth(childs, builder);
         ensureMaxDepth(childs);
+        TypeList.add(thisKlass);
         return new MainKlass(name, thisKlass, variableDeclarations,
                 functionDefinitions, testFunction, printVariables);
     }
@@ -119,7 +118,7 @@
             .filter(c -> c.isCFDeviation() && c.countDepth() > maxDepth)
             .collect(Collectors.toList());
         for (IRNode child : filtered) {
-            List<IRNode> leaves = null;
+            List<IRNode> leaves;
             do {
                 long depth = Math.max(child.countDepth(), maxDepth + 1);
                 leaves = child.getDeviantBlocks(depth);
@@ -138,16 +137,14 @@
     private void addMoreChildren(List<IRNode> childs, int minDepth, IRNodeBuilder builder)
             throws ProductionFailedException {
         while (!childs.isEmpty() && IRNode.countDepth(childs) < minDepth) {
-            PseudoRandom.shuffle(childs);
-            IRNode randomChild = childs.get(0);
+            IRNode randomChild = childs.get(PseudoRandom.randomNotNegative(childs.size()));
             List<IRNode> leaves = randomChild.getStackableLeaves();
             if (!leaves.isEmpty()) {
-                PseudoRandom.shuffle(leaves);
-                Block randomLeaf = (Block) leaves.get(0);
-                TypeKlass klass = (TypeKlass) randomChild.getKlass();
+                Block randomLeaf = (Block) leaves.get(PseudoRandom.randomNotNegative(leaves.size()));
+                TypeKlass owner = randomChild.getOwner();
                 int newLevel = randomLeaf.getLevel() + 1;
-                Type retType = randomLeaf.getReturnType();
-                IRNode newBlock = builder.setOwnerKlass(klass)
+                Type retType = randomLeaf.getResultType();
+                IRNode newBlock = builder.setOwnerKlass(owner)
                         .setResultType(retType)
                         .setComplexityLimit(complexityLimit)
                         .setStatementLimit(statementsInFunctionLimit)
--- a/hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/factories/NonStaticMemberVariableFactory.java	Mon May 16 17:01:53 2016 +0300
+++ b/hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/factories/NonStaticMemberVariableFactory.java	Wed May 18 20:19:23 2016 +0300
@@ -34,7 +34,7 @@
 import jdk.test.lib.jittester.types.TypeKlass;
 import jdk.test.lib.jittester.utils.PseudoRandom;
 
-class NonStaticMemberVariableFactory extends Factory {
+class NonStaticMemberVariableFactory extends Factory<NonStaticMemberVariable> {
     private final Type type;
     private final int flags;
     private final long complexityLimit;
@@ -53,7 +53,7 @@
     }
 
     @Override
-    public IRNode produce() throws ProductionFailedException {
+    public NonStaticMemberVariable produce() throws ProductionFailedException {
         // Get the variables of the requested type from SymbolTable
         ArrayList<Symbol> variables = new ArrayList<>(SymbolTable.get(type, VariableInfo.class));
         if (!variables.isEmpty()) {
@@ -70,7 +70,7 @@
                         && (varInfo.flags & VariableInfo.STATIC) == 0
                         && (varInfo.flags & VariableInfo.LOCAL) == 0) {
                     try {
-                        IRNode object = builder.setResultType(varInfo.klass)
+                        IRNode object = builder.setResultType(varInfo.owner)
                                 .getExpressionFactory().produce();
                         return new NonStaticMemberVariable(object, varInfo);
                     } catch (ProductionFailedException e) {
--- a/hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/factories/NothingFactory.java	Mon May 16 17:01:53 2016 +0300
+++ b/hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/factories/NothingFactory.java	Wed May 18 20:19:23 2016 +0300
@@ -26,7 +26,7 @@
 import jdk.test.lib.jittester.Nothing;
 import jdk.test.lib.jittester.ProductionFailedException;
 
-public class NothingFactory extends Factory {
+public class NothingFactory extends Factory<Nothing> {
     @Override
     public Nothing produce() throws ProductionFailedException {
         return new Nothing();
--- a/hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/factories/OperatorFactory.java	Mon May 16 17:01:53 2016 +0300
+++ b/hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/factories/OperatorFactory.java	Wed May 18 20:19:23 2016 +0300
@@ -23,12 +23,14 @@
 
 package jdk.test.lib.jittester.factories;
 
-public abstract class OperatorFactory extends Factory {
-    protected long complexityLimit;
-    protected boolean exceptionSafe;
-    protected boolean noconsts;
+import jdk.test.lib.jittester.Operator;
+
+public abstract class OperatorFactory<T extends Operator> extends Factory<T> {
+    protected final long complexityLimit;
+    protected final boolean exceptionSafe;
+    protected final boolean noconsts;
+    protected final int operatorPriority;
     protected int operatorLimit;
-    protected int operatorPriority;
 
     protected OperatorFactory(int operatorPriority, long complexityLimit, int operatorLimit,
             boolean exceptionSafe, boolean noconsts) {
--- a/hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/factories/PrintVariablesFactory.java	Mon May 16 17:01:53 2016 +0300
+++ b/hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/factories/PrintVariablesFactory.java	Wed May 18 20:19:23 2016 +0300
@@ -23,27 +23,21 @@
 
 package jdk.test.lib.jittester.factories;
 
-import jdk.test.lib.jittester.IRNode;
 import jdk.test.lib.jittester.PrintVariables;
 import jdk.test.lib.jittester.ProductionFailedException;
-import jdk.test.lib.jittester.SymbolTable;
-import jdk.test.lib.jittester.VariableInfo;
 import jdk.test.lib.jittester.types.TypeKlass;
 
-class PrintVariablesFactory extends Factory {
-    private final String printerName;
+class PrintVariablesFactory extends Factory<PrintVariables> {
     private final TypeKlass ownerClass;
     private final int level;
 
-    PrintVariablesFactory(String printerName, TypeKlass ownerClass, int level) {
-        this.printerName = printerName;
+    PrintVariablesFactory(TypeKlass ownerClass, int level) {
         this.ownerClass = ownerClass;
         this.level = level;
     }
 
     @Override
-    public IRNode produce() throws ProductionFailedException {
-        return new PrintVariables(printerName, SymbolTable.getAllCombined(ownerClass,
-                VariableInfo.class), level);
+    public PrintVariables produce() throws ProductionFailedException {
+        return new PrintVariables(ownerClass, level);
     }
 }
--- a/hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/factories/ReturnFactory.java	Mon May 16 17:01:53 2016 +0300
+++ b/hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/factories/ReturnFactory.java	Wed May 18 20:19:23 2016 +0300
@@ -23,13 +23,12 @@
 
 package jdk.test.lib.jittester.factories;
 
-import jdk.test.lib.jittester.IRNode;
 import jdk.test.lib.jittester.ProductionFailedException;
 import jdk.test.lib.jittester.Type;
 import jdk.test.lib.jittester.functions.Return;
 import jdk.test.lib.jittester.types.TypeKlass;
 
-class ReturnFactory extends SafeFactory {
+class ReturnFactory extends SafeFactory<Return> {
     private final long complexityLimit;
     private final int operatorLimit;
     private final Type resultType;
@@ -46,7 +45,7 @@
     }
 
     @Override
-    protected IRNode sproduce() throws ProductionFailedException {
+    protected Return sproduce() throws ProductionFailedException {
         return new Return(new IRNodeBuilder().setComplexityLimit(complexityLimit - 1)
                 .setOperatorLimit(operatorLimit - 1)
                 .setOwnerKlass(ownerClass)
--- a/hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/factories/SafeFactory.java	Mon May 16 17:01:53 2016 +0300
+++ b/hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/factories/SafeFactory.java	Wed May 18 20:19:23 2016 +0300
@@ -27,14 +27,14 @@
 import jdk.test.lib.jittester.ProductionFailedException;
 import jdk.test.lib.jittester.SymbolTable;
 
-public abstract class SafeFactory extends Factory {
-    protected abstract IRNode sproduce() throws ProductionFailedException;
+public abstract class SafeFactory<T extends IRNode> extends Factory<T> {
+    protected abstract T sproduce() throws ProductionFailedException;
 
     @Override
-    public IRNode produce() throws ProductionFailedException {
+    public T produce() throws ProductionFailedException {
         try {
             SymbolTable.push();
-            IRNode p = sproduce();
+            T p = sproduce();
             SymbolTable.merge();
             return p;
         } catch (ProductionFailedException e) {
--- a/hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/factories/StatementFactory.java	Mon May 16 17:01:53 2016 +0300
+++ b/hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/factories/StatementFactory.java	Wed May 18 20:19:23 2016 +0300
@@ -32,15 +32,15 @@
 import jdk.test.lib.jittester.types.TypeKlass;
 import jdk.test.lib.jittester.utils.PseudoRandom;
 
-class StatementFactory extends Factory {
-    private final Rule rule;
+class StatementFactory extends Factory<Statement> {
+    private final Rule<IRNode> rule;
     private final boolean needSemicolon;
 
     StatementFactory(long complexityLimit, int operatorLimit,
             TypeKlass ownerClass, boolean exceptionSafe,
             boolean noconsts, boolean needSemicolon ){
         this.needSemicolon = needSemicolon;
-        rule = new Rule("statement");
+        rule = new Rule<>("statement");
         IRNodeBuilder builder = new IRNodeBuilder()
                 .setComplexityLimit(complexityLimit)
                 .setOperatorLimit(operatorLimit)
@@ -54,7 +54,7 @@
     }
 
     @Override
-    public IRNode produce() throws ProductionFailedException {
+    public Statement produce() throws ProductionFailedException {
         ProductionLimiter.setLimit();
         try {
             return new Statement(rule.produce(), needSemicolon);
--- a/hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/factories/StaticConstructorDefinitionFactory.java	Mon May 16 17:01:53 2016 +0300
+++ b/hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/factories/StaticConstructorDefinitionFactory.java	Wed May 18 20:19:23 2016 +0300
@@ -26,13 +26,13 @@
 import jdk.test.lib.jittester.IRNode;
 import jdk.test.lib.jittester.ProductionFailedException;
 import jdk.test.lib.jittester.SymbolTable;
+import jdk.test.lib.jittester.TypeList;
 import jdk.test.lib.jittester.VariableInfo;
 import jdk.test.lib.jittester.functions.StaticConstructorDefinition;
 import jdk.test.lib.jittester.types.TypeKlass;
-import jdk.test.lib.jittester.types.TypeVoid;
 import jdk.test.lib.jittester.utils.PseudoRandom;
 
-class StaticConstructorDefinitionFactory extends Factory {
+class StaticConstructorDefinitionFactory extends Factory<StaticConstructorDefinition> {
     private final long complexityLimit;
     private final int statementLimit;
     private final int operatorLimit;
@@ -49,7 +49,7 @@
     }
 
     @Override
-    public IRNode produce() throws ProductionFailedException {
+    public StaticConstructorDefinition produce() throws ProductionFailedException {
         SymbolTable.push();
         IRNode body;
         try {
@@ -57,7 +57,7 @@
             long complLimit = (long) (PseudoRandom.random() * complexityLimit);
             body = new IRNodeBuilder()
                     .setOwnerKlass(ownerClass)
-                    .setResultType(new TypeVoid())
+                    .setResultType(TypeList.VOID)
                     .setComplexityLimit(complLimit)
                     .setStatementLimit(statementLimit)
                     .setOperatorLimit(operatorLimit)
--- a/hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/factories/StaticMemberVariableFactory.java	Mon May 16 17:01:53 2016 +0300
+++ b/hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/factories/StaticMemberVariableFactory.java	Wed May 18 20:19:23 2016 +0300
@@ -24,7 +24,7 @@
 package jdk.test.lib.jittester.factories;
 
 import java.util.ArrayList;
-import jdk.test.lib.jittester.IRNode;
+
 import jdk.test.lib.jittester.ProductionFailedException;
 import jdk.test.lib.jittester.StaticMemberVariable;
 import jdk.test.lib.jittester.Symbol;
@@ -34,7 +34,7 @@
 import jdk.test.lib.jittester.types.TypeKlass;
 import jdk.test.lib.jittester.utils.PseudoRandom;
 
-class StaticMemberVariableFactory extends Factory {
+class StaticMemberVariableFactory extends Factory<StaticMemberVariable> {
     private final Type type;
     private final int flags;
     private final Type ownerClass;
@@ -46,7 +46,7 @@
     }
 
     @Override
-    public IRNode produce() throws ProductionFailedException {
+    public StaticMemberVariable produce() throws ProductionFailedException {
         // Get the variables of the requested type from SymbolTable
         ArrayList<Symbol> variables = new ArrayList<>(SymbolTable.get(type, VariableInfo.class));
         if (!variables.isEmpty()) {
--- a/hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/factories/SwitchFactory.java	Mon May 16 17:01:53 2016 +0300
+++ b/hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/factories/SwitchFactory.java	Wed May 18 20:19:23 2016 +0300
@@ -26,6 +26,7 @@
 import java.util.ArrayList;
 import java.util.HashSet;
 import java.util.List;
+
 import jdk.test.lib.jittester.BuiltInType;
 import jdk.test.lib.jittester.IRNode;
 import jdk.test.lib.jittester.Literal;
@@ -34,21 +35,18 @@
 import jdk.test.lib.jittester.Rule;
 import jdk.test.lib.jittester.Switch;
 import jdk.test.lib.jittester.Type;
+import jdk.test.lib.jittester.TypeList;
 import jdk.test.lib.jittester.utils.TypeUtil;
 import jdk.test.lib.jittester.types.TypeKlass;
-import jdk.test.lib.jittester.types.TypeByte;
-import jdk.test.lib.jittester.types.TypeChar;
-import jdk.test.lib.jittester.types.TypeInt;
-import jdk.test.lib.jittester.types.TypeShort;
 import jdk.test.lib.jittester.utils.PseudoRandom;
 
-class SwitchFactory extends SafeFactory {
-    private int caseBlockIdx;
-    protected long complexityLimit;
-    protected int statementLimit, operatorLimit;
-    private boolean canHaveReturn = false;
+class SwitchFactory extends SafeFactory<Switch> {
+    private final int statementLimit;
+    private final int operatorLimit;
+    private final boolean canHaveReturn;
     private final TypeKlass ownerClass;
     private final int level;
+    private final long complexityLimit;
 
     SwitchFactory(TypeKlass ownerClass, long complexityLimit, int statementLimit,
             int operatorLimit, int level, boolean canHaveReturn) {
@@ -61,13 +59,13 @@
     }
 
     @Override
-    protected IRNode sproduce() throws ProductionFailedException {
+    protected Switch sproduce() throws ProductionFailedException {
         if (statementLimit > 0 && complexityLimit > 0) {
             List<Type> switchTypes = new ArrayList<>();
-            switchTypes.add(new TypeChar());
-            switchTypes.add(new TypeByte());
-            switchTypes.add(new TypeShort());
-            switchTypes.add(new TypeInt());
+            switchTypes.add(TypeList.CHAR);
+            switchTypes.add(TypeList.BYTE);
+            switchTypes.add(TypeList.SHORT);
+            switchTypes.add(TypeList.INT);
             PseudoRandom.shuffle(switchTypes);
             IRNodeBuilder builder = new IRNodeBuilder()
                     .setOwnerKlass(ownerClass)
@@ -95,8 +93,8 @@
                             .produce();
                     accumulatedComplexity += currentComplexityLimit;
                     List<Type> caseTypes = new ArrayList<>();
-                    caseTypes.add(new TypeByte());
-                    caseTypes.add(new TypeChar());
+                    caseTypes.add(TypeList.BYTE);
+                    caseTypes.add(TypeList.CHAR);
                     caseTypes = new ArrayList<>(TypeUtil.getLessCapaciousOrEqualThan(caseTypes,
                             (BuiltInType) type));
                     if (PseudoRandom.randomBoolean()) { // "default"
@@ -104,7 +102,7 @@
                                 * (statementLimit - accumulatedStatements));
                         currentComplexityLimit = (long) (PseudoRandom.random()
                                 * (complexityLimit - accumulatedComplexity));
-                        caseConsts.add(null);
+                        caseConsts.add(new Nothing());
                         caseBlocks.add(builder.setComplexityLimit(currentComplexityLimit)
                                 .setStatementLimit(currentStatementsLimit)
                                 .setLevel(level + 1)
@@ -128,7 +126,7 @@
                             if (tryCount >= 10) {
                                 continue MAIN_LOOP;
                             }
-                            Literal literal = (Literal) builder.setResultType(caseTypes.get(0))
+                            Literal literal = builder.setResultType(caseTypes.get(0))
                                     .getLiteralFactory().produce();
                             int value = 0;
                             if (literal.value instanceof Integer) {
@@ -149,7 +147,7 @@
                                 break;
                             }
                         }
-                        Rule rule = new Rule("case_block");
+                        Rule<IRNode> rule = new Rule<>("case_block");
                         rule.add("block", builder.setComplexityLimit(currentComplexityLimit)
                                 .setStatementLimit(currentStatementsLimit)
                                 .setLevel(level)
@@ -170,7 +168,7 @@
                     }
                     PseudoRandom.shuffle(caseConsts);
                     List<IRNode> accum = new ArrayList<>();
-                    caseBlockIdx = 1 + caseConsts.size();
+                    int caseBlockIdx = 1 + caseConsts.size();
                     accum.add(switchExp);
                     for (int i = 1; i < caseBlockIdx; ++i) {
                         accum.add(caseConsts.get(i - 1));
--- a/hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/factories/TernaryOperatorFactory.java	Mon May 16 17:01:53 2016 +0300
+++ b/hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/factories/TernaryOperatorFactory.java	Wed May 18 20:19:23 2016 +0300
@@ -23,21 +23,18 @@
 
 package jdk.test.lib.jittester.factories;
 
-import jdk.test.lib.Pair;
 import jdk.test.lib.jittester.IRNode;
 import jdk.test.lib.jittester.ProductionFailedException;
 import jdk.test.lib.jittester.SymbolTable;
 import jdk.test.lib.jittester.TernaryOperator;
 import jdk.test.lib.jittester.Type;
 import jdk.test.lib.jittester.TypeList;
-import jdk.test.lib.jittester.utils.TypeUtil;
 import jdk.test.lib.jittester.types.TypeKlass;
-import jdk.test.lib.jittester.types.TypeBoolean;
 import jdk.test.lib.jittester.utils.PseudoRandom;
 
-class TernaryOperatorFactory extends OperatorFactory {
-    protected final Type resultType;
-    protected final TypeKlass ownerClass;
+class TernaryOperatorFactory extends OperatorFactory<TernaryOperator> {
+    private final Type resultType;
+    private final TypeKlass ownerClass;
 
     TernaryOperatorFactory(long complexityLimit, int operatorLimit, TypeKlass ownerClass,
             Type resultType, boolean exceptionSafe, boolean noconsts) {
@@ -46,15 +43,7 @@
         this.ownerClass = ownerClass;
     }
 
-    private Pair<Type, Type> generateTypes() {
-        Pair<Type, Type> types = new Pair<>(resultType, PseudoRandom.randomElement(
-                TypeUtil.getImplicitlyCastable(TypeList.getAll(), resultType)));
-        if (PseudoRandom.randomBoolean())
-            types = new Pair<>(types.second, types.first);
-        return types;
-    }
-
-    private IRNode generateProduction(Type conditionType, Type leftType, Type rightType) throws ProductionFailedException {
+    private TernaryOperator generateProduction() throws ProductionFailedException {
         int leftOpLimit = (int) (PseudoRandom.random() * 0.3 * (operatorLimit - 1));
         int rightOpLimit = (int) (PseudoRandom.random() * 0.3 * (operatorLimit - 1));
         int condOpLimit = operatorLimit - 1 - leftOpLimit - rightOpLimit;
@@ -69,7 +58,7 @@
                 .setExceptionSafe(exceptionSafe);
         IRNode conditionalExp = builder.setComplexityLimit(condComplLimit)
                 .setOperatorLimit(condOpLimit)
-                .setResultType(conditionType)
+                .setResultType(TypeList.BOOLEAN)
                 .setNoConsts(noconsts)
                 .getExpressionFactory()
                 .produce();
@@ -79,7 +68,7 @@
         try {
             leftExp = builder.setComplexityLimit(leftComplLimit)
                     .setOperatorLimit(leftOpLimit)
-                    .setResultType(leftType)
+                    .setResultType(resultType)
                     .setNoConsts(false)
                     .getExpressionFactory()
                     .produce();
@@ -91,7 +80,7 @@
         try {
             rightExp = builder.setComplexityLimit(rightComplLimit)
                     .setOperatorLimit(rightOpLimit)
-                    .setResultType(rightType)
+                    .setResultType(resultType)
                     .setNoConsts(false)
                     .getExpressionFactory()
                     .produce();
@@ -102,16 +91,10 @@
     }
 
     @Override
-    public IRNode produce() throws ProductionFailedException {
-        Pair<Type, Type> types;
-        try {
-            types = generateTypes();
-        } catch (RuntimeException ex) {
-            throw new ProductionFailedException(ex.getMessage());
-        }
+    public TernaryOperator produce() throws ProductionFailedException {
         try {
             SymbolTable.push();
-            IRNode result = generateProduction(new TypeBoolean(), types.first, types.second);
+            TernaryOperator result = generateProduction();
             SymbolTable.merge();
             return result;
         } catch (ProductionFailedException e) {
--- a/hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/factories/ThrowFactory.java	Mon May 16 17:01:53 2016 +0300
+++ b/hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/factories/ThrowFactory.java	Wed May 18 20:19:23 2016 +0300
@@ -30,8 +30,8 @@
 import jdk.test.lib.jittester.Type;
 import jdk.test.lib.jittester.types.TypeKlass;
 
-class ThrowFactory extends SafeFactory {
-    private final Rule rule;
+class ThrowFactory extends SafeFactory<Throw> {
+    private final Rule<IRNode> rule;
 
     ThrowFactory(long complexityLimit, int operatorLimit, TypeKlass ownerClass,
             Type resultType, boolean exceptionSafe) {
@@ -42,7 +42,7 @@
                 .setResultType(resultType)
                 .setExceptionSafe(exceptionSafe)
                 .setNoConsts(false);
-        rule = new Rule("throw");
+        rule = new Rule<>("throw");
         rule.add("constant", b.setIsConstant(true).setIsInitialized(true).getVariableFactory());
         rule.add("variable", b.setIsConstant(false).setIsInitialized(true).getVariableFactory());
 
@@ -51,7 +51,7 @@
     }
 
     @Override
-    protected IRNode sproduce() throws ProductionFailedException {
+    protected Throw sproduce() throws ProductionFailedException {
         return new Throw(rule.produce());
     }
 }
--- a/hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/factories/TryCatchBlockFactory.java	Mon May 16 17:01:53 2016 +0300
+++ b/hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/factories/TryCatchBlockFactory.java	Wed May 18 20:19:23 2016 +0300
@@ -25,8 +25,9 @@
 
 import java.util.ArrayList;
 import java.util.List;
+
+import jdk.test.lib.jittester.Block;
 import jdk.test.lib.jittester.CatchBlock;
-import jdk.test.lib.jittester.IRNode;
 import jdk.test.lib.jittester.ProductionFailedException;
 import jdk.test.lib.jittester.TryCatchBlock;
 import jdk.test.lib.jittester.Type;
@@ -35,7 +36,7 @@
 import jdk.test.lib.jittester.types.TypeKlass;
 import jdk.test.lib.jittester.utils.PseudoRandom;
 
-class TryCatchBlockFactory extends Factory {
+class TryCatchBlockFactory extends Factory<TryCatchBlock> {
     private final static double CATCH_SELECTION_COEF = 0.1d;
     private final Type returnType;
     private final long complexityLimit;
@@ -64,7 +65,7 @@
     }
 
     @Override
-    public IRNode produce() throws ProductionFailedException {
+    public TryCatchBlock produce() throws ProductionFailedException {
         if (complexityLimit < 1 || statementLimit < 1) {
             throw new ProductionFailedException();
         }
@@ -77,7 +78,7 @@
                 .setCanHaveReturn(canHaveReturn)
                 .setCanHaveContinues(canHaveContinues)
                 .setCanHaveBreaks(canHaveBreaks);
-        IRNode body = getBlock(builder, 0.6);
+        Block body = getBlock(builder, 0.6);
         int catchBlocksCount = (int) (CATCH_SELECTION_COEF
                 * PseudoRandom.random() * uncheckedThrowables.size());
         List<CatchBlock> catchBlocks = new ArrayList<>();
@@ -92,7 +93,7 @@
             catchBlocks.add(new CatchBlock(getBlock(builder, 0.3/catchBlocksCount),
                     whatToCatch, level));
         }
-        IRNode finallyBody = PseudoRandom.randomBoolean() || catchBlocksCount == 0 ? getBlock(builder, 0.1) : null;
+        Block finallyBody = PseudoRandom.randomBoolean() || catchBlocksCount == 0 ? getBlock(builder, 0.1) : null;
         return new TryCatchBlock(body, finallyBody, catchBlocks, level);
     }
 
@@ -106,7 +107,7 @@
         return selected;
     }
 
-    private IRNode getBlock(IRNodeBuilder builder, double weight)
+    private Block getBlock(IRNodeBuilder builder, double weight)
             throws ProductionFailedException {
         long actualComplexityLim = (long) (weight * PseudoRandom.random()
                 * complexityLimit);
--- a/hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/factories/UnaryOperatorFactory.java	Mon May 16 17:01:53 2016 +0300
+++ b/hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/factories/UnaryOperatorFactory.java	Wed May 18 20:19:23 2016 +0300
@@ -23,13 +23,13 @@
 
 package jdk.test.lib.jittester.factories;
 
-import jdk.test.lib.jittester.IRNode;
 import jdk.test.lib.jittester.OperatorKind;
 import jdk.test.lib.jittester.ProductionFailedException;
 import jdk.test.lib.jittester.SymbolTable;
 import jdk.test.lib.jittester.Type;
+import jdk.test.lib.jittester.UnaryOperator;
 
-public abstract class UnaryOperatorFactory extends OperatorFactory {
+public abstract class UnaryOperatorFactory extends OperatorFactory<UnaryOperator> {
     protected final OperatorKind opKind;
     protected final Type resultType;
     protected final Type ownerClass;
@@ -42,16 +42,16 @@
         this.ownerClass = ownerClass;
     }
 
-    protected Type generateType() throws ProductionFailedException {
+    protected Type generateType() {
         return resultType;
     }
 
-    protected abstract IRNode generateProduction(Type type) throws ProductionFailedException;
+    protected abstract UnaryOperator generateProduction(Type type) throws ProductionFailedException;
 
     protected abstract boolean isApplicable(Type resultType);
 
     @Override
-    public IRNode produce() throws ProductionFailedException {
+    public UnaryOperator produce() throws ProductionFailedException {
         if (!isApplicable(resultType)) {
             //avoid implicit use of resultType.toString()
             throw new ProductionFailedException("Type " + resultType.getName()
@@ -65,7 +65,7 @@
         }
         try {
             SymbolTable.push();
-            IRNode result = generateProduction(type);
+            UnaryOperator result = generateProduction(type);
             SymbolTable.merge();
             return result;
         } catch (ProductionFailedException e) {
--- a/hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/factories/UnaryPlusMinusOperatorFactory.java	Mon May 16 17:01:53 2016 +0300
+++ b/hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/factories/UnaryPlusMinusOperatorFactory.java	Wed May 18 20:19:23 2016 +0300
@@ -24,15 +24,12 @@
 package jdk.test.lib.jittester.factories;
 
 import jdk.test.lib.jittester.BuiltInType;
-import jdk.test.lib.jittester.IRNode;
 import jdk.test.lib.jittester.OperatorKind;
 import jdk.test.lib.jittester.ProductionFailedException;
 import jdk.test.lib.jittester.Type;
 import jdk.test.lib.jittester.TypeList;
 import jdk.test.lib.jittester.utils.TypeUtil;
 import jdk.test.lib.jittester.UnaryOperator;
-import jdk.test.lib.jittester.types.TypeBoolean;
-import jdk.test.lib.jittester.types.TypeInt;
 import jdk.test.lib.jittester.types.TypeKlass;
 import jdk.test.lib.jittester.utils.PseudoRandom;
 
@@ -44,16 +41,16 @@
 
     @Override
     protected boolean isApplicable(Type resultType) {
-        if (!TypeList.isBuiltIn(resultType) || resultType.equals(new TypeBoolean())) {
+        if (!TypeList.isBuiltIn(resultType) || resultType.equals(TypeList.BOOLEAN)) {
             return false;
         }
         BuiltInType resType = (BuiltInType) resultType;
-        return resType.equals(new TypeInt()) || resType.isMoreCapaciousThan(new TypeInt());
+        return resType.equals(TypeList.INT) || resType.isMoreCapaciousThan(TypeList.INT);
     }
 
     @Override
-    protected Type generateType() throws ProductionFailedException {
-        if (resultType.equals(new TypeInt())) {
+    protected Type generateType() {
+        if (resultType.equals(TypeList.INT)) {
             return PseudoRandom.randomElement(TypeUtil.getImplicitlyCastable(TypeList.getBuiltIn(), resultType));
         } else {
             return resultType;
@@ -61,7 +58,7 @@
     }
 
     @Override
-    protected IRNode generateProduction(Type type) throws ProductionFailedException {
+    protected UnaryOperator generateProduction(Type type) throws ProductionFailedException {
         return new UnaryOperator(opKind, new IRNodeBuilder()
                 .setComplexityLimit(complexityLimit)
                 .setOperatorLimit(operatorLimit)
--- a/hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/factories/VariableDeclarationBlockFactory.java	Mon May 16 17:01:53 2016 +0300
+++ b/hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/factories/VariableDeclarationBlockFactory.java	Wed May 18 20:19:23 2016 +0300
@@ -24,14 +24,15 @@
 package jdk.test.lib.jittester.factories;
 
 import java.util.ArrayList;
-import jdk.test.lib.jittester.IRNode;
+
+import jdk.test.lib.jittester.Declaration;
 import jdk.test.lib.jittester.ProductionFailedException;
 import jdk.test.lib.jittester.ProductionParams;
 import jdk.test.lib.jittester.VariableDeclarationBlock;
 import jdk.test.lib.jittester.types.TypeKlass;
 import jdk.test.lib.jittester.utils.PseudoRandom;
 
-class VariableDeclarationBlockFactory extends Factory {
+class VariableDeclarationBlockFactory extends Factory<VariableDeclarationBlock> {
     private final long complexityLimit;
     private final int operatorLimit;
     private final boolean exceptionSafe;
@@ -48,10 +49,10 @@
     }
 
     @Override
-    public IRNode produce() throws ProductionFailedException {
-        ArrayList<IRNode> content = new ArrayList<>();
+    public VariableDeclarationBlock produce() throws ProductionFailedException {
+        ArrayList<Declaration> content = new ArrayList<>();
         int limit = (int) Math.ceil(PseudoRandom.random() * ProductionParams.dataMemberLimit.value());
-        DeclarationFactory declFactory = new IRNodeBuilder()
+        Factory<Declaration> declFactory = new IRNodeBuilder()
                 .setOwnerKlass(ownerClass)
                 .setComplexityLimit(complexityLimit)
                 .setOperatorLimit(operatorLimit)
--- a/hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/factories/VariableDeclarationFactory.java	Mon May 16 17:01:53 2016 +0300
+++ b/hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/factories/VariableDeclarationFactory.java	Wed May 18 20:19:23 2016 +0300
@@ -24,7 +24,7 @@
 package jdk.test.lib.jittester.factories;
 
 import java.util.LinkedList;
-import jdk.test.lib.jittester.IRNode;
+
 import jdk.test.lib.jittester.ProductionFailedException;
 import jdk.test.lib.jittester.SymbolTable;
 import jdk.test.lib.jittester.Type;
@@ -34,10 +34,10 @@
 import jdk.test.lib.jittester.types.TypeKlass;
 import jdk.test.lib.jittester.utils.PseudoRandom;
 
-class VariableDeclarationFactory extends Factory {
-    protected final boolean isStatic;
-    protected final boolean isLocal;
-    protected final TypeKlass ownerClass;
+class VariableDeclarationFactory extends Factory<VariableDeclaration> {
+    private final boolean isStatic;
+    private final boolean isLocal;
+    private final TypeKlass ownerClass;
     private Type resultType;
 
     VariableDeclarationFactory(TypeKlass ownerClass, boolean isStatic, boolean isLocal, Type resultType) {
@@ -48,8 +48,8 @@
     }
 
     @Override
-    public  IRNode produce() throws ProductionFailedException {
-        if (resultType == TypeList.getVoid()) {
+    public VariableDeclaration produce() throws ProductionFailedException {
+        if (resultType.equals(TypeList.VOID)) {
             LinkedList<Type> types = new LinkedList<>(TypeList.getAll());
             PseudoRandom.shuffle(types);
             if (types.isEmpty()) {
--- a/hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/factories/VariableFactory.java	Mon May 16 17:01:53 2016 +0300
+++ b/hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/factories/VariableFactory.java	Wed May 18 20:19:23 2016 +0300
@@ -23,15 +23,15 @@
 
 package jdk.test.lib.jittester.factories;
 
-import jdk.test.lib.jittester.IRNode;
 import jdk.test.lib.jittester.ProductionFailedException;
 import jdk.test.lib.jittester.Rule;
 import jdk.test.lib.jittester.Type;
+import jdk.test.lib.jittester.VariableBase;
 import jdk.test.lib.jittester.VariableInfo;
 import jdk.test.lib.jittester.types.TypeKlass;
 
-class VariableFactory extends Factory {
-    private final Rule rule;
+class VariableFactory extends Factory<VariableBase> {
+    private final Rule<VariableBase> rule;
 
     VariableFactory(long complexityLimit, int operatorLimit, TypeKlass ownerClass, Type resultType,
             boolean constant, boolean initialized, boolean exceptionSafe, boolean noconsts) {
@@ -42,7 +42,7 @@
         if (initialized) {
             flags |= VariableInfo.INITIALIZED;
         }
-        rule = new Rule("variable");
+        rule = new Rule<>("variable");
         IRNodeBuilder b = new IRNodeBuilder().setResultType(resultType)
                 .setFlags(flags)
                 .setComplexityLimit(complexityLimit)
@@ -55,7 +55,7 @@
     }
 
     @Override
-    public IRNode produce() throws ProductionFailedException {
+    public VariableBase produce() throws ProductionFailedException {
         return rule.produce();
     }
 }
--- a/hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/factories/VariableInitializationFactory.java	Mon May 16 17:01:53 2016 +0300
+++ b/hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/factories/VariableInitializationFactory.java	Wed May 18 20:19:23 2016 +0300
@@ -37,7 +37,7 @@
 import jdk.test.lib.jittester.types.TypeKlass;
 import jdk.test.lib.jittester.utils.PseudoRandom;
 
-class VariableInitializationFactory extends SafeFactory {
+class VariableInitializationFactory extends SafeFactory<VariableInitialization> {
     private final int operatorLimit;
     private final long complexityLimit;
     private final boolean constant;
@@ -58,7 +58,7 @@
     }
 
     @Override
-    protected IRNode sproduce() throws ProductionFailedException {
+    protected VariableInitialization sproduce() throws ProductionFailedException {
         LinkedList<Type> types = new LinkedList<>(TypeList.getAll());
         PseudoRandom.shuffle(types);
         if (types.isEmpty()) {
@@ -71,7 +71,7 @@
                 .setResultType(resultType)
                 .setExceptionSafe(exceptionSafe)
                 .setNoConsts(false);
-        Rule rule = new Rule("initializer");
+        Rule<IRNode> rule = new Rule<>("initializer");
         rule.add("literal_initializer", b.getLiteralFactory());
         if (!ProductionParams.disableExprInInit.value()) {
             rule.add("expression", b.getLimitedExpressionFactory());
--- a/hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/factories/WhileFactory.java	Mon May 16 17:01:53 2016 +0300
+++ b/hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/factories/WhileFactory.java	Wed May 18 20:19:23 2016 +0300
@@ -23,21 +23,21 @@
 
 package jdk.test.lib.jittester.factories;
 
-import jdk.test.lib.jittester.IRNode;
-import jdk.test.lib.jittester.Initialization;
+import jdk.test.lib.jittester.Block;
 import jdk.test.lib.jittester.Literal;
 import jdk.test.lib.jittester.LocalVariable;
-import jdk.test.lib.jittester.Nothing;
 import jdk.test.lib.jittester.ProductionFailedException;
 import jdk.test.lib.jittester.SymbolTable;
 import jdk.test.lib.jittester.Type;
+import jdk.test.lib.jittester.TypeList;
 import jdk.test.lib.jittester.loops.Loop;
 import jdk.test.lib.jittester.loops.While;
 import jdk.test.lib.jittester.types.TypeKlass;
-import jdk.test.lib.jittester.types.TypeInt;
 import jdk.test.lib.jittester.utils.PseudoRandom;
 
-class WhileFactory extends SafeFactory {
+import java.util.LinkedList;
+
+class WhileFactory extends SafeFactory<While> {
     private final Loop loop;
     private final long complexityLimit;
     private final int statementLimit;
@@ -61,7 +61,8 @@
     }
 
     @Override
-    protected IRNode sproduce() throws ProductionFailedException {
+    protected While sproduce() throws ProductionFailedException {
+        Block emptyBlock = new Block(ownerClass, returnType, new LinkedList<>(), level - 1);
         if (statementLimit <= 0 || complexityLimit <= 0) {
             throw new ProductionFailedException();
         }
@@ -91,7 +92,7 @@
                 .setResultType(returnType)
                 .setOperatorLimit(operatorLimit);
         loop.initialization = builder.getCounterInitializerFactory(0).produce();
-        IRNode header;
+        Block header;
         try {
             header = builder.setComplexityLimit(headerComplLimit)
                     .setStatementLimit(headerStatementLimit)
@@ -103,15 +104,15 @@
                     .getBlockFactory()
                     .produce();
         } catch (ProductionFailedException e) {
-            header = new Nothing();
+            header = emptyBlock;
         }
-        LocalVariable counter = new LocalVariable(((Initialization) loop.initialization).get());
-        Literal limiter = new Literal(Integer.valueOf((int) thisLoopIterLimit), new TypeInt());
+        LocalVariable counter = new LocalVariable(loop.initialization.getVariableInfo());
+        Literal limiter = new Literal((int) thisLoopIterLimit, TypeList.INT);
         loop.condition = builder.setComplexityLimit(condComplLimit)
                 .setLocalVariable(counter)
                 .getLoopingConditionFactory(limiter)
                 .produce();
-        IRNode body1;
+        Block body1;
         SymbolTable.push();
         try {
             body1 = builder.setComplexityLimit(body1ComplLimit)
@@ -124,10 +125,10 @@
                     .getBlockFactory()
                     .produce();
         } catch (ProductionFailedException e) {
-            body1 = new Nothing();
+            body1 = emptyBlock;
         }
         loop.manipulator = builder.setLocalVariable(counter).getCounterManipulatorFactory().produce();
-        IRNode body2;
+        Block body2;
         try {
             body2 = builder.setComplexityLimit(body2ComplLimit)
                     .setStatementLimit(body2StatementLimit)
@@ -139,9 +140,9 @@
                     .getBlockFactory()
                     .produce();
         } catch (ProductionFailedException e) {
-            body2 = new Nothing();
+            body2 = emptyBlock;
         }
-        IRNode body3;
+        Block body3;
         try {
             body3 = builder.setComplexityLimit(body3ComplLimit)
                     .setStatementLimit(body3StatementLimit)
@@ -153,7 +154,7 @@
                     .getBlockFactory()
                     .produce();
         } catch (ProductionFailedException e) {
-            body3 = new Nothing();
+            body3 = emptyBlock;
         }
         SymbolTable.pop();
         return new While(level, loop, thisLoopIterLimit, header, body1, body2, body3);
--- a/hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/functions/ArgumentDeclaration.java	Mon May 16 17:01:53 2016 +0300
+++ b/hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/functions/ArgumentDeclaration.java	Wed May 18 20:19:23 2016 +0300
@@ -28,9 +28,10 @@
 import jdk.test.lib.jittester.visitors.Visitor;
 
 public class ArgumentDeclaration extends IRNode {
-    public VariableInfo variableInfo;
+    public final VariableInfo variableInfo;
 
     public ArgumentDeclaration(VariableInfo variableInfo) {
+        super(variableInfo.type);
         this.variableInfo = variableInfo;
     }
 
--- a/hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/functions/ConstructorDefinition.java	Mon May 16 17:01:53 2016 +0300
+++ b/hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/functions/ConstructorDefinition.java	Wed May 18 20:19:23 2016 +0300
@@ -32,7 +32,9 @@
 
     public ConstructorDefinition(FunctionInfo functionInfo,
             ArrayList<ArgumentDeclaration> argumentsDeclaration, IRNode body) {
+        super(functionInfo.type);
         this.functionInfo = functionInfo;
+        this.owner = functionInfo.owner;
         addChild(body);
         addChildren(argumentsDeclaration);
     }
--- a/hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/functions/ConstructorDefinitionBlock.java	Mon May 16 17:01:53 2016 +0300
+++ b/hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/functions/ConstructorDefinitionBlock.java	Wed May 18 20:19:23 2016 +0300
@@ -25,10 +25,12 @@
 
 import java.util.ArrayList;
 import jdk.test.lib.jittester.IRNode;
+import jdk.test.lib.jittester.TypeList;
 import jdk.test.lib.jittester.visitors.Visitor;
 
 public class ConstructorDefinitionBlock extends IRNode {
     public ConstructorDefinitionBlock(ArrayList<IRNode> content, int level) {
+        super(TypeList.VOID);
         this.level = level;
         addChildren(content);
     }
--- a/hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/functions/Function.java	Mon May 16 17:01:53 2016 +0300
+++ b/hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/functions/Function.java	Wed May 18 20:19:23 2016 +0300
@@ -36,7 +36,8 @@
     private FunctionInfo functionInfo = new FunctionInfo();
 
     public Function(TypeKlass ownerClass, FunctionInfo functionInfo, List<IRNode> args) {
-        setKlass(ownerClass);
+        super(functionInfo.type);
+        setOwner(ownerClass);
         this.functionInfo = functionInfo;
         addChildren(args);
     }
@@ -48,14 +49,14 @@
             argsComplexity += child.complexity();
         }
         long funcComplexity = functionInfo.complexity;
-        TypeKlass typeKlass = (TypeKlass) this.klass;
+        TypeKlass typeKlass = this.owner;
         if (functionInfo.isConstructor()) {
             // Sum complexities of all default constructors of parent classes
             for (TypeKlass parent : typeKlass.getAllParents()) {
                 Collection<Symbol> parentFuncs = SymbolTable.getAllCombined(parent, FunctionInfo.class);
                 for (Symbol f : parentFuncs) {
                     FunctionInfo c = (FunctionInfo) f;
-                    if (c.name.equals(c.klass.getName()) && c.argTypes.isEmpty()) {
+                    if (c.name.equals(c.owner.getName()) && c.argTypes.isEmpty()) {
                         funcComplexity += c.complexity;
                     }
                 }
@@ -66,7 +67,7 @@
             for (TypeKlass child : typeKlass.getAllChildren()) {
                 Collection<Symbol> childFuncs = SymbolTable.getAllCombined(child, FunctionInfo.class);
                 for (Symbol childFunc : childFuncs) {
-                    if (((FunctionInfo) childFunc).equals(functionInfo)) {
+                    if (childFunc.equals(functionInfo)) {
                         funcComplexity = Math.max(funcComplexity, ((FunctionInfo) childFunc).complexity);
                     }
                 }
--- a/hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/functions/FunctionDeclaration.java	Mon May 16 17:01:53 2016 +0300
+++ b/hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/functions/FunctionDeclaration.java	Wed May 18 20:19:23 2016 +0300
@@ -32,7 +32,9 @@
 
     public FunctionDeclaration(FunctionInfo functionInfo,
             ArrayList<ArgumentDeclaration> argumentsDeclaration) {
+        super(functionInfo.type);
         this.functionInfo = functionInfo;
+        this.owner = functionInfo.owner;
         addChildren(argumentsDeclaration);
     }
 
--- a/hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/functions/FunctionDeclarationBlock.java	Mon May 16 17:01:53 2016 +0300
+++ b/hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/functions/FunctionDeclarationBlock.java	Wed May 18 20:19:23 2016 +0300
@@ -25,12 +25,14 @@
 
 import java.util.ArrayList;
 import jdk.test.lib.jittester.IRNode;
+import jdk.test.lib.jittester.TypeList;
 import jdk.test.lib.jittester.types.TypeKlass;
 import jdk.test.lib.jittester.visitors.Visitor;
 
 public class FunctionDeclarationBlock extends IRNode {
     public FunctionDeclarationBlock(TypeKlass ownerClass, ArrayList<IRNode> content, int level) {
-        setKlass(ownerClass);
+        super(TypeList.VOID);
+        setOwner(ownerClass);
         this.level = level;
         addChildren(content);
     }
--- a/hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/functions/FunctionDefinition.java	Mon May 16 17:01:53 2016 +0300
+++ b/hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/functions/FunctionDefinition.java	Wed May 18 20:19:23 2016 +0300
@@ -23,9 +23,10 @@
 
 package jdk.test.lib.jittester.functions;
 
-import java.util.ArrayList;
 import java.util.Collection;
 import java.util.LinkedList;
+import java.util.List;
+
 import jdk.test.lib.jittester.IRNode;
 import jdk.test.lib.jittester.Symbol;
 import jdk.test.lib.jittester.SymbolTable;
@@ -36,8 +37,10 @@
     private final FunctionInfo functionInfo;
 
     public FunctionDefinition(FunctionInfo functionInfo,
-            ArrayList<ArgumentDeclaration> argumentsDeclaration, IRNode body, IRNode ret) {
+                              List<? extends ArgumentDeclaration> argumentsDeclaration, IRNode body, Return ret) {
+        super(functionInfo.type);
         this.functionInfo = functionInfo;
+        this.owner = functionInfo.owner;
         addChild(body);
         addChild(ret);
         addChildren(argumentsDeclaration);
--- a/hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/functions/FunctionDefinitionBlock.java	Mon May 16 17:01:53 2016 +0300
+++ b/hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/functions/FunctionDefinitionBlock.java	Wed May 18 20:19:23 2016 +0300
@@ -25,12 +25,14 @@
 
 import java.util.ArrayList;
 import jdk.test.lib.jittester.IRNode;
+import jdk.test.lib.jittester.TypeList;
 import jdk.test.lib.jittester.types.TypeKlass;
 import jdk.test.lib.jittester.visitors.Visitor;
 
 public class FunctionDefinitionBlock extends IRNode {
     public FunctionDefinitionBlock(ArrayList<IRNode> content, int level, TypeKlass ownerClass) {
-        setKlass(ownerClass);
+        super(TypeList.VOID);
+        setOwner(ownerClass);
         addChildren(content);
         this.level = level;
     }
@@ -44,10 +46,6 @@
         return complexity;
     }
 
-    protected int size() {
-        return getChildren() != null ? getChildren().size() : 0;
-    }
-
     @Override
     public<T> T accept(Visitor<T> v) {
         return v.visit(this);
--- a/hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/functions/FunctionInfo.java	Mon May 16 17:01:53 2016 +0300
+++ b/hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/functions/FunctionInfo.java	Wed May 18 20:19:23 2016 +0300
@@ -25,6 +25,7 @@
 
 import java.util.ArrayList;
 import java.util.Arrays;
+
 import jdk.test.lib.jittester.Symbol;
 import jdk.test.lib.jittester.Type;
 import jdk.test.lib.jittester.VariableInfo;
@@ -89,7 +90,7 @@
 
         try {
             FunctionInfo f = (FunctionInfo) o;
-            return klass.equals(f.klass) && hasEqualSignature(o);
+            return owner.equals(f.owner) && hasEqualSignature(o);
         } catch (Exception e) {
         }
         return false;
@@ -117,7 +118,7 @@
     }
 
     public boolean isConstructor() {
-        return name.equals(klass.getName());
+        return name.equals(owner.getName());
     }
 
     @Override
--- a/hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/functions/FunctionRedefinition.java	Mon May 16 17:01:53 2016 +0300
+++ b/hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/functions/FunctionRedefinition.java	Wed May 18 20:19:23 2016 +0300
@@ -23,16 +23,19 @@
 
 package jdk.test.lib.jittester.functions;
 
-import java.util.ArrayList;
+import java.util.List;
+
 import jdk.test.lib.jittester.IRNode;
 import jdk.test.lib.jittester.visitors.Visitor;
 
 public class FunctionRedefinition extends IRNode {
     private final FunctionInfo functionInfo;
 
-    protected FunctionRedefinition(FunctionInfo functionInfo,
-            ArrayList<ArgumentDeclaration> argumentsDeclaration, IRNode body, IRNode ret) {
+    public FunctionRedefinition(FunctionInfo functionInfo,
+                                   List<? extends ArgumentDeclaration> argumentsDeclaration, IRNode body, Return ret) {
+        super(functionInfo.type);
         this.functionInfo = functionInfo;
+        this.owner = functionInfo.owner;
         addChild(body);
         addChild(ret);
         addChildren(argumentsDeclaration);
--- a/hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/functions/FunctionRedefinitionBlock.java	Mon May 16 17:01:53 2016 +0300
+++ b/hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/functions/FunctionRedefinitionBlock.java	Wed May 18 20:19:23 2016 +0300
@@ -25,10 +25,12 @@
 
 import java.util.ArrayList;
 import jdk.test.lib.jittester.IRNode;
+import jdk.test.lib.jittester.TypeList;
 import jdk.test.lib.jittester.visitors.Visitor;
 
 public class FunctionRedefinitionBlock extends IRNode {
     public FunctionRedefinitionBlock(ArrayList<IRNode> content, int level) {
+        super(TypeList.VOID);
         this.level = level;
         addChildren(content);
     }
@@ -42,10 +44,6 @@
         return complexity;
     }
 
-    protected int size() {
-        return getChildren() != null ? getChildren().size() : 0;
-    }
-
     @Override
     public<T> T accept(Visitor<T> v) {
         return v.visit(this);
--- a/hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/functions/Return.java	Mon May 16 17:01:53 2016 +0300
+++ b/hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/functions/Return.java	Wed May 18 20:19:23 2016 +0300
@@ -30,6 +30,7 @@
     private final IRNode returnExpression;
 
     public Return(IRNode returnExpression) {
+        super(returnExpression.getResultType());
         this.returnExpression = returnExpression;
         addChild(returnExpression);
     }
--- a/hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/functions/StaticConstructorDefinition.java	Mon May 16 17:01:53 2016 +0300
+++ b/hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/functions/StaticConstructorDefinition.java	Wed May 18 20:19:23 2016 +0300
@@ -28,6 +28,8 @@
 
 public class StaticConstructorDefinition extends IRNode {
     public StaticConstructorDefinition(IRNode body) {
+        super(body.getResultType());
+        this.owner = body.getOwner();
         addChild(body);
     }
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/jtreg/Printer.java	Wed May 18 20:19:23 2016 +0300
@@ -0,0 +1,165 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package jdk.test.lib.jittester.jtreg;
+
+import java.util.Stack;
+
+public class Printer {
+
+    public static String print(boolean arg) {
+        return String.valueOf(arg);
+    }
+
+    public static String print(byte arg) {
+        return String.valueOf(arg);
+    }
+
+    public static String print(short arg) {
+        return String.valueOf(arg);
+    }
+
+    public static String print(char arg) {
+        return String.valueOf((int) arg);
+    }
+
+    public static String print(int arg) {
+        return String.valueOf(arg);
+    }
+
+    public static String print(long arg) {
+        return String.valueOf(arg);
+    }
+
+    public static String print(float arg) {
+        return String.valueOf(arg);
+    }
+
+    public static String print(double arg) {
+        return String.valueOf(arg);
+    }
+
+    public static String print(Object arg) {
+        return print_r(new Stack<>(), arg);
+    }
+
+    private static String print_r(Stack<Object> visitedObjects, Object arg) {
+        String result = "";
+        if (arg == null) {
+            result += "null";
+        } else if (arg.getClass().isArray()) {
+            for (int i = 0; i < visitedObjects.size(); i++) {
+                if (visitedObjects.elementAt(i) == arg) {
+                    return "<recursive>";
+                }
+            }
+
+            visitedObjects.push(arg);
+
+            final String delimiter = ", ";
+            result += "[";
+
+            if (arg instanceof Object[]) {
+                Object[] array = (Object[]) arg;
+                for (int i = 0; i < array.length; i++) {
+                    result += print_r(visitedObjects, array[i]);
+                    if (i < array.length - 1) {
+                        result += delimiter;
+                    }
+                }
+            } else if (arg instanceof boolean[]) {
+                boolean[] array = (boolean[]) arg;
+                for (int i = 0; i < array.length; i++) {
+                    result += print(array[i]);
+                    if (i < array.length - 1) {
+                        result += delimiter;
+                    }
+                }
+            } else if (arg instanceof byte[]) {
+                byte[] array = (byte[]) arg;
+                for (int i = 0; i < array.length; i++) {
+                    result += print(array[i]);
+                    if (i < array.length - 1) {
+                        result += delimiter;
+                    }
+                }
+            } else if (arg instanceof short[]) {
+                short[] array = (short[]) arg;
+                for (int i = 0; i < array.length; i++) {
+                    result += print(array[i]);
+                    if (i < array.length - 1) {
+                        result += delimiter;
+                    }
+                }
+            } else if (arg instanceof char[]) {
+                char[] array = (char[]) arg;
+                for (int i = 0; i < array.length; i++) {
+                    result += print(array[i]);
+                    if (i < array.length - 1) {
+                        result += delimiter;
+                    }
+                }
+            } else if (arg instanceof int[]) {
+                int[] array = (int[]) arg;
+                for (int i = 0; i < array.length; i++) {
+                    result += print(array[i]);
+                    if (i < array.length - 1) {
+                        result += delimiter;
+                    }
+                }
+            } else if (arg instanceof long[]) {
+                long[] array = (long[]) arg;
+                for (int i = 0; i < array.length; i++) {
+                    result += print(array[i]);
+                    if (i < array.length - 1) {
+                        result += delimiter;
+                    }
+                }
+            } else if (arg instanceof float[]) {
+                float[] array = (float[]) arg;
+                for (int i = 0; i < array.length; i++) {
+                    result += print(array[i]);
+                    if (i < array.length - 1) {
+                        result += delimiter;
+                    }
+                }
+            } else if (arg instanceof double[]) {
+                double[] array = (double[]) arg;
+                for (int i = 0; i < array.length; i++) {
+                    result += print(array[i]);
+                    if (i < array.length - 1) {
+                        result += delimiter;
+                    }
+                }
+            }
+
+            result += "]";
+            visitedObjects.pop();
+
+        } else {
+            result += arg.toString();
+        }
+
+        return result;
+    }
+}
--- a/hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/loops/CounterManipulator.java	Mon May 16 17:01:53 2016 +0300
+++ b/hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/loops/CounterManipulator.java	Wed May 18 20:19:23 2016 +0300
@@ -25,6 +25,7 @@
 
 import jdk.test.lib.jittester.IRNode;
 import jdk.test.lib.jittester.LocalVariable;
+import jdk.test.lib.jittester.Statement;
 import jdk.test.lib.jittester.visitors.Visitor;
 
 /*
@@ -36,7 +37,8 @@
 public class CounterManipulator extends IRNode {
     LocalVariable counter;
 
-    public CounterManipulator(IRNode manipulator) {
+    public CounterManipulator(Statement manipulator) {
+        super(manipulator.getResultType());
         addChild(manipulator);
     }
 
--- a/hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/loops/DoWhile.java	Mon May 16 17:01:53 2016 +0300
+++ b/hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/loops/DoWhile.java	Wed May 18 20:19:23 2016 +0300
@@ -42,7 +42,7 @@
         HEADER,
         BODY1,
         BODY2,
-    };
+    }
     private final Loop loop;
     // header;                  [subblock]
     // do {
@@ -52,8 +52,9 @@
     // } while(condition);
     private long thisLoopIterLimit = 0;
 
-    public DoWhile(int level, Loop loop, long thisLoopIterLimit, IRNode header,
-            IRNode body1, IRNode body2) {
+    public DoWhile(int level, Loop loop, long thisLoopIterLimit, Block header,
+                   Block body1, Block body2) {
+        super(body1.getResultType());
         this.level = level;
         this.loop = loop;
         this.thisLoopIterLimit = thisLoopIterLimit;
@@ -85,13 +86,12 @@
         IRNode header = getChildren().get(DoWhilePart.HEADER.ordinal());
         List<IRNode> siblings = getParent().getChildren();
         int index = siblings.indexOf(this);
+        siblings.set(index++, loop.initialization);
         if (header instanceof Block) {
-            siblings.remove(this);
             siblings.addAll(index, header.getChildren());
         } else {
-            siblings.set(index, header);
+            siblings.add(index, header);
         }
-        siblings.add(index + header.getChildren().size(), loop.initialization);
         return true;
     }
 }
--- a/hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/loops/For.java	Mon May 16 17:01:53 2016 +0300
+++ b/hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/loops/For.java	Wed May 18 20:19:23 2016 +0300
@@ -26,6 +26,7 @@
 import java.util.List;
 import jdk.test.lib.jittester.Block;
 import jdk.test.lib.jittester.IRNode;
+import jdk.test.lib.jittester.Statement;
 import jdk.test.lib.jittester.visitors.Visitor;
 
 public class For extends IRNode {
@@ -45,7 +46,7 @@
         BODY1,
         BODY2,
         BODY3,
-    };
+    }
 
     private final Loop loop;
     // header;                       // [subblock]
@@ -57,8 +58,9 @@
     // }
     private long thisLoopIterLimit = 0;
     public For(int level, Loop loop, long thisLoopIterLimit,
-            IRNode header, IRNode statement1,
-            IRNode statement2, IRNode body1, IRNode body2, IRNode body3) {
+               Block header, Statement statement1,
+               Statement statement2, Block body1, Block body2, Block body3) {
+        super(body1.getResultType());
         this.level = level;
         this.loop = loop;
         this.thisLoopIterLimit = thisLoopIterLimit;
@@ -100,13 +102,12 @@
         IRNode header = getChildren().get(ForPart.HEADER.ordinal());
         List<IRNode> siblings = getParent().getChildren();
         int index = siblings.indexOf(this);
+        siblings.set(index++, loop.initialization);
         if (header instanceof Block) {
-            siblings.remove(this);
             siblings.addAll(index, header.getChildren());
         } else {
-            siblings.set(index, header);
+            siblings.add(index, header);
         }
-        siblings.add(index + header.getChildren().size(), loop.initialization);
         return true;
     }
 }
--- a/hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/loops/Loop.java	Mon May 16 17:01:53 2016 +0300
+++ b/hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/loops/Loop.java	Wed May 18 20:19:23 2016 +0300
@@ -23,11 +23,10 @@
 
 package jdk.test.lib.jittester.loops;
 
-import jdk.test.lib.jittester.IRNode;
 
 // Just a structure to hold the values needed to handle basic loop production
 public class Loop {
-    public IRNode initialization;
-    public IRNode condition;
-    public IRNode manipulator;
+    public CounterInitializer initialization;
+    public LoopingCondition condition;
+    public CounterManipulator manipulator;
 }
--- a/hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/loops/LoopingCondition.java	Mon May 16 17:01:53 2016 +0300
+++ b/hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/loops/LoopingCondition.java	Wed May 18 20:19:23 2016 +0300
@@ -30,6 +30,7 @@
     private final IRNode condition;
 
     public LoopingCondition(IRNode condition) {
+        super(condition.getResultType());
         this.condition = condition;
         addChild(condition);
     }
--- a/hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/loops/While.java	Mon May 16 17:01:53 2016 +0300
+++ b/hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/loops/While.java	Wed May 18 20:19:23 2016 +0300
@@ -38,7 +38,7 @@
         BODY1,
         BODY2,
         BODY3,
-    };
+    }
 
     private final Loop loop;
     // int counter = x;
@@ -51,8 +51,9 @@
     // }
     private final long thisLoopIterLimit;
 
-    public While(int level, Loop loop, long thisLoopIterLimit, IRNode header,
-            IRNode body1, IRNode body2, IRNode body3) {
+    public While(int level, Loop loop, long thisLoopIterLimit, Block header,
+                 Block body1, Block body2, Block body3) {
+        super(body1.getResultType());
         this.loop = loop;
         this.level = level;
         this.thisLoopIterLimit = thisLoopIterLimit;
@@ -88,13 +89,12 @@
         IRNode header = getChildren().get(WhilePart.HEADER.ordinal());
         List<IRNode> siblings = getParent().getChildren();
         int index = siblings.indexOf(this);
+        siblings.set(index++, loop.initialization);
         if (header instanceof Block) {
-            siblings.remove(this);
             siblings.addAll(index, header.getChildren());
         } else {
-            siblings.set(index, header);
+            siblings.add(index, header);
         }
-        siblings.add(index + header.getChildren().size(), loop.initialization);
         return true;
     }
 
--- a/hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/types/TypeArray.java	Mon May 16 17:01:53 2016 +0300
+++ b/hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/types/TypeArray.java	Wed May 18 20:19:23 2016 +0300
@@ -26,6 +26,9 @@
 import java.util.ArrayList;
 import java.util.List;
 import java.util.Objects;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+
 import jdk.test.lib.jittester.ProductionParams;
 import jdk.test.lib.jittester.SymbolTable;
 import jdk.test.lib.jittester.Type;
@@ -47,26 +50,29 @@
     public final int dimensions;
     private List<Byte> dims = new ArrayList<>();
 
-    public TypeArray() {
-        this(new TypeVoid(), 0);
-    }
-
     public TypeArray(Type type, int dimensions) {
         super("Array", TypeKlass.FINAL);
-        addParent("java.lang.Object");
-        setParent((TypeKlass) TypeList.find("java.lang.Object"));
+        addParent(TypeList.OBJECT.getName());
+        setParent(TypeList.OBJECT);
         this.type = type;
         this.dimensions = dimensions;
     }
 
+    public String getName() {
+        String dimString = Stream.generate(() -> "[]")
+                .limit(dimensions)
+                .collect(Collectors.joining());
+        return type.getName() + dimString;
+    }
+
     @Override
     protected void exportSymbols() {
-        SymbolTable.add(new VariableInfo("length", this, new TypeInt(), VariableInfo.PUBLIC | VariableInfo.FINAL));
+        SymbolTable.add(new VariableInfo("length", this, TypeList.INT, VariableInfo.PUBLIC | VariableInfo.FINAL));
     }
 
     @Override
     public boolean equals(Object t) {
-                if (this == t) {
+        if (this == t) {
             return true;
         }
         if (t == null || !(t instanceof TypeArray)) {
@@ -95,8 +101,7 @@
 
     @Override
     public int compareTo(Type t) {
-        int r = 0;
-        r = super.compareTo(t);
+        int r = super.compareTo(t);
         if (r == 0) {
             try {
                 TypeArray a = (TypeArray) t;
--- a/hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/types/TypeKlass.java	Mon May 16 17:01:53 2016 +0300
+++ b/hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/types/TypeKlass.java	Wed May 18 20:19:23 2016 +0300
@@ -33,24 +33,27 @@
 import jdk.test.lib.jittester.TypeList;
 
 public class TypeKlass extends Type {
+    private TypeKlass parentKlass;
+    private final HashSet<String> parentsList;
+    private final HashSet<String> childrenList;
+    private final HashSet<Symbol> symbolsSet;
+    private int flags;
 
-    private TypeKlass parent;
-    private HashSet<String> parentsList;
-    private HashSet<String> childrenList;
-    private final HashSet<Symbol> symbolsSet;
     public static final int NONE = 0x00;
     public static final int FINAL = 0x01;
     public static final int INTERFACE = 0x02;
     public static final int ABSTRACT = 0x04;
-    private int flags = NONE;
+
 
     public TypeKlass(String name) {
-        this(name, 0);
+        this(name, NONE);
     }
 
     public TypeKlass(String name, int flags) {
         super(name);
         this.flags = flags;
+        parentsList = new HashSet<>();
+        childrenList = new HashSet<>();
         symbolsSet = new HashSet<>();
     }
 
@@ -76,39 +79,27 @@
 
     @Override
     protected void exportSymbols() {
-        symbolsSet.stream().forEach(symbol -> {
-            SymbolTable.add(symbol);
-        });
+        symbolsSet.stream().forEach(SymbolTable::add);
     }
 
     public void setParent(TypeKlass p) {
-        parent = p;
+        parentKlass = p;
     }
 
     public void addParent(String p) {
-        if (parentsList == null) {
-            parentsList = new HashSet<>();
-        }
         parentsList.add(p);
     }
 
     public void addChild(String c) {
-        if (childrenList == null) {
-            childrenList = new HashSet<>();
-        }
         childrenList.add(c);
     }
 
     protected void removeParent(String p) {
-        if (parentsList != null) {
-            parentsList.remove(p);
-        }
+        parentsList.remove(p);
     }
 
     protected void removeChild(String c) {
-        if (childrenList != null) {
-            childrenList.remove(c);
-        }
+        childrenList.remove(c);
     }
 
     public HashSet<String> getParentsNames() {
@@ -131,37 +122,27 @@
 
     public TreeSet<TypeKlass> getAllParents() {
         TreeSet<TypeKlass> result = new TreeSet<>();
-        if (parentsList != null) {
-            for (String parentName : parentsList) {
-                Type _parentKlass = TypeList.find(new TypeKlass(parentName));
-                if (_parentKlass != null) {
-                    try {
-                        TypeKlass parentKlass = (TypeKlass) _parentKlass;
-                        result.add(parentKlass);
-                        result.addAll(parentKlass.getAllParents());
-                    } catch (Exception e) {
-                    }
-                }
-            }
-        }
+        parentsList.stream()
+                .map(TypeList::find)
+                .filter(parentKlass -> parentKlass != null)
+                .map(parentKlass -> (TypeKlass) parentKlass)
+                .forEach(parentKlass -> {
+                    result.add(parentKlass);
+                    result.addAll(parentKlass.getAllParents());
+        });
         return result;
     }
 
     public TreeSet<TypeKlass> getAllChildren() {
         TreeSet<TypeKlass> r = new TreeSet<>();
-        if (childrenList != null) {
-            for (String childName : childrenList) {
-                Type _childKlass = TypeList.find(new TypeKlass(childName));
-                if (_childKlass != null) {
-                    try {
-                        TypeKlass childKlass = (TypeKlass) _childKlass;
-                        r.add(childKlass);
-                        r.addAll(childKlass.getAllChildren());
-                    } catch (Exception e) {
-                    }
-                }
-            }
-        }
+        childrenList.stream()
+                .map(TypeList::find)
+                .filter(childKlass -> childKlass != null)
+                .map(childKlass -> (TypeKlass) childKlass)
+                .forEach(childKlass -> {
+                    r.add(childKlass);
+                    r.addAll(childKlass.getAllChildren());
+        });
         return r;
     }
 
@@ -179,8 +160,11 @@
     // we cannot guarantee that no exception will occur.
     @Override
     public boolean canExplicitlyCastTo(Type t) {
+        if (equals(t)) {
+            return true;
+        }
         if (t instanceof TypeKlass && !ProductionParams.disableDowncasts.value()) {
-            return equals(t) || getAllChildren().contains(t);
+            return getAllChildren().contains(t);
         }
 
         return false;
@@ -205,4 +189,8 @@
     public boolean isInterface() {
         return (flags & INTERFACE) > 0;
     }
+
+    public TypeKlass getParent() {
+        return parentKlass;
+    }
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/utils/FixedTrees.java	Wed May 18 20:19:23 2016 +0300
@@ -0,0 +1,213 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package jdk.test.lib.jittester.utils;
+
+import java.util.ArrayList;
+import java.util.LinkedList;
+import java.util.List;
+import jdk.test.lib.jittester.BinaryOperator;
+import jdk.test.lib.jittester.Block;
+import jdk.test.lib.jittester.CatchBlock;
+import jdk.test.lib.jittester.IRNode;
+import jdk.test.lib.jittester.Literal;
+import jdk.test.lib.jittester.LocalVariable;
+import jdk.test.lib.jittester.NonStaticMemberVariable;
+import jdk.test.lib.jittester.Nothing;
+import jdk.test.lib.jittester.Operator;
+import jdk.test.lib.jittester.OperatorKind;
+import jdk.test.lib.jittester.PrintVariables;
+import jdk.test.lib.jittester.ProductionFailedException;
+import jdk.test.lib.jittester.Statement;
+import jdk.test.lib.jittester.StaticMemberVariable;
+import jdk.test.lib.jittester.Symbol;
+import jdk.test.lib.jittester.TryCatchBlock;
+import jdk.test.lib.jittester.Type;
+import jdk.test.lib.jittester.TypeList;
+import jdk.test.lib.jittester.VariableInfo;
+import jdk.test.lib.jittester.VariableInitialization;
+import jdk.test.lib.jittester.functions.ArgumentDeclaration;
+import jdk.test.lib.jittester.functions.Function;
+import jdk.test.lib.jittester.functions.FunctionDefinition;
+import jdk.test.lib.jittester.functions.FunctionInfo;
+import jdk.test.lib.jittester.functions.Return;
+import jdk.test.lib.jittester.jtreg.Printer;
+import jdk.test.lib.jittester.loops.CounterInitializer;
+import jdk.test.lib.jittester.loops.CounterManipulator;
+import jdk.test.lib.jittester.loops.For;
+import jdk.test.lib.jittester.loops.Loop;
+import jdk.test.lib.jittester.loops.LoopingCondition;
+import jdk.test.lib.jittester.types.TypeArray;
+import jdk.test.lib.jittester.types.TypeKlass;
+
+public class FixedTrees {
+    public static FunctionDefinition printVariablesAsFunction(PrintVariables node) {
+        TypeKlass owner = node.getOwner();
+
+        ArrayList<IRNode> nodes = new ArrayList<>();
+
+        VariableInfo resultInfo = new VariableInfo("result", node.getOwner(), TypeList.STRING, VariableInfo.LOCAL);
+        nodes.add(new Statement(new VariableInitialization(resultInfo, new Literal("[", TypeList.STRING)), true));
+        LocalVariable resultVar = new LocalVariable(resultInfo);
+
+        List<Symbol> vars = node.getVars();
+
+        TypeKlass printerKlass = new TypeKlass(Printer.class.getName());
+        Literal EOL = new Literal("\n", TypeList.STRING);
+        VariableInfo thisInfo = new VariableInfo("this", node.getOwner(),
+                node.getOwner(), VariableInfo.LOCAL | VariableInfo.INITIALIZED);
+
+        LocalVariable thisVar = new LocalVariable(thisInfo);
+
+        for (int i = 0; i < vars.size(); i++) {
+            Symbol v = vars.get(i);
+            nodes.add(new Statement(new BinaryOperator(OperatorKind.COMPOUND_ADD, TypeList.STRING, resultVar,
+                    new Literal(v.owner.getName() + "." + v.name + " = ", TypeList.STRING)), true));
+            VariableInfo argInfo = new VariableInfo("arg", printerKlass,
+                    v.type instanceof TypeKlass ? TypeList.OBJECT : v.type,
+                    VariableInfo.LOCAL | VariableInfo.INITIALIZED);
+            FunctionInfo printInfo = new FunctionInfo("print", printerKlass,
+                    TypeList.STRING, 0,  FunctionInfo.PUBLIC | FunctionInfo.STATIC, argInfo);
+            Function call = new Function(owner, printInfo, null);
+            VariableInfo varInfo = new VariableInfo(v.name, v.owner, v.type, v.flags);
+            if (v.isStatic()) {
+                call.addChild(new StaticMemberVariable(v.owner, varInfo));
+            } else {
+                call.addChild(new NonStaticMemberVariable(thisVar, varInfo));
+            }
+            nodes.add(new Statement(new BinaryOperator(OperatorKind.COMPOUND_ADD, TypeList.STRING, resultVar,
+                    call), true));
+            if (i < vars.size() - 1) {
+                nodes.add(new Statement(new BinaryOperator(OperatorKind.COMPOUND_ADD, TypeList.STRING, resultVar,
+                        EOL), true));
+            }
+        }
+        nodes.add(new Statement(
+                new BinaryOperator(OperatorKind.COMPOUND_ADD, TypeList.STRING, resultVar, new Literal("]\n", TypeList.STRING)),
+                true));
+
+        Block block = new Block(node.getOwner(), TypeList.STRING, nodes, 1);
+        FunctionInfo toStringInfo = new FunctionInfo("toString", owner, TypeList.STRING, 0L, FunctionInfo.PUBLIC, thisInfo);
+        return new FunctionDefinition(toStringInfo, new ArrayList<>(), block, new Return(resultVar));
+    }
+    public static FunctionDefinition generateMainOrExecuteMethod(TypeKlass owner, boolean isMain) {
+        Nothing nothing = new Nothing();
+        ArrayList<IRNode> testCallNodeContent = new ArrayList<>();
+        VariableInfo tInfo = new VariableInfo("t", owner, owner, VariableInfo.LOCAL);
+        LocalVariable tVar = new LocalVariable(tInfo);
+        Function testCallNode = new Function(owner, new FunctionInfo("test", owner, TypeList.VOID,
+                0L, FunctionInfo.PRIVATE, tInfo), null);
+        testCallNode.addChild(tVar);
+        testCallNodeContent.add(new Statement(testCallNode, true));
+        // { t.test(); }
+        Block testCallNodeBlock = new Block(owner, TypeList.VOID, testCallNodeContent, 4);
+
+        IRNode tryNode = testCallNodeBlock;
+        if (isMain) {
+            VariableInfo iInfo = new VariableInfo("i", owner, TypeList.INT, VariableInfo.LOCAL);
+            LocalVariable iVar = new LocalVariable(iInfo);
+            Operator increaseCounter = new BinaryOperator(OperatorKind.ASSIGN, TypeList.INT,
+                    iVar,
+                    new BinaryOperator(OperatorKind.ADD, TypeList.INT,
+                            iVar, new Literal(1, TypeList.INT)));
+            Loop loop = new Loop();
+            Block emptyBlock = new Block(owner, TypeList.VOID, new LinkedList<>(), 3);
+            loop.initialization = new CounterInitializer(iInfo, new Literal(0, TypeList.INT));
+            loop.manipulator = new CounterManipulator(new Statement(increaseCounter, false));
+            loop.condition = new LoopingCondition(new BinaryOperator(OperatorKind.LT, TypeList.BOOLEAN, iVar,
+                    new Literal(150000, TypeList.INT)));
+            For forNode = new For(4, loop, 150000, emptyBlock, new Statement(nothing, false),
+                    new Statement(nothing, false), testCallNodeBlock, emptyBlock, emptyBlock);
+            tryNode = forNode;
+        }
+
+        FunctionInfo constrInfo = new FunctionInfo(owner.getName(), owner, owner, 0, FunctionInfo.PUBLIC);
+        Function testConstructor = new Function(owner, constrInfo, null);
+        // Test t = new Test()
+        VariableInitialization testInit = new VariableInitialization(tInfo, testConstructor);
+
+        TypeKlass throwableKlass = new TypeKlass("java.lang.Throwable");
+        List<Type> throwables = new ArrayList<>();
+        throwables.add(throwableKlass);
+
+        VariableInfo exInfo = new VariableInfo("ex", owner, throwableKlass,
+                VariableInfo.LOCAL | VariableInfo.INITIALIZED);
+        FunctionInfo printStackTraceInfo = new FunctionInfo("printStackTrace", throwableKlass,
+                TypeList.VOID, 0, FunctionInfo.PUBLIC, exInfo);
+        Function printStackTraceCall = new Function(throwableKlass, printStackTraceInfo, null);
+        printStackTraceCall.addChild(new LocalVariable(exInfo));
+        ArrayList<IRNode> printStackTraceCallBlockContent = new ArrayList<>();
+        // { ex.printStackTrace(); }
+        printStackTraceCallBlockContent.add(new Statement(printStackTraceCall, true));
+
+        Block printStackTraceCallBlock = new Block(owner, TypeList.VOID, printStackTraceCallBlockContent, 3);
+        List<CatchBlock> catchBlocks1 = new ArrayList<>();
+        catchBlocks1.add(new CatchBlock(printStackTraceCallBlock, throwables, 3));
+        List<CatchBlock> catchBlocks2 = new ArrayList<>();
+        catchBlocks2.add(new CatchBlock(printStackTraceCallBlock, throwables, 3));
+        List<CatchBlock> catchBlocks3 = new ArrayList<>();
+        catchBlocks3.add(new CatchBlock(printStackTraceCallBlock, throwables, 2));
+
+        TryCatchBlock tryCatch1 = new TryCatchBlock(tryNode, nothing, catchBlocks1, 3);
+        TypeKlass printStreamKlass = new TypeKlass("java.io.PrintStream");
+        TypeKlass systemKlass = new TypeKlass("java.lang.System");
+        FunctionInfo systemOutPrintlnInfo = new FunctionInfo("println", printStreamKlass,
+                TypeList.VOID, 0, FunctionInfo.PUBLIC,
+                new VariableInfo("this", owner, printStreamKlass, VariableInfo.LOCAL | VariableInfo.INITIALIZED),
+                new VariableInfo("t", owner, TypeList.OBJECT,
+                        VariableInfo.LOCAL  | VariableInfo.INITIALIZED));
+        List<IRNode> printlnArgs = new ArrayList<>();
+        VariableInfo systemOutInfo = new VariableInfo("out", systemKlass, printStreamKlass,
+                VariableInfo.STATIC | VariableInfo.PUBLIC);
+        StaticMemberVariable systemOutVar = new StaticMemberVariable(owner, systemOutInfo);
+        printlnArgs.add(systemOutVar);
+        printlnArgs.add(tVar);
+        Function println = new Function(printStreamKlass, systemOutPrintlnInfo, printlnArgs);
+        ArrayList<IRNode> printlnBlockContent = new ArrayList<>();
+        printlnBlockContent.add(new Statement(println, true));
+        Block printlnBlock = new Block(owner, TypeList.VOID, printlnBlockContent, 3);
+        TryCatchBlock tryCatch2 = new TryCatchBlock(printlnBlock, nothing, catchBlocks2, 3);
+
+        List<IRNode> mainTryCatchBlockContent = new ArrayList<>();
+        mainTryCatchBlockContent.add(new Statement(testInit, true));
+        mainTryCatchBlockContent.add(tryCatch1);
+        mainTryCatchBlockContent.add(tryCatch2);
+        Block mainTryCatchBlock = new Block(owner, TypeList.VOID, mainTryCatchBlockContent, 2);
+        TryCatchBlock mainTryCatch = new TryCatchBlock(mainTryCatchBlock, nothing, catchBlocks3, 2);
+        ArrayList<IRNode> bodyContent = new ArrayList<>();
+        bodyContent.add(mainTryCatch);
+        Block funcBody = new Block(owner, TypeList.VOID, bodyContent, 1);
+
+        // static main(String[] args)V or static execute()V
+        VariableInfo mainArgs = new VariableInfo("args", owner,
+                new TypeArray(TypeList.STRING, 1), VariableInfo.LOCAL);
+        FunctionInfo fInfo = isMain
+                ? new FunctionInfo("main", owner, TypeList.VOID, 0, FunctionInfo.PUBLIC | FunctionInfo.STATIC, mainArgs)
+                : new FunctionInfo("execute", owner, TypeList.VOID, 0, FunctionInfo.PUBLIC | FunctionInfo.STATIC);
+        ArrayList<ArgumentDeclaration> argDecl = new ArrayList<>();
+        if (isMain) {
+            argDecl.add(new ArgumentDeclaration(mainArgs));
+        }
+        return new FunctionDefinition(fInfo, argDecl, funcBody, new Return(nothing));
+    }
+}
--- a/hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/utils/OptionResolver.java	Mon May 16 17:01:53 2016 +0300
+++ b/hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/utils/OptionResolver.java	Wed May 18 20:19:23 2016 +0300
@@ -166,11 +166,10 @@
     }
 
     public abstract class Option<T> {
-
-        Character shortName;
-        String longName;
-        protected T defaultValue;
-        protected String description;
+        protected final Character shortName;
+        protected final String longName;
+        protected final T defaultValue;
+        protected final String description;
 
         public Option(Character shortName, String longName, T defaultValue, String description) {
             this.shortName = shortName;
@@ -200,6 +199,10 @@
             return (T) values.getOrDefault(this, defaultValue);
         }
 
+        public boolean isSet() {
+            return values.containsKey(this);
+        }
+
         public boolean isFlag() {
             return false;
         }
--- a/hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/utils/PseudoRandom.java	Mon May 16 17:01:53 2016 +0300
+++ b/hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/utils/PseudoRandom.java	Wed May 18 20:19:23 2016 +0300
@@ -23,18 +23,31 @@
 
 package jdk.test.lib.jittester.utils;
 
+import java.lang.reflect.Field;
 import java.util.Collection;
 import java.util.Collections;
 import java.util.Iterator;
 import java.util.List;
 import java.util.NoSuchElementException;
+import java.util.Random;
+import java.util.concurrent.atomic.AtomicLong;
 
 /**
  * This class is used for any random generation operations.
  */
 public class PseudoRandom {
 
-    private static java.util.Random random = null;
+    private static Random random = null;
+    private static final Field SEED_FIELD;
+
+    static {
+        try {
+            SEED_FIELD = Random.class.getDeclaredField("seed");
+            SEED_FIELD.setAccessible(true);
+        } catch (ReflectiveOperationException roe) {
+            throw new Error("Can't get seed field: " + roe, roe);
+        }
+    }
 
     public static void reset(String seed) {
         if (seed == null || seed.length() == 0) {
@@ -71,9 +84,9 @@
         Collections.shuffle(list, random);
     }
 
-    public static byte randomNotNegative(byte limit) {
-        byte result = (byte) (limit * random.nextDouble());
-        return (byte)Math.abs(result);
+    public static int randomNotNegative(int limit) {
+        int result = (int) (limit * random.nextDouble());
+        return Math.abs(result);
     }
 
     public static <T> T randomElement(Collection<T> collection) {
@@ -103,4 +116,21 @@
             throw new NoSuchElementException("Empty, no element can be randomly selected");
         return array[random.nextInt(array.length)];
     }
+
+    public static long getCurrentSeed() {
+        try {
+            return ((AtomicLong)SEED_FIELD.get(random)).get();
+        } catch (ReflectiveOperationException roe) {
+            throw new Error("Can't get seed: " + roe, roe);
+        }
+    }
+
+    public static void setCurrentSeed(long seed) {
+        try {
+            AtomicLong seedObject = (AtomicLong)SEED_FIELD.get(random);
+            seedObject.set(seed);
+        } catch (ReflectiveOperationException roe) {
+            throw new Error("Can't set seed: " + roe, roe);
+        }
+    }
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/visitors/ByteCodeVisitor.java	Wed May 18 20:19:23 2016 +0300
@@ -0,0 +1,1831 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package jdk.test.lib.jittester.visitors;
+
+import java.util.ArrayDeque;
+import java.util.Deque;
+import java.util.HashMap;
+import java.util.List;
+import java.util.NoSuchElementException;
+import java.util.Objects;
+import java.util.SortedMap;
+import java.util.TreeMap;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+
+import jdk.internal.org.objectweb.asm.ClassWriter;
+import jdk.internal.org.objectweb.asm.FieldVisitor;
+import jdk.internal.org.objectweb.asm.Label;
+import jdk.internal.org.objectweb.asm.MethodVisitor;
+import jdk.internal.org.objectweb.asm.Opcodes;
+import jdk.test.lib.Pair;
+import jdk.test.lib.jittester.BinaryOperator;
+import jdk.test.lib.jittester.Block;
+import jdk.test.lib.jittester.BuiltInType;
+import jdk.test.lib.jittester.Break;
+import jdk.test.lib.jittester.CastOperator;
+import jdk.test.lib.jittester.CatchBlock;
+import jdk.test.lib.jittester.Continue;
+import jdk.test.lib.jittester.Declaration;
+import jdk.test.lib.jittester.IRNode;
+import jdk.test.lib.jittester.If;
+import jdk.test.lib.jittester.Initialization;
+import jdk.test.lib.jittester.Literal;
+import jdk.test.lib.jittester.LocalVariable;
+import jdk.test.lib.jittester.NonStaticMemberVariable;
+import jdk.test.lib.jittester.Nothing;
+import jdk.test.lib.jittester.Operator;
+import jdk.test.lib.jittester.OperatorKind;
+import jdk.test.lib.jittester.PrintVariables;
+import jdk.test.lib.jittester.ProductionParams;
+import jdk.test.lib.jittester.Statement;
+import jdk.test.lib.jittester.StaticMemberVariable;
+import jdk.test.lib.jittester.Switch;
+import jdk.test.lib.jittester.Symbol;
+import jdk.test.lib.jittester.TernaryOperator;
+import jdk.test.lib.jittester.Throw;
+import jdk.test.lib.jittester.TryCatchBlock;
+import jdk.test.lib.jittester.Type;
+import jdk.test.lib.jittester.TypeList;
+import jdk.test.lib.jittester.UnaryOperator;
+import jdk.test.lib.jittester.VariableBase;
+import jdk.test.lib.jittester.VariableDeclaration;
+import jdk.test.lib.jittester.VariableDeclarationBlock;
+import jdk.test.lib.jittester.VariableInfo;
+import jdk.test.lib.jittester.VariableInitialization;
+import jdk.test.lib.jittester.arrays.ArrayCreation;
+import jdk.test.lib.jittester.arrays.ArrayElement;
+import jdk.test.lib.jittester.arrays.ArrayExtraction;
+import jdk.test.lib.jittester.classes.ClassDefinitionBlock;
+import jdk.test.lib.jittester.classes.Interface;
+import jdk.test.lib.jittester.classes.Klass;
+import jdk.test.lib.jittester.classes.MainKlass;
+import jdk.test.lib.jittester.functions.ArgumentDeclaration;
+import jdk.test.lib.jittester.functions.ConstructorDefinition;
+import jdk.test.lib.jittester.functions.ConstructorDefinitionBlock;
+import jdk.test.lib.jittester.functions.Function;
+import jdk.test.lib.jittester.functions.FunctionDeclaration;
+import jdk.test.lib.jittester.functions.FunctionDeclarationBlock;
+import jdk.test.lib.jittester.functions.FunctionDefinition;
+import jdk.test.lib.jittester.functions.FunctionDefinitionBlock;
+import jdk.test.lib.jittester.functions.FunctionInfo;
+import jdk.test.lib.jittester.functions.FunctionRedefinition;
+import jdk.test.lib.jittester.functions.FunctionRedefinitionBlock;
+import jdk.test.lib.jittester.functions.Return;
+import jdk.test.lib.jittester.functions.StaticConstructorDefinition;
+import jdk.test.lib.jittester.loops.CounterInitializer;
+import jdk.test.lib.jittester.loops.CounterManipulator;
+import jdk.test.lib.jittester.loops.DoWhile;
+import jdk.test.lib.jittester.loops.For;
+import jdk.test.lib.jittester.loops.Loop;
+import jdk.test.lib.jittester.loops.LoopingCondition;
+import jdk.test.lib.jittester.loops.While;
+import jdk.test.lib.jittester.types.TypeArray;
+import jdk.test.lib.jittester.types.TypeKlass;
+import jdk.test.lib.jittester.utils.FixedTrees;
+import jdk.test.lib.jittester.utils.PseudoRandom;
+
+public class ByteCodeVisitor implements Visitor<byte[]> {
+    private final GeneratedClassesContext context = new GeneratedClassesContext();
+    private final byte[] EMPTY_BYTE_ARRAY = new byte[0];
+    private final int CLASS_WRITER_FLAGS = ContextDependedClassWriter.COMPUTE_MAXS | ContextDependedClassWriter.COMPUTE_FRAMES;
+    private final HashMap<String, ContextDependedClassWriter> classWriters = new HashMap<>();
+    private MethodVisitor currentMV;
+    private TypeKlass currentClass;
+    private final LocalVariablesTable locals = new LocalVariablesTable();
+    private final Deque<Label> endLabels = new ArrayDeque<>();
+    private final Deque<Label> beginLabels = new ArrayDeque<>();
+
+    @Override
+    public byte[] visit(ArgumentDeclaration node) {
+        /* handled by FunctionDefinition for ByteCodeVisitor */
+        return EMPTY_BYTE_ARRAY;
+    }
+
+    @Override
+    public byte[] visit(ArrayCreation node) {
+        int dimensions = node.getDimensionsCount();
+        TypeArray arrayType = node.getArrayType();
+        Type basicType = arrayType.type;
+        for (IRNode child : node.getChildren()) {
+            child.accept(this);
+        }
+        if (dimensions == 1) {
+            if (basicType.equals(TypeList.BOOLEAN)) {
+                currentMV.visitIntInsn(Opcodes.NEWARRAY, Opcodes.T_BOOLEAN);
+            } else if (basicType.equals(TypeList.BYTE)) {
+                currentMV.visitIntInsn(Opcodes.NEWARRAY, Opcodes.T_BYTE);
+            } else if (basicType.equals(TypeList.CHAR)) {
+                currentMV.visitIntInsn(Opcodes.NEWARRAY, Opcodes.T_CHAR);
+            } else if (basicType.equals(TypeList.SHORT)) {
+                currentMV.visitIntInsn(Opcodes.NEWARRAY, Opcodes.T_SHORT);
+            } else if (basicType.equals(TypeList.INT)) {
+                currentMV.visitIntInsn(Opcodes.NEWARRAY, Opcodes.T_INT);
+            } else if (basicType.equals(TypeList.LONG)) {
+                currentMV.visitIntInsn(Opcodes.NEWARRAY, Opcodes.T_LONG);
+            } else if (basicType.equals(TypeList.FLOAT)) {
+                currentMV.visitIntInsn(Opcodes.NEWARRAY, Opcodes.T_FLOAT);
+            } else if (basicType.equals(TypeList.DOUBLE)) {
+                currentMV.visitIntInsn(Opcodes.NEWARRAY, Opcodes.T_DOUBLE);
+            } else {
+                currentMV.visitTypeInsn(Opcodes.ANEWARRAY, asInternalName(basicType.getName()));
+            }
+        } else {
+            currentMV.visitMultiANewArrayInsn(new String(arrayType.accept(this)), dimensions);
+        }
+        return EMPTY_BYTE_ARRAY;
+    }
+
+    @Override
+    public byte[] visit(ArrayElement node) {
+        node.getChild(0).accept(this);
+        int dimensions = node.getChildren().size() - 1;
+        Type resultType = node.getResultType();
+        for (int i = 1; i < dimensions; i++) {
+            node.getChild(i).accept(this);
+            currentMV.visitInsn(Opcodes.AALOAD);
+        }
+        node.getChild(dimensions).accept(this);
+        if (resultType.equals(TypeList.BOOLEAN) || resultType.equals(TypeList.BYTE)) {
+            currentMV.visitInsn(Opcodes.BALOAD);
+        } else if (resultType.equals(TypeList.CHAR)) {
+            currentMV.visitInsn(Opcodes.CALOAD);
+        } else if (resultType.equals(TypeList.SHORT)) {
+            currentMV.visitInsn(Opcodes.SALOAD);
+        } else if (resultType.equals(TypeList.INT)) {
+            currentMV.visitInsn(Opcodes.IALOAD);
+        } else if (resultType.equals(TypeList.LONG)) {
+            currentMV.visitInsn(Opcodes.LALOAD);
+        } else if (resultType.equals(TypeList.FLOAT)) {
+            currentMV.visitInsn(Opcodes.FALOAD);
+        } else if (resultType.equals(TypeList.DOUBLE)) {
+            currentMV.visitInsn(Opcodes.DALOAD);
+        } else {
+            currentMV.visitInsn(Opcodes.AALOAD);
+        }
+        return EMPTY_BYTE_ARRAY;
+    }
+
+    @Override
+    public byte[] visit(ArrayExtraction node) {
+        node.getChild(0).accept(this);
+        int dimensions = node.getChildren().size() - 1;
+        Type resultType = node.getResultType();
+        for (int i = 1; i < dimensions; i++) {
+            node.getChild(i).accept(this);
+            currentMV.visitInsn(Opcodes.AALOAD);
+        }
+        node.getChild(dimensions).accept(this);
+        if (resultType.equals(TypeList.BOOLEAN) || resultType.equals(TypeList.BYTE)) {
+            currentMV.visitInsn(Opcodes.BALOAD);
+        } else if (resultType.equals(TypeList.CHAR)) {
+            currentMV.visitInsn(Opcodes.CALOAD);
+        } else if (resultType.equals(TypeList.SHORT)) {
+            currentMV.visitInsn(Opcodes.SALOAD);
+        } else if (resultType.equals(TypeList.INT)) {
+            currentMV.visitInsn(Opcodes.IALOAD);
+        } else if (resultType.equals(TypeList.LONG)) {
+            currentMV.visitInsn(Opcodes.LALOAD);
+        } else if (resultType.equals(TypeList.FLOAT)) {
+            currentMV.visitInsn(Opcodes.FALOAD);
+        } else if (resultType.equals(TypeList.DOUBLE)) {
+            currentMV.visitInsn(Opcodes.DALOAD);
+        } else {
+            currentMV.visitInsn(Opcodes.AALOAD);
+        }
+        return EMPTY_BYTE_ARRAY;
+    }
+
+    @Override
+    public byte[] visit(BinaryOperator node) {
+        OperatorKind kind = node.getOperationKind();
+        IRNode left = node.getChild(Operator.Order.LEFT.ordinal());
+        IRNode right = node.getChild(Operator.Order.RIGHT.ordinal());
+        Type resultType = node.getResultType();
+        if (left == null || right == null) {
+            return EMPTY_BYTE_ARRAY;
+        }
+        boolean needTypeConversion = false;
+        boolean convertRightArg = false;
+        Type leftType = left.getResultType();
+        Type rightType = right.getResultType();
+        if (!leftType.equals(rightType) && leftType instanceof BuiltInType
+                && rightType instanceof BuiltInType
+                && kind != OperatorKind.SAR && kind != OperatorKind.SHL
+                && kind != OperatorKind.SHR && kind != OperatorKind.ASSIGN
+                && kind != OperatorKind.AND && kind != OperatorKind.OR) {
+            needTypeConversion = true;
+            BuiltInType leftBuiltIn = (BuiltInType) leftType;
+            BuiltInType rightBuiltIn = (BuiltInType) rightType;
+            convertRightArg = leftBuiltIn.isMoreCapaciousThan(rightBuiltIn);
+        }
+        Type mostCapacious = convertRightArg ? leftType : rightType;
+        if (!rightType.equals(TypeList.INT)
+                && (kind == OperatorKind.SHL || kind == OperatorKind.SHR
+                || kind == OperatorKind.SAR)) {
+            left.accept(this);
+            right.accept(this);
+            convertTopType(rightType, TypeList.INT);
+        } else if (kind != OperatorKind.ASSIGN && kind != OperatorKind.OR
+                && kind != OperatorKind.AND && kind != OperatorKind.COMPOUND_ADD
+                && kind != OperatorKind.COMPOUND_AND && kind != OperatorKind.COMPOUND_DIV
+                && kind != OperatorKind.COMPOUND_MOD && kind != OperatorKind.COMPOUND_MUL
+                && kind != OperatorKind.COMPOUND_OR && kind != OperatorKind.COMPOUND_SAR
+                && kind != OperatorKind.COMPOUND_SHL && kind != OperatorKind.COMPOUND_SHR
+                && kind != OperatorKind.COMPOUND_SUB && kind != OperatorKind.COMPOUND_XOR
+                && kind != OperatorKind.STRADD) {
+                /* "assign", "and", "or", concat and all compound operators are
+                    handled differently and shouldn't just place left and right
+                    operands on stack */
+            left.accept(this);
+            if (needTypeConversion && !convertRightArg) {
+                convertTopType(leftType, rightType);
+            }
+            right.accept(this);
+            if (needTypeConversion && convertRightArg) {
+                convertTopType(rightType, leftType);
+            }
+        }
+        switch (kind) {
+            case ASSIGN:
+                VariableInfo vi = ((VariableBase)left).getVariableInfo();
+                Type varType = vi.type;
+                if (left instanceof LocalVariable) {
+                    right.accept(this);
+                    convertTopType(rightType, leftType);
+                    int index = locals.getLocalIndex(vi);
+                    if (varType.equals(TypeList.LONG)) {
+                        currentMV.visitVarInsn(Opcodes.LSTORE, index);
+                        currentMV.visitVarInsn(Opcodes.LLOAD, index);
+                    } else if (varType.equals(TypeList.DOUBLE)) {
+                        currentMV.visitVarInsn(Opcodes.DSTORE, index);
+                        currentMV.visitVarInsn(Opcodes.DLOAD, index);
+                    } else if (varType.equals(TypeList.FLOAT)) {
+                        currentMV.visitVarInsn(Opcodes.FSTORE, index);
+                        currentMV.visitVarInsn(Opcodes.FLOAD, index);
+                    } else if (varType instanceof TypeKlass) {
+                        currentMV.visitVarInsn(Opcodes.ASTORE, index);
+                        currentMV.visitVarInsn(Opcodes.ALOAD, index);
+                    } else {
+                        currentMV.visitVarInsn(Opcodes.ISTORE, index);
+                        currentMV.visitVarInsn(Opcodes.ILOAD, index);
+                    }
+                } else if (left instanceof StaticMemberVariable) {
+                    right.accept(this);
+                    convertTopType(rightType, leftType);
+                    String typeDescr = new String(vi.type.accept(this));
+                    String ownerName = asInternalName(vi.getOwner().getName());
+                    currentMV.visitFieldInsn(Opcodes.PUTSTATIC, ownerName,
+                            vi.name, typeDescr);
+                    currentMV.visitFieldInsn(Opcodes.GETSTATIC, ownerName,
+                            vi.name, typeDescr);
+                } else if (left instanceof NonStaticMemberVariable) {
+                    // put object to stack for putfield
+                    left.getChild(0).accept(this);
+                    // put object to stack for getfield
+                    currentMV.visitInsn(Opcodes.DUP);
+                    right.accept(this);
+                    convertTopType(rightType, leftType);
+                    String typeDescr = new String(vi.type.accept(this));
+                    String ownerName = asInternalName(vi.getOwner().getName());
+                    currentMV.visitFieldInsn(Opcodes.PUTFIELD, ownerName,
+                            vi.name, typeDescr);
+                    currentMV.visitFieldInsn(Opcodes.GETFIELD, ownerName,
+                            vi.name, typeDescr);
+                } else {
+                    throw new IllegalArgumentException("illegal left operand : "
+                            + left + "("+left.getClass()+")");
+                }
+                break;
+            case OR:
+                generateBasicLogicOperator(Opcodes.IFNE, false, left, right);
+                break;
+            case AND:
+                generateBasicLogicOperator(Opcodes.IFEQ, true,  left, right);
+                break;
+            case BIT_OR:
+                if (mostCapacious.equals(TypeList.LONG)) {
+                    currentMV.visitInsn(Opcodes.LOR);
+                } else {
+                    currentMV.visitInsn(Opcodes.IOR);
+                }
+                break;
+            case BIT_XOR:
+                if (mostCapacious.equals(TypeList.LONG)) {
+                    currentMV.visitInsn(Opcodes.LXOR);
+                } else {
+                    currentMV.visitInsn(Opcodes.IXOR);
+                }
+                break;
+            case BIT_AND:
+                if (mostCapacious.equals(TypeList.LONG)) {
+                    currentMV.visitInsn(Opcodes.LAND);
+                } else {
+                    currentMV.visitInsn(Opcodes.IAND);
+                }
+                break;
+            case EQ:
+                generateCmpBasedCode(mostCapacious, Opcodes.IFEQ, Opcodes.IF_ICMPEQ);
+                break;
+            case NE:
+                generateCmpBasedCode(mostCapacious, Opcodes.IFNE, Opcodes.IF_ICMPNE);
+                break;
+            case GT:
+                generateCmpBasedCode(mostCapacious, Opcodes.IFGT, Opcodes.IF_ICMPGT);
+                break;
+            case LT:
+                generateCmpBasedCode(mostCapacious, Opcodes.IFLT, Opcodes.IF_ICMPLT);
+                break;
+            case GE:
+                generateCmpBasedCode(mostCapacious, Opcodes.IFGE, Opcodes.IF_ICMPGE);
+                break;
+            case LE:
+                generateCmpBasedCode(mostCapacious, Opcodes.IFLE, Opcodes.IF_ICMPLE);
+                break;
+            case SHR:
+                if (leftType.equals(TypeList.LONG)) {
+                    currentMV.visitInsn(Opcodes.LSHR);
+                } else {
+                    currentMV.visitInsn(Opcodes.ISHR);
+                }
+                break;
+            case SHL:
+                if (leftType.equals(TypeList.LONG)) {
+                    currentMV.visitInsn(Opcodes.LSHL);
+                } else {
+                    currentMV.visitInsn(Opcodes.ISHL);
+                }
+                break;
+            case SAR:
+                if (leftType.equals(TypeList.LONG)) {
+                    currentMV.visitInsn(Opcodes.LUSHR);
+                } else {
+                    currentMV.visitInsn(Opcodes.IUSHR);
+                }
+                break;
+            case STRADD:
+                // we use String::valueOf to change null to "null"
+                left.accept(this);
+                currentMV.visitMethodInsn(Opcodes.INVOKESTATIC, "java/lang/String", "valueOf",
+                        "(Ljava/lang/Object;)Ljava/lang/String;", false /* not interface */);
+                right.accept(this);
+                currentMV.visitMethodInsn(Opcodes.INVOKESTATIC, "java/lang/String", "valueOf",
+                        "(Ljava/lang/Object;)Ljava/lang/String;", false /* not interface */);
+                currentMV.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/String", "concat",
+                        "(Ljava/lang/String;)Ljava/lang/String;", false /* not interface */);
+                break;
+            case ADD:
+                if (mostCapacious.equals(TypeList.LONG)) {
+                    currentMV.visitInsn(Opcodes.LADD);
+                } else if (mostCapacious.equals(TypeList.DOUBLE)) {
+                    currentMV.visitInsn(Opcodes.DADD);
+                } else if (mostCapacious.equals(TypeList.FLOAT)) {
+                    currentMV.visitInsn(Opcodes.FADD);
+                } else {
+                    currentMV.visitInsn(Opcodes.IADD);
+                }
+                break;
+            case SUB:
+                if (mostCapacious.equals(TypeList.LONG)) {
+                    currentMV.visitInsn(Opcodes.LSUB);
+                } else if (mostCapacious.equals(TypeList.DOUBLE)) {
+                    currentMV.visitInsn(Opcodes.DSUB);
+                } else if (mostCapacious.equals(TypeList.FLOAT)) {
+                    currentMV.visitInsn(Opcodes.FSUB);
+                } else {
+                    currentMV.visitInsn(Opcodes.ISUB);
+                }
+                break;
+            case MUL:
+                if (mostCapacious.equals(TypeList.LONG)) {
+                    currentMV.visitInsn(Opcodes.LMUL);
+                } else if (mostCapacious.equals(TypeList.DOUBLE)) {
+                    currentMV.visitInsn(Opcodes.DMUL);
+                } else if (mostCapacious.equals(TypeList.FLOAT)) {
+                    currentMV.visitInsn(Opcodes.FMUL);
+                } else {
+                    currentMV.visitInsn(Opcodes.IMUL);
+                }
+                break;
+            case DIV:
+                if (mostCapacious.equals(TypeList.LONG)) {
+                    currentMV.visitInsn(Opcodes.LDIV);
+                } else if (mostCapacious.equals(TypeList.DOUBLE)) {
+                    currentMV.visitInsn(Opcodes.DDIV);
+                } else if (mostCapacious.equals(TypeList.FLOAT)) {
+                    currentMV.visitInsn(Opcodes.FDIV);
+                } else {
+                    currentMV.visitInsn(Opcodes.IDIV);
+                }
+                break;
+            case MOD:
+                if (mostCapacious.equals(TypeList.LONG)) {
+                    currentMV.visitInsn(Opcodes.LREM);
+                } else if (mostCapacious.equals(TypeList.DOUBLE)) {
+                    currentMV.visitInsn(Opcodes.DREM);
+                } else if (mostCapacious.equals(TypeList.FLOAT)) {
+                    currentMV.visitInsn(Opcodes.FREM);
+                } else {
+                    currentMV.visitInsn(Opcodes.IREM);
+                }
+                break;
+            case COMPOUND_ADD:
+                lowerCompoundBinaryOperator("java.lang.String".equals(leftType.getName())
+                        ? OperatorKind.STRADD : OperatorKind.ADD, node);
+                break;
+            case COMPOUND_SUB:
+                lowerCompoundBinaryOperator(OperatorKind.SUB, node);
+                break;
+            case COMPOUND_MUL:
+                lowerCompoundBinaryOperator(OperatorKind.MUL, node);
+                break;
+            case COMPOUND_DIV:
+                lowerCompoundBinaryOperator(OperatorKind.DIV, node);
+                break;
+            case COMPOUND_MOD:
+                lowerCompoundBinaryOperator(OperatorKind.MOD, node);
+                break;
+            case COMPOUND_AND:
+                lowerCompoundBinaryOperator(leftType.equals(TypeList.BOOLEAN)
+                        ? OperatorKind.AND : OperatorKind.BIT_AND, node);
+                break;
+            case COMPOUND_OR:
+                lowerCompoundBinaryOperator(leftType.equals(TypeList.BOOLEAN)
+                        ? OperatorKind.OR : OperatorKind.BIT_OR, node);
+                break;
+            case COMPOUND_XOR:
+                lowerCompoundBinaryOperator(OperatorKind.BIT_XOR, node);
+                break;
+            case COMPOUND_SHR:
+                lowerCompoundBinaryOperator(OperatorKind.SHR, node);
+                break;
+            case COMPOUND_SHL:
+                lowerCompoundBinaryOperator(OperatorKind.SHL, node);
+                break;
+            case COMPOUND_SAR:
+                lowerCompoundBinaryOperator(OperatorKind.SAR, node);
+                break;
+            default:
+                throw new Error("Unsupported binary operator");
+        }
+        return EMPTY_BYTE_ARRAY;
+    }
+
+    private static int tmpObject;
+    private void lowerCompoundBinaryOperator(OperatorKind kind, IRNode node) {
+        IRNode left = node.getChild(Operator.Order.LEFT.ordinal());
+        IRNode right = node.getChild(Operator.Order.RIGHT.ordinal());
+
+        if (left instanceof NonStaticMemberVariable) {
+            NonStaticMemberVariable var = (NonStaticMemberVariable) left;
+            IRNode holder = var.getChild(0);
+            Type type = holder.getResultType();
+            VariableInfo tmpInfo = new VariableInfo("tmpObject_" + tmpObject++,
+                    currentClass, type, VariableInfo.LOCAL);
+            new Statement(new VariableInitialization(tmpInfo, holder), true).accept(this);
+            left = new NonStaticMemberVariable(new LocalVariable(tmpInfo), var.getVariableInfo());
+        }
+        Type leftType = left.getResultType();
+        Type rightType = right.getResultType();
+        Type resultType = leftType;
+        if (leftType instanceof BuiltInType && rightType instanceof BuiltInType) {
+            if (kind != OperatorKind.SHL && kind != OperatorKind.SHR && kind != OperatorKind.SAR
+                    && ((BuiltInType) rightType).isMoreCapaciousThan((BuiltInType) leftType)) {
+                resultType = rightType;
+            }
+        }
+        IRNode result = new CastOperator(leftType,
+                new BinaryOperator(kind, resultType, left, right));
+        new BinaryOperator(OperatorKind.ASSIGN, leftType, left, result).accept(this);
+    }
+
+    private void generateBasicLogicOperator(int ifOpcode, boolean retTrueFirst, IRNode left,
+            IRNode right) {
+        Label secondCase = new Label();
+        Label endLabel = new Label();
+        left.accept(this);
+        currentMV.visitJumpInsn(ifOpcode, secondCase);
+        right.accept(this);
+        currentMV.visitJumpInsn(ifOpcode, secondCase);
+        currentMV.visitInsn(retTrueFirst ? Opcodes.ICONST_1 : Opcodes.ICONST_0);
+        currentMV.visitJumpInsn(Opcodes.GOTO, endLabel);
+        currentMV.visitLabel(secondCase);
+        currentMV.visitInsn(retTrueFirst ? Opcodes.ICONST_0 : Opcodes.ICONST_1);
+        currentMV.visitLabel(endLabel);
+    }
+
+    private void generateCmpBasedCode(Type type, int nonIntOpcode, int intOpcode) {
+        boolean useNonIntOpcode = false;
+        if (type.equals(TypeList.LONG) || type.equals(TypeList.FLOAT)
+                || type.equals(TypeList.DOUBLE)) {
+            if (type.equals(TypeList.LONG)) {
+                currentMV.visitInsn(Opcodes.LCMP);
+            } else if (type.equals(TypeList.FLOAT)) {
+                currentMV.visitInsn(Opcodes.FCMPL);
+            } else {
+                currentMV.visitInsn(Opcodes.DCMPL);
+            }
+            useNonIntOpcode = true;
+        }
+        int opcodeToUse;
+        if (!useNonIntOpcode) {
+            if (type instanceof TypeKlass) {
+                if (intOpcode == Opcodes.IF_ICMPEQ) {
+                    opcodeToUse = Opcodes.IF_ACMPEQ;
+                } else if (intOpcode == Opcodes.IF_ICMPNE) {
+                    opcodeToUse = Opcodes.IF_ACMPNE;
+                } else {
+                    throw new Error("Can't compare references");
+                }
+            } else {
+                opcodeToUse = intOpcode;
+            }
+        } else {
+            opcodeToUse = nonIntOpcode;
+        }
+        Label retTrue = new Label();
+        Label end = new Label();
+        currentMV.visitJumpInsn(opcodeToUse, retTrue);
+        currentMV.visitInsn(Opcodes.ICONST_0);
+        currentMV.visitJumpInsn(Opcodes.GOTO, end);
+        currentMV.visitLabel(retTrue);
+        currentMV.visitInsn(Opcodes.ICONST_1);
+        currentMV.visitLabel(end);
+    }
+
+    /*
+     * Converts top-stack element from one builtin type to another
+     */
+    private void convertTopType(Type from, Type to) {
+        if (!(from instanceof BuiltInType) || !(to instanceof BuiltInType) || from.equals(to)) {
+            return; // skip
+        }
+        boolean castedToInt = false;
+        if (from.equals(TypeList.FLOAT)) {
+            if (to.equals(TypeList.DOUBLE)) {
+                currentMV.visitInsn(Opcodes.F2D);
+            } else if (to.equals(TypeList.LONG)) {
+                currentMV.visitInsn(Opcodes.F2L);
+            } else {
+                currentMV.visitInsn(Opcodes.F2I);
+                castedToInt = true;
+            }
+        } else if (from.equals(TypeList.DOUBLE)) {
+            if (to.equals(TypeList.FLOAT)) {
+                currentMV.visitInsn(Opcodes.D2F);
+            } else if (to.equals(TypeList.LONG)) {
+                currentMV.visitInsn(Opcodes.D2L);
+            } else {
+                currentMV.visitInsn(Opcodes.D2I);
+                castedToInt = true;
+            }
+        } else if (from.equals(TypeList.LONG)) {
+            if (to.equals(TypeList.DOUBLE)) {
+                currentMV.visitInsn(Opcodes.L2D);
+            } else if (to.equals(TypeList.FLOAT)) {
+                currentMV.visitInsn(Opcodes.L2F);
+            } else {
+                currentMV.visitInsn(Opcodes.L2I);
+                castedToInt = true;
+            }
+        } else {
+            if (to.equals(TypeList.BYTE)) {
+                currentMV.visitInsn(Opcodes.I2B);
+            } else if (to.equals(TypeList.CHAR)) {
+                currentMV.visitInsn(Opcodes.I2C);
+            } else if (to.equals(TypeList.SHORT)) {
+                currentMV.visitInsn(Opcodes.I2S);
+            } else if (to.equals(TypeList.LONG)) {
+                currentMV.visitInsn(Opcodes.I2L);
+            } else if (to.equals(TypeList.FLOAT)) {
+                currentMV.visitInsn(Opcodes.I2F);
+            } else if (to.equals(TypeList.DOUBLE)) {
+                currentMV.visitInsn(Opcodes.I2D);
+            }
+        }
+        if (castedToInt) {
+            if (to.equals(TypeList.BYTE)) {
+                currentMV.visitInsn(Opcodes.I2B);
+            } else if (to.equals(TypeList.CHAR)) {
+                currentMV.visitInsn(Opcodes.I2C);
+            } else if (to.equals(TypeList.SHORT)) {
+                currentMV.visitInsn(Opcodes.I2S);
+            }
+        }
+    }
+
+    @Override
+    public byte[] visit(Block node) {
+        return iterateBlock(node);
+    }
+
+    @Override
+    public byte[] visit(Break node) {
+        Label label = endLabels.peek();
+        if (label != null) {
+            currentMV.visitJumpInsn(Opcodes.GOTO, label);
+        }
+        return EMPTY_BYTE_ARRAY;
+    }
+
+    @Override
+    public byte[] visit(CastOperator node) {
+        IRNode expression = node.getChild(0);
+        expression.accept(this);
+        Type to = node.getResultType();
+        Type from = expression.getResultType();
+        // TODO boxing/unboxing
+        if (!TypeList.isBuiltIn(to) || !TypeList.isBuiltIn(from)) {
+            // class cast
+            currentMV.visitTypeInsn(Opcodes.CHECKCAST, asInternalName(to.getName()));
+        } else {
+            convertTopType(from, to);
+        }
+        return EMPTY_BYTE_ARRAY;
+    }
+
+    @Override
+    public byte[] visit(CatchBlock node) {
+        Type type = node.throwables.get(0);
+        VariableInfo exInfo = new VariableInfo("ex", currentClass,
+                type, VariableInfo.LOCAL);
+        int index = locals.getLocalIndex(exInfo);
+        currentMV.visitVarInsn(Opcodes.ASTORE, index);
+        node.getChild(0).accept(this);
+        return EMPTY_BYTE_ARRAY;
+    }
+
+    @Override
+    public byte[] visit(ClassDefinitionBlock node) {
+        return iterateBlock(node);
+    }
+
+    @Override
+    public byte[] visit(ConstructorDefinition node) {
+        FunctionInfo info = node.getFunctionInfo();
+        String ownerName = node.getOwner().getName();
+        TypeKlass parentClass = currentClass.getParent();
+        ContextDependedClassWriter cw = classWriters.get(ownerName);
+
+        String descriptor = getDescriptor(node, 1, "V");
+        currentMV = cw.visitMethod(asAccessFlags(info), "<init>", descriptor, null, null);
+        currentMV.visitVarInsn(Opcodes.ALOAD, 0);
+        currentMV.visitMethodInsn(Opcodes.INVOKESPECIAL,
+                parentClass != null ? asInternalName(parentClass.getName()) : "java/lang/Object",
+                "<init>", "()V", false);
+        locals.initConstructorArguments(node.getOwner(), info);
+        // TODO: add datamemebers as child to all ctors
+        generateDataMembers(node.getParent().getParent().getChild(Klass.KlassPart.DATA_MEMBERS.ordinal()));
+        IRNode body = node.getChild(0);
+        body.accept(this);
+        currentMV.visitInsn(Opcodes.RETURN);
+        currentMV.visitMaxs(0, 0);
+        currentMV.visitEnd();
+        return EMPTY_BYTE_ARRAY;
+    }
+
+    private void generateDataMembers(IRNode node) {
+        // TODO shouldn't we skip declaration?
+        if (node != null) {
+            node.accept(this);
+        }
+    }
+
+    @Override
+    public byte[] visit(ConstructorDefinitionBlock node) {
+        return iterateBlock(node);
+    }
+
+    @Override
+    public byte[] visit(Continue node) {
+        Label label = beginLabels.peek();
+        if (label != null) {
+            currentMV.visitJumpInsn(Opcodes.GOTO, label);
+        }
+        return EMPTY_BYTE_ARRAY;
+    }
+
+    @Override
+    public byte[] visit(CounterInitializer node) {
+        visitLocalVar(node);
+        emitPop(node.getVariableInfo().type);
+        return EMPTY_BYTE_ARRAY;
+    }
+
+    private byte[] visitLocalVar(Initialization node) {
+        VariableInfo vi = node.getVariableInfo();
+        int index = locals.addLocal(vi);
+        int store;
+        node.getChild(0).accept(this); // place initialization expression on stack
+        emitDup(vi.type);
+        if (vi.type instanceof TypeKlass) {
+            store = Opcodes.ASTORE;
+        } else if (vi.type.equals(TypeList.DOUBLE)) {
+            store = Opcodes.DSTORE;
+        } else if (vi.type.equals(TypeList.LONG)) {
+            store = Opcodes.LSTORE;
+        } else if (vi.type.equals(TypeList.FLOAT)) {
+            store = Opcodes.FSTORE;
+        } else {
+            store = Opcodes.ISTORE;
+        }
+        currentMV.visitVarInsn(store, index);
+        return EMPTY_BYTE_ARRAY;
+    }
+
+    @Override
+    public byte[] visit(CounterManipulator node) {
+        return node.getChild(0).accept(this);
+    }
+
+    @Override
+    public byte[] visit(Declaration node) {
+        IRNode child = node.getChild(0);
+        child.accept(this);
+        if (child instanceof Initialization) {
+            emitPop(((Initialization) child).getVariableInfo().type);
+        }
+        return EMPTY_BYTE_ARRAY;
+    }
+
+    @Override
+    public byte[] visit(DoWhile node) {
+        Loop loop = node.getLoop();
+        loop.initialization.accept(this);
+        node.getChild(DoWhile.DoWhilePart.HEADER.ordinal()).accept(this);
+        Label currentLoopBegin = new Label();
+        beginLabels.push(currentLoopBegin);
+        Label currentLoopEnd = new Label();
+        endLabels.push(currentLoopEnd);
+        currentMV.visitLabel(currentLoopBegin);
+        node.getChild(DoWhile.DoWhilePart.BODY1.ordinal()).accept(this);
+        loop.manipulator.accept(this);
+        node.getChild(DoWhile.DoWhilePart.BODY2.ordinal()).accept(this);
+        loop.condition.accept(this);
+        assert loop.condition.getResultType() == TypeList.BOOLEAN;
+        currentMV.visitJumpInsn(Opcodes.IFEQ, currentLoopBegin);
+        currentMV.visitLabel(currentLoopEnd);
+        Label a = beginLabels.pop();
+        assert currentLoopBegin == a;
+        a = endLabels.pop();
+        assert currentLoopEnd == a;
+        return EMPTY_BYTE_ARRAY;
+    }
+
+    @Override
+    public byte[] visit(For node) {
+        Loop loop = node.getLoop();
+        loop.initialization.accept(this);
+        node.getChild(For.ForPart.HEADER.ordinal()).accept(this);
+        node.getChild(For.ForPart.STATEMENT1.ordinal()).accept(this);
+        Label currentLoopBegin = new Label();
+        beginLabels.push(currentLoopBegin);
+        currentMV.visitLabel(currentLoopBegin);
+        loop.condition.accept(this);
+        assert loop.condition.getResultType() == TypeList.BOOLEAN;
+        Label currentLoopEnd = new Label();
+        endLabels.push(currentLoopEnd);
+        currentMV.visitJumpInsn(Opcodes.IFEQ, currentLoopEnd);
+        node.getChild(For.ForPart.STATEMENT2.ordinal()).accept(this);
+        node.getChild(For.ForPart.BODY1.ordinal()).accept(this);
+        loop.manipulator.accept(this);
+        node.getChild(For.ForPart.BODY2.ordinal()).accept(this);
+        node.getChild(For.ForPart.BODY3.ordinal()).accept(this);
+        currentMV.visitJumpInsn(Opcodes.GOTO, currentLoopBegin);
+        currentMV.visitLabel(currentLoopEnd);
+        Label a = beginLabels.pop();
+        assert currentLoopBegin == a;
+        a = endLabels.pop();
+        assert currentLoopEnd == a;
+        return EMPTY_BYTE_ARRAY;
+    }
+
+    @Override
+    public byte[] visit(Function node) {
+        FunctionInfo info = node.getValue();
+        boolean needInstance = !info.isStatic() && !info.isConstructor();
+        if (needInstance) {
+            node.getChild(0).accept(this); // placing instance on stack
+        }
+        // call itself with specific invoke*
+        String signature = info.argTypes.stream()
+                .skip(!needInstance ? 0 : 1)
+                .map(vi -> new String(vi.type.accept(this)))
+                .collect(Collectors.joining("", "(", ")"))
+                + (info.isConstructor() ? "V" : new String(node.getResultType().accept(this)));
+        int invokeCode = Opcodes.INVOKEVIRTUAL;
+        if (info.isStatic()) {
+            invokeCode = Opcodes.INVOKESTATIC;
+        } else if (info.isConstructor() || info.isPrivate()) {
+            // TODO : superclass method invocation?
+            invokeCode = Opcodes.INVOKESPECIAL;
+        } else {
+            if (info.owner.isInterface()) {
+                invokeCode = Opcodes.INVOKEINTERFACE;
+            }
+        }
+        if (info.isConstructor()) {
+            currentMV.visitTypeInsn(Opcodes.NEW, asInternalName(info.owner.getName()));
+            currentMV.visitInsn(Opcodes.DUP);
+        }
+        // calculating parameters
+        node.getChildren().stream()
+                .skip(!needInstance ? 0 : 1)
+                .forEachOrdered(c -> c.accept(this));
+        currentMV.visitMethodInsn(invokeCode, asInternalName(info.owner.getName()),
+                info.isConstructor() ? "<init>" : info.name, signature,
+                invokeCode == Opcodes.INVOKEINTERFACE);
+        return EMPTY_BYTE_ARRAY;
+    }
+
+    @Override
+    public byte[] visit(FunctionDeclaration node) {
+        FunctionInfo info = node.getFunctionInfo();
+        String ownerName = node.getOwner().getName();
+        ContextDependedClassWriter cw = classWriters.get(ownerName);
+        String returnType = new String(info.type.accept(this));
+
+        String descriptor = getDescriptor(node, 0, returnType);
+        currentMV = cw.visitMethod(asAccessFlags(info) + Opcodes.ACC_ABSTRACT,
+                info.name, descriptor, null, null);
+        currentMV.visitEnd();
+        return EMPTY_BYTE_ARRAY;
+    }
+
+    @Override
+    public byte[] visit(FunctionDeclarationBlock node) {
+        return iterateBlock(node);
+    }
+
+    @Override
+    public byte[] visit(FunctionDefinition node) {
+        FunctionInfo info = node.getFunctionInfo();
+        String ownerName = node.getOwner().getName();
+        ContextDependedClassWriter cw = classWriters.get(ownerName);
+        String returnType = new String(info.type.accept(this));
+
+        String descriptor = getDescriptor(node, 2, returnType);
+        currentMV = cw.visitMethod(asAccessFlags(info), info.name, descriptor, null, null);
+        locals.initFunctionArguments(info);
+        IRNode body = node.getChild(0);
+        body.accept(this);
+        IRNode ret = node.getChild(1);
+        ret.accept(this);
+        currentMV.visitMaxs(0, 0);
+        currentMV.visitEnd();
+        return EMPTY_BYTE_ARRAY;
+    }
+
+    @Override
+    public byte[] visit(FunctionDefinitionBlock node) {
+        return iterateBlock(node);
+    }
+
+    @Override
+    public byte[] visit(FunctionRedefinition node) {
+        FunctionInfo info = node.getFunctionInfo();
+        String ownerName = node.getOwner().getName();
+        ContextDependedClassWriter cw = classWriters.get(ownerName);
+        String returnType = new String(info.type.accept(this));
+        String descriptor = getDescriptor(node, 2, returnType);
+        currentMV = cw.visitMethod(asAccessFlags(info), info.name, descriptor, null, null);
+        locals.initFunctionArguments(info);
+        IRNode body = node.getChild(0);
+        body.accept(this);
+        IRNode ret = node.getChild(1);
+        ret.accept(this);
+        currentMV.visitMaxs(0, 0);
+        currentMV.visitEnd();
+        return EMPTY_BYTE_ARRAY;
+    }
+
+    @Override
+    public byte[] visit(FunctionRedefinitionBlock node) {
+        return iterateBlock(node);
+    }
+
+    @Override
+    public byte[] visit(If node) {
+        IRNode conditionBlock = node.getChild(If.IfPart.CONDITION.ordinal());
+        // get the condition type to emit correct if
+        conditionBlock.accept(this);
+        generateIf(Opcodes.IFEQ, node.getChild(If.IfPart.THEN.ordinal()),
+                node.getChild(If.IfPart.ELSE.ordinal()));
+        return EMPTY_BYTE_ARRAY;
+    }
+
+    /*
+     * Generates if block with then and else blocks for the given IF opcode
+     */
+    private void generateIf(int ifOpcode, IRNode thenBlock, IRNode elseBlock) {
+        Label elseLabel = new Label();
+        // if the opposite condition is met then go to the else statement
+        currentMV.visitJumpInsn(ifOpcode, elseLabel);
+        // write THEN block
+        thenBlock.accept(this);
+        if (elseBlock != null) {
+            // goto the end after THEN
+            Label endLabel = new Label();
+            currentMV.visitJumpInsn(Opcodes.GOTO, endLabel);
+            // ELSE block
+            currentMV.visitLabel(elseLabel);
+            elseBlock.accept(this);
+            currentMV.visitLabel(endLabel);
+        } else {
+            currentMV.visitLabel(elseLabel);
+        }
+    }
+
+    @Override
+    public byte[] visit(Initialization node) {
+        VariableInfo vi = node.getVariableInfo();
+        if (vi.isLocal()) {
+            return visitLocalVar(node);
+        }
+        String ownerName = vi.getOwner().getName();
+        ContextDependedClassWriter cw = classWriters.get(ownerName);
+        String typeName = new String(vi.type.accept(this));
+        // constant value used only for final static fields
+        FieldVisitor fw = cw.visitField(asAccessFlags(vi), vi.name,
+                typeName,
+                null /* Generic */,
+                null /* Constant value */);
+        fw.visitEnd(); // doesn't need visitAnnotation and visitAttribute
+        if (vi.isStatic()) {
+            node.getChild(0).accept(this); // put value to stack
+            emitDup(vi.type);
+            currentMV.visitFieldInsn(Opcodes.PUTSTATIC,
+                    asInternalName(vi.getOwner().getName()),
+                    vi.name,
+                    new String(vi.type.accept(this)));
+        } else {
+            // TODO : can it be another object?
+            currentMV.visitVarInsn(Opcodes.ALOAD, 0); // put this to stack
+            node.getChild(0).accept(this); // put value to stack
+            emitDupX1(vi.type);
+            currentMV.visitFieldInsn(Opcodes.PUTFIELD,
+                    asInternalName(vi.getOwner().getName()),
+                    vi.name,
+                    new String(vi.type.accept(this)));
+        }
+        return EMPTY_BYTE_ARRAY;
+    }
+
+    private void emitDupX1(Type type) {
+        if (TypeList.DOUBLE.equals(type) || TypeList.LONG.equals(type)) {
+            currentMV.visitInsn(Opcodes.DUP2_X1);
+        } else if (!TypeList.VOID.equals(type)){
+            currentMV.visitInsn(Opcodes.DUP_X1);
+        }
+    }
+
+    private void emitDup(Type type) {
+        if (TypeList.DOUBLE.equals(type) || TypeList.LONG.equals(type)) {
+            currentMV.visitInsn(Opcodes.DUP2);
+        } else if (!TypeList.VOID.equals(type)){
+            currentMV.visitInsn(Opcodes.DUP);
+        }
+    }
+
+    @Override
+    public byte[] visit(Interface node) {
+        String name = node.getName();
+        ContextDependedClassWriter classWriter = new ContextDependedClassWriter(context, CLASS_WRITER_FLAGS);
+        classWriters.put(name, classWriter);
+        TypeKlass parentKlass = node.getParentKlass();
+        classWriter.visit(Opcodes.V1_8,
+                          Opcodes.ACC_ABSTRACT | Opcodes.ACC_INTERFACE,
+                          asInternalName(name),
+                          null /* Generic */,
+                          "java/lang/Object",
+                          parentKlass == null ? null : new String[] {
+                                  asInternalName(parentKlass.getName())});
+        if (node.getChildren().size() > 0) {
+            node.getChild(0).accept(this);
+        }
+
+        classWriter.visitEnd();
+        byte[] byteCode = classWriter.toByteArray();
+        context.register(name, byteCode);
+        return byteCode;
+    }
+
+    @Override
+    public byte[] visit(Klass node) {
+        String name = node.getName();
+        TypeKlass prevClass = currentClass;
+        currentClass = node.getThisKlass();
+        ContextDependedClassWriter classWriter = new ContextDependedClassWriter(context, CLASS_WRITER_FLAGS);
+        classWriters.put(name, classWriter);
+        TypeKlass thisClass = node.getThisKlass();
+        TypeKlass parentClass = node.getParentKlass();
+        String[] interfaces = node.getInterfaces().stream()
+                .map(IRNode::getName)
+                .map(ByteCodeVisitor::asInternalName)
+                .toArray(String[]::new);
+        classWriter.visit(Opcodes.V1_8, asAccessFlags(thisClass),
+                asInternalName(name),
+                null /* Generic */,
+                parentClass != null ? asInternalName(parentClass.getName()) : "java/lang/Object",
+                interfaces);
+
+        IRNode constructors = node.getChild(Klass.KlassPart.CONSTRUCTORS.ordinal());
+        if (constructors != null) {
+            constructors.accept(this);
+        } else {
+            // generate default ctor
+            currentMV = classWriter.visitMethod(Opcodes.ACC_PUBLIC, "<init>", "()V", null, null);
+            currentMV.visitVarInsn(Opcodes.ALOAD, 0);
+            currentMV.visitMethodInsn(Opcodes.INVOKESPECIAL, "java/lang/Object", "<init>", "()V", false);
+            locals.clear();
+            locals.addLocal(new VariableInfo("this", thisClass, thisClass, VariableInfo.NONE));
+            generateDataMembers(node.getChild(Klass.KlassPart.DATA_MEMBERS.ordinal()));
+            currentMV.visitInsn(Opcodes.RETURN);
+            currentMV.visitMaxs(0, 0);
+            currentMV.visitEnd();
+        }
+        IRNode redefinedFunctions = node.getChild(Klass.KlassPart.REDEFINED_FUNCTIONS.ordinal());
+        if (redefinedFunctions != null) {
+            redefinedFunctions.accept(this);
+        }
+        IRNode overridenFunctions = node.getChild(Klass.KlassPart.OVERRIDEN_FUNCTIONS.ordinal());
+        if (overridenFunctions != null) {
+            overridenFunctions.accept(this);
+        }
+        IRNode memberFunctions = node.getChild(Klass.KlassPart.MEMBER_FUNCTIONS.ordinal());
+        if (memberFunctions != null) {
+            memberFunctions.accept(this);
+        }
+        IRNode memberFunctionDecls = node.getChild(Klass.KlassPart.MEMBER_FUNCTIONS_DECLARATIONS.ordinal());
+        if (memberFunctionDecls != null) {
+            memberFunctionDecls.accept(this);
+        }
+        IRNode printVariables = node.getChild(Klass.KlassPart.PRINT_VARIABLES.ordinal());
+        if (printVariables != null) {
+            printVariables.accept(this);
+        }
+        classWriter.visitEnd();
+        byte[] byteCode = classWriter.toByteArray();
+        context.register(name, byteCode);
+        currentClass = prevClass;
+        return byteCode;
+    }
+
+    private void visitLiteral(boolean value) {
+        double chance = PseudoRandom.random();
+        if (chance < CONSTANT_INST_CHANCE) {
+            currentMV.visitInsn(value ? Opcodes.ICONST_1 : Opcodes.ICONST_0);
+        } else {
+            currentMV.visitIntInsn(Opcodes.BIPUSH, value ? 1 : 0);
+        }
+    }
+
+    private void visitLiteral(byte value) {
+        double chance = PseudoRandom.random();
+        if (chance < CONSTANT_INST_CHANCE && value > -2 && value < 6) {
+            currentMV.visitInsn(Opcodes.ICONST_0 + value);
+        } else {
+            currentMV.visitIntInsn(Opcodes.BIPUSH, value);
+        }
+    }
+
+    private void visitLiteral(short value) {
+        double chance = PseudoRandom.random();
+        if (chance < CONSTANT_INST_CHANCE && value > -2 && value < 6) {
+            currentMV.visitInsn(Opcodes.ICONST_0 + value);
+        } else {
+            currentMV.visitIntInsn(Opcodes.SIPUSH, value);
+        }
+    }
+
+    private void visitLiteral(char value) {
+        double chance = PseudoRandom.random();
+        if (chance < CONSTANT_INST_CHANCE && value < 6) {
+            currentMV.visitInsn(Opcodes.ICONST_0 + value);
+        } else {
+            // TODO : check for widechar/unicode
+            currentMV.visitIntInsn(Opcodes.BIPUSH, value);
+        }
+    }
+
+    private void visitLiteral(int value) {
+        double chance = PseudoRandom.random();
+        if (chance < CONSTANT_INST_CHANCE && value > -2 && value < 6) {
+            currentMV.visitInsn(Opcodes.ICONST_0 + value);
+        } else {
+            currentMV.visitLdcInsn(value);
+        }
+    }
+
+    private void visitLiteral(long value) {
+        double chance = PseudoRandom.random();
+        if (chance < CONSTANT_INST_CHANCE && value > -1 && value < 2) {
+            currentMV.visitInsn(Opcodes.LCONST_0 + (int)value);
+        } else {
+            currentMV.visitLdcInsn(value);
+        }
+    }
+
+    private void visitLiteral(float value) {
+        double chance = PseudoRandom.random();
+        if (chance < CONSTANT_INST_CHANCE && (value == 0.0f || value == 1.0f || value == 2.0f)) {
+            currentMV.visitInsn(Opcodes.FCONST_0 + (int)value);
+        } else {
+            currentMV.visitLdcInsn(value);
+        }
+    }
+
+    private void visitLiteral(double value) {
+        double chance = PseudoRandom.random();
+        if (chance < CONSTANT_INST_CHANCE && (value == 0.0 || value == 1.0)) {
+            currentMV.visitInsn(Opcodes.DCONST_0 + (int)value);
+        } else {
+            currentMV.visitLdcInsn(value);
+        }
+    }
+
+    @Override
+    public byte[] visit(Literal node) {
+        /*
+            ICONST_n (−1 ≤ n ≤ 5) <==> BIPUSH <n>
+            LCONST_n (0 ≤ n ≤ 1)
+            FCONST_n (0 ≤ n ≤ 2)
+            DCONST_n (0 ≤ n ≤ 1)
+            ACONST_NULL
+
+            BIPUSH b, −128 ≤ b < 127
+            SIPUSH s, −32768 ≤ s < 32767
+            LDC cst (int, float, long, double, String or Type)
+        */
+        Type type = node.getResultType();
+        double chance = PseudoRandom.random();
+        if (type.equals(TypeList.BOOLEAN)) {
+            visitLiteral(Boolean.valueOf(node.getValue().toString()));
+        } else if (type.equals(TypeList.BYTE)) {
+            visitLiteral(Byte.valueOf(node.getValue().toString()));
+        } else if (type.equals(TypeList.SHORT)) {
+            visitLiteral(Short.valueOf(node.getValue().toString()));
+        } else if (type.equals(TypeList.CHAR)) {
+            visitLiteral(node.getValue().toString().charAt(0));
+        } else if (type.equals(TypeList.INT)) {
+            visitLiteral(Integer.valueOf(node.getValue().toString()));
+        } else if (type.equals(TypeList.LONG)) {
+            visitLiteral(Long.valueOf(node.getValue().toString()));
+        } else if (type.equals(TypeList.FLOAT)) {
+            visitLiteral(Float.valueOf(node.getValue().toString()));
+        } else if (type.equals(TypeList.DOUBLE)) {
+            visitLiteral(Double.valueOf(node.getValue().toString()));
+        } else {
+            currentMV.visitLdcInsn(node.getValue());
+        }
+        return EMPTY_BYTE_ARRAY;
+    }
+    private static final double CONSTANT_INST_CHANCE = 0.5;
+
+    @Override
+    public byte[] visit(LocalVariable node) {
+        // This node is for "reading" only. Writing is handled in BinaryOperator visit(see ASSIGN)
+        VariableInfo vi = node.getVariableInfo();
+        Type varType = vi.type;
+        int index = locals.getLocalIndex(vi);
+        if (varType.equals(TypeList.LONG)) {
+            currentMV.visitVarInsn(Opcodes.LLOAD, index);
+        } else if (varType.equals(TypeList.DOUBLE)) {
+            currentMV.visitVarInsn(Opcodes.DLOAD, index);
+        } else if (varType.equals(TypeList.FLOAT)) {
+            currentMV.visitVarInsn(Opcodes.FLOAD, index);
+        } else if (varType instanceof TypeKlass) {
+            currentMV.visitVarInsn(Opcodes.ALOAD, index);
+        } else {
+            currentMV.visitVarInsn(Opcodes.ILOAD, index);
+        }
+        return EMPTY_BYTE_ARRAY;
+    }
+
+    @Override
+    public byte[] visit(LoopingCondition node) {
+        return node.getCondition().accept(this);
+    }
+
+    @Override
+    public byte[] visit(MainKlass node) {
+        TypeKlass prevClass = currentClass;
+        currentClass = node.getThisKlass();
+        String name = node.getName();
+        ContextDependedClassWriter mainClassWriter = new ContextDependedClassWriter(context, CLASS_WRITER_FLAGS);
+        classWriters.put(name, mainClassWriter);
+
+        TypeKlass thisClass = node.getThisKlass();
+        mainClassWriter.visit(Opcodes.V1_8, Opcodes.ACC_PUBLIC,
+                asInternalName(name),
+                null /* Generic */,
+                "java/lang/Object",
+                null /* interfaces */);
+        // TODO: constructor for main class
+        currentMV = mainClassWriter.visitMethod(Opcodes.ACC_PUBLIC, "<init>", "()V", null, null);
+        currentMV.visitVarInsn(Opcodes.ALOAD, 0);
+        currentMV.visitMethodInsn(Opcodes.INVOKESPECIAL, "java/lang/Object", "<init>", "()V", false);
+        locals.clear();
+        locals.addLocal(new VariableInfo("this", thisClass, thisClass, VariableInfo.NONE));
+        generateDataMembers(node.getChild(MainKlass.MainKlassPart.DATA_MEMBERS.ordinal()));
+        currentMV.visitInsn(Opcodes.RETURN);
+        currentMV.visitMaxs(0, 0);
+        currentMV.visitEnd();
+
+        IRNode memberFunctions = node.getChild(MainKlass.MainKlassPart.MEMBER_FUNCTIONS.ordinal());
+        if (memberFunctions != null) {
+            memberFunctions.accept(this);
+        }
+        IRNode testFunction = node.getChild(MainKlass.MainKlassPart.TEST_FUNCTION.ordinal());
+        if (testFunction != null) {
+            currentMV = mainClassWriter.visitMethod(
+                    Opcodes.ACC_PRIVATE,
+                    "test",
+                    "()V",
+                    null,
+                    null);
+            locals.clear();
+            locals.addLocal(new VariableInfo("this", thisClass, thisClass, VariableInfo.NONE));
+            testFunction.accept(this);
+            currentMV.visitInsn(Opcodes.RETURN);
+            currentMV.visitMaxs(0, 0);
+            currentMV.visitEnd();
+        }
+        IRNode printVariables = node.getChild(MainKlass.MainKlassPart.PRINT_VARIABLES.ordinal());
+        if (printVariables != null) {
+            printVariables.accept(this);
+        }
+
+        mainClassWriter.visitEnd();
+
+        byte[] byteCode = mainClassWriter.toByteArray();
+        context.register(name, byteCode);
+        currentClass = prevClass;
+        return byteCode;
+    }
+
+    @Override
+    public byte[] visit(NonStaticMemberVariable node) {
+        // This node is for "reading" only. Writing is handled in BinaryOperator visit(see ASSIGN)
+        VariableInfo vi = node.getVariableInfo();
+        // put object to stack
+        node.getChild(0).accept(this);
+        currentMV.visitFieldInsn(Opcodes.GETFIELD, asInternalName(vi.getOwner().getName()), vi.name,
+                new String(vi.type.accept(this)));
+        return EMPTY_BYTE_ARRAY;
+    }
+
+    @Override
+    public byte[] visit(Nothing node) {
+        // TODO : add randomness
+        currentMV.visitInsn(Opcodes.NOP);
+        return EMPTY_BYTE_ARRAY;
+    }
+
+    @Override
+    public byte[] visit(PrintVariables node) {
+        return FixedTrees.printVariablesAsFunction(node).accept(this);
+    }
+
+    @Override
+    public byte[] visit(Return node) {
+        node.getExpression().accept(this);
+        Type result = node.getResultType();
+        if (result instanceof TypeKlass) {
+            currentMV.visitInsn(Opcodes.ARETURN);
+        } else if (result.equals(TypeList.VOID)) {
+            currentMV.visitInsn(Opcodes.RETURN);
+        } else if (result.equals(TypeList.DOUBLE)) {
+            currentMV.visitInsn(Opcodes.DRETURN);
+        } else if (result.equals(TypeList.FLOAT)) {
+            currentMV.visitInsn(Opcodes.FRETURN);
+        } else if (result.equals(TypeList.LONG)) {
+            currentMV.visitInsn(Opcodes.LRETURN);
+        } else {
+            currentMV.visitInsn(Opcodes.IRETURN);
+        }
+        return EMPTY_BYTE_ARRAY;
+    }
+
+    @Override
+    public byte[] visit(Statement node) {
+        IRNode child = node.getChild(0);
+        child.accept(this);
+        Type resultType = child.getResultType();
+        emitPop(resultType);
+        return EMPTY_BYTE_ARRAY;
+    }
+
+    private void emitPop(Type resultType) {
+        if (resultType.equals(TypeList.LONG) || resultType.equals(TypeList.DOUBLE)) {
+            currentMV.visitInsn(Opcodes.POP2);
+        } else if (!resultType.equals(TypeList.VOID)) {
+            currentMV.visitInsn(Opcodes.POP);
+        }
+    }
+
+    @Override
+    public byte[] visit(StaticConstructorDefinition node) {
+        String ownerName = node.getOwner().getName();
+        ContextDependedClassWriter cw = classWriters.get(ownerName);
+        String descriptor = getDescriptor(node, 1, "V");
+        currentMV = cw.visitMethod(Opcodes.ACC_STATIC, "<clinit>", descriptor, null, null);
+        locals.clear();
+        IRNode body = node.getChild(0);
+        body.accept(this);
+        currentMV.visitInsn(Opcodes.RETURN);
+        currentMV.visitMaxs(0, 0);
+        currentMV.visitEnd();
+        return EMPTY_BYTE_ARRAY;
+    }
+
+    @Override
+    public byte[] visit(StaticMemberVariable node) {
+        // This node is for "reading" only. Writing is handled in BinaryOperator visit(see ASSIGN)
+        VariableInfo vi = node.getVariableInfo();
+        currentMV.visitFieldInsn(Opcodes.GETSTATIC,
+                asInternalName(vi.getOwner().getName()),
+                vi.name,
+                new String(vi.type.accept(this)));
+        return EMPTY_BYTE_ARRAY;
+    }
+
+    @Override
+    public byte[] visit(Switch node) {
+        node.getChild(0).accept(this);
+        int caseBlockIdx = node.getCaseBlockIndex();
+        Label defaultCase = new Label();
+        IRNode defaultBlock = null;
+        SortedMap<Integer, Pair<Label, IRNode>> cases = new TreeMap<>();
+        for (int i = 0; i < caseBlockIdx - 1; ++i) {
+            if (node.getChild(i + 1) instanceof Nothing) {
+                defaultBlock = node.getChild(i + caseBlockIdx);
+            } else {
+                Literal literal = (Literal) node.getChild(i + 1);
+                int value = 0;
+                if (literal.value instanceof Integer) {
+                    value = (Integer) literal.value;
+                } else if (literal.value instanceof Short) {
+                    value = (Short) literal.value;
+                } else if (literal.value instanceof Byte) {
+                    value = (Byte) literal.value;
+                } else if (literal.value instanceof Character) {
+                    value = (Character) literal.value;
+                }
+                cases.put(value, new Pair<>(new Label(), node.getChild(i + caseBlockIdx)));
+            }
+        }
+        Label breakLabel = new Label();
+        endLabels.push(breakLabel);
+        currentMV.visitLookupSwitchInsn(defaultCase,
+                cases.keySet().stream()
+                        .mapToInt(Integer::intValue)
+                        .toArray(),
+                cases.values().stream()
+                        .map(p -> p.first)
+                        .toArray(Label[]::new));
+        for (Pair<Label, IRNode> p : cases.values()) {
+            currentMV.visitLabel(p.first);
+            p.second.accept(this);
+        }
+        currentMV.visitLabel(defaultCase);
+        if (defaultBlock != null) {
+            defaultBlock.accept(this);
+        }
+        Label a = endLabels.pop();
+        assert breakLabel == a;
+        currentMV.visitLabel(breakLabel);
+        return EMPTY_BYTE_ARRAY;
+    }
+
+    @Override
+    public byte[] visit(TernaryOperator node) {
+        IRNode conditionBlock = node.getChild(TernaryOperator.TernaryPart.CONDITION.ordinal());
+        // get the condition type to emit correct if
+        conditionBlock.accept(this);
+        generateIf(Opcodes.IFEQ, node.getChild(TernaryOperator.TernaryPart.TRUE.ordinal()),
+                node.getChild(TernaryOperator.TernaryPart.FALSE.ordinal()));
+        return EMPTY_BYTE_ARRAY;
+    }
+
+    @Override
+    public byte[] visit(Throw node) {
+        node.getThowable().accept(this);
+        currentMV.visitInsn(Opcodes.ATHROW);
+        return EMPTY_BYTE_ARRAY;
+    }
+
+    @Override
+    public byte[] visit(TryCatchBlock node) {
+        List<? extends IRNode> children = node.getChildren();
+        IRNode tryBlock = children.get(0);
+        IRNode finallyBlock = children.get(1);
+        Label tryStart = new Label();
+        Label tryEnd = new Label();
+        Label finallyStart = new Label();
+        Label finallyEnd = new Label();
+
+        currentMV.visitLabel(tryStart);
+        tryBlock.accept(this);
+        currentMV.visitLabel(tryEnd);
+        finallyBlock.accept(this);
+        currentMV.visitJumpInsn(Opcodes.GOTO, finallyEnd);
+        VariableInfo exInfo = new VariableInfo("ex", currentClass,
+                new TypeKlass("java.lang.Throwable"), VariableInfo.LOCAL);
+        int index = locals.addLocal(exInfo);
+        for (int i = 2; i < children.size(); ++i) {
+            Label handlerBegin = new Label();
+            Label handlerEnd = new Label();
+            CatchBlock catchBlock = (CatchBlock) children.get(i);
+            for (Type t : catchBlock.throwables) {
+                currentMV.visitTryCatchBlock(tryStart, tryEnd, handlerBegin, asInternalName(t.getName()));
+            }
+            currentMV.visitLabel(handlerBegin);
+            catchBlock.accept(this);
+            currentMV.visitLabel(handlerEnd);
+            finallyBlock.accept(this);
+            currentMV.visitJumpInsn(Opcodes.GOTO, finallyEnd);
+            currentMV.visitTryCatchBlock(handlerBegin, handlerEnd, finallyStart, null);
+        }
+
+        currentMV.visitTryCatchBlock(tryStart, tryEnd, finallyStart, null);
+        currentMV.visitLabel(finallyStart);
+        currentMV.visitVarInsn(Opcodes.ASTORE, index);
+        finallyBlock.accept(this);
+        currentMV.visitVarInsn(Opcodes.ALOAD, index);
+        currentMV.visitInsn(Opcodes.ATHROW);
+        currentMV.visitLabel(finallyEnd);
+        return EMPTY_BYTE_ARRAY;
+    }
+
+    @Override
+    public byte[] visit(Type node) {
+        String name;
+        if (TypeList.isBuiltIn(node)) {
+            switch (node.getName()) {
+                case "void":
+                    name = "V";
+                    break;
+                case "boolean":
+                    name = "Z";
+                    break;
+                case "byte":
+                    name = "B";
+                    break;
+                case "char":
+                    name = "C";
+                    break;
+                case "short":
+                    name = "S";
+                    break;
+                case "int":
+                    name = "I";
+                    break;
+                case "long":
+                    name = "J";
+                    break;
+                case "float":
+                    name = "F";
+                    break;
+                case "double":
+                    name = "D";
+                    break;
+                default:
+                    throw new IllegalArgumentException("Unknown type '" + node.getName());
+            }
+        } else {
+            name = "L" + asInternalName(node.getName()) + ";";
+        }
+        return name.getBytes();
+    }
+
+    @Override
+    public byte[] visit(TypeArray node) {
+        String name;
+        String prefix = Stream.generate(() -> "[")
+                .limit(node.dimensions)
+                .collect(Collectors.joining());
+        name = prefix + new String(node.getType().accept(this));
+        return name.getBytes();
+    }
+
+    @Override
+    public byte[] visit(UnaryOperator node) {
+        OperatorKind opKind = node.getOperationKind();
+        IRNode exp = node.getChild(0);
+        // argument expression is handled separately for inc and dec operators
+        if (opKind != OperatorKind.POST_DEC && opKind != OperatorKind.POST_INC
+                && opKind != OperatorKind.PRE_DEC && opKind != OperatorKind.PRE_INC) {
+            exp.accept(this);
+        }
+        Type resultType = exp.getResultType();
+        switch (opKind) {
+            case NOT:
+                Label retTrueForNot = new Label();
+                Label endForNot = new Label();
+                currentMV.visitJumpInsn(Opcodes.IFEQ, retTrueForNot);
+                currentMV.visitInsn(Opcodes.ICONST_0);
+                currentMV.visitJumpInsn(Opcodes.GOTO, endForNot);
+                currentMV.visitLabel(retTrueForNot);
+                currentMV.visitInsn(Opcodes.ICONST_1);
+                currentMV.visitLabel(endForNot);
+                break;
+            case BIT_NOT:
+                if (resultType.equals(TypeList.LONG)) {
+                    currentMV.visitLdcInsn(-1L);
+                    currentMV.visitInsn(Opcodes.LXOR);
+                } else {
+                    currentMV.visitInsn(Opcodes.ICONST_M1);
+                    currentMV.visitInsn(Opcodes.IXOR);
+                }
+                break;
+            case UNARY_MINUS:
+                if (resultType.equals(TypeList.LONG)) {
+                    currentMV.visitInsn(Opcodes.LNEG);
+                } else if (resultType.equals(TypeList.FLOAT)) {
+                    currentMV.visitInsn(Opcodes.FNEG);
+                } else if (resultType.equals(TypeList.DOUBLE)) {
+                    currentMV.visitInsn(Opcodes.DNEG);
+                } else {
+                    currentMV.visitInsn(Opcodes.INEG);
+                }
+                break;
+            case UNARY_PLUS:
+                break;
+            case PRE_DEC:
+                lowerIncDecUnaryOperator(OperatorKind.SUB, true, node);
+                break;
+            case POST_DEC:
+                lowerIncDecUnaryOperator(OperatorKind.SUB, false, node);
+                break;
+            case PRE_INC:
+                lowerIncDecUnaryOperator(OperatorKind.ADD, true, node);
+                break;
+            case POST_INC:
+                lowerIncDecUnaryOperator(OperatorKind.ADD, false, node);
+                break;
+            default:
+                throw new RuntimeException("Incorrect unary operator: " + opKind);
+        }
+        return EMPTY_BYTE_ARRAY;
+    }
+
+    private void lowerIncDecUnaryOperator(OperatorKind kind, boolean isPrefix, IRNode node) {
+        IRNode var = node.getChild(0);
+        Literal one;
+        Type resultType = node.getResultType();
+        if (resultType.equals(TypeList.LONG)) {
+            one = new Literal(1L, TypeList.LONG);
+        } else if (resultType.equals(TypeList.INT)) {
+            one = new Literal(1, TypeList.INT);
+        } else if (resultType.equals(TypeList.SHORT)) {
+            one = new Literal((short) 1, TypeList.SHORT);
+        } else {
+            one = new Literal((byte) 1, TypeList.BYTE);
+        }
+        if (var instanceof NonStaticMemberVariable) {
+            IRNode holder = var.getChild(0);
+            Type type = holder.getResultType();
+            VariableInfo tmpInfo = new VariableInfo("tmpObject_" + tmpObject++,
+                    currentClass, type, VariableInfo.LOCAL);
+            new Statement(new VariableInitialization(tmpInfo, holder), true).accept(this);
+            var = new NonStaticMemberVariable(new LocalVariable(tmpInfo),
+                    ((NonStaticMemberVariable) var).getVariableInfo());
+        }
+        BinaryOperator calculation = new BinaryOperator(kind, resultType, var, one);
+        BinaryOperator changeValue = new BinaryOperator(OperatorKind.ASSIGN, resultType, var, calculation);
+        Statement finalChangeStatement = new Statement(changeValue, true);
+        if (isPrefix) {
+            finalChangeStatement.accept(this);
+            var.accept(this);
+        } else {
+            var.accept(this);
+            finalChangeStatement.accept(this);
+        }
+    }
+
+    @Override
+    public byte[] visit(VariableDeclaration node) {
+        VariableInfo vi = node.getVariableInfo();
+        String ownerName = vi.getOwner().getName();
+        ContextDependedClassWriter cw = classWriters.get(ownerName);
+        String typeName = new String(vi.type.accept(this));
+        if (vi.isLocal()) {
+            locals.addLocal(vi);
+        } else {
+            FieldVisitor fv = cw.visitField(asAccessFlags(vi),
+                    vi.name,
+                    typeName,
+                    null /* Generic */,
+                    null /* Constant value */);
+            fv.visitEnd(); // doesn't need visitAnnotation and visitAttribute
+        }
+        return EMPTY_BYTE_ARRAY;
+    }
+
+    @Override
+    public byte[] visit(VariableDeclarationBlock node) {
+        return iterateBlock(node);
+    }
+
+    @Override
+    public byte[] visit(While node) {
+        Loop loop = node.getLoop();
+        loop.initialization.accept(this);
+        node.getChild(While.WhilePart.HEADER.ordinal()).accept(this);
+        Label currentLoopBegin = new Label();
+        beginLabels.push(currentLoopBegin);
+        currentMV.visitLabel(currentLoopBegin);
+        loop.condition.accept(this);
+        assert loop.condition.getResultType() == TypeList.BOOLEAN;
+        Label currentLoopEnd = new Label();
+        endLabels.push(currentLoopEnd);
+        currentMV.visitJumpInsn(Opcodes.IFEQ, currentLoopEnd);
+        node.getChild(While.WhilePart.BODY1.ordinal()).accept(this);
+        loop.manipulator.accept(this);
+        node.getChild(While.WhilePart.BODY2.ordinal()).accept(this);
+        node.getChild(While.WhilePart.BODY3.ordinal()).accept(this);
+        currentMV.visitJumpInsn(Opcodes.GOTO, currentLoopBegin);
+        currentMV.visitLabel(currentLoopEnd);
+        Label a = beginLabels.pop();
+        assert currentLoopBegin == a;
+        a = endLabels.pop();
+        assert currentLoopEnd == a;
+        return EMPTY_BYTE_ARRAY;
+    }
+
+    public byte[] getByteCode(String name) {
+        return context.get(name);
+    }
+
+    private static byte[] concat(byte[] a, byte[] b) {
+        byte[] r = new byte[a.length + b.length];
+        System.arraycopy(a, 0, r, 0, a.length);
+        System.arraycopy(b, 0, r, a.length, b.length);
+        return r;
+    }
+
+    private String argTypeToString(ArgumentDeclaration declarations) {
+        return new String(declarations.variableInfo.type.accept(this));
+    }
+
+    private byte[] iterateBlock(IRNode node) {
+        return node.getChildren().stream()
+                .map(ch -> ch.accept(this))
+                .reduce(new byte[0], ByteCodeVisitor::concat);
+    }
+
+    private String getDescriptor(IRNode node, int skipChilds, String returnType) {
+        return node.getChildren().stream()
+                .skip(skipChilds)
+                .map(c -> argTypeToString((ArgumentDeclaration)c))
+                .collect(Collectors.joining("", "(", ")" + returnType));
+    }
+
+    private static String asInternalName(String type) {
+        return type.replace('.', '/');
+    }
+
+    private static int asAccessFlags(TypeKlass klass) {
+        int attr = Opcodes.ACC_SUPER;
+        attr |= klass.isFinal() ? Opcodes.ACC_FINAL : 0;
+        attr |= klass.isAbstract() ? Opcodes.ACC_ABSTRACT : 0;
+        attr |= klass.isInterface() ? Opcodes.ACC_INTERFACE : 0;
+
+        return attr;
+    }
+
+    private static int asAccessFlags(FunctionInfo fi) {
+        int result = asAccessFlags((Symbol) fi);
+        result |= ProductionParams.enableStrictFP.value() ? Opcodes.ACC_STRICT : 0;
+        result |= fi.isSynchronized() ? Opcodes.ACC_SYNCHRONIZED : 0;
+        return result;
+    }
+
+    private static int asAccessFlags(Symbol s) {
+        int attr = 0;
+        attr |= s.isPublic() ? Opcodes.ACC_PUBLIC : 0;
+        attr |= s.isPrivate() ? Opcodes.ACC_PRIVATE : 0;
+        attr |= s.isProtected() ? Opcodes.ACC_PROTECTED : 0;
+        attr |= s.isStatic() ? Opcodes.ACC_STATIC : 0;
+        attr |= s.isFinal() ? Opcodes.ACC_FINAL : 0;
+
+        return attr;
+    }
+
+    private static class LocalVariablesTable {
+        private int nextLocalIndex = 0;
+        // a map keeping local variable table index for a local variable
+        private final HashMap<String, Integer> locals = new HashMap<>();
+
+        public int addLocal(VariableInfo vi) {
+            int indexToReturn = nextLocalIndex;
+            locals.put(vi.name, nextLocalIndex++);
+            if (vi.type.equals(TypeList.DOUBLE) || vi.type.equals(TypeList.LONG)) {
+                nextLocalIndex++;
+            }
+            return indexToReturn;
+        }
+
+        public int getLocalIndex(VariableInfo vi) {
+            if (!locals.containsKey(vi.name)) {
+                throw new NoSuchElementException(vi.name);
+            }
+            return locals.get(vi.name);
+        }
+
+        public void clear() {
+            locals.clear();
+            nextLocalIndex = 0;
+        }
+
+        public void initFunctionArguments(FunctionInfo info) {
+            initArguments(null, info);
+        }
+
+        public void initConstructorArguments(TypeKlass owner, FunctionInfo info) {
+            Objects.requireNonNull(owner, "owner is null");
+            initArguments(owner, info);
+        }
+
+        private void initArguments(TypeKlass owner, FunctionInfo info) {
+            clear();
+            if (owner != null) {
+                addLocal(new VariableInfo("this", owner, owner, VariableInfo.LOCAL | VariableInfo.INITIALIZED));
+            }
+            for (VariableInfo vi : info.argTypes) {
+                addLocal(vi);
+            }
+        }
+    }
+
+    private static class GeneratedClassesContext extends java.lang.ClassLoader {
+        private final HashMap<String, byte[]> byteCodes = new HashMap<>();
+
+        public void register(String name, byte[] bytecode) {
+            defineClass(name, bytecode, 0, bytecode.length);
+            byteCodes.put(name, bytecode);
+        }
+
+        public byte[] get(String name) {
+            return byteCodes.get(name);
+        }
+    }
+
+
+    private static class ContextDependedClassWriter extends ClassWriter {
+        private final GeneratedClassesContext context;
+
+        public ContextDependedClassWriter(GeneratedClassesContext context, int flags) {
+            super(flags);
+            this.context = context;
+        }
+
+        protected String getCommonSuperClass(String className1, String className2) {
+            Class<?> klass1;
+            Class<?> klass2;
+            try {
+                klass1 = Class.forName(className1.replace('/', '.'), false, context);
+                klass2 = Class.forName(className2.replace('/', '.'), false, context);
+            } catch (ClassNotFoundException e) {
+                throw new Error("can not get common supper for " + className1
+                                + " and " + className2, e);
+            }
+
+            if (klass1.isAssignableFrom(klass2)) {
+                return className1;
+            } else if (klass2.isAssignableFrom(klass1)) {
+                return className2;
+            } else if (!klass1.isInterface() && !klass2.isInterface()) {
+                do {
+                    klass1 = klass1.getSuperclass();
+                } while (!klass1.isAssignableFrom(klass2));
+
+                return asInternalName(className1);
+            } else {
+                return "java/lang/Object";
+            }
+        }
+    }
+}
--- a/hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/visitors/JavaCodeVisitor.java	Mon May 16 17:01:53 2016 +0300
+++ b/hotspot/test/testlibrary/jittester/src/jdk/test/lib/jittester/visitors/JavaCodeVisitor.java	Wed May 18 20:19:23 2016 +0300
@@ -23,8 +23,6 @@
 
 package jdk.test.lib.jittester.visitors;
 
-import java.util.HashSet;
-import java.util.Iterator;
 import java.util.List;
 import java.util.Locale;
 import java.util.Objects;
@@ -41,10 +39,10 @@
 import jdk.test.lib.jittester.Initialization;
 import jdk.test.lib.jittester.Literal;
 import jdk.test.lib.jittester.LocalVariable;
-import jdk.test.lib.jittester.LogicOperator;
 import jdk.test.lib.jittester.NonStaticMemberVariable;
 import jdk.test.lib.jittester.Nothing;
 import jdk.test.lib.jittester.Operator;
+import jdk.test.lib.jittester.OperatorKind;
 import jdk.test.lib.jittester.PrintVariables;
 import jdk.test.lib.jittester.ProductionParams;
 import jdk.test.lib.jittester.Statement;
@@ -89,13 +87,8 @@
 import jdk.test.lib.jittester.loops.LoopingCondition;
 import jdk.test.lib.jittester.loops.While;
 import jdk.test.lib.jittester.types.TypeArray;
-import jdk.test.lib.jittester.types.TypeByte;
 import jdk.test.lib.jittester.types.TypeKlass;
-import jdk.test.lib.jittester.types.TypeChar;
-import jdk.test.lib.jittester.types.TypeDouble;
-import jdk.test.lib.jittester.types.TypeFloat;
-import jdk.test.lib.jittester.types.TypeLong;
-import jdk.test.lib.jittester.types.TypeShort;
+import jdk.test.lib.jittester.utils.FixedTrees;
 import jdk.test.lib.jittester.utils.PrintingUtils;
 
 public class JavaCodeVisitor implements Visitor<String> {
@@ -128,7 +121,91 @@
         return attrs;
     }
 
-    public String expressionToJavaCode(Operator t, IRNode p, Operator.Order o) {
+    private String operatorToJaveCode(OperatorKind operationKind) {
+       switch (operationKind) {
+           case COMPOUND_ADD:
+               return  "+=";
+           case COMPOUND_SUB:
+               return "-=";
+           case COMPOUND_MUL:
+               return "*=";
+           case COMPOUND_DIV:
+               return "/=";
+           case COMPOUND_MOD:
+               return "%=";
+           case COMPOUND_AND:
+               return "&=";
+           case COMPOUND_OR:
+               return "|=";
+           case COMPOUND_XOR:
+               return "^=";
+           case COMPOUND_SHR:
+               return ">>=";
+           case COMPOUND_SHL:
+               return "<<=";
+           case COMPOUND_SAR:
+               return ">>>=";
+           case ASSIGN:
+               return "=";
+           case OR:
+               return "||";
+           case BIT_OR:
+               return "|";
+           case BIT_XOR:
+               return "^";
+           case AND:
+               return "&&";
+           case BIT_AND:
+               return "&";
+           case EQ:
+               return "==";
+           case NE:
+               return "!=";
+           case GT:
+               return ">";
+           case LT:
+               return "<";
+           case GE:
+               return ">=";
+           case LE:
+               return "<=";
+           case SHR:
+               return ">>";
+           case SHL:
+               return "<<";
+           case SAR:
+               return ">>>";
+           case ADD:
+           case STRADD:
+               return "+";
+           case SUB:
+               return "-";
+           case MUL:
+               return "*";
+           case DIV:
+               return "/";
+           case MOD:
+               return "%";
+           case NOT:
+               return "!";
+           case BIT_NOT:
+               return "~";
+           case UNARY_PLUS:
+               return "+";
+           case UNARY_MINUS:
+               return "-";
+           case PRE_DEC:
+           case POST_DEC:
+               return "--";
+           case PRE_INC:
+           case POST_INC:
+               return "++";
+           default:
+               throw new IllegalArgumentException("Unkown operator kind " + operationKind);
+       }
+    }
+
+    private String expressionToJavaCode(Operator t, IRNode p, Operator.Order o) {
         String result;
         try {
             if ((o == Operator.Order.LEFT && ((Operator) p).getPriority() < t.getPriority())
@@ -151,8 +228,8 @@
 
     @Override
     public String visit(ArrayCreation node) {
-        Type arrayType = node.getArrayType();
-        String type = arrayType.accept(this);
+        Type arrayElemType = node.getArrayType().type;
+        String type = arrayElemType.accept(this);
         String name = node.getVariable().getName();
         StringBuilder code = new StringBuilder()
                 .append(node.getVariable().accept(this))
@@ -165,7 +242,7 @@
                 .map(p -> p.accept(this))
                 .collect(Collectors.joining("][", "[", "]")));
         code.append(";\n");
-        if (!TypeList.isBuiltIn(arrayType)) {
+        if (!TypeList.isBuiltIn(arrayElemType)) {
             code.append(PrintingUtils.align(node.getParent().getLevel()))
                 .append("java.util.Arrays.fill(")
                 .append(name)
@@ -220,7 +297,7 @@
             return "null";
         }
         return expressionToJavaCode(node, left, Operator.Order.LEFT)
-               + " " + node.getOperationCode() + " "
+               + " " + operatorToJaveCode(node.getOperationKind()) + " "
                + expressionToJavaCode(node, right, Operator.Order.RIGHT);
     }
 
@@ -320,7 +397,7 @@
 
     @Override
     public String visit(CounterInitializer node) {
-        VariableInfo vi = node.get();
+        VariableInfo vi = node.getVariableInfo();
         return vi.type.accept(this) + " " + vi.name + " = " + node.getChild(0).accept(this)+ ";";
     }
 
@@ -407,8 +484,8 @@
                 + ")";
         String prefix = "";
         if (value.isStatic()) {
-            if(!node.getKlass().equals(value.klass)) {
-                prefix = value.klass.getName() + ".";
+            if(!node.getOwner().equals(value.owner)) {
+                prefix = value.owner.getName() + ".";
             }
         } else if (value.isConstructor()) {
             prefix = "new ";
@@ -434,7 +511,7 @@
                 .collect(Collectors.joining(", "));
 
         FunctionInfo functionInfo = node.getFunctionInfo();
-        return (functionInfo.klass.isInterface() ? "" : "abstract ")
+        return (functionInfo.owner.isInterface() ? "" : "abstract ")
                 + funcAttributes(functionInfo) + functionInfo.type.accept(this)+ " "
                 + functionInfo.name + "(" + args + ");";
     }
@@ -464,7 +541,7 @@
                 + PrintingUtils.align(node.getLevel() + 1) + "{\n"
                 + body.accept(this)
                 + (ret != null ? PrintingUtils.align(node.getLevel() + 2) + ret.accept(this) + "\n" : "")
-                + PrintingUtils.align(node.getLevel() + 1) + "}";
+                + PrintingUtils.align(node.getLevel() + 1) + "}\n";
     }
 
     @Override
@@ -483,6 +560,7 @@
     @Override
     public String visit(FunctionRedefinition node) {
         String args = node.getChildren().stream()
+                .skip(2)
                 .map(c -> c.accept(this))
                 .collect(Collectors.joining(", "));
 
@@ -490,10 +568,10 @@
         IRNode ret = node.getChild(1);
         int level = node.getLevel();
         FunctionInfo functionInfo = node.getFunctionInfo();
-        return funcAttributes(functionInfo) + functionInfo.type + " " + functionInfo.name + "(" + args + ")" + "\n"
+        return funcAttributes(functionInfo) + functionInfo.type.accept(this) + " " + functionInfo.name + "(" + args + ")" + "\n"
                 + PrintingUtils.align(level + 1) + "{\n"
-                + body
-                + (ret != null ? PrintingUtils.align(level + 2) + ret + "\n" : "")
+                + body.accept(this)
+                + (ret != null ? PrintingUtils.align(level + 2) + ret.accept(this) + "\n" : "")
                 + PrintingUtils.align(level + 1) + "}";
     }
 
@@ -551,10 +629,11 @@
                 + (thisKlass.isFinal() ? "final " : "")
                 + (thisKlass.isAbstract() ? "abstract " : "")
                 + "class " + node.getName()
-                + (node.getParentKlass()!= null ? " extends " + node.getParentKlass().getName() : "");
+                + (node.getParentKlass() != null && !node.getParentKlass().equals(TypeList.OBJECT)
+                ? " extends " + node.getParentKlass().getName() : "");
         List<TypeKlass> interfaces = node.getInterfaces();
         r += interfaces.stream()
-                .map(c -> c.getName())
+                .map(Type::getName)
                 .collect(Collectors.joining(", ", (interfaces.isEmpty() ? "" : " implements "), ""));
         IRNode dataMembers = node.getChild(Klass.KlassPart.DATA_MEMBERS.ordinal());
         IRNode constructors = node.getChild(Klass.KlassPart.CONSTRUCTORS.ordinal());
@@ -570,10 +649,7 @@
              + (overridenFunctions != null ? (overridenFunctions.accept(this)+ "\n") : "")
              + (memberFunctionDecls != null ? (memberFunctionDecls.accept(this)+ "\n") : "")
              + (memberFunctions != null ? (memberFunctions.accept(this)+ "\n") : "")
-             + "    public String toString()\n"
-             + "    {\n"
              + printVariables.accept(this)
-             + "    }\n"
              + "}\n";
         return r;
     }
@@ -582,43 +658,42 @@
     public String visit(Literal node) {
         Type resultType = node.getResultType();
         Object value = node.getValue();
-        if (resultType.equals(new TypeLong())) {
+        if (resultType.equals(TypeList.LONG)) {
             return value.toString() + "L";
         }
-        if (resultType.equals(new TypeFloat())) {
+        if (resultType.equals(TypeList.FLOAT)) {
             return String.format((Locale) null,
-                "%." + ProductionParams.floatingPointPrecision.value() + "EF",
+                "%EF",
                 Double.parseDouble(value.toString()));
         }
-        if (resultType.equals(new TypeDouble())) {
+        if (resultType.equals(TypeList.DOUBLE)) {
             return String.format((Locale) null,
-                "%." + 2 * ProductionParams.floatingPointPrecision.value() + "E",
+                "%E",
                 Double.parseDouble(value.toString()));
         }
-        if (resultType.equals(new TypeChar())) {
-            if (((Character) value).charValue() == '\\') {
+        if (resultType.equals(TypeList.CHAR)) {
+            if ((Character) value == '\\') {
                 return "\'" + "\\\\" + "\'";
             } else {
                 return "\'" + value.toString() + "\'";
             }
         }
-        if (resultType.equals(new TypeShort())) {
+        if (resultType.equals(TypeList.SHORT)) {
             return "(short) " + value.toString();
         }
-        if (resultType.equals(new TypeByte())) {
+        if (resultType.equals(TypeList.BYTE)) {
             return "(byte) " + value.toString();
         }
+        if (resultType.equals(TypeList.STRING)) {
+            // TOOD handle other non-printable
+            return "\"" + value.toString().replace("\n", "\\n") + "\"";
+        }
         return value.toString();
     }
 
     @Override
     public String visit(LocalVariable node) {
-        return node.get().name;
-    }
-
-    @Override
-    public String visit(LogicOperator node) {
-        throw new UnsupportedOperationException("Not supported yet.");
+        return node.getVariableInfo().name;
     }
 
     @Override
@@ -633,182 +708,16 @@
         IRNode memberFunctions = node.getChild(MainKlass.MainKlassPart.MEMBER_FUNCTIONS.ordinal());
         IRNode testFunction = node.getChild(MainKlass.MainKlassPart.TEST_FUNCTION.ordinal());
         IRNode printVariables = node.getChild(MainKlass.MainKlassPart.PRINT_VARIABLES.ordinal());
-        String executeFunction = "    public static String execute()\n"
-                + "    {\n"
-                + "        try {\n"
-                + "            " + name + " t = new " + name + "();\n"
-                + "            try { t.test(); }\n"
-                + "            catch(Throwable e) { }\n"
-                + "            try { return t.toString(); }\n"
-                + "            catch (Throwable e) { return \"Error during result conversion to String\"; }\n"
-                + "        } catch (Throwable e) { return \"Error during test execution\"; }\n"
-                + "    }\n";
-        String mainFunction = "    public static void main(String[] args)\n"
-                + "    {\n"
-                + "        try {\n"
-                + "            " + name + " t = new " + name + "();\n"
-                + "            try {\n"
-                + "                for (int i = 0; i < 150000; ++i) {\n"
-                + "                    t.test();\n"
-                + "                }\n"
-                + "            }\n"
-                + "            catch(Throwable e) { e.printStackTrace(); }\n"
-                + "            try { System.out.println(t); }\n"
-                + "            catch(Throwable e) { e.printStackTrace();}\n"
-                + "        } catch (Throwable e) { e.printStackTrace(); }\n"
-                + "    }\n";
-        String printerClass = "    static class Printer\n"
-                + "    {\n"
-                + "        public static String print(boolean arg) { return String.valueOf(arg); }\n"
-                + "        public static String print(byte arg)    { return String.valueOf(arg); }\n"
-                + "        public static String print(short arg)   { return String.valueOf(arg); }\n"
-                + "        public static String print(char arg)    { return String.valueOf((int)arg); }\n"
-                + "        public static String print(int arg)     { return String.valueOf(arg); }\n"
-                + "        public static String print(long arg)    { return String.valueOf(arg); }\n"
-                + "        public static String print(float arg)   { return String.valueOf(arg); }\n"
-                + "        public static String print(double arg)  { return String.valueOf(arg); }\n"
-                + "\n"
-                + "\n"
-                + "        public static String print(Object arg)\n"
-                + "        {\n"
-                + "            return print_r(new java.util.Stack(), arg);\n"
-                + "        }\n"
-                + "\n"
-                + "        private static String print_r(java.util.Stack visitedObjects, Object arg)\n"
-                + "        {\n"
-                + "            String result = \"\";\n"
-                + "            if (arg == null)\n"
-                + "                result += \"null\";\n"
-                + "            else\n"
-                + "            if (arg.getClass().isArray())\n"
-                + "            {\n"
-                + "                for (int i = 0; i < visitedObjects.size(); i++)\n"
-                + "                    if (visitedObjects.elementAt(i) == arg) return \"<recursive>\";\n"
-                + "\n"
-                + "                visitedObjects.push(arg);\n"
-                + "\n"
-                + "                final String delimiter = \", \";\n"
-                + "                result += \"[\";\n"
-                + "\n"
-                + "                if (arg instanceof Object[])\n"
-                + "                {\n"
-                + "                    Object[] array = (Object[]) arg;\n"
-                + "                    for (int i = 0; i < array.length; i++)\n"
-                + "                    {\n"
-                + "                        result += print_r(visitedObjects, array[i]);\n"
-                + "                        if (i < array.length - 1) result += delimiter;\n"
-                + "                    }\n"
-                + "                }\n"
-                + "                else\n"
-                + "                if (arg instanceof boolean[])\n"
-                + "                {\n"
-                + "                    boolean[] array = (boolean[]) arg;\n"
-                + "                    for (int i = 0; i < array.length; i++)\n"
-                + "                    {\n"
-                + "                        result += print(array[i]);\n"
-                + "                        if (i < array.length - 1) result += delimiter;\n"
-                + "                    }\n"
-                + "                }\n"
-                + "                else\n"
-                + "                if (arg instanceof byte[])\n"
-                + "                {\n"
-                + "                    byte[] array = (byte[]) arg;\n"
-                + "                    for (int i = 0; i < array.length; i++)\n"
-                + "                    {\n"
-                + "                        result += print(array[i]);\n"
-                + "                        if (i < array.length - 1) result += delimiter;\n"
-                + "                    }\n"
-                + "                }\n"
-                + "                else\n"
-                + "                if (arg instanceof short[])\n"
-                + "                {\n"
-                + "                    short[] array = (short[]) arg;\n"
-                + "                    for (int i = 0; i < array.length; i++)\n"
-                + "                    {\n"
-                + "                        result += print(array[i]);\n"
-                + "                        if (i < array.length - 1) result += delimiter;\n"
-                + "                    }\n"
-                + "                }\n"
-                + "                else\n"
-                + "                if (arg instanceof char[])\n"
-                + "                {\n"
-                + "                    char[] array = (char[]) arg;\n"
-                + "                    for (int i = 0; i < array.length; i++)\n"
-                + "                    {\n"
-                + "                        result += print(array[i]);\n"
-                + "                        if (i < array.length - 1) result += delimiter;\n"
-                + "                    }\n"
-                + "                }\n"
-                + "                else\n"
-                + "                if (arg instanceof int[])\n"
-                + "                {\n"
-                + "                     int[] array = (int[]) arg;\n"
-                + "                     for (int i = 0; i < array.length; i++)\n"
-                + "                     {\n"
-                + "                        result += print(array[i]);\n"
-                + "                        if (i < array.length - 1) result += delimiter;\n"
-                + "                     }\n"
-                + "                }\n"
-                + "                else\n"
-                + "                if (arg instanceof long[])\n"
-                + "                {\n"
-                + "                    long[] array = (long[]) arg;\n"
-                + "                    for (int i = 0; i < array.length; i++)\n"
-                + "                    {\n"
-                + "                        result += print(array[i]);\n"
-                + "                        if (i < array.length - 1) result += delimiter;\n"
-                + "                    }\n"
-                + "                }\n"
-                + "                else\n"
-                + "                if (arg instanceof float[])\n"
-                + "                {\n"
-                + "                    float[] array = (float[]) arg;\n"
-                + "                    for (int i = 0; i < array.length; i++)\n"
-                + "                    {\n"
-                + "                        result += print(array[i]);\n"
-                + "                        if (i < array.length - 1) result += delimiter;\n"
-                + "                    }\n"
-                + "                }\n"
-                + "                else\n"
-                + "                if (arg instanceof double[])\n"
-                + "                {\n"
-                + "                    double[] array = (double[]) arg;\n"
-                + "                    for (int i = 0; i < array.length; i++)\n"
-                + "                    {\n"
-                + "                        result += print(array[i]);\n"
-                + "                        if (i < array.length - 1) result += delimiter;\n"
-                + "                    }\n"
-                + "                }\n"
-                + "\n"
-                + "                result += \"]\";\n"
-                + "                visitedObjects.pop();\n"
-                + "\n"
-                + "            } else\n"
-                + "            {\n"
-                + "                result += arg.toString();\n"
-                + "            }\n"
-                + "\n"
-                + "            return result;\n"
-                + "        }\n"
-                + "    }\n";
 
         return (ProductionParams.enableStrictFP.value() ? "strictfp " : "")
                 + "public class " + name + " {\n"
                 + dataMembers.accept(this)+ "\n"
                 + (memberFunctions != null ? memberFunctions.accept(this): "") + "\n"
-                + executeFunction
-                + "\n"
-                + mainFunction
-                + "\n&qu