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

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

Issue 2994363002: Fix the local variable lookup in the locals handler. (Closed)
Patch Set: stephen comments 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 '../constants/expressions.dart'; 10 import '../constants/expressions.dart';
(...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after
106 _capturedScopesMap[node] = 106 _capturedScopesMap[node] =
107 new JsCapturedLoopScope.from(scope, localsMap); 107 new JsCapturedLoopScope.from(scope, localsMap);
108 } else { 108 } else {
109 _capturedScopesMap[node] = new JsCapturedScope.from(scope, localsMap); 109 _capturedScopesMap[node] = new JsCapturedScope.from(scope, localsMap);
110 } 110 }
111 }); 111 });
112 112
113 Map<ir.FunctionNode, KernelScopeInfo> closuresToGenerate = 113 Map<ir.FunctionNode, KernelScopeInfo> closuresToGenerate =
114 model.closuresToGenerate; 114 model.closuresToGenerate;
115 for (ir.FunctionNode node in closuresToGenerate.keys) { 115 for (ir.FunctionNode node in closuresToGenerate.keys) {
116 _produceSyntheticElements( 116 KernelClosureClass closureClass = _produceSyntheticElements(
117 member, node, closuresToGenerate[node], closedWorldRefiner); 117 member, node, closuresToGenerate[node], closedWorldRefiner);
118 // Add also for the call method.
119 _scopeMap[closureClass.callMethod] = closureClass;
118 } 120 }
119 }); 121 });
120 } 122 }
121 123
122 /// Given what variables are captured at each point, construct closure classes 124 /// Given what variables are captured at each point, construct closure classes
123 /// with fields containing the captured variables to replicate the Dart 125 /// with fields containing the captured variables to replicate the Dart
124 /// closure semantics in JS. If this closure captures any variables (meaning 126 /// closure semantics in JS. If this closure captures any variables (meaning
125 /// the closure accesses a variable that gets accessed at some point), then 127 /// the closure accesses a variable that gets accessed at some point), then
126 /// boxForCapturedVariables stores the local context for those variables. 128 /// boxForCapturedVariables stores the local context for those variables.
127 /// If no variables are captured, this parameter is null. 129 /// If no variables are captured, this parameter is null.
128 void _produceSyntheticElements(MemberEntity member, ir.FunctionNode node, 130 KernelClosureClass _produceSyntheticElements(
129 KernelScopeInfo info, JsClosedWorld closedWorldRefiner) { 131 MemberEntity member,
132 ir.FunctionNode node,
133 KernelScopeInfo info,
134 JsClosedWorld closedWorldRefiner) {
130 KernelToLocalsMap localsMap = _globalLocalsMap.getLocalsMap(member); 135 KernelToLocalsMap localsMap = _globalLocalsMap.getLocalsMap(member);
131 KernelClosureClass closureClass = closedWorldRefiner.buildClosureClass( 136 KernelClosureClass closureClass = closedWorldRefiner.buildClosureClass(
132 member, node, member.library, info, node.location, localsMap); 137 member, node, member.library, info, node.location, localsMap);
133 138
134 // We want the original declaration where that function is used to point 139 // We want the original declaration where that function is used to point
135 // to the correct closure class. 140 // to the correct closure class.
136 _closureRepresentationMap[closureClass.callMethod] = closureClass; 141 _closureRepresentationMap[closureClass.callMethod] = closureClass;
137 Entity entity; 142 Entity entity;
138 if (node.parent is ir.Member) { 143 if (node.parent is ir.Member) {
139 entity = _elementMap.getMember(node.parent); 144 entity = _elementMap.getMember(node.parent);
140 } else { 145 } else {
141 entity = localsMap.getLocalFunction(node.parent); 146 entity = localsMap.getLocalFunction(node.parent);
142 } 147 }
143 assert(entity != null); 148 assert(entity != null);
144 _closureRepresentationMap[entity] = closureClass; 149 _closureRepresentationMap[entity] = closureClass;
150 return closureClass;
145 } 151 }
146 152
147 @override 153 @override
148 ScopeInfo getScopeInfo(Entity entity) { 154 ScopeInfo getScopeInfo(Entity entity) {
149 // TODO(johnniwinther): Remove this check when constructor bodies a created 155 // TODO(johnniwinther): Remove this check when constructor bodies a created
150 // eagerly with the J-model; a constructor body should have it's own 156 // eagerly with the J-model; a constructor body should have it's own
151 // [ClosureRepresentationInfo]. 157 // [ClosureRepresentationInfo].
152 if (entity is ConstructorBodyEntity) { 158 if (entity is ConstructorBodyEntity) {
153 ConstructorBodyEntity constructorBody = entity; 159 ConstructorBodyEntity constructorBody = entity;
154 entity = constructorBody.constructor; 160 entity = constructorBody.constructor;
(...skipping 172 matching lines...) Expand 10 before | Expand all | Expand 10 after
327 : this.boxedLoopVariables = capturedScope.boxedLoopVariables 333 : this.boxedLoopVariables = capturedScope.boxedLoopVariables
328 .map(localsMap.getLocalVariable) 334 .map(localsMap.getLocalVariable)
329 .toList(), 335 .toList(),
330 super.from(capturedScope, localsMap); 336 super.from(capturedScope, localsMap);
331 337
332 bool get hasBoxedLoopVariables => boxedLoopVariables.isNotEmpty; 338 bool get hasBoxedLoopVariables => boxedLoopVariables.isNotEmpty;
333 } 339 }
334 340
335 // TODO(johnniwinther): Add unittest for the computed [ClosureClass]. 341 // TODO(johnniwinther): Add unittest for the computed [ClosureClass].
336 class KernelClosureClass extends JsScopeInfo 342 class KernelClosureClass extends JsScopeInfo
337 implements ClosureRepresentationInfo, JClass { 343 implements ClosureRepresentationInfo {
338 final String name;
339 final JLibrary library;
340 JFunction callMethod; 344 JFunction callMethod;
341 final Local closureEntity; 345 final Local closureEntity;
342 final Local thisLocal; 346 final Local thisLocal;
343 347 final JClass closureClassEntity;
344 /// Index into the classData, classList and classEnvironment lists where this
345 /// entity is stored in [JsToFrontendMapImpl].
346 final int classIndex;
347 348
348 final Map<Local, JField> localToFieldMap = new Map<Local, JField>(); 349 final Map<Local, JField> localToFieldMap = new Map<Local, JField>();
349 350
350 KernelClosureClass.fromScopeInfo( 351 KernelClosureClass.fromScopeInfo(
352 this.closureClassEntity,
351 ir.FunctionNode closureSourceNode, 353 ir.FunctionNode closureSourceNode,
352 this.name,
353 this.classIndex,
354 this.library,
355 KernelScopeInfo info, 354 KernelScopeInfo info,
356 KernelToLocalsMap localsMap) 355 KernelToLocalsMap localsMap)
357 : closureEntity = closureSourceNode.parent is ir.Member 356 : closureEntity = closureSourceNode.parent is ir.Member
358 ? null 357 ? null
359 : localsMap.getLocalFunction(closureSourceNode.parent), 358 : localsMap.getLocalFunction(closureSourceNode.parent),
360 thisLocal = 359 thisLocal =
361 info.hasThisLocal ? new ThisLocal(localsMap.currentMember) : null, 360 info.hasThisLocal ? new ThisLocal(localsMap.currentMember) : null,
362 super.from(info, localsMap); 361 super.from(info, localsMap);
363 362
364 ClassEntity get closureClassEntity => this;
365
366 List<Local> get createdFieldEntities => localToFieldMap.keys.toList(); 363 List<Local> get createdFieldEntities => localToFieldMap.keys.toList();
367 364
368 FieldEntity get thisFieldEntity => localToFieldMap[thisLocal]; 365 FieldEntity get thisFieldEntity => localToFieldMap[thisLocal];
369 366
370 void forEachCapturedVariable(f(Local from, JField to)) { 367 void forEachCapturedVariable(f(Local from, JField to)) {
371 localToFieldMap.forEach(f); 368 localToFieldMap.forEach(f);
372 } 369 }
373 370
374 @override 371 @override
375 void forEachBoxedVariable(f(Local local, JField field)) { 372 void forEachBoxedVariable(f(Local local, JField field)) {
376 for (Local l in localToFieldMap.keys) { 373 for (Local l in localToFieldMap.keys) {
377 if (localToFieldMap[l] is JBoxedField) f(l, localToFieldMap[l]); 374 if (localToFieldMap[l] is JBoxedField) f(l, localToFieldMap[l]);
378 } 375 }
379 } 376 }
380 377
381 void forEachFreeVariable(f(Local variable, JField field)) { 378 void forEachFreeVariable(f(Local variable, JField field)) {
382 for (Local l in localToFieldMap.keys) { 379 for (Local l in localToFieldMap.keys) {
383 var jField = localToFieldMap[l]; 380 var jField = localToFieldMap[l];
384 if (jField is! JBoxedField && jField is! BoxLocal) f(l, jField); 381 if (jField is! JBoxedField && jField is! BoxLocal) f(l, jField);
385 } 382 }
386 } 383 }
387 384
388 bool isVariableBoxed(Local variable) => 385 bool isVariableBoxed(Local variable) =>
389 localToFieldMap.keys.contains(variable); 386 localToFieldMap.keys.contains(variable);
390 387
391 bool get isClosure => true; 388 bool get isClosure => true;
392
393 bool get isAbstract => false;
394
395 String toString() => '${jsElementPrefix}class($name)';
396 } 389 }
397 390
398 /// A local variable to disambiguate between a variable that has been captured 391 /// A local variable to disambiguate between a variable that has been captured
399 /// from one scope to another. This is the ir.Node version that corresponds to 392 /// from one scope to another. This is the ir.Node version that corresponds to
400 /// [BoxLocal]. 393 /// [BoxLocal].
401 class NodeBox { 394 class NodeBox {
402 final String name; 395 final String name;
403 final ir.TreeNode executableContext; 396 final ir.TreeNode executableContext;
404 NodeBox(this.name, this.executableContext); 397 NodeBox(this.name, this.executableContext);
405 } 398 }
406 399
400 class JClosureClass extends JClass {
401 // TODO(efortuna): Storing this map here is so horrible. Instead store this on
402 // the ScopeModel (because all of the closures share that localsMap) and then
403 // set populate the getLocalVariable lookup with this localsMap for all the
404 // closures.
405 final KernelToLocalsMap localsMap;
406
407 JClosureClass(this.localsMap, JLibrary library, int classIndex, String name)
408 : super(library, classIndex, name, isAbstract: false);
409
410 @override
411 bool get isClosure => true;
412
413 String toString() => '${jsElementPrefix}closure_class($name)';
414 }
415
407 class JClosureField extends JField { 416 class JClosureField extends JField {
408 JClosureField(String name, int memberIndex, 417 JClosureField(String name, int memberIndex,
409 KernelClosureClass containingClass, bool isConst, bool isAssignable) 418 KernelClosureClass containingClass, bool isConst, bool isAssignable)
410 : super(memberIndex, containingClass.library, containingClass, 419 : super(
411 new Name(name, containingClass.library), 420 memberIndex,
412 isAssignable: isAssignable, isConst: isConst, isStatic: false); 421 containingClass.closureClassEntity.library,
422 containingClass.closureClassEntity,
423 new Name(name, containingClass.closureClassEntity.library),
424 isAssignable: isAssignable,
425 isConst: isConst,
426 isStatic: false);
413 } 427 }
414 428
415 /// A ClosureField that has been "boxed" to prevent name shadowing with the 429 /// A ClosureField that has been "boxed" to prevent name shadowing with the
416 /// original variable and ensure that this variable is updated/read with the 430 /// original variable and ensure that this variable is updated/read with the
417 /// most recent value. 431 /// most recent value.
418 /// This corresponds to BoxFieldElement; we reuse BoxLocal from the original 432 /// This corresponds to BoxFieldElement; we reuse BoxLocal from the original
419 /// algorithm to correspond to the actual name of the variable. 433 /// algorithm to correspond to the actual name of the variable.
420 class JBoxedField extends JField { 434 class JBoxedField extends JField {
421 final BoxLocal box; 435 final BoxLocal box;
422 JBoxedField(String name, int memberIndex, this.box, 436 JBoxedField(String name, int memberIndex, this.box, JClass containingClass,
423 KernelClosureClass containingClass, bool isConst, bool isAssignable) 437 bool isConst, bool isAssignable)
424 : super(memberIndex, containingClass.library, containingClass, 438 : super(memberIndex, containingClass.library, containingClass,
425 new Name(name, containingClass.library), 439 new Name(name, containingClass.library),
426 isAssignable: isAssignable, isConst: isConst); 440 isAssignable: isAssignable, isConst: isConst);
427 } 441 }
428 442
429 class ClosureClassDefinition implements ClassDefinition { 443 class ClosureClassDefinition implements ClassDefinition {
430 final ClassEntity cls; 444 final ClassEntity cls;
431 final SourceSpan location; 445 final SourceSpan location;
432 446
433 ClosureClassDefinition(this.cls, this.location); 447 ClosureClassDefinition(this.cls, this.location);
(...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after
523 KernelScopeInfo scopeInfo; 537 KernelScopeInfo scopeInfo;
524 538
525 /// Collected [CapturedScope] data for nodes. 539 /// Collected [CapturedScope] data for nodes.
526 Map<ir.Node, KernelCapturedScope> capturedScopesMap = 540 Map<ir.Node, KernelCapturedScope> capturedScopesMap =
527 <ir.Node, KernelCapturedScope>{}; 541 <ir.Node, KernelCapturedScope>{};
528 542
529 /// Collected [ScopeInfo] data for nodes. 543 /// Collected [ScopeInfo] data for nodes.
530 Map<ir.FunctionNode, KernelScopeInfo> closuresToGenerate = 544 Map<ir.FunctionNode, KernelScopeInfo> closuresToGenerate =
531 <ir.FunctionNode, KernelScopeInfo>{}; 545 <ir.FunctionNode, KernelScopeInfo>{};
532 } 546 }
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