Package kilim.analysis

Source Code of kilim.analysis.Usage

/* Copyright (c) 2006, Sriram Srinivasan
*
* You may distribute this software under the terms of the license
* specified in the file "License"
*/

package kilim.analysis;

import java.util.ArrayList;
import java.util.BitSet;

/**
* Each BasicBlock owns one instance of Usage. This class maintains, in essence, three vectors of
* booleans, indexed by the local variable number. Since it is <i>very</i> rare for a method to have
* more than 31 local variables, the vectors are represented by int bitmaps. For more than this, the
* basic block creates an instance of BigUsage that is functionally identical (TODO)
*
* Note that we don't need to track usage of operand stack. All elements of the operand stack are
* always live, and always need to be stored and restored (during stack switching). This is not true
* of local vars; a var may have a valid value which may not be used downstream, so we track which
* vars must be taken seriously.
*
* @see BasicBlock
*/
public class Usage {
    /**
     * The number of local vars in the owning BB's frame
     */
    private int nLocals;

    /**
     * bit(i) == 1 (counting from LSB) if the ith local var is live downstream
     */
    private BitSet in;

    /**
     * use.bit(i) == 1 (from LSB) if the ith var is read before it has been written. The bit vector
     * as a whole represents the set of vars that the BB needs from its predecessors.
     */
    private BitSet use;

    /**
     * def.bit(i) == 1 (from LSB) if the ith var is written into before it has been read. It
     * represents all the vars that this BB is capable of supplying downstream on its own, hence
     * those vars are not required to be supplied by its predecessors (even if they do supply them,
     * they will be overwritten anyway).
     */
    private BitSet def;

    public Usage(int numLocals) {
        nLocals = numLocals;
        in = new BitSet(numLocals);
        use = new BitSet(numLocals);
        def = new BitSet(numLocals);
    }

    public void read(int var) {
        assert var < nLocals : "local var num=" + var + " exceeds nLocals = " + nLocals;
        if (!def.get(var)) {
            // is not def'd earlier
            use.set(var);
        }
    }

    public void write(int var) {
        assert var < nLocals : "local var num=" + var + " exceeds nLocals = " + nLocals;
        def.set(var);
    }

    /**
     * return true if var is live at the entrance to this BB.
     */
    public boolean isLiveIn(int var) {
        return in.get(var);
    }

    /**
     * This is the standard liveness calculation (Dragon Book, section 10.6). At each BB (and its
     * corresponding usage), we evaluate "in" using use and def. in = use U (out \ def) where out =
     * U succ.in, for all successors
     */
    public boolean evalLiveIn(ArrayList<Usage> succUsage) {
        BitSet out = new BitSet(nLocals);
        BitSet old_in = (BitSet) in.clone();
        if (succUsage.size() == 0) {
            in = use;
        } else {
            // calculate out = U succ.in
            out = (BitSet) succUsage.get(0).in.clone();
            for (int i = 1; i < succUsage.size(); i++) {
                out.or(succUsage.get(i).in);
            }
            // calc out \ def == out & ~def == ~(out | def)
            BitSet def1 = (BitSet) def.clone();
            def1.flip(0, nLocals);
            out.and(def1);
            out.or(use);
            in = out;
        }
        return !(in.equals(old_in));
    }

    /**
     * Called to coalesce a successor's usage into the current BB. Important: This should be called
     * before live variable analysis begins, because we don't bother merging this.in.
     */
    void absorb(Usage succ) {
        BitSet b = (BitSet) this.def.clone();
        b.flip(0, nLocals);
        b.and(succ.use);
        this.use.or(b);
        this.def.or(succ.def);
    }

    public String toString() {
        StringBuffer sb = new StringBuffer();
        sb.append("use");
        printBits(sb, use);
        sb.append("def");
        printBits(sb, def);
        sb.append("in");
        printBits(sb, in);
        return sb.toString();
    }

    private void printBits(StringBuffer sb, BitSet b) {
        int numDefined = 0;
        for (int i = 0; i < nLocals; i++) {
            if (b.get(i))
                numDefined++;
        }
        sb.append('(').append(numDefined).append("): ");
        for (int i = 0; i < nLocals; i++) {
            if (b.get(i))
                sb.append(i).append(' ');
        }
        sb.append('\n');
    }

    /**
     * This is purely for testing purposes.
     *
     * @param var
     *            local var index
     */
    public void setLiveIn(int var) {
        in.set(var);
    }

    Usage copy() {
        Usage ret = new Usage(nLocals);
        ret.use = use;
        ret.def = def;
        return ret;
    }
}
TOP

Related Classes of kilim.analysis.Usage

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.