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