Search in sources :

Example 1 with Program

use of de.mirkosertic.bytecoder.ssa.Program in project Bytecoder by mirkosertic.

the class InlineGotoOptimizerTest method testSimpleFlow.

@Test
public void testSimpleFlow() {
    Program theProgram = new Program();
    ControlFlowGraph theGraph = theProgram.getControlFlowGraph();
    RegionNode theNode = theGraph.createAt(BytecodeOpcodeAddress.START_AT_ZERO, RegionNode.BlockType.NORMAL);
    RegionNode theNode2 = theGraph.createAt(new BytecodeOpcodeAddress(20), RegionNode.BlockType.NORMAL);
    theNode.getExpressions().add(new GotoExpression(new BytecodeOpcodeAddress(20)));
    theNode.addSuccessor(theNode2);
    theNode2.getExpressions().add(new ReturnExpression());
    theGraph.calculateReachabilityAndMarkBackEdges();
    InlineGotoOptimizer theOptimizer = new InlineGotoOptimizer();
    theOptimizer.optimize(theGraph, null);
    Assert.assertEquals(1, theGraph.getKnownNodes().size(), 0);
    Assert.assertEquals(1, theGraph.getDominatedNodes().size(), 0);
    Assert.assertTrue(theGraph.getKnownNodes().contains(theNode));
    Assert.assertEquals(1, theNode.getExpressions().size(), 0);
    Assert.assertTrue(theNode.getExpressions().toList().get(0) instanceof ReturnExpression);
    Assert.assertEquals(0, theNode.getSuccessors().size(), 0);
    Relooper theRelooper = new Relooper();
    Relooper.Block theRoot = theRelooper.reloop(theGraph);
}
Also used : ReturnExpression(de.mirkosertic.bytecoder.ssa.ReturnExpression) Program(de.mirkosertic.bytecoder.ssa.Program) GotoExpression(de.mirkosertic.bytecoder.ssa.GotoExpression) Relooper(de.mirkosertic.bytecoder.relooper.Relooper) ControlFlowGraph(de.mirkosertic.bytecoder.ssa.ControlFlowGraph) BytecodeOpcodeAddress(de.mirkosertic.bytecoder.core.BytecodeOpcodeAddress) RegionNode(de.mirkosertic.bytecoder.ssa.RegionNode) Test(org.junit.Test)

Example 2 with Program

use of de.mirkosertic.bytecoder.ssa.Program in project Bytecoder by mirkosertic.

the class InlineGotoOptimizerTest method testIf.

@Test
public void testIf() {
    Program theProgram = new Program();
    ControlFlowGraph theGraph = theProgram.getControlFlowGraph();
    RegionNode theNode = theGraph.createAt(BytecodeOpcodeAddress.START_AT_ZERO, RegionNode.BlockType.NORMAL);
    RegionNode theNode1 = theGraph.createAt(new BytecodeOpcodeAddress(20), RegionNode.BlockType.NORMAL);
    RegionNode theNode2 = theGraph.createAt(new BytecodeOpcodeAddress(40), RegionNode.BlockType.NORMAL);
    RegionNode theNode3 = theGraph.createAt(new BytecodeOpcodeAddress(60), RegionNode.BlockType.NORMAL);
    theNode.addSuccessor(theNode1);
    theNode.addSuccessor(theNode2);
    ExpressionList theTrueClause = new ExpressionList();
    theTrueClause.add(new GotoExpression(new BytecodeOpcodeAddress(20)));
    IFExpression theIF = new IFExpression(new BytecodeOpcodeAddress(0), new BytecodeOpcodeAddress(20), new IntegerValue(10), theTrueClause);
    theNode.getExpressions().add(theIF);
    theNode.getExpressions().add(new GotoExpression(new BytecodeOpcodeAddress(40)));
    theNode1.addSuccessor(theNode3);
    theNode1.getExpressions().add(new GotoExpression(new BytecodeOpcodeAddress(60)));
    theNode2.addSuccessor(theNode3);
    theNode2.getExpressions().add(new GotoExpression(new BytecodeOpcodeAddress(60)));
    theNode3.getExpressions().add(new ReturnExpression());
    theGraph.calculateReachabilityAndMarkBackEdges();
    InlineGotoOptimizer theOptimizer = new InlineGotoOptimizer();
    theOptimizer.optimize(theGraph, null);
    System.out.println(theGraph.toDOT());
}
Also used : ReturnExpression(de.mirkosertic.bytecoder.ssa.ReturnExpression) Program(de.mirkosertic.bytecoder.ssa.Program) GotoExpression(de.mirkosertic.bytecoder.ssa.GotoExpression) ControlFlowGraph(de.mirkosertic.bytecoder.ssa.ControlFlowGraph) IntegerValue(de.mirkosertic.bytecoder.ssa.IntegerValue) BytecodeOpcodeAddress(de.mirkosertic.bytecoder.core.BytecodeOpcodeAddress) IFExpression(de.mirkosertic.bytecoder.ssa.IFExpression) RegionNode(de.mirkosertic.bytecoder.ssa.RegionNode) ExpressionList(de.mirkosertic.bytecoder.ssa.ExpressionList) Test(org.junit.Test)

