/* * This is a prototype implementation of the concept of Feature-Sen * sitive Dataflow Analysis. More details in the AOSD'12 paper: * Dataflow Analysis for Software Product Lines * * This 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 software 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 software; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA, or see the FSF site: http://www.fsf.org. */ package br.ufal.cideei.soot.analyses; import java.util.Collection; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Set; import java.util.Map.Entry; import org.apache.commons.lang.builder.EqualsBuilder; import org.apache.commons.lang.builder.HashCodeBuilder; import soot.toolkits.scalar.AbstractFlowSet; import soot.toolkits.scalar.ArraySparseSet; import soot.toolkits.scalar.FlowSet; import br.ufal.cideei.soot.instrument.IConfigRep; import br.ufal.cideei.soot.instrument.ILazyConfigRep; import br.ufal.cideei.soot.instrument.bitrep.BitVectorConfigRep; public class MapLiftedFlowSet extends AbstractFlowSet { protected HashMap<IConfigRep, FlowSet> map; public HashMap<IConfigRep, FlowSet> getMapping() { return map; } protected MapLiftedFlowSet(Map<IConfigRep, FlowSet> map) { this.map = new HashMap<IConfigRep, FlowSet>(map); } public MapLiftedFlowSet(Collection<IConfigRep> configs) { map = new HashMap<IConfigRep, FlowSet>(); for (IConfigRep config : configs) { map.put(config, new ArraySparseSet()); } } public MapLiftedFlowSet(IConfigRep seed) { map = new HashMap<IConfigRep, FlowSet>(); map.put(seed, new ArraySparseSet()); } public FlowSet getLattice(IConfigRep config) { return this.map.get(config); } @Override public MapLiftedFlowSet clone() { Set<Entry<IConfigRep, FlowSet>> entrySet = map.entrySet(); Map<IConfigRep, FlowSet> newMap = new HashMap<IConfigRep, FlowSet>(); for (Entry<IConfigRep, FlowSet> entry : entrySet) { newMap.put(entry.getKey(), entry.getValue().clone()); } return new MapLiftedFlowSet(newMap); } @Override public void copy(FlowSet dest) { MapLiftedFlowSet destLifted = (MapLiftedFlowSet) dest; dest.clear(); Set<Entry<IConfigRep, FlowSet>> entrySet = map.entrySet(); for (Entry<IConfigRep, FlowSet> entry : entrySet) { IConfigRep key = entry.getKey(); FlowSet value = entry.getValue(); destLifted.map.put(key, value.clone()); } } public Set<IConfigRep> getConfigurations() { return map.keySet(); } @Override public boolean equals(Object o) { if (o == null) return false; if (this == o) return true; if (!(o instanceof MapLiftedFlowSet)) return false; MapLiftedFlowSet that = (MapLiftedFlowSet) o; return new EqualsBuilder().append(this.map, that.map).isEquals(); } @Override public int hashCode() { return new HashCodeBuilder(17, 31).append(this.map).toHashCode(); } @Override public void clear() { map.clear(); } @Override public void union(FlowSet aOther, FlowSet aDest) { // #ifdef LAZY //@ MapLiftedFlowSet other = (MapLiftedFlowSet) aOther; //@ MapLiftedFlowSet dest = (MapLiftedFlowSet) aDest; //@ //@ Set<Entry<IConfigRep, FlowSet>> entrySet = this.map.entrySet(); //@ Set<Entry<IConfigRep, FlowSet>> otherEntrySet = other.map.entrySet(); //@ //@ HashMap<IConfigRep, FlowSet> destMap = new HashMap<IConfigRep, FlowSet>(); //@ //@ for (Entry<IConfigRep, FlowSet> entry : entrySet) { //@ for (Entry<IConfigRep, FlowSet> otherEntry : otherEntrySet) { //@ ILazyConfigRep key = (ILazyConfigRep) entry.getKey(); //@ ILazyConfigRep otherKey = (ILazyConfigRep) otherEntry.getKey(); //@ //@ ILazyConfigRep intersection = key.intersection(otherKey); //@ if (intersection.size() != 0) { //@ FlowSet otherFlowSet = otherEntry.getValue(); //@ ArraySparseSet destFlowSet = new ArraySparseSet(); //@ entry.getValue().union(otherFlowSet, destFlowSet); //@ destMap.put(intersection, destFlowSet); //@ } //@ } //@ } //@ //@ dest.map = destMap; //@ // #else MapLiftedFlowSet otherLifted = (MapLiftedFlowSet) aOther; MapLiftedFlowSet destLifted = (MapLiftedFlowSet) aDest; Set<Entry<IConfigRep, FlowSet>> entrySet = map.entrySet(); for (Entry<IConfigRep, FlowSet> entry : entrySet) { // key IConfigRep config = entry.getKey(); // val FlowSet thisNormal = entry.getValue(); FlowSet otherNormal = otherLifted.map.get(config); if (otherNormal == null) { otherNormal = new ArraySparseSet(); } ArraySparseSet destNewFlowSet = new ArraySparseSet(); destLifted.map.put(config, destNewFlowSet); thisNormal.union(otherNormal, destNewFlowSet); } // #endif } @Override public void intersection(FlowSet aOther, FlowSet aDest) { // #ifdef LAZY //@ MapLiftedFlowSet other = (MapLiftedFlowSet) aOther; //@ MapLiftedFlowSet dest = (MapLiftedFlowSet) aDest; //@ //@ Set<Entry<IConfigRep, FlowSet>> entrySet = this.map.entrySet(); //@ Set<Entry<IConfigRep, FlowSet>> otherEntrySet = other.map.entrySet(); //@ //@ HashMap<IConfigRep, FlowSet> destMap = new HashMap<IConfigRep, FlowSet>(); //@ //@ for (Entry<IConfigRep, FlowSet> entry : entrySet) { //@ for (Entry<IConfigRep, FlowSet> otherEntry : otherEntrySet) { //@ ILazyConfigRep key = (ILazyConfigRep) entry.getKey(); //@ ILazyConfigRep otherKey = (ILazyConfigRep) otherEntry.getKey(); //@ //@ ILazyConfigRep intersection = key.intersection(otherKey); //@ if (intersection.size() != 0) { //@ FlowSet otherFlowSet = otherEntry.getValue(); //@ ArraySparseSet destFlowSet = new ArraySparseSet(); //@ entry.getValue().intersection(otherFlowSet, destFlowSet); //@ destMap.put(intersection, destFlowSet); //@ } //@ } //@ } //@ //@ dest.map = destMap; //@ // #else MapLiftedFlowSet otherLifted = (MapLiftedFlowSet) aOther; MapLiftedFlowSet destLifted = (MapLiftedFlowSet) aDest; Set<Entry<IConfigRep, FlowSet>> entrySet = map.entrySet(); for (Entry<IConfigRep, FlowSet> entry : entrySet) { // key IConfigRep config = entry.getKey(); // val FlowSet thisNormal = entry.getValue(); FlowSet otherNormal = otherLifted.map.get(config); if (otherNormal == null) { otherNormal = new ArraySparseSet(); } ArraySparseSet destNewFlowSet = new ArraySparseSet(); destLifted.map.put(config, destNewFlowSet); thisNormal.intersection(otherNormal, destNewFlowSet); } // #endif } public FlowSet add(IConfigRep config, FlowSet flow) { return map.put(config, flow); } @Override public void add(Object arg0) { throw new UnsupportedOperationException(); } @Override public boolean contains(Object arg0) { throw new UnsupportedOperationException(); } @Override public boolean isEmpty() { throw new UnsupportedOperationException(); } @Override public void remove(Object arg0) { throw new UnsupportedOperationException(); } @Override public int size() { return this.map.size(); } @Override public List toList() { throw new UnsupportedOperationException(); } @Override public String toString() { return map.toString(); } }