Skip to content

Commit bb7adad

Browse files
committed
Fix #188.
1 parent 6577885 commit bb7adad

File tree

3 files changed

+126
-119
lines changed

3 files changed

+126
-119
lines changed

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

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -362,20 +362,20 @@ private IR getEnclosingMethodIR(EclipseProjectAnalysisEngine<InstanceKey> engine
362362
}
363363

364364
/**
365-
* @return The {@link CGNode} representing the enclosing method of this stream.
365+
* @return The {@link CGNode}s representing the enclosing method of this stream.
366366
* @throws NoEnclosingMethodNodeFoundException
367367
* If the call graph doesn't contain a node for the enclosing
368368
* method.
369369
*/
370-
protected CGNode getEnclosingMethodNode(EclipseProjectAnalysisEngine<InstanceKey> engine)
370+
protected Collection<CGNode> getEnclosingMethodNodes(EclipseProjectAnalysisEngine<InstanceKey> engine)
371371
throws IOException, CoreException, NoEnclosingMethodNodeFoundException {
372372
MethodReference methodReference = this.getEnclosingMethodReference();
373373
Set<CGNode> nodes = engine.getCallGraph().getNodes(methodReference);
374374

375375
if (nodes.isEmpty())
376376
throw new NoEnclosingMethodNodeFoundException(methodReference);
377377
else
378-
return nodes.iterator().next(); // just return the first.
378+
return nodes;
379379
}
380380

