Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(234)

Unified Diff: pkg/compiler/lib/src/types/types.dart

Issue 2468303003: dart2js: move type-mask intermediate data from tree-elements into the global (Closed)
Patch Set: Created 4 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: pkg/compiler/lib/src/types/types.dart
diff --git a/pkg/compiler/lib/src/types/types.dart b/pkg/compiler/lib/src/types/types.dart
index ad890dc6c79f6aaaee44a7880f2eb00d1abbeba8..f55ec95bfbe3201ab99d08a127033d4c3a985df4 100644
--- a/pkg/compiler/lib/src/types/types.dart
+++ b/pkg/compiler/lib/src/types/types.dart
@@ -7,20 +7,165 @@ library types;
import '../common/tasks.dart' show CompilerTask;
import '../compiler.dart' show Compiler;
import '../elements/elements.dart';
-import '../inferrer/type_graph_inferrer.dart' show TypeGraphInferrer;
+import '../inferrer/type_graph_inferrer.dart'
+ show TypeGraphInferrer, TypeInformationSystem;
import '../tree/tree.dart';
import '../resolution/tree_elements.dart';
import '../universe/selector.dart' show Selector;
+import '../util/util.dart' show Maplet;
import 'masks.dart';
export 'masks.dart';
+/// Results about a single element (e.g. a method, parameter, or field)
+/// produced by the global type-inference algorithm.
+///
+/// All queries in this class may contain results that assume whole-program
+/// closed-world semantics. Any [TypeMask] for an element or node that we return
+/// was inferred to be a "guaranteed type", that means, it is a type that we
+/// can prove to be correct for all executions of the program.
Johnni Winther 2016/11/03 08:50:21 Add `Thus the trivial inference will return false
Siggi Cherem (dart-lang) 2016/11/03 21:12:15 Done.
+abstract class GlobalTypeInferenceElementResult {
+ /// Whether the method element associated with this result always throws.
+ bool get throwsAlways;
+
+ /// Whether the element associated with this result is only called once in one
+ /// location in the entire program.
+ bool get isCalledOnce;
+
+ /// The inferred type when this result belongs to a parameter or field
+ /// element, null otherwise.
+ TypeMask get type;
+
+ /// The inferred return type when this result belongs to a function element.
+ TypeMask get returnType;
+
+ /// Returns the type of a list allocation [node] (which can be a list
+ /// literal or a list new expression).
+ TypeMask typeOfNewList(Node node);
+
+ /// Returns the type of a send [node].
+ TypeMask typeOfSend(Node node);
+
+ /// Returns the type of the operator of a complex send-set [node], for
+ /// example, the type of `+` in `a += b`.
+ TypeMask typeOfGetter(SendSet node);
+
+ /// Returns the type of the getter in a complex send-set [node], for example,
+ /// the type of the `a.f` getter in `a.f += b`.
+ TypeMask typeOfOperator(SendSet node);
+
+ /// Returns the type of the iterator in a [loop].
+ TypeMask typeOfIterator(ForIn node);
+
+ /// Returns the type of the `moveNext` call of an iterator in a [loop].
+ TypeMask typeOfIteratorMoveNext(ForIn node);
+
+ /// Returns the type of the `current` getter of an iterator in a [loop].
+ TypeMask typeOfIteratorCurrent(ForIn node);
+}
+
+class GlobalTypeInferenceElementResultImpl
+ implements GlobalTypeInferenceElementResult {
+ // TODO(sigmund): delete, store data directly here.
+ final Element _owner;
+
+ // TODO(sigmund): split - stop using _data after inference is done.
+ final GlobalTypeInferenceElementData _data;
+
+ // TODO(sigmund): store relevant data & drop reference to inference engine.
+ final TypesInferrer _inferrer;
+ final bool _isJsInterop;
+ final TypeMask _dynamic;
+
+ GlobalTypeInferenceElementResultImpl(this._owner, this._data, this._inferrer,
+ this._isJsInterop, this._dynamic);
+
+ bool get isCalledOnce => _inferrer.isCalledOnce(_owner);
+
+ TypeMask get returnType =>
+ _isJsInterop ? _dynamic : _inferrer.getReturnTypeOfElement(_owner);
+
+ TypeMask get type =>
+ _isJsInterop ? _dynamic : _inferrer.getTypeOfElement(_owner);
+
+ bool get throwsAlways {
+ TypeMask mask = this.returnType;
+ // Always throws if the return type was inferred to be non-null empty.
+ return mask != null && mask.isEmpty;
+ }
+
+ TypeMask typeOfNewList(Node node) =>
+ _inferrer.getTypeForNewList(_owner, node);
+
+ TypeMask typeOfSend(Node node) => _data?.typeOfSend(node);
+ TypeMask typeOfGetter(SendSet node) => _data?.typeOfGetter(node);
+ TypeMask typeOfOperator(SendSet node) => _data?.typeOfOperator(node);
+ TypeMask typeOfIterator(ForIn node) => _data?.typeOfIterator(node);
+ TypeMask typeOfIteratorMoveNext(ForIn node) =>
+ _data?.typeOfIteratorMoveNext(node);
+ TypeMask typeOfIteratorCurrent(ForIn node) =>
+ _data?.typeOfIteratorCurrent(node);
+}
+
+/// Internal data used during type-inference to store intermediate results about
+/// a single element.
+class GlobalTypeInferenceElementData {
Siggi Cherem (dart-lang) 2016/11/03 01:03:38 I expect this will move under the inferrer, but I'
+ Map<Object, TypeMask> _typeMasks;
+
+ TypeMask _get(Object node) => _typeMasks != null ? _typeMasks[node] : null;
+ void _set(Object node, TypeMask mask) {
+ _typeMasks ??= new Maplet<Object, TypeMask>();
+ _typeMasks[node] = mask;
+ }
+
+ TypeMask typeOfSend(Node node) => _get(node);
+ TypeMask typeOfGetter(SendSet node) => _get(node.selector);
+ TypeMask typeOfOperator(SendSet node) => _get(node.assignmentOperator);
+
+ void setTypeMask(Node node, TypeMask mask) {
+ _set(node, mask);
+ }
+
+ void setGetterTypeMaskInComplexSendSet(SendSet node, TypeMask mask) {
+ _set(node.selector, mask);
+ }
+
+ void setOperatorTypeMaskInComplexSendSet(SendSet node, TypeMask mask) {
+ _set(node.assignmentOperator, mask);
+ }
+
+ // TODO(sigmund): clean up. We store data about 3 selectors for "for in"
+ // nodes: the iterator, move-next, and current element. Because our map keys
+ // are nodes, we need to fabricate different keys to keep these selectors
+ // separate. The current implementation does this by using
+ // children of the for-in node (these children were picked arbitrarily).
+
+ TypeMask typeOfIterator(ForIn node) => _get(node);
+
+ TypeMask typeOfIteratorMoveNext(ForIn node) => _get(node.forToken);
+
+ TypeMask typeOfIteratorCurrent(ForIn node) => _get(node.inToken);
+
+ void setIteratorTypeMask(ForIn node, TypeMask mask) {
+ _set(node, mask);
+ }
+
+ void setMoveNextTypeMask(ForIn node, TypeMask mask) {
+ _set(node.forToken, mask);
+ }
+
+ void setCurrentTypeMask(ForIn node, TypeMask mask) {
+ _set(node.inToken, mask);
+ }
+}
+
/// API to interact with the global type-inference engine.
abstract class TypesInferrer {
void analyzeMain(Element element);
TypeMask getReturnTypeOfElement(Element element);
TypeMask getTypeOfElement(Element element);
TypeMask getTypeForNewList(Element owner, Node node);
+
Johnni Winther 2016/11/03 08:50:21 Remove extra line?
Siggi Cherem (dart-lang) 2016/11/03 21:12:15 Done.
TypeMask getTypeOfSelector(Selector selector, TypeMask mask);
void clear();
bool isCalledOnce(Element element);
@@ -35,91 +180,37 @@ abstract class TypesInferrer {
/// can prove to be correct for all executions of the program.
class GlobalTypeInferenceResults {
// TODO(sigmund): store relevant data & drop reference to inference engine.
- final TypesInferrer _inferrer;
+ final TypeGraphInferrer _inferrer;
final Compiler compiler;
final TypeMask dynamicType;
-
- GlobalTypeInferenceResults(this._inferrer, this.compiler, CommonMasks masks)
- : dynamicType = masks.dynamicType;
-
- /// Returns the type of a parameter or field [element], if any.
- TypeMask typeOf(Element element) {
- // TODO(24489): trust some JsInterop types.
- if (compiler.backend.isJsInterop(element)) return dynamicType;
- return _inferrer.getTypeOfElement(element);
+ final Map<Element, GlobalTypeInferenceElementResult> _elementResults = {};
+
+ GlobalTypeInferenceElementResult resultOf(AstElement element) {
Johnni Winther 2016/11/03 08:50:21 Add a TODO to (at some point in the future) fail i
Siggi Cherem (dart-lang) 2016/11/03 21:12:15 Done.
+ return _elementResults.putIfAbsent(
+ element,
+ () => new GlobalTypeInferenceElementResultImpl(
+ element,
+ _inferrer.inferrer.inTreeData[element],
+ _inferrer,
+ compiler.backend.isJsInterop(element),
+ dynamicType));
}
- /// Returns the return type of a method or function [element].
- TypeMask returnTypeOf(Element element) {
- // TODO(24489): trust some JsInterop types.
- if (compiler.backend.isJsInterop(element)) return dynamicType;
- return _inferrer.getReturnTypeOfElement(element);
- }
+ GlobalTypeInferenceResults(this._inferrer, this.compiler, CommonMasks masks,
+ TypeInformationSystem types)
+ : dynamicType = masks.dynamicType;
/// Returns the type of a [selector] when applied to a receiver with the given
/// type [mask].
TypeMask typeOfSelector(Selector selector, TypeMask mask) =>
_inferrer.getTypeOfSelector(selector, mask);
- /// Returns whether the method [element] always throws.
- bool throwsAlways(Element element) {
- // We know the element always throws if the return type was inferred to be
- // non-null empty.
- TypeMask returnType = returnTypeOf(element);
- return returnType != null && returnType.isEmpty;
- }
-
- /// Returns whether [element] is only called once in the entire program.
- bool isCalledOnce(Element element) => _inferrer.isCalledOnce(element);
-
- // TODO(sigmund): introduce a new class [ElementInferenceResult] that can be
- // used to collect any information that is specific about the body within a
- // single element (basically everything below this line). We could consider
- // moving some of the functions above too, for example:
- // results.throwsAlways(element)
- // could become:
- // results[element].alwaysThrows;
- //
-
- /// Returns the type of a list allocation [node] occuring within [owner].
- ///
- /// [node] can be a list literal or a list new expression.
- TypeMask typeOfNewList(Element owner, Node node) =>
- _inferrer.getTypeForNewList(owner, node);
-
/// Returns whether a fixed-length constructor call goes through a growable
/// check.
+ // TODO(sigmund): move into the result of the element containing such
+ // constructor call.
bool isFixedArrayCheckedForGrowable(Node ctorCall) =>
_inferrer.isFixedArrayCheckedForGrowable(ctorCall);
-
- /// Returns the type of a send [node].
- TypeMask typeOfSend(
- Node node,
- // TODO(sigmund): move inference data out of TreeElements
- TreeElements elements) =>
- elements.getTypeMask(node);
-
- /// Returns the type of the operator of a complex send-set [node], for
- /// example, the type of `+` in `a += b`.
- TypeMask typeOfOperator(Send node, TreeElements elements) =>
- elements.getOperatorTypeMaskInComplexSendSet(node);
-
- /// Returns the type of the getter in a complex send-set [node], for example,
- /// the type of the `a.f` getter in `a.f += b`.
- TypeMask typeOfGetter(node, elements) =>
- elements.getGetterTypeMaskInComplexSendSet(node);
-
- /// Returns the type of the iterator in a [loop].
- TypeMask typeOfIterator(ForIn loop, elements) =>
- elements.getIteratorTypeMask(loop);
-
- /// Returns the type of the `moveNext` call of an iterator in a [loop].
- TypeMask typeOfIteratorMoveNext(ForIn loop, elements) =>
- elements.getMoveNextTypeMask(loop);
-
- /// Returns the type of the `current` getter of an iterator in a [loop].
- TypeMask typeOfIteratorCurrent(ForIn node, elements) =>
- elements.getCurrentTypeMask(node);
}
/// Global analysis that infers concrete types.
@@ -128,7 +219,7 @@ class GlobalTypeInferenceTask extends CompilerTask {
final String name = 'Type inference';
final Compiler compiler;
- TypesInferrer typesInferrer;
+ TypeGraphInferrer typesInferrer;
CommonMasks masks;
GlobalTypeInferenceResults results;
@@ -144,7 +235,8 @@ class GlobalTypeInferenceTask extends CompilerTask {
measure(() {
typesInferrer.analyzeMain(mainElement);
typesInferrer.clear();
- results = new GlobalTypeInferenceResults(typesInferrer, compiler, masks);
+ results = new GlobalTypeInferenceResults(
+ typesInferrer, compiler, masks, typesInferrer.inferrer.types);
});
}
}

Powered by Google App Engine
This is Rietveld 408576698