| 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/typer.h" |
| 6 |
| 5 #include "src/base/flags.h" | 7 #include "src/base/flags.h" |
| 8 #include "src/base/lazy-instance.h" |
| 6 #include "src/bootstrapper.h" | 9 #include "src/bootstrapper.h" |
| 7 #include "src/compiler/graph-reducer.h" | 10 #include "src/compiler/graph-reducer.h" |
| 8 #include "src/compiler/js-operator.h" | 11 #include "src/compiler/js-operator.h" |
| 9 #include "src/compiler/node.h" | 12 #include "src/compiler/node.h" |
| 10 #include "src/compiler/node-properties.h" | 13 #include "src/compiler/node-properties.h" |
| 11 #include "src/compiler/simplified-operator.h" | 14 #include "src/compiler/simplified-operator.h" |
| 12 #include "src/compiler/typer.h" | |
| 13 | 15 |
| 14 namespace v8 { | 16 namespace v8 { |
| 15 namespace internal { | 17 namespace internal { |
| 16 namespace compiler { | 18 namespace compiler { |
| 17 | 19 |
| 18 #define NATIVE_TYPES(V) \ | 20 class TyperCache final { |
| 19 V(Int8) \ | 21 private: |
| 20 V(Uint8) \ | 22 // This has to be first for the initialization magic to work. |
| 21 V(Int16) \ | 23 Zone zone_; |
| 22 V(Uint16) \ | |
| 23 V(Int32) \ | |
| 24 V(Uint32) \ | |
| 25 V(Float32) \ | |
| 26 V(Float64) | |
| 27 | 24 |
| 28 enum LazyCachedType { | 25 public: |
| 29 kInteger, | 26 TyperCache() = default; |
| 30 kWeakint, | |
| 31 kWeakintFunc1, | |
| 32 kRandomFunc0, | |
| 33 kAnyFunc0, | |
| 34 kAnyFunc1, | |
| 35 kAnyFunc2, | |
| 36 kAnyFunc3, | |
| 37 kNumberFunc0, | |
| 38 kNumberFunc1, | |
| 39 kNumberFunc2, | |
| 40 kImulFunc, | |
| 41 kClz32Func, | |
| 42 kArrayBufferFunc, | |
| 43 #define TYPED_ARRAY_CASE(Type, type, TYPE, ctype, size) \ | |
| 44 k##Type, k##Type##Array, k##Type##ArrayFunc, | |
| 45 TYPED_ARRAYS(TYPED_ARRAY_CASE) | |
| 46 #undef TYPED_ARRAY_CASE | |
| 47 kNumLazyCachedTypes | |
| 48 }; | |
| 49 | 27 |
| 28 Type* const kInt8 = |
| 29 CreateNative(CreateRange<int8_t>(), Type::UntaggedSigned8()); |
| 30 Type* const kUint8 = |
| 31 CreateNative(CreateRange<uint8_t>(), Type::UntaggedUnsigned8()); |
| 32 Type* const kUint8Clamped = kUint8; |
| 33 Type* const kInt16 = |
| 34 CreateNative(CreateRange<int16_t>(), Type::UntaggedSigned16()); |
| 35 Type* const kUint16 = |
| 36 CreateNative(CreateRange<uint16_t>(), Type::UntaggedUnsigned16()); |
| 37 Type* const kInt32 = CreateNative(Type::Signed32(), Type::UntaggedSigned32()); |
| 38 Type* const kUint32 = |
| 39 CreateNative(Type::Unsigned32(), Type::UntaggedUnsigned32()); |
| 40 Type* const kFloat32 = CreateNative(Type::Number(), Type::UntaggedFloat32()); |
| 41 Type* const kFloat64 = CreateNative(Type::Number(), Type::UntaggedFloat64()); |
| 50 | 42 |
| 51 // Constructs and caches types lazily. | 43 Type* const kSingletonZero = CreateRange(0.0, 0.0); |
| 52 // TODO(turbofan): these types could be globally cached or cached per isolate. | 44 Type* const kSingletonOne = CreateRange(1.0, 1.0); |
| 53 class LazyTypeCache final : public ZoneObject { | 45 Type* const kZeroOrOne = CreateRange(0.0, 1.0); |
| 54 public: | 46 Type* const kZeroish = |
| 55 explicit LazyTypeCache(Isolate* isolate, Zone* zone) | 47 Type::Union(kSingletonZero, Type::MinusZeroOrNaN(), zone()); |
| 56 : isolate_(isolate), zone_(zone) { | 48 Type* const kInteger = CreateRange(-V8_INFINITY, V8_INFINITY); |
| 57 memset(cache_, 0, sizeof(cache_)); | 49 Type* const kWeakint = Type::Union(kInteger, Type::MinusZeroOrNaN(), zone()); |
| 58 } | 50 Type* const kWeakintFunc1 = Type::Function(kWeakint, Type::Number(), zone()); |
| 59 | 51 |
| 60 V8_INLINE Type* Get(LazyCachedType type) { | 52 Type* const kRandomFunc0 = Type::Function(Type::OrderedNumber(), zone()); |
| 61 int const index = static_cast<int>(type); | 53 Type* const kAnyFunc0 = Type::Function(Type::Any(), zone()); |
| 62 DCHECK_LT(index, kNumLazyCachedTypes); | 54 Type* const kAnyFunc1 = Type::Function(Type::Any(), Type::Any(), zone()); |
| 63 if (cache_[index] == NULL) cache_[index] = Create(type); | 55 Type* const kAnyFunc2 = |
| 64 return cache_[index]; | 56 Type::Function(Type::Any(), Type::Any(), Type::Any(), zone()); |
| 65 } | 57 Type* const kAnyFunc3 = Type::Function(Type::Any(), Type::Any(), Type::Any(), |
| 58 Type::Any(), zone()); |
| 59 Type* const kNumberFunc0 = Type::Function(Type::Number(), zone()); |
| 60 Type* const kNumberFunc1 = |
| 61 Type::Function(Type::Number(), Type::Number(), zone()); |
| 62 Type* const kNumberFunc2 = |
| 63 Type::Function(Type::Number(), Type::Number(), Type::Number(), zone()); |
| 64 Type* const kImulFunc = Type::Function(Type::Signed32(), Type::Integral32(), |
| 65 Type::Integral32(), zone()); |
| 66 Type* const kClz32Func = |
| 67 Type::Function(CreateRange(0, 32), Type::Number(), zone()); |
| 68 Type* const kArrayBufferFunc = |
| 69 Type::Function(Type::Object(zone()), Type::Unsigned32(), zone()); |
| 70 |
| 71 #define TYPED_ARRAY(TypeName, type_name, TYPE_NAME, ctype, size) \ |
| 72 Type* const k##TypeName##Array = CreateArray(k##TypeName); \ |
| 73 Type* const k##TypeName##ArrayFunc = CreateArrayFunction(k##TypeName##Array); |
| 74 TYPED_ARRAYS(TYPED_ARRAY) |
| 75 #undef TYPED_ARRAY |
| 66 | 76 |
| 67 private: | 77 private: |
| 68 Type* Create(LazyCachedType type) { | 78 Type* CreateArray(Type* element) { return Type::Array(element, zone()); } |
| 69 switch (type) { | |
| 70 case kInt8: | |
| 71 return CreateNative(CreateRange<int8_t>(), Type::UntaggedSigned8()); | |
| 72 case kUint8: | |
| 73 return CreateNative(CreateRange<uint8_t>(), Type::UntaggedUnsigned8()); | |
| 74 case kInt16: | |
| 75 return CreateNative(CreateRange<int16_t>(), Type::UntaggedSigned16()); | |
| 76 case kUint16: | |
| 77 return CreateNative(CreateRange<uint16_t>(), | |
| 78 Type::UntaggedUnsigned16()); | |
| 79 case kInt32: | |
| 80 return CreateNative(Type::Signed32(), Type::UntaggedSigned32()); | |
| 81 case kUint32: | |
| 82 return CreateNative(Type::Unsigned32(), Type::UntaggedUnsigned32()); | |
| 83 case kFloat32: | |
| 84 return CreateNative(Type::Number(), Type::UntaggedFloat32()); | |
| 85 case kFloat64: | |
| 86 return CreateNative(Type::Number(), Type::UntaggedFloat64()); | |
| 87 case kUint8Clamped: | |
| 88 return Get(kUint8); | |
| 89 case kInteger: | |
| 90 return CreateRange(-V8_INFINITY, V8_INFINITY); | |
| 91 case kWeakint: | |
| 92 return Type::Union(Get(kInteger), Type::MinusZeroOrNaN(), zone()); | |
| 93 case kWeakintFunc1: | |
| 94 return Type::Function(Get(kWeakint), Type::Number(), zone()); | |
| 95 case kRandomFunc0: | |
| 96 return Type::Function(Type::OrderedNumber(), zone()); | |
| 97 case kAnyFunc0: | |
| 98 return Type::Function(Type::Any(), zone()); | |
| 99 case kAnyFunc1: | |
| 100 return Type::Function(Type::Any(), Type::Any(), zone()); | |
| 101 case kAnyFunc2: | |
| 102 return Type::Function(Type::Any(), Type::Any(), Type::Any(), zone()); | |
| 103 case kAnyFunc3: | |
| 104 return Type::Function(Type::Any(), Type::Any(), Type::Any(), | |
| 105 Type::Any(), zone()); | |
| 106 case kNumberFunc0: | |
| 107 return Type::Function(Type::Number(), zone()); | |
| 108 case kNumberFunc1: | |
| 109 return Type::Function(Type::Number(), Type::Number(), zone()); | |
| 110 case kNumberFunc2: | |
| 111 return Type::Function(Type::Number(), Type::Number(), Type::Number(), | |
| 112 zone()); | |
| 113 case kImulFunc: | |
| 114 return Type::Function(Type::Signed32(), Type::Integral32(), | |
| 115 Type::Integral32(), zone()); | |
| 116 case kClz32Func: | |
| 117 return Type::Function(CreateRange(0, 32), Type::Number(), zone()); | |
| 118 case kArrayBufferFunc: | |
| 119 return Type::Function(Type::Object(zone()), Type::Unsigned32(), zone()); | |
| 120 #define TYPED_ARRAY_CASE(Type, type, TYPE, ctype, size) \ | |
| 121 case k##Type##Array: \ | |
| 122 return CreateArray(Get(k##Type)); \ | |
| 123 case k##Type##ArrayFunc: \ | |
| 124 return CreateArrayFunction(Get(k##Type##Array)); | |
| 125 TYPED_ARRAYS(TYPED_ARRAY_CASE) | |
| 126 #undef TYPED_ARRAY_CASE | |
| 127 case kNumLazyCachedTypes: | |
| 128 break; | |
| 129 } | |
| 130 UNREACHABLE(); | |
| 131 return NULL; | |
| 132 } | |
| 133 | 79 |
| 134 Type* CreateArray(Type* element) const { | 80 Type* CreateArrayFunction(Type* array) { |
| 135 return Type::Array(element, zone()); | |
| 136 } | |
| 137 | |
| 138 Type* CreateArrayFunction(Type* array) const { | |
| 139 Type* arg1 = Type::Union(Type::Unsigned32(), Type::Object(), zone()); | 81 Type* arg1 = Type::Union(Type::Unsigned32(), Type::Object(), zone()); |
| 140 Type* arg2 = Type::Union(Type::Unsigned32(), Type::Undefined(), zone()); | 82 Type* arg2 = Type::Union(Type::Unsigned32(), Type::Undefined(), zone()); |
| 141 Type* arg3 = arg2; | 83 Type* arg3 = arg2; |
| 142 return Type::Function(array, arg1, arg2, arg3, zone()); | 84 return Type::Function(array, arg1, arg2, arg3, zone()); |
| 143 } | 85 } |
| 144 | 86 |
| 145 Type* CreateNative(Type* semantic, Type* representation) const { | 87 Type* CreateNative(Type* semantic, Type* representation) { |
| 146 return Type::Intersect(semantic, representation, zone()); | 88 return Type::Intersect(semantic, representation, zone()); |
| 147 } | 89 } |
| 148 | 90 |
| 149 template <typename T> | 91 template <typename T> |
| 150 Type* CreateRange() const { | 92 Type* CreateRange() { |
| 151 return CreateRange(std::numeric_limits<T>::min(), | 93 return CreateRange(std::numeric_limits<T>::min(), |
| 152 std::numeric_limits<T>::max()); | 94 std::numeric_limits<T>::max()); |
| 153 } | 95 } |
| 154 | 96 |
| 155 Type* CreateRange(double min, double max) const { | 97 Type* CreateRange(double min, double max) { |
| 156 return Type::Range(min, max, zone()); | 98 return Type::Range(min, max, zone()); |
| 157 } | 99 } |
| 158 | 100 |
| 159 Factory* factory() const { return isolate()->factory(); } | 101 Zone* zone() { return &zone_; } |
| 160 Isolate* isolate() const { return isolate_; } | 102 }; |
| 161 Zone* zone() const { return zone_; } | |
| 162 | 103 |
| 163 Type* cache_[kNumLazyCachedTypes]; | 104 |
| 164 Isolate* isolate_; | 105 namespace { |
| 165 Zone* zone_; | 106 |
| 166 }; | 107 base::LazyInstance<TyperCache>::type kCache = LAZY_INSTANCE_INITIALIZER; |
| 108 |
| 109 } // namespace |
| 167 | 110 |
| 168 | 111 |
| 169 class Typer::Decorator final : public GraphDecorator { | 112 class Typer::Decorator final : public GraphDecorator { |
| 170 public: | 113 public: |
| 171 explicit Decorator(Typer* typer) : typer_(typer) {} | 114 explicit Decorator(Typer* typer) : typer_(typer) {} |
| 172 void Decorate(Node* node) final; | 115 void Decorate(Node* node) final; |
| 173 | 116 |
| 174 private: | 117 private: |
| 175 Typer* typer_; | 118 Typer* const typer_; |
| 176 }; | 119 }; |
| 177 | 120 |
| 178 | 121 |
| 179 Typer::Typer(Isolate* isolate, Graph* graph, Type::FunctionType* function_type, | 122 Typer::Typer(Isolate* isolate, Graph* graph, Type::FunctionType* function_type, |
| 180 MaybeHandle<Context> context) | 123 MaybeHandle<Context> context) |
| 181 : isolate_(isolate), | 124 : isolate_(isolate), |
| 182 graph_(graph), | 125 graph_(graph), |
| 183 function_type_(function_type), | 126 function_type_(function_type), |
| 184 context_(context), | 127 context_(context), |
| 185 decorator_(NULL), | 128 decorator_(nullptr), |
| 186 cache_(new (graph->zone()) LazyTypeCache(isolate, graph->zone())) { | 129 cache_(kCache.Get()) { |
| 187 Zone* zone = this->zone(); | 130 Zone* zone = this->zone(); |
| 188 Factory* const factory = isolate->factory(); | 131 Factory* const factory = isolate->factory(); |
| 189 | 132 |
| 190 Type* infinity = Type::Constant(factory->infinity_value(), zone); | 133 Type* infinity = Type::Constant(factory->infinity_value(), zone); |
| 191 Type* minus_infinity = Type::Constant(factory->minus_infinity_value(), zone); | 134 Type* minus_infinity = Type::Constant(factory->minus_infinity_value(), zone); |
| 192 Type* truncating_to_zero = | 135 Type* truncating_to_zero = |
| 193 Type::Union(Type::Union(infinity, minus_infinity, zone), | 136 Type::Union(Type::Union(infinity, minus_infinity, zone), |
| 194 Type::MinusZeroOrNaN(), zone); | 137 Type::MinusZeroOrNaN(), zone); |
| 195 | 138 |
| 196 singleton_false_ = Type::Constant(factory->false_value(), zone); | 139 singleton_false_ = Type::Constant(factory->false_value(), zone); |
| 197 singleton_true_ = Type::Constant(factory->true_value(), zone); | 140 singleton_true_ = Type::Constant(factory->true_value(), zone); |
| 198 singleton_zero_ = Type::Range(0.0, 0.0, zone); | |
| 199 singleton_one_ = Type::Range(1.0, 1.0, zone); | |
| 200 zero_or_one_ = Type::Range(0.0, 1.0, zone); | |
| 201 zeroish_ = Type::Union(singleton_zero_, Type::MinusZeroOrNaN(), zone); | |
| 202 signed32ish_ = Type::Union(Type::Signed32(), truncating_to_zero, zone); | 141 signed32ish_ = Type::Union(Type::Signed32(), truncating_to_zero, zone); |
| 203 unsigned32ish_ = Type::Union(Type::Unsigned32(), truncating_to_zero, zone); | 142 unsigned32ish_ = Type::Union(Type::Unsigned32(), truncating_to_zero, zone); |
| 204 falsish_ = | 143 falsish_ = Type::Union( |
| 205 Type::Union(Type::Undetectable(), | 144 Type::Undetectable(), |
| 206 Type::Union(Type::Union(singleton_false_, zeroish_, zone), | 145 Type::Union(Type::Union(singleton_false_, cache_.kZeroish, zone), |
| 207 Type::NullOrUndefined(), zone), | 146 Type::NullOrUndefined(), zone), |
| 208 zone); | 147 zone); |
| 209 truish_ = Type::Union( | 148 truish_ = Type::Union( |
| 210 singleton_true_, | 149 singleton_true_, |
| 211 Type::Union(Type::DetectableReceiver(), Type::Symbol(), zone), zone); | 150 Type::Union(Type::DetectableReceiver(), Type::Symbol(), zone), zone); |
| 212 | 151 |
| 213 decorator_ = new (zone) Decorator(this); | 152 decorator_ = new (zone) Decorator(this); |
| 214 graph_->AddDecorator(decorator_); | 153 graph_->AddDecorator(decorator_); |
| 215 } | 154 } |
| 216 | 155 |
| 217 | 156 |
| 218 Typer::~Typer() { | 157 Typer::~Typer() { |
| (...skipping 301 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 520 : t->singleton_false_; | 459 : t->singleton_false_; |
| 521 } | 460 } |
| 522 // Type should be non empty, so we know it should be true. | 461 // Type should be non empty, so we know it should be true. |
| 523 DCHECK((outcome & kComparisonTrue) != 0); | 462 DCHECK((outcome & kComparisonTrue) != 0); |
| 524 return t->singleton_true_; | 463 return t->singleton_true_; |
| 525 } | 464 } |
| 526 | 465 |
| 527 | 466 |
| 528 Type* Typer::Visitor::Rangify(Type* type, Typer* t) { | 467 Type* Typer::Visitor::Rangify(Type* type, Typer* t) { |
| 529 if (type->IsRange()) return type; // Shortcut. | 468 if (type->IsRange()) return type; // Shortcut. |
| 530 if (!type->Is(t->cache_->Get(kInteger))) { | 469 if (!type->Is(t->cache_.kInteger)) { |
| 531 return type; // Give up on non-integer types. | 470 return type; // Give up on non-integer types. |
| 532 } | 471 } |
| 533 double min = type->Min(); | 472 double min = type->Min(); |
| 534 double max = type->Max(); | 473 double max = type->Max(); |
| 535 // Handle the degenerate case of empty bitset types (such as | 474 // Handle the degenerate case of empty bitset types (such as |
| 536 // OtherUnsigned31 and OtherSigned32 on 64-bit architectures). | 475 // OtherUnsigned31 and OtherSigned32 on 64-bit architectures). |
| 537 if (std::isnan(min)) { | 476 if (std::isnan(min)) { |
| 538 DCHECK(std::isnan(max)); | 477 DCHECK(std::isnan(max)); |
| 539 return type; | 478 return type; |
| 540 } | 479 } |
| (...skipping 19 matching lines...) Expand all Loading... |
| 560 if (type->Is(Type::PlainNumber()) && (type->Max() < 0 || 0 < type->Min())) { | 499 if (type->Is(Type::PlainNumber()) && (type->Max() < 0 || 0 < type->Min())) { |
| 561 return t->singleton_true_; // Ruled out nan, -0 and +0. | 500 return t->singleton_true_; // Ruled out nan, -0 and +0. |
| 562 } | 501 } |
| 563 return Type::Boolean(); | 502 return Type::Boolean(); |
| 564 } | 503 } |
| 565 | 504 |
| 566 | 505 |
| 567 Type* Typer::Visitor::ToNumber(Type* type, Typer* t) { | 506 Type* Typer::Visitor::ToNumber(Type* type, Typer* t) { |
| 568 if (type->Is(Type::Number())) return type; | 507 if (type->Is(Type::Number())) return type; |
| 569 if (type->Is(Type::NullOrUndefined())) { | 508 if (type->Is(Type::NullOrUndefined())) { |
| 570 if (type->Is(Type::Null())) return t->singleton_zero_; | 509 if (type->Is(Type::Null())) return t->cache_.kSingletonZero; |
| 571 if (type->Is(Type::Undefined())) return Type::NaN(); | 510 if (type->Is(Type::Undefined())) return Type::NaN(); |
| 572 return Type::Union(Type::NaN(), t->singleton_zero_, t->zone()); | 511 return Type::Union(Type::NaN(), t->cache_.kSingletonZero, t->zone()); |
| 573 } | 512 } |
| 574 if (type->Is(Type::NumberOrUndefined())) { | 513 if (type->Is(Type::NumberOrUndefined())) { |
| 575 return Type::Union(Type::Intersect(type, Type::Number(), t->zone()), | 514 return Type::Union(Type::Intersect(type, Type::Number(), t->zone()), |
| 576 Type::NaN(), t->zone()); | 515 Type::NaN(), t->zone()); |
| 577 } | 516 } |
| 578 if (type->Is(t->singleton_false_)) return t->singleton_zero_; | 517 if (type->Is(t->singleton_false_)) return t->cache_.kSingletonZero; |
| 579 if (type->Is(t->singleton_true_)) return t->singleton_one_; | 518 if (type->Is(t->singleton_true_)) return t->cache_.kSingletonOne; |
| 580 if (type->Is(Type::Boolean())) return t->zero_or_one_; | 519 if (type->Is(Type::Boolean())) return t->cache_.kZeroOrOne; |
| 581 if (type->Is(Type::BooleanOrNumber())) { | 520 if (type->Is(Type::BooleanOrNumber())) { |
| 582 return Type::Union(Type::Intersect(type, Type::Number(), t->zone()), | 521 return Type::Union(Type::Intersect(type, Type::Number(), t->zone()), |
| 583 t->zero_or_one_, t->zone()); | 522 t->cache_.kZeroOrOne, t->zone()); |
| 584 } | 523 } |
| 585 return Type::Number(); | 524 return Type::Number(); |
| 586 } | 525 } |
| 587 | 526 |
| 588 | 527 |
| 589 Type* Typer::Visitor::ToString(Type* type, Typer* t) { | 528 Type* Typer::Visitor::ToString(Type* type, Typer* t) { |
| 590 if (type->Is(Type::String())) return type; | 529 if (type->Is(Type::String())) return type; |
| 591 return Type::String(); | 530 return Type::String(); |
| 592 } | 531 } |
| 593 | 532 |
| 594 | 533 |
| 595 Type* Typer::Visitor::NumberToInt32(Type* type, Typer* t) { | 534 Type* Typer::Visitor::NumberToInt32(Type* type, Typer* t) { |
| 596 // TODO(neis): DCHECK(type->Is(Type::Number())); | 535 // TODO(neis): DCHECK(type->Is(Type::Number())); |
| 597 if (type->Is(Type::Signed32())) return type; | 536 if (type->Is(Type::Signed32())) return type; |
| 598 if (type->Is(t->zeroish_)) return t->singleton_zero_; | 537 if (type->Is(t->cache_.kZeroish)) return t->cache_.kSingletonZero; |
| 599 if (type->Is(t->signed32ish_)) { | 538 if (type->Is(t->signed32ish_)) { |
| 600 return Type::Intersect(Type::Union(type, t->singleton_zero_, t->zone()), | 539 return Type::Intersect( |
| 601 Type::Signed32(), t->zone()); | 540 Type::Union(type, t->cache_.kSingletonZero, t->zone()), |
| 541 Type::Signed32(), t->zone()); |
| 602 } | 542 } |
| 603 return Type::Signed32(); | 543 return Type::Signed32(); |
| 604 } | 544 } |
| 605 | 545 |
| 606 | 546 |
| 607 Type* Typer::Visitor::NumberToUint32(Type* type, Typer* t) { | 547 Type* Typer::Visitor::NumberToUint32(Type* type, Typer* t) { |
| 608 // TODO(neis): DCHECK(type->Is(Type::Number())); | 548 // TODO(neis): DCHECK(type->Is(Type::Number())); |
| 609 if (type->Is(Type::Unsigned32())) return type; | 549 if (type->Is(Type::Unsigned32())) return type; |
| 610 if (type->Is(t->zeroish_)) return t->singleton_zero_; | 550 if (type->Is(t->cache_.kZeroish)) return t->cache_.kSingletonZero; |
| 611 if (type->Is(t->unsigned32ish_)) { | 551 if (type->Is(t->unsigned32ish_)) { |
| 612 return Type::Intersect(Type::Union(type, t->singleton_zero_, t->zone()), | 552 return Type::Intersect( |
| 613 Type::Unsigned32(), t->zone()); | 553 Type::Union(type, t->cache_.kSingletonZero, t->zone()), |
| 554 Type::Unsigned32(), t->zone()); |
| 614 } | 555 } |
| 615 return Type::Unsigned32(); | 556 return Type::Unsigned32(); |
| 616 } | 557 } |
| 617 | 558 |
| 618 | 559 |
| 619 // ----------------------------------------------------------------------------- | 560 // ----------------------------------------------------------------------------- |
| 620 | 561 |
| 621 | 562 |
| 622 // Control operators. | 563 // Control operators. |
| 623 | 564 |
| (...skipping 534 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1158 double rmin = rhs->Min(); | 1099 double rmin = rhs->Min(); |
| 1159 double rmax = rhs->Max(); | 1100 double rmax = rhs->Max(); |
| 1160 results[0] = lmin * rmin; | 1101 results[0] = lmin * rmin; |
| 1161 results[1] = lmin * rmax; | 1102 results[1] = lmin * rmax; |
| 1162 results[2] = lmax * rmin; | 1103 results[2] = lmax * rmin; |
| 1163 results[3] = lmax * rmax; | 1104 results[3] = lmax * rmax; |
| 1164 // If the result may be nan, we give up on calculating a precise type, because | 1105 // If the result may be nan, we give up on calculating a precise type, because |
| 1165 // the discontinuity makes it too complicated. Note that even if none of the | 1106 // the discontinuity makes it too complicated. Note that even if none of the |
| 1166 // "results" above is nan, the actual result may still be, so we have to do a | 1107 // "results" above is nan, the actual result may still be, so we have to do a |
| 1167 // different check: | 1108 // different check: |
| 1168 bool maybe_nan = (lhs->Maybe(t->singleton_zero_) && | 1109 bool maybe_nan = (lhs->Maybe(t->cache_.kSingletonZero) && |
| 1169 (rmin == -V8_INFINITY || rmax == +V8_INFINITY)) || | 1110 (rmin == -V8_INFINITY || rmax == +V8_INFINITY)) || |
| 1170 (rhs->Maybe(t->singleton_zero_) && | 1111 (rhs->Maybe(t->cache_.kSingletonZero) && |
| 1171 (lmin == -V8_INFINITY || lmax == +V8_INFINITY)); | 1112 (lmin == -V8_INFINITY || lmax == +V8_INFINITY)); |
| 1172 if (maybe_nan) return t->cache_->Get(kWeakint); // Giving up. | 1113 if (maybe_nan) return t->cache_.kWeakint; // Giving up. |
| 1173 bool maybe_minuszero = (lhs->Maybe(t->singleton_zero_) && rmin < 0) || | 1114 bool maybe_minuszero = (lhs->Maybe(t->cache_.kSingletonZero) && rmin < 0) || |
| 1174 (rhs->Maybe(t->singleton_zero_) && lmin < 0); | 1115 (rhs->Maybe(t->cache_.kSingletonZero) && lmin < 0); |
| 1175 Type* range = | 1116 Type* range = |
| 1176 Type::Range(array_min(results, 4), array_max(results, 4), t->zone()); | 1117 Type::Range(array_min(results, 4), array_max(results, 4), t->zone()); |
| 1177 return maybe_minuszero ? Type::Union(range, Type::MinusZero(), t->zone()) | 1118 return maybe_minuszero ? Type::Union(range, Type::MinusZero(), t->zone()) |
| 1178 : range; | 1119 : range; |
| 1179 } | 1120 } |
| 1180 | 1121 |
| 1181 | 1122 |
| 1182 Type* Typer::Visitor::JSMultiplyTyper(Type* lhs, Type* rhs, Typer* t) { | 1123 Type* Typer::Visitor::JSMultiplyTyper(Type* lhs, Type* rhs, Typer* t) { |
| 1183 lhs = Rangify(ToNumber(lhs, t), t); | 1124 lhs = Rangify(ToNumber(lhs, t), t); |
| 1184 rhs = Rangify(ToNumber(rhs, t), t); | 1125 rhs = Rangify(ToNumber(rhs, t), t); |
| 1185 if (lhs->Is(Type::NaN()) || rhs->Is(Type::NaN())) return Type::NaN(); | 1126 if (lhs->Is(Type::NaN()) || rhs->Is(Type::NaN())) return Type::NaN(); |
| 1186 if (lhs->IsRange() && rhs->IsRange()) { | 1127 if (lhs->IsRange() && rhs->IsRange()) { |
| 1187 return JSMultiplyRanger(lhs->AsRange(), rhs->AsRange(), t); | 1128 return JSMultiplyRanger(lhs->AsRange(), rhs->AsRange(), t); |
| 1188 } | 1129 } |
| 1189 return Type::Number(); | 1130 return Type::Number(); |
| 1190 } | 1131 } |
| 1191 | 1132 |
| 1192 | 1133 |
| 1193 Type* Typer::Visitor::JSDivideTyper(Type* lhs, Type* rhs, Typer* t) { | 1134 Type* Typer::Visitor::JSDivideTyper(Type* lhs, Type* rhs, Typer* t) { |
| 1194 lhs = ToNumber(lhs, t); | 1135 lhs = ToNumber(lhs, t); |
| 1195 rhs = ToNumber(rhs, t); | 1136 rhs = ToNumber(rhs, t); |
| 1196 if (lhs->Is(Type::NaN()) || rhs->Is(Type::NaN())) return Type::NaN(); | 1137 if (lhs->Is(Type::NaN()) || rhs->Is(Type::NaN())) return Type::NaN(); |
| 1197 // Division is tricky, so all we do is try ruling out nan. | 1138 // Division is tricky, so all we do is try ruling out nan. |
| 1198 // TODO(neis): try ruling out -0 as well? | 1139 // TODO(neis): try ruling out -0 as well? |
| 1199 bool maybe_nan = | 1140 bool maybe_nan = |
| 1200 lhs->Maybe(Type::NaN()) || rhs->Maybe(t->zeroish_) || | 1141 lhs->Maybe(Type::NaN()) || rhs->Maybe(t->cache_.kZeroish) || |
| 1201 ((lhs->Min() == -V8_INFINITY || lhs->Max() == +V8_INFINITY) && | 1142 ((lhs->Min() == -V8_INFINITY || lhs->Max() == +V8_INFINITY) && |
| 1202 (rhs->Min() == -V8_INFINITY || rhs->Max() == +V8_INFINITY)); | 1143 (rhs->Min() == -V8_INFINITY || rhs->Max() == +V8_INFINITY)); |
| 1203 return maybe_nan ? Type::Number() : Type::OrderedNumber(); | 1144 return maybe_nan ? Type::Number() : Type::OrderedNumber(); |
| 1204 } | 1145 } |
| 1205 | 1146 |
| 1206 | 1147 |
| 1207 Type* Typer::Visitor::JSModulusRanger(Type::RangeType* lhs, | 1148 Type* Typer::Visitor::JSModulusRanger(Type::RangeType* lhs, |
| 1208 Type::RangeType* rhs, Typer* t) { | 1149 Type::RangeType* rhs, Typer* t) { |
| 1209 double lmin = lhs->Min(); | 1150 double lmin = lhs->Min(); |
| 1210 double lmax = lhs->Max(); | 1151 double lmax = lhs->Max(); |
| (...skipping 24 matching lines...) Expand all Loading... |
| 1235 result = Type::Union(result, Type::MinusZero(), t->zone()); | 1176 result = Type::Union(result, Type::MinusZero(), t->zone()); |
| 1236 return result; | 1177 return result; |
| 1237 } | 1178 } |
| 1238 | 1179 |
| 1239 | 1180 |
| 1240 Type* Typer::Visitor::JSModulusTyper(Type* lhs, Type* rhs, Typer* t) { | 1181 Type* Typer::Visitor::JSModulusTyper(Type* lhs, Type* rhs, Typer* t) { |
| 1241 lhs = ToNumber(lhs, t); | 1182 lhs = ToNumber(lhs, t); |
| 1242 rhs = ToNumber(rhs, t); | 1183 rhs = ToNumber(rhs, t); |
| 1243 if (lhs->Is(Type::NaN()) || rhs->Is(Type::NaN())) return Type::NaN(); | 1184 if (lhs->Is(Type::NaN()) || rhs->Is(Type::NaN())) return Type::NaN(); |
| 1244 | 1185 |
| 1245 if (lhs->Maybe(Type::NaN()) || rhs->Maybe(t->zeroish_) || | 1186 if (lhs->Maybe(Type::NaN()) || rhs->Maybe(t->cache_.kZeroish) || |
| 1246 lhs->Min() == -V8_INFINITY || lhs->Max() == +V8_INFINITY) { | 1187 lhs->Min() == -V8_INFINITY || lhs->Max() == +V8_INFINITY) { |
| 1247 // Result maybe NaN. | 1188 // Result maybe NaN. |
| 1248 return Type::Number(); | 1189 return Type::Number(); |
| 1249 } | 1190 } |
| 1250 | 1191 |
| 1251 lhs = Rangify(lhs, t); | 1192 lhs = Rangify(lhs, t); |
| 1252 rhs = Rangify(rhs, t); | 1193 rhs = Rangify(rhs, t); |
| 1253 if (lhs->IsRange() && rhs->IsRange()) { | 1194 if (lhs->IsRange() && rhs->IsRange()) { |
| 1254 return JSModulusRanger(lhs->AsRange(), rhs->AsRange(), t); | 1195 return JSModulusRanger(lhs->AsRange(), rhs->AsRange(), t); |
| 1255 } | 1196 } |
| (...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1368 static const double kWeakenMaxLimits[] = { | 1309 static const double kWeakenMaxLimits[] = { |
| 1369 0.0, 1073741823.0, 2147483647.0, 4294967295.0, 8589934591.0, | 1310 0.0, 1073741823.0, 2147483647.0, 4294967295.0, 8589934591.0, |
| 1370 17179869183.0, 34359738367.0, 68719476735.0, 137438953471.0, | 1311 17179869183.0, 34359738367.0, 68719476735.0, 137438953471.0, |
| 1371 274877906943.0, 549755813887.0, 1099511627775.0, 2199023255551.0, | 1312 274877906943.0, 549755813887.0, 1099511627775.0, 2199023255551.0, |
| 1372 4398046511103.0, 8796093022207.0, 17592186044415.0, 35184372088831.0, | 1313 4398046511103.0, 8796093022207.0, 17592186044415.0, 35184372088831.0, |
| 1373 70368744177663.0, 140737488355327.0, 281474976710655.0, | 1314 70368744177663.0, 140737488355327.0, 281474976710655.0, |
| 1374 562949953421311.0}; | 1315 562949953421311.0}; |
| 1375 STATIC_ASSERT(arraysize(kWeakenMinLimits) == arraysize(kWeakenMaxLimits)); | 1316 STATIC_ASSERT(arraysize(kWeakenMinLimits) == arraysize(kWeakenMaxLimits)); |
| 1376 | 1317 |
| 1377 // If the types have nothing to do with integers, return the types. | 1318 // If the types have nothing to do with integers, return the types. |
| 1378 Type* const integer = typer_->cache_->Get(kInteger); | 1319 Type* const integer = typer_->cache_.kInteger; |
| 1379 if (!previous_type->Maybe(integer)) { | 1320 if (!previous_type->Maybe(integer)) { |
| 1380 return current_type; | 1321 return current_type; |
| 1381 } | 1322 } |
| 1382 DCHECK(current_type->Maybe(integer)); | 1323 DCHECK(current_type->Maybe(integer)); |
| 1383 | 1324 |
| 1384 Type* current_integer = Type::Intersect(current_type, integer, zone()); | 1325 Type* current_integer = Type::Intersect(current_type, integer, zone()); |
| 1385 Type* previous_integer = Type::Intersect(previous_type, integer, zone()); | 1326 Type* previous_integer = Type::Intersect(previous_type, integer, zone()); |
| 1386 | 1327 |
| 1387 // Once we start weakening a node, we should always weaken. | 1328 // Once we start weakening a node, we should always weaken. |
| 1388 if (!IsWeakened(node->id())) { | 1329 if (!IsWeakened(node->id())) { |
| (...skipping 443 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1832 return Bounds(FieldAccessOf(node->op()).type); | 1773 return Bounds(FieldAccessOf(node->op()).type); |
| 1833 } | 1774 } |
| 1834 | 1775 |
| 1835 | 1776 |
| 1836 Bounds Typer::Visitor::TypeLoadBuffer(Node* node) { | 1777 Bounds Typer::Visitor::TypeLoadBuffer(Node* node) { |
| 1837 // TODO(bmeurer): This typing is not yet correct. Since we can still access | 1778 // TODO(bmeurer): This typing is not yet correct. Since we can still access |
| 1838 // out of bounds, the type in the general case has to include Undefined. | 1779 // out of bounds, the type in the general case has to include Undefined. |
| 1839 switch (BufferAccessOf(node->op()).external_array_type()) { | 1780 switch (BufferAccessOf(node->op()).external_array_type()) { |
| 1840 #define TYPED_ARRAY_CASE(Type, type, TYPE, ctype, size) \ | 1781 #define TYPED_ARRAY_CASE(Type, type, TYPE, ctype, size) \ |
| 1841 case kExternal##Type##Array: \ | 1782 case kExternal##Type##Array: \ |
| 1842 return Bounds(typer_->cache_->Get(k##Type)); | 1783 return Bounds(typer_->cache_.k##Type); |
| 1843 TYPED_ARRAYS(TYPED_ARRAY_CASE) | 1784 TYPED_ARRAYS(TYPED_ARRAY_CASE) |
| 1844 #undef TYPED_ARRAY_CASE | 1785 #undef TYPED_ARRAY_CASE |
| 1845 } | 1786 } |
| 1846 UNREACHABLE(); | 1787 UNREACHABLE(); |
| 1847 return Bounds(); | 1788 return Bounds(); |
| 1848 } | 1789 } |
| 1849 | 1790 |
| 1850 | 1791 |
| 1851 Bounds Typer::Visitor::TypeLoadElement(Node* node) { | 1792 Bounds Typer::Visitor::TypeLoadElement(Node* node) { |
| 1852 return Bounds(ElementAccessOf(node->op()).type); | 1793 return Bounds(ElementAccessOf(node->op()).type); |
| (...skipping 486 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2339 | 2280 |
| 2340 | 2281 |
| 2341 // Heap constants. | 2282 // Heap constants. |
| 2342 | 2283 |
| 2343 | 2284 |
| 2344 Type* Typer::Visitor::TypeConstant(Handle<Object> value) { | 2285 Type* Typer::Visitor::TypeConstant(Handle<Object> value) { |
| 2345 if (value->IsJSFunction()) { | 2286 if (value->IsJSFunction()) { |
| 2346 if (JSFunction::cast(*value)->shared()->HasBuiltinFunctionId()) { | 2287 if (JSFunction::cast(*value)->shared()->HasBuiltinFunctionId()) { |
| 2347 switch (JSFunction::cast(*value)->shared()->builtin_function_id()) { | 2288 switch (JSFunction::cast(*value)->shared()->builtin_function_id()) { |
| 2348 case kMathRandom: | 2289 case kMathRandom: |
| 2349 return typer_->cache_->Get(kRandomFunc0); | 2290 return typer_->cache_.kRandomFunc0; |
| 2350 case kMathFloor: | 2291 case kMathFloor: |
| 2351 case kMathRound: | 2292 case kMathRound: |
| 2352 case kMathCeil: | 2293 case kMathCeil: |
| 2353 return typer_->cache_->Get(kWeakintFunc1); | 2294 return typer_->cache_.kWeakintFunc1; |
| 2354 // Unary math functions. | 2295 // Unary math functions. |
| 2355 case kMathAbs: // TODO(rossberg): can't express overloading | 2296 case kMathAbs: // TODO(rossberg): can't express overloading |
| 2356 case kMathLog: | 2297 case kMathLog: |
| 2357 case kMathExp: | 2298 case kMathExp: |
| 2358 case kMathSqrt: | 2299 case kMathSqrt: |
| 2359 case kMathCos: | 2300 case kMathCos: |
| 2360 case kMathSin: | 2301 case kMathSin: |
| 2361 case kMathTan: | 2302 case kMathTan: |
| 2362 case kMathAcos: | 2303 case kMathAcos: |
| 2363 case kMathAsin: | 2304 case kMathAsin: |
| 2364 case kMathAtan: | 2305 case kMathAtan: |
| 2365 case kMathFround: | 2306 case kMathFround: |
| 2366 return typer_->cache_->Get(kNumberFunc1); | 2307 return typer_->cache_.kNumberFunc1; |
| 2367 // Binary math functions. | 2308 // Binary math functions. |
| 2368 case kMathAtan2: | 2309 case kMathAtan2: |
| 2369 case kMathPow: | 2310 case kMathPow: |
| 2370 case kMathMax: | 2311 case kMathMax: |
| 2371 case kMathMin: | 2312 case kMathMin: |
| 2372 return typer_->cache_->Get(kNumberFunc2); | 2313 return typer_->cache_.kNumberFunc2; |
| 2373 case kMathImul: | 2314 case kMathImul: |
| 2374 return typer_->cache_->Get(kImulFunc); | 2315 return typer_->cache_.kImulFunc; |
| 2375 case kMathClz32: | 2316 case kMathClz32: |
| 2376 return typer_->cache_->Get(kClz32Func); | 2317 return typer_->cache_.kClz32Func; |
| 2377 default: | 2318 default: |
| 2378 break; | 2319 break; |
| 2379 } | 2320 } |
| 2380 } else if (JSFunction::cast(*value)->IsBuiltin() && !context().is_null()) { | 2321 } else if (JSFunction::cast(*value)->IsBuiltin() && !context().is_null()) { |
| 2381 Handle<Context> native = | 2322 Handle<Context> native = |
| 2382 handle(context().ToHandleChecked()->native_context(), isolate()); | 2323 handle(context().ToHandleChecked()->native_context(), isolate()); |
| 2383 if (*value == native->array_buffer_fun()) { | 2324 if (*value == native->array_buffer_fun()) { |
| 2384 return typer_->cache_->Get(kArrayBufferFunc); | 2325 return typer_->cache_.kArrayBufferFunc; |
| 2385 } else if (*value == native->int8_array_fun()) { | 2326 } else if (*value == native->int8_array_fun()) { |
| 2386 return typer_->cache_->Get(kInt8ArrayFunc); | 2327 return typer_->cache_.kInt8ArrayFunc; |
| 2387 } else if (*value == native->int16_array_fun()) { | 2328 } else if (*value == native->int16_array_fun()) { |
| 2388 return typer_->cache_->Get(kInt16ArrayFunc); | 2329 return typer_->cache_.kInt16ArrayFunc; |
| 2389 } else if (*value == native->int32_array_fun()) { | 2330 } else if (*value == native->int32_array_fun()) { |
| 2390 return typer_->cache_->Get(kInt32ArrayFunc); | 2331 return typer_->cache_.kInt32ArrayFunc; |
| 2391 } else if (*value == native->uint8_array_fun()) { | 2332 } else if (*value == native->uint8_array_fun()) { |
| 2392 return typer_->cache_->Get(kUint8ArrayFunc); | 2333 return typer_->cache_.kUint8ArrayFunc; |
| 2393 } else if (*value == native->uint16_array_fun()) { | 2334 } else if (*value == native->uint16_array_fun()) { |
| 2394 return typer_->cache_->Get(kUint16ArrayFunc); | 2335 return typer_->cache_.kUint16ArrayFunc; |
| 2395 } else if (*value == native->uint32_array_fun()) { | 2336 } else if (*value == native->uint32_array_fun()) { |
| 2396 return typer_->cache_->Get(kUint32ArrayFunc); | 2337 return typer_->cache_.kUint32ArrayFunc; |
| 2397 } else if (*value == native->float32_array_fun()) { | 2338 } else if (*value == native->float32_array_fun()) { |
| 2398 return typer_->cache_->Get(kFloat32ArrayFunc); | 2339 return typer_->cache_.kFloat32ArrayFunc; |
| 2399 } else if (*value == native->float64_array_fun()) { | 2340 } else if (*value == native->float64_array_fun()) { |
| 2400 return typer_->cache_->Get(kFloat64ArrayFunc); | 2341 return typer_->cache_.kFloat64ArrayFunc; |
| 2401 } | 2342 } |
| 2402 } | 2343 } |
| 2403 int const arity = | 2344 int const arity = |
| 2404 JSFunction::cast(*value)->shared()->internal_formal_parameter_count(); | 2345 JSFunction::cast(*value)->shared()->internal_formal_parameter_count(); |
| 2405 switch (arity) { | 2346 switch (arity) { |
| 2406 case SharedFunctionInfo::kDontAdaptArgumentsSentinel: | 2347 case SharedFunctionInfo::kDontAdaptArgumentsSentinel: |
| 2407 // Some smart optimization at work... &%$!&@+$! | 2348 // Some smart optimization at work... &%$!&@+$! |
| 2408 return Type::Any(zone()); | 2349 return Type::Any(zone()); |
| 2409 case 0: | 2350 case 0: |
| 2410 return typer_->cache_->Get(kAnyFunc0); | 2351 return typer_->cache_.kAnyFunc0; |
| 2411 case 1: | 2352 case 1: |
| 2412 return typer_->cache_->Get(kAnyFunc1); | 2353 return typer_->cache_.kAnyFunc1; |
| 2413 case 2: | 2354 case 2: |
| 2414 return typer_->cache_->Get(kAnyFunc2); | 2355 return typer_->cache_.kAnyFunc2; |
| 2415 case 3: | 2356 case 3: |
| 2416 return typer_->cache_->Get(kAnyFunc3); | 2357 return typer_->cache_.kAnyFunc3; |
| 2417 default: { | 2358 default: { |
| 2418 DCHECK_LT(3, arity); | 2359 DCHECK_LT(3, arity); |
| 2419 Type** const params = zone()->NewArray<Type*>(arity); | 2360 Type** const params = zone()->NewArray<Type*>(arity); |
| 2420 std::fill(¶ms[0], ¶ms[arity], Type::Any(zone())); | 2361 std::fill(¶ms[0], ¶ms[arity], Type::Any(zone())); |
| 2421 return Type::Function(Type::Any(zone()), arity, params, zone()); | 2362 return Type::Function(Type::Any(zone()), arity, params, zone()); |
| 2422 } | 2363 } |
| 2423 } | 2364 } |
| 2424 } else if (value->IsJSTypedArray()) { | 2365 } else if (value->IsJSTypedArray()) { |
| 2425 switch (JSTypedArray::cast(*value)->type()) { | 2366 switch (JSTypedArray::cast(*value)->type()) { |
| 2426 #define TYPED_ARRAY_CASE(Type, type, TYPE, ctype, size) \ | 2367 #define TYPED_ARRAY_CASE(Type, type, TYPE, ctype, size) \ |
| 2427 case kExternal##Type##Array: \ | 2368 case kExternal##Type##Array: \ |
| 2428 return typer_->cache_->Get(k##Type##Array); | 2369 return typer_->cache_.k##Type##Array; |
| 2429 TYPED_ARRAYS(TYPED_ARRAY_CASE) | 2370 TYPED_ARRAYS(TYPED_ARRAY_CASE) |
| 2430 #undef TYPED_ARRAY_CASE | 2371 #undef TYPED_ARRAY_CASE |
| 2431 } | 2372 } |
| 2432 } | 2373 } |
| 2433 return Type::Constant(value, zone()); | 2374 return Type::Constant(value, zone()); |
| 2434 } | 2375 } |
| 2435 | 2376 |
| 2436 } // namespace compiler | 2377 } // namespace compiler |
| 2437 } // namespace internal | 2378 } // namespace internal |
| 2438 } // namespace v8 | 2379 } // namespace v8 |
| OLD | NEW |