Search in sources :

Example 1 with Instruction

use of com.codename1.tools.translator.bytecodes.Instruction in project CodenameOne by codenameone.

the class BytecodeMethod method appendMethodC.

public void appendMethodC(StringBuilder b) {
    if (nativeMethod) {
        return;
    }
    appendCMethodPrefix(b, "");
    b.append(" {\n");
    if (eliminated) {
        if (returnType.isVoid()) {
            b.append("    return;\n}\n\n");
        } else {
            b.append("    return 0;\n}\n\n");
        }
        return;
    }
    b.append(declaration);
    boolean hasInstructions = true;
    if (optimizerOn) {
        hasInstructions = optimize();
    }
    if (hasInstructions) {
        Set<String> added = new HashSet<String>();
        for (LocalVariable lv : localVariables) {
            String variableName = lv.getQualifier() + "locals_" + lv.getIndex() + "_";
            if (!added.contains(variableName) && lv.getQualifier() != 'o') {
                added.add(variableName);
                b.append("    volatile ");
                switch(lv.getQualifier()) {
                    case 'i':
                        b.append("JAVA_INT");
                        break;
                    case 'l':
                        b.append("JAVA_LONG");
                        break;
                    case 'f':
                        b.append("JAVA_FLOAT");
                        break;
                    case 'd':
                        b.append("JAVA_DOUBLE");
                        break;
                }
                b.append(" ").append(lv.getQualifier()).append("locals_").append(lv.getIndex()).append("_ = 0; /* ").append(lv.getOrigName()).append(" */\n");
            }
        }
        if (staticMethod) {
            if (methodName.equals("__CLINIT__")) {
                b.append("    DEFINE_METHOD_STACK(");
            } else {
                b.append("    __STATIC_INITIALIZER_");
                b.append(clsName.replace('/', '_').replace('$', '_'));
                b.append("(threadStateData);\n    DEFINE_METHOD_STACK(");
            }
        } else {
            b.append("    DEFINE_INSTANCE_METHOD_STACK(");
        }
        b.append(maxStack);
        b.append(", ");
        b.append(maxLocals);
        b.append(", 0, ");
        b.append(Parser.addToConstantPool(clsName));
        b.append(", ");
        b.append(Parser.addToConstantPool(methodName));
        b.append(");\n");
        int startOffset = 0;
        if (synchronizedMethod) {
            if (staticMethod) {
                b.append("    monitorEnter(threadStateData, (JAVA_OBJECT)&class__");
                b.append(clsName);
                b.append(");\n");
            } else {
                b.append("    monitorEnter(threadStateData, __cn1ThisObject);\n");
            }
        }
        if (!staticMethod) {
            b.append("    locals[0].data.o = __cn1ThisObject; locals[0].type = CN1_TYPE_OBJECT; ");
            startOffset++;
        }
        int localsOffset = startOffset;
        for (int iter = 0; iter < arguments.size(); iter++) {
            ByteCodeMethodArg arg = arguments.get(iter);
            if (arg.getQualifier() == 'o') {
                b.append("    locals[");
                b.append(localsOffset);
                b.append("].data.");
                b.append(arg.getQualifier());
                b.append(" = __cn1Arg");
                b.append(iter + 1);
                b.append(";\n");
                b.append("    locals[");
                b.append(localsOffset);
                b.append("].type = CN1_TYPE_OBJECT;\n");
            } else {
                b.append("    ");
                if (!hasLocalVariableWithIndex(arg.getQualifier(), localsOffset)) {
                    switch(arg.getQualifier()) {
                        case 'i':
                            b.append("JAVA_INT");
                            break;
                        case 'f':
                            b.append("JAVA_FLOAT");
                            break;
                        case 'd':
                            b.append("JAVA_DOUBLE");
                            break;
                        case 'l':
                            b.append("JAVA_LONG");
                            break;
                        default:
                            b.append("JAVA_INT");
                            break;
                    }
                    b.append(" ");
                }
                b.append(arg.getQualifier());
                b.append("locals_");
                b.append(localsOffset);
                b.append("_");
                b.append(" = __cn1Arg");
                b.append(iter + 1);
                b.append(";\n");
            }
            // For now we'll still allocate space for locals that we're not using
            // so we keep the indexes the same for objects.
            localsOffset++;
            if (arg.isDoubleOrLong()) {
                localsOffset++;
            }
        }
    }
    BasicInstruction.setSynchronizedMethod(synchronizedMethod, staticMethod, clsName);
    TryCatch.reset();
    BasicInstruction.setHasInstructions(hasInstructions);
    for (Instruction i : instructions) {
        i.setMaxes(maxStack, maxLocals);
        i.appendInstruction(b, instructions);
    }
    if (instructions.size() == 0) {
        if (returnType.isVoid()) {
            b.append("    return;\n}\n\n");
        } else {
            b.append("    return 0;\n}\n\n");
        }
        return;
    }
    Instruction inst = instructions.get(instructions.size() - 1);
    int lastInstruction = inst.getOpcode();
    if (lastInstruction == -1 || inst instanceof LabelInstruction) {
        if (instructions.size() > 2) {
            inst = instructions.get(instructions.size() - 2);
            lastInstruction = inst.getOpcode();
        }
    }
    if (lastInstruction == Opcodes.RETURN || lastInstruction == Opcodes.ARETURN || lastInstruction == Opcodes.IRETURN || lastInstruction == Opcodes.LRETURN || lastInstruction == Opcodes.FRETURN || lastInstruction == Opcodes.DRETURN || lastInstruction == -1) {
        b.append("}\n\n");
    } else {
        if (returnType.isVoid()) {
            b.append("    return;\n}\n\n");
        } else {
            b.append("    return 0;\n}\n\n");
        }
    }
}
Also used : LabelInstruction(com.codename1.tools.translator.bytecodes.LabelInstruction) LocalVariable(com.codename1.tools.translator.bytecodes.LocalVariable) BasicInstruction(com.codename1.tools.translator.bytecodes.BasicInstruction) SwitchInstruction(com.codename1.tools.translator.bytecodes.SwitchInstruction) TypeInstruction(com.codename1.tools.translator.bytecodes.TypeInstruction) Instruction(com.codename1.tools.translator.bytecodes.Instruction) LabelInstruction(com.codename1.tools.translator.bytecodes.LabelInstruction) HashSet(java.util.HashSet)

