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); |