OLD | NEW |
1 // Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2016, 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 kernel.tree_shaker; | 5 library kernel.tree_shaker; |
6 | 6 |
7 import '../ast.dart'; | 7 import '../ast.dart'; |
8 import '../class_hierarchy.dart'; | 8 import '../class_hierarchy.dart'; |
9 import '../core_types.dart'; | 9 import '../core_types.dart'; |
10 import '../type_environment.dart'; | 10 import '../type_environment.dart'; |
11 import '../library_index.dart'; | 11 import '../library_index.dart'; |
12 | 12 |
13 Program transformProgram(CoreTypes coreTypes, Program program, | 13 Program transformProgram( |
| 14 CoreTypes coreTypes, ClassHierarchy hierarchy, Program program, |
14 {List<ProgramRoot> programRoots}) { | 15 {List<ProgramRoot> programRoots}) { |
15 new TreeShaker(coreTypes, program, programRoots: programRoots) | 16 new TreeShaker(coreTypes, hierarchy, program, programRoots: programRoots) |
16 .transform(program); | 17 .transform(program); |
17 return program; | 18 return program; |
18 } | 19 } |
19 | 20 |
20 enum ProgramRootKind { | 21 enum ProgramRootKind { |
21 /// The root is a class which will be instantiated by | 22 /// The root is a class which will be instantiated by |
22 /// external / non-Dart code. | 23 /// external / non-Dart code. |
23 ExternallyInstantiatedClass, | 24 ExternallyInstantiatedClass, |
24 | 25 |
25 /// The root is a setter function or a field. | 26 /// The root is a setter function or a field. |
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
83 /// | 84 /// |
84 /// The tree shaker computes the following in a fixed-point iteration: | 85 /// The tree shaker computes the following in a fixed-point iteration: |
85 /// - a set of instantiated classes | 86 /// - a set of instantiated classes |
86 /// - for each member, a set of potential host classes | 87 /// - for each member, a set of potential host classes |
87 /// - a set of names used in dynamic dispatch not on `this` | 88 /// - a set of names used in dynamic dispatch not on `this` |
88 /// | 89 /// |
89 /// If the `dart:mirrors` library is used then nothing will be tree-shaken. | 90 /// If the `dart:mirrors` library is used then nothing will be tree-shaken. |
90 // | 91 // |
91 // TODO(asgerf): Tree shake unused instance fields. | 92 // TODO(asgerf): Tree shake unused instance fields. |
92 class TreeShaker { | 93 class TreeShaker { |
| 94 final CoreTypes coreTypes; |
| 95 final ClosedWorldClassHierarchy hierarchy; |
93 final Program program; | 96 final Program program; |
94 final ClosedWorldClassHierarchy hierarchy; | |
95 final CoreTypes coreTypes; | |
96 final bool strongMode; | 97 final bool strongMode; |
97 final List<ProgramRoot> programRoots; | 98 final List<ProgramRoot> programRoots; |
98 | 99 |
99 /// Map from classes to set of names that have been dispatched with that class | 100 /// Map from classes to set of names that have been dispatched with that class |
100 /// as the static receiver type (meaning any subtype of that class can be | 101 /// as the static receiver type (meaning any subtype of that class can be |
101 /// the potential concrete receiver). | 102 /// the potential concrete receiver). |
102 /// | 103 /// |
103 /// The map is implemented as a list, indexed by | 104 /// The map is implemented as a list, indexed by |
104 /// [ClassHierarchy.getClassIndex]. | 105 /// [ClassHierarchy.getClassIndex]. |
105 final List<Set<Name>> _dispatchedNames; | 106 final List<Set<Name>> _dispatchedNames; |
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
162 | 163 |
163 Library _mirrorsLibrary; | 164 Library _mirrorsLibrary; |
164 | 165 |
165 /// Set to true if any use of the `dart:mirrors` API is found. | 166 /// Set to true if any use of the `dart:mirrors` API is found. |
166 bool isUsingMirrors = false; | 167 bool isUsingMirrors = false; |
167 | 168 |
168 /// If we have roots, we will shake, even if we encounter some elements from | 169 /// If we have roots, we will shake, even if we encounter some elements from |
169 /// the mirrors library. | 170 /// the mirrors library. |
170 bool get forceShaking => programRoots != null && programRoots.isNotEmpty; | 171 bool get forceShaking => programRoots != null && programRoots.isNotEmpty; |
171 | 172 |
172 TreeShaker(CoreTypes coreTypes, Program program, | 173 TreeShaker(CoreTypes coreTypes, ClassHierarchy hierarchy, Program program, |
173 {ClassHierarchy hierarchy, | 174 {bool strongMode: false, List<ProgramRoot> programRoots}) |
174 bool strongMode: false, | 175 : this._internal(coreTypes, hierarchy, program, strongMode, programRoots); |
175 List<ProgramRoot> programRoots}) | |
176 : this._internal(program, hierarchy ?? new ClassHierarchy(program), | |
177 coreTypes, strongMode, programRoots); | |
178 | 176 |
179 bool isMemberBodyUsed(Member member) { | 177 bool isMemberBodyUsed(Member member) { |
180 return _usedMembers.containsKey(member); | 178 return _usedMembers.containsKey(member); |
181 } | 179 } |
182 | 180 |
183 bool isMemberOverridden(Member member) { | 181 bool isMemberOverridden(Member member) { |
184 return _overriddenMembers.contains(member); | 182 return _overriddenMembers.contains(member); |
185 } | 183 } |
186 | 184 |
187 bool isMemberUsed(Member member) { | 185 bool isMemberUsed(Member member) { |
(...skipping 14 matching lines...) Expand all Loading... |
202 } | 200 } |
203 | 201 |
204 /// Applies the tree shaking results to the program. | 202 /// Applies the tree shaking results to the program. |
205 /// | 203 /// |
206 /// This removes unused classes, members, and hierarchy data. | 204 /// This removes unused classes, members, and hierarchy data. |
207 void transform(Program program) { | 205 void transform(Program program) { |
208 if (isUsingMirrors) return; // Give up if using mirrors. | 206 if (isUsingMirrors) return; // Give up if using mirrors. |
209 new _TreeShakingTransformer(this).transform(program); | 207 new _TreeShakingTransformer(this).transform(program); |
210 } | 208 } |
211 | 209 |
212 TreeShaker._internal(this.program, ClosedWorldClassHierarchy hierarchy, | 210 TreeShaker._internal(this.coreTypes, this.hierarchy, this.program, |
213 this.coreTypes, this.strongMode, this.programRoots) | 211 this.strongMode, this.programRoots) |
214 : this.hierarchy = hierarchy, | 212 : this._dispatchedNames = new List<Set<Name>>(hierarchy.classes.length), |
215 this._dispatchedNames = new List<Set<Name>>(hierarchy.classes.length), | |
216 this._usedMembersWithHost = | 213 this._usedMembersWithHost = |
217 new List<Set<Member>>(hierarchy.classes.length), | 214 new List<Set<Member>>(hierarchy.classes.length), |
218 this._classRetention = new List<ClassRetention>.filled( | 215 this._classRetention = new List<ClassRetention>.filled( |
219 hierarchy.classes.length, ClassRetention.None) { | 216 hierarchy.classes.length, ClassRetention.None) { |
220 _visitor = new _TreeShakerVisitor(this); | 217 _visitor = new _TreeShakerVisitor(this); |
221 _covariantVisitor = new _ExternalTypeVisitor(this, isCovariant: true); | 218 _covariantVisitor = new _ExternalTypeVisitor(this, isCovariant: true); |
222 _contravariantVisitor = | 219 _contravariantVisitor = |
223 new _ExternalTypeVisitor(this, isContravariant: true); | 220 new _ExternalTypeVisitor(this, isContravariant: true); |
224 _invariantVisitor = new _ExternalTypeVisitor(this, | 221 _invariantVisitor = new _ExternalTypeVisitor(this, |
225 isCovariant: true, isContravariant: true); | 222 isCovariant: true, isContravariant: true); |
(...skipping 857 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1083 classNode == coreTypes.futureClass || | 1080 classNode == coreTypes.futureClass || |
1084 classNode == coreTypes.streamClass || | 1081 classNode == coreTypes.streamClass || |
1085 classNode == coreTypes.listClass || | 1082 classNode == coreTypes.listClass || |
1086 classNode == coreTypes.mapClass; | 1083 classNode == coreTypes.mapClass; |
1087 } | 1084 } |
1088 } | 1085 } |
1089 | 1086 |
1090 /// Exception that is thrown to stop the tree shaking analysis when a use | 1087 /// Exception that is thrown to stop the tree shaking analysis when a use |
1091 /// of `dart:mirrors` is found. | 1088 /// of `dart:mirrors` is found. |
1092 class _UsingMirrorsException {} | 1089 class _UsingMirrorsException {} |
OLD | NEW |