Example 2 with Instruction

use of com.codename1.tools.translator.bytecodes.Instruction in project CodenameOne by codenameone.

the class BytecodeMethod method optimize.

boolean optimize() {
    int instructionCount = instructions.size();
    // optimize away a method that only contains the void return instruction e.g. blank constructors etc.
    if (instructionCount < 6) {
        int realCount = instructionCount;
        Instruction actual = null;
        for (int iter = 0; iter < instructionCount; iter++) {
            Instruction current = instructions.get(iter);
            if (current instanceof LabelInstruction) {
                realCount--;
                continue;
            }
            if (current instanceof LineNumber) {
                realCount--;
                continue;
            }
            actual = current;
        }
        if (realCount == 1 && actual != null && actual.getOpcode() == Opcodes.RETURN) {
            return false;
        }
    }
    boolean astoreCalls = false;
    boolean hasInstructions = false;
    boolean hasTryCatch = false;
    for (int iter = 0; iter < instructionCount - 1; iter++) {
        Instruction current = instructions.get(iter);
        if (current instanceof TryCatch) {
            hasTryCatch = true;
        }
        current.setMethod(this);
        if (current.isOptimized()) {
            continue;
        }
        int currentOpcode = current.getOpcode();
        switch(currentOpcode) {
            case Opcodes.CHECKCAST:
                {
                    // Remove the check cast for now as it gets in the way of other optimizations
                    instructions.remove(iter);
                    iter--;
                    instructionCount--;
                    break;
                }
        }
    }
    for (int iter = 0; iter < instructionCount - 1; iter++) {
        Instruction current = instructions.get(iter);
        if (current.isOptimized()) {
            // we should skip it and proceed to the next one
            continue;
        }
        Instruction next = instructions.get(iter + 1);
        int currentOpcode = current.getOpcode();
        int nextOpcode = next.getOpcode();
        if (ArithmeticExpression.isArithmeticOp(current)) {
            int addedIndex = ArithmeticExpression.tryReduce(instructions, iter);
            if (addedIndex >= 0) {
                iter = addedIndex;
                instructionCount = instructions.size();
                continue;
            }
        }
        if (current instanceof Field) {
            int newIter = Field.tryReduce(instructions, iter);
            if (newIter >= 0) {
                iter = newIter;
                instructionCount = instructions.size();
                continue;
            }
        }
        switch(currentOpcode) {
            case Opcodes.ARRAYLENGTH:
                {
                    if (!dependentClasses.contains("java_lang_NullPointerException")) {
                        dependentClasses.add("java_lang_NullPointerException");
                    }
                    int newIter = ArrayLengthExpression.tryReduce(instructions, iter);
                    if (newIter >= 0) {
                        instructionCount = instructions.size();
                        iter = newIter;
                        continue;
                    }
                    break;
                }
            case Opcodes.DUP:
                {
                    int newIter = DupExpression.tryReduce(instructions, iter);
                    if (newIter >= 0) {
                        iter = newIter;
                        instructionCount = instructions.size();
                        continue;
                    }
                    break;
                }
            case Opcodes.POP:
                {
                    if (iter > 0) {
                        Instruction prev = instructions.get(iter - 1);
                        if (prev instanceof CustomInvoke) {
                            CustomInvoke inv = (CustomInvoke) prev;
                            if (inv.methodHasReturnValue()) {
                                inv.setNoReturn(true);
                                instructions.remove(iter);
                                iter--;
                                instructionCount--;
                                continue;
                            }
                        }
                    }
                    break;
                }
            case Opcodes.ASTORE:
            case Opcodes.ISTORE:
            case Opcodes.DSTORE:
            case Opcodes.LSTORE:
            case Opcodes.FSTORE:
                {
                    if (iter > 0 && current instanceof VarOp) {
                        VarOp currentVarOp = (VarOp) current;
                        Instruction prev = instructions.get(iter - 1);
                        if (prev instanceof AssignableExpression) {
                            AssignableExpression expr = (AssignableExpression) prev;
                            StringBuilder sb = new StringBuilder();
                            if (currentVarOp.assignFrom(expr, sb)) {
                                instructions.remove(iter - 1);
                                instructions.remove(iter - 1);
                                instructions.add(iter - 1, new CustomIntruction(sb.toString(), sb.toString(), dependentClasses));
                                iter = iter - 1;
                                instructionCount = instructions.size();
                                continue;
                            }
                        } else if (prev instanceof CustomInvoke) {
                            CustomInvoke inv = (CustomInvoke) prev;
                            StringBuilder sb = new StringBuilder();
                            if (currentVarOp.assignFrom(inv, sb)) {
                                instructions.remove(iter - 1);
                                instructions.remove(iter - 1);
                                instructions.add(iter - 1, new CustomIntruction(sb.toString(), sb.toString(), dependentClasses));
                                iter = iter - 1;
                                instructionCount = instructions.size();
                                continue;
                            }
                        }
                    }
                    break;
                }
            case Opcodes.IRETURN:
            case Opcodes.FRETURN:
            case Opcodes.ARETURN:
            case Opcodes.LRETURN:
            case Opcodes.DRETURN:
                {
                    if (iter > 0 && current instanceof BasicInstruction) {
                        Instruction prev = instructions.get(iter - 1);
                        if (prev instanceof AssignableExpression) {
                            AssignableExpression expr = (AssignableExpression) prev;
                            StringBuilder sb = new StringBuilder();
                            if (expr.assignTo(null, sb)) {
                                instructions.remove(iter - 1);
                                instructions.remove(iter - 1);
                                String exprString = sb.toString().trim();
                                String retVal = exprString;
                                sb.setLength(0);
                                if (!prev.isConstant()) {
                                    sb.append("\n{\n    ");
                                    switch(currentOpcode) {
                                        case Opcodes.IRETURN:
                                            sb.append("JAVA_INT");
                                            break;
                                        case Opcodes.FRETURN:
                                            sb.append("JAVA_FLOAT");
                                            break;
                                        case Opcodes.ARETURN:
                                            sb.append("JAVA_OBJECT");
                                            break;
                                        case Opcodes.LRETURN:
                                            sb.append("JAVA_LONG");
                                            break;
                                        case Opcodes.DRETURN:
                                            sb.append("JAVA_DOUBLE");
                                            break;
                                    }
                                    sb.append(" ___returnValue=").append(exprString).append(";\n");
                                    retVal = "___returnValue";
                                }
                                if (synchronizedMethod) {
                                    if (staticMethod) {
                                        sb.append("    monitorExit(threadStateData, (JAVA_OBJECT)&class__");
                                        sb.append(getClsName());
                                        sb.append(");\n");
                                    } else {
                                        sb.append("    monitorExit(threadStateData, __cn1ThisObject);\n");
                                    }
                                }
                                if (hasTryCatch) {
                                    sb.append("    releaseForReturnInException(threadStateData, cn1LocalsBeginInThread, methodBlockOffset); return ").append(retVal).append(";\n");
                                } else {
                                    sb.append("    releaseForReturn(threadStateData, cn1LocalsBeginInThread); return ").append(retVal).append(";\n");
                                }
                                if (!prev.isConstant()) {
                                    sb.append("}\n");
                                }
                                instructions.add(iter - 1, new CustomIntruction(sb.toString(), sb.toString(), dependentClasses));
                                iter--;
                                instructionCount = instructions.size();
                                continue;
                            }
                        } else if (prev instanceof CustomInvoke) {
                            CustomInvoke expr = (CustomInvoke) prev;
                            String returnType = expr.getReturnValue();
                            if (returnType != null && !"JAVA_OBJECT".equals(returnType)) {
                                // We can't safely return a JAVA_OBJECT directly because it needs to be added
                                // to the stack for the GC
                                StringBuilder sb = new StringBuilder();
                                if (expr.appendExpression(sb)) {
                                    instructions.remove(iter - 1);
                                    instructions.remove(iter - 1);
                                    String exprString = sb.toString().trim();
                                    String retVal = exprString;
                                    sb.setLength(0);
                                    if (!expr.isConstant()) {
                                        sb.append("\n{\n    ");
                                        switch(currentOpcode) {
                                            case Opcodes.IRETURN:
                                                sb.append("JAVA_INT");
                                                break;
                                            case Opcodes.FRETURN:
                                                sb.append("JAVA_FLOAT");
                                                break;
                                            case Opcodes.ARETURN:
                                                sb.append("JAVA_OBJECT");
                                                break;
                                            case Opcodes.LRETURN:
                                                sb.append("JAVA_LONG");
                                                break;
                                            case Opcodes.DRETURN:
                                                sb.append("JAVA_DOUBLE");
                                                break;
                                        }
                                        sb.append(" ___returnValue=").append(exprString).append(";\n");
                                        retVal = "___returnValue";
                                    }
                                    if (synchronizedMethod) {
                                        if (staticMethod) {
                                            sb.append("    monitorExit(threadStateData, (JAVA_OBJECT)&class__");
                                            sb.append(getClsName());
                                            sb.append(");\n");
                                        } else {
                                            sb.append("    monitorExit(threadStateData, __cn1ThisObject);\n");
                                        }
                                    }
                                    if (hasTryCatch) {
                                        sb.append("    releaseForReturnInException(threadStateData, cn1LocalsBeginInThread, methodBlockOffset); return ").append(retVal).append(";\n");
                                    } else {
                                        sb.append("    releaseForReturn(threadStateData, cn1LocalsBeginInThread); return ").append(retVal).append(";\n");
                                    }
                                    if (!expr.isConstant()) {
                                        sb.append("}\n");
                                    }
                                    instructions.add(iter - 1, new CustomIntruction(sb.toString(), sb.toString(), dependentClasses));
                                    iter--;
                                    instructionCount = instructions.size();
                                    continue;
                                }
                            }
                        }
                    }
                    break;
                }
            case Opcodes.BASTORE:
            case Opcodes.SASTORE:
            case Opcodes.CASTORE:
            case Opcodes.AASTORE:
            case Opcodes.IASTORE:
            case Opcodes.DASTORE:
            case Opcodes.LASTORE:
            case Opcodes.FASTORE:
                {
                    if (iter > 2 && current instanceof BasicInstruction) {
                        StringBuilder devNull = new StringBuilder();
                        String arrayLiteral = null;
                        String indexLiteral = null;
                        String valueLiteral = null;
                        Instruction prev3 = instructions.get(iter - 3);
                        if (prev3 instanceof AssignableExpression) {
                            if (((AssignableExpression) prev3).assignTo(null, devNull)) {
                                arrayLiteral = devNull.toString().trim();
                            }
                        }
                        devNull.setLength(0);
                        Instruction prev2 = instructions.get(iter - 2);
                        if (prev2 instanceof AssignableExpression) {
                            if (((AssignableExpression) prev2).assignTo(null, devNull)) {
                                indexLiteral = devNull.toString().trim();
                            }
                        }
                        devNull.setLength(0);
                        Instruction prev1 = instructions.get(iter - 1);
                        if (prev1 instanceof AssignableExpression) {
                            if (((AssignableExpression) prev1).assignTo(null, devNull)) {
                                valueLiteral = devNull.toString().trim();
                            }
                        } else if (prev1 instanceof CustomInvoke) {
                            devNull.setLength(0);
                            if (((CustomInvoke) prev1).appendExpression(devNull)) {
                                valueLiteral = devNull.toString().trim();
                            }
                        }
                        if (arrayLiteral != null && indexLiteral != null && valueLiteral != null) {
                            String elementType = null;
                            switch(current.getOpcode()) {
                                case Opcodes.AASTORE:
                                    elementType = "OBJECT";
                                    break;
                                case Opcodes.IASTORE:
                                    elementType = "INT";
                                    break;
                                case Opcodes.DASTORE:
                                    elementType = "DOUBLE";
                                    break;
                                case Opcodes.LASTORE:
                                    elementType = "LONG";
                                    break;
                                case Opcodes.FASTORE:
                                    elementType = "FLOAT";
                                    break;
                                case Opcodes.CASTORE:
                                    elementType = "CHAR";
                                    break;
                                case Opcodes.BASTORE:
                                    elementType = "BYTE";
                                    break;
                                case Opcodes.SASTORE:
                                    elementType = "SHORT";
                                    break;
                            }
                            if (elementType == null) {
                                break;
                            }
                            instructions.remove(iter - 3);
                            instructions.remove(iter - 3);
                            instructions.remove(iter - 3);
                            instructions.remove(iter - 3);
                            String code = "    CN1_SET_ARRAY_ELEMENT_" + elementType + "(" + arrayLiteral + ", " + indexLiteral + ", " + valueLiteral + ");\n";
                            instructions.add(iter - 3, new CustomIntruction(code, code, dependentClasses));
                            iter = iter - 3;
                            instructionCount = instructions.size();
                            continue;
                        }
                    }
                    break;
                }
            case Opcodes.FALOAD:
            case Opcodes.BALOAD:
            case Opcodes.IALOAD:
            case Opcodes.LALOAD:
            case Opcodes.DALOAD:
            case Opcodes.AALOAD:
            case Opcodes.SALOAD:
            case Opcodes.CALOAD:
                {
                    int newIter = ArrayLoadExpression.tryReduce(instructions, iter);
                    if (newIter >= 0) {
                        iter = newIter;
                        instructionCount = instructions.size();
                        continue;
                    }
                    break;
                }
            /* Try to optimize if statements that just use constants
                   and local variables so that they don't need the intermediate
                   push and pop from the stack.
                */
            case Opcodes.IF_ACMPEQ:
            case Opcodes.IF_ACMPNE:
            case Opcodes.IF_ICMPLE:
            case Opcodes.IF_ICMPLT:
            case Opcodes.IF_ICMPNE:
            case Opcodes.IF_ICMPGT:
            case Opcodes.IF_ICMPEQ:
            case Opcodes.IF_ICMPGE:
                {
                    if (iter > 1) {
                        Instruction leftArg = instructions.get(iter - 2);
                        Instruction rightArg = instructions.get(iter - 1);
                        String leftLiteral = null;
                        String rightLiteral = null;
                        if (leftArg instanceof AssignableExpression) {
                            StringBuilder sb = new StringBuilder();
                            if (((AssignableExpression) leftArg).assignTo(null, sb)) {
                                leftLiteral = sb.toString().trim();
                            }
                        } else if (leftArg instanceof CustomInvoke) {
                            CustomInvoke inv = (CustomInvoke) leftArg;
                            StringBuilder sb = new StringBuilder();
                            if (!"JAVA_OBJECT".equals(inv.getReturnValue()) && inv.appendExpression(sb)) {
                                leftLiteral = sb.toString().trim();
                            }
                        }
                        if (rightArg instanceof AssignableExpression) {
                            StringBuilder sb = new StringBuilder();
                            if (((AssignableExpression) rightArg).assignTo(null, sb)) {
                                rightLiteral = sb.toString().trim();
                            }
                        } else if (rightArg instanceof CustomInvoke) {
                            CustomInvoke inv = (CustomInvoke) rightArg;
                            StringBuilder sb = new StringBuilder();
                            if (!"JAVA_OBJECT".equals(inv.getReturnValue()) && inv.appendExpression(sb)) {
                                rightLiteral = sb.toString().trim();
                            }
                        }
                        if (rightLiteral != null && leftLiteral != null) {
                            Jump jmp = (Jump) current;
                            instructions.remove(iter - 2);
                            instructions.remove(iter - 2);
                            instructions.remove(iter - 2);
                            // instructions.remove(iter-2);
                            iter -= 2;
                            // instructionCount -= 2;
                            StringBuilder sb = new StringBuilder();
                            String operator = null;
                            String opName = null;
                            switch(currentOpcode) {
                                case Opcodes.IF_ICMPLE:
                                    operator = "<=";
                                    opName = "IF_ICMPLE";
                                    break;
                                case Opcodes.IF_ICMPLT:
                                    operator = "<";
                                    opName = "IF_IMPLT";
                                    break;
                                case Opcodes.IF_ICMPNE:
                                    operator = "!=";
                                    opName = "IF_ICMPNE";
                                    break;
                                case Opcodes.IF_ICMPGT:
                                    operator = ">";
                                    opName = "IF_ICMPGT";
                                    break;
                                case Opcodes.IF_ICMPGE:
                                    operator = ">=";
                                    opName = "IF_ICMPGE";
                                    break;
                                case Opcodes.IF_ICMPEQ:
                                    operator = "==";
                                    opName = "IF_ICMPEQ";
                                    break;
                                case Opcodes.IF_ACMPEQ:
                                    operator = "==";
                                    opName = "IF_ACMPEQ";
                                    break;
                                case Opcodes.IF_ACMPNE:
                                    operator = "!=";
                                    opName = "IF_ACMPNE";
                                    break;
                                default:
                                    throw new RuntimeException("Invalid operator during optimization of integer comparison");
                            }
                            sb.append("if (").append(leftLiteral).append(operator).append(rightLiteral).append(") /* ").append(opName).append(" CustomJump */ ");
                            CustomJump newJump = CustomJump.create(jmp, sb.toString());
                            // jmp.setCustomCompareCode(sb.toString());
                            newJump.setOptimized(true);
                            instructions.add(iter, newJump);
                            instructionCount = instructions.size();
                        }
                    }
                    break;
                }
            case Opcodes.IFNONNULL:
            case Opcodes.IFNULL:
            case Opcodes.IFLE:
            case Opcodes.IFLT:
            case Opcodes.IFNE:
            case Opcodes.IFGT:
            case Opcodes.IFEQ:
            case Opcodes.IFGE:
                {
                    String rightArg = "0";
                    if (currentOpcode == Opcodes.IFNONNULL || currentOpcode == Opcodes.IFNULL) {
                        rightArg = "JAVA_NULL";
                    }
                    if (iter > 0) {
                        Instruction leftArg = instructions.get(iter - 1);
                        String leftLiteral = null;
                        if (leftArg instanceof AssignableExpression) {
                            StringBuilder sb = new StringBuilder();
                            if (((AssignableExpression) leftArg).assignTo(null, sb)) {
                                leftLiteral = sb.toString().trim();
                            }
                        } else if (leftArg instanceof CustomInvoke) {
                            CustomInvoke inv = (CustomInvoke) leftArg;
                            StringBuilder sb = new StringBuilder();
                            if (inv.appendExpression(sb)) {
                                leftLiteral = sb.toString().trim();
                            }
                        }
                        if (leftLiteral != null) {
                            Jump jmp = (Jump) current;
                            instructions.remove(iter - 1);
                            instructions.remove(iter - 1);
                            // instructions.remove(iter-2);
                            iter -= 1;
                            // instructionCount -= 2;
                            StringBuilder sb = new StringBuilder();
                            String operator = null;
                            String opName = null;
                            switch(currentOpcode) {
                                case Opcodes.IFLE:
                                    operator = "<=";
                                    opName = "IFLE";
                                    break;
                                case Opcodes.IFLT:
                                    operator = "<";
                                    opName = "IFLT";
                                    break;
                                case Opcodes.IFNE:
                                    operator = "!=";
                                    opName = "IFNE";
                                    break;
                                case Opcodes.IFGT:
                                    operator = ">";
                                    opName = "IFGT";
                                    break;
                                case Opcodes.IFGE:
                                    operator = ">=";
                                    opName = "IFGE";
                                    break;
                                case Opcodes.IFEQ:
                                    operator = "==";
                                    opName = "IFEQ";
                                    break;
                                case Opcodes.IFNULL:
                                    operator = "==";
                                    opName = "IFNULL";
                                    break;
                                case Opcodes.IFNONNULL:
                                    operator = "!=";
                                    opName = "IFNONNULL";
                                    break;
                                default:
                                    throw new RuntimeException("Invalid operator during optimization of integer comparison");
                            }
                            sb.append("if (").append(leftLiteral).append(operator).append(rightArg).append(") /* ").append(opName).append(" CustomJump */ ");
                            CustomJump newJump = CustomJump.create(jmp, sb.toString());
                            // jmp.setCustomCompareCode(sb.toString());
                            newJump.setOptimized(true);
                            instructions.add(iter, newJump);
                            instructionCount = instructions.size();
                        }
                    }
                    break;
                }
            case Opcodes.INVOKEVIRTUAL:
            case Opcodes.INVOKESTATIC:
            case Opcodes.INVOKESPECIAL:
            case Opcodes.INVOKEINTERFACE:
                {
                    if (current instanceof Invoke) {
                        Invoke inv = (Invoke) current;
                        List<ByteCodeMethodArg> invocationArgs = inv.getArgs();
                        int numArgs = invocationArgs.size();
                        // }
                        if (iter >= numArgs) {
                            String[] argLiterals = new String[numArgs];
                            StringBuilder devNull = new StringBuilder();
                            for (int i = 0; i < numArgs; i++) {
                                devNull.setLength(0);
                                Instruction instr = instructions.get(iter - numArgs + i);
                                if (instr instanceof AssignableExpression && ((AssignableExpression) instr).assignTo(null, devNull)) {
                                    argLiterals[i] = devNull.toString().trim();
                                } else if (instr instanceof CustomInvoke) {
                                    CustomInvoke cinv = (CustomInvoke) instr;
                                    devNull.setLength(0);
                                    if (!"JAVA_OBJECT".equals(cinv.getReturnValue()) && cinv.appendExpression(devNull)) {
                                        // We can't add invocations that return objects directly
                                        // because they need to be added to the stack for GC
                                        argLiterals[i] = devNull.toString().trim();
                                    }
                                } else if (instr instanceof ArithmeticExpression) {
                                    argLiterals[i] = ((ArithmeticExpression) instr).getExpressionAsString().trim();
                                } else if (instr instanceof VarOp) {
                                    VarOp var = (VarOp) instr;
                                    switch(instr.getOpcode()) {
                                        case Opcodes.ALOAD:
                                            {
                                                if (!isStatic() && var.getIndex() == 0) {
                                                    argLiterals[i] = "__cn1ThisObject";
                                                } else {
                                                    argLiterals[i] = "locals[" + var.getIndex() + "].data.o";
                                                }
                                                break;
                                            }
                                        case Opcodes.ILOAD:
                                            {
                                                argLiterals[i] = "ilocals_" + var.getIndex() + "_";
                                                break;
                                            }
                                        case Opcodes.ACONST_NULL:
                                            {
                                                argLiterals[i] = "JAVA_NULL";
                                                break;
                                            }
                                        case Opcodes.DLOAD:
                                            {
                                                argLiterals[i] = "dlocals_" + var.getIndex() + "_";
                                                break;
                                            }
                                        case Opcodes.FLOAD:
                                            {
                                                argLiterals[i] = "flocals_" + var.getIndex() + "_";
                                                break;
                                            }
                                        case Opcodes.LLOAD:
                                            {
                                                argLiterals[i] = "llocals_" + var.getIndex() + "_";
                                                break;
                                            }
                                        case Opcodes.ICONST_0:
                                            {
                                                argLiterals[i] = "0";
                                                break;
                                            }
                                        case Opcodes.ICONST_1:
                                            {
                                                argLiterals[i] = "1";
                                                break;
                                            }
                                        case Opcodes.ICONST_2:
                                            {
                                                argLiterals[i] = "2";
                                                break;
                                            }
                                        case Opcodes.ICONST_3:
                                            {
                                                argLiterals[i] = "3";
                                                break;
                                            }
                                        case Opcodes.ICONST_4:
                                            {
                                                argLiterals[i] = "4";
                                                break;
                                            }
                                        case Opcodes.ICONST_5:
                                            {
                                                argLiterals[i] = "5";
                                                break;
                                            }
                                        case Opcodes.ICONST_M1:
                                            {
                                                argLiterals[i] = "-1";
                                                break;
                                            }
                                        case Opcodes.LCONST_0:
                                            {
                                                argLiterals[i] = "(JAVA_LONG)0";
                                                break;
                                            }
                                        case Opcodes.LCONST_1:
                                            {
                                                argLiterals[i] = "(JAVA_LONG)1";
                                                break;
                                            }
                                        case Opcodes.BIPUSH:
                                        case Opcodes.SIPUSH:
                                            {
                                                argLiterals[i] = String.valueOf(var.getIndex());
                                                break;
                                            }
                                    }
                                } else {
                                    switch(instr.getOpcode()) {
                                        case Opcodes.ACONST_NULL:
                                            {
                                                argLiterals[i] = "JAVA_NULL";
                                                break;
                                            }
                                        case Opcodes.ICONST_0:
                                            {
                                                argLiterals[i] = "0";
                                                break;
                                            }
                                        case Opcodes.ICONST_1:
                                            {
                                                argLiterals[i] = "1";
                                                break;
                                            }
                                        case Opcodes.ICONST_2:
                                            {
                                                argLiterals[i] = "2";
                                                break;
                                            }
                                        case Opcodes.ICONST_3:
                                            {
                                                argLiterals[i] = "3";
                                                break;
                                            }
                                        case Opcodes.ICONST_4:
                                            {
                                                argLiterals[i] = "4";
                                                break;
                                            }
                                        case Opcodes.ICONST_5:
                                            {
                                                argLiterals[i] = "5";
                                                break;
                                            }
                                        case Opcodes.ICONST_M1:
                                            {
                                                argLiterals[i] = "-1";
                                                break;
                                            }
                                        case Opcodes.LCONST_0:
                                            {
                                                argLiterals[i] = "(JAVA_LONG)0";
                                                break;
                                            }
                                        case Opcodes.LCONST_1:
                                            {
                                                argLiterals[i] = "(JAVA_LONG)1";
                                                break;
                                            }
                                        case Opcodes.BIPUSH:
                                            {
                                                if (instr instanceof BasicInstruction) {
                                                    argLiterals[i] = String.valueOf(((BasicInstruction) instr).getValue());
                                                }
                                                break;
                                            }
                                        case Opcodes.LDC:
                                            {
                                                if (instr instanceof Ldc) {
                                                    Ldc ldc = (Ldc) instr;
                                                    argLiterals[i] = ldc.getValueAsString();
                                                }
                                                break;
                                            }
                                    }
                                }
                            }
                            // Check to make sure that we have all the args as literals.
                            boolean missingLiteral = false;
                            for (String lit : argLiterals) {
                                if (lit == null) {
                                    missingLiteral = true;
                                    break;
                                }
                            }
                            // add them to our invoke instruction.
                            if (!missingLiteral) {
                                CustomInvoke newInvoke = CustomInvoke.create(inv);
                                instructions.remove(iter);
                                instructions.add(iter, newInvoke);
                                int newIter = iter;
                                for (int i = 0; i < numArgs; i++) {
                                    instructions.remove(iter - numArgs);
                                    newIter--;
                                    newInvoke.setLiteralArg(i, argLiterals[i]);
                                }
                                if (inv.getOpcode() != Opcodes.INVOKESTATIC) {
                                    Instruction ldTarget = instructions.get(iter - numArgs - 1);
                                    if (ldTarget instanceof AssignableExpression) {
                                        StringBuilder targetExprStr = new StringBuilder();
                                        if (((AssignableExpression) ldTarget).assignTo(null, targetExprStr)) {
                                            newInvoke.setTargetObjectLiteral(targetExprStr.toString().trim());
                                            instructions.remove(iter - numArgs - 1);
                                            newIter--;
                                        }
                                    } else if (ldTarget instanceof CustomInvoke) {
                                    // WE Can't pass a custom invoke as the target directly
                                    // because it the return value needs to be added to the
                                    // stack for the GC
                                    } else {
                                        switch(ldTarget.getOpcode()) {
                                            case Opcodes.ALOAD:
                                                {
                                                    VarOp v = (VarOp) ldTarget;
                                                    if (isStatic() && v.getIndex() == 0) {
                                                        newInvoke.setTargetObjectLiteral("__cn1ThisObject");
                                                    } else {
                                                        newInvoke.setTargetObjectLiteral("locals[" + v.getIndex() + "].data.o");
                                                    }
                                                    instructions.remove(iter - numArgs - 1);
                                                    newIter--;
                                                    break;
                                                }
                                        }
                                    }
                                }
                                newInvoke.setOptimized(true);
                                // iter = 0;
                                instructionCount = instructions.size();
                                iter = newIter;
                            }
                        }
                    }
                    break;
                }
        }
        astoreCalls = astoreCalls || currentOpcode == Opcodes.ASTORE || currentOpcode == Opcodes.ISTORE || currentOpcode == Opcodes.LSTORE || currentOpcode == Opcodes.DSTORE || currentOpcode == Opcodes.FSTORE;
        hasInstructions = hasInstructions | current.getOpcode() != -1;
    }
    return hasInstructions;
}
Also used : TryCatch(com.codename1.tools.translator.bytecodes.TryCatch) VarOp(com.codename1.tools.translator.bytecodes.VarOp) CustomIntruction(com.codename1.tools.translator.bytecodes.CustomIntruction) LabelInstruction(com.codename1.tools.translator.bytecodes.LabelInstruction) Ldc(com.codename1.tools.translator.bytecodes.Ldc) BasicInstruction(com.codename1.tools.translator.bytecodes.BasicInstruction) SwitchInstruction(com.codename1.tools.translator.bytecodes.SwitchInstruction) TypeInstruction(com.codename1.tools.translator.bytecodes.TypeInstruction) Instruction(com.codename1.tools.translator.bytecodes.Instruction) LabelInstruction(com.codename1.tools.translator.bytecodes.LabelInstruction) ArithmeticExpression(com.codename1.tools.translator.bytecodes.ArithmeticExpression) CustomInvoke(com.codename1.tools.translator.bytecodes.CustomInvoke) Jump(com.codename1.tools.translator.bytecodes.Jump) CustomJump(com.codename1.tools.translator.bytecodes.CustomJump) LineNumber(com.codename1.tools.translator.bytecodes.LineNumber) CustomInvoke(com.codename1.tools.translator.bytecodes.CustomInvoke) Invoke(com.codename1.tools.translator.bytecodes.Invoke) Field(com.codename1.tools.translator.bytecodes.Field) BasicInstruction(com.codename1.tools.translator.bytecodes.BasicInstruction) AssignableExpression(com.codename1.tools.translator.bytecodes.AssignableExpression) CustomJump(com.codename1.tools.translator.bytecodes.CustomJump) ArrayList(java.util.ArrayList) List(java.util.List)

