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 |