001: /*
002: * Copyright 1994-2003 Sun Microsystems, Inc. All Rights Reserved.
003: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
004: *
005: * This code is free software; you can redistribute it and/or modify it
006: * under the terms of the GNU General Public License version 2 only, as
007: * published by the Free Software Foundation. Sun designates this
008: * particular file as subject to the "Classpath" exception as provided
009: * by Sun in the LICENSE file that accompanied this code.
010: *
011: * This code is distributed in the hope that it will be useful, but WITHOUT
012: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
013: * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
014: * version 2 for more details (a copy is included in the LICENSE file that
015: * accompanied this code).
016: *
017: * You should have received a copy of the GNU General Public License version
018: * 2 along with this work; if not, write to the Free Software Foundation,
019: * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
020: *
021: * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
022: * CA 95054 USA or visit www.sun.com if you need additional information or
023: * have any questions.
024: */
025:
026: package sun.tools.tree;
027:
028: import sun.tools.java.*;
029: import sun.tools.asm.Assembler;
030:
031: /**
032: * WARNING: The contents of this source file are not part of any
033: * supported API. Code that depends on them does so at its own risk:
034: * they are subject to change or removal without notice.
035: */
036: public class AssignAddExpression extends AssignOpExpression {
037: /**
038: * Constructor
039: */
040: public AssignAddExpression(long where, Expression left,
041: Expression right) {
042: super (ASGADD, where, left, right);
043: }
044:
045: /**
046: * The cost of inlining this statement
047: */
048: public int costInline(int thresh, Environment env, Context ctx) {
049: return type.isType(TC_CLASS) ? 25 : super .costInline(thresh,
050: env, ctx);
051: }
052:
053: /**
054: * Code
055: */
056: void code(Environment env, Context ctx, Assembler asm,
057: boolean valNeeded) {
058: if (itype.isType(TC_CLASS)) {
059: // Create code for String += <value>
060: try {
061: // Create new string buffer.
062: Type argTypes[] = { Type.tString };
063: ClassDeclaration c = env
064: .getClassDeclaration(idJavaLangStringBuffer);
065:
066: if (updater == null) {
067:
068: // No access method is needed.
069:
070: asm.add(where, opc_new, c);
071: asm.add(where, opc_dup);
072: // stack: ...<buffer><buffer>
073: int depth = left.codeLValue(env, ctx, asm);
074: codeDup(env, ctx, asm, depth, 2); // copy past 2 string buffers
075: // stack: ...[<getter args>]<buffer><buffer>[<getter args>]
076: // where <buffer> isn't yet initialized, and the <getter args>
077: // has length depth and is whatever is needed to get/set the
078: // value
079: left.codeLoad(env, ctx, asm);
080: left.ensureString(env, ctx, asm); // Why is this needed?
081: // stack: ...[<getter args>]<buffer><buffer><string>
082: // call .<init>(String)
083: ClassDefinition sourceClass = ctx.field
084: .getClassDefinition();
085: MemberDefinition f = c.getClassDefinition(env)
086: .matchMethod(env, sourceClass, idInit,
087: argTypes);
088: asm.add(where, opc_invokespecial, f);
089: // stack: ...[<getter args>]<initialized buffer>
090: // .append(value).toString()
091: right.codeAppend(env, ctx, asm, c, false);
092: f = c.getClassDefinition(env).matchMethod(env,
093: sourceClass, idToString);
094: asm.add(where, opc_invokevirtual, f);
095: // stack: ...[<getter args>]<string>
096: // dup the string past the <getter args>, if necessary.
097: if (valNeeded) {
098: codeDup(env, ctx, asm,
099: Type.tString.stackSize(), depth);
100: // stack: ...<string>[<getter args>]<string>
101: }
102: // store
103: left.codeStore(env, ctx, asm);
104:
105: } else {
106:
107: // Access method is required.
108: // (Handling this case fixes 4102566.)
109:
110: updater.startUpdate(env, ctx, asm, false);
111: // stack: ...[<getter args>]<string>
112: left.ensureString(env, ctx, asm); // Why is this needed?
113: asm.add(where, opc_new, c);
114: // stack: ...[<getter args>]<string><buffer>
115: asm.add(where, opc_dup_x1);
116: // stack: ...[<getter args>]<buffer><string><buffer>
117: asm.add(where, opc_swap);
118: // stack: ...[<getter args>]<buffer><buffer><string>
119: // call .<init>(String)
120: ClassDefinition sourceClass = ctx.field
121: .getClassDefinition();
122: MemberDefinition f = c.getClassDefinition(env)
123: .matchMethod(env, sourceClass, idInit,
124: argTypes);
125: asm.add(where, opc_invokespecial, f);
126: // stack: ...[<getter args>]<initialized buffer>
127: // .append(value).toString()
128: right.codeAppend(env, ctx, asm, c, false);
129: f = c.getClassDefinition(env).matchMethod(env,
130: sourceClass, idToString);
131: asm.add(where, opc_invokevirtual, f);
132: // stack: .. [<getter args>]<string>
133: updater.finishUpdate(env, ctx, asm, valNeeded);
134:
135: }
136:
137: } catch (ClassNotFound e) {
138: throw new CompilerError(e);
139: } catch (AmbiguousMember e) {
140: throw new CompilerError(e);
141: }
142: } else {
143: super .code(env, ctx, asm, valNeeded);
144: }
145: }
146:
147: /**
148: * Code
149: */
150: void codeOperation(Environment env, Context ctx, Assembler asm) {
151: asm.add(where, opc_iadd + itype.getTypeCodeOffset());
152: }
153: }
|