Example 3 with Instruction

use of com.codename1.tools.translator.bytecodes.Instruction in project CodenameOne by codenameone.

the class BytecodeMethod method isMethodUsed.

// [ddyer 4/2017] avoid creating a lot of temporary objects.
// more than 3x faster than the old way.
public boolean isMethodUsed(BytecodeMethod bm0) {
    SignatureSet bm = (SignatureSet) bm0;
    if (usedSigs == null) {
        usedSigs = new Hashtable<String, SignatureSet>();
        for (Instruction ins : instructions) {
            String sname = ins.getMethodName();
            if (sname != null) {
                SignatureSet ss = usedSigs.get(sname);
                // either use the instruction itself, or create a set of them
                ss = ss == null ? ins : new MultipleSignatureSet((SignatureSet) ins, ss);
                usedSigs.put(sname, ss);
            }
        }
    }
    String name = bm.getMethodName();
    SignatureSet ss = usedSigs.get("__INIT__".equals(name) ? "<init>" : name);
    return ((ss == null) ? false : ss.containsSignature(bm));
}
Also used : BasicInstruction(com.codename1.tools.translator.bytecodes.BasicInstruction) SwitchInstruction(com.codename1.tools.translator.bytecodes.SwitchInstruction) TypeInstruction(com.codename1.tools.translator.bytecodes.TypeInstruction) Instruction(com.codename1.tools.translator.bytecodes.Instruction) LabelInstruction(com.codename1.tools.translator.bytecodes.LabelInstruction)

