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

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: . 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
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 ClassEntity closureClassEntity;
sra1 2017/08/16 22:25:19 JClass makes direction more explict
Emily Fortuna 2017/08/16 22:55:46 Done.
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. Is there a better
402 // way?
403 final KernelToLocalsMap localsMap;
sra1 2017/08/16 22:25:19 This (or the part that deals with ir.VariableDefin
Emily Fortuna 2017/08/16 22:55:46 added TODO
404
405 JClosureClass(this.localsMap, JLibrary library, int classIndex, String name)
406 : super(library, classIndex, name, isAbstract: false);
407
408 @override
409 bool get isClosure => true;
410
411 String toString() => '${jsElementPrefix}closure_class($name)';
412 }
413
407 class JClosureField extends JField { 414 class JClosureField extends JField {
408 JClosureField(String name, int memberIndex, 415 JClosureField(String name, int memberIndex,
409 KernelClosureClass containingClass, bool isConst, bool isAssignable) 416 KernelClosureClass containingClass, bool isConst, bool isAssignable)
410 : super(memberIndex, containingClass.library, containingClass, 417 : super(
411 new Name(name, containingClass.library), 418 memberIndex,
412 isAssignable: isAssignable, isConst: isConst, isStatic: false); 419 containingClass.closureClassEntity.library,
420 containingClass.closureClassEntity,
421 new Name(name, containingClass.closureClassEntity.library),
422 isAssignable: isAssignable,
423 isConst: isConst,
424 isStatic: false);
413 } 425 }
414 426
415 /// A ClosureField that has been "boxed" to prevent name shadowing with the 427 /// 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 428 /// original variable and ensure that this variable is updated/read with the
417 /// most recent value. 429 /// most recent value.
418 /// This corresponds to BoxFieldElement; we reuse BoxLocal from the original 430 /// This corresponds to BoxFieldElement; we reuse BoxLocal from the original
419 /// algorithm to correspond to the actual name of the variable. 431 /// algorithm to correspond to the actual name of the variable.
420 class JBoxedField extends JField { 432 class JBoxedField extends JField {
421 final BoxLocal box; 433 final BoxLocal box;
422 JBoxedField(String name, int memberIndex, this.box, 434 JBoxedField(String name, int memberIndex, this.box, JClass containingClass,
423 KernelClosureClass containingClass, bool isConst, bool isAssignable) 435 bool isConst, bool isAssignable)
424 : super(memberIndex, containingClass.library, containingClass, 436 : super(memberIndex, containingClass.library, containingClass,
425 new Name(name, containingClass.library), 437 new Name(name, containingClass.library),
426 isAssignable: isAssignable, isConst: isConst); 438 isAssignable: isAssignable, isConst: isConst);
427 } 439 }
428 440
429 class ClosureClassDefinition implements ClassDefinition { 441 class ClosureClassDefinition implements ClassDefinition {
430 final ClassEntity cls; 442 final ClassEntity cls;
431 final SourceSpan location; 443 final SourceSpan location;
432 444
433 ClosureClassDefinition(this.cls, this.location); 445 ClosureClassDefinition(this.cls, this.location);
(...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after
523 KernelScopeInfo scopeInfo; 535 KernelScopeInfo scopeInfo;
524 536
525 /// Collected [CapturedScope] data for nodes. 537 /// Collected [CapturedScope] data for nodes.
526 Map<ir.Node, KernelCapturedScope> capturedScopesMap = 538 Map<ir.Node, KernelCapturedScope> capturedScopesMap =
527 <ir.Node, KernelCapturedScope>{}; 539 <ir.Node, KernelCapturedScope>{};
528 540
529 /// Collected [ScopeInfo] data for nodes. 541 /// Collected [ScopeInfo] data for nodes.
530 Map<ir.FunctionNode, KernelScopeInfo> closuresToGenerate = 542 Map<ir.FunctionNode, KernelScopeInfo> closuresToGenerate =
531 <ir.FunctionNode, KernelScopeInfo>{}; 543 <ir.FunctionNode, KernelScopeInfo>{};
532 } 544 }
OLDNEW
« no previous file with comments | « no previous file | pkg/compiler/lib/src/js_model/closure_visitors.dart » ('j') | pkg/compiler/lib/src/js_model/locals.dart » ('J')

Powered by Google App Engine
This is Rietveld 408576698