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:
Zoltan Herczeg
2017-09-29 16:15:13 +02:00
committed by GitHub
parent 6d53931055
commit 29ea702fa4
4 changed files with 115 additions and 126 deletions
+100 -81
View File
@@ -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 */
+12 -34
View File
@@ -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
/** /**
+2 -8
View File
@@ -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.
+1 -3
View File
@@ -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 */