Allocates a buffer of size between [0, 2^62 - 1 - sizeof(FreeListNode)] bytes.
| 57 | |
| 58 | /// Allocates a buffer of size between [0, 2^62 - 1 - sizeof(FreeListNode)] bytes. |
| 59 | uint8_t* Allocate(const int64_t requested_size) { |
| 60 | DCHECK_GE(requested_size, 0); |
| 61 | /// Return a non-nullptr dummy pointer. nullptr is reserved for failures. |
| 62 | if (UNLIKELY(requested_size == 0)) return mem_pool_->EmptyAllocPtr(); |
| 63 | ++net_allocations_; |
| 64 | /// MemPool allocations are 8-byte aligned, so making allocations < 8 bytes |
| 65 | /// doesn't save memory and eliminates opportunities to recycle allocations. |
| 66 | int64_t actual_size = std::max<int64_t>(8, requested_size); |
| 67 | int free_list_idx = BitUtil::Log2Ceiling64(actual_size); |
| 68 | DCHECK_LT(free_list_idx, NUM_LISTS); |
| 69 | FreeListNode* allocation = lists_[free_list_idx].next; |
| 70 | if (allocation == nullptr) { |
| 71 | // There wasn't an existing allocation of the right size, allocate a new one. |
| 72 | actual_size = 1LL << free_list_idx; |
| 73 | allocation = reinterpret_cast<FreeListNode*>( |
| 74 | mem_pool_->Allocate(actual_size + sizeof(FreeListNode))); |
| 75 | if (UNLIKELY(allocation == nullptr)) { |
| 76 | --net_allocations_; |
| 77 | return nullptr; |
| 78 | } |
| 79 | // Memory will be returned unpoisoned from MemPool. Poison the whole range and then |
| 80 | // deal with unpoisoning both allocation paths in one place below. |
| 81 | ASAN_POISON_MEMORY_REGION(allocation, sizeof(FreeListNode) + actual_size); |
| 82 | } else { |
| 83 | // Remove this allocation from the list. |
| 84 | lists_[free_list_idx].next = allocation->next; |
| 85 | } |
| 86 | DCHECK(allocation != nullptr); |
| 87 | #ifdef ADDRESS_SANITIZER |
| 88 | uint8_t* ptr = reinterpret_cast<uint8_t*>(allocation); |
| 89 | ASAN_UNPOISON_MEMORY_REGION(ptr, sizeof(FreeListNode) + requested_size); |
| 90 | alloc_to_size_[ptr + sizeof(FreeListNode)] = requested_size; |
| 91 | #endif |
| 92 | // Set the back node to point back to the list it came from so know where |
| 93 | // to add it on Free(). |
| 94 | allocation->list = &lists_[free_list_idx]; |
| 95 | return reinterpret_cast<uint8_t*>(allocation) + sizeof(FreeListNode); |
| 96 | } |
| 97 | |
| 98 | void Free(uint8_t* ptr) { |
| 99 | if (UNLIKELY(ptr == nullptr || ptr == mem_pool_->EmptyAllocPtr())) return; |
nothing calls this directly
no test coverage detected