Free the GC mark bit to increase the number of object types. (#2032)
JerryScript-DCO-1.0-Signed-off-by: Zoltan Herczeg zherczeg.u-szeged@partner.samsung.com
This commit is contained in:
+100
-81
@@ -47,20 +47,12 @@
|
|||||||
* @{
|
* @{
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/**
|
/*
|
||||||
* Current state of an object's visited flag that
|
* The garbage collector uses the reference counter
|
||||||
* indicates whether the object is in visited state:
|
* of object: it increases the counter by one when
|
||||||
*
|
* the object is marked at the first time.
|
||||||
* visited_field | visited_flip_flag | real_value
|
|
||||||
* false | false | false
|
|
||||||
* false | true | true
|
|
||||||
* true | false | true
|
|
||||||
* true | true | false
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
static void ecma_gc_mark (ecma_object_t *object_p);
|
|
||||||
static void ecma_gc_sweep (ecma_object_t *object_p);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get next object in list of objects with same generation.
|
* Get next object in list of objects with same generation.
|
||||||
*/
|
*/
|
||||||
@@ -92,27 +84,19 @@ ecma_gc_is_object_visited (ecma_object_t *object_p) /**< object */
|
|||||||
{
|
{
|
||||||
JERRY_ASSERT (object_p != NULL);
|
JERRY_ASSERT (object_p != NULL);
|
||||||
|
|
||||||
bool flag_value = (object_p->type_flags_refs & ECMA_OBJECT_FLAG_GC_VISITED) != 0;
|
return (object_p->type_flags_refs >= ECMA_OBJECT_REF_ONE);
|
||||||
|
|
||||||
return flag_value != JERRY_CONTEXT (ecma_gc_visited_flip_flag);
|
|
||||||
} /* ecma_gc_is_object_visited */
|
} /* ecma_gc_is_object_visited */
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set visited flag of the object.
|
* Set visited flag of the object.
|
||||||
*/
|
*/
|
||||||
static inline void
|
static inline void
|
||||||
ecma_gc_set_object_visited (ecma_object_t *object_p, /**< object */
|
ecma_gc_set_object_visited (ecma_object_t *object_p) /**< object */
|
||||||
bool is_visited) /**< flag value */
|
|
||||||
{
|
{
|
||||||
JERRY_ASSERT (object_p != NULL);
|
/* Set reference counter to one if it is zero. */
|
||||||
|
if (object_p->type_flags_refs < ECMA_OBJECT_REF_ONE)
|
||||||
if (is_visited != JERRY_CONTEXT (ecma_gc_visited_flip_flag))
|
|
||||||
{
|
{
|
||||||
object_p->type_flags_refs = (uint16_t) (object_p->type_flags_refs | ECMA_OBJECT_FLAG_GC_VISITED);
|
object_p->type_flags_refs |= ECMA_OBJECT_REF_ONE;
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
object_p->type_flags_refs = (uint16_t) (object_p->type_flags_refs & ~ECMA_OBJECT_FLAG_GC_VISITED);
|
|
||||||
}
|
}
|
||||||
} /* ecma_gc_set_object_visited */
|
} /* ecma_gc_set_object_visited */
|
||||||
|
|
||||||
@@ -130,11 +114,8 @@ ecma_init_gc_info (ecma_object_t *object_p) /**< object */
|
|||||||
JERRY_ASSERT (object_p->type_flags_refs < ECMA_OBJECT_REF_ONE);
|
JERRY_ASSERT (object_p->type_flags_refs < ECMA_OBJECT_REF_ONE);
|
||||||
object_p->type_flags_refs = (uint16_t) (object_p->type_flags_refs | ECMA_OBJECT_REF_ONE);
|
object_p->type_flags_refs = (uint16_t) (object_p->type_flags_refs | ECMA_OBJECT_REF_ONE);
|
||||||
|
|
||||||
ecma_gc_set_object_next (object_p, JERRY_CONTEXT (ecma_gc_objects_lists) [ECMA_GC_COLOR_WHITE_GRAY]);
|
ecma_gc_set_object_next (object_p, JERRY_CONTEXT (ecma_gc_objects_p));
|
||||||
JERRY_CONTEXT (ecma_gc_objects_lists) [ECMA_GC_COLOR_WHITE_GRAY] = object_p;
|
JERRY_CONTEXT (ecma_gc_objects_p) = object_p;
|
||||||
|
|
||||||
/* Should be set to false at the beginning of garbage collection */
|
|
||||||
ecma_gc_set_object_visited (object_p, false);
|
|
||||||
} /* ecma_init_gc_info */
|
} /* ecma_init_gc_info */
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -156,7 +137,7 @@ ecma_ref_object (ecma_object_t *object_p) /**< object */
|
|||||||
/**
|
/**
|
||||||
* Decrease reference counter of an object
|
* Decrease reference counter of an object
|
||||||
*/
|
*/
|
||||||
void
|
inline void __attr_always_inline___
|
||||||
ecma_deref_object (ecma_object_t *object_p) /**< object */
|
ecma_deref_object (ecma_object_t *object_p) /**< object */
|
||||||
{
|
{
|
||||||
JERRY_ASSERT (object_p->type_flags_refs >= ECMA_OBJECT_REF_ONE);
|
JERRY_ASSERT (object_p->type_flags_refs >= ECMA_OBJECT_REF_ONE);
|
||||||
@@ -188,7 +169,7 @@ ecma_gc_mark_property (ecma_property_pair_t *property_pair_p, /**< property pair
|
|||||||
{
|
{
|
||||||
ecma_object_t *value_obj_p = ecma_get_object_from_value (value);
|
ecma_object_t *value_obj_p = ecma_get_object_from_value (value);
|
||||||
|
|
||||||
ecma_gc_set_object_visited (value_obj_p, true);
|
ecma_gc_set_object_visited (value_obj_p);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -200,12 +181,12 @@ ecma_gc_mark_property (ecma_property_pair_t *property_pair_p, /**< property pair
|
|||||||
|
|
||||||
if (getter_obj_p != NULL)
|
if (getter_obj_p != NULL)
|
||||||
{
|
{
|
||||||
ecma_gc_set_object_visited (getter_obj_p, true);
|
ecma_gc_set_object_visited (getter_obj_p);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (setter_obj_p != NULL)
|
if (setter_obj_p != NULL)
|
||||||
{
|
{
|
||||||
ecma_gc_set_object_visited (setter_obj_p, true);
|
ecma_gc_set_object_visited (setter_obj_p);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -226,7 +207,7 @@ ecma_gc_mark_property (ecma_property_pair_t *property_pair_p, /**< property pair
|
|||||||
/**
|
/**
|
||||||
* Mark objects as visited starting from specified object as root
|
* Mark objects as visited starting from specified object as root
|
||||||
*/
|
*/
|
||||||
void
|
static void
|
||||||
ecma_gc_mark (ecma_object_t *object_p) /**< object to mark from */
|
ecma_gc_mark (ecma_object_t *object_p) /**< object to mark from */
|
||||||
{
|
{
|
||||||
JERRY_ASSERT (object_p != NULL);
|
JERRY_ASSERT (object_p != NULL);
|
||||||
@@ -239,13 +220,13 @@ ecma_gc_mark (ecma_object_t *object_p) /**< object to mark from */
|
|||||||
ecma_object_t *lex_env_p = ecma_get_lex_env_outer_reference (object_p);
|
ecma_object_t *lex_env_p = ecma_get_lex_env_outer_reference (object_p);
|
||||||
if (lex_env_p != NULL)
|
if (lex_env_p != NULL)
|
||||||
{
|
{
|
||||||
ecma_gc_set_object_visited (lex_env_p, true);
|
ecma_gc_set_object_visited (lex_env_p);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ecma_get_lex_env_type (object_p) != ECMA_LEXICAL_ENVIRONMENT_DECLARATIVE)
|
if (ecma_get_lex_env_type (object_p) != ECMA_LEXICAL_ENVIRONMENT_DECLARATIVE)
|
||||||
{
|
{
|
||||||
ecma_object_t *binding_object_p = ecma_get_lex_env_binding_object (object_p);
|
ecma_object_t *binding_object_p = ecma_get_lex_env_binding_object (object_p);
|
||||||
ecma_gc_set_object_visited (binding_object_p, true);
|
ecma_gc_set_object_visited (binding_object_p);
|
||||||
|
|
||||||
traverse_properties = false;
|
traverse_properties = false;
|
||||||
}
|
}
|
||||||
@@ -255,7 +236,7 @@ ecma_gc_mark (ecma_object_t *object_p) /**< object to mark from */
|
|||||||
ecma_object_t *proto_p = ecma_get_object_prototype (object_p);
|
ecma_object_t *proto_p = ecma_get_object_prototype (object_p);
|
||||||
if (proto_p != NULL)
|
if (proto_p != NULL)
|
||||||
{
|
{
|
||||||
ecma_gc_set_object_visited (proto_p, true);
|
ecma_gc_set_object_visited (proto_p);
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (ecma_get_object_type (object_p))
|
switch (ecma_get_object_type (object_p))
|
||||||
@@ -272,7 +253,7 @@ ecma_gc_mark (ecma_object_t *object_p) /**< object to mark from */
|
|||||||
|
|
||||||
if (ecma_is_value_object (result))
|
if (ecma_is_value_object (result))
|
||||||
{
|
{
|
||||||
ecma_gc_set_object_visited (ecma_get_object_from_value (result), true);
|
ecma_gc_set_object_visited (ecma_get_object_from_value (result));
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Mark all reactions. */
|
/* Mark all reactions. */
|
||||||
@@ -281,14 +262,14 @@ ecma_gc_mark (ecma_object_t *object_p) /**< object to mark from */
|
|||||||
|
|
||||||
while (ecma_collection_iterator_next (&iter))
|
while (ecma_collection_iterator_next (&iter))
|
||||||
{
|
{
|
||||||
ecma_gc_set_object_visited (ecma_get_object_from_value (*iter.current_value_p), true);
|
ecma_gc_set_object_visited (ecma_get_object_from_value (*iter.current_value_p));
|
||||||
}
|
}
|
||||||
|
|
||||||
ecma_collection_iterator_init (&iter, ((ecma_promise_object_t *) ext_object_p)->reject_reactions);
|
ecma_collection_iterator_init (&iter, ((ecma_promise_object_t *) ext_object_p)->reject_reactions);
|
||||||
|
|
||||||
while (ecma_collection_iterator_next (&iter))
|
while (ecma_collection_iterator_next (&iter))
|
||||||
{
|
{
|
||||||
ecma_gc_set_object_visited (ecma_get_object_from_value (*iter.current_value_p), true);
|
ecma_gc_set_object_visited (ecma_get_object_from_value (*iter.current_value_p));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -306,14 +287,14 @@ ecma_gc_mark (ecma_object_t *object_p) /**< object to mark from */
|
|||||||
ecma_object_t *lex_env_p = ECMA_GET_INTERNAL_VALUE_POINTER (ecma_object_t,
|
ecma_object_t *lex_env_p = ECMA_GET_INTERNAL_VALUE_POINTER (ecma_object_t,
|
||||||
ext_object_p->u.pseudo_array.u2.lex_env_cp);
|
ext_object_p->u.pseudo_array.u2.lex_env_cp);
|
||||||
|
|
||||||
ecma_gc_set_object_visited (lex_env_p, true);
|
ecma_gc_set_object_visited (lex_env_p);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
#ifndef CONFIG_DISABLE_ES2015_TYPEDARRAY_BUILTIN
|
#ifndef CONFIG_DISABLE_ES2015_TYPEDARRAY_BUILTIN
|
||||||
case ECMA_PSEUDO_ARRAY_TYPEDARRAY:
|
case ECMA_PSEUDO_ARRAY_TYPEDARRAY:
|
||||||
case ECMA_PSEUDO_ARRAY_TYPEDARRAY_WITH_INFO:
|
case ECMA_PSEUDO_ARRAY_TYPEDARRAY_WITH_INFO:
|
||||||
{
|
{
|
||||||
ecma_gc_set_object_visited (ecma_typedarray_get_arraybuffer (object_p), true);
|
ecma_gc_set_object_visited (ecma_typedarray_get_arraybuffer (object_p));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
#endif /* !CONFIG_DISABLE_ES2015_TYPEDARRAY_BUILTIN */
|
#endif /* !CONFIG_DISABLE_ES2015_TYPEDARRAY_BUILTIN */
|
||||||
@@ -334,7 +315,7 @@ ecma_gc_mark (ecma_object_t *object_p) /**< object to mark from */
|
|||||||
target_func_obj_p = ECMA_GET_INTERNAL_VALUE_POINTER (ecma_object_t,
|
target_func_obj_p = ECMA_GET_INTERNAL_VALUE_POINTER (ecma_object_t,
|
||||||
ext_function_p->u.bound_function.target_function);
|
ext_function_p->u.bound_function.target_function);
|
||||||
|
|
||||||
ecma_gc_set_object_visited (target_func_obj_p, true);
|
ecma_gc_set_object_visited (target_func_obj_p);
|
||||||
|
|
||||||
ecma_value_t args_len_or_this = ext_function_p->u.bound_function.args_len_or_this;
|
ecma_value_t args_len_or_this = ext_function_p->u.bound_function.args_len_or_this;
|
||||||
|
|
||||||
@@ -342,7 +323,7 @@ ecma_gc_mark (ecma_object_t *object_p) /**< object to mark from */
|
|||||||
{
|
{
|
||||||
if (ecma_is_value_object (args_len_or_this))
|
if (ecma_is_value_object (args_len_or_this))
|
||||||
{
|
{
|
||||||
ecma_gc_set_object_visited (ecma_get_object_from_value (args_len_or_this), true);
|
ecma_gc_set_object_visited (ecma_get_object_from_value (args_len_or_this));
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -356,7 +337,7 @@ ecma_gc_mark (ecma_object_t *object_p) /**< object to mark from */
|
|||||||
{
|
{
|
||||||
if (ecma_is_value_object (args_p[i]))
|
if (ecma_is_value_object (args_p[i]))
|
||||||
{
|
{
|
||||||
ecma_gc_set_object_visited (ecma_get_object_from_value (args_p[i]), true);
|
ecma_gc_set_object_visited (ecma_get_object_from_value (args_p[i]));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@@ -370,7 +351,7 @@ ecma_gc_mark (ecma_object_t *object_p) /**< object to mark from */
|
|||||||
ecma_object_t *scope_p = ECMA_GET_INTERNAL_VALUE_POINTER (ecma_object_t,
|
ecma_object_t *scope_p = ECMA_GET_INTERNAL_VALUE_POINTER (ecma_object_t,
|
||||||
ext_func_p->u.function.scope_cp);
|
ext_func_p->u.function.scope_cp);
|
||||||
|
|
||||||
ecma_gc_set_object_visited (scope_p, true);
|
ecma_gc_set_object_visited (scope_p);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -441,8 +422,8 @@ ecma_gc_free_native_pointer (ecma_property_t *property_p, /**< property */
|
|||||||
/**
|
/**
|
||||||
* Free specified object.
|
* Free specified object.
|
||||||
*/
|
*/
|
||||||
void
|
static void
|
||||||
ecma_gc_sweep (ecma_object_t *object_p) /**< object to free */
|
ecma_gc_free_object (ecma_object_t *object_p) /**< object to free */
|
||||||
{
|
{
|
||||||
JERRY_ASSERT (object_p != NULL
|
JERRY_ASSERT (object_p != NULL
|
||||||
&& !ecma_gc_is_object_visited (object_p)
|
&& !ecma_gc_is_object_visited (object_p)
|
||||||
@@ -695,7 +676,7 @@ ecma_gc_sweep (ecma_object_t *object_p) /**< object to free */
|
|||||||
}
|
}
|
||||||
|
|
||||||
ecma_dealloc_object (object_p);
|
ecma_dealloc_object (object_p);
|
||||||
} /* ecma_gc_sweep */
|
} /* ecma_gc_free_object */
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Run garbage collection
|
* Run garbage collection
|
||||||
@@ -705,51 +686,85 @@ ecma_gc_run (jmem_free_unused_memory_severity_t severity) /**< gc severity */
|
|||||||
{
|
{
|
||||||
JERRY_CONTEXT (ecma_gc_new_objects) = 0;
|
JERRY_CONTEXT (ecma_gc_new_objects) = 0;
|
||||||
|
|
||||||
JERRY_ASSERT (JERRY_CONTEXT (ecma_gc_objects_lists) [ECMA_GC_COLOR_BLACK] == NULL);
|
ecma_object_t *white_gray_objects_p = JERRY_CONTEXT (ecma_gc_objects_p);
|
||||||
|
ecma_object_t *black_objects_p = NULL;
|
||||||
|
|
||||||
/* if some object is referenced from stack or globals (i.e. it is root), mark it */
|
ecma_object_t *obj_iter_p = white_gray_objects_p;
|
||||||
for (ecma_object_t *obj_iter_p = JERRY_CONTEXT (ecma_gc_objects_lists) [ECMA_GC_COLOR_WHITE_GRAY];
|
ecma_object_t *obj_prev_p = NULL;
|
||||||
obj_iter_p != NULL;
|
|
||||||
obj_iter_p = ecma_gc_get_object_next (obj_iter_p))
|
/* Move root objects (i.e. they have global or stack references) to the black list. */
|
||||||
|
while (obj_iter_p != NULL)
|
||||||
{
|
{
|
||||||
JERRY_ASSERT (!ecma_gc_is_object_visited (obj_iter_p));
|
ecma_object_t *obj_next_p = ecma_gc_get_object_next (obj_iter_p);
|
||||||
|
|
||||||
if (obj_iter_p->type_flags_refs >= ECMA_OBJECT_REF_ONE)
|
JERRY_ASSERT (obj_prev_p == NULL
|
||||||
|
|| ecma_gc_get_object_next (obj_prev_p) == obj_iter_p);
|
||||||
|
|
||||||
|
if (ecma_gc_is_object_visited (obj_iter_p))
|
||||||
{
|
{
|
||||||
ecma_gc_set_object_visited (obj_iter_p, true);
|
/* Moving the object to list of marked objects. */
|
||||||
|
if (likely (obj_prev_p != NULL))
|
||||||
|
{
|
||||||
|
obj_prev_p->gc_next_cp = obj_iter_p->gc_next_cp;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
white_gray_objects_p = obj_next_p;
|
||||||
|
}
|
||||||
|
|
||||||
|
ecma_gc_set_object_next (obj_iter_p, black_objects_p);
|
||||||
|
black_objects_p = obj_iter_p;
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
obj_prev_p = obj_iter_p;
|
||||||
|
}
|
||||||
|
|
||||||
|
obj_iter_p = obj_next_p;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool marked_anything_during_current_iteration = false;
|
/* Mark root objects. */
|
||||||
|
obj_iter_p = black_objects_p;
|
||||||
|
while (obj_iter_p != NULL)
|
||||||
|
{
|
||||||
|
ecma_gc_mark (obj_iter_p);
|
||||||
|
obj_iter_p = ecma_gc_get_object_next (obj_iter_p);
|
||||||
|
}
|
||||||
|
|
||||||
|
ecma_object_t *first_root_object_p = black_objects_p;
|
||||||
|
|
||||||
|
/* Mark non-root objects. */
|
||||||
|
bool marked_anything_during_current_iteration;
|
||||||
|
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
marked_anything_during_current_iteration = false;
|
marked_anything_during_current_iteration = false;
|
||||||
|
|
||||||
ecma_object_t *obj_prev_p = NULL;
|
obj_prev_p = NULL;
|
||||||
ecma_object_t *obj_iter_p = JERRY_CONTEXT (ecma_gc_objects_lists) [ECMA_GC_COLOR_WHITE_GRAY];
|
obj_iter_p = white_gray_objects_p;
|
||||||
|
|
||||||
while (obj_iter_p != NULL)
|
while (obj_iter_p != NULL)
|
||||||
{
|
{
|
||||||
ecma_object_t *obj_next_p = ecma_gc_get_object_next (obj_iter_p);
|
ecma_object_t *obj_next_p = ecma_gc_get_object_next (obj_iter_p);
|
||||||
|
|
||||||
|
JERRY_ASSERT (obj_prev_p == NULL
|
||||||
|
|| ecma_gc_get_object_next (obj_prev_p) == obj_iter_p);
|
||||||
|
|
||||||
if (ecma_gc_is_object_visited (obj_iter_p))
|
if (ecma_gc_is_object_visited (obj_iter_p))
|
||||||
{
|
{
|
||||||
/* Moving the object to list of marked objects */
|
/* Moving the object to list of marked objects */
|
||||||
ecma_gc_set_object_next (obj_iter_p, JERRY_CONTEXT (ecma_gc_objects_lists) [ECMA_GC_COLOR_BLACK]);
|
|
||||||
JERRY_CONTEXT (ecma_gc_objects_lists) [ECMA_GC_COLOR_BLACK] = obj_iter_p;
|
|
||||||
|
|
||||||
if (likely (obj_prev_p != NULL))
|
if (likely (obj_prev_p != NULL))
|
||||||
{
|
{
|
||||||
JERRY_ASSERT (ecma_gc_get_object_next (obj_prev_p) == obj_iter_p);
|
obj_prev_p->gc_next_cp = obj_iter_p->gc_next_cp;
|
||||||
|
|
||||||
ecma_gc_set_object_next (obj_prev_p, obj_next_p);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
JERRY_CONTEXT (ecma_gc_objects_lists) [ECMA_GC_COLOR_WHITE_GRAY] = obj_next_p;
|
white_gray_objects_p = obj_next_p;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ecma_gc_set_object_next (obj_iter_p, black_objects_p);
|
||||||
|
black_objects_p = obj_iter_p;
|
||||||
|
|
||||||
ecma_gc_mark (obj_iter_p);
|
ecma_gc_mark (obj_iter_p);
|
||||||
marked_anything_during_current_iteration = true;
|
marked_anything_during_current_iteration = true;
|
||||||
}
|
}
|
||||||
@@ -763,8 +778,8 @@ ecma_gc_run (jmem_free_unused_memory_severity_t severity) /**< gc severity */
|
|||||||
}
|
}
|
||||||
while (marked_anything_during_current_iteration);
|
while (marked_anything_during_current_iteration);
|
||||||
|
|
||||||
/* Sweeping objects that are currently unmarked */
|
/* Sweep objects that are currently unmarked. */
|
||||||
ecma_object_t *obj_iter_p = JERRY_CONTEXT (ecma_gc_objects_lists) [ECMA_GC_COLOR_WHITE_GRAY];
|
obj_iter_p = white_gray_objects_p;
|
||||||
|
|
||||||
while (obj_iter_p != NULL)
|
while (obj_iter_p != NULL)
|
||||||
{
|
{
|
||||||
@@ -772,19 +787,28 @@ ecma_gc_run (jmem_free_unused_memory_severity_t severity) /**< gc severity */
|
|||||||
|
|
||||||
JERRY_ASSERT (!ecma_gc_is_object_visited (obj_iter_p));
|
JERRY_ASSERT (!ecma_gc_is_object_visited (obj_iter_p));
|
||||||
|
|
||||||
ecma_gc_sweep (obj_iter_p);
|
ecma_gc_free_object (obj_iter_p);
|
||||||
obj_iter_p = obj_next_p;
|
obj_iter_p = obj_next_p;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Reset the reference counter of non-root black objects. */
|
||||||
|
obj_iter_p = black_objects_p;
|
||||||
|
|
||||||
|
while (obj_iter_p != first_root_object_p)
|
||||||
|
{
|
||||||
|
/* The reference counter must be 1. */
|
||||||
|
ecma_deref_object (obj_iter_p);
|
||||||
|
JERRY_ASSERT (obj_iter_p->type_flags_refs < ECMA_OBJECT_REF_ONE);
|
||||||
|
|
||||||
|
obj_iter_p = ecma_gc_get_object_next (obj_iter_p);
|
||||||
|
}
|
||||||
|
|
||||||
if (severity == JMEM_FREE_UNUSED_MEMORY_SEVERITY_HIGH)
|
if (severity == JMEM_FREE_UNUSED_MEMORY_SEVERITY_HIGH)
|
||||||
{
|
{
|
||||||
/* Remove the property hashmap of BLACK objects */
|
obj_iter_p = black_objects_p;
|
||||||
obj_iter_p = JERRY_CONTEXT (ecma_gc_objects_lists) [ECMA_GC_COLOR_BLACK];
|
|
||||||
|
|
||||||
while (obj_iter_p != NULL)
|
while (obj_iter_p != NULL)
|
||||||
{
|
{
|
||||||
JERRY_ASSERT (ecma_gc_is_object_visited (obj_iter_p));
|
|
||||||
|
|
||||||
if (!ecma_is_lexical_environment (obj_iter_p)
|
if (!ecma_is_lexical_environment (obj_iter_p)
|
||||||
|| ecma_get_lex_env_type (obj_iter_p) == ECMA_LEXICAL_ENVIRONMENT_DECLARATIVE)
|
|| ecma_get_lex_env_type (obj_iter_p) == ECMA_LEXICAL_ENVIRONMENT_DECLARATIVE)
|
||||||
{
|
{
|
||||||
@@ -800,12 +824,7 @@ ecma_gc_run (jmem_free_unused_memory_severity_t severity) /**< gc severity */
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Unmarking all objects */
|
JERRY_CONTEXT (ecma_gc_objects_p) = black_objects_p;
|
||||||
ecma_object_t *black_objects = JERRY_CONTEXT (ecma_gc_objects_lists) [ECMA_GC_COLOR_BLACK];
|
|
||||||
JERRY_CONTEXT (ecma_gc_objects_lists)[ECMA_GC_COLOR_WHITE_GRAY] = black_objects;
|
|
||||||
JERRY_CONTEXT (ecma_gc_objects_lists) [ECMA_GC_COLOR_BLACK] = NULL;
|
|
||||||
|
|
||||||
JERRY_CONTEXT (ecma_gc_visited_flip_flag) = !JERRY_CONTEXT (ecma_gc_visited_flip_flag);
|
|
||||||
|
|
||||||
#ifndef CONFIG_DISABLE_REGEXP_BUILTIN
|
#ifndef CONFIG_DISABLE_REGEXP_BUILTIN
|
||||||
/* Free RegExp bytecodes stored in cache */
|
/* Free RegExp bytecodes stored in cache */
|
||||||
|
|||||||
@@ -583,6 +583,8 @@ typedef enum
|
|||||||
ECMA_OBJECT_TYPE_BOUND_FUNCTION = 5, /**< Function objects (15.3), created through 15.3.4.5 routine */
|
ECMA_OBJECT_TYPE_BOUND_FUNCTION = 5, /**< Function objects (15.3), created through 15.3.4.5 routine */
|
||||||
ECMA_OBJECT_TYPE_PSEUDO_ARRAY = 6, /**< Array-like object, such as Arguments object (10.6) */
|
ECMA_OBJECT_TYPE_PSEUDO_ARRAY = 6, /**< Array-like object, such as Arguments object (10.6) */
|
||||||
|
|
||||||
|
/* Types between 13-15 cannot have a built-in flag. See ecma_lexical_environment_type_t. */
|
||||||
|
|
||||||
ECMA_OBJECT_TYPE__MAX = ECMA_OBJECT_TYPE_PSEUDO_ARRAY /**< maximum value */
|
ECMA_OBJECT_TYPE__MAX = ECMA_OBJECT_TYPE_PSEUDO_ARRAY /**< maximum value */
|
||||||
} ecma_object_type_t;
|
} ecma_object_type_t;
|
||||||
|
|
||||||
@@ -603,14 +605,11 @@ typedef enum
|
|||||||
*/
|
*/
|
||||||
typedef enum
|
typedef enum
|
||||||
{
|
{
|
||||||
/* ECMA_OBJECT_TYPE_GENERAL (0) with built-in flag. */
|
/* Types between 0 - 12 are ecma_object_type_t which can have a built-in flag. */
|
||||||
/* ECMA_OBJECT_TYPE_CLASS (1) with built-in flag. */
|
|
||||||
/* ECMA_OBJECT_TYPE_FUNCTION (2) with built-in flag. */
|
ECMA_LEXICAL_ENVIRONMENT_DECLARATIVE = 13, /**< declarative lexical environment */
|
||||||
/* ECMA_OBJECT_TYPE_EXTERNAL_FUNCTION (3) with built-in flag. */
|
ECMA_LEXICAL_ENVIRONMENT_OBJECT_BOUND = 14, /**< object-bound lexical environment */
|
||||||
/* ECMA_OBJECT_TYPE_ARRAY (4) with built-in flag. */
|
ECMA_LEXICAL_ENVIRONMENT_THIS_OBJECT_BOUND = 15, /**< object-bound lexical environment
|
||||||
ECMA_LEXICAL_ENVIRONMENT_DECLARATIVE = 5, /**< declarative lexical environment */
|
|
||||||
ECMA_LEXICAL_ENVIRONMENT_OBJECT_BOUND = 6, /**< object-bound lexical environment */
|
|
||||||
ECMA_LEXICAL_ENVIRONMENT_THIS_OBJECT_BOUND = 7, /**< object-bound lexical environment
|
|
||||||
* with provideThis flag */
|
* with provideThis flag */
|
||||||
|
|
||||||
ECMA_LEXICAL_ENVIRONMENT_TYPE_START = ECMA_LEXICAL_ENVIRONMENT_DECLARATIVE, /**< first lexical
|
ECMA_LEXICAL_ENVIRONMENT_TYPE_START = ECMA_LEXICAL_ENVIRONMENT_DECLARATIVE, /**< first lexical
|
||||||
@@ -621,19 +620,14 @@ typedef enum
|
|||||||
/**
|
/**
|
||||||
* Ecma object type mask for getting the object type.
|
* Ecma object type mask for getting the object type.
|
||||||
*/
|
*/
|
||||||
#define ECMA_OBJECT_TYPE_MASK 0x07u
|
#define ECMA_OBJECT_TYPE_MASK 0x0fu
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Ecma object is built-in or lexical environment.
|
* Ecma object is built-in or lexical environment. When this flag is set, the object is a
|
||||||
* - built-in, if object type is less than ECMA_LEXICAL_ENVIRONMENT_TYPES_START
|
* - built-in, if object type is less than ECMA_LEXICAL_ENVIRONMENT_TYPES_START
|
||||||
* - lexical environment, if object type is greater or equal than ECMA_LEXICAL_ENVIRONMENT_TYPES_START
|
* - lexical environment, if object type is greater or equal than ECMA_LEXICAL_ENVIRONMENT_TYPES_START
|
||||||
*/
|
*/
|
||||||
#define ECMA_OBJECT_FLAG_BUILT_IN_OR_LEXICAL_ENV 0x08
|
#define ECMA_OBJECT_FLAG_BUILT_IN_OR_LEXICAL_ENV 0x10
|
||||||
|
|
||||||
/**
|
|
||||||
* This object is visited by the garbage collector.
|
|
||||||
*/
|
|
||||||
#define ECMA_OBJECT_FLAG_GC_VISITED 0x10
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Extensible object.
|
* Extensible object.
|
||||||
@@ -656,10 +650,9 @@ typedef enum
|
|||||||
*/
|
*/
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
/** type : 3 bit : ecma_object_type_t or ecma_lexical_environment_type_t
|
/** type : 4 bit : ecma_object_type_t or ecma_lexical_environment_type_t
|
||||||
depending on ECMA_OBJECT_FLAG_BUILT_IN_OR_LEXICAL_ENV
|
depending on ECMA_OBJECT_FLAG_BUILT_IN_OR_LEXICAL_ENV
|
||||||
flags : 3 bit : ECMA_OBJECT_FLAG_BUILT_IN_OR_LEXICAL_ENV,
|
flags : 2 bit : ECMA_OBJECT_FLAG_BUILT_IN_OR_LEXICAL_ENV,
|
||||||
ECMA_OBJECT_FLAG_GC_VISITED,
|
|
||||||
ECMA_OBJECT_FLAG_EXTENSIBLE
|
ECMA_OBJECT_FLAG_EXTENSIBLE
|
||||||
refs : 10 bit (max 1023) */
|
refs : 10 bit (max 1023) */
|
||||||
uint16_t type_flags_refs;
|
uint16_t type_flags_refs;
|
||||||
@@ -1143,21 +1136,6 @@ typedef struct
|
|||||||
* If regexp, the other flags must be RE_FLAG... */
|
* If regexp, the other flags must be RE_FLAG... */
|
||||||
} ecma_compiled_code_t;
|
} ecma_compiled_code_t;
|
||||||
|
|
||||||
/**
|
|
||||||
* An object's GC color
|
|
||||||
*
|
|
||||||
* Tri-color marking:
|
|
||||||
* WHITE_GRAY, unvisited -> WHITE: not referenced by a live object or the reference not found yet
|
|
||||||
* WHITE_GRAY, visited -> GRAY: referenced by some live object
|
|
||||||
* BLACK -> BLACK: all referenced objects are gray or black
|
|
||||||
*/
|
|
||||||
typedef enum
|
|
||||||
{
|
|
||||||
ECMA_GC_COLOR_WHITE_GRAY, /**< white or gray */
|
|
||||||
ECMA_GC_COLOR_BLACK, /**< black */
|
|
||||||
ECMA_GC_COLOR__COUNT /**< number of colors */
|
|
||||||
} ecma_gc_color_t;
|
|
||||||
|
|
||||||
#ifndef CONFIG_ECMA_PROPERTY_HASHMAP_DISABLE
|
#ifndef CONFIG_ECMA_PROPERTY_HASHMAP_DISABLE
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -60,17 +60,11 @@ JERRY_STATIC_ASSERT (ECMA_OBJECT_TYPE_MASK >= ECMA_LEXICAL_ENVIRONMENT_TYPE__MAX
|
|||||||
JERRY_STATIC_ASSERT (ECMA_OBJECT_TYPE_MASK + 1 == ECMA_OBJECT_FLAG_BUILT_IN_OR_LEXICAL_ENV,
|
JERRY_STATIC_ASSERT (ECMA_OBJECT_TYPE_MASK + 1 == ECMA_OBJECT_FLAG_BUILT_IN_OR_LEXICAL_ENV,
|
||||||
ecma_built_in_flag_must_follow_the_object_type);
|
ecma_built_in_flag_must_follow_the_object_type);
|
||||||
|
|
||||||
/**
|
|
||||||
* The ecma gc visited flag must follow the built in flag.
|
|
||||||
*/
|
|
||||||
JERRY_STATIC_ASSERT (ECMA_OBJECT_FLAG_GC_VISITED == (ECMA_OBJECT_FLAG_BUILT_IN_OR_LEXICAL_ENV << 1),
|
|
||||||
ecma_gc_visited_flag_must_follow_the_built_in_flag);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The ecma extensible flag must follow the gc visited flag.
|
* The ecma extensible flag must follow the gc visited flag.
|
||||||
*/
|
*/
|
||||||
JERRY_STATIC_ASSERT (ECMA_OBJECT_FLAG_EXTENSIBLE == (ECMA_OBJECT_FLAG_GC_VISITED << 1),
|
JERRY_STATIC_ASSERT (ECMA_OBJECT_FLAG_EXTENSIBLE == (ECMA_OBJECT_FLAG_BUILT_IN_OR_LEXICAL_ENV << 1),
|
||||||
ecma_extensible_flag_must_follow_the_gc_visited_flag);
|
ecma_extensible_flag_must_follow_the_built_in_flag);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The ecma object ref one must follow the extensible flag.
|
* The ecma object ref one must follow the extensible flag.
|
||||||
|
|||||||
@@ -62,8 +62,7 @@ typedef struct
|
|||||||
#ifndef CONFIG_DISABLE_REGEXP_BUILTIN
|
#ifndef CONFIG_DISABLE_REGEXP_BUILTIN
|
||||||
const re_compiled_code_t *re_cache[RE_CACHE_SIZE]; /**< regex cache */
|
const re_compiled_code_t *re_cache[RE_CACHE_SIZE]; /**< regex cache */
|
||||||
#endif /* !CONFIG_DISABLE_REGEXP_BUILTIN */
|
#endif /* !CONFIG_DISABLE_REGEXP_BUILTIN */
|
||||||
ecma_object_t *ecma_gc_objects_lists[ECMA_GC_COLOR__COUNT]; /**< List of marked (visited during
|
ecma_object_t *ecma_gc_objects_p; /**< List of currently alive objects. */
|
||||||
* current GC session) and umarked objects */
|
|
||||||
jmem_heap_free_t *jmem_heap_list_skip_p; /**< This is used to speed up deallocation. */
|
jmem_heap_free_t *jmem_heap_list_skip_p; /**< This is used to speed up deallocation. */
|
||||||
jmem_pools_chunk_t *jmem_free_8_byte_chunk_p; /**< list of free eight byte pool chunks */
|
jmem_pools_chunk_t *jmem_free_8_byte_chunk_p; /**< list of free eight byte pool chunks */
|
||||||
#ifdef JERRY_CPOINTER_32_BIT
|
#ifdef JERRY_CPOINTER_32_BIT
|
||||||
@@ -84,7 +83,6 @@ typedef struct
|
|||||||
* causes call of "try give memory back" callbacks */
|
* causes call of "try give memory back" callbacks */
|
||||||
uint32_t lit_magic_string_ex_count; /**< external magic strings count */
|
uint32_t lit_magic_string_ex_count; /**< external magic strings count */
|
||||||
uint32_t jerry_init_flags; /**< run-time configuration flags */
|
uint32_t jerry_init_flags; /**< run-time configuration flags */
|
||||||
uint8_t ecma_gc_visited_flip_flag; /**< current state of an object's visited flag */
|
|
||||||
uint8_t is_direct_eval_form_call; /**< direct call from eval */
|
uint8_t is_direct_eval_form_call; /**< direct call from eval */
|
||||||
uint8_t jerry_api_available; /**< API availability flag */
|
uint8_t jerry_api_available; /**< API availability flag */
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user