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>
This commit is contained in:
Johnni Winther 2018-05-08 11:20:44 +00:00 committed by commit-bot@chromium.org
parent d3c7df35b4
commit 51fa3f3b0c
15 changed files with 361 additions and 257 deletions

View file

@ -101,7 +101,7 @@ void handleSsaNative(SsaAstGraphBuilder builder, Expression nativeBody) {
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) {

View file

@ -727,8 +727,8 @@ class SsaAstGraphBuilder extends ast.Visitor
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 @@ class SsaAstGraphBuilder extends ast.Visitor
},
visitThen: () {
closeAndGotoExit(new HReturn(
abstractValueDomain,
graph.addConstantBool(false, closedWorld),
sourceInformationBuilder
.buildImplicitReturn(functionElement)));
@ -796,7 +797,7 @@ class SsaAstGraphBuilder extends ast.Visitor
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 @@ class SsaAstGraphBuilder extends ast.Visitor
}
}
closeAndGotoExit(new HReturn(
value, sourceInformationBuilder.buildReturn(sourceInfoNode)));
closeAndGotoExit(new HReturn(abstractValueDomain, value,
sourceInformationBuilder.buildReturn(sourceInfoNode)));
return closeFunction();
}
@ -1358,7 +1359,8 @@ class SsaAstGraphBuilder extends ast.Visitor
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 @@ class SsaAstGraphBuilder extends ast.Visitor
}
}
if (inliningStack.isEmpty) {
closeAndGotoExit(new HReturn(newObject,
closeAndGotoExit(new HReturn(abstractValueDomain, newObject,
sourceInformationBuilder.buildImplicitReturn(functionElement)));
return closeFunction();
} else {
@ -1466,7 +1468,7 @@ class SsaAstGraphBuilder extends ast.Visitor
parameters,
sourceInformationBuilder.buildDeclaration(element),
isGenerativeConstructorBody: element.isGenerativeConstructorBody);
close(new HGoto()).addSuccessor(block);
close(new HGoto(abstractValueDomain)).addSuccessor(block);
open(block);
@ -1598,8 +1600,8 @@ class SsaAstGraphBuilder extends ast.Visitor
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 @@ class SsaAstGraphBuilder extends ast.Visitor
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 @@ class SsaAstGraphBuilder extends ast.Visitor
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 @@ class SsaAstGraphBuilder extends ast.Visitor
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 @@ class SsaAstGraphBuilder extends ast.Visitor
// 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 @@ class SsaAstGraphBuilder extends ast.Visitor
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 @@ class SsaAstGraphBuilder extends ast.Visitor
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 @@ class SsaAstGraphBuilder extends ast.Visitor
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 @@ class SsaAstGraphBuilder extends ast.Visitor
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 @@ class SsaAstGraphBuilder extends ast.Visitor
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 @@ class SsaAstGraphBuilder extends ast.Visitor
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 @@ class SsaAstGraphBuilder extends ast.Visitor
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 @@ class SsaAstGraphBuilder extends ast.Visitor
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 @@ class SsaAstGraphBuilder extends ast.Visitor
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 @@ class SsaAstGraphBuilder extends ast.Visitor
// 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 @@ class SsaAstGraphBuilder extends ast.Visitor
// 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 @@ class SsaAstGraphBuilder extends ast.Visitor
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 @@ class SsaAstGraphBuilder extends ast.Visitor
// 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 @@ class SsaAstGraphBuilder extends ast.Visitor
// 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 @@ class SsaAstGraphBuilder extends ast.Visitor
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 @@ class SsaAstGraphBuilder extends ast.Visitor
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 @@ class SsaAstGraphBuilder extends ast.Visitor
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 @@ class SsaAstGraphBuilder extends ast.Visitor
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);
}

View file

