src/share/classes/com/sun/tools/javac/comp/ConstFold.java

Wed, 27 Apr 2016 01:34:52 +0800

author
aoqi
date
Wed, 27 Apr 2016 01:34:52 +0800
changeset 0
959103a6100f
child 2525
2eb010b6cb22
permissions
-rw-r--r--

Initial load
http://hg.openjdk.java.net/jdk8u/jdk8u/langtools/
changeset: 2573:53ca196be1ae
tag: jdk8u25-b17

aoqi@0 1 /*
aoqi@0 2 * Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved.
aoqi@0 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
aoqi@0 4 *
aoqi@0 5 * This code is free software; you can redistribute it and/or modify it
aoqi@0 6 * under the terms of the GNU General Public License version 2 only, as
aoqi@0 7 * published by the Free Software Foundation. Oracle designates this
aoqi@0 8 * particular file as subject to the "Classpath" exception as provided
aoqi@0 9 * by Oracle in the LICENSE file that accompanied this code.
aoqi@0 10 *
aoqi@0 11 * This code is distributed in the hope that it will be useful, but WITHOUT
aoqi@0 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
aoqi@0 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
aoqi@0 14 * version 2 for more details (a copy is included in the LICENSE file that
aoqi@0 15 * accompanied this code).
aoqi@0 16 *
aoqi@0 17 * You should have received a copy of the GNU General Public License version
aoqi@0 18 * 2 along with this work; if not, write to the Free Software Foundation,
aoqi@0 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
aoqi@0 20 *
aoqi@0 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
aoqi@0 22 * or visit www.oracle.com if you need additional information or have any
aoqi@0 23 * questions.
aoqi@0 24 */
aoqi@0 25
aoqi@0 26 package com.sun.tools.javac.comp;
aoqi@0 27
aoqi@0 28 import com.sun.tools.javac.code.*;
aoqi@0 29 import com.sun.tools.javac.jvm.*;
aoqi@0 30 import com.sun.tools.javac.util.*;
aoqi@0 31
aoqi@0 32 import static com.sun.tools.javac.code.TypeTag.BOOLEAN;
aoqi@0 33
aoqi@0 34 import static com.sun.tools.javac.jvm.ByteCodes.*;
aoqi@0 35
aoqi@0 36 /** Helper class for constant folding, used by the attribution phase.
aoqi@0 37 * This class is marked strictfp as mandated by JLS 15.4.
aoqi@0 38 *
aoqi@0 39 * <p><b>This is NOT part of any supported API.
aoqi@0 40 * If you write code that depends on this, you do so at your own risk.
aoqi@0 41 * This code and its internal interfaces are subject to change or
aoqi@0 42 * deletion without notice.</b>
aoqi@0 43 */
aoqi@0 44 strictfp class ConstFold {
aoqi@0 45 protected static final Context.Key<ConstFold> constFoldKey =
aoqi@0 46 new Context.Key<ConstFold>();
aoqi@0 47
aoqi@0 48 private Symtab syms;
aoqi@0 49
aoqi@0 50 public static ConstFold instance(Context context) {
aoqi@0 51 ConstFold instance = context.get(constFoldKey);
aoqi@0 52 if (instance == null)
aoqi@0 53 instance = new ConstFold(context);
aoqi@0 54 return instance;
aoqi@0 55 }
aoqi@0 56
aoqi@0 57 private ConstFold(Context context) {
aoqi@0 58 context.put(constFoldKey, this);
aoqi@0 59
aoqi@0 60 syms = Symtab.instance(context);
aoqi@0 61 }
aoqi@0 62
aoqi@0 63 static final Integer minusOne = -1;
aoqi@0 64 static final Integer zero = 0;
aoqi@0 65 static final Integer one = 1;
aoqi@0 66
aoqi@0 67 /** Convert boolean to integer (true = 1, false = 0).
aoqi@0 68 */
aoqi@0 69 private static Integer b2i(boolean b) {
aoqi@0 70 return b ? one : zero;
aoqi@0 71 }
aoqi@0 72 private static int intValue(Object x) { return ((Number)x).intValue(); }
aoqi@0 73 private static long longValue(Object x) { return ((Number)x).longValue(); }
aoqi@0 74 private static float floatValue(Object x) { return ((Number)x).floatValue(); }
aoqi@0 75 private static double doubleValue(Object x) { return ((Number)x).doubleValue(); }
aoqi@0 76
aoqi@0 77 /** Fold binary or unary operation, returning constant type reflecting the
aoqi@0 78 * operations result. Return null if fold failed due to an
aoqi@0 79 * arithmetic exception.
aoqi@0 80 * @param opcode The operation's opcode instruction (usually a byte code),
aoqi@0 81 * as entered by class Symtab.
aoqi@0 82 * @param argtypes The operation's argument types (a list of length 1 or 2).
aoqi@0 83 * Argument types are assumed to have non-null constValue's.
aoqi@0 84 */
aoqi@0 85 Type fold(int opcode, List<Type> argtypes) {
aoqi@0 86 int argCount = argtypes.length();
aoqi@0 87 if (argCount == 1)
aoqi@0 88 return fold1(opcode, argtypes.head);
aoqi@0 89 else if (argCount == 2)
aoqi@0 90 return fold2(opcode, argtypes.head, argtypes.tail.head);
aoqi@0 91 else
aoqi@0 92 throw new AssertionError();
aoqi@0 93 }
aoqi@0 94
aoqi@0 95 /** Fold unary operation.
aoqi@0 96 * @param opcode The operation's opcode instruction (usually a byte code),
aoqi@0 97 * as entered by class Symtab.
aoqi@0 98 * opcode's ifeq to ifge are for postprocessing
aoqi@0 99 * xcmp; ifxx pairs of instructions.
aoqi@0 100 * @param operand The operation's operand type.
aoqi@0 101 * Argument types are assumed to have non-null constValue's.
aoqi@0 102 */
aoqi@0 103 Type fold1(int opcode, Type operand) {
aoqi@0 104 try {
aoqi@0 105 Object od = operand.constValue();
aoqi@0 106 switch (opcode) {
aoqi@0 107 case nop:
aoqi@0 108 return operand;
aoqi@0 109 case ineg: // unary -
aoqi@0 110 return syms.intType.constType(-intValue(od));
aoqi@0 111 case ixor: // ~
aoqi@0 112 return syms.intType.constType(~intValue(od));
aoqi@0 113 case bool_not: // !
aoqi@0 114 return syms.booleanType.constType(b2i(intValue(od) == 0));
aoqi@0 115 case ifeq:
aoqi@0 116 return syms.booleanType.constType(b2i(intValue(od) == 0));
aoqi@0 117 case ifne:
aoqi@0 118 return syms.booleanType.constType(b2i(intValue(od) != 0));
aoqi@0 119 case iflt:
aoqi@0 120 return syms.booleanType.constType(b2i(intValue(od) < 0));
aoqi@0 121 case ifgt:
aoqi@0 122 return syms.booleanType.constType(b2i(intValue(od) > 0));
aoqi@0 123 case ifle:
aoqi@0 124 return syms.booleanType.constType(b2i(intValue(od) <= 0));
aoqi@0 125 case ifge:
aoqi@0 126 return syms.booleanType.constType(b2i(intValue(od) >= 0));
aoqi@0 127
aoqi@0 128 case lneg: // unary -
aoqi@0 129 return syms.longType.constType(new Long(-longValue(od)));
aoqi@0 130 case lxor: // ~
aoqi@0 131 return syms.longType.constType(new Long(~longValue(od)));
aoqi@0 132
aoqi@0 133 case fneg: // unary -
aoqi@0 134 return syms.floatType.constType(new Float(-floatValue(od)));
aoqi@0 135
aoqi@0 136 case dneg: // ~
aoqi@0 137 return syms.doubleType.constType(new Double(-doubleValue(od)));
aoqi@0 138
aoqi@0 139 default:
aoqi@0 140 return null;
aoqi@0 141 }
aoqi@0 142 } catch (ArithmeticException e) {
aoqi@0 143 return null;
aoqi@0 144 }
aoqi@0 145 }
aoqi@0 146
aoqi@0 147 /** Fold binary operation.
aoqi@0 148 * @param opcode The operation's opcode instruction (usually a byte code),
aoqi@0 149 * as entered by class Symtab.
aoqi@0 150 * opcode's ifeq to ifge are for postprocessing
aoqi@0 151 * xcmp; ifxx pairs of instructions.
aoqi@0 152 * @param left The type of the operation's left operand.
aoqi@0 153 * @param right The type of the operation's right operand.
aoqi@0 154 */
aoqi@0 155 Type fold2(int opcode, Type left, Type right) {
aoqi@0 156 try {
aoqi@0 157 if (opcode > ByteCodes.preMask) {
aoqi@0 158 // we are seeing a composite instruction of the form xcmp; ifxx.
aoqi@0 159 // In this case fold both instructions separately.
aoqi@0 160 Type t1 = fold2(opcode >> ByteCodes.preShift, left, right);
aoqi@0 161 return (t1.constValue() == null) ? t1
aoqi@0 162 : fold1(opcode & ByteCodes.preMask, t1);
aoqi@0 163 } else {
aoqi@0 164 Object l = left.constValue();
aoqi@0 165 Object r = right.constValue();
aoqi@0 166 switch (opcode) {
aoqi@0 167 case iadd:
aoqi@0 168 return syms.intType.constType(intValue(l) + intValue(r));
aoqi@0 169 case isub:
aoqi@0 170 return syms.intType.constType(intValue(l) - intValue(r));
aoqi@0 171 case imul:
aoqi@0 172 return syms.intType.constType(intValue(l) * intValue(r));
aoqi@0 173 case idiv:
aoqi@0 174 return syms.intType.constType(intValue(l) / intValue(r));
aoqi@0 175 case imod:
aoqi@0 176 return syms.intType.constType(intValue(l) % intValue(r));
aoqi@0 177 case iand:
aoqi@0 178 return (left.hasTag(BOOLEAN)
aoqi@0 179 ? syms.booleanType : syms.intType)
aoqi@0 180 .constType(intValue(l) & intValue(r));
aoqi@0 181 case bool_and:
aoqi@0 182 return syms.booleanType.constType(b2i((intValue(l) & intValue(r)) != 0));
aoqi@0 183 case ior:
aoqi@0 184 return (left.hasTag(BOOLEAN)
aoqi@0 185 ? syms.booleanType : syms.intType)
aoqi@0 186 .constType(intValue(l) | intValue(r));
aoqi@0 187 case bool_or:
aoqi@0 188 return syms.booleanType.constType(b2i((intValue(l) | intValue(r)) != 0));
aoqi@0 189 case ixor:
aoqi@0 190 return (left.hasTag(BOOLEAN)
aoqi@0 191 ? syms.booleanType : syms.intType)
aoqi@0 192 .constType(intValue(l) ^ intValue(r));
aoqi@0 193 case ishl: case ishll:
aoqi@0 194 return syms.intType.constType(intValue(l) << intValue(r));
aoqi@0 195 case ishr: case ishrl:
aoqi@0 196 return syms.intType.constType(intValue(l) >> intValue(r));
aoqi@0 197 case iushr: case iushrl:
aoqi@0 198 return syms.intType.constType(intValue(l) >>> intValue(r));
aoqi@0 199 case if_icmpeq:
aoqi@0 200 return syms.booleanType.constType(
aoqi@0 201 b2i(intValue(l) == intValue(r)));
aoqi@0 202 case if_icmpne:
aoqi@0 203 return syms.booleanType.constType(
aoqi@0 204 b2i(intValue(l) != intValue(r)));
aoqi@0 205 case if_icmplt:
aoqi@0 206 return syms.booleanType.constType(
aoqi@0 207 b2i(intValue(l) < intValue(r)));
aoqi@0 208 case if_icmpgt:
aoqi@0 209 return syms.booleanType.constType(
aoqi@0 210 b2i(intValue(l) > intValue(r)));
aoqi@0 211 case if_icmple:
aoqi@0 212 return syms.booleanType.constType(
aoqi@0 213 b2i(intValue(l) <= intValue(r)));
aoqi@0 214 case if_icmpge:
aoqi@0 215 return syms.booleanType.constType(
aoqi@0 216 b2i(intValue(l) >= intValue(r)));
aoqi@0 217
aoqi@0 218 case ladd:
aoqi@0 219 return syms.longType.constType(
aoqi@0 220 new Long(longValue(l) + longValue(r)));
aoqi@0 221 case lsub:
aoqi@0 222 return syms.longType.constType(
aoqi@0 223 new Long(longValue(l) - longValue(r)));
aoqi@0 224 case lmul:
aoqi@0 225 return syms.longType.constType(
aoqi@0 226 new Long(longValue(l) * longValue(r)));
aoqi@0 227 case ldiv:
aoqi@0 228 return syms.longType.constType(
aoqi@0 229 new Long(longValue(l) / longValue(r)));
aoqi@0 230 case lmod:
aoqi@0 231 return syms.longType.constType(
aoqi@0 232 new Long(longValue(l) % longValue(r)));
aoqi@0 233 case land:
aoqi@0 234 return syms.longType.constType(
aoqi@0 235 new Long(longValue(l) & longValue(r)));
aoqi@0 236 case lor:
aoqi@0 237 return syms.longType.constType(
aoqi@0 238 new Long(longValue(l) | longValue(r)));
aoqi@0 239 case lxor:
aoqi@0 240 return syms.longType.constType(
aoqi@0 241 new Long(longValue(l) ^ longValue(r)));
aoqi@0 242 case lshl: case lshll:
aoqi@0 243 return syms.longType.constType(
aoqi@0 244 new Long(longValue(l) << intValue(r)));
aoqi@0 245 case lshr: case lshrl:
aoqi@0 246 return syms.longType.constType(
aoqi@0 247 new Long(longValue(l) >> intValue(r)));
aoqi@0 248 case lushr:
aoqi@0 249 return syms.longType.constType(
aoqi@0 250 new Long(longValue(l) >>> intValue(r)));
aoqi@0 251 case lcmp:
aoqi@0 252 if (longValue(l) < longValue(r))
aoqi@0 253 return syms.intType.constType(minusOne);
aoqi@0 254 else if (longValue(l) > longValue(r))
aoqi@0 255 return syms.intType.constType(one);
aoqi@0 256 else
aoqi@0 257 return syms.intType.constType(zero);
aoqi@0 258 case fadd:
aoqi@0 259 return syms.floatType.constType(
aoqi@0 260 new Float(floatValue(l) + floatValue(r)));
aoqi@0 261 case fsub:
aoqi@0 262 return syms.floatType.constType(
aoqi@0 263 new Float(floatValue(l) - floatValue(r)));
aoqi@0 264 case fmul:
aoqi@0 265 return syms.floatType.constType(
aoqi@0 266 new Float(floatValue(l) * floatValue(r)));
aoqi@0 267 case fdiv:
aoqi@0 268 return syms.floatType.constType(
aoqi@0 269 new Float(floatValue(l) / floatValue(r)));
aoqi@0 270 case fmod:
aoqi@0 271 return syms.floatType.constType(
aoqi@0 272 new Float(floatValue(l) % floatValue(r)));
aoqi@0 273 case fcmpg: case fcmpl:
aoqi@0 274 if (floatValue(l) < floatValue(r))
aoqi@0 275 return syms.intType.constType(minusOne);
aoqi@0 276 else if (floatValue(l) > floatValue(r))
aoqi@0 277 return syms.intType.constType(one);
aoqi@0 278 else if (floatValue(l) == floatValue(r))
aoqi@0 279 return syms.intType.constType(zero);
aoqi@0 280 else if (opcode == fcmpg)
aoqi@0 281 return syms.intType.constType(one);
aoqi@0 282 else
aoqi@0 283 return syms.intType.constType(minusOne);
aoqi@0 284 case dadd:
aoqi@0 285 return syms.doubleType.constType(
aoqi@0 286 new Double(doubleValue(l) + doubleValue(r)));
aoqi@0 287 case dsub:
aoqi@0 288 return syms.doubleType.constType(
aoqi@0 289 new Double(doubleValue(l) - doubleValue(r)));
aoqi@0 290 case dmul:
aoqi@0 291 return syms.doubleType.constType(
aoqi@0 292 new Double(doubleValue(l) * doubleValue(r)));
aoqi@0 293 case ddiv:
aoqi@0 294 return syms.doubleType.constType(
aoqi@0 295 new Double(doubleValue(l) / doubleValue(r)));
aoqi@0 296 case dmod:
aoqi@0 297 return syms.doubleType.constType(
aoqi@0 298 new Double(doubleValue(l) % doubleValue(r)));
aoqi@0 299 case dcmpg: case dcmpl:
aoqi@0 300 if (doubleValue(l) < doubleValue(r))
aoqi@0 301 return syms.intType.constType(minusOne);
aoqi@0 302 else if (doubleValue(l) > doubleValue(r))
aoqi@0 303 return syms.intType.constType(one);
aoqi@0 304 else if (doubleValue(l) == doubleValue(r))
aoqi@0 305 return syms.intType.constType(zero);
aoqi@0 306 else if (opcode == dcmpg)
aoqi@0 307 return syms.intType.constType(one);
aoqi@0 308 else
aoqi@0 309 return syms.intType.constType(minusOne);
aoqi@0 310 case if_acmpeq:
aoqi@0 311 return syms.booleanType.constType(b2i(l.equals(r)));
aoqi@0 312 case if_acmpne:
aoqi@0 313 return syms.booleanType.constType(b2i(!l.equals(r)));
aoqi@0 314 case string_add:
aoqi@0 315 return syms.stringType.constType(
aoqi@0 316 left.stringValue() + right.stringValue());
aoqi@0 317 default:
aoqi@0 318 return null;
aoqi@0 319 }
aoqi@0 320 }
aoqi@0 321 } catch (ArithmeticException e) {
aoqi@0 322 return null;
aoqi@0 323 }
aoqi@0 324 }
aoqi@0 325
aoqi@0 326 /** Coerce constant type to target type.
aoqi@0 327 * @param etype The source type of the coercion,
aoqi@0 328 * which is assumed to be a constant type compatible with
aoqi@0 329 * ttype.
aoqi@0 330 * @param ttype The target type of the coercion.
aoqi@0 331 */
aoqi@0 332 Type coerce(Type etype, Type ttype) {
aoqi@0 333 // WAS if (etype.baseType() == ttype.baseType())
aoqi@0 334 if (etype.tsym.type == ttype.tsym.type)
aoqi@0 335 return etype;
aoqi@0 336 if (etype.isNumeric()) {
aoqi@0 337 Object n = etype.constValue();
aoqi@0 338 switch (ttype.getTag()) {
aoqi@0 339 case BYTE:
aoqi@0 340 return syms.byteType.constType(0 + (byte)intValue(n));
aoqi@0 341 case CHAR:
aoqi@0 342 return syms.charType.constType(0 + (char)intValue(n));
aoqi@0 343 case SHORT:
aoqi@0 344 return syms.shortType.constType(0 + (short)intValue(n));
aoqi@0 345 case INT:
aoqi@0 346 return syms.intType.constType(intValue(n));
aoqi@0 347 case LONG:
aoqi@0 348 return syms.longType.constType(longValue(n));
aoqi@0 349 case FLOAT:
aoqi@0 350 return syms.floatType.constType(floatValue(n));
aoqi@0 351 case DOUBLE:
aoqi@0 352 return syms.doubleType.constType(doubleValue(n));
aoqi@0 353 }
aoqi@0 354 }
aoqi@0 355 return ttype;
aoqi@0 356 }
aoqi@0 357 }

mercurial