1/* 2 * Copyright (c) 1994, 2003, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26package sun.tools.tree; 27 28import sun.tools.java.*; 29import sun.tools.asm.Assembler; 30 31/** 32 * WARNING: The contents of this source file are not part of any 33 * supported API. Code that depends on them does so at its own risk: 34 * they are subject to change or removal without notice. 35 */ 36public 37class AssignAddExpression extends AssignOpExpression { 38 /** 39 * Constructor 40 */ 41 public AssignAddExpression(long where, Expression left, Expression right) { 42 super(ASGADD, where, left, right); 43 } 44 45 46 /** 47 * The cost of inlining this statement 48 */ 49 public int costInline(int thresh, Environment env, Context ctx) { 50 return type.isType(TC_CLASS) ? 25 : super.costInline(thresh, env, ctx); 51 } 52 53 /** 54 * Code 55 */ 56 void code(Environment env, Context ctx, Assembler asm, boolean valNeeded) { 57 if (itype.isType(TC_CLASS)) { 58 // Create code for String += <value> 59 try { 60 // Create new string buffer. 61 Type argTypes[] = {Type.tString}; 62 ClassDeclaration c = 63 env.getClassDeclaration(idJavaLangStringBuffer); 64 65 if (updater == null) { 66 67 // No access method is needed. 68 69 asm.add(where, opc_new, c); 70 asm.add(where, opc_dup); 71 // stack: ...<buffer><buffer> 72 int depth = left.codeLValue(env, ctx, asm); 73 codeDup(env, ctx, asm, depth, 2); // copy past 2 string buffers 74 // stack: ...[<getter args>]<buffer><buffer>[<getter args>] 75 // where <buffer> isn't yet initialized, and the <getter args> 76 // has length depth and is whatever is needed to get/set the 77 // value 78 left.codeLoad(env, ctx, asm); 79 left.ensureString(env, ctx, asm); // Why is this needed? 80 // stack: ...[<getter args>]<buffer><buffer><string> 81 // call .<init>(String) 82 ClassDefinition sourceClass = ctx.field.getClassDefinition(); 83 MemberDefinition f = c.getClassDefinition(env) 84 .matchMethod(env, sourceClass, 85 idInit, argTypes); 86 asm.add(where, opc_invokespecial, f); 87 // stack: ...[<getter args>]<initialized buffer> 88 // .append(value).toString() 89 right.codeAppend(env, ctx, asm, c, false); 90 f = c.getClassDefinition(env) 91 .matchMethod(env, sourceClass, idToString); 92 asm.add(where, opc_invokevirtual, f); 93 // stack: ...[<getter args>]<string> 94 // dup the string past the <getter args>, if necessary. 95 if (valNeeded) { 96 codeDup(env, ctx, asm, Type.tString.stackSize(), depth); 97 // stack: ...<string>[<getter args>]<string> 98 } 99 // store 100 left.codeStore(env, ctx, asm); 101 102 } else { 103 104 // Access method is required. 105 // (Handling this case fixes 4102566.) 106 107 updater.startUpdate(env, ctx, asm, false); 108 // stack: ...[<getter args>]<string> 109 left.ensureString(env, ctx, asm); // Why is this needed? 110 asm.add(where, opc_new, c); 111 // stack: ...[<getter args>]<string><buffer> 112 asm.add(where, opc_dup_x1); 113 // stack: ...[<getter args>]<buffer><string><buffer> 114 asm.add(where, opc_swap); 115 // stack: ...[<getter args>]<buffer><buffer><string> 116 // call .<init>(String) 117 ClassDefinition sourceClass = ctx.field.getClassDefinition(); 118 MemberDefinition f = c.getClassDefinition(env) 119 .matchMethod(env, sourceClass, 120 idInit, argTypes); 121 asm.add(where, opc_invokespecial, f); 122 // stack: ...[<getter args>]<initialized buffer> 123 // .append(value).toString() 124 right.codeAppend(env, ctx, asm, c, false); 125 f = c.getClassDefinition(env) 126 .matchMethod(env, sourceClass, idToString); 127 asm.add(where, opc_invokevirtual, f); 128 // stack: .. [<getter args>]<string> 129 updater.finishUpdate(env, ctx, asm, valNeeded); 130 131 } 132 133 } catch (ClassNotFound e) { 134 throw new CompilerError(e); 135 } catch (AmbiguousMember e) { 136 throw new CompilerError(e); 137 } 138 } else { 139 super.code(env, ctx, asm, valNeeded); 140 } 141 } 142 143 /** 144 * Code 145 */ 146 void codeOperation(Environment env, Context ctx, Assembler asm) { 147 asm.add(where, opc_iadd + itype.getTypeCodeOffset()); 148 } 149} 150