/** * Optimizations for OP_convert_d: convert_d, convert_d -> convert_d pushbyte n, convert_d -> * pushdouble n pushint n, convert_d -> pushdouble n pushuint n, convert_d -> pushdouble n * pushdouble n, convert_d -> pushdouble n pushnan, convert_d -> pushnan lf32, convert_d -> lf32 * lf64, convert_d -> lf64 * * @param i The convert_d instruction */ private void op_convert_d(InstructionInfo i) { InstructionInfo prev = previous(1); switch (prev.getOpcode()) { case OP_pushbyte: { // replace pushbyte, convert d with pushdouble - should be faster replace( 1, InstructionFactory.getInstruction( OP_pushdouble, new Double(convertByteImmediateToDouble(prev.getImmediate())))); break; } case OP_pushint: case OP_pushuint: { // replace pushint , convert d with pushdouble - should be faster replace( 1, InstructionFactory.getInstruction( OP_pushdouble, new Double(((Number) prev.getOperand(0)).doubleValue()))); break; } case OP_pushdouble: case OP_pushnan: case OP_lf32: case OP_lf64: case OP_convert_d: { // result is already a double, just erase the op_convert_d delete(0); break; } default: { // nothing to do - instruction has already been added } } }
/** Optimizations for OP_pop: callprop, pop -> callpropvoid callsuper, pop -> callsupervoid */ private void op_pop(InstructionInfo i) { InstructionInfo prev = previous(1); switch (prev.getOpcode()) { case OP_callproperty: { replace( 1, InstructionFactory.createModifiedInstruction(OP_callpropvoid, prev.getInstruction())); break; } case OP_callsuper: { replace( 1, InstructionFactory.createModifiedInstruction( OP_callsupervoid, prev.getInstruction())); break; } default: { // nothing to do, instruction has already been added } } }
/** * Optimizations for OP_getproperty: findpropstrict name, getproperty name -> getlex name * * @param i the getproperty instruction */ private void op_getproperty(InstructionInfo i) { InstructionInfo prev = previous(1); switch (prev.getOpcode()) { case OP_findpropstrict: { // can optimize findpropstrict, followed by getprop of the same name // if there are any instructions btwn the findpropstrict and getprop (such as to compute a // runtime // multiname), we won't match this pattern if (i.getOperand(0).equals(prev.getOperand(0))) replace( 1, InstructionFactory.createModifiedInstruction(OP_getlex, prev.getInstruction())); break; } } }
/** Optimizations for OP_getlocal: setlocal N, getlocal N -> dup, setlocal N */ private void OP_getlocal(InstructionInfo i) { InstructionInfo prev = previous(1); InstructionInfo cur = previous(0); switch (prev.getOpcode()) { case OP_setlocal: { if (cur.getInstruction().getImmediate() != prev.getInstruction().getImmediate()) break; // set,get of different locals Instruction[] newInsns = { InstructionFactory.getInstruction(OP_dup), prev.getInstruction() }; replace(1, newInsns); break; } default: { // nothing to do, instruction has already been added } } }
/** * Optimizations for OP_iftrue: convert_b, iftrue -> iftrue equals, iftrue -> ifeq strictequals, * iftrue -> ifstricteq lessthen, iftrue -> iflt lessequals, iftrue -> ifle greaterthan, iftrue -> * ifgt greaterequals, iftrue -> ifge pushfalse, iftrue -> jump pushtrue, iftrue -> nothing * strictequals, not, iftrue -> ifstrictne equals, not, iftrue -> ifne lessthan, not, iftrue -> * ifnlt lessequals, not, iftrue -> ifnle greaterthan, not, iftrue -> ifngt greaterequals, * not,iftrue -> ifnge not, iftrue -> iffalse * * @param i the iftrue instruction */ private void op_iftrue(InstructionInfo i) { InstructionInfo prev = previous(1); switch (isTrueInstructionInfo(prev)) { case FALSE: delete(1); return; case TRUE: replace(1, InstructionFactory.createModifiedInstruction(OP_jump, i.getInstruction())); return; case DONT_KNOW: break; // continue on if we don't know it's a constant boolean default: assert false; } switch (prev.getOpcode()) { case OP_convert_b: { replace(1, i.getInstruction()); break; } case OP_equals: { replace(1, InstructionFactory.createModifiedInstruction(OP_ifeq, i.getInstruction())); break; } case OP_strictequals: { replace( 1, InstructionFactory.createModifiedInstruction(OP_ifstricteq, i.getInstruction())); break; } case OP_lessthan: { replace(1, InstructionFactory.createModifiedInstruction(OP_iflt, i.getInstruction())); break; } case OP_lessequals: { replace(1, InstructionFactory.createModifiedInstruction(OP_ifle, i.getInstruction())); break; } case OP_greaterthan: { replace(1, InstructionFactory.createModifiedInstruction(OP_ifgt, i.getInstruction())); break; } case OP_greaterequals: { replace(1, InstructionFactory.createModifiedInstruction(OP_ifge, i.getInstruction())); break; } case OP_not: { InstructionInfo prev2 = previous(2); switch (prev2.getOpcode()) { case OP_strictequals: { replace( 2, InstructionFactory.createModifiedInstruction( OP_ifstrictne, i.getInstruction())); break; } case OP_equals: { replace( 2, InstructionFactory.createModifiedInstruction(OP_ifne, i.getInstruction())); break; } case OP_lessthan: { replace( 2, InstructionFactory.createModifiedInstruction(OP_ifnlt, i.getInstruction())); break; } case OP_lessequals: { replace( 2, InstructionFactory.createModifiedInstruction(OP_ifnle, i.getInstruction())); break; } case OP_greaterthan: { replace( 2, InstructionFactory.createModifiedInstruction(OP_ifngt, i.getInstruction())); break; } case OP_greaterequals: { replace( 2, InstructionFactory.createModifiedInstruction(OP_ifnge, i.getInstruction())); break; } default: { replace( 1, InstructionFactory.createModifiedInstruction(OP_iffalse, i.getInstruction())); break; } } break; } default: // nothing to do, instruction was already added } }
/** * Optimizations for OP_iffalse: convert_b, iffalse -> iffalse equals, iffalse -> ifne * strictequals, iffalse -> strictne lessthen, iffalse -> ifnlt lessequals, iffalse -> ifnle * greaterthan, iffalse -> ifngt greaterequals, iffalse -> ifnge pushfalse, iffalse -> jump * pushtrue, iffalse -> nothing strictequals, not, iffalse -> ifstrictequals equals, not, iffalse * -> ifeq lessthan, not, iffalse -> iflt lessequals, not, iffalse -> ifle greaterthan, not, * iffalse -> ifgt greaterequals, not,iffalse -> ifge not, iffalse -> iftrue * * @param i the iffalse instruction */ private void op_iffalse(InstructionInfo i) { InstructionInfo prev = previous(1); // Check if we know what's on the stack. If so, we don't need // to do a conditional branch switch (isTrueInstructionInfo(prev)) { case TRUE: delete(1); // if we can't branch, just eat the push / iffalse instructions return; case FALSE: replace(1, InstructionFactory.createModifiedInstruction(OP_jump, i.getInstruction())); // If we always branch, then replace the push / iffalse with an uncontidional jump return; case DONT_KNOW: break; // continue on if we don't know it's a constant boolean default: assert false; } switch (prev.getOpcode()) { case OP_convert_b: { // replace with just iffalse replace(1, i.getInstruction()); break; } case OP_equals: { replace(1, InstructionFactory.createModifiedInstruction(OP_ifne, i.getInstruction())); break; } case OP_strictequals: { replace( 1, InstructionFactory.createModifiedInstruction(OP_ifstrictne, i.getInstruction())); break; } case OP_lessthan: { replace(1, InstructionFactory.createModifiedInstruction(OP_ifnlt, i.getInstruction())); break; } case OP_lessequals: { replace(1, InstructionFactory.createModifiedInstruction(OP_ifnle, i.getInstruction())); break; } case OP_greaterthan: { replace(1, InstructionFactory.createModifiedInstruction(OP_ifngt, i.getInstruction())); break; } case OP_greaterequals: { replace(1, InstructionFactory.createModifiedInstruction(OP_ifnge, i.getInstruction())); break; } case OP_not: { InstructionInfo prev2 = previous(2); switch (prev2.getOpcode()) { case OP_strictequals: { replace( 2, InstructionFactory.createModifiedInstruction( OP_ifstricteq, i.getInstruction())); break; } case OP_equals: { replace( 2, InstructionFactory.createModifiedInstruction(OP_ifeq, i.getInstruction())); break; } case OP_lessthan: { replace( 2, InstructionFactory.createModifiedInstruction(OP_iflt, i.getInstruction())); break; } case OP_lessequals: { replace( 2, InstructionFactory.createModifiedInstruction(OP_ifle, i.getInstruction())); break; } case OP_greaterthan: { replace( 2, InstructionFactory.createModifiedInstruction(OP_ifgt, i.getInstruction())); break; } case OP_greaterequals: { replace( 2, InstructionFactory.createModifiedInstruction(OP_ifge, i.getInstruction())); break; } default: { replace( 1, InstructionFactory.createModifiedInstruction(OP_iftrue, i.getInstruction())); break; } } break; } default: { // nothing to do, instruction was already added } } }
/** * Helper method to invert if expr target jump other-target to if not expr other-target Used to * optimize some common patterns with if's and jumps */ private Instruction invertIf(InstructionInfo oldIf, InstructionInfo oldJump) { Instruction newIf = null; switch (oldIf.getOpcode()) { case OP_ifeq: { newIf = InstructionFactory.createModifiedInstruction(OP_ifne, oldJump.getInstruction()); break; } case OP_ifstricteq: { newIf = InstructionFactory.createModifiedInstruction(OP_ifstrictne, oldJump.getInstruction()); break; } case OP_ifstrictne: { newIf = InstructionFactory.createModifiedInstruction(OP_ifstricteq, oldJump.getInstruction()); break; } case OP_ifge: { newIf = InstructionFactory.createModifiedInstruction(OP_ifnge, oldJump.getInstruction()); break; } case OP_ifgt: { newIf = InstructionFactory.createModifiedInstruction(OP_ifngt, oldJump.getInstruction()); break; } case OP_iflt: { newIf = InstructionFactory.createModifiedInstruction(OP_ifnlt, oldJump.getInstruction()); break; } case OP_ifle: { newIf = InstructionFactory.createModifiedInstruction(OP_ifnle, oldJump.getInstruction()); break; } case OP_ifne: { newIf = InstructionFactory.createModifiedInstruction(OP_ifeq, oldJump.getInstruction()); break; } case OP_ifnge: { newIf = InstructionFactory.createModifiedInstruction(OP_ifge, oldJump.getInstruction()); break; } case OP_ifngt: { newIf = InstructionFactory.createModifiedInstruction(OP_ifgt, oldJump.getInstruction()); break; } case OP_ifnlt: { newIf = InstructionFactory.createModifiedInstruction(OP_iflt, oldJump.getInstruction()); break; } case OP_ifnle: { newIf = InstructionFactory.createModifiedInstruction(OP_ifle, oldJump.getInstruction()); break; } case OP_iftrue: { newIf = InstructionFactory.createModifiedInstruction(OP_iffalse, oldJump.getInstruction()); break; } case OP_iffalse: { newIf = InstructionFactory.createModifiedInstruction(OP_iftrue, oldJump.getInstruction()); break; } } return newIf; }
@Override public void visitInstruction(int opcode, Object single_operand) { visitInstruction(InstructionFactory.getInstruction(opcode, single_operand)); }
@Override public void visitInstruction(int opcode, Object[] operands) { visitInstruction(InstructionFactory.getInstruction(opcode, operands)); }
@Override public void visitInstruction(int opcode, int immediate_operand) { visitInstruction(InstructionFactory.getInstruction(opcode, immediate_operand)); }
@Override public void visitInstruction(int opcode) { visitInstruction(InstructionFactory.getInstruction(opcode)); }