/* * Copyright 1994-2003 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. Sun designates this * particular file as subject to the "Classpath" exception as provided * by Sun in the LICENSE file that accompanied this code. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, * CA 95054 USA or visit www.sun.com if you need additional information or * have any questions. */ package sun.tools.tree; import sun.tools.java.*; import sun.tools.asm.Assembler; /** * WARNING: The contents of this source file are not part of any * supported API. Code that depends on them does so at its own risk: * they are subject to change or removal without notice. */ public class AssignAddExpression extends AssignOpExpression { /** * Constructor */ public AssignAddExpression(long where, Expression left, Expression right) { super(ASGADD, where, left, right); } /** * The cost of inlining this statement */ public int costInline(int thresh, Environment env, Context ctx) { return type.isType(TC_CLASS) ? 25 : super.costInline(thresh, env, ctx); } /** * Code */ void code(Environment env, Context ctx, Assembler asm, boolean valNeeded) { if (itype.isType(TC_CLASS)) { // Create code for String += <value> try { // Create new string buffer. 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); // stack: ...<buffer><buffer> int depth = left.codeLValue(env, ctx, asm); codeDup(env, ctx, asm, depth, 2); // copy past 2 string buffers // 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 // value left.codeLoad(env, ctx, asm); left.ensureString(env, ctx, asm); // Why is this needed? // stack: ...[<getter args>]<buffer><buffer><string> // call .<init>(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> // .append(value).toString() 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> // dup the string past the <getter args>, if necessary. if (valNeeded) { codeDup(env, ctx, asm, Type.tString.stackSize(), depth); // stack: ...<string>[<getter args>]<string> } // store 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); // Why is this needed? asm.add(where, opc_new, c); // stack: ...[<getter args>]<string><buffer> asm.add(where, opc_dup_x1); // stack: ...[<getter args>]<buffer><string><buffer> asm.add(where, opc_swap); // stack: ...[<getter args>]<buffer><buffer><string> // call .<init>(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> // .append(value).toString() 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> 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); } } /** * Code */ void codeOperation(Environment env, Context ctx, Assembler asm) { asm.add(where, opc_iadd + itype.getTypeCodeOffset()); } }