diff options
author | Lei Zhang <thestig@chromium.org> | 2018-10-16 18:40:15 +0000 |
---|---|---|
committer | Chromium commit bot <commit-bot@chromium.org> | 2018-10-16 18:40:15 +0000 |
commit | f1fae3cd1b9492cf9411dffd3c486b9672d8cc76 (patch) | |
tree | bee5d8b2528e714149d399163519f0fa35ec532b /third_party/base/allocator/partition_allocator/partition_bucket.h | |
parent | 1b6fcaad0722fb586620efc974726dee3fb0f80f (diff) | |
download | pdfium-f1fae3cd1b9492cf9411dffd3c486b9672d8cc76.tar.xz |
Update PartitionAlloc from Chromium at r599712.
BUG=pdfium:1170
Change-Id: I0f8dfb3d517beaa682a9ca7ad4831c5a7a10dc3b
Reviewed-on: https://pdfium-review.googlesource.com/c/44073
Reviewed-by: Tom Sepez <tsepez@chromium.org>
Commit-Queue: Lei Zhang <thestig@chromium.org>
Diffstat (limited to 'third_party/base/allocator/partition_allocator/partition_bucket.h')
-rw-r--r-- | third_party/base/allocator/partition_allocator/partition_bucket.h | 130 |
1 files changed, 130 insertions, 0 deletions
diff --git a/third_party/base/allocator/partition_allocator/partition_bucket.h b/third_party/base/allocator/partition_allocator/partition_bucket.h new file mode 100644 index 0000000000..a89099b8e8 --- /dev/null +++ b/third_party/base/allocator/partition_allocator/partition_bucket.h @@ -0,0 +1,130 @@ +// Copyright (c) 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef THIRD_PARTY_BASE_ALLOCATOR_PARTITION_ALLOCATOR_PARTITION_BUCKET_H_ +#define THIRD_PARTY_BASE_ALLOCATOR_PARTITION_ALLOCATOR_PARTITION_BUCKET_H_ + +#include <stddef.h> +#include <stdint.h> + +#include "third_party/base/allocator/partition_allocator/partition_alloc_constants.h" +#include "third_party/base/base_export.h" +#include "third_party/base/compiler_specific.h" + +namespace pdfium { +namespace base { +namespace internal { + +struct PartitionPage; +struct PartitionRootBase; + +struct PartitionBucket { + // Accessed most in hot path => goes first. + PartitionPage* active_pages_head; + + PartitionPage* empty_pages_head; + PartitionPage* decommitted_pages_head; + uint32_t slot_size; + uint32_t num_system_pages_per_slot_span : 8; + uint32_t num_full_pages : 24; + + // Public API. + void Init(uint32_t new_slot_size); + + // Sets |is_already_zeroed| to true if the allocation was satisfied by + // requesting (a) new page(s) from the operating system, or false otherwise. + // This enables an optimization for when callers use |PartitionAllocZeroFill|: + // there is no need to call memset on fresh pages; the OS has already zeroed + // them. (See |PartitionRootBase::AllocFromBucket|.) + // + // Note the matching Free() functions are in PartitionPage. + BASE_EXPORT NOINLINE void* SlowPathAlloc(PartitionRootBase* root, + int flags, + size_t size, + bool* is_already_zeroed); + + ALWAYS_INLINE bool is_direct_mapped() const { + return !num_system_pages_per_slot_span; + } + ALWAYS_INLINE size_t get_bytes_per_span() const { + // TODO(ajwong): Change to CheckedMul. https://crbug.com/787153 + // https://crbug.com/680657 + return num_system_pages_per_slot_span * kSystemPageSize; + } + ALWAYS_INLINE uint16_t get_slots_per_span() const { + // TODO(ajwong): Change to CheckedMul. https://crbug.com/787153 + // https://crbug.com/680657 + return static_cast<uint16_t>(get_bytes_per_span() / slot_size); + } + + static ALWAYS_INLINE size_t get_direct_map_size(size_t size) { + // Caller must check that the size is not above the kGenericMaxDirectMapped + // limit before calling. This also guards against integer overflow in the + // calculation here. + DCHECK(size <= kGenericMaxDirectMapped); + return (size + kSystemPageOffsetMask) & kSystemPageBaseMask; + } + + // TODO(ajwong): Can this be made private? https://crbug.com/787153 + static PartitionBucket* get_sentinel_bucket(); + + // This helper function scans a bucket's active page list for a suitable new + // active page. When it finds a suitable new active page (one that has + // free slots and is not empty), it is set as the new active page. If there + // is no suitable new active page, the current active page is set to + // PartitionPage::get_sentinel_page(). As potential pages are scanned, they + // are tidied up according to their state. Empty pages are swept on to the + // empty page list, decommitted pages on to the decommitted page list and full + // pages are unlinked from any list. + // + // This is where the guts of the bucket maintenance is done! + bool SetNewActivePage(); + + private: + static void OutOfMemory(const PartitionRootBase* root); + static void OutOfMemoryWithLotsOfUncommitedPages(); + + static NOINLINE void OnFull(); + + // Returns a natural number of PartitionPages (calculated by + // get_system_pages_per_slot_span()) to allocate from the current + // SuperPage when the bucket runs out of slots. + ALWAYS_INLINE uint16_t get_pages_per_slot_span(); + + // Returns the number of system pages in a slot span. + // + // The calculation attemps to find the best number of System Pages to + // allocate for the given slot_size to minimize wasted space. It uses a + // heuristic that looks at number of bytes wasted after the last slot and + // attempts to account for the PTE usage of each System Page. + uint8_t get_system_pages_per_slot_span(); + + // Allocates a new slot span with size |num_partition_pages| from the + // current extent. Metadata within this slot span will be uninitialized. + // Returns nullptr on error. + ALWAYS_INLINE void* AllocNewSlotSpan(PartitionRootBase* root, + int flags, + uint16_t num_partition_pages); + + // Each bucket allocates a slot span when it runs out of slots. + // A slot span's size is equal to get_pages_per_slot_span() number of + // PartitionPages. This function initializes all PartitionPage within the + // span to point to the first PartitionPage which holds all the metadata + // for the span and registers this bucket as the owner of the span. It does + // NOT put the slots into the bucket's freelist. + ALWAYS_INLINE void InitializeSlotSpan(PartitionPage* page); + + // Allocates one slot from the given |page| and then adds the remainder to + // the current bucket. If the |page| was freshly allocated, it must have been + // passed through InitializeSlotSpan() first. + ALWAYS_INLINE char* AllocAndFillFreelist(PartitionPage* page); + + static PartitionBucket sentinel_bucket_; +}; + +} // namespace internal +} // namespace base +} // namespace pdfium + +#endif // THIRD_PARTY_BASE_ALLOCATOR_PARTITION_ALLOCATOR_PARTITION_BUCKET_H_ |