package dk.brics.jspointers.cfg2dataflow; import java.util.HashMap; import java.util.Map; import java.util.Set; import dk.brics.jscontrolflow.Function; import dk.brics.jscontrolflow.IStatement; import dk.brics.jscontrolflow.analysis.privatevars.PrivateVariables; import dk.brics.jscontrolflow.analysis.reachdef.ReachingDefinitions; import dk.brics.jscontrolflow.analysis.reachdef.VariableDefinition; import dk.brics.jscontrolflow.scope.WithScope; import dk.brics.jscontrolflow.statements.BinaryOperation; import dk.brics.jscontrolflow.statements.Call; import dk.brics.jscontrolflow.statements.CallConstructor; import dk.brics.jscontrolflow.statements.CallProperty; import dk.brics.jscontrolflow.statements.CallVariable; import dk.brics.jscontrolflow.statements.CreateFunction; import dk.brics.jscontrolflow.statements.DeleteProperty; import dk.brics.jscontrolflow.statements.EnterWith; import dk.brics.jscontrolflow.statements.GetNextProperty; import dk.brics.jscontrolflow.statements.IPropertyAccessStatement; import dk.brics.jscontrolflow.statements.IVariableAccessStatement; import dk.brics.jscontrolflow.statements.InvokeStatement; import dk.brics.jscontrolflow.statements.NewObject; import dk.brics.jscontrolflow.statements.ReadProperty; import dk.brics.jscontrolflow.statements.ReadVariable; import dk.brics.jscontrolflow.statements.WriteProperty; import dk.brics.jscontrolflow.statements.WriteVariable; import dk.brics.jspointers.dataflow.AllocNode; import dk.brics.jspointers.dataflow.DeleteNode; import dk.brics.jspointers.dataflow.FlowNode; import dk.brics.jspointers.dataflow.IInvocationFlowNode; import dk.brics.jspointers.dataflow.ILoadFlowNode; import dk.brics.jspointers.dataflow.IPropertyAccessFlowNode; import dk.brics.jspointers.dataflow.IStoreFlowNode; import dk.brics.jspointers.dataflow.IVariableAccessFlowNode; import dk.brics.jspointers.dataflow.InitializeFunctionNode; import dk.brics.jspointers.dataflow.InputPoint; import dk.brics.jspointers.dataflow.InvokeNode; import dk.brics.jspointers.dataflow.LoadAndInvokeNode; import dk.brics.jspointers.dataflow.LoadDynamicNode; import dk.brics.jspointers.dataflow.LoadNode; import dk.brics.jspointers.dataflow.OutputPoint; import dk.brics.jspointers.dataflow.StoreDynamicNode; import dk.brics.jspointers.dataflow.StoreIfPresentNode; import dk.brics.jspointers.dataflow.StoreNode; import dk.brics.jspointers.dataflow.StubNode; import dk.brics.jspointers.dataflow.VarReadGlobalNode; import dk.brics.jspointers.dataflow.VarReadInterscopeNode; import dk.brics.jspointers.dataflow.VarReadNode; import dk.brics.jspointers.dataflow.VarWriteGlobalNode; import dk.brics.jspointers.dataflow.VarWriteInterscopeNode; import dk.brics.jspointers.dataflow.VarWriteNode; import dk.brics.jsutil.MultiMap; import dk.brics.jsutil.Pair; public class Controlflow2DataflowBinding implements IControlflow2DataflowBinding { private MultiMap<IStatement,FlowNode> properties = new MultiMap<IStatement,FlowNode>(); private MultiMap<IVariableAccessStatement,IVariableAccessFlowNode> variables = new MultiMap<IVariableAccessStatement,IVariableAccessFlowNode>(); private MultiMap<IStatement,FlowNode> invokes = new MultiMap<IStatement,FlowNode>(); private MultiMap<IStatement,FlowNode> allocs = new MultiMap<IStatement,FlowNode>(); private MultiMap<BinaryOperation,StubNode> inExps = new MultiMap<BinaryOperation, StubNode>(); private MultiMap<CreateFunction,InitializeFunctionNode> functions = new MultiMap<CreateFunction, InitializeFunctionNode>(); private MultiMap<GetNextProperty,LoadDynamicNode> getprtys = new MultiMap<GetNextProperty, LoadDynamicNode>(); private Map<Function,ReachingDefinitions> reachingDefs = new HashMap<Function, ReachingDefinitions>(); private Map<Function,PrivateVariables> privateVars = new HashMap<Function, PrivateVariables>(); private Map<EnterWith, StubNode> with = new HashMap<EnterWith, StubNode>(); private MultiMap<Pair<Function,Integer>, OutputPoint> var2outputPoints = new MultiMap<Pair<Function,Integer>, OutputPoint>(); private MultiMap<VariableDefinition, OutputPoint> definitions; private MultiMap<VariableDefinition, InputPoint> uses; @SuppressWarnings("unchecked") private <T> Set<? extends T> lookupProperty(IStatement stm) { return (Set<? extends T>)properties.getView(stm); } @SuppressWarnings("unchecked") private <T> Set<? extends T> lookupInvoke(IStatement stm) { return (Set<? extends T>)invokes.getView(stm); } @SuppressWarnings("unchecked") private <T> Set<? extends T> lookupAlloc(IStatement stm) { return (Set<? extends T>)allocs.getView(stm); } public Set<? extends IPropertyAccessFlowNode> getPropertyAccess(IPropertyAccessStatement stm) { return lookupProperty(stm); } public Set<? extends ILoadFlowNode> getReadProperty(ReadProperty stm) { return lookupProperty(stm); } public Set<? extends IStoreFlowNode> getWriteProperty(WriteProperty stm) { return lookupProperty(stm); } public Set<? extends IInvocationFlowNode> getInvoke(InvokeStatement stm) { return lookupInvoke(stm); } public Set<? extends AllocNode> getNewObject(NewObject stm) { return lookupAlloc(stm); } public Set<? extends IPropertyAccessFlowNode> getWithScopeAccess(IVariableAccessStatement stm) { return lookupProperty(stm); } public Set<? extends StubNode> getInExpObjectArg(BinaryOperation stm) { if (stm.getOperator() != BinaryOperation.Operator.IN) throw new IllegalArgumentException(stm + " is not an IN operation"); return inExps.getView(stm); } public Set<? extends InitializeFunctionNode> getFunctionNodes(CreateFunction stm) { return functions.getView(stm); } public Set<? extends LoadDynamicNode> getGetNextPropertyNodes(GetNextProperty stm) { return getprtys.getView(stm); } public ReachingDefinitions getReachingDefinitions(Function function) { return reachingDefs.get(function); } public PrivateVariables getPrivateVariables(Function function) { return privateVars.get(function); } public Set<? extends IVariableAccessFlowNode> getVariableAccess(IVariableAccessStatement stm) { return variables.getView(stm); } public StubNode getWithNode(EnterWith stm) { return with.get(stm); } public Set<OutputPoint> getVariableOutputPoints(Function func, int var) { return var2outputPoints.getView(Pair.make(func,var)); } @Override public void addReadProperty(ReadProperty stm, LoadNode node) { properties.add(stm, node); } @Override public void addReadProperty(ReadProperty stm, LoadDynamicNode node) { properties.add(stm, node); } @Override public void addWriteProperty(WriteProperty stm, StoreNode node) { properties.add(stm, node); } @Override public void addWriteProperty(WriteProperty stm, StoreDynamicNode node) { properties.add(stm, node); } @Override public void addCall(Call stm, InvokeNode node) { invokes.add(stm, node); } @Override public void addCallProperty(CallProperty stm, LoadAndInvokeNode node) { properties.add(stm, node); invokes.add(stm, node); } @Override public void addCallProperty(CallProperty stm, LoadDynamicNode load, InvokeNode invoke) { properties.add(stm, load); invokes.add(stm, invoke); } @Override public void addCallConstructor(CallConstructor stm, AllocNode alloc, InvokeNode invoke) { invokes.add(stm, invoke); } @Override public void addCallVariable(CallVariable stm, VarReadNode read, InvokeNode invoke) { invokes.add(stm, invoke); variables.add(stm, read); } @Override public void addCallVariable(CallVariable stm, VarReadInterscopeNode read, InvokeNode invoke) { invokes.add(stm, invoke); variables.add(stm, read); } @Override public void addCallVariable(CallVariable stm, VarReadGlobalNode read, InvokeNode invoke) { invokes.add(stm, invoke); variables.add(stm, read); } @Override public void addCallVariable(CallVariable stm, LoadNode load, WithScope withScope, InvokeNode invoke) { invokes.add(stm, invoke); properties.add(stm, load); } @Override public void addCallVariable(CallVariable stm, InvokeNode invoke) { invokes.add(stm, invoke); } @Override public void addReadVariable(ReadVariable stm, VarReadNode node) { variables.add(stm, node); } @Override public void addReadVariable(ReadVariable stm, VarReadInterscopeNode node) { variables.add(stm, node); } @Override public void addReadVariable(ReadVariable stm, VarReadGlobalNode node) { variables.add(stm, node); } @Override public void addReadVariable(ReadVariable stm, LoadNode node, WithScope withScope) { properties.add(stm, node); } @Override public void addWriteVariable(WriteVariable stm, VarWriteNode node) { variables.add(stm, node); } @Override public void addWriteVariable(WriteVariable stm, VarWriteInterscopeNode node) { variables.add(stm, node); } @Override public void addWriteVariable(WriteVariable stm, VarWriteGlobalNode node) { variables.add(stm, node); } @Override public void addWriteVariable(WriteVariable stm, StoreIfPresentNode node, WithScope withScope) { properties.add(stm, node); } @Override public void addNewObject(NewObject stm, AllocNode node) { allocs.add(stm, node); } @Override public void addDeleteProperty(DeleteProperty stm, DeleteNode node) { properties.add(stm, node); } @Override public void addBinaryOperation(BinaryOperation stm, StubNode arg1, StubNode arg2) { switch (stm.getOperator()) { case IN: inExps.add(stm, arg2); break; } } @Override public void addCreateFunction(CreateFunction stm, InitializeFunctionNode node) { functions.add(stm, node); } @Override public void addGetNextProperty(GetNextProperty stm, LoadDynamicNode node) { getprtys.add(stm, node); } @Override public void setReachingDefinitions(Function function, PrivateVariables privateVars, ReachingDefinitions reachingDefs) { this.reachingDefs.put(function, reachingDefs); this.privateVars.put(function, privateVars); } @Override public void addWith(EnterWith stm, StubNode stub) { with.put(stm, stub); } @Override public void addVariableOutputPoint(Function func, int var, OutputPoint op) { var2outputPoints.add(Pair.make(func, var), op); } @Override public void setDefUse(MultiMap<VariableDefinition, OutputPoint> defs, MultiMap<VariableDefinition, InputPoint> uses) { definitions = defs; this.uses = uses; } public MultiMap<VariableDefinition, OutputPoint> getDefinitions() { return definitions; } public MultiMap<VariableDefinition, InputPoint> getUses() { return uses; } }