Skip to content

Commit 2e16019

Browse files
committed
More gc-friendly property hashmap allocation.
- New allocator is added that returns null on out of memory, property hasmap create uses this allocator for now. - Property hashmaps of objects are removed durring a high severity gc. Follow up patch is in progress. JerryScript-DCO-1.0-Signed-off-by: István Kádár ikadar@inf.u-szeged.hu
1 parent 9bce5b0 commit 2e16019

File tree

7 files changed

+80
-12
lines changed

7 files changed

+80
-12
lines changed

jerry-core/ecma/base/ecma-gc.c

Lines changed: 23 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -506,7 +506,7 @@ ecma_gc_sweep (ecma_object_t *object_p) /**< object to free */
506506
* Run garbage collection
507507
*/
508508
void
509-
ecma_gc_run (void)
509+
ecma_gc_run (jmem_free_unused_memory_severity_t severity) /**< gc severity */
510510
{
511511
ecma_gc_new_objects_since_last_gc = 0;
512512

@@ -577,6 +577,26 @@ ecma_gc_run (void)
577577
ecma_gc_sweep (obj_iter_p);
578578
}
579579

580+
if (severity == JMEM_FREE_UNUSED_MEMORY_SEVERITY_HIGH)
581+
{
582+
/* Remove the property hashmap of BLACK objects */
583+
for (ecma_object_t *obj_iter_p = ecma_gc_objects_lists[ECMA_GC_COLOR_BLACK], *obj_next_p;
584+
obj_iter_p != NULL;
585+
obj_iter_p = obj_next_p)
586+
{
587+
obj_next_p = ecma_gc_get_object_next (obj_iter_p);
588+
589+
JERRY_ASSERT (ecma_gc_is_object_visited (obj_iter_p));
590+
591+
ecma_property_header_t *prop_iter_p = ecma_get_property_list (obj_iter_p);
592+
if (prop_iter_p != NULL
593+
&& ECMA_PROPERTY_GET_TYPE (prop_iter_p->types + 0) == ECMA_PROPERTY_TYPE_HASHMAP)
594+
{
595+
ecma_property_hashmap_free (obj_iter_p);
596+
}
597+
}
598+
}
599+
580600
/* Unmarking all objects */
581601
ecma_gc_objects_lists[ECMA_GC_COLOR_WHITE_GRAY] = ecma_gc_objects_lists[ECMA_GC_COLOR_BLACK];
582602
ecma_gc_objects_lists[ECMA_GC_COLOR_BLACK] = NULL;
@@ -603,15 +623,15 @@ ecma_free_unused_memory (jmem_free_unused_memory_severity_t severity) /**< sever
603623
*/
604624
if (ecma_gc_new_objects_since_last_gc * CONFIG_ECMA_GC_NEW_OBJECTS_SHARE_TO_START_GC > ecma_gc_objects_number)
605625
{
606-
ecma_gc_run ();
626+
ecma_gc_run (severity);
607627
}
608628
}
609629
else
610630
{
611631
JERRY_ASSERT (severity == JMEM_FREE_UNUSED_MEMORY_SEVERITY_HIGH);
612632

613633
/* Freeing as much memory as we currently can */
614-
ecma_gc_run ();
634+
ecma_gc_run (severity);
615635
}
616636
} /* ecma_free_unused_memory */
617637

jerry-core/ecma/base/ecma-gc.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ extern void ecma_gc_init (void);
3030
extern void ecma_init_gc_info (ecma_object_t *);
3131
extern void ecma_ref_object (ecma_object_t *);
3232
extern void ecma_deref_object (ecma_object_t *);
33-
extern void ecma_gc_run (void);
33+
extern void ecma_gc_run (jmem_free_unused_memory_severity_t);
3434
extern void ecma_free_unused_memory (jmem_free_unused_memory_severity_t);
3535

3636
/**

jerry-core/ecma/base/ecma-init-finalize.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ ecma_finalize (void)
5454

5555
ecma_finalize_environment ();
5656
ecma_finalize_builtins ();
57-
ecma_gc_run ();
57+
ecma_gc_run (JMEM_FREE_UNUSED_MEMORY_SEVERITY_LOW);
5858
ecma_finalize_lit_storage ();
5959
} /* ecma_finalize */
6060

jerry-core/ecma/base/ecma-property-hashmap.c

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -110,7 +110,12 @@ ecma_property_hashmap_create (ecma_object_t *object_p) /**< object */
110110

111111
size_t total_size = ECMA_PROPERTY_HASHMAP_GET_TOTAL_SIZE (max_property_count);
112112

