OLD | NEW |
---|---|
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 |
OLD | NEW |