Skip to content

Commit c537b83

Browse files
Speeding up procedure for getting start of a heap block's data space for one-chunked blocks, removing general blocks support from the procedure.
- heap area is aligned on heap chunk size; - mem_heap_get_block_start is renamed to mem_heap_get_chunked_block_start, now this interface is applicable only to one-chunked blocks, and is significantly faster - instead of iterating list of heap blocks to find block header, it just aligns value of pointer to heap chunk size. JerryScript-DCO-1.0-Signed-off-by: Ruben Ayrapetyan r.ayrapetyan@samsung.com
1 parent 99ecdd4 commit c537b83

File tree

4 files changed

+77
-39
lines changed

4 files changed

+77
-39
lines changed

jerry-core/mem/mem-allocator.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,8 @@
3030
/**
3131
* Area for heap
3232
*/
33-
static uint8_t mem_heap_area[ MEM_HEAP_AREA_SIZE ] __attribute__ ((aligned (MEM_ALIGNMENT)));
33+
static uint8_t mem_heap_area[ MEM_HEAP_AREA_SIZE ] __attribute__ ((aligned (JERRY_MAX (MEM_ALIGNMENT,
34+
MEM_HEAP_CHUNK_SIZE))));
3435

3536
/**
3637
* The 'try to give memory back' callback

jerry-core/mem/mem-heap.cpp

Lines changed: 43 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -396,15 +396,22 @@ mem_is_block_free (const mem_block_header_t *block_header_p) /**< block header *
396396

397397
/**
398398
* Startup initialization of heap
399+
*
400+
* Note:
401+
* heap start and size should be aligned on MEM_HEAP_CHUNK_SIZE
399402
*/
400403
void
401404
mem_heap_init (uint8_t *heap_start, /**< first address of heap space */
402405
size_t heap_size) /**< heap space size */
403406
{
404407
JERRY_ASSERT (heap_start != NULL);
405408
JERRY_ASSERT (heap_size != 0);
406-
JERRY_ASSERT (heap_size % MEM_HEAP_CHUNK_SIZE == 0);
409+
410+
JERRY_STATIC_ASSERT ((MEM_HEAP_CHUNK_SIZE & (MEM_HEAP_CHUNK_SIZE - 1u)) == 0);
407411
JERRY_ASSERT ((uintptr_t) heap_start % MEM_ALIGNMENT == 0);
412+
JERRY_ASSERT ((uintptr_t) heap_start % MEM_HEAP_CHUNK_SIZE == 0);
413+
JERRY_ASSERT (heap_size % MEM_HEAP_CHUNK_SIZE == 0);
414+
408415
JERRY_ASSERT (heap_size <= (1u << MEM_HEAP_OFFSET_LOG));
409416

410417
mem_heap.heap_start = heap_start;
@@ -800,6 +807,7 @@ mem_heap_free_block (void *ptr) /**< pointer to beginning of data space of the b
800807

801808
/* marking the block free */
802809
block_p->allocated_bytes = 0;
810+
block_p->length_type = mem_block_length_type_t::GENERAL;
803811

804812
if (next_block_p != NULL)
805813
{
@@ -866,12 +874,12 @@ mem_heap_free_block (void *ptr) /**< pointer to beginning of data space of the b
866874
} /* mem_heap_free_block */
867875

868876
/**
869-
* Find beginning of user data in a block from pointer,
877+
* Find beginning of user data in a one-chunked block from pointer,
870878
* pointing into it, i.e. into [block_data_space_start; block_data_space_end) range.
871879
*
872880
* Note:
873-
* Pointer must point to the memory region which was previously allocated
874-
* with mem_heap_alloc_block and is currently valid.
881+
* Pointer must point to the one-chunked memory region which was previously allocated
882+
* with mem_heap_alloc_chunked_block and is currently valid.
875883
*
876884
* Note:
877885
* The interface should only be used for determining where the user space of heap-allocated block begins.
@@ -880,49 +888,59 @@ mem_heap_free_block (void *ptr) /**< pointer to beginning of data space of the b
880888
* @return beginning of user data space of block identified by the pointer
881889
*/
882890
void*
883-
mem_heap_get_block_start (void *ptr) /**< pointer into a block */
891+
mem_heap_get_chunked_block_start (void *ptr) /**< pointer into a block */
884892
{
885-
mem_check_heap ();
886-
887-
/*
888-
* PERF: consider introducing bitmap of block beginnings
889-
*/
893+
JERRY_STATIC_ASSERT ((MEM_HEAP_CHUNK_SIZE & (MEM_HEAP_CHUNK_SIZE - 1u)) == 0);
894+
JERRY_ASSERT (((uintptr_t) mem_heap.heap_start % MEM_HEAP_CHUNK_SIZE) == 0);
890895

891896
JERRY_ASSERT (mem_heap.heap_start <= ptr
892897
&& ptr < mem_heap.heap_start + mem_heap.heap_size);
893898

894-
const mem_block_header_t *block_p = mem_heap.first_block_p;
899+
uintptr_t uintptr = (uintptr_t) ptr;
900+
uintptr_t uintptr_chunk_aligned = JERRY_ALIGNDOWN (uintptr, MEM_HEAP_CHUNK_SIZE);
901+
902+
JERRY_ASSERT (uintptr > uintptr_chunk_aligned);
903+
904+
mem_block_header_t *block_p = (mem_block_header_t *) uintptr_chunk_aligned;
905+
JERRY_ASSERT (block_p->length_type == mem_block_length_type_t::ONE_CHUNKED);
906+
907+
#ifndef JERRY_NDEBUG
908+
const mem_block_header_t *block_iter_p = mem_heap.first_block_p;
909+
bool is_found = false;
895910

896911
/* searching for corresponding block */
897-
while (block_p != NULL)
912+
while (block_iter_p != NULL)
898913
{
899-
VALGRIND_DEFINED_STRUCT (block_p);
914+
VALGRIND_DEFINED_STRUCT (block_iter_p);
900915

901-
const mem_block_header_t *next_block_p = mem_get_next_block_by_direction (block_p,
916+
const mem_block_header_t *next_block_p = mem_get_next_block_by_direction (block_iter_p,
902917
MEM_DIRECTION_NEXT);
903-
bool is_found = (ptr > block_p
904-
&& (ptr < next_block_p
905-
|| next_block_p == NULL));
918+
is_found = (ptr > block_iter_p
919+
&& (ptr < next_block_p
920+
|| next_block_p == NULL));
906921

907922
if (is_found)
908923
{
909-
JERRY_ASSERT (!mem_is_block_free (block_p));
910-
JERRY_ASSERT (block_p + 1 <= ptr);
911-
JERRY_ASSERT (ptr < ((uint8_t*) (block_p + 1) + block_p->allocated_bytes));
924+
JERRY_ASSERT (!mem_is_block_free (block_iter_p));
925+
JERRY_ASSERT (block_iter_p + 1 <= ptr);
926+
JERRY_ASSERT (ptr < ((uint8_t*) (block_iter_p + 1) + block_iter_p->allocated_bytes));
912927
}
913928

914-
VALGRIND_NOACCESS_STRUCT (block_p);
929+
VALGRIND_NOACCESS_STRUCT (block_iter_p);
915930

916931
if (is_found)
917932
{
918-
return (void*) (block_p + 1);
933+
break;
919934
}
920935

921-
block_p = next_block_p;
936+
block_iter_p = next_block_p;
922937
}
923938

924-
JERRY_UNREACHABLE ();
925-
} /* mem_heap_get_block_start */
939+
JERRY_ASSERT (is_found && block_p == block_iter_p);
940+
#endif /* !JERRY_NDEBUG */
941+
942+
return (void*) (block_p + 1);
943+
} /* mem_heap_get_chunked_block_start */
926944

927945
/**
928946
* Get size of one-chunked block data space

jerry-core/mem/mem-heap.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ extern void mem_heap_finalize (void);
4444
extern void* mem_heap_alloc_block (size_t size_in_bytes, mem_heap_alloc_term_t alloc_term);
4545
extern void* mem_heap_alloc_chunked_block (mem_heap_alloc_term_t alloc_term);
4646
extern void mem_heap_free_block (void *ptr);
47-
extern void* mem_heap_get_block_start (void *ptr);
47+
extern void* mem_heap_get_chunked_block_start (void *ptr);
4848
extern size_t mem_heap_get_chunked_block_data_size (void);
4949
extern size_t __attr_pure___ mem_heap_recommend_allocation_size (size_t minimum_allocation_size);
5050
extern void mem_heap_print (bool dump_block_headers, bool dump_block_data, bool dump_stats);

tests/unit/test_heap.cpp

Lines changed: 31 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ extern "C"
3939

4040
uint8_t *ptrs[test_sub_iters];
4141
size_t sizes[test_sub_iters];
42+
bool is_one_chunked[test_sub_iters];
4243

4344
static void
4445
test_heap_give_some_memory_back (mem_try_give_memory_back_severity_t severity)
@@ -82,12 +83,13 @@ test_heap_give_some_memory_back (mem_try_give_memory_back_severity_t severity)
8283
}
8384
} /* test_heap_give_some_memory_back */
8485

86+
uint8_t test_native_heap[test_heap_size] __attribute__ ((aligned (JERRY_MAX (MEM_ALIGNMENT,
87+
MEM_HEAP_CHUNK_SIZE))));
88+
8589
int
8690
main (int __attr_unused___ argc,
8791
char __attr_unused___ **argv)
8892
{
89-
uint8_t test_native_heap[test_heap_size];
90-
9193
mem_heap_init (test_native_heap, sizeof (test_native_heap));
9294

9395
srand ((unsigned int) time (NULL));
@@ -103,17 +105,31 @@ main (int __attr_unused___ argc,
103105
{
104106
for (uint32_t j = 0; j < test_sub_iters; j++)
105107
{
106-
size_t size = (size_t) rand () % test_threshold_block_size;
107-
ptrs[j] = (uint8_t*) mem_heap_alloc_block (size,
108-
(rand () % 2) ?
109-
MEM_HEAP_ALLOC_LONG_TERM : MEM_HEAP_ALLOC_SHORT_TERM);
110-
sizes[j] = size;
108+
if (rand () % 2)
109+
{
110+
size_t size = (size_t) rand () % test_threshold_block_size;
111+
ptrs[j] = (uint8_t*) mem_heap_alloc_block (size,
112+
(rand () % 2) ?
113+
MEM_HEAP_ALLOC_LONG_TERM : MEM_HEAP_ALLOC_SHORT_TERM);
114+
sizes[j] = size;
115+
is_one_chunked[j] = false;
116+
}
117+
else
118+
{
119+
ptrs[j] = (uint8_t*) mem_heap_alloc_chunked_block ((rand () % 2) ?
120+
MEM_HEAP_ALLOC_LONG_TERM : MEM_HEAP_ALLOC_SHORT_TERM);
121+
sizes[j] = mem_heap_get_chunked_block_data_size ();
122+
is_one_chunked[j] = true;
123+
}
111124

112-
JERRY_ASSERT (size == 0 || ptrs[j] != NULL);
125+
JERRY_ASSERT (sizes[j] == 0 || ptrs[j] != NULL);
113126
memset (ptrs[j], 0, sizes[j]);
114127

115-
JERRY_ASSERT (ptrs[j] == NULL
116-
|| mem_heap_get_block_start (ptrs[j] + (size_t) rand () % sizes[j]) == ptrs[j]);
128+
if (is_one_chunked[j])
129+
{
130+
JERRY_ASSERT (ptrs[j] != NULL
131+
&& mem_heap_get_chunked_block_start (ptrs[j] + (size_t) rand () % sizes[j]) == ptrs[j]);
132+
}
117133
}
118134

119135
// mem_heap_print (true);
@@ -127,8 +143,11 @@ main (int __attr_unused___ argc,
127143
JERRY_ASSERT (ptrs[j][k] == 0);
128144
}
129145

130-
JERRY_ASSERT (sizes[j] == 0
131-
|| mem_heap_get_block_start (ptrs[j] + (size_t) rand () % sizes[j]) == ptrs[j]);
146+
if (is_one_chunked[j])
147+
{
148+
JERRY_ASSERT (sizes[j] == 0
149+
|| mem_heap_get_chunked_block_start (ptrs[j] + (size_t) rand () % sizes[j]) == ptrs[j]);
150+
}
132151

133152
mem_heap_free_block (ptrs[j]);
134153

0 commit comments

Comments
 (0)