Example 3 with Program

use of de.mirkosertic.bytecoder.ssa.Program in project Bytecoder by mirkosertic.

the class RelooperTest method testEndlessLoop.

@Test
public void testEndlessLoop() {
    Program theProgram = new Program();
    ControlFlowGraph theGraph = new ControlFlowGraph(theProgram);
    RegionNode theNode1 = theGraph.createAt(BytecodeOpcodeAddress.START_AT_ZERO, RegionNode.BlockType.NORMAL);
    theNode1.getExpressions().add(new GotoExpression(new BytecodeOpcodeAddress(10)));
    RegionNode theNode2 = theGraph.createAt(new BytecodeOpcodeAddress(10), RegionNode.BlockType.NORMAL);
    theNode2.getExpressions().add(new GotoExpression(new BytecodeOpcodeAddress(20)));
    RegionNode theNode3 = theGraph.createAt(new BytecodeOpcodeAddress(20), RegionNode.BlockType.NORMAL);
    theNode3.getExpressions().add(new GotoExpression(BytecodeOpcodeAddress.START_AT_ZERO));
    theNode1.addSuccessor(theNode2);
    theNode2.addSuccessor(theNode3);
    theNode3.addSuccessor(theNode1);
    theGraph.calculateReachabilityAndMarkBackEdges();
    Relooper theRelooper = new Relooper();
    Relooper.Block theBlock = theRelooper.reloop(theGraph);
    theRelooper.debugPrint(System.out, theBlock);
}
Also used : Program(de.mirkosertic.bytecoder.ssa.Program) GotoExpression(de.mirkosertic.bytecoder.ssa.GotoExpression) ControlFlowGraph(de.mirkosertic.bytecoder.ssa.ControlFlowGraph) BytecodeOpcodeAddress(de.mirkosertic.bytecoder.core.BytecodeOpcodeAddress) RegionNode(de.mirkosertic.bytecoder.ssa.RegionNode) Test(org.junit.Test)

Example 4 with Program

use of de.mirkosertic.bytecoder.ssa.Program in project Bytecoder by mirkosertic.

the class JSSSACompilerBackend method generateCodeFor.

