mirror of
https://github.com/dart-lang/sdk
synced 2024-10-03 06:21:30 +00:00
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:
parent
d3c7df35b4
commit
51fa3f3b0c
|
@ -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) {
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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));
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
Loading…
Reference in a new issue