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