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 <math.h> | |
6 | |
7 #include "src/types.h" | 5 #include "src/types.h" |
8 | 6 |
9 #include "src/ostreams.h" | 7 #include "src/ostreams.h" |
10 #include "src/types-inl.h" | 8 #include "src/types-inl.h" |
11 | 9 |
12 namespace v8 { | 10 namespace v8 { |
13 namespace internal { | 11 namespace internal { |
14 | 12 |
15 | |
16 // ----------------------------------------------------------------------------- | |
17 // Range-related custom order on doubles. | |
18 // We want -0 to be less than +0. | |
19 | |
20 static bool dle(double x, double y) { | |
21 return x <= y && copysign(1, x) <= copysign(1, y); | |
22 } | |
23 | |
24 | |
25 static bool deq(double x, double y) { | |
26 return dle(x, y) && dle(y, x); | |
27 } | |
28 | |
29 | |
30 // ----------------------------------------------------------------------------- | 13 // ----------------------------------------------------------------------------- |
31 // Glb and lub computation. | 14 // Glb and lub computation. |
32 | 15 |
33 // The largest bitset subsumed by this type. | 16 // The largest bitset subsumed by this type. |
34 template<class Config> | 17 template<class Config> |
35 int TypeImpl<Config>::BitsetType::Glb(TypeImpl* type) { | 18 int TypeImpl<Config>::BitsetType::Glb(TypeImpl* type) { |
36 DisallowHeapAllocation no_allocation; | 19 DisallowHeapAllocation no_allocation; |
37 if (type->IsBitset()) { | 20 if (type->IsBitset()) { |
38 return type->AsBitset(); | 21 return type->AsBitset(); |
39 } else if (type->IsUnion()) { | 22 } else if (type->IsUnion()) { |
(...skipping 18 matching lines...) Expand all Loading... |
58 for (int i = 0; i < unioned->Length(); ++i) { | 41 for (int i = 0; i < unioned->Length(); ++i) { |
59 bitset |= unioned->Get(i)->BitsetLub(); | 42 bitset |= unioned->Get(i)->BitsetLub(); |
60 } | 43 } |
61 return bitset; | 44 return bitset; |
62 } else if (type->IsClass()) { | 45 } else if (type->IsClass()) { |
63 // Little hack to avoid the need for a region for handlification here... | 46 // Little hack to avoid the need for a region for handlification here... |
64 return Config::is_class(type) ? Lub(*Config::as_class(type)) : | 47 return Config::is_class(type) ? Lub(*Config::as_class(type)) : |
65 type->AsClass()->Bound(NULL)->AsBitset(); | 48 type->AsClass()->Bound(NULL)->AsBitset(); |
66 } else if (type->IsConstant()) { | 49 } else if (type->IsConstant()) { |
67 return type->AsConstant()->Bound()->AsBitset(); | 50 return type->AsConstant()->Bound()->AsBitset(); |
68 } else if (type->IsRange()) { | |
69 return type->AsRange()->Bound()->AsBitset(); | |
70 } else if (type->IsContext()) { | 51 } else if (type->IsContext()) { |
71 return type->AsContext()->Bound()->AsBitset(); | 52 return type->AsContext()->Bound()->AsBitset(); |
72 } else if (type->IsArray()) { | 53 } else if (type->IsArray()) { |
73 return type->AsArray()->Bound()->AsBitset(); | 54 return type->AsArray()->Bound()->AsBitset(); |
74 } else if (type->IsFunction()) { | 55 } else if (type->IsFunction()) { |
75 return type->AsFunction()->Bound()->AsBitset(); | 56 return type->AsFunction()->Bound()->AsBitset(); |
76 } else { | 57 } else { |
77 UNREACHABLE(); | 58 UNREACHABLE(); |
78 return kNone; | 59 return kNone; |
79 } | 60 } |
(...skipping 10 matching lines...) Expand all Loading... |
90 UnionHandle unioned = handle(type->AsUnion()); | 71 UnionHandle unioned = handle(type->AsUnion()); |
91 int bitset = kNone; | 72 int bitset = kNone; |
92 for (int i = 0; i < unioned->Length(); ++i) { | 73 for (int i = 0; i < unioned->Length(); ++i) { |
93 bitset |= unioned->Get(i)->InherentBitsetLub(); | 74 bitset |= unioned->Get(i)->InherentBitsetLub(); |
94 } | 75 } |
95 return bitset; | 76 return bitset; |
96 } else if (type->IsClass()) { | 77 } else if (type->IsClass()) { |
97 return Lub(*type->AsClass()->Map()); | 78 return Lub(*type->AsClass()->Map()); |
98 } else if (type->IsConstant()) { | 79 } else if (type->IsConstant()) { |
99 return Lub(*type->AsConstant()->Value()); | 80 return Lub(*type->AsConstant()->Value()); |
100 } else if (type->IsRange()) { | |
101 return Lub(type->AsRange()->Min(), type->AsRange()->Max()); | |
102 } else if (type->IsContext()) { | 81 } else if (type->IsContext()) { |
103 return kInternal & kTaggedPtr; | 82 return kInternal & kTaggedPtr; |
104 } else if (type->IsArray()) { | 83 } else if (type->IsArray()) { |
105 return kArray; | 84 return kArray; |
106 } else if (type->IsFunction()) { | 85 } else if (type->IsFunction()) { |
107 return kFunction; | 86 return kFunction; |
108 } else { | 87 } else { |
109 UNREACHABLE(); | 88 UNREACHABLE(); |
110 return kNone; | 89 return kNone; |
111 } | 90 } |
(...skipping 15 matching lines...) Expand all Loading... |
127 DisallowHeapAllocation no_allocation; | 106 DisallowHeapAllocation no_allocation; |
128 if (i::IsMinusZero(value)) return kMinusZero; | 107 if (i::IsMinusZero(value)) return kMinusZero; |
129 if (std::isnan(value)) return kNaN; | 108 if (std::isnan(value)) return kNaN; |
130 if (IsUint32Double(value)) return Lub(FastD2UI(value)); | 109 if (IsUint32Double(value)) return Lub(FastD2UI(value)); |
131 if (IsInt32Double(value)) return Lub(FastD2I(value)); | 110 if (IsInt32Double(value)) return Lub(FastD2I(value)); |
132 return kOtherNumber; | 111 return kOtherNumber; |
133 } | 112 } |
134 | 113 |
135 | 114 |
136 template<class Config> | 115 template<class Config> |
137 int TypeImpl<Config>::BitsetType::Lub(double min, double max) { | |
138 DisallowHeapAllocation no_allocation; | |
139 DCHECK(dle(min, max)); | |
140 if (deq(min, max)) return BitsetType::Lub(min); // Singleton range. | |
141 int bitset = BitsetType::kNumber ^ SEMANTIC(BitsetType::kNaN); | |
142 if (dle(0, min) || max < 0) bitset ^= SEMANTIC(BitsetType::kMinusZero); | |
143 return bitset; | |
144 // TODO(neis): Could refine this further by doing more checks on min/max. | |
145 } | |
146 | |
147 | |
148 template<class Config> | |
149 int TypeImpl<Config>::BitsetType::Lub(int32_t value) { | 116 int TypeImpl<Config>::BitsetType::Lub(int32_t value) { |
150 if (value >= 0x40000000) { | 117 if (value >= 0x40000000) { |
151 return i::SmiValuesAre31Bits() ? kOtherUnsigned31 : kUnsignedSmall; | 118 return i::SmiValuesAre31Bits() ? kOtherUnsigned31 : kUnsignedSmall; |
152 } | 119 } |
153 if (value >= 0) return kUnsignedSmall; | 120 if (value >= 0) return kUnsignedSmall; |
154 if (value >= -0x40000000) return kOtherSignedSmall; | 121 if (value >= -0x40000000) return kOtherSignedSmall; |
155 return i::SmiValuesAre31Bits() ? kOtherSigned32 : kOtherSignedSmall; | 122 return i::SmiValuesAre31Bits() ? kOtherSigned32 : kOtherSignedSmall; |
156 } | 123 } |
157 | 124 |
158 | 125 |
(...skipping 123 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
282 && *this->AsClass()->Map() == *that->AsClass()->Map() | 249 && *this->AsClass()->Map() == *that->AsClass()->Map() |
283 && ((Config::is_class(that) && Config::is_class(this)) || | 250 && ((Config::is_class(that) && Config::is_class(this)) || |
284 BitsetType::New(this->BitsetLub())->Is( | 251 BitsetType::New(this->BitsetLub())->Is( |
285 BitsetType::New(that->BitsetLub()))); | 252 BitsetType::New(that->BitsetLub()))); |
286 } | 253 } |
287 if (that->IsConstant()) { | 254 if (that->IsConstant()) { |
288 return this->IsConstant() | 255 return this->IsConstant() |
289 && *this->AsConstant()->Value() == *that->AsConstant()->Value() | 256 && *this->AsConstant()->Value() == *that->AsConstant()->Value() |
290 && this->AsConstant()->Bound()->Is(that->AsConstant()->Bound()); | 257 && this->AsConstant()->Bound()->Is(that->AsConstant()->Bound()); |
291 } | 258 } |
292 if (that->IsRange()) { | |
293 return this->IsRange() | |
294 && this->AsRange()->Bound()->Is(that->AsRange()->Bound()) | |
295 && dle(that->AsRange()->Min(), this->AsRange()->Min()) | |
296 && dle(this->AsRange()->Max(), that->AsRange()->Max()); | |
297 } | |
298 if (that->IsContext()) { | 259 if (that->IsContext()) { |
299 return this->IsContext() | 260 return this->IsContext() |
300 && this->AsContext()->Outer()->Equals(that->AsContext()->Outer()); | 261 && this->AsContext()->Outer()->Equals(that->AsContext()->Outer()); |
301 } | 262 } |
302 if (that->IsArray()) { | 263 if (that->IsArray()) { |
303 return this->IsArray() | 264 return this->IsArray() |
304 && this->AsArray()->Element()->Equals(that->AsArray()->Element()); | 265 && this->AsArray()->Element()->Equals(that->AsArray()->Element()); |
305 } | 266 } |
306 if (that->IsFunction()) { | 267 if (that->IsFunction()) { |
307 // We currently do not allow for any variance here, in order to keep | 268 // We currently do not allow for any variance here, in order to keep |
(...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
420 } | 381 } |
421 | 382 |
422 return false; | 383 return false; |
423 } | 384 } |
424 | 385 |
425 | 386 |
426 // Check if value is contained in (inhabits) type. | 387 // Check if value is contained in (inhabits) type. |
427 template<class Config> | 388 template<class Config> |
428 bool TypeImpl<Config>::Contains(i::Object* value) { | 389 bool TypeImpl<Config>::Contains(i::Object* value) { |
429 DisallowHeapAllocation no_allocation; | 390 DisallowHeapAllocation no_allocation; |
430 if (this->IsRange()) { | |
431 return value->IsNumber() && | |
432 dle(this->AsRange()->Min(), value->Number()) && | |
433 dle(value->Number(), this->AsRange()->Max()) && | |
434 BitsetType::Is(BitsetType::Lub(value), this->BitsetLub()); | |
435 } | |
436 for (Iterator<i::Object> it = this->Constants(); !it.Done(); it.Advance()) { | 391 for (Iterator<i::Object> it = this->Constants(); !it.Done(); it.Advance()) { |
437 if (*it.Current() == value) return true; | 392 if (*it.Current() == value) return true; |
438 } | 393 } |
439 return BitsetType::New(BitsetType::Lub(value))->Is(this); | 394 return BitsetType::New(BitsetType::Lub(value))->Is(this); |
440 } | 395 } |
441 | 396 |
442 | 397 |
443 template<class Config> | 398 template<class Config> |
444 bool TypeImpl<Config>::UnionType::Wellformed() { | 399 bool TypeImpl<Config>::UnionType::Wellformed() { |
445 DCHECK(this->Length() >= 2); | 400 DCHECK(this->Length() >= 2); |
(...skipping 12 matching lines...) Expand all Loading... |
458 // Union and intersection | 413 // Union and intersection |
459 | 414 |
460 template<class Config> | 415 template<class Config> |
461 typename TypeImpl<Config>::TypeHandle TypeImpl<Config>::Rebound( | 416 typename TypeImpl<Config>::TypeHandle TypeImpl<Config>::Rebound( |
462 int bitset, Region* region) { | 417 int bitset, Region* region) { |
463 TypeHandle bound = BitsetType::New(bitset, region); | 418 TypeHandle bound = BitsetType::New(bitset, region); |
464 if (this->IsClass()) { | 419 if (this->IsClass()) { |
465 return ClassType::New(this->AsClass()->Map(), bound, region); | 420 return ClassType::New(this->AsClass()->Map(), bound, region); |
466 } else if (this->IsConstant()) { | 421 } else if (this->IsConstant()) { |
467 return ConstantType::New(this->AsConstant()->Value(), bound, region); | 422 return ConstantType::New(this->AsConstant()->Value(), bound, region); |
468 } else if (this->IsRange()) { | |
469 return RangeType::New( | |
470 this->AsRange()->Min(), this->AsRange()->Max(), bound, region); | |
471 } else if (this->IsContext()) { | 423 } else if (this->IsContext()) { |
472 return ContextType::New(this->AsContext()->Outer(), bound, region); | 424 return ContextType::New(this->AsContext()->Outer(), bound, region); |
473 } else if (this->IsArray()) { | 425 } else if (this->IsArray()) { |
474 return ArrayType::New(this->AsArray()->Element(), bound, region); | 426 return ArrayType::New(this->AsArray()->Element(), bound, region); |
475 } else if (this->IsFunction()) { | 427 } else if (this->IsFunction()) { |
476 FunctionHandle function = Config::handle(this->AsFunction()); | 428 FunctionHandle function = Config::handle(this->AsFunction()); |
477 int arity = function->Arity(); | 429 int arity = function->Arity(); |
478 FunctionHandle type = FunctionType::New( | 430 FunctionHandle type = FunctionType::New( |
479 function->Result(), function->Receiver(), bound, arity, region); | 431 function->Result(), function->Receiver(), bound, arity, region); |
480 for (int i = 0; i < arity; ++i) { | 432 for (int i = 0; i < arity; ++i) { |
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
549 if (type->IsUnion()) { | 501 if (type->IsUnion()) { |
550 UnionHandle unioned = handle(type->AsUnion()); | 502 UnionHandle unioned = handle(type->AsUnion()); |
551 for (int i = 0; i < unioned->Length(); ++i) { | 503 for (int i = 0; i < unioned->Length(); ++i) { |
552 TypeHandle type_i = unioned->Get(i); | 504 TypeHandle type_i = unioned->Get(i); |
553 DCHECK(i == 0 || !(type_i->IsBitset() || type_i->Is(unioned->Get(0)))); | 505 DCHECK(i == 0 || !(type_i->IsBitset() || type_i->Is(unioned->Get(0)))); |
554 if (!type_i->IsBitset()) { | 506 if (!type_i->IsBitset()) { |
555 size = ExtendUnion(result, size, type_i, other, is_intersect, region); | 507 size = ExtendUnion(result, size, type_i, other, is_intersect, region); |
556 } | 508 } |
557 } | 509 } |
558 } else if (!type->IsBitset()) { | 510 } else if (!type->IsBitset()) { |
559 DCHECK(type->IsClass() || type->IsConstant() || type->IsRange() || | 511 DCHECK(type->IsClass() || type->IsConstant() || |
560 type->IsContext() || type->IsArray() || type->IsFunction()); | 512 type->IsArray() || type->IsFunction() || type->IsContext()); |
561 int inherent_bound = type->InherentBitsetLub(); | 513 int inherent_bound = type->InherentBitsetLub(); |
562 int old_bound = type->BitsetLub(); | 514 int old_bound = type->BitsetLub(); |
563 int other_bound = type->BoundBy(other->unhandle()) & inherent_bound; | 515 int other_bound = type->BoundBy(other->unhandle()) & inherent_bound; |
564 int new_bound = | 516 int new_bound = |
565 is_intersect ? (old_bound & other_bound) : (old_bound | other_bound); | 517 is_intersect ? (old_bound & other_bound) : (old_bound | other_bound); |
566 if (new_bound != BitsetType::kNone) { | 518 if (new_bound != BitsetType::kNone) { |
567 int i = type->IndexInUnion(new_bound, result, size); | 519 int i = type->IndexInUnion(new_bound, result, size); |
568 if (i == -1) { | 520 if (i == -1) { |
569 i = size++; | 521 i = size++; |
570 } else if (result->Get(i)->IsBitset()) { | 522 } else if (result->Get(i)->IsBitset()) { |
(...skipping 222 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
793 typename TypeImpl<Config>::TypeHandle TypeImpl<Config>::Convert( | 745 typename TypeImpl<Config>::TypeHandle TypeImpl<Config>::Convert( |
794 typename OtherType::TypeHandle type, Region* region) { | 746 typename OtherType::TypeHandle type, Region* region) { |
795 if (type->IsBitset()) { | 747 if (type->IsBitset()) { |
796 return BitsetType::New(type->AsBitset(), region); | 748 return BitsetType::New(type->AsBitset(), region); |
797 } else if (type->IsClass()) { | 749 } else if (type->IsClass()) { |
798 TypeHandle bound = BitsetType::New(type->BitsetLub(), region); | 750 TypeHandle bound = BitsetType::New(type->BitsetLub(), region); |
799 return ClassType::New(type->AsClass()->Map(), bound, region); | 751 return ClassType::New(type->AsClass()->Map(), bound, region); |
800 } else if (type->IsConstant()) { | 752 } else if (type->IsConstant()) { |
801 TypeHandle bound = Convert<OtherType>(type->AsConstant()->Bound(), region); | 753 TypeHandle bound = Convert<OtherType>(type->AsConstant()->Bound(), region); |
802 return ConstantType::New(type->AsConstant()->Value(), bound, region); | 754 return ConstantType::New(type->AsConstant()->Value(), bound, region); |
803 } else if (type->IsRange()) { | |
804 TypeHandle bound = Convert<OtherType>(type->AsRange()->Bound(), region); | |
805 return RangeType::New( | |
806 type->AsRange()->Min(), type->AsRange()->Max(), bound, region); | |
807 } else if (type->IsContext()) { | 755 } else if (type->IsContext()) { |
808 TypeHandle bound = Convert<OtherType>(type->AsContext()->Bound(), region); | 756 TypeHandle bound = Convert<OtherType>(type->AsContext()->Bound(), region); |
809 TypeHandle outer = Convert<OtherType>(type->AsContext()->Outer(), region); | 757 TypeHandle outer = Convert<OtherType>(type->AsContext()->Outer(), region); |
810 return ContextType::New(outer, bound, region); | 758 return ContextType::New(outer, bound, region); |
811 } else if (type->IsUnion()) { | 759 } else if (type->IsUnion()) { |
812 int length = type->AsUnion()->Length(); | 760 int length = type->AsUnion()->Length(); |
813 UnionHandle unioned = UnionType::New(length, region); | 761 UnionHandle unioned = UnionType::New(length, region); |
814 for (int i = 0; i < length; ++i) { | 762 for (int i = 0; i < length; ++i) { |
815 TypeHandle t = Convert<OtherType>(type->AsUnion()->Get(i), region); | 763 TypeHandle t = Convert<OtherType>(type->AsUnion()->Get(i), region); |
816 unioned->Set(i, t); | 764 unioned->Set(i, t); |
(...skipping 163 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
980 template class TypeImpl<HeapTypeConfig>::Iterator<i::Object>; | 928 template class TypeImpl<HeapTypeConfig>::Iterator<i::Object>; |
981 | 929 |
982 template TypeImpl<ZoneTypeConfig>::TypeHandle | 930 template TypeImpl<ZoneTypeConfig>::TypeHandle |
983 TypeImpl<ZoneTypeConfig>::Convert<HeapType>( | 931 TypeImpl<ZoneTypeConfig>::Convert<HeapType>( |
984 TypeImpl<HeapTypeConfig>::TypeHandle, TypeImpl<ZoneTypeConfig>::Region*); | 932 TypeImpl<HeapTypeConfig>::TypeHandle, TypeImpl<ZoneTypeConfig>::Region*); |
985 template TypeImpl<HeapTypeConfig>::TypeHandle | 933 template TypeImpl<HeapTypeConfig>::TypeHandle |
986 TypeImpl<HeapTypeConfig>::Convert<Type>( | 934 TypeImpl<HeapTypeConfig>::Convert<Type>( |
987 TypeImpl<ZoneTypeConfig>::TypeHandle, TypeImpl<HeapTypeConfig>::Region*); | 935 TypeImpl<ZoneTypeConfig>::TypeHandle, TypeImpl<HeapTypeConfig>::Region*); |
988 | 936 |
989 } } // namespace v8::internal | 937 } } // namespace v8::internal |
OLD | NEW |