--- parser3/src/main/pa_memory.C 2003/07/24 11:36:34 1.2 +++ parser3/src/main/pa_memory.C 2024/11/09 17:28:22 1.22 @@ -1,102 +1,62 @@ /** @file Parser: memory reference counting classes. - Copyright (c) 2001-2003 ArtLebedev Group (http://www.artlebedev.com) - Author: Alexandr Petrosian (http://paf.design.ru) + Copyright (c) 2001-2024 Art. Lebedev Studio (http://www.artlebedev.com) + Authors: Konstantin Morshnev , Alexandr Petrosian */ -static const char* IDENT_MEMORY_C="$Date: 2003/07/24 11:36:34 $"; - #include "pa_sapi.h" #include "pa_common.h" +#include "pa_threads.h" + +volatile const char * IDENT_PA_MEMORY_C="$Id: pa_memory.C,v 1.22 2024/11/09 17:28:22 moko Exp $" IDENT_PA_MEMORY_H; void *pa_fail_alloc(const char* what, size_t size) { #ifdef PA_DEBUG_DISABLE_GC SAPI::die("out of memory (in pa_fail_alloc)"); #else - SAPI::die("out of memory: failed to %s %u bytes. " - "heap_used=%lu, heap_free=%lu, bytes_since_gc=%lu, total_bytes=%lu", - what, size, - GC_get_heap_size(), - GC_get_free_bytes(), - GC_get_bytes_since_gc(), - GC_get_total_bytes() - ); + SAPI::die("out of memory: failed to %s %u bytes. heap_used=%u, heap_free=%u, bytes_since_gc=%u, total_bytes=%u", + what, size, GC_get_heap_size(), GC_get_free_bytes(), GC_get_bytes_since_gc(), GC_get_total_bytes()); #endif // never reached return 0; } - -#ifdef PA_DEBUG_GC_MEMORY - -const size_t HEADTAIL_SIZE=4; - -static size_t debug_size(size_t user_size) { - return user_size+HEADTAIL_SIZE*2; -} - -const int BEFORE_MARK=0xBEF0BEF0; -const int AFTER_MARK=0xAFEEAFEE; -const char PAD_MARK='\xAD'; - -static void* fill_return_user(void* aptr, size_t pure_size) { - char* ptr=(char*)aptr; - memcpy(ptr, &BEFORE_MARK, HEADTAIL_SIZE); - memcpy(ptr+pure_size-HEADTAIL_SIZE, &AFTER_MARK, HEADTAIL_SIZE); - - // pAD - size_t raw_size=GC_size(aptr); - for(size_t i=pure_size; i=(char*)0x01c357e40 && ptr<=((char*)0x01c357e4+100)) - //printf("valid:0x%p\n", ptr); - - return ptr+HEADTAIL_SIZE; -} -static void* check_return_debug(void* auser_ptr) { - char* user_ptr=(char*)auser_ptr; - char* ptr=user_ptr-HEADTAIL_SIZE; - - size_t raw_size=GC_size(ptr); - assert(raw_size!=0); - - size_t pure_size=raw_size; - while(ptr[pure_size-1]==PAD_MARK) - pure_size--; - - assert(memcmp(ptr, &BEFORE_MARK, HEADTAIL_SIZE)==0); - assert(memcmp(ptr+pure_size-HEADTAIL_SIZE, &AFTER_MARK, HEADTAIL_SIZE)==0); - - return ptr; -} - - -void* pa_gc_malloc(size_t size) { - size=debug_size(size); - return fill_return_user(GC_MALLOC(size), size); -} - -void* pa_gc_malloc_atomic(size_t size) { - size=debug_size(size); - return fill_return_user(GC_MALLOC_ATOMIC(size), size); +#ifdef _MSC_VER +// pa_fail_alloc referenced in function GC_default_on_abort in gc.lib(misc.c) and thus should be extern "C" +extern "C" void *pa_fail_alloc(const char* what); + +void *pa_fail_alloc(const char* what) { + SAPI::die("fatal memory error: %s. heap_used=%u, heap_free=%u, bytes_since_gc=%u, total_bytes=%u", + what, GC_get_heap_size(), GC_get_free_bytes(), GC_get_bytes_since_gc(), GC_get_total_bytes()); + // never reached + return 0; } +#endif -void* pa_gc_realloc(void* user_ptr, size_t size) { - GC_is_visible(user_ptr); +int pa_free_space_divisor = 0; - //printf("realloc: 0x%p -> %u\n", ptr, size); - size=debug_size(size); - return fill_return_user( - GC_realloc( - check_return_debug(user_ptr), - size), - size); -} -void pa_gc_free(void* ptr) { - // ignore free +void pa_gc_collect(bool forced){ +#ifndef PA_DEBUG_DISABLE_GC + int divisor = pa_free_space_divisor; // as it can change during collect in multithreaded enviroment + if(!divisor) GC_enable(); + if(!divisor || forced) GC_gcollect(); + if(!divisor) GC_disable(); +#endif } - +void pa_gc_set_free_space_divisor(int divisor){ +#ifndef PA_DEBUG_DISABLE_GC + if(divisor != pa_free_space_divisor){ + SYNCHRONIZED; + if(pa_free_space_divisor){ + if(!divisor) GC_disable(); + } else { + if(divisor) GC_enable(); + } + if(divisor) + GC_set_free_space_divisor(divisor); + pa_free_space_divisor = divisor; + } #endif +}