/** Create a copy of the expression for method inlining */ public Expression copyInline(Context ctx) { AssignOpExpression e = (AssignOpExpression) clone(); e.left = left.copyInline(ctx); e.right = right.copyInline(ctx); if (updater != null) { e.updater = updater.copyInline(ctx); } return e; }
/** Inline */ public Expression inlineValue(Environment env, Context ctx) { // Why not inlineLHS? But that does not work. left = left.inlineValue(env, ctx); right = right.inlineValue(env, ctx); if (updater != null) { updater = updater.inline(env, ctx); } return this; }
/** Code */ void code(Environment env, Context ctx, Assembler asm, boolean valNeeded) { // Handle cases in which a '+=' or '-=' operator can be optimized using // the 'iinc' instruction. See also 'IncDecExpression.codeIncDec'. // The 'iinc' instruction cannot be used if an access method call is required. int val = getIncrement(); if (val != NOINC && updater == null) { int v = ((LocalMember) ((IdentifierExpression) left).field).number; int[] operands = {v, val}; asm.add(where, opc_iinc, operands); if (valNeeded) { left.codeValue(env, ctx, asm); } return; } if (updater == null) { // Field is directly accessible. int depth = left.codeLValue(env, ctx, asm); codeDup(env, ctx, asm, depth, 0); left.codeLoad(env, ctx, asm); codeConversion(env, ctx, asm, left.type, itype); right.codeValue(env, ctx, asm); codeOperation(env, ctx, asm); codeConversion(env, ctx, asm, itype, type); if (valNeeded) { codeDup(env, ctx, asm, type.stackSize(), depth); } left.codeStore(env, ctx, asm); } else { // Must use access methods. updater.startUpdate(env, ctx, asm, false); codeConversion(env, ctx, asm, left.type, itype); right.codeValue(env, ctx, asm); codeOperation(env, ctx, asm); codeConversion(env, ctx, asm, itype, type); updater.finishUpdate(env, ctx, asm, valNeeded); } }
/** The cost of inlining this statement */ public int costInline(int thresh, Environment env, Context ctx) { /*----------* return (getIncrement() != NOINC) ? 2 : (3 + super.costInline(thresh, env, ctx)); *----------*/ if (updater == null) { return (getIncrement() != NOINC) // Increment variable in place. Count 3 bytes for 'iinc'. ? 3 // Cost of rhs expression + cost of lhs expression + cost // of load/op/store instructions. E.g.: iload = 1 or 2, // istore = 1 or 2, iadd = 1. Cost could be higher if // getfield/putfield or conversions needed, lower if rhs is // a small constant. Costs are highly approximate. : right.costInline(thresh, env, ctx) + left.costInline(thresh, env, ctx) + 4; } else { // Cost of rhs expression + (2 * cost of access method call) + // cost of operator. Does not account for cost of conversions, // or duplications in value-needed context. return right.costInline(thresh, env, ctx) + updater.costInline(thresh, env, ctx, true) + 1; } }