mirror of
https://github.com/jerryscript-project/jerryscript.git
synced 2025-12-15 16:29:21 +00:00
Changing garbage collector to non-generational.
This commit is contained in:
parent
d1f6760f01
commit
a751ab4f9d
@ -37,9 +37,9 @@
|
||||
/**
|
||||
* Global lists of objects sorted by generation identifier.
|
||||
*/
|
||||
static ecma_object_t *ecma_gc_objects_lists[ ECMA_GC_GEN_COUNT ];
|
||||
static ecma_object_t *ecma_gc_objects_lists;
|
||||
|
||||
static void ecma_gc_mark (ecma_object_t *object_p, ecma_gc_gen_t maximum_gen_to_traverse);
|
||||
static void ecma_gc_mark (ecma_object_t *object_p);
|
||||
static void ecma_gc_sweep (ecma_object_t *object_p);
|
||||
|
||||
/**
|
||||
@ -70,39 +70,6 @@ ecma_gc_set_object_refs (ecma_object_t *object_p, /**< object */
|
||||
ECMA_OBJECT_GC_REFS_WIDTH);
|
||||
} /* ecma_gc_set_object_refs */
|
||||
|
||||
/**
|
||||
* Get GC generation of the object.
|
||||
*/
|
||||
static ecma_gc_gen_t
|
||||
ecma_gc_get_object_generation (ecma_object_t *object_p) /**< object */
|
||||
{
|
||||
JERRY_ASSERT (object_p != NULL);
|
||||
|
||||
ecma_gc_gen_t ret = (ecma_gc_gen_t) jrt_extract_bit_field (object_p->container,
|
||||
ECMA_OBJECT_GC_GENERATION_POS,
|
||||
ECMA_OBJECT_GC_GENERATION_WIDTH);
|
||||
|
||||
JERRY_ASSERT (ret < ECMA_GC_GEN_COUNT);
|
||||
|
||||
return ret;
|
||||
} /* ecma_gc_get_object_generation */
|
||||
|
||||
/**
|
||||
* Set GC generation of the object.
|
||||
*/
|
||||
static void
|
||||
ecma_gc_set_object_generation (ecma_object_t *object_p, /**< object */
|
||||
ecma_gc_gen_t generation) /**< generation */
|
||||
{
|
||||
JERRY_ASSERT (object_p != NULL);
|
||||
JERRY_ASSERT (generation < ECMA_GC_GEN_COUNT);
|
||||
|
||||
object_p->container = jrt_set_bit_field_value (object_p->container,
|
||||
generation,
|
||||
ECMA_OBJECT_GC_GENERATION_POS,
|
||||
ECMA_OBJECT_GC_GENERATION_WIDTH);
|
||||
} /* ecma_gc_set_object_generation */
|
||||
|
||||
/**
|
||||
* Get next object in list of objects with same generation.
|
||||
*/
|
||||
@ -167,34 +134,6 @@ ecma_gc_set_object_visited (ecma_object_t *object_p, /**< object */
|
||||
ECMA_OBJECT_GC_VISITED_WIDTH);
|
||||
} /* ecma_gc_set_object_visited */
|
||||
|
||||
/**
|
||||
* Get may_ref_younger_objects flag of the object.
|
||||
*/
|
||||
static bool
|
||||
ecma_gc_is_object_may_ref_younger_objects (ecma_object_t *object_p) /**< object */
|
||||
{
|
||||
JERRY_ASSERT (object_p != NULL);
|
||||
|
||||
return jrt_extract_bit_field (object_p->container,
|
||||
ECMA_OBJECT_GC_MAY_REF_YOUNGER_OBJECTS_POS,
|
||||
ECMA_OBJECT_GC_MAY_REF_YOUNGER_OBJECTS_WIDTH);
|
||||
} /* ecma_gc_is_object_may_ref_younger_objects */
|
||||
|
||||
/**
|
||||
* Set may_ref_younger_objects flag of the object.
|
||||
*/
|
||||
static void
|
||||
ecma_gc_set_object_may_ref_younger_objects (ecma_object_t *object_p, /**< object */
|
||||
bool is_may_ref_younger_objects) /**< flag value */
|
||||
{
|
||||
JERRY_ASSERT (object_p != NULL);
|
||||
|
||||
object_p->container = jrt_set_bit_field_value (object_p->container,
|
||||
is_may_ref_younger_objects,
|
||||
ECMA_OBJECT_GC_MAY_REF_YOUNGER_OBJECTS_POS,
|
||||
ECMA_OBJECT_GC_MAY_REF_YOUNGER_OBJECTS_WIDTH);
|
||||
} /* ecma_gc_set_object_may_ref_younger_objects */
|
||||
|
||||
/**
|
||||
* Initialize GC information for the object
|
||||
*/
|
||||
@ -203,14 +142,11 @@ ecma_init_gc_info (ecma_object_t *object_p) /**< object */
|
||||
{
|
||||
ecma_gc_set_object_refs (object_p, 1);
|
||||
|
||||
ecma_gc_set_object_generation (object_p, ECMA_GC_GEN_0);
|
||||
ecma_gc_set_object_next (object_p, ecma_gc_objects_lists[ ECMA_GC_GEN_0 ]);
|
||||
ecma_gc_objects_lists[ ECMA_GC_GEN_0 ] = object_p;
|
||||
ecma_gc_set_object_next (object_p, ecma_gc_objects_lists);
|
||||
ecma_gc_objects_lists = object_p;
|
||||
|
||||
/* Should be set to false at the beginning of garbage collection */
|
||||
ecma_gc_set_object_visited (object_p, true);
|
||||
|
||||
ecma_gc_set_object_may_ref_younger_objects (object_p, false);
|
||||
} /* ecma_init_gc_info */
|
||||
|
||||
/**
|
||||
@ -232,66 +168,25 @@ ecma_deref_object (ecma_object_t *object_p) /**< object */
|
||||
ecma_gc_set_object_refs (object_p, ecma_gc_get_object_refs (object_p) - 1);
|
||||
} /* ecma_deref_object */
|
||||
|
||||
/**
|
||||
* Set may_ref_younger_objects of specified object to true,
|
||||
* if value is object-value and it's object's generation
|
||||
* is less than generation of object specified by obj_p.
|
||||
*/
|
||||
void
|
||||
ecma_gc_update_may_ref_younger_object_flag_by_value (ecma_object_t *obj_p, /**< object */
|
||||
const ecma_value_t& value) /**< value */
|
||||
{
|
||||
if (!ecma_is_value_object (value))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
ecma_object_t *ref_obj_p = ecma_get_object_from_value (value);
|
||||
JERRY_ASSERT(ref_obj_p != NULL);
|
||||
|
||||
ecma_gc_update_may_ref_younger_object_flag_by_object (obj_p, ref_obj_p);
|
||||
} /* ecma_gc_update_may_ref_younger_object_flag_by_value */
|
||||
|
||||
void
|
||||
ecma_gc_update_may_ref_younger_object_flag_by_object (ecma_object_t *obj_p, /**< object */
|
||||
ecma_object_t *ref_obj_p) /**< referenced object
|
||||
or NULL */
|
||||
{
|
||||
if (ref_obj_p == NULL)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (ecma_gc_get_object_generation (ref_obj_p) < ecma_gc_get_object_generation (obj_p))
|
||||
{
|
||||
ecma_gc_set_object_may_ref_younger_objects (obj_p, true);
|
||||
}
|
||||
} /* ecma_gc_update_may_ref_younger_object_flag_by_object */
|
||||
|
||||
/**
|
||||
* Initialize garbage collector
|
||||
*/
|
||||
void
|
||||
ecma_gc_init (void)
|
||||
{
|
||||
memset (ecma_gc_objects_lists, 0, sizeof (ecma_gc_objects_lists));
|
||||
ecma_gc_objects_lists = NULL;
|
||||
} /* ecma_gc_init */
|
||||
|
||||
/**
|
||||
* Mark objects as visited starting from specified object as root
|
||||
* if referenced object's generation is less or equal to maximum_gen_to_traverse.
|
||||
*/
|
||||
void
|
||||
ecma_gc_mark (ecma_object_t *object_p, /**< start object */
|
||||
ecma_gc_gen_t maximum_gen_to_traverse) /**< start recursive traverse
|
||||
if referenced object generation
|
||||
is less or equal to maximum_gen_to_traverse */
|
||||
ecma_gc_mark (ecma_object_t *object_p) /**< start object */
|
||||
{
|
||||
JERRY_ASSERT(object_p != NULL);
|
||||
|
||||
ecma_gc_set_object_visited (object_p, true);
|
||||
|
||||
bool does_ref_a_younger_object = false;
|
||||
bool traverse_properties = true;
|
||||
|
||||
if (ecma_is_lexical_environment (object_p))
|
||||
@ -299,34 +194,18 @@ ecma_gc_mark (ecma_object_t *object_p, /**< start object */
|
||||
ecma_object_t *lex_env_p = ecma_get_lex_env_outer_reference (object_p);
|
||||
if (lex_env_p != NULL)
|
||||
{
|
||||
if (ecma_gc_get_object_generation (lex_env_p) <= maximum_gen_to_traverse)
|
||||
if (!ecma_gc_is_object_visited (lex_env_p))
|
||||
{
|
||||
if (!ecma_gc_is_object_visited (lex_env_p))
|
||||
{
|
||||
ecma_gc_mark (lex_env_p, ECMA_GC_GEN_COUNT);
|
||||
}
|
||||
}
|
||||
|
||||
if (ecma_gc_get_object_generation (lex_env_p) < ecma_gc_get_object_generation (object_p))
|
||||
{
|
||||
does_ref_a_younger_object = true;
|
||||
ecma_gc_mark (lex_env_p);
|
||||
}
|
||||
}
|
||||
|
||||
if (ecma_get_lex_env_type (object_p) == ECMA_LEXICAL_ENVIRONMENT_OBJECTBOUND)
|
||||
{
|
||||
ecma_object_t *binding_object_p = ecma_get_lex_env_binding_object (object_p);
|
||||
if (ecma_gc_get_object_generation (binding_object_p) <= maximum_gen_to_traverse)
|
||||
if (!ecma_gc_is_object_visited (binding_object_p))
|
||||
{
|
||||
if (!ecma_gc_is_object_visited (binding_object_p))
|
||||
{
|
||||
ecma_gc_mark (binding_object_p, ECMA_GC_GEN_COUNT);
|
||||
}
|
||||
}
|
||||
|
||||
if (ecma_gc_get_object_generation (binding_object_p) < ecma_gc_get_object_generation (object_p))
|
||||
{
|
||||
does_ref_a_younger_object = true;
|
||||
ecma_gc_mark (binding_object_p);
|
||||
}
|
||||
|
||||
traverse_properties = false;
|
||||
@ -337,17 +216,9 @@ ecma_gc_mark (ecma_object_t *object_p, /**< start object */
|
||||
ecma_object_t *proto_p = ecma_get_object_prototype (object_p);
|
||||
if (proto_p != NULL)
|
||||
{
|
||||
if (ecma_gc_get_object_generation (proto_p) <= maximum_gen_to_traverse)
|
||||
if (!ecma_gc_is_object_visited (proto_p))
|
||||
{
|
||||
if (!ecma_gc_is_object_visited (proto_p))
|
||||
{
|
||||
ecma_gc_mark (proto_p, ECMA_GC_GEN_COUNT);
|
||||
}
|
||||
}
|
||||
|
||||
if (ecma_gc_get_object_generation (proto_p) < ecma_gc_get_object_generation (object_p))
|
||||
{
|
||||
does_ref_a_younger_object = true;
|
||||
ecma_gc_mark (proto_p);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -371,17 +242,9 @@ ecma_gc_mark (ecma_object_t *object_p, /**< start object */
|
||||
{
|
||||
ecma_object_t *value_obj_p = ecma_get_object_from_value (value);
|
||||
|
||||
if (ecma_gc_get_object_generation (value_obj_p) <= maximum_gen_to_traverse)
|
||||
if (!ecma_gc_is_object_visited (value_obj_p))
|
||||
{
|
||||
if (!ecma_gc_is_object_visited (value_obj_p))
|
||||
{
|
||||
ecma_gc_mark (value_obj_p, ECMA_GC_GEN_COUNT);
|
||||
}
|
||||
}
|
||||
|
||||
if (ecma_gc_get_object_generation (value_obj_p) < ecma_gc_get_object_generation (object_p))
|
||||
{
|
||||
does_ref_a_younger_object = true;
|
||||
ecma_gc_mark (value_obj_p);
|
||||
}
|
||||
}
|
||||
|
||||
@ -395,33 +258,17 @@ ecma_gc_mark (ecma_object_t *object_p, /**< start object */
|
||||
|
||||
if (getter_obj_p != NULL)
|
||||
{
|
||||
if (ecma_gc_get_object_generation (getter_obj_p) <= maximum_gen_to_traverse)
|
||||
if (!ecma_gc_is_object_visited (getter_obj_p))
|
||||
{
|
||||
if (!ecma_gc_is_object_visited (getter_obj_p))
|
||||
{
|
||||
ecma_gc_mark (getter_obj_p, ECMA_GC_GEN_COUNT);
|
||||
}
|
||||
}
|
||||
|
||||
if (ecma_gc_get_object_generation (getter_obj_p) < ecma_gc_get_object_generation (object_p))
|
||||
{
|
||||
does_ref_a_younger_object = true;
|
||||
ecma_gc_mark (getter_obj_p);
|
||||
}
|
||||
}
|
||||
|
||||
if (setter_obj_p != NULL)
|
||||
{
|
||||
if (ecma_gc_get_object_generation (setter_obj_p) <= maximum_gen_to_traverse)
|
||||
if (!ecma_gc_is_object_visited (setter_obj_p))
|
||||
{
|
||||
if (!ecma_gc_is_object_visited (setter_obj_p))
|
||||
{
|
||||
ecma_gc_mark (setter_obj_p, ECMA_GC_GEN_COUNT);
|
||||
}
|
||||
}
|
||||
|
||||
if (ecma_gc_get_object_generation (setter_obj_p) < ecma_gc_get_object_generation (object_p))
|
||||
{
|
||||
does_ref_a_younger_object = true;
|
||||
ecma_gc_mark (setter_obj_p);
|
||||
}
|
||||
}
|
||||
|
||||
@ -470,17 +317,9 @@ ecma_gc_mark (ecma_object_t *object_p, /**< start object */
|
||||
{
|
||||
ecma_object_t *obj_p = ECMA_GET_NON_NULL_POINTER(ecma_object_t, property_value);
|
||||
|
||||
if (ecma_gc_get_object_generation (obj_p) <= maximum_gen_to_traverse)
|
||||
if (!ecma_gc_is_object_visited (obj_p))
|
||||
{
|
||||
if (!ecma_gc_is_object_visited (obj_p))
|
||||
{
|
||||
ecma_gc_mark (obj_p, ECMA_GC_GEN_COUNT);
|
||||
}
|
||||
}
|
||||
|
||||
if (ecma_gc_get_object_generation (obj_p) < ecma_gc_get_object_generation (object_p))
|
||||
{
|
||||
does_ref_a_younger_object = true;
|
||||
ecma_gc_mark (obj_p);
|
||||
}
|
||||
|
||||
break;
|
||||
@ -492,11 +331,6 @@ ecma_gc_mark (ecma_object_t *object_p, /**< start object */
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!does_ref_a_younger_object)
|
||||
{
|
||||
ecma_gc_set_object_may_ref_younger_objects (object_p, false);
|
||||
}
|
||||
} /* ecma_gc_mark */
|
||||
|
||||
/**
|
||||
@ -530,34 +364,26 @@ ecma_gc_sweep (ecma_object_t *object_p) /**< object to free */
|
||||
* Run garbage collecting
|
||||
*/
|
||||
void
|
||||
ecma_gc_run (ecma_gc_gen_t max_gen_to_collect) /**< maximum generation to run collection on */
|
||||
ecma_gc_run (void)
|
||||
{
|
||||
JERRY_ASSERT(max_gen_to_collect < ECMA_GC_GEN_COUNT);
|
||||
|
||||
/* clearing visited flags for all objects of generations to be processed */
|
||||
for (ecma_gc_gen_t gen_id = ECMA_GC_GEN_0; gen_id <= max_gen_to_collect; gen_id = (ecma_gc_gen_t) (gen_id + 1))
|
||||
for (ecma_object_t *obj_iter_p = ecma_gc_objects_lists;
|
||||
obj_iter_p != NULL;
|
||||
obj_iter_p = ecma_gc_get_object_next (obj_iter_p))
|
||||
{
|
||||
for (ecma_object_t *obj_iter_p = ecma_gc_objects_lists[ gen_id ];
|
||||
obj_iter_p != NULL;
|
||||
obj_iter_p = ecma_gc_get_object_next (obj_iter_p))
|
||||
{
|
||||
ecma_gc_set_object_visited (obj_iter_p, false);
|
||||
}
|
||||
ecma_gc_set_object_visited (obj_iter_p, false);
|
||||
}
|
||||
|
||||
/* if some object is referenced from stack or globals (i.e. it is root),
|
||||
* start recursive marking traverse from the object */
|
||||
for (ecma_gc_gen_t gen_id = ECMA_GC_GEN_0; gen_id <= max_gen_to_collect; gen_id = (ecma_gc_gen_t) (gen_id + 1))
|
||||
for (ecma_object_t *obj_iter_p = ecma_gc_objects_lists;
|
||||
obj_iter_p != NULL;
|
||||
obj_iter_p = ecma_gc_get_object_next (obj_iter_p))
|
||||
{
|
||||
for (ecma_object_t *obj_iter_p = ecma_gc_objects_lists[ gen_id ];
|
||||
obj_iter_p != NULL;
|
||||
obj_iter_p = ecma_gc_get_object_next (obj_iter_p))
|
||||
if (ecma_gc_get_object_refs (obj_iter_p) > 0
|
||||
&& !ecma_gc_is_object_visited (obj_iter_p))
|
||||
{
|
||||
if (ecma_gc_get_object_refs (obj_iter_p) > 0
|
||||
&& !ecma_gc_is_object_visited (obj_iter_p))
|
||||
{
|
||||
ecma_gc_mark (obj_iter_p, ECMA_GC_GEN_COUNT);
|
||||
}
|
||||
ecma_gc_mark (obj_iter_p);
|
||||
}
|
||||
}
|
||||
|
||||
@ -577,119 +403,36 @@ ecma_gc_run (ecma_gc_gen_t max_gen_to_collect) /**< maximum generation to run co
|
||||
|
||||
if (!ecma_gc_is_object_visited (obj_p))
|
||||
{
|
||||
ecma_gc_mark (obj_p, ECMA_GC_GEN_COUNT);
|
||||
ecma_gc_mark (obj_p);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* if some object from generations that are not processed during current session may reference
|
||||
* younger generations, start recursive marking traverse from the object, but one the first level
|
||||
* consider only references to object of at most max_gen_to_collect generation */
|
||||
for (ecma_gc_gen_t gen_id = (ecma_gc_gen_t) (max_gen_to_collect + 1);
|
||||
gen_id < ECMA_GC_GEN_COUNT;
|
||||
gen_id = (ecma_gc_gen_t) (gen_id + 1))
|
||||
for (ecma_object_t *obj_iter_p = ecma_gc_objects_lists, *obj_prev_p = NULL, *obj_next_p;
|
||||
obj_iter_p != NULL;
|
||||
obj_iter_p = obj_next_p)
|
||||
{
|
||||
for (ecma_object_t *obj_iter_p = ecma_gc_objects_lists[ gen_id ];
|
||||
obj_iter_p != NULL;
|
||||
obj_iter_p = ecma_gc_get_object_next (obj_iter_p))
|
||||
obj_next_p = ecma_gc_get_object_next (obj_iter_p);
|
||||
|
||||
if (!ecma_gc_is_object_visited (obj_iter_p))
|
||||
{
|
||||
if (ecma_gc_is_object_may_ref_younger_objects (obj_iter_p))
|
||||
ecma_gc_sweep (obj_iter_p);
|
||||
|
||||
if (likely (obj_prev_p != NULL))
|
||||
{
|
||||
ecma_gc_mark (obj_iter_p, max_gen_to_collect);
|
||||
}
|
||||
#ifndef JERRY_NDEBUG
|
||||
else if (gen_id > ECMA_GC_GEN_0)
|
||||
{
|
||||
ecma_gc_set_object_may_ref_younger_objects (obj_iter_p, true);
|
||||
ecma_gc_mark (obj_iter_p, (ecma_gc_gen_t) (gen_id - 1));
|
||||
JERRY_ASSERT (!ecma_gc_is_object_may_ref_younger_objects (obj_iter_p));
|
||||
}
|
||||
#endif /* !JERRY_NDEBUG */
|
||||
}
|
||||
}
|
||||
|
||||
JERRY_ASSERT (max_gen_to_collect <= ECMA_GC_GEN_COUNT);
|
||||
ecma_object_t *gen_last_obj_p[ ECMA_GC_GEN_COUNT ];
|
||||
#ifndef JERRY_NDEBUG
|
||||
memset (gen_last_obj_p, 0, sizeof (gen_last_obj_p));
|
||||
#endif /* !JERRY_NDEBUG */
|
||||
|
||||
for (ecma_gc_gen_t gen_id = ECMA_GC_GEN_0; gen_id <= max_gen_to_collect; gen_id = (ecma_gc_gen_t) (gen_id + 1))
|
||||
{
|
||||
ecma_object_t *obj_prev_p = NULL;
|
||||
|
||||
for (ecma_object_t *obj_iter_p = ecma_gc_objects_lists[ gen_id ],
|
||||
*obj_next_p;
|
||||
obj_iter_p != NULL;
|
||||
obj_iter_p = obj_next_p)
|
||||
{
|
||||
obj_next_p = ecma_gc_get_object_next (obj_iter_p);
|
||||
|
||||
if (!ecma_gc_is_object_visited (obj_iter_p))
|
||||
{
|
||||
ecma_gc_sweep (obj_iter_p);
|
||||
|
||||
if (likely (obj_prev_p != NULL))
|
||||
{
|
||||
ecma_gc_set_object_next (obj_prev_p, obj_next_p);
|
||||
}
|
||||
else
|
||||
{
|
||||
ecma_gc_objects_lists[ gen_id ] = obj_next_p;
|
||||
}
|
||||
ecma_gc_set_object_next (obj_prev_p, obj_next_p);
|
||||
}
|
||||
else
|
||||
{
|
||||
obj_prev_p = obj_iter_p;
|
||||
|
||||
if (ecma_gc_get_object_generation (obj_iter_p) != ECMA_GC_GEN_COUNT - 1)
|
||||
{
|
||||
/* the object will be promoted to next generation */
|
||||
ecma_gc_set_object_generation (obj_iter_p, (ecma_gc_gen_t) (ecma_gc_get_object_generation (obj_iter_p) + 1));
|
||||
}
|
||||
ecma_gc_objects_lists = obj_next_p;
|
||||
}
|
||||
}
|
||||
|
||||
gen_last_obj_p[ gen_id ] = obj_prev_p;
|
||||
}
|
||||
|
||||
ecma_gc_gen_t gen_to_promote = max_gen_to_collect;
|
||||
if (unlikely (gen_to_promote == ECMA_GC_GEN_COUNT - 1))
|
||||
{
|
||||
/* not promoting last generation */
|
||||
gen_to_promote = (ecma_gc_gen_t) (gen_to_promote - 1);
|
||||
}
|
||||
|
||||
/* promoting to next generation */
|
||||
if (gen_last_obj_p[ gen_to_promote ] != NULL)
|
||||
{
|
||||
ecma_gc_set_object_next (gen_last_obj_p [gen_to_promote], ecma_gc_objects_lists[ gen_to_promote + 1 ]);
|
||||
ecma_gc_objects_lists[ gen_to_promote + 1 ] = ecma_gc_objects_lists[ gen_to_promote ];
|
||||
ecma_gc_objects_lists[ gen_to_promote ] = NULL;
|
||||
}
|
||||
|
||||
for (int32_t gen_id = (int32_t)gen_to_promote - 1;
|
||||
gen_id >= 0;
|
||||
gen_id--)
|
||||
{
|
||||
ecma_gc_objects_lists[ gen_id + 1 ] = ecma_gc_objects_lists[ gen_id ];
|
||||
ecma_gc_objects_lists[ gen_id ] = NULL;
|
||||
}
|
||||
|
||||
#ifndef JERRY_NDEBUG
|
||||
for (ecma_gc_gen_t gen_id = ECMA_GC_GEN_0;
|
||||
gen_id < ECMA_GC_GEN_COUNT;
|
||||
gen_id = (ecma_gc_gen_t) (gen_id + 1))
|
||||
{
|
||||
for (ecma_object_t *obj_iter_p = ecma_gc_objects_lists[ gen_id ];
|
||||
obj_iter_p != NULL;
|
||||
obj_iter_p = ecma_gc_get_object_next (obj_iter_p))
|
||||
else
|
||||
{
|
||||
JERRY_ASSERT(ecma_gc_get_object_generation (obj_iter_p) == gen_id);
|
||||
obj_prev_p = obj_iter_p;
|
||||
}
|
||||
}
|
||||
#endif /* !JERRY_NDEBUG */
|
||||
} /* ecma_gc_run */
|
||||
|
||||
/**
|
||||
@ -701,15 +444,12 @@ ecma_try_to_give_back_some_memory (mem_try_give_memory_back_severity_t severity)
|
||||
{
|
||||
if (severity == MEM_TRY_GIVE_MEMORY_BACK_SEVERITY_LOW)
|
||||
{
|
||||
ecma_gc_run (ECMA_GC_GEN_0);
|
||||
ecma_gc_run ();
|
||||
}
|
||||
else if (severity == MEM_TRY_GIVE_MEMORY_BACK_SEVERITY_MEDIUM)
|
||||
else if (severity == MEM_TRY_GIVE_MEMORY_BACK_SEVERITY_MEDIUM
|
||||
|| severity == MEM_TRY_GIVE_MEMORY_BACK_SEVERITY_HIGH)
|
||||
{
|
||||
ecma_gc_run (ECMA_GC_GEN_1);
|
||||
}
|
||||
else if (severity == MEM_TRY_GIVE_MEMORY_BACK_SEVERITY_HIGH)
|
||||
{
|
||||
ecma_gc_run (ECMA_GC_GEN_2);
|
||||
/* we have already done simple GC as requests come in ascending severity order */
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -718,7 +458,7 @@ ecma_try_to_give_back_some_memory (mem_try_give_memory_back_severity_t severity)
|
||||
/* Freeing as much memory as we currently can */
|
||||
ecma_lcache_invalidate_all ();
|
||||
|
||||
ecma_gc_run ((ecma_gc_gen_t) (ECMA_GC_GEN_COUNT - 1));
|
||||
ecma_gc_run ();
|
||||
}
|
||||
} /* ecma_try_to_give_back_some_memory */
|
||||
|
||||
|
||||
@ -26,24 +26,11 @@
|
||||
#include "ecma-globals.h"
|
||||
#include "mem-allocator.h"
|
||||
|
||||
/**
|
||||
* GC generation identifier
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
ECMA_GC_GEN_0, /**< generation 0 */
|
||||
ECMA_GC_GEN_1, /**< generation 1 */
|
||||
ECMA_GC_GEN_2, /**< generation 2 */
|
||||
ECMA_GC_GEN_COUNT /**< generations' number */
|
||||
} ecma_gc_gen_t;
|
||||
|
||||
extern void ecma_gc_init (void);
|
||||
extern void ecma_init_gc_info (ecma_object_t *object_p);
|
||||
extern void ecma_ref_object (ecma_object_t *object_p);
|
||||
extern void ecma_deref_object (ecma_object_t *object_p);
|
||||
extern void ecma_gc_update_may_ref_younger_object_flag_by_value (ecma_object_t *obj_p, const ecma_value_t& value);
|
||||
extern void ecma_gc_update_may_ref_younger_object_flag_by_object (ecma_object_t *obj_p, ecma_object_t *ref_obj_p);
|
||||
extern void ecma_gc_run (ecma_gc_gen_t max_gen_to_collect);
|
||||
extern void ecma_gc_run (void);
|
||||
extern void ecma_try_to_give_back_some_memory (mem_try_give_memory_back_severity_t severity);
|
||||
|
||||
#endif /* !ECMA_GC_H */
|
||||
|
||||
@ -400,18 +400,11 @@ typedef struct
|
||||
ECMA_OBJECT_IS_LEXICAL_ENVIRONMENT_WIDTH)
|
||||
#define ECMA_OBJECT_GC_REFS_WIDTH (CONFIG_ECMA_REFERENCE_COUNTER_WIDTH)
|
||||
|
||||
/**
|
||||
* Identifier of GC generation.
|
||||
*/
|
||||
#define ECMA_OBJECT_GC_GENERATION_POS (ECMA_OBJECT_GC_REFS_POS + \
|
||||
ECMA_OBJECT_GC_REFS_WIDTH)
|
||||
#define ECMA_OBJECT_GC_GENERATION_WIDTH (2)
|
||||
|
||||
/**
|
||||
* Compressed pointer to next object in the global list of objects with same generation.
|
||||
*/
|
||||
#define ECMA_OBJECT_GC_NEXT_CP_POS (ECMA_OBJECT_GC_GENERATION_POS + \
|
||||
ECMA_OBJECT_GC_GENERATION_WIDTH)
|
||||
#define ECMA_OBJECT_GC_NEXT_CP_POS (ECMA_OBJECT_GC_REFS_POS + \
|
||||
ECMA_OBJECT_GC_REFS_WIDTH)
|
||||
#define ECMA_OBJECT_GC_NEXT_CP_WIDTH (ECMA_POINTER_FIELD_WIDTH)
|
||||
|
||||
/**
|
||||
@ -434,8 +427,8 @@ typedef struct
|
||||
/**
|
||||
* Attribute 'Extensible'
|
||||
*/
|
||||
#define ECMA_OBJECT_OBJ_EXTENSIBLE_POS (ECMA_OBJECT_GC_MAY_REF_YOUNGER_OBJECTS_POS + \
|
||||
ECMA_OBJECT_GC_MAY_REF_YOUNGER_OBJECTS_WIDTH)
|
||||
#define ECMA_OBJECT_OBJ_EXTENSIBLE_POS (ECMA_OBJECT_GC_VISITED_POS + \
|
||||
ECMA_OBJECT_GC_VISITED_WIDTH)
|
||||
#define ECMA_OBJECT_OBJ_EXTENSIBLE_WIDTH (1)
|
||||
|
||||
/**
|
||||
@ -471,8 +464,8 @@ typedef struct
|
||||
/**
|
||||
* Type of lexical environment (ecma_lexical_environment_type_t).
|
||||
*/
|
||||
#define ECMA_OBJECT_LEX_ENV_TYPE_POS (ECMA_OBJECT_GC_MAY_REF_YOUNGER_OBJECTS_POS + \
|
||||
ECMA_OBJECT_GC_MAY_REF_YOUNGER_OBJECTS_WIDTH)
|
||||
#define ECMA_OBJECT_LEX_ENV_TYPE_POS (ECMA_OBJECT_GC_VISITED_POS + \
|
||||
ECMA_OBJECT_GC_VISITED_WIDTH)
|
||||
#define ECMA_OBJECT_LEX_ENV_TYPE_WIDTH (1)
|
||||
|
||||
/**
|
||||
|
||||
@ -695,7 +695,7 @@ ecma_copy_or_ref_ecma_string (ecma_string_t *string_desc_p) /**< string descript
|
||||
|
||||
/* First trying to free unreachable objects that maybe refer to the string */
|
||||
ecma_lcache_invalidate_all ();
|
||||
ecma_gc_run ((ecma_gc_gen_t) (ECMA_GC_GEN_COUNT - 1));
|
||||
ecma_gc_run ();
|
||||
|
||||
if (current_refs == string_desc_p->refs)
|
||||
{
|
||||
|
||||
@ -69,7 +69,6 @@ ecma_create_object (ecma_object_t *prototype_object_p, /**< pointer to prototybe
|
||||
prototype_object_cp,
|
||||
ECMA_OBJECT_OBJ_PROTOTYPE_OBJECT_CP_POS,
|
||||
ECMA_OBJECT_OBJ_PROTOTYPE_OBJECT_CP_WIDTH);
|
||||
ecma_gc_update_may_ref_younger_object_flag_by_object (object_p, prototype_object_p);
|
||||
|
||||
ecma_set_object_is_builtin (object_p, false);
|
||||
|
||||
@ -113,7 +112,6 @@ ecma_create_decl_lex_env (ecma_object_t *outer_lexical_environment_p) /**< outer
|
||||
outer_reference_cp,
|
||||
ECMA_OBJECT_LEX_ENV_OUTER_REFERENCE_CP_POS,
|
||||
ECMA_OBJECT_LEX_ENV_OUTER_REFERENCE_CP_WIDTH);
|
||||
ecma_gc_update_may_ref_younger_object_flag_by_object (new_lexical_environment_p, outer_lexical_environment_p);
|
||||
|
||||
/*
|
||||
* Declarative lexical environments do not really have the flag,
|
||||
@ -165,7 +163,6 @@ ecma_create_object_lex_env (ecma_object_t *outer_lexical_environment_p, /**< out
|
||||
outer_reference_cp,
|
||||
ECMA_OBJECT_LEX_ENV_OUTER_REFERENCE_CP_POS,
|
||||
ECMA_OBJECT_LEX_ENV_OUTER_REFERENCE_CP_WIDTH);
|
||||
ecma_gc_update_may_ref_younger_object_flag_by_object (new_lexical_environment_p, outer_lexical_environment_p);
|
||||
|
||||
new_lexical_environment_p->container = jrt_set_bit_field_value (new_lexical_environment_p->container,
|
||||
provide_this,
|
||||
@ -178,7 +175,6 @@ ecma_create_object_lex_env (ecma_object_t *outer_lexical_environment_p, /**< out
|
||||
bound_object_cp,
|
||||
ECMA_OBJECT_PROPERTIES_OR_BOUND_OBJECT_CP_POS,
|
||||
ECMA_OBJECT_PROPERTIES_OR_BOUND_OBJECT_CP_WIDTH);
|
||||
ecma_gc_update_may_ref_younger_object_flag_by_object (new_lexical_environment_p, binding_obj_p);
|
||||
|
||||
return new_lexical_environment_p;
|
||||
} /* ecma_create_object_lex_env */
|
||||
@ -950,8 +946,6 @@ ecma_named_data_property_assign_value (ecma_object_t *obj_p, /**< object */
|
||||
ecma_free_value (v, false);
|
||||
|
||||
prop_p->u.named_data_property.value = ecma_copy_value (value, false);
|
||||
ecma_gc_update_may_ref_younger_object_flag_by_value (obj_p,
|
||||
prop_p->u.named_data_property.value);
|
||||
}
|
||||
} /* ecma_named_data_property_assign_value */
|
||||
|
||||
@ -993,8 +987,6 @@ ecma_set_named_accessor_property_getter (ecma_object_t* object_p, /**< the prope
|
||||
ecma_assert_object_contains_the_property (object_p, prop_p);
|
||||
|
||||
ECMA_SET_POINTER (prop_p->u.named_accessor_property.get_p, getter_p);
|
||||
|
||||
ecma_gc_update_may_ref_younger_object_flag_by_object (object_p, getter_p);
|
||||
} /* ecma_named_accessor_property_set_getter */
|
||||
|
||||
/**
|
||||
@ -1009,8 +1001,6 @@ ecma_set_named_accessor_property_setter (ecma_object_t* object_p, /**< the prope
|
||||
ecma_assert_object_contains_the_property (object_p, prop_p);
|
||||
|
||||
ECMA_SET_POINTER (prop_p->u.named_accessor_property.set_p, setter_p);
|
||||
|
||||
ecma_gc_update_may_ref_younger_object_flag_by_object (object_p, setter_p);
|
||||
} /* ecma_named_accessor_property_set_setter */
|
||||
|
||||
/**
|
||||
|
||||
@ -162,7 +162,6 @@ ecma_op_create_function_object (ecma_string_t* formal_parameter_list_p[], /**< f
|
||||
// 9.
|
||||
ecma_property_t *scope_prop_p = ecma_create_internal_property (f, ECMA_INTERNAL_PROPERTY_SCOPE);
|
||||
ECMA_SET_POINTER(scope_prop_p->u.internal_property.value, scope_p);
|
||||
ecma_gc_update_may_ref_younger_object_flag_by_object (f, scope_p);
|
||||
|
||||
// 10., 11.
|
||||
ecma_property_t *formal_parameters_prop_p = ecma_create_internal_property (f,
|
||||
|
||||
@ -53,7 +53,7 @@ ecma_finalize (void)
|
||||
ecma_stack_finalize ();
|
||||
ecma_finalize_builtins ();
|
||||
ecma_lcache_invalidate_all ();
|
||||
ecma_gc_run ((ecma_gc_gen_t) (ECMA_GC_GEN_COUNT - 1));
|
||||
ecma_gc_run ();
|
||||
} /* ecma_finalize */
|
||||
|
||||
/**
|
||||
|
||||
@ -193,12 +193,10 @@ ecma_create_arguments_object (ecma_object_t *func_obj_p, /**< callee function */
|
||||
ecma_property_t *parameters_map_prop_p = ecma_create_internal_property (obj_p,
|
||||
ECMA_INTERNAL_PROPERTY_PARAMETERS_MAP);
|
||||
ECMA_SET_POINTER(parameters_map_prop_p->u.internal_property.value, map_p);
|
||||
ecma_gc_update_may_ref_younger_object_flag_by_object (obj_p, map_p);
|
||||
|
||||
ecma_property_t *scope_prop_p = ecma_create_internal_property (map_p,
|
||||
ECMA_INTERNAL_PROPERTY_SCOPE);
|
||||
ECMA_SET_POINTER(scope_prop_p->u.internal_property.value, lex_env_p);
|
||||
ecma_gc_update_may_ref_younger_object_flag_by_object (map_p, lex_env_p);
|
||||
|
||||
ecma_deref_object (map_p);
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user