All Downloads are FREE. Search and download functionalities are using the official Maven repository.

edu.umd.cs.findbugs.ba.FrameDataflowAnalysis Maven / Gradle / Ivy

There is a newer version: 4.8.6
Show newest version
/*
 * Bytecode Analysis Framework
 * Copyright (C) 2003,2004 University of Maryland
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library 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
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */

package edu.umd.cs.findbugs.ba;

import java.util.Iterator;

import javax.annotation.CheckForNull;

/**
 * A convenient base class for dataflow analysis classes which use Frames as
 * values.
 *
 * @author David Hovemeyer
 * @see Frame
 * @see DataflowAnalysis
 */
public abstract class FrameDataflowAnalysis> extends
        ForwardDataflowAnalysis {
    public FrameDataflowAnalysis(DepthFirstSearch dfs) {
        super(dfs);
    }

    @Override
    public void copy(FrameType source, FrameType dest) {
        dest.copyFrom(source);
    }

    @Override
    public void makeFactTop(FrameType fact) {
        fact.setTop();
    }

    @Override
    public boolean isTop(FrameType fact) {
        return fact.isTop();
    }

    @Override
    public boolean same(FrameType fact1, FrameType fact2) {
        return fact1.sameAs(fact2);
    }

    /**
     * Get the dataflow fact representing the point just before given Location.
     * Note "before" is meant in the logical sense, so for backward analyses,
     * before means after the location in the control flow sense.
     *
     * @return the fact at the point just before the location
     */

    public FrameType getFactAtPC(CFG cfg, int pc) throws DataflowAnalysisException {
        FrameType result = createFact();
        makeFactTop(result);

        for (Location l : cfg.locations()) {
            if (l.getHandle().getPosition() == pc) {
                FrameType fact = getFactAtLocation(l);
                if (isFactValid(fact)) {
                    mergeInto(fact, result);
                }
            }
        }
        return result;
    }

    /**
     * Get the dataflow fact representing the point just before given Location.
     * Note "before" is meant in the logical sense, so for backward analyses,
     * before means after the location in the control flow sense.
     *
     * @return the fact at the point just before the location
     */

    public FrameType getFactBeforeExceptionCheck(CFG cfg, int pc) throws DataflowAnalysisException {
        FrameType result = createFact();
        makeFactTop(result);

        for (Location loc : cfg.getLocationsContainingInstructionWithOffset(pc)) {
            BasicBlock b = loc.getBasicBlock();
            BasicBlock b2 = null;
            if (b.getFirstInstruction() != null && b.getFirstInstruction().getPosition() == pc) {
                b2 = cfg.getPredecessorWithEdgeType(b, EdgeTypes.FALL_THROUGH_EDGE);
            }
            if (b2 != null && b2.isExceptionThrower()) {
                for (Iterator i = cfg.incomingEdgeIterator(b2); i.hasNext();) {
                    Edge e = i.next();
                    FrameType fact = getFactOnEdge(e);
                    if (isFactValid(fact)) {
                        mergeInto(fact, result);
                    }
                }
            } else {
                FrameType fact = getFactAtLocation(loc);
                if (isFactValid(fact)) {
                    mergeInto(fact, result);
                }
            }
        }
        return result;
    }

    @Override
    public boolean isFactValid(FrameType fact) {
        return fact.isValid();
    }

    @Override
    public int getLastUpdateTimestamp(FrameType fact) {
        return fact.getLastUpdateTimestamp();
    }

    @Override
    public void setLastUpdateTimestamp(FrameType fact, int lastTimestamp) {
        fact.setLastUpdateTimestamp(lastTimestamp);
    }

    /**
     * 

Create a modifiable copy of a frame. This is useful for meetInto(), if * the frame needs to be modified in a path-sensitive fashion. A typical * usage pattern is: *

* *
     * FrameType copy = null;
     * if (someCondition()) {
     *     copy = modifyFrame(fact, copy);
     *     // modify copy
     * }
     * if (someOtherCondition()) {
     *     copy = modifyFrame(fact, copy);
     *     // modify copy
     * }
     * if (copy != null)
     *     fact = copy;
     * mergeInto(fact, result);
     * 
*

* The advantage of using modifyFrame() is that new code can be added before * or after other places where the frame is modified, and the code will * remain correct.

* * @param orig * the original frame * @param copy * the modifiable copy (returned by a previous call to * modifyFrame()), or null if this is the first time * modifyFrame() is being called * @return a modifiable copy of fact */ final protected FrameType modifyFrame(FrameType orig, @CheckForNull FrameType copy) { if (copy == null) { copy = createFact(); copy.copyFrom(orig); } return copy; } /** * Merge one frame into another. * * @param other * the frame to merge with the result * @param result * the result frame, which is modified to be the merge of the two * frames */ protected void mergeInto(FrameType other, FrameType result) throws DataflowAnalysisException { // Handle if result Frame or the other Frame is the special "TOP" value. if (result.isTop()) { // Result is the identity element, so copy the other Frame result.copyFrom(other); return; } else if (other.isTop()) { // Other Frame is the identity element, so result stays the same return; } // Handle if result Frame or the other Frame is the special "BOTTOM" // value. if (result.isBottom()) { // Result is the bottom element, so it stays that way return; } else if (other.isBottom()) { // Other Frame is the bottom element, so result becomes the bottom // element too result.setBottom(); return; } // If the number of slots in the Frames differs, // then the result is the special "BOTTOM" value. if (result.getNumSlots() != other.getNumSlots()) { result.setBottom(); return; } // Usual case: ordinary Frames consisting of the same number of values. // Merge each value in the two slot lists element-wise. for (int i = 0; i < result.getNumSlots(); ++i) { mergeValues(other, result, i); } } /** * Merge the values contained in a given slot of two Frames. * * @param otherFrame * a Frame * @param resultFrame * a Frame which will contain the resulting merged value * @param slot * a slot in both frames * @throws DataflowAnalysisException */ protected abstract void mergeValues(FrameType otherFrame, FrameType resultFrame, int slot) throws DataflowAnalysisException; }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy