| Index: sdk/lib/_internal/compiler/implementation/types/simple_types_inferrer.dart
|
| ===================================================================
|
| --- sdk/lib/_internal/compiler/implementation/types/simple_types_inferrer.dart (revision 22937)
|
| +++ sdk/lib/_internal/compiler/implementation/types/simple_types_inferrer.dart (working copy)
|
| @@ -623,6 +623,9 @@
|
|
|
| bool recordType(Element analyzedElement, TypeMask type) {
|
| assert(type != null);
|
| + assert(analyzedElement.isField()
|
| + || analyzedElement.isParameter()
|
| + || analyzedElement.isFieldParameter());
|
| return internalRecordType(analyzedElement, type, typeOf);
|
| }
|
|
|
| @@ -1340,7 +1343,7 @@
|
| class LocalsHandler {
|
| final InternalSimpleTypesInferrer inferrer;
|
| final Map<Element, TypeMask> locals;
|
| - final Set<Element> capturedAndBoxed;
|
| + final Map<Element, Element> capturedAndBoxed;
|
| final Map<Element, TypeMask> fieldsInitializedInConstructor;
|
| final bool inTryBlock;
|
| bool isThisExposed;
|
| @@ -1353,13 +1356,14 @@
|
|
|
| LocalsHandler(this.inferrer)
|
| : locals = new Map<Element, TypeMask>(),
|
| - capturedAndBoxed = new Set<Element>(),
|
| + capturedAndBoxed = new Map<Element, Element>(),
|
| fieldsInitializedInConstructor = new Map<Element, TypeMask>(),
|
| inTryBlock = false,
|
| isThisExposed = true;
|
| LocalsHandler.from(LocalsHandler other, {bool inTryBlock: false})
|
| : locals = new Map<Element, TypeMask>.from(other.locals),
|
| - capturedAndBoxed = new Set<Element>.from(other.capturedAndBoxed),
|
| + capturedAndBoxed = new Map<Element, Element>.from(
|
| + other.capturedAndBoxed),
|
| fieldsInitializedInConstructor = new Map<Element, TypeMask>.from(
|
| other.fieldsInitializedInConstructor),
|
| inTryBlock = other.inTryBlock || inTryBlock,
|
| @@ -1367,8 +1371,8 @@
|
| isThisExposed = other.isThisExposed;
|
|
|
| TypeMask use(Element local) {
|
| - if (capturedAndBoxed.contains(local)) {
|
| - return inferrer.typeOfElement(local);
|
| + if (capturedAndBoxed.containsKey(local)) {
|
| + return inferrer.typeOfElement(capturedAndBoxed[local]);
|
| }
|
| return locals[local];
|
| }
|
| @@ -1379,7 +1383,7 @@
|
| || inferrer.compiler.enableTypeAssertions) {
|
| type = inferrer.narrowType(type, local.computeType(inferrer.compiler));
|
| }
|
| - if (capturedAndBoxed.contains(local) || inTryBlock) {
|
| + if (capturedAndBoxed.containsKey(local) || inTryBlock) {
|
| // If a local is captured and boxed, or is set in a try block,
|
| // we compute the LUB of its assignments.
|
| //
|
| @@ -1391,8 +1395,8 @@
|
| locals[local] = type;
|
| }
|
|
|
| - void setCapturedAndBoxed(Element local) {
|
| - capturedAndBoxed.add(local);
|
| + void setCapturedAndBoxed(Element local, Element field) {
|
| + capturedAndBoxed[local] = field;
|
| }
|
|
|
| /**
|
| @@ -1405,7 +1409,7 @@
|
| // Iterating over a map and just updating its entries is OK.
|
| locals.forEach((Element local, TypeMask oldType) {
|
| TypeMask otherType = other.locals[local];
|
| - bool isCaptured = capturedAndBoxed.contains(local);
|
| + bool isCaptured = capturedAndBoxed.containsKey(local);
|
| if (otherType == null) {
|
| if (!isCaptured) {
|
| // If [local] is not in the other map and is not captured
|
| @@ -1436,12 +1440,12 @@
|
| // Update the locals that are captured and boxed. We
|
| // unconditionally add them to [this] because we register the type
|
| // of boxed variables after analyzing all closures.
|
| - other.capturedAndBoxed.forEach((Element element) {
|
| - capturedAndBoxed.add(element);
|
| + other.capturedAndBoxed.forEach((Element local, Element field) {
|
| + capturedAndBoxed[local] = field;
|
| // If [element] is not in our [locals], we need to update it.
|
| // Otherwise, we have already computed the LUB of it.
|
| - if (locals[element] == null) {
|
| - locals[element] = other.locals[element];
|
| + if (locals[local] == null) {
|
| + locals[local] = other.locals[local];
|
| }
|
| });
|
|
|
| @@ -1534,14 +1538,14 @@
|
| // Update the locals that are boxed in [locals]. These locals will
|
| // be handled specially, in that we are computing their LUB at
|
| // each update, and reading them yields the type that was found in a
|
| - // previous analysis ouf [outermostElement].
|
| + // previous analysis of [outermostElement].
|
| ClosureClassMap closureData =
|
| compiler.closureToClassMapper.computeClosureToClassMapping(
|
| analyzedElement, node, elements);
|
| ClosureScope scopeData = closureData.capturingScopes[node];
|
| if (scopeData != null) {
|
| - scopeData.capturedVariableMapping.forEach((Element variable, _) {
|
| - locals.setCapturedAndBoxed(variable);
|
| + scopeData.capturedVariableMapping.forEach((variable, field) {
|
| + locals.setCapturedAndBoxed(variable, field);
|
| });
|
| }
|
| if (analyzedElement.isField()) {
|
| @@ -1639,8 +1643,8 @@
|
|
|
| if (analyzedElement == outermostElement) {
|
| bool changed = false;
|
| - locals.capturedAndBoxed.forEach((Element local) {
|
| - if (inferrer.recordType(local, locals.locals[local])) {
|
| + locals.capturedAndBoxed.forEach((Element local, Element field) {
|
| + if (inferrer.recordType(field, locals.locals[local])) {
|
| changed = true;
|
| }
|
| });
|
| @@ -1709,11 +1713,11 @@
|
| // same as [newType].
|
| ClosureClassMap nestedClosureData =
|
| compiler.closureToClassMapper.getMappingForNestedFunction(node);
|
| - nestedClosureData.forEachNonBoxedCapturedVariable((Element variable) {
|
| + nestedClosureData.forEachNonBoxedCapturedVariable((variable, field) {
|
| // The type may be null for instance contexts (this and type
|
| // parameters), as well as captured argument checks.
|
| if (locals.locals[variable] == null) return;
|
| - inferrer.recordType(variable, locals.locals[variable]);
|
| + inferrer.recordType(field, locals.locals[variable]);
|
| });
|
|
|
| return inferrer.functionType;
|
|
|