| 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 152 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 163 '[]=', | 163 '[]=', |
| 164 | 164 |
| 165 // From JSArray. | 165 // From JSArray. |
| 166 'checkMutable', | 166 'checkMutable', |
| 167 'checkGrowable', | 167 'checkGrowable', |
| 168 ]); | 168 ]); |
| 169 | 169 |
| 170 bool _VERBOSE = false; | 170 bool _VERBOSE = false; |
| 171 | 171 |
| 172 class ContainerTracerVisitor implements TypeInformationVisitor { | 172 class ContainerTracerVisitor implements TypeInformationVisitor { |
| 173 final ContainerTypeInformation container; | 173 final ListTypeInformation container; |
| 174 final TypeGraphInferrerEngine inferrer; | 174 final TypeGraphInferrerEngine inferrer; |
| 175 final Compiler compiler; | 175 final Compiler compiler; |
| 176 | 176 |
| 177 | 177 |
| 178 // Work list that gets populated with [TypeInformation] that could | 178 // Work list that gets populated with [TypeInformation] that could |
| 179 // contain the container. | 179 // contain the container. |
| 180 final List<TypeInformation> workList = <TypeInformation>[]; | 180 final List<TypeInformation> workList = <TypeInformation>[]; |
| 181 | 181 |
| 182 // Work list of containers to analyze after analyzing the users of a | 182 // Work list of containers to analyze after analyzing the users of a |
| 183 // [TypeInformation] that may be [container]. We know [container] | 183 // [TypeInformation] that may be [container]. We know [container] |
| 184 // has been stored in these containers and we must check how | 184 // has been stored in these containers and we must check how |
| 185 // [container] escapes from these containers. | 185 // [container] escapes from these containers. |
| 186 final List<ContainerTypeInformation> containersToAnalyze = | 186 final List<ListTypeInformation> containersToAnalyze = |
| 187 <ContainerTypeInformation>[]; | 187 <ListTypeInformation>[]; |
| 188 | 188 |
| 189 // The current [TypeInformation] in the analysis. | 189 // The current [TypeInformation] in the analysis. |
| 190 TypeInformation currentUser; | 190 TypeInformation currentUser; |
| 191 | 191 |
| 192 // The list of found assignments to the container. | 192 // The list of found assignments to the container. |
| 193 final List<TypeInformation> assignments = <TypeInformation>[]; | 193 final List<TypeInformation> assignments = <TypeInformation>[]; |
| 194 | 194 |
| 195 bool callsGrowableMethod = false; | 195 bool callsGrowableMethod = false; |
| 196 bool continueAnalyzing = true; | 196 bool continueAnalyzing = true; |
| 197 | 197 |
| (...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 252 | 252 |
| 253 visitPhiElementTypeInformation(PhiElementTypeInformation info) { | 253 visitPhiElementTypeInformation(PhiElementTypeInformation info) { |
| 254 addNewEscapeInformation(info); | 254 addNewEscapeInformation(info); |
| 255 } | 255 } |
| 256 | 256 |
| 257 visitElementInContainerTypeInformation( | 257 visitElementInContainerTypeInformation( |
| 258 ElementInContainerTypeInformation info) { | 258 ElementInContainerTypeInformation info) { |
| 259 addNewEscapeInformation(info); | 259 addNewEscapeInformation(info); |
| 260 } | 260 } |
| 261 | 261 |
| 262 visitContainerTypeInformation(ContainerTypeInformation info) { | 262 visitListTypeInformation(ListTypeInformation info) { |
| 263 containersToAnalyze.add(info); | 263 containersToAnalyze.add(info); |
| 264 } | 264 } |
| 265 | 265 |
| 266 visitMapTypeInformation(MapTypeInformation info) { |
| 267 bailout('Stored in a map'); |
| 268 } |
| 269 |
| 266 visitConcreteTypeInformation(ConcreteTypeInformation info) {} | 270 visitConcreteTypeInformation(ConcreteTypeInformation info) {} |
| 267 | 271 |
| 268 visitClosureCallSiteTypeInformation(ClosureCallSiteTypeInformation info) { | 272 visitClosureCallSiteTypeInformation(ClosureCallSiteTypeInformation info) { |
| 269 bailout('Passed to a closure'); | 273 bailout('Passed to a closure'); |
| 270 } | 274 } |
| 271 | 275 |
| 272 visitStaticCallSiteTypeInformation(StaticCallSiteTypeInformation info) { | 276 visitStaticCallSiteTypeInformation(StaticCallSiteTypeInformation info) { |
| 273 Element called = info.calledElement; | 277 Element called = info.calledElement; |
| 274 if (called.isForeign(compiler) && called.name == 'JS') { | 278 if (called.isForeign(compiler) && called.name == 'JS') { |
| 275 bailout('Used in JS ${info.call}'); | 279 bailout('Used in JS ${info.call}'); |
| 276 } | 280 } |
| 277 if (inferrer.types.getInferredTypeOf(called) == currentUser) { | 281 if (inferrer.types.getInferredTypeOf(called) == currentUser) { |
| 278 addNewEscapeInformation(info); | 282 addNewEscapeInformation(info); |
| 279 } | 283 } |
| 280 } | 284 } |
| 281 | 285 |
| 282 void analyzeStoredIntoContainer(ContainerTypeInformation container) { | 286 void analyzeStoredIntoContainer(ListTypeInformation container) { |
| 283 inferrer.analyzeContainer(container); | 287 inferrer.analyzeContainer(container); |
| 284 if (container.bailedOut) { | 288 if (container.bailedOut) { |
| 285 bailout('Stored in a container that bailed out'); | 289 bailout('Stored in a container that bailed out'); |
| 286 } else { | 290 } else { |
| 287 container.flowsInto.forEach((flow) { | 291 container.flowsInto.forEach((flow) { |
| 288 flow.users.forEach((user) { | 292 flow.users.forEach((user) { |
| 289 if (user is !DynamicCallSiteTypeInformation) return; | 293 if (user is !DynamicCallSiteTypeInformation) return; |
| 290 if (user.receiver != flow) return; | 294 if (user.receiver != flow) return; |
| 291 if (returnsElementTypeSet.contains(user.selector)) { | 295 if (returnsElementTypeSet.contains(user.selector)) { |
| 292 addNewEscapeInformation(user); | 296 addNewEscapeInformation(user); |
| (...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 341 callsGrowableMethod = true; | 345 callsGrowableMethod = true; |
| 342 assignments.add(inferrer.types.nullType); | 346 assignments.add(inferrer.types.nullType); |
| 343 } | 347 } |
| 344 } else if (selector.isCall() | 348 } else if (selector.isCall() |
| 345 && !info.targets.every((element) => element.isFunction())) { | 349 && !info.targets.every((element) => element.isFunction())) { |
| 346 bailout('Passed to a closure'); | 350 bailout('Passed to a closure'); |
| 347 return; | 351 return; |
| 348 } else if (isAddedToContainer(info)) { | 352 } else if (isAddedToContainer(info)) { |
| 349 ContainerTypeMask mask = info.receiver.type; | 353 ContainerTypeMask mask = info.receiver.type; |
| 350 if (mask.allocationNode != null) { | 354 if (mask.allocationNode != null) { |
| 351 ContainerTypeInformation container = | 355 ListTypeInformation container = |
| 352 inferrer.types.allocatedContainers[mask.allocationNode]; | 356 inferrer.types.allocatedLists[mask.allocationNode]; |
| 353 containersToAnalyze.add(container); | 357 containersToAnalyze.add(container); |
| 354 } else { | 358 } else { |
| 355 // The [ContainerTypeMask] is a union of two containers, and | 359 // The [ContainerTypeMask] is a union of two containers, and |
| 356 // we lose track of where these containers have been allocated | 360 // we lose track of where these containers have been allocated |
| 357 // at this point. | 361 // at this point. |
| 358 bailout('Stored in too many containers'); | 362 bailout('Stored in too many containers'); |
| 359 } | 363 } |
| 360 } | 364 } |
| 361 | 365 |
| 362 if (info.targets | 366 if (info.targets |
| (...skipping 28 matching lines...) Expand all Loading... |
| 391 bailout('Escape in reflection'); | 395 bailout('Escape in reflection'); |
| 392 } | 396 } |
| 393 if (isParameterOfListAddingMethod(info.element)) { | 397 if (isParameterOfListAddingMethod(info.element)) { |
| 394 // These elements are being handled in | 398 // These elements are being handled in |
| 395 // [visitDynamicCallSiteTypeInformation]. | 399 // [visitDynamicCallSiteTypeInformation]. |
| 396 return; | 400 return; |
| 397 } | 401 } |
| 398 addNewEscapeInformation(info); | 402 addNewEscapeInformation(info); |
| 399 } | 403 } |
| 400 } | 404 } |
| OLD | NEW |