diff --git a/CMakeLists.txt b/CMakeLists.txt index 3cc1bb83c..39203a85b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -58,9 +58,10 @@ project (Jerry CXX C ASM) set(CMAKE_SHARED_LIBRARY_LINK_CXX_FLAGS ) # Defining options - option(ENABLE_VALGRIND "Enable valgrind helpers in memory allocators" OFF) - option(ENABLE_LTO "Enable LTO build" ON) - option(ENABLE_LOG "Enable LOG build" OFF) + option(ENABLE_VALGRIND "Enable valgrind helpers in memory allocators" OFF) + option(ENABLE_VALGRIND_FREYA "Enable valgrind-freya helpers in memory allocators" OFF) + option(ENABLE_LTO "Enable LTO build" ON) + option(ENABLE_LOG "Enable LOG build" OFF) if("${PLATFORM}" STREQUAL "LINUX") set(PLATFORM_EXT "LINUX") diff --git a/Makefile b/Makefile index 575d1a438..45dacff7c 100644 --- a/Makefile +++ b/Makefile @@ -49,6 +49,13 @@ VALGRIND := OFF endif + # Valgrind Freya + VALGRIND_FREYA ?= OFF + + ifneq ($(VALGRIND_FREYA),ON) + VALGRIND_FREYA := OFF + endif + # Static checkers STATIC_CHECK ?= OFF @@ -132,10 +139,11 @@ export SHELL=/bin/bash # Building all options combinations OPTIONS_COMBINATIONS := $(foreach __OPTION,ON OFF,$(__COMBINATION)-VALGRIND-$(__OPTION)) + OPTIONS_COMBINATIONS := $(foreach __COMBINATION,$(OPTIONS_COMBINATIONS),$(foreach __OPTION,ON OFF,$(__COMBINATION)-VALGRIND_FREYA-$(__OPTION))) OPTIONS_COMBINATIONS := $(foreach __COMBINATION,$(OPTIONS_COMBINATIONS),$(foreach __OPTION,ON OFF,$(__COMBINATION)-LTO-$(__OPTION))) # Building current options string - OPTIONS_STRING := -VALGRIND-$(VALGRIND)-LTO-$(LTO) + OPTIONS_STRING := -VALGRIND-$(VALGRIND)-VALGRIND_FREYA-$(VALGRIND_FREYA)-LTO-$(LTO) # Build directories BUILD_DIR_PREFIX := ./build/obj @@ -179,6 +187,7 @@ $(BUILD_DIRS_NATIVE): $(Q) cd $@ && \ (cmake \ -DENABLE_VALGRIND=$(VALGRIND) \ + -DENABLE_VALGRIND_FREYA=$(VALGRIND_FREYA) \ -DENABLE_LOG=$(LOG) \ -DENABLE_LTO=$(LTO) \ -DUSE_COMPILER_DEFAULT_LIBC=$(USE_COMPILER_DEFAULT_LIBC) \ @@ -189,14 +198,14 @@ $(BUILD_DIRS_NATIVE): $(BUILD_DIRS_STM32F3): prerequisites $(Q) mkdir -p $@ $(Q) cd $@ && \ - (cmake -DENABLE_VALGRIND=$(VALGRIND) -DENABLE_LTO=$(LTO) -DCMAKE_TOOLCHAIN_FILE=build/configs/toolchain_mcu_stm32f3.cmake ../../.. 2>&1 | tee cmake.log $(QLOG) ; ( exit $${PIPESTATUS[0]} ) ) || \ + (cmake -DENABLE_VALGRIND=$(VALGRIND) -DENABLE_VALGRIND_FREYA=$(VALGRIND_FREYA) -DENABLE_LTO=$(LTO) -DCMAKE_TOOLCHAIN_FILE=build/configs/toolchain_mcu_stm32f3.cmake ../../.. 2>&1 | tee cmake.log $(QLOG) ; ( exit $${PIPESTATUS[0]} ) ) || \ (echo "CMake run failed. See "`pwd`"/cmake.log for details."; exit 1;) .PHONY: $(BUILD_DIRS_STM32F4) $(BUILD_DIRS_STM32F4): prerequisites $(Q) mkdir -p $@ $(Q) cd $@ && \ - (cmake -DENABLE_VALGRIND=$(VALGRIND) -DENABLE_LTO=$(LTO) -DCMAKE_TOOLCHAIN_FILE=build/configs/toolchain_mcu_stm32f4.cmake ../../.. 2>&1 | tee cmake.log $(QLOG) ; ( exit $${PIPESTATUS[0]} ) ) || \ + (cmake -DENABLE_VALGRIND=$(VALGRIND) -DENABLE_VALGRIND_FREYA=$(VALGRIND_FREYA) -DENABLE_LTO=$(LTO) -DCMAKE_TOOLCHAIN_FILE=build/configs/toolchain_mcu_stm32f4.cmake ../../.. 2>&1 | tee cmake.log $(QLOG) ; ( exit $${PIPESTATUS[0]} ) ) || \ (echo "CMake run failed. See "`pwd`"/cmake.log for details."; exit 1;) .PHONY: $(JERRY_NATIVE_TARGETS) diff --git a/jerry-core/CMakeLists.txt b/jerry-core/CMakeLists.txt index 3699c1468..599b08e39 100644 --- a/jerry-core/CMakeLists.txt +++ b/jerry-core/CMakeLists.txt @@ -81,6 +81,9 @@ project (JerryCore CXX C ASM) # Valgrind set(DEFINES_JERRY_VALGRIND JERRY_VALGRIND) + # Valgrind Freya + set(DEFINES_JERRY_VALGRIND_FREYA JERRY_VALGRIND_FREYA) + # Platform-specific # Linux @@ -154,6 +157,12 @@ project (JerryCore CXX C ASM) set(INCLUDE_CORE ${INCLUDE_CORE} ${INCLUDE_THIRD_PARTY_VALGRIND}) endif() + # Valgrind Freya + if("${ENABLE_VALGRIND_FREYA}" STREQUAL "ON") + set(DEFINES_JERRY ${DEFINES_JERRY} ${DEFINES_JERRY_VALGRIND_FREYA}) + set(INCLUDE_CORE ${INCLUDE_CORE} ${INCLUDE_THIRD_PARTY_VALGRIND}) + endif() + # Log if("${ENABLE_LOG}" STREQUAL "ON") set(DEFINES_JERRY ${DEFINES_JERRY} JERRY_ENABLE_LOG) diff --git a/jerry-core/mem/mem-heap.cpp b/jerry-core/mem/mem-heap.cpp index 8e6c61e1e..d778db331 100644 --- a/jerry-core/mem/mem-heap.cpp +++ b/jerry-core/mem/mem-heap.cpp @@ -41,15 +41,54 @@ #ifdef JERRY_VALGRIND # include "memcheck.h" -# define VALGRIND_NOACCESS_SPACE(p, s) (void)VALGRIND_MAKE_MEM_NOACCESS((p), (s)) -# define VALGRIND_UNDEFINED_SPACE(p, s) (void)VALGRIND_MAKE_MEM_UNDEFINED((p), (s)) -# define VALGRIND_DEFINED_SPACE(p, s) (void)VALGRIND_MAKE_MEM_DEFINED((p), (s)) +# define VALGRIND_NOACCESS_SPACE(p, s) VALGRIND_MAKE_MEM_NOACCESS((p), (s)) +# define VALGRIND_UNDEFINED_SPACE(p, s) VALGRIND_MAKE_MEM_UNDEFINED((p), (s)) +# define VALGRIND_DEFINED_SPACE(p, s) VALGRIND_MAKE_MEM_DEFINED((p), (s)) + #else /* JERRY_VALGRIND */ # define VALGRIND_NOACCESS_SPACE(p, s) # define VALGRIND_UNDEFINED_SPACE(p, s) # define VALGRIND_DEFINED_SPACE(p, s) #endif /* JERRY_VALGRIND */ +#ifdef JERRY_VALGRIND_FREYA +# include "memcheck.h" + +/** + * Tells whether a pool manager allocator request is in progress. + */ +static bool valgrind_freya_mempool_request = false; + +/** + * Called by pool manager before a heap allocation or free. + */ +void mem_heap_valgrind_freya_mempool_request (void) +{ + valgrind_freya_mempool_request = true; +} /* mem_heap_valgrind_freya_mempool_request */ + +# define VALGRIND_FREYA_CHECK_MEMPOOL_REQUEST \ + bool mempool_request = valgrind_freya_mempool_request; \ + valgrind_freya_mempool_request = false + +# define VALGRIND_FREYA_MALLOCLIKE_SPACE(p, s) \ + if (!mempool_request) \ + { \ + VALGRIND_MALLOCLIKE_BLOCK((p), (s), 0, 0); \ + } + +# define VALGRIND_FREYA_FREELIKE_SPACE(p) \ + if (!mempool_request) \ + { \ + VALGRIND_FREELIKE_BLOCK((p), 0); \ + } + +#else /* JERRY_VALGRIND_FREYA */ +# define VALGRIND_FREYA_CHECK_MEMPOOL_REQUEST +# define VALGRIND_FREYA_MALLOCLIKE_SPACE(p, s) +# define VALGRIND_FREYA_FREELIKE_SPACE(p) +#endif /* JERRY_VALGRIND_FREYA */ + /** * Length type of the block */ @@ -489,6 +528,8 @@ mem_heap_alloc_block_try_give_memory_back (size_t size_in_bytes, /**< size of re * (one-chunked or general) */ mem_heap_alloc_term_t alloc_term) /**< expected allocation term */ { + VALGRIND_FREYA_CHECK_MEMPOOL_REQUEST; + #ifdef MEM_GC_BEFORE_EACH_ALLOC mem_run_try_to_give_memory_back_callbacks (MEM_TRY_GIVE_MEMORY_BACK_SEVERITY_CRITICAL); #endif /* MEM_GC_BEFORE_EACH_ALLOC */ @@ -503,6 +544,7 @@ mem_heap_alloc_block_try_give_memory_back (size_t size_in_bytes, /**< size of re if (likely (data_space_p != NULL)) { + VALGRIND_FREYA_MALLOCLIKE_SPACE (data_space_p, size_in_bytes); return data_space_p; } @@ -516,6 +558,7 @@ mem_heap_alloc_block_try_give_memory_back (size_t size_in_bytes, /**< size of re if (data_space_p != NULL) { + VALGRIND_FREYA_MALLOCLIKE_SPACE (data_space_p, size_in_bytes); return data_space_p; } } @@ -580,6 +623,8 @@ mem_heap_alloc_chunked_block (mem_heap_alloc_term_t alloc_term) /**< expected al void mem_heap_free_block (void *ptr) /**< pointer to beginning of data space of the block */ { + VALGRIND_FREYA_CHECK_MEMPOOL_REQUEST; + uint8_t *uint8_ptr = (uint8_t*) ptr; /* checking that uint8_ptr points to the heap */ @@ -661,6 +706,7 @@ mem_heap_free_block (void *ptr) /**< pointer to beginning of data space of the b VALGRIND_CHECK_MEM_IS_ADDRESSABLE (ptr, mem_heap_allocated_bytes[chunk_index]); #endif /* JERRY_VALGRIND */ + VALGRIND_FREYA_FREELIKE_SPACE (ptr); VALGRIND_NOACCESS_SPACE (ptr, chunks * MEM_HEAP_CHUNK_SIZE); JERRY_ASSERT (mem_heap_allocated_chunks >= chunks); diff --git a/jerry-core/mem/mem-heap.h b/jerry-core/mem/mem-heap.h index 5715e3e66..72c67dfce 100644 --- a/jerry-core/mem/mem-heap.h +++ b/jerry-core/mem/mem-heap.h @@ -83,6 +83,22 @@ extern void mem_heap_get_stats (mem_heap_stats_t *); extern void mem_heap_stats_reset_peak (void); #endif /* MEM_STATS */ +#ifdef JERRY_VALGRIND_FREYA + +#ifdef JERRY_VALGRIND +#error Valgrind and valgrind-freya modes are not compatible. +#endif + +extern void mem_heap_valgrind_freya_mempool_request (void); + +#define MEM_HEAP_VALGRIND_FREYA_MEMPOOL_REQUEST() mem_heap_valgrind_freya_mempool_request () + +#else /* JERRY_VALGRIND_FREYA */ + +#define MEM_HEAP_VALGRIND_FREYA_MEMPOOL_REQUEST() + +#endif /* JERRY_VALGRIND_FREYA */ + /** * Define a local array variable and allocate memory for the array on the heap. * diff --git a/jerry-core/mem/mem-poolman.cpp b/jerry-core/mem/mem-poolman.cpp index 96ff7ed29..239cbfa87 100644 --- a/jerry-core/mem/mem-poolman.cpp +++ b/jerry-core/mem/mem-poolman.cpp @@ -136,15 +136,25 @@ static void mem_pools_stat_free_chunk (void); #ifdef JERRY_VALGRIND # include "memcheck.h" -# define VALGRIND_NOACCESS_SPACE(p, s) (void)VALGRIND_MAKE_MEM_NOACCESS((p), (s)) -# define VALGRIND_UNDEFINED_SPACE(p, s) (void)VALGRIND_MAKE_MEM_UNDEFINED((p), (s)) -# define VALGRIND_DEFINED_SPACE(p, s) (void)VALGRIND_MAKE_MEM_DEFINED((p), (s)) +# define VALGRIND_NOACCESS_SPACE(p, s) VALGRIND_MAKE_MEM_NOACCESS((p), (s)) +# define VALGRIND_UNDEFINED_SPACE(p, s) VALGRIND_MAKE_MEM_UNDEFINED((p), (s)) +# define VALGRIND_DEFINED_SPACE(p, s) VALGRIND_MAKE_MEM_DEFINED((p), (s)) #else /* JERRY_VALGRIND */ # define VALGRIND_NOACCESS_SPACE(p, s) # define VALGRIND_UNDEFINED_SPACE(p, s) # define VALGRIND_DEFINED_SPACE(p, s) #endif /* JERRY_VALGRIND */ +#ifdef JERRY_VALGRIND_FREYA +# include "memcheck.h" + +# define VALGRIND_FREYA_MALLOCLIKE_SPACE(p, s) VALGRIND_MALLOCLIKE_BLOCK((p), (s), 0, 0) +# define VALGRIND_FREYA_FREELIKE_SPACE(p) VALGRIND_FREELIKE_BLOCK((p), 0) +#else /* JERRY_VALGRIND_FREYA */ +# define VALGRIND_FREYA_MALLOCLIKE_SPACE(p, s) +# define VALGRIND_FREYA_FREELIKE_SPACE(p) +#endif /* JERRY_VALGRIND_FREYA */ + /** * Initialize pool manager */ @@ -391,6 +401,7 @@ mem_pools_collect_empty (void) mem_free_chunks_number -= MEM_POOL_CHUNKS_NUMBER; #endif /* !JERRY_NDEBUG */ + MEM_HEAP_VALGRIND_FREYA_MEMPOOL_REQUEST (); mem_heap_free_block (pool_list_iter_p); MEM_POOLS_STAT_FREE_POOL (); @@ -455,11 +466,13 @@ mem_pools_alloc_longpath (void) JERRY_ASSERT (MEM_POOL_SIZE <= mem_heap_get_chunked_block_data_size ()); JERRY_ASSERT (MEM_POOL_CHUNKS_NUMBER >= 1); + MEM_HEAP_VALGRIND_FREYA_MEMPOOL_REQUEST (); mem_pool_chunk_t *pool_start_p = (mem_pool_chunk_t*) mem_heap_alloc_chunked_block (MEM_HEAP_ALLOC_LONG_TERM); if (mem_free_chunk_p != NULL) { /* some chunks were freed due to GC invoked by heap allocator */ + MEM_HEAP_VALGRIND_FREYA_MEMPOOL_REQUEST (); mem_heap_free_block (pool_start_p); return; @@ -549,6 +562,7 @@ mem_pools_alloc (void) mem_check_pools (); + VALGRIND_FREYA_MALLOCLIKE_SPACE (chunk_p, MEM_POOL_CHUNK_SIZE); return (uint8_t *) chunk_p; } else @@ -574,6 +588,7 @@ mem_pools_free (uint8_t *chunk_p) /**< pointer to the chunk */ chunk_to_free_p->u.free.next_p = mem_free_chunk_p; mem_free_chunk_p = chunk_to_free_p; + VALGRIND_FREYA_FREELIKE_SPACE (chunk_to_free_p); VALGRIND_NOACCESS_SPACE (chunk_to_free_p, MEM_POOL_CHUNK_SIZE); #ifndef JERRY_NDEBUG