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

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

Issue 3009693002: Handle int/double literals in inference (Closed)
Patch Set: Updated cf. comments 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 TypeInformation _returnType;
37 final Set<Local> _capturedVariables = new Set<Local>();
37 38
38 KernelTypeGraphBuilder.internal(this.analyzedMember, this.inferrer, 39 KernelTypeGraphBuilder(
39 this.compiler, this.locals, this.analyzedNode) 40 this._options,
40 : this.types = inferrer.types { 41 this._closedWorld,
41 if (locals != null) return; 42 this._closureDataLookup,
43 this._inferrer,
44 this._analyzedMember,
45 this._analyzedNode,
46 [this._locals])
47 : this._types = _inferrer.types {
48 if (_locals != null) return;
42 49
43 FieldInitializationScope<ir.Node> fieldScope = 50 FieldInitializationScope<ir.Node> fieldScope =
44 analyzedNode is ir.Constructor 51 _analyzedNode is ir.Constructor
45 ? new FieldInitializationScope(types) 52 ? new FieldInitializationScope(_types)
46 : null; 53 : null;
47 locals = new LocalsHandler( 54 _locals = new LocalsHandler(
48 inferrer, types, compiler.options, analyzedNode, fieldScope); 55 _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 } 56 }
61 57
62 TypeInformation run() { 58 TypeInformation run() {
63 if (analyzedMember.isField) { 59 if (_analyzedMember.isField) {
64 if (analyzedNode == null || analyzedNode is ir.NullLiteral) { 60 if (_analyzedNode == null || _analyzedNode is ir.NullLiteral) {
65 // Eagerly bailout, because computing the closure data only 61 // Eagerly bailout, because computing the closure data only
66 // works for functions and field assignments. 62 // works for functions and field assignments.
67 return types.nullType; 63 return _types.nullType;
68 } 64 }
69 } 65 }
70 66
71 // Update the locals that are boxed in [locals]. These locals will 67 // Update the locals that are boxed in [locals]. These locals will
72 // be handled specially, in that we are computing their LUB at 68 // 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 69 // each update, and reading them yields the type that was found in a
74 // previous analysis of [outermostElement]. 70 // previous analysis of [outermostElement].
75 ClosureRepresentationInfo closureData = compiler 71 ClosureRepresentationInfo closureData =
76 .backendStrategy.closureDataLookup 72 _closureDataLookup.getClosureInfoForMember(_analyzedMember);
77 .getClosureInfoForMember(analyzedMember);
78 closureData.forEachCapturedVariable((variable, field) { 73 closureData.forEachCapturedVariable((variable, field) {
79 locals.setCaptured(variable, field); 74 _locals.setCaptured(variable, field);
80 }); 75 });
81 closureData.forEachBoxedVariable((variable, field) { 76 closureData.forEachBoxedVariable((variable, field) {
82 locals.setCapturedAndBoxed(variable, field); 77 _locals.setCapturedAndBoxed(variable, field);
83 }); 78 });
84 79
85 return analyzedNode.accept(this); 80 return _analyzedNode.accept(this);
86 } 81 }
87 82
88 void recordReturnType(TypeInformation type) { 83 void recordReturnType(TypeInformation type) {
89 FunctionEntity analyzedMethod = analyzedMember; 84 FunctionEntity analyzedMethod = _analyzedMember;
90 returnType = 85 _returnType =
91 inferrer.addReturnTypeForMethod(analyzedMethod, returnType, type); 86 _inferrer.addReturnTypeForMethod(analyzedMethod, _returnType, type);
92 } 87 }
93 88
94 void initializationIsIndefinite() { 89 void initializationIsIndefinite() {
95 MemberEntity member = analyzedMember; 90 MemberEntity member = _analyzedMember;
96 if (member is ConstructorEntity && member.isGenerativeConstructor) { 91 if (member is ConstructorEntity && member.isGenerativeConstructor) {
97 locals.fieldScope.isIndefinite = true; 92 _locals.fieldScope.isIndefinite = true;
98 } 93 }
99 } 94 }
100 95
101 TypeInformation visit(ir.Node node) { 96 TypeInformation visit(ir.Node node) {
102 return node == null ? null : node.accept(this); 97 return node == null ? null : node.accept(this);
103 } 98 }
104 99
105 @override 100 @override
106 TypeInformation visitFunctionNode(ir.FunctionNode node) { 101 TypeInformation visitFunctionNode(ir.FunctionNode node) {
107 // TODO(redemption): Handle constructors. 102 // TODO(redemption): Handle constructors.
108 // TODO(redemption): Handle native methods. 103 // TODO(redemption): Handle native methods.
109 // TODO(redemption): Set up parameters. 104 // TODO(redemption): Set up parameters.
110 visit(node.body); 105 visit(node.body);
111 switch (node.asyncMarker) { 106 switch (node.asyncMarker) {
112 case ir.AsyncMarker.Sync: 107 case ir.AsyncMarker.Sync:
113 if (returnType == null) { 108 if (_returnType == null) {
114 // No return in the body. 109 // No return in the body.
115 returnType = locals.seenReturnOrThrow 110 _returnType = _locals.seenReturnOrThrow
116 ? types.nonNullEmpty() // Body always throws. 111 ? _types.nonNullEmpty() // Body always throws.
117 : types.nullType; 112 : _types.nullType;
118 } else if (!locals.seenReturnOrThrow) { 113 } else if (!_locals.seenReturnOrThrow) {
119 // We haven'TypeInformation seen returns on all branches. So the metho d may 114 // We haven'TypeInformation seen returns on all branches. So the metho d may
120 // also return null. 115 // also return null.
121 recordReturnType(types.nullType); 116 recordReturnType(_types.nullType);
122 } 117 }
123 break; 118 break;
124 119
125 case ir.AsyncMarker.SyncStar: 120 case ir.AsyncMarker.SyncStar:
126 // TODO(asgerf): Maybe make a ContainerTypeMask for these? The type 121 // TODO(asgerf): Maybe make a ContainerTypeMask for these? The type
127 // contained is the method body's return type. 122 // contained is the method body's return type.
128 recordReturnType(types.syncStarIterableType); 123 recordReturnType(_types.syncStarIterableType);
129 break; 124 break;
130 125
131 case ir.AsyncMarker.Async: 126 case ir.AsyncMarker.Async:
132 recordReturnType(types.asyncFutureType); 127 recordReturnType(_types.asyncFutureType);
133 break; 128 break;
134 129
135 case ir.AsyncMarker.AsyncStar: 130 case ir.AsyncMarker.AsyncStar:
136 recordReturnType(types.asyncStarStreamType); 131 recordReturnType(_types.asyncStarStreamType);
137 break; 132 break;
138 case ir.AsyncMarker.SyncYielding: 133 case ir.AsyncMarker.SyncYielding:
139 failedAt( 134 failedAt(
140 analyzedMember, "Unexpected async marker: ${node.asyncMarker}"); 135 _analyzedMember, "Unexpected async marker: ${node.asyncMarker}");
141 break; 136 break;
142 } 137 }
143 return returnType; 138 return _returnType;
144 } 139 }
145 140
146 @override 141 @override
147 TypeInformation defaultExpression(ir.Expression expression) { 142 TypeInformation defaultExpression(ir.Expression expression) {
148 // TODO(efortuna): Remove when more is implemented. 143 // TODO(efortuna): Remove when more is implemented.
149 return types.dynamicType; 144 return _types.dynamicType;
150 } 145 }
151 146
152 @override 147 @override
153 TypeInformation visitNullLiteral(ir.NullLiteral literal) { 148 TypeInformation visitNullLiteral(ir.NullLiteral literal) {
154 return types.nullType; 149 return _types.nullType;
155 } 150 }
156 151
157 @override 152 @override
158 TypeInformation visitBlock(ir.Block block) { 153 TypeInformation visitBlock(ir.Block block) {
159 for (ir.Statement statement in block.statements) { 154 for (ir.Statement statement in block.statements) {
160 statement.accept(this); 155 statement.accept(this);
161 if (locals.aborts) break; 156 if (_locals.aborts) break;
162 } 157 }
163 return null; 158 return null;
164 } 159 }
165 160
166 @override 161 @override
167 TypeInformation visitListLiteral(ir.ListLiteral listLiteral) { 162 TypeInformation visitListLiteral(ir.ListLiteral listLiteral) {
168 // We only set the type once. We don't need to re-visit the children 163 // We only set the type once. We don't need to re-visit the children
169 // when re-analyzing the node. 164 // when re-analyzing the node.
170 return inferrer.concreteTypes.putIfAbsent(listLiteral, () { 165 return _inferrer.concreteTypes.putIfAbsent(listLiteral, () {
171 TypeInformation elementType; 166 TypeInformation elementType;
172 int length = 0; 167 int length = 0;
173 for (ir.Expression element in listLiteral.expressions) { 168 for (ir.Expression element in listLiteral.expressions) {
174 TypeInformation type = element.accept(this); 169 TypeInformation type = element.accept(this);
175 elementType = elementType == null 170 elementType = elementType == null
176 ? types.allocatePhi(null, null, type, isTry: false) 171 ? _types.allocatePhi(null, null, type, isTry: false)
177 : types.addPhiInput(null, elementType, type); 172 : _types.addPhiInput(null, elementType, type);
178 length++; 173 length++;
179 } 174 }
180 elementType = elementType == null 175 elementType = elementType == null
181 ? types.nonNullEmpty() 176 ? _types.nonNullEmpty()
182 : types.simplifyPhi(null, null, elementType); 177 : _types.simplifyPhi(null, null, elementType);
183 TypeInformation containerType = 178 TypeInformation containerType =
184 listLiteral.isConst ? types.constListType : types.growableListType; 179 listLiteral.isConst ? _types.constListType : _types.growableListType;
185 return types.allocateList( 180 return _types.allocateList(
186 containerType, listLiteral, analyzedMember, elementType, length); 181 containerType, listLiteral, _analyzedMember, elementType, length);
187 }); 182 });
188 } 183 }
189 184
190 @override 185 @override
191 TypeInformation visitReturnStatement(ir.ReturnStatement node) { 186 TypeInformation visitReturnStatement(ir.ReturnStatement node) {
192 ir.Node expression = node.expression; 187 ir.Node expression = node.expression;
193 recordReturnType( 188 recordReturnType(
194 expression == null ? types.nullType : expression.accept(this)); 189 expression == null ? _types.nullType : expression.accept(this));
195 locals.seenReturnOrThrow = true; 190 _locals.seenReturnOrThrow = true;
196 initializationIsIndefinite(); 191 initializationIsIndefinite();
197 return null; 192 return null;
198 } 193 }
194
195 @override
196 TypeInformation visitIntLiteral(ir.IntLiteral node) {
197 ConstantSystem constantSystem = _closedWorld.constantSystem;
198 // The JavaScript backend may turn this literal into a double at
199 // runtime.
200 return _types.getConcreteTypeFor(
201 computeTypeMask(_closedWorld, constantSystem.createInt(node.value)));
202 }
203
204 @override
205 TypeInformation visitDoubleLiteral(ir.DoubleLiteral node) {
206 ConstantSystem constantSystem = _closedWorld.constantSystem;
207 // The JavaScript backend may turn this literal into an integer at
208 // runtime.
209 return _types.getConcreteTypeFor(
210 computeTypeMask(_closedWorld, constantSystem.createDouble(node.value)));
211 }
199 } 212 }
OLDNEW
« no previous file with comments | « pkg/compiler/lib/src/inferrer/builder.dart ('k') | pkg/compiler/lib/src/inferrer/kernel_inferrer_engine.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698