Skip to content

Add analysis for complex mutable reductions #186

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 10 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
package edu.cuny.hunter.streamrefactoring.core.analysis;

public enum CollectorKind {
CONCURRENT,
NONCONCURRENT
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,13 @@ public enum PreconditionSuccess {
P2,
P3,
P4,
P5
P5,
P6,
P7,
P8,
P9,
P10,
P11,
P12,
P13
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,5 +7,6 @@
*/
public enum Refactoring {
CONVERT_SEQUENTIAL_STREAM_TO_PARALLEL,
OPTIMIZE_PARALLEL_STREAM
OPTIMIZE_PARALLEL_STREAM,
OPTIMIZE_COMPLEX_MUTABLE_REDUCTION
}
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,8 @@ public class Stream {
private IR enclosingMethodDeclarationIR;

private final TypeDeclaration enclosingTypeDeclaration;

private CollectorKind collectorKind;

private boolean hasNoTerminalOperation;

Expand Down Expand Up @@ -508,6 +510,10 @@ public Set<Ordering> getPossibleOrderings() {
return this.possibleOrderings.stream().map(e -> e == null ? initialOrdering : e).collect(Collectors.toSet());
}

public CollectorKind getCollectorKind() {
return this.collectorKind;
}

public Refactoring getRefactoring() {
return this.refactoring;
}
Expand Down Expand Up @@ -707,6 +713,10 @@ protected void setInitialOrdering(Ordering initialOrdering) {
Objects.requireNonNull(initialOrdering);
this.initialOrdering = initialOrdering;
}

protected void setCollectorKind(CollectorKind collectorKind) {
this.collectorKind = collectorKind;
}

private void setPassingPrecondition(PreconditionSuccess succcess) {
if (this.passingPrecondition == null)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@
import com.ibm.wala.ipa.callgraph.propagation.NormalAllocationInNode;
import com.ibm.wala.ipa.callgraph.propagation.PointerKey;
import com.ibm.wala.ipa.cfg.BasicBlockInContext;
import com.ibm.wala.ipa.cha.ClassHierarchy;
import com.ibm.wala.ipa.cha.IClassHierarchy;
import com.ibm.wala.ipa.modref.ModRef;
import com.ibm.wala.shrikeCT.InvalidClassFileException;
Expand Down Expand Up @@ -209,8 +210,17 @@ protected static StreamAttributeTypestateRule[] createStreamAttributeTypestateRu
// @formatter:on
}

private static boolean deriveRomForScalarMethod(SSAInvokeInstruction invokeInstruction)
private static boolean deriveRomForScalarMethod(Collection<TypeAbstraction> possibleReturnTypes,
SSAInvokeInstruction invokeInstruction, IClassHierarchy hierarchy)
throws UnknownIfReduceOrderMattersException {
boolean allImplementMap = possibleReturnTypes.stream().map(TypeAbstraction::getTypeReference)
.allMatch(t -> Util.implementsMap(t, hierarchy));

if (allImplementMap) {
// TODO: we should be the complex mutable reduction case #64. Note that it may
// not be a call to collect(). It could be a call to reduce().
}

MethodReference declaredTarget = invokeInstruction.getCallSite().getDeclaredTarget();

if (isTerminalOperationWhereReduceOrderMattersIsUnknown(declaredTarget))
Expand Down Expand Up @@ -553,7 +563,7 @@ private boolean deriveRomForNonScalarMethod(Collection<TypeAbstraction> possible
// default to ordered.
ordering = Ordering.ORDERED;
LOGGER.warning("Can't determine ordering for possible return types: " + possibleReturnTypes
+ ". Defaulting to: " + ordering);
+ ". Defaulting to: " + ordering + ".");
}

switch (ordering) {
Expand Down Expand Up @@ -606,7 +616,8 @@ private void discoverIfReduceOrderingPossiblyMatters(EclipseProjectAnalysisEngin
else {
boolean scalar = Util.isScalar(possibleReturnTypes);
if (scalar)
rom = deriveRomForScalarMethod(invokeInstruction);
rom = deriveRomForScalarMethod(possibleReturnTypes, invokeInstruction,
engine.getClassHierarchy());
else // !scalar
rom = this.deriveRomForNonScalarMethod(possibleReturnTypes, orderingInference);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
public enum TransformationAction {
CONVERT_TO_PARALLEL,
UNORDER,
CONVERT_TO_SEQUENTIAL

CONVERT_TO_SEQUENTIAL,
CONVERT_COLLECTOR_TO_CONCURRENT,
CONVERT_COLLECTOR_TO_NON_CONCURRENT
}
Original file line number Diff line number Diff line change
Expand Up @@ -576,6 +576,10 @@ public static boolean implementsIterable(TypeReference reference, IClassHierarch
return implementsType(reference, classHierarchy, Util::isIterable);
}

public static boolean implementsMap(TypeReference reference, IClassHierarchy hierarchy) {
return implementsType(reference, hierarchy, Util::isMap);
}

public static boolean implementsType(TypeReference typeReference, IClassHierarchy classHierarchy,
Predicate<IClass> predicate) {
IClass clazz = classHierarchy.lookupClass(typeReference);
Expand Down Expand Up @@ -618,6 +622,10 @@ public static boolean isCollector(IClass clazz) {
return Util.isType(clazz, "java/util/stream", "Collector");
}

public static boolean isMap(IClass clazz) {
return Util.isType(clazz, "java/util", "Map");
}

/**
* check whether the annotation is "EntryPoint"
*/
Expand Down Expand Up @@ -655,8 +663,7 @@ else if (typeReference.isPrimitiveType())
return true;
else if (typeReference.isReferenceType()) {
IClass type = typeAbstraction.getType();
return !edu.cuny.hunter.streamrefactoring.core.analysis.Util.isIterable(type)
&& type.getAllImplementedInterfaces().stream().noneMatch(Util::isIterable);
return !isIterable(type) && type.getAllImplementedInterfaces().stream().noneMatch(Util::isIterable);
} else
throw new IllegalArgumentException("Can't tell if type is scalar: " + typeAbstraction);
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
package p;

import java.util.ArrayList;
import java.util.Collection;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.ConcurrentNavigableMap;
import java.util.concurrent.ConcurrentSkipListMap;
import java.util.stream.Collectors;
import java.util.Set;

import edu.cuny.hunter.streamrefactoring.annotations.EntryPoint;

import p.A.Widget.Color;

public class A {

static class Widget {
enum Color {
RED,
BLUE,
GREEN,
PINK,
ORANGE,
YELLOW
};

public Color getColor() {
return this.getColor();
}
}

@EntryPoint
void m() {
Collection<Widget> orderedWidgets = new ArrayList<>();

Map<Color, List<Widget>> widgetsByColor = orderedWidgets.parallelStream()
.collect(Collectors.groupingBy(Widget::getColor));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
package p;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import edu.cuny.hunter.streamrefactoring.annotations.*;
import p.A.Widget.Color;

public class A {

static class Widget {
enum Color {
RED,
BLUE,
GREEN,
PINK,
ORANGE,
YELLOW
};

public Color getColor() {
return this.getColor();
}
}

@EntryPoint
void m() {
// an "unordered" collection of widgets.
Collection<Widget> unorderedWidgets = new HashSet<>();
// populate the collection ...

Map<Color, List<Widget>> widgetsByColor = unorderedWidgets.stream()
.collect(Collectors.groupingBy(Widget::getColor));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
package p;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.HashMap;
import java.util.stream.Collectors;

import edu.cuny.hunter.streamrefactoring.annotations.*;
import p.A.Widget.Color;

public class A {

static class Widget {
enum Color {
RED,
BLUE,
GREEN,
PINK,
ORANGE,
YELLOW
};

public Color getColor() {
return this.getColor();
}
}

@EntryPoint
void m() {
Collection<Widget> orderedWidgets = new ArrayList<>();

Map<Color, Set<Widget>> widgetsByColor2 = orderedWidgets.stream()
.collect(Collectors.groupingBy(Widget::getColor, HashMap::new, Collectors.toSet()));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
package p;

import java.util.*;
import java.util.stream.*;
import java.util.concurrent.*;

import edu.cuny.hunter.streamrefactoring.annotations.*;
import p.A.Widget.Color;

public class A {

static class Widget {
enum Color {
RED,
BLUE,
GREEN,
PINK,
ORANGE,
YELLOW
};

public Color getColor() {
return this.getColor();
}
}

@EntryPoint
void m() {
Collection<Widget> orderedWidgets = new ArrayList<>();

Map<Color, Set<Widget>> widgetsByColor2 = orderedWidgets.stream().collect(Collectors.groupingByConcurrent(
Widget::getColor, ConcurrentHashMap::new, Collectors.toCollection(LinkedHashSet::new)));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
package p;

import java.util.ArrayList;
import java.util.Collection;
import java.util.LinkedHashSet;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.stream.Collectors;

import edu.cuny.hunter.streamrefactoring.annotations.*;
import p.A.Widget.Color;

public class A {

static class Widget {
enum Color {
RED, BLUE, GREEN, PINK, ORANGE, YELLOW
};

public Color getColor() {
return this.getColor();
}
}

/**
* P10 in table 3
*/
@EntryPoint
void m() {
Collection<Widget> orderedWidgets = new ArrayList<>();
Map<Color, Set<Widget>> widgetsByColor = orderedWidgets.stream().collect(Collectors.groupingByConcurrent(
Widget::getColor, ConcurrentHashMap::new, Collectors.toCollection(LinkedHashSet::new)));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
package p;

import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;

import edu.cuny.hunter.streamrefactoring.annotations.*;
import p.A.Widget.Color;

public class A {

static class Widget {
enum Color {
RED, BLUE, GREEN, PINK, ORANGE, YELLOW
};

public Color getColor() {
return this.getColor();
}
}

/**
* P11 in table 3
*/
@EntryPoint
void m() {
Collection<Widget> orderedWidgets = new ArrayList<>();
Map<Color, Set<Widget>> widgetsByColor = orderedWidgets.parallelStream()
.collect(Collectors.groupingBy(Widget::getColor, HashMap::new, Collectors.toSet()));
}
}
Loading