diff --git a/jerry-core/mem/mem-heap.cpp b/jerry-core/mem/mem-heap.cpp index 3cc0b3835..edd32d87e 100644 --- a/jerry-core/mem/mem-heap.cpp +++ b/jerry-core/mem/mem-heap.cpp @@ -891,6 +891,65 @@ mem_heap_free_block (void *ptr) /**< pointer to beginning of data space of the b mem_check_heap (); } /* mem_heap_free_block */ +/** + * Find beginning of user data in a block from pointer, + * pointing into it, i.e. into [block_data_space_start; block_data_space_end) range. + * + * Note: + * Pointer must point to the memory region which was previously allocated + * with mem_heap_alloc_block and is currently valid. + * + * Note: + * The interface should only be used for determining where the user space of heap-allocated block begins. + * Caller should never rely on some specific internals of heap implementation. + * + * @return beginning of user data space of block identified by the pointer + */ +void* +mem_heap_get_block_start (void *ptr) /**< pointer into a block */ +{ + mem_check_heap (); + + /* + * PERF: consider introducing bitmap of block beginnings + */ + + JERRY_ASSERT (mem_heap.heap_start <= ptr + && ptr < mem_heap.heap_start + mem_heap.heap_size); + + const mem_block_header_t *block_p = mem_heap.first_block_p; + + /* searching for corresponding block */ + while (block_p != NULL) + { + VALGRIND_DEFINED_STRUCT (block_p); + + const mem_block_header_t *next_block_p = mem_get_next_block_by_direction (block_p, + MEM_DIRECTION_NEXT); + bool is_found = (ptr > block_p + && (ptr < next_block_p + || next_block_p == NULL)); + + if (is_found) + { + JERRY_ASSERT (block_p->magic_num == MEM_MAGIC_NUM_OF_ALLOCATED_BLOCK); + JERRY_ASSERT (block_p + 1 <= ptr); + JERRY_ASSERT (ptr < ((uint8_t*) (block_p + 1) + block_p->allocated_bytes)); + } + + VALGRIND_NOACCESS_STRUCT (block_p); + + if (is_found) + { + return (void*) (block_p + 1); + } + + block_p = next_block_p; + } + + JERRY_UNREACHABLE (); +} /* mem_heap_get_block_start */ + /** * Recommend allocation size based on chunk size. * diff --git a/jerry-core/mem/mem-heap.h b/jerry-core/mem/mem-heap.h index 6dfdcab05..203b147a3 100644 --- a/jerry-core/mem/mem-heap.h +++ b/jerry-core/mem/mem-heap.h @@ -44,6 +44,7 @@ extern void mem_heap_finalize (void); extern void* mem_heap_alloc_block (size_t size_in_bytes, mem_heap_alloc_term_t alloc_term); extern bool mem_heap_try_resize_block (void *ptr, size_t size_in_bytes); extern void mem_heap_free_block (void *ptr); +extern void* mem_heap_get_block_start (void *ptr); extern size_t __attr_pure___ mem_heap_recommend_allocation_size (size_t minimum_allocation_size); extern void mem_heap_print (bool dump_block_headers, bool dump_block_data, bool dump_stats); diff --git a/tests/unit/test_heap.cpp b/tests/unit/test_heap.cpp index 8c92993e0..e26d36eba 100644 --- a/tests/unit/test_heap.cpp +++ b/tests/unit/test_heap.cpp @@ -111,6 +111,9 @@ main (int __attr_unused___ argc, JERRY_ASSERT (size == 0 || ptrs[j] != NULL); memset (ptrs[j], 0, sizes[j]); + + JERRY_ASSERT (ptrs[j] == NULL + || mem_heap_get_block_start (ptrs[j] + (size_t) rand () % sizes [j]) == ptrs[j]); } // mem_heap_print (true); @@ -131,6 +134,9 @@ main (int __attr_unused___ argc, sizes[j] = new_size; memset (ptrs[j], 0, sizes[j]); } + + JERRY_ASSERT (sizes [j] == 0 + || mem_heap_get_block_start (ptrs[j] + (size_t) rand () % sizes [j]) == ptrs[j]); } } @@ -142,7 +148,12 @@ main (int __attr_unused___ argc, { JERRY_ASSERT(ptrs[j][k] == 0); } + + JERRY_ASSERT (sizes [j] == 0 + || mem_heap_get_block_start (ptrs[j] + (size_t) rand () % sizes [j]) == ptrs[j]); + mem_heap_free_block (ptrs[j]); + ptrs[j] = NULL; } }