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