Skip to content

Commit 6b0061c

Browse files
committed
Merge branch 'saledouble-issue_103_new'
2 parents 25f026c + f58a917 commit 6b0061c

File tree

7 files changed

+270
-112
lines changed

7 files changed

+270
-112
lines changed

edu.cuny.hunter.streamrefactoring.core/src/edu/cuny/hunter/streamrefactoring/core/analysis/StreamStateMachine.java

+114-111
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,6 @@
2222

2323
import org.eclipse.core.runtime.CoreException;
2424
import org.eclipse.core.runtime.NullProgressMonitor;
25-
import org.eclipse.jdt.core.dom.MethodInvocation;
2625

2726
import com.google.common.collect.HashBasedTable;
2827
import com.google.common.collect.Table;
@@ -277,118 +276,122 @@ public void start() throws IOException, CoreException, CallGraphBuilderCancelExc
277276
// get the supergraph for the instance result.
278277
ICFGSupergraph supergraph = instanceResult.getSupergraph();
279278

280-
// FIXME This doesn't make a whole lot of sense. Only looking at
281-
// the node of where the stream was declared: TODO: Can this be
282-
// somehow rewritten to get blocks corresponding to terminal
283-
// operations?
284-
CGNode cgNode = this.getStream().getEnclosingMethodNode();
285-
286-
for (Iterator<CallSiteReference> callSites = cgNode.iterateCallSites(); callSites.hasNext();) {
287-
CallSiteReference callSiteReference = callSites.next();
288-
MethodReference calledMethod = callSiteReference.getDeclaredTarget();
289-
290-
// is it a terminal operation? TODO: Should this be
291-
// cached somehow? Collection of all terminal operation
292-
// invocations?
293-
if (isTerminalOperation(calledMethod)) {
294-
// get the basic block for the call.
295-
ISSABasicBlock[] blocksForCall = cgNode.getIR().getBasicBlocksForCall(callSiteReference);
296-
297-
assert blocksForCall.length == 1 : "Expecting only a single basic block for the call: "
298-
+ callSiteReference;
299-
300-
for (int i = 0; i < blocksForCall.length; i++) {
301-
ISSABasicBlock block = blocksForCall[i];
302-
303-
BasicBlockInContext<IExplodedBasicBlock> blockInContext = getBasicBlockInContextForBlock(
304-
block, cgNode, supergraph)
305-
.orElseThrow(() -> new IllegalStateException(
306-
"No basic block in context for block: " + block));
307-
308-
if (!terminalBlockToPossibleReceivers.containsKey(blockInContext)) {
309-
// associate possible receivers with the
310-
// blockInContext.
311-
// search through each instruction in the
312-
// block.
313-
int processedInstructions = 0;
314-
for (Iterator<SSAInstruction> it = block.iterator(); it.hasNext();) {
315-
SSAInstruction instruction = it.next();
316-
317-
// if it's a phi instruction.
318-
if (instruction instanceof SSAPhiInstruction)
319-
// skip it. The pointer analysis
320-
// below will handle it.
321-
continue;
322-
323-
// Get the possible receivers. This
324-
// number corresponds to the value
325-
// number of the receiver of the method.
326-
int valueNumberForReceiver = instruction.getUse(0);
327-
328-
// it should be represented by a pointer
329-
// key.
330-
PointerKey pointerKey = engine.getHeapGraph().getHeapModel()
331-
.getPointerKeyForLocal(cgNode, valueNumberForReceiver);
332-
333-
// get the points to set for the
334-
// receiver. This will give us all
335-
// object instances that the receiver
336-
// reference points to.
337-
OrdinalSet<InstanceKey> pointsToSet = engine.getPointerAnalysis()
338-
.getPointsToSet(pointerKey);
339-
assert pointsToSet != null : "The points-to set (I think) should not be null for pointer: "
340-
+ pointerKey;
341-
342-
OrdinalSet<InstanceKey> previousReceivers = terminalBlockToPossibleReceivers
343-
.put(blockInContext, pointsToSet);
344-
assert previousReceivers == null : "Reassociating a blockInContext: "
345-
+ blockInContext + " with a new points-to set: " + pointsToSet
346-
+ " that was originally: " + previousReceivers;
347-
348-
++processedInstructions;
279+
// TODO: Can this be somehow rewritten to get blocks
280+
// corresponding to terminal operations?
281+
// for each call graph node in the call graph.
282+
for (CGNode cgNode : engine.getCallGraph()) {
283+
// for each call site in the call graph node.
284+
for (Iterator<CallSiteReference> callSites = cgNode.iterateCallSites(); callSites.hasNext();) {
285+
// get the call site reference.
286+
CallSiteReference callSiteReference = callSites.next();
287+
288+
// get the (declared) called method at the call site.
289+
MethodReference calledMethod = callSiteReference.getDeclaredTarget();
290+
291+
// is it a terminal operation? TODO: Should this be
292+
// cached somehow? Collection of all terminal operation
293+
// invocations?
294+
if (isTerminalOperation(calledMethod)) {
295+
// get the basic block for the call.
296+
297+
ISSABasicBlock[] blocksForCall = cgNode.getIR().getBasicBlocksForCall(callSiteReference);
298+
299+
assert blocksForCall.length == 1 : "Expecting only a single basic block for the call: "
300+
+ callSiteReference;
301+
302+
for (int i = 0; i < blocksForCall.length; i++) {
303+
ISSABasicBlock block = blocksForCall[i];
304+
305+
BasicBlockInContext<IExplodedBasicBlock> blockInContext = getBasicBlockInContextForBlock(
306+
block, cgNode, supergraph)
307+
.orElseThrow(() -> new IllegalStateException(
308+
"No basic block in context for block: " + block));
309+
310+
if (!terminalBlockToPossibleReceivers.containsKey(blockInContext)) {
311+
// associate possible receivers with the
312+
// blockInContext.
313+
// search through each instruction in the
314+
// block.
315+
int processedInstructions = 0;
316+
for (Iterator<SSAInstruction> it = block.iterator(); it.hasNext();) {
317+
SSAInstruction instruction = it.next();
318+
319+
// if it's a phi instruction.
320+
if (instruction instanceof SSAPhiInstruction)
321+
// skip it. The pointer analysis
322+
// below will handle it.
323+
continue;
324+
325+
// Get the possible receivers. This
326+
// number corresponds to the value
327+
// number of the receiver of the method.
328+
int valueNumberForReceiver = instruction.getUse(0);
329+
330+
// it should be represented by a pointer
331+
// key.
332+
PointerKey pointerKey = engine.getHeapGraph().getHeapModel()
333+
.getPointerKeyForLocal(cgNode, valueNumberForReceiver);
334+
335+
// get the points to set for the
336+
// receiver. This will give us all
337+
// object instances that the receiver
338+
// reference points to.
339+
OrdinalSet<InstanceKey> pointsToSet = engine.getPointerAnalysis()
340+
.getPointsToSet(pointerKey);
341+
assert pointsToSet != null : "The points-to set (I think) should not be null for pointer: "
342+
+ pointerKey;
343+
344+
OrdinalSet<InstanceKey> previousReceivers = terminalBlockToPossibleReceivers
345+
.put(blockInContext, pointsToSet);
346+
assert previousReceivers == null : "Reassociating a blockInContext: "
347+
+ blockInContext + " with a new points-to set: " + pointsToSet
348+
+ " that was originally: " + previousReceivers;
349+
350+
++processedInstructions;
351+
}
352+
353+
assert processedInstructions == 1 : "Expecting to process one and only one instruction here.";
349354
}
350355

351-
assert processedInstructions == 1 : "Expecting to process one and only one instruction here.";
352-
}
353-
354-
IntSet intSet = instanceResult.getResult().getResult(blockInContext);
355-
for (IntIterator it = intSet.intIterator(); it.hasNext();) {
356-
int nextInt = it.next();
357-
358-
// retrieve the state set for this instance
359-
// and block.
360-
Map<TypestateRule, Set<IDFAState>> ruleToStates = instanceBlockStateTable
361-
.get(instanceKey, blockInContext);
362-
363-
// if it doesn't yet exist.
364-
if (ruleToStates == null) {
365-
// allocate a new rule map.
366-
ruleToStates = new HashMap<>();
367-
368-
// place it in the table.
369-
instanceBlockStateTable.put(instanceKey, blockInContext, ruleToStates);
370-
}
371-
372-
Set<IDFAState> stateSet = ruleToStates.get(rule);
373-
374-
// if it does not yet exist.
375-
if (stateSet == null) {
376-
// allocate a new set.
377-
stateSet = new HashSet<>();
378-
379-
// place it in the map.
380-
ruleToStates.put(rule, stateSet);
381-
}
382-
383-
// get the facts.
384-
Factoid factoid = instanceResult.getDomain().getMappedObject(nextInt);
385-
if (factoid != DUMMY_ZERO) {
386-
BaseFactoid baseFactoid = (BaseFactoid) factoid;
387-
assert baseFactoid.instance.equals(
388-
instanceKey) : "Sanity check that the fact instance should be the same as the instance being examined.";
389-
390-
// add the encountered state to the set.
391-
stateSet.add(baseFactoid.state);
356+
IntSet intSet = instanceResult.getResult().getResult(blockInContext);
357+
for (IntIterator it = intSet.intIterator(); it.hasNext();) {
358+
int nextInt = it.next();
359+
360+
// retrieve the state set for this instance
361+
// and block.
362+
Map<TypestateRule, Set<IDFAState>> ruleToStates = instanceBlockStateTable
363+
.get(instanceKey, blockInContext);
364+
365+
// if it doesn't yet exist.
366+
if (ruleToStates == null) {
367+
// allocate a new rule map.
368+
ruleToStates = new HashMap<>();
369+
370+
// place it in the table.
371+
instanceBlockStateTable.put(instanceKey, blockInContext, ruleToStates);
372+
}
373+
374+
Set<IDFAState> stateSet = ruleToStates.get(rule);
375+
376+
// if it does not yet exist.
377+
if (stateSet == null) {
378+
// allocate a new set.
379+
stateSet = new HashSet<>();
380+
381+
// place it in the map.
382+
ruleToStates.put(rule, stateSet);
383+
}
384+
385+
// get the facts.
386+
Factoid factoid = instanceResult.getDomain().getMappedObject(nextInt);
387+
if (factoid != DUMMY_ZERO) {
388+
BaseFactoid baseFactoid = (BaseFactoid) factoid;
389+
assert baseFactoid.instance.equals(
390+
instanceKey) : "Sanity check that the fact instance should be the same as the instance being examined.";
391+
392+
// add the encountered state to the set.
393+
stateSet.add(baseFactoid.state);
394+
}
392395
}
393396
}
394397
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
package p;
2+
3+
import java.util.HashSet;
4+
import java.util.stream.*;
5+
6+
import edu.cuny.hunter.streamrefactoring.annotations.*;
7+
8+
class A {
9+
10+
Stream<Object> m() {
11+
Stream<Object> stream = new HashSet<>().stream().distinct();
12+
return stream;
13+
}
14+
15+
@EntryPoint
16+
void n() {
17+
Stream<Object> s = m();
18+
s.count();
19+
}
20+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
package p;
2+
3+
import java.util.HashSet;
4+
import java.util.stream.*;
5+
6+
import edu.cuny.hunter.streamrefactoring.annotations.*;
7+
8+
class A {
9+
10+
Stream<Object> m() {
11+
Stream<Object> stream = new HashSet<>().stream();
12+
return stream;
13+
}
14+
15+
@EntryPoint
16+
void n() {
17+
Stream<Object> s = m();
18+
s.distinct().count();
19+
}
20+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
package p;
2+
3+
import java.util.HashSet;
4+
import java.util.stream.*;
5+
6+
import edu.cuny.hunter.streamrefactoring.annotations.*;
7+
8+
class A {
9+
10+
Stream<Object> m() {
11+
Stream<Object> stream = new HashSet<>().stream().sorted();
12+
return stream;
13+
}
14+
15+
@EntryPoint
16+
void n() {
17+
Stream<Object> s = m();
18+
s.distinct().count();
19+
}
20+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
package p;
2+
3+
import java.util.HashSet;
4+
import java.util.stream.*;
5+
6+
import edu.cuny.hunter.streamrefactoring.annotations.*;
7+
8+
class A {
9+
10+
Stream<Object> m() {
11+
Stream<Object> stream = new HashSet<>().stream().parallel();
12+
return stream;
13+
}
14+
15+
@EntryPoint
16+
void n() {
17+
Stream<Object> s = m();
18+
s.distinct().count();
19+
}
20+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
package p;
2+
3+
import java.util.HashSet;
4+
import java.util.stream.*;
5+
6+
import edu.cuny.hunter.streamrefactoring.annotations.*;
7+
8+
class A {
9+
10+
Stream<Object> m() {
11+
Stream<Object> stream = new HashSet<>().stream().parallel();
12+
return stream;
13+
}
14+
15+
void n(Stream<Object> s) {
16+
s.distinct().count();
17+
}
18+
19+
@EntryPoint
20+
public void main(String[] args) {
21+
n(m());
22+
}
23+
}

0 commit comments

Comments
 (0)