381381
MethodReference getEnclosingMethodReference() {
@@ -622,12 +622,12 @@ private void inferInitialOrdering(EclipseProjectAnalysisEngine<InstanceKey> engi
622622
throw new UnhandledCaseException("Encountered unhandled case, most likely an embedded stream.");
623623
}
624624

625-
// get the enclosing method node.
626-
CGNode node = null;
625+
// get the enclosing method nodes.
626+
Collection<CGNode> nodeCollection = null;
627627
try {
628-
node = this.getEnclosingMethodNode(engine);
628+
nodeCollection = this.getEnclosingMethodNodes(engine);
629629
} catch (NoEnclosingMethodNodeFoundException e) {
630-
LOGGER.log(Level.WARNING, "Can't find enclosing method node for " + this.getCreation()
630+
LOGGER.log(Level.WARNING, "Can't find enclosing method nodes for " + this.getCreation()
631631
+ ". Falling back to: " + Ordering.ORDERED + ".", e);
632632
this.setInitialOrdering(Ordering.ORDERED);
633633
return;
@@ -638,7 +638,8 @@ private void inferInitialOrdering(EclipseProjectAnalysisEngine<InstanceKey> engi
638638
IMethod calledMethod = null;
639639
Ordering ordering = null;
640640
try {
641-
possibleTypes = getPossibleTypesInterprocedurally(node, valueNumber, engine, orderingInference);
641+
possibleTypes = getPossibleTypesInterprocedurally(nodeCollection, valueNumber, engine,
642+
orderingInference);
642643

643644
// Possible types: check each one.
644645
calledMethod = (IMethod) calledMethodBinding.getJavaElement();

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -590,8 +590,8 @@ private void discoverIfReduceOrderingPossiblyMatters(EclipseProjectAnalysisEngin
590590
if (numOfRetVals > 0) {
591591
int returnValue = invokeInstruction.getReturnValue(0);
592592

593-
possibleReturnTypes = Util.getPossibleTypesInterprocedurally(block.getNode(), returnValue, engine,
594-
orderingInference);
593+
possibleReturnTypes = Util.getPossibleTypesInterprocedurally(Collections.singleton(block.getNode()),
594+
returnValue, engine, orderingInference);
595595

596596
LOGGER.fine("Possible reduce types are: " + possibleReturnTypes);
597597
} else

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

Lines changed: 115 additions & 109 deletions
Original file line numberDiff line numberDiff line change
@@ -431,124 +431,130 @@ static Collection<TypeAbstraction> getPossibleTypes(int valueNumber, TypeInferen
431431
return ret;
432432
}
433433

434-
public static Collection<TypeAbstraction> getPossibleTypesInterprocedurally(CGNode node, int valueNumber,
435-
EclipseProjectAnalysisEngine<InstanceKey> engine, OrderingInference orderingInference)
434+
public static Collection<TypeAbstraction> getPossibleTypesInterprocedurally(Collection<CGNode> nodeCollection,
435+
int valueNumber, EclipseProjectAnalysisEngine<InstanceKey> engine, OrderingInference orderingInference)
436436
throws NoniterableException, NoninstantiableException, CannotExtractSpliteratorException,
437437
UTFDataFormatException, JavaModelException {
438438
Collection<TypeAbstraction> ret = new HashSet<>();
439439

440-
PointerKey valueKey = engine.getHeapGraph().getHeapModel().getPointerKeyForLocal(node, valueNumber);
441-
LOGGER.fine(() -> "Value pointer key is: " + valueKey);
442-
443-
OrdinalSet<InstanceKey> pointsToSet = engine.getPointerAnalysis().getPointsToSet(valueKey);
444-
assert pointsToSet != null;
445-
LOGGER.fine(() -> "PointsTo set is: " + pointsToSet);
446-
447-
for (InstanceKey instanceKey : pointsToSet) {
448-
IClass concreteClass = instanceKey.getConcreteType();
449-
450-
if (!(concreteClass instanceof SyntheticClass)) {
451-
LOGGER.fine(() -> "Found non-synthetic concrete type: " + concreteClass);
452-
453-
// Workaround #38, problem seemingly with generics.
454-
// Due to type erasure, we may have the problem if the return
455-
// type is java.lang.Object.
456-
// Find the return type of the instruction.
457-
TypeInference inference = TypeInference.make(node.getIR(), false);
458-
Collection<TypeAbstraction> returnTypes = Util.getPossibleTypes(valueNumber, inference);
459-
460-
// for each return type.
461-
for (TypeAbstraction rType : returnTypes) {
462-
PointType concreteType = new PointType(concreteClass);
463-
464-
if (rType.getType().getReference().equals(TypeReference.JavaLangObject)) {
465-
IR ir = node.getIR();
466-
IMethod method = ir.getMethod();
467-
IBytecodeMethod bytecodeMethod = (IBytecodeMethod) method;
468-
469-
// get the definition instruction.
470-
SSAInvokeInstruction def = (SSAInvokeInstruction) node.getDU().getDef(valueNumber);
471-
472-
// which index is it into the instruction array?
473-
int instructionIndex = Util.indexOf(ir.getInstructions(), def);
474-
475-
// get the bytecode index.
476-
int bytecodeIndex;
477-
try {
478-
bytecodeIndex = bytecodeMethod.getBytecodeIndex(instructionIndex);
479-
} catch (InvalidClassFileException e) {
480-
throw new IllegalArgumentException(
481-
"Value number: " + valueNumber + " does not have a definition (" + instructionIndex
482-
+ ") corresponding to a bytecode index.",
483-
e);
484-
}
440+
// for each call graph node.
441+
for (CGNode node : nodeCollection) {
442+
// get the pointer key.
443+
PointerKey valueKey = engine.getHeapGraph().getHeapModel().getPointerKeyForLocal(node, valueNumber);
444+
LOGGER.fine(() -> "Value pointer key is: " + valueKey);
445+
446+
OrdinalSet<InstanceKey> pointsToSet = engine.getPointerAnalysis().getPointsToSet(valueKey);
447+
assert pointsToSet != null;
448+
LOGGER.fine(() -> "PointsTo set is: " + pointsToSet);
449+
450+
for (InstanceKey instanceKey : pointsToSet) {
451+
IClass concreteClass = instanceKey.getConcreteType();
452+
453+
if (!(concreteClass instanceof SyntheticClass)) {
454+
LOGGER.fine(() -> "Found non-synthetic concrete type: " + concreteClass);
455+
456+
// Workaround #38, problem seemingly with generics.
457+
// Due to type erasure, we may have the problem if the return
458+
// type is java.lang.Object.
459+
// Find the return type of the instruction.
460+
TypeInference inference = TypeInference.make(node.getIR(), false);
461+
Collection<TypeAbstraction> returnTypes = Util.getPossibleTypes(valueNumber, inference);
462+
463+
// for each return type.
464+
for (TypeAbstraction rType : returnTypes) {
465+
PointType concreteType = new PointType(concreteClass);
466+
467+
if (rType.getType().getReference().equals(TypeReference.JavaLangObject)) {
468+
IR ir = node.getIR();
469+
IMethod method = ir.getMethod();
470+
IBytecodeMethod bytecodeMethod = (IBytecodeMethod) method;
471+
472+
// get the definition instruction.
473+
SSAInvokeInstruction def = (SSAInvokeInstruction) node.getDU().getDef(valueNumber);
474+
475+
// which index is it into the instruction array?
476+
int instructionIndex = Util.indexOf(ir.getInstructions(), def);
477+
478+
// get the bytecode index.
479+
int bytecodeIndex;
480+
try {
481+
bytecodeIndex = bytecodeMethod.getBytecodeIndex(instructionIndex);
482+
} catch (InvalidClassFileException e) {
483+
throw new IllegalArgumentException(
484+
"Value number: " + valueNumber + " does not have a definition ("
485+
+ instructionIndex + ") corresponding to a bytecode index.",
486+
e);
487+
}
485488

486-
// get the source information
487-
SourcePosition sourcePosition;
488-
try {
489-
sourcePosition = method.getSourcePosition(bytecodeIndex);
490-
} catch (InvalidClassFileException e) {
491-
throw new IllegalArgumentException(
492-
"Value number: " + valueNumber + " does not have bytecode index (" + bytecodeIndex
493-
+ ") corresponding to a bytecode index.",
494-
e);
495-
}
489+
// get the source information
490+
SourcePosition sourcePosition;
491+
try {
492+
sourcePosition = method.getSourcePosition(bytecodeIndex);
493+
} catch (InvalidClassFileException e) {
494+
throw new IllegalArgumentException(
495+
"Value number: " + valueNumber + " does not have bytecode index ("
496+
+ bytecodeIndex + ") corresponding to a bytecode index.",
497+
e);
498+
}
496499

497-
// let's assume that the source file is in the same project.
498-
IJavaProject enclosingProject = engine.getProject();
499-
500-
String fqn = method.getDeclaringClass().getName().getPackage().toUnicodeString() + "."
501-
+ method.getDeclaringClass().getName().getClassName().toUnicodeString();
502-
IType type = enclosingProject.findType(fqn.replace('/', '.'));
503-
// FIXME: Need to (i) exclude from result timer and (ii) use the cache in
504-
// ConvertToParallelStreamRefactoringProcessor #141.
505-
CompilationUnit unit = RefactoringASTParser.parseWithASTProvider(type.getTypeRoot(), true,
506-
null);
507-
508-
// We have the CompilationUnit corresponding to the instruction's file. Can we
509-
// correlate the instruction to the method invocation in the AST?
510-
MethodInvocation correspondingInvocation = findCorrespondingMethodInvocation(unit,
511-
sourcePosition, def.getCallSite().getDeclaredTarget());
512-
513-
// what does the method return?
514-
ITypeBinding genericReturnType = correspondingInvocation.resolveMethodBinding().getReturnType();
515-
516-
// Is it compatible with the concrete type we got from WALA? But first, we'll
517-
// need to translate the Eclipse JDT type over to a IClass.
518-
TypeReference genericTypeRef = getJDTIdentifyMapper(correspondingInvocation)
519-
.getTypeRef(genericReturnType);
520-
IClass genericClass = node.getClassHierarchy().lookupClass(genericTypeRef);
521-
522-
boolean assignableFrom = node.getClassHierarchy().isAssignableFrom(genericClass, concreteClass);
523-
524-
// if it's assignable.
525-
if (assignableFrom)
526-
// would the ordering be consistent?
527-
if (wouldOrderingBeConsistent(Collections.unmodifiableCollection(ret), concreteType,
528-
orderingInference)) {
529-
// if so, add it.
530-
LOGGER.fine("Add type straight up: " + concreteType);
531-
ret.add(concreteType);
532-
} else {
533-
// otherwise, would the generic type cause the
534-
// ordering to be inconsistent?
535-
PointType genericType = new PointType(genericClass);
536-
537-
if (wouldOrderingBeConsistent(Collections.unmodifiableCollection(ret), genericType,
500+
// let's assume that the source file is in the same project.
501+
IJavaProject enclosingProject = engine.getProject();
502+
503+
String fqn = method.getDeclaringClass().getName().getPackage().toUnicodeString() + "."
504+
+ method.getDeclaringClass().getName().getClassName().toUnicodeString();
505+
IType type = enclosingProject.findType(fqn.replace('/', '.'));
506+
// FIXME: Need to (i) exclude from result timer and (ii) use the cache in
507+
// ConvertToParallelStreamRefactoringProcessor #141.
508+
CompilationUnit unit = RefactoringASTParser.parseWithASTProvider(type.getTypeRoot(), true,
509+
null);
510+
511+
// We have the CompilationUnit corresponding to the instruction's file. Can we
512+
// correlate the instruction to the method invocation in the AST?
513+
MethodInvocation correspondingInvocation = findCorrespondingMethodInvocation(unit,
514+
sourcePosition, def.getCallSite().getDeclaredTarget());
515+
516+
// what does the method return?
517+
ITypeBinding genericReturnType = correspondingInvocation.resolveMethodBinding()
518+
.getReturnType();
519+
520+
// Is it compatible with the concrete type we got from WALA? But first, we'll
521+
// need to translate the Eclipse JDT type over to a IClass.
522+
TypeReference genericTypeRef = getJDTIdentifyMapper(correspondingInvocation)
523+
.getTypeRef(genericReturnType);
524+
IClass genericClass = node.getClassHierarchy().lookupClass(genericTypeRef);
525+
526+
boolean assignableFrom = node.getClassHierarchy().isAssignableFrom(genericClass,
527+
concreteClass);
528+
529+
// if it's assignable.
530+
if (assignableFrom)
531+
// would the ordering be consistent?
532+
if (wouldOrderingBeConsistent(Collections.unmodifiableCollection(ret), concreteType,
538533
orderingInference)) {
539-
LOGGER.fine("Defaulting to generic type: " + genericType);
540-
ret.add(genericType);
541-
} else {
542-
// fall back to the concrete type.
543-
LOGGER.fine("Defaulting to concrete type eventhough it isn't consistent: "
544-
+ concreteType);
534+
// if so, add it.
535+
LOGGER.fine("Add type straight up: " + concreteType);
545536
ret.add(concreteType);
537+
} else {
538+
// otherwise, would the generic type cause the
539+
// ordering to be inconsistent?
540+
PointType genericType = new PointType(genericClass);
541+
542+
if (wouldOrderingBeConsistent(Collections.unmodifiableCollection(ret), genericType,
543+
orderingInference)) {
544+
LOGGER.fine("Defaulting to generic type: " + genericType);
545+
ret.add(genericType);
546+
} else {
547+
// fall back to the concrete type.
548+
LOGGER.fine("Defaulting to concrete type eventhough it isn't consistent: "
549+
+ concreteType);
550+
ret.add(concreteType);
551+
}
546552
}
547-
}
548-
} else {
549-
// just add it.
550-
LOGGER.fine("Add type straight up: " + concreteType);
551-
ret.add(concreteType);
553+
} else {
554+
// just add it.
555+
LOGGER.fine("Add type straight up: " + concreteType);
556+
ret.add(concreteType);
557+
}
552558
}
553559
}
554560
}

0 commit comments

Comments
 (0)