Index: pkg/compiler/lib/src/ssa/builder.dart |
diff --git a/pkg/compiler/lib/src/ssa/builder.dart b/pkg/compiler/lib/src/ssa/builder.dart |
index 3cb1c8246b7d9ae19b5968cbcfffd8543e427521..a26c26e90ff3e184a2a686b7ff3c74b81caf4ef9 100644 |
--- a/pkg/compiler/lib/src/ssa/builder.dart |
+++ b/pkg/compiler/lib/src/ssa/builder.dart |
@@ -141,7 +141,16 @@ class SsaBuilder extends ast.Visitor |
// used only for codegen, but currently we want to experiment using it for |
// code-analysis too. |
final CodegenRegistry registry; |
+ |
+ /// All results from the global type-inference analysis. |
final GlobalTypeInferenceResults inferenceResults; |
+ |
+ /// Results from the global type-inference analysis corresponding to the |
+ /// current element being visited. |
+ /// |
+ /// Invariant: this property is updated together with [resolvedAst]. |
+ GlobalTypeInferenceElementResult elementInferenceResults; |
+ |
final JavaScriptBackend backend; |
final ConstantSystem constantSystem; |
final RuntimeTypes rti; |
@@ -193,6 +202,8 @@ class SsaBuilder extends ast.Visitor |
this.inferenceResults = backend.compiler.globalInference.results { |
assert(target.isImplementation); |
compiler = backend.compiler; |
+ elementInferenceResults = _resultOf(target); |
+ assert(elementInferenceResults != null); |
graph.element = target; |
sourceElementStack.add(target); |
sourceInformationBuilder = |
@@ -234,6 +245,17 @@ class SsaBuilder extends ast.Visitor |
// implementation/declaration distinction. |
Element get sourceElement => sourceElementStack.last; |
+ /// Helper to retrieve global inference results for [element] with special |
+ /// care for `ConstructorBodyElement`s which don't exist at the time the |
+ /// global analysis run. |
+ /// |
+ /// Note: this helper is used selectively. When we know that we are in a |
+ /// context were we don't expect to see a constructor body element, we |
+ /// directly fetch the data from the global inference results. |
+ GlobalTypeInferenceElementResult _resultOf(AstElement element) => |
+ inferenceResults.resultOf( |
+ element is ConstructorBodyElementX ? element.constructor : element); |
+ |
bool get _checkOrTrustTypes => |
compiler.options.enableTypeAssertions || |
compiler.options.trustTypeAnnotations; |
@@ -436,7 +458,7 @@ class SsaBuilder extends ast.Visitor |
// A generative constructor body is not seen by global analysis, |
// so we should not query for its type. |
if (!element.isGenerativeConstructorBody) { |
- if (inferenceResults.throwsAlways(element)) { |
+ if (inferenceResults.resultOf(element).throwsAlways) { |
isReachable = false; |
return false; |
} |
@@ -568,12 +590,10 @@ class SsaBuilder extends ast.Visitor |
return inliningStack.isEmpty || inliningStack.last.allFunctionsCalledOnce; |
} |
- bool isFunctionCalledOnce(Element element) { |
- if (element is ConstructorBodyElement) { |
- // ConstructorBodyElements are not in the type inference graph. |
- return false; |
- } |
- return inferenceResults.isCalledOnce(element); |
+ bool isFunctionCalledOnce(element) { |
+ // ConstructorBodyElements are not in the type inference graph. |
+ if (element is ConstructorBodyElement) return false; |
+ return inferenceResults.resultOf(element).isCalledOnce; |
} |
bool isCalledOnce(Element element) { |
@@ -759,8 +779,8 @@ class SsaBuilder extends ast.Visitor |
} |
} |
- closeAndGotoExit(new HReturn(value, sourceInformationBuilder.buildReturn( |
- sourceInfoNode))); |
+ closeAndGotoExit(new HReturn( |
+ value, sourceInformationBuilder.buildReturn(sourceInfoNode))); |
return closeFunction(); |
} |
@@ -868,6 +888,7 @@ class SsaBuilder extends ast.Visitor |
returnLocal = state.oldReturnLocal; |
inTryStatement = state.inTryStatement; |
resolvedAst = state.oldResolvedAst; |
+ elementInferenceResults = state.oldElementInferenceResults; |
returnType = state.oldReturnType; |
assert(stack.isEmpty); |
stack = state.oldStack; |
@@ -1000,6 +1021,8 @@ class SsaBuilder extends ast.Visitor |
// Build the initializers in the context of the new constructor. |
ResolvedAst oldResolvedAst = resolvedAst; |
resolvedAst = callee.resolvedAst; |
+ final oldElementInferenceResults = elementInferenceResults; |
+ elementInferenceResults = inferenceResults.resultOf(callee); |
ClosureClassMap oldClosureData = localsHandler.closureData; |
ClosureClassMap newClosureData = |
compiler.closureToClassMapper.getClosureToClassMapping(resolvedAst); |
@@ -1010,6 +1033,7 @@ class SsaBuilder extends ast.Visitor |
buildInitializers(callee, constructorResolvedAsts, fieldValues); |
localsHandler.closureData = oldClosureData; |
resolvedAst = oldResolvedAst; |
+ elementInferenceResults = oldElementInferenceResults; |
}); |
} |
@@ -1172,11 +1196,14 @@ class SsaBuilder extends ast.Visitor |
ast.Node right = initializer; |
ResolvedAst savedResolvedAst = resolvedAst; |
resolvedAst = fieldResolvedAst; |
+ final oldElementInferenceResults = elementInferenceResults; |
+ elementInferenceResults = inferenceResults.resultOf(member); |
// In case the field initializer uses closures, run the |
// closure to class mapper. |
compiler.closureToClassMapper.getClosureToClassMapping(resolvedAst); |
inlinedFrom(fieldResolvedAst, () => right.accept(this)); |
resolvedAst = savedResolvedAst; |
+ elementInferenceResults = oldElementInferenceResults; |
fieldValues[member] = pop(); |
} |
}); |
@@ -2069,7 +2096,7 @@ class SsaBuilder extends ast.Visitor |
} |
pushInvokeDynamic(node, elements.getSelector(node), |
- inferenceResults.typeOfSend(node, elements), [operand], |
+ elementInferenceResults.typeOfSend(node), [operand], |
sourceInformation: sourceInformationBuilder.buildGeneric(node)); |
} |
@@ -2100,7 +2127,7 @@ class SsaBuilder extends ast.Visitor |
visitAndPop(left), |
visitAndPop(right), |
elements.getSelector(node), |
- inferenceResults.typeOfSend(node, elements), |
+ elementInferenceResults.typeOfSend(node), |
node, |
sourceInformation: |
sourceInformationBuilder.buildGeneric(node.selector)); |
@@ -2263,7 +2290,7 @@ class SsaBuilder extends ast.Visitor |
void generateDynamicGet(ast.Send node) { |
HInstruction receiver = generateInstanceSendReceiver(node); |
generateInstanceGetterWithCompiledReceiver(node, elements.getSelector(node), |
- inferenceResults.typeOfSend(node, elements), receiver); |
+ elementInferenceResults.typeOfSend(node), receiver); |
} |
/// Generate a closurization of the static or top level [function]. |
@@ -2312,7 +2339,7 @@ class SsaBuilder extends ast.Visitor |
generateInstanceGetterWithCompiledReceiver( |
node, |
elements.getSelector(node), |
- inferenceResults.typeOfSend(node, elements), |
+ elementInferenceResults.typeOfSend(node), |
expression); |
}); |
} |
@@ -2377,7 +2404,7 @@ class SsaBuilder extends ast.Visitor |
if (selector == null) { |
assert(send != null); |
selector = elements.getSelector(send); |
- mask ??= inferenceResults.typeOfSend(send, elements); |
+ mask ??= elementInferenceResults.typeOfSend(send); |
} |
if (location == null) { |
assert(send != null); |
@@ -2648,7 +2675,7 @@ class SsaBuilder extends ast.Visitor |
void _generateDynamicSend(ast.Send node, HInstruction receiver) { |
Selector selector = elements.getSelector(node); |
- TypeMask mask = inferenceResults.typeOfSend(node, elements); |
+ TypeMask mask = elementInferenceResults.typeOfSend(node); |
SourceInformation sourceInformation = |
sourceInformationBuilder.buildCall(node, node.selector); |
@@ -4427,7 +4454,7 @@ class SsaBuilder extends ast.Visitor |
receiver, |
rhs, |
elements.getOperatorSelectorInComplexSendSet(node), |
- inferenceResults.typeOfOperator(node, elements), |
+ elementInferenceResults.typeOfOperator(node), |
node, |
sourceInformation: |
sourceInformationBuilder.buildGeneric(node.assignmentOperator)); |
@@ -4790,7 +4817,7 @@ class SsaBuilder extends ast.Visitor |
} |
pushInvokeDynamic(node, elements.getGetterSelectorInComplexSendSet(node), |
- inferenceResults.typeOfGetter(node, elements), [receiver, index]); |
+ elementInferenceResults.typeOfGetter(node), [receiver, index]); |
HInstruction getterInstruction = pop(); |
if (node.isIfNullAssignment) { |
// Compile x[i] ??= e as: |
@@ -4805,7 +4832,7 @@ class SsaBuilder extends ast.Visitor |
pushInvokeDynamic( |
node, |
elements.getSelector(node), |
- inferenceResults.typeOfSend(node, elements), |
+ elementInferenceResults.typeOfSend(node), |
[receiver, index, value]); |
pop(); |
stack.add(value); |
@@ -4813,11 +4840,8 @@ class SsaBuilder extends ast.Visitor |
} else { |
handleComplexOperatorSend(node, getterInstruction, arguments); |
HInstruction value = pop(); |
- pushInvokeDynamic( |
- node, |
- elements.getSelector(node), |
- inferenceResults.typeOfSend(node, elements), |
- [receiver, index, value]); |
+ pushInvokeDynamic(node, elements.getSelector(node), |
+ elementInferenceResults.typeOfSend(node), [receiver, index, value]); |
pop(); |
if (node.isPostfix) { |
stack.add(getterInstruction); |
@@ -5021,7 +5045,7 @@ class SsaBuilder extends ast.Visitor |
generateInstanceGetterWithCompiledReceiver( |
node, |
elements.getGetterSelectorInComplexSendSet(node), |
- inferenceResults.typeOfGetter(node, elements), |
+ elementInferenceResults.typeOfGetter(node), |
receiver); |
HInstruction getterInstruction = pop(); |
if (node.isIfNullAssignment) { |
@@ -5484,7 +5508,7 @@ class SsaBuilder extends ast.Visitor |
} |
_inferredTypeOfNewList(ast.Node node) => |
- inferenceResults.typeOfNewList(sourceElement, node) ?? |
+ _resultOf(sourceElement).typeOfNewList(node) ?? |
compiler.commonMasks.dynamicType; |
visitConditional(ast.Conditional node) { |
@@ -5580,7 +5604,7 @@ class SsaBuilder extends ast.Visitor |
HInstruction buildCondition() { |
Selector selector = Selectors.moveNext; |
- TypeMask mask = inferenceResults.typeOfIteratorMoveNext(node, elements); |
+ TypeMask mask = elementInferenceResults.typeOfIteratorMoveNext(node); |
pushInvokeDynamic(node, selector, mask, [streamIterator]); |
HInstruction future = pop(); |
push(new HAwait( |
@@ -5592,8 +5616,7 @@ class SsaBuilder extends ast.Visitor |
void buildBody() { |
Selector call = Selectors.current; |
- TypeMask callMask = |
- inferenceResults.typeOfIteratorCurrent(node, elements); |
+ TypeMask callMask = elementInferenceResults.typeOfIteratorCurrent(node); |
pushInvokeDynamic(node, call, callMask, [streamIterator]); |
ast.Node identifier = node.declaredIdentifier; |
@@ -5602,7 +5625,7 @@ class SsaBuilder extends ast.Visitor |
HInstruction value = pop(); |
if (identifier.asSend() != null && |
Elements.isInstanceSend(identifier, elements)) { |
- TypeMask mask = inferenceResults.typeOfSend(identifier, elements); |
+ TypeMask mask = elementInferenceResults.typeOfSend(identifier); |
HInstruction receiver = generateInstanceSendReceiver(identifier); |
assert(receiver != null); |
generateInstanceSetterWithCompiledReceiver(null, receiver, value, |
@@ -5641,7 +5664,7 @@ class SsaBuilder extends ast.Visitor |
// method is inlined. We would require full scalar replacement in that |
// case. |
- TypeMask mask = inferenceResults.typeOfIterator(node, elements); |
+ TypeMask mask = elementInferenceResults.typeOfIterator(node); |
ClosedWorld closedWorld = compiler.closedWorld; |
if (mask != null && |
@@ -5666,7 +5689,7 @@ class SsaBuilder extends ast.Visitor |
void buildInitializer() { |
Selector selector = Selectors.iterator; |
- TypeMask mask = inferenceResults.typeOfIterator(node, elements); |
+ TypeMask mask = elementInferenceResults.typeOfIterator(node); |
visit(node.expression); |
HInstruction receiver = pop(); |
pushInvokeDynamic(node, selector, mask, [receiver]); |
@@ -5675,14 +5698,14 @@ class SsaBuilder extends ast.Visitor |
HInstruction buildCondition() { |
Selector selector = Selectors.moveNext; |
- TypeMask mask = inferenceResults.typeOfIteratorMoveNext(node, elements); |
+ TypeMask mask = elementInferenceResults.typeOfIteratorMoveNext(node); |
pushInvokeDynamic(node, selector, mask, [iterator]); |
return popBoolified(); |
} |
void buildBody() { |
Selector call = Selectors.current; |
- TypeMask mask = inferenceResults.typeOfIteratorCurrent(node, elements); |
+ TypeMask mask = elementInferenceResults.typeOfIteratorCurrent(node); |
pushInvokeDynamic(node, call, mask, [iterator]); |
buildAssignLoopVariable(node, pop()); |
visit(node.body); |
@@ -5699,7 +5722,7 @@ class SsaBuilder extends ast.Visitor |
if (identifier.asSend() != null && |
Elements.isInstanceSend(identifier, elements)) { |
- TypeMask mask = inferenceResults.typeOfSend(identifier, elements); |
+ TypeMask mask = elementInferenceResults.typeOfSend(identifier); |
HInstruction receiver = generateInstanceSendReceiver(identifier); |
assert(receiver != null); |
generateInstanceSetterWithCompiledReceiver(null, receiver, value, |
@@ -6638,8 +6661,10 @@ class SsaBuilder extends ast.Visitor |
stack, |
localsHandler, |
inTryStatement, |
- allInlinedFunctionsCalledOnce && isFunctionCalledOnce(function)); |
+ isCalledOnce(function), |
+ elementInferenceResults); |
resolvedAst = functionResolvedAst; |
+ elementInferenceResults = _resultOf(function); |
inliningStack.add(state); |
// Setting up the state of the (AST) builder is performed even when the |
@@ -6960,6 +6985,7 @@ class AstInliningState extends InliningState { |
final LocalsHandler oldLocalsHandler; |
final bool inTryStatement; |
final bool allFunctionsCalledOnce; |
+ final GlobalTypeInferenceElementResult oldElementInferenceResults; |
AstInliningState( |
FunctionElement function, |
@@ -6969,7 +6995,8 @@ class AstInliningState extends InliningState { |
this.oldStack, |
this.oldLocalsHandler, |
this.inTryStatement, |
- this.allFunctionsCalledOnce) |
+ this.allFunctionsCalledOnce, |
+ this.oldElementInferenceResults) |
: super(function); |
} |