Skip to content

Commit f377aca

Browse files
committed
Merge branch 'issue_103_new' of https://github.com/saledouble/Java-8-Stream-Refactoring into saledouble-issue_103_new
2 parents 25f026c + 6ea3f22 commit f377aca

File tree

7 files changed

+265
-108
lines changed

7 files changed

+265
-108
lines changed

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

Lines changed: 109 additions & 107 deletions
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;
@@ -281,114 +280,117 @@ public void start() throws IOException, CoreException, CallGraphBuilderCancelExc
281280
// the node of where the stream was declared: TODO: Can this be
282281
// somehow rewritten to get blocks corresponding to terminal
283282
// 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;
283+
Iterator<CGNode> cgNodes = this.getStream().getAnalysisEngine().getCallGraph().iterator();
284+
for (;cgNodes.hasNext();) {
285+
CGNode cgNode = cgNodes.next();
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+
296+
ISSABasicBlock[] blocksForCall = cgNode.getIR().getBasicBlocksForCall(callSiteReference);
297+
298+
assert blocksForCall.length == 1 : "Expecting only a single basic block for the call: "
299+
+ callSiteReference;
300+
301+
for (int i = 0; i < blocksForCall.length; i++) {
302+
ISSABasicBlock block = blocksForCall[i];
303+
304+
BasicBlockInContext<IExplodedBasicBlock> blockInContext = getBasicBlockInContextForBlock(
305+
block, cgNode, supergraph)
306+
.orElseThrow(() -> new IllegalStateException(
307+
"No basic block in context for block: " + block));
308+
309+
if (!terminalBlockToPossibleReceivers.containsKey(blockInContext)) {
310+
// associate possible receivers with the
311+
// blockInContext.
312+
// search through each instruction in the
313+
// block.
314+
int processedInstructions = 0;
315+
for (Iterator<SSAInstruction> it = block.iterator(); it.hasNext();) {
316+
SSAInstruction instruction = it.next();
317+
318+
// if it's a phi instruction.
319+
if (instruction instanceof SSAPhiInstruction)
320+
// skip it. The pointer analysis
321+
// below will handle it.
322+
continue;
323+
324+
// Get the possible receivers. This
325+
// number corresponds to the value
326+
// number of the receiver of the method.
327+
int valueNumberForReceiver = instruction.getUse(0);
328+
329+
// it should be represented by a pointer
330+
// key.
331+
PointerKey pointerKey = engine.getHeapGraph().getHeapModel()
332+
.getPointerKeyForLocal(cgNode, valueNumberForReceiver);
333+
334+
// get the points to set for the
335+
// receiver. This will give us all
336+
// object instances that the receiver
337+
// reference points to.
338+
OrdinalSet<InstanceKey> pointsToSet = engine.getPointerAnalysis()
339+
.getPointsToSet(pointerKey);
340+
assert pointsToSet != null : "The points-to set (I think) should not be null for pointer: "
341+
+ pointerKey;
342+
343+
OrdinalSet<InstanceKey> previousReceivers = terminalBlockToPossibleReceivers
344+
.put(blockInContext, pointsToSet);
345+
assert previousReceivers == null : "Reassociating a blockInContext: "
346+
+ blockInContext + " with a new points-to set: " + pointsToSet
347+
+ " that was originally: " + previousReceivers;
348+
349+
++processedInstructions;
350+
}
351+
352+
assert processedInstructions == 1 : "Expecting to process one and only one instruction here.";
349353
}
350354

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);
355+
IntSet intSet = instanceResult.getResult().getResult(blockInContext);
356+
for (IntIterator it = intSet.intIterator(); it.hasNext();) {
357+
int nextInt = it.next();
358+
359+
// retrieve the state set for this instance
360+
// and block.
361+
Map<TypestateRule, Set<IDFAState>> ruleToStates = instanceBlockStateTable
362+
.get(instanceKey, blockInContext);
363+
364+
// if it doesn't yet exist.
365+
if (ruleToStates == null) {
366+
// allocate a new rule map.
367+
ruleToStates = new HashMap<>();
368+
369+
// place it in the table.
370+
instanceBlockStateTable.put(instanceKey, blockInContext, ruleToStates);
371+
}
372+
373+
Set<IDFAState> stateSet = ruleToStates.get(rule);
374+
375+
// if it does not yet exist.
376+
if (stateSet == null) {
377+
// allocate a new set.
378+
stateSet = new HashSet<>();
379+
380+
// place it in the map.
381+
ruleToStates.put(rule, stateSet);
382+
}
383+
384+
// get the facts.
385+
Factoid factoid = instanceResult.getDomain().getMappedObject(nextInt);
386+
if (factoid != DUMMY_ZERO) {
387+
BaseFactoid baseFactoid = (BaseFactoid) factoid;
388+
assert baseFactoid.instance.equals(
389+
instanceKey) : "Sanity check that the fact instance should be the same as the instance being examined.";
390+
391+
// add the encountered state to the set.
392+
stateSet.add(baseFactoid.state);
393+
}
392394
}
393395
}
394396
}
Lines changed: 20 additions & 0 deletions
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+
}
Lines changed: 20 additions & 0 deletions
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+
}
Lines changed: 20 additions & 0 deletions
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+
}
Lines changed: 20 additions & 0 deletions
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+
}
Lines changed: 23 additions & 0 deletions
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)