blob: b69abc75521c68b6c99447274f63a392ea579436 [file] [log] [blame]
/*
* Copyright (c) 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.
*/
#include "pas_config.h"
#if LIBPAS_ENABLED
#include "jit_heap_config.h"
#if PAS_ENABLE_JIT
#include "bmalloc_heap_config.h"
#include "pas_basic_heap_config_enumerator_data.h"
#include "pas_bitfit_page_config_inlines.h"
#include "pas_enumerable_page_malloc.h"
#include "pas_heap_config_inlines.h"
#include "pas_root.h"
#if defined(PAS_BMALLOC)
#include "BPlatform.h"
#endif
pas_heap_config jit_heap_config = JIT_HEAP_CONFIG;
pas_simple_large_free_heap jit_fresh_memory_heap = PAS_SIMPLE_LARGE_FREE_HEAP_INITIALIZER;
static pas_aligned_allocation_result fresh_memory_aligned_allocator(size_t size,
pas_alignment alignment,
void *arg)
{
PAS_UNUSED_PARAM(size);
PAS_UNUSED_PARAM(alignment);
PAS_ASSERT(!arg);
return pas_aligned_allocation_result_create_empty();
}
static void initialize_fresh_memory_config(pas_large_free_heap_config* config)
{
config->type_size = 1;
config->min_alignment = 1;
config->aligned_allocator = fresh_memory_aligned_allocator;
config->aligned_allocator_arg = NULL;
config->deallocator = NULL;
config->deallocator_arg = NULL;
}
static pas_allocation_result allocate_from_fresh(size_t size, pas_alignment alignment)
{
pas_large_free_heap_config config;
pas_heap_lock_assert_held();
initialize_fresh_memory_config(&config);
return pas_simple_large_free_heap_try_allocate(&jit_fresh_memory_heap, size, alignment, &config);
}
static pas_allocation_result page_provider(
size_t size, pas_alignment alignment, const char* name,
pas_heap* heap, pas_physical_memory_transaction* transaction, void* arg)
{
PAS_UNUSED_PARAM(name);
PAS_UNUSED_PARAM(heap);
PAS_UNUSED_PARAM(transaction);
PAS_ASSERT(!arg);
return allocate_from_fresh(size, alignment);
}
pas_large_heap_physical_page_sharing_cache jit_large_fresh_memory_heap = {
.free_heap = PAS_SIMPLE_LARGE_FREE_HEAP_INITIALIZER,
.provider = page_provider,
.provider_arg = NULL
};
pas_page_header_table jit_small_bitfit_page_header_table =
PAS_PAGE_HEADER_TABLE_INITIALIZER(JIT_SMALL_PAGE_SIZE);
pas_page_header_table jit_medium_bitfit_page_header_table =
PAS_PAGE_HEADER_TABLE_INITIALIZER(JIT_MEDIUM_PAGE_SIZE);
pas_heap_runtime_config jit_heap_runtime_config = {
.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 = 0,
.directory_size_bound_for_baseline_allocators = 0,
.directory_size_bound_for_no_view_cache = UINT_MAX,
.max_segregated_object_size = 0,
.max_bitfit_object_size = UINT_MAX,
.view_cache_capacity_for_object_size = pas_heap_runtime_config_zero_view_cache_capacity
};
jit_heap_config_root_data jit_root_data = {
.small_bitfit_page_header_table = &jit_small_bitfit_page_header_table,
.medium_bitfit_page_header_table = &jit_medium_bitfit_page_header_table
};
void jit_heap_config_activate(void)
{
/* Make sure that the bmalloc heap config initializes before we do anything else, since that
one will want to be designated. */
pas_heap_config_activate(&bmalloc_heap_config);
}
pas_page_base* jit_page_header_for_boundary_remote(pas_enumerator* enumerator, void* boundary)
{
pas_basic_heap_config_enumerator_data* data;
data = enumerator->heap_config_datas[pas_heap_config_kind_jit];
PAS_ASSERT(data);
return pas_ptr_hash_map_get(&data->page_header_table, boundary).value;
}
void* jit_small_bitfit_allocate_page(
pas_segregated_heap* heap, pas_physical_memory_transaction* transaction)
{
PAS_UNUSED_PARAM(heap);
PAS_UNUSED_PARAM(transaction);
return (void*)allocate_from_fresh(
JIT_SMALL_PAGE_SIZE, pas_alignment_create_traditional(JIT_SMALL_PAGE_SIZE)).begin;
}
pas_page_base* jit_small_bitfit_create_page_header(
void* boundary, pas_lock_hold_mode heap_lock_hold_mode)
{
pas_page_base* result;
pas_heap_lock_lock_conditionally(heap_lock_hold_mode);
result = pas_page_header_table_add(&jit_small_bitfit_page_header_table,
JIT_SMALL_PAGE_SIZE,
JIT_HEAP_CONFIG.small_bitfit_config.base.page_header_size,
boundary);
pas_heap_lock_unlock_conditionally(heap_lock_hold_mode);
return result;
}
void jit_small_bitfit_destroy_page_header(
pas_page_base* page, pas_lock_hold_mode heap_lock_hold_mode)
{
pas_heap_lock_lock_conditionally(heap_lock_hold_mode);
pas_page_header_table_remove(&jit_small_bitfit_page_header_table,
JIT_SMALL_PAGE_SIZE,
page);
pas_heap_lock_unlock_conditionally(heap_lock_hold_mode);
}
void* jit_medium_bitfit_allocate_page(
pas_segregated_heap* heap, pas_physical_memory_transaction* transaction)
{
PAS_UNUSED_PARAM(heap);
PAS_UNUSED_PARAM(transaction);
return (void*)allocate_from_fresh(
JIT_MEDIUM_PAGE_SIZE, pas_alignment_create_traditional(JIT_MEDIUM_PAGE_SIZE)).begin;
}
pas_page_base* jit_medium_bitfit_create_page_header(
void* boundary, pas_lock_hold_mode heap_lock_hold_mode)
{
pas_page_base* result;
pas_heap_lock_lock_conditionally(heap_lock_hold_mode);
result = pas_page_header_table_add(&jit_medium_bitfit_page_header_table,
JIT_MEDIUM_PAGE_SIZE,
JIT_HEAP_CONFIG.medium_bitfit_config.base.page_header_size,
boundary);
pas_heap_lock_unlock_conditionally(heap_lock_hold_mode);
return result;
}
void jit_medium_bitfit_destroy_page_header(
pas_page_base* page, pas_lock_hold_mode heap_lock_hold_mode)
{
pas_heap_lock_lock_conditionally(heap_lock_hold_mode);
pas_page_header_table_remove(&jit_medium_bitfit_page_header_table,
JIT_MEDIUM_PAGE_SIZE,
page);
pas_heap_lock_unlock_conditionally(heap_lock_hold_mode);
}
pas_aligned_allocation_result jit_aligned_allocator(
size_t size, pas_alignment alignment, pas_large_heap* large_heap, pas_heap_config* config)
{
pas_aligned_allocation_result result;
size_t aligned_size;
pas_allocation_result allocation_result;
PAS_UNUSED_PARAM(large_heap);
PAS_UNUSED_PARAM(config);
pas_zero_memory(&result, sizeof(result));
aligned_size = pas_round_up_to_power_of_2(size, alignment.alignment);
allocation_result = pas_large_heap_physical_page_sharing_cache_try_allocate_with_alignment(
&jit_large_fresh_memory_heap, aligned_size, alignment, false);
if (!allocation_result.did_succeed)
return result;
result.result = (void*)allocation_result.begin;
result.result_size = size;
result.left_padding = (void*)allocation_result.begin;
result.left_padding_size = 0;
result.right_padding = (char*)(void*)allocation_result.begin + size;
result.right_padding_size = aligned_size - size;
result.zero_mode = allocation_result.zero_mode;
return result;
}
void* jit_prepare_to_enumerate(pas_enumerator* enumerator)
{
pas_basic_heap_config_enumerator_data* result;
pas_heap_config** configs;
pas_heap_config* config;
jit_heap_config_root_data* root_data;
configs = pas_enumerator_read(
enumerator, enumerator->root->heap_configs,
sizeof(pas_heap_config*) * pas_heap_config_kind_num_kinds);
if (!configs)
return NULL;
config = pas_enumerator_read(
enumerator, configs[pas_heap_config_kind_jit], sizeof(pas_heap_config));
if (!config)
return NULL;
root_data = pas_enumerator_read(
enumerator, config->root_data, sizeof(jit_heap_config_root_data));
if (!root_data)
return NULL;
result = pas_enumerator_allocate(enumerator, sizeof(pas_basic_heap_config_enumerator_data));
pas_ptr_hash_map_construct(&result->page_header_table);
if (!pas_basic_heap_config_enumerator_data_add_page_header_table(
result,
enumerator,
pas_enumerator_read(
enumerator, root_data->small_bitfit_page_header_table, sizeof(pas_page_header_table))))
return NULL;
if (!pas_basic_heap_config_enumerator_data_add_page_header_table(
result,
enumerator,
pas_enumerator_read(
enumerator, root_data->medium_bitfit_page_header_table, sizeof(pas_page_header_table))))
return NULL;
return result;
}
bool jit_heap_config_for_each_shared_page_directory(
pas_segregated_heap* heap,
bool (*callback)(pas_segregated_shared_page_directory* directory,
void* arg),
void* arg)
{
PAS_UNUSED_PARAM(heap);
PAS_UNUSED_PARAM(callback);
PAS_UNUSED_PARAM(arg);
return true;
}
bool jit_heap_config_for_each_shared_page_directory_remote(
pas_enumerator* enumerator,
pas_segregated_heap* heap,
bool (*callback)(pas_enumerator* enumerator,
pas_segregated_shared_page_directory* directory,
void* arg),
void* arg)
{
PAS_UNUSED_PARAM(enumerator);
PAS_UNUSED_PARAM(heap);
PAS_UNUSED_PARAM(callback);
PAS_UNUSED_PARAM(arg);
return true;
}
void jit_heap_config_add_fresh_memory(pas_range range)
{
pas_large_free_heap_config config;
PAS_ASSERT(pas_is_aligned(range.begin, pas_page_malloc_alignment()));
PAS_ASSERT(pas_is_aligned(range.end, pas_page_malloc_alignment()));
pas_heap_lock_assert_held();
pas_enumerable_range_list_append(&pas_enumerable_page_malloc_page_list, range);
initialize_fresh_memory_config(&config);
pas_simple_large_free_heap_deallocate(
&jit_fresh_memory_heap, range.begin, range.end, pas_zero_mode_is_all_zero, &config);
}
PAS_BITFIT_PAGE_CONFIG_SPECIALIZATION_DEFINITIONS(
jit_small_bitfit_page_config, JIT_HEAP_CONFIG.small_bitfit_config);
PAS_BITFIT_PAGE_CONFIG_SPECIALIZATION_DEFINITIONS(
jit_medium_bitfit_page_config, JIT_HEAP_CONFIG.medium_bitfit_config);
PAS_HEAP_CONFIG_SPECIALIZATION_DEFINITIONS(
jit_heap_config, JIT_HEAP_CONFIG);
#endif /* PAS_ENABLE_JIT */
#endif /* LIBPAS_ENABLED */