Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(365)

Side by Side Diff: pkg/compiler/lib/src/js_model/closure.dart

Issue 2981423003: Move .getLocalFunction from KernelToElementMap to KernelToLocalsMap (Closed)
Patch Set: Created 3 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2017, 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 'package:kernel/ast.dart' as ir; 5 import 'package:kernel/ast.dart' as ir;
6 6
7 import '../closure.dart'; 7 import '../closure.dart';
8 import '../common.dart'; 8 import '../common.dart';
9 import '../common/tasks.dart'; 9 import '../common/tasks.dart';
10 import '../elements/elements.dart'; 10 import '../elements/elements.dart';
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
54 54
55 /// The combined steps of generating our intermediate representation of 55 /// The combined steps of generating our intermediate representation of
56 /// closures that need to be rewritten and generating the element model. 56 /// closures that need to be rewritten and generating the element model.
57 /// Ultimately these two steps will be split apart with the second step 57 /// Ultimately these two steps will be split apart with the second step
58 /// happening later in compilation just before codegen. These steps are 58 /// happening later in compilation just before codegen. These steps are
59 /// combined here currently to provide a consistent interface to the rest of 59 /// combined here currently to provide a consistent interface to the rest of
60 /// the compiler until we are ready to separate these phases. 60 /// the compiler until we are ready to separate these phases.
61 @override 61 @override
62 void convertClosures(Iterable<MemberEntity> processedEntities, 62 void convertClosures(Iterable<MemberEntity> processedEntities,
63 ClosedWorldRefiner closedWorldRefiner) { 63 ClosedWorldRefiner closedWorldRefiner) {
64 var closuresToGenerate = <ir.TreeNode, ScopeInfo>{}; 64 var closuresToGenerate = <MemberEntity, Map<ir.TreeNode, ScopeInfo>>{};
65
65 processedEntities.forEach((MemberEntity kEntity) { 66 processedEntities.forEach((MemberEntity kEntity) {
66 MemberEntity entity = _kToJElementMap.toBackendMember(kEntity); 67 MemberEntity entity = _kToJElementMap.toBackendMember(kEntity);
67 if (entity.isAbstract) return; 68 if (entity.isAbstract) return;
68 if (entity.isField && !entity.isInstanceMember) { 69 if (entity.isField && !entity.isInstanceMember) {
69 MemberDefinition definition = _elementMap.getMemberDefinition(entity); 70 MemberDefinition definition = _elementMap.getMemberDefinition(entity);
70 assert(definition.kind == MemberKind.regular, 71 assert(definition.kind == MemberKind.regular,
71 failedAt(entity, "Unexpected member definition $definition")); 72 failedAt(entity, "Unexpected member definition $definition"));
72 ir.Field field = definition.node; 73 ir.Field field = definition.node;
73 // Skip top-level/static fields without an initializer. 74 // Skip top-level/static fields without an initializer.
74 if (field.initializer == null) return; 75 if (field.initializer == null) return;
75 } 76 }
76 _buildClosureModel(entity, closuresToGenerate, closedWorldRefiner); 77 closuresToGenerate[entity] =
78 _buildClosureModel(entity, closedWorldRefiner);
77 }); 79 });
78 80
79 for (ir.TreeNode node in closuresToGenerate.keys) { 81 closuresToGenerate.forEach(
80 _produceSyntheticElements( 82 (MemberEntity member, Map<ir.TreeNode, ScopeInfo> closuresToGenerate) {
81 node, closuresToGenerate[node], closedWorldRefiner); 83 for (ir.TreeNode node in closuresToGenerate.keys) {
82 } 84 _produceSyntheticElements(
85 member, node, closuresToGenerate[node], closedWorldRefiner);
86 }
87 });
83 } 88 }
84 89
85 /// Inspect members and mark if those members capture any state that needs to 90 /// Inspect members and mark if those members capture any state that needs to
86 /// be marked as free variables. 91 /// be marked as free variables.
87 void _buildClosureModel( 92 Map<ir.TreeNode, ScopeInfo> _buildClosureModel(
88 MemberEntity entity, 93 MemberEntity entity, ClosedWorldRefiner closedWorldRefiner) {
89 Map<ir.TreeNode, ScopeInfo> closuresToGenerate, 94 assert(!_scopeMap.containsKey(entity),
90 ClosedWorldRefiner closedWorldRefiner) { 95 failedAt(entity, "ScopeInfo already computed for $entity."));
91 if (_scopeMap.keys.contains(entity)) return; 96 Map<ir.TreeNode, ScopeInfo> closuresToGenerate = <ir.TreeNode, ScopeInfo>{};
92 MemberDefinition definition = _elementMap.getMemberDefinition(entity); 97 MemberDefinition definition = _elementMap.getMemberDefinition(entity);
93 switch (definition.kind) { 98 switch (definition.kind) {
94 case MemberKind.regular: 99 case MemberKind.regular:
95 case MemberKind.constructor: 100 case MemberKind.constructor:
96 break; 101 break;
97 default: 102 default:
98 failedAt(entity, "Unexpected member definition $definition"); 103 failedAt(entity, "Unexpected member definition $definition");
99 } 104 }
100 ir.Node node = definition.node; 105 ir.Node node = definition.node;
101 if (_capturedScopesMap.keys.contains(node)) return; 106 assert(!_scopeMap.containsKey(entity),
107 failedAt(entity, "CaptureScope already computed for $node."));
102 CapturedScopeBuilder translator = new CapturedScopeBuilder( 108 CapturedScopeBuilder translator = new CapturedScopeBuilder(
103 entity, 109 entity,
104 _capturedScopesMap, 110 _capturedScopesMap,
105 _scopeMap, 111 _scopeMap,
106 closuresToGenerate, 112 closuresToGenerate,
107 _globalLocalsMap.getLocalsMap(entity), 113 _globalLocalsMap.getLocalsMap(entity));
108 _elementMap);
109 if (entity.isField) { 114 if (entity.isField) {
110 if (node is ir.Field && node.initializer != null) { 115 if (node is ir.Field && node.initializer != null) {
111 translator.translateLazyInitializer(node); 116 translator.translateLazyInitializer(node);
112 } 117 }
113 } else { 118 } else {
114 assert(node is ir.Procedure || node is ir.Constructor); 119 assert(node is ir.Procedure || node is ir.Constructor);
115 translator.translateConstructorOrProcedure(node); 120 translator.translateConstructorOrProcedure(node);
116 } 121 }
122 return closuresToGenerate;
117 } 123 }
118 124
119 /// Given what variables are captured at each point, construct closure classes 125 /// Given what variables are captured at each point, construct closure classes
120 /// with fields containing the captured variables to replicate the Dart 126 /// with fields containing the captured variables to replicate the Dart
121 /// closure semantics in JS. If this closure captures any variables (meaning 127 /// closure semantics in JS. If this closure captures any variables (meaning
122 /// the closure accesses a variable that gets accessed at some point), then 128 /// the closure accesses a variable that gets accessed at some point), then
123 /// boxForCapturedVariables stores the local context for those variables. 129 /// boxForCapturedVariables stores the local context for those variables.
124 /// If no variables are captured, this parameter is null. 130 /// If no variables are captured, this parameter is null.
125 void _produceSyntheticElements( 131 void _produceSyntheticElements(
132 MemberEntity member,
126 ir.TreeNode /* ir.Member | ir.FunctionNode */ node, 133 ir.TreeNode /* ir.Member | ir.FunctionNode */ node,
127 ScopeInfo info, 134 ScopeInfo info,
128 ClosedWorldRefiner closedWorldRefiner) { 135 ClosedWorldRefiner closedWorldRefiner) {
136 String name = _computeClosureName(node);
137 KernelClosureClass closureClass = new KernelClosureClass.fromScopeInfo(
138 name, member.library, info, node.location);
139
129 Entity entity; 140 Entity entity;
130 ir.Library library;
131 if (node is ir.Member) { 141 if (node is ir.Member) {
132 entity = _elementMap.getMember(node); 142 entity = member;
133 library = node.enclosingLibrary;
134 } else { 143 } else {
135 assert(node is ir.FunctionNode); 144 assert(node is ir.FunctionNode);
136 entity = _elementMap.getLocalFunction(node.parent); 145 KernelToLocalsMap localsMap = _globalLocalsMap.getLocalsMap(member);
137 // TODO(efortuna): Consider the less roundabout way of getting this value 146 entity = localsMap.getLocalFunction(node.parent);
138 // which is just storing the "enclosingLibrary" value of the original call 147 // We want the original declaration where that function is used to point
139 // to CapturedScopeBuilder. 148 // to the correct closure class.
140 ir.TreeNode temp = node; 149 _closureRepresentationMap[closureClass.callMethod] = closureClass;
141 while (temp != null && temp is! ir.Library) {
142 temp = temp.parent;
143 }
144 assert(temp is ir.Library);
145 library = temp;
146 } 150 }
147 assert(entity != null); 151 assert(entity != null);
148
149 String name = _computeClosureName(node);
150 KernelClosureClass closureClass = new KernelClosureClass.fromScopeInfo(
151 name, _elementMap.getLibrary(library), info, node.location);
152 if (node is ir.FunctionNode) {
153 // We want the original declaration where that function is used to point
154 // to the correct closure class.
155 // TODO(efortuna): entity equivalent of element.declaration?
156 node = (node as ir.FunctionNode).parent;
157 _closureRepresentationMap[closureClass.callMethod] = closureClass;
158 }
159
160 _closureRepresentationMap[entity] = closureClass; 152 _closureRepresentationMap[entity] = closureClass;
161 153
162 // Register that a new class has been created. 154 // Register that a new class has been created.
163 closedWorldRefiner.registerClosureClass( 155 closedWorldRefiner.registerClosureClass(closureClass);
164 closureClass, node is ir.Member && node.isInstanceMember);
165 } 156 }
166 157
167 // Returns a non-unique name for the given closure element. 158 // Returns a non-unique name for the given closure element.
168 String _computeClosureName(ir.TreeNode treeNode) { 159 String _computeClosureName(ir.TreeNode treeNode) {
169 var parts = <String>[]; 160 var parts = <String>[];
170 if (treeNode is ir.Field && treeNode.name.name != "") { 161 if (treeNode is ir.Field && treeNode.name.name != "") {
171 parts.add(treeNode.name.name); 162 parts.add(treeNode.name.name);
172 } else { 163 } else {
173 parts.add('closure'); 164 parts.add('closure');
174 } 165 }
(...skipping 173 matching lines...) Expand 10 before | Expand all | Expand 10 after
348 KernelClosureClass.fromScopeInfo( 339 KernelClosureClass.fromScopeInfo(
349 this.name, this.library, KernelScopeInfo info, this.location) 340 this.name, this.library, KernelScopeInfo info, this.location)
350 : super.from(info.thisLocal, info) { 341 : super.from(info.thisLocal, info) {
351 // Make a corresponding field entity in this closure class for every single 342 // Make a corresponding field entity in this closure class for every single
352 // freeVariable in the KernelScopeInfo.freeVariable. 343 // freeVariable in the KernelScopeInfo.freeVariable.
353 int i = 0; 344 int i = 0;
354 for (ir.VariableDeclaration variable in info.freeVariables) { 345 for (ir.VariableDeclaration variable in info.freeVariables) {
355 // NOTE: This construction order may be slightly different than the 346 // NOTE: This construction order may be slightly different than the
356 // old Element version. The old version did all the boxed items and then 347 // old Element version. The old version did all the boxed items and then
357 // all the others. 348 // all the others.
358 Local capturedLocal = info.localsMap.getLocal(variable); 349 Local capturedLocal = info.localsMap.getLocalVariable(variable);
359 if (info.isBoxed(capturedLocal)) { 350 if (info.isBoxed(capturedLocal)) {
360 // TODO(efortuna): Coming soon. 351 // TODO(efortuna): Coming soon.
361 } else { 352 } else {
362 localToFieldMap[capturedLocal] = new ClosureField( 353 localToFieldMap[capturedLocal] = new ClosureField(
363 _getClosureVariableName(capturedLocal.name, i), 354 _getClosureVariableName(capturedLocal.name, i),
364 this, 355 this,
365 variable.isConst, 356 variable.isConst,
366 variable.isFinal || variable.isConst); 357 variable.isFinal || variable.isConst);
367 // TODO(efortuna): These probably need to get registered somewhere. 358 // TODO(efortuna): These probably need to get registered somewhere.
368 } 359 }
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after
434 ClosureClassDefinition(this.cls, this.location); 425 ClosureClassDefinition(this.cls, this.location);
435 426
436 ClassKind get kind => ClassKind.closure; 427 ClassKind get kind => ClassKind.closure;
437 428
438 ir.Node get node => 429 ir.Node get node =>
439 throw new UnsupportedError('ClosureClassDefinition.node for $cls'); 430 throw new UnsupportedError('ClosureClassDefinition.node for $cls');
440 431
441 String toString() => 432 String toString() =>
442 'ClosureClassDefinition(kind:$kind,cls:$cls,location:$location)'; 433 'ClosureClassDefinition(kind:$kind,cls:$cls,location:$location)';
443 } 434 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698