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