| Index: pkg/compiler/lib/src/ssa/locals_handler.dart
|
| diff --git a/pkg/compiler/lib/src/ssa/locals_handler.dart b/pkg/compiler/lib/src/ssa/locals_handler.dart
|
| index 81af015f00ba57ca3a22d81fc90a03daaaae0e3d..46388324eacb3b4104b3a896d71f946acddbad49 100644
|
| --- a/pkg/compiler/lib/src/ssa/locals_handler.dart
|
| +++ b/pkg/compiler/lib/src/ssa/locals_handler.dart
|
| @@ -10,6 +10,7 @@ import '../elements/types.dart';
|
| import '../io/source_information.dart';
|
| import '../js_backend/native_data.dart';
|
| import '../js_backend/interceptor_data.dart';
|
| +import '../js_model/closure.dart' show JClosureField, JRecord;
|
| import '../tree/tree.dart' as ast;
|
| import '../types/types.dart';
|
| import '../world.dart' show ClosedWorld;
|
| @@ -154,9 +155,7 @@ class LocalsHandler {
|
| directLocals[closureInfo.context] = box;
|
| // Make sure that accesses to the boxed locals go into the box. We also
|
| // need to make sure that parameters are copied into the box if necessary.
|
| - closureInfo.forEachBoxedVariable((_from, _to) {
|
| - LocalVariableElement from = _from;
|
| - BoxFieldElement to = _to;
|
| + closureInfo.forEachBoxedVariable((Local from, FieldEntity boxTo) {
|
| // The [from] can only be a parameter for function-scopes and not
|
| // loop scopes.
|
| if (from.isRegularParameter && !forGenerativeConstructorBody) {
|
| @@ -168,10 +167,10 @@ class LocalsHandler {
|
| // constructor body, because it receives a box that already
|
| // contains the updates as the last parameter.
|
| HInstruction instruction = readLocal(from);
|
| - redirectElement(from, to);
|
| + redirectElement(from, boxTo);
|
| updateLocal(from, instruction);
|
| } else {
|
| - redirectElement(from, to);
|
| + redirectElement(from, boxTo);
|
| }
|
| });
|
| }
|
| @@ -302,8 +301,11 @@ class LocalsHandler {
|
| if (isAccessedDirectly(local)) return false;
|
| if (scopeInfo is! ClosureRepresentationInfo) return false;
|
| FieldEntity redirectTarget = redirectionMapping[local];
|
| + print(
|
| + 'is stored in closure field $local ${isAccessedDirectly(local)} ${scopeInfo.runtimeType} ${redirectTarget.runtimeType}');
|
| if (redirectTarget == null) return false;
|
| - return redirectTarget is ClosureFieldElement;
|
| + return redirectTarget is ClosureFieldElement ||
|
| + redirectTarget is JClosureField;
|
| }
|
|
|
| bool isBoxed(Local local) {
|
| @@ -341,8 +343,9 @@ class LocalsHandler {
|
| }
|
| return value;
|
| } else if (isStoredInClosureField(local)) {
|
| + print('bbbbbbb $local');
|
| ClosureRepresentationInfo closureData = scopeInfo;
|
| - ClosureFieldElement redirect = redirectionMapping[local];
|
| + FieldEntity redirect = redirectionMapping[local];
|
| HInstruction receiver = readLocal(closureData.closureEntity);
|
| TypeMask type = local is BoxLocal
|
| ? commonMasks.nonNullType
|
| @@ -351,12 +354,21 @@ class LocalsHandler {
|
| builder.add(fieldGet);
|
| return fieldGet..sourceInformation = sourceInformation;
|
| } else if (isBoxed(local)) {
|
| - BoxFieldElement redirect = redirectionMapping[local];
|
| + FieldEntity redirect = redirectionMapping[local];
|
| + BoxLocal localBox;
|
| // In the function that declares the captured variable the box is
|
| // accessed as direct local. Inside the nested closure the box is
|
| // accessed through a closure-field.
|
| // Calling [readLocal] makes sure we generate the correct code to get
|
| // the box.
|
| + print("AAAAAAAAAAAAAA $local $redirect ${redirect.runtimeType}");
|
| + if (redirect is BoxFieldElement) {
|
| + localBox = redirect.box;
|
| + } else if (redirect is JRecord) {
|
| + localBox = redirect.box;
|
| + }
|
| + assert(localBox != null);
|
| +
|
| HInstruction box = readLocal(redirect.box);
|
| HInstruction lookup =
|
| new HFieldGet(redirect, box, getTypeOfCapturedVariable(redirect));
|
| @@ -416,12 +428,21 @@ class LocalsHandler {
|
| if (isAccessedDirectly(local)) {
|
| directLocals[local] = value;
|
| } else if (isBoxed(local)) {
|
| - BoxFieldElement redirect = redirectionMapping[local];
|
| + FieldEntity redirect = redirectionMapping[local];
|
| + assert(redirect != null);
|
| + BoxLocal localBox;
|
| + if (redirect is BoxFieldElement) {
|
| + localBox = redirect.box;
|
| + } else if (redirect is JRecord) {
|
| + localBox = redirect.box;
|
| + }
|
| + assert(localBox != null);
|
| +
|
| // The box itself could be captured, or be local. A local variable that
|
| // is captured will be boxed, but the box itself will be a local.
|
| // Inside the closure the box is stored in a closure-field and cannot
|
| // be accessed directly.
|
| - HInstruction box = readLocal(redirect.box);
|
| + HInstruction box = readLocal(localBox);
|
| builder.add(new HFieldSet(redirect, box, value)
|
| ..sourceInformation = sourceInformation);
|
| } else {
|
| @@ -643,10 +664,10 @@ class LocalsHandler {
|
| return result;
|
| }
|
|
|
| - Map<Element, TypeMask> cachedTypesOfCapturedVariables =
|
| - new Map<Element, TypeMask>();
|
| + Map<FieldEntity, TypeMask> cachedTypesOfCapturedVariables =
|
| + new Map<FieldEntity, TypeMask>();
|
|
|
| - TypeMask getTypeOfCapturedVariable(FieldElement element) {
|
| + TypeMask getTypeOfCapturedVariable(FieldEntity element) {
|
| return cachedTypesOfCapturedVariables.putIfAbsent(element, () {
|
| return TypeMaskFactory.inferredTypeForMember(
|
| element, _globalInferenceResults);
|
|
|