| 96 | } |
| 97 | |
| 98 | bool BFCAllocator::Extend(size_t alignment, size_t rounded_bytes) { |
| 99 | size_t available_bytes = memory_limit_ - total_region_allocated_bytes_; |
| 100 | // Rounds available_bytes down to the nearest multiple of kMinAllocationSize. |
| 101 | available_bytes = (available_bytes / kMinAllocationSize) * kMinAllocationSize; |
| 102 | |
| 103 | // Do we have enough space to handle the client's request? |
| 104 | // If not, fail immediately. |
| 105 | if (rounded_bytes > available_bytes) { |
| 106 | return false; |
| 107 | } |
| 108 | |
| 109 | // If curr_region_allocation_bytes_ is not enough to satisfy the |
| 110 | // allocation, keep multiplying by a power of two until that is |
| 111 | // sufficient. |
| 112 | bool increased_allocation = false; |
| 113 | while (rounded_bytes > curr_region_allocation_bytes_) { |
| 114 | curr_region_allocation_bytes_ *= 2; |
| 115 | increased_allocation = true; |
| 116 | } |
| 117 | |
| 118 | // Try allocating. |
| 119 | size_t bytes = std::min(curr_region_allocation_bytes_, available_bytes); |
| 120 | void* mem_addr = sub_allocator_->Alloc(alignment, bytes); |
| 121 | if (mem_addr == nullptr && !started_backpedal_) { |
| 122 | // Only backpedal once. |
| 123 | started_backpedal_ = true; |
| 124 | |
| 125 | static constexpr float kBackpedalFactor = 0.9; |
| 126 | |
| 127 | // Try allocating less memory. |
| 128 | while (mem_addr == nullptr) { |
| 129 | bytes = RoundedBytes(bytes * kBackpedalFactor); |
| 130 | if (bytes < rounded_bytes) break; |
| 131 | mem_addr = sub_allocator_->Alloc(alignment, bytes); |
| 132 | } |
| 133 | } |
| 134 | |
| 135 | if (mem_addr == nullptr) { |
| 136 | return false; |
| 137 | } |
| 138 | |
| 139 | if (!increased_allocation) { |
| 140 | // Increase the region size of the next required allocation. |
| 141 | curr_region_allocation_bytes_ *= 2; |
| 142 | } |
| 143 | |
| 144 | VLOG(1) << "Extending allocation by " |
| 145 | << strings::HumanReadableNumBytes(bytes) << " bytes for " |
| 146 | << Name() << "."; |
| 147 | |
| 148 | total_region_allocated_bytes_ += bytes; |
| 149 | VLOG(1) << "Total allocated bytes: " |
| 150 | << strings::HumanReadableNumBytes(total_region_allocated_bytes_); |
| 151 | |
| 152 | VLOG(1) << "Allocated memory at " << mem_addr << " to " |
| 153 | << static_cast<void*>(static_cast<char*>(mem_addr) + bytes); |
| 154 | region_manager_.AddAllocationRegion(mem_addr, bytes); |
| 155 | |