alvinalexander.com | career | drupal | java | mac | mysql | perl | scala | uml | unix  

Java example source code file (ConstFold.java)

This example Java source code file (ConstFold.java) is included in the alvinalexander.com "Java Source Code Warehouse" project. The intent of this project is to help you "Learn Java by Example" TM.

Learn more about this Java project at its project page.

Java - Java tags/keywords

arithmeticexception, assertionerror, byte, char, constfold, double, float, integer, list, long, object, short, symtab, type

The ConstFold.java Java example source code

/*
 * Copyright (c) 1999, 2013, 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 com.sun.tools.javac.comp;

import com.sun.tools.javac.code.*;
import com.sun.tools.javac.jvm.*;
import com.sun.tools.javac.util.*;

import static com.sun.tools.javac.code.TypeTag.BOOLEAN;

import static com.sun.tools.javac.jvm.ByteCodes.*;

/** Helper class for constant folding, used by the attribution phase.
 *  This class is marked strictfp as mandated by JLS 15.4.
 *
 *  <p>This is NOT part of any supported API.
 *  If you write code that depends on this, you do so at your own risk.
 *  This code and its internal interfaces are subject to change or
 *  deletion without notice.</b>
 */
strictfp class ConstFold {
    protected static final Context.Key<ConstFold> constFoldKey =
        new Context.Key<ConstFold>();

    private Symtab syms;

    public static ConstFold instance(Context context) {
        ConstFold instance = context.get(constFoldKey);
        if (instance == null)
            instance = new ConstFold(context);
        return instance;
    }

    private ConstFold(Context context) {
        context.put(constFoldKey, this);

        syms = Symtab.instance(context);
    }

    static final Integer minusOne = -1;
    static final Integer zero     = 0;
    static final Integer one      = 1;

   /** Convert boolean to integer (true = 1, false = 0).
    */
    private static Integer b2i(boolean b) {
        return b ? one : zero;
    }
    private static int intValue(Object x) { return ((Number)x).intValue(); }
    private static long longValue(Object x) { return ((Number)x).longValue(); }
    private static float floatValue(Object x) { return ((Number)x).floatValue(); }
    private static double doubleValue(Object x) { return ((Number)x).doubleValue(); }

    /** Fold binary or unary operation, returning constant type reflecting the
     *  operations result. Return null if fold failed due to an
     *  arithmetic exception.
     *  @param opcode    The operation's opcode instruction (usually a byte code),
     *                   as entered by class Symtab.
     *  @param argtypes  The operation's argument types (a list of length 1 or 2).
     *                   Argument types are assumed to have non-null constValue's.
     */
    Type fold(int opcode, List<Type> argtypes) {
        int argCount = argtypes.length();
        if (argCount == 1)
            return fold1(opcode, argtypes.head);
        else if (argCount == 2)
            return fold2(opcode, argtypes.head, argtypes.tail.head);
        else
            throw new AssertionError();
    }

    /** Fold unary operation.
     *  @param opcode    The operation's opcode instruction (usually a byte code),
     *                   as entered by class Symtab.
     *                   opcode's ifeq to ifge are for postprocessing
     *                   xcmp; ifxx pairs of instructions.
     *  @param operand   The operation's operand type.
     *                   Argument types are assumed to have non-null constValue's.
     */
    Type fold1(int opcode, Type operand) {
        try {
            Object od = operand.constValue();
            switch (opcode) {
            case nop:
                return operand;
            case ineg: // unary -
                return syms.intType.constType(-intValue(od));
            case ixor: // ~
                return syms.intType.constType(~intValue(od));
            case bool_not: // !
                return syms.booleanType.constType(b2i(intValue(od) == 0));
            case ifeq:
                return syms.booleanType.constType(b2i(intValue(od) == 0));
            case ifne:
                return syms.booleanType.constType(b2i(intValue(od) != 0));
            case iflt:
                return syms.booleanType.constType(b2i(intValue(od) < 0));
            case ifgt:
                return syms.booleanType.constType(b2i(intValue(od) > 0));
            case ifle:
                return syms.booleanType.constType(b2i(intValue(od) <= 0));
            case ifge:
                return syms.booleanType.constType(b2i(intValue(od) >= 0));

            case lneg: // unary -
                return syms.longType.constType(new Long(-longValue(od)));
            case lxor: // ~
                return syms.longType.constType(new Long(~longValue(od)));

            case fneg: // unary -
                return syms.floatType.constType(new Float(-floatValue(od)));

            case dneg: // ~
                return syms.doubleType.constType(new Double(-doubleValue(od)));

            default:
                return null;
            }
        } catch (ArithmeticException e) {
            return null;
        }
    }

    /** Fold binary operation.
     *  @param opcode    The operation's opcode instruction (usually a byte code),
     *                   as entered by class Symtab.
     *                   opcode's ifeq to ifge are for postprocessing
     *                   xcmp; ifxx pairs of instructions.
     *  @param left      The type of the operation's left operand.
     *  @param right     The type of the operation's right operand.
     */
    Type fold2(int opcode, Type left, Type right) {
        try {
            if (opcode > ByteCodes.preMask) {
                // we are seeing a composite instruction of the form xcmp; ifxx.
                // In this case fold both instructions separately.
                Type t1 = fold2(opcode >> ByteCodes.preShift, left, right);
                return (t1.constValue() == null) ? t1
                    : fold1(opcode & ByteCodes.preMask, t1);
            } else {
                Object l = left.constValue();
                Object r = right.constValue();
                switch (opcode) {
                case iadd:
                    return syms.intType.constType(intValue(l) + intValue(r));
                case isub:
                    return syms.intType.constType(intValue(l) - intValue(r));
                case imul:
                    return syms.intType.constType(intValue(l) * intValue(r));
                case idiv:
                    return syms.intType.constType(intValue(l) / intValue(r));
                case imod:
                    return syms.intType.constType(intValue(l) % intValue(r));
                case iand:
                    return (left.hasTag(BOOLEAN)
                      ? syms.booleanType : syms.intType)
                      .constType(intValue(l) & intValue(r));
                case bool_and:
                    return syms.booleanType.constType(b2i((intValue(l) & intValue(r)) != 0));
                case ior:
                    return (left.hasTag(BOOLEAN)
                      ? syms.booleanType : syms.intType)
                      .constType(intValue(l) | intValue(r));
                case bool_or:
                    return syms.booleanType.constType(b2i((intValue(l) | intValue(r)) != 0));
                case ixor:
                    return (left.hasTag(BOOLEAN)
                      ? syms.booleanType : syms.intType)
                      .constType(intValue(l) ^ intValue(r));
                case ishl: case ishll:
                    return syms.intType.constType(intValue(l) << intValue(r));
                case ishr: case ishrl:
                    return syms.intType.constType(intValue(l) >> intValue(r));
                case iushr: case iushrl:
                    return syms.intType.constType(intValue(l) >>> intValue(r));
                case if_icmpeq:
                    return syms.booleanType.constType(
                        b2i(intValue(l) == intValue(r)));
                case if_icmpne:
                    return syms.booleanType.constType(
                        b2i(intValue(l) != intValue(r)));
                case if_icmplt:
                    return syms.booleanType.constType(
                        b2i(intValue(l) < intValue(r)));
                case if_icmpgt:
                    return syms.booleanType.constType(
                        b2i(intValue(l) > intValue(r)));
                case if_icmple:
                    return syms.booleanType.constType(
                        b2i(intValue(l) <= intValue(r)));
                case if_icmpge:
                    return syms.booleanType.constType(
                        b2i(intValue(l) >= intValue(r)));

                case ladd:
                    return syms.longType.constType(
                        new Long(longValue(l) + longValue(r)));
                case lsub:
                    return syms.longType.constType(
                        new Long(longValue(l) - longValue(r)));
                case lmul:
                    return syms.longType.constType(
                        new Long(longValue(l) * longValue(r)));
                case ldiv:
                    return syms.longType.constType(
                        new Long(longValue(l) / longValue(r)));
                case lmod:
                    return syms.longType.constType(
                        new Long(longValue(l) % longValue(r)));
                case land:
                    return syms.longType.constType(
                        new Long(longValue(l) & longValue(r)));
                case lor:
                    return syms.longType.constType(
                        new Long(longValue(l) | longValue(r)));
                case lxor:
                    return syms.longType.constType(
                        new Long(longValue(l) ^ longValue(r)));
                case lshl: case lshll:
                    return syms.longType.constType(
                        new Long(longValue(l) << intValue(r)));
                case lshr: case lshrl:
                    return syms.longType.constType(
                        new Long(longValue(l) >> intValue(r)));
                case lushr:
                    return syms.longType.constType(
                        new Long(longValue(l) >>> intValue(r)));
                case lcmp:
                    if (longValue(l) < longValue(r))
                        return syms.intType.constType(minusOne);
                    else if (longValue(l) > longValue(r))
                        return syms.intType.constType(one);
                    else
                        return syms.intType.constType(zero);
                case fadd:
                    return syms.floatType.constType(
                        new Float(floatValue(l) + floatValue(r)));
                case fsub:
                    return syms.floatType.constType(
                        new Float(floatValue(l) - floatValue(r)));
                case fmul:
                    return syms.floatType.constType(
                        new Float(floatValue(l) * floatValue(r)));
                case fdiv:
                    return syms.floatType.constType(
                        new Float(floatValue(l) / floatValue(r)));
                case fmod:
                    return syms.floatType.constType(
                        new Float(floatValue(l) % floatValue(r)));
                case fcmpg: case fcmpl:
                    if (floatValue(l) < floatValue(r))
                        return syms.intType.constType(minusOne);
                    else if (floatValue(l) > floatValue(r))
                        return syms.intType.constType(one);
                    else if (floatValue(l) == floatValue(r))
                        return syms.intType.constType(zero);
                    else if (opcode == fcmpg)
                        return syms.intType.constType(one);
                    else
                        return syms.intType.constType(minusOne);
                case dadd:
                    return syms.doubleType.constType(
                        new Double(doubleValue(l) + doubleValue(r)));
                case dsub:
                    return syms.doubleType.constType(
                        new Double(doubleValue(l) - doubleValue(r)));
                case dmul:
                    return syms.doubleType.constType(
                        new Double(doubleValue(l) * doubleValue(r)));
                case ddiv:
                    return syms.doubleType.constType(
                        new Double(doubleValue(l) / doubleValue(r)));
                case dmod:
                    return syms.doubleType.constType(
                        new Double(doubleValue(l) % doubleValue(r)));
                case dcmpg: case dcmpl:
                    if (doubleValue(l) < doubleValue(r))
                        return syms.intType.constType(minusOne);
                    else if (doubleValue(l) > doubleValue(r))
                        return syms.intType.constType(one);
                    else if (doubleValue(l) == doubleValue(r))
                        return syms.intType.constType(zero);
                    else if (opcode == dcmpg)
                        return syms.intType.constType(one);
                    else
                        return syms.intType.constType(minusOne);
                case if_acmpeq:
                    return syms.booleanType.constType(b2i(l.equals(r)));
                case if_acmpne:
                    return syms.booleanType.constType(b2i(!l.equals(r)));
                case string_add:
                    return syms.stringType.constType(
                        left.stringValue() + right.stringValue());
                default:
                    return null;
                }
            }
        } catch (ArithmeticException e) {
            return null;
        }
    }

    /** Coerce constant type to target type.
     *  @param etype      The source type of the coercion,
     *                    which is assumed to be a constant type compatible with
     *                    ttype.
     *  @param ttype      The target type of the coercion.
     */
     Type coerce(Type etype, Type ttype) {
         // WAS if (etype.baseType() == ttype.baseType())
         if (etype.tsym.type == ttype.tsym.type)
             return etype;
         if (etype.isNumeric()) {
             Object n = etype.constValue();
             switch (ttype.getTag()) {
             case BYTE:
                 return syms.byteType.constType(0 + (byte)intValue(n));
             case CHAR:
                 return syms.charType.constType(0 + (char)intValue(n));
             case SHORT:
                 return syms.shortType.constType(0 + (short)intValue(n));
             case INT:
                 return syms.intType.constType(intValue(n));
             case LONG:
                 return syms.longType.constType(longValue(n));
             case FLOAT:
                 return syms.floatType.constType(floatValue(n));
             case DOUBLE:
                 return syms.doubleType.constType(doubleValue(n));
             }
         }
         return ttype;
     }
}

Other Java examples (source code examples)

Here is a short list of links related to this Java ConstFold.java source code file:

... this post is sponsored by my books ...

#1 New Release!

FP Best Seller

 

new blog posts

 

Copyright 1998-2021 Alvin Alexander, alvinalexander.com
All Rights Reserved.

A percentage of advertising revenue from
pages under the /java/jwarehouse URI on this website is
paid back to open source projects.