| OLD | NEW |
| 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2013, 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 part of type_graph_inferrer; | 5 part of type_graph_inferrer; |
| 6 | 6 |
| 7 /** | 7 /** |
| 8 * A set of selector names that [List] implements, that we know do not | 8 * A set of selector names that [List] implements, that we know do not |
| 9 * change the element type of the list, or let the list escape to code | 9 * change the element type of the list, or let the list escape to code |
| 10 * that might change the element type. | 10 * that might change the element type. |
| (...skipping 121 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 132 final TypeGraphInferrerEngine inferrer; | 132 final TypeGraphInferrerEngine inferrer; |
| 133 final Compiler compiler; | 133 final Compiler compiler; |
| 134 | 134 |
| 135 // The set of [TypeInformation] where the traced container could | 135 // The set of [TypeInformation] where the traced container could |
| 136 // flow in, and operations done on them. | 136 // flow in, and operations done on them. |
| 137 final Setlet<TypeInformation> allUsers = new Setlet<TypeInformation>(); | 137 final Setlet<TypeInformation> allUsers = new Setlet<TypeInformation>(); |
| 138 | 138 |
| 139 // The list of found assignments to the container. | 139 // The list of found assignments to the container. |
| 140 final List<TypeInformation> assignments = <TypeInformation>[]; | 140 final List<TypeInformation> assignments = <TypeInformation>[]; |
| 141 | 141 |
| 142 bool enableLengthTracking = true; | 142 bool callsGrowableMethod = false; |
| 143 bool continueAnalyzing = true; | 143 bool continueAnalyzing = true; |
| 144 | 144 |
| 145 static const int MAX_ANALYSIS_COUNT = 16; | 145 static const int MAX_ANALYSIS_COUNT = 16; |
| 146 final Setlet<Element> analyzedElements = new Setlet<Element>(); | 146 final Setlet<Element> analyzedElements = new Setlet<Element>(); |
| 147 | 147 |
| 148 ContainerTracerVisitor(this.container, inferrer) | 148 ContainerTracerVisitor(this.container, inferrer) |
| 149 : this.inferrer = inferrer, this.compiler = inferrer.compiler; | 149 : this.inferrer = inferrer, this.compiler = inferrer.compiler; |
| 150 | 150 |
| 151 List<TypeInformation> run() { | 151 List<TypeInformation> run() { |
| 152 // Collect the [TypeInformation] where the container can flow in, | 152 // Collect the [TypeInformation] where the container can flow in, |
| 153 // as well as the operations done on all these [TypeInformation]s. | 153 // as well as the operations done on all these [TypeInformation]s. |
| 154 List<TypeInformation> workList = <TypeInformation>[]; | 154 List<TypeInformation> workList = <TypeInformation>[]; |
| (...skipping 16 matching lines...) Expand all Loading... |
| 171 } | 171 } |
| 172 | 172 |
| 173 if (continueAnalyzing) { | 173 if (continueAnalyzing) { |
| 174 for (TypeInformation info in allUsers) { | 174 for (TypeInformation info in allUsers) { |
| 175 info.accept(this); | 175 info.accept(this); |
| 176 if (!continueAnalyzing) break; | 176 if (!continueAnalyzing) break; |
| 177 } | 177 } |
| 178 } | 178 } |
| 179 | 179 |
| 180 if (continueAnalyzing) { | 180 if (continueAnalyzing) { |
| 181 if (enableLengthTracking && container.inferredLength == null) { | 181 if (!callsGrowableMethod && container.inferredLength == null) { |
| 182 container.inferredLength = container.originalLength; | 182 container.inferredLength = container.originalLength; |
| 183 } | 183 } |
| 184 return assignments; | 184 return assignments; |
| 185 } | 185 } |
| 186 return null; | 186 return null; |
| 187 } | 187 } |
| 188 | 188 |
| 189 void bailout(String reason) { | 189 void bailout(String reason) { |
| 190 if (_VERBOSE) { | 190 if (_VERBOSE) { |
| 191 ContainerTypeMask mask = container.type; | 191 ContainerTypeMask mask = container.type; |
| 192 print('Bailing out on ${mask.allocationNode} ${mask.allocationElement} ' | 192 print('Bailing out on ${mask.allocationNode} ${mask.allocationElement} ' |
| 193 'because: $reason'); | 193 'because: $reason'); |
| 194 } | 194 } |
| 195 continueAnalyzing = false; | 195 continueAnalyzing = false; |
| 196 enableLengthTracking = false; | 196 callsGrowableMethod = true; |
| 197 } | 197 } |
| 198 | 198 |
| 199 visitNarrowTypeInformation(NarrowTypeInformation info) {} | 199 visitNarrowTypeInformation(NarrowTypeInformation info) {} |
| 200 visitPhiElementTypeInformation(PhiElementTypeInformation info) {} | 200 visitPhiElementTypeInformation(PhiElementTypeInformation info) {} |
| 201 visitElementInContainerTypeInformation( | 201 visitElementInContainerTypeInformation( |
| 202 ElementInContainerTypeInformation info) {} | 202 ElementInContainerTypeInformation info) {} |
| 203 | 203 |
| 204 visitContainerTypeInformation(ContainerTypeInformation info) { | 204 visitContainerTypeInformation(ContainerTypeInformation info) { |
| 205 if (container != info) { | 205 if (container != info) { |
| 206 bailout('Stored in a container'); | 206 bailout('Stored in a container'); |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 241 return; | 241 return; |
| 242 } | 242 } |
| 243 } else if (selector.isIndexSet()) { | 243 } else if (selector.isIndexSet()) { |
| 244 assignments.add(info.arguments.positional[1]); | 244 assignments.add(info.arguments.positional[1]); |
| 245 } else if (!selector.isIndex()) { | 245 } else if (!selector.isIndex()) { |
| 246 bailout('Used in a not-ok selector'); | 246 bailout('Used in a not-ok selector'); |
| 247 return; | 247 return; |
| 248 } | 248 } |
| 249 } | 249 } |
| 250 if (!doNotChangeLengthSelectorsSet.contains(selectorName)) { | 250 if (!doNotChangeLengthSelectorsSet.contains(selectorName)) { |
| 251 enableLengthTracking = false; | 251 callsGrowableMethod = true; |
| 252 } | 252 } |
| 253 if (selectorName == 'length' && selector.isSetter()) { | 253 if (selectorName == 'length' && selector.isSetter()) { |
| 254 enableLengthTracking = false; | 254 callsGrowableMethod = true; |
| 255 assignments.add(inferrer.types.nullType); | 255 assignments.add(inferrer.types.nullType); |
| 256 } | 256 } |
| 257 } else if (selector.isCall() | 257 } else if (selector.isCall() |
| 258 && !info.targets.every((element) => element.isFunction())) { | 258 && !info.targets.every((element) => element.isFunction())) { |
| 259 bailout('Passed to a closure'); | 259 bailout('Passed to a closure'); |
| 260 return; | 260 return; |
| 261 } | 261 } |
| 262 } | 262 } |
| 263 | 263 |
| 264 bool isClosure(Element element) { | 264 bool isClosure(Element element) { |
| 265 if (!element.isFunction()) return false; | 265 if (!element.isFunction()) return false; |
| 266 Element outermost = element.getOutermostEnclosingMemberOrTopLevel(); | 266 Element outermost = element.getOutermostEnclosingMemberOrTopLevel(); |
| 267 return outermost.declaration != element.declaration; | 267 return outermost.declaration != element.declaration; |
| 268 } | 268 } |
| 269 | 269 |
| 270 visitElementTypeInformation(ElementTypeInformation info) { | 270 visitElementTypeInformation(ElementTypeInformation info) { |
| 271 if (isClosure(info.element)) { | 271 if (isClosure(info.element)) { |
| 272 bailout('Returned from a closure'); | 272 bailout('Returned from a closure'); |
| 273 } | 273 } |
| 274 } | 274 } |
| 275 } | 275 } |
| OLD | NEW |