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 26 package sun.tools.tree; 27 28 import sun.tools.java.*; 29 import sun.tools.asm.Assembler; 30 import java.util.Hashtable; 31 32 /** 33 * WARNING: The contents of this source file are not part of any 34 * supported API. Code that depends on them does so at its own risk: 35 * they are subject to change or removal without notice. 36 */ 37 public 38 class IncDecExpression extends UnaryExpression { 39 40 private FieldUpdater updater = null; 41 42 /** 43 * Constructor 44 */ 45 public IncDecExpression(int op, long where, Expression right) { 46 super(op, where, right.type, right); 47 } 48 49 /** 50 * Check an increment or decrement expression 51 */ 52 public Vset checkValue(Environment env, Context ctx, Vset vset, Hashtable exp) { 53 vset = right.checkAssignOp(env, ctx, vset, exp, this); 54 if (right.type.inMask(TM_NUMBER)) { 55 type = right.type; 56 } else { 57 if (!right.type.isType(TC_ERROR)) { 58 env.error(where, "invalid.arg.type", right.type, opNames[op]); 59 } 60 type = Type.tError; 61 } 62 updater = right.getUpdater(env, ctx); // Must be called after 'checkAssignOp'. 63 return vset; 64 } 65 66 /** 67 * Check void expression 68 */ 69 public Vset check(Environment env, Context ctx, Vset vset, Hashtable exp) { 70 return checkValue(env, ctx, vset, exp); 71 } 72 73 /** 74 * Inline 75 */ 76 public Expression inline(Environment env, Context ctx) { 77 return inlineValue(env, ctx); 78 } 79 public Expression inlineValue(Environment env, Context ctx) { 80 // Why not inlineLHS? But that does not work. 81 right = right.inlineValue(env, ctx); 82 if (updater != null) { 83 updater = updater.inline(env, ctx); 84 } 85 return this; 86 } 87 88 public int costInline(int thresh, Environment env, Context ctx) { 89 if (updater == null) { 90 if ((right.op == IDENT) && type.isType(TC_INT) && 91 (((IdentifierExpression)right).field.isLocal())) { 92 // Increment variable in place. Count 3 bytes for 'iinc'. 93 return 3; 94 } 95 // Cost to load lhs reference, fetch local, increment, and store. 96 // Load/store cost will be higher if variable is a field. Note that 97 // costs are highly approximate. See 'AssignOpExpression.costInline' 98 // Does not account for cost of conversions,or duplications in 99 // value-needed context.. 100 return right.costInline(thresh, env, ctx) + 4; 101 } else { 102 // Cost of two access method calls (get/set) + cost of increment. 103 return updater.costInline(thresh, env, ctx, true) + 1; 104 } 105 } 106 107 108 /** 109 * Code 110 */ 111 112 private void codeIncDecOp(Assembler asm, boolean inc) { 113 switch (type.getTypeCode()) { 114 case TC_BYTE: 115 asm.add(where, opc_ldc, new Integer(1)); 116 asm.add(where, inc ? opc_iadd : opc_isub); 117 asm.add(where, opc_i2b); 118 break; 119 case TC_SHORT: 120 asm.add(where, opc_ldc, new Integer(1)); 121 asm.add(where, inc ? opc_iadd : opc_isub); 122 asm.add(where, opc_i2s); 123 break; 124 case TC_CHAR: 125 asm.add(where, opc_ldc, new Integer(1)); 126 asm.add(where, inc ? opc_iadd : opc_isub); 127 asm.add(where, opc_i2c); 128 break; 129 case TC_INT: 130 asm.add(where, opc_ldc, new Integer(1)); 131 asm.add(where, inc ? opc_iadd : opc_isub); 132 break; 133 case TC_LONG: 134 asm.add(where, opc_ldc2_w, new Long(1)); 135 asm.add(where, inc ? opc_ladd : opc_lsub); 136 break; 137 case TC_FLOAT: 138 asm.add(where, opc_ldc, new Float(1)); 139 asm.add(where, inc ? opc_fadd : opc_fsub); 140 break; 141 case TC_DOUBLE: 142 asm.add(where, opc_ldc2_w, new Double(1)); 143 asm.add(where, inc ? opc_dadd : opc_dsub); 144 break; 145 default: 146 throw new CompilerError("invalid type"); 147 } 148 } 149 150 void codeIncDec(Environment env, Context ctx, Assembler asm, boolean inc, boolean prefix, boolean valNeeded) { 151 152 // The 'iinc' instruction cannot be used if an access method call is required. 153 if ((right.op == IDENT) && type.isType(TC_INT) && 154 (((IdentifierExpression)right).field.isLocal()) && updater == null) { 155 if (valNeeded && !prefix) { 156 right.codeLoad(env, ctx, asm); 157 } 158 int v = ((LocalMember)((IdentifierExpression)right).field).number; 159 int[] operands = { v, inc ? 1 : -1 }; 160 asm.add(where, opc_iinc, operands); 161 if (valNeeded && prefix) { 162 right.codeLoad(env, ctx, asm); 163 } 164 return; 165 166 } 167 168 if (updater == null) { 169 // Field is directly accessible. 170 int depth = right.codeLValue(env, ctx, asm); 171 codeDup(env, ctx, asm, depth, 0); 172 right.codeLoad(env, ctx, asm); 173 if (valNeeded && !prefix) { 174 codeDup(env, ctx, asm, type.stackSize(), depth); 175 } 176 codeIncDecOp(asm, inc); 177 if (valNeeded && prefix) { 178 codeDup(env, ctx, asm, type.stackSize(), depth); 179 } 180 right.codeStore(env, ctx, asm); 181 } else { 182 // Must use access methods. 183 updater.startUpdate(env, ctx, asm, (valNeeded && !prefix)); 184 codeIncDecOp(asm, inc); 185 updater.finishUpdate(env, ctx, asm, (valNeeded && prefix)); 186 } 187 } 188 189 }