use of org.checkerframework.checker.interning.qual.FindDistinct in project checker-framework by typetools.
the class ForwardAnalysisImpl method runAnalysisFor.
@Override
public S runAnalysisFor(@FindDistinct Node node, Analysis.BeforeOrAfter preOrPost, TransferInput<V, S> blockTransferInput, IdentityHashMap<Node, V> nodeValues, Map<TransferInput<V, S>, IdentityHashMap<Node, TransferResult<V, S>>> analysisCaches) {
Block block = node.getBlock();
assert block != null : "@AssumeAssertion(nullness): invariant";
Node oldCurrentNode = currentNode;
// Prepare cache
IdentityHashMap<Node, TransferResult<V, S>> cache;
if (analysisCaches != null) {
cache = analysisCaches.computeIfAbsent(blockTransferInput, __ -> new IdentityHashMap<>());
} else {
cache = null;
}
if (isRunning) {
assert currentInput != null : "@AssumeAssertion(nullness): invariant";
return currentInput.getRegularStore();
}
setNodeValues(nodeValues);
isRunning = true;
try {
switch(block.getType()) {
case REGULAR_BLOCK:
{
RegularBlock rb = (RegularBlock) block;
// Apply transfer function to contents until we found the node we are looking for.
TransferInput<V, S> store = blockTransferInput;
TransferResult<V, S> transferResult;
for (Node n : rb.getNodes()) {
setCurrentNode(n);
if (n == node && preOrPost == Analysis.BeforeOrAfter.BEFORE) {
return store.getRegularStore();
}
if (cache != null && cache.containsKey(n)) {
transferResult = cache.get(n);
} else {
// Copy the store to avoid changing other blocks' transfer inputs in {@link #inputs}
transferResult = callTransferFunction(n, store.copy());
if (cache != null) {
cache.put(n, transferResult);
}
}
if (n == node) {
return transferResult.getRegularStore();
}
store = new TransferInput<>(n, this, transferResult);
}
throw new BugInCF("node %s is not in node.getBlock()=%s", node, block);
}
case EXCEPTION_BLOCK:
{
ExceptionBlock eb = (ExceptionBlock) block;
// Apply the transfer function to content
if (eb.getNode() != node) {
throw new BugInCF("Node should be equal to eb.getNode(). But get: node: " + node + "\teb.getNode(): " + eb.getNode());
}
if (preOrPost == Analysis.BeforeOrAfter.BEFORE) {
return blockTransferInput.getRegularStore();
}
setCurrentNode(node);
// Copy the store to avoid changing other blocks' transfer inputs in {@link #inputs}
TransferResult<V, S> transferResult;
if (cache != null && cache.containsKey(node)) {
transferResult = cache.get(node);
} else {
// Copy the store to avoid changing other blocks' transfer inputs in {@link #inputs}
transferResult = callTransferFunction(node, blockTransferInput.copy());
if (cache != null) {
cache.put(node, transferResult);
}
}
return transferResult.getRegularStore();
}
default:
// Only regular blocks and exceptional blocks can hold nodes.
throw new BugInCF("Unexpected block type: " + block.getType());
}
} finally {
setCurrentNode(oldCurrentNode);
isRunning = false;
}
}
Aggregations