|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
|
|
package sun.tools.tree; |
|
|
|
import sun.tools.java.*; |
|
import sun.tools.asm.Assembler; |
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
public |
|
class AssignAddExpression extends AssignOpExpression { |
|
|
|
|
|
*/ |
|
public AssignAddExpression(long where, Expression left, Expression right) { |
|
super(ASGADD, where, left, right); |
|
} |
|
|
|
|
|
|
|
|
|
*/ |
|
public int costInline(int thresh, Environment env, Context ctx) { |
|
return type.isType(TC_CLASS) ? 25 : super.costInline(thresh, env, ctx); |
|
} |
|
|
|
|
|
|
|
*/ |
|
void code(Environment env, Context ctx, Assembler asm, boolean valNeeded) { |
|
if (itype.isType(TC_CLASS)) { |
|
|
|
try { |
|
|
|
Type argTypes[] = {Type.tString}; |
|
ClassDeclaration c = |
|
env.getClassDeclaration(idJavaLangStringBuffer); |
|
|
|
if (updater == null) { |
|
|
|
// No access method is needed. |
|
|
|
asm.add(where, opc_new, c); |
|
asm.add(where, opc_dup); |
|
|
|
int depth = left.codeLValue(env, ctx, asm); |
|
codeDup(env, ctx, asm, depth, 2); |
|
// stack: ...[<getter args>]<buffer><buffer>[<getter args>] |
|
// where <buffer> isn't yet initialized, and the <getter args> |
|
// has length depth and is whatever is needed to get/set the |
|
|
|
left.codeLoad(env, ctx, asm); |
|
left.ensureString(env, ctx, asm); |
|
// stack: ...[<getter args>]<buffer><buffer><string> |
|
|
|
ClassDefinition sourceClass = ctx.field.getClassDefinition(); |
|
MemberDefinition f = c.getClassDefinition(env) |
|
.matchMethod(env, sourceClass, |
|
idInit, argTypes); |
|
asm.add(where, opc_invokespecial, f); |
|
// stack: ...[<getter args>]<initialized buffer> |
|
|
|
right.codeAppend(env, ctx, asm, c, false); |
|
f = c.getClassDefinition(env) |
|
.matchMethod(env, sourceClass, idToString); |
|
asm.add(where, opc_invokevirtual, f); |
|
// stack: ...[<getter args>]<string> |
|
|
|
if (valNeeded) { |
|
codeDup(env, ctx, asm, Type.tString.stackSize(), depth); |
|
// stack: ...<string>[<getter args>]<string> |
|
} |
|
|
|
left.codeStore(env, ctx, asm); |
|
|
|
} else { |
|
|
|
// Access method is required. |
|
// (Handling this case fixes 4102566.) |
|
|
|
updater.startUpdate(env, ctx, asm, false); |
|
// stack: ...[<getter args>]<string> |
|
left.ensureString(env, ctx, asm); |
|
asm.add(where, opc_new, c); |
|
|
|
asm.add(where, opc_dup_x1); |
|
|
|
asm.add(where, opc_swap); |
|
// stack: ...[<getter args>]<buffer><buffer><string> |
|
|
|
ClassDefinition sourceClass = ctx.field.getClassDefinition(); |
|
MemberDefinition f = c.getClassDefinition(env) |
|
.matchMethod(env, sourceClass, |
|
idInit, argTypes); |
|
asm.add(where, opc_invokespecial, f); |
|
// stack: ...[<getter args>]<initialized buffer> |
|
|
|
right.codeAppend(env, ctx, asm, c, false); |
|
f = c.getClassDefinition(env) |
|
.matchMethod(env, sourceClass, idToString); |
|
asm.add(where, opc_invokevirtual, f); |
|
|
|
updater.finishUpdate(env, ctx, asm, valNeeded); |
|
|
|
} |
|
|
|
} catch (ClassNotFound e) { |
|
throw new CompilerError(e); |
|
} catch (AmbiguousMember e) { |
|
throw new CompilerError(e); |
|
} |
|
} else { |
|
super.code(env, ctx, asm, valNeeded); |
|
} |
|
} |
|
|
|
|
|
|
|
*/ |
|
void codeOperation(Environment env, Context ctx, Assembler asm) { |
|
asm.add(where, opc_iadd + itype.getTypeCodeOffset()); |
|
} |
|
} |