Decouple HNode from TypeMask
Change-Id: Ie13d928d51ad7e080ad13402bed3c974da66a2c4
Reviewed-on: https://dart-review.googlesource.com/54020
Reviewed-by: Sigmund Cherem <sigmund@google.com>
Commit-Queue: Johnni Winther <johnniwinther@google.com>
diff --git a/pkg/compiler/lib/src/native/ssa.dart b/pkg/compiler/lib/src/native/ssa.dart
index 5fc3b5d..240df64 100644
--- a/pkg/compiler/lib/src/native/ssa.dart
+++ b/pkg/compiler/lib/src/native/ssa.dart
@@ -101,7 +101,7 @@
effects: new SideEffects()));
// TODO(johnniwinther): Provide source information.
builder
- .close(new HReturn(builder.pop(), null))
+ .close(new HReturn(builder.abstractValueDomain, builder.pop(), null))
.addSuccessor(builder.graph.exit);
} else {
if (parameters.parameterCount != 0) {
diff --git a/pkg/compiler/lib/src/ssa/builder.dart b/pkg/compiler/lib/src/ssa/builder.dart
index 9224019..a18d29f 100644
--- a/pkg/compiler/lib/src/ssa/builder.dart
+++ b/pkg/compiler/lib/src/ssa/builder.dart
@@ -727,8 +727,8 @@
push(invokeJsInteropFunction(functionElement, parameters.values.toList(),
sourceInformationBuilder.buildGeneric(function)));
var value = pop();
- closeAndGotoExit(new HReturn(
- value, sourceInformationBuilder.buildReturn(functionElement.node)));
+ closeAndGotoExit(new HReturn(abstractValueDomain, value,
+ sourceInformationBuilder.buildReturn(functionElement.node)));
return closeFunction();
}
assert(!function.modifiers.isExternal, failedAt(functionElement));
@@ -747,6 +747,7 @@
},
visitThen: () {
closeAndGotoExit(new HReturn(
+ abstractValueDomain,
graph.addConstantBool(false, closedWorld),
sourceInformationBuilder
.buildImplicitReturn(functionElement)));
@@ -796,7 +797,7 @@
graph.entry.addBefore(graph.entry.last, parameter);
HInstruction value = typeBuilder.potentiallyCheckOrTrustTypeOfParameter(
parameter, field.type);
- add(new HFieldSet(field, thisInstruction, value));
+ add(new HFieldSet(abstractValueDomain, field, thisInstruction, value));
return closeFunction();
}
@@ -827,8 +828,8 @@
}
}
- closeAndGotoExit(new HReturn(
- value, sourceInformationBuilder.buildReturn(sourceInfoNode)));
+ closeAndGotoExit(new HReturn(abstractValueDomain, value,
+ sourceInformationBuilder.buildReturn(sourceInfoNode)));
return closeFunction();
}
@@ -1358,7 +1359,8 @@
add(new HFieldGet(null, newObject, commonMasks.dynamicType,
isAssignable: false));
for (int i = 0; i < fields.length; i++) {
- add(new HFieldSet(fields[i], newObject, constructorArguments[i]));
+ add(new HFieldSet(abstractValueDomain, fields[i], newObject,
+ constructorArguments[i]));
}
}
removeInlinedInstantiation(type);
@@ -1431,7 +1433,7 @@
}
}
if (inliningStack.isEmpty) {
- closeAndGotoExit(new HReturn(newObject,
+ closeAndGotoExit(new HReturn(abstractValueDomain, newObject,
sourceInformationBuilder.buildImplicitReturn(functionElement)));
return closeFunction();
} else {
@@ -1466,7 +1468,7 @@
parameters,
sourceInformationBuilder.buildDeclaration(element),
isGenerativeConstructorBody: element.isGenerativeConstructorBody);
- close(new HGoto()).addSuccessor(block);
+ close(new HGoto(abstractValueDomain)).addSuccessor(block);
open(block);
@@ -1598,8 +1600,8 @@
HGraph closeFunction() {
// TODO(kasperl): Make this goto an implicit return.
- if (!isAborted()) closeAndGotoExit(new HGoto());
- graph.finalize();
+ if (!isAborted()) closeAndGotoExit(new HGoto(abstractValueDomain));
+ graph.finalize(abstractValueDomain);
return graph;
}
@@ -1715,8 +1717,8 @@
if (throwExpression != null && inliningStack.isEmpty) {
visitThrowExpression(throwExpression.expression);
handleInTryStatement();
- closeAndGotoExit(
- new HThrow(pop(), sourceInformationBuilder.buildThrow(node)));
+ closeAndGotoExit(new HThrow(abstractValueDomain, pop(),
+ sourceInformationBuilder.buildThrow(node)));
} else {
visit(node.expression);
pop();
@@ -1813,7 +1815,7 @@
HBasicBlock bodyExitBlock;
bool isAbortingBody = false;
if (current != null) {
- bodyExitBlock = close(new HGoto());
+ bodyExitBlock = close(new HGoto(abstractValueDomain));
} else {
isAbortingBody = true;
bodyExitBlock = lastOpenedBlock;
@@ -1858,13 +1860,13 @@
visit(node.condition);
assert(!isAborted());
HInstruction conditionInstruction = popBoolified();
- HBasicBlock conditionEndBlock = close(
- new HLoopBranch(conditionInstruction, HLoopBranch.DO_WHILE_LOOP));
+ HBasicBlock conditionEndBlock = close(new HLoopBranch(abstractValueDomain,
+ conditionInstruction, HLoopBranch.DO_WHILE_LOOP));
HBasicBlock avoidCriticalEdge = addNewBlock();
conditionEndBlock.addSuccessor(avoidCriticalEdge);
open(avoidCriticalEdge);
- close(new HGoto());
+ close(new HGoto(abstractValueDomain));
avoidCriticalEdge.addSuccessor(loopEntryBlock); // The back-edge.
conditionExpression =
@@ -1873,7 +1875,7 @@
// Avoid a critical edge from the condition to the loop-exit body.
HBasicBlock conditionExitBlock = addNewBlock();
open(conditionExitBlock);
- close(new HGoto());
+ close(new HGoto(abstractValueDomain));
conditionEndBlock.addSuccessor(conditionExitBlock);
loopHandler.endLoop(
@@ -1913,7 +1915,8 @@
loopEntryBlock.setBlockFlow(info, current);
jumpHandler.forEachBreak((HBreak breakInstruction, _) {
HBasicBlock block = breakInstruction.block;
- block.addAtExit(new HBreak.toLabel(label, sourceInformation));
+ block.addAtExit(new HBreak.toLabel(
+ abstractValueDomain, label, sourceInformation));
block.remove(breakInstruction);
});
}
@@ -2431,7 +2434,8 @@
FieldElement field = element;
value = typeBuilder.potentiallyCheckOrTrustTypeOfAssignment(
value, field.type);
- addWithPosition(new HStaticStore(field, value), location);
+ addWithPosition(
+ new HStaticStore(abstractValueDomain, field, value), location);
}
stack.add(value);
} else if (Elements.isError(element)) {
@@ -5219,8 +5223,8 @@
reporter.internalError(node, 'rethrowableException should not be null.');
}
handleInTryStatement();
- closeAndGotoExit(new HThrow(
- exception, sourceInformationBuilder.buildThrow(node),
+ closeAndGotoExit(new HThrow(abstractValueDomain, exception,
+ sourceInformationBuilder.buildThrow(node),
isRethrow: true));
}
@@ -5361,8 +5365,8 @@
visitThrowExpression(node.expression);
if (isReachable) {
handleInTryStatement();
- push(new HThrowExpression(
- pop(), sourceInformationBuilder.buildThrow(node)));
+ push(new HThrowExpression(abstractValueDomain, pop(),
+ sourceInformationBuilder.buildThrow(node)));
isReachable = false;
}
}
@@ -5370,8 +5374,8 @@
visitYield(ast.Yield node) {
visit(node.expression);
HInstruction yielded = pop();
- add(new HYield(
- yielded, node.hasStar, sourceInformationBuilder.buildYield(node)));
+ add(new HYield(abstractValueDomain, yielded, node.hasStar,
+ sourceInformationBuilder.buildYield(node)));
}
visitAwait(ast.Await node) {
@@ -6218,7 +6222,8 @@
return;
}
- HSwitch switchInstruction = new HSwitch(<HInstruction>[expression]);
+ HSwitch switchInstruction =
+ new HSwitch(abstractValueDomain, <HInstruction>[expression]);
HBasicBlock expressionEnd = close(switchInstruction);
LocalsHandler savedLocals = localsHandler;
@@ -6249,7 +6254,8 @@
if (caseIterator.hasNext && isReachable) {
pushInvokeStatic(switchCase, commonElements.fallThroughError, []);
HInstruction error = pop();
- closeAndGotoExit(new HThrow(error, error.sourceInformation));
+ closeAndGotoExit(
+ new HThrow(abstractValueDomain, error, error.sourceInformation));
} else if (!isDefaultCase(switchCase)) {
// If there is no default, we will add one later to avoid
// the critical edge. So we generate a break statement to make
@@ -6278,7 +6284,7 @@
assert(false, failedAt(errorNode, 'Continue cannot target a switch.'));
});
if (!isAborted()) {
- current.close(new HGoto());
+ current.close(new HGoto(abstractValueDomain));
lastOpenedBlock.addSuccessor(joinBlock);
caseHandlers.add(localsHandler);
}
@@ -6288,7 +6294,7 @@
HBasicBlock defaultCase = addNewBlock();
expressionEnd.addSuccessor(defaultCase);
open(defaultCase);
- close(new HGoto());
+ close(new HGoto(abstractValueDomain));
defaultCase.addSuccessor(joinBlock);
caseHandlers.add(savedLocals);
statements.add(new HSubGraphBlockInformation(
@@ -6341,7 +6347,7 @@
// variables were used in a non-dominated block.
LocalsHandler savedLocals = new LocalsHandler.from(localsHandler);
HBasicBlock enterBlock = openNewBlock();
- HTry tryInstruction = new HTry();
+ HTry tryInstruction = new HTry(abstractValueDomain);
close(tryInstruction);
bool oldInTryStatement = inTryStatement;
inTryStatement = true;
@@ -6357,7 +6363,7 @@
// We use a [HExitTry] instead of a [HGoto] for the try block
// because it will have two successors: the join block, and
// the finally block.
- if (!isAborted()) endTryBlock = close(new HExitTry());
+ if (!isAborted()) endTryBlock = close(new HExitTry(abstractValueDomain));
SubGraph bodyGraph = new SubGraph(startTryBlock, lastOpenedBlock);
SubGraph finallyGraph = null;
@@ -6366,7 +6372,7 @@
startFinallyBlock = graph.addNewBlock();
open(startFinallyBlock);
buildFinally();
- if (!isAborted()) endFinallyBlock = close(new HGoto());
+ if (!isAborted()) endFinallyBlock = close(new HGoto(abstractValueDomain));
tryInstruction.finallyBlock = startFinallyBlock;
finallyGraph = new SubGraph(startFinallyBlock, lastOpenedBlock);
@@ -6431,7 +6437,7 @@
// in a non-dominated block.
LocalsHandler savedLocals = new LocalsHandler.from(localsHandler);
HBasicBlock enterBlock = openNewBlock();
- HTry tryInstruction = new HTry();
+ HTry tryInstruction = new HTry(abstractValueDomain);
close(tryInstruction);
bool oldInTryStatement = inTryStatement;
inTryStatement = true;
@@ -6449,7 +6455,7 @@
// We use a [HExitTry] instead of a [HGoto] for the try block
// because it will have multiple successors: the join block, and
// the catch or finally block.
- if (!isAborted()) endTryBlock = close(new HExitTry());
+ if (!isAborted()) endTryBlock = close(new HExitTry(abstractValueDomain));
SubGraph bodyGraph = new SubGraph(startTryBlock, lastOpenedBlock);
SubGraph catchGraph = null;
HLocalValue exception = null;
@@ -6531,7 +6537,8 @@
void visitElse() {
if (link.isEmpty) {
- closeAndGotoExit(new HThrow(exception, exception.sourceInformation,
+ closeAndGotoExit(new HThrow(
+ abstractValueDomain, exception, exception.sourceInformation,
isRethrow: true));
} else {
ast.CatchBlock newBlock = link.head;
@@ -6555,7 +6562,7 @@
visitThen: visitThen,
visitElse: visitElse,
sourceInformation: sourceInformationBuilder.buildCatch(firstBlock));
- if (!isAborted()) endCatchBlock = close(new HGoto());
+ if (!isAborted()) endCatchBlock = close(new HGoto(abstractValueDomain));
rethrowableException = oldRethrowableException;
tryInstruction.catchBlock = startCatchBlock;
@@ -6568,7 +6575,7 @@
startFinallyBlock = graph.addNewBlock();
open(startFinallyBlock);
visit(node.finallyBlock);
- if (!isAborted()) endFinallyBlock = close(new HGoto());
+ if (!isAborted()) endFinallyBlock = close(new HGoto(abstractValueDomain));
tryInstruction.finallyBlock = startFinallyBlock;
finallyGraph = new SubGraph(startFinallyBlock, lastOpenedBlock);
}
@@ -6693,8 +6700,8 @@
void emitReturn(HInstruction value, ast.Node node) {
if (inliningStack.isEmpty) {
- closeAndGotoExit(
- new HReturn(value, sourceInformationBuilder.buildReturn(node)));
+ closeAndGotoExit(new HReturn(abstractValueDomain, value,
+ sourceInformationBuilder.buildReturn(node)));
} else {
localsHandler.updateLocal(returnLocal, value);
}
diff --git a/pkg/compiler/lib/src/ssa/builder_kernel.dart b/pkg/compiler/lib/src/ssa/builder_kernel.dart
index 859e6e7..7f0236d 100644
--- a/pkg/compiler/lib/src/ssa/builder_kernel.dart
+++ b/pkg/compiler/lib/src/ssa/builder_kernel.dart
@@ -323,7 +323,7 @@
graph.entry.addBefore(graph.entry.last, parameter);
HInstruction value = typeBuilder.potentiallyCheckOrTrustTypeOfParameter(
parameter, _getDartTypeIfValid(node.type));
- add(new HFieldSet(field, thisInstruction, value));
+ add(new HFieldSet(abstractValueDomain, field, thisInstruction, value));
} else {
if (node.initializer != null) {
node.initializer.accept(this);
@@ -336,8 +336,8 @@
stack.add(graph.addConstantNull(closedWorld));
}
HInstruction value = pop();
- closeAndGotoExit(
- new HReturn(value, _sourceInformationBuilder.buildReturn(node)));
+ closeAndGotoExit(new HReturn(abstractValueDomain, value,
+ _sourceInformationBuilder.buildReturn(node)));
}
closeFunction();
}
@@ -496,7 +496,8 @@
add(new HFieldGet(null, newObject, commonMasks.dynamicType,
isAssignable: false));
for (int i = 0; i < fields.length; i++) {
- add(new HFieldSet(fields[i], newObject, constructorArguments[i]));
+ add(new HFieldSet(abstractValueDomain, fields[i], newObject,
+ constructorArguments[i]));
}
} else {
// Create the runtime type information, if needed.
@@ -604,7 +605,8 @@
}
if (_inliningStack.isEmpty) {
- closeAndGotoExit(new HReturn(newObject, sourceInformation));
+ closeAndGotoExit(
+ new HReturn(abstractValueDomain, newObject, sourceInformation));
closeFunction();
} else {
localsHandler.updateLocal(_returnLocal, newObject,
@@ -920,8 +922,8 @@
typeArguments,
commonMasks.functionType));
HInstruction value = pop();
- close(new HReturn(
- value, _sourceInformationBuilder.buildReturn(originalClosureNode)))
+ close(new HReturn(abstractValueDomain, value,
+ _sourceInformationBuilder.buildReturn(originalClosureNode)))
.addSuccessor(graph.exit);
closeFunction();
@@ -954,6 +956,7 @@
},
visitThen: () {
closeAndGotoExit(new HReturn(
+ abstractValueDomain,
graph.addConstantBool(false, closedWorld),
_sourceInformationBuilder.buildReturn(functionNode)));
},
@@ -1083,8 +1086,8 @@
if (targetElement.isSetter) {
value = graph.addConstantNull(closedWorld);
}
- close(new HReturn(
- value, _sourceInformationBuilder.buildReturn(functionNode)))
+ close(new HReturn(abstractValueDomain, value,
+ _sourceInformationBuilder.buildReturn(functionNode)))
.addSuccessor(graph.exit);
}
// TODO(sra): Handle JS-interop methods.
@@ -1129,7 +1132,7 @@
parameterMap,
_sourceInformationBuilder.buildDeclaration(targetElement),
isGenerativeConstructorBody: targetElement is ConstructorBodyEntity);
- close(new HGoto()).addSuccessor(block);
+ close(new HGoto(abstractValueDomain)).addSuccessor(block);
open(block);
@@ -1144,8 +1147,8 @@
}
void closeFunction() {
- if (!isAborted()) closeAndGotoExit(new HGoto());
- graph.finalize();
+ if (!isAborted()) closeAndGotoExit(new HGoto(abstractValueDomain));
+ graph.finalize(abstractValueDomain);
}
@override
@@ -1246,7 +1249,8 @@
handleInTryStatement();
SourceInformation sourceInformation =
_sourceInformationBuilder.buildThrow(node.expression);
- closeAndGotoExit(new HThrow(pop(), sourceInformation));
+ closeAndGotoExit(
+ new HThrow(abstractValueDomain, pop(), sourceInformation));
} else {
expression.accept(this);
pop();
@@ -1713,7 +1717,7 @@
HBasicBlock bodyExitBlock;
bool isAbortingBody = false;
if (current != null) {
- bodyExitBlock = close(new HGoto());
+ bodyExitBlock = close(new HGoto(abstractValueDomain));
} else {
isAbortingBody = true;
bodyExitBlock = lastOpenedBlock;
@@ -1758,13 +1762,13 @@
node.condition.accept(this);
assert(!isAborted());
HInstruction conditionInstruction = popBoolified();
- HBasicBlock conditionEndBlock = close(
- new HLoopBranch(conditionInstruction, HLoopBranch.DO_WHILE_LOOP));
+ HBasicBlock conditionEndBlock = close(new HLoopBranch(abstractValueDomain,
+ conditionInstruction, HLoopBranch.DO_WHILE_LOOP));
HBasicBlock avoidCriticalEdge = addNewBlock();
conditionEndBlock.addSuccessor(avoidCriticalEdge);
open(avoidCriticalEdge);
- close(new HGoto());
+ close(new HGoto(abstractValueDomain));
avoidCriticalEdge.addSuccessor(loopEntryBlock); // The back-edge.
conditionExpression =
@@ -1773,7 +1777,7 @@
// Avoid a critical edge from the condition to the loop-exit body.
HBasicBlock conditionExitBlock = addNewBlock();
open(conditionExitBlock);
- close(new HGoto());
+ close(new HGoto(abstractValueDomain));
conditionEndBlock.addSuccessor(conditionExitBlock);
loopHandler.endLoop(
@@ -1813,7 +1817,8 @@
loopEntryBlock.setBlockFlow(info, current);
jumpHandler.forEachBreak((HBreak breakInstruction, _) {
HBasicBlock block = breakInstruction.block;
- block.addAtExit(new HBreak.toLabel(label, sourceInformation));
+ block.addAtExit(new HBreak.toLabel(
+ abstractValueDomain, label, sourceInformation));
block.remove(breakInstruction);
});
}
@@ -2312,7 +2317,8 @@
return;
}
- HSwitch switchInstruction = new HSwitch(<HInstruction>[expression]);
+ HSwitch switchInstruction =
+ new HSwitch(abstractValueDomain, <HInstruction>[expression]);
HBasicBlock expressionEnd = close(switchInstruction);
LocalsHandler savedLocals = localsHandler;
@@ -2372,7 +2378,7 @@
'Continue cannot target a switch.'));
});
if (!isAborted()) {
- current.close(new HGoto());
+ current.close(new HGoto(abstractValueDomain));
lastOpenedBlock.addSuccessor(joinBlock);
caseHandlers.add(localsHandler);
}
@@ -2382,7 +2388,7 @@
HBasicBlock defaultCase = addNewBlock();
expressionEnd.addSuccessor(defaultCase);
open(defaultCase);
- close(new HGoto());
+ close(new HGoto(abstractValueDomain));
defaultCase.addSuccessor(joinBlock);
caseHandlers.add(savedLocals);
statements.add(new HSubGraphBlockInformation(
@@ -2725,6 +2731,7 @@
pop();
} else {
add(new HStaticStore(
+ abstractValueDomain,
_elementMap.getMember(staticTarget),
typeBuilder.potentiallyCheckOrTrustTypeOfAssignment(
value, _getDartTypeIfValid(staticTarget.setterType))));
@@ -4534,7 +4541,7 @@
SourceInformation sourceInformation =
_sourceInformationBuilder.buildThrow(node);
handleInTryStatement();
- push(new HThrowExpression(pop(), sourceInformation));
+ push(new HThrowExpression(abstractValueDomain, pop(), sourceInformation));
isReachable = false;
}
}
@@ -4551,8 +4558,8 @@
void visitYieldStatement(ir.YieldStatement node) {
node.expression.accept(this);
- add(new HYield(
- pop(), node.isYieldStar, _sourceInformationBuilder.buildYield(node)));
+ add(new HYield(abstractValueDomain, pop(), node.isYieldStar,
+ _sourceInformationBuilder.buildYield(node)));
}
@override
@@ -4575,7 +4582,9 @@
handleInTryStatement();
SourceInformation sourceInformation =
_sourceInformationBuilder.buildThrow(node);
- closeAndGotoExit(new HThrow(exception, sourceInformation, isRethrow: true));
+ closeAndGotoExit(new HThrow(
+ abstractValueDomain, exception, sourceInformation,
+ isRethrow: true));
// ir.Rethrow is an expression so we need to push a value - a constant with
// no type.
stack.add(graph.addConstantUnreachable(closedWorld));
@@ -5100,7 +5109,8 @@
void _emitReturn(HInstruction value, SourceInformation sourceInformation) {
if (_inliningStack.isEmpty) {
- closeAndGotoExit(new HReturn(value, sourceInformation));
+ closeAndGotoExit(
+ new HReturn(abstractValueDomain, value, sourceInformation));
} else {
localsHandler.updateLocal(_returnLocal, value);
}
@@ -5453,7 +5463,7 @@
LocalsHandler originalSavedLocals;
TryCatchFinallyBuilder(this.kernelBuilder, this.trySourceInformation) {
- tryInstruction = new HTry();
+ tryInstruction = new HTry(kernelBuilder.abstractValueDomain);
originalSavedLocals = new LocalsHandler.from(kernelBuilder.localsHandler);
enterBlock = kernelBuilder.openNewBlock();
kernelBuilder.close(tryInstruction);
@@ -5524,7 +5534,8 @@
kernelBuilder.open(startFinallyBlock);
buildFinalizer();
if (!kernelBuilder.isAborted()) {
- endFinallyBlock = kernelBuilder.close(new HGoto());
+ endFinallyBlock =
+ kernelBuilder.close(new HGoto(kernelBuilder.abstractValueDomain));
}
tryInstruction.finallyBlock = startFinallyBlock;
finallyGraph =
@@ -5536,7 +5547,8 @@
// because it will have multiple successors: the join block, and
// the catch or finally block.
if (!kernelBuilder.isAborted()) {
- endTryBlock = kernelBuilder.close(new HExitTry());
+ endTryBlock =
+ kernelBuilder.close(new HExitTry(kernelBuilder.abstractValueDomain));
}
bodyGraph = new SubGraph(startTryBlock, kernelBuilder.lastOpenedBlock);
}
@@ -5601,7 +5613,9 @@
void visitElse() {
if (catchesIndex >= tryCatch.catches.length) {
kernelBuilder.closeAndGotoExit(new HThrow(
- exception, exception.sourceInformation,
+ kernelBuilder.abstractValueDomain,
+ exception,
+ exception.sourceInformation,
isRethrow: true));
} else {
ir.Catch nextCatch = tryCatch.catches[catchesIndex];
@@ -5626,7 +5640,8 @@
sourceInformation:
kernelBuilder._sourceInformationBuilder.buildCatch(firstBlock));
if (!kernelBuilder.isAborted()) {
- endCatchBlock = kernelBuilder.close(new HGoto());
+ endCatchBlock =
+ kernelBuilder.close(new HGoto(kernelBuilder.abstractValueDomain));
}
kernelBuilder.rethrowableException = oldRethrowableException;
diff --git a/pkg/compiler/lib/src/ssa/graph_builder.dart b/pkg/compiler/lib/src/ssa/graph_builder.dart
index e13dc3f..4215366 100644
--- a/pkg/compiler/lib/src/ssa/graph_builder.dart
+++ b/pkg/compiler/lib/src/ssa/graph_builder.dart
@@ -202,7 +202,7 @@
}
void goto(HBasicBlock from, HBasicBlock to) {
- from.close(new HGoto());
+ from.close(new HGoto(abstractValueDomain));
from.addSuccessor(to);
}
@@ -275,7 +275,7 @@
/// specify special successors if we are already in a try/catch/finally block.
void handleInTryStatement() {
if (!inTryStatement) return;
- HBasicBlock block = close(new HExitTry());
+ HBasicBlock block = close(new HExitTry(abstractValueDomain));
HBasicBlock newBlock = graph.addNewBlock();
block.addSuccessor(newBlock);
open(newBlock);
diff --git a/pkg/compiler/lib/src/ssa/invoke_dynamic_specializers.dart b/pkg/compiler/lib/src/ssa/invoke_dynamic_specializers.dart
index b37002d..0ca17d5 100644
--- a/pkg/compiler/lib/src/ssa/invoke_dynamic_specializers.dart
+++ b/pkg/compiler/lib/src/ssa/invoke_dynamic_specializers.dart
@@ -139,7 +139,8 @@
return null;
}
}
- return new HIndexAssign(receiver, index, value, instruction.selector);
+ return new HIndexAssign(closedWorld.abstractValueDomain, receiver, index,
+ value, instruction.selector);
}
/// Returns [true] if [value] meets the requirements for being stored into
diff --git a/pkg/compiler/lib/src/ssa/jump_handler.dart b/pkg/compiler/lib/src/ssa/jump_handler.dart
index d8dc2ee..3687961 100644
--- a/pkg/compiler/lib/src/ssa/jump_handler.dart
+++ b/pkg/compiler/lib/src/ssa/jump_handler.dart
@@ -88,9 +88,11 @@
[LabelDefinition label]) {
HInstruction breakInstruction;
if (label == null) {
- breakInstruction = new HBreak(target, sourceInformation);
+ breakInstruction =
+ new HBreak(builder.abstractValueDomain, target, sourceInformation);
} else {
- breakInstruction = new HBreak.toLabel(label, sourceInformation);
+ breakInstruction = new HBreak.toLabel(
+ builder.abstractValueDomain, label, sourceInformation);
}
LocalsHandler locals = new LocalsHandler.from(builder.localsHandler);
builder.close(breakInstruction);
@@ -101,9 +103,11 @@
[LabelDefinition label]) {
HInstruction continueInstruction;
if (label == null) {
- continueInstruction = new HContinue(target, sourceInformation);
+ continueInstruction =
+ new HContinue(builder.abstractValueDomain, target, sourceInformation);
} else {
- continueInstruction = new HContinue.toLabel(label, sourceInformation);
+ continueInstruction = new HContinue.toLabel(
+ builder.abstractValueDomain, label, sourceInformation);
// Switch case continue statements must be handled by the
// [SwitchCaseJumpHandler].
assert(!label.target.isSwitchCase);
@@ -171,8 +175,9 @@
// for a switch statement with continue statements. See
// [SsaFromAstMixin.buildComplexSwitchStatement] for detail.
- HInstruction breakInstruction =
- new HBreak(target, sourceInformation, breakSwitchContinueLoop: true);
+ HInstruction breakInstruction = new HBreak(
+ builder.abstractValueDomain, target, sourceInformation,
+ breakSwitchContinueLoop: true);
LocalsHandler locals = new LocalsHandler.from(builder.localsHandler);
builder.close(breakInstruction);
jumps.add(new _JumpHandlerEntry(breakInstruction, locals));
@@ -199,7 +204,7 @@
assert(label.target.labels.contains(label));
HInstruction continueInstruction =
- new HContinue(target, sourceInformation);
+ new HContinue(builder.abstractValueDomain, target, sourceInformation);
LocalsHandler locals = new LocalsHandler.from(builder.localsHandler);
builder.close(continueInstruction);
jumps.add(new _JumpHandlerEntry(continueInstruction, locals));
diff --git a/pkg/compiler/lib/src/ssa/locals_handler.dart b/pkg/compiler/lib/src/ssa/locals_handler.dart
index 4922a85..2f3973b 100644
--- a/pkg/compiler/lib/src/ssa/locals_handler.dart
+++ b/pkg/compiler/lib/src/ssa/locals_handler.dart
@@ -443,13 +443,15 @@
// Inside the closure the box is stored in a closure-field and cannot
// be accessed directly.
HInstruction box = readLocal(localBox);
- builder.add(new HFieldSet(redirect, box, value)
- ..sourceInformation = sourceInformation);
+ builder.add(
+ new HFieldSet(builder.abstractValueDomain, redirect, box, value)
+ ..sourceInformation = sourceInformation);
} else {
assert(_isUsedInTryOrGenerator(local));
HLocalValue localValue = getLocal(local);
- builder.add(new HLocalSet(local, localValue, value)
- ..sourceInformation = sourceInformation);
+ builder.add(
+ new HLocalSet(builder.abstractValueDomain, local, localValue, value)
+ ..sourceInformation = sourceInformation);
}
}
diff --git a/pkg/compiler/lib/src/ssa/loop_handler.dart b/pkg/compiler/lib/src/ssa/loop_handler.dart
index 4bace0e..89ea833 100644
--- a/pkg/compiler/lib/src/ssa/loop_handler.dart
+++ b/pkg/compiler/lib/src/ssa/loop_handler.dart
@@ -65,8 +65,8 @@
if (startBlock == null) startBlock = conditionBlock;
HInstruction conditionInstruction = condition();
- HBasicBlock conditionEndBlock =
- builder.close(new HLoopBranch(conditionInstruction));
+ HBasicBlock conditionEndBlock = builder.close(
+ new HLoopBranch(builder.abstractValueDomain, conditionInstruction));
SubExpression conditionExpression =
new SubExpression(conditionBlock, conditionEndBlock);
@@ -85,7 +85,8 @@
SubGraph bodyGraph = new SubGraph(beginBodyBlock, builder.lastOpenedBlock);
HBasicBlock bodyBlock = builder.current;
- if (builder.current != null) builder.close(new HGoto());
+ if (builder.current != null)
+ builder.close(new HGoto(builder.abstractValueDomain));
SubExpression updateGraph;
@@ -133,7 +134,8 @@
update();
- HBasicBlock updateEndBlock = builder.close(new HGoto());
+ HBasicBlock updateEndBlock =
+ builder.close(new HGoto(builder.abstractValueDomain));
// The back-edge completing the cycle.
updateEndBlock.addSuccessor(conditionBlock);
updateGraph = new SubExpression(updateBlock, updateEndBlock);
@@ -141,7 +143,7 @@
// Avoid a critical edge from the condition to the loop-exit body.
HBasicBlock conditionExitBlock = builder.addNewBlock();
builder.open(conditionExitBlock);
- builder.close(new HGoto());
+ builder.close(new HGoto(builder.abstractValueDomain));
conditionEndBlock.addSuccessor(conditionExitBlock);
endLoop(conditionBlock, conditionExitBlock, jumpHandler, savedLocals);
@@ -172,7 +174,7 @@
// label to the if.
HBasicBlock elseBlock = builder.addNewBlock();
builder.open(elseBlock);
- builder.close(new HGoto());
+ builder.close(new HGoto(builder.abstractValueDomain));
// Pass the elseBlock as the branchBlock, because that's the block we go
// to just before leaving the 'loop'.
endLoop(conditionBlock, elseBlock, jumpHandler, savedLocals);
@@ -184,7 +186,8 @@
// Remove the [HLoopBranch] instruction and replace it with
// [HIf].
HInstruction condition = conditionEndBlock.last.inputs[0];
- conditionEndBlock.addAtExit(new HIf(condition));
+ conditionEndBlock
+ .addAtExit(new HIf(builder.abstractValueDomain, condition));
conditionEndBlock.addSuccessor(elseBlock);
conditionEndBlock.remove(conditionEndBlock.last);
HIfBlockInformation info = new HIfBlockInformation(
@@ -210,7 +213,8 @@
jumpHandler.forEachBreak((HBreak breakInstruction, _) {
HBasicBlock block = breakInstruction.block;
- block.addAtExit(new HBreak.toLabel(label, sourceInformation));
+ block.addAtExit(new HBreak.toLabel(
+ builder.abstractValueDomain, label, sourceInformation));
block.remove(breakInstruction);
});
}
@@ -224,7 +228,8 @@
/// Also notifies the locals handler that we're entering a loop.
JumpHandler beginLoopHeader(T node, JumpTarget jumpTarget) {
assert(!builder.isAborted());
- HBasicBlock previousBlock = builder.close(new HGoto());
+ HBasicBlock previousBlock =
+ builder.close(new HGoto(builder.abstractValueDomain));
JumpHandler jumpHandler =
createJumpHandler(node, jumpTarget, isLoopJump: true);
diff --git a/pkg/compiler/lib/src/ssa/nodes.dart b/pkg/compiler/lib/src/ssa/nodes.dart
index 984a270..a42c238 100644
--- a/pkg/compiler/lib/src/ssa/nodes.dart
+++ b/pkg/compiler/lib/src/ssa/nodes.dart
@@ -15,9 +15,7 @@
import '../js/js.dart' as js;
import '../js_backend/js_backend.dart';
import '../native/native.dart' as native;
-import '../types/constants.dart' show computeTypeMask;
import '../types/abstract_value_domain.dart';
-import '../types/types.dart';
import '../universe/selector.dart' show Selector;
import '../universe/side_effects.dart' show SideEffects;
import '../util/util.dart';
@@ -261,7 +259,8 @@
// We use `null` as the value for invalid constant expressions.
constant = const NullConstantValue();
}
- TypeMask type = computeTypeMask(closedWorld, constant);
+ AbstractValue type = closedWorld.abstractValueDomain
+ .computeAbstractValueForConstant(constant);
result = new HConstant.internal(constant, type)
..sourceInformation = sourceInformation;
entry.addAtExit(result);
@@ -318,15 +317,15 @@
// A constant with an empty type used as the HInstruction of an expression
// in an unreachable context.
return addConstant(
- new SyntheticConstantValue(
- SyntheticConstantKind.EMPTY_VALUE, const TypeMask.nonNullEmpty()),
+ new SyntheticConstantValue(SyntheticConstantKind.EMPTY_VALUE,
+ closedWorld.abstractValueDomain.emptyType),
closedWorld);
}
- void finalize() {
+ void finalize(AbstractValueDomain domain) {
addBlock(exit);
exit.open();
- exit.close(new HExit());
+ exit.close(new HExit(domain));
assignDominators();
}
@@ -1271,8 +1270,8 @@
throw 'creating compound check to $type (this = ${this})';
} else {
InterfaceType interfaceType = type;
- TypeMask subtype =
- new TypeMask.subtype(interfaceType.element, closedWorld);
+ AbstractValue subtype = closedWorld.abstractValueDomain
+ .createNullableSubtype(interfaceType.element);
return new HTypeConversion(type, kind, subtype, this, sourceInformation);
}
}
@@ -1449,12 +1448,12 @@
* codegen decisions just prior to generating JavaScript.
*/
abstract class HLateInstruction extends HInstruction {
- HLateInstruction(List<HInstruction> inputs, TypeMask type)
+ HLateInstruction(List<HInstruction> inputs, AbstractValue type)
: super(inputs, type);
}
class HBoolify extends HInstruction {
- HBoolify(HInstruction value, TypeMask type)
+ HBoolify(HInstruction value, AbstractValue type)
: super(<HInstruction>[value], type) {
setUseGvn();
sourceInformation = value.sourceInformation;
@@ -1514,14 +1513,19 @@
}
abstract class HConditionalBranch extends HControlFlow {
- HConditionalBranch(inputs) : super(inputs);
+ HConditionalBranch(AbstractValueDomain domain, List<HInstruction> inputs)
+ : super(domain, inputs);
HInstruction get condition => inputs[0];
HBasicBlock get trueBranch => block.successors[0];
HBasicBlock get falseBranch => block.successors[1];
}
abstract class HControlFlow extends HInstruction {
- HControlFlow(inputs) : super(inputs, const TypeMask.nonNullEmpty());
+ HControlFlow(AbstractValueDomain domain, List<HInstruction> inputs)
+ // TODO(johnniwinther): May only expression-like [HInstruction]s should
+ // have an `instructionType`, or statement-like [HInstruction]s should
+ // have a throwing getter.
+ : super(inputs, domain.emptyType);
bool isControlFlow() => true;
bool isJsStatement() => true;
}
@@ -1543,7 +1547,7 @@
/// the closure class.
FunctionEntity callMethod;
- HCreate(this.element, List<HInstruction> inputs, TypeMask type,
+ HCreate(this.element, List<HInstruction> inputs, AbstractValue type,
SourceInformation sourceInformation,
{this.instantiatedTypes, this.hasRtiInput: false, this.callMethod})
: super(inputs, type) {
@@ -1564,7 +1568,7 @@
// Allocates a box to hold mutated captured variables.
class HCreateBox extends HInstruction {
- HCreateBox(TypeMask type) : super(<HInstruction>[], type);
+ HCreateBox(AbstractValue type) : super(<HInstruction>[], type);
bool isAllocation(AbstractValueDomain domain) => true;
@@ -1595,11 +1599,11 @@
abstract class HInvokeDynamic extends HInvoke {
final InvokeDynamicSpecializer specializer;
Selector selector;
- TypeMask mask;
+ AbstractValue mask;
MemberEntity element;
HInvokeDynamic(Selector selector, this.mask, this.element,
- List<HInstruction> inputs, bool isIntercepted, TypeMask type)
+ List<HInstruction> inputs, bool isIntercepted, AbstractValue type)
: this.selector = selector,
specializer = isIntercepted
? InvokeDynamicSpecializer.lookupSpecializer(selector)
@@ -1638,8 +1642,8 @@
class HInvokeClosure extends HInvokeDynamic {
final List<DartType> typeArguments;
- HInvokeClosure(Selector selector, List<HInstruction> inputs, TypeMask type,
- this.typeArguments)
+ HInvokeClosure(Selector selector, List<HInstruction> inputs,
+ AbstractValue type, this.typeArguments)
: super(selector, null, null, inputs, false, type) {
assert(selector.isClosureCall);
assert(selector.callStructure.typeArgumentCount == typeArguments.length);
@@ -1653,9 +1657,9 @@
HInvokeDynamicMethod(
Selector selector,
- TypeMask mask,
+ AbstractValue mask,
List<HInstruction> inputs,
- TypeMask type,
+ AbstractValue type,
this.typeArguments,
SourceInformation sourceInformation,
{bool isIntercepted: false})
@@ -1669,8 +1673,13 @@
}
abstract class HInvokeDynamicField extends HInvokeDynamic {
- HInvokeDynamicField(Selector selector, TypeMask mask, MemberEntity element,
- List<HInstruction> inputs, bool isIntercepted, TypeMask type)
+ HInvokeDynamicField(
+ Selector selector,
+ AbstractValue mask,
+ MemberEntity element,
+ List<HInstruction> inputs,
+ bool isIntercepted,
+ AbstractValue type)
: super(selector, mask, element, inputs, isIntercepted, type);
String toString() => 'invoke dynamic field: selector=$selector, mask=$mask';
@@ -1679,11 +1688,11 @@
class HInvokeDynamicGetter extends HInvokeDynamicField {
HInvokeDynamicGetter(
Selector selector,
- TypeMask mask,
+ AbstractValue mask,
MemberEntity element,
List<HInstruction> inputs,
bool isIntercepted,
- TypeMask type,
+ AbstractValue type,
SourceInformation sourceInformation)
: super(selector, mask, element, inputs, isIntercepted, type) {
this.sourceInformation = sourceInformation;
@@ -1705,11 +1714,11 @@
class HInvokeDynamicSetter extends HInvokeDynamicField {
HInvokeDynamicSetter(
Selector selector,
- TypeMask mask,
+ AbstractValue mask,
MemberEntity element,
List<HInstruction> inputs,
bool isIntercepted,
- TypeMask type,
+ AbstractValue type,
SourceInformation sourceInformation)
: super(selector, mask, element, inputs, isIntercepted, type) {
this.sourceInformation = sourceInformation;
@@ -1739,7 +1748,7 @@
List<DartType> instantiatedTypes;
/** The first input must be the target. */
- HInvokeStatic(this.element, inputs, TypeMask type, this.typeArguments,
+ HInvokeStatic(this.element, inputs, AbstractValue type, this.typeArguments,
{this.targetCanThrow: true, bool isIntercepted: false})
: super(inputs, type) {
isInterceptedCall = isIntercepted;
@@ -1764,7 +1773,7 @@
this.selector,
List<HInstruction> inputs,
bool isIntercepted,
- TypeMask type,
+ AbstractValue type,
List<DartType> typeArguments,
SourceInformation sourceInformation,
{this.isSetter})
@@ -1802,7 +1811,7 @@
HInvokeConstructorBody(
ConstructorBodyEntity element,
List<HInstruction> inputs,
- TypeMask type,
+ AbstractValue type,
SourceInformation sourceInformation)
: super(element, inputs, type, const <DartType>[]) {
this.sourceInformation = sourceInformation;
@@ -1815,7 +1824,7 @@
abstract class HFieldAccess extends HInstruction {
final FieldEntity element;
- HFieldAccess(this.element, List<HInstruction> inputs, TypeMask type)
+ HFieldAccess(this.element, List<HInstruction> inputs, AbstractValue type)
: super(inputs, type);
HInstruction get receiver => inputs[0];
@@ -1824,7 +1833,7 @@
class HFieldGet extends HFieldAccess {
final bool isAssignable;
- HFieldGet(FieldEntity element, HInstruction receiver, TypeMask type,
+ HFieldGet(FieldEntity element, HInstruction receiver, AbstractValue type,
{bool isAssignable})
: this.isAssignable =
(isAssignable != null) ? isAssignable : element.isAssignable,
@@ -1865,9 +1874,9 @@
}
class HFieldSet extends HFieldAccess {
- HFieldSet(FieldEntity element, HInstruction receiver, HInstruction value)
- : super(element, <HInstruction>[receiver, value],
- const TypeMask.nonNullEmpty()) {
+ HFieldSet(AbstractValueDomain domain, FieldEntity element,
+ HInstruction receiver, HInstruction value)
+ : super(element, <HInstruction>[receiver, value], domain.emptyType) {
sideEffects.clearAllSideEffects();
sideEffects.clearAllDependencies();
sideEffects.setChangesInstanceProperty();
@@ -1887,7 +1896,8 @@
class HGetLength extends HInstruction {
final bool isAssignable;
- HGetLength(HInstruction receiver, TypeMask type, {bool this.isAssignable})
+ HGetLength(HInstruction receiver, AbstractValue type,
+ {bool this.isAssignable})
: super(<HInstruction>[receiver], type) {
assert(isAssignable != null);
sideEffects.clearAllSideEffects();
@@ -1926,7 +1936,7 @@
final int opKind;
HReadModifyWrite._(this.element, this.jsOp, this.opKind,
- List<HInstruction> inputs, TypeMask type)
+ List<HInstruction> inputs, AbstractValue type)
: super(inputs, type) {
sideEffects.clearAllSideEffects();
sideEffects.clearAllDependencies();
@@ -1935,16 +1945,16 @@
}
HReadModifyWrite.assignOp(FieldEntity element, String jsOp,
- HInstruction receiver, HInstruction operand, TypeMask type)
+ HInstruction receiver, HInstruction operand, AbstractValue type)
: this._(
element, jsOp, ASSIGN_OP, <HInstruction>[receiver, operand], type);
- HReadModifyWrite.preOp(
- FieldEntity element, String jsOp, HInstruction receiver, TypeMask type)
+ HReadModifyWrite.preOp(FieldEntity element, String jsOp,
+ HInstruction receiver, AbstractValue type)
: this._(element, jsOp, PRE_OP, <HInstruction>[receiver], type);
- HReadModifyWrite.postOp(
- FieldEntity element, String jsOp, HInstruction receiver, TypeMask type)
+ HReadModifyWrite.postOp(FieldEntity element, String jsOp,
+ HInstruction receiver, AbstractValue type)
: this._(element, jsOp, POST_OP, <HInstruction>[receiver], type);
HInstruction get receiver => inputs[0];
@@ -1968,7 +1978,7 @@
abstract class HLocalAccess extends HInstruction {
final Local variable;
- HLocalAccess(this.variable, List<HInstruction> inputs, TypeMask type)
+ HLocalAccess(this.variable, List<HInstruction> inputs, AbstractValue type)
: super(inputs, type);
HInstruction get receiver => inputs[0];
@@ -1977,7 +1987,7 @@
class HLocalGet extends HLocalAccess {
// No need to use GVN for a [HLocalGet], it is just a local
// access.
- HLocalGet(Local variable, HLocalValue local, TypeMask type,
+ HLocalGet(Local variable, HLocalValue local, AbstractValue type,
SourceInformation sourceInformation)
: super(variable, <HInstruction>[local], type) {
this.sourceInformation = sourceInformation;
@@ -1989,9 +1999,9 @@
}
class HLocalSet extends HLocalAccess {
- HLocalSet(Local variable, HLocalValue local, HInstruction value)
- : super(variable, <HInstruction>[local, value],
- const TypeMask.nonNullEmpty());
+ HLocalSet(AbstractValueDomain domain, Local variable, HLocalValue local,
+ HInstruction value)
+ : super(variable, <HInstruction>[local, value], domain.emptyType);
accept(HVisitor visitor) => visitor.visitLocalSet(this);
@@ -2001,7 +2011,7 @@
}
abstract class HForeign extends HInstruction {
- HForeign(TypeMask type, List<HInstruction> inputs) : super(inputs, type);
+ HForeign(AbstractValue type, List<HInstruction> inputs) : super(inputs, type);
bool get isStatement => false;
native.NativeBehavior get nativeBehavior => null;
@@ -2018,7 +2028,7 @@
native.NativeThrowBehavior throwBehavior;
final FunctionEntity foreignFunction;
- HForeignCode(this.codeTemplate, TypeMask type, List<HInstruction> inputs,
+ HForeignCode(this.codeTemplate, AbstractValue type, List<HInstruction> inputs,
{this.isStatement: false,
SideEffects effects,
native.NativeBehavior nativeBehavior,
@@ -2044,8 +2054,12 @@
}
}
- HForeignCode.statement(js.Template codeTemplate, List<HInstruction> inputs,
- SideEffects effects, native.NativeBehavior nativeBehavior, TypeMask type)
+ HForeignCode.statement(
+ js.Template codeTemplate,
+ List<HInstruction> inputs,
+ SideEffects effects,
+ native.NativeBehavior nativeBehavior,
+ AbstractValue type)
: this(codeTemplate, type, inputs,
isStatement: true,
effects: effects,
@@ -2083,7 +2097,7 @@
abstract class HInvokeBinary extends HInstruction {
final Selector selector;
HInvokeBinary(
- HInstruction left, HInstruction right, this.selector, TypeMask type)
+ HInstruction left, HInstruction right, this.selector, AbstractValue type)
: super(<HInstruction>[left, right], type) {
sideEffects.clearAllSideEffects();
sideEffects.clearAllDependencies();
@@ -2097,14 +2111,15 @@
}
abstract class HBinaryArithmetic extends HInvokeBinary {
- HBinaryArithmetic(
- HInstruction left, HInstruction right, Selector selector, TypeMask type)
+ HBinaryArithmetic(HInstruction left, HInstruction right, Selector selector,
+ AbstractValue type)
: super(left, right, selector, type);
BinaryOperation operation(ConstantSystem constantSystem);
}
class HAdd extends HBinaryArithmetic {
- HAdd(HInstruction left, HInstruction right, Selector selector, TypeMask type)
+ HAdd(HInstruction left, HInstruction right, Selector selector,
+ AbstractValue type)
: super(left, right, selector, type);
accept(HVisitor visitor) => visitor.visitAdd(this);
@@ -2116,8 +2131,8 @@
}
class HDivide extends HBinaryArithmetic {
- HDivide(
- HInstruction left, HInstruction right, Selector selector, TypeMask type)
+ HDivide(HInstruction left, HInstruction right, Selector selector,
+ AbstractValue type)
: super(left, right, selector, type);
accept(HVisitor visitor) => visitor.visitDivide(this);
@@ -2129,8 +2144,8 @@
}
class HMultiply extends HBinaryArithmetic {
- HMultiply(
- HInstruction left, HInstruction right, Selector selector, TypeMask type)
+ HMultiply(HInstruction left, HInstruction right, Selector selector,
+ AbstractValue type)
: super(left, right, selector, type);
accept(HVisitor visitor) => visitor.visitMultiply(this);
@@ -2141,8 +2156,8 @@
}
class HSubtract extends HBinaryArithmetic {
- HSubtract(
- HInstruction left, HInstruction right, Selector selector, TypeMask type)
+ HSubtract(HInstruction left, HInstruction right, Selector selector,
+ AbstractValue type)
: super(left, right, selector, type);
accept(HVisitor visitor) => visitor.visitSubtract(this);
@@ -2154,8 +2169,8 @@
}
class HTruncatingDivide extends HBinaryArithmetic {
- HTruncatingDivide(
- HInstruction left, HInstruction right, Selector selector, TypeMask type)
+ HTruncatingDivide(HInstruction left, HInstruction right, Selector selector,
+ AbstractValue type)
: super(left, right, selector, type);
accept(HVisitor visitor) => visitor.visitTruncatingDivide(this);
@@ -2167,8 +2182,8 @@
}
class HRemainder extends HBinaryArithmetic {
- HRemainder(
- HInstruction left, HInstruction right, Selector selector, TypeMask type)
+ HRemainder(HInstruction left, HInstruction right, Selector selector,
+ AbstractValue type)
: super(left, right, selector, type);
accept(HVisitor visitor) => visitor.visitRemainder(this);
@@ -2185,7 +2200,8 @@
* Its block has one successor per constant, and one for the default.
*/
class HSwitch extends HControlFlow {
- HSwitch(List<HInstruction> inputs) : super(inputs);
+ HSwitch(AbstractValueDomain domain, List<HInstruction> inputs)
+ : super(domain, inputs);
HConstant constant(int index) => inputs[index + 1];
HInstruction get expression => inputs[0];
@@ -2203,14 +2219,14 @@
}
abstract class HBinaryBitOp extends HInvokeBinary {
- HBinaryBitOp(
- HInstruction left, HInstruction right, Selector selector, TypeMask type)
+ HBinaryBitOp(HInstruction left, HInstruction right, Selector selector,
+ AbstractValue type)
: super(left, right, selector, type);
}
class HShiftLeft extends HBinaryBitOp {
- HShiftLeft(
- HInstruction left, HInstruction right, Selector selector, TypeMask type)
+ HShiftLeft(HInstruction left, HInstruction right, Selector selector,
+ AbstractValue type)
: super(left, right, selector, type);
accept(HVisitor visitor) => visitor.visitShiftLeft(this);
@@ -2222,8 +2238,8 @@
}
class HShiftRight extends HBinaryBitOp {
- HShiftRight(
- HInstruction left, HInstruction right, Selector selector, TypeMask type)
+ HShiftRight(HInstruction left, HInstruction right, Selector selector,
+ AbstractValue type)
: super(left, right, selector, type);
accept(HVisitor visitor) => visitor.visitShiftRight(this);
@@ -2235,8 +2251,8 @@
}
class HBitOr extends HBinaryBitOp {
- HBitOr(
- HInstruction left, HInstruction right, Selector selector, TypeMask type)
+ HBitOr(HInstruction left, HInstruction right, Selector selector,
+ AbstractValue type)
: super(left, right, selector, type);
accept(HVisitor visitor) => visitor.visitBitOr(this);
@@ -2248,8 +2264,8 @@
}
class HBitAnd extends HBinaryBitOp {
- HBitAnd(
- HInstruction left, HInstruction right, Selector selector, TypeMask type)
+ HBitAnd(HInstruction left, HInstruction right, Selector selector,
+ AbstractValue type)
: super(left, right, selector, type);
accept(HVisitor visitor) => visitor.visitBitAnd(this);
@@ -2261,8 +2277,8 @@
}
class HBitXor extends HBinaryBitOp {
- HBitXor(
- HInstruction left, HInstruction right, Selector selector, TypeMask type)
+ HBitXor(HInstruction left, HInstruction right, Selector selector,
+ AbstractValue type)
: super(left, right, selector, type);
accept(HVisitor visitor) => visitor.visitBitXor(this);
@@ -2288,7 +2304,7 @@
}
class HNegate extends HInvokeUnary {
- HNegate(HInstruction input, Selector selector, TypeMask type)
+ HNegate(HInstruction input, Selector selector, AbstractValue type)
: super(input, selector, type);
accept(HVisitor visitor) => visitor.visitNegate(this);
@@ -2300,7 +2316,7 @@
}
class HAbs extends HInvokeUnary {
- HAbs(HInstruction input, Selector selector, TypeMask type)
+ HAbs(HInstruction input, Selector selector, AbstractValue type)
: super(input, selector, type);
accept(HVisitor visitor) => visitor.visitAbs(this);
@@ -2311,7 +2327,7 @@
}
class HBitNot extends HInvokeUnary {
- HBitNot(HInstruction input, Selector selector, TypeMask type)
+ HBitNot(HInstruction input, Selector selector, AbstractValue type)
: super(input, selector, type);
accept(HVisitor visitor) => visitor.visitBitNot(this);
@@ -2323,13 +2339,13 @@
}
class HExit extends HControlFlow {
- HExit() : super(const <HInstruction>[]);
+ HExit(AbstractValueDomain domain) : super(domain, const <HInstruction>[]);
toString() => 'exit';
accept(HVisitor visitor) => visitor.visitExit(this);
}
class HGoto extends HControlFlow {
- HGoto() : super(const <HInstruction>[]);
+ HGoto(AbstractValueDomain domain) : super(domain, const <HInstruction>[]);
toString() => 'goto';
accept(HVisitor visitor) => visitor.visitGoto(this);
}
@@ -2337,15 +2353,17 @@
abstract class HJump extends HControlFlow {
final JumpTarget target;
final LabelDefinition label;
- HJump(this.target, SourceInformation sourceInformation)
+ HJump(AbstractValueDomain domain, this.target,
+ SourceInformation sourceInformation)
: label = null,
- super(const <HInstruction>[]) {
+ super(domain, const <HInstruction>[]) {
this.sourceInformation = sourceInformation;
}
- HJump.toLabel(LabelDefinition label, SourceInformation sourceInformation)
+ HJump.toLabel(AbstractValueDomain domain, LabelDefinition label,
+ SourceInformation sourceInformation)
: label = label,
target = label.target,
- super(const <HInstruction>[]) {
+ super(domain, const <HInstruction>[]) {
this.sourceInformation = sourceInformation;
}
}
@@ -2356,13 +2374,15 @@
/// [SsaFromAstMixin.buildComplexSwitchStatement] for detail.
final bool breakSwitchContinueLoop;
- HBreak(JumpTarget target, SourceInformation sourceInformation,
+ HBreak(AbstractValueDomain domain, JumpTarget target,
+ SourceInformation sourceInformation,
{bool this.breakSwitchContinueLoop: false})
- : super(target, sourceInformation);
+ : super(domain, target, sourceInformation);
- HBreak.toLabel(LabelDefinition label, SourceInformation sourceInformation)
+ HBreak.toLabel(AbstractValueDomain domain, LabelDefinition label,
+ SourceInformation sourceInformation)
: breakSwitchContinueLoop = false,
- super.toLabel(label, sourceInformation);
+ super.toLabel(domain, label, sourceInformation);
String toString() => (label != null) ? 'break ${label.labelName}' : 'break';
@@ -2370,11 +2390,13 @@
}
class HContinue extends HJump {
- HContinue(JumpTarget target, SourceInformation sourceInformation)
- : super(target, sourceInformation);
+ HContinue(AbstractValueDomain domain, JumpTarget target,
+ SourceInformation sourceInformation)
+ : super(domain, target, sourceInformation);
- HContinue.toLabel(LabelDefinition label, SourceInformation sourceInformation)
- : super.toLabel(label, sourceInformation);
+ HContinue.toLabel(AbstractValueDomain domain, LabelDefinition label,
+ SourceInformation sourceInformation)
+ : super.toLabel(domain, label, sourceInformation);
String toString() =>
(label != null) ? 'continue ${label.labelName}' : 'continue';
@@ -2386,7 +2408,7 @@
HLocalValue exception;
HBasicBlock catchBlock;
HBasicBlock finallyBlock;
- HTry() : super(const <HInstruction>[]);
+ HTry(AbstractValueDomain domain) : super(domain, const <HInstruction>[]);
toString() => 'try';
accept(HVisitor visitor) => visitor.visitTry(this);
HBasicBlock get joinBlock => this.block.successors.last;
@@ -2398,7 +2420,7 @@
// leads to one of this instruction a predecessor of catch and
// finally.
class HExitTry extends HControlFlow {
- HExitTry() : super(const <HInstruction>[]);
+ HExitTry(AbstractValueDomain domain) : super(domain, const <HInstruction>[]);
toString() => 'exit try';
accept(HVisitor visitor) => visitor.visitExitTry(this);
HBasicBlock get bodyTrySuccessor => block.successors[0];
@@ -2406,7 +2428,8 @@
class HIf extends HConditionalBranch {
HBlockFlow blockInformation = null;
- HIf(HInstruction condition) : super(<HInstruction>[condition]);
+ HIf(AbstractValueDomain domain, HInstruction condition)
+ : super(domain, <HInstruction>[condition]);
toString() => 'if';
accept(HVisitor visitor) => visitor.visitIf(this);
@@ -2428,15 +2451,16 @@
static const int DO_WHILE_LOOP = 1;
final int kind;
- HLoopBranch(HInstruction condition, [this.kind = CONDITION_FIRST_LOOP])
- : super(<HInstruction>[condition]);
+ HLoopBranch(AbstractValueDomain domain, HInstruction condition,
+ [this.kind = CONDITION_FIRST_LOOP])
+ : super(domain, <HInstruction>[condition]);
toString() => 'loop-branch';
accept(HVisitor visitor) => visitor.visitLoopBranch(this);
}
class HConstant extends HInstruction {
final ConstantValue constant;
- HConstant.internal(this.constant, TypeMask constantType)
+ HConstant.internal(this.constant, AbstractValue constantType)
: super(<HInstruction>[], constantType);
toString() => 'literal: ${constant.toStructuredText()}';
@@ -2468,7 +2492,8 @@
}
class HNot extends HInstruction {
- HNot(HInstruction value, TypeMask type) : super(<HInstruction>[value], type) {
+ HNot(HInstruction value, AbstractValue type)
+ : super(<HInstruction>[value], type) {
setUseGvn();
}
@@ -2484,7 +2509,8 @@
* value from the start, whereas [HLocalValue]s need to be initialized first.
*/
class HLocalValue extends HInstruction {
- HLocalValue(Entity variable, TypeMask type) : super(<HInstruction>[], type) {
+ HLocalValue(Entity variable, AbstractValue type)
+ : super(<HInstruction>[], type) {
sourceElement = variable;
}
@@ -2511,7 +2537,7 @@
}
class HThis extends HParameterValue {
- HThis(ThisLocal element, TypeMask type) : super(element, type);
+ HThis(ThisLocal element, AbstractValue type) : super(element, type);
ThisLocal get sourceElement => super.sourceElement;
void set sourceElement(covariant ThisLocal local) {
@@ -2540,15 +2566,15 @@
// The order of the [inputs] must correspond to the order of the
// predecessor-edges. That is if an input comes from the first predecessor
// of the surrounding block, then the input must be the first in the [HPhi].
- HPhi(Local variable, List<HInstruction> inputs, TypeMask type)
+ HPhi(Local variable, List<HInstruction> inputs, AbstractValue type)
: super(inputs, type) {
sourceElement = variable;
}
- HPhi.noInputs(Local variable, TypeMask type)
+ HPhi.noInputs(Local variable, AbstractValue type)
: this(variable, <HInstruction>[], type);
- HPhi.singleInput(Local variable, HInstruction input, TypeMask type)
+ HPhi.singleInput(Local variable, HInstruction input, AbstractValue type)
: this(variable, <HInstruction>[input], type);
- HPhi.manyInputs(Local variable, List<HInstruction> inputs, TypeMask type)
+ HPhi.manyInputs(Local variable, List<HInstruction> inputs, AbstractValue type)
: this(variable, inputs, type);
void addInput(HInstruction input) {
@@ -2627,8 +2653,9 @@
}
class HReturn extends HControlFlow {
- HReturn(HInstruction value, SourceInformation sourceInformation)
- : super(<HInstruction>[value]) {
+ HReturn(AbstractValueDomain domain, HInstruction value,
+ SourceInformation sourceInformation)
+ : super(domain, <HInstruction>[value]) {
this.sourceInformation = sourceInformation;
}
toString() => 'return';
@@ -2636,8 +2663,9 @@
}
class HThrowExpression extends HInstruction {
- HThrowExpression(HInstruction value, SourceInformation sourceInformation)
- : super(<HInstruction>[value], const TypeMask.nonNullEmpty()) {
+ HThrowExpression(AbstractValueDomain domain, HInstruction value,
+ SourceInformation sourceInformation)
+ : super(<HInstruction>[value], domain.emptyType) {
this.sourceInformation = sourceInformation;
}
toString() => 'throw expression';
@@ -2646,7 +2674,7 @@
}
class HAwait extends HInstruction {
- HAwait(HInstruction value, TypeMask type)
+ HAwait(HInstruction value, AbstractValue type)
: super(<HInstruction>[value], type);
toString() => 'await';
accept(HVisitor visitor) => visitor.visitAwait(this);
@@ -2656,8 +2684,9 @@
}
class HYield extends HInstruction {
- HYield(HInstruction value, this.hasStar, SourceInformation sourceInformation)
- : super(<HInstruction>[value], const TypeMask.nonNullEmpty()) {
+ HYield(AbstractValueDomain domain, HInstruction value, this.hasStar,
+ SourceInformation sourceInformation)
+ : super(<HInstruction>[value], domain.emptyType) {
this.sourceInformation = sourceInformation;
}
bool hasStar;
@@ -2669,9 +2698,10 @@
class HThrow extends HControlFlow {
final bool isRethrow;
- HThrow(HInstruction value, SourceInformation sourceInformation,
+ HThrow(AbstractValueDomain domain, HInstruction value,
+ SourceInformation sourceInformation,
{this.isRethrow: false})
- : super(<HInstruction>[value]) {
+ : super(domain, <HInstruction>[value]) {
this.sourceInformation = sourceInformation;
}
toString() => 'throw';
@@ -2680,7 +2710,7 @@
class HStatic extends HInstruction {
final MemberEntity element;
- HStatic(this.element, TypeMask type, SourceInformation sourceInformation)
+ HStatic(this.element, AbstractValue type, SourceInformation sourceInformation)
: super(<HInstruction>[], type) {
assert(element != null);
sideEffects.clearAllSideEffects();
@@ -2715,7 +2745,7 @@
// (a && C.JSArray_methods).get$first(a)
//
- HInterceptor(HInstruction receiver, TypeMask type)
+ HInterceptor(HInstruction receiver, AbstractValue type)
: super(<HInstruction>[receiver], type) {
this.sourceInformation = receiver.sourceInformation;
sideEffects.clearAllSideEffects();
@@ -2760,9 +2790,9 @@
HOneShotInterceptor(
AbstractValueDomain domain,
Selector selector,
- TypeMask mask,
+ AbstractValue mask,
List<HInstruction> inputs,
- TypeMask type,
+ AbstractValue type,
this.typeArguments,
this.interceptedClasses)
: super(selector, mask, null, inputs, true, type) {
@@ -2780,7 +2810,8 @@
class HLazyStatic extends HInstruction {
final FieldEntity element;
- HLazyStatic(this.element, TypeMask type, SourceInformation sourceInformation)
+ HLazyStatic(
+ this.element, AbstractValue type, SourceInformation sourceInformation)
: super(<HInstruction>[], type) {
// TODO(4931): The first access has side-effects, but we afterwards we
// should be able to GVN.
@@ -2800,8 +2831,8 @@
class HStaticStore extends HInstruction {
MemberEntity element;
- HStaticStore(this.element, HInstruction value)
- : super(<HInstruction>[value], const TypeMask.nonNullEmpty()) {
+ HStaticStore(AbstractValueDomain domain, this.element, HInstruction value)
+ : super(<HInstruction>[value], domain.emptyType) {
sideEffects.clearAllSideEffects();
sideEffects.clearAllDependencies();
sideEffects.setChangesStaticProperty();
@@ -2816,7 +2847,8 @@
}
class HLiteralList extends HInstruction {
- HLiteralList(List<HInstruction> inputs, TypeMask type) : super(inputs, type);
+ HLiteralList(List<HInstruction> inputs, AbstractValue type)
+ : super(inputs, type);
toString() => 'literal list';
accept(HVisitor visitor) => visitor.visitLiteralList(this);
@@ -2829,8 +2861,8 @@
*/
class HIndex extends HInstruction {
final Selector selector;
- HIndex(
- HInstruction receiver, HInstruction index, this.selector, TypeMask type)
+ HIndex(HInstruction receiver, HInstruction index, this.selector,
+ AbstractValue type)
: super(<HInstruction>[receiver, index], type) {
sideEffects.clearAllSideEffects();
sideEffects.clearAllDependencies();
@@ -2863,10 +2895,9 @@
*/
class HIndexAssign extends HInstruction {
final Selector selector;
- HIndexAssign(HInstruction receiver, HInstruction index, HInstruction value,
- this.selector)
- : super(<HInstruction>[receiver, index, value],
- const TypeMask.nonNullEmpty()) {
+ HIndexAssign(AbstractValueDomain domain, HInstruction receiver,
+ HInstruction index, HInstruction value, this.selector)
+ : super(<HInstruction>[receiver, index, value], domain.emptyType) {
sideEffects.clearAllSideEffects();
sideEffects.clearAllDependencies();
sideEffects.setChangesIndex();
@@ -2901,14 +2932,14 @@
final int kind;
final bool useInstanceOf;
- HIs.direct(DartType typeExpression, HInstruction expression, TypeMask type,
- SourceInformation sourceInformation)
+ HIs.direct(DartType typeExpression, HInstruction expression,
+ AbstractValue type, SourceInformation sourceInformation)
: this.internal(
typeExpression, [expression], RAW_CHECK, type, sourceInformation);
// Pre-verified that the check can be done using 'instanceof'.
HIs.instanceOf(DartType typeExpression, HInstruction expression,
- TypeMask type, SourceInformation sourceInformation)
+ AbstractValue type, SourceInformation sourceInformation)
: this.internal(
typeExpression, [expression], RAW_CHECK, type, sourceInformation,
useInstanceOf: true);
@@ -2917,7 +2948,7 @@
DartType typeExpression,
HInstruction expression,
HInterceptor interceptor,
- TypeMask type,
+ AbstractValue type,
SourceInformation sourceInformation) {
assert(
(typeExpression.isFunctionType || typeExpression.isInterfaceType) &&
@@ -2927,18 +2958,26 @@
RAW_CHECK, type, sourceInformation);
}
- HIs.compound(DartType typeExpression, HInstruction expression,
- HInstruction call, TypeMask type, SourceInformation sourceInformation)
+ HIs.compound(
+ DartType typeExpression,
+ HInstruction expression,
+ HInstruction call,
+ AbstractValue type,
+ SourceInformation sourceInformation)
: this.internal(typeExpression, [expression, call], COMPOUND_CHECK, type,
sourceInformation);
- HIs.variable(DartType typeExpression, HInstruction expression,
- HInstruction call, TypeMask type, SourceInformation sourceInformation)
+ HIs.variable(
+ DartType typeExpression,
+ HInstruction expression,
+ HInstruction call,
+ AbstractValue type,
+ SourceInformation sourceInformation)
: this.internal(typeExpression, [expression, call], VARIABLE_CHECK, type,
sourceInformation);
HIs.internal(this.typeExpression, List<HInstruction> inputs, this.kind,
- TypeMask type, SourceInformation sourceInformation,
+ AbstractValue type, SourceInformation sourceInformation,
{bool this.useInstanceOf: false})
: super(inputs, type) {
assert(kind >= RAW_CHECK && kind <= VARIABLE_CHECK);
@@ -2983,7 +3022,7 @@
class HIsViaInterceptor extends HLateInstruction {
final DartType typeExpression;
HIsViaInterceptor(
- this.typeExpression, HInstruction interceptor, TypeMask type)
+ this.typeExpression, HInstruction interceptor, AbstractValue type)
: super(<HInstruction>[interceptor], type) {
setUseGvn();
}
@@ -3017,10 +3056,11 @@
//
final Selector receiverTypeCheckSelector;
- TypeMask checkedType; // Not final because we refine it.
- TypeMask inputType; // Holds input type for codegen after HTypeKnown removal.
+ AbstractValue checkedType; // Not final because we refine it.
+ AbstractValue
+ inputType; // Holds input type for codegen after HTypeKnown removal.
- HTypeConversion(this.typeExpression, this.kind, TypeMask type,
+ HTypeConversion(this.typeExpression, this.kind, AbstractValue type,
HInstruction input, SourceInformation sourceInformation,
{this.receiverTypeCheckSelector})
: checkedType = type,
@@ -3032,7 +3072,7 @@
}
HTypeConversion.withTypeRepresentation(this.typeExpression, this.kind,
- TypeMask type, HInstruction input, HInstruction typeRepresentation)
+ AbstractValue type, HInstruction input, HInstruction typeRepresentation)
: checkedType = type,
receiverTypeCheckSelector = null,
super(<HInstruction>[input, typeRepresentation], type) {
@@ -3040,8 +3080,8 @@
sourceElement = input.sourceElement;
}
- HTypeConversion.viaMethodOnType(this.typeExpression, this.kind, TypeMask type,
- HInstruction reifiedType, HInstruction input)
+ HTypeConversion.viaMethodOnType(this.typeExpression, this.kind,
+ AbstractValue type, HInstruction reifiedType, HInstruction input)
: checkedType = type,
receiverTypeCheckSelector = null,
super(<HInstruction>[reifiedType, input], type) {
@@ -3104,16 +3144,16 @@
/// The [HTypeKnown] instruction marks a value with a refined type.
class HTypeKnown extends HCheck {
- TypeMask knownType;
+ AbstractValue knownType;
final bool _isMovable;
- HTypeKnown.pinned(TypeMask knownType, HInstruction input)
+ HTypeKnown.pinned(AbstractValue knownType, HInstruction input)
: this.knownType = knownType,
this._isMovable = false,
super(<HInstruction>[input], knownType);
HTypeKnown.witnessed(
- TypeMask knownType, HInstruction input, HInstruction witness)
+ AbstractValue knownType, HInstruction input, HInstruction witness)
: this.knownType = knownType,
this._isMovable = true,
super(<HInstruction>[input, witness], knownType);
@@ -3152,7 +3192,7 @@
}
class HStringConcat extends HInstruction {
- HStringConcat(HInstruction left, HInstruction right, TypeMask type)
+ HStringConcat(HInstruction left, HInstruction right, AbstractValue type)
: super(<HInstruction>[left, right], type) {
// TODO(sra): Until Issue 9293 is fixed, this false dependency keeps the
// concats bunched with stringified inputs for much better looking code with
@@ -3172,7 +3212,7 @@
* into a String value.
*/
class HStringify extends HInstruction {
- HStringify(HInstruction input, TypeMask type)
+ HStringify(HInstruction input, AbstractValue type)
: super(<HInstruction>[input], type) {
sideEffects.setAllSideEffects();
sideEffects.setDependsOnSomething();
@@ -3462,7 +3502,7 @@
/// Reads raw reified type info from an object.
class HTypeInfoReadRaw extends HInstruction {
- HTypeInfoReadRaw(HInstruction receiver, TypeMask instructionType)
+ HTypeInfoReadRaw(HInstruction receiver, AbstractValue instructionType)
: super(<HInstruction>[receiver], instructionType) {
setUseGvn();
}
@@ -3488,14 +3528,14 @@
final bool isIntercepted;
HTypeInfoReadVariable.intercepted(this.variable, HInstruction interceptor,
- HInstruction receiver, TypeMask instructionType)
+ HInstruction receiver, AbstractValue instructionType)
: isIntercepted = true,
super(<HInstruction>[interceptor, receiver], instructionType) {
setUseGvn();
}
HTypeInfoReadVariable.noInterceptor(
- this.variable, HInstruction receiver, TypeMask instructionType)
+ this.variable, HInstruction receiver, AbstractValue instructionType)
: isIntercepted = false,
super(<HInstruction>[receiver], instructionType) {
setUseGvn();
@@ -3578,7 +3618,7 @@
final TypeInfoExpressionKind kind;
final DartType dartType;
HTypeInfoExpression(this.kind, this.dartType, List<HInstruction> inputs,
- TypeMask instructionType)
+ AbstractValue instructionType)
: super(inputs, instructionType) {
setUseGvn();
}
diff --git a/pkg/compiler/lib/src/ssa/optimize.dart b/pkg/compiler/lib/src/ssa/optimize.dart
index f3174f2..170afb3 100644
--- a/pkg/compiler/lib/src/ssa/optimize.dart
+++ b/pkg/compiler/lib/src/ssa/optimize.dart
@@ -1130,7 +1130,7 @@
value = other;
}
}
- return new HFieldSet(field, receiver, value);
+ return new HFieldSet(_abstractValueDomain, field, receiver, value);
}
HInstruction visitInvokeClosure(HInvokeClosure node) {
diff --git a/pkg/compiler/lib/src/ssa/ssa_branch_builder.dart b/pkg/compiler/lib/src/ssa/ssa_branch_builder.dart
index 537fd50..f628a1e 100644
--- a/pkg/compiler/lib/src/ssa/ssa_branch_builder.dart
+++ b/pkg/compiler/lib/src/ssa/ssa_branch_builder.dart
@@ -42,7 +42,8 @@
checkNotAborted();
assert(identical(builder.current, builder.lastOpenedBlock));
HInstruction conditionValue = builder.popBoolified();
- HIf branch = new HIf(conditionValue)..sourceInformation = sourceInformation;
+ HIf branch = new HIf(builder.abstractValueDomain, conditionValue)
+ ..sourceInformation = sourceInformation;
HBasicBlock conditionExitBlock = builder.current;
builder.close(branch);
conditionBranch.exitLocals = builder.localsHandler;
diff --git a/pkg/compiler/lib/src/ssa/types_propagation.dart b/pkg/compiler/lib/src/ssa/types_propagation.dart
index 5b84020..f5e50bb 100644
--- a/pkg/compiler/lib/src/ssa/types_propagation.dart
+++ b/pkg/compiler/lib/src/ssa/types_propagation.dart
@@ -258,7 +258,7 @@
HInstruction input = instruction.checkedInput;
TypeMask inputType = input.instructionType;
TypeMask outputType =
- instruction.knownType.intersection(inputType, closedWorld);
+ abstractValueDomain.intersection(instruction.knownType, inputType);
if (inputType != outputType) {
input.replaceAllUsersDominatedBy(instruction.next, instruction);
}
diff --git a/pkg/compiler/lib/src/types/abstract_value_domain.dart b/pkg/compiler/lib/src/types/abstract_value_domain.dart
index 0bf4247..3ce4ce1 100644
--- a/pkg/compiler/lib/src/types/abstract_value_domain.dart
+++ b/pkg/compiler/lib/src/types/abstract_value_domain.dart
@@ -4,6 +4,7 @@
library dart2js.abstract_value_domain;
+import '../constants/values.dart' show ConstantValue;
import '../elements/entities.dart';
/// A value in an abstraction of runtime values.
@@ -93,6 +94,8 @@
/// Creates an [AbstractValue] for non-null instance that implements [cls].
AbstractValue createNonNullSubtype(ClassEntity cls);
+ AbstractValue createNullableSubtype(ClassEntity cls);
+
/// Returns `true` if [value] is a native typed array or `null` at runtime.
bool isTypedArray(covariant AbstractValue value);
@@ -237,4 +240,7 @@
/// Returns `true` if [a] contains all non-null runtime values.
bool containsAll(covariant AbstractValue a);
+
+ /// Computes the [AbstractValue] corresponding to the constant [value].
+ AbstractValue computeAbstractValueForConstant(ConstantValue value);
}
diff --git a/pkg/compiler/lib/src/types/masks.dart b/pkg/compiler/lib/src/types/masks.dart
index 2f8448f..24203e1 100644
--- a/pkg/compiler/lib/src/types/masks.dart
+++ b/pkg/compiler/lib/src/types/masks.dart
@@ -6,7 +6,7 @@
import '../common.dart';
import '../common_elements.dart' show CommonElements;
-import '../constants/values.dart' show PrimitiveConstantValue;
+import '../constants/values.dart' show ConstantValue, PrimitiveConstantValue;
import '../elements/entities.dart';
import '../inferrer/type_graph_inferrer.dart' show TypeGraphInferrer;
import '../universe/selector.dart' show Selector;
@@ -18,6 +18,7 @@
import '../util/util.dart';
import '../world.dart' show ClassQuery, ClosedWorld;
import 'abstract_value_domain.dart';
+import 'constants.dart';
part 'container_type_mask.dart';
part 'dictionary_type_mask.dart';
@@ -195,6 +196,10 @@
return new TypeMask.nonNullSubtype(cls, _closedWorld);
}
+ TypeMask createNullableSubtype(ClassEntity cls) {
+ return new TypeMask.subtype(cls, _closedWorld);
+ }
+
TypeMask excludeNull(TypeMask mask) => mask.nonNullable();
@override
@@ -365,4 +370,9 @@
bool areDisjoint(TypeMask a, TypeMask b) => a.isDisjoint(b, _closedWorld);
bool containsAll(TypeMask a) => a.containsAll(_closedWorld);
+
+ @override
+ AbstractValue computeAbstractValueForConstant(ConstantValue value) {
+ return computeTypeMask(_closedWorld, value);
+ }
}
diff --git a/tests/compiler/dart2js/codegen/value_range2_test.dart b/tests/compiler/dart2js/codegen/value_range2_test.dart
index f4b9376..be9df0f 100644
--- a/tests/compiler/dart2js/codegen/value_range2_test.dart
+++ b/tests/compiler/dart2js/codegen/value_range2_test.dart
@@ -5,12 +5,24 @@
import "package:expect/expect.dart";
import "package:compiler/src/ssa/nodes.dart";
import "package:compiler/src/ssa/value_range_analyzer.dart";
+import "package:compiler/src/types/abstract_value_domain.dart";
import "package:compiler/src/js_backend/constant_system_javascript.dart";
ValueRangeInfo info = new ValueRangeInfo(const JavaScriptConstantSystem());
-Value instructionValue = info.newInstructionValue(new HBreak(null, null));
-Value lengthValue = info.newPositiveValue(new HBreak(null, null));
+class AbstractValueDomainMock implements AbstractValueDomain {
+ const AbstractValueDomainMock();
+
+ @override
+ noSuchMethod(Invocation invocation) => null;
+}
+
+AbstractValueDomain abstractValueDomain = const AbstractValueDomainMock();
+
+Value instructionValue =
+ info.newInstructionValue(new HBreak(abstractValueDomain, null, null));
+Value lengthValue =
+ info.newPositiveValue(new HBreak(abstractValueDomain, null, null));
Range createSingleRange(Value value) => info.newNormalizedRange(value, value);