diff --git a/vm/ByteCodeTranslator/src/com/codename1/tools/translator/BytecodeMethod.java b/vm/ByteCodeTranslator/src/com/codename1/tools/translator/BytecodeMethod.java index 14f56f231c..e672cccb66 100644 --- a/vm/ByteCodeTranslator/src/com/codename1/tools/translator/BytecodeMethod.java +++ b/vm/ByteCodeTranslator/src/com/codename1/tools/translator/BytecodeMethod.java @@ -106,6 +106,7 @@ public static void setDependencyGraph(MethodDependencyGraph dependencyGraph) { private final static Set virtualMethodsInvoked = new TreeSet(); private String desc; private boolean eliminated; + private boolean barebone; static boolean optimizerOn; @@ -115,6 +116,150 @@ public static void setDependencyGraph(MethodDependencyGraph dependencyGraph) { optimizerOn = op == null || op.equalsIgnoreCase("on"); //optimizerOn = false; } + + public boolean isBarebone() { + return barebone; + } + + private boolean checkBarebone() { + if(synchronizedMethod || nativeMethod || hasExceptionHandlingOrMethodCalls() || localVariables.size() > 0) { + return false; + } + int argSlots = 0; + if(!staticMethod) { + argSlots++; + } + for(ByteCodeMethodArg arg : arguments) { + argSlots++; + if(arg.isDoubleOrLong()) { + argSlots++; + } + } + if(maxLocals > argSlots) { + return false; + } + for(Instruction i : instructions) { + if(i instanceof LabelInstruction || i instanceof LineNumber || i instanceof IInc || + i instanceof Jump || i instanceof CustomJump || i instanceof LocalVariable) { + continue; + } + if(i instanceof BasicInstruction) { + int op = i.getOpcode(); + switch(op) { + case Opcodes.SIPUSH: + case Opcodes.BIPUSH: + case Opcodes.ICONST_0: + case Opcodes.ICONST_1: + case Opcodes.ICONST_2: + case Opcodes.ICONST_3: + case Opcodes.ICONST_4: + case Opcodes.ICONST_5: + case Opcodes.ICONST_M1: + case Opcodes.LCONST_0: + case Opcodes.LCONST_1: + case Opcodes.FCONST_0: + case Opcodes.FCONST_1: + case Opcodes.FCONST_2: + case Opcodes.DCONST_0: + case Opcodes.DCONST_1: + case Opcodes.RETURN: + case Opcodes.IRETURN: + case Opcodes.LRETURN: + case Opcodes.FRETURN: + case Opcodes.DRETURN: + case Opcodes.ARETURN: + case Opcodes.NOP: + case Opcodes.POP: + case Opcodes.POP2: + case Opcodes.DUP: + case Opcodes.DUP2: + case Opcodes.DUP_X1: + case Opcodes.DUP2_X1: + case Opcodes.DUP_X2: + case Opcodes.DUP2_X2: + case Opcodes.SWAP: + case Opcodes.IADD: + case Opcodes.LADD: + case Opcodes.FADD: + case Opcodes.DADD: + case Opcodes.ISUB: + case Opcodes.LSUB: + case Opcodes.FSUB: + case Opcodes.DSUB: + case Opcodes.IMUL: + case Opcodes.LMUL: + case Opcodes.FMUL: + case Opcodes.DMUL: + case Opcodes.IDIV: + case Opcodes.LDIV: + case Opcodes.FDIV: + case Opcodes.DDIV: + case Opcodes.IREM: + case Opcodes.LREM: + case Opcodes.FREM: + case Opcodes.DREM: + case Opcodes.INEG: + case Opcodes.LNEG: + case Opcodes.FNEG: + case Opcodes.DNEG: + case Opcodes.ISHL: + case Opcodes.LSHL: + case Opcodes.ISHR: + case Opcodes.LSHR: + case Opcodes.IUSHR: + case Opcodes.LUSHR: + case Opcodes.IAND: + case Opcodes.LAND: + case Opcodes.IOR: + case Opcodes.LOR: + case Opcodes.IXOR: + case Opcodes.LXOR: + case Opcodes.I2L: + case Opcodes.I2F: + case Opcodes.I2D: + case Opcodes.L2I: + case Opcodes.L2F: + case Opcodes.L2D: + case Opcodes.F2I: + case Opcodes.F2L: + case Opcodes.F2D: + case Opcodes.D2I: + case Opcodes.D2L: + case Opcodes.D2F: + case Opcodes.I2B: + case Opcodes.I2C: + case Opcodes.I2S: + case Opcodes.LCMP: + case Opcodes.FCMPG: + case Opcodes.FCMPL: + case Opcodes.DCMPL: + case Opcodes.DCMPG: + continue; + } + return false; + } + if(i instanceof VarOp) { + continue; + } + if(i instanceof ArithmeticExpression) { + continue; + } + if(i instanceof Field) { + int op = i.getOpcode(); + if(op == Opcodes.GETFIELD) { + continue; + } + if(op == Opcodes.PUTFIELD) { + if(((Field)i).isObject()) { + return false; + } + continue; + } + } + return false; + } + return true; + } public BytecodeMethod(String clsName, int access, String name, String desc, String signature, String[] exceptions) { methodName = name; @@ -603,6 +748,42 @@ private boolean hasLocalVariableWithIndex(char qualifier, int index) { return false; } + private void fixUpBarebone() { + for (Instruction i : instructions) { + if (i instanceof CustomJump) { + CustomJump cj = (CustomJump)i; + String cmp = cj.getCustomCompareCode(); + if (cmp != null) { + cj.setCustomCompareCode(cmp.replaceAll("locals\\[(\\d+)\\]\\.data\\.o", "olocals_$1_")); + } + } else if (i instanceof CustomIntruction) { + CustomIntruction ci = (CustomIntruction)i; + String code = ci.getCode(); + if (code != null) { + ci.setCode(code.replaceAll("locals\\[(\\d+)\\]\\.data\\.o", "olocals_$1_")); + } + String complexCode = ci.getComplexCode(); + if (complexCode != null) { + ci.setComplexCode(complexCode.replaceAll("locals\\[(\\d+)\\]\\.data\\.o", "olocals_$1_")); + } + } else if (i instanceof CustomInvoke) { + CustomInvoke ci = (CustomInvoke)i; + String target = ci.getTargetObjectLiteral(); + if (target != null) { + ci.setTargetObjectLiteral(target.replaceAll("locals\\[(\\d+)\\]\\.data\\.o", "olocals_$1_")); + } + String[] args = ci.getLiteralArgs(); + if (args != null) { + for (int j=0; j added = new HashSet(); for (LocalVariable lv : localVariables) { String variableName = lv.getQualifier() + "locals_"+lv.getIndex()+"_"; - if (!added.contains(variableName) && lv.getQualifier() != 'o') { + if (!added.contains(variableName) && (barebone || lv.getQualifier() != 'o')) { added.add(variableName); b.append(" volatile "); switch (lv.getQualifier()) { @@ -641,30 +826,36 @@ public void appendMethodC(StringBuilder b) { b.append("JAVA_FLOAT"); break; case 'd' : b.append("JAVA_DOUBLE"); break; + case 'o' : + b.append("JAVA_OBJECT"); 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("); + if(!barebone) { + 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(" __STATIC_INITIALIZER_"); - b.append(clsName.replace('/', '_').replace('$', '_')); - b.append("(threadStateData);\n DEFINE_METHOD_STACK("); + 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"); } else { - b.append(" DEFINE_INSTANCE_METHOD_STACK("); + b.append(" struct elementStruct* SP = &threadStateData->threadObjectStack[threadStateData->threadObjectStackOffset];\n"); } - 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) { @@ -676,25 +867,34 @@ public void appendMethodC(StringBuilder b) { } } if(!staticMethod) { - b.append(" locals[0].data.o = __cn1ThisObject; locals[0].type = CN1_TYPE_OBJECT; "); + if(!barebone) { + 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."); + if(barebone) { + b.append(" JAVA_OBJECT olocals_"); + b.append(localsOffset); + b.append("_ = __cn1Arg"); + b.append(iter + 1); + b.append(";\n"); + } else { + 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"); - + 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)) { @@ -739,6 +939,7 @@ public void appendMethodC(StringBuilder b) { TryCatch.reset(); BasicInstruction.setHasInstructions(hasInstructions); for(Instruction i : instructions) { + i.setMethod(this); i.setMaxes(maxStack, maxLocals); i.appendInstruction(b, instructions); } diff --git a/vm/ByteCodeTranslator/src/com/codename1/tools/translator/bytecodes/BasicInstruction.java b/vm/ByteCodeTranslator/src/com/codename1/tools/translator/bytecodes/BasicInstruction.java index 79d3f7eeac..779d247bec 100644 --- a/vm/ByteCodeTranslator/src/com/codename1/tools/translator/bytecodes/BasicInstruction.java +++ b/vm/ByteCodeTranslator/src/com/codename1/tools/translator/bytecodes/BasicInstruction.java @@ -532,9 +532,13 @@ public void appendInstruction(StringBuilder b, List instructions) { // b.append(maxLocals); // b.append(", stack, locals, methodBlockOffset); \n return SP[-1].data.i;\n"); } else { - b.append(" releaseForReturn(threadStateData, cn1LocalsBeginInThread); return SP[-1].data.i;\n"); + if(getMethod() != null && getMethod().isBarebone()) { + b.append(" return SP[-1].data.i;\n"); + } else { + b.append(" releaseForReturn(threadStateData, cn1LocalsBeginInThread); return SP[-1].data.i;\n"); // b.append(maxLocals); // b.append(", stack, locals); \n return SP[-1].data.i;\n"); + } } break; @@ -544,7 +548,11 @@ public void appendInstruction(StringBuilder b, List instructions) { if(TryCatch.isTryCatchInMethod()) { b.append(" releaseForReturnInException(threadStateData, cn1LocalsBeginInThread, methodBlockOffset); \n return POP_LONG();\n"); } else { - b.append(" releaseForReturn(threadStateData, cn1LocalsBeginInThread); \n return POP_LONG();\n"); + if(getMethod() != null && getMethod().isBarebone()) { + b.append(" return POP_LONG();\n"); + } else { + b.append(" releaseForReturn(threadStateData, cn1LocalsBeginInThread); \n return POP_LONG();\n"); + } } break; @@ -554,7 +562,11 @@ public void appendInstruction(StringBuilder b, List instructions) { if(TryCatch.isTryCatchInMethod()) { b.append(" releaseForReturnInException(threadStateData, cn1LocalsBeginInThread, methodBlockOffset); \n return POP_FLOAT();\n"); } else { - b.append(" releaseForReturn(threadStateData, cn1LocalsBeginInThread); \n return POP_FLOAT();\n"); + if(getMethod() != null && getMethod().isBarebone()) { + b.append(" return POP_FLOAT();\n"); + } else { + b.append(" releaseForReturn(threadStateData, cn1LocalsBeginInThread); \n return POP_FLOAT();\n"); + } } break; @@ -564,7 +576,11 @@ public void appendInstruction(StringBuilder b, List instructions) { if(TryCatch.isTryCatchInMethod()) { b.append(" releaseForReturnInException(threadStateData, cn1LocalsBeginInThread, methodBlockOffset); \n return POP_DOUBLE();\n"); } else { - b.append(" releaseForReturn(threadStateData, cn1LocalsBeginInThread); \n return POP_DOUBLE();\n"); + if(getMethod() != null && getMethod().isBarebone()) { + b.append(" return POP_DOUBLE();\n"); + } else { + b.append(" releaseForReturn(threadStateData, cn1LocalsBeginInThread); \n return POP_DOUBLE();\n"); + } } break; @@ -574,7 +590,11 @@ public void appendInstruction(StringBuilder b, List instructions) { if(TryCatch.isTryCatchInMethod()) { b.append(" releaseForReturnInException(threadStateData, cn1LocalsBeginInThread, methodBlockOffset); \n return POP_OBJ();\n"); } else { - b.append(" releaseForReturn(threadStateData, cn1LocalsBeginInThread); \n return POP_OBJ();\n"); + if(getMethod() != null && getMethod().isBarebone()) { + b.append(" return POP_OBJ();\n"); + } else { + b.append(" releaseForReturn(threadStateData, cn1LocalsBeginInThread); \n return POP_OBJ();\n"); + } } break; @@ -588,7 +608,11 @@ public void appendInstruction(StringBuilder b, List instructions) { if(TryCatch.isTryCatchInMethod()) { b.append(" releaseForReturnInException(threadStateData, cn1LocalsBeginInThread, methodBlockOffset); \n return;\n"); } else { - b.append(" releaseForReturn(threadStateData, cn1LocalsBeginInThread); \n return;\n"); + if(getMethod() != null && getMethod().isBarebone()) { + b.append(" return;\n"); + } else { + b.append(" releaseForReturn(threadStateData, cn1LocalsBeginInThread); \n return;\n"); + } } break; diff --git a/vm/ByteCodeTranslator/src/com/codename1/tools/translator/bytecodes/CustomIntruction.java b/vm/ByteCodeTranslator/src/com/codename1/tools/translator/bytecodes/CustomIntruction.java index 890db8cdb8..32fa3ea030 100644 --- a/vm/ByteCodeTranslator/src/com/codename1/tools/translator/bytecodes/CustomIntruction.java +++ b/vm/ByteCodeTranslator/src/com/codename1/tools/translator/bytecodes/CustomIntruction.java @@ -71,6 +71,22 @@ public AssignableExpression getAssignableExpression() { return assignableExpression; } + public String getCode() { + return code; + } + + public void setCode(String code) { + this.code = code; + } + + public String getComplexCode() { + return complexCode; + } + + public void setComplexCode(String complexCode) { + this.complexCode = complexCode; + } + @Override public boolean assignTo(String varName, StringBuilder sb) { if (assignableExpression != null) { diff --git a/vm/ByteCodeTranslator/src/com/codename1/tools/translator/bytecodes/CustomInvoke.java b/vm/ByteCodeTranslator/src/com/codename1/tools/translator/bytecodes/CustomInvoke.java index a239dcba0c..31ff14c547 100644 --- a/vm/ByteCodeTranslator/src/com/codename1/tools/translator/bytecodes/CustomInvoke.java +++ b/vm/ByteCodeTranslator/src/com/codename1/tools/translator/bytecodes/CustomInvoke.java @@ -499,6 +499,10 @@ public void setLiteralArg(int index, String arg) { } literalArgs[index] = arg; } + + public String[] getLiteralArgs() { + return literalArgs; + } private int getNumLiteralArgs() { if (literalArgs == null) { diff --git a/vm/ByteCodeTranslator/src/com/codename1/tools/translator/bytecodes/CustomJump.java b/vm/ByteCodeTranslator/src/com/codename1/tools/translator/bytecodes/CustomJump.java index 50b12a3f39..2f42bf32d5 100644 --- a/vm/ByteCodeTranslator/src/com/codename1/tools/translator/bytecodes/CustomJump.java +++ b/vm/ByteCodeTranslator/src/com/codename1/tools/translator/bytecodes/CustomJump.java @@ -72,4 +72,8 @@ public void appendInstruction(StringBuilder b, List instructions) { public void setCustomCompareCode(String code) { this.customCompareCode = code; } + + public String getCustomCompareCode() { + return customCompareCode; + } } diff --git a/vm/ByteCodeTranslator/src/com/codename1/tools/translator/bytecodes/IInc.java b/vm/ByteCodeTranslator/src/com/codename1/tools/translator/bytecodes/IInc.java index 0b539f2cc1..d2d7fc24e2 100644 --- a/vm/ByteCodeTranslator/src/com/codename1/tools/translator/bytecodes/IInc.java +++ b/vm/ByteCodeTranslator/src/com/codename1/tools/translator/bytecodes/IInc.java @@ -41,6 +41,14 @@ public IInc(int var, int num) { @Override public void appendInstruction(StringBuilder b) { + if(getMethod() != null && getMethod().isBarebone()) { + b.append(" ilocals_"); + b.append(var); + b.append("_ += "); + b.append(num); + b.append(";\n"); + return; + } b.append(" BC_IINC("); b.append(var); b.append(", "); diff --git a/vm/ByteCodeTranslator/src/com/codename1/tools/translator/bytecodes/VarOp.java b/vm/ByteCodeTranslator/src/com/codename1/tools/translator/bytecodes/VarOp.java index 70bba642ac..8ed28d0b7d 100644 --- a/vm/ByteCodeTranslator/src/com/codename1/tools/translator/bytecodes/VarOp.java +++ b/vm/ByteCodeTranslator/src/com/codename1/tools/translator/bytecodes/VarOp.java @@ -84,9 +84,15 @@ public boolean assignTo(String varName, StringBuilder sb) { if (getMethod() != null && !getMethod().isStatic() && var == 0) { b.append("__cn1ThisObject"); } else { - b.append("locals["); - b.append(var); - b.append("].data.o"); + if(getMethod() != null && getMethod().isBarebone()) { + b.append("olocals_"); + b.append(var); + b.append("_"); + } else { + b.append("locals["); + b.append(var); + b.append("].data.o"); + } } break; default: @@ -113,6 +119,12 @@ public boolean assignFrom(AssignableExpression ex, StringBuilder b) { case Opcodes.DSTORE: return ex.assignTo("dlocals_"+var+"_", b); case Opcodes.ASTORE: { + if(getMethod() != null && getMethod().isBarebone()) { + if (!getMethod().isStatic() && var == 0) { + return ex.assignTo("__cn1ThisObject", b); + } + return ex.assignTo("olocals_" + var + "_", b); + } StringBuilder sb = new StringBuilder(); sb.append("locals[").append(var).append("].type=CN1_TYPE_INVALID;"); boolean res = ex.assignTo("locals["+var+"].data.o", sb); @@ -161,6 +173,16 @@ public boolean assignFrom(CustomInvoke ex, StringBuilder b) { break; case Opcodes.ASTORE: { + if(getMethod() != null && getMethod().isBarebone()) { + if (ex.appendExpression(sb)) { + if (!getMethod().isStatic() && var == 0) { + b.append("__cn1ThisObject = ").append(sb.toString().trim()).append(";\n"); + } else { + b.append("olocals_").append(var).append("_ = ").append(sb.toString().trim()).append(";\n"); + } + return true; + } + } StringBuilder sb2 = new StringBuilder(); //sb2.append("locals[").append(var).append("].type=CN1_TYPE_INVALID; "); if (ex.appendExpression(sb)) { @@ -184,36 +206,104 @@ public void appendInstruction(StringBuilder b) { b.append(" "); switch(opcode) { case Opcodes.ILOAD: + if (getMethod() != null && getMethod().isBarebone()) { + b.append("PUSH_INT(ilocals_"); + b.append(var); + b.append("_); /* ILOAD */\n"); + return; + } b.append("(*SP).type = CN1_TYPE_INT; /* ILOAD */ \n" + " (*SP).data.i = ilocals_"); b.append(var); b.append("_; \n SP++;\n"); return; case Opcodes.LLOAD: + if (getMethod() != null && getMethod().isBarebone()) { + b.append("PUSH_LONG(llocals_"); + b.append(var); + b.append("_); /* LLOAD */\n"); + return; + } b.append("BC_LLOAD("); break; case Opcodes.FLOAD: + if (getMethod() != null && getMethod().isBarebone()) { + b.append("PUSH_FLOAT(flocals_"); + b.append(var); + b.append("_); /* FLOAD */\n"); + return; + } b.append("BC_FLOAD("); break; case Opcodes.DLOAD: + if (getMethod() != null && getMethod().isBarebone()) { + b.append("PUSH_DOUBLE(dlocals_"); + b.append(var); + b.append("_); /* DLOAD */\n"); + return; + } b.append("BC_DLOAD("); break; case Opcodes.ALOAD: + if (getMethod() != null && getMethod().isBarebone()) { + if (!getMethod().isStatic() && var == 0) { + b.append("PUSH_POINTER(__cn1ThisObject); /* ALOAD */\n"); + } else { + b.append("PUSH_POINTER(olocals_"); + b.append(var); + b.append("_); /* ALOAD */\n"); + } + return; + } b.append("BC_ALOAD("); break; case Opcodes.ISTORE: + if (getMethod() != null && getMethod().isBarebone()) { + b.append("ilocals_"); + b.append(var); + b.append("_ = POP_INT(); /* ISTORE */\n"); + return; + } b.append("BC_ISTORE("); break; case Opcodes.LSTORE: + if (getMethod() != null && getMethod().isBarebone()) { + b.append("llocals_"); + b.append(var); + b.append("_ = POP_LONG(); /* LSTORE */\n"); + return; + } b.append("BC_LSTORE("); break; case Opcodes.FSTORE: + if (getMethod() != null && getMethod().isBarebone()) { + b.append("flocals_"); + b.append(var); + b.append("_ = POP_FLOAT(); /* FSTORE */\n"); + return; + } b.append("BC_FSTORE("); break; case Opcodes.DSTORE: + if (getMethod() != null && getMethod().isBarebone()) { + b.append("dlocals_"); + b.append(var); + b.append("_ = POP_DOUBLE(); /* DSTORE */\n"); + return; + } b.append("BC_DSTORE("); break; case Opcodes.ASTORE: + if(getMethod() != null && getMethod().isBarebone()) { + if (!getMethod().isStatic() && var == 0) { + b.append("__cn1ThisObject = POP_OBJ(); /* ASTORE */\n"); + } else { + b.append("olocals_"); + b.append(var); + b.append("_ = POP_OBJ(); /* ASTORE */\n"); + } + return; + } b.append("BC_ASTORE("); break; case Opcodes.RET: