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