113-
ecma_property_hashmap_t *hashmap_p = (ecma_property_hashmap_t *) jmem_heap_alloc_block (total_size);
113+
ecma_property_hashmap_t *hashmap_p = (ecma_property_hashmap_t *) jmem_heap_alloc_block_null_on_error (total_size);
114+
if (hashmap_p == NULL)
115+
{
116+
return;
117+
}
118+
114119
memset (hashmap_p, 0, total_size);
115120

116121
hashmap_p->header.types[0].type_and_flags = ECMA_PROPERTY_TYPE_HASHMAP;

jerry-core/jerry.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -229,7 +229,7 @@ jerry_gc (void)
229229
{
230230
jerry_assert_api_available ();
231231

232-
ecma_gc_run ();
232+
ecma_gc_run (JMEM_FREE_UNUSED_MEMORY_SEVERITY_LOW);
233233
} /* jerry_gc */
234234

235235
/**

jerry-core/jmem/jmem-heap.c

Lines changed: 47 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -364,12 +364,17 @@ void *jmem_heap_alloc_block_internal (const size_t size)
364364
* Allocation of memory block, running 'try to give memory back' callbacks, if there is not enough memory.
365365
*
366366
* Note:
367-
* if after running the callbacks, there is still not enough memory, engine is terminated with ERR_OUT_OF_MEMORY.
367+
* if there is still not enough memory after running the callbacks
368+
* - NULL value will be returned if parmeter 'ret_null_on_error' is true
369+
* - the engine will terminate with ERR_OUT_OF_MEMORY if 'ret_null_on_error' is false
368370
*
369-
* @return pointer to allocated memory block
371+
* @return NULL, if the required memory size is 0
372+
* also NULL, if 'ret_null_on_error' is true and the allocation fails because of there is not enough memory
370373
*/
371-
void * __attribute__((hot))
372-
jmem_heap_alloc_block (const size_t size)
374+
static void *
375+
jmem_heap_gc_and_alloc_block (const size_t size, /**< required memory size */
376+
bool ret_null_on_error) /**< indicates whether return null or terminate
377+
with ERR_OUT_OF_MEMORY on out of memory */
373378
{
374379
if (unlikely (size == 0))
375380
{
@@ -412,9 +417,46 @@ jmem_heap_alloc_block (const size_t size)
412417

413418
JERRY_ASSERT (data_space_p == NULL);
414419

415-
jerry_fatal (ERR_OUT_OF_MEMORY);
420+
if (!ret_null_on_error)
421+
{
422+
jerry_fatal (ERR_OUT_OF_MEMORY);
423+
}
424+
425+
return data_space_p;
426+
} /* jmem_heap_gc_and_alloc_block */
427+
428+
/**
429+
* Allocation of memory block, running 'try to give memory back' callbacks, if there is not enough memory.
430+
*
431+
* Note:
432+
* If there is still not enough memory after running the callbacks, then the engine will be
433+
* terminated with ERR_OUT_OF_MEMORY.
434+
*
435+
* @return NULL, if the required memory is 0
436+
* pointer to allocated memory block, otherwise
437+
*/
438+
void * __attribute__((hot)) __attr_always_inline___
439+
jmem_heap_alloc_block (const size_t size) /**< required memory size */
440+
{
441+
return jmem_heap_gc_and_alloc_block (size, false);
416442
} /* jmem_heap_alloc_block */
417443

444+
/**
445+
* Allocation of memory block, running 'try to give memory back' callbacks, if there is not enough memory.
446+
*
447+
* Note:
448+
* If there is still not enough memory after running the callbacks, NULL will be returned.
449+
*
450+
* @return NULL, if the required memory size is 0
451+
* also NULL, if the allocation has failed
452+
* pointer to the allocated memory block, otherwise
453+
*/
454+
void * __attribute__((hot)) __attr_always_inline___
455+
jmem_heap_alloc_block_null_on_error (const size_t size) /**< required memory size */
456+
{
457+
return jmem_heap_gc_and_alloc_block (size, true);
458+
} /* jmem_heap_alloc_block_null_on_error */
459+
418460
/**
419461
* Allocate block and store block size.
420462
*

jerry-core/jmem/jmem-heap.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
extern void jmem_heap_init (void);
3333
extern void jmem_heap_finalize (void);
3434
extern void *jmem_heap_alloc_block (const size_t);
35+
extern void *jmem_heap_alloc_block_null_on_error (const size_t);
3536
extern void jmem_heap_free_block (void *, const size_t);
3637
extern void *jmem_heap_alloc_block_store_size (size_t);
3738
extern void jmem_heap_free_block_size_stored (void *);

0 commit comments

Comments
 (0)