| OLD | NEW |
| (Empty) |
| 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 | |
| 3 // found in the LICENSE file. | |
| 4 | |
| 5 #include <iomanip> | |
| 6 | |
| 7 #include "src/types.h" | |
| 8 | |
| 9 #include "src/handles-inl.h" | |
| 10 #include "src/ostreams.h" | |
| 11 | |
| 12 namespace v8 { | |
| 13 namespace internal { | |
| 14 | |
| 15 | |
| 16 // NOTE: If code is marked as being a "shortcut", this means that removing | |
| 17 // the code won't affect the semantics of the surrounding function definition. | |
| 18 | |
| 19 // static | |
| 20 bool Type::IsInteger(i::Object* x) { | |
| 21 return x->IsNumber() && Type::IsInteger(x->Number()); | |
| 22 } | |
| 23 | |
| 24 // ----------------------------------------------------------------------------- | |
| 25 // Range-related helper functions. | |
| 26 | |
| 27 bool RangeType::Limits::IsEmpty() { return this->min > this->max; } | |
| 28 | |
| 29 RangeType::Limits RangeType::Limits::Intersect(Limits lhs, Limits rhs) { | |
| 30 DisallowHeapAllocation no_allocation; | |
| 31 Limits result(lhs); | |
| 32 if (lhs.min < rhs.min) result.min = rhs.min; | |
| 33 if (lhs.max > rhs.max) result.max = rhs.max; | |
| 34 return result; | |
| 35 } | |
| 36 | |
| 37 RangeType::Limits RangeType::Limits::Union(Limits lhs, Limits rhs) { | |
| 38 DisallowHeapAllocation no_allocation; | |
| 39 if (lhs.IsEmpty()) return rhs; | |
| 40 if (rhs.IsEmpty()) return lhs; | |
| 41 Limits result(lhs); | |
| 42 if (lhs.min > rhs.min) result.min = rhs.min; | |
| 43 if (lhs.max < rhs.max) result.max = rhs.max; | |
| 44 return result; | |
| 45 } | |
| 46 | |
| 47 bool Type::Overlap(RangeType* lhs, RangeType* rhs) { | |
| 48 DisallowHeapAllocation no_allocation; | |
| 49 return !RangeType::Limits::Intersect(RangeType::Limits(lhs), | |
| 50 RangeType::Limits(rhs)) | |
| 51 .IsEmpty(); | |
| 52 } | |
| 53 | |
| 54 bool Type::Contains(RangeType* lhs, RangeType* rhs) { | |
| 55 DisallowHeapAllocation no_allocation; | |
| 56 return lhs->Min() <= rhs->Min() && rhs->Max() <= lhs->Max(); | |
| 57 } | |
| 58 | |
| 59 bool Type::Contains(RangeType* lhs, ConstantType* rhs) { | |
| 60 DisallowHeapAllocation no_allocation; | |
| 61 return IsInteger(*rhs->Value()) && | |
| 62 lhs->Min() <= rhs->Value()->Number() && | |
| 63 rhs->Value()->Number() <= lhs->Max(); | |
| 64 } | |
| 65 | |
| 66 bool Type::Contains(RangeType* range, i::Object* val) { | |
| 67 DisallowHeapAllocation no_allocation; | |
| 68 return IsInteger(val) && | |
| 69 range->Min() <= val->Number() && val->Number() <= range->Max(); | |
| 70 } | |
| 71 | |
| 72 | |
| 73 // ----------------------------------------------------------------------------- | |
| 74 // Min and Max computation. | |
| 75 | |
| 76 double Type::Min() { | |
| 77 DCHECK(this->SemanticIs(Number())); | |
| 78 if (this->IsBitset()) return BitsetType::Min(this->AsBitset()); | |
| 79 if (this->IsUnion()) { | |
| 80 double min = +V8_INFINITY; | |
| 81 for (int i = 0, n = this->AsUnion()->Length(); i < n; ++i) { | |
| 82 min = std::min(min, this->AsUnion()->Get(i)->Min()); | |
| 83 } | |
| 84 return min; | |
| 85 } | |
| 86 if (this->IsRange()) return this->AsRange()->Min(); | |
| 87 if (this->IsConstant()) return this->AsConstant()->Value()->Number(); | |
| 88 UNREACHABLE(); | |
| 89 return 0; | |
| 90 } | |
| 91 | |
| 92 double Type::Max() { | |
| 93 DCHECK(this->SemanticIs(Number())); | |
| 94 if (this->IsBitset()) return BitsetType::Max(this->AsBitset()); | |
| 95 if (this->IsUnion()) { | |
| 96 double max = -V8_INFINITY; | |
| 97 for (int i = 0, n = this->AsUnion()->Length(); i < n; ++i) { | |
| 98 max = std::max(max, this->AsUnion()->Get(i)->Max()); | |
| 99 } | |
| 100 return max; | |
| 101 } | |
| 102 if (this->IsRange()) return this->AsRange()->Max(); | |
| 103 if (this->IsConstant()) return this->AsConstant()->Value()->Number(); | |
| 104 UNREACHABLE(); | |
| 105 return 0; | |
| 106 } | |
| 107 | |
| 108 | |
| 109 // ----------------------------------------------------------------------------- | |
| 110 // Glb and lub computation. | |
| 111 | |
| 112 | |
| 113 // The largest bitset subsumed by this type. | |
| 114 Type::bitset BitsetType::Glb(Type* type) { | |
| 115 DisallowHeapAllocation no_allocation; | |
| 116 // Fast case. | |
| 117 if (IsBitset(type)) { | |
| 118 return type->AsBitset(); | |
| 119 } else if (type->IsUnion()) { | |
| 120 SLOW_DCHECK(type->AsUnion()->Wellformed()); | |
| 121 return type->AsUnion()->Get(0)->BitsetGlb() | | |
| 122 SEMANTIC(type->AsUnion()->Get(1)->BitsetGlb()); // Shortcut. | |
| 123 } else if (type->IsRange()) { | |
| 124 bitset glb = SEMANTIC( | |
| 125 BitsetType::Glb(type->AsRange()->Min(), type->AsRange()->Max())); | |
| 126 return glb | REPRESENTATION(type->BitsetLub()); | |
| 127 } else { | |
| 128 return type->Representation(); | |
| 129 } | |
| 130 } | |
| 131 | |
| 132 | |
| 133 // The smallest bitset subsuming this type, possibly not a proper one. | |
| 134 Type::bitset BitsetType::Lub(Type* type) { | |
| 135 DisallowHeapAllocation no_allocation; | |
| 136 if (IsBitset(type)) return type->AsBitset(); | |
| 137 if (type->IsUnion()) { | |
| 138 // Take the representation from the first element, which is always | |
| 139 // a bitset. | |
| 140 int bitset = type->AsUnion()->Get(0)->BitsetLub(); | |
| 141 for (int i = 0, n = type->AsUnion()->Length(); i < n; ++i) { | |
| 142 // Other elements only contribute their semantic part. | |
| 143 bitset |= SEMANTIC(type->AsUnion()->Get(i)->BitsetLub()); | |
| 144 } | |
| 145 return bitset; | |
| 146 } | |
| 147 if (type->IsConstant()) return type->AsConstant()->Lub(); | |
| 148 if (type->IsRange()) return type->AsRange()->Lub(); | |
| 149 if (type->IsTuple()) return kOtherInternal; | |
| 150 UNREACHABLE(); | |
| 151 return kNone; | |
| 152 } | |
| 153 | |
| 154 Type::bitset BitsetType::Lub(i::Map* map) { | |
| 155 DisallowHeapAllocation no_allocation; | |
| 156 switch (map->instance_type()) { | |
| 157 case STRING_TYPE: | |
| 158 case ONE_BYTE_STRING_TYPE: | |
| 159 case CONS_STRING_TYPE: | |
| 160 case CONS_ONE_BYTE_STRING_TYPE: | |
| 161 case SLICED_STRING_TYPE: | |
| 162 case SLICED_ONE_BYTE_STRING_TYPE: | |
| 163 case EXTERNAL_STRING_TYPE: | |
| 164 case EXTERNAL_ONE_BYTE_STRING_TYPE: | |
| 165 case EXTERNAL_STRING_WITH_ONE_BYTE_DATA_TYPE: | |
| 166 case SHORT_EXTERNAL_STRING_TYPE: | |
| 167 case SHORT_EXTERNAL_ONE_BYTE_STRING_TYPE: | |
| 168 case SHORT_EXTERNAL_STRING_WITH_ONE_BYTE_DATA_TYPE: | |
| 169 return kOtherString; | |
| 170 case INTERNALIZED_STRING_TYPE: | |
| 171 case ONE_BYTE_INTERNALIZED_STRING_TYPE: | |
| 172 case EXTERNAL_INTERNALIZED_STRING_TYPE: | |
| 173 case EXTERNAL_ONE_BYTE_INTERNALIZED_STRING_TYPE: | |
| 174 case EXTERNAL_INTERNALIZED_STRING_WITH_ONE_BYTE_DATA_TYPE: | |
| 175 case SHORT_EXTERNAL_INTERNALIZED_STRING_TYPE: | |
| 176 case SHORT_EXTERNAL_ONE_BYTE_INTERNALIZED_STRING_TYPE: | |
| 177 case SHORT_EXTERNAL_INTERNALIZED_STRING_WITH_ONE_BYTE_DATA_TYPE: | |
| 178 return kInternalizedString; | |
| 179 case SYMBOL_TYPE: | |
| 180 return kSymbol; | |
| 181 case ODDBALL_TYPE: { | |
| 182 Heap* heap = map->GetHeap(); | |
| 183 if (map == heap->undefined_map()) return kUndefined; | |
| 184 if (map == heap->null_map()) return kNull; | |
| 185 if (map == heap->boolean_map()) return kBoolean; | |
| 186 if (map == heap->the_hole_map()) return kHole; | |
| 187 DCHECK(map == heap->uninitialized_map() || | |
| 188 map == heap->no_interceptor_result_sentinel_map() || | |
| 189 map == heap->termination_exception_map() || | |
| 190 map == heap->arguments_marker_map() || | |
| 191 map == heap->optimized_out_map() || | |
| 192 map == heap->stale_register_map()); | |
| 193 return kOtherInternal & kTaggedPointer; | |
| 194 } | |
| 195 case HEAP_NUMBER_TYPE: | |
| 196 return kNumber & kTaggedPointer; | |
| 197 case SIMD128_VALUE_TYPE: | |
| 198 return kSimd; | |
| 199 case JS_OBJECT_TYPE: | |
| 200 case JS_ARGUMENTS_TYPE: | |
| 201 case JS_ERROR_TYPE: | |
| 202 case JS_GLOBAL_OBJECT_TYPE: | |
| 203 case JS_GLOBAL_PROXY_TYPE: | |
| 204 case JS_API_OBJECT_TYPE: | |
| 205 case JS_SPECIAL_API_OBJECT_TYPE: | |
| 206 if (map->is_undetectable()) return kOtherUndetectable; | |
| 207 return kOtherObject; | |
| 208 case JS_VALUE_TYPE: | |
| 209 case JS_MESSAGE_OBJECT_TYPE: | |
| 210 case JS_DATE_TYPE: | |
| 211 case JS_CONTEXT_EXTENSION_OBJECT_TYPE: | |
| 212 case JS_GENERATOR_OBJECT_TYPE: | |
| 213 case JS_MODULE_TYPE: | |
| 214 case JS_ARRAY_BUFFER_TYPE: | |
| 215 case JS_ARRAY_TYPE: | |
| 216 case JS_REGEXP_TYPE: // TODO(rossberg): there should be a RegExp type. | |
| 217 case JS_TYPED_ARRAY_TYPE: | |
| 218 case JS_DATA_VIEW_TYPE: | |
| 219 case JS_SET_TYPE: | |
| 220 case JS_MAP_TYPE: | |
| 221 case JS_SET_ITERATOR_TYPE: | |
| 222 case JS_MAP_ITERATOR_TYPE: | |
| 223 case JS_WEAK_MAP_TYPE: | |
| 224 case JS_WEAK_SET_TYPE: | |
| 225 case JS_PROMISE_TYPE: | |
| 226 case JS_BOUND_FUNCTION_TYPE: | |
| 227 DCHECK(!map->is_undetectable()); | |
| 228 return kOtherObject; | |
| 229 case JS_FUNCTION_TYPE: | |
| 230 DCHECK(!map->is_undetectable()); | |
| 231 return kFunction; | |
| 232 case JS_PROXY_TYPE: | |
| 233 DCHECK(!map->is_undetectable()); | |
| 234 return kProxy; | |
| 235 case MAP_TYPE: | |
| 236 case ALLOCATION_SITE_TYPE: | |
| 237 case ACCESSOR_INFO_TYPE: | |
| 238 case SHARED_FUNCTION_INFO_TYPE: | |
| 239 case ACCESSOR_PAIR_TYPE: | |
| 240 case FIXED_ARRAY_TYPE: | |
| 241 case FIXED_DOUBLE_ARRAY_TYPE: | |
| 242 case BYTE_ARRAY_TYPE: | |
| 243 case BYTECODE_ARRAY_TYPE: | |
| 244 case TRANSITION_ARRAY_TYPE: | |
| 245 case FOREIGN_TYPE: | |
| 246 case SCRIPT_TYPE: | |
| 247 case CODE_TYPE: | |
| 248 case PROPERTY_CELL_TYPE: | |
| 249 return kOtherInternal & kTaggedPointer; | |
| 250 | |
| 251 // Remaining instance types are unsupported for now. If any of them do | |
| 252 // require bit set types, they should get kOtherInternal & kTaggedPointer. | |
| 253 case MUTABLE_HEAP_NUMBER_TYPE: | |
| 254 case FREE_SPACE_TYPE: | |
| 255 #define FIXED_TYPED_ARRAY_CASE(Type, type, TYPE, ctype, size) \ | |
| 256 case FIXED_##TYPE##_ARRAY_TYPE: | |
| 257 | |
| 258 TYPED_ARRAYS(FIXED_TYPED_ARRAY_CASE) | |
| 259 #undef FIXED_TYPED_ARRAY_CASE | |
| 260 case FILLER_TYPE: | |
| 261 case ACCESS_CHECK_INFO_TYPE: | |
| 262 case INTERCEPTOR_INFO_TYPE: | |
| 263 case CALL_HANDLER_INFO_TYPE: | |
| 264 case FUNCTION_TEMPLATE_INFO_TYPE: | |
| 265 case OBJECT_TEMPLATE_INFO_TYPE: | |
| 266 case SIGNATURE_INFO_TYPE: | |
| 267 case TYPE_SWITCH_INFO_TYPE: | |
| 268 case ALLOCATION_MEMENTO_TYPE: | |
| 269 case TYPE_FEEDBACK_INFO_TYPE: | |
| 270 case ALIASED_ARGUMENTS_ENTRY_TYPE: | |
| 271 case BOX_TYPE: | |
| 272 case DEBUG_INFO_TYPE: | |
| 273 case BREAK_POINT_INFO_TYPE: | |
| 274 case CELL_TYPE: | |
| 275 case WEAK_CELL_TYPE: | |
| 276 case PROTOTYPE_INFO_TYPE: | |
| 277 case CONTEXT_EXTENSION_TYPE: | |
| 278 UNREACHABLE(); | |
| 279 return kNone; | |
| 280 } | |
| 281 UNREACHABLE(); | |
| 282 return kNone; | |
| 283 } | |
| 284 | |
| 285 Type::bitset BitsetType::Lub(i::Object* value) { | |
| 286 DisallowHeapAllocation no_allocation; | |
| 287 if (value->IsNumber()) { | |
| 288 return Lub(value->Number()) & | |
| 289 (value->IsSmi() ? kTaggedSigned : kTaggedPointer); | |
| 290 } | |
| 291 return Lub(i::HeapObject::cast(value)->map()); | |
| 292 } | |
| 293 | |
| 294 Type::bitset BitsetType::Lub(double value) { | |
| 295 DisallowHeapAllocation no_allocation; | |
| 296 if (i::IsMinusZero(value)) return kMinusZero; | |
| 297 if (std::isnan(value)) return kNaN; | |
| 298 if (IsUint32Double(value) || IsInt32Double(value)) return Lub(value, value); | |
| 299 return kOtherNumber; | |
| 300 } | |
| 301 | |
| 302 | |
| 303 // Minimum values of plain numeric bitsets. | |
| 304 const BitsetType::Boundary BitsetType::BoundariesArray[] = { | |
| 305 {kOtherNumber, kPlainNumber, -V8_INFINITY}, | |
| 306 {kOtherSigned32, kNegative32, kMinInt}, | |
| 307 {kNegative31, kNegative31, -0x40000000}, | |
| 308 {kUnsigned30, kUnsigned30, 0}, | |
| 309 {kOtherUnsigned31, kUnsigned31, 0x40000000}, | |
| 310 {kOtherUnsigned32, kUnsigned32, 0x80000000}, | |
| 311 {kOtherNumber, kPlainNumber, static_cast<double>(kMaxUInt32) + 1}}; | |
| 312 | |
| 313 const BitsetType::Boundary* BitsetType::Boundaries() { return BoundariesArray; } | |
| 314 | |
| 315 size_t BitsetType::BoundariesSize() { | |
| 316 // Windows doesn't like arraysize here. | |
| 317 // return arraysize(BoundariesArray); | |
| 318 return 7; | |
| 319 } | |
| 320 | |
| 321 Type::bitset BitsetType::ExpandInternals(Type::bitset bits) { | |
| 322 DisallowHeapAllocation no_allocation; | |
| 323 if (!(bits & SEMANTIC(kPlainNumber))) return bits; // Shortcut. | |
| 324 const Boundary* boundaries = Boundaries(); | |
| 325 for (size_t i = 0; i < BoundariesSize(); ++i) { | |
| 326 DCHECK(BitsetType::Is(boundaries[i].internal, boundaries[i].external)); | |
| 327 if (bits & SEMANTIC(boundaries[i].internal)) | |
| 328 bits |= SEMANTIC(boundaries[i].external); | |
| 329 } | |
| 330 return bits; | |
| 331 } | |
| 332 | |
| 333 Type::bitset BitsetType::Lub(double min, double max) { | |
| 334 DisallowHeapAllocation no_allocation; | |
| 335 int lub = kNone; | |
| 336 const Boundary* mins = Boundaries(); | |
| 337 | |
| 338 for (size_t i = 1; i < BoundariesSize(); ++i) { | |
| 339 if (min < mins[i].min) { | |
| 340 lub |= mins[i-1].internal; | |
| 341 if (max < mins[i].min) return lub; | |
| 342 } | |
| 343 } | |
| 344 return lub | mins[BoundariesSize() - 1].internal; | |
| 345 } | |
| 346 | |
| 347 Type::bitset BitsetType::NumberBits(bitset bits) { | |
| 348 return SEMANTIC(bits & kPlainNumber); | |
| 349 } | |
| 350 | |
| 351 Type::bitset BitsetType::Glb(double min, double max) { | |
| 352 DisallowHeapAllocation no_allocation; | |
| 353 int glb = kNone; | |
| 354 const Boundary* mins = Boundaries(); | |
| 355 | |
| 356 // If the range does not touch 0, the bound is empty. | |
| 357 if (max < -1 || min > 0) return glb; | |
| 358 | |
| 359 for (size_t i = 1; i + 1 < BoundariesSize(); ++i) { | |
| 360 if (min <= mins[i].min) { | |
| 361 if (max + 1 < mins[i + 1].min) break; | |
| 362 glb |= mins[i].external; | |
| 363 } | |
| 364 } | |
| 365 // OtherNumber also contains float numbers, so it can never be | |
| 366 // in the greatest lower bound. | |
| 367 return glb & ~(SEMANTIC(kOtherNumber)); | |
| 368 } | |
| 369 | |
| 370 double BitsetType::Min(bitset bits) { | |
| 371 DisallowHeapAllocation no_allocation; | |
| 372 DCHECK(Is(SEMANTIC(bits), kNumber)); | |
| 373 const Boundary* mins = Boundaries(); | |
| 374 bool mz = SEMANTIC(bits & kMinusZero); | |
| 375 for (size_t i = 0; i < BoundariesSize(); ++i) { | |
| 376 if (Is(SEMANTIC(mins[i].internal), bits)) { | |
| 377 return mz ? std::min(0.0, mins[i].min) : mins[i].min; | |
| 378 } | |
| 379 } | |
| 380 if (mz) return 0; | |
| 381 return std::numeric_limits<double>::quiet_NaN(); | |
| 382 } | |
| 383 | |
| 384 double BitsetType::Max(bitset bits) { | |
| 385 DisallowHeapAllocation no_allocation; | |
| 386 DCHECK(Is(SEMANTIC(bits), kNumber)); | |
| 387 const Boundary* mins = Boundaries(); | |
| 388 bool mz = SEMANTIC(bits & kMinusZero); | |
| 389 if (BitsetType::Is(SEMANTIC(mins[BoundariesSize() - 1].internal), bits)) { | |
| 390 return +V8_INFINITY; | |
| 391 } | |
| 392 for (size_t i = BoundariesSize() - 1; i-- > 0;) { | |
| 393 if (Is(SEMANTIC(mins[i].internal), bits)) { | |
| 394 return mz ? | |
| 395 std::max(0.0, mins[i+1].min - 1) : mins[i+1].min - 1; | |
| 396 } | |
| 397 } | |
| 398 if (mz) return 0; | |
| 399 return std::numeric_limits<double>::quiet_NaN(); | |
| 400 } | |
| 401 | |
| 402 | |
| 403 // ----------------------------------------------------------------------------- | |
| 404 // Predicates. | |
| 405 | |
| 406 bool Type::SimplyEquals(Type* that) { | |
| 407 DisallowHeapAllocation no_allocation; | |
| 408 if (this->IsConstant()) { | |
| 409 return that->IsConstant() | |
| 410 && *this->AsConstant()->Value() == *that->AsConstant()->Value(); | |
| 411 } | |
| 412 if (this->IsTuple()) { | |
| 413 if (!that->IsTuple()) return false; | |
| 414 TupleType* this_tuple = this->AsTuple(); | |
| 415 TupleType* that_tuple = that->AsTuple(); | |
| 416 if (this_tuple->Arity() != that_tuple->Arity()) { | |
| 417 return false; | |
| 418 } | |
| 419 for (int i = 0, n = this_tuple->Arity(); i < n; ++i) { | |
| 420 if (!this_tuple->Element(i)->Equals(that_tuple->Element(i))) return false; | |
| 421 } | |
| 422 return true; | |
| 423 } | |
| 424 UNREACHABLE(); | |
| 425 return false; | |
| 426 } | |
| 427 | |
| 428 Type::bitset Type::Representation() { | |
| 429 return REPRESENTATION(this->BitsetLub()); | |
| 430 } | |
| 431 | |
| 432 | |
| 433 // Check if [this] <= [that]. | |
| 434 bool Type::SlowIs(Type* that) { | |
| 435 DisallowHeapAllocation no_allocation; | |
| 436 | |
| 437 // Fast bitset cases | |
| 438 if (that->IsBitset()) { | |
| 439 return BitsetType::Is(this->BitsetLub(), that->AsBitset()); | |
| 440 } | |
| 441 | |
| 442 if (this->IsBitset()) { | |
| 443 return BitsetType::Is(this->AsBitset(), that->BitsetGlb()); | |
| 444 } | |
| 445 | |
| 446 // Check the representations. | |
| 447 if (!BitsetType::Is(Representation(), that->Representation())) { | |
| 448 return false; | |
| 449 } | |
| 450 | |
| 451 // Check the semantic part. | |
| 452 return SemanticIs(that); | |
| 453 } | |
| 454 | |
| 455 | |
| 456 // Check if SEMANTIC([this]) <= SEMANTIC([that]). The result of the method | |
| 457 // should be independent of the representation axis of the types. | |
| 458 bool Type::SemanticIs(Type* that) { | |
| 459 DisallowHeapAllocation no_allocation; | |
| 460 | |
| 461 if (this == that) return true; | |
| 462 | |
| 463 if (that->IsBitset()) { | |
| 464 return BitsetType::Is(SEMANTIC(this->BitsetLub()), that->AsBitset()); | |
| 465 } | |
| 466 if (this->IsBitset()) { | |
| 467 return BitsetType::Is(SEMANTIC(this->AsBitset()), that->BitsetGlb()); | |
| 468 } | |
| 469 | |
| 470 // (T1 \/ ... \/ Tn) <= T if (T1 <= T) /\ ... /\ (Tn <= T) | |
| 471 if (this->IsUnion()) { | |
| 472 for (int i = 0, n = this->AsUnion()->Length(); i < n; ++i) { | |
| 473 if (!this->AsUnion()->Get(i)->SemanticIs(that)) return false; | |
| 474 } | |
| 475 return true; | |
| 476 } | |
| 477 | |
| 478 // T <= (T1 \/ ... \/ Tn) if (T <= T1) \/ ... \/ (T <= Tn) | |
| 479 if (that->IsUnion()) { | |
| 480 for (int i = 0, n = that->AsUnion()->Length(); i < n; ++i) { | |
| 481 if (this->SemanticIs(that->AsUnion()->Get(i))) return true; | |
| 482 if (i > 1 && this->IsRange()) return false; // Shortcut. | |
| 483 } | |
| 484 return false; | |
| 485 } | |
| 486 | |
| 487 if (that->IsRange()) { | |
| 488 return (this->IsRange() && Contains(that->AsRange(), this->AsRange())) || | |
| 489 (this->IsConstant() && | |
| 490 Contains(that->AsRange(), this->AsConstant())); | |
| 491 } | |
| 492 if (this->IsRange()) return false; | |
| 493 | |
| 494 return this->SimplyEquals(that); | |
| 495 } | |
| 496 | |
| 497 | |
| 498 // Check if [this] and [that] overlap. | |
| 499 bool Type::Maybe(Type* that) { | |
| 500 DisallowHeapAllocation no_allocation; | |
| 501 | |
| 502 // Take care of the representation part (and also approximate | |
| 503 // the semantic part). | |
| 504 if (!BitsetType::IsInhabited(this->BitsetLub() & that->BitsetLub())) | |
| 505 return false; | |
| 506 | |
| 507 return SemanticMaybe(that); | |
| 508 } | |
| 509 | |
| 510 bool Type::SemanticMaybe(Type* that) { | |
| 511 DisallowHeapAllocation no_allocation; | |
| 512 | |
| 513 // (T1 \/ ... \/ Tn) overlaps T if (T1 overlaps T) \/ ... \/ (Tn overlaps T) | |
| 514 if (this->IsUnion()) { | |
| 515 for (int i = 0, n = this->AsUnion()->Length(); i < n; ++i) { | |
| 516 if (this->AsUnion()->Get(i)->SemanticMaybe(that)) return true; | |
| 517 } | |
| 518 return false; | |
| 519 } | |
| 520 | |
| 521 // T overlaps (T1 \/ ... \/ Tn) if (T overlaps T1) \/ ... \/ (T overlaps Tn) | |
| 522 if (that->IsUnion()) { | |
| 523 for (int i = 0, n = that->AsUnion()->Length(); i < n; ++i) { | |
| 524 if (this->SemanticMaybe(that->AsUnion()->Get(i))) return true; | |
| 525 } | |
| 526 return false; | |
| 527 } | |
| 528 | |
| 529 if (!BitsetType::SemanticIsInhabited(this->BitsetLub() & that->BitsetLub())) | |
| 530 return false; | |
| 531 | |
| 532 if (this->IsBitset() && that->IsBitset()) return true; | |
| 533 | |
| 534 if (this->IsRange()) { | |
| 535 if (that->IsConstant()) { | |
| 536 return Contains(this->AsRange(), that->AsConstant()); | |
| 537 } | |
| 538 if (that->IsRange()) { | |
| 539 return Overlap(this->AsRange(), that->AsRange()); | |
| 540 } | |
| 541 if (that->IsBitset()) { | |
| 542 bitset number_bits = BitsetType::NumberBits(that->AsBitset()); | |
| 543 if (number_bits == BitsetType::kNone) { | |
| 544 return false; | |
| 545 } | |
| 546 double min = std::max(BitsetType::Min(number_bits), this->Min()); | |
| 547 double max = std::min(BitsetType::Max(number_bits), this->Max()); | |
| 548 return min <= max; | |
| 549 } | |
| 550 } | |
| 551 if (that->IsRange()) { | |
| 552 return that->SemanticMaybe(this); // This case is handled above. | |
| 553 } | |
| 554 | |
| 555 if (this->IsBitset() || that->IsBitset()) return true; | |
| 556 | |
| 557 return this->SimplyEquals(that); | |
| 558 } | |
| 559 | |
| 560 | |
| 561 // Return the range in [this], or [NULL]. | |
| 562 Type* Type::GetRange() { | |
| 563 DisallowHeapAllocation no_allocation; | |
| 564 if (this->IsRange()) return this; | |
| 565 if (this->IsUnion() && this->AsUnion()->Get(1)->IsRange()) { | |
| 566 return this->AsUnion()->Get(1); | |
| 567 } | |
| 568 return NULL; | |
| 569 } | |
| 570 | |
| 571 bool Type::Contains(i::Object* value) { | |
| 572 DisallowHeapAllocation no_allocation; | |
| 573 for (Iterator<i::Object> it = this->Constants(); !it.Done(); it.Advance()) { | |
| 574 if (*it.Current() == value) return true; | |
| 575 } | |
| 576 if (IsInteger(value)) { | |
| 577 Type* range = this->GetRange(); | |
| 578 if (range != NULL && Contains(range->AsRange(), value)) return true; | |
| 579 } | |
| 580 return BitsetType::New(BitsetType::Lub(value))->Is(this); | |
| 581 } | |
| 582 | |
| 583 bool UnionType::Wellformed() { | |
| 584 DisallowHeapAllocation no_allocation; | |
| 585 // This checks the invariants of the union representation: | |
| 586 // 1. There are at least two elements. | |
| 587 // 2. The first element is a bitset, no other element is a bitset. | |
| 588 // 3. At most one element is a range, and it must be the second one. | |
| 589 // 4. No element is itself a union. | |
| 590 // 5. No element (except the bitset) is a subtype of any other. | |
| 591 // 6. If there is a range, then the bitset type does not contain | |
| 592 // plain number bits. | |
| 593 DCHECK(this->Length() >= 2); // (1) | |
| 594 DCHECK(this->Get(0)->IsBitset()); // (2a) | |
| 595 | |
| 596 for (int i = 0; i < this->Length(); ++i) { | |
| 597 if (i != 0) DCHECK(!this->Get(i)->IsBitset()); // (2b) | |
| 598 if (i != 1) DCHECK(!this->Get(i)->IsRange()); // (3) | |
| 599 DCHECK(!this->Get(i)->IsUnion()); // (4) | |
| 600 for (int j = 0; j < this->Length(); ++j) { | |
| 601 if (i != j && i != 0) | |
| 602 DCHECK(!this->Get(i)->SemanticIs(this->Get(j))); // (5) | |
| 603 } | |
| 604 } | |
| 605 DCHECK(!this->Get(1)->IsRange() || | |
| 606 (BitsetType::NumberBits(this->Get(0)->AsBitset()) == | |
| 607 BitsetType::kNone)); // (6) | |
| 608 return true; | |
| 609 } | |
| 610 | |
| 611 | |
| 612 // ----------------------------------------------------------------------------- | |
| 613 // Union and intersection | |
| 614 | |
| 615 | |
| 616 static bool AddIsSafe(int x, int y) { | |
| 617 return x >= 0 ? | |
| 618 y <= std::numeric_limits<int>::max() - x : | |
| 619 y >= std::numeric_limits<int>::min() - x; | |
| 620 } | |
| 621 | |
| 622 Type* Type::Intersect(Type* type1, Type* type2, Zone* zone) { | |
| 623 // Fast case: bit sets. | |
| 624 if (type1->IsBitset() && type2->IsBitset()) { | |
| 625 return BitsetType::New(type1->AsBitset() & type2->AsBitset()); | |
| 626 } | |
| 627 | |
| 628 // Fast case: top or bottom types. | |
| 629 if (type1->IsNone() || type2->IsAny()) return type1; // Shortcut. | |
| 630 if (type2->IsNone() || type1->IsAny()) return type2; // Shortcut. | |
| 631 | |
| 632 // Semi-fast case. | |
| 633 if (type1->Is(type2)) return type1; | |
| 634 if (type2->Is(type1)) return type2; | |
| 635 | |
| 636 // Slow case: create union. | |
| 637 | |
| 638 // Figure out the representation of the result first. | |
| 639 // The rest of the method should not change this representation and | |
| 640 // it should not make any decisions based on representations (i.e., | |
| 641 // it should only use the semantic part of types). | |
| 642 const bitset representation = | |
| 643 type1->Representation() & type2->Representation(); | |
| 644 | |
| 645 // Semantic subtyping check - this is needed for consistency with the | |
| 646 // semi-fast case above - we should behave the same way regardless of | |
| 647 // representations. Intersection with a universal bitset should only update | |
| 648 // the representations. | |
| 649 if (type1->SemanticIs(type2)) { | |
| 650 type2 = Any(); | |
| 651 } else if (type2->SemanticIs(type1)) { | |
| 652 type1 = Any(); | |
| 653 } | |
| 654 | |
| 655 bitset bits = | |
| 656 SEMANTIC(type1->BitsetGlb() & type2->BitsetGlb()) | representation; | |
| 657 int size1 = type1->IsUnion() ? type1->AsUnion()->Length() : 1; | |
| 658 int size2 = type2->IsUnion() ? type2->AsUnion()->Length() : 1; | |
| 659 if (!AddIsSafe(size1, size2)) return Any(); | |
| 660 int size = size1 + size2; | |
| 661 if (!AddIsSafe(size, 2)) return Any(); | |
| 662 size += 2; | |
| 663 Type* result_type = UnionType::New(size, zone); | |
| 664 UnionType* result = result_type->AsUnion(); | |
| 665 size = 0; | |
| 666 | |
| 667 // Deal with bitsets. | |
| 668 result->Set(size++, BitsetType::New(bits)); | |
| 669 | |
| 670 RangeType::Limits lims = RangeType::Limits::Empty(); | |
| 671 size = IntersectAux(type1, type2, result, size, &lims, zone); | |
| 672 | |
| 673 // If the range is not empty, then insert it into the union and | |
| 674 // remove the number bits from the bitset. | |
| 675 if (!lims.IsEmpty()) { | |
| 676 size = UpdateRange(RangeType::New(lims, representation, zone), result, size, | |
| 677 zone); | |
| 678 | |
| 679 // Remove the number bits. | |
| 680 bitset number_bits = BitsetType::NumberBits(bits); | |
| 681 bits &= ~number_bits; | |
| 682 result->Set(0, BitsetType::New(bits)); | |
| 683 } | |
| 684 return NormalizeUnion(result_type, size, zone); | |
| 685 } | |
| 686 | |
| 687 int Type::UpdateRange(Type* range, UnionType* result, int size, Zone* zone) { | |
| 688 if (size == 1) { | |
| 689 result->Set(size++, range); | |
| 690 } else { | |
| 691 // Make space for the range. | |
| 692 result->Set(size++, result->Get(1)); | |
| 693 result->Set(1, range); | |
| 694 } | |
| 695 | |
| 696 // Remove any components that just got subsumed. | |
| 697 for (int i = 2; i < size; ) { | |
| 698 if (result->Get(i)->SemanticIs(range)) { | |
| 699 result->Set(i, result->Get(--size)); | |
| 700 } else { | |
| 701 ++i; | |
| 702 } | |
| 703 } | |
| 704 return size; | |
| 705 } | |
| 706 | |
| 707 RangeType::Limits Type::ToLimits(bitset bits, Zone* zone) { | |
| 708 bitset number_bits = BitsetType::NumberBits(bits); | |
| 709 | |
| 710 if (number_bits == BitsetType::kNone) { | |
| 711 return RangeType::Limits::Empty(); | |
| 712 } | |
| 713 | |
| 714 return RangeType::Limits(BitsetType::Min(number_bits), | |
| 715 BitsetType::Max(number_bits)); | |
| 716 } | |
| 717 | |
| 718 RangeType::Limits Type::IntersectRangeAndBitset(Type* range, Type* bitset, | |
| 719 Zone* zone) { | |
| 720 RangeType::Limits range_lims(range->AsRange()); | |
| 721 RangeType::Limits bitset_lims = ToLimits(bitset->AsBitset(), zone); | |
| 722 return RangeType::Limits::Intersect(range_lims, bitset_lims); | |
| 723 } | |
| 724 | |
| 725 int Type::IntersectAux(Type* lhs, Type* rhs, UnionType* result, int size, | |
| 726 RangeType::Limits* lims, Zone* zone) { | |
| 727 if (lhs->IsUnion()) { | |
| 728 for (int i = 0, n = lhs->AsUnion()->Length(); i < n; ++i) { | |
| 729 size = | |
| 730 IntersectAux(lhs->AsUnion()->Get(i), rhs, result, size, lims, zone); | |
| 731 } | |
| 732 return size; | |
| 733 } | |
| 734 if (rhs->IsUnion()) { | |
| 735 for (int i = 0, n = rhs->AsUnion()->Length(); i < n; ++i) { | |
| 736 size = | |
| 737 IntersectAux(lhs, rhs->AsUnion()->Get(i), result, size, lims, zone); | |
| 738 } | |
| 739 return size; | |
| 740 } | |
| 741 | |
| 742 if (!BitsetType::SemanticIsInhabited(lhs->BitsetLub() & rhs->BitsetLub())) { | |
| 743 return size; | |
| 744 } | |
| 745 | |
| 746 if (lhs->IsRange()) { | |
| 747 if (rhs->IsBitset()) { | |
| 748 RangeType::Limits lim = IntersectRangeAndBitset(lhs, rhs, zone); | |
| 749 | |
| 750 if (!lim.IsEmpty()) { | |
| 751 *lims = RangeType::Limits::Union(lim, *lims); | |
| 752 } | |
| 753 return size; | |
| 754 } | |
| 755 if (rhs->IsConstant() && Contains(lhs->AsRange(), rhs->AsConstant())) { | |
| 756 return AddToUnion(rhs, result, size, zone); | |
| 757 } | |
| 758 if (rhs->IsRange()) { | |
| 759 RangeType::Limits lim = RangeType::Limits::Intersect( | |
| 760 RangeType::Limits(lhs->AsRange()), RangeType::Limits(rhs->AsRange())); | |
| 761 if (!lim.IsEmpty()) { | |
| 762 *lims = RangeType::Limits::Union(lim, *lims); | |
| 763 } | |
| 764 } | |
| 765 return size; | |
| 766 } | |
| 767 if (rhs->IsRange()) { | |
| 768 // This case is handled symmetrically above. | |
| 769 return IntersectAux(rhs, lhs, result, size, lims, zone); | |
| 770 } | |
| 771 if (lhs->IsBitset() || rhs->IsBitset()) { | |
| 772 return AddToUnion(lhs->IsBitset() ? rhs : lhs, result, size, zone); | |
| 773 } | |
| 774 if (lhs->SimplyEquals(rhs)) { | |
| 775 return AddToUnion(lhs, result, size, zone); | |
| 776 } | |
| 777 return size; | |
| 778 } | |
| 779 | |
| 780 | |
| 781 // Make sure that we produce a well-formed range and bitset: | |
| 782 // If the range is non-empty, the number bits in the bitset should be | |
| 783 // clear. Moreover, if we have a canonical range (such as Signed32), | |
| 784 // we want to produce a bitset rather than a range. | |
| 785 Type* Type::NormalizeRangeAndBitset(Type* range, bitset* bits, Zone* zone) { | |
| 786 // Fast path: If the bitset does not mention numbers, we can just keep the | |
| 787 // range. | |
| 788 bitset number_bits = BitsetType::NumberBits(*bits); | |
| 789 if (number_bits == 0) { | |
| 790 return range; | |
| 791 } | |
| 792 | |
| 793 // If the range is semantically contained within the bitset, return None and | |
| 794 // leave the bitset untouched. | |
| 795 bitset range_lub = SEMANTIC(range->BitsetLub()); | |
| 796 if (BitsetType::Is(range_lub, *bits)) { | |
| 797 return None(); | |
| 798 } | |
| 799 | |
| 800 // Slow path: reconcile the bitset range and the range. | |
| 801 double bitset_min = BitsetType::Min(number_bits); | |
| 802 double bitset_max = BitsetType::Max(number_bits); | |
| 803 | |
| 804 double range_min = range->Min(); | |
| 805 double range_max = range->Max(); | |
| 806 | |
| 807 // Remove the number bits from the bitset, they would just confuse us now. | |
| 808 // NOTE: bits contains OtherNumber iff bits contains PlainNumber, in which | |
| 809 // case we already returned after the subtype check above. | |
| 810 *bits &= ~number_bits; | |
| 811 | |
| 812 if (range_min <= bitset_min && range_max >= bitset_max) { | |
| 813 // Bitset is contained within the range, just return the range. | |
| 814 return range; | |
| 815 } | |
| 816 | |
| 817 if (bitset_min < range_min) { | |
| 818 range_min = bitset_min; | |
| 819 } | |
| 820 if (bitset_max > range_max) { | |
| 821 range_max = bitset_max; | |
| 822 } | |
| 823 return RangeType::New(range_min, range_max, BitsetType::kNone, zone); | |
| 824 } | |
| 825 | |
| 826 Type* Type::Union(Type* type1, Type* type2, Zone* zone) { | |
| 827 // Fast case: bit sets. | |
| 828 if (type1->IsBitset() && type2->IsBitset()) { | |
| 829 return BitsetType::New(type1->AsBitset() | type2->AsBitset()); | |
| 830 } | |
| 831 | |
| 832 // Fast case: top or bottom types. | |
| 833 if (type1->IsAny() || type2->IsNone()) return type1; | |
| 834 if (type2->IsAny() || type1->IsNone()) return type2; | |
| 835 | |
| 836 // Semi-fast case. | |
| 837 if (type1->Is(type2)) return type2; | |
| 838 if (type2->Is(type1)) return type1; | |
| 839 | |
| 840 // Figure out the representation of the result. | |
| 841 // The rest of the method should not change this representation and | |
| 842 // it should not make any decisions based on representations (i.e., | |
| 843 // it should only use the semantic part of types). | |
| 844 const bitset representation = | |
| 845 type1->Representation() | type2->Representation(); | |
| 846 | |
| 847 // Slow case: create union. | |
| 848 int size1 = type1->IsUnion() ? type1->AsUnion()->Length() : 1; | |
| 849 int size2 = type2->IsUnion() ? type2->AsUnion()->Length() : 1; | |
| 850 if (!AddIsSafe(size1, size2)) return Any(); | |
| 851 int size = size1 + size2; | |
| 852 if (!AddIsSafe(size, 2)) return Any(); | |
| 853 size += 2; | |
| 854 Type* result_type = UnionType::New(size, zone); | |
| 855 UnionType* result = result_type->AsUnion(); | |
| 856 size = 0; | |
| 857 | |
| 858 // Compute the new bitset. | |
| 859 bitset new_bitset = SEMANTIC(type1->BitsetGlb() | type2->BitsetGlb()); | |
| 860 | |
| 861 // Deal with ranges. | |
| 862 Type* range = None(); | |
| 863 Type* range1 = type1->GetRange(); | |
| 864 Type* range2 = type2->GetRange(); | |
| 865 if (range1 != NULL && range2 != NULL) { | |
| 866 RangeType::Limits lims = | |
| 867 RangeType::Limits::Union(RangeType::Limits(range1->AsRange()), | |
| 868 RangeType::Limits(range2->AsRange())); | |
| 869 Type* union_range = RangeType::New(lims, representation, zone); | |
| 870 range = NormalizeRangeAndBitset(union_range, &new_bitset, zone); | |
| 871 } else if (range1 != NULL) { | |
| 872 range = NormalizeRangeAndBitset(range1, &new_bitset, zone); | |
| 873 } else if (range2 != NULL) { | |
| 874 range = NormalizeRangeAndBitset(range2, &new_bitset, zone); | |
| 875 } | |
| 876 new_bitset = SEMANTIC(new_bitset) | representation; | |
| 877 Type* bits = BitsetType::New(new_bitset); | |
| 878 result->Set(size++, bits); | |
| 879 if (!range->IsNone()) result->Set(size++, range); | |
| 880 | |
| 881 size = AddToUnion(type1, result, size, zone); | |
| 882 size = AddToUnion(type2, result, size, zone); | |
| 883 return NormalizeUnion(result_type, size, zone); | |
| 884 } | |
| 885 | |
| 886 | |
| 887 // Add [type] to [result] unless [type] is bitset, range, or already subsumed. | |
| 888 // Return new size of [result]. | |
| 889 int Type::AddToUnion(Type* type, UnionType* result, int size, Zone* zone) { | |
| 890 if (type->IsBitset() || type->IsRange()) return size; | |
| 891 if (type->IsUnion()) { | |
| 892 for (int i = 0, n = type->AsUnion()->Length(); i < n; ++i) { | |
| 893 size = AddToUnion(type->AsUnion()->Get(i), result, size, zone); | |
| 894 } | |
| 895 return size; | |
| 896 } | |
| 897 for (int i = 0; i < size; ++i) { | |
| 898 if (type->SemanticIs(result->Get(i))) return size; | |
| 899 } | |
| 900 result->Set(size++, type); | |
| 901 return size; | |
| 902 } | |
| 903 | |
| 904 Type* Type::NormalizeUnion(Type* union_type, int size, Zone* zone) { | |
| 905 UnionType* unioned = union_type->AsUnion(); | |
| 906 DCHECK(size >= 1); | |
| 907 DCHECK(unioned->Get(0)->IsBitset()); | |
| 908 // If the union has just one element, return it. | |
| 909 if (size == 1) { | |
| 910 return unioned->Get(0); | |
| 911 } | |
| 912 bitset bits = unioned->Get(0)->AsBitset(); | |
| 913 // If the union only consists of a range, we can get rid of the union. | |
| 914 if (size == 2 && SEMANTIC(bits) == BitsetType::kNone) { | |
| 915 bitset representation = REPRESENTATION(bits); | |
| 916 if (representation == unioned->Get(1)->Representation()) { | |
| 917 return unioned->Get(1); | |
| 918 } | |
| 919 if (unioned->Get(1)->IsRange()) { | |
| 920 return RangeType::New(unioned->Get(1)->AsRange()->Min(), | |
| 921 unioned->Get(1)->AsRange()->Max(), | |
| 922 unioned->Get(0)->AsBitset(), zone); | |
| 923 } | |
| 924 } | |
| 925 unioned->Shrink(size); | |
| 926 SLOW_DCHECK(unioned->Wellformed()); | |
| 927 return union_type; | |
| 928 } | |
| 929 | |
| 930 | |
| 931 // ----------------------------------------------------------------------------- | |
| 932 // Component extraction | |
| 933 | |
| 934 // static | |
| 935 Type* Type::Representation(Type* t, Zone* zone) { | |
| 936 return BitsetType::New(t->Representation()); | |
| 937 } | |
| 938 | |
| 939 | |
| 940 // static | |
| 941 Type* Type::Semantic(Type* t, Zone* zone) { | |
| 942 return Intersect(t, BitsetType::New(BitsetType::kSemantic), zone); | |
| 943 } | |
| 944 | |
| 945 | |
| 946 // ----------------------------------------------------------------------------- | |
| 947 // Iteration. | |
| 948 | |
| 949 int Type::NumConstants() { | |
| 950 DisallowHeapAllocation no_allocation; | |
| 951 if (this->IsConstant()) { | |
| 952 return 1; | |
| 953 } else if (this->IsUnion()) { | |
| 954 int result = 0; | |
| 955 for (int i = 0, n = this->AsUnion()->Length(); i < n; ++i) { | |
| 956 if (this->AsUnion()->Get(i)->IsConstant()) ++result; | |
| 957 } | |
| 958 return result; | |
| 959 } else { | |
| 960 return 0; | |
| 961 } | |
| 962 } | |
| 963 | |
| 964 template <class T> | |
| 965 Type* Type::Iterator<T>::get_type() { | |
| 966 DCHECK(!Done()); | |
| 967 return type_->IsUnion() ? type_->AsUnion()->Get(index_) : type_; | |
| 968 } | |
| 969 | |
| 970 | |
| 971 // C++ cannot specialise nested templates, so we have to go through this | |
| 972 // contortion with an auxiliary template to simulate it. | |
| 973 template <class T> | |
| 974 struct TypeImplIteratorAux { | |
| 975 static bool matches(Type* type); | |
| 976 static i::Handle<T> current(Type* type); | |
| 977 }; | |
| 978 | |
| 979 template <> | |
| 980 struct TypeImplIteratorAux<i::Object> { | |
| 981 static bool matches(Type* type) { return type->IsConstant(); } | |
| 982 static i::Handle<i::Object> current(Type* type) { | |
| 983 return type->AsConstant()->Value(); | |
| 984 } | |
| 985 }; | |
| 986 | |
| 987 template <class T> | |
| 988 bool Type::Iterator<T>::matches(Type* type) { | |
| 989 return TypeImplIteratorAux<T>::matches(type); | |
| 990 } | |
| 991 | |
| 992 template <class T> | |
| 993 i::Handle<T> Type::Iterator<T>::Current() { | |
| 994 return TypeImplIteratorAux<T>::current(get_type()); | |
| 995 } | |
| 996 | |
| 997 template <class T> | |
| 998 void Type::Iterator<T>::Advance() { | |
| 999 DisallowHeapAllocation no_allocation; | |
| 1000 ++index_; | |
| 1001 if (type_->IsUnion()) { | |
| 1002 for (int n = type_->AsUnion()->Length(); index_ < n; ++index_) { | |
| 1003 if (matches(type_->AsUnion()->Get(index_))) return; | |
| 1004 } | |
| 1005 } else if (index_ == 0 && matches(type_)) { | |
| 1006 return; | |
| 1007 } | |
| 1008 index_ = -1; | |
| 1009 } | |
| 1010 | |
| 1011 | |
| 1012 // ----------------------------------------------------------------------------- | |
| 1013 // Printing. | |
| 1014 | |
| 1015 const char* BitsetType::Name(bitset bits) { | |
| 1016 switch (bits) { | |
| 1017 case REPRESENTATION(kAny): return "Any"; | |
| 1018 #define RETURN_NAMED_REPRESENTATION_TYPE(type, value) \ | |
| 1019 case REPRESENTATION(k##type): return #type; | |
| 1020 REPRESENTATION_BITSET_TYPE_LIST(RETURN_NAMED_REPRESENTATION_TYPE) | |
| 1021 #undef RETURN_NAMED_REPRESENTATION_TYPE | |
| 1022 | |
| 1023 #define RETURN_NAMED_SEMANTIC_TYPE(type, value) \ | |
| 1024 case SEMANTIC(k##type): return #type; | |
| 1025 SEMANTIC_BITSET_TYPE_LIST(RETURN_NAMED_SEMANTIC_TYPE) | |
| 1026 INTERNAL_BITSET_TYPE_LIST(RETURN_NAMED_SEMANTIC_TYPE) | |
| 1027 #undef RETURN_NAMED_SEMANTIC_TYPE | |
| 1028 | |
| 1029 default: | |
| 1030 return NULL; | |
| 1031 } | |
| 1032 } | |
| 1033 | |
| 1034 void BitsetType::Print(std::ostream& os, // NOLINT | |
| 1035 bitset bits) { | |
| 1036 DisallowHeapAllocation no_allocation; | |
| 1037 const char* name = Name(bits); | |
| 1038 if (name != NULL) { | |
| 1039 os << name; | |
| 1040 return; | |
| 1041 } | |
| 1042 | |
| 1043 // clang-format off | |
| 1044 static const bitset named_bitsets[] = { | |
| 1045 #define BITSET_CONSTANT(type, value) REPRESENTATION(k##type), | |
| 1046 REPRESENTATION_BITSET_TYPE_LIST(BITSET_CONSTANT) | |
| 1047 #undef BITSET_CONSTANT | |
| 1048 | |
| 1049 #define BITSET_CONSTANT(type, value) SEMANTIC(k##type), | |
| 1050 INTERNAL_BITSET_TYPE_LIST(BITSET_CONSTANT) | |
| 1051 SEMANTIC_BITSET_TYPE_LIST(BITSET_CONSTANT) | |
| 1052 #undef BITSET_CONSTANT | |
| 1053 }; | |
| 1054 // clang-format on | |
| 1055 | |
| 1056 bool is_first = true; | |
| 1057 os << "("; | |
| 1058 for (int i(arraysize(named_bitsets) - 1); bits != 0 && i >= 0; --i) { | |
| 1059 bitset subset = named_bitsets[i]; | |
| 1060 if ((bits & subset) == subset) { | |
| 1061 if (!is_first) os << " | "; | |
| 1062 is_first = false; | |
| 1063 os << Name(subset); | |
| 1064 bits -= subset; | |
| 1065 } | |
| 1066 } | |
| 1067 DCHECK(bits == 0); | |
| 1068 os << ")"; | |
| 1069 } | |
| 1070 | |
| 1071 void Type::PrintTo(std::ostream& os, PrintDimension dim) { | |
| 1072 DisallowHeapAllocation no_allocation; | |
| 1073 if (dim != REPRESENTATION_DIM) { | |
| 1074 if (this->IsBitset()) { | |
| 1075 BitsetType::Print(os, SEMANTIC(this->AsBitset())); | |
| 1076 } else if (this->IsConstant()) { | |
| 1077 os << "Constant(" << Brief(*this->AsConstant()->Value()) << ")"; | |
| 1078 } else if (this->IsRange()) { | |
| 1079 std::ostream::fmtflags saved_flags = os.setf(std::ios::fixed); | |
| 1080 std::streamsize saved_precision = os.precision(0); | |
| 1081 os << "Range(" << this->AsRange()->Min() << ", " << this->AsRange()->Max() | |
| 1082 << ")"; | |
| 1083 os.flags(saved_flags); | |
| 1084 os.precision(saved_precision); | |
| 1085 } else if (this->IsUnion()) { | |
| 1086 os << "("; | |
| 1087 for (int i = 0, n = this->AsUnion()->Length(); i < n; ++i) { | |
| 1088 Type* type_i = this->AsUnion()->Get(i); | |
| 1089 if (i > 0) os << " | "; | |
| 1090 type_i->PrintTo(os, dim); | |
| 1091 } | |
| 1092 os << ")"; | |
| 1093 } else if (this->IsTuple()) { | |
| 1094 os << "<"; | |
| 1095 for (int i = 0, n = this->AsTuple()->Arity(); i < n; ++i) { | |
| 1096 Type* type_i = this->AsTuple()->Element(i); | |
| 1097 if (i > 0) os << ", "; | |
| 1098 type_i->PrintTo(os, dim); | |
| 1099 } | |
| 1100 os << ">"; | |
| 1101 } else { | |
| 1102 UNREACHABLE(); | |
| 1103 } | |
| 1104 } | |
| 1105 if (dim == BOTH_DIMS) os << "/"; | |
| 1106 if (dim != SEMANTIC_DIM) { | |
| 1107 BitsetType::Print(os, REPRESENTATION(this->BitsetLub())); | |
| 1108 } | |
| 1109 } | |
| 1110 | |
| 1111 | |
| 1112 #ifdef DEBUG | |
| 1113 void Type::Print() { | |
| 1114 OFStream os(stdout); | |
| 1115 PrintTo(os); | |
| 1116 os << std::endl; | |
| 1117 } | |
| 1118 void BitsetType::Print(bitset bits) { | |
| 1119 OFStream os(stdout); | |
| 1120 Print(os, bits); | |
| 1121 os << std::endl; | |
| 1122 } | |
| 1123 #endif | |
| 1124 | |
| 1125 BitsetType::bitset BitsetType::SignedSmall() { | |
| 1126 return i::SmiValuesAre31Bits() ? kSigned31 : kSigned32; | |
| 1127 } | |
| 1128 | |
| 1129 BitsetType::bitset BitsetType::UnsignedSmall() { | |
| 1130 return i::SmiValuesAre31Bits() ? kUnsigned30 : kUnsigned31; | |
| 1131 } | |
| 1132 | |
| 1133 // ----------------------------------------------------------------------------- | |
| 1134 // Instantiations. | |
| 1135 | |
| 1136 template class Type::Iterator<i::Object>; | |
| 1137 | |
| 1138 } // namespace internal | |
| 1139 } // namespace v8 | |
| OLD | NEW |