@Override
public JSCompileResult generateCodeFor(CompileOptions aOptions, BytecodeLinkerContext aLinkerContext, Class aEntryPointClass, String aEntryPointMethodName, BytecodeMethodSignature aEntryPointSignatue) {
    BytecodeLinkedClass theExceptionRethrower = aLinkerContext.resolveClass(BytecodeObjectTypeRef.fromRuntimeClass(ExceptionRethrower.class));
    theExceptionRethrower.resolveStaticMethod("registerExceptionOutcome", registerExceptionOutcomeSignature);
    theExceptionRethrower.resolveStaticMethod("getLastOutcomeOrNullAndReset", getLastExceptionOutcomeSignature);
    StringWriter theStrWriter = new StringWriter();
    PrintWriter theWriter = new PrintWriter(theStrWriter);
    theWriter.println("'use strict';");
    theWriter.println();
    theWriter.println("var bytecoderGlobalMemory = [];");
    theWriter.println();
    theWriter.println("var bytecoder = {");
    theWriter.println();
    theWriter.println("     logDebug : function(aValue) { ");
    theWriter.println("         console.log(aValue);");
    theWriter.println("     }, ");
    theWriter.println();
    theWriter.println("     logByteArrayAsString : function(aArray) { ");
    theWriter.println("         var theResult = '';");
    theWriter.println("         for (var i=0;i<aArray.data.length;i++) {");
    theWriter.println("             theResult += String.fromCharCode(aArray.data[i]);");
    theWriter.println("         }");
    theWriter.println("         console.log(theResult);");
    theWriter.println("     }, ");
    theWriter.println();
    theWriter.println("     newString : function(aByteArray) { ");
    BytecodeObjectTypeRef theStringTypeRef = BytecodeObjectTypeRef.fromRuntimeClass(String.class);
    BytecodeObjectTypeRef theArrayTypeRef = BytecodeObjectTypeRef.fromRuntimeClass(Array.class);
    BytecodeMethodSignature theStringConstructorSignature = new BytecodeMethodSignature(BytecodePrimitiveTypeRef.VOID, new BytecodeTypeRef[] { new BytecodeArrayTypeRef(BytecodePrimitiveTypeRef.BYTE, 1) });
    // Construct a String
    theWriter.println("          var theNewString = new " + JSWriterUtils.toClassName(theStringTypeRef) + ".Create();");
    theWriter.println("          var theBytes = new " + JSWriterUtils.toClassName(theArrayTypeRef) + ".Create();");
    theWriter.println("          theBytes.data = aByteArray;");
    theWriter.println("          " + JSWriterUtils.toClassName(theStringTypeRef) + '.' + JSWriterUtils.toMethodName("init", theStringConstructorSignature) + "(theNewString, theBytes);");
    theWriter.println("          return theNewString;");
    theWriter.println("     },");
    theWriter.println();
    theWriter.println("     newMultiArray : function(aDimensions, aDefault) {");
    theWriter.println("         var theLength = aDimensions[0];");
    theWriter.println("         var theArray = bytecoder.newArray(theLength, aDefault);");
    theWriter.println("         if (aDimensions.length > 1) {");
    theWriter.println("             var theNewDimensions = aDimensions.slice(0);");
    theWriter.println("             theNewDimensions.shift();");
    theWriter.println("             for (var i=0;i<theLength;i++) {");
    theWriter.println("                 theArray.data[i] = bytecoder.newMultiArray(theNewDimensions, aDefault);");
    theWriter.println("             }");
    theWriter.println("         }");
    theWriter.println("         return theArray;");
    theWriter.println("     },");
    theWriter.println();
    theWriter.println("     newArray : function(aLength, aDefault) {");
    BytecodeObjectTypeRef theArrayType = BytecodeObjectTypeRef.fromRuntimeClass(Array.class);
    theWriter.println("          var theInstance = new " + JSWriterUtils.toClassName(theArrayType) + ".Create();");
    theWriter.println("          theInstance.data = [];");
    theWriter.println("          theInstance.data.length = aLength;");
    theWriter.println("          for (var i=0;i<aLength;i++) {");
    theWriter.println("             theInstance.data[i] = aDefault;");
    theWriter.println("          }");
    theWriter.println("          return theInstance;");
    theWriter.println("     },");
    theWriter.println();
    theWriter.println("     dynamicType : function(aFunction) { ");
    theWriter.println("         return new Proxy({}, {");
    theWriter.println("             get: function(target, name) {");
    theWriter.println("                 return function(inst, _p1, _p2, _p3, _p4, _p5, _p6, _p7, _p8, _p9) {");
    theWriter.println("                    return aFunction(_p1, _p2, _p3, _p4, _p5, _p6, _p7, _p8, _p9);");
    theWriter.println("                 }");
    theWriter.println("             }");
    theWriter.println("         });");
    theWriter.println("     }, ");
    theWriter.println();
    theWriter.println("     resolveStaticCallSiteObject: function(aWhere, aKey, aProducerFunction) {");
    theWriter.println("         var resolvedCallsiteObject = aWhere.__staticCallSites[aKey];");
    theWriter.println("         if (resolvedCallsiteObject == null) {");
    theWriter.println("             resolvedCallsiteObject = aProducerFunction();");
    theWriter.println("             aWhere.__staticCallSites[aKey] = resolvedCallsiteObject;");
    theWriter.println("         }");
    theWriter.println("         return resolvedCallsiteObject;");
    theWriter.println("     },");
    theWriter.println();
    theWriter.println("     imports : [],");
    theWriter.println();
    theWriter.println("     stringpool : [],");
    theWriter.println();
    theWriter.println("};");
    theWriter.println();
    ConstantPool thePool = new ConstantPool();
    aLinkerContext.linkedClasses().forEach(theEntry -> {
        BytecodeLinkedClass theLinkedClass = theEntry.targetNode();
        // Here we collect everything that is required for class initialization
        // this includes the super class, all implementing interfaces and also static
        // dependencies of the class initialization code
        List<BytecodeObjectTypeRef> theInitDependencies = new ArrayList<>();
        BytecodeLinkedClass theSuperClass = theLinkedClass.getSuperClass();
        if (theSuperClass != null) {
            theInitDependencies.add(theSuperClass.getClassName());
        }
        for (BytecodeLinkedClass theInterface : theLinkedClass.getImplementingTypes()) {
            if (!theInitDependencies.contains(theInterface.getClassName())) {
                theInitDependencies.add(theInterface.getClassName());
            }
        }
        BytecodeResolvedMethods theMethods = theLinkedClass.resolvedMethods();
        String theJSClassName = JSWriterUtils.toClassName(theEntry.edgeType().objectTypeRef());
        theWriter.println("var " + theJSClassName + " = {");
        // First of all, we add static fields required by the framework
        theWriter.println("    __initialized : false,");
        theWriter.println("    __staticCallSites : [],");
        theWriter.print("    __typeId : ");
        theWriter.print(theLinkedClass.getUniqueId());
        theWriter.println(",");
        theWriter.print("    __implementedTypes : [");
        {
            boolean first = true;
            for (BytecodeLinkedClass theType : theLinkedClass.getImplementingTypes()) {
                if (!first) {
                    theWriter.print(",");
                }
                first = false;
                theWriter.print(theType.getUniqueId());
            }
        }
        theWriter.println("],");
        // then we add class specific static fields
        BytecodeResolvedFields theStaticFields = theLinkedClass.resolvedFields();
        theStaticFields.streamForStaticFields().forEach(aFieldEntry -> {
            BytecodeTypeRef theFieldType = aFieldEntry.getValue().getTypeRef();
            if (theFieldType.isPrimitive()) {
                BytecodePrimitiveTypeRef thePrimitive = (BytecodePrimitiveTypeRef) theFieldType;
                switch(thePrimitive) {
                    case BOOLEAN:
                        {
                            theWriter.print("    ");
                            theWriter.print(aFieldEntry.getValue().getName().stringValue());
                            theWriter.print(" : false, // declared in ");
                            theWriter.println(aFieldEntry.getProvidingClass().getClassName().name());
                            break;
                        }
                    default:
                        {
                            theWriter.print("    ");
                            theWriter.print(aFieldEntry.getValue().getName().stringValue());
                            theWriter.print(" : 0, // declared in ");
                            theWriter.println(aFieldEntry.getProvidingClass().getClassName().name());
                            break;
                        }
                }
            } else {
                theWriter.print("    ");
                theWriter.print(aFieldEntry.getValue().getName().stringValue());
                theWriter.print(" : null, // declared in ");
                theWriter.println(aFieldEntry.getProvidingClass().getClassName().name());
            }
        });
        theWriter.println();
        if (!theLinkedClass.getBytecodeClass().getAccessFlags().isAbstract()) {
            // The Constructor function initializes all object members with null
            // Only non abstract classes can be instantiated
            BytecodeResolvedFields theInstanceFields = theLinkedClass.resolvedFields();
            theWriter.println("    Create : function() {");
            theInstanceFields.streamForInstanceFields().forEach(aFieldEntry -> {
                BytecodeTypeRef theFieldType = aFieldEntry.getValue().getTypeRef();
                if (theFieldType.isPrimitive()) {
                    BytecodePrimitiveTypeRef thePrimitive = (BytecodePrimitiveTypeRef) theFieldType;
                    switch(thePrimitive) {
                        case BOOLEAN:
                            {
                                theWriter.print("        this.");
                                theWriter.print(aFieldEntry.getValue().getName().stringValue());
                                theWriter.print(" = false; // declared in ");
                                theWriter.println(aFieldEntry.getProvidingClass().getClassName().name());
                                break;
                            }
                        default:
                            {
                                theWriter.print("        this.");
                                theWriter.print(aFieldEntry.getValue().getName().stringValue());
                                theWriter.print(" = 0; // declared in ");
                                theWriter.println(aFieldEntry.getProvidingClass().getClassName().name());
                                break;
                            }
                    }
                } else {
                    theWriter.print("        this.");
                    theWriter.print(aFieldEntry.getValue().getName().stringValue());
                    theWriter.print(" = null; // declared in ");
                    theWriter.println(aFieldEntry.getProvidingClass().getClassName().name());
                }
            });
            theWriter.println("    },");
            theWriter.println();
        }
        if (!theLinkedClass.getBytecodeClass().getAccessFlags().isInterface()) {
            theWriter.println("    instanceOf : function(aType) {");
            theWriter.print("        return ");
            theWriter.print(theJSClassName);
            theWriter.println(".__implementedTypes.includes(aType.__typeId);");
            theWriter.println("    },");
            theWriter.println();
            theWriter.println("    ClassgetClass : function() {");
            theWriter.print("        return ");
            theWriter.print(theJSClassName);
            theWriter.println(";");
            theWriter.println("    },");
            theWriter.println();
            theWriter.println("    BOOLEANdesiredAssertionStatus : function() {");
            theWriter.println("        return false;");
            theWriter.println("    },");
            theWriter.println();
            theWriter.println("    A1jlObjectgetEnumConstants : function(aClazz) {");
            theWriter.println("        return aClazz.$VALUES;");
            theWriter.println("    },");
        }
        theMethods.stream().forEach(aEntry -> {
            BytecodeMethod theMethod = aEntry.getValue();
            BytecodeMethodSignature theCurrentMethodSignature = theMethod.getSignature();
            // If the method is provided by the runtime, we do not need to generate the implementation
            if (theMethod.getAttributes().getAnnotationByType(EmulatedByRuntime.class.getName()) != null) {
                return;
            }
            // Do not generate code for abstract methods
            if (theMethod.getAccessFlags().isAbstract()) {
                return;
            }
            if (!(aEntry.getProvidingClass() == theLinkedClass)) {
                // But include static methods, as they are inherited from the base classes
                if (aEntry.getValue().getAccessFlags().isStatic() && !aEntry.getValue().isClassInitializer()) {
                    StringBuilder theArguments = new StringBuilder();
                    ;
                    for (int i = 0; i < theCurrentMethodSignature.getArguments().length; i++) {
                        if (i > 0) {
                            theArguments.append(',');
                        }
                        theArguments.append('p');
                        theArguments.append(i);
                    }
                    // Static methods will just delegate to the implementation in the class
                    theWriter.println();
                    theWriter.println("    " + JSWriterUtils.toMethodName(theMethod.getName().stringValue(), theCurrentMethodSignature) + " : function(" + theArguments + ") {");
                    if (!theCurrentMethodSignature.getReturnType().isVoid()) {
                        theWriter.print("         return ");
                    } else {
                        theWriter.print("         ");
                    }
                    theWriter.print(JSWriterUtils.toClassName(aEntry.getProvidingClass().getClassName()));
                    theWriter.print(".");
                    theWriter.print(JSWriterUtils.toMethodName(theMethod.getName().stringValue(), theCurrentMethodSignature));
                    theWriter.print("(");
                    theWriter.print(theArguments);
                    theWriter.println(");");
                    theWriter.println("    },");
                }
                return;
            }
            aLinkerContext.getLogger().info("Compiling {}.{}", theLinkedClass.getClassName().name(), theMethod.getName().stringValue());
            ProgramGenerator theGenerator = programGeneratorFactory.createFor(aLinkerContext);
            Program theSSAProgram = theGenerator.generateFrom(aEntry.getProvidingClass().getBytecodeClass(), theMethod);
            // Run optimizer
            aOptions.getOptimizer().optimize(theSSAProgram.getControlFlowGraph(), aLinkerContext);
            StringBuilder theArguments = new StringBuilder();
            for (Program.Argument theArgument : theSSAProgram.getArguments()) {
                if (theArguments.length() > 0) {
                    theArguments.append(',');
                }
                theArguments.append(theArgument.getVariable().getName());
            }
            if (theMethod.getAccessFlags().isNative()) {
                if (theLinkedClass.getBytecodeClass().getAttributes().getAnnotationByType(EmulatedByRuntime.class.getName()) != null) {
                    return;
                }
                BytecodeImportedLink theLink = theLinkedClass.linkfor(theMethod);
                theWriter.println();
                theWriter.println("    " + JSWriterUtils.toMethodName(theMethod.getName().stringValue(), theCurrentMethodSignature) + " : function(" + theArguments + ") {");
                theWriter.print("         return bytecoder.imports.");
                theWriter.print(theLink.getModuleName());
                theWriter.print(".");
                theWriter.print(theLink.getLinkName());
                theWriter.print("(");
                theWriter.print(theArguments);
                theWriter.println(");");
                theWriter.println("    },");
                return;
            }
            theWriter.println();
            theWriter.println("    " + JSWriterUtils.toMethodName(theMethod.getName().stringValue(), theCurrentMethodSignature) + " : function(" + theArguments + ") {");
            if (Objects.equals(theMethod.getName().stringValue(), "<clinit>")) {
                for (BytecodeObjectTypeRef theRef : theSSAProgram.getStaticReferences()) {
                    if (!theInitDependencies.contains(theRef)) {
                        theInitDependencies.add(theRef);
                    }
                }
            }
            if (aOptions.isDebugOutput()) {
                theWriter.println("        /**");
                theWriter.println("        " + theSSAProgram.getControlFlowGraph().toDOT());
                theWriter.println("        */");
            }
            JSSSAWriter theVariablesWriter = new JSSSAWriter(aOptions, theSSAProgram, "        ", theWriter, aLinkerContext, thePool);
            for (Variable theVariable : theSSAProgram.globalVariables()) {
                if (!theVariable.isSynthetic()) {
                    theVariablesWriter.print("var ");
                    theVariablesWriter.print(theVariable.getName());
                    theVariablesWriter.print(" = null;");
                    theVariablesWriter.print(" // type is ");
                    theVariablesWriter.print(theVariable.resolveType().resolve().name());
                    theVariablesWriter.print(" # of inits = " + theVariable.incomingDataFlows().size());
                    theVariablesWriter.println();
                }
            }
            // Try to reloop it!
            try {
                Relooper theRelooper = new Relooper();
                Relooper.Block theReloopedBlock = theRelooper.reloop(theSSAProgram.getControlFlowGraph());
                theVariablesWriter.printRelooped(theReloopedBlock);
            } catch (Exception e) {
                System.out.println(theSSAProgram.getControlFlowGraph().toDOT());
                throw new IllegalStateException("Error relooping cfg for " + theLinkedClass.getClassName().name() + '.' + theMethod.getName().stringValue(), e);
            }
            theWriter.println("    },");
        });
        theWriter.println();
        theWriter.println("    classInitCheck : function() {");
        theWriter.println("        if (!" + theJSClassName + ".__initialized) {");
        theWriter.println("            " + theJSClassName + ".__initialized = true;");
        if (!theLinkedClass.getBytecodeClass().getAccessFlags().isAbstract()) {
            // Now we have to setup the prototype
            // Only in case this class can be instantiated of course
            theWriter.println("            var thePrototype = " + theJSClassName + ".Create.prototype;");
            theWriter.println("            thePrototype.instanceOf = " + theJSClassName + ".instanceOf;");
            theWriter.println("            thePrototype.ClassgetClass = " + theJSClassName + ".ClassgetClass;");
            List<BytecodeResolvedMethods.MethodEntry> theEntries = theMethods.stream().collect(Collectors.toList());
            Set<String> theVisitedMethods = new HashSet<>();
            for (int i = theEntries.size() - 1; i >= 0; i--) {
                BytecodeResolvedMethods.MethodEntry aEntry = theEntries.get(i);
                BytecodeMethod theMethod = aEntry.getValue();
                String theMethodName = JSWriterUtils.toMethodName(theMethod.getName().stringValue(), theMethod.getSignature());
                if (!theMethod.getAccessFlags().isStatic() && !theMethod.getAccessFlags().isAbstract() && !theMethod.isConstructor() && !theMethod.isClassInitializer()) {
                    if (theVisitedMethods.add(theMethodName)) {
                        theWriter.print("            thePrototype.");
                        theWriter.print(theMethodName);
                        theWriter.print(" = ");
                        theWriter.print(JSWriterUtils.toClassName(aEntry.getProvidingClass().getClassName()));
                        theWriter.print(".");
                        theWriter.print(theMethodName);
                        theWriter.println(";");
                    }
                }
            }
        }
        for (BytecodeObjectTypeRef theRef : theInitDependencies) {
            if (!Objects.equals(theRef, theEntry.edgeType().objectTypeRef())) {
                theWriter.print("            ");
                theWriter.print(JSWriterUtils.toClassName(theRef));
                theWriter.println(".classInitCheck();");
            }
        }
        if (theLinkedClass.hasClassInitializer()) {
            theWriter.println("            " + theJSClassName + ".VOIDclinit();");
        }
        theWriter.println("        }");
        theWriter.println("    },");
        theWriter.println();
        theWriter.println("};");
        theWriter.println();
    });
    theWriter.println();
    theWriter.println("bytecoder.bootstrap = function() {");
    List<StringValue> theValues = thePool.stringValues();
    for (int i = 0; i < theValues.size(); i++) {
        StringValue theValue = theValues.get(i);
        theWriter.print("    bytecoder.stringpool[");
        theWriter.print(i);
        theWriter.print("] = bytecoder.newString(");
        theWriter.print(JSWriterUtils.toArray(theValue.getStringValue().getBytes()));
        theWriter.println(");");
    }
    aLinkerContext.linkedClasses().forEach(aEntry -> {
        if (!aEntry.targetNode().getBytecodeClass().getAccessFlags().isInterface()) {
            theWriter.print("    ");
            theWriter.print(JSWriterUtils.toClassName(aEntry.edgeType().objectTypeRef()));
            theWriter.println(".classInitCheck();");
        }
    });
    theWriter.println("}");
    theWriter.flush();
    return new JSCompileResult(theStrWriter.toString());
}
Also used : Variable(de.mirkosertic.bytecoder.ssa.Variable) BytecodeMethodSignature(de.mirkosertic.bytecoder.core.BytecodeMethodSignature) ArrayList(java.util.ArrayList) BytecodeMethod(de.mirkosertic.bytecoder.core.BytecodeMethod) ProgramGenerator(de.mirkosertic.bytecoder.ssa.ProgramGenerator) BytecodeResolvedMethods(de.mirkosertic.bytecoder.core.BytecodeResolvedMethods) StringWriter(java.io.StringWriter) BytecodeLinkedClass(de.mirkosertic.bytecoder.core.BytecodeLinkedClass) StringValue(de.mirkosertic.bytecoder.ssa.StringValue) BytecodeResolvedFields(de.mirkosertic.bytecoder.core.BytecodeResolvedFields) PrintWriter(java.io.PrintWriter) HashSet(java.util.HashSet) BytecodeProgram(de.mirkosertic.bytecoder.core.BytecodeProgram) Program(de.mirkosertic.bytecoder.ssa.Program) BytecodePrimitiveTypeRef(de.mirkosertic.bytecoder.core.BytecodePrimitiveTypeRef) BytecodeTypeRef(de.mirkosertic.bytecoder.core.BytecodeTypeRef) BytecodeObjectTypeRef(de.mirkosertic.bytecoder.core.BytecodeObjectTypeRef) Relooper(de.mirkosertic.bytecoder.relooper.Relooper) BytecodeArrayTypeRef(de.mirkosertic.bytecoder.core.BytecodeArrayTypeRef) ConstantPool(de.mirkosertic.bytecoder.backend.ConstantPool) BytecodeImportedLink(de.mirkosertic.bytecoder.core.BytecodeImportedLink) ExceptionRethrower(de.mirkosertic.bytecoder.classlib.ExceptionRethrower)

