Package dk.brics.string.intermediate.operations

Source Code of dk.brics.string.intermediate.operations.FieldUsageAnalysis

package dk.brics.string.intermediate.operations;

import java.util.Collection;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;

import dk.brics.string.intermediate.Call;
import dk.brics.string.intermediate.Field;
import dk.brics.string.intermediate.FieldStatement;
import dk.brics.string.intermediate.Method;
import dk.brics.string.intermediate.Statement;
import dk.brics.string.util.MultiMap;

/**
* Finds the set of fields that each method reads and/or modifies.
* <p/>
* Formally, a method reads the field <tt>F</tt> if it contains a reference to <tt>F</tt>,
* or a call to a method that reads <tt>F</tt>. Likewise, it assigns to <tt>F</tt> if it
* contains an assignment to <tt>F</tt>, or a call to a method that assigns to <tt>F</tt>.
*/
public class FieldUsageAnalysis {
 
  private MultiMap<Method, Field> uses = new MultiMap<Method, Field>();
 
  public FieldUsageAnalysis(Collection<? extends Method> methods) {
    // find non-transitive usage
    for (Method method : methods) {
      for (Statement statement : method.getStatements()) {
        if (statement instanceof FieldStatement) {
            FieldStatement stm = (FieldStatement)statement;
          Field field = stm.getField();
          uses.add(method, field);
        }
      }
    }
   
    // apply transitive closure
    // TODO does the cubic framework provide a faster solution to this??
    Set<Method> methodQueue = new HashSet<Method>();
    methodQueue.addAll(methods);
    while (!methodQueue.isEmpty()) {
      // pop a method from the queue
      Iterator<Method> it = methodQueue.iterator();
      Method method = it.next();
      it.remove();
     
      // add defined fields backwards to all callers
      Set<Field> use = uses.getView(method);
      for (Call call : method.getCallSites()) {
        Method callerMethod = call.getMethod();
        if (callerMethod == method)
          continue;
       
        boolean changed = uses.addAll(callerMethod, use);
       
        if (changed) {
          methodQueue.add(callerMethod);
        }
      }
    }
  }
 
  /**
   * Returns the set of fields that may be read and/or modified
   * as a result of invoking the method.
   * @param method a method
   * @return an unmodifiable set
   */
  public Set<Field> getUsedFields(Method method) {
      return uses.getView(method);
  }
}
TOP

Related Classes of dk.brics.string.intermediate.operations.FieldUsageAnalysis

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.