use of com.codename1.tools.translator.bytecodes.Jump in project CodenameOne by codenameone.
the class HTMLComponent method goToAnchor.
/**
* Jumps to the given anchor
*
* @param anchorName The anchor to jump to
*/
void goToAnchor(String anchorName) {
Label anchorCmp = (Label) anchors.get(anchorName);
if (anchorCmp != null) {
int cx = anchorCmp.getX();
int cy = anchorCmp.getY();
int h = getHeight();
if (anchorCmp.getAbsoluteY() - getY() + h > getPreferredH()) {
h = getPreferredH() - (anchorCmp.getAbsoluteY() - getY());
}
scrollRectToVisible(cx, cy, getWidth(), h, anchorCmp);
}
}
use of com.codename1.tools.translator.bytecodes.Jump 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;
}
Aggregations