/******************************************************************************* * Copyright (c) 2013 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.alg; import java.util.Iterator; import com.ibm.wala.classLoader.IClass; import com.ibm.wala.classLoader.IField; import com.ibm.wala.classLoader.IMethod; import com.ibm.wala.classLoader.NewSiteReference; import com.ibm.wala.classLoader.ProgramCounter; import com.ibm.wala.ipa.callgraph.CGNode; import com.ibm.wala.ipa.callgraph.ContextKey; import com.ibm.wala.ipa.callgraph.propagation.FilteredPointerKey; import com.ibm.wala.ipa.callgraph.propagation.FilteredPointerKey.TypeFilter; import com.ibm.wala.ipa.callgraph.propagation.HeapModel; import com.ibm.wala.ipa.callgraph.propagation.InstanceKey; import com.ibm.wala.ipa.callgraph.propagation.PointerKey; import com.ibm.wala.ipa.cha.IClassHierarchy; import com.ibm.wala.types.TypeReference; import com.ibm.wala.util.debug.Assertions; /** * a {@link HeapModel} that delegates to another except for pointer keys representing <code>this</code> parameters of methods, for * which it returns a {@link FilteredPointerKey} for the type of the parameter * * @see {@link DemandRefinementPointsTo} * @author manu * */ class ThisFilteringHeapModel implements HeapModel { private final HeapModel delegate; private final IClassHierarchy cha; @Override public IClassHierarchy getClassHierarchy() { return delegate.getClassHierarchy(); } @Override public FilteredPointerKey getFilteredPointerKeyForLocal(CGNode node, int valueNumber, TypeFilter filter) { return delegate.getFilteredPointerKeyForLocal(node, valueNumber, filter); } @Override public InstanceKey getInstanceKeyForAllocation(CGNode node, NewSiteReference allocation) { return delegate.getInstanceKeyForAllocation(node, allocation); } @Override public InstanceKey getInstanceKeyForMetadataObject(Object obj, TypeReference objType) { return delegate.getInstanceKeyForMetadataObject(obj, objType); } @Override public InstanceKey getInstanceKeyForConstant(TypeReference type, Object S) { return delegate.getInstanceKeyForConstant(type, S); } @Override public InstanceKey getInstanceKeyForMultiNewArray(CGNode node, NewSiteReference allocation, int dim) { return delegate.getInstanceKeyForMultiNewArray(node, allocation, dim); } @Override public InstanceKey getInstanceKeyForPEI(CGNode node, ProgramCounter instr, TypeReference type) { return delegate.getInstanceKeyForPEI(node, instr, type); } @Override public PointerKey getPointerKeyForArrayContents(InstanceKey I) { return delegate.getPointerKeyForArrayContents(I); } @Override public PointerKey getPointerKeyForExceptionalReturnValue(CGNode node) { return delegate.getPointerKeyForExceptionalReturnValue(node); } @Override public PointerKey getPointerKeyForInstanceField(InstanceKey I, IField field) { return delegate.getPointerKeyForInstanceField(I, field); } @Override public PointerKey getPointerKeyForLocal(CGNode node, int valueNumber) { if (!node.getMethod().isStatic() && valueNumber == 1) { return delegate.getFilteredPointerKeyForLocal(node, valueNumber, getFilter(node)); } else { return delegate.getPointerKeyForLocal(node, valueNumber); } } private FilteredPointerKey.TypeFilter getFilter(CGNode target) { FilteredPointerKey.TypeFilter filter = (FilteredPointerKey.TypeFilter) target.getContext().get(ContextKey.PARAMETERS[0]); if (filter != null) { return filter; } else { // the context does not select a particular concrete type for the // receiver. IClass C = getReceiverClass(target.getMethod()); return new FilteredPointerKey.SingleClassFilter(C); } } /** * @param method * @return the receiver class for this method. */ private IClass getReceiverClass(IMethod method) { TypeReference formalType = method.getParameterType(0); IClass C = cha.lookupClass(formalType); if (method.isStatic()) { Assertions.UNREACHABLE("asked for receiver of static method " + method); } if (C == null) { Assertions.UNREACHABLE("no class found for " + formalType + " recv of " + method); } return C; } @Override public PointerKey getPointerKeyForReturnValue(CGNode node) { return delegate.getPointerKeyForReturnValue(node); } @Override public PointerKey getPointerKeyForStaticField(IField f) { return delegate.getPointerKeyForStaticField(f); } @Override public Iterator<PointerKey> iteratePointerKeys() { return delegate.iteratePointerKeys(); } public ThisFilteringHeapModel(HeapModel delegate, IClassHierarchy cha) { if (delegate == null) { throw new IllegalArgumentException("delegate null"); } this.delegate = delegate; this.cha = cha; } }