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

Side by Side Diff: src/compiler/typer.cc

Issue 509343002: Better typing and type verification (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Drop typedness from graph Created 6 years, 2 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 | Annotate | Revision Log
OLDNEW
1 // Copyright 2014 the V8 project authors. All rights reserved. 1 // Copyright 2014 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "src/compiler/graph-inl.h" 5 #include "src/compiler/graph-inl.h"
6 #include "src/compiler/js-operator.h" 6 #include "src/compiler/js-operator.h"
7 #include "src/compiler/node.h" 7 #include "src/compiler/node.h"
8 #include "src/compiler/node-properties-inl.h" 8 #include "src/compiler/node-properties-inl.h"
9 #include "src/compiler/node-properties.h" 9 #include "src/compiler/node-properties.h"
10 #include "src/compiler/simplified-operator.h" 10 #include "src/compiler/simplified-operator.h"
11 #include "src/compiler/typer.h" 11 #include "src/compiler/typer.h"
12 12
13 namespace v8 { 13 namespace v8 {
14 namespace internal { 14 namespace internal {
15 namespace compiler { 15 namespace compiler {
16 16
17 Typer::Typer(Zone* zone) : zone_(zone) { 17
18 class Typer::Decorator : public GraphDecorator {
19 public:
20 explicit Decorator(Typer* typer) : typer_(typer) {}
21 virtual void Decorate(Node* node);
22
23 private:
24 Typer* typer_;
25 };
26
27
28 Typer::Typer(Graph* graph, MaybeHandle<Context> context)
29 : graph_(graph), context_(context), decorator_(NULL) {
30 Zone* zone = this->zone();
18 Type* number = Type::Number(zone); 31 Type* number = Type::Number(zone);
19 Type* signed32 = Type::Signed32(zone); 32 Type* signed32 = Type::Signed32(zone);
20 Type* unsigned32 = Type::Unsigned32(zone); 33 Type* unsigned32 = Type::Unsigned32(zone);
21 Type* integral32 = Type::Integral32(zone); 34 Type* integral32 = Type::Integral32(zone);
22 Type* object = Type::Object(zone); 35 Type* object = Type::Object(zone);
23 Type* undefined = Type::Undefined(zone); 36 Type* undefined = Type::Undefined(zone);
24 number_fun0_ = Type::Function(number, zone); 37 number_fun0_ = Type::Function(number, zone);
25 number_fun1_ = Type::Function(number, number, zone); 38 number_fun1_ = Type::Function(number, number, zone);
26 number_fun2_ = Type::Function(number, number, number, zone); 39 number_fun2_ = Type::Function(number, number, number, zone);
27 imul_fun_ = Type::Function(signed32, integral32, integral32, zone); 40 imul_fun_ = Type::Function(signed32, integral32, integral32, zone);
(...skipping 27 matching lines...) Expand all
55 int16_array_fun_ = Type::Function(int16_array, arg1, arg2, arg3, zone); 68 int16_array_fun_ = Type::Function(int16_array, arg1, arg2, arg3, zone);
56 int32_array_fun_ = Type::Function(int32_array, arg1, arg2, arg3, zone); 69 int32_array_fun_ = Type::Function(int32_array, arg1, arg2, arg3, zone);
57 uint8_array_fun_ = Type::Function(uint8_array, arg1, arg2, arg3, zone); 70 uint8_array_fun_ = Type::Function(uint8_array, arg1, arg2, arg3, zone);
58 uint16_array_fun_ = Type::Function(uint16_array, arg1, arg2, arg3, zone); 71 uint16_array_fun_ = Type::Function(uint16_array, arg1, arg2, arg3, zone);
59 uint32_array_fun_ = Type::Function(uint32_array, arg1, arg2, arg3, zone); 72 uint32_array_fun_ = Type::Function(uint32_array, arg1, arg2, arg3, zone);
60 float32_array_fun_ = Type::Function(float32_array, arg1, arg2, arg3, zone); 73 float32_array_fun_ = Type::Function(float32_array, arg1, arg2, arg3, zone);
61 float64_array_fun_ = Type::Function(float64_array, arg1, arg2, arg3, zone); 74 float64_array_fun_ = Type::Function(float64_array, arg1, arg2, arg3, zone);
62 } 75 }
63 76
64 77
78 Typer::~Typer() {
79 if (decorator_) graph_->RemoveDecorator(decorator_);
80 }
81
82
65 class Typer::Visitor : public NullNodeVisitor { 83 class Typer::Visitor : public NullNodeVisitor {
66 public: 84 public:
67 Visitor(Typer* typer, MaybeHandle<Context> context) 85 explicit Visitor(Typer* typer) : typer_(typer) {}
68 : typer_(typer), context_(context) {}
69 86
70 Bounds TypeNode(Node* node) { 87 Bounds TypeNode(Node* node) {
71 switch (node->opcode()) { 88 switch (node->opcode()) {
72 #define DECLARE_CASE(x) case IrOpcode::k##x: return Type##x(node); 89 #define DECLARE_CASE(x) case IrOpcode::k##x: return Type##x(node);
90 DECLARE_CASE(Start)
73 VALUE_OP_LIST(DECLARE_CASE) 91 VALUE_OP_LIST(DECLARE_CASE)
74 #undef DECLARE_CASE 92 #undef DECLARE_CASE
75 93
76 #define DECLARE_CASE(x) case IrOpcode::k##x: 94 #define DECLARE_CASE(x) case IrOpcode::k##x:
77 CONTROL_OP_LIST(DECLARE_CASE) 95 DECLARE_CASE(End)
96 INNER_CONTROL_OP_LIST(DECLARE_CASE)
78 #undef DECLARE_CASE 97 #undef DECLARE_CASE
79 break; 98 break;
80 } 99 }
81 return Bounds(Type::None(zone())); 100 UNREACHABLE();
101 return Bounds();
82 } 102 }
83 103
84 Type* TypeConstant(Handle<Object> value); 104 Type* TypeConstant(Handle<Object> value);
85 105
86 protected: 106 protected:
87 #define DECLARE_METHOD(x) inline Bounds Type##x(Node* node); 107 #define DECLARE_METHOD(x) inline Bounds Type##x(Node* node);
108 DECLARE_METHOD(Start)
88 VALUE_OP_LIST(DECLARE_METHOD) 109 VALUE_OP_LIST(DECLARE_METHOD)
89 #undef DECLARE_METHOD 110 #undef DECLARE_METHOD
90 111
91 Bounds OperandType(Node* node, int i) { 112 Bounds operand(Node* node, int i) {
92 return NodeProperties::GetBounds(NodeProperties::GetValueInput(node, i)); 113 Node* operand_node = NodeProperties::GetValueInput(node, i);
114 return GetBoundsOrNone(operand_node);
93 } 115 }
94 116
95 Type* ContextType(Node* node) { 117 Type* context_type(Node* node) {
96 Bounds result = 118 Bounds result = GetBoundsOrNone(NodeProperties::GetContextInput(node));
97 NodeProperties::GetBounds(NodeProperties::GetContextInput(node));
98 DCHECK(result.upper->Is(Type::Internal())); 119 DCHECK(result.upper->Is(Type::Internal()));
99 DCHECK(result.lower->Equals(result.upper)); 120 DCHECK(result.lower->Equals(result.upper));
100 return result.upper; 121 return result.upper;
101 } 122 }
102 123
103 Zone* zone() { return typer_->zone(); } 124 Zone* zone() { return typer_->zone(); }
104 Isolate* isolate() { return typer_->isolate(); } 125 Isolate* isolate() { return typer_->isolate(); }
105 MaybeHandle<Context> context() { return context_; } 126 Graph* graph() { return typer_->graph(); }
127 MaybeHandle<Context> context() { return typer_->context(); }
106 128
107 private: 129 private:
108 Typer* typer_; 130 Typer* typer_;
109 MaybeHandle<Context> context_; 131
132 Bounds GetBoundsOrNone(Node* node) {
133 return NodeProperties::IsTyped(node)
134 ? NodeProperties::GetBounds(node) : Bounds(Type::None(zone()));
135 }
110 }; 136 };
111 137
112 138
113 class Typer::RunVisitor : public Typer::Visitor { 139 class Typer::RunVisitor : public Typer::Visitor {
114 public: 140 public:
115 RunVisitor(Typer* typer, MaybeHandle<Context> context) 141 explicit RunVisitor(Typer* typer)
116 : Visitor(typer, context), 142 : Visitor(typer),
117 phis(NodeSet::key_compare(), NodeSet::allocator_type(typer->zone())) {} 143 phis(NodeSet::key_compare(), NodeSet::allocator_type(typer->zone())) {}
118 144
119 GenericGraphVisit::Control Pre(Node* node) {
120 return NodeProperties::IsControl(node)
121 && node->opcode() != IrOpcode::kEnd
122 && node->opcode() != IrOpcode::kMerge
123 && node->opcode() != IrOpcode::kReturn
124 ? GenericGraphVisit::SKIP : GenericGraphVisit::CONTINUE;
125 }
126
127 GenericGraphVisit::Control Post(Node* node) { 145 GenericGraphVisit::Control Post(Node* node) {
128 Bounds bounds = TypeNode(node); 146 if (OperatorProperties::HasValueOutput(node->op())) {
129 if (node->opcode() == IrOpcode::kPhi) { 147 Bounds bounds = TypeNode(node);
148 NodeProperties::SetBounds(node, bounds);
130 // Remember phis for least fixpoint iteration. 149 // Remember phis for least fixpoint iteration.
131 phis.insert(node); 150 if (node->opcode() == IrOpcode::kPhi) phis.insert(node);
132 } else {
133 NodeProperties::SetBounds(node, bounds);
134 } 151 }
135 return GenericGraphVisit::CONTINUE; 152 return GenericGraphVisit::CONTINUE;
136 } 153 }
137 154
138 NodeSet phis; 155 NodeSet phis;
139 }; 156 };
140 157
141 158
142 class Typer::NarrowVisitor : public Typer::Visitor { 159 class Typer::NarrowVisitor : public Typer::Visitor {
143 public: 160 public:
144 NarrowVisitor(Typer* typer, MaybeHandle<Context> context) 161 explicit NarrowVisitor(Typer* typer) : Visitor(typer) {}
145 : Visitor(typer, context) {}
146 162
147 GenericGraphVisit::Control Pre(Node* node) { 163 GenericGraphVisit::Control Pre(Node* node) {
148 Bounds previous = NodeProperties::GetBounds(node); 164 if (OperatorProperties::HasValueOutput(node->op())) {
149 Bounds bounds = TypeNode(node); 165 Bounds previous = NodeProperties::GetBounds(node);
150 NodeProperties::SetBounds(node, Bounds::Both(bounds, previous, zone())); 166 Bounds bounds = TypeNode(node);
151 DCHECK(bounds.Narrows(previous)); 167 NodeProperties::SetBounds(node, Bounds::Both(bounds, previous, zone()));
152 // Stop when nothing changed (but allow reentry in case it does later). 168 DCHECK(bounds.Narrows(previous));
153 return previous.Narrows(bounds) 169 // Stop when nothing changed (but allow re-entry in case it does later).
154 ? GenericGraphVisit::DEFER : GenericGraphVisit::REENTER; 170 return previous.Narrows(bounds)
171 ? GenericGraphVisit::DEFER : GenericGraphVisit::REENTER;
172 } else {
173 return GenericGraphVisit::SKIP;
174 }
155 } 175 }
156 176
157 GenericGraphVisit::Control Post(Node* node) { 177 GenericGraphVisit::Control Post(Node* node) {
158 return GenericGraphVisit::REENTER; 178 return GenericGraphVisit::REENTER;
159 } 179 }
160 }; 180 };
161 181
162 182
163 class Typer::WidenVisitor : public Typer::Visitor { 183 class Typer::WidenVisitor : public Typer::Visitor {
164 public: 184 public:
165 WidenVisitor(Typer* typer, MaybeHandle<Context> context) 185 explicit WidenVisitor(Typer* typer) : Visitor(typer) {}
166 : Visitor(typer, context) {}
167 186
168 GenericGraphVisit::Control Pre(Node* node) { 187 GenericGraphVisit::Control Pre(Node* node) {
169 Bounds previous = NodeProperties::GetBounds(node); 188 if (OperatorProperties::HasValueOutput(node->op())) {
170 Bounds bounds = TypeNode(node); 189 Bounds previous = NodeProperties::GetBounds(node);
171 DCHECK(previous.lower->Is(bounds.lower)); 190 Bounds bounds = TypeNode(node);
172 DCHECK(previous.upper->Is(bounds.upper)); 191 DCHECK(previous.lower->Is(bounds.lower));
173 NodeProperties::SetBounds(node, bounds); // TODO(rossberg): Either? 192 DCHECK(previous.upper->Is(bounds.upper));
174 // Stop when nothing changed (but allow reentry in case it does later). 193 NodeProperties::SetBounds(node, bounds); // TODO(rossberg): Either?
175 return bounds.Narrows(previous) 194 // Stop when nothing changed (but allow re-entry in case it does later).
176 ? GenericGraphVisit::DEFER : GenericGraphVisit::REENTER; 195 return bounds.Narrows(previous)
196 ? GenericGraphVisit::DEFER : GenericGraphVisit::REENTER;
197 } else {
198 return GenericGraphVisit::SKIP;
199 }
177 } 200 }
178 201
179 GenericGraphVisit::Control Post(Node* node) { 202 GenericGraphVisit::Control Post(Node* node) {
180 return GenericGraphVisit::REENTER; 203 return GenericGraphVisit::REENTER;
181 } 204 }
182 }; 205 };
183 206
184 207
185 void Typer::Run(Graph* graph, MaybeHandle<Context> context) { 208 void Typer::Run() {
186 RunVisitor typing(this, context); 209 RunVisitor typing(this);
187 graph->VisitNodeInputsFromEnd(&typing); 210 graph_->VisitNodeInputsFromEnd(&typing);
188 // Find least fixpoint. 211 // Find least fixpoint.
189 for (NodeSetIter i = typing.phis.begin(); i != typing.phis.end(); ++i) { 212 WidenVisitor widen(this);
190 Widen(graph, *i, context); 213 for (NodeSetIter it = typing.phis.begin(); it != typing.phis.end(); ++it) {
214 graph_->VisitNodeUsesFrom(*it, &widen);
215 }
216
217 DCHECK(decorator_ == NULL);
218 decorator_ = new (zone()) Decorator(this);
219 graph_->AddDecorator(decorator_);
220 }
221
222
223 void Typer::Narrow(Node* start) {
224 NarrowVisitor typing(this);
225 graph_->VisitNodeUsesFrom(start, &typing);
226 }
227
228
229 void Typer::Decorator::Decorate(Node* node) {
230 if (OperatorProperties::HasValueOutput(node->op())) {
231 Visitor typing(typer_);
232 Bounds bounds = typing.TypeNode(node);
233 NodeProperties::SetBounds(node, bounds);
191 } 234 }
192 } 235 }
193 236
194 237
195 void Typer::Narrow(Graph* graph, Node* start, MaybeHandle<Context> context) { 238 // -----------------------------------------------------------------------------
196 NarrowVisitor typing(this, context);
197 graph->VisitNodeUsesFrom(start, &typing);
198 }
199 239
240 // Control operators.
200 241
201 void Typer::Widen(Graph* graph, Node* start, MaybeHandle<Context> context) { 242 Bounds Typer::Visitor::TypeStart(Node* node) {
202 WidenVisitor typing(this, context); 243 return Bounds(Type::Internal(zone()));
203 graph->VisitNodeUsesFrom(start, &typing);
204 }
205
206
207 void Typer::Init(Node* node) {
208 Visitor typing(this, MaybeHandle<Context>());
209 Bounds bounds = typing.TypeNode(node);
210 NodeProperties::SetBounds(node, bounds);
211 } 244 }
212 245
213 246
214 // Common operators. 247 // Common operators.
248
215 Bounds Typer::Visitor::TypeParameter(Node* node) { 249 Bounds Typer::Visitor::TypeParameter(Node* node) {
216 return Bounds::Unbounded(zone()); 250 return Bounds::Unbounded(zone());
217 } 251 }
218 252
219 253
220 Bounds Typer::Visitor::TypeInt32Constant(Node* node) { 254 Bounds Typer::Visitor::TypeInt32Constant(Node* node) {
221 // TODO(titzer): only call Type::Of() if the type is not already known. 255 // TODO(titzer): only call Type::Of() if the type is not already known.
222 return Bounds(Type::Of(ValueOf<int32_t>(node->op()), zone())); 256 return Bounds(Type::Of(ValueOf<int32_t>(node->op()), zone()));
223 } 257 }
224 258
(...skipping 22 matching lines...) Expand all
247 } 281 }
248 282
249 283
250 Bounds Typer::Visitor::TypeExternalConstant(Node* node) { 284 Bounds Typer::Visitor::TypeExternalConstant(Node* node) {
251 return Bounds(Type::Internal(zone())); 285 return Bounds(Type::Internal(zone()));
252 } 286 }
253 287
254 288
255 Bounds Typer::Visitor::TypePhi(Node* node) { 289 Bounds Typer::Visitor::TypePhi(Node* node) {
256 int arity = OperatorProperties::GetValueInputCount(node->op()); 290 int arity = OperatorProperties::GetValueInputCount(node->op());
257 Bounds bounds = OperandType(node, 0); 291 Bounds bounds = operand(node, 0);
258 for (int i = 1; i < arity; ++i) { 292 for (int i = 1; i < arity; ++i) {
259 bounds = Bounds::Either(bounds, OperandType(node, i), zone()); 293 bounds = Bounds::Either(bounds, operand(node, i), zone());
260 } 294 }
261 return bounds; 295 return bounds;
262 } 296 }
263 297
264 298
265 Bounds Typer::Visitor::TypeEffectPhi(Node* node) { 299 Bounds Typer::Visitor::TypeEffectPhi(Node* node) {
266 return Bounds(Type::None(zone())); 300 UNREACHABLE();
301 return Bounds();
267 } 302 }
268 303
269 304
270 Bounds Typer::Visitor::TypeControlEffect(Node* node) { 305 Bounds Typer::Visitor::TypeControlEffect(Node* node) {
271 return Bounds(Type::None(zone())); 306 UNREACHABLE();
307 return Bounds();
272 } 308 }
273 309
274 310
275 Bounds Typer::Visitor::TypeValueEffect(Node* node) { 311 Bounds Typer::Visitor::TypeValueEffect(Node* node) {
276 return Bounds(Type::None(zone())); 312 UNREACHABLE();
313 return Bounds();
277 } 314 }
278 315
279 316
280 Bounds Typer::Visitor::TypeFinish(Node* node) { return OperandType(node, 0); } 317 Bounds Typer::Visitor::TypeFinish(Node* node) {
318 return operand(node, 0);
319 }
281 320
282 321
283 Bounds Typer::Visitor::TypeFrameState(Node* node) { 322 Bounds Typer::Visitor::TypeFrameState(Node* node) {
284 return Bounds(Type::None(zone())); 323 UNREACHABLE();
324 return Bounds();
285 } 325 }
286 326
287 327
288 Bounds Typer::Visitor::TypeStateValues(Node* node) { 328 Bounds Typer::Visitor::TypeStateValues(Node* node) {
289 return Bounds(Type::None(zone())); 329 UNREACHABLE();
330 return Bounds();
290 } 331 }
291 332
292 333
293 Bounds Typer::Visitor::TypeCall(Node* node) { 334 Bounds Typer::Visitor::TypeCall(Node* node) {
294 return Bounds::Unbounded(zone()); 335 return Bounds::Unbounded(zone());
295 } 336 }
296 337
297 338
298 Bounds Typer::Visitor::TypeProjection(Node* node) { 339 Bounds Typer::Visitor::TypeProjection(Node* node) {
299 // TODO(titzer): use the output type of the input to determine the bounds. 340 // TODO(titzer): use the output type of the input to determine the bounds.
300 return Bounds::Unbounded(zone()); 341 return Bounds::Unbounded(zone());
301 } 342 }
302 343
303 344
304 // JS comparison operators. 345 // JS comparison operators.
305 346
306 #define DEFINE_METHOD(x) \ 347 #define DEFINE_METHOD(x) \
307 Bounds Typer::Visitor::Type##x(Node* node) { \ 348 Bounds Typer::Visitor::Type##x(Node* node) { \
308 return Bounds(Type::Boolean(zone())); \ 349 return Bounds(Type::Boolean(zone())); \
309 } 350 }
310 JS_COMPARE_BINOP_LIST(DEFINE_METHOD) 351 JS_COMPARE_BINOP_LIST(DEFINE_METHOD)
311 #undef DEFINE_METHOD 352 #undef DEFINE_METHOD
312 353
313 354
314 // JS bitwise operators. 355 // JS bitwise operators.
315 356
316 Bounds Typer::Visitor::TypeJSBitwiseOr(Node* node) { 357 Bounds Typer::Visitor::TypeJSBitwiseOr(Node* node) {
317 Bounds left = OperandType(node, 0); 358 Bounds left = operand(node, 0);
318 Bounds right = OperandType(node, 1); 359 Bounds right = operand(node, 1);
319 Type* upper = Type::Union(left.upper, right.upper, zone()); 360 Type* upper = Type::Union(left.upper, right.upper, zone());
320 if (!upper->Is(Type::Signed32())) upper = Type::Signed32(zone()); 361 if (!upper->Is(Type::Signed32())) upper = Type::Signed32(zone());
321 Type* lower = Type::Intersect(Type::SignedSmall(zone()), upper, zone()); 362 Type* lower = Type::Intersect(Type::SignedSmall(zone()), upper, zone());
322 return Bounds(lower, upper); 363 return Bounds(lower, upper);
323 } 364 }
324 365
325 366
326 Bounds Typer::Visitor::TypeJSBitwiseAnd(Node* node) { 367 Bounds Typer::Visitor::TypeJSBitwiseAnd(Node* node) {
327 Bounds left = OperandType(node, 0); 368 Bounds left = operand(node, 0);
328 Bounds right = OperandType(node, 1); 369 Bounds right = operand(node, 1);
329 Type* upper = Type::Union(left.upper, right.upper, zone()); 370 Type* upper = Type::Union(left.upper, right.upper, zone());
330 if (!upper->Is(Type::Signed32())) upper = Type::Signed32(zone()); 371 if (!upper->Is(Type::Signed32())) upper = Type::Signed32(zone());
331 Type* lower = Type::Intersect(Type::SignedSmall(zone()), upper, zone()); 372 Type* lower = Type::Intersect(Type::SignedSmall(zone()), upper, zone());
332 return Bounds(lower, upper); 373 return Bounds(lower, upper);
333 } 374 }
334 375
335 376
336 Bounds Typer::Visitor::TypeJSBitwiseXor(Node* node) { 377 Bounds Typer::Visitor::TypeJSBitwiseXor(Node* node) {
337 return Bounds(Type::SignedSmall(zone()), Type::Signed32(zone())); 378 return Bounds(Type::SignedSmall(zone()), Type::Signed32(zone()));
338 } 379 }
(...skipping 10 matching lines...) Expand all
349 390
350 391
351 Bounds Typer::Visitor::TypeJSShiftRightLogical(Node* node) { 392 Bounds Typer::Visitor::TypeJSShiftRightLogical(Node* node) {
352 return Bounds(Type::UnsignedSmall(zone()), Type::Unsigned32(zone())); 393 return Bounds(Type::UnsignedSmall(zone()), Type::Unsigned32(zone()));
353 } 394 }
354 395
355 396
356 // JS arithmetic operators. 397 // JS arithmetic operators.
357 398
358 Bounds Typer::Visitor::TypeJSAdd(Node* node) { 399 Bounds Typer::Visitor::TypeJSAdd(Node* node) {
359 Bounds left = OperandType(node, 0); 400 Bounds left = operand(node, 0);
360 Bounds right = OperandType(node, 1); 401 Bounds right = operand(node, 1);
361 Type* lower = 402 Type* lower =
362 left.lower->Is(Type::None()) || right.lower->Is(Type::None()) ? 403 left.lower->Is(Type::None()) || right.lower->Is(Type::None()) ?
363 Type::None(zone()) : 404 Type::None(zone()) :
364 left.lower->Is(Type::Number()) && right.lower->Is(Type::Number()) ? 405 left.lower->Is(Type::Number()) && right.lower->Is(Type::Number()) ?
365 Type::SignedSmall(zone()) : 406 Type::SignedSmall(zone()) :
366 left.lower->Is(Type::String()) || right.lower->Is(Type::String()) ? 407 left.lower->Is(Type::String()) || right.lower->Is(Type::String()) ?
367 Type::String(zone()) : Type::None(zone()); 408 Type::String(zone()) : Type::None(zone());
368 Type* upper = 409 Type* upper =
369 left.upper->Is(Type::None()) && right.upper->Is(Type::None()) ? 410 left.upper->Is(Type::None()) && right.upper->Is(Type::None()) ?
370 Type::None(zone()) : 411 Type::None(zone()) :
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after
424 return Bounds(Type::None(zone()), Type::String(zone())); 465 return Bounds(Type::None(zone()), Type::String(zone()));
425 } 466 }
426 467
427 468
428 Bounds Typer::Visitor::TypeJSToName(Node* node) { 469 Bounds Typer::Visitor::TypeJSToName(Node* node) {
429 return Bounds(Type::None(zone()), Type::Name(zone())); 470 return Bounds(Type::None(zone()), Type::Name(zone()));
430 } 471 }
431 472
432 473
433 Bounds Typer::Visitor::TypeJSToObject(Node* node) { 474 Bounds Typer::Visitor::TypeJSToObject(Node* node) {
434 return Bounds(Type::None(zone()), Type::Object(zone())); 475 return Bounds(Type::None(zone()), Type::Receiver(zone()));
435 } 476 }
436 477
437 478
438 // JS object operators. 479 // JS object operators.
439 480
440 Bounds Typer::Visitor::TypeJSCreate(Node* node) { 481 Bounds Typer::Visitor::TypeJSCreate(Node* node) {
441 return Bounds(Type::None(zone()), Type::Object(zone())); 482 return Bounds(Type::None(zone()), Type::Object(zone()));
442 } 483 }
443 484
444 485
445 Bounds Typer::Visitor::TypeJSLoadProperty(Node* node) { 486 Bounds Typer::Visitor::TypeJSLoadProperty(Node* node) {
446 Bounds object = OperandType(node, 0); 487 Bounds object = operand(node, 0);
447 Bounds name = OperandType(node, 1); 488 Bounds name = operand(node, 1);
448 Bounds result = Bounds::Unbounded(zone()); 489 Bounds result = Bounds::Unbounded(zone());
449 // TODO(rossberg): Use range types and sized array types to filter undefined. 490 // TODO(rossberg): Use range types and sized array types to filter undefined.
450 if (object.lower->IsArray() && name.lower->Is(Type::Integral32())) { 491 if (object.lower->IsArray() && name.lower->Is(Type::Integral32())) {
451 result.lower = Type::Union( 492 result.lower = Type::Union(
452 object.lower->AsArray()->Element(), Type::Undefined(zone()), zone()); 493 object.lower->AsArray()->Element(), Type::Undefined(zone()), zone());
453 } 494 }
454 if (object.upper->IsArray() && name.upper->Is(Type::Integral32())) { 495 if (object.upper->IsArray() && name.upper->Is(Type::Integral32())) {
455 result.upper = Type::Union( 496 result.upper = Type::Union(
456 object.upper->AsArray()->Element(), Type::Undefined(zone()), zone()); 497 object.upper->AsArray()->Element(), Type::Undefined(zone()), zone());
457 } 498 }
458 return result; 499 return result;
459 } 500 }
460 501
461 502
462 Bounds Typer::Visitor::TypeJSLoadNamed(Node* node) { 503 Bounds Typer::Visitor::TypeJSLoadNamed(Node* node) {
463 return Bounds::Unbounded(zone()); 504 return Bounds::Unbounded(zone());
464 } 505 }
465 506
466 507
467 Bounds Typer::Visitor::TypeJSStoreProperty(Node* node) { 508 Bounds Typer::Visitor::TypeJSStoreProperty(Node* node) {
468 return Bounds(Type::None(zone())); 509 UNREACHABLE();
510 return Bounds();
469 } 511 }
470 512
471 513
472 Bounds Typer::Visitor::TypeJSStoreNamed(Node* node) { 514 Bounds Typer::Visitor::TypeJSStoreNamed(Node* node) {
473 return Bounds(Type::None(zone())); 515 UNREACHABLE();
516 return Bounds();
474 } 517 }
475 518
476 519
477 Bounds Typer::Visitor::TypeJSDeleteProperty(Node* node) { 520 Bounds Typer::Visitor::TypeJSDeleteProperty(Node* node) {
478 return Bounds(Type::Boolean(zone())); 521 return Bounds(Type::Boolean(zone()));
479 } 522 }
480 523
481 524
482 Bounds Typer::Visitor::TypeJSHasProperty(Node* node) { 525 Bounds Typer::Visitor::TypeJSHasProperty(Node* node) {
483 return Bounds(Type::Boolean(zone())); 526 return Bounds(Type::Boolean(zone()));
484 } 527 }
485 528
486 529
487 Bounds Typer::Visitor::TypeJSInstanceOf(Node* node) { 530 Bounds Typer::Visitor::TypeJSInstanceOf(Node* node) {
488 return Bounds(Type::Boolean(zone())); 531 return Bounds(Type::Boolean(zone()));
489 } 532 }
490 533
491 534
492 // JS context operators. 535 // JS context operators.
493 536
494 Bounds Typer::Visitor::TypeJSLoadContext(Node* node) { 537 Bounds Typer::Visitor::TypeJSLoadContext(Node* node) {
495 Bounds outer = OperandType(node, 0); 538 Bounds outer = operand(node, 0);
496 DCHECK(outer.upper->Is(Type::Internal())); 539 DCHECK(outer.upper->Maybe(Type::Internal()));
497 DCHECK(outer.lower->Equals(outer.upper)); 540 // TODO(rossberg): More precisely, instead of the above assertion, we should
541 // back-propagate the constraint that it has to be a subtype of Internal.
542
498 ContextAccess access = OpParameter<ContextAccess>(node); 543 ContextAccess access = OpParameter<ContextAccess>(node);
499 Type* context_type = outer.upper; 544 Type* context_type = outer.upper;
500 MaybeHandle<Context> context; 545 MaybeHandle<Context> context;
501 if (context_type->IsConstant()) { 546 if (context_type->IsConstant()) {
502 context = Handle<Context>::cast(context_type->AsConstant()->Value()); 547 context = Handle<Context>::cast(context_type->AsConstant()->Value());
503 } 548 }
504 // Walk context chain (as far as known), mirroring dynamic lookup. 549 // Walk context chain (as far as known), mirroring dynamic lookup.
505 // Since contexts are mutable, the information is only useful as a lower 550 // Since contexts are mutable, the information is only useful as a lower
506 // bound. 551 // bound.
507 // TODO(rossberg): Could use scope info to fix upper bounds for constant 552 // TODO(rossberg): Could use scope info to fix upper bounds for constant
(...skipping 13 matching lines...) Expand all
521 } else { 566 } else {
522 Handle<Object> value = 567 Handle<Object> value =
523 handle(context.ToHandleChecked()->get(access.index()), isolate()); 568 handle(context.ToHandleChecked()->get(access.index()), isolate());
524 Type* lower = TypeConstant(value); 569 Type* lower = TypeConstant(value);
525 return Bounds(lower, Type::Any(zone())); 570 return Bounds(lower, Type::Any(zone()));
526 } 571 }
527 } 572 }
528 573
529 574
530 Bounds Typer::Visitor::TypeJSStoreContext(Node* node) { 575 Bounds Typer::Visitor::TypeJSStoreContext(Node* node) {
531 return Bounds(Type::None(zone())); 576 UNREACHABLE();
577 return Bounds();
532 } 578 }
533 579
534 580
535 Bounds Typer::Visitor::TypeJSCreateFunctionContext(Node* node) { 581 Bounds Typer::Visitor::TypeJSCreateFunctionContext(Node* node) {
536 Type* outer = ContextType(node); 582 Type* outer = context_type(node);
537 return Bounds(Type::Context(outer, zone())); 583 return Bounds(Type::Context(outer, zone()));
538 } 584 }
539 585
540 586
541 Bounds Typer::Visitor::TypeJSCreateCatchContext(Node* node) { 587 Bounds Typer::Visitor::TypeJSCreateCatchContext(Node* node) {
542 Type* outer = ContextType(node); 588 Type* outer = context_type(node);
543 return Bounds(Type::Context(outer, zone())); 589 return Bounds(Type::Context(outer, zone()));
544 } 590 }
545 591
546 592
547 Bounds Typer::Visitor::TypeJSCreateWithContext(Node* node) { 593 Bounds Typer::Visitor::TypeJSCreateWithContext(Node* node) {
548 Type* outer = ContextType(node); 594 Type* outer = context_type(node);
549 return Bounds(Type::Context(outer, zone())); 595 return Bounds(Type::Context(outer, zone()));
550 } 596 }
551 597
552 598
553 Bounds Typer::Visitor::TypeJSCreateBlockContext(Node* node) { 599 Bounds Typer::Visitor::TypeJSCreateBlockContext(Node* node) {
554 Type* outer = ContextType(node); 600 Type* outer = context_type(node);
555 return Bounds(Type::Context(outer, zone())); 601 return Bounds(Type::Context(outer, zone()));
556 } 602 }
557 603
558 604
559 Bounds Typer::Visitor::TypeJSCreateModuleContext(Node* node) { 605 Bounds Typer::Visitor::TypeJSCreateModuleContext(Node* node) {
560 // TODO(rossberg): this is probably incorrect 606 // TODO(rossberg): this is probably incorrect
561 Type* outer = ContextType(node); 607 Type* outer = context_type(node);
562 return Bounds(Type::Context(outer, zone())); 608 return Bounds(Type::Context(outer, zone()));
563 } 609 }
564 610
565 611
566 Bounds Typer::Visitor::TypeJSCreateGlobalContext(Node* node) { 612 Bounds Typer::Visitor::TypeJSCreateGlobalContext(Node* node) {
567 Type* outer = ContextType(node); 613 Type* outer = context_type(node);
568 return Bounds(Type::Context(outer, zone())); 614 return Bounds(Type::Context(outer, zone()));
569 } 615 }
570 616
571 617
572 // JS other operators. 618 // JS other operators.
573 619
574 Bounds Typer::Visitor::TypeJSYield(Node* node) { 620 Bounds Typer::Visitor::TypeJSYield(Node* node) {
575 return Bounds::Unbounded(zone()); 621 return Bounds::Unbounded(zone());
576 } 622 }
577 623
578 624
579 Bounds Typer::Visitor::TypeJSCallConstruct(Node* node) { 625 Bounds Typer::Visitor::TypeJSCallConstruct(Node* node) {
580 return Bounds(Type::None(zone()), Type::Receiver(zone())); 626 return Bounds(Type::None(zone()), Type::Receiver(zone()));
581 } 627 }
582 628
583 629
584 Bounds Typer::Visitor::TypeJSCallFunction(Node* node) { 630 Bounds Typer::Visitor::TypeJSCallFunction(Node* node) {
585 Bounds fun = OperandType(node, 0); 631 Bounds fun = operand(node, 0);
586 Type* lower = fun.lower->IsFunction() 632 Type* lower = fun.lower->IsFunction()
587 ? fun.lower->AsFunction()->Result() : Type::None(zone()); 633 ? fun.lower->AsFunction()->Result() : Type::None(zone());
588 Type* upper = fun.upper->IsFunction() 634 Type* upper = fun.upper->IsFunction()
589 ? fun.upper->AsFunction()->Result() : Type::Any(zone()); 635 ? fun.upper->AsFunction()->Result() : Type::Any(zone());
590 return Bounds(lower, upper); 636 return Bounds(lower, upper);
591 } 637 }
592 638
593 639
594 Bounds Typer::Visitor::TypeJSCallRuntime(Node* node) { 640 Bounds Typer::Visitor::TypeJSCallRuntime(Node* node) {
595 return Bounds::Unbounded(zone()); 641 return Bounds::Unbounded(zone());
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after
642 return Bounds(Type::Number(zone())); 688 return Bounds(Type::Number(zone()));
643 } 689 }
644 690
645 691
646 Bounds Typer::Visitor::TypeNumberModulus(Node* node) { 692 Bounds Typer::Visitor::TypeNumberModulus(Node* node) {
647 return Bounds(Type::Number(zone())); 693 return Bounds(Type::Number(zone()));
648 } 694 }
649 695
650 696
651 Bounds Typer::Visitor::TypeNumberToInt32(Node* node) { 697 Bounds Typer::Visitor::TypeNumberToInt32(Node* node) {
652 Bounds arg = OperandType(node, 0); 698 Bounds arg = operand(node, 0);
653 Type* s32 = Type::Signed32(zone()); 699 Type* s32 = Type::Signed32(zone());
654 Type* lower = arg.lower->Is(s32) ? arg.lower : s32; 700 Type* lower = arg.lower->Is(s32) ? arg.lower : s32;
655 Type* upper = arg.upper->Is(s32) ? arg.upper : s32; 701 Type* upper = arg.upper->Is(s32) ? arg.upper : s32;
656 return Bounds(lower, upper); 702 return Bounds(lower, upper);
657 } 703 }
658 704
659 705
660 Bounds Typer::Visitor::TypeNumberToUint32(Node* node) { 706 Bounds Typer::Visitor::TypeNumberToUint32(Node* node) {
661 Bounds arg = OperandType(node, 0); 707 Bounds arg = operand(node, 0);
662 Type* u32 = Type::Unsigned32(zone()); 708 Type* u32 = Type::Unsigned32(zone());
663 Type* lower = arg.lower->Is(u32) ? arg.lower : u32; 709 Type* lower = arg.lower->Is(u32) ? arg.lower : u32;
664 Type* upper = arg.upper->Is(u32) ? arg.upper : u32; 710 Type* upper = arg.upper->Is(u32) ? arg.upper : u32;
665 return Bounds(lower, upper); 711 return Bounds(lower, upper);
666 } 712 }
667 713
668 714
669 Bounds Typer::Visitor::TypeReferenceEqual(Node* node) { 715 Bounds Typer::Visitor::TypeReferenceEqual(Node* node) {
670 return Bounds(Type::Boolean(zone())); 716 return Bounds(Type::Boolean(zone()));
671 } 717 }
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after
742 return Bounds(FieldAccessOf(node->op()).type); 788 return Bounds(FieldAccessOf(node->op()).type);
743 } 789 }
744 790
745 791
746 Bounds Typer::Visitor::TypeLoadElement(Node* node) { 792 Bounds Typer::Visitor::TypeLoadElement(Node* node) {
747 return Bounds(ElementAccessOf(node->op()).type); 793 return Bounds(ElementAccessOf(node->op()).type);
748 } 794 }
749 795
750 796
751 Bounds Typer::Visitor::TypeStoreField(Node* node) { 797 Bounds Typer::Visitor::TypeStoreField(Node* node) {
752 return Bounds(Type::None()); 798 UNREACHABLE();
799 return Bounds();
753 } 800 }
754 801
755 802
756 Bounds Typer::Visitor::TypeStoreElement(Node* node) { 803 Bounds Typer::Visitor::TypeStoreElement(Node* node) {
757 return Bounds(Type::None()); 804 UNREACHABLE();
805 return Bounds();
758 } 806 }
759 807
760 808
761 // Machine operators. 809 // Machine operators.
762 810
763 // TODO(rossberg): implement 811 // TODO(rossberg): implement
764 #define DEFINE_METHOD(x) \ 812 #define DEFINE_METHOD(x) \
765 Bounds Typer::Visitor::Type##x(Node* node) { return Bounds(Type::None()); } 813 Bounds Typer::Visitor::Type##x(Node* node) { return Bounds(Type::None()); }
766 MACHINE_OP_LIST(DEFINE_METHOD) 814 MACHINE_OP_LIST(DEFINE_METHOD)
767 #undef DEFINE_METHOD 815 #undef DEFINE_METHOD
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after
824 return typer_->uint32_array_fun_; 872 return typer_->uint32_array_fun_;
825 } else if (*value == native->float32_array_fun()) { 873 } else if (*value == native->float32_array_fun()) {
826 return typer_->float32_array_fun_; 874 return typer_->float32_array_fun_;
827 } else if (*value == native->float64_array_fun()) { 875 } else if (*value == native->float64_array_fun()) {
828 return typer_->float64_array_fun_; 876 return typer_->float64_array_fun_;
829 } 877 }
830 } 878 }
831 return Type::Constant(value, zone()); 879 return Type::Constant(value, zone());
832 } 880 }
833 881
834
835 namespace {
836
837 class TyperDecorator : public GraphDecorator {
838 public:
839 explicit TyperDecorator(Typer* typer) : typer_(typer) {}
840 virtual void Decorate(Node* node) { typer_->Init(node); }
841
842 private:
843 Typer* typer_;
844 };
845
846 }
847
848
849 void Typer::DecorateGraph(Graph* graph) {
850 graph->AddDecorator(new (zone()) TyperDecorator(this));
851 }
852
853 } 882 }
854 } 883 }
855 } // namespace v8::internal::compiler 884 } // namespace v8::internal::compiler
OLDNEW
« src/compiler/js-graph.cc ('K') | « src/compiler/typer.h ('k') | src/compiler/verifier.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698