161 lines
5.6 KiB
Java
161 lines
5.6 KiB
Java
/*******************************************************************************
|
|
* Copyright (c) 2002 - 2008 IBM Corporation.
|
|
* All rights reserved. This program and the accompanying materials
|
|
* are made available under the terms of the Eclipse Public License v1.0
|
|
* which accompanies this distribution, and is available at
|
|
* http://www.eclipse.org/legal/epl-v10.html
|
|
*
|
|
* Contributors:
|
|
* IBM Corporation - initial API and implementation
|
|
*******************************************************************************/
|
|
|
|
package com.ibm.wala.demandpa.util;
|
|
|
|
import java.util.ArrayList;
|
|
import java.util.Collection;
|
|
import java.util.Map;
|
|
import java.util.Set;
|
|
|
|
import com.ibm.wala.classLoader.IField;
|
|
import com.ibm.wala.ipa.callgraph.CallGraph;
|
|
import com.ibm.wala.ipa.callgraph.propagation.HeapModel;
|
|
import com.ibm.wala.ipa.callgraph.propagation.InstanceKey;
|
|
import com.ibm.wala.ipa.callgraph.propagation.PointerAnalysis;
|
|
import com.ibm.wala.ipa.callgraph.propagation.PointerKey;
|
|
import com.ibm.wala.ipa.modref.ModRef;
|
|
import com.ibm.wala.ipa.slicer.NormalStatement;
|
|
import com.ibm.wala.ipa.slicer.SDG;
|
|
import com.ibm.wala.ipa.slicer.Slicer.ControlDependenceOptions;
|
|
import com.ibm.wala.ipa.slicer.Slicer.DataDependenceOptions;
|
|
import com.ibm.wala.ipa.slicer.Statement;
|
|
import com.ibm.wala.ipa.slicer.thin.CISlicer;
|
|
import com.ibm.wala.util.collections.MapUtil;
|
|
import com.ibm.wala.util.debug.Assertions;
|
|
|
|
/**
|
|
* A {@link MemoryAccessMap} that makes use of a pre-computed
|
|
* {@link PointerAnalysis} to reduce the number of considered accesses.
|
|
*
|
|
* @author manu
|
|
*
|
|
*/
|
|
public class PABasedMemoryAccessMap implements MemoryAccessMap {
|
|
|
|
private static final boolean DEBUG = false;
|
|
|
|
private final PointerAnalysis<InstanceKey> pa;
|
|
|
|
private final HeapModel heapModel;
|
|
|
|
private final Map<PointerKey, Set<Statement>> invMod;
|
|
|
|
private final Map<PointerKey, Set<Statement>> invRef;
|
|
|
|
public PABasedMemoryAccessMap(CallGraph cg, PointerAnalysis<InstanceKey> pa) {
|
|
this(cg, pa, new SDG<InstanceKey>(cg, pa, DataDependenceOptions.NO_BASE_NO_HEAP_NO_EXCEPTIONS, ControlDependenceOptions.NONE));
|
|
}
|
|
|
|
public PABasedMemoryAccessMap(CallGraph cg, PointerAnalysis<InstanceKey> pa, SDG<InstanceKey> sdg) {
|
|
this(cg, pa, CISlicer.scanForMod(sdg, pa, true, ModRef.make()), CISlicer.scanForRef(sdg, pa));
|
|
}
|
|
|
|
public PABasedMemoryAccessMap(CallGraph cg, PointerAnalysis<InstanceKey> pa, Map<Statement, Set<PointerKey>> mod,
|
|
Map<Statement, Set<PointerKey>> ref) {
|
|
if (pa == null) {
|
|
throw new IllegalArgumentException("null pa");
|
|
}
|
|
this.pa = pa;
|
|
this.heapModel = pa.getHeapModel();
|
|
invMod = MapUtil.inverseMap(mod);
|
|
invRef = MapUtil.inverseMap(ref);
|
|
}
|
|
|
|
@Override
|
|
public Collection<MemoryAccess> getArrayReads(PointerKey arrayRef) {
|
|
Collection<MemoryAccess> memAccesses = new ArrayList<MemoryAccess>();
|
|
if (DEBUG) {
|
|
System.err.println(("looking at reads of array ref " + arrayRef));
|
|
}
|
|
for (InstanceKey ik : pa.getPointsToSet(arrayRef)) {
|
|
PointerKey ack = heapModel.getPointerKeyForArrayContents(ik);
|
|
convertStmtsToMemoryAccess(invRef.get(ack), memAccesses);
|
|
}
|
|
return memAccesses;
|
|
}
|
|
|
|
@Override
|
|
public Collection<MemoryAccess> getArrayWrites(PointerKey arrayRef) {
|
|
Collection<MemoryAccess> memAccesses = new ArrayList<MemoryAccess>();
|
|
if (DEBUG) {
|
|
System.err.println(("looking at writes to array ref " + arrayRef));
|
|
}
|
|
for (InstanceKey ik : pa.getPointsToSet(arrayRef)) {
|
|
if (DEBUG) {
|
|
System.err.println(("instance key " + ik + " class " + ik.getClass()));
|
|
}
|
|
PointerKey ack = heapModel.getPointerKeyForArrayContents(ik);
|
|
convertStmtsToMemoryAccess(invMod.get(ack), memAccesses);
|
|
}
|
|
return memAccesses;
|
|
}
|
|
|
|
@Override
|
|
public Collection<MemoryAccess> getFieldReads(PointerKey baseRef, IField field) {
|
|
Collection<MemoryAccess> memAccesses = new ArrayList<MemoryAccess>();
|
|
for (InstanceKey ik : pa.getPointsToSet(baseRef)) {
|
|
PointerKey ifk = heapModel.getPointerKeyForInstanceField(ik, field);
|
|
convertStmtsToMemoryAccess(invRef.get(ifk), memAccesses);
|
|
}
|
|
return memAccesses;
|
|
}
|
|
|
|
@Override
|
|
public Collection<MemoryAccess> getFieldWrites(PointerKey baseRef, IField field) {
|
|
Collection<MemoryAccess> memAccesses = new ArrayList<MemoryAccess>();
|
|
for (InstanceKey ik : pa.getPointsToSet(baseRef)) {
|
|
PointerKey ifk = heapModel.getPointerKeyForInstanceField(ik, field);
|
|
convertStmtsToMemoryAccess(invMod.get(ifk), memAccesses);
|
|
}
|
|
return memAccesses;
|
|
}
|
|
|
|
@Override
|
|
public Collection<MemoryAccess> getStaticFieldReads(IField field) {
|
|
Collection<MemoryAccess> result = new ArrayList<MemoryAccess>();
|
|
convertStmtsToMemoryAccess(invRef.get(heapModel.getPointerKeyForStaticField(field)), result);
|
|
return result;
|
|
}
|
|
|
|
@Override
|
|
public Collection<MemoryAccess> getStaticFieldWrites(IField field) {
|
|
Collection<MemoryAccess> result = new ArrayList<MemoryAccess>();
|
|
convertStmtsToMemoryAccess(invMod.get(heapModel.getPointerKeyForStaticField(field)), result);
|
|
return result;
|
|
}
|
|
|
|
private static void convertStmtsToMemoryAccess(Collection<Statement> stmts, Collection<MemoryAccess> result) {
|
|
if (stmts == null) {
|
|
return;
|
|
}
|
|
if (DEBUG) {
|
|
System.err.println(("statements: " + stmts));
|
|
}
|
|
for (Statement s : stmts) {
|
|
switch (s.getKind()) {
|
|
case NORMAL:
|
|
NormalStatement normStmt = (NormalStatement) s;
|
|
result.add(new MemoryAccess(normStmt.getInstructionIndex(), normStmt.getNode()));
|
|
break;
|
|
default:
|
|
Assertions.UNREACHABLE();
|
|
}
|
|
}
|
|
}
|
|
|
|
@Override
|
|
public HeapModel getHeapModel() {
|
|
return heapModel;
|
|
}
|
|
|
|
}
|