Aggregations

BasicInstruction (com.codename1.tools.translator.bytecodes.BasicInstruction)3 Instruction (com.codename1.tools.translator.bytecodes.Instruction)3 LabelInstruction (com.codename1.tools.translator.bytecodes.LabelInstruction)3 SwitchInstruction (com.codename1.tools.translator.bytecodes.SwitchInstruction)3 TypeInstruction (com.codename1.tools.translator.bytecodes.TypeInstruction)3 ArithmeticExpression (com.codename1.tools.translator.bytecodes.ArithmeticExpression)1 AssignableExpression (com.codename1.tools.translator.bytecodes.AssignableExpression)1 CustomIntruction (com.codename1.tools.translator.bytecodes.CustomIntruction)1 CustomInvoke (com.codename1.tools.translator.bytecodes.CustomInvoke)1 CustomJump (com.codename1.tools.translator.bytecodes.CustomJump)1 Field (com.codename1.tools.translator.bytecodes.Field)1 Invoke (com.codename1.tools.translator.bytecodes.Invoke)1 Jump (com.codename1.tools.translator.bytecodes.Jump)1 Ldc (com.codename1.tools.translator.bytecodes.Ldc)1 LineNumber (com.codename1.tools.translator.bytecodes.LineNumber)1 LocalVariable (com.codename1.tools.translator.bytecodes.LocalVariable)1 TryCatch (com.codename1.tools.translator.bytecodes.TryCatch)1 VarOp (com.codename1.tools.translator.bytecodes.VarOp)1 ArrayList (java.util.ArrayList)1 HashSet (java.util.HashSet)1