| 678 | } |
| 679 | |
| 680 | int64_t HashStringAllocator::checkConsistency() const { |
| 681 | static const auto kHugePageSize = memory::AllocationTraits::kHugePageSize; |
| 682 | |
| 683 | uint64_t numFree = 0; |
| 684 | uint64_t freeBytes = 0; |
| 685 | int64_t allocatedBytes = 0; |
| 686 | for (auto i = 0; i < pool_.numRanges(); ++i) { |
| 687 | auto topRange = pool_.rangeAt(i); |
| 688 | auto topRangeSize = topRange.size(); |
| 689 | if (topRangeSize >= kHugePageSize) { |
| 690 | BOLT_CHECK_EQ(0, topRangeSize % kHugePageSize); |
| 691 | } |
| 692 | // Some ranges are short and contain one arena. Some are multiples of huge |
| 693 | // page size and contain one arena per huge page. |
| 694 | for (int64_t subRangeStart = 0; subRangeStart < topRangeSize; |
| 695 | subRangeStart += kHugePageSize) { |
| 696 | auto range = folly::Range<char*>( |
| 697 | topRange.data() + subRangeStart, |
| 698 | std::min<int64_t>(topRangeSize, kHugePageSize)); |
| 699 | auto size = range.size() - simd::kPadding; |
| 700 | bool previousFree = false; |
| 701 | auto end = reinterpret_cast<Header*>(range.data() + size); |
| 702 | auto header = reinterpret_cast<Header*>(range.data()); |
| 703 | while (header != end) { |
| 704 | BOLT_CHECK_GE(reinterpret_cast<char*>(header), range.data()); |
| 705 | BOLT_CHECK_LT( |
| 706 | reinterpret_cast<char*>(header), reinterpret_cast<char*>(end)); |
| 707 | BOLT_CHECK_LE( |
| 708 | reinterpret_cast<char*>(header->end()), |
| 709 | reinterpret_cast<char*>(end)); |
| 710 | BOLT_CHECK_EQ(header->isPreviousFree(), previousFree); |
| 711 | |
| 712 | if (header->isFree()) { |
| 713 | BOLT_CHECK(!previousFree); |
| 714 | BOLT_CHECK(!header->isContinued()); |
| 715 | if (header->next()) { |
| 716 | BOLT_CHECK_EQ( |
| 717 | header->size(), |
| 718 | *(reinterpret_cast<int32_t*>(header->end()) - 1)); |
| 719 | } |
| 720 | ++numFree; |
| 721 | freeBytes += sizeof(Header) + header->size(); |
| 722 | } else if (header->isContinued()) { |
| 723 | // If the content of the header is continued, check the |
| 724 | // continue header is readable and not free. |
| 725 | auto continued = header->nextContinued(); |
| 726 | BOLT_CHECK(!continued->isFree()); |
| 727 | allocatedBytes += header->size() - Header::kContinuedPtrSize; |
| 728 | } else { |
| 729 | allocatedBytes += header->size(); |
| 730 | } |
| 731 | previousFree = header->isFree(); |
| 732 | header = reinterpret_cast<Header*>(header->end()); |
| 733 | } |
| 734 | } |
| 735 | } |
| 736 | |
| 737 | BOLT_CHECK_EQ(numFree, numFree_); |
nothing calls this directly
no test coverage detected