4
4
5
5
import 'package:meta/meta.dart' ;
6
6
7
- /// Set this boolean to `true` to permanently enable the feature of allowing
8
- /// local boolean variables to influence promotion (see
9
- /// https://github.com/dart-lang/language/issues/1274). While this boolean is
10
- /// `false` , the feature remains experimental and can be activated via an
11
- /// optional boolean parameter to the [FlowAnalysis] constructor.
12
- ///
13
- /// Changing this value to `true` will cause some dead code warnings to appear
14
- /// for code that only exists to support the old behavior.
15
- const bool allowLocalBooleanVarsToPromoteByDefault = true ;
16
-
17
7
/// [AssignedVariables] is a helper class capable of computing the set of
18
8
/// variables that are potentially written to, and potentially captured by
19
9
/// closures, at various locations inside the code being analyzed. This class
@@ -242,6 +232,11 @@ class AssignedVariables<Node extends Object, Variable extends Object> {
242
232
'{${_info .keys .map ((k ) => '$k (${k .hashCode })' ).join (',' )}}' ));
243
233
}
244
234
235
+ /// Indicates whether information is stored for the given [node] .
236
+ bool _hasInfoForNode (Node node) {
237
+ return _info[node] != null ;
238
+ }
239
+
245
240
void _printOn (StringBuffer sb) {
246
241
sb.write ('_info=$_info ,' );
247
242
sb.write ('_stack=$_stack ,' );
@@ -402,10 +397,8 @@ class ExpressionInfo<Variable extends Object, Type extends Object> {
402
397
abstract class FlowAnalysis <Node extends Object , Statement extends Node ,
403
398
Expression extends Object , Variable extends Object , Type extends Object > {
404
399
factory FlowAnalysis (TypeOperations <Variable , Type > typeOperations,
405
- AssignedVariables <Node , Variable > assignedVariables,
406
- {bool allowLocalBooleanVarsToPromote = false }) {
407
- return new _FlowAnalysisImpl (typeOperations, assignedVariables,
408
- allowLocalBooleanVarsToPromote: allowLocalBooleanVarsToPromote);
400
+ AssignedVariables <Node , Variable > assignedVariables) {
401
+ return new _FlowAnalysisImpl (typeOperations, assignedVariables);
409
402
}
410
403
411
404
factory FlowAnalysis .legacy (TypeOperations <Variable , Type > typeOperations,
@@ -976,12 +969,10 @@ class FlowAnalysisDebug<Node extends Object, Statement extends Node,
976
969
bool _exceptionOccurred = false ;
977
970
978
971
factory FlowAnalysisDebug (TypeOperations <Variable , Type > typeOperations,
979
- AssignedVariables <Node , Variable > assignedVariables,
980
- {bool allowLocalBooleanVarsToPromote = false }) {
972
+ AssignedVariables <Node , Variable > assignedVariables) {
981
973
print ('FlowAnalysisDebug()' );
982
- return new FlowAnalysisDebug ._(new _FlowAnalysisImpl (
983
- typeOperations, assignedVariables,
984
- allowLocalBooleanVarsToPromote: allowLocalBooleanVarsToPromote));
974
+ return new FlowAnalysisDebug ._(
975
+ new _FlowAnalysisImpl (typeOperations, assignedVariables));
985
976
}
986
977
987
978
factory FlowAnalysisDebug .legacy (
@@ -1881,79 +1872,6 @@ class FlowModel<Variable extends Object, Type extends Object> {
1881
1872
return _identicalOrNew (this , base , newReachable, newVariableInfo);
1882
1873
}
1883
1874
1884
- /// Updates the state to reflect a control path that is known to have
1885
- /// previously passed through some [other] state.
1886
- ///
1887
- /// Approximately, this method forms the union of the definite assignments and
1888
- /// promotions in `this` state and the [other] state. More precisely:
1889
- ///
1890
- /// The control flow path is considered reachable if both this state and the
1891
- /// other state are reachable. Variables are considered definitely assigned
1892
- /// if they were definitely assigned in either this state or the other state.
1893
- /// Variable type promotions are taken from this state, unless the promotion
1894
- /// in the other state is more specific, and the variable is "safe". A
1895
- /// variable is considered safe if there is no chance that it was assigned
1896
- /// more recently than the "other" state.
1897
- ///
1898
- /// This is used after a `try/finally` statement to combine the promotions and
1899
- /// definite assignments that occurred in the `try` and `finally` blocks
1900
- /// (where `this` is the state from the `finally` block and `other` is the
1901
- /// state from the `try` block). Variables that are assigned in the `finally`
1902
- /// block are considered "unsafe" because the assignment might have cancelled
1903
- /// the effect of any promotion that occurred inside the `try` block.
1904
- FlowModel <Variable , Type > restrict (
1905
- TypeOperations <Variable , Type > typeOperations,
1906
- FlowModel <Variable , Type > other,
1907
- Set <Variable > unsafe) {
1908
- if (allowLocalBooleanVarsToPromoteByDefault) {
1909
- // TODO(paulberry): when we hardcode
1910
- // allowLocalBooleanVarsToPromoteByDefault to `true`, we should remove
1911
- // this method entirely.
1912
- throw new StateError ('This method should not be called anymore' );
1913
- }
1914
- Reachability newReachable =
1915
- Reachability .restrict (reachable, other.reachable);
1916
-
1917
- Map <Variable ?, VariableModel <Variable , Type >> newVariableInfo =
1918
- < Variable ? , VariableModel <Variable , Type >> {};
1919
- bool variableInfoMatchesThis = true ;
1920
- bool variableInfoMatchesOther = true ;
1921
- for (MapEntry <Variable ?, VariableModel <Variable , Type >> entry
1922
- in variableInfo.entries) {
1923
- Variable ? variable = entry.key;
1924
- VariableModel <Variable , Type > thisModel = entry.value;
1925
- VariableModel <Variable , Type >? otherModel = other.variableInfo[variable];
1926
- if (otherModel == null ) {
1927
- variableInfoMatchesThis = false ;
1928
- continue ;
1929
- }
1930
- VariableModel <Variable , Type > restricted = thisModel.restrict (
1931
- typeOperations, otherModel, unsafe.contains (variable));
1932
- newVariableInfo[variable] = restricted;
1933
- if (! identical (restricted, thisModel)) variableInfoMatchesThis = false ;
1934
- if (! identical (restricted, otherModel)) variableInfoMatchesOther = false ;
1935
- }
1936
- if (variableInfoMatchesOther) {
1937
- for (Variable ? variable in other.variableInfo.keys) {
1938
- if (! variableInfo.containsKey (variable)) {
1939
- variableInfoMatchesOther = false ;
1940
- break ;
1941
- }
1942
- }
1943
- }
1944
- assert (variableInfoMatchesThis ==
1945
- _variableInfosEqual (newVariableInfo, variableInfo));
1946
- assert (variableInfoMatchesOther ==
1947
- _variableInfosEqual (newVariableInfo, other.variableInfo));
1948
- if (variableInfoMatchesThis) {
1949
- newVariableInfo = variableInfo;
1950
- } else if (variableInfoMatchesOther) {
1951
- newVariableInfo = other.variableInfo;
1952
- }
1953
-
1954
- return _identicalOrNew (this , other, newReachable, newVariableInfo);
1955
- }
1956
-
1957
1875
/// Updates the state to indicate that the control flow path is unreachable.
1958
1876
FlowModel <Variable , Type > setUnreachable () {
1959
1877
if (! reachable.locallyReachable) return this ;
@@ -2799,59 +2717,6 @@ class VariableModel<Variable extends Object, Type extends Object> {
2799
2717
ssaNode: writeCaptured ? null : new SsaNode <Variable , Type >(null ));
2800
2718
}
2801
2719
2802
- /// Returns an updated model reflect a control path that is known to have
2803
- /// previously passed through some [other] state. See [FlowModel.restrict]
2804
- /// for details.
2805
- VariableModel <Variable , Type > restrict (
2806
- TypeOperations <Variable , Type > typeOperations,
2807
- VariableModel <Variable , Type > otherModel,
2808
- bool unsafe) {
2809
- if (allowLocalBooleanVarsToPromoteByDefault) {
2810
- // TODO(paulberry): when we hardcode
2811
- // allowLocalBooleanVarsToPromoteByDefault to `true`, we should remove
2812
- // this method entirely.
2813
- throw new StateError ('This method should not be called anymore' );
2814
- }
2815
- List <Type >? thisPromotedTypes = promotedTypes;
2816
- List <Type >? otherPromotedTypes = otherModel.promotedTypes;
2817
- bool newAssigned = assigned || otherModel.assigned;
2818
- // The variable can only be unassigned in this state if it was also
2819
- // unassigned in the other state or if the other state didn't complete
2820
- // normally. For the latter case the resulting state is unreachable but to
2821
- // avoid creating a variable model that is both assigned and unassigned we
2822
- // take the intersection below.
2823
- //
2824
- // This situation can occur in try-finally like:
2825
- //
2826
- // method() {
2827
- // var local;
2828
- // try {
2829
- // local = 0;
2830
- // return; // assigned
2831
- // } finally {
2832
- // local; // unassigned
2833
- // }
2834
- // local; // unreachable state
2835
- // }
2836
- //
2837
- bool newUnassigned = unassigned && otherModel.unassigned;
2838
- bool newWriteCaptured = writeCaptured || otherModel.writeCaptured;
2839
- List <Type >? newPromotedTypes;
2840
- if (newWriteCaptured) {
2841
- // Write-captured variables can't be promoted
2842
- newPromotedTypes = null ;
2843
- } else if (unsafe) {
2844
- // There was an assignment to the variable in the "this" path, so none of
2845
- // the promotions from the "other" path can be used.
2846
- newPromotedTypes = thisPromotedTypes;
2847
- } else {
2848
- newPromotedTypes = rebasePromotedTypes (
2849
- typeOperations, thisPromotedTypes, otherPromotedTypes);
2850
- }
2851
- return _identicalOrNew (this , otherModel, newPromotedTypes, tested,
2852
- newAssigned, newUnassigned, newWriteCaptured ? null : ssaNode);
2853
- }
2854
-
2855
2720
/// Updates `this` with a new set of properties.
2856
2721
VariableModel <Variable , Type > setProperties (
2857
2722
Map <String , VariableModel <Variable , Type >> newProperties) =>
@@ -3526,18 +3391,7 @@ class _FlowAnalysisImpl<Node extends Object, Statement extends Node,
3526
3391
3527
3392
final AssignedVariables <Node , Variable > _assignedVariables;
3528
3393
3529
- /// Set this boolean to `true` to temporarily enable the feature of allowing
3530
- /// local boolean variables to influence promotion, for this flow analysis
3531
- /// session (see https://github.com/dart-lang/language/issues/1274). Once the
3532
- /// top level const [allowLocalBooleanVarsToPromoteByDefault] is changed to
3533
- /// `true` , this field will always be `true` , so it can be safely removed.
3534
- final bool allowLocalBooleanVarsToPromote;
3535
-
3536
- _FlowAnalysisImpl (this .typeOperations, this ._assignedVariables,
3537
- {bool allowLocalBooleanVarsToPromote = false })
3538
- : allowLocalBooleanVarsToPromote =
3539
- allowLocalBooleanVarsToPromoteByDefault ||
3540
- allowLocalBooleanVarsToPromote;
3394
+ _FlowAnalysisImpl (this .typeOperations, this ._assignedVariables);
3541
3395
3542
3396
@override
3543
3397
bool get isReachable => _current.reachable.overallReachable;
@@ -4188,17 +4042,13 @@ class _FlowAnalysisImpl<Node extends Object, Statement extends Node,
4188
4042
4189
4043
@override
4190
4044
void tryFinallyStatement_end (Node finallyBlock) {
4191
- AssignedVariablesNodeInfo <Variable > info =
4192
- _assignedVariables._getInfoForNode (finallyBlock);
4045
+ // We used to need info for `finally` blocks but we don't anymore.
4046
+ assert (! _assignedVariables._hasInfoForNode (finallyBlock),
4047
+ 'No assigned variables info should have been stored for $finallyBlock ' );
4193
4048
_TryFinallyContext <Variable , Type > context =
4194
4049
_stack.removeLast () as _TryFinallyContext <Variable , Type >;
4195
- if (allowLocalBooleanVarsToPromote) {
4196
- _current = context._afterBodyAndCatches
4197
- .attachFinally (typeOperations, context._beforeFinally, _current);
4198
- } else {
4199
- _current = _current.restrict (
4200
- typeOperations, context._afterBodyAndCatches, info._written);
4201
- }
4050
+ _current = context._afterBodyAndCatches
4051
+ .attachFinally (typeOperations, context._beforeFinally, _current);
4202
4052
}
4203
4053
4204
4054
@override
@@ -4220,13 +4070,11 @@ class _FlowAnalysisImpl<Node extends Object, Statement extends Node,
4220
4070
_storeExpressionReference (expression, variableReference);
4221
4071
VariableModel <Variable , Type > variableModel =
4222
4072
variableReference.getInfo (_current.variableInfo);
4223
- if (allowLocalBooleanVarsToPromote) {
4224
- ExpressionInfo <Variable , Type >? expressionInfo = variableModel
4225
- .ssaNode? .expressionInfo
4226
- ? .rebaseForward (typeOperations, _current);
4227
- if (expressionInfo != null ) {
4228
- _storeExpressionInfo (expression, expressionInfo);
4229
- }
4073
+ ExpressionInfo <Variable , Type >? expressionInfo = variableModel
4074
+ .ssaNode? .expressionInfo
4075
+ ? .rebaseForward (typeOperations, _current);
4076
+ if (expressionInfo != null ) {
4077
+ _storeExpressionInfo (expression, expressionInfo);
4230
4078
}
4231
4079
return variableModel.promotedTypes? .last;
4232
4080
}
0 commit comments