| /* |
| * Copyright (c) 2018-2021 Apple Inc. All rights reserved. |
| * |
| * Redistribution and use in source and binary forms, with or without |
| * modification, are permitted provided that the following conditions |
| * are met: |
| * 1. Redistributions of source code must retain the above copyright |
| * notice, this list of conditions and the following disclaimer. |
| * 2. Redistributions in binary form must reproduce the above copyright |
| * notice, this list of conditions and the following disclaimer in the |
| * documentation and/or other materials provided with the distribution. |
| * |
| * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY |
| * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
| * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR |
| * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR |
| * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, |
| * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, |
| * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR |
| * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY |
| * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
| * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
| * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| */ |
| |
| #ifndef PAS_HEAP_CONFIG_UTILS_INLINES_H |
| #define PAS_HEAP_CONFIG_UTILS_INLINES_H |
| |
| #include "pas_bitfit_page_config_utils_inlines.h" |
| #include "pas_heap_config_inlines.h" |
| #include "pas_heap_config_utils.h" |
| #include "pas_large_heap_physical_page_sharing_cache.h" |
| #include "pas_medium_megapage_cache.h" |
| #include "pas_segregated_page_config_utils_inlines.h" |
| |
| PAS_BEGIN_EXTERN_C; |
| |
| PAS_API pas_aligned_allocation_result |
| pas_heap_config_utils_allocate_aligned( |
| size_t size, |
| pas_alignment alignment, |
| pas_large_heap* large_heap, |
| pas_heap_config* config, |
| bool should_zero); |
| |
| PAS_API void* pas_heap_config_utils_prepare_to_enumerate(pas_enumerator* enumerator, |
| pas_heap_config* config); |
| |
| typedef struct { |
| bool allocate_page_should_zero; |
| pas_heap_runtime_config_view_cache_capacity_for_object_size_callback intrinsic_view_cache_capacity; |
| } pas_basic_heap_config_definitions_arguments; |
| |
| #define PAS_BASIC_HEAP_CONFIG_DEFINITIONS(name, upcase_name, ...) \ |
| pas_basic_heap_page_caches name ## _page_caches = \ |
| PAS_BASIC_HEAP_PAGE_CACHES_INITIALIZER(PAS_SMALL_SHARED_PAGE_LOG_SHIFT, \ |
| PAS_MEDIUM_SHARED_PAGE_LOG_SHIFT); \ |
| \ |
| pas_basic_heap_runtime_config name ## _intrinsic_runtime_config = { \ |
| .base = { \ |
| .lookup_kind = pas_segregated_heap_lookup_primitive, \ |
| .sharing_mode = pas_share_pages, \ |
| .statically_allocated = true, \ |
| .is_part_of_heap = true, \ |
| .directory_size_bound_for_partial_views = \ |
| PAS_INTRINSIC_BOUND_FOR_PARTIAL_VIEWS, \ |
| .directory_size_bound_for_baseline_allocators = \ |
| PAS_INTRINSIC_BOUND_FOR_BASELINE_ALLOCATORS, \ |
| .directory_size_bound_for_no_view_cache = \ |
| PAS_INTRINSIC_BOUND_FOR_NO_VIEW_CACHE, \ |
| .max_segregated_object_size = \ |
| PAS_INTRINSIC_MAX_SEGREGATED_OBJECT_SIZE, \ |
| .max_bitfit_object_size = \ |
| PAS_INTRINSIC_MAX_BITFIT_OBJECT_SIZE, \ |
| .view_cache_capacity_for_object_size = \ |
| ((pas_basic_heap_config_definitions_arguments){__VA_ARGS__}).intrinsic_view_cache_capacity, \ |
| }, \ |
| .page_caches = &name ## _page_caches \ |
| }; \ |
| \ |
| pas_basic_heap_runtime_config name ## _primitive_runtime_config = { \ |
| .base = { \ |
| .lookup_kind = pas_segregated_heap_lookup_primitive, \ |
| .sharing_mode = pas_share_pages, \ |
| .statically_allocated = false, \ |
| .is_part_of_heap = true, \ |
| .directory_size_bound_for_partial_views = \ |
| PAS_PRIMITIVE_BOUND_FOR_PARTIAL_VIEWS, \ |
| .directory_size_bound_for_baseline_allocators = \ |
| PAS_PRIMITIVE_BOUND_FOR_BASELINE_ALLOCATORS, \ |
| .directory_size_bound_for_no_view_cache = \ |
| PAS_PRIMITIVE_BOUND_FOR_NO_VIEW_CACHE, \ |
| .max_segregated_object_size = \ |
| PAS_PRIMITIVE_MAX_SEGREGATED_OBJECT_SIZE, \ |
| .max_bitfit_object_size = \ |
| PAS_PRIMITIVE_MAX_BITFIT_OBJECT_SIZE, \ |
| .view_cache_capacity_for_object_size = pas_heap_runtime_config_zero_view_cache_capacity, \ |
| }, \ |
| .page_caches = &name ## _page_caches \ |
| }; \ |
| \ |
| pas_basic_heap_runtime_config name ## _typed_runtime_config = { \ |
| .base = { \ |
| .lookup_kind = pas_segregated_heap_lookup_type_based, \ |
| .sharing_mode = pas_share_pages, \ |
| .statically_allocated = false, \ |
| .is_part_of_heap = true, \ |
| .directory_size_bound_for_partial_views = \ |
| PAS_TYPED_BOUND_FOR_PARTIAL_VIEWS, \ |
| .directory_size_bound_for_baseline_allocators = \ |
| PAS_TYPED_BOUND_FOR_BASELINE_ALLOCATORS, \ |
| .directory_size_bound_for_no_view_cache = \ |
| PAS_TYPED_BOUND_FOR_NO_VIEW_CACHE, \ |
| .max_segregated_object_size = \ |
| PAS_TYPED_MAX_SEGREGATED_OBJECT_SIZE, \ |
| .max_bitfit_object_size = \ |
| PAS_TYPED_MAX_BITFIT_OBJECT_SIZE, \ |
| .view_cache_capacity_for_object_size = pas_heap_runtime_config_zero_view_cache_capacity, \ |
| }, \ |
| .page_caches = &name ## _page_caches \ |
| }; \ |
| \ |
| pas_basic_heap_runtime_config name ## _flex_runtime_config = { \ |
| .base = { \ |
| .lookup_kind = pas_segregated_heap_lookup_primitive, \ |
| .sharing_mode = pas_share_pages, \ |
| .statically_allocated = false, \ |
| .is_part_of_heap = true, \ |
| .directory_size_bound_for_partial_views = \ |
| PAS_FLEX_BOUND_FOR_PARTIAL_VIEWS, \ |
| .directory_size_bound_for_baseline_allocators = \ |
| PAS_FLEX_BOUND_FOR_BASELINE_ALLOCATORS, \ |
| .directory_size_bound_for_no_view_cache = \ |
| PAS_FLEX_BOUND_FOR_NO_VIEW_CACHE, \ |
| .max_segregated_object_size = \ |
| PAS_FLEX_MAX_SEGREGATED_OBJECT_SIZE, \ |
| .max_bitfit_object_size = \ |
| PAS_FLEX_MAX_BITFIT_OBJECT_SIZE, \ |
| .view_cache_capacity_for_object_size = pas_heap_runtime_config_zero_view_cache_capacity, \ |
| }, \ |
| .page_caches = &name ## _page_caches \ |
| }; \ |
| \ |
| void* name ## _heap_config_allocate_small_segregated_page( \ |
| pas_segregated_heap* heap, pas_physical_memory_transaction* transaction) \ |
| { \ |
| pas_basic_heap_config_definitions_arguments arguments = {__VA_ARGS__}; \ |
| \ |
| pas_segregated_page_config page_config; \ |
| pas_basic_heap_page_caches* page_caches; \ |
| void* allocation; \ |
| \ |
| page_config = upcase_name ## _HEAP_CONFIG.small_segregated_config; \ |
| \ |
| PAS_ASSERT(page_config.base.is_enabled); \ |
| \ |
| page_caches = ((pas_basic_heap_runtime_config*)heap->runtime_config)->page_caches; \ |
| \ |
| allocation = pas_fast_megapage_cache_try_allocate( \ |
| &page_caches->small_segregated_megapage_cache, \ |
| &name ## _megapage_table, \ |
| page_config.base.page_config_ptr, \ |
| pas_small_segregated_fast_megapage_kind, \ |
| arguments.allocate_page_should_zero, \ |
| pas_heap_for_segregated_heap(heap), \ |
| transaction); \ |
| \ |
| return allocation; \ |
| } \ |
| \ |
| void* name ## _heap_config_allocate_small_bitfit_page( \ |
| pas_segregated_heap* heap, pas_physical_memory_transaction* transaction) \ |
| { \ |
| pas_basic_heap_config_definitions_arguments arguments = {__VA_ARGS__}; \ |
| \ |
| pas_bitfit_page_config page_config; \ |
| pas_basic_heap_page_caches* page_caches; \ |
| void* allocation; \ |
| \ |
| page_config = upcase_name ## _HEAP_CONFIG.small_bitfit_config; \ |
| \ |
| PAS_ASSERT(page_config.base.is_enabled); \ |
| \ |
| page_caches = ((pas_basic_heap_runtime_config*)heap->runtime_config)->page_caches; \ |
| \ |
| allocation = pas_fast_megapage_cache_try_allocate( \ |
| &page_caches->small_bitfit_megapage_cache, \ |
| &name ## _megapage_table, \ |
| page_config.base.page_config_ptr, \ |
| pas_small_bitfit_fast_megapage_kind, \ |
| arguments.allocate_page_should_zero, \ |
| pas_heap_for_segregated_heap(heap), \ |
| transaction); \ |
| \ |
| return allocation; \ |
| } \ |
| \ |
| void* name ## _heap_config_allocate_medium_segregated_page( \ |
| pas_segregated_heap* heap, pas_physical_memory_transaction* transaction) \ |
| { \ |
| pas_basic_heap_config_definitions_arguments arguments = {__VA_ARGS__}; \ |
| \ |
| pas_segregated_page_config page_config; \ |
| pas_basic_heap_page_caches* page_caches; \ |
| void* allocation; \ |
| \ |
| page_config = upcase_name ## _HEAP_CONFIG.medium_segregated_config; \ |
| \ |
| PAS_ASSERT(page_config.base.is_enabled); \ |
| \ |
| page_caches = ((pas_basic_heap_runtime_config*)heap->runtime_config)->page_caches; \ |
| \ |
| allocation = pas_medium_megapage_cache_try_allocate( \ |
| &page_caches->medium_megapage_cache, \ |
| page_config.base.page_config_ptr, \ |
| arguments.allocate_page_should_zero, \ |
| pas_heap_for_segregated_heap(heap), \ |
| transaction); \ |
| \ |
| return allocation; \ |
| } \ |
| \ |
| void* name ## _heap_config_allocate_medium_bitfit_page( \ |
| pas_segregated_heap* heap, pas_physical_memory_transaction* transaction) \ |
| { \ |
| pas_basic_heap_config_definitions_arguments arguments = {__VA_ARGS__}; \ |
| \ |
| pas_bitfit_page_config page_config; \ |
| pas_basic_heap_page_caches* page_caches; \ |
| void* allocation; \ |
| \ |
| page_config = upcase_name ## _HEAP_CONFIG.medium_bitfit_config; \ |
| \ |
| PAS_ASSERT(page_config.base.is_enabled); \ |
| \ |
| page_caches = ((pas_basic_heap_runtime_config*)heap->runtime_config)->page_caches; \ |
| \ |
| allocation = pas_medium_megapage_cache_try_allocate( \ |
| &page_caches->medium_megapage_cache, \ |
| page_config.base.page_config_ptr, \ |
| arguments.allocate_page_should_zero, \ |
| pas_heap_for_segregated_heap(heap), \ |
| transaction); \ |
| \ |
| return allocation; \ |
| } \ |
| \ |
| void* name ## _heap_config_allocate_marge_bitfit_page( \ |
| pas_segregated_heap* heap, pas_physical_memory_transaction* transaction) \ |
| { \ |
| pas_basic_heap_config_definitions_arguments arguments = {__VA_ARGS__}; \ |
| \ |
| pas_bitfit_page_config page_config; \ |
| pas_basic_heap_page_caches* page_caches; \ |
| void* allocation; \ |
| \ |
| page_config = upcase_name ## _HEAP_CONFIG.marge_bitfit_config; \ |
| \ |
| PAS_ASSERT(page_config.base.is_enabled); \ |
| \ |
| page_caches = ((pas_basic_heap_runtime_config*)heap->runtime_config)->page_caches; \ |
| \ |
| allocation = pas_medium_megapage_cache_try_allocate( \ |
| &page_caches->medium_megapage_cache, \ |
| page_config.base.page_config_ptr, \ |
| arguments.allocate_page_should_zero, \ |
| pas_heap_for_segregated_heap(heap), \ |
| transaction); \ |
| \ |
| return allocation; \ |
| } \ |
| \ |
| pas_aligned_allocation_result name ## _aligned_allocator( \ |
| size_t size, \ |
| pas_alignment alignment, \ |
| pas_large_heap* large_heap, \ |
| pas_heap_config* config) \ |
| { \ |
| return pas_heap_config_utils_allocate_aligned( \ |
| size, alignment, large_heap, config, \ |
| ((pas_basic_heap_config_definitions_arguments){__VA_ARGS__}).allocate_page_should_zero); \ |
| } \ |
| \ |
| pas_fast_megapage_table name ## _megapage_table = PAS_FAST_MEGAPAGE_TABLE_INITIALIZER; \ |
| pas_page_header_table name ## _medium_page_header_table = PAS_PAGE_HEADER_TABLE_INITIALIZER( \ |
| upcase_name ##_HEAP_CONFIG.medium_segregated_config.base.page_size); \ |
| pas_page_header_table name ## _marge_page_header_table = PAS_PAGE_HEADER_TABLE_INITIALIZER( \ |
| upcase_name ##_HEAP_CONFIG.marge_bitfit_config.base.page_size); \ |
| \ |
| pas_basic_heap_config_root_data name ## _root_data = { \ |
| .medium_page_header_table = &name ## _medium_page_header_table, \ |
| .marge_page_header_table = &name ## _marge_page_header_table \ |
| }; \ |
| \ |
| void* name ## _prepare_to_enumerate(pas_enumerator* enumerator) \ |
| { \ |
| return pas_heap_config_utils_prepare_to_enumerate(enumerator, &name ## _heap_config); \ |
| } \ |
| \ |
| PAS_BASIC_SEGREGATED_PAGE_CONFIG_DEFINITIONS( \ |
| name ## _small_segregated, \ |
| .page_config = upcase_name ## _HEAP_CONFIG.small_segregated_config, \ |
| .header_table = NULL); \ |
| \ |
| PAS_BASIC_SEGREGATED_PAGE_CONFIG_DEFINITIONS( \ |
| name ## _medium_segregated, \ |
| .page_config = upcase_name ## _HEAP_CONFIG.medium_segregated_config, \ |
| .header_table = &name ## _medium_page_header_table); \ |
| \ |
| PAS_BASIC_BITFIT_PAGE_CONFIG_DEFINITIONS( \ |
| name ## _small_bitfit, \ |
| .page_config = upcase_name ## _HEAP_CONFIG.small_bitfit_config, \ |
| .header_table = NULL); \ |
| \ |
| PAS_BASIC_BITFIT_PAGE_CONFIG_DEFINITIONS( \ |
| name ## _medium_bitfit, \ |
| .page_config = upcase_name ## _HEAP_CONFIG.medium_bitfit_config, \ |
| .header_table = &name ## _medium_page_header_table); \ |
| \ |
| PAS_BASIC_BITFIT_PAGE_CONFIG_DEFINITIONS( \ |
| name ## _marge_bitfit, \ |
| .page_config = upcase_name ## _HEAP_CONFIG.marge_bitfit_config, \ |
| .header_table = &name ## _marge_page_header_table); \ |
| \ |
| PAS_HEAP_CONFIG_SPECIALIZATION_DEFINITIONS(name ## _heap_config, upcase_name ## _HEAP_CONFIG) |
| |
| PAS_END_EXTERN_C; |
| |
| #endif /* PAS_HEAP_CONFIG_UTILS_INLINES_H */ |
| |