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