|
43 | 43 | import com.ibm.wala.util.collections.HashMapFactory;
|
44 | 44 | import com.ibm.wala.util.collections.Pair;
|
45 | 45 | import com.ibm.wala.util.intset.OrdinalSet;
|
| 46 | +import java.util.HashSet; |
46 | 47 | import java.util.Map;
|
| 48 | +import java.util.Set; |
47 | 49 | import java.util.logging.Logger;
|
48 | 50 |
|
49 | 51 | public class PythonInstanceMethodTrampolineTargetSelector<T>
|
@@ -87,6 +89,8 @@ protected boolean shouldProcess(CGNode caller, CallSiteReference site, IClass re
|
87 | 89 |
|
88 | 90 | @Override
|
89 | 91 | public IMethod getCalleeTarget(CGNode caller, CallSiteReference site, IClass receiver) {
|
| 92 | + // TODO: Callable detection may need to be moved. See https://github.com/wala/ML/issues/207. If |
| 93 | + // it stays here, we should further document the receiver swapping process. |
90 | 94 | if (isCallable(receiver)) {
|
91 | 95 | LOGGER.fine("Encountered callable.");
|
92 | 96 |
|
@@ -223,6 +227,9 @@ private IClass getCallable(CGNode caller, IClassHierarchy cha, PythonInvokeInstr
|
223 | 227 | PointerKey receiver = pkf.getPointerKeyForLocal(caller, call.getUse(0));
|
224 | 228 | OrdinalSet<InstanceKey> objs = builder.getPointerAnalysis().getPointsToSet(receiver);
|
225 | 229 |
|
| 230 | + // The set of potential callables to be returned. |
| 231 | + Set<IClass> callableSet = new HashSet<>(); |
| 232 | + |
226 | 233 | for (InstanceKey o : objs) {
|
227 | 234 | AllocationSiteInNode instanceKey = getAllocationSiteInNode(o);
|
228 | 235 | if (instanceKey != null) {
|
@@ -254,10 +261,22 @@ private IClass getCallable(CGNode caller, IClassHierarchy cha, PythonInvokeInstr
|
254 | 261 | LOGGER.info("Applying callable workaround for https://github.com/wala/ML/issues/118.");
|
255 | 262 | }
|
256 | 263 |
|
257 |
| - if (callable != null) return callable; |
| 264 | + callableSet.add(callable); |
258 | 265 | }
|
259 | 266 | }
|
260 | 267 |
|
| 268 | + // if there's only one possible option. |
| 269 | + if (callableSet.size() == 1) { |
| 270 | + IClass callable = callableSet.iterator().next(); |
| 271 | + assert callable != null : "Callable should be non-null."; |
| 272 | + return callable; |
| 273 | + } |
| 274 | + |
| 275 | + // if we have multiple candidates. |
| 276 | + if (callableSet.size() > 1) |
| 277 | + // we cannot accurately select one. |
| 278 | + LOGGER.warning("Multiple (" + callableSet.size() + ") callable targets found."); |
| 279 | + |
261 | 280 | return null;
|
262 | 281 | }
|
263 | 282 |
|
|
0 commit comments