| OLD | NEW |
| 1 // Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file |
| 2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
| 3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
| 4 | 4 |
| 5 library dev_compiler.src.codegen.side_effect_analysis; | 5 library dev_compiler.src.codegen.side_effect_analysis; |
| 6 | 6 |
| 7 import 'package:analyzer/src/generated/ast.dart'; | 7 import 'package:analyzer/src/generated/ast.dart'; |
| 8 import 'package:analyzer/src/generated/constant.dart'; | 8 import 'package:analyzer/src/generated/constant.dart'; |
| 9 import 'package:analyzer/src/generated/element.dart'; | 9 import 'package:analyzer/src/generated/element.dart'; |
| 10 import 'package:analyzer/src/generated/error.dart' show ErrorReporter; | 10 import 'package:analyzer/src/generated/error.dart' show ErrorReporter; |
| (...skipping 18 matching lines...) Expand all Loading... |
| 29 /// | 29 /// |
| 30 /// This method is conservative: it should never return `true` unless it is | 30 /// This method is conservative: it should never return `true` unless it is |
| 31 /// certain the [node] is stateless, because generated code may rely on the | 31 /// certain the [node] is stateless, because generated code may rely on the |
| 32 /// correctness of a `true` value. However it may return `false` for things | 32 /// correctness of a `true` value. However it may return `false` for things |
| 33 /// that are in fact, stateless. | 33 /// that are in fact, stateless. |
| 34 bool isStateless(Expression node, [AstNode context]) { | 34 bool isStateless(Expression node, [AstNode context]) { |
| 35 // `this` and `super` cannot be reassigned. | 35 // `this` and `super` cannot be reassigned. |
| 36 if (node is ThisExpression || node is SuperExpression) return true; | 36 if (node is ThisExpression || node is SuperExpression) return true; |
| 37 if (node is SimpleIdentifier) { | 37 if (node is SimpleIdentifier) { |
| 38 var e = node.staticElement; | 38 var e = node.staticElement; |
| 39 if (e is PropertyAccessorElement) e = | 39 if (e is PropertyAccessorElement) |
| 40 (e as PropertyAccessorElement).variable; | 40 e = (e as PropertyAccessorElement).variable; |
| 41 if (e is VariableElement && !e.isSynthetic) { | 41 if (e is VariableElement && !e.isSynthetic) { |
| 42 if (e.isFinal) return true; | 42 if (e.isFinal) return true; |
| 43 if (e is LocalVariableElement || e is ParameterElement) { | 43 if (e is LocalVariableElement || e is ParameterElement) { |
| 44 // make sure the local isn't mutated in the context. | 44 // make sure the local isn't mutated in the context. |
| 45 return !_isPotentiallyMutated(e, context); | 45 return !_isPotentiallyMutated(e, context); |
| 46 } | 46 } |
| 47 } | 47 } |
| 48 } | 48 } |
| 49 return false; | 49 return false; |
| 50 } | 50 } |
| (...skipping 19 matching lines...) Expand all Loading... |
| 70 class _AssignmentFinder extends RecursiveAstVisitor { | 70 class _AssignmentFinder extends RecursiveAstVisitor { |
| 71 final VariableElement _variable; | 71 final VariableElement _variable; |
| 72 bool _potentiallyMutated = false; | 72 bool _potentiallyMutated = false; |
| 73 | 73 |
| 74 _AssignmentFinder(this._variable); | 74 _AssignmentFinder(this._variable); |
| 75 | 75 |
| 76 @override | 76 @override |
| 77 visitSimpleIdentifier(SimpleIdentifier node) { | 77 visitSimpleIdentifier(SimpleIdentifier node) { |
| 78 // Ignore if qualified. | 78 // Ignore if qualified. |
| 79 AstNode parent = node.parent; | 79 AstNode parent = node.parent; |
| 80 if (parent is PrefixedIdentifier && | 80 if (parent is PrefixedIdentifier && identical(parent.identifier, node)) |
| 81 identical(parent.identifier, node)) return; | 81 return; |
| 82 if (parent is PropertyAccess && | 82 if (parent is PropertyAccess && identical(parent.propertyName, node)) |
| 83 identical(parent.propertyName, node)) return; | 83 return; |
| 84 if (parent is MethodInvocation && | 84 if (parent is MethodInvocation && identical(parent.methodName, node)) |
| 85 identical(parent.methodName, node)) return; | 85 return; |
| 86 if (parent is ConstructorName) return; | 86 if (parent is ConstructorName) return; |
| 87 if (parent is Label) return; | 87 if (parent is Label) return; |
| 88 | 88 |
| 89 if (node.inSetterContext() && node.staticElement == _variable) { | 89 if (node.inSetterContext() && node.staticElement == _variable) { |
| 90 _potentiallyMutated = true; | 90 _potentiallyMutated = true; |
| 91 } | 91 } |
| 92 } | 92 } |
| 93 } | 93 } |
| 94 | 94 |
| 95 class ConstFieldVisitor { | 95 class ConstFieldVisitor { |
| (...skipping 22 matching lines...) Expand all Loading... |
| 118 // ConstantEvaluator will not compute constants for non-const fields, | 118 // ConstantEvaluator will not compute constants for non-const fields, |
| 119 // so run ConstantVisitor for those to figure out if the initializer is | 119 // so run ConstantVisitor for those to figure out if the initializer is |
| 120 // actually a constant (and therefore side effect free to evaluate). | 120 // actually a constant (and therefore side effect free to evaluate). |
| 121 assert(!field.isConst); | 121 assert(!field.isConst); |
| 122 | 122 |
| 123 var initializer = field.initializer; | 123 var initializer = field.initializer; |
| 124 if (initializer == null) return null; | 124 if (initializer == null) return null; |
| 125 return initializer.accept(_constantVisitor); | 125 return initializer.accept(_constantVisitor); |
| 126 } | 126 } |
| 127 } | 127 } |
| OLD | NEW |