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

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

Issue 618803003: Refine expression typing, esp. by propagating range information. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Fix constant node typing. 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
« no previous file with comments | « src/compiler/typer.h ('k') | test/cctest/compiler/test-js-constant-cache.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 Typer::Typer(Zone* zone) : zone_(zone) {
18 Factory* f = zone->isolate()->factory(); 18 Factory* f = zone->isolate()->factory();
19 19
20 Handle<Object> zero = f->NewNumber(0);
21 Handle<Object> one = f->NewNumber(1);
22 Handle<Object> positive_infinity = f->NewNumber(+V8_INFINITY);
23 Handle<Object> negative_infinity = f->NewNumber(-V8_INFINITY);
24
25 negative_signed32 = Type::Union(
26 Type::SignedSmall(), Type::OtherSigned32(), zone);
27 non_negative_signed32 = Type::Union(
28 Type::UnsignedSmall(), Type::OtherUnsigned31(), zone);
29 undefined_or_null = Type::Union(Type::Undefined(), Type::Null(), zone);
30 singleton_false = Type::Constant(f->false_value(), zone);
31 singleton_true = Type::Constant(f->true_value(), zone);
32 singleton_zero = Type::Range(zero, zero, zone);
33 singleton_one = Type::Range(one, one, zone);
34 zero_or_one = Type::Union(singleton_zero, singleton_one, zone);
35 zeroish = Type::Union(
36 singleton_zero, Type::Union(Type::NaN(), Type::MinusZero(), zone), zone);
37 falsish = Type::Union(zeroish, undefined_or_null, zone);
38 integer = Type::Range(negative_infinity, positive_infinity, zone);
39
20 Type* number = Type::Number(); 40 Type* number = Type::Number();
21 Type* signed32 = Type::Signed32(); 41 Type* signed32 = Type::Signed32();
22 Type* unsigned32 = Type::Unsigned32(); 42 Type* unsigned32 = Type::Unsigned32();
23 Type* integral32 = Type::Integral32(); 43 Type* integral32 = Type::Integral32();
24 Type* object = Type::Object(); 44 Type* object = Type::Object();
25 Type* undefined = Type::Undefined(); 45 Type* undefined = Type::Undefined();
26 Type* weakint = Type::Union( 46 Type* weakint = Type::Union(
27 Type::Range(f->NewNumber(-V8_INFINITY), f->NewNumber(+V8_INFINITY), zone), 47 integer, Type::Union(Type::NaN(), Type::MinusZero(), zone), zone);
28 Type::Union(Type::NaN(), Type::MinusZero(), zone), zone);
29 48
30 number_fun0_ = Type::Function(number, zone); 49 number_fun0_ = Type::Function(number, zone);
31 number_fun1_ = Type::Function(number, number, zone); 50 number_fun1_ = Type::Function(number, number, zone);
32 number_fun2_ = Type::Function(number, number, number, zone); 51 number_fun2_ = Type::Function(number, number, number, zone);
33 weakint_fun1_ = Type::Function(weakint, number, zone); 52 weakint_fun1_ = Type::Function(weakint, number, zone);
34 imul_fun_ = Type::Function(signed32, integral32, integral32, zone); 53 imul_fun_ = Type::Function(signed32, integral32, integral32, zone);
35 random_fun_ = Type::Function(Type::Union( 54 random_fun_ = Type::Function(Type::Union(
36 Type::UnsignedSmall(), Type::OtherNumber(), zone), zone); 55 Type::UnsignedSmall(), Type::OtherNumber(), zone), zone);
37 56
57 Type* int8 = Type::Intersect(
58 Type::Range(f->NewNumber(-0x7F), f->NewNumber(0x7F-1), zone),
59 Type::UntaggedInt8(), zone);
60 Type* int16 = Type::Intersect(
61 Type::Range(f->NewNumber(-0x7FFF), f->NewNumber(0x7FFF-1), zone),
62 Type::UntaggedInt16(), zone);
63 Type* uint8 = Type::Intersect(
64 Type::Range(zero, f->NewNumber(0xFF-1), zone),
65 Type::UntaggedInt8(), zone);
66 Type* uint16 = Type::Intersect(
67 Type::Range(zero, f->NewNumber(0xFFFF-1), zone),
68 Type::UntaggedInt16(), zone);
38 69
39 #define NATIVE_TYPE(sem, rep) \ 70 #define NATIVE_TYPE(sem, rep) \
40 Type::Intersect(Type::sem(zone), Type::rep(zone), zone) 71 Type::Intersect(Type::sem(), Type::rep(), zone)
41 // TODO(rossberg): Use range types for more precision, once we have them.
42 Type* int8 = NATIVE_TYPE(SignedSmall, UntaggedInt8);
43 Type* int16 = NATIVE_TYPE(SignedSmall, UntaggedInt16);
44 Type* int32 = NATIVE_TYPE(Signed32, UntaggedInt32); 72 Type* int32 = NATIVE_TYPE(Signed32, UntaggedInt32);
45 Type* uint8 = NATIVE_TYPE(UnsignedSmall, UntaggedInt8);
46 Type* uint16 = NATIVE_TYPE(UnsignedSmall, UntaggedInt16);
47 Type* uint32 = NATIVE_TYPE(Unsigned32, UntaggedInt32); 73 Type* uint32 = NATIVE_TYPE(Unsigned32, UntaggedInt32);
48 Type* float32 = NATIVE_TYPE(Number, UntaggedFloat32); 74 Type* float32 = NATIVE_TYPE(Number, UntaggedFloat32);
49 Type* float64 = NATIVE_TYPE(Number, UntaggedFloat64); 75 Type* float64 = NATIVE_TYPE(Number, UntaggedFloat64);
50 #undef NATIVE_TYPE 76 #undef NATIVE_TYPE
77
51 Type* buffer = Type::Buffer(zone); 78 Type* buffer = Type::Buffer(zone);
52 Type* int8_array = Type::Array(int8, zone); 79 Type* int8_array = Type::Array(int8, zone);
53 Type* int16_array = Type::Array(int16, zone); 80 Type* int16_array = Type::Array(int16, zone);
54 Type* int32_array = Type::Array(int32, zone); 81 Type* int32_array = Type::Array(int32, zone);
55 Type* uint8_array = Type::Array(uint8, zone); 82 Type* uint8_array = Type::Array(uint8, zone);
56 Type* uint16_array = Type::Array(uint16, zone); 83 Type* uint16_array = Type::Array(uint16, zone);
57 Type* uint32_array = Type::Array(uint32, zone); 84 Type* uint32_array = Type::Array(uint32, zone);
58 Type* float32_array = Type::Array(float32, zone); 85 Type* float32_array = Type::Array(float32, zone);
59 Type* float64_array = Type::Array(float64, zone); 86 Type* float64_array = Type::Array(float64, zone);
60 Type* arg1 = Type::Union(unsigned32, object, zone); 87 Type* arg1 = Type::Union(unsigned32, object, zone);
(...skipping 11 matching lines...) Expand all
72 } 99 }
73 100
74 101
75 class Typer::Visitor : public NullNodeVisitor { 102 class Typer::Visitor : public NullNodeVisitor {
76 public: 103 public:
77 Visitor(Typer* typer, MaybeHandle<Context> context) 104 Visitor(Typer* typer, MaybeHandle<Context> context)
78 : typer_(typer), context_(context) {} 105 : typer_(typer), context_(context) {}
79 106
80 Bounds TypeNode(Node* node) { 107 Bounds TypeNode(Node* node) {
81 switch (node->opcode()) { 108 switch (node->opcode()) {
109 #define DECLARE_CASE(x) \
110 case IrOpcode::k##x: return TypeBinaryOp(node, x##Typer);
111 JS_SIMPLE_BINOP_LIST(DECLARE_CASE)
112 #undef DECLARE_CASE
113
82 #define DECLARE_CASE(x) case IrOpcode::k##x: return Type##x(node); 114 #define DECLARE_CASE(x) case IrOpcode::k##x: return Type##x(node);
83 DECLARE_CASE(Start) 115 DECLARE_CASE(Start)
84 VALUE_OP_LIST(DECLARE_CASE) 116 // VALUE_OP_LIST without JS_SIMPLE_BINOP_LIST:
117 COMMON_OP_LIST(DECLARE_CASE)
118 SIMPLIFIED_OP_LIST(DECLARE_CASE)
119 MACHINE_OP_LIST(DECLARE_CASE)
120 JS_SIMPLE_UNOP_LIST(DECLARE_CASE)
121 JS_OBJECT_OP_LIST(DECLARE_CASE)
122 JS_CONTEXT_OP_LIST(DECLARE_CASE)
123 JS_OTHER_OP_LIST(DECLARE_CASE)
85 #undef DECLARE_CASE 124 #undef DECLARE_CASE
86 125
87 #define DECLARE_CASE(x) case IrOpcode::k##x: 126 #define DECLARE_CASE(x) case IrOpcode::k##x:
88 DECLARE_CASE(End) 127 DECLARE_CASE(End)
89 INNER_CONTROL_OP_LIST(DECLARE_CASE) 128 INNER_CONTROL_OP_LIST(DECLARE_CASE)
90 #undef DECLARE_CASE 129 #undef DECLARE_CASE
91 break; 130 break;
92 } 131 }
93 UNREACHABLE(); 132 UNREACHABLE();
94 return Bounds(); 133 return Bounds();
95 } 134 }
96 135
97 Type* TypeConstant(Handle<Object> value); 136 Type* TypeConstant(Handle<Object> value);
98 137
99 protected: 138 protected:
100 #define DECLARE_METHOD(x) inline Bounds Type##x(Node* node); 139 #define DECLARE_METHOD(x) inline Bounds Type##x(Node* node);
101 DECLARE_METHOD(Start) 140 DECLARE_METHOD(Start)
102 VALUE_OP_LIST(DECLARE_METHOD) 141 VALUE_OP_LIST(DECLARE_METHOD)
103 #undef DECLARE_METHOD 142 #undef DECLARE_METHOD
104 143
105 Bounds OperandType(Node* node, int i) { 144 static Bounds OperandType(Node* node, int i) {
106 return NodeProperties::GetBounds(NodeProperties::GetValueInput(node, i)); 145 return NodeProperties::GetBounds(NodeProperties::GetValueInput(node, i));
107 } 146 }
108 147
109 Type* ContextType(Node* node) { 148 static Type* ContextType(Node* node) {
110 Bounds result = 149 Bounds result =
111 NodeProperties::GetBounds(NodeProperties::GetContextInput(node)); 150 NodeProperties::GetBounds(NodeProperties::GetContextInput(node));
112 DCHECK(result.upper->Maybe(Type::Internal())); 151 DCHECK(result.upper->Maybe(Type::Internal()));
113 // TODO(rossberg): More precisely, instead of the above assertion, we should 152 // TODO(rossberg): More precisely, instead of the above assertion, we should
114 // back-propagate the constraint that it has to be a subtype of Internal. 153 // back-propagate the constraint that it has to be a subtype of Internal.
115 return result.upper; 154 return result.upper;
116 } 155 }
117 156
118 Zone* zone() { return typer_->zone(); } 157 Zone* zone() { return typer_->zone(); }
119 Isolate* isolate() { return typer_->isolate(); } 158 Isolate* isolate() { return typer_->isolate(); }
120 MaybeHandle<Context> context() { return context_; } 159 MaybeHandle<Context> context() { return context_; }
121 160
122 private: 161 private:
123 Typer* typer_; 162 Typer* typer_;
124 MaybeHandle<Context> context_; 163 MaybeHandle<Context> context_;
164
165 typedef Type* (*UnaryTyperFun)(Type*, Typer* t);
rossberg 2014/10/02 11:57:33 Is there a reason why we can't make these Visitor
neis1 2014/10/02 15:29:10 These functions need access to the private members
166 typedef Type* (*BinaryTyperFun)(Type*, Type*, Typer* t);
167
168 Bounds TypeUnaryOp(Node* node, UnaryTyperFun);
169 Bounds TypeBinaryOp(Node* node, BinaryTyperFun);
170
171 static Type* Invert(Type*, Typer*);
172 static Type* FalsifyUndefined(Type*, Typer*);
173
174 static Type* ToPrimitive(Type*, Typer*);
175 static Type* ToBoolean(Type*, Typer*);
176 static Type* ToNumber(Type*, Typer*);
177 static Type* ToString(Type*, Typer*);
178 static Type* NumberToInt32(Type*, Typer*);
179 static Type* NumberToUint32(Type*, Typer*);
180
181 static Type* JSAddRanger(Type::RangeType*, Type::RangeType*, Typer*);
182 static Type* JSSubtractRanger(Type::RangeType*, Type::RangeType*, Typer*);
183 static Type* JSMultiplyRanger(Type::RangeType*, Type::RangeType*, Typer*);
184 static Type* JSDivideRanger(Type::RangeType*, Type::RangeType*, Typer*);
185
186 static Type* JSEqualTyper(Type*, Type*, Typer*);
rossberg 2014/10/02 11:57:33 Can we create this list from macros as well?
neis1 2014/10/02 15:29:10 Done.
187 static Type* JSNotEqualTyper(Type*, Type*, Typer*);
188 static Type* JSStrictEqualTyper(Type*, Type*, Typer*);
189 static Type* JSStrictNotEqualTyper(Type*, Type*, Typer*);
190 static Type* JSCompareTyper(Type*, Type*, Typer*);
191 static Type* JSLessThanTyper(Type*, Type*, Typer*);
192 static Type* JSGreaterThanTyper(Type*, Type*, Typer*);
193 static Type* JSLessThanOrEqualTyper(Type*, Type*, Typer*);
194 static Type* JSGreaterThanOrEqualTyper(Type*, Type*, Typer*);
195 static Type* JSBitwiseOrTyper(Type*, Type*, Typer*);
196 static Type* JSBitwiseAndTyper(Type*, Type*, Typer*);
197 static Type* JSBitwiseXorTyper(Type*, Type*, Typer*);
198 static Type* JSShiftLessTyper(Type*, Type*, Typer*);
199 static Type* JSShiftLeftTyper(Type*, Type*, Typer*);
200 static Type* JSShiftRightTyper(Type*, Type*, Typer*);
201 static Type* JSShiftRightLogicalTyper(Type*, Type*, Typer*);
202 static Type* JSAddTyper(Type*, Type*, Typer*);
203 static Type* JSSubtractTyper(Type*, Type*, Typer*);
204 static Type* JSMultiplyTyper(Type*, Type*, Typer*);
205 static Type* JSDivideTyper(Type*, Type*, Typer*);
206 static Type* JSModulusTyper(Type*, Type*, Typer*);
207 static Type* JSUnaryNotTyper(Type*, Typer*);
208 static Type* JSLoadPropertyTyper(Type*, Type*, Typer*);
209 static Type* JSCallFunctionTyper(Type*, Typer*);
125 }; 210 };
126 211
127 212
128 class Typer::RunVisitor : public Typer::Visitor { 213 class Typer::RunVisitor : public Typer::Visitor {
129 public: 214 public:
130 RunVisitor(Typer* typer, MaybeHandle<Context> context) 215 RunVisitor(Typer* typer, MaybeHandle<Context> context)
131 : Visitor(typer, context), 216 : Visitor(typer, context),
132 redo(NodeSet::key_compare(), NodeSet::allocator_type(typer->zone())) {} 217 redo(NodeSet::key_compare(), NodeSet::allocator_type(typer->zone())) {}
133 218
134 GenericGraphVisit::Control Post(Node* node) { 219 GenericGraphVisit::Control Post(Node* node) {
(...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after
231 Visitor typing(this, MaybeHandle<Context>()); 316 Visitor typing(this, MaybeHandle<Context>());
232 Bounds bounds = typing.TypeNode(node); 317 Bounds bounds = typing.TypeNode(node);
233 NodeProperties::SetBounds(node, bounds); 318 NodeProperties::SetBounds(node, bounds);
234 } 319 }
235 } 320 }
236 321
237 322
238 // ----------------------------------------------------------------------------- 323 // -----------------------------------------------------------------------------
239 324
240 325
326 Bounds Typer::Visitor::TypeUnaryOp(Node* node, UnaryTyperFun f) {
327 Bounds input = OperandType(node, 0);
328 Type* upper = input.upper->Is(Type::None())
329 ? Type::None()
330 : f(input.upper, typer_);
331 Type* lower = input.lower->Is(Type::None())
332 ? Type::None()
333 : (upper->IsConstant() || input.lower == input.upper)
rossberg 2014/10/02 11:57:33 Check the latter condition first.
neis1 2014/10/02 15:29:10 Done.
334 ? upper // TODO(neis): Extend this to Range(x,x), NaN, MinusZero, ...?
335 : f(input.lower, typer_);
336 return Bounds(lower, upper);
337 }
338
339
340 Bounds Typer::Visitor::TypeBinaryOp(Node* node, BinaryTyperFun f) {
341 Bounds left = OperandType(node, 0);
342 Bounds right = OperandType(node, 1);
343 Type* upper = left.upper->Is(Type::None()) || right.upper->Is(Type::None())
344 ? Type::None()
345 : f(left.upper, right.upper, typer_);
346 Type* lower = left.lower->Is(Type::None()) || right.lower->Is(Type::None())
347 ? Type::None()
348 : (upper->IsConstant() ||
349 (left.lower == left.upper && right.lower == right.upper))
350 ? upper
351 : f(left.lower, right.lower, typer_);
352 return Bounds(lower, upper);
353 }
354
355
356 Type* Typer::Visitor::Invert(Type* type, Typer* t) {
357 if (type->Is(t->singleton_false)) return t->singleton_true;
358 if (type->Is(t->singleton_true)) return t->singleton_false;
359 return type;
360 }
361
362
363 Type* Typer::Visitor::FalsifyUndefined(Type* type, Typer* t) {
364 if (type->Is(Type::Undefined())) return t->singleton_false;
365 return type;
366 }
367
368
369 // Type conversion.
370
371
372 Type* Typer::Visitor::ToPrimitive(Type* type, Typer* t) {
373 if (type->Is(Type::Primitive()) && !type->Maybe(Type::Receiver())) {
374 return type;
375 }
376 return Type::Primitive();
377 }
378
379
380 Type* Typer::Visitor::ToBoolean(Type* type, Typer* t) {
381 if (type->Is(Type::Boolean())) return type;
382 if (type->Is(Type::Object())) return t->singleton_true;
rossberg 2014/10/02 11:57:33 Receiver? In fact, you need to distinguish Detecta
neis1 2014/10/02 15:29:10 Right, I meant Receiver. Okay, I wasn't aware of
383 if (type->Is(t->falsish)) return t->singleton_false;
384 if ((type->IsRange() || type->Is(Type::Integral32())) &&
rossberg 2014/10/02 11:57:33 Why doesn't this apply to all numbers?
neis1 2014/10/02 15:29:10 Because of nan (e.g. if type is e.g. SignedSmall|N
385 (type->Max() < 0 || 0 < type->Min())) {
386 return t->singleton_true;
387 }
388 return Type::Boolean();
389 }
390
391
392 Type* Typer::Visitor::ToNumber(Type* type, Typer* t) {
393 if (type->Is(Type::Number())) return type;
394 if (type->Is(Type::Undefined())) return Type::NaN();
395 if (type->Is(t->singleton_false)) return t->singleton_zero;
396 if (type->Is(t->singleton_true)) return t->singleton_one;
397 if (type->Is(Type::Boolean())) return t->zero_or_one;
398 return Type::Number();
399 }
400
401
402 Type* Typer::Visitor::ToString(Type* type, Typer* t) {
403 if (type->Is(Type::String())) return type;
404 return Type::String();
405 }
406
407
408 Type* Typer::Visitor::NumberToInt32(Type* type, Typer* t) {
409 DCHECK(type->Is(Type::Number()));
410 if (type->Is(Type::Signed32())) return type;
411 if (type->Is(t->zeroish)) return t->singleton_zero;
412 return Type::Signed32();
413 }
414
415
416 Type* Typer::Visitor::NumberToUint32(Type* type, Typer* t) {
417 DCHECK(type->Is(Type::Number()));
418 if (type->Is(Type::Unsigned32())) return type;
419 if (type->Is(t->zeroish)) return t->singleton_zero;
420 return Type::Unsigned32();
421 }
422
423
424 // -----------------------------------------------------------------------------
425
426
241 // Control operators. 427 // Control operators.
242 428
429
243 Bounds Typer::Visitor::TypeStart(Node* node) { 430 Bounds Typer::Visitor::TypeStart(Node* node) {
244 return Bounds(Type::Internal(zone())); 431 return Bounds(Type::Internal());
245 } 432 }
246 433
247 434
248 // Common operators. 435 // Common operators.
249 436
437
250 Bounds Typer::Visitor::TypeParameter(Node* node) { 438 Bounds Typer::Visitor::TypeParameter(Node* node) {
251 return Bounds::Unbounded(zone()); 439 return Bounds::Unbounded(zone());
252 } 440 }
253 441
254 442
255 Bounds Typer::Visitor::TypeInt32Constant(Node* node) { 443 Bounds Typer::Visitor::TypeInt32Constant(Node* node) {
256 // TODO(titzer): only call Type::Of() if the type is not already known. 444 Factory* f = zone()->isolate()->factory();
257 return Bounds(Type::Of(OpParameter<int32_t>(node), zone())); 445 Handle<Object> number = f->NewNumber(OpParameter<int32_t>(node));
446 return Bounds(Type::Intersect(
447 Type::Range(number, number, zone()), Type::UntaggedInt32(), zone()));
258 } 448 }
259 449
260 450
261 Bounds Typer::Visitor::TypeInt64Constant(Node* node) { 451 Bounds Typer::Visitor::TypeInt64Constant(Node* node) {
262 // TODO(titzer): only call Type::Of() if the type is not already known. 452 return Bounds(Type::Internal()); // TODO(rossberg): Add int64 bitset type?
263 return Bounds(
264 Type::Of(static_cast<double>(OpParameter<int64_t>(node)), zone()));
265 } 453 }
266 454
267 455
268 Bounds Typer::Visitor::TypeFloat32Constant(Node* node) { 456 Bounds Typer::Visitor::TypeFloat32Constant(Node* node) {
269 // TODO(titzer): only call Type::Of() if the type is not already known. 457 return Bounds(Type::Intersect(
270 return Bounds(Type::Of(OpParameter<float>(node), zone())); 458 Type::Of(OpParameter<float>(node), zone()),
459 Type::UntaggedFloat32(), zone()));
271 } 460 }
272 461
273 462
274 Bounds Typer::Visitor::TypeFloat64Constant(Node* node) { 463 Bounds Typer::Visitor::TypeFloat64Constant(Node* node) {
275 // TODO(titzer): only call Type::Of() if the type is not already known. 464 return Bounds(Type::Intersect(
276 return Bounds(Type::Of(OpParameter<double>(node), zone())); 465 Type::Of(OpParameter<double>(node), zone()),
466 Type::UntaggedFloat64(), zone()));
277 } 467 }
278 468
279 469
280 Bounds Typer::Visitor::TypeNumberConstant(Node* node) { 470 Bounds Typer::Visitor::TypeNumberConstant(Node* node) {
281 // TODO(titzer): only call Type::Of() if the type is not already known. 471 Factory* f = zone()->isolate()->factory();
282 return Bounds(Type::Of(OpParameter<double>(node), zone())); 472 return Bounds(Type::Constant(
473 f->NewNumber(OpParameter<double>(node)), zone()));
283 } 474 }
284 475
285 476
286 Bounds Typer::Visitor::TypeHeapConstant(Node* node) { 477 Bounds Typer::Visitor::TypeHeapConstant(Node* node) {
287 return Bounds(TypeConstant(OpParameter<Unique<Object> >(node).handle())); 478 return Bounds(TypeConstant(OpParameter<Unique<Object> >(node).handle()));
288 } 479 }
289 480
290 481
291 Bounds Typer::Visitor::TypeExternalConstant(Node* node) { 482 Bounds Typer::Visitor::TypeExternalConstant(Node* node) {
292 return Bounds(Type::Internal(zone())); 483 return Bounds(Type::Internal());
293 } 484 }
294 485
295 486
296 Bounds Typer::Visitor::TypePhi(Node* node) { 487 Bounds Typer::Visitor::TypePhi(Node* node) {
297 int arity = OperatorProperties::GetValueInputCount(node->op()); 488 int arity = OperatorProperties::GetValueInputCount(node->op());
298 Bounds bounds = OperandType(node, 0); 489 Bounds bounds = OperandType(node, 0);
299 for (int i = 1; i < arity; ++i) { 490 for (int i = 1; i < arity; ++i) {
300 bounds = Bounds::Either(bounds, OperandType(node, i), zone()); 491 bounds = Bounds::Either(bounds, OperandType(node, i), zone());
301 } 492 }
302 return bounds; 493 return bounds;
(...skipping 18 matching lines...) Expand all
321 } 512 }
322 513
323 514
324 Bounds Typer::Visitor::TypeFinish(Node* node) { 515 Bounds Typer::Visitor::TypeFinish(Node* node) {
325 return OperandType(node, 0); 516 return OperandType(node, 0);
326 } 517 }
327 518
328 519
329 Bounds Typer::Visitor::TypeFrameState(Node* node) { 520 Bounds Typer::Visitor::TypeFrameState(Node* node) {
330 // TODO(rossberg): Ideally FrameState wouldn't have a value output. 521 // TODO(rossberg): Ideally FrameState wouldn't have a value output.
331 return Bounds(Type::Internal(zone())); 522 return Bounds(Type::Internal());
332 } 523 }
333 524
334 525
335 Bounds Typer::Visitor::TypeStateValues(Node* node) { 526 Bounds Typer::Visitor::TypeStateValues(Node* node) {
336 return Bounds(Type::Internal(zone())); 527 return Bounds(Type::Internal());
337 } 528 }
338 529
339 530
340 Bounds Typer::Visitor::TypeCall(Node* node) { 531 Bounds Typer::Visitor::TypeCall(Node* node) {
341 return Bounds::Unbounded(zone()); 532 return Bounds::Unbounded(zone());
342 } 533 }
343 534
344 535
345 Bounds Typer::Visitor::TypeProjection(Node* node) { 536 Bounds Typer::Visitor::TypeProjection(Node* node) {
346 // TODO(titzer): use the output type of the input to determine the bounds. 537 // TODO(titzer): use the output type of the input to determine the bounds.
347 return Bounds::Unbounded(zone()); 538 return Bounds::Unbounded(zone());
348 } 539 }
349 540
350 541
351 // JS comparison operators. 542 // JS comparison operators.
352 543
353 #define DEFINE_METHOD(x) \ 544
354 Bounds Typer::Visitor::Type##x(Node* node) { \ 545 Type* Typer::Visitor::JSEqualTyper(Type* lhs, Type* rhs, Typer* t) {
355 return Bounds(Type::Boolean(zone())); \ 546 if (lhs->Is(Type::NaN()) || rhs->Is(Type::NaN())) return t->singleton_false;
356 } 547 if (lhs->Is(t->undefined_or_null) && rhs->Is(t->undefined_or_null)) {
357 JS_COMPARE_BINOP_LIST(DEFINE_METHOD) 548 return t->singleton_true;
358 #undef DEFINE_METHOD 549 }
550 if (lhs->Is(Type::Number()) && rhs->Is(Type::Number()) &&
551 (lhs->Max() < rhs->Min() || lhs->Min() > rhs->Max())) {
552 return t->singleton_false;
553 }
554 if (lhs->IsConstant() && rhs->Is(lhs)) {
555 // Types are equal and are inhabited only by a single semantic value,
556 // which is not nan due to the earlier check.
557 // TODO(neis): Extend this to Range(x,x), MinusZero, ...?
558 return t->singleton_true;
559 }
560 return Type::Boolean();
561 }
562
563
564 Type* Typer::Visitor::JSNotEqualTyper(Type* lhs, Type* rhs, Typer* t) {
565 return Invert(JSEqualTyper(lhs, rhs, t), t);
566 }
567
568
569 static Type* ESType(Type* type) {
rossberg 2014/10/02 11:57:34 Nit: call this JSType, since JS is what we say eve
neis1 2014/10/02 15:29:10 Done.
570 if (type->Is(Type::Boolean())) return Type::Boolean();
571 if (type->Is(Type::String())) return Type::String();
572 if (type->Is(Type::Number())) return Type::Number();
573 if (type->Is(Type::Undefined())) return Type::Undefined();
574 if (type->Is(Type::Null())) return Type::Null();
575 if (type->Is(Type::Symbol())) return Type::Symbol();
576 if (type->Is(Type::Receiver())) return Type::Receiver(); // ES "Object"
577 return Type::Any();
578 }
579
580
581 Type* Typer::Visitor::JSStrictEqualTyper(Type* lhs, Type* rhs, Typer* t) {
582 if (!ESType(lhs)->Maybe(ESType(rhs))) return t->singleton_false;
583 if (lhs->Is(Type::NaN()) || rhs->Is(Type::NaN())) return t->singleton_false;
584 if (lhs->Is(Type::Number()) && rhs->Is(Type::Number()) &&
585 (lhs->Max() < rhs->Min() || lhs->Min() > rhs->Max())) {
586 return t->singleton_false;
587 }
588 if (lhs->IsConstant() && rhs->Is(lhs)) {
589 // Types are equal and are inhabited only by a single semantic value,
590 // which is not nan due to the earlier check.
591 return t->singleton_true;
592 }
593 return Type::Boolean();
594 }
595
596
597 Type* Typer::Visitor::JSStrictNotEqualTyper(Type* lhs, Type* rhs, Typer* t) {
598 return Invert(JSStrictEqualTyper(lhs, rhs, t), t);
599 }
600
601
602 Type* Typer::Visitor::JSCompareTyper(Type* lhs, Type* rhs, Typer* t) {
rossberg 2014/10/02 11:57:33 Add a comment saying that the comparison is <, ret
neis1 2014/10/02 15:29:10 Done.
603 lhs = ToPrimitive(lhs, t);
604 rhs = ToPrimitive(rhs, t);
605 if (lhs->Maybe(Type::String()) && rhs->Maybe(Type::String())) {
606 return Type::Boolean();
607 }
608 lhs = ToNumber(lhs, t);
609 rhs = ToNumber(rhs, t);
610 if (lhs->Is(Type::NaN()) || rhs->Is(Type::NaN())) return Type::Undefined();
611 if (lhs->IsConstant() && rhs->Is(lhs)) {
612 // Types are equal and are inhabited only by a single semantic value,
613 // which is not NaN due to the previous check.
614 return t->singleton_false;
615 }
616 if (lhs->Min() >= rhs->Max()) return t->singleton_false;
617 if (lhs->Max() < rhs->Min() &&
618 !lhs->Maybe(Type::NaN()) && !rhs->Maybe(Type::NaN())) {
619 return t->singleton_true;
620 }
621 return Type::Boolean();
622 }
623
624
625 Type* Typer::Visitor::JSLessThanTyper(Type* lhs, Type* rhs, Typer* t) {
626 return FalsifyUndefined(JSCompareTyper(lhs, rhs, t), t);
627 }
628
629
630 Type* Typer::Visitor::JSGreaterThanTyper(Type* lhs, Type* rhs, Typer* t) {
631 return FalsifyUndefined(JSCompareTyper(rhs, lhs, t), t);
632 }
633
634
635 Type* Typer::Visitor::JSLessThanOrEqualTyper(Type* lhs, Type* rhs, Typer* t) {
636 return FalsifyUndefined(Invert(JSCompareTyper(rhs, lhs, t), t), t);
637 }
638
639
640 Type* Typer::Visitor::JSGreaterThanOrEqualTyper(
641 Type* lhs, Type* rhs, Typer* t) {
642 return FalsifyUndefined(Invert(JSCompareTyper(lhs, rhs, t), t), t);
643 }
359 644
360 645
361 // JS bitwise operators. 646 // JS bitwise operators.
362 647
363 Bounds Typer::Visitor::TypeJSBitwiseOr(Node* node) { 648
364 Bounds left = OperandType(node, 0); 649 Type* Typer::Visitor::JSBitwiseOrTyper(Type* lhs, Type* rhs, Typer* t) {
rossberg 2014/10/02 11:57:33 Shouldn't these functions also detect the cases wh
neis1 2014/10/02 15:29:10 Yes, that's a natural extension. Added a TODO.
365 Bounds right = OperandType(node, 1); 650 Factory* f = t->zone()->isolate()->factory();
366 Type* upper = Type::Union(left.upper, right.upper, zone()); 651 lhs = NumberToInt32(ToNumber(lhs, t), t);
367 if (!upper->Is(Type::Signed32())) upper = Type::Signed32(zone()); 652 rhs = NumberToInt32(ToNumber(rhs, t), t);
368 Type* lower = Type::Intersect(Type::SignedSmall(zone()), upper, zone()); 653 double lmin = lhs->Min();
369 return Bounds(lower, upper); 654 double rmin = rhs->Min();
370 } 655 double lmax = lhs->Max();
371 656 double rmax = rhs->Max();
372 657 // Or-ing any two values results in a value no smaller than their minimum.
373 Bounds Typer::Visitor::TypeJSBitwiseAnd(Node* node) { 658 // Even no smaller than their maximum if both values are non-negative.
374 Bounds left = OperandType(node, 0); 659 Handle<Object> min = f->NewNumber(
375 Bounds right = OperandType(node, 1); 660 lmin >= 0 && rmin >= 0 ? std::max(lmin, rmin) : std::min(lmin, rmin));
376 Type* upper = Type::Union(left.upper, right.upper, zone()); 661 if (lmax < 0 || rmax < 0) {
377 if (!upper->Is(Type::Signed32())) upper = Type::Signed32(zone()); 662 // Or-ing two values of which at least one is negative results in a negative
378 Type* lower = Type::Intersect(Type::SignedSmall(zone()), upper, zone()); 663 // value.
379 return Bounds(lower, upper); 664 Handle<Object> max = f->NewNumber(-1);
380 } 665 return Type::Range(min, max, t->zone());
381 666 }
382 667 Handle<Object> max = f->NewNumber(Type::Signed32()->Max());
383 Bounds Typer::Visitor::TypeJSBitwiseXor(Node* node) { 668 return Type::Range(min, max, t->zone());
384 return Bounds(Type::SignedSmall(zone()), Type::Signed32(zone())); 669 }
385 } 670
386 671
387 672 Type* Typer::Visitor::JSBitwiseAndTyper(Type* lhs, Type* rhs, Typer* t) {
388 Bounds Typer::Visitor::TypeJSShiftLeft(Node* node) { 673 Factory* f = t->zone()->isolate()->factory();
389 return Bounds(Type::SignedSmall(zone()), Type::Signed32(zone())); 674 lhs = NumberToInt32(ToNumber(lhs, t), t);
390 } 675 rhs = NumberToInt32(ToNumber(rhs, t), t);
391 676 double lmin = lhs->Min();
392 677 double rmin = rhs->Min();
393 Bounds Typer::Visitor::TypeJSShiftRight(Node* node) { 678 double lmax = lhs->Max();
394 return Bounds(Type::SignedSmall(zone()), Type::Signed32(zone())); 679 double rmax = rhs->Max();
395 } 680 // And-ing any two values results in a value no larger than their maximum.
396 681 // Even no larger than their minimum if both values are non-negative.
397 682 Handle<Object> max = f->NewNumber(
398 Bounds Typer::Visitor::TypeJSShiftRightLogical(Node* node) { 683 lmin >= 0 && rmin >= 0 ? std::min(lmax, rmax) : std::max(lmax, rmax));
399 return Bounds(Type::UnsignedSmall(zone()), Type::Unsigned32(zone())); 684 if (lmin >= 0 || rmin >= 0) {
685 // And-ing two values of which at least one is non-negative results in a
686 // non-negative value.
687 Handle<Object> min = f->NewNumber(0);
688 return Type::Range(min, max, t->zone());
689 }
690 Handle<Object> min = f->NewNumber(Type::Signed32()->Min());
691 return Type::Range(min, max, t->zone());
692 }
693
694
695 Type* Typer::Visitor::JSBitwiseXorTyper(Type* lhs, Type* rhs, Typer* t) {
696 lhs = NumberToInt32(ToNumber(lhs, t), t);
697 rhs = NumberToInt32(ToNumber(rhs, t), t);
698 double lmin = lhs->Min();
699 double rmin = rhs->Min();
700 double lmax = lhs->Max();
701 double rmax = rhs->Max();
702 if ((lmin >= 0 && rmin >= 0) || (lmax < 0 && rmax < 0)) {
703 // Xor-ing negative or non-negative values results in a non-negative value.
704 return t->non_negative_signed32;
705 }
706 if ((lmax < 0 && rmin >= 0) || (lmin >= 0 && rmax < 0)) {
707 // Xor-ing a negative and a non-negative value results in a negative value.
708 return t->negative_signed32;
709 }
710 return Type::Signed32();
711 }
712
713
714 Type* Typer::Visitor::JSShiftLeftTyper(Type* lhs, Type* rhs, Typer* t) {
715 return Type::Signed32();
716 }
717
718
719 Type* Typer::Visitor::JSShiftRightTyper(Type* lhs, Type* rhs, Typer* t) {
720 lhs = NumberToInt32(ToNumber(lhs, t), t);
721 Factory* f = t->zone()->isolate()->factory();
722 if (lhs->Min() >= 0) {
723 // Right-shifting a non-negative value cannot make it negative, nor larger.
724 Handle<Object> min = f->NewNumber(0);
725 Handle<Object> max = f->NewNumber(lhs->Max());
726 return Type::Range(min, max, t->zone());
727 }
728 if (lhs->Max() < 0) {
729 // Right-shifting a negative value cannot make it non-negative, nor smaller.
730 Handle<Object> min = f->NewNumber(lhs->Min());
731 Handle<Object> max = f->NewNumber(-1);
732 return Type::Range(min, max, t->zone());
733 }
734 return Type::Signed32();
735 }
736
737
738 Type* Typer::Visitor::JSShiftRightLogicalTyper(Type* lhs, Type* rhs, Typer* t) {
739 lhs = NumberToUint32(ToNumber(lhs, t), t);
740 Factory* f = t->zone()->isolate()->factory();
741 // Logical right-shifting any value cannot make it larger.
742 Handle<Object> min = f->NewNumber(0);
743 Handle<Object> max = f->NewNumber(lhs->Max());
744 return Type::Range(min, max, t->zone());
400 } 745 }
401 746
402 747
403 // JS arithmetic operators. 748 // JS arithmetic operators.
404 749
405 Bounds Typer::Visitor::TypeJSAdd(Node* node) { 750
406 Bounds left = OperandType(node, 0); 751 Type* Typer::Visitor::JSAddTyper(Type* lhs, Type* rhs, Typer* t) {
407 Bounds right = OperandType(node, 1); 752 lhs = ToPrimitive(lhs, t);
408 Type* lower = 753 rhs = ToPrimitive(rhs, t);
409 left.lower->Is(Type::None()) || right.lower->Is(Type::None()) ? 754 if (lhs->Maybe(Type::String()) || rhs->Maybe(Type::String())) {
410 Type::None(zone()) : 755 if (lhs->Is(Type::String()) || rhs->Is(Type::String())) {
411 left.lower->Is(Type::Number()) && right.lower->Is(Type::Number()) ? 756 return Type::String();
412 Type::SignedSmall(zone()) : 757 } else {
413 left.lower->Is(Type::String()) || right.lower->Is(Type::String()) ? 758 return Type::NumberOrString();
414 Type::String(zone()) : Type::None(zone()); 759 }
415 Type* upper = 760 }
416 left.upper->Is(Type::None()) && right.upper->Is(Type::None()) ? 761 lhs = ToNumber(lhs, t);
417 Type::None(zone()) : 762 rhs = ToNumber(rhs, t);
418 left.upper->Is(Type::Number()) && right.upper->Is(Type::Number()) ? 763 if (lhs->Is(Type::NaN()) || rhs->Is(Type::NaN())) return Type::NaN();
419 Type::Number(zone()) : 764 // TODO(neis): Do some analysis.
420 left.upper->Is(Type::String()) || right.upper->Is(Type::String()) ? 765 // TODO(neis): Deal with numeric bitsets here and elsewhere.
421 Type::String(zone()) : Type::NumberOrString(zone()); 766 return Type::Number();
422 return Bounds(lower, upper); 767 }
423 } 768
424 769
425 770 Type* Typer::Visitor::JSSubtractTyper(Type* lhs, Type* rhs, Typer* t) {
426 Bounds Typer::Visitor::TypeJSSubtract(Node* node) { 771 lhs = ToNumber(lhs, t);
427 return Bounds(Type::SignedSmall(zone()), Type::Number(zone())); 772 rhs = ToNumber(rhs, t);
428 } 773 if (lhs->Is(Type::NaN()) || rhs->Is(Type::NaN())) return Type::NaN();
429 774 // TODO(neis): Do some analysis.
430 775 return Type::Number();
431 Bounds Typer::Visitor::TypeJSMultiply(Node* node) { 776 }
432 return Bounds(Type::SignedSmall(zone()), Type::Number(zone())); 777
433 } 778
434 779 Type* Typer::Visitor::JSMultiplyTyper(Type* lhs, Type* rhs, Typer* t) {
435 780 lhs = ToNumber(lhs, t);
436 Bounds Typer::Visitor::TypeJSDivide(Node* node) { 781 rhs = ToNumber(rhs, t);
437 return Bounds(Type::SignedSmall(zone()), Type::Number(zone())); 782 if (lhs->Is(Type::NaN()) || rhs->Is(Type::NaN())) return Type::NaN();
438 } 783 // TODO(neis): Do some analysis.
439 784 return Type::Number();
440 785 }
441 Bounds Typer::Visitor::TypeJSModulus(Node* node) { 786
442 return Bounds(Type::SignedSmall(zone()), Type::Number(zone())); 787
788 Type* Typer::Visitor::JSDivideTyper(Type* lhs, Type* rhs, Typer* t) {
789 lhs = ToNumber(lhs, t);
790 rhs = ToNumber(rhs, t);
791 if (lhs->Is(Type::NaN()) || rhs->Is(Type::NaN())) return Type::NaN();
792 // TODO(neis): Do some analysis.
793 return Type::Number();
794 }
795
796
797 Type* Typer::Visitor::JSModulusTyper(Type* lhs, Type* rhs, Typer* t) {
798 lhs = ToNumber(lhs, t);
799 rhs = ToNumber(rhs, t);
800 if (lhs->Is(Type::NaN()) || rhs->Is(Type::NaN())) return Type::NaN();
801 // TODO(neis): Do some analysis.
802 return Type::Number();
443 } 803 }
444 804
445 805
446 // JS unary operators. 806 // JS unary operators.
447 807
808
809 Type* Typer::Visitor::JSUnaryNotTyper(Type* type, Typer* t) {
810 return Invert(ToBoolean(type, t), t);
811 }
812
813
448 Bounds Typer::Visitor::TypeJSUnaryNot(Node* node) { 814 Bounds Typer::Visitor::TypeJSUnaryNot(Node* node) {
449 return Bounds(Type::Boolean(zone())); 815 return TypeUnaryOp(node, JSUnaryNotTyper);
450 } 816 }
451 817
452 818
453 Bounds Typer::Visitor::TypeJSTypeOf(Node* node) { 819 Bounds Typer::Visitor::TypeJSTypeOf(Node* node) {
454 return Bounds(Type::InternalizedString(zone())); 820 return Bounds(Type::InternalizedString());
455 } 821 }
456 822
457 823
458 // JS conversion operators. 824 // JS conversion operators.
459 825
826
460 Bounds Typer::Visitor::TypeJSToBoolean(Node* node) { 827 Bounds Typer::Visitor::TypeJSToBoolean(Node* node) {
461 return Bounds(Type::Boolean(zone())); 828 return TypeUnaryOp(node, ToBoolean);
462 } 829 }
463 830
464 831
465 Bounds Typer::Visitor::TypeJSToNumber(Node* node) { 832 Bounds Typer::Visitor::TypeJSToNumber(Node* node) {
466 return Bounds(Type::SignedSmall(zone()), Type::Number(zone())); 833 return TypeUnaryOp(node, ToNumber);
467 } 834 }
468 835
469 836
470 Bounds Typer::Visitor::TypeJSToString(Node* node) { 837 Bounds Typer::Visitor::TypeJSToString(Node* node) {
471 return Bounds(Type::None(zone()), Type::String(zone())); 838 return TypeUnaryOp(node, ToString);
472 } 839 }
473 840
474 841
475 Bounds Typer::Visitor::TypeJSToName(Node* node) { 842 Bounds Typer::Visitor::TypeJSToName(Node* node) {
476 return Bounds(Type::None(zone()), Type::Name(zone())); 843 return Bounds(Type::None(), Type::Name());
477 } 844 }
478 845
479 846
480 Bounds Typer::Visitor::TypeJSToObject(Node* node) { 847 Bounds Typer::Visitor::TypeJSToObject(Node* node) {
481 return Bounds(Type::None(zone()), Type::Receiver(zone())); 848 return Bounds(Type::None(), Type::Receiver());
482 } 849 }
483 850
484 851
485 // JS object operators. 852 // JS object operators.
486 853
854
487 Bounds Typer::Visitor::TypeJSCreate(Node* node) { 855 Bounds Typer::Visitor::TypeJSCreate(Node* node) {
488 return Bounds(Type::None(zone()), Type::Object(zone())); 856 return Bounds(Type::None(), Type::Object());
857 }
858
859
860 Type* Typer::Visitor::JSLoadPropertyTyper(Type* object, Type* name, Typer* t) {
861 // TODO(rossberg): Use range types and sized array types to filter undefined.
862 if (object->IsArray() && name->Is(Type::Integral32())) {
863 return Type::Union(
864 object->AsArray()->Element(), Type::Undefined(), t->zone());
865 }
866 return Type::Any();
489 } 867 }
490 868
491 869
492 Bounds Typer::Visitor::TypeJSLoadProperty(Node* node) { 870 Bounds Typer::Visitor::TypeJSLoadProperty(Node* node) {
493 Bounds object = OperandType(node, 0); 871 return TypeBinaryOp(node, JSLoadPropertyTyper);
rossberg 2014/10/02 11:57:33 This doesn't seem right. The lower bound would bec
neis1 2014/10/02 15:29:11 Yep, I expected this complaint. I don't really un
494 Bounds name = OperandType(node, 1); 872 }
495 Bounds result = Bounds::Unbounded(zone()); 873
496 // TODO(rossberg): Use range types and sized array types to filter undefined. 874
497 if (object.lower->IsArray() && name.lower->Is(Type::Integral32())) {
498 result.lower = Type::Union(
499 object.lower->AsArray()->Element(), Type::Undefined(zone()), zone());
500 }
501 if (object.upper->IsArray() && name.upper->Is(Type::Integral32())) {
502 result.upper = Type::Union(
503 object.upper->AsArray()->Element(), Type::Undefined(zone()), zone());
504 }
505 return result;
506 }
507
508
509 Bounds Typer::Visitor::TypeJSLoadNamed(Node* node) { 875 Bounds Typer::Visitor::TypeJSLoadNamed(Node* node) {
510 return Bounds::Unbounded(zone()); 876 return Bounds::Unbounded(zone());
511 } 877 }
512 878
513 879
514 Bounds Typer::Visitor::TypeJSStoreProperty(Node* node) { 880 Bounds Typer::Visitor::TypeJSStoreProperty(Node* node) {
515 UNREACHABLE(); 881 UNREACHABLE();
516 return Bounds(); 882 return Bounds();
517 } 883 }
518 884
519 885
520 Bounds Typer::Visitor::TypeJSStoreNamed(Node* node) { 886 Bounds Typer::Visitor::TypeJSStoreNamed(Node* node) {
521 UNREACHABLE(); 887 UNREACHABLE();
522 return Bounds(); 888 return Bounds();
523 } 889 }
524 890
525 891
526 Bounds Typer::Visitor::TypeJSDeleteProperty(Node* node) { 892 Bounds Typer::Visitor::TypeJSDeleteProperty(Node* node) {
527 return Bounds(Type::Boolean(zone())); 893 return Bounds(Type::Boolean());
528 } 894 }
529 895
530 896
531 Bounds Typer::Visitor::TypeJSHasProperty(Node* node) { 897 Bounds Typer::Visitor::TypeJSHasProperty(Node* node) {
532 return Bounds(Type::Boolean(zone())); 898 return Bounds(Type::Boolean());
533 } 899 }
534 900
535 901
536 Bounds Typer::Visitor::TypeJSInstanceOf(Node* node) { 902 Bounds Typer::Visitor::TypeJSInstanceOf(Node* node) {
537 return Bounds(Type::Boolean(zone())); 903 return Bounds(Type::Boolean());
538 } 904 }
539 905
540 906
541 // JS context operators. 907 // JS context operators.
542 908
909
543 Bounds Typer::Visitor::TypeJSLoadContext(Node* node) { 910 Bounds Typer::Visitor::TypeJSLoadContext(Node* node) {
544 Bounds outer = OperandType(node, 0); 911 Bounds outer = OperandType(node, 0);
545 DCHECK(outer.upper->Maybe(Type::Internal())); 912 DCHECK(outer.upper->Maybe(Type::Internal()));
546 // TODO(rossberg): More precisely, instead of the above assertion, we should 913 // TODO(rossberg): More precisely, instead of the above assertion, we should
547 // back-propagate the constraint that it has to be a subtype of Internal. 914 // back-propagate the constraint that it has to be a subtype of Internal.
548 915
549 ContextAccess access = OpParameter<ContextAccess>(node); 916 ContextAccess access = OpParameter<ContextAccess>(node);
550 Type* context_type = outer.upper; 917 Type* context_type = outer.upper;
551 MaybeHandle<Context> context; 918 MaybeHandle<Context> context;
552 if (context_type->IsConstant()) { 919 if (context_type->IsConstant()) {
(...skipping 14 matching lines...) Expand all
567 context = handle(context.ToHandleChecked()->previous(), isolate()); 934 context = handle(context.ToHandleChecked()->previous(), isolate());
568 } 935 }
569 } 936 }
570 if (context.is_null()) { 937 if (context.is_null()) {
571 return Bounds::Unbounded(zone()); 938 return Bounds::Unbounded(zone());
572 } else { 939 } else {
573 Handle<Object> value = 940 Handle<Object> value =
574 handle(context.ToHandleChecked()->get(static_cast<int>(access.index())), 941 handle(context.ToHandleChecked()->get(static_cast<int>(access.index())),
575 isolate()); 942 isolate());
576 Type* lower = TypeConstant(value); 943 Type* lower = TypeConstant(value);
577 return Bounds(lower, Type::Any(zone())); 944 return Bounds(lower, Type::Any());
578 } 945 }
579 } 946 }
580 947
581 948
582 Bounds Typer::Visitor::TypeJSStoreContext(Node* node) { 949 Bounds Typer::Visitor::TypeJSStoreContext(Node* node) {
583 UNREACHABLE(); 950 UNREACHABLE();
584 return Bounds(); 951 return Bounds();
585 } 952 }
586 953
587 954
(...skipping 29 matching lines...) Expand all
617 984
618 985
619 Bounds Typer::Visitor::TypeJSCreateGlobalContext(Node* node) { 986 Bounds Typer::Visitor::TypeJSCreateGlobalContext(Node* node) {
620 Type* outer = ContextType(node); 987 Type* outer = ContextType(node);
621 return Bounds(Type::Context(outer, zone())); 988 return Bounds(Type::Context(outer, zone()));
622 } 989 }
623 990
624 991
625 // JS other operators. 992 // JS other operators.
626 993
994
627 Bounds Typer::Visitor::TypeJSYield(Node* node) { 995 Bounds Typer::Visitor::TypeJSYield(Node* node) {
628 return Bounds::Unbounded(zone()); 996 return Bounds::Unbounded(zone());
629 } 997 }
630 998
631 999
632 Bounds Typer::Visitor::TypeJSCallConstruct(Node* node) { 1000 Bounds Typer::Visitor::TypeJSCallConstruct(Node* node) {
633 return Bounds(Type::None(zone()), Type::Receiver(zone())); 1001 return Bounds(Type::None(), Type::Receiver());
1002 }
1003
1004
1005 Type* Typer::Visitor::JSCallFunctionTyper(Type* fun, Typer* t) {
1006 return fun->IsFunction() ? fun->AsFunction()->Result() : Type::Any();
634 } 1007 }
635 1008
636 1009
637 Bounds Typer::Visitor::TypeJSCallFunction(Node* node) { 1010 Bounds Typer::Visitor::TypeJSCallFunction(Node* node) {
638 Bounds fun = OperandType(node, 0); 1011 return TypeUnaryOp(node, JSCallFunctionTyper); // We ignore argument types.
rossberg 2014/10/02 11:57:33 Same here.
639 Type* lower = fun.lower->IsFunction()
640 ? fun.lower->AsFunction()->Result() : Type::None(zone());
641 Type* upper = fun.upper->IsFunction()
642 ? fun.upper->AsFunction()->Result() : Type::Any(zone());
643 return Bounds(lower, upper);
644 } 1012 }
645 1013
646 1014
647 Bounds Typer::Visitor::TypeJSCallRuntime(Node* node) { 1015 Bounds Typer::Visitor::TypeJSCallRuntime(Node* node) {
648 return Bounds::Unbounded(zone()); 1016 return Bounds::Unbounded(zone());
649 } 1017 }
650 1018
651 1019
652 Bounds Typer::Visitor::TypeJSDebugger(Node* node) { 1020 Bounds Typer::Visitor::TypeJSDebugger(Node* node) {
653 return Bounds::Unbounded(zone()); 1021 return Bounds::Unbounded(zone());
654 } 1022 }
655 1023
656 1024
657 // Simplified operators. 1025 // Simplified operators.
658 1026
1027
659 Bounds Typer::Visitor::TypeBooleanNot(Node* node) { 1028 Bounds Typer::Visitor::TypeBooleanNot(Node* node) {
660 return Bounds(Type::Boolean(zone())); 1029 return Bounds(Type::Boolean());
661 } 1030 }
662 1031
663 1032
664 Bounds Typer::Visitor::TypeBooleanToNumber(Node* node) { 1033 Bounds Typer::Visitor::TypeBooleanToNumber(Node* node) {
665 return Bounds(Type::Number(zone())); 1034 return Bounds(Type::Number());
666 } 1035 }
667 1036
668 1037
669 Bounds Typer::Visitor::TypeNumberEqual(Node* node) { 1038 Bounds Typer::Visitor::TypeNumberEqual(Node* node) {
670 return Bounds(Type::Boolean(zone())); 1039 return Bounds(Type::Boolean());
671 } 1040 }
672 1041
673 1042
674 Bounds Typer::Visitor::TypeNumberLessThan(Node* node) { 1043 Bounds Typer::Visitor::TypeNumberLessThan(Node* node) {
675 return Bounds(Type::Boolean(zone())); 1044 return Bounds(Type::Boolean());
676 } 1045 }
677 1046
678 1047
679 Bounds Typer::Visitor::TypeNumberLessThanOrEqual(Node* node) { 1048 Bounds Typer::Visitor::TypeNumberLessThanOrEqual(Node* node) {
680 return Bounds(Type::Boolean(zone())); 1049 return Bounds(Type::Boolean());
681 } 1050 }
682 1051
683 1052
684 Bounds Typer::Visitor::TypeNumberAdd(Node* node) { 1053 Bounds Typer::Visitor::TypeNumberAdd(Node* node) {
685 return Bounds(Type::Number(zone())); 1054 return Bounds(Type::Number());
686 } 1055 }
687 1056
688 1057
689 Bounds Typer::Visitor::TypeNumberSubtract(Node* node) { 1058 Bounds Typer::Visitor::TypeNumberSubtract(Node* node) {
690 return Bounds(Type::Number(zone())); 1059 return Bounds(Type::Number());
691 } 1060 }
692 1061
693 1062
694 Bounds Typer::Visitor::TypeNumberMultiply(Node* node) { 1063 Bounds Typer::Visitor::TypeNumberMultiply(Node* node) {
695 return Bounds(Type::Number(zone())); 1064 return Bounds(Type::Number());
696 } 1065 }
697 1066
698 1067
699 Bounds Typer::Visitor::TypeNumberDivide(Node* node) { 1068 Bounds Typer::Visitor::TypeNumberDivide(Node* node) {
700 return Bounds(Type::Number(zone())); 1069 return Bounds(Type::Number());
701 } 1070 }
702 1071
703 1072
704 Bounds Typer::Visitor::TypeNumberModulus(Node* node) { 1073 Bounds Typer::Visitor::TypeNumberModulus(Node* node) {
705 return Bounds(Type::Number(zone())); 1074 return Bounds(Type::Number());
706 } 1075 }
707 1076
708 1077
709 Bounds Typer::Visitor::TypeNumberToInt32(Node* node) { 1078 Bounds Typer::Visitor::TypeNumberToInt32(Node* node) {
710 Bounds arg = OperandType(node, 0); 1079 return TypeUnaryOp(node, NumberToInt32);
711 Type* s32 = Type::Signed32(zone());
712 Type* lower = arg.lower->Is(s32) ? arg.lower : s32;
713 Type* upper = arg.upper->Is(s32) ? arg.upper : s32;
714 return Bounds(lower, upper);
715 } 1080 }
716 1081
717 1082
718 Bounds Typer::Visitor::TypeNumberToUint32(Node* node) { 1083 Bounds Typer::Visitor::TypeNumberToUint32(Node* node) {
719 Bounds arg = OperandType(node, 0); 1084 return TypeUnaryOp(node, NumberToUint32);
720 Type* u32 = Type::Unsigned32(zone());
721 Type* lower = arg.lower->Is(u32) ? arg.lower : u32;
722 Type* upper = arg.upper->Is(u32) ? arg.upper : u32;
723 return Bounds(lower, upper);
724 } 1085 }
725 1086
726 1087
727 Bounds Typer::Visitor::TypeReferenceEqual(Node* node) { 1088 Bounds Typer::Visitor::TypeReferenceEqual(Node* node) {
728 return Bounds(Type::Boolean(zone())); 1089 return Bounds(Type::Boolean());
729 } 1090 }
730 1091
731 1092
732 Bounds Typer::Visitor::TypeStringEqual(Node* node) { 1093 Bounds Typer::Visitor::TypeStringEqual(Node* node) {
733 return Bounds(Type::Boolean(zone())); 1094 return Bounds(Type::Boolean());
734 } 1095 }
735 1096
736 1097
737 Bounds Typer::Visitor::TypeStringLessThan(Node* node) { 1098 Bounds Typer::Visitor::TypeStringLessThan(Node* node) {
738 return Bounds(Type::Boolean(zone())); 1099 return Bounds(Type::Boolean());
739 } 1100 }
740 1101
741 1102
742 Bounds Typer::Visitor::TypeStringLessThanOrEqual(Node* node) { 1103 Bounds Typer::Visitor::TypeStringLessThanOrEqual(Node* node) {
743 return Bounds(Type::Boolean(zone())); 1104 return Bounds(Type::Boolean());
744 } 1105 }
745 1106
746 1107
747 Bounds Typer::Visitor::TypeStringAdd(Node* node) { 1108 Bounds Typer::Visitor::TypeStringAdd(Node* node) {
748 return Bounds(Type::String(zone())); 1109 return Bounds(Type::String());
1110 }
1111
1112
1113 static Type* ChangeRepresentation(Type* type, Type* rep, Zone* zone) {
1114 // TODO(neis): Enable when expressible.
1115 /*
1116 return Type::Union(
1117 Type::Intersect(type, Type::Semantic(), zone),
1118 Type::Intersect(rep, Type::Representation(), zone), zone);
1119 */
1120 return type;
749 } 1121 }
750 1122
751 1123
752 Bounds Typer::Visitor::TypeChangeTaggedToInt32(Node* node) { 1124 Bounds Typer::Visitor::TypeChangeTaggedToInt32(Node* node) {
753 // TODO(titzer): type is type of input, representation is Word32. 1125 Bounds arg = OperandType(node, 0);
754 return Bounds(Type::Integral32()); 1126 DCHECK(arg.upper->Is(Type::Signed32()));
1127 return Bounds(
1128 ChangeRepresentation(arg.lower, Type::UntaggedInt32(), zone()),
1129 ChangeRepresentation(arg.upper, Type::UntaggedInt32(), zone()));
755 } 1130 }
756 1131
757 1132
758 Bounds Typer::Visitor::TypeChangeTaggedToUint32(Node* node) { 1133 Bounds Typer::Visitor::TypeChangeTaggedToUint32(Node* node) {
759 return Bounds(Type::Integral32()); // TODO(titzer): add appropriate rep 1134 Bounds arg = OperandType(node, 0);
1135 DCHECK(arg.upper->Is(Type::Unsigned32()));
1136 return Bounds(
1137 ChangeRepresentation(arg.lower, Type::UntaggedInt32(), zone()),
1138 ChangeRepresentation(arg.upper, Type::UntaggedInt32(), zone()));
760 } 1139 }
761 1140
762 1141
763 Bounds Typer::Visitor::TypeChangeTaggedToFloat64(Node* node) { 1142 Bounds Typer::Visitor::TypeChangeTaggedToFloat64(Node* node) {
764 // TODO(titzer): type is type of input, representation is Float64. 1143 Bounds arg = OperandType(node, 0);
765 return Bounds(Type::Number()); 1144 DCHECK(arg.upper->Is(Type::Number()));
1145 return Bounds(
1146 ChangeRepresentation(arg.lower, Type::UntaggedFloat64(), zone()),
1147 ChangeRepresentation(arg.upper, Type::UntaggedFloat64(), zone()));
766 } 1148 }
767 1149
768 1150
769 Bounds Typer::Visitor::TypeChangeInt32ToTagged(Node* node) { 1151 Bounds Typer::Visitor::TypeChangeInt32ToTagged(Node* node) {
770 // TODO(titzer): type is type of input, representation is Tagged. 1152 Bounds arg = OperandType(node, 0);
771 return Bounds(Type::Integral32()); 1153 DCHECK(arg.upper->Is(Type::Signed32()));
1154 return Bounds(
1155 ChangeRepresentation(arg.lower, Type::Tagged(), zone()),
1156 ChangeRepresentation(arg.upper, Type::Tagged(), zone()));
772 } 1157 }
773 1158
774 1159
775 Bounds Typer::Visitor::TypeChangeUint32ToTagged(Node* node) { 1160 Bounds Typer::Visitor::TypeChangeUint32ToTagged(Node* node) {
776 // TODO(titzer): type is type of input, representation is Tagged. 1161 Bounds arg = OperandType(node, 0);
777 return Bounds(Type::Unsigned32()); 1162 DCHECK(arg.upper->Is(Type::Unsigned32()));
1163 return Bounds(
1164 ChangeRepresentation(arg.lower, Type::Tagged(), zone()),
1165 ChangeRepresentation(arg.upper, Type::Tagged(), zone()));
778 } 1166 }
779 1167
780 1168
781 Bounds Typer::Visitor::TypeChangeFloat64ToTagged(Node* node) { 1169 Bounds Typer::Visitor::TypeChangeFloat64ToTagged(Node* node) {
782 // TODO(titzer): type is type of input, representation is Tagged. 1170 Bounds arg = OperandType(node, 0);
783 return Bounds(Type::Number()); 1171 // CHECK(arg.upper->Is(Type::Number()));
1172 // TODO(neis): This check currently fails due to inconsistent typing.
1173 return Bounds(
1174 ChangeRepresentation(arg.lower, Type::Tagged(), zone()),
1175 ChangeRepresentation(arg.upper, Type::Tagged(), zone()));
784 } 1176 }
785 1177
786 1178
787 Bounds Typer::Visitor::TypeChangeBoolToBit(Node* node) { 1179 Bounds Typer::Visitor::TypeChangeBoolToBit(Node* node) {
788 // TODO(titzer): type is type of input, representation is Bit. 1180 Bounds arg = OperandType(node, 0);
789 return Bounds(Type::Boolean()); 1181 DCHECK(arg.upper->Is(Type::Boolean()));
1182 return Bounds(
1183 ChangeRepresentation(arg.lower, Type::UntaggedInt1(), zone()),
1184 ChangeRepresentation(arg.upper, Type::UntaggedInt1(), zone()));
790 } 1185 }
791 1186
792 1187
793 Bounds Typer::Visitor::TypeChangeBitToBool(Node* node) { 1188 Bounds Typer::Visitor::TypeChangeBitToBool(Node* node) {
794 // TODO(titzer): type is type of input, representation is Tagged. 1189 Bounds arg = OperandType(node, 0);
795 return Bounds(Type::Boolean()); 1190 DCHECK(arg.upper->Is(Type::Boolean()));
1191 return Bounds(
1192 ChangeRepresentation(arg.lower, Type::TaggedPtr(), zone()),
1193 ChangeRepresentation(arg.upper, Type::TaggedPtr(), zone()));
796 } 1194 }
797 1195
798 1196
799 Bounds Typer::Visitor::TypeLoadField(Node* node) { 1197 Bounds Typer::Visitor::TypeLoadField(Node* node) {
800 return Bounds(FieldAccessOf(node->op()).type); 1198 return Bounds(FieldAccessOf(node->op()).type);
801 } 1199 }
802 1200
803 1201
804 Bounds Typer::Visitor::TypeLoadElement(Node* node) { 1202 Bounds Typer::Visitor::TypeLoadElement(Node* node) {
805 return Bounds(ElementAccessOf(node->op()).type); 1203 return Bounds(ElementAccessOf(node->op()).type);
806 } 1204 }
807 1205
808 1206
809 Bounds Typer::Visitor::TypeStoreField(Node* node) { 1207 Bounds Typer::Visitor::TypeStoreField(Node* node) {
810 UNREACHABLE(); 1208 UNREACHABLE();
811 return Bounds(); 1209 return Bounds();
812 } 1210 }
813 1211
814 1212
815 Bounds Typer::Visitor::TypeStoreElement(Node* node) { 1213 Bounds Typer::Visitor::TypeStoreElement(Node* node) {
816 UNREACHABLE(); 1214 UNREACHABLE();
817 return Bounds(); 1215 return Bounds();
818 } 1216 }
819 1217
820 1218
821 // Machine operators. 1219 // Machine operators.
822 1220
1221
823 // TODO(rossberg): implement 1222 // TODO(rossberg): implement
824 #define DEFINE_METHOD(x) \ 1223 #define DEFINE_METHOD(x) \
825 Bounds Typer::Visitor::Type##x(Node* node) { return Bounds(Type::None()); } 1224 Bounds Typer::Visitor::Type##x(Node* node) { \
1225 return Bounds::Unbounded(zone()); \
1226 }
826 MACHINE_OP_LIST(DEFINE_METHOD) 1227 MACHINE_OP_LIST(DEFINE_METHOD)
827 #undef DEFINE_METHOD 1228 #undef DEFINE_METHOD
828 1229
829 1230
830 // Heap constants. 1231 // Heap constants.
831 1232
832 Type* Typer::Visitor::TypeConstant(Handle<Object> value) { 1233 Type* Typer::Visitor::TypeConstant(Handle<Object> value) {
833 if (value->IsJSFunction() && JSFunction::cast(*value)->IsBuiltin() && 1234 if (value->IsJSFunction() && JSFunction::cast(*value)->IsBuiltin() &&
834 !context().is_null()) { 1235 !context().is_null()) {
835 Handle<Context> native = 1236 Handle<Context> native =
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after
906 } 1307 }
907 1308
908 1309
909 void Typer::DecorateGraph(Graph* graph) { 1310 void Typer::DecorateGraph(Graph* graph) {
910 graph->AddDecorator(new (zone()) TyperDecorator(this)); 1311 graph->AddDecorator(new (zone()) TyperDecorator(this));
911 } 1312 }
912 1313
913 } 1314 }
914 } 1315 }
915 } // namespace v8::internal::compiler 1316 } // namespace v8::internal::compiler
OLDNEW
« no previous file with comments | « src/compiler/typer.h ('k') | test/cctest/compiler/test-js-constant-cache.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698