@ -323,7 +323,7 @@ class KernelSsaGraphBuilder extends ir.Visitor
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 @@ class KernelSsaGraphBuilder extends ir.Visitor
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 @@ class KernelSsaGraphBuilder extends ir.Visitor
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 @@ class KernelSsaGraphBuilder extends ir.Visitor
}
if (_inliningStack.isEmpty) {
closeAndGotoExit(new HReturn(newObject, sourceInformation));
closeAndGotoExit(
new HReturn(abstractValueDomain, newObject, sourceInformation));
closeFunction();
} else {
localsHandler.updateLocal(_returnLocal, newObject,
@ -920,8 +922,8 @@ class KernelSsaGraphBuilder extends ir.Visitor
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 @@ class KernelSsaGraphBuilder extends ir.Visitor
},
visitThen: () {
closeAndGotoExit(new HReturn(
abstractValueDomain,
graph.addConstantBool(false, closedWorld),
_sourceInformationBuilder.buildReturn(functionNode)));
},
@ -1083,8 +1086,8 @@ class KernelSsaGraphBuilder extends ir.Visitor
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 @@ class KernelSsaGraphBuilder extends ir.Visitor
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 @@ class KernelSsaGraphBuilder extends ir.Visitor
}
void closeFunction() {
if (!isAborted()) closeAndGotoExit(new HGoto());
graph.finalize();
if (!isAborted()) closeAndGotoExit(new HGoto(abstractValueDomain));
graph.finalize(abstractValueDomain);
}
@override
@ -1246,7 +1249,8 @@ class KernelSsaGraphBuilder extends ir.Visitor
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 @@ class KernelSsaGraphBuilder extends ir.Visitor
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 @@ class KernelSsaGraphBuilder extends ir.Visitor
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 @@ class KernelSsaGraphBuilder extends ir.Visitor
// 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 @@ class KernelSsaGraphBuilder extends ir.Visitor
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 @@ class KernelSsaGraphBuilder extends ir.Visitor
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 @@ class KernelSsaGraphBuilder extends ir.Visitor
'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 @@ class KernelSsaGraphBuilder extends ir.Visitor
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 @@ class KernelSsaGraphBuilder extends ir.Visitor
pop();
} else {
add(new HStaticStore(
abstractValueDomain,
_elementMap.getMember(staticTarget),
typeBuilder.potentiallyCheckOrTrustTypeOfAssignment(
value, _getDartTypeIfValid(staticTarget.setterType))));
@ -4534,7 +4541,7 @@ class KernelSsaGraphBuilder extends ir.Visitor
SourceInformation sourceInformation =
_sourceInformationBuilder.buildThrow(node);
handleInTryStatement();
push(new HThrowExpression(pop(), sourceInformation));
push(new HThrowExpression(abstractValueDomain, pop(), sourceInformation));
isReachable = false;
}
}
@ -4551,8 +4558,8 @@ class KernelSsaGraphBuilder extends ir.Visitor
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 @@ class KernelSsaGraphBuilder extends ir.Visitor
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 @@ class KernelSsaGraphBuilder extends ir.Visitor
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 @@ class TryCatchFinallyBuilder {
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 @@ class TryCatchFinallyBuilder {
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 @@ class TryCatchFinallyBuilder {
// 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 @@ class TryCatchFinallyBuilder {
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 @@ class TryCatchFinallyBuilder {
sourceInformation:
kernelBuilder._sourceInformationBuilder.buildCatch(firstBlock));
if (!kernelBuilder.isAborted()) {
endCatchBlock = kernelBuilder.close(new HGoto());
endCatchBlock =
kernelBuilder.close(new HGoto(kernelBuilder.abstractValueDomain));
}
kernelBuilder.rethrowableException = oldRethrowableException;

View file

@ -202,7 +202,7 @@ abstract class GraphBuilder {
}
void goto(HBasicBlock from, HBasicBlock to) {
from.close(new HGoto());
from.close(new HGoto(abstractValueDomain));
from.addSuccessor(to);
}
@ -275,7 +275,7 @@ abstract class GraphBuilder {
/// 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);

View file

@ -139,7 +139,8 @@ class IndexAssignSpecializer extends InvokeDynamicSpecializer {
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

View file

@ -88,9 +88,11 @@ class TargetJumpHandler implements JumpHandler {
[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 @@ class TargetJumpHandler implements JumpHandler {
[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 @@ abstract class SwitchCaseJumpHandler extends TargetJumpHandler {
// 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 @@ abstract class SwitchCaseJumpHandler extends TargetJumpHandler {
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));

View file

@ -443,13 +443,15 @@ class LocalsHandler {
// 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);
}
}

View file

@ -65,8 +65,8 @@ abstract class LoopHandler<T> {
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 @@ abstract class LoopHandler<T> {
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 @@ abstract class LoopHandler<T> {
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 @@ abstract class LoopHandler<T> {
// 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 @@ abstract class LoopHandler<T> {
// 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 @@ abstract class LoopHandler<T> {
// 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 @@ abstract class LoopHandler<T> {
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 @@ abstract class LoopHandler<T> {
/// 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);

View file

@ -15,9 +15,7 @@ import '../io/source_information.dart';
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 @@ class HGraph {
// 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 @@ class HGraph {
// 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 @@ abstract class HInstruction implements Spannable {
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 @@ class HRef extends HInstruction {
* 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 @@ class HBoundsCheck extends HCheck {
}
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 @@ class HCreate extends HInstruction {
/// 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 @@ class HCreate extends HInstruction {
// 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 HInvoke extends HInstruction {
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 @@ abstract class HInvokeDynamic extends HInvoke {
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 @@ class HInvokeDynamicMethod extends HInvokeDynamic {
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 @@ class HInvokeDynamicMethod extends HInvokeDynamic {
}
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 @@ abstract class HInvokeDynamicField extends HInvokeDynamic {
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 HInvokeDynamicGetter extends HInvokeDynamicField {
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 @@ class HInvokeStatic extends HInvoke {
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 @@ class HInvokeSuper extends HInvokeStatic {
this.selector,
List<HInstruction> inputs,
bool isIntercepted,
TypeMask type,
AbstractValue type,
List<DartType> typeArguments,
SourceInformation sourceInformation,
{this.isSetter})
@ -1802,7 +1811,7 @@ class HInvokeConstructorBody extends HInvokeStatic {
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 @@ class HInvokeConstructorBody extends HInvokeStatic {
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 @@ abstract class HFieldAccess extends HInstruction {
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 HFieldGet extends HFieldAccess {
}
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 HFieldSet extends HFieldAccess {
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 @@ class HReadModifyWrite extends HLateInstruction {
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 @@ class HReadModifyWrite extends HLateInstruction {
}
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 @@ class HReadModifyWrite extends HLateInstruction {
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 @@ abstract class HLocalAccess extends HInstruction {
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 HLocalGet extends HLocalAccess {
}
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 @@ class HLocalSet extends HLocalAccess {
}
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 @@ class HForeignCode extends HForeign {
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 @@ class HForeignCode extends HForeign {
}
}
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 @@ class HForeignCode extends HForeign {
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 HInvokeBinary extends HInstruction {
}
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 HAdd extends HBinaryArithmetic {
}
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 HDivide extends HBinaryArithmetic {
}
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 HMultiply extends HBinaryArithmetic {
}
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 HSubtract extends HBinaryArithmetic {
}
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 HTruncatingDivide extends HBinaryArithmetic {
}
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 @@ class HRemainder extends HBinaryArithmetic {
* 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 @@ class HSwitch extends HControlFlow {
}
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 HShiftLeft extends HBinaryBitOp {
}
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 HShiftRight extends HBinaryBitOp {
}
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 HBitOr extends HBinaryBitOp {
}
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 HBitAnd extends HBinaryBitOp {
}
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 @@ abstract class HInvokeUnary extends HInstruction {
}
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 HNegate extends HInvokeUnary {
}
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 HAbs extends HInvokeUnary {
}
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 HBitNot extends HInvokeUnary {
}
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 @@ class HGoto extends HControlFlow {
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 @@ class HBreak extends HJump {
/// [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 HBreak extends HJump {
}
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 @@ class HTry extends HControlFlow {
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 @@ class HTry extends HControlFlow {
// 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 HExitTry extends HControlFlow {
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 @@ class HLoopBranch extends HConditionalBranch {
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 HConstant extends HInstruction {
}
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 @@ class HNot extends HInstruction {
* 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 HParameterValue extends HLocalValue {
}
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 @@ class HPhi extends HInstruction {
// 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 HLessEqual extends HRelational {
}
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 HReturn extends HControlFlow {
}
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 HThrowExpression extends HInstruction {
}
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 HAwait extends HInstruction {
}
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 HYield extends HInstruction {
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 HThrow extends HControlFlow {
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 @@ class HInterceptor extends HInstruction {
// (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 @@ class HOneShotInterceptor extends HInvokeDynamic {
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 HOneShotInterceptor extends HInvokeDynamic {
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 HLazyStatic extends HInstruction {
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 HStaticStore extends HInstruction {
}
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 HLiteralList extends HInstruction {
*/
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 HIndex extends HInstruction {
*/
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 @@ class HIs extends HInstruction {
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 @@ class HIs extends HInstruction {
DartType typeExpression,
HInstruction expression,
HInterceptor interceptor,
TypeMask type,
AbstractValue type,
SourceInformation sourceInformation) {
assert(
(typeExpression.isFunctionType || typeExpression.isInterfaceType) &&
@ -2927,18 +2958,26 @@ class HIs extends HInstruction {
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 HIs extends HInstruction {
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 @@ class HTypeConversion extends HCheck {
//
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 @@ class HTypeConversion extends HCheck {
}
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 @@ class HTypeConversion extends HCheck {
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 @@ class HTypeConversion extends HCheck {
/// 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 HRangeConversion extends HCheck {
}
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 @@ class HStringConcat extends HInstruction {
* 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 @@ class HSwitchBlockInformation implements HStatementInformation {
/// 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 @@ class HTypeInfoReadVariable extends HInstruction {
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 @@ class HTypeInfoExpression extends HInstruction {
final TypeInfoExpressionKind kind;
final DartType dartType;
HTypeInfoExpression(this.kind, this.dartType, List<HInstruction> inputs,
TypeMask instructionType)
AbstractValue instructionType)
: super(inputs, instructionType) {
setUseGvn();
}

View file

@ -1130,7 +1130,7 @@ class SsaInstructionSimplifier extends HBaseVisitor
value = other;
}
}
return new HFieldSet(field, receiver, value);
return new HFieldSet(_abstractValueDomain, field, receiver, value);
}
HInstruction visitInvokeClosure(HInvokeClosure node) {

View file

@ -42,7 +42,8 @@ class SsaBranchBuilder {
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;

View file

@ -258,7 +258,7 @@ class SsaTypePropagator extends HBaseVisitor implements OptimizationPhase {
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);
}

View file

@ -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 @@ abstract class AbstractValueDomain {
/// 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 @@ abstract class AbstractValueDomain {
/// 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);
}

View file

@ -6,7 +6,7 @@ library masks;
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 '../universe/world_builder.dart'
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 @@ class CommonMasks implements AbstractValueDomain {
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 @@ class CommonMasks implements AbstractValueDomain {
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);
}
}

View file

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