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

soot.jimple.toolkits.pointer.MethodRWSet Maven / Gradle / Ivy

There is a newer version: 2.5.0-9
Show newest version
/* Soot - a J*va Optimization Framework
 * Copyright (C) 2003 Ondrej Lhotak
 *
 * 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 soot.jimple.toolkits.pointer;
import java.util.*;
import soot.*;

/** Represents the read or write set of a statement. */
public class MethodRWSet extends RWSet {
    public Set globals;
    public Map fields;
    protected boolean callsNative = false;
    protected boolean isFull = false;
    public static final int MAX_SIZE = Integer.MAX_VALUE;

    public String toString() {
        boolean empty = true;
        StringBuffer ret = new StringBuffer();
        if( fields != null ) {
            for (Object element : fields.keySet()) {
                final Object field = element;
                ret.append( "[Field: "+field+" "+fields.get(field)+"]\n" );
                empty = false;
            }
        }
        if( globals != null ) {
            for( Iterator globalIt = globals.iterator(); globalIt.hasNext(); ) {
                final Object global = globalIt.next();
                ret.append( "[Global: "+global+"]\n" );
                empty = false;
            }
        }
        if(empty) ret.append("empty");
        return ret.toString();
    }

   	public int size()
	{
		if(globals == null)
		{
			if(fields == null)
				return 0;
			else
				return fields.size();
		}
		else
		{
			if(fields == null)
				return globals.size();
			else
				return globals.size() + fields.size();
		}
	}

    //static int count = 0;
    public MethodRWSet() {
        /*
	count++;
	if( 0 == (count % 1000) ) {
	    G.v().out.println( "Created "+count+"th MethodRWSet" );
	}
        */
    }
    public boolean getCallsNative() {
	return callsNative;
    }

    public boolean setCallsNative() {
	boolean ret = !callsNative;
	callsNative = true;
	return ret;
    }

    /** Returns an iterator over any globals read/written. */
    public Set getGlobals() {
	if( isFull ) return G.v().MethodRWSet_allGlobals;
	if( globals == null ) return Collections.EMPTY_SET;
	return globals;
    }

    /** Returns an iterator over any fields read/written. */
    public Set getFields() {
	if( isFull ) return G.v().MethodRWSet_allFields;
	if( fields == null ) return Collections.EMPTY_SET;
	return fields.keySet();
    }

    /** Returns a set of base objects whose field f is read/written. */
    public PointsToSet getBaseForField( Object f ) {
	if( isFull ) return FullObjectSet.v();
	if( fields == null ) return null;
	return fields.get( f );
    }

    public boolean hasNonEmptyIntersection( RWSet oth ) {
	if( isFull ) return oth != null;
	if( !(oth instanceof MethodRWSet) ) {
	    return oth.hasNonEmptyIntersection( this );
	}
	MethodRWSet other = (MethodRWSet) oth;
	if( globals != null && other.globals != null
		&& !globals.isEmpty() && !other.globals.isEmpty() ) {
	    for( Iterator it = other.globals.iterator(); it.hasNext(); ) {
		if( globals.contains( it.next() ) ) return true;
	    }
	}
	if( fields != null && other.fields != null
		&& !fields.isEmpty() && !other.fields.isEmpty() ) {
	    for (Object element : other.fields.keySet()) {
	        final Object field = element;
		if( fields.containsKey( field ) ) {
		    if( Union.hasNonEmptyIntersection(
                                getBaseForField( field ),
				other.getBaseForField( field ) ) ) {
			return true;
		    }
		}
	    }
	}
	return false;
    }

    /** Adds the RWSet other into this set. */
    public boolean union( RWSet other ) {
	if( other == null ) return false;
	if( isFull ) return false;
	boolean ret = false;
	if( other instanceof MethodRWSet ) {
	    MethodRWSet o = (MethodRWSet) other;
	    if( o.getCallsNative() ) {
		ret = !getCallsNative() | ret;
		setCallsNative();
	    }
	    if( o.isFull ) {
		ret = !isFull | ret;
		isFull = true;
                if( true ) throw new RuntimeException( "attempt to add full set "+o+" into "+this );
		globals = null;
		fields = null;
		return ret;
	    }
	    if( o.globals != null ) {
		if( globals == null ) globals = new HashSet();
		ret = globals.addAll( o.globals ) | ret;
		if( globals.size() > MAX_SIZE ) {
		    globals = null;
		    isFull = true;
                throw new RuntimeException( "attempt to add full set "+o+" into "+this );
		}
	    }
	    if( o.fields != null ) {
		for (Object element : o.fields.keySet()) {
		    final Object field = element;
		    PointsToSet os = o.getBaseForField( field );
		    ret = addFieldRef( os, field ) | ret;
		}
	    }
	} else {
	    StmtRWSet oth = (StmtRWSet) other;
	    if( oth.base != null ) {
		ret = addFieldRef( oth.base, oth.field ) | ret;
	    } else if( oth.field != null ) {
		ret = addGlobal( (SootField) oth.field ) | ret;
	    }
	}
	if( !getCallsNative() && other.getCallsNative() ) {
	    setCallsNative();
	    return true;
	}
	return ret;
    }

    public boolean addGlobal( SootField global ) {
	if( globals == null ) globals = new HashSet();
	boolean ret = globals.add( global );
	if( globals.size() > MAX_SIZE ) {
	    globals = null;
	    isFull = true;
                throw new RuntimeException( "attempt to add more than "+MAX_SIZE+" globals into "+this );
	}
	return ret;
    }
    public boolean addFieldRef( PointsToSet otherBase, Object field ) {
	boolean ret = false;
	if( fields == null ) fields = new HashMap();
	PointsToSet base = getBaseForField( field );
	if( base instanceof FullObjectSet ) return false;
	if( otherBase instanceof FullObjectSet ) {
	    fields.put( field, otherBase );
	    return true;
	}
	if( otherBase.equals( base ) ) return false;
	Union u;
	if( base == null || !(base instanceof Union) ) {
	    u = G.v().Union_factory.newUnion();
	    if( base != null) u.addAll( base );
	    fields.put( field, u );
	    if( base == null ) addedField( fields.size() );
	    ret = true;
	    if( fields.keySet().size() > MAX_SIZE ) {
		fields = null;
		isFull = true;
            if( true )    throw new RuntimeException( "attempt to add more than "+MAX_SIZE+" fields into "+this );
		return true;
	    }
	} else {
	    u = (Union) base;
	}
	ret = u.addAll( otherBase ) | ret;
	return ret;
    }
    static void addedField( int size ) {
    }
    public boolean isEquivTo( RWSet other ) {
	return other == this;
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy