| Index: pkg/compiler/lib/src/js_model/closure.dart
|
| diff --git a/pkg/compiler/lib/src/js_model/closure.dart b/pkg/compiler/lib/src/js_model/closure.dart
|
| index 6cccab98e8c8d6fb3a291a2c0a30d5522db518e9..42f41ff96340249ed31ffc528087defef670181b 100644
|
| --- a/pkg/compiler/lib/src/js_model/closure.dart
|
| +++ b/pkg/compiler/lib/src/js_model/closure.dart
|
| @@ -17,6 +17,32 @@ import 'elements.dart';
|
| import 'closure_visitors.dart';
|
| import 'locals.dart';
|
|
|
| +class KernelClosureAnalysis {
|
| + /// Inspect members and mark if those members capture any state that needs to
|
| + /// be marked as free variables.
|
| + static ClosureModel computeClosureModel(MemberEntity entity, ir.Member node) {
|
| + if (entity.isAbstract) return null;
|
| + if (entity.isField && !entity.isInstanceMember) {
|
| + ir.Field field = node;
|
| + // Skip top-level/static fields without an initializer.
|
| + if (field.initializer == null) return null;
|
| + }
|
| +
|
| + ClosureModel model = new ClosureModel();
|
| + CapturedScopeBuilder translator = new CapturedScopeBuilder(model,
|
| + hasThisLocal: entity.isInstanceMember || entity.isConstructor);
|
| + if (entity.isField) {
|
| + if (node is ir.Field && node.initializer != null) {
|
| + translator.translateLazyInitializer(node);
|
| + }
|
| + } else {
|
| + assert(node is ir.Procedure || node is ir.Constructor);
|
| + translator.translateConstructorOrProcedure(node);
|
| + }
|
| + return model;
|
| + }
|
| +}
|
| +
|
| /// Closure conversion code using our new Entity model. Closure conversion is
|
| /// necessary because the semantics of closures are slightly different in Dart
|
| /// than JavaScript. Closure conversion is separated out into two phases:
|
| @@ -35,6 +61,7 @@ import 'locals.dart';
|
| class KernelClosureConversionTask extends ClosureConversionTask<ir.Node> {
|
| final KernelToElementMapForBuilding _elementMap;
|
| final GlobalLocalsMap _globalLocalsMap;
|
| + final Map<MemberEntity, ClosureModel> _closureModels;
|
|
|
| /// Map of the scoping information that corresponds to a particular entity.
|
| Map<Entity, ScopeInfo> _scopeMap = <Entity, ScopeInfo>{};
|
| @@ -43,13 +70,8 @@ class KernelClosureConversionTask extends ClosureConversionTask<ir.Node> {
|
| Map<Entity, ClosureRepresentationInfo> _closureRepresentationMap =
|
| <Entity, ClosureRepresentationInfo>{};
|
|
|
| - /// Should only be used at the very beginning to ensure we are looking at the
|
| - /// right kind of elements.
|
| - // TODO(efortuna): Remove this map once we have one kernel backend strategy.
|
| - final JsToFrontendMap _kToJElementMap;
|
| -
|
| KernelClosureConversionTask(Measurer measurer, this._elementMap,
|
| - this._kToJElementMap, this._globalLocalsMap)
|
| + this._globalLocalsMap, this._closureModels)
|
| : super(measurer);
|
|
|
| /// The combined steps of generating our intermediate representation of
|
| @@ -61,32 +83,7 @@ class KernelClosureConversionTask extends ClosureConversionTask<ir.Node> {
|
| @override
|
| void convertClosures(Iterable<MemberEntity> processedEntities,
|
| ClosedWorldRefiner closedWorldRefiner) {
|
| - Map<MemberEntity, ClosureModel> closureModels =
|
| - _computeClosureModels(processedEntities);
|
| - _createClosureEntities(closureModels, closedWorldRefiner);
|
| - }
|
| -
|
| - // TODO(johnniwinther,efortuna): Compute this during resolution. See
|
| - // documentation on [convertClosures].
|
| - Map<MemberEntity, ClosureModel> _computeClosureModels(
|
| - Iterable<MemberEntity> processedEntities) {
|
| - Map<MemberEntity, ClosureModel> closureModels =
|
| - <MemberEntity, ClosureModel>{};
|
| -
|
| - processedEntities.forEach((MemberEntity kEntity) {
|
| - MemberEntity entity = _kToJElementMap.toBackendMember(kEntity);
|
| - if (entity.isAbstract) return;
|
| - if (entity.isField && !entity.isInstanceMember) {
|
| - MemberDefinition definition = _elementMap.getMemberDefinition(entity);
|
| - assert(definition.kind == MemberKind.regular,
|
| - failedAt(entity, "Unexpected member definition $definition"));
|
| - ir.Field field = definition.node;
|
| - // Skip top-level/static fields without an initializer.
|
| - if (field.initializer == null) return;
|
| - }
|
| - closureModels[entity] = _buildClosureModel(entity);
|
| - });
|
| - return closureModels;
|
| + _createClosureEntities(_closureModels, closedWorldRefiner);
|
| }
|
|
|
| void _createClosureEntities(Map<MemberEntity, ClosureModel> closureModels,
|
| @@ -116,32 +113,6 @@ class KernelClosureConversionTask extends ClosureConversionTask<ir.Node> {
|
| });
|
| }
|
|
|
| - /// Inspect members and mark if those members capture any state that needs to
|
| - /// be marked as free variables.
|
| - ClosureModel _buildClosureModel(MemberEntity entity) {
|
| - ClosureModel model = new ClosureModel();
|
| - MemberDefinition definition = _elementMap.getMemberDefinition(entity);
|
| - switch (definition.kind) {
|
| - case MemberKind.regular:
|
| - case MemberKind.constructor:
|
| - break;
|
| - default:
|
| - failedAt(entity, "Unexpected member definition $definition");
|
| - }
|
| - ir.Node node = definition.node;
|
| - CapturedScopeBuilder translator = new CapturedScopeBuilder(model,
|
| - hasThisLocal: entity.isInstanceMember || entity.isConstructor);
|
| - if (entity.isField) {
|
| - if (node is ir.Field && node.initializer != null) {
|
| - translator.translateLazyInitializer(node);
|
| - }
|
| - } else {
|
| - assert(node is ir.Procedure || node is ir.Constructor);
|
| - translator.translateConstructorOrProcedure(node);
|
| - }
|
| - return model;
|
| - }
|
| -
|
| /// Given what variables are captured at each point, construct closure classes
|
| /// with fields containing the captured variables to replicate the Dart
|
| /// closure semantics in JS. If this closure captures any variables (meaning
|
|
|