Index: pkg/compiler/lib/src/ssa/kernel_ast_adapter.dart |
diff --git a/pkg/compiler/lib/src/ssa/kernel_ast_adapter.dart b/pkg/compiler/lib/src/ssa/kernel_ast_adapter.dart |
index 7f5b6f05f79fd0f4449052372e0ed627fbd18e6d..86aee00033e96b6efae6aca5aa52479642bf262c 100644 |
--- a/pkg/compiler/lib/src/ssa/kernel_ast_adapter.dart |
+++ b/pkg/compiler/lib/src/ssa/kernel_ast_adapter.dart |
@@ -15,9 +15,12 @@ import '../kernel/kernel.dart'; |
import '../resolution/tree_elements.dart'; |
import '../tree/tree.dart' as ast; |
import '../types/masks.dart'; |
+import '../types/types.dart'; |
import '../universe/call_structure.dart'; |
import '../universe/selector.dart'; |
import '../universe/side_effects.dart'; |
+import '../world.dart'; |
+import 'locals_handler.dart'; |
import 'types.dart'; |
/// A helper class that abstracts all accesses of the AST from Kernel nodes. |
@@ -29,6 +32,8 @@ class KernelAstAdapter { |
final ResolvedAst _resolvedAst; |
final Map<ir.Node, ast.Node> _nodeToAst; |
final Map<ir.Node, Element> _nodeToElement; |
+ final Map<ir.VariableDeclaration, SyntheticLocal> _syntheticLocals = |
+ <ir.VariableDeclaration, SyntheticLocal>{}; |
DartTypeConverter _typeConverter; |
KernelAstAdapter(this.kernel, this._backend, this._resolvedAst, |
@@ -54,6 +59,8 @@ class KernelAstAdapter { |
Compiler get _compiler => _backend.compiler; |
TreeElements get elements => _resolvedAst.elements; |
+ GlobalTypeInferenceResults get _inferenceResults => |
+ _compiler.globalInference.results; |
ConstantValue getConstantForSymbol(ir.SymbolLiteral node) { |
ast.Node astNode = getNode(node); |
@@ -76,6 +83,15 @@ class KernelAstAdapter { |
return result; |
} |
+ Local getLocal(ir.VariableDeclaration variable) { |
+ // If this is a synthetic local, return the synthetic local |
+ if (variable.name == null) { |
+ return _syntheticLocals.putIfAbsent( |
+ variable, () => new SyntheticLocal("x", null)); |
+ } |
+ return getElement(variable) as LocalElement; |
+ } |
+ |
bool getCanThrow(ir.Node procedure) { |
FunctionElement function = getElement(procedure); |
return !_compiler.closedWorld.getCannotThrow(function); |
@@ -101,8 +117,15 @@ class KernelAstAdapter { |
name.name, name.isPrivate ? getElement(name.library) : null); |
} |
- // TODO(het): Create the selector directly from the invocation |
- Selector getSelector(ir.InvocationExpression invocation) { |
+ Selector getSelector(ir.Expression node) { |
+ if (node is ir.PropertyGet) return getGetterSelector(node); |
+ if (node is ir.InvocationExpression) return getInvocationSelector(node); |
+ _compiler.reporter.internalError(getNode(node), |
+ "Can only get the selector for a property get or an invocation."); |
+ return null; |
+ } |
+ |
+ Selector getInvocationSelector(ir.InvocationExpression invocation) { |
Name name = getName(invocation.name); |
SelectorKind kind; |
if (Elements.isOperatorName(invocation.name.name)) { |
@@ -126,28 +149,75 @@ class KernelAstAdapter { |
return new Selector.getter(name); |
} |
- TypeMask typeOfInvocation(ir.MethodInvocation invocation) { |
- return _compiler.globalInference.results |
- .typeOfSend(getNode(invocation), elements); |
+ TypeMask typeOfInvocation(ir.Expression send) { |
+ return _inferenceResults.typeOfSend(getNode(send), elements); |
} |
TypeMask typeOfGet(ir.PropertyGet getter) { |
- return _compiler.globalInference.results |
- .typeOfSend(getNode(getter), elements); |
+ return _inferenceResults.typeOfSend(getNode(getter), elements); |
} |
- TypeMask inferredTypeOf(ir.Member node) { |
- return TypeMaskFactory.inferredTypeForElement(getElement(node), _compiler); |
+ TypeMask typeOfSend(ir.Expression send) { |
+ assert(send is ir.InvocationExpression || send is ir.PropertyGet); |
+ return _inferenceResults.typeOfSend(getNode(send), elements); |
} |
- TypeMask selectorTypeOf(ir.MethodInvocation invocation) { |
- return TypeMaskFactory.inferredTypeForSelector( |
- getSelector(invocation), typeOfInvocation(invocation), _compiler); |
+ TypeMask typeOfNewList(Element owner, ir.ListLiteral listLiteral) { |
+ return _inferenceResults.typeOfNewList(owner, getNode(listLiteral)) ?? |
+ _compiler.commonMasks.dynamicType; |
+ } |
+ |
+ TypeMask typeOfIterator(ir.ForInStatement forInStatement) { |
+ return _inferenceResults.typeOfIterator(getNode(forInStatement), elements); |
+ } |
+ |
+ TypeMask typeOfIteratorCurrent(ir.ForInStatement forInStatement) { |
+ return _inferenceResults.typeOfIteratorCurrent( |
+ getNode(forInStatement), elements); |
+ } |
+ |
+ TypeMask typeOfIteratorMoveNext(ir.ForInStatement forInStatement) { |
+ return _inferenceResults.typeOfIteratorMoveNext( |
+ getNode(forInStatement), elements); |
+ } |
+ |
+ bool isJsIndexableIterator(ir.ForInStatement forInStatement) { |
+ TypeMask mask = typeOfIterator(forInStatement); |
+ ClosedWorld closedWorld = _compiler.closedWorld; |
+ return mask != null && |
+ mask.satisfies(_backend.helpers.jsIndexableClass, closedWorld) && |
+ // String is indexable but not iterable. |
+ !mask.satisfies(_backend.helpers.jsStringClass, closedWorld); |
+ } |
+ |
+ bool isFixedLength(TypeMask mask) { |
+ ClosedWorld closedWorld = _compiler.closedWorld; |
+ JavaScriptBackend backend = _compiler.backend; |
+ if (mask.isContainer && (mask as ContainerTypeMask).length != null) { |
+ // A container on which we have inferred the length. |
+ return true; |
+ } |
+ // TODO(sra): Recognize any combination of fixed length indexables. |
+ if (mask.containsOnly(backend.helpers.jsFixedArrayClass) || |
+ mask.containsOnly(backend.helpers.jsUnmodifiableArrayClass) || |
+ mask.containsOnlyString(closedWorld) || |
+ backend.isTypedArray(mask)) { |
+ return true; |
+ } |
+ return false; |
} |
- TypeMask selectorGetterTypeOf(ir.PropertyGet getter) { |
+ TypeMask inferredIndexType(ir.ForInStatement forInStatement) { |
return TypeMaskFactory.inferredTypeForSelector( |
- getGetterSelector(getter), typeOfGet(getter), _compiler); |
+ new Selector.index(), typeOfIterator(forInStatement), _compiler); |
+ } |
+ |
+ TypeMask inferredTypeOf(ir.Member node) { |
+ return TypeMaskFactory.inferredTypeForElement(getElement(node), _compiler); |
+ } |
+ |
+ TypeMask selectorTypeOf(Selector selector, TypeMask mask) { |
+ return TypeMaskFactory.inferredTypeForSelector(selector, mask, _compiler); |
} |
ConstantValue getConstantFor(ir.Node node) { |
@@ -159,12 +229,11 @@ class KernelAstAdapter { |
} |
bool isIntercepted(ir.Node node) { |
- Selector selector; |
- if (node is ir.PropertyGet) { |
- selector = getGetterSelector(node); |
- } else { |
- selector = getSelector(node); |
- } |
+ Selector selector = getSelector(node); |
+ return _backend.isInterceptedSelector(selector); |
+ } |
+ |
+ bool isInterceptedSelector(Selector selector) { |
return _backend.isInterceptedSelector(selector); |
} |
@@ -177,6 +246,15 @@ class KernelAstAdapter { |
ir.Procedure get mapLiteralConstructorEmpty => |
kernel.functions[_backend.helpers.mapLiteralConstructorEmpty]; |
+ Element get jsIndexableLength => _backend.helpers.jsIndexableLength; |
+ |
+ ir.Procedure get checkConcurrentModificationError => |
+ kernel.functions[_backend.helpers.checkConcurrentModificationError]; |
+ |
+ TypeMask get checkConcurrentModificationErrorReturnType => |
+ TypeMaskFactory.inferredReturnTypeForElement( |
+ _backend.helpers.checkConcurrentModificationError, _compiler); |
+ |
DartType getDartType(ir.DartType type) { |
return type.accept(_typeConverter); |
} |