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
This commit is contained in:
@@ -506,7 +506,7 @@ ecma_gc_sweep (ecma_object_t *object_p) /**< object to free */
|
||||
* Run garbage collection
|
||||
*/
|
||||
void
|
||||
ecma_gc_run (void)
|
||||
ecma_gc_run (jmem_free_unused_memory_severity_t severity) /**< gc severity */
|
||||
{
|
||||
ecma_gc_new_objects_since_last_gc = 0;
|
||||
|
||||
@@ -577,6 +577,26 @@ ecma_gc_run (void)
|
||||
ecma_gc_sweep (obj_iter_p);
|
||||
}
|
||||
|
||||
if (severity == JMEM_FREE_UNUSED_MEMORY_SEVERITY_HIGH)
|
||||
{
|
||||
/* Remove the property hashmap of BLACK objects */
|
||||
for (ecma_object_t *obj_iter_p = ecma_gc_objects_lists[ECMA_GC_COLOR_BLACK], *obj_next_p;
|
||||
obj_iter_p != NULL;
|
||||
obj_iter_p = obj_next_p)
|
||||
{
|
||||
obj_next_p = ecma_gc_get_object_next (obj_iter_p);
|
||||
|
||||
JERRY_ASSERT (ecma_gc_is_object_visited (obj_iter_p));
|
||||
|
||||
ecma_property_header_t *prop_iter_p = ecma_get_property_list (obj_iter_p);
|
||||
if (prop_iter_p != NULL
|
||||
&& ECMA_PROPERTY_GET_TYPE (prop_iter_p->types + 0) == ECMA_PROPERTY_TYPE_HASHMAP)
|
||||
{
|
||||
ecma_property_hashmap_free (obj_iter_p);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Unmarking all objects */
|
||||
ecma_gc_objects_lists[ECMA_GC_COLOR_WHITE_GRAY] = ecma_gc_objects_lists[ECMA_GC_COLOR_BLACK];
|
||||
ecma_gc_objects_lists[ECMA_GC_COLOR_BLACK] = NULL;
|
||||
@@ -603,7 +623,7 @@ ecma_free_unused_memory (jmem_free_unused_memory_severity_t severity) /**< sever
|
||||
*/
|
||||
if (ecma_gc_new_objects_since_last_gc * CONFIG_ECMA_GC_NEW_OBJECTS_SHARE_TO_START_GC > ecma_gc_objects_number)
|
||||
{
|
||||
ecma_gc_run ();
|
||||
ecma_gc_run (severity);
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -611,7 +631,7 @@ ecma_free_unused_memory (jmem_free_unused_memory_severity_t severity) /**< sever
|
||||
JERRY_ASSERT (severity == JMEM_FREE_UNUSED_MEMORY_SEVERITY_HIGH);
|
||||
|
||||
/* Freeing as much memory as we currently can */
|
||||
ecma_gc_run ();
|
||||
ecma_gc_run (severity);
|
||||
}
|
||||
} /* ecma_free_unused_memory */
|
||||
|
||||
|
||||
@@ -30,7 +30,7 @@ extern void ecma_gc_init (void);
|
||||
extern void ecma_init_gc_info (ecma_object_t *);
|
||||
extern void ecma_ref_object (ecma_object_t *);
|
||||
extern void ecma_deref_object (ecma_object_t *);
|
||||
extern void ecma_gc_run (void);
|
||||
extern void ecma_gc_run (jmem_free_unused_memory_severity_t);
|
||||
extern void ecma_free_unused_memory (jmem_free_unused_memory_severity_t);
|
||||
|
||||
/**
|
||||
|
||||
@@ -54,7 +54,7 @@ ecma_finalize (void)
|
||||
|
||||
ecma_finalize_environment ();
|
||||
ecma_finalize_builtins ();
|
||||
ecma_gc_run ();
|
||||
ecma_gc_run (JMEM_FREE_UNUSED_MEMORY_SEVERITY_LOW);
|
||||
ecma_finalize_lit_storage ();
|
||||
} /* ecma_finalize */
|
||||
|
||||
|
||||
@@ -110,7 +110,13 @@ ecma_property_hashmap_create (ecma_object_t *object_p) /**< object */
|
||||
|
||||
size_t total_size = ECMA_PROPERTY_HASHMAP_GET_TOTAL_SIZE (max_property_count);
|
||||
|
||||
ecma_property_hashmap_t *hashmap_p = (ecma_property_hashmap_t *) jmem_heap_alloc_block (total_size);
|
||||
ecma_property_hashmap_t *hashmap_p = (ecma_property_hashmap_t *) jmem_heap_alloc_block_null_on_error (total_size);
|
||||
|
||||
if (hashmap_p == NULL)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
memset (hashmap_p, 0, total_size);
|
||||
|
||||
hashmap_p->header.types[0].type_and_flags = ECMA_PROPERTY_TYPE_HASHMAP;
|
||||
|
||||
+1
-1
@@ -224,7 +224,7 @@ jerry_gc (void)
|
||||
{
|
||||
jerry_assert_api_available ();
|
||||
|
||||
ecma_gc_run ();
|
||||
ecma_gc_run (JMEM_FREE_UNUSED_MEMORY_SEVERITY_LOW);
|
||||
} /* jerry_gc */
|
||||
|
||||
/**
|
||||
|
||||
@@ -321,12 +321,17 @@ void *jmem_heap_alloc_block_internal (const size_t size)
|
||||
* Allocation of memory block, running 'try to give memory back' callbacks, if there is not enough memory.
|
||||
*
|
||||
* Note:
|
||||
* if after running the callbacks, there is still not enough memory, engine is terminated with ERR_OUT_OF_MEMORY.
|
||||
* if there is still not enough memory after running the callbacks
|
||||
* - NULL value will be returned if parmeter 'ret_null_on_error' is true
|
||||
* - the engine will terminate with ERR_OUT_OF_MEMORY if 'ret_null_on_error' is false
|
||||
*
|
||||
* @return pointer to allocated memory block
|
||||
* @return NULL, if the required memory size is 0
|
||||
* also NULL, if 'ret_null_on_error' is true and the allocation fails because of there is not enough memory
|
||||
*/
|
||||
void * __attribute__((hot))
|
||||
jmem_heap_alloc_block (const size_t size)
|
||||
static void *
|
||||
jmem_heap_gc_and_alloc_block (const size_t size, /**< required memory size */
|
||||
bool ret_null_on_error) /**< indicates whether return null or terminate
|
||||
with ERR_OUT_OF_MEMORY on out of memory */
|
||||
{
|
||||
if (unlikely (size == 0))
|
||||
{
|
||||
@@ -369,9 +374,46 @@ jmem_heap_alloc_block (const size_t size)
|
||||
|
||||
JERRY_ASSERT (data_space_p == NULL);
|
||||
|
||||
jerry_fatal (ERR_OUT_OF_MEMORY);
|
||||
if (!ret_null_on_error)
|
||||
{
|
||||
jerry_fatal (ERR_OUT_OF_MEMORY);
|
||||
}
|
||||
|
||||
return data_space_p;
|
||||
} /* jmem_heap_gc_and_alloc_block */
|
||||
|
||||
/**
|
||||
* Allocation of memory block, running 'try to give memory back' callbacks, if there is not enough memory.
|
||||
*
|
||||
* Note:
|
||||
* If there is still not enough memory after running the callbacks, then the engine will be
|
||||
* terminated with ERR_OUT_OF_MEMORY.
|
||||
*
|
||||
* @return NULL, if the required memory is 0
|
||||
* pointer to allocated memory block, otherwise
|
||||
*/
|
||||
void * __attribute__((hot)) __attr_always_inline___
|
||||
jmem_heap_alloc_block (const size_t size) /**< required memory size */
|
||||
{
|
||||
return jmem_heap_gc_and_alloc_block (size, false);
|
||||
} /* jmem_heap_alloc_block */
|
||||
|
||||
/**
|
||||
* Allocation of memory block, running 'try to give memory back' callbacks, if there is not enough memory.
|
||||
*
|
||||
* Note:
|
||||
* If there is still not enough memory after running the callbacks, NULL will be returned.
|
||||
*
|
||||
* @return NULL, if the required memory size is 0
|
||||
* also NULL, if the allocation has failed
|
||||
* pointer to the allocated memory block, otherwise
|
||||
*/
|
||||
void * __attribute__((hot)) __attr_always_inline___
|
||||
jmem_heap_alloc_block_null_on_error (const size_t size) /**< required memory size */
|
||||
{
|
||||
return jmem_heap_gc_and_alloc_block (size, true);
|
||||
} /* jmem_heap_alloc_block_null_on_error */
|
||||
|
||||
/**
|
||||
* Allocate block and store block size.
|
||||
*
|
||||
|
||||
@@ -32,6 +32,7 @@
|
||||
extern void jmem_heap_init (void);
|
||||
extern void jmem_heap_finalize (void);
|
||||
extern void *jmem_heap_alloc_block (const size_t);
|
||||
extern void *jmem_heap_alloc_block_null_on_error (const size_t);
|
||||
extern void jmem_heap_free_block (void *, const size_t);
|
||||
extern void *jmem_heap_alloc_block_store_size (size_t);
|
||||
extern void jmem_heap_free_block_size_stored (void *);
|
||||
|
||||
Reference in New Issue
Block a user