use of com.codename1.tools.translator.bytecodes.CustomInvoke in project CodenameOne by codenameone.
the class CustomInvoke method appendExpression.
public boolean appendExpression(StringBuilder b) {
// special case for clone on an array which isn't a real method invocation
if (name.equals("clone") && owner.indexOf('[') > -1) {
if (targetObjectLiteral != null) {
b.append("cloneArray(").append(targetObjectLiteral).append(")");
} else {
b.append("cloneArray(POP_OBJ(1))");
}
return true;
}
StringBuilder bld = new StringBuilder();
if (origOpcode == Opcodes.INVOKEINTERFACE || origOpcode == Opcodes.INVOKEVIRTUAL) {
// b.append(" ");
bld.append("virtual_");
}
if (origOpcode == Opcodes.INVOKESTATIC) {
// find the actual class of the static method to workaround javac not defining it correctly
ByteCodeClass bc = Parser.getClassObject(owner.replace('/', '_').replace('$', '_'));
owner = findActualOwner(bc);
}
bld.append(owner.replace('/', '_').replace('$', '_'));
bld.append("_");
if (name.equals("<init>")) {
bld.append("__INIT__");
} else {
if (name.equals("<clinit>")) {
bld.append("__CLINIT__");
} else {
bld.append(name);
}
}
bld.append("__");
ArrayList<String> args = new ArrayList<String>();
String returnVal = BytecodeMethod.appendMethodSignatureSuffixFromDesc(desc, bld, args);
int numLiteralArgs = this.getNumLiteralArgs();
if (numLiteralArgs > 0) {
b.append("/* CustomInvoke */");
}
boolean noPop = false;
b.append(bld);
b.append("(threadStateData");
if (origOpcode != Opcodes.INVOKESTATIC) {
if (targetObjectLiteral == null) {
// b.append("].data.o");
return false;
} else {
b.append(", ").append(targetObjectLiteral);
numLiteralArgs++;
}
}
// int offset = args.size();
// int numArgs = offset;
int argIndex = 0;
for (String a : args) {
b.append(", ");
if (literalArgs != null && literalArgs[argIndex] != null) {
b.append(literalArgs[argIndex]);
} else {
return false;
// b.append("SP[-");
// b.append(offset);
// b.append("].data.");
// b.append(a);
// offset--;
}
argIndex++;
}
if (returnVal == null) {
return false;
}
b.append(")");
return true;
}
use of com.codename1.tools.translator.bytecodes.CustomInvoke 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;
}
use of com.codename1.tools.translator.bytecodes.CustomInvoke in project CodenameOne by codenameone.
the class CustomInvoke method appendInstruction.
@Override
public void appendInstruction(StringBuilder b) {
// special case for clone on an array which isn't a real method invocation
if (name.equals("clone") && owner.indexOf('[') > -1) {
if (targetObjectLiteral != null) {
b.append(" PUSH_OBJ(cloneArray(").append(targetObjectLiteral).append("));\n");
} else {
b.append(" POP_MANY_AND_PUSH_OBJ(cloneArray(PEEK_OBJ(1)), 1);\n");
}
return;
}
StringBuilder bld = new StringBuilder();
if (origOpcode == Opcodes.INVOKEINTERFACE || origOpcode == Opcodes.INVOKEVIRTUAL) {
b.append(" ");
bld.append("virtual_");
} else {
b.append(" ");
}
if (origOpcode == Opcodes.INVOKESTATIC) {
// find the actual class of the static method to workaround javac not defining it correctly
ByteCodeClass bc = Parser.getClassObject(owner.replace('/', '_').replace('$', '_'));
owner = findActualOwner(bc);
}
// if(owner.replace('/', '_').replace('$', '_').equals("java_lang_System_1") && name.equals("sleep")) {
// System.out.println("Break");
// }
bld.append(owner.replace('/', '_').replace('$', '_'));
bld.append("_");
if (name.equals("<init>")) {
bld.append("__INIT__");
} else {
if (name.equals("<clinit>")) {
bld.append("__CLINIT__");
} else {
bld.append(name);
}
}
bld.append("__");
ArrayList<String> args = new ArrayList<String>();
String returnVal = BytecodeMethod.appendMethodSignatureSuffixFromDesc(desc, bld, args);
int numLiteralArgs = this.getNumLiteralArgs();
if (numLiteralArgs > 0) {
b.append("/* CustomInvoke */");
}
boolean noPop = false;
if (returnVal == null || noReturn) {
b.append(bld);
} else {
if (args.size() - numLiteralArgs == 0 && origOpcode == Opcodes.INVOKESTATIC) {
// special case for static method
if (returnVal.equals("JAVA_OBJECT")) {
b.append("PUSH_OBJ");
} else {
if (returnVal.equals("JAVA_INT")) {
b.append("PUSH_INT");
} else {
if (returnVal.equals("JAVA_LONG")) {
b.append("PUSH_LONG");
} else {
if (returnVal.equals("JAVA_DOUBLE")) {
b.append("PUSH_DOUBLE");
} else {
if (returnVal.equals("JAVA_FLOAT")) {
b.append("PUSH_FLOAT");
} else {
throw new UnsupportedOperationException("Unknown type: " + returnVal);
}
}
}
}
}
// b.append(returnVal);
noPop = true;
b.append("(");
} else {
// b.append("POP_MANY_AND_");
// b.append(returnVal);
b.append("{ ");
b.append(returnVal);
b.append(" tmpResult = ");
}
b.append(bld);
}
b.append("(threadStateData");
if (origOpcode != Opcodes.INVOKESTATIC) {
if (targetObjectLiteral == null) {
b.append(", SP[-");
b.append(args.size() + 1 - numLiteralArgs);
b.append("].data.o");
} else {
b.append(", " + targetObjectLiteral);
numLiteralArgs++;
}
}
int offset = args.size();
// int numArgs = offset;
int argIndex = 0;
for (String a : args) {
b.append(", ");
if (literalArgs != null && literalArgs[argIndex] != null) {
b.append(literalArgs[argIndex]);
} else {
b.append("SP[-");
b.append(offset);
b.append("].data.");
b.append(a);
offset--;
}
argIndex++;
}
if (noPop) {
b.append("));\n");
return;
}
if (returnVal != null && !noReturn) {
b.append(");\n");
if (origOpcode != Opcodes.INVOKESTATIC) {
if (args.size() - numLiteralArgs > 0) {
b.append(" SP -= ");
b.append(args.size() - numLiteralArgs);
b.append(";\n");
}
} else {
if (args.size() - numLiteralArgs > 1) {
b.append(" SP -= ");
b.append(args.size() - numLiteralArgs - 1);
b.append(";\n");
}
}
if (targetObjectLiteral == null) {
if (returnVal.equals("JAVA_OBJECT")) {
b.append(" SP[-1].data.o = tmpResult; SP[-1].type = CN1_TYPE_OBJECT; }\n");
} else {
if (returnVal.equals("JAVA_INT")) {
b.append(" SP[-1].data.i = tmpResult; SP[-1].type = CN1_TYPE_INT; }\n");
} else {
if (returnVal.equals("JAVA_LONG")) {
b.append(" SP[-1].data.l = tmpResult; SP[-1].type = CN1_TYPE_LONG; }\n");
} else {
if (returnVal.equals("JAVA_DOUBLE")) {
b.append(" SP[-1].data.d = tmpResult; SP[-1].type = CN1_TYPE_DOUBLE; }\n");
} else {
if (returnVal.equals("JAVA_FLOAT")) {
b.append(" SP[-1].data.f = tmpResult; SP[-1].type = CN1_TYPE_FLOAT; }\n");
} else {
throw new UnsupportedOperationException("Unknown type: " + returnVal);
}
}
}
}
}
} else {
if (returnVal.equals("JAVA_OBJECT")) {
b.append(" PUSH_OBJ(tmpResult); }\n");
} else {
if (returnVal.equals("JAVA_INT")) {
b.append(" PUSH_INT(tmpResult); }\n");
} else {
if (returnVal.equals("JAVA_LONG")) {
b.append(" PUSH_LONG(tmpResult); }\n");
} else {
if (returnVal.equals("JAVA_DOUBLE")) {
b.append(" PUSH_DOUBLE(tmpResult); }\n");
} else {
if (returnVal.equals("JAVA_FLOAT")) {
b.append(" PUSH_FLOAT(tmpResult); }\n");
} else {
throw new UnsupportedOperationException("Unknown type: " + returnVal);
}
}
}
}
}
}
return;
}
b.append("); ");
int val;
if (origOpcode != Opcodes.INVOKESTATIC) {
val = args.size() + 1 - numLiteralArgs;
} else {
val = args.size() - numLiteralArgs;
}
if (val > 0) {
b.append(" SP -= ");
b.append(val);
b.append(";\n");
} else {
b.append("\n");
}
}
Aggregations