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 |