mirror of
https://github.com/dart-lang/sdk
synced 2024-09-05 00:13:50 +00:00
Split LocalsHandler.mergeDiamondFlow into mergeFlow and mergeDiamondFlow.
Change-Id: Ic3e512a2abc67bf3c79c4c2f36f5e0b5e298c4aa Reviewed-on: https://dart-review.googlesource.com/c/85285 Commit-Queue: Johnni Winther <johnniwinther@google.com> Auto-Submit: Johnni Winther <johnniwinther@google.com> Reviewed-by: Sigmund Cherem <sigmund@google.com>
This commit is contained in:
parent
56dec98f0b
commit
b505f0830a
|
@ -49,7 +49,7 @@ class KernelTypeGraphBuilder extends ir.Visitor<TypeInformation> {
|
|||
final bool _inGenerativeConstructor;
|
||||
|
||||
LocalsHandler _locals;
|
||||
FieldInitializationScope _fields;
|
||||
FieldInitializationScope _fieldScope;
|
||||
final SideEffectsBuilder _sideEffectsBuilder;
|
||||
final Map<JumpTarget, List<LocalsHandler>> _breaksFor =
|
||||
<JumpTarget, List<LocalsHandler>>{};
|
||||
|
@ -71,7 +71,9 @@ class KernelTypeGraphBuilder extends ir.Visitor<TypeInformation> {
|
|||
|
||||
KernelTypeGraphBuilder(this._options, this._closedWorld, this._inferrer,
|
||||
this._analyzedMember, this._analyzedNode, this._localsMap,
|
||||
[this._locals, this._fields, Map<Local, FieldEntity> capturedAndBoxed])
|
||||
[this._locals,
|
||||
this._fieldScope,
|
||||
Map<Local, FieldEntity> capturedAndBoxed])
|
||||
: this._types = _inferrer.types,
|
||||
this._memberData = _inferrer.dataOfMember(_analyzedMember),
|
||||
// TODO(johnniwinther): Should side effects also be tracked for field
|
||||
|
@ -86,7 +88,8 @@ class KernelTypeGraphBuilder extends ir.Visitor<TypeInformation> {
|
|||
: <Local, FieldEntity>{} {
|
||||
if (_locals != null) return;
|
||||
|
||||
_fields = _inGenerativeConstructor ? new FieldInitializationScope() : null;
|
||||
_fieldScope =
|
||||
_inGenerativeConstructor ? new FieldInitializationScope() : null;
|
||||
_locals = new LocalsHandler(_analyzedNode);
|
||||
}
|
||||
|
||||
|
@ -99,12 +102,12 @@ class KernelTypeGraphBuilder extends ir.Visitor<TypeInformation> {
|
|||
bool get inLoop => _loopLevel > 0;
|
||||
|
||||
bool get _isThisExposed {
|
||||
return _inGenerativeConstructor ? _fields.isThisExposed : true;
|
||||
return _inGenerativeConstructor ? _fieldScope.isThisExposed : true;
|
||||
}
|
||||
|
||||
void _markThisAsExposed() {
|
||||
if (_inGenerativeConstructor) {
|
||||
_fields.isThisExposed = true;
|
||||
_fieldScope.isThisExposed = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -141,7 +144,7 @@ class KernelTypeGraphBuilder extends ir.Visitor<TypeInformation> {
|
|||
if (!selector.isSetter &&
|
||||
_isInClassOrSubclass(field) &&
|
||||
field.isAssignable &&
|
||||
_fields.readField(field) == null &&
|
||||
_fieldScope.readField(field) == null &&
|
||||
getFieldInitializer(_elementMap, field) == null) {
|
||||
// If the field is being used before this constructor
|
||||
// actually had a chance to initialize it, say it can be
|
||||
|
@ -198,7 +201,7 @@ class KernelTypeGraphBuilder extends ir.Visitor<TypeInformation> {
|
|||
|
||||
void initializationIsIndefinite() {
|
||||
if (_inGenerativeConstructor) {
|
||||
_fields.isIndefinite = true;
|
||||
_fieldScope.isIndefinite = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -257,7 +260,7 @@ class KernelTypeGraphBuilder extends ir.Visitor<TypeInformation> {
|
|||
_elementMap.elementEnvironment.forEachLocalClassMember(cls,
|
||||
(MemberEntity member) {
|
||||
if (member.isField && member.isInstanceMember && member.isAssignable) {
|
||||
TypeInformation type = _fields.readField(member);
|
||||
TypeInformation type = _fieldScope.readField(member);
|
||||
MemberDefinition definition = _elementMap.getMemberDefinition(member);
|
||||
assert(definition.kind == MemberKind.regular);
|
||||
ir.Field node = definition.node;
|
||||
|
@ -291,7 +294,7 @@ class KernelTypeGraphBuilder extends ir.Visitor<TypeInformation> {
|
|||
visitFieldInitializer(ir.FieldInitializer node) {
|
||||
TypeInformation rhsType = visit(node.value);
|
||||
FieldEntity field = _elementMap.getField(node.field);
|
||||
_fields.updateField(field, rhsType);
|
||||
_fieldScope.updateField(field, rhsType);
|
||||
_inferrer.recordTypeOfField(field, rhsType);
|
||||
return null;
|
||||
}
|
||||
|
@ -456,24 +459,24 @@ class KernelTypeGraphBuilder extends ir.Visitor<TypeInformation> {
|
|||
bool simpleCondition =
|
||||
handleCondition(node.condition, positiveTests, negativeTests);
|
||||
LocalsHandler localsBefore = _locals;
|
||||
FieldInitializationScope fieldScopeBefore = _fields;
|
||||
FieldInitializationScope fieldScopeBefore = _fieldScope;
|
||||
|
||||
_locals = new LocalsHandler.from(localsBefore, node);
|
||||
_updateIsChecks(positiveTests, negativeTests);
|
||||
LocalsHandler localsAfterCondition = _locals;
|
||||
FieldInitializationScope fieldScopeAfterThen = _fields;
|
||||
FieldInitializationScope fieldScopeAfterThen = _fieldScope;
|
||||
|
||||
_locals = new LocalsHandler.from(localsBefore, node);
|
||||
_fields = new FieldInitializationScope.from(fieldScopeBefore);
|
||||
_fieldScope = new FieldInitializationScope.from(fieldScopeBefore);
|
||||
if (simpleCondition) _updateIsChecks(negativeTests, positiveTests);
|
||||
visit(node.message);
|
||||
|
||||
LocalsHandler localsAfterMessage = _locals;
|
||||
FieldInitializationScope fieldScopeAfterMessage = _fields;
|
||||
FieldInitializationScope fieldScopeAfterMessage = _fieldScope;
|
||||
localsAfterMessage.seenReturnOrThrow = true;
|
||||
_locals = localsBefore.mergeDiamondFlow(
|
||||
_inferrer, localsAfterCondition, localsAfterMessage);
|
||||
_fields = fieldScopeBefore?.mergeDiamondFlow(
|
||||
_fieldScope = fieldScopeBefore?.mergeDiamondFlow(
|
||||
_inferrer, fieldScopeAfterThen, fieldScopeAfterMessage);
|
||||
return null;
|
||||
}
|
||||
|
@ -535,15 +538,15 @@ class KernelTypeGraphBuilder extends ir.Visitor<TypeInformation> {
|
|||
changed = false;
|
||||
for (ir.SwitchCase switchCase in node.cases) {
|
||||
LocalsHandler localsBeforeCase = _locals;
|
||||
FieldInitializationScope fieldScopeBeforeCase = _fields;
|
||||
FieldInitializationScope fieldScopeBeforeCase = _fieldScope;
|
||||
_locals = new LocalsHandler.from(localsBeforeCase, switchCase);
|
||||
_fields = new FieldInitializationScope.from(fieldScopeBeforeCase);
|
||||
_fieldScope = new FieldInitializationScope.from(fieldScopeBeforeCase);
|
||||
visit(switchCase);
|
||||
LocalsHandler localsAfterCase = _locals;
|
||||
changed = localsBeforeCase.mergeAll(_inferrer, [localsAfterCase]) ||
|
||||
changed;
|
||||
_locals = localsBeforeCase;
|
||||
_fields = fieldScopeBeforeCase;
|
||||
_fieldScope = fieldScopeBeforeCase;
|
||||
}
|
||||
} while (changed);
|
||||
_locals.endLoop(_inferrer, node);
|
||||
|
@ -551,7 +554,7 @@ class KernelTypeGraphBuilder extends ir.Visitor<TypeInformation> {
|
|||
continueTargets.forEach(_clearBreaksAndContinues);
|
||||
} else {
|
||||
LocalsHandler localsBeforeCase = _locals;
|
||||
FieldInitializationScope fieldScopeBeforeCase = _fields;
|
||||
FieldInitializationScope fieldScopeBeforeCase = _fieldScope;
|
||||
List<LocalsHandler> localsToMerge = <LocalsHandler>[];
|
||||
bool hasDefaultCase = false;
|
||||
|
||||
|
@ -566,7 +569,7 @@ class KernelTypeGraphBuilder extends ir.Visitor<TypeInformation> {
|
|||
localsBeforeCase.mergeAfterBreaks(_inferrer, localsToMerge,
|
||||
keepOwnLocals: !hasDefaultCase);
|
||||
_locals = localsBeforeCase;
|
||||
_fields = fieldScopeBeforeCase;
|
||||
_fieldScope = fieldScopeBeforeCase;
|
||||
}
|
||||
_clearBreaksAndContinues(jumpTarget);
|
||||
return null;
|
||||
|
@ -1029,14 +1032,14 @@ class KernelTypeGraphBuilder extends ir.Visitor<TypeInformation> {
|
|||
_loopLevel++;
|
||||
bool changed = false;
|
||||
LocalsHandler localsBefore = _locals;
|
||||
FieldInitializationScope fieldScopeBefore = _fields;
|
||||
FieldInitializationScope fieldScopeBefore = _fieldScope;
|
||||
localsBefore.startLoop(_inferrer, node);
|
||||
do {
|
||||
// Setup (and clear in case of multiple iterations of the loop)
|
||||
// the lists of breaks and continues seen in the loop.
|
||||
_setupBreaksAndContinues(target);
|
||||
_locals = new LocalsHandler.from(localsBefore, node);
|
||||
_fields = new FieldInitializationScope.from(fieldScopeBefore);
|
||||
_fieldScope = new FieldInitializationScope.from(fieldScopeBefore);
|
||||
logic();
|
||||
changed = localsBefore.mergeAll(_inferrer, _getLoopBackEdges(target));
|
||||
} while (changed);
|
||||
|
@ -1045,7 +1048,7 @@ class KernelTypeGraphBuilder extends ir.Visitor<TypeInformation> {
|
|||
bool keepOwnLocals = node is! ir.DoStatement;
|
||||
_locals = localsBefore.mergeAfterBreaks(_inferrer, _getBreaks(target),
|
||||
keepOwnLocals: keepOwnLocals);
|
||||
_fields = fieldScopeBefore;
|
||||
_fieldScope = fieldScopeBefore;
|
||||
_clearBreaksAndContinues(target);
|
||||
return null;
|
||||
}
|
||||
|
@ -1311,7 +1314,7 @@ class KernelTypeGraphBuilder extends ir.Visitor<TypeInformation> {
|
|||
MemberEntity single = targets.first;
|
||||
if (single.isField) {
|
||||
FieldEntity field = single;
|
||||
_fields.updateField(field, rhsType);
|
||||
_fieldScope.updateField(field, rhsType);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1397,26 +1400,26 @@ class KernelTypeGraphBuilder extends ir.Visitor<TypeInformation> {
|
|||
bool simpleCondition =
|
||||
handleCondition(node.condition, positiveTests, negativeTests);
|
||||
LocalsHandler localsBefore = _locals;
|
||||
FieldInitializationScope fieldScopeBefore = _fields;
|
||||
FieldInitializationScope fieldScopeBefore = _fieldScope;
|
||||
_locals = new LocalsHandler.from(localsBefore, node);
|
||||
_fields = new FieldInitializationScope.from(fieldScopeBefore);
|
||||
_fieldScope = new FieldInitializationScope.from(fieldScopeBefore);
|
||||
_updateIsChecks(positiveTests, negativeTests);
|
||||
visit(node.then);
|
||||
|
||||
LocalsHandler localsAfterThen = _locals;
|
||||
FieldInitializationScope fieldScopeAfterThen = _fields;
|
||||
FieldInitializationScope fieldScopeAfterThen = _fieldScope;
|
||||
_locals = new LocalsHandler.from(localsBefore, node);
|
||||
_fields = new FieldInitializationScope.from(fieldScopeBefore);
|
||||
_fieldScope = new FieldInitializationScope.from(fieldScopeBefore);
|
||||
if (simpleCondition) {
|
||||
_updateIsChecks(negativeTests, positiveTests);
|
||||
}
|
||||
visit(node.otherwise);
|
||||
LocalsHandler localsAfterElse = _locals;
|
||||
FieldInitializationScope fieldScopeAfterElse = _fields;
|
||||
FieldInitializationScope fieldScopeAfterElse = _fieldScope;
|
||||
|
||||
_locals = localsBefore.mergeDiamondFlow(
|
||||
_inferrer, localsAfterThen, localsAfterElse);
|
||||
_fields = fieldScopeBefore?.mergeDiamondFlow(
|
||||
_fieldScope = fieldScopeBefore?.mergeDiamondFlow(
|
||||
_inferrer, fieldScopeAfterThen, fieldScopeAfterElse);
|
||||
return null;
|
||||
}
|
||||
|
@ -1454,9 +1457,9 @@ class KernelTypeGraphBuilder extends ir.Visitor<TypeInformation> {
|
|||
}
|
||||
visit(node.left, conditionContext: _accumulateIsChecks);
|
||||
LocalsHandler localsBefore = _locals;
|
||||
FieldInitializationScope fieldScopeBefore = _fields;
|
||||
FieldInitializationScope fieldScopeBefore = _fieldScope;
|
||||
_locals = new LocalsHandler.from(localsBefore, node);
|
||||
_fields = new FieldInitializationScope.from(fieldScopeBefore);
|
||||
_fieldScope = new FieldInitializationScope.from(fieldScopeBefore);
|
||||
_updateIsChecks(_positiveIsChecks, _negativeIsChecks);
|
||||
|
||||
LocalsHandler narrowed;
|
||||
|
@ -1480,8 +1483,8 @@ class KernelTypeGraphBuilder extends ir.Visitor<TypeInformation> {
|
|||
_positiveIsChecks.removeWhere(invalidatedInRightHandSide);
|
||||
_negativeIsChecks.removeWhere(invalidatedInRightHandSide);
|
||||
}
|
||||
_locals = localsBefore.mergeDiamondFlow(_inferrer, _locals, null);
|
||||
_fields = fieldScopeBefore?.mergeDiamondFlow(_inferrer, _fields, null);
|
||||
_locals = localsBefore.mergeFlow(_inferrer, _locals);
|
||||
_fieldScope = fieldScopeBefore;
|
||||
return _types.boolType;
|
||||
} else if (node.operator == '||') {
|
||||
_conditionIsSimple = false;
|
||||
|
@ -1490,15 +1493,15 @@ class KernelTypeGraphBuilder extends ir.Visitor<TypeInformation> {
|
|||
bool isSimple =
|
||||
handleCondition(node.left, positiveIsChecks, negativeIsChecks);
|
||||
LocalsHandler localsBefore = _locals;
|
||||
FieldInitializationScope fieldScopeBefore = _fields;
|
||||
FieldInitializationScope fieldScopeBefore = _fieldScope;
|
||||
_locals = new LocalsHandler.from(_locals, node);
|
||||
_fields = new FieldInitializationScope.from(fieldScopeBefore);
|
||||
_fieldScope = new FieldInitializationScope.from(fieldScopeBefore);
|
||||
if (isSimple) {
|
||||
_updateIsChecks(negativeIsChecks, positiveIsChecks);
|
||||
}
|
||||
visit(node.right, conditionContext: false);
|
||||
_locals = localsBefore.mergeDiamondFlow(_inferrer, _locals, null);
|
||||
_fields = fieldScopeBefore?.mergeDiamondFlow(_inferrer, _fields, null);
|
||||
_locals = localsBefore.mergeFlow(_inferrer, _locals);
|
||||
_fieldScope = fieldScopeBefore;
|
||||
return _types.boolType;
|
||||
}
|
||||
failedAt(CURRENT_ELEMENT_SPANNABLE,
|
||||
|
@ -1514,21 +1517,21 @@ class KernelTypeGraphBuilder extends ir.Visitor<TypeInformation> {
|
|||
handleCondition(node.condition, positiveTests, negativeTests);
|
||||
LocalsHandler localsBefore = _locals;
|
||||
_locals = new LocalsHandler.from(localsBefore, node);
|
||||
FieldInitializationScope fieldScopeBefore = _fields;
|
||||
_fields = new FieldInitializationScope.from(fieldScopeBefore);
|
||||
FieldInitializationScope fieldScopeBefore = _fieldScope;
|
||||
_fieldScope = new FieldInitializationScope.from(fieldScopeBefore);
|
||||
_updateIsChecks(positiveTests, negativeTests);
|
||||
TypeInformation firstType = visit(node.then);
|
||||
LocalsHandler localsAfterThen = _locals;
|
||||
FieldInitializationScope fieldScopeAfterThen = _fields;
|
||||
FieldInitializationScope fieldScopeAfterThen = _fieldScope;
|
||||
_locals = new LocalsHandler.from(localsBefore, node);
|
||||
_fields = new FieldInitializationScope.from(fieldScopeBefore);
|
||||
_fieldScope = new FieldInitializationScope.from(fieldScopeBefore);
|
||||
if (simpleCondition) _updateIsChecks(negativeTests, positiveTests);
|
||||
TypeInformation secondType = visit(node.otherwise);
|
||||
LocalsHandler localsAfterElse = _locals;
|
||||
FieldInitializationScope fieldScopeAfterElse = _fields;
|
||||
FieldInitializationScope fieldScopeAfterElse = _fieldScope;
|
||||
_locals = localsBefore.mergeDiamondFlow(
|
||||
_inferrer, localsAfterThen, localsAfterElse);
|
||||
_fields = fieldScopeBefore?.mergeDiamondFlow(
|
||||
_fieldScope = fieldScopeBefore?.mergeDiamondFlow(
|
||||
_inferrer, fieldScopeAfterThen, fieldScopeAfterElse);
|
||||
return _types.allocateDiamondPhi(firstType, secondType);
|
||||
}
|
||||
|
@ -1580,7 +1583,7 @@ class KernelTypeGraphBuilder extends ir.Visitor<TypeInformation> {
|
|||
LocalsHandler closureLocals =
|
||||
new LocalsHandler.from(_locals, node, useOtherTryBlock: false);
|
||||
FieldInitializationScope closureFieldScope =
|
||||
new FieldInitializationScope.from(_fields);
|
||||
new FieldInitializationScope.from(_fieldScope);
|
||||
KernelTypeGraphBuilder visitor = new KernelTypeGraphBuilder(
|
||||
_options,
|
||||
_closedWorld,
|
||||
|
@ -1653,30 +1656,24 @@ class KernelTypeGraphBuilder extends ir.Visitor<TypeInformation> {
|
|||
@override
|
||||
visitTryCatch(ir.TryCatch node) {
|
||||
LocalsHandler localsBefore = _locals;
|
||||
FieldInitializationScope fieldScopeBefore = _fields;
|
||||
FieldInitializationScope fieldScopeBefore = _fieldScope;
|
||||
_locals = new LocalsHandler.from(localsBefore, node,
|
||||
isTry: true, useOtherTryBlock: false);
|
||||
_fields = new FieldInitializationScope.from(fieldScopeBefore);
|
||||
_fieldScope = new FieldInitializationScope.from(fieldScopeBefore);
|
||||
initializationIsIndefinite();
|
||||
visit(node.body);
|
||||
LocalsHandler localsAfterBody = _locals;
|
||||
FieldInitializationScope fieldScopeAfterBody = _fields;
|
||||
|
||||
_locals = localsBefore.mergeDiamondFlow(_inferrer, localsAfterBody, null);
|
||||
_fields = fieldScopeBefore?.mergeDiamondFlow(
|
||||
_inferrer, fieldScopeAfterBody, null);
|
||||
_locals = localsBefore.mergeFlow(_inferrer, localsAfterBody);
|
||||
_fieldScope = fieldScopeBefore;
|
||||
for (ir.Catch catchBlock in node.catches) {
|
||||
LocalsHandler localsBeforeCatch = _locals;
|
||||
FieldInitializationScope fieldScopeBeforeCatch = _fields;
|
||||
FieldInitializationScope fieldScopeBeforeCatch = _fieldScope;
|
||||
_locals = new LocalsHandler.from(localsBeforeCatch, catchBlock);
|
||||
_fields = new FieldInitializationScope.from(fieldScopeBeforeCatch);
|
||||
_fieldScope = new FieldInitializationScope.from(fieldScopeBeforeCatch);
|
||||
visit(catchBlock);
|
||||
LocalsHandler localsAfterCatch = _locals;
|
||||
FieldInitializationScope fieldScopeAfterCatch = _fields;
|
||||
_locals =
|
||||
localsBeforeCatch.mergeDiamondFlow(_inferrer, localsAfterCatch, null);
|
||||
_fields = fieldScopeBeforeCatch?.mergeDiamondFlow(
|
||||
_inferrer, fieldScopeAfterCatch, null);
|
||||
_locals = localsBeforeCatch.mergeFlow(_inferrer, localsAfterCatch);
|
||||
_fieldScope = fieldScopeBeforeCatch;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
@ -1684,17 +1681,15 @@ class KernelTypeGraphBuilder extends ir.Visitor<TypeInformation> {
|
|||
@override
|
||||
visitTryFinally(ir.TryFinally node) {
|
||||
LocalsHandler localsBefore = _locals;
|
||||
FieldInitializationScope fieldScopeBefore = _fields;
|
||||
FieldInitializationScope fieldScopeBefore = _fieldScope;
|
||||
_locals = new LocalsHandler.from(localsBefore, node,
|
||||
isTry: true, useOtherTryBlock: false);
|
||||
_fields = new FieldInitializationScope.from(fieldScopeBefore);
|
||||
_fieldScope = new FieldInitializationScope.from(fieldScopeBefore);
|
||||
initializationIsIndefinite();
|
||||
visit(node.body);
|
||||
LocalsHandler localsAfterBody = _locals;
|
||||
FieldInitializationScope fieldScopeAfterBody = _fields;
|
||||
_locals = localsBefore.mergeDiamondFlow(_inferrer, localsAfterBody, null);
|
||||
_fields = fieldScopeBefore?.mergeDiamondFlow(
|
||||
_inferrer, fieldScopeAfterBody, null);
|
||||
_locals = localsBefore.mergeFlow(_inferrer, localsAfterBody);
|
||||
_fieldScope = fieldScopeBefore;
|
||||
visit(node.finalizer);
|
||||
return null;
|
||||
}
|
||||
|
|
|
@ -144,9 +144,11 @@ class FieldInitializationScope {
|
|||
fields?.forEach(f);
|
||||
}
|
||||
|
||||
/// Returns the join between [thenScope] and [elseScope] which models the
|
||||
/// flow through either [thenScope] or [elseScope].
|
||||
FieldInitializationScope mergeDiamondFlow(InferrerEngine inferrer,
|
||||
FieldInitializationScope thenScope, FieldInitializationScope elseScope) {
|
||||
if (elseScope == null) return this;
|
||||
assert(elseScope != null);
|
||||
|
||||
// Quick bailout check. If [isThisExposed] or [isIndefinite] is true, we
|
||||
// know the code following won'TypeInformation do anything.
|
||||
|
@ -154,7 +156,7 @@ class FieldInitializationScope {
|
|||
if (isIndefinite) return this;
|
||||
|
||||
FieldInitializationScope otherScope =
|
||||
(elseScope == null || elseScope.fields == null) ? this : elseScope;
|
||||
elseScope.fields == null ? this : elseScope;
|
||||
|
||||
thenScope.forEach((FieldEntity field, TypeInformation type) {
|
||||
TypeInformation otherType = otherScope.readField(field);
|
||||
|
@ -329,17 +331,15 @@ class LocalsHandler {
|
|||
update(inferrer, capturedAndBoxed, local, newType, node, type);
|
||||
}
|
||||
|
||||
LocalsHandler mergeDiamondFlow(InferrerEngine inferrer,
|
||||
LocalsHandler thenBranch, LocalsHandler elseBranch) {
|
||||
seenReturnOrThrow = thenBranch.seenReturnOrThrow &&
|
||||
elseBranch != null &&
|
||||
elseBranch.seenReturnOrThrow;
|
||||
seenBreakOrContinue = thenBranch.seenBreakOrContinue &&
|
||||
elseBranch != null &&
|
||||
elseBranch.seenBreakOrContinue;
|
||||
if (aborts) return this;
|
||||
/// Returns the join between this locals handler and [other] which models the
|
||||
/// flow through either this or [other].
|
||||
LocalsHandler mergeFlow(InferrerEngine inferrer, LocalsHandler other) {
|
||||
seenReturnOrThrow = false;
|
||||
seenBreakOrContinue = false;
|
||||
|
||||
void mergeOneBranch(LocalsHandler other) {
|
||||
if (other.aborts) {
|
||||
return this;
|
||||
} else {
|
||||
other._locals.forEachOwnLocal((Local local, TypeInformation type) {
|
||||
TypeInformation myType = _locals[local];
|
||||
if (myType == null) return; // Variable is only defined in [other].
|
||||
|
@ -347,6 +347,19 @@ class LocalsHandler {
|
|||
_locals[local] = inferrer.types.allocateDiamondPhi(myType, type);
|
||||
});
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
/// Returns the join between [thenBranch] and [elseBranch] which models the
|
||||
/// flow through either [thenBranch] or [elseBranch].
|
||||
LocalsHandler mergeDiamondFlow(InferrerEngine inferrer,
|
||||
LocalsHandler thenBranch, LocalsHandler elseBranch) {
|
||||
assert(elseBranch != null);
|
||||
seenReturnOrThrow =
|
||||
thenBranch.seenReturnOrThrow && elseBranch.seenReturnOrThrow;
|
||||
seenBreakOrContinue =
|
||||
thenBranch.seenBreakOrContinue && elseBranch.seenBreakOrContinue;
|
||||
if (aborts) return this;
|
||||
|
||||
void inPlaceUpdateOneBranch(LocalsHandler other) {
|
||||
other._locals.forEachOwnLocal((Local local, TypeInformation type) {
|
||||
|
@ -358,10 +371,7 @@ class LocalsHandler {
|
|||
}
|
||||
|
||||
if (thenBranch.aborts) {
|
||||
if (elseBranch == null) return this;
|
||||
inPlaceUpdateOneBranch(elseBranch);
|
||||
} else if (elseBranch == null) {
|
||||
mergeOneBranch(thenBranch);
|
||||
} else if (elseBranch.aborts) {
|
||||
inPlaceUpdateOneBranch(thenBranch);
|
||||
} else {
|
||||
|
|
Loading…
Reference in a new issue