Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2012, 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 import 'common/names.dart' show Identifiers; | 5 import 'common/names.dart' show Identifiers; |
| 6 import 'common/resolution.dart' show ParsingContext, Resolution; | 6 import 'common/resolution.dart' show ParsingContext, Resolution; |
| 7 import 'common/tasks.dart' show CompilerTask, Measurer; | 7 import 'common/tasks.dart' show CompilerTask, Measurer; |
| 8 import 'common.dart'; | 8 import 'common.dart'; |
| 9 import 'compiler.dart' show Compiler; | 9 import 'compiler.dart' show Compiler; |
| 10 import 'constants/expressions.dart'; | 10 import 'constants/expressions.dart'; |
| (...skipping 24 matching lines...) Expand all Loading... | |
| 35 ClosedWorldRefiner closedWorldRefiner); | 35 ClosedWorldRefiner closedWorldRefiner); |
| 36 } | 36 } |
| 37 | 37 |
| 38 /// Class that provides information for how closures are rewritten/represented | 38 /// Class that provides information for how closures are rewritten/represented |
| 39 /// to preserve Dart semantics when compiled to JavaScript. Given a particular | 39 /// to preserve Dart semantics when compiled to JavaScript. Given a particular |
| 40 /// node to look up, it returns a information about the internal representation | 40 /// node to look up, it returns a information about the internal representation |
| 41 /// of how closure conversion is implemented. T is an ir.Node or Node. | 41 /// of how closure conversion is implemented. T is an ir.Node or Node. |
| 42 abstract class ClosureDataLookup<T> { | 42 abstract class ClosureDataLookup<T> { |
| 43 /// Look up information about the variables that have been mutated and are | 43 /// Look up information about the variables that have been mutated and are |
| 44 /// used inside the scope of [node]. | 44 /// used inside the scope of [node]. |
| 45 // TODO(johnniwinther): Split this up into two functions, one for members and | 45 ScopeInfo getScopeInfo(MemberEntity member); |
| 46 // one for local functions. | |
| 47 ScopeInfo getScopeInfo(covariant Entity member); | |
| 48 | 46 |
| 49 /// This returns the same information as ScopeInfo, but can be called in | 47 /// This returns the same information as ScopeInfo, but can be called in |
| 50 /// situations when you are sure you are dealing with a closure specifically. | 48 /// situations when you are sure you are dealing with a closure specifically. |
| 51 ClosureRepresentationInfo getClosureRepresentationInfo( | 49 // TODO(johnniwinther,efortuna): Can we use [getScopeInfo] instead? |
|
Emily Fortuna
2017/08/18 21:04:43
you should be able to. In fact, getScopeInfo curre
Johnni Winther
2017/08/19 08:28:28
Ok, I'll look into it.
| |
| 52 covariant Entity member); | 50 ClosureRepresentationInfo getMemberRepresentationInfo(MemberEntity member); |
|
Emily Fortuna
2017/08/18 21:04:43
consider calling these:
getClosureInfoForMember
ge
Johnni Winther
2017/08/19 08:28:28
Done.
| |
| 51 | |
| 52 ClosureRepresentationInfo getClosureRepresentationInfo(T localFunction); | |
| 53 | |
| 54 ClosureRepresentationInfo getMemberRepresentationInfoForTesting( | |
| 55 MemberEntity member); | |
| 53 | 56 |
| 54 ClosureRepresentationInfo getClosureRepresentationInfoForTesting( | 57 ClosureRepresentationInfo getClosureRepresentationInfoForTesting( |
| 55 covariant Entity member); | 58 T localFunction); |
| 56 | 59 |
| 57 /// Look up information about a loop, in case any variables it declares need | 60 /// Look up information about a loop, in case any variables it declares need |
| 58 /// to be boxed/snapshotted. | 61 /// to be boxed/snapshotted. |
| 59 CapturedLoopScope getCapturedLoopScope(T loopNode); | 62 CapturedLoopScope getCapturedLoopScope(T loopNode); |
| 60 | 63 |
| 61 /// Accessor to the information about scopes that closures capture. Used by | 64 /// Accessor to the information about scopes that closures capture. Used by |
| 62 /// the SSA builder. | 65 /// the SSA builder. |
| 63 CapturedScope getCapturedScope(MemberEntity entity); | 66 CapturedScope getCapturedScope(MemberEntity entity); |
| 64 } | 67 } |
| 65 | 68 |
| (...skipping 183 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 249 bool isVariableBoxed(Local variable) => false; | 252 bool isVariableBoxed(Local variable) => false; |
| 250 | 253 |
| 251 // TODO(efortuna): Remove this method. The old system was using | 254 // TODO(efortuna): Remove this method. The old system was using |
| 252 // ClosureClassMaps for situations other than closure class maps, and that's | 255 // ClosureClassMaps for situations other than closure class maps, and that's |
| 253 // just confusing. | 256 // just confusing. |
| 254 bool get isClosure => false; | 257 bool get isClosure => false; |
| 255 } | 258 } |
| 256 | 259 |
| 257 class ClosureTask extends ClosureConversionTask<Node> { | 260 class ClosureTask extends ClosureConversionTask<Node> { |
| 258 Map<Node, CapturedScopeImpl> _closureInfoMap = <Node, CapturedScopeImpl>{}; | 261 Map<Node, CapturedScopeImpl> _closureInfoMap = <Node, CapturedScopeImpl>{}; |
| 259 Map<Element, ClosureClassMap> _closureMappingCache = | 262 Map<MemberElement, ClosureClassMap> _closureMemberMappingCache = |
| 260 <Element, ClosureClassMap>{}; | 263 <MemberElement, ClosureClassMap>{}; |
| 264 Map<FunctionExpression, ClosureClassMap> _closureNodeMappingCache = | |
| 265 <FunctionExpression, ClosureClassMap>{}; | |
| 261 Compiler compiler; | 266 Compiler compiler; |
| 262 ClosureTask(Compiler compiler) | 267 ClosureTask(Compiler compiler) |
| 263 : compiler = compiler, | 268 : compiler = compiler, |
| 264 super(compiler.measurer); | 269 super(compiler.measurer); |
| 265 | 270 |
| 266 String get name => "Closure Simplifier"; | 271 String get name => "Closure Simplifier"; |
| 267 | 272 |
| 268 DiagnosticReporter get reporter => compiler.reporter; | 273 DiagnosticReporter get reporter => compiler.reporter; |
| 269 | 274 |
| 270 void convertClosures(Iterable<MemberEntity> processedEntities, | 275 void convertClosures(Iterable<MemberEntity> processedEntities, |
| 271 ClosedWorldRefiner closedWorldRefiner) { | 276 ClosedWorldRefiner closedWorldRefiner) { |
| 272 createClosureClasses(closedWorldRefiner); | 277 createClosureClasses(closedWorldRefiner); |
| 273 } | 278 } |
| 274 | 279 |
| 275 CapturedScope _getCapturedScope(Node node) { | 280 CapturedScope _getCapturedScope(Node node) { |
| 276 var value = _closureInfoMap[node]; | 281 var value = _closureInfoMap[node]; |
| 277 return value == null ? const CapturedScope() : value; | 282 return value == null ? const CapturedScope() : value; |
| 278 } | 283 } |
| 279 | 284 |
| 280 CapturedScope getCapturedScope(covariant MemberElement member) { | 285 CapturedScope getCapturedScope(covariant MemberElement member) { |
| 281 ResolvedAst resolvedAst = member.resolvedAst; | 286 ResolvedAst resolvedAst = member.resolvedAst; |
| 282 if (resolvedAst.kind != ResolvedAstKind.PARSED) | 287 if (resolvedAst.kind != ResolvedAstKind.PARSED) |
| 283 return const CapturedScope(); | 288 return const CapturedScope(); |
| 284 return _getCapturedScope(resolvedAst.node); | 289 return _getCapturedScope(resolvedAst.node); |
| 285 } | 290 } |
| 286 | 291 |
| 287 ScopeInfo getScopeInfo(Element member) { | 292 ScopeInfo getScopeInfo(MemberEntity member) { |
| 288 return getClosureToClassMapping(member); | 293 return _getMemberMapping(member); |
| 289 } | 294 } |
| 290 | 295 |
| 291 ClosureRepresentationInfo getClosureRepresentationInfo(Element member) { | 296 ClosureRepresentationInfo getMemberRepresentationInfo(MemberEntity member) { |
| 292 return getClosureToClassMapping(member); | 297 return _getMemberMapping(member); |
| 298 } | |
| 299 | |
| 300 ClosureRepresentationInfo getClosureRepresentationInfo( | |
| 301 covariant FunctionExpression node) { | |
| 302 return _getClosureMapping(node); | |
| 303 } | |
| 304 | |
| 305 ClosureRepresentationInfo getMemberRepresentationInfoForTesting( | |
| 306 MemberEntity member) { | |
| 307 return getMemberRepresentationInfo(member); | |
| 293 } | 308 } |
| 294 | 309 |
| 295 ClosureRepresentationInfo getClosureRepresentationInfoForTesting( | 310 ClosureRepresentationInfo getClosureRepresentationInfoForTesting( |
| 296 Element member) { | 311 covariant FunctionExpression node) { |
| 297 return getClosureRepresentationInfo(member); | 312 return getClosureRepresentationInfo(node); |
| 298 } | 313 } |
| 299 | 314 |
| 300 CapturedLoopScope getCapturedLoopScope(Node loopNode) { | 315 CapturedLoopScope getCapturedLoopScope(Node loopNode) { |
| 301 var value = _closureInfoMap[loopNode]; | 316 var value = _closureInfoMap[loopNode]; |
| 302 return value == null ? const CapturedLoopScope() : value; | 317 return value == null ? const CapturedLoopScope() : value; |
| 303 } | 318 } |
| 304 | 319 |
| 305 /// Returns the [ClosureClassMap] computed for [resolvedAst]. | 320 /// Returns the [ClosureClassMap] computed for [element]. |
| 306 ClosureClassMap getClosureToClassMapping(Element element) { | 321 ClosureClassMap _getMemberMapping(MemberElement element) { |
| 307 return measure(() { | 322 return measure(() { |
| 308 if (element.isGenerativeConstructorBody) { | 323 if (element.isGenerativeConstructorBody) { |
| 309 ConstructorBodyElement constructorBody = element; | 324 ConstructorBodyElement constructorBody = element; |
| 310 element = constructorBody.constructor; | 325 element = constructorBody.constructor; |
| 311 } | 326 } |
| 312 ClosureClassMap closureClassMap = _closureMappingCache[element]; | 327 ClosureClassMap closureClassMap = _closureMemberMappingCache[element]; |
| 313 assert(closureClassMap != null, | 328 assert(closureClassMap != null, |
| 314 failedAt(element, "No ClosureClassMap computed for ${element}.")); | 329 failedAt(element, "No ClosureClassMap computed for ${element}.")); |
| 315 return closureClassMap; | 330 return closureClassMap; |
| 316 }); | 331 }); |
| 317 } | 332 } |
| 318 | 333 |
| 334 /// Returns the [ClosureClassMap] computed for [node]. | |
| 335 ClosureClassMap _getClosureMapping(FunctionExpression node) { | |
| 336 return measure(() { | |
| 337 ClosureClassMap closureClassMap = _closureNodeMappingCache[node]; | |
| 338 assert(closureClassMap != null, | |
| 339 failedAt(node, "No ClosureClassMap computed for ${node}.")); | |
| 340 return closureClassMap; | |
| 341 }); | |
| 342 } | |
| 343 | |
| 319 /// Create [ClosureClassMap]s for all live members. | 344 /// Create [ClosureClassMap]s for all live members. |
| 320 void createClosureClasses(ClosedWorldRefiner closedWorldRefiner) { | 345 void createClosureClasses(ClosedWorldRefiner closedWorldRefiner) { |
| 321 compiler.enqueuer.resolution.processedEntities | 346 compiler.enqueuer.resolution.processedEntities |
| 322 .forEach((MemberEntity _element) { | 347 .forEach((MemberEntity _element) { |
| 323 MemberElement element = _element; | 348 MemberElement element = _element; |
| 324 ResolvedAst resolvedAst = element.resolvedAst; | 349 ResolvedAst resolvedAst = element.resolvedAst; |
| 325 if (element.isAbstract) return; | 350 if (element.isAbstract) return; |
| 326 if (element.isField && | 351 if (element.isField && |
| 327 !element.isInstanceMember && | 352 !element.isInstanceMember && |
| 328 resolvedAst.body == null) { | 353 resolvedAst.body == null) { |
| 329 // Skip top-level/static fields without an initializer. | 354 // Skip top-level/static fields without an initializer. |
| 330 return; | 355 return; |
| 331 } | 356 } |
| 332 computeClosureToClassMapping(element, closedWorldRefiner); | 357 computeClosureToClassMapping(element, closedWorldRefiner); |
| 333 }); | 358 }); |
| 334 } | 359 } |
| 335 | 360 |
| 336 ClosureClassMap computeClosureToClassMapping( | 361 ClosureClassMap computeClosureToClassMapping( |
| 337 MemberElement element, ClosedWorldRefiner closedWorldRefiner) { | 362 MemberElement element, ClosedWorldRefiner closedWorldRefiner) { |
| 338 return measure(() { | 363 return measure(() { |
| 339 ClosureClassMap cached = _closureMappingCache[element]; | 364 ClosureClassMap cached = _closureMemberMappingCache[element]; |
| 340 if (cached != null) return cached; | 365 if (cached != null) return cached; |
| 341 if (element.resolvedAst.kind != ResolvedAstKind.PARSED) { | 366 if (element.resolvedAst.kind != ResolvedAstKind.PARSED) { |
| 342 return _closureMappingCache[element] = | 367 return _closureMemberMappingCache[element] = |
| 343 new ClosureClassMap(null, null, null, new ThisLocal(element)); | 368 new ClosureClassMap(null, null, null, new ThisLocal(element)); |
| 344 } | 369 } |
| 345 return reporter.withCurrentElement(element.implementation, () { | 370 return reporter.withCurrentElement(element.implementation, () { |
| 346 Node node = element.resolvedAst.node; | 371 Node node = element.resolvedAst.node; |
| 347 TreeElements elements = element.resolvedAst.elements; | 372 TreeElements elements = element.resolvedAst.elements; |
| 348 | 373 |
| 349 ClosureTranslator translator = new ClosureTranslator( | 374 ClosureTranslator translator = new ClosureTranslator( |
| 350 compiler, | 375 compiler, |
| 351 closedWorldRefiner, | 376 closedWorldRefiner, |
| 352 elements, | 377 elements, |
| 353 _closureMappingCache, | 378 _closureMemberMappingCache, |
| 379 _closureNodeMappingCache, | |
| 354 _closureInfoMap); | 380 _closureInfoMap); |
| 355 | 381 |
| 356 // The translator will store the computed closure-mappings inside the | 382 // The translator will store the computed closure-mappings inside the |
| 357 // cache. One for given node and one for each nested closure. | 383 // cache. One for given node and one for each nested closure. |
| 358 if (node is FunctionExpression) { | 384 if (node is FunctionExpression) { |
| 359 translator.translateFunction(element, node); | 385 translator.translateFunction(element, node); |
| 360 } else if (element.isSynthesized) { | 386 } else if (element.isSynthesized) { |
| 361 reporter.internalError( | 387 reporter.internalError( |
| 362 element, "Unexpected synthesized element: $element"); | 388 element, "Unexpected synthesized element: $element"); |
| 363 _closureMappingCache[element] = | 389 _closureMemberMappingCache[element] = |
| 364 new ClosureClassMap(null, null, null, new ThisLocal(element)); | 390 new ClosureClassMap(null, null, null, new ThisLocal(element)); |
| 365 } else { | 391 } else { |
| 366 assert(element.isField, | 392 assert(element.isField, |
| 367 failedAt(element, "Expected $element to be a field.")); | 393 failedAt(element, "Expected $element to be a field.")); |
| 368 Node initializer = element.resolvedAst.body; | 394 Node initializer = element.resolvedAst.body; |
| 369 if (initializer != null) { | 395 if (initializer != null) { |
| 370 // The lazy initializer of a static. | 396 // The lazy initializer of a static. |
| 371 translator.translateLazyInitializer(element, node, initializer); | 397 translator.translateLazyInitializer(element, node, initializer); |
| 372 } else { | 398 } else { |
| 373 assert( | 399 assert( |
| 374 element.isInstanceMember, | 400 element.isInstanceMember, |
| 375 failedAt( | 401 failedAt( |
| 376 element, | 402 element, |
| 377 "Expected $element (${element.runtimeType}) " | 403 "Expected $element (${element.runtimeType}) " |
| 378 "to be an instance field.")); | 404 "to be an instance field.")); |
| 379 _closureMappingCache[element] = | 405 _closureMemberMappingCache[element] = |
| 380 new ClosureClassMap(null, null, null, new ThisLocal(element)); | 406 new ClosureClassMap(null, null, null, new ThisLocal(element)); |
| 381 } | 407 } |
| 382 } | 408 } |
| 383 assert(_closureMappingCache[element] != null, | 409 assert(_closureMemberMappingCache[element] != null, |
| 384 failedAt(element, "No ClosureClassMap computed for ${element}.")); | 410 failedAt(element, "No ClosureClassMap computed for ${element}.")); |
| 385 return _closureMappingCache[element]; | 411 return _closureMemberMappingCache[element]; |
| 386 }); | 412 }); |
| 387 }); | 413 }); |
| 388 } | 414 } |
| 389 } | 415 } |
| 390 | 416 |
| 391 // TODO(ahe): These classes continuously cause problems. We need to | 417 // TODO(ahe): These classes continuously cause problems. We need to |
| 392 // find a more general solution. | 418 // find a more general solution. |
| 393 class ClosureFieldElement extends ElementX | 419 class ClosureFieldElement extends ElementX |
| 394 implements FieldElement, PrivatelyNamedJSEntity { | 420 implements FieldElement, PrivatelyNamedJSEntity { |
| 395 /// The [BoxLocal] or [LocalElement] being accessed through the field. | 421 /// The [BoxLocal] or [LocalElement] being accessed through the field. |
| (...skipping 454 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 850 } | 876 } |
| 851 | 877 |
| 852 class ClosureTranslator extends Visitor { | 878 class ClosureTranslator extends Visitor { |
| 853 final Compiler compiler; | 879 final Compiler compiler; |
| 854 final ClosedWorldRefiner closedWorldRefiner; | 880 final ClosedWorldRefiner closedWorldRefiner; |
| 855 final TreeElements elements; | 881 final TreeElements elements; |
| 856 int closureFieldCounter = 0; | 882 int closureFieldCounter = 0; |
| 857 int boxedFieldCounter = 0; | 883 int boxedFieldCounter = 0; |
| 858 bool inTryStatement = false; | 884 bool inTryStatement = false; |
| 859 | 885 |
| 860 final Map<Element, ClosureClassMap> closureMappingCache; | 886 final Map<MemberElement, ClosureClassMap> memberMappingCache; |
| 887 final Map<FunctionExpression, ClosureClassMap> nodeMappingCache; | |
| 861 final Map<Node, CapturedScopeImpl> closureInfo; | 888 final Map<Node, CapturedScopeImpl> closureInfo; |
| 862 | 889 |
| 863 // Map of captured variables. Initially they will map to `null`. If | 890 // Map of captured variables. Initially they will map to `null`. If |
| 864 // a variable needs to be boxed then the scope declaring the variable | 891 // a variable needs to be boxed then the scope declaring the variable |
| 865 // will update this to mapping to the capturing [BoxFieldElement]. | 892 // will update this to mapping to the capturing [BoxFieldElement]. |
| 866 Map<Local, BoxFieldElement> _capturedVariableMapping = | 893 Map<Local, BoxFieldElement> _capturedVariableMapping = |
| 867 new Map<Local, BoxFieldElement>(); | 894 new Map<Local, BoxFieldElement>(); |
| 868 | 895 |
| 869 // List of encountered closures. | 896 // List of encountered closures. |
| 870 List<LocalFunctionElement> closures = <LocalFunctionElement>[]; | 897 List<FunctionExpression> closures = <FunctionExpression>[]; |
| 871 | 898 |
| 872 // The local variables that have been declared in the current scope. | 899 // The local variables that have been declared in the current scope. |
| 873 List<LocalVariableElement> scopeVariables; | 900 List<LocalVariableElement> scopeVariables; |
| 874 | 901 |
| 875 // Keep track of the mutated local variables so that we don't need to box | 902 // Keep track of the mutated local variables so that we don't need to box |
| 876 // non-mutated variables. | 903 // non-mutated variables. |
| 877 Set<LocalVariableElement> mutatedVariables = new Set<LocalVariableElement>(); | 904 Set<LocalVariableElement> mutatedVariables = new Set<LocalVariableElement>(); |
| 878 | 905 |
| 879 MemberElement outermostElement; | 906 MemberElement outermostElement; |
| 880 ExecutableElement executableContext; | 907 ExecutableElement executableContext; |
| 881 | 908 |
| 882 // The closureData of the currentFunctionElement. | 909 // The closureData of the currentFunctionElement. |
| 883 ClosureClassMap closureData; | 910 ClosureClassMap closureData; |
| 884 | 911 |
| 885 bool insideClosure = false; | 912 bool insideClosure = false; |
| 886 | 913 |
| 887 ClosureTranslator(this.compiler, this.closedWorldRefiner, this.elements, | 914 ClosureTranslator(this.compiler, this.closedWorldRefiner, this.elements, |
| 888 this.closureMappingCache, this.closureInfo); | 915 this.memberMappingCache, this.nodeMappingCache, this.closureInfo); |
| 889 | 916 |
| 890 DiagnosticReporter get reporter => compiler.reporter; | 917 DiagnosticReporter get reporter => compiler.reporter; |
| 891 | 918 |
| 892 RuntimeTypesNeed get rtiNeed => closedWorldRefiner.closedWorld.rtiNeed; | 919 RuntimeTypesNeed get rtiNeed => closedWorldRefiner.closedWorld.rtiNeed; |
| 893 | 920 |
| 894 /// Generate a unique name for the [id]th closure field, with proposed name | 921 /// Generate a unique name for the [id]th closure field, with proposed name |
| 895 /// [name]. | 922 /// [name]. |
| 896 /// | 923 /// |
| 897 /// The result is used as the name of [ClosureFieldElement]s, and must | 924 /// The result is used as the name of [ClosureFieldElement]s, and must |
| 898 /// therefore be unique to avoid breaking an invariant in the element model | 925 /// therefore be unique to avoid breaking an invariant in the element model |
| (...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 958 visitInvokable(element, node, () { | 985 visitInvokable(element, node, () { |
| 959 visit(initializer); | 986 visit(initializer); |
| 960 }); | 987 }); |
| 961 updateClosures(); | 988 updateClosures(); |
| 962 } | 989 } |
| 963 | 990 |
| 964 // This function runs through all of the existing closures and updates their | 991 // This function runs through all of the existing closures and updates their |
| 965 // free variables to the boxed value. It also adds the field-elements to the | 992 // free variables to the boxed value. It also adds the field-elements to the |
| 966 // class representing the closure. | 993 // class representing the closure. |
| 967 void updateClosures() { | 994 void updateClosures() { |
| 968 for (LocalFunctionElement closure in closures) { | 995 for (FunctionExpression closure in closures) { |
| 969 // The captured variables that need to be stored in a field of the closure | 996 // The captured variables that need to be stored in a field of the closure |
| 970 // class. | 997 // class. |
| 971 Set<Local> fieldCaptures = new Set<Local>(); | 998 Set<Local> fieldCaptures = new Set<Local>(); |
| 972 Set<BoxLocal> boxes = new Set<BoxLocal>(); | 999 Set<BoxLocal> boxes = new Set<BoxLocal>(); |
| 973 ClosureClassMap data = closureMappingCache[closure]; | 1000 ClosureClassMap data = nodeMappingCache[closure]; |
| 974 // We get a copy of the keys and iterate over it, to avoid modifications | 1001 // We get a copy of the keys and iterate over it, to avoid modifications |
| 975 // to the map while iterating over it. | 1002 // to the map while iterating over it. |
| 976 Iterable<Local> freeVariables = data.freeVariables.toList(); | 1003 Iterable<Local> freeVariables = data.freeVariables.toList(); |
| 977 freeVariables.forEach((Local fromElement) { | 1004 freeVariables.forEach((Local fromElement) { |
| 978 assert(data.isFreeVariable(fromElement)); | 1005 assert(data.isFreeVariable(fromElement)); |
| 979 assert(data.freeVariableMap[fromElement] == null); | 1006 assert(data.freeVariableMap[fromElement] == null); |
| 980 assert(isCapturedVariable(fromElement)); | 1007 assert(isCapturedVariable(fromElement)); |
| 981 BoxFieldElement boxFieldElement = | 1008 BoxFieldElement boxFieldElement = |
| 982 getCapturedVariableBoxField(fromElement); | 1009 getCapturedVariableBoxField(fromElement); |
| 983 if (boxFieldElement == null) { | 1010 if (boxFieldElement == null) { |
| (...skipping 423 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1407 bool oldInsideClosure = insideClosure; | 1434 bool oldInsideClosure = insideClosure; |
| 1408 Element oldFunctionElement = executableContext; | 1435 Element oldFunctionElement = executableContext; |
| 1409 ClosureClassMap oldClosureData = closureData; | 1436 ClosureClassMap oldClosureData = closureData; |
| 1410 | 1437 |
| 1411 insideClosure = outermostElement != null; | 1438 insideClosure = outermostElement != null; |
| 1412 LocalFunctionElement closure; | 1439 LocalFunctionElement closure; |
| 1413 executableContext = element; | 1440 executableContext = element; |
| 1414 bool needsRti = false; | 1441 bool needsRti = false; |
| 1415 if (insideClosure) { | 1442 if (insideClosure) { |
| 1416 closure = element; | 1443 closure = element; |
| 1417 closures.add(closure); | 1444 closures.add(node); |
| 1418 closureData = globalizeClosure(node, closure); | 1445 nodeMappingCache[node] = closureData = globalizeClosure(node, closure); |
| 1419 needsRti = compiler.options.enableTypeAssertions || | 1446 needsRti = compiler.options.enableTypeAssertions || |
| 1420 rtiNeed.localFunctionNeedsRti(closure); | 1447 rtiNeed.localFunctionNeedsRti(closure); |
| 1421 } else { | 1448 } else { |
| 1422 outermostElement = element; | 1449 outermostElement = element; |
| 1423 ThisLocal thisElement = null; | 1450 ThisLocal thisElement = null; |
| 1424 if (element.isInstanceMember || element.isGenerativeConstructor) { | 1451 if (element.isInstanceMember || element.isGenerativeConstructor) { |
| 1425 MemberElement member = element; | 1452 MemberElement member = element; |
| 1426 thisElement = new ThisLocal(member); | 1453 thisElement = new ThisLocal(member); |
| 1427 } | 1454 } |
| 1428 closureData = new ClosureClassMap(null, null, null, thisElement); | 1455 closureData = new ClosureClassMap(null, null, null, thisElement); |
| 1456 memberMappingCache[element] = closureData; | |
| 1457 memberMappingCache[element.declaration] = closureData; | |
| 1429 if (element is MethodElement) { | 1458 if (element is MethodElement) { |
| 1430 needsRti = compiler.options.enableTypeAssertions || | 1459 needsRti = compiler.options.enableTypeAssertions || |
| 1431 rtiNeed.methodNeedsRti(element); | 1460 rtiNeed.methodNeedsRti(element); |
| 1432 } | 1461 } |
| 1433 } | 1462 } |
| 1434 closureMappingCache[element] = closureData; | |
| 1435 closureMappingCache[element.declaration] = closureData; | |
| 1436 if (closureData.callMethod != null) { | 1463 if (closureData.callMethod != null) { |
| 1437 closureMappingCache[closureData.callMethod] = closureData; | 1464 memberMappingCache[closureData.callMethod] = closureData; |
| 1438 } | 1465 } |
| 1439 | 1466 |
| 1440 inNewScope(node, () { | 1467 inNewScope(node, () { |
| 1441 // If the method needs RTI, or checked mode is set, we need to | 1468 // If the method needs RTI, or checked mode is set, we need to |
| 1442 // escape the potential type variables used in that closure. | 1469 // escape the potential type variables used in that closure. |
| 1443 if (needsRti) { | 1470 if (needsRti) { |
| 1444 analyzeTypeVariables(element.type); | 1471 analyzeTypeVariables(element.type); |
| 1445 } | 1472 } |
| 1446 | 1473 |
| 1447 visitChildren(); | 1474 visitChildren(); |
| (...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1547 /// | 1574 /// |
| 1548 /// Move the below classes to a JS model eventually. | 1575 /// Move the below classes to a JS model eventually. |
| 1549 /// | 1576 /// |
| 1550 abstract class JSEntity implements MemberEntity { | 1577 abstract class JSEntity implements MemberEntity { |
| 1551 Local get declaredEntity; | 1578 Local get declaredEntity; |
| 1552 } | 1579 } |
| 1553 | 1580 |
| 1554 abstract class PrivatelyNamedJSEntity implements JSEntity { | 1581 abstract class PrivatelyNamedJSEntity implements JSEntity { |
| 1555 Entity get rootOfScope; | 1582 Entity get rootOfScope; |
| 1556 } | 1583 } |
| OLD | NEW |