/** * 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; } } }
/** * evaluates an instruction and determines if it will result in true or false on TOS. * * @param i is an instruction to analyze * @return whether TOS is true, false, or not known */ private static ConstantBoolean isTrueInstructionInfo(InstructionInfo i) { ConstantBoolean ret = ConstantBoolean.DONT_KNOW; switch (i.getOpcode()) { case OP_pushtrue: ret = ConstantBoolean.TRUE; break; case OP_pushfalse: ret = ConstantBoolean.FALSE; break; case OP_pushbyte: { int value = i.getImmediate(); assert value >= 0; ret = ECMASupport.toBoolean(value) ? ConstantBoolean.TRUE : ConstantBoolean.FALSE; break; } case OP_pushint: { int value = (Integer) i.getOperand(0); ret = ECMASupport.toBoolean(value) ? ConstantBoolean.TRUE : ConstantBoolean.FALSE; break; } case OP_pushuint: { long value = (Long) i.getOperand(0); ret = ECMASupport.toBoolean(value) ? ConstantBoolean.TRUE : ConstantBoolean.FALSE; break; } case OP_pushstring: { String value = i.getOperand(0).toString(); ret = ECMASupport.toBoolean(value) ? ConstantBoolean.TRUE : ConstantBoolean.FALSE; break; } case OP_pushnull: ret = ConstantBoolean.FALSE; break; } return ret; }
/** * Helper method to perform optimizations around jumps when we get a labeling operation. Shared * with labelNext and labelCurrent methods * * @param l the Label object passed into the label operation * @param kind what kind of labeling operation are we doing (labelNext or labelCurrent) */ private void jumpOptimizations(Label l, LabelKind kind) { // Need to start looking at different indexes for label current vs. label next // this is because for a label next, the next instruction won't have come in yet. int idx = kind == LabelKind.LABEL_CURRENT ? 1 : 0; InstructionInfo prev = previous(idx); switch (prev.getOpcode()) { case OP_jump: { InstructionInfo prev2 = previous(idx + 1); Instruction insn = prev2.getInstruction(); if (insn != null && insn.isBranch() && insn.getTarget() == l) { // If the previous instructions were an if that jumped here, and it // only jumped over another jump, then we can invert the if instruction // and save a jump // iffalse L1, jump L2, L1 -> iftrue L2, L1 Instruction newIf = invertIf(prev2, prev); if (newIf != null) { if (kind == LabelKind.LABEL_CURRENT) { // labelCurrent, so we need to preserve the last instruction Instruction[] newInsns = {newIf, previous(0).getInstruction()}; replace(idx + 1, newInsns); } else { // labelNext so we can just delete the last instruction replace(idx + 1, newIf); } } } // If the previous instruction was a jump, and it just jumped // to the next instruction, then we can remove the jump and just fall // through // jump L1, L1 -> L1 else if (prev.getOperand(0) == l) { if (kind == LabelKind.LABEL_NEXT) // can just delete the jump because we don't have the next instruction yet delete(idx); else // replace the jump with its target replace(idx, previous(0).getInstruction()); } } } }
/** * 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 } } }