Example 5 with Program

use of de.mirkosertic.bytecoder.ssa.Program in project Bytecoder by mirkosertic.

the class JSSSAWriter method print.

private void print(ResolveCallsiteObjectExpression aValue) {
    print("bytecoder.resolveStaticCallSiteObject(");
    print(JSWriterUtils.toClassName(aValue.getOwningClass().getThisInfo()));
    print(",'");
    print(aValue.getCallsiteId());
    println("', function() {");
    Program theProgram = aValue.getProgram();
    RegionNode theBootstrapCode = aValue.getBootstrapMethod();
    JSSSAWriter theNested = withDeeperIndent();
    for (Variable theVariable : theProgram.globalVariables()) {
        theNested.print("var ");
        theNested.print(theVariable.getName());
        theNested.println(" = null;");
    }
    theNested.writeExpressions(theBootstrapCode.getExpressions());
    print("})");
}
Also used : Program(de.mirkosertic.bytecoder.ssa.Program) Variable(de.mirkosertic.bytecoder.ssa.Variable) RegionNode(de.mirkosertic.bytecoder.ssa.RegionNode)

Aggregations

Program (de.mirkosertic.bytecoder.ssa.Program)14 RegionNode (de.mirkosertic.bytecoder.ssa.RegionNode)11 ControlFlowGraph (de.mirkosertic.bytecoder.ssa.ControlFlowGraph)9 Test (org.junit.Test)9 BytecodeOpcodeAddress (de.mirkosertic.bytecoder.core.BytecodeOpcodeAddress)8 GotoExpression (de.mirkosertic.bytecoder.ssa.GotoExpression)6 ReturnExpression (de.mirkosertic.bytecoder.ssa.ReturnExpression)6 Relooper (de.mirkosertic.bytecoder.relooper.Relooper)5 Variable (de.mirkosertic.bytecoder.ssa.Variable)5 BytecodeMethodSignature (de.mirkosertic.bytecoder.core.BytecodeMethodSignature)4 BytecodeLinkedClass (de.mirkosertic.bytecoder.core.BytecodeLinkedClass)3 BytecodeMethod (de.mirkosertic.bytecoder.core.BytecodeMethod)3 BytecodeObjectTypeRef (de.mirkosertic.bytecoder.core.BytecodeObjectTypeRef)3 BytecodeResolvedMethods (de.mirkosertic.bytecoder.core.BytecodeResolvedMethods)3 BytecodeTypeRef (de.mirkosertic.bytecoder.core.BytecodeTypeRef)3 ProgramGenerator (de.mirkosertic.bytecoder.ssa.ProgramGenerator)3 PrintWriter (java.io.PrintWriter)3 StringWriter (java.io.StringWriter)3 ConstantPool (de.mirkosertic.bytecoder.backend.ConstantPool)2 BytecodeArrayTypeRef (de.mirkosertic.bytecoder.core.BytecodeArrayTypeRef)2