/*
 * Copyright (c) 1994, 2003, Oracle and/or its affiliates. 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.  Oracle designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.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.
/** * 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
/** * Constructor */
public AssignAddExpression(long where, Expression left, Expression right) { super(ASGADD, where, left, right); }
The cost of inlining this statement
/** * 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
/** * 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
/** * Code */
void codeOperation(Environment env, Context ctx, Assembler asm) { asm.add(where, opc_iadd + itype.getTypeCodeOffset()); } }