22
22
import java .util .stream .Collectors ;
23
23
24
24
import org .eclipse .core .runtime .CoreException ;
25
- import org .eclipse .core .runtime .NullProgressMonitor ;
25
+ import org .eclipse .core .runtime .IProgressMonitor ;
26
+ import org .eclipse .core .runtime .SubMonitor ;
26
27
import org .eclipse .jdt .core .JavaModelException ;
27
28
28
29
import com .google .common .collect .HashBasedTable ;
@@ -567,8 +568,11 @@ private boolean deriveRomForNonScalarMethod(Collection<TypeAbstraction> possible
567
568
}
568
569
569
570
private void discoverIfReduceOrderingPossiblyMatters (EclipseProjectAnalysisEngine <InstanceKey > engine ,
570
- OrderingInference orderingInference ) throws UTFDataFormatException , JavaModelException ,
571
- NoniterableException , NoninstantiableException , CannotExtractSpliteratorException {
571
+ OrderingInference orderingInference , IProgressMonitor monitor ) throws UTFDataFormatException ,
572
+ JavaModelException , NoniterableException , NoninstantiableException , CannotExtractSpliteratorException {
573
+ monitor .beginTask ("Discovering if reduce order matters..." ,
574
+ this .terminalBlockToPossibleReceivers .keySet ().size ());
575
+
572
576
// for each terminal operation call, I think?
573
577
for (BasicBlockInContext <IExplodedBasicBlock > block : this .terminalBlockToPossibleReceivers .keySet ()) {
574
578
int processedInstructions = 0 ;
@@ -648,6 +652,7 @@ private void discoverIfReduceOrderingPossiblyMatters(EclipseProjectAnalysisEngin
648
652
++processedInstructions ;
649
653
}
650
654
assert processedInstructions == 1 : "Expecting to process one and only one instruction here." ;
655
+ monitor .worked (1 );
651
656
}
652
657
}
653
658
@@ -721,8 +726,10 @@ private void discoverLambdaSideEffects(EclipseProjectAnalysisEngine<InstanceKey>
721
726
LOGGER .warning ("Def was an instance of a: " + def .getClass ());
722
727
}
723
728
724
- private void discoverPossibleSideEffects (EclipseProjectAnalysisEngine <InstanceKey > engine )
729
+ private void discoverPossibleSideEffects (EclipseProjectAnalysisEngine <InstanceKey > engine , IProgressMonitor monitor )
725
730
throws IOException , CoreException {
731
+ SubMonitor subMonitor = SubMonitor .convert (monitor , "Discovering side-effects..." , 100 );
732
+
726
733
// create the ModRef analysis.
727
734
ModRef <InstanceKey > modRef = ModRef .make ();
728
735
@@ -732,6 +739,9 @@ private void discoverPossibleSideEffects(EclipseProjectAnalysisEngine<InstanceKe
732
739
Map <CGNode , OrdinalSet <PointerKey >> mod = modRef .computeMod (engine .getCallGraph (), engine .getPointerAnalysis ());
733
740
734
741
// for each terminal operation call, I think?
742
+ SubMonitor loopMonitor = subMonitor .split (50 , SubMonitor .SUPPRESS_NONE )
743
+ .setWorkRemaining (this .terminalBlockToPossibleReceivers .keySet ().size ());
744
+
735
745
for (BasicBlockInContext <IExplodedBasicBlock > block : this .terminalBlockToPossibleReceivers .keySet ()) {
736
746
int processedInstructions = 0 ;
737
747
for (SSAInstruction instruction : block ) {
@@ -760,10 +770,13 @@ private void discoverPossibleSideEffects(EclipseProjectAnalysisEngine<InstanceKe
760
770
}
761
771
762
772
assert processedInstructions == 1 : "Expecting to process one and only one instruction here." ;
773
+ loopMonitor .worked (1 );
763
774
}
764
775
765
776
// for each instance in the analysis result (these should be the
766
777
// "intermediate" streams).
778
+ loopMonitor = subMonitor .split (50 , SubMonitor .SUPPRESS_NONE ).setWorkRemaining (this .trackedInstances .size ());
779
+
767
780
for (InstanceKey instance : this .trackedInstances ) {
768
781
// make sure that the stream is the result of an intermediate
769
782
// operation.
@@ -792,14 +805,18 @@ private void discoverPossibleSideEffects(EclipseProjectAnalysisEngine<InstanceKe
792
805
this .discoverLambdaSideEffects (engine , mod , Collections .singleton (instance ),
793
806
callString .getMethods ()[0 ].getReference (), ir , use );
794
807
}
808
+
809
+ loopMonitor .worked (1 );
795
810
}
796
811
}
797
812
798
- private void discoverPossibleStatefulIntermediateOperations (IClassHierarchy hierarchy , CallGraph callGraph )
799
- throws IOException , CoreException {
813
+ private void discoverPossibleStatefulIntermediateOperations (IClassHierarchy hierarchy , CallGraph callGraph ,
814
+ IProgressMonitor monitor ) throws IOException , CoreException {
815
+ monitor .beginTask ("Discovering stateful intermediate operations..." , this .trackedInstances .size ());
816
+
800
817
// for each instance in the analysis result (these should be the
801
818
// "intermediate" streams).
802
- for (InstanceKey instance : this .trackedInstances )
819
+ for (InstanceKey instance : this .trackedInstances ) {
803
820
if (!this .instanceToStatefulIntermediateOperationContainment .containsKey (instance )) {
804
821
// make sure that the stream is the result of an intermediate
805
822
// operation.
@@ -816,21 +833,26 @@ private void discoverPossibleStatefulIntermediateOperations(IClassHierarchy hier
816
833
}
817
834
this .instanceToStatefulIntermediateOperationContainment .put (instance , found );
818
835
}
836
+ monitor .worked (1 );
837
+ }
819
838
}
820
839
821
- private void discoverTerminalOperations () {
840
+ private void discoverTerminalOperations (IProgressMonitor monitor ) {
822
841
Collection <OrdinalSet <InstanceKey >> receiverSetsThatHaveTerminalOperations = this .terminalBlockToPossibleReceivers
823
842
.values ();
824
843
825
844
// This will be the OK set.
826
845
Collection <InstanceKey > validStreams = new HashSet <>();
827
846
828
847
// Now, we need to flatten the receiver sets.
829
- for (OrdinalSet <InstanceKey > receiverSet : receiverSetsThatHaveTerminalOperations )
848
+ monitor .beginTask ("Flattening..." , receiverSetsThatHaveTerminalOperations .size ());
849
+ for (OrdinalSet <InstanceKey > receiverSet : receiverSetsThatHaveTerminalOperations ) {
830
850
// for each receiver set
831
851
for (InstanceKey instance : receiverSet )
832
852
// add it to the OK set.
833
853
validStreams .add (instance );
854
+ monitor .worked (1 );
855
+ }
834
856
835
857
// Now, we have the OK set. Let's propagate it.
836
858
this .propagateStreamInstanceProperty (validStreams );
@@ -864,8 +886,9 @@ private void fillInstanceToPredecessorMap(EclipseProjectAnalysisEngine<InstanceK
864
886
}
865
887
}
866
888
867
- private void fillInstanceToStreamMap (Set <Stream > streamSet , EclipseProjectAnalysisEngine <InstanceKey > engine )
868
- throws InvalidClassFileException , IOException , CoreException {
889
+ private void fillInstanceToStreamMap (Set <Stream > streamSet , EclipseProjectAnalysisEngine <InstanceKey > engine ,
890
+ IProgressMonitor monitor ) throws InvalidClassFileException , IOException , CoreException {
891
+ monitor .beginTask ("Propagating..." , streamSet .size ());
869
892
int skippedStreams = 0 ;
870
893
for (Stream stream : streamSet ) {
871
894
InstanceKey instanceKey = null ;
@@ -904,6 +927,7 @@ private void fillInstanceToStreamMap(Set<Stream> streamSet, EclipseProjectAnalys
904
927
LOGGER .warning ("Reassociating stream: " + stream .getCreation () + " with: " + instanceKey
905
928
+ ". Old stream was: " + oldValue .getCreation () + "." );
906
929
930
+ monitor .worked (1 );
907
931
} // end each stream.
908
932
909
933
// sanity check since it's a bijection.
@@ -952,9 +976,10 @@ private void propagateStreamInstanceProperty(Collection<InstanceKey> streamInsta
952
976
}
953
977
954
978
public Map <TypestateRule , Statistics > start (Set <Stream > streamSet , EclipseProjectAnalysisEngine <InstanceKey > engine ,
955
- OrderingInference orderingInference )
979
+ OrderingInference orderingInference , IProgressMonitor monitor )
956
980
throws PropertiesException , CancelException , IOException , CoreException , NoniterableException ,
957
981
NoninstantiableException , CannotExtractSpliteratorException , InvalidClassFileException {
982
+ SubMonitor subMonitor = SubMonitor .convert (monitor , "Performing typestate analysis (may take a while)" , 100 );
958
983
Map <TypestateRule , Statistics > ret = new HashMap <>();
959
984
960
985
BenignOracle ora = new ModifiedBenignOracle (engine .getCallGraph (), engine .getPointerAnalysis ());
@@ -973,6 +998,8 @@ public Map<TypestateRule, Statistics> start(Set<Stream> streamSet, EclipseProjec
973
998
StreamAttributeTypestateRule [] ruleArray = createStreamAttributeTypestateRules (streamClass );
974
999
975
1000
// for each rule.
1001
+ SubMonitor ruleMonitor = subMonitor .split (70 , SubMonitor .SUPPRESS_NONE ).setWorkRemaining (ruleArray .length );
1002
+
976
1003
for (StreamAttributeTypestateRule rule : ruleArray ) {
977
1004
// create a DFA based on the rule.
978
1005
TypeStateProperty dfa = new TypeStateProperty (rule , engine .getClassHierarchy ());
@@ -984,7 +1011,7 @@ public Map<TypestateRule, Statistics> start(Set<Stream> streamSet, EclipseProjec
984
1011
985
1012
AggregateSolverResult result ;
986
1013
try {
987
- result = (AggregateSolverResult ) solver .perform (new NullProgressMonitor ( ));
1014
+ result = (AggregateSolverResult ) solver .perform (ruleMonitor . split ( 50 , SubMonitor . SUPPRESS_NONE ));
988
1015
} catch (SolverTimeoutException | MaxFindingsException | SetUpException | WalaException e ) {
989
1016
throw new RuntimeException ("Exception caught during typestate analysis." , e );
990
1017
}
@@ -997,6 +1024,9 @@ public Map<TypestateRule, Statistics> start(Set<Stream> streamSet, EclipseProjec
997
1024
assert lastStatistics == null : "Reassociating statistics." ;
998
1025
999
1026
// for each instance in the typestate analysis result.
1027
+ SubMonitor instanceMonitor = ruleMonitor .split (20 , SubMonitor .SUPPRESS_NONE )
1028
+ .setWorkRemaining (result .totalInstancesNum ());
1029
+
1000
1030
for (Iterator <InstanceKey > iterator = result .iterateInstances (); iterator .hasNext ();) {
1001
1031
// get the instance's key.
1002
1032
InstanceKey instanceKey = iterator .next ();
@@ -1140,6 +1170,7 @@ public Map<TypestateRule, Statistics> start(Set<Stream> streamSet, EclipseProjec
1140
1170
}
1141
1171
}
1142
1172
}
1173
+ instanceMonitor .worked (1 );
1143
1174
} // end for each instance in the typestate analysis result.
1144
1175
1145
1176
// fill the instance to predecessors map if it's empty.
@@ -1183,23 +1214,26 @@ public Map<TypestateRule, Statistics> start(Set<Stream> streamSet, EclipseProjec
1183
1214
});
1184
1215
}
1185
1216
}
1217
+ ruleMonitor .worked (1 );
1186
1218
} // end for each rule.
1187
1219
1188
1220
// create a mapping between stream instances (from the analysis) and stream
1189
1221
// objects (from the refactoring).
1190
- this .fillInstanceToStreamMap (streamSet , engine );
1222
+ this .fillInstanceToStreamMap (streamSet , engine , subMonitor . split ( 5 , SubMonitor . SUPPRESS_NONE ) );
1191
1223
1192
- this .discoverTerminalOperations ();
1224
+ this .discoverTerminalOperations (subMonitor . split ( 5 , SubMonitor . SUPPRESS_NONE ) );
1193
1225
1194
1226
// fill the instance side-effect set.
1195
- this .discoverPossibleSideEffects (engine );
1227
+ this .discoverPossibleSideEffects (engine , subMonitor . split ( 5 , SubMonitor . SUPPRESS_NONE ) );
1196
1228
1197
1229
// discover whether any stateful intermediate operations are
1198
1230
// present.
1199
- this .discoverPossibleStatefulIntermediateOperations (engine .getClassHierarchy (), engine .getCallGraph ());
1231
+ this .discoverPossibleStatefulIntermediateOperations (engine .getClassHierarchy (), engine .getCallGraph (),
1232
+ subMonitor .split (5 , SubMonitor .SUPPRESS_NONE ));
1200
1233
1201
1234
// does reduction order matter?
1202
- this .discoverIfReduceOrderingPossiblyMatters (engine , orderingInference );
1235
+ this .discoverIfReduceOrderingPossiblyMatters (engine , orderingInference ,
1236
+ subMonitor .split (5 , SubMonitor .SUPPRESS_NONE ));
1203
1237
1204
1238
// propagate the instances with side-effects.
1205
1239
this .propagateStreamInstanceProperty (this .instancesWithSideEffects );
0 commit comments