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

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

Issue 2991903002: Add Closure call method to created closure class (Closed)
Patch Set: . Created 3 years, 4 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
« no previous file with comments | « no previous file | pkg/compiler/lib/src/js_model/closure_visitors.dart » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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';
11 import '../elements/entities.dart'; 10 import '../elements/entities.dart';
12 import '../elements/entity_utils.dart' as utils;
13 import '../elements/names.dart' show Name; 11 import '../elements/names.dart' show Name;
14 import '../kernel/element_map.dart'; 12 import '../kernel/element_map.dart';
15 import '../world.dart'; 13 import '../world.dart';
16 import 'elements.dart'; 14 import 'elements.dart';
17 import 'closure_visitors.dart'; 15 import 'closure_visitors.dart';
18 import 'locals.dart'; 16 import 'locals.dart';
19 import 'js_strategy.dart' show JsClosedWorld; 17 import 'js_strategy.dart' show JsClosedWorld;
20 18
21 /// Closure conversion code using our new Entity model. Closure conversion is 19 /// Closure conversion code using our new Entity model. Closure conversion is
22 /// necessary because the semantics of closures are slightly different in Dart 20 /// necessary because the semantics of closures are slightly different in Dart
(...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after
101 model.capturedScopesMap 99 model.capturedScopesMap
102 .forEach((ir.Node node, KernelCapturedScope scope) { 100 .forEach((ir.Node node, KernelCapturedScope scope) {
103 if (scope is KernelCapturedLoopScope) { 101 if (scope is KernelCapturedLoopScope) {
104 _capturedScopesMap[node] = 102 _capturedScopesMap[node] =
105 new JsCapturedLoopScope.from(scope, localsMap); 103 new JsCapturedLoopScope.from(scope, localsMap);
106 } else { 104 } else {
107 _capturedScopesMap[node] = new JsCapturedScope.from(scope, localsMap); 105 _capturedScopesMap[node] = new JsCapturedScope.from(scope, localsMap);
108 } 106 }
109 }); 107 });
110 108
111 Map<ir.TreeNode, KernelScopeInfo> closuresToGenerate = 109 Map<ir.FunctionNode, KernelScopeInfo> closuresToGenerate =
112 model.closuresToGenerate; 110 model.closuresToGenerate;
113 for (ir.TreeNode node in closuresToGenerate.keys) { 111 for (ir.FunctionNode node in closuresToGenerate.keys) {
114 _produceSyntheticElements( 112 _produceSyntheticElements(
115 member, node, closuresToGenerate[node], closedWorldRefiner); 113 member, node, closuresToGenerate[node], closedWorldRefiner);
116 } 114 }
117 }); 115 });
118 } 116 }
119 117
120 /// Inspect members and mark if those members capture any state that needs to 118 /// Inspect members and mark if those members capture any state that needs to
121 /// be marked as free variables. 119 /// be marked as free variables.
122 ClosureModel _buildClosureModel(MemberEntity entity) { 120 ClosureModel _buildClosureModel(MemberEntity entity) {
123 ClosureModel model = new ClosureModel(); 121 ClosureModel model = new ClosureModel();
(...skipping 18 matching lines...) Expand all
142 } 140 }
143 return model; 141 return model;
144 } 142 }
145 143
146 /// Given what variables are captured at each point, construct closure classes 144 /// Given what variables are captured at each point, construct closure classes
147 /// with fields containing the captured variables to replicate the Dart 145 /// with fields containing the captured variables to replicate the Dart
148 /// closure semantics in JS. If this closure captures any variables (meaning 146 /// closure semantics in JS. If this closure captures any variables (meaning
149 /// the closure accesses a variable that gets accessed at some point), then 147 /// the closure accesses a variable that gets accessed at some point), then
150 /// boxForCapturedVariables stores the local context for those variables. 148 /// boxForCapturedVariables stores the local context for those variables.
151 /// If no variables are captured, this parameter is null. 149 /// If no variables are captured, this parameter is null.
152 void _produceSyntheticElements( 150 void _produceSyntheticElements(MemberEntity member, ir.FunctionNode node,
153 MemberEntity member, 151 KernelScopeInfo info, JsClosedWorld closedWorldRefiner) {
154 ir.TreeNode /* ir.Member | ir.FunctionNode */ node,
155 KernelScopeInfo info,
156 JsClosedWorld closedWorldRefiner) {
157 String name = _computeClosureName(node);
158 KernelToLocalsMap localsMap = _globalLocalsMap.getLocalsMap(member); 152 KernelToLocalsMap localsMap = _globalLocalsMap.getLocalsMap(member);
159 KernelClosureClass closureClass = closedWorldRefiner.buildClosureClass( 153 KernelClosureClass closureClass = closedWorldRefiner.buildClosureClass(
160 name, member.library, info, node.location, localsMap); 154 member, node, member.library, info, node.location, localsMap);
161 155
162 Entity entity; 156 // We want the original declaration where that function is used to point
163 if (node is ir.Member) { 157 // to the correct closure class.
164 entity = member; 158 _closureRepresentationMap[closureClass.callMethod] = closureClass;
165 } else { 159 Entity entity = localsMap.getLocalFunction(node.parent);
166 assert(node is ir.FunctionNode);
167 entity = localsMap.getLocalFunction(node.parent);
168 // We want the original declaration where that function is used to point
169 // to the correct closure class.
170 _closureRepresentationMap[closureClass.callMethod] = closureClass;
171 }
172 assert(entity != null); 160 assert(entity != null);
173 _closureRepresentationMap[entity] = closureClass; 161 _closureRepresentationMap[entity] = closureClass;
174 } 162 }
175 163
176 // Returns a non-unique name for the given closure element.
177 String _computeClosureName(ir.TreeNode treeNode) {
178 var parts = <String>[];
179 if (treeNode is ir.Field && treeNode.name.name != "") {
180 parts.add(treeNode.name.name);
181 } else {
182 parts.add('closure');
183 }
184 ir.TreeNode node = treeNode.parent;
185 while (node != null &&
186 (node is ir.Constructor ||
187 node is ir.Class ||
188 node is ir.FunctionNode ||
189 node is ir.Procedure)) {
190 // TODO(johnniwinther): Simplify computed names.
191 if (node is ir.Constructor ||
192 node.parent is ir.Constructor ||
193 (node is ir.Procedure && node.kind == ir.ProcedureKind.Factory)) {
194 FunctionEntity entity;
195 if (node.parent is ir.Constructor) {
196 entity = _elementMap.getConstructorBody(node);
197 } else {
198 entity = _elementMap.getMember(node);
199 }
200 parts.add(utils.reconstructConstructorName(entity));
201 } else {
202 String surroundingName = '';
203 if (node is ir.Class) {
204 surroundingName = Elements.operatorNameToIdentifier(node.name);
205 } else if (node is ir.Procedure) {
206 surroundingName = Elements.operatorNameToIdentifier(node.name.name);
207 }
208 parts.add(surroundingName);
209 }
210 // A generative constructors's parent is the class; the class name is
211 // already part of the generative constructor's name.
212 if (node is ir.Constructor) break;
213 node = node.parent;
214 }
215 return parts.reversed.join('_');
216 }
217
218 @override 164 @override
219 ScopeInfo getScopeInfo(Entity entity) { 165 ScopeInfo getScopeInfo(Entity entity) {
220 // TODO(johnniwinther): Remove this check when constructor bodies a created 166 // TODO(johnniwinther): Remove this check when constructor bodies a created
221 // eagerly with the J-model; a constructor body should have it's own 167 // eagerly with the J-model; a constructor body should have it's own
222 // [ClosureRepresentationInfo]. 168 // [ClosureRepresentationInfo].
223 if (entity is ConstructorBodyEntity) { 169 if (entity is ConstructorBodyEntity) {
224 ConstructorBodyEntity constructorBody = entity; 170 ConstructorBodyEntity constructorBody = entity;
225 entity = constructorBody.constructor; 171 entity = constructorBody.constructor;
226 } 172 }
227 173
(...skipping 155 matching lines...) Expand 10 before | Expand all | Expand 10 after
383 bool get hasBoxedLoopVariables => boxedLoopVariables.isNotEmpty; 329 bool get hasBoxedLoopVariables => boxedLoopVariables.isNotEmpty;
384 } 330 }
385 331
386 // TODO(johnniwinther): Add unittest for the computed [ClosureClass]. 332 // TODO(johnniwinther): Add unittest for the computed [ClosureClass].
387 class KernelClosureClass extends JsScopeInfo 333 class KernelClosureClass extends JsScopeInfo
388 implements ClosureRepresentationInfo, JClass { 334 implements ClosureRepresentationInfo, JClass {
389 final ir.Location location; 335 final ir.Location location;
390 336
391 final String name; 337 final String name;
392 final JLibrary library; 338 final JLibrary library;
339 JFunction callMethod;
393 340
394 /// Index into the classData, classList and classEnvironment lists where this 341 /// Index into the classData, classList and classEnvironment lists where this
395 /// entity is stored in [JsToFrontendMapImpl]. 342 /// entity is stored in [JsToFrontendMapImpl].
396 final int classIndex; 343 final int classIndex;
397 344
398 final Map<Local, JField> localToFieldMap = new Map<Local, JField>(); 345 final Map<Local, JField> localToFieldMap = new Map<Local, JField>();
399 346
400 KernelClosureClass.fromScopeInfo(this.name, this.classIndex, this.library, 347 KernelClosureClass.fromScopeInfo(this.name, this.classIndex, this.library,
401 KernelScopeInfo info, this.location, KernelToLocalsMap localsMap) 348 KernelScopeInfo info, this.location, KernelToLocalsMap localsMap)
402 : super.from(info, localsMap); 349 : super.from(info, localsMap);
403 350
404 // TODO(efortuna): Implement. 351 // TODO(efortuna): Implement.
405 Local get closureEntity => null; 352 Local get closureEntity => null;
406 353
407 ClassEntity get closureClassEntity => this; 354 ClassEntity get closureClassEntity => this;
408 355
409 // TODO(efortuna): Implement.
410 FunctionEntity get callMethod => null;
411
412 List<Local> get createdFieldEntities => localToFieldMap.keys.toList(); 356 List<Local> get createdFieldEntities => localToFieldMap.keys.toList();
413 357
414 // TODO(efortuna): Implement. 358 // TODO(efortuna): Implement.
415 FieldEntity get thisFieldEntity => null; 359 FieldEntity get thisFieldEntity => null;
416 360
417 void forEachCapturedVariable(f(Local from, JField to)) { 361 void forEachCapturedVariable(f(Local from, JField to)) {
418 localToFieldMap.forEach(f); 362 localToFieldMap.forEach(f);
419 } 363 }
420 364
421 // TODO(efortuna): Implement. 365 // TODO(efortuna): Implement.
422 @override 366 @override
423 void forEachBoxedVariable(f(Local local, JField field)) {} 367 void forEachBoxedVariable(f(Local local, JField field)) {}
424 368
425 // TODO(efortuna): Implement. 369 // TODO(efortuna): Implement.
426 void forEachFreeVariable(f(Local variable, JField field)) {} 370 void forEachFreeVariable(f(Local variable, JField field)) {}
427 371
428 // TODO(efortuna): Implement. 372 // TODO(efortuna): Implement.
429 bool isVariableBoxed(Local variable) => false; 373 bool isVariableBoxed(Local variable) => false;
430 374
431 bool get isClosure => true; 375 bool get isClosure => true;
432 376
433 bool get isAbstract => false; 377 bool get isAbstract => false;
434 378
435 String toString() => '${jsElementPrefix}class($name)'; 379 String toString() => '${jsElementPrefix}class($name)';
436 } 380 }
437 381
438 class ClosureField extends JField { 382 class JClosureField extends JField {
439 ClosureField(String name, int memberIndex, KernelClosureClass containingClass, 383 JClosureField(String name, int memberIndex,
440 bool isConst, bool isAssignable) 384 KernelClosureClass containingClass, bool isConst, bool isAssignable)
441 : super(memberIndex, containingClass.library, containingClass, 385 : super(memberIndex, containingClass.library, containingClass,
442 new Name(name, containingClass.library), 386 new Name(name, containingClass.library),
443 isAssignable: isAssignable, isConst: isConst); 387 isAssignable: isAssignable, isConst: isConst);
444 } 388 }
445 389
446 class ClosureClassDefinition implements ClassDefinition { 390 class ClosureClassDefinition implements ClassDefinition {
447 final ClassEntity cls; 391 final ClassEntity cls;
448 final ir.Location location; 392 final ir.Location location;
449 393
450 ClosureClassDefinition(this.cls, this.location); 394 ClosureClassDefinition(this.cls, this.location);
(...skipping 25 matching lines...) Expand all
476 // TODO(johnniwinther): [scopeInfo] seem to be missing only for fields 420 // TODO(johnniwinther): [scopeInfo] seem to be missing only for fields
477 // without initializers; we shouldn't even create a [ClosureModel] in these 421 // without initializers; we shouldn't even create a [ClosureModel] in these
478 // cases. 422 // cases.
479 KernelScopeInfo scopeInfo; 423 KernelScopeInfo scopeInfo;
480 424
481 /// Collected [CapturedScope] data for nodes. 425 /// Collected [CapturedScope] data for nodes.
482 Map<ir.Node, KernelCapturedScope> capturedScopesMap = 426 Map<ir.Node, KernelCapturedScope> capturedScopesMap =
483 <ir.Node, KernelCapturedScope>{}; 427 <ir.Node, KernelCapturedScope>{};
484 428
485 /// Collected [ScopeInfo] data for nodes. 429 /// Collected [ScopeInfo] data for nodes.
486 Map<ir.TreeNode, KernelScopeInfo> closuresToGenerate = 430 Map<ir.FunctionNode, KernelScopeInfo> closuresToGenerate =
487 <ir.TreeNode, KernelScopeInfo>{}; 431 <ir.FunctionNode, KernelScopeInfo>{};
488 } 432 }
OLDNEW
« no previous file with comments | « no previous file | pkg/compiler/lib/src/js_model/closure_visitors.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698