OLD | NEW |
(Empty) | |
| 1 // Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file |
| 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. |
| 4 |
| 5 import 'package:kernel/ast.dart' as ir; |
| 6 |
| 7 import '../closure.dart'; |
| 8 import '../common/tasks.dart'; |
| 9 import '../elements/entities.dart'; |
| 10 import '../world.dart'; |
| 11 import 'element_map.dart'; |
| 12 import 'kernel_backend_strategy.dart'; |
| 13 |
| 14 class KernelClosureDataBuilder extends ir.Visitor { |
| 15 final KernelToLocalsMap _localsMap; |
| 16 final KernelClosureRepresentationInfo info; |
| 17 |
| 18 bool _inTry = false; |
| 19 |
| 20 KernelClosureDataBuilder(this._localsMap, ThisLocal thisLocal) |
| 21 : info = new KernelClosureRepresentationInfo(thisLocal); |
| 22 |
| 23 @override |
| 24 defaultNode(ir.Node node) { |
| 25 node.visitChildren(this); |
| 26 } |
| 27 |
| 28 @override |
| 29 visitTryCatch(ir.TryCatch node) { |
| 30 bool oldInTry = _inTry; |
| 31 _inTry = true; |
| 32 node.visitChildren(this); |
| 33 _inTry = oldInTry; |
| 34 } |
| 35 |
| 36 @override |
| 37 visitTryFinally(ir.TryFinally node) { |
| 38 bool oldInTry = _inTry; |
| 39 _inTry = true; |
| 40 node.visitChildren(this); |
| 41 _inTry = oldInTry; |
| 42 } |
| 43 |
| 44 @override |
| 45 visitVariableGet(ir.VariableGet node) { |
| 46 if (_inTry) { |
| 47 info.registerUsedInTryOrSync(_localsMap.getLocal(node.variable)); |
| 48 } |
| 49 } |
| 50 } |
| 51 |
| 52 /// Closure conversion code using our new Entity model. Closure conversion is |
| 53 /// necessary because the semantics of closures are slightly different in Dart |
| 54 /// than JavaScript. Closure conversion is separated out into two phases: |
| 55 /// generation of a new (temporary) representation to store where variables need |
| 56 /// to be hoisted/captured up at another level to re-write the closure, and then |
| 57 /// the code generation phase where we generate elements and/or instructions to |
| 58 /// represent this new code path. |
| 59 /// |
| 60 /// For a general explanation of how closure conversion works at a high level, |
| 61 /// check out: |
| 62 /// http://siek.blogspot.com/2012/07/essence-of-closure-conversion.html or |
| 63 /// http://matt.might.net/articles/closure-conversion/. |
| 64 class KernelClosureConversionTask extends ClosureConversionTask<ir.Node> { |
| 65 final KernelToElementMap _elementMap; |
| 66 final GlobalLocalsMap _globalLocalsMap; |
| 67 Map<Entity, ClosureRepresentationInfo> _infoMap = |
| 68 <Entity, ClosureRepresentationInfo>{}; |
| 69 |
| 70 KernelClosureConversionTask( |
| 71 Measurer measurer, this._elementMap, this._globalLocalsMap) |
| 72 : super(measurer); |
| 73 |
| 74 /// The combined steps of generating our intermediate representation of |
| 75 /// closures that need to be rewritten and generating the element model. |
| 76 /// Ultimately these two steps will be split apart with the second step |
| 77 /// happening later in compilation just before codegen. These steps are |
| 78 /// combined here currently to provide a consistent interface to the rest of |
| 79 /// the compiler until we are ready to separate these phases. |
| 80 @override |
| 81 void convertClosures(Iterable<MemberEntity> processedEntities, |
| 82 ClosedWorldRefiner closedWorldRefiner) { |
| 83 // TODO(efortuna): implement. |
| 84 } |
| 85 |
| 86 /// TODO(johnniwinther,efortuna): Implement this. |
| 87 @override |
| 88 ClosureAnalysisInfo getClosureAnalysisInfo(ir.Node node) { |
| 89 return const ClosureAnalysisInfo(); |
| 90 } |
| 91 |
| 92 /// TODO(johnniwinther,efortuna): Implement this. |
| 93 @override |
| 94 LoopClosureRepresentationInfo getClosureRepresentationInfoForLoop( |
| 95 ir.Node loopNode) { |
| 96 return const LoopClosureRepresentationInfo(); |
| 97 } |
| 98 |
| 99 @override |
| 100 ClosureRepresentationInfo getClosureRepresentationInfo(Entity entity) { |
| 101 return _infoMap.putIfAbsent(entity, () { |
| 102 if (entity is MemberEntity) { |
| 103 ir.Member node = _elementMap.getMemberNode(entity); |
| 104 ThisLocal thisLocal; |
| 105 if (entity.isInstanceMember) { |
| 106 thisLocal = new ThisLocal(entity); |
| 107 } |
| 108 KernelClosureDataBuilder builder = new KernelClosureDataBuilder( |
| 109 _globalLocalsMap.getLocalsMap(entity), thisLocal); |
| 110 node.accept(builder); |
| 111 return builder.info; |
| 112 } |
| 113 |
| 114 /// TODO(johnniwinther,efortuna): Implement this. |
| 115 return const ClosureRepresentationInfo(); |
| 116 }); |
| 117 } |
| 118 } |
| 119 |
| 120 // TODO(johnniwinther): Add unittest for the computed |
| 121 // [ClosureRepresentationInfo]. |
| 122 class KernelClosureRepresentationInfo extends ClosureRepresentationInfo { |
| 123 final ThisLocal thisLocal; |
| 124 final Set<Local> _localsUsedInTryOrSync = new Set<Local>(); |
| 125 |
| 126 KernelClosureRepresentationInfo(this.thisLocal); |
| 127 |
| 128 void registerUsedInTryOrSync(Local local) { |
| 129 _localsUsedInTryOrSync.add(local); |
| 130 } |
| 131 |
| 132 bool variableIsUsedInTryOrSync(Local variable) => |
| 133 _localsUsedInTryOrSync.contains(variable); |
| 134 } |
OLD | NEW |