diff --git a/lib/Base/Arena.cpp b/lib/Base/Arena.cpp index fa57883..42f37c6 100644 --- a/lib/Base/Arena.cpp +++ b/lib/Base/Arena.cpp @@ -82,7 +82,12 @@ bool arena_commit_first_pages (Arena* arena, s64 commit_size, s64 start_offset) return true; } -Arena* bootstrap_arena (Arena_Reserve new_reserve, s32 default_commit_page_count) { +// Arena* bootstrap_arena (Arena_Reserve new_reserve, s32 default_commit_page_count) { +Arena* bootstrap_arena_internal (Arena_Reserve new_reserve, s32 default_commit_page_count, string file_path, + string function_name, s32 line_number) { + // #TODO: Store info in debug mode: + // + Save thread ID/name MAKE A COPY OBVIOUSLY! + PUSH default_allocator! + // WE USE default_allocator because this arena may be used to back an array! s64 commit_size = default_commit_page_count * PLATFORM_MEMORY_PAGE_SIZE; Assert(commit_size <= reserve_size(new_reserve)); @@ -93,11 +98,18 @@ Arena* bootstrap_arena (Arena_Reserve new_reserve, s32 default_commit_page_count return nullptr; } - memcpy(arena_ptr, &new_arena, sizeof(Arena)); + memcpy(arena_ptr, &new_arena, sizeof(Arena)); arena_ptr->current_point = arena_start(arena_ptr); arena_set_bootstrap_flag(arena_ptr); +// #if BUILD_DEBUG +// { push_allocator(default_allocator()); +// arena_ptr->file_path = copy_string(file_path); +// arena_ptr->function_name = +// } +// #endif + return arena_ptr; } diff --git a/lib/Base/Arena.h b/lib/Base/Arena.h index fac9b41..ac05285 100644 --- a/lib/Base/Arena.h +++ b/lib/Base/Arena.h @@ -3,8 +3,8 @@ struct ExpandableArena; // fwd declare #temp #if OS_WINDOWS - constexpr u32 ARENA_DEFAULT_COMMIT_PAGE_COUNT = 16; // 16 * 4k page = 64kB - constexpr s64 ARENA_DEFAULT_COMMIT_SIZE_BYTES = 65536; + const u32 ARENA_DEFAULT_COMMIT_PAGE_COUNT = 16; // 16 * 4k page = 64kB + const s64 ARENA_DEFAULT_COMMIT_SIZE_BYTES = 65536; #endif constexpr u16 ARENA_DEFAULT_ALIGNMENT = CPU_REGISTER_WIDTH_BYTES; @@ -65,6 +65,11 @@ struct Arena { Arena_Reserve reserve_size = Arena_Reserve::Size_64K; Arena_Flags flags = Arena_Flags::None; u32 initial_commit_page_count = ARENA_DEFAULT_COMMIT_PAGE_COUNT; +#if BUILD_DEBUG + string file_path; + string function_name; + s32 line_number; +#endif }; typedef void* (*Memory_Wipe_Function)(void* memory, u64 byte_count); @@ -72,9 +77,18 @@ typedef void* (*Memory_Wipe_Function)(void* memory, u64 byte_count); void* arena_allocator_proc (Allocator_Mode mode, s64 requested_size, s64 old_size, void* old_memory, void* allocator_data); // Main API -Arena* bootstrap_arena (Arena_Reserve new_reserve, s32 default_commit_page_count=ARENA_DEFAULT_COMMIT_PAGE_COUNT); +#if BUILD_DEBUG +#define bootstrap_arena(_reserve_) \ + bootstrap_arena_internal((_reserve_), (s32)ARENA_DEFAULT_COMMIT_PAGE_COUNT, __FILE__, __FUNCTION__, __LINE__) +#else +#define bootstrap_arena(_reserve_) \ + bootstrap_arena_internal((_reserve_), (s32)ARENA_DEFAULT_COMMIT_PAGE_COUNT) +#endif -void arena_init (Arena* arena, Arena_Reserve new_reserve, s32 default_commit_page_count=16); // For when we're *not* bootstrapping arenas: (I'm debating if we should keep this..) +Arena* bootstrap_arena_internal (Arena_Reserve new_reserve, s32 commit_page_count=ARENA_DEFAULT_COMMIT_PAGE_COUNT, + string file_path="", string function_name="", s32 line_number=0); + +void arena_init (Arena* arena, Arena_Reserve new_reserve, s32 commit_page_count=16); // For when we're *not* bootstrapping arenas: (I'm debating if we should keep this..) bool arena_commit_first_pages (Arena* arena, s64 commit_size, s64 start_offset=0); // This is useful for initializing arenas (arena_init), and for starting Arena-backed arrays. void arena_clear_flags (Arena* arena); @@ -146,7 +160,7 @@ struct FixedArena { void* fixed_arena_allocator_proc (Allocator_Mode mode, s64 requested_size, s64 old_size, void* old_memory, void* allocator_data); // #FixedArena API -FixedArena* bootstrap_fixed_arena (s64 size, Allocator backing_allocator); +FixedArena* bootstrap_fixed_arena (s64 size, Allocator backing_allocator = { default_allocator_proc, nullptr }); force_inline void destroy_arena (FixedArena* arena); Allocator allocator (FixedArena* arena); diff --git a/lib/Base/Arena_Array.h b/lib/Base/Arena_Array.h index 85b1192..db9fbd4 100644 --- a/lib/Base/Arena_Array.h +++ b/lib/Base/Arena_Array.h @@ -1,6 +1,10 @@ #pragma once +#if BUILD_DEBUG +constexpr s64 ARRAY_ARENA_START_OFFSET = 2 * 64; // sizeof(Arena)+sizeof(array) +#else constexpr s64 ARRAY_ARENA_START_OFFSET = 64; +#endif template struct ArenaArray { // #downcasts to an ArrayView. @@ -41,13 +45,22 @@ ArenaArray* arena_array_new (s64 preallocate_count, Arena_Reserve reserve_siz array->count = 0; array->arena = arena; + // #TODO: Should align to next cache line! array->data = array_start(*array); return array; } template T* array_start (ArenaArray& array) { - return (T*)(array.arena->memory_base + ARRAY_ARENA_START_OFFSET); + T* memory = (T*)(array.arena->memory_base + ARRAY_ARENA_START_OFFSET); + Assert((u8*)memory >= (u8*)array.arena->current_point); + return memory; +} + +s64 max_array_size (ArenaArray& array) { + u8* address_limit = array.arena->memory_base + reserve_size(array.arena); + u8* address_start = array_start(array); + return (s64)(address_limit - address_start); } template bool is_valid (ArenaArray* array) { @@ -160,10 +173,6 @@ template void array_resize (ArenaArray& array, s64 desired_item_ } } -s64 max_array_size (ArenaArray& array) { - return reserve_size(array.arena) - sizeof(Arena) - sizeof(ArenaArray); -} - void array_arena_realloc (ArenaArray& array, s64 new_size, s64 old_size) { Assert(new_size <= max_array_size(array)); diff --git a/lib/Base/Base_Thread_Context.cpp b/lib/Base/Base_Thread_Context.cpp index d61922f..d2c257c 100644 --- a/lib/Base/Base_Thread_Context.cpp +++ b/lib/Base/Base_Thread_Context.cpp @@ -16,10 +16,10 @@ internal void Bootstrap_Main_Thread_Context () { // initialize_arena_free_list(default_allocator()); // 2. #NewContext Setup thread local context - ExpandableArena* arena_ex = expandable_arena_new(Arena_Reserve::Size_64M, 16); + ExpandableArena* arena_ex = bootstrap_expandable_arena(Arena_Reserve::Size_64M); thread_local_context = New(allocator(arena_ex)); - thread_local_context->temp = expandable_arena_new(Arena_Reserve::Size_2M, 16); + thread_local_context->temp = bootstrap_expandable_arena(Arena_Reserve::Size_2M); thread_local_context->arena = arena_ex; thread_local_context->allocator = allocator(arena_ex); thread_local_context->thread_idx = 0; diff --git a/lib/Base/ErrorType.cpp b/lib/Base/ErrorType.cpp index 47c3d68..54182a2 100644 --- a/lib/Base/ErrorType.cpp +++ b/lib/Base/ErrorType.cpp @@ -54,19 +54,19 @@ string to_string (Error* error) { } #define log_todo(fmt, ...) \ - Log_Error_2(__FILE__, __FUNCTION__, __LINE__, ErrorClass::TODO, fmt, ##__VA_ARGS__) + log_error_internal(__FILE__, __FUNCTION__, __LINE__, ErrorClass::TODO, fmt, ##__VA_ARGS__) #define log_fatal_error(fmt, ...) \ - Log_Error_2(__FILE__, __FUNCTION__, __LINE__, ErrorClass::FATAL, fmt, ##__VA_ARGS__) + log_error_internal(__FILE__, __FUNCTION__, __LINE__, ErrorClass::FATAL, fmt, ##__VA_ARGS__) #define log_error(fmt, ...) \ - Log_Error_2(__FILE__, __FUNCTION__, __LINE__, ErrorClass::ERROR, fmt, ##__VA_ARGS__) + log_error_internal(__FILE__, __FUNCTION__, __LINE__, ErrorClass::ERROR, fmt, ##__VA_ARGS__) #define log_warning(fmt, ...) \ - Log_Error_2(__FILE__, __FUNCTION__, __LINE__, ErrorClass::WARNING, fmt, ##__VA_ARGS__) + log_error_internal(__FILE__, __FUNCTION__, __LINE__, ErrorClass::WARNING, fmt, ##__VA_ARGS__) #define log_none(fmt, ...) \ - Log_Error_2(__FILE__, __FUNCTION__, __LINE__, ErrorClass::NONE, fmt, ##__VA_ARGS__) + log_error_internal(__FILE__, __FUNCTION__, __LINE__, ErrorClass::NONE, fmt, ##__VA_ARGS__) Error* new_error (ErrorClass severity, string error_string) { Error* error = New(); @@ -77,7 +77,7 @@ Error* new_error (ErrorClass severity, string error_string) { return error; } -void Log_Error_2 (string file_path, string function_name, s32 line_number, ErrorClass severity, string fmt, ...) { +void log_error_internal (string file_path, string function_name, s32 line_number, ErrorClass severity, string fmt, ...) { auto tctx = thread_context(); Assert(tctx != nullptr); push_arena(tctx->error_arena); diff --git a/lib/Base/Expandable_Arena.cpp b/lib/Base/Expandable_Arena.cpp index 31c8493..a6f480f 100644 --- a/lib/Base/Expandable_Arena.cpp +++ b/lib/Base/Expandable_Arena.cpp @@ -1,5 +1,11 @@ -ExpandableArena* expandable_arena_new (Arena_Reserve starting_reserve, s32 commit_page_count) { - ExpandableArena* new_arena = (ExpandableArena*)bootstrap_arena(starting_reserve, commit_page_count); +ExpandableArena* bootstrap_expandable_arena_internal (Arena_Reserve new_reserve, s32 commit_page_count, + string file_path, string function_name, s32 line_number) { + ExpandableArena* new_arena = (ExpandableArena*)bootstrap_arena_internal( + new_reserve, + commit_page_count, + file_path, + function_name, + line_number); // Note: beyond first 32 bytes (sizeof(Arena)) ExpandableArena will not be initialized, // so we do it here: new_arena->current = (Arena*)new_arena; @@ -15,6 +21,10 @@ ExpandableArena* expandable_arena_new (Arena_Reserve starting_reserve, s32 commi return new_arena; } +// force_inline ExpandableArena* bootstrap_expandable_arena (Arena_Reserve new_reserve, s32 commit_page_count) { +// return bootstrap_expandable_arena_internal(new_reserve, commit_page_count, __FILE__, __FUNCTION__, __LINE__); +// } + void* expandable_arena_allocator_proc (Allocator_Mode mode, s64 requested_size, s64 old_size, void* old_memory, void* allocator_data) { ExpandableArena* arena = (ExpandableArena*)allocator_data; Assert(arena != nullptr); diff --git a/lib/Base/Expandable_Arena.h b/lib/Base/Expandable_Arena.h index 1d238fd..52405a7 100644 --- a/lib/Base/Expandable_Arena.h +++ b/lib/Base/Expandable_Arena.h @@ -16,9 +16,26 @@ struct ExpandableArena { // Note that this downcasts to Arena*, so can be initialized in the same way. Arena* current; Array next_arenas; +#if BUILD_DEBUG + string info; + string file_path; + string function_name; + s32 line_number; +#endif }; -ExpandableArena* expandable_arena_new (Arena_Reserve starting_reserve=Arena_Reserve::Size_64K, s32 commit_page_count=8); +#if BUILD_DEBUG +#define bootstrap_expandable_arena(_reserve_) \ + bootstrap_expandable_arena_internal((_reserve_), (s32)ARENA_DEFAULT_COMMIT_PAGE_COUNT, __FILE__, __FUNCTION__, __LINE__) +#else +#define bootstrap_expandable_arena(_reserve_) \ + bootstrap_expandable_arena_internal((_reserve_), (s32)ARENA_DEFAULT_COMMIT_PAGE_COUNT) +#endif + +ExpandableArena* bootstrap_expandable_arena_internal (Arena_Reserve new_reserve=Arena_Reserve::Size_64K, s32 commit_page_count=ARENA_DEFAULT_COMMIT_PAGE_COUNT, + string file_path="", string function_name="", s32 line_number=0); + +// ExpandableArena* bootstrap_expandable_arena_internal (Arena_Reserve starting_reserve=Arena_Reserve::Size_64K, s32 commit_page_count=8); void* expandable_arena_allocator_proc (Allocator_Mode mode, s64 requested_size, s64 old_size, void* old_memory, void* allocator_data); bool is_valid (ExpandableArena* arena); void* expandable_arena_alloc (ExpandableArena* arena_ex, s64 byte_count); diff --git a/lib/Base/Logger.cpp b/lib/Base/Logger.cpp index abb9bca..a4e1393 100644 --- a/lib/Base/Logger.cpp +++ b/lib/Base/Logger.cpp @@ -29,4 +29,4 @@ void print (string message) { void print_error (string error_message) { Logger* logger = context_logger(); logger->proc(error_message, Log_Level::Error, logger->data); -} \ No newline at end of file +} diff --git a/lib/Base/String.h b/lib/Base/String.h index 0215be3..7626616 100644 --- a/lib/Base/String.h +++ b/lib/Base/String.h @@ -112,23 +112,3 @@ string trim_right (string s, string chars=DEFAULT_SPACES, bool replace_with_zero // Need an API for inserting various types (ints, floats, etc.) into a String_Builder, and advancing // the count. -// #string_builder -// #limitations This won't be as fast as Jon's String_Builder in jai because we're backing it with an -// Arena, which requires a variable number of cycles depending on if our process has -// memory available already. It also has a max capacity depending on what Arena_Reserve we choose. -// That being said, the implementation is much simpler. -typedef ArenaArray String_Builder; // struct String_Builder - -force_inline String_Builder* new_string_builder (Arena_Reserve new_reserve=Arena_Reserve::Size_64K); -force_inline void append (String_Builder* sb, string s); -void append (String_Builder* sb, ArrayView strings); -// This should probably be called append_but_do_not_increment_count -internal force_inline void append_no_add (String_Builder* sb, string s); // for appending null terminators, does not increment count. -void print_to_builder (String_Builder* sb, string format, ...); -void print_to_builder_internal (String_Builder* sb, string format, va_list args); -string string_view (String_Builder* sb); -internal force_inline void reset_string_builder (String_Builder* sb, bool keep_memory=false); - -// #rename copy_string_and_free_builder -force_inline string builder_to_string (String_Builder* sb); // returns copy and frees string_builder -internal force_inline void free_string_builder (String_Builder* sb); diff --git a/lib/Base/String_Builder.h b/lib/Base/String_Builder.h new file mode 100644 index 0000000..62d3322 --- /dev/null +++ b/lib/Base/String_Builder.h @@ -0,0 +1,20 @@ +// #string_builder +// #limitations This won't be as fast as Jon's String_Builder in jai because we're backing it with an +// Arena, which requires a variable number of cycles depending on if our process has +// memory available already. It also has a max capacity depending on what Arena_Reserve we choose. +// That being said, the implementation is much simpler. +typedef ArenaArray String_Builder; // struct String_Builder + +force_inline String_Builder* new_string_builder (Arena_Reserve new_reserve=Arena_Reserve::Size_64K); +force_inline void append (String_Builder* sb, string s); +void append (String_Builder* sb, ArrayView strings); +// This should probably be called append_but_do_not_increment_count +internal force_inline void append_no_add (String_Builder* sb, string s); // for appending null terminators, does not increment count. +void print_to_builder (String_Builder* sb, string format, ...); +void print_to_builder_internal (String_Builder* sb, string format, va_list args); +string string_view (String_Builder* sb); +internal force_inline void reset_string_builder (String_Builder* sb, bool keep_memory=false); + +// #rename copy_string_and_free_builder +force_inline string builder_to_string (String_Builder* sb); // returns copy and frees string_builder +internal force_inline void free_string_builder (String_Builder* sb); diff --git a/lib/OS/OS_Win32.cpp b/lib/OS/OS_Win32.cpp index eee3946..100bf2d 100644 --- a/lib/OS/OS_Win32.cpp +++ b/lib/OS/OS_Win32.cpp @@ -282,12 +282,12 @@ internal bool thread_init (Thread* thread, Thread_Proc proc, string thread_name) s64 this_thread_index = InterlockedIncrement(&next_thread_index); // 2. #NewContext Setup NEW thread local context - ExpandableArena* arena_ex = expandable_arena_new(Arena_Reserve::Size_64M, 16); + ExpandableArena* arena_ex = bootstrap_expandable_arena(Arena_Reserve::Size_64M); push_arena(arena_ex); // #NOTE: we don't assign thread_local_context until we hit the #thread_entry_point thread->context = New(); - thread->context->temp = expandable_arena_new(Arena_Reserve::Size_2M, 16); + thread->context->temp = bootstrap_expandable_arena(Arena_Reserve::Size_2M); thread->context->arena = arena_ex; thread->context->allocator = allocator(arena_ex); thread->context->thread_idx = (s32)this_thread_index; diff --git a/lib_main.cpp b/lib_main.cpp index e835d74..482d9fa 100644 --- a/lib_main.cpp +++ b/lib_main.cpp @@ -15,9 +15,10 @@ #include "lib/Base/Allocator.h" #include "lib/Base/Array.h" #include "lib/Base/General_Purpose_Allocator.h" +#include "lib/Base/String.h" #include "lib/Base/Arena.h" #include "lib/Base/Arena_Array.h" -#include "lib/Base/String.h" +#include "lib/Base/String_Builder.h" #include "lib/Base/Hash_Functions.h" #include "lib/Base/Hash_Table.h" #include "lib/Base/Arena_Hash_Table.h"