Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2014 the V8 project authors. All rights reserved. | 1 // Copyright 2014 the V8 project authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "src/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 numbers. | |
| 16 // We want -0 to be less than +0. | |
| 17 | |
| 18 static bool le(double x, double y) { | |
| 19 return x <= y && copysign(1, x) <= copysign(1, y); | |
| 20 } | |
| 21 | |
| 22 | |
| 23 static bool eq(double x, double y) { | |
| 24 return le(x, y) && le(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 DCHECK(le(min, max)); | |
| 137 DisallowHeapAllocation no_allocation; | |
|
rossberg
2014/08/06 13:27:31
Nit: put this first
| |
| 138 if (eq(min, max)) { | |
|
rossberg
2014/08/06 13:27:31
Style nit: same line:
if (eq(min, max)) return
| |
| 139 return BitsetType::Lub(min); // Singleton range. | |
| 140 } | |
| 141 int bitset = BitsetType::kNumber ^ SEMANTIC(BitsetType::kNaN); | |
| 142 if (le(0, min) || max < 0) | |
|
rossberg
2014/08/06 13:27:31
Style nit: same line
| |
| 143 bitset ^= SEMANTIC(BitsetType::kMinusZero); | |
| 144 return bitset; | |
| 145 // TODO(neis): Could refine this further by doing more checks on min/max. | |
| 146 } | |
| 147 | |
| 148 | |
| 149 template<class Config> | |
| 116 int TypeImpl<Config>::BitsetType::Lub(int32_t value) { | 150 int TypeImpl<Config>::BitsetType::Lub(int32_t value) { |
| 117 if (value >= 0x40000000) { | 151 if (value >= 0x40000000) { |
| 118 return i::SmiValuesAre31Bits() ? kOtherUnsigned31 : kUnsignedSmall; | 152 return i::SmiValuesAre31Bits() ? kOtherUnsigned31 : kUnsignedSmall; |
| 119 } | 153 } |
| 120 if (value >= 0) return kUnsignedSmall; | 154 if (value >= 0) return kUnsignedSmall; |
| 121 if (value >= -0x40000000) return kOtherSignedSmall; | 155 if (value >= -0x40000000) return kOtherSignedSmall; |
| 122 return i::SmiValuesAre31Bits() ? kOtherSigned32 : kOtherSignedSmall; | 156 return i::SmiValuesAre31Bits() ? kOtherSigned32 : kOtherSignedSmall; |
| 123 } | 157 } |
| 124 | 158 |
| 125 | 159 |
| (...skipping 123 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 249 && *this->AsClass()->Map() == *that->AsClass()->Map() | 283 && *this->AsClass()->Map() == *that->AsClass()->Map() |
| 250 && ((Config::is_class(that) && Config::is_class(this)) || | 284 && ((Config::is_class(that) && Config::is_class(this)) || |
| 251 BitsetType::New(this->BitsetLub())->Is( | 285 BitsetType::New(this->BitsetLub())->Is( |
| 252 BitsetType::New(that->BitsetLub()))); | 286 BitsetType::New(that->BitsetLub()))); |
| 253 } | 287 } |
| 254 if (that->IsConstant()) { | 288 if (that->IsConstant()) { |
| 255 return this->IsConstant() | 289 return this->IsConstant() |
| 256 && *this->AsConstant()->Value() == *that->AsConstant()->Value() | 290 && *this->AsConstant()->Value() == *that->AsConstant()->Value() |
| 257 && this->AsConstant()->Bound()->Is(that->AsConstant()->Bound()); | 291 && this->AsConstant()->Bound()->Is(that->AsConstant()->Bound()); |
| 258 } | 292 } |
| 293 if (that->IsRange()) { | |
| 294 return this->IsRange() | |
| 295 && this->AsRange()->Bound()->Is(that->AsRange()->Bound()) | |
| 296 && le(that->AsRange()->Min(), this->AsRange()->Min()) | |
| 297 && le(this->AsRange()->Max(), that->AsRange()->Max()); | |
| 298 } | |
| 259 if (that->IsContext()) { | 299 if (that->IsContext()) { |
| 260 return this->IsContext() | 300 return this->IsContext() |
| 261 && this->AsContext()->Outer()->Equals(that->AsContext()->Outer()); | 301 && this->AsContext()->Outer()->Equals(that->AsContext()->Outer()); |
| 262 } | 302 } |
| 263 if (that->IsArray()) { | 303 if (that->IsArray()) { |
| 264 return this->IsArray() | 304 return this->IsArray() |
| 265 && this->AsArray()->Element()->Equals(that->AsArray()->Element()); | 305 && this->AsArray()->Element()->Equals(that->AsArray()->Element()); |
| 266 } | 306 } |
| 267 if (that->IsFunction()) { | 307 if (that->IsFunction()) { |
| 268 // We currently do not allow for any variance here, in order to keep | 308 // 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 } | 421 } |
| 382 | 422 |
| 383 return false; | 423 return false; |
| 384 } | 424 } |
| 385 | 425 |
| 386 | 426 |
| 387 // Check if value is contained in (inhabits) type. | 427 // Check if value is contained in (inhabits) type. |
| 388 template<class Config> | 428 template<class Config> |
| 389 bool TypeImpl<Config>::Contains(i::Object* value) { | 429 bool TypeImpl<Config>::Contains(i::Object* value) { |
| 390 DisallowHeapAllocation no_allocation; | 430 DisallowHeapAllocation no_allocation; |
| 431 if (this->IsRange()) { | |
| 432 return value->IsNumber() && | |
| 433 le(this->AsRange()->Min(), value->Number()) && | |
| 434 le(value->Number(), this->AsRange()->Max()) && | |
| 435 BitsetType::Is(BitsetType::Lub(value), this->BitsetLub()); | |
| 436 } | |
| 391 for (Iterator<i::Object> it = this->Constants(); !it.Done(); it.Advance()) { | 437 for (Iterator<i::Object> it = this->Constants(); !it.Done(); it.Advance()) { |
| 392 if (*it.Current() == value) return true; | 438 if (*it.Current() == value) return true; |
| 393 } | 439 } |
| 394 return BitsetType::New(BitsetType::Lub(value))->Is(this); | 440 return BitsetType::New(BitsetType::Lub(value))->Is(this); |
| 395 } | 441 } |
| 396 | 442 |
| 397 | 443 |
| 398 template<class Config> | 444 template<class Config> |
| 399 bool TypeImpl<Config>::UnionType::Wellformed() { | 445 bool TypeImpl<Config>::UnionType::Wellformed() { |
| 400 DCHECK(this->Length() >= 2); | 446 DCHECK(this->Length() >= 2); |
| (...skipping 12 matching lines...) Expand all Loading... | |
| 413 // Union and intersection | 459 // Union and intersection |
| 414 | 460 |
| 415 template<class Config> | 461 template<class Config> |
| 416 typename TypeImpl<Config>::TypeHandle TypeImpl<Config>::Rebound( | 462 typename TypeImpl<Config>::TypeHandle TypeImpl<Config>::Rebound( |
| 417 int bitset, Region* region) { | 463 int bitset, Region* region) { |
| 418 TypeHandle bound = BitsetType::New(bitset, region); | 464 TypeHandle bound = BitsetType::New(bitset, region); |
| 419 if (this->IsClass()) { | 465 if (this->IsClass()) { |
| 420 return ClassType::New(this->AsClass()->Map(), bound, region); | 466 return ClassType::New(this->AsClass()->Map(), bound, region); |
| 421 } else if (this->IsConstant()) { | 467 } else if (this->IsConstant()) { |
| 422 return ConstantType::New(this->AsConstant()->Value(), bound, region); | 468 return ConstantType::New(this->AsConstant()->Value(), bound, region); |
| 469 } else if (this->IsRange()) { | |
| 470 return RangeType::New( | |
| 471 this->AsRange()->Min(), this->AsRange()->Max(), bound, region); | |
| 423 } else if (this->IsContext()) { | 472 } else if (this->IsContext()) { |
| 424 return ContextType::New(this->AsContext()->Outer(), bound, region); | 473 return ContextType::New(this->AsContext()->Outer(), bound, region); |
| 425 } else if (this->IsArray()) { | 474 } else if (this->IsArray()) { |
| 426 return ArrayType::New(this->AsArray()->Element(), bound, region); | 475 return ArrayType::New(this->AsArray()->Element(), bound, region); |
| 427 } else if (this->IsFunction()) { | 476 } else if (this->IsFunction()) { |
| 428 FunctionType* function = this->AsFunction(); | 477 FunctionType* function = this->AsFunction(); |
| 429 int arity = function->Arity(); | 478 int arity = function->Arity(); |
| 430 FunctionHandle type = FunctionType::New( | 479 FunctionHandle type = FunctionType::New( |
| 431 function->Result(), function->Receiver(), bound, arity, region); | 480 function->Result(), function->Receiver(), bound, arity, region); |
| 432 for (int i = 0; i < arity; ++i) { | 481 for (int i = 0; i < arity; ++i) { |
| (...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 501 if (type->IsUnion()) { | 550 if (type->IsUnion()) { |
| 502 UnionHandle unioned = handle(type->AsUnion()); | 551 UnionHandle unioned = handle(type->AsUnion()); |
| 503 for (int i = 0; i < unioned->Length(); ++i) { | 552 for (int i = 0; i < unioned->Length(); ++i) { |
| 504 TypeHandle type_i = unioned->Get(i); | 553 TypeHandle type_i = unioned->Get(i); |
| 505 DCHECK(i == 0 || !(type_i->IsBitset() || type_i->Is(unioned->Get(0)))); | 554 DCHECK(i == 0 || !(type_i->IsBitset() || type_i->Is(unioned->Get(0)))); |
| 506 if (!type_i->IsBitset()) { | 555 if (!type_i->IsBitset()) { |
| 507 size = ExtendUnion(result, size, type_i, other, is_intersect, region); | 556 size = ExtendUnion(result, size, type_i, other, is_intersect, region); |
| 508 } | 557 } |
| 509 } | 558 } |
| 510 } else if (!type->IsBitset()) { | 559 } else if (!type->IsBitset()) { |
| 511 DCHECK(type->IsClass() || type->IsConstant() || | 560 DCHECK(type->IsClass() || type->IsConstant() || type->IsRange() || |
| 512 type->IsArray() || type->IsFunction() || type->IsContext()); | 561 type->IsContext() || type->IsArray() || type->IsFunction()); |
| 513 int inherent_bound = type->InherentBitsetLub(); | 562 int inherent_bound = type->InherentBitsetLub(); |
| 514 int old_bound = type->BitsetLub(); | 563 int old_bound = type->BitsetLub(); |
| 515 int other_bound = type->BoundBy(other->unhandle()) & inherent_bound; | 564 int other_bound = type->BoundBy(other->unhandle()) & inherent_bound; |
| 516 int new_bound = | 565 int new_bound = |
| 517 is_intersect ? (old_bound & other_bound) : (old_bound | other_bound); | 566 is_intersect ? (old_bound & other_bound) : (old_bound | other_bound); |
| 518 if (new_bound != BitsetType::kNone) { | 567 if (new_bound != BitsetType::kNone) { |
| 519 int i = type->IndexInUnion(new_bound, result, size); | 568 int i = type->IndexInUnion(new_bound, result, size); |
| 520 if (i == -1) { | 569 if (i == -1) { |
| 521 i = size++; | 570 i = size++; |
| 522 } else if (result->Get(i)->IsBitset()) { | 571 } else if (result->Get(i)->IsBitset()) { |
| (...skipping 224 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 747 if (type->IsBitset()) { | 796 if (type->IsBitset()) { |
| 748 return BitsetType::New(type->AsBitset(), region); | 797 return BitsetType::New(type->AsBitset(), region); |
| 749 } else if (type->IsClass()) { | 798 } else if (type->IsClass()) { |
| 750 return ClassType::New( | 799 return ClassType::New( |
| 751 type->AsClass()->Map(), | 800 type->AsClass()->Map(), |
| 752 BitsetType::New(type->BitsetLub(), region), region); | 801 BitsetType::New(type->BitsetLub(), region), region); |
| 753 } else if (type->IsConstant()) { | 802 } else if (type->IsConstant()) { |
| 754 return ConstantType::New( | 803 return ConstantType::New( |
| 755 type->AsConstant()->Value(), | 804 type->AsConstant()->Value(), |
| 756 Convert<OtherType>(type->AsConstant()->Bound(), region), region); | 805 Convert<OtherType>(type->AsConstant()->Bound(), region), region); |
| 806 } else if (type->IsRange()) { | |
| 807 return RangeType::New( | |
| 808 type->AsRange()->Min(), type->AsRange()->Max(), | |
| 809 Convert<OtherType>(type->AsRange()->Bound(), region), region); | |
| 757 } else if (type->IsContext()) { | 810 } else if (type->IsContext()) { |
| 758 TypeHandle outer = Convert<OtherType>(type->AsContext()->Outer(), region); | 811 TypeHandle outer = Convert<OtherType>(type->AsContext()->Outer(), region); |
| 759 return ContextType::New(outer, region); | 812 return ContextType::New(outer, region); |
| 760 } else if (type->IsUnion()) { | 813 } else if (type->IsUnion()) { |
| 761 int length = type->AsUnion()->Length(); | 814 int length = type->AsUnion()->Length(); |
| 762 UnionHandle unioned = UnionType::New(length, region); | 815 UnionHandle unioned = UnionType::New(length, region); |
| 763 for (int i = 0; i < length; ++i) { | 816 for (int i = 0; i < length; ++i) { |
| 764 unioned->Set(i, Convert<OtherType>(type->AsUnion()->Get(i), region)); | 817 unioned->Set(i, Convert<OtherType>(type->AsUnion()->Get(i), region)); |
| 765 } | 818 } |
| 766 return unioned; | 819 return unioned; |
| (...skipping 150 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 917 template class TypeImpl<HeapTypeConfig>::Iterator<i::Object>; | 970 template class TypeImpl<HeapTypeConfig>::Iterator<i::Object>; |
| 918 | 971 |
| 919 template TypeImpl<ZoneTypeConfig>::TypeHandle | 972 template TypeImpl<ZoneTypeConfig>::TypeHandle |
| 920 TypeImpl<ZoneTypeConfig>::Convert<HeapType>( | 973 TypeImpl<ZoneTypeConfig>::Convert<HeapType>( |
| 921 TypeImpl<HeapTypeConfig>::TypeHandle, TypeImpl<ZoneTypeConfig>::Region*); | 974 TypeImpl<HeapTypeConfig>::TypeHandle, TypeImpl<ZoneTypeConfig>::Region*); |
| 922 template TypeImpl<HeapTypeConfig>::TypeHandle | 975 template TypeImpl<HeapTypeConfig>::TypeHandle |
| 923 TypeImpl<HeapTypeConfig>::Convert<Type>( | 976 TypeImpl<HeapTypeConfig>::Convert<Type>( |
| 924 TypeImpl<ZoneTypeConfig>::TypeHandle, TypeImpl<HeapTypeConfig>::Region*); | 977 TypeImpl<ZoneTypeConfig>::TypeHandle, TypeImpl<HeapTypeConfig>::Region*); |
| 925 | 978 |
| 926 } } // namespace v8::internal | 979 } } // namespace v8::internal |
| OLD | NEW |