001/*
002 * Copyright (c) 2009, 2015, Oracle and/or its affiliates. All rights reserved.
003 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
004 *
005 * This code is free software; you can redistribute it and/or modify it
006 * under the terms of the GNU General Public License version 2 only, as
007 * published by the Free Software Foundation.
008 *
009 * This code is distributed in the hope that it will be useful, but WITHOUT
010 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
011 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
012 * version 2 for more details (a copy is included in the LICENSE file that
013 * accompanied this code).
014 *
015 * You should have received a copy of the GNU General Public License version
016 * 2 along with this work; if not, write to the Free Software Foundation,
017 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
018 *
019 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
020 * or visit www.oracle.com if you need additional information or have any
021 * questions.
022 */
023package com.oracle.graal.java;
024
025import java.util.*;
026
027import com.oracle.graal.java.BciBlockMapping.BciBlock;
028
029public final class LargeLocalLiveness extends LocalLiveness {
030    private BitSet[] localsLiveIn;
031    private BitSet[] localsLiveOut;
032    private BitSet[] localsLiveGen;
033    private BitSet[] localsLiveKill;
034    private BitSet[] localsChangedInLoop;
035
036    public LargeLocalLiveness(BciBlock[] blocks, int maxLocals, int loopCount) {
037        super(blocks);
038        int blocksSize = blocks.length;
039        localsLiveIn = new BitSet[blocksSize];
040        localsLiveOut = new BitSet[blocksSize];
041        localsLiveGen = new BitSet[blocksSize];
042        localsLiveKill = new BitSet[blocksSize];
043        for (int i = 0; i < blocksSize; i++) {
044            localsLiveIn[i] = new BitSet(maxLocals);
045            localsLiveOut[i] = new BitSet(maxLocals);
046            localsLiveGen[i] = new BitSet(maxLocals);
047            localsLiveKill[i] = new BitSet(maxLocals);
048        }
049        localsChangedInLoop = new BitSet[loopCount];
050        for (int i = 0; i < loopCount; ++i) {
051            localsChangedInLoop[i] = new BitSet(maxLocals);
052        }
053    }
054
055    @Override
056    protected String debugLiveIn(int blockID) {
057        return localsLiveIn[blockID].toString();
058    }
059
060    @Override
061    protected String debugLiveOut(int blockID) {
062        return localsLiveOut[blockID].toString();
063    }
064
065    @Override
066    protected String debugLiveGen(int blockID) {
067        return localsLiveGen[blockID].toString();
068    }
069
070    @Override
071    protected String debugLiveKill(int blockID) {
072        return localsLiveKill[blockID].toString();
073    }
074
075    @Override
076    protected int liveOutCardinality(int blockID) {
077        return localsLiveOut[blockID].cardinality();
078    }
079
080    @Override
081    protected void propagateLiveness(int blockID, int successorID) {
082        localsLiveOut[blockID].or(localsLiveIn[successorID]);
083    }
084
085    @Override
086    protected void updateLiveness(int blockID) {
087        BitSet liveIn = localsLiveIn[blockID];
088        liveIn.clear();
089        liveIn.or(localsLiveOut[blockID]);
090        liveIn.andNot(localsLiveKill[blockID]);
091        liveIn.or(localsLiveGen[blockID]);
092    }
093
094    @Override
095    protected void loadOne(int blockID, int local) {
096        if (!localsLiveKill[blockID].get(local)) {
097            localsLiveGen[blockID].set(local);
098        }
099    }
100
101    @Override
102    protected void storeOne(int blockID, int local) {
103        if (!localsLiveGen[blockID].get(local)) {
104            localsLiveKill[blockID].set(local);
105        }
106
107        BciBlock block = blocks[blockID];
108        long tmp = block.loops;
109        int pos = 0;
110        while (tmp != 0) {
111            if ((tmp & 1L) == 1L) {
112                this.localsChangedInLoop[pos].set(local);
113            }
114            tmp >>= 1;
115            ++pos;
116        }
117    }
118
119    @Override
120    public boolean localIsLiveIn(BciBlock block, int local) {
121        return block.getId() >= Integer.MAX_VALUE ? true : localsLiveIn[block.getId()].get(local);
122    }
123
124    @Override
125    public boolean localIsLiveOut(BciBlock block, int local) {
126        return block.getId() >= Integer.MAX_VALUE ? true : localsLiveOut[block.getId()].get(local);
127    }
128
129    @Override
130    public boolean localIsChangedInLoop(int loopId, int local) {
131        return localsChangedInLoop[loopId].get(local);
132    }
133}