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

Side by Side Diff: pkg/compiler/lib/src/inferrer/builder_kernel.dart

Issue 3009693002: Handle int/double literals in inference (Closed)
Patch Set: Created 3 years, 3 months 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 unified diff | Download patch
OLDNEW
1 // Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a 2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file. 3 // BSD-style license that can be found in the LICENSE file.
4 4
5 import 'package:kernel/ast.dart' as ir; 5 import 'package:kernel/ast.dart' as ir;
6 6
7 import '../closure.dart'; 7 import '../closure.dart';
8 import '../common.dart'; 8 import '../common.dart';
9 import '../compiler.dart'; 9 import '../constants/constant_system.dart';
10 import '../elements/entities.dart'; 10 import '../elements/entities.dart';
11 import '../kernel/element_map.dart'; 11 import '../options.dart';
12 import '../types/constants.dart';
12 import '../universe/side_effects.dart' show SideEffects; 13 import '../universe/side_effects.dart' show SideEffects;
14 import '../world.dart';
13 import 'inferrer_engine.dart'; 15 import 'inferrer_engine.dart';
14 import 'locals_handler.dart'; 16 import 'locals_handler.dart';
15 import 'type_graph_nodes.dart'; 17 import 'type_graph_nodes.dart';
16 import 'type_system.dart'; 18 import 'type_system.dart';
17 19
18 /// [KernelTypeGraphBuilder] constructs a type-inference graph for a particular 20 /// [KernelTypeGraphBuilder] constructs a type-inference graph for a particular
19 /// element. 21 /// element.
20 /// 22 ///
21 /// Calling [run] will start the work of visiting the body of the code to 23 /// Calling [run] will start the work of visiting the body of the code to
22 /// construct a set of inference-nodes that abstractly represent what the code 24 /// construct a set of inference-nodes that abstractly represent what the code
23 /// is doing. 25 /// is doing.
24 class KernelTypeGraphBuilder extends ir.Visitor<TypeInformation> { 26 class KernelTypeGraphBuilder extends ir.Visitor<TypeInformation> {
25 final Compiler compiler; 27 final CompilerOptions _options;
26 final MemberEntity analyzedMember; 28 final ClosedWorld _closedWorld;
27 final ir.Node analyzedNode; 29 final ClosureDataLookup<ir.Node> _closureDataLookup;
28 final TypeSystem<ir.Node> types; 30 final InferrerEngine<ir.Node> _inferrer;
29 LocalsHandler locals; 31 final TypeSystem<ir.Node> _types;
30 final InferrerEngine<ir.Node> inferrer; 32 final MemberEntity _analyzedMember;
31 SideEffects sideEffects = new SideEffects.empty(); 33 final ir.Node _analyzedNode;
32 int loopLevel = 0; 34 LocalsHandler _locals;
33 bool get inLoop => loopLevel > 0;
34 TypeInformation returnType;
35 35
36 final Set<Local> capturedVariables = new Set<Local>(); 36 /// ignore: UNUSED_FIELD
37 SideEffects _sideEffects = new SideEffects.empty();
Siggi Cherem (dart-lang) 2017/08/28 22:34:57 nit: remove? I'm guessing you'll start using it in
Johnni Winther 2017/08/29 08:31:24 It wasn't added, just moved and renamed to be priv
38 int _loopLevel = 0;
37 39
38 KernelTypeGraphBuilder.internal(this.analyzedMember, this.inferrer, 40 /// ignore: UNUSED_ELEMENT
39 this.compiler, this.locals, this.analyzedNode) 41 bool get _inLoop => _loopLevel > 0;
40 : this.types = inferrer.types { 42 TypeInformation _returnType;
41 if (locals != null) return; 43
44 /// ignore: UNUSED_FIELD
45 final Set<Local> _capturedVariables = new Set<Local>();
46
47 KernelTypeGraphBuilder(
48 this._options,
49 this._closedWorld,
50 this._closureDataLookup,
51 this._inferrer,
52 this._analyzedMember,
53 this._analyzedNode,
54 [this._locals])
55 : this._types = _inferrer.types {
56 if (_locals != null) return;
42 57
43 FieldInitializationScope<ir.Node> fieldScope = 58 FieldInitializationScope<ir.Node> fieldScope =
44 analyzedNode is ir.Constructor 59 _analyzedNode is ir.Constructor
45 ? new FieldInitializationScope(types) 60 ? new FieldInitializationScope(_types)
46 : null; 61 : null;
47 locals = new LocalsHandler( 62 _locals = new LocalsHandler(
48 inferrer, types, compiler.options, analyzedNode, fieldScope); 63 _inferrer, _types, _options, _analyzedNode, fieldScope);
49 }
50
51 factory KernelTypeGraphBuilder(
52 MemberEntity element,
53 Compiler compiler,
54 KernelToElementMapForBuilding elementMap,
55 InferrerEngine<ir.Node> inferrer,
56 ir.TreeNode analyzedNode,
57 [LocalsHandler<ir.Node> handler]) {
58 return new KernelTypeGraphBuilder.internal(
59 element, inferrer, compiler, handler, analyzedNode);
60 } 64 }
61 65
62 TypeInformation run() { 66 TypeInformation run() {
63 if (analyzedMember.isField) { 67 if (_analyzedMember.isField) {
64 if (analyzedNode == null || analyzedNode is ir.NullLiteral) { 68 if (_analyzedNode == null || _analyzedNode is ir.NullLiteral) {
65 // Eagerly bailout, because computing the closure data only 69 // Eagerly bailout, because computing the closure data only
66 // works for functions and field assignments. 70 // works for functions and field assignments.
67 return types.nullType; 71 return _types.nullType;
68 } 72 }
69 } 73 }
70 74
71 // Update the locals that are boxed in [locals]. These locals will 75 // Update the locals that are boxed in [locals]. These locals will
72 // be handled specially, in that we are computing their LUB at 76 // be handled specially, in that we are computing their LUB at
73 // each update, and reading them yields the type that was found in a 77 // each update, and reading them yields the type that was found in a
74 // previous analysis of [outermostElement]. 78 // previous analysis of [outermostElement].
75 ClosureRepresentationInfo closureData = compiler 79 ClosureRepresentationInfo closureData =
76 .backendStrategy.closureDataLookup 80 _closureDataLookup.getClosureInfoForMember(_analyzedMember);
77 .getClosureInfoForMember(analyzedMember);
78 closureData.forEachCapturedVariable((variable, field) { 81 closureData.forEachCapturedVariable((variable, field) {
79 locals.setCaptured(variable, field); 82 _locals.setCaptured(variable, field);
80 }); 83 });
81 closureData.forEachBoxedVariable((variable, field) { 84 closureData.forEachBoxedVariable((variable, field) {
82 locals.setCapturedAndBoxed(variable, field); 85 _locals.setCapturedAndBoxed(variable, field);
83 }); 86 });
84 87
85 return analyzedNode.accept(this); 88 return _analyzedNode.accept(this);
86 } 89 }
87 90
88 void recordReturnType(TypeInformation type) { 91 void recordReturnType(TypeInformation type) {
89 FunctionEntity analyzedMethod = analyzedMember; 92 FunctionEntity analyzedMethod = _analyzedMember;
90 returnType = 93 _returnType =
91 inferrer.addReturnTypeForMethod(analyzedMethod, returnType, type); 94 _inferrer.addReturnTypeForMethod(analyzedMethod, _returnType, type);
92 } 95 }
93 96
94 void initializationIsIndefinite() { 97 void initializationIsIndefinite() {
95 MemberEntity member = analyzedMember; 98 MemberEntity member = _analyzedMember;
96 if (member is ConstructorEntity && member.isGenerativeConstructor) { 99 if (member is ConstructorEntity && member.isGenerativeConstructor) {
97 locals.fieldScope.isIndefinite = true; 100 _locals.fieldScope.isIndefinite = true;
98 } 101 }
99 } 102 }
100 103
101 TypeInformation visit(ir.Node node) { 104 TypeInformation visit(ir.Node node) {
102 return node == null ? null : node.accept(this); 105 return node == null ? null : node.accept(this);
103 } 106 }
104 107
105 @override 108 @override
106 TypeInformation visitFunctionNode(ir.FunctionNode node) { 109 TypeInformation visitFunctionNode(ir.FunctionNode node) {
107 // TODO(redemption): Handle constructors. 110 // TODO(redemption): Handle constructors.
108 // TODO(redemption): Handle native methods. 111 // TODO(redemption): Handle native methods.
109 // TODO(redemption): Set up parameters. 112 // TODO(redemption): Set up parameters.
110 visit(node.body); 113 visit(node.body);
111 switch (node.asyncMarker) { 114 switch (node.asyncMarker) {
112 case ir.AsyncMarker.Sync: 115 case ir.AsyncMarker.Sync:
113 if (returnType == null) { 116 if (_returnType == null) {
114 // No return in the body. 117 // No return in the body.
115 returnType = locals.seenReturnOrThrow 118 _returnType = _locals.seenReturnOrThrow
116 ? types.nonNullEmpty() // Body always throws. 119 ? _types.nonNullEmpty() // Body always throws.
117 : types.nullType; 120 : _types.nullType;
118 } else if (!locals.seenReturnOrThrow) { 121 } else if (!_locals.seenReturnOrThrow) {
119 // We haven'TypeInformation seen returns on all branches. So the metho d may 122 // We haven'TypeInformation seen returns on all branches. So the metho d may
120 // also return null. 123 // also return null.
121 recordReturnType(types.nullType); 124 recordReturnType(_types.nullType);
122 } 125 }
123 break; 126 break;
124 127
125 case ir.AsyncMarker.SyncStar: 128 case ir.AsyncMarker.SyncStar:
126 // TODO(asgerf): Maybe make a ContainerTypeMask for these? The type 129 // TODO(asgerf): Maybe make a ContainerTypeMask for these? The type
127 // contained is the method body's return type. 130 // contained is the method body's return type.
128 recordReturnType(types.syncStarIterableType); 131 recordReturnType(_types.syncStarIterableType);
129 break; 132 break;
130 133
131 case ir.AsyncMarker.Async: 134 case ir.AsyncMarker.Async:
132 recordReturnType(types.asyncFutureType); 135 recordReturnType(_types.asyncFutureType);
133 break; 136 break;
134 137
135 case ir.AsyncMarker.AsyncStar: 138 case ir.AsyncMarker.AsyncStar:
136 recordReturnType(types.asyncStarStreamType); 139 recordReturnType(_types.asyncStarStreamType);
137 break; 140 break;
138 case ir.AsyncMarker.SyncYielding: 141 case ir.AsyncMarker.SyncYielding:
139 failedAt( 142 failedAt(
140 analyzedMember, "Unexpected async marker: ${node.asyncMarker}"); 143 _analyzedMember, "Unexpected async marker: ${node.asyncMarker}");
141 break; 144 break;
142 } 145 }
143 return returnType; 146 return _returnType;
144 } 147 }
145 148
146 @override 149 @override
147 TypeInformation defaultExpression(ir.Expression expression) { 150 TypeInformation defaultExpression(ir.Expression expression) {
148 // TODO(efortuna): Remove when more is implemented. 151 // TODO(efortuna): Remove when more is implemented.
149 return types.dynamicType; 152 return _types.dynamicType;
150 } 153 }
151 154
152 @override 155 @override
153 TypeInformation visitNullLiteral(ir.NullLiteral literal) { 156 TypeInformation visitNullLiteral(ir.NullLiteral literal) {
154 return types.nullType; 157 return _types.nullType;
155 } 158 }
156 159
157 @override 160 @override
158 TypeInformation visitBlock(ir.Block block) { 161 TypeInformation visitBlock(ir.Block block) {
159 for (ir.Statement statement in block.statements) { 162 for (ir.Statement statement in block.statements) {
160 statement.accept(this); 163 statement.accept(this);
161 if (locals.aborts) break; 164 if (_locals.aborts) break;
162 } 165 }
163 return null; 166 return null;
164 } 167 }
165 168
166 @override 169 @override
167 TypeInformation visitListLiteral(ir.ListLiteral listLiteral) { 170 TypeInformation visitListLiteral(ir.ListLiteral listLiteral) {
168 // We only set the type once. We don't need to re-visit the children 171 // We only set the type once. We don't need to re-visit the children
169 // when re-analyzing the node. 172 // when re-analyzing the node.
170 return inferrer.concreteTypes.putIfAbsent(listLiteral, () { 173 return _inferrer.concreteTypes.putIfAbsent(listLiteral, () {
171 TypeInformation elementType; 174 TypeInformation elementType;
172 int length = 0; 175 int length = 0;
173 for (ir.Expression element in listLiteral.expressions) { 176 for (ir.Expression element in listLiteral.expressions) {
174 TypeInformation type = element.accept(this); 177 TypeInformation type = element.accept(this);
175 elementType = elementType == null 178 elementType = elementType == null
176 ? types.allocatePhi(null, null, type, isTry: false) 179 ? _types.allocatePhi(null, null, type, isTry: false)
177 : types.addPhiInput(null, elementType, type); 180 : _types.addPhiInput(null, elementType, type);
178 length++; 181 length++;
179 } 182 }
180 elementType = elementType == null 183 elementType = elementType == null
181 ? types.nonNullEmpty() 184 ? _types.nonNullEmpty()
182 : types.simplifyPhi(null, null, elementType); 185 : _types.simplifyPhi(null, null, elementType);
183 TypeInformation containerType = 186 TypeInformation containerType =
184 listLiteral.isConst ? types.constListType : types.growableListType; 187 listLiteral.isConst ? _types.constListType : _types.growableListType;
185 return types.allocateList( 188 return _types.allocateList(
186 containerType, listLiteral, analyzedMember, elementType, length); 189 containerType, listLiteral, _analyzedMember, elementType, length);
187 }); 190 });
188 } 191 }
189 192
190 @override 193 @override
191 TypeInformation visitReturnStatement(ir.ReturnStatement node) { 194 TypeInformation visitReturnStatement(ir.ReturnStatement node) {
192 ir.Node expression = node.expression; 195 ir.Node expression = node.expression;
193 recordReturnType( 196 recordReturnType(
194 expression == null ? types.nullType : expression.accept(this)); 197 expression == null ? _types.nullType : expression.accept(this));
195 locals.seenReturnOrThrow = true; 198 _locals.seenReturnOrThrow = true;
196 initializationIsIndefinite(); 199 initializationIsIndefinite();
197 return null; 200 return null;
198 } 201 }
202
203 @override
204 TypeInformation visitIntLiteral(ir.IntLiteral node) {
205 ConstantSystem constantSystem = _closedWorld.constantSystem;
206 // The JavaScript backend may turn this literal into a double at
207 // runtime.
208 return _types.getConcreteTypeFor(
209 computeTypeMask(_closedWorld, constantSystem.createInt(node.value)));
210 }
211
212 @override
213 TypeInformation visitDoubleLiteral(ir.DoubleLiteral node) {
214 ConstantSystem constantSystem = _closedWorld.constantSystem;
215 // The JavaScript backend may turn this literal into an integer at
216 // runtime.
217 return _types.getConcreteTypeFor(
218 computeTypeMask(_closedWorld, constantSystem.createDouble(node.value)));
219 }
199 } 220 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698