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 |