Remove redundant fields from LocalsHandler
Change-Id: I6ba0db5996e0a6e1b9799cba01a1c5b6f9d81a42
Reviewed-on: https://dart-review.googlesource.com/c/84427
Reviewed-by: Sigmund Cherem <sigmund@google.com>
Commit-Queue: Johnni Winther <johnniwinther@google.com>
diff --git a/pkg/compiler/lib/src/inferrer/builder_kernel.dart b/pkg/compiler/lib/src/inferrer/builder_kernel.dart
index e2fd017..cbb7f3a 100644
--- a/pkg/compiler/lib/src/inferrer/builder_kernel.dart
+++ b/pkg/compiler/lib/src/inferrer/builder_kernel.dart
@@ -82,9 +82,8 @@
if (_locals != null) return;
FieldInitializationScope fieldScope =
- _inGenerativeConstructor ? new FieldInitializationScope(_types) : null;
- _locals = new LocalsHandler(
- _inferrer, _types, _options, _analyzedNode, fieldScope);
+ _inGenerativeConstructor ? new FieldInitializationScope() : null;
+ _locals = new LocalsHandler(_analyzedNode, fieldScope);
}
JsToElementMap get _elementMap => _closedWorld.elementMap;
@@ -226,7 +225,8 @@
void handleParameter(ir.VariableDeclaration node, {bool isOptional}) {
Local local = _localsMap.getLocalVariable(node);
DartType type = _localsMap.getLocalType(_elementMap, local);
- _locals.update(local, _inferrer.typeOfParameter(local), node, type);
+ _locals.update(
+ _inferrer, local, _inferrer.typeOfParameter(local), node, type);
if (isOptional) {
TypeInformation type;
if (node.initializer != null) {
@@ -460,7 +460,7 @@
if (simpleCondition) _updateIsChecks(negativeTests, positiveTests);
visit(node.message);
_locals.seenReturnOrThrow = true;
- saved.mergeDiamondFlow(thenLocals, _locals);
+ saved.mergeDiamondFlow(_inferrer, thenLocals, _locals);
_locals = saved;
return null;
}
@@ -489,7 +489,7 @@
JumpTarget jumpTarget = _localsMap.getJumpTargetForLabel(node);
_setupBreaksAndContinues(jumpTarget);
visit(body);
- _locals.mergeAfterBreaks(_getBreaks(jumpTarget));
+ _locals.mergeAfterBreaks(_inferrer, _getBreaks(jumpTarget));
_clearBreaksAndContinues(jumpTarget);
}
return null;
@@ -517,18 +517,18 @@
// visit all cases and update [locals] until we have reached a
// fixed point.
bool changed;
- _locals.startLoop(node);
+ _locals.startLoop(_inferrer, node);
do {
changed = false;
for (ir.SwitchCase switchCase in node.cases) {
LocalsHandler saved = _locals;
_locals = new LocalsHandler.from(_locals, switchCase);
visit(switchCase);
- changed = saved.mergeAll([_locals]) || changed;
+ changed = saved.mergeAll(_inferrer, [_locals]) || changed;
_locals = saved;
}
} while (changed);
- _locals.endLoop(node);
+ _locals.endLoop(_inferrer, node);
continueTargets.forEach(_clearBreaksAndContinues);
} else {
@@ -544,7 +544,8 @@
visit(switchCase);
localsToMerge.add(_locals);
}
- saved.mergeAfterBreaks(localsToMerge, keepOwnLocals: !hasDefaultCase);
+ saved.mergeAfterBreaks(_inferrer, localsToMerge,
+ keepOwnLocals: !hasDefaultCase);
_locals = saved;
}
_clearBreaksAndContinues(jumpTarget);
@@ -682,9 +683,9 @@
Local local = _localsMap.getLocalVariable(node);
DartType type = _localsMap.getLocalType(_elementMap, local);
if (node.initializer == null) {
- _locals.update(local, _types.nullType, node, type);
+ _locals.update(_inferrer, local, _types.nullType, node, type);
} else {
- _locals.update(local, visit(node.initializer), node, type);
+ _locals.update(_inferrer, local, visit(node.initializer), node, type);
}
if (node.initializer is ir.ThisExpression) {
_markThisAsExposed();
@@ -695,7 +696,7 @@
@override
TypeInformation visitVariableGet(ir.VariableGet node) {
Local local = _localsMap.getLocalVariable(node.variable);
- TypeInformation type = _locals.use(local);
+ TypeInformation type = _locals.use(_inferrer, local);
assert(type != null, "Missing type information for $local.");
return type;
}
@@ -708,7 +709,7 @@
}
Local local = _localsMap.getLocalVariable(node.variable);
DartType type = _localsMap.getLocalType(_elementMap, local);
- _locals.update(local, rhsType, node, type);
+ _locals.update(_inferrer, local, rhsType, node, type);
return rhsType;
}
@@ -820,7 +821,7 @@
TypeInformation refinedType = _types
.refineReceiver(selector, mask, receiverType, isConditional: false);
DartType type = _localsMap.getLocalType(_elementMap, local);
- _locals.update(local, refinedType, node, type);
+ _locals.update(_inferrer, local, refinedType, node, type);
List<Refinement> refinements = _localRefinementMap[variable];
if (refinements != null) {
refinements.add(new Refinement(selector, mask));
@@ -903,12 +904,12 @@
if (refinements.isNotEmpty) {
Local local = _localsMap.getLocalVariable(alias);
DartType type = _localsMap.getLocalType(_elementMap, local);
- TypeInformation localType = _locals.use(local);
+ TypeInformation localType = _locals.use(_inferrer, local);
for (Refinement refinement in refinements) {
localType = _types.refineReceiver(
refinement.selector, refinement.mask, localType,
isConditional: true);
- _locals.update(local, localType, node, type);
+ _locals.update(_inferrer, local, localType, node, type);
}
}
}
@@ -961,7 +962,8 @@
Local variable = _localsMap.getLocalVariable(node.variable);
DartType variableType = _localsMap.getLocalType(_elementMap, variable);
- _locals.update(variable, currentType, node.variable, variableType);
+ _locals.update(
+ _inferrer, variable, currentType, node.variable, variableType);
JumpTarget target = _localsMap.getJumpTargetForForIn(node);
return handleLoop(node, target, () {
@@ -1002,19 +1004,20 @@
_loopLevel++;
bool changed = false;
LocalsHandler saved = _locals;
- saved.startLoop(node);
+ saved.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(saved, node);
logic();
- changed = saved.mergeAll(_getLoopBackEdges(target));
+ changed = saved.mergeAll(_inferrer, _getLoopBackEdges(target));
} while (changed);
_loopLevel--;
- saved.endLoop(node);
+ saved.endLoop(_inferrer, node);
bool keepOwnLocals = node is! ir.DoStatement;
- saved.mergeAfterBreaks(_getBreaks(target), keepOwnLocals: keepOwnLocals);
+ saved.mergeAfterBreaks(_inferrer, _getBreaks(target),
+ keepOwnLocals: keepOwnLocals);
_locals = saved;
_clearBreaksAndContinues(target);
return null;
@@ -1342,18 +1345,19 @@
List<IsCheck> positiveTests, List<IsCheck> negativeTests) {
for (IsCheck check in positiveTests) {
if (check.type != null) {
- _locals.narrow(check.local, check.type, check.node);
+ _locals.narrow(_inferrer, check.local, check.type, check.node);
} else {
DartType localType = _localsMap.getLocalType(_elementMap, check.local);
- _locals.update(check.local, _types.nullType, check.node, localType);
+ _locals.update(
+ _inferrer, check.local, _types.nullType, check.node, localType);
}
}
for (IsCheck check in negativeTests) {
if (check.type != null) {
// TODO(johnniwinther): Use negative type knowledge.
} else {
- _locals.narrow(
- check.local, _closedWorld.commonElements.objectType, check.node);
+ _locals.narrow(_inferrer, check.local,
+ _closedWorld.commonElements.objectType, check.node);
}
}
}
@@ -1374,7 +1378,7 @@
_updateIsChecks(negativeTests, positiveTests);
}
visit(node.otherwise);
- saved.mergeDiamondFlow(thenLocals, _locals);
+ saved.mergeDiamondFlow(_inferrer, thenLocals, _locals);
_locals = saved;
return null;
}
@@ -1431,7 +1435,7 @@
_positiveIsChecks.removeWhere(invalidatedInRightHandSide);
_negativeIsChecks.removeWhere(invalidatedInRightHandSide);
}
- saved.mergeDiamondFlow(_locals, null);
+ saved.mergeDiamondFlow(_inferrer, _locals, null);
_locals = saved;
return _types.boolType;
} else if (node.operator == '||') {
@@ -1446,7 +1450,7 @@
_updateIsChecks(negativeIsChecks, positiveIsChecks);
}
visit(node.right, conditionContext: false);
- saved.mergeDiamondFlow(_locals, null);
+ saved.mergeDiamondFlow(_inferrer, _locals, null);
_locals = saved;
return _types.boolType;
}
@@ -1469,7 +1473,7 @@
_locals = new LocalsHandler.from(saved, node);
if (simpleCondition) _updateIsChecks(negativeTests, positiveTests);
TypeInformation secondType = visit(node.otherwise);
- saved.mergeDiamondFlow(thenLocals, _locals);
+ saved.mergeDiamondFlow(_inferrer, thenLocals, _locals);
_locals = saved;
return _types.allocateDiamondPhi(firstType, secondType);
}
@@ -1508,7 +1512,7 @@
if (variable != null) {
Local local = _localsMap.getLocalVariable(variable);
DartType type = _localsMap.getLocalType(_elementMap, local);
- _locals.update(local, localFunctionType, node, type);
+ _locals.update(_inferrer, local, localFunctionType, node, type);
}
// We don't put the closure in the work queue of the
@@ -1590,13 +1594,13 @@
isTry: true, useOtherTryBlock: false);
initializationIsIndefinite();
visit(node.body);
- saved.mergeDiamondFlow(_locals, null);
+ saved.mergeDiamondFlow(_inferrer, _locals, null);
_locals = saved;
for (ir.Catch catchBlock in node.catches) {
saved = _locals;
_locals = new LocalsHandler.from(_locals, catchBlock);
visit(catchBlock);
- saved.mergeDiamondFlow(_locals, null);
+ saved.mergeDiamondFlow(_inferrer, _locals, null);
_locals = saved;
}
return null;
@@ -1609,7 +1613,7 @@
isTry: true, useOtherTryBlock: false);
initializationIsIndefinite();
visit(node.body);
- saved.mergeDiamondFlow(_locals, null);
+ saved.mergeDiamondFlow(_inferrer, _locals, null);
_locals = saved;
visit(node.finalizer);
return null;
@@ -1630,13 +1634,14 @@
mask = _types.dynamicType;
}
Local local = _localsMap.getLocalVariable(exception);
- _locals.update(local, mask, node, const DynamicType());
+ _locals.update(_inferrer, local, mask, node, const DynamicType());
}
ir.VariableDeclaration stackTrace = node.stackTrace;
if (stackTrace != null) {
Local local = _localsMap.getLocalVariable(stackTrace);
// TODO(johnniwinther): Use a mask based on [StackTrace].
- _locals.update(local, _types.dynamicType, node, const DynamicType());
+ _locals.update(
+ _inferrer, local, _types.dynamicType, node, const DynamicType());
}
visit(node.body);
return null;
diff --git a/pkg/compiler/lib/src/inferrer/locals_handler.dart b/pkg/compiler/lib/src/inferrer/locals_handler.dart
index ae92797..b0b1fd8 100644
--- a/pkg/compiler/lib/src/inferrer/locals_handler.dart
+++ b/pkg/compiler/lib/src/inferrer/locals_handler.dart
@@ -6,13 +6,11 @@
import 'dart:collection' show IterableMixin;
import 'package:kernel/ast.dart' as ir;
-import '../options.dart' show CompilerOptions;
import '../elements/entities.dart';
import '../elements/types.dart';
import '../util/util.dart';
import 'inferrer_engine.dart';
import 'type_graph_nodes.dart';
-import 'type_system.dart';
/**
* A variable scope holds types for variables. It has a link to a
@@ -111,7 +109,6 @@
/// Tracks initializers via initializations and assignments.
class FieldInitializationScope {
- final TypeSystem types;
Map<FieldEntity, TypeInformation> fields;
bool isThisExposed;
@@ -119,13 +116,12 @@
/// e.g. an early return or caught exception.
bool isIndefinite;
- FieldInitializationScope(this.types)
+ FieldInitializationScope()
: isThisExposed = false,
isIndefinite = false;
FieldInitializationScope.internalFrom(FieldInitializationScope other)
- : types = other.types,
- isThisExposed = other.isThisExposed,
+ : isThisExposed = other.isThisExposed,
isIndefinite = other.isIndefinite;
factory FieldInitializationScope.from(FieldInitializationScope other) {
@@ -148,7 +144,7 @@
fields?.forEach(f);
}
- void mergeDiamondFlow(
+ void mergeDiamondFlow(InferrerEngine inferrer,
FieldInitializationScope thenScope, FieldInitializationScope elseScope) {
// Quick bailout check. If [isThisExposed] or [isIndefinite] is true, we
// know the code following won'TypeInformation do anything.
@@ -161,7 +157,7 @@
thenScope.forEach((FieldEntity field, TypeInformation type) {
TypeInformation otherType = otherScope.readField(field);
if (otherType == null) return;
- updateField(field, types.allocateDiamondPhi(type, otherType));
+ updateField(field, inferrer.types.allocateDiamondPhi(type, otherType));
});
isThisExposed = thenScope.isThisExposed || elseScope.isThisExposed;
@@ -249,9 +245,6 @@
* Placeholder for inferred types of local variables.
*/
class LocalsHandler {
- final CompilerOptions options;
- final TypeSystem types;
- final InferrerEngine inferrer;
final VariableScope locals;
final Map<Local, FieldEntity> _capturedAndBoxed;
final FieldInitializationScope fieldScope;
@@ -265,8 +258,10 @@
bool get inTryBlock => tryBlock != null;
- LocalsHandler(this.inferrer, this.types, this.options, ir.Node block,
- [this.fieldScope])
+ LocalsHandler.internal(ir.Node block, this.fieldScope, this.locals,
+ this._capturedAndBoxed, this.tryBlock);
+
+ LocalsHandler(ir.Node block, [this.fieldScope])
: locals = new VariableScope(block, isTry: false),
_capturedAndBoxed = new Map<Local, FieldEntity>(),
tryBlock = null;
@@ -275,10 +270,7 @@
{bool isTry: false, bool useOtherTryBlock: true})
: locals = new VariableScope(block, isTry: isTry, parent: other.locals),
fieldScope = new FieldInitializationScope.from(other.fieldScope),
- _capturedAndBoxed = other._capturedAndBoxed,
- types = other.types,
- inferrer = other.inferrer,
- options = other.options {
+ _capturedAndBoxed = other._capturedAndBoxed {
tryBlock = useOtherTryBlock ? other.tryBlock : this;
}
@@ -286,21 +278,15 @@
: locals = new VariableScope.deepCopyOf(other.locals),
fieldScope = new FieldInitializationScope.from(other.fieldScope),
_capturedAndBoxed = other._capturedAndBoxed,
- tryBlock = other.tryBlock,
- types = other.types,
- inferrer = other.inferrer,
- options = other.options;
+ tryBlock = other.tryBlock;
LocalsHandler.topLevelCopyOf(LocalsHandler other)
: locals = new VariableScope.topLevelCopyOf(other.locals),
fieldScope = new FieldInitializationScope.from(other.fieldScope),
_capturedAndBoxed = other._capturedAndBoxed,
- tryBlock = other.tryBlock,
- types = other.types,
- inferrer = other.inferrer,
- options = other.options;
+ tryBlock = other.tryBlock;
- TypeInformation use(Local local) {
+ TypeInformation use(InferrerEngine inferrer, Local local) {
if (_capturedAndBoxed.containsKey(local)) {
FieldEntity field = _capturedAndBoxed[local];
return inferrer.typeOfMember(field);
@@ -309,12 +295,12 @@
}
}
- void update(
- Local local, TypeInformation type, ir.Node node, DartType staticType,
+ void update(InferrerEngine inferrer, Local local, TypeInformation type,
+ ir.Node node, DartType staticType,
{bool isSetIfNull: false}) {
assert(type != null);
- if (!options.assignmentCheckPolicy.isIgnored) {
- type = types.narrowType(type, staticType);
+ if (!inferrer.options.assignmentCheckPolicy.isIgnored) {
+ type = inferrer.types.narrowType(type, staticType);
}
updateLocal() {
TypeInformation currentType = locals[local];
@@ -322,10 +308,10 @@
if (isSetIfNull && currentType != null) {
// If-null assignments may return either the new or the original value
// narrowed to non-null.
- type = types.addPhiInput(
+ type = inferrer.types.addPhiInput(
local,
- types.allocatePhi(
- locals.block, local, types.narrowNotNull(currentType),
+ inferrer.types.allocatePhi(
+ locals.block, local, inferrer.types.narrowNotNull(currentType),
isTry: locals.isTry),
type);
}
@@ -342,10 +328,11 @@
// the right phi for it.
TypeInformation existing = tryBlock.locals.parent[local];
if (existing != null) {
- TypeInformation phiType = types.allocatePhi(
+ TypeInformation phiType = inferrer.types.allocatePhi(
tryBlock.locals.block, local, existing,
isTry: tryBlock.locals.isTry);
- TypeInformation inputType = types.addPhiInput(local, phiType, type);
+ TypeInformation inputType =
+ inferrer.types.addPhiInput(local, phiType, type);
tryBlock.locals.parent[local] = inputType;
}
// Update the current handler unconditionally with the new
@@ -356,21 +343,23 @@
}
}
- void narrow(Local local, DartType type, ir.Node node,
+ void narrow(InferrerEngine inferrer, Local local, DartType type, ir.Node node,
{bool isSetIfNull: false}) {
- TypeInformation existing = use(local);
+ TypeInformation existing = use(inferrer, local);
TypeInformation newType =
- types.narrowType(existing, type, isNullable: false);
- update(local, newType, node, type, isSetIfNull: isSetIfNull);
+ inferrer.types.narrowType(existing, type, isNullable: false);
+ update(inferrer, local, newType, node, type, isSetIfNull: isSetIfNull);
}
void setCapturedAndBoxed(Local local, FieldEntity field) {
_capturedAndBoxed[local] = field;
}
- void mergeDiamondFlow(LocalsHandler thenBranch, LocalsHandler elseBranch) {
+ void mergeDiamondFlow(InferrerEngine inferrer, LocalsHandler thenBranch,
+ LocalsHandler elseBranch) {
if (fieldScope != null && elseBranch != null) {
- fieldScope.mergeDiamondFlow(thenBranch.fieldScope, elseBranch.fieldScope);
+ fieldScope.mergeDiamondFlow(
+ inferrer, thenBranch.fieldScope, elseBranch.fieldScope);
}
seenReturnOrThrow = thenBranch.seenReturnOrThrow &&
elseBranch != null &&
@@ -385,7 +374,7 @@
TypeInformation myType = locals[local];
if (myType == null) return; // Variable is only defined in [other].
if (type == myType) return;
- locals[local] = types.allocateDiamondPhi(myType, type);
+ locals[local] = inferrer.types.allocateDiamondPhi(myType, type);
});
}
@@ -414,7 +403,7 @@
if (thenType == elseType) {
locals[local] = thenType;
} else {
- locals[local] = types.allocateDiamondPhi(thenType, elseType);
+ locals[local] = inferrer.types.allocateDiamondPhi(thenType, elseType);
}
}
@@ -459,7 +448,7 @@
* where [:this:] is the [LocalsHandler] for the paths through the
* labeled statement that do not break out.
*/
- void mergeAfterBreaks(List<LocalsHandler> handlers,
+ void mergeAfterBreaks(InferrerEngine inferrer, List<LocalsHandler> handlers,
{bool keepOwnLocals: true}) {
ir.Node level = locals.block;
// Use a separate locals handler to perform the merge in, so that Phi
@@ -472,7 +461,7 @@
// Merge all other handlers.
for (LocalsHandler handler in handlers) {
allBranchesAbort = allBranchesAbort && handler.seenReturnOrThrow;
- merged.mergeHandler(handler, seenLocals);
+ merged.mergeHandler(inferrer, handler, seenLocals);
}
// If we want to keep own locals, we merge [seenLocals] from [this] into
// [merged] to update the Phi nodes with original values.
@@ -480,15 +469,15 @@
for (Local variable in seenLocals) {
TypeInformation originalType = locals[variable];
if (originalType != null) {
- merged.locals[variable] = types.addPhiInput(
- variable, merged.locals[variable], originalType);
+ merged.locals[variable] = inferrer.types
+ .addPhiInput(variable, merged.locals[variable], originalType);
}
}
}
// Clean up Phi nodes with single input and store back result into
// actual locals handler.
merged.locals.forEachOwnLocal((Local variable, TypeInformation type) {
- locals[variable] = types.simplifyPhi(level, variable, type);
+ locals[variable] = inferrer.types.simplifyPhi(level, variable, type);
});
seenReturnOrThrow =
allBranchesAbort && (!keepOwnLocals || seenReturnOrThrow);
@@ -500,7 +489,8 @@
* unless the local is already present in the set [seen]. This effectively
* overwrites the current type knowledge in this handler.
*/
- bool mergeHandler(LocalsHandler other, [Set<Local> seen]) {
+ bool mergeHandler(InferrerEngine inferrer, LocalsHandler other,
+ [Set<Local> seen]) {
if (other.seenReturnOrThrow) return false;
bool changed = false;
other.locals.forEachLocalUntilNode(locals.block, (local, otherType) {
@@ -508,11 +498,11 @@
if (myType == null) return;
TypeInformation newType;
if (seen != null && !seen.contains(local)) {
- newType = types.allocatePhi(locals.block, local, otherType,
- isTry: locals.isTry);
+ newType = inferrer.types
+ .allocatePhi(locals.block, local, otherType, isTry: locals.isTry);
seen.add(local);
} else {
- newType = types.addPhiInput(local, myType, otherType);
+ newType = inferrer.types.addPhiInput(local, myType, otherType);
}
if (newType != myType) {
changed = true;
@@ -526,28 +516,29 @@
* Merge all [LocalsHandler] in [handlers] into this handler.
* Returns whether a local in this handler has changed.
*/
- bool mergeAll(List<LocalsHandler> handlers) {
+ bool mergeAll(InferrerEngine inferrer, List<LocalsHandler> handlers) {
bool changed = false;
assert(!seenReturnOrThrow);
handlers.forEach((other) {
- changed = mergeHandler(other) || changed;
+ changed = mergeHandler(inferrer, other) || changed;
});
return changed;
}
- void startLoop(ir.Node loop) {
+ void startLoop(InferrerEngine inferrer, ir.Node loop) {
locals.forEachLocal((Local variable, TypeInformation type) {
TypeInformation newType =
- types.allocateLoopPhi(loop, variable, type, isTry: false);
+ inferrer.types.allocateLoopPhi(loop, variable, type, isTry: false);
if (newType != type) {
locals[variable] = newType;
}
});
}
- void endLoop(ir.Node loop) {
+ void endLoop(InferrerEngine inferrer, ir.Node loop) {
locals.forEachLocal((Local variable, TypeInformation type) {
- TypeInformation newType = types.simplifyPhi(loop, variable, type);
+ TypeInformation newType =
+ inferrer.types.simplifyPhi(loop, variable, type);
if (newType != type) {
locals[variable] = newType;
}