Skip to content

Move GC, lcache, literal storage, lexical env global variables to jerry context. #1219

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Jul 25, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
116 changes: 48 additions & 68 deletions jerry-core/ecma/base/ecma-gc.c
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
#include "ecma-helpers.h"
#include "ecma-lcache.h"
#include "ecma-property-hashmap.h"
#include "jcontext.h"
#include "jrt.h"
#include "jrt-libc-includes.h"
#include "jrt-bit-fields.h"
Expand All @@ -44,44 +45,15 @@
*/

/**
* An object's GC color
* Current state of an object's visited flag that
* indicates whether the object is in visited state:
*
* 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;

/**
* List of marked (visited during current GC session) and umarked objects
*/
static ecma_object_t *ecma_gc_objects_lists[ECMA_GC_COLOR__COUNT];

/**
* Current state of an object's visited flag that indicates whether the object is in visited state:
* visited_field | visited_flip_flag | real_value
* false | false | false
* false | true | true
* true | false | true
* true | true | false
*/
static bool ecma_gc_visited_flip_flag = false;

/**
* Number of currently allocated objects
*/
static size_t ecma_gc_objects_number = 0;

/**
* Number of newly allocated objects since last GC session
*/
static size_t ecma_gc_new_objects_since_last_gc = 0;

static void ecma_gc_mark (ecma_object_t *object_p);
static void ecma_gc_sweep (ecma_object_t *object_p);
Expand Down Expand Up @@ -119,7 +91,7 @@ ecma_gc_is_object_visited (ecma_object_t *object_p) /**< object */

bool flag_value = (object_p->type_flags_refs & ECMA_OBJECT_FLAG_GC_VISITED) != 0;

return flag_value != ecma_gc_visited_flip_flag;
return flag_value != JERRY_CONTEXT (ecma_gc_visited_flip_flag);
} /* ecma_gc_is_object_visited */

/**
Expand All @@ -131,7 +103,7 @@ ecma_gc_set_object_visited (ecma_object_t *object_p, /**< object */
{
JERRY_ASSERT (object_p != NULL);

if (is_visited != ecma_gc_visited_flip_flag)
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);
}
Expand All @@ -147,16 +119,16 @@ ecma_gc_set_object_visited (ecma_object_t *object_p, /**< object */
inline void
ecma_init_gc_info (ecma_object_t *object_p) /**< object */
{
ecma_gc_objects_number++;
ecma_gc_new_objects_since_last_gc++;
JERRY_CONTEXT (ecma_gc_objects_number)++;
JERRY_CONTEXT (ecma_gc_new_objects)++;

JERRY_ASSERT (ecma_gc_new_objects_since_last_gc <= ecma_gc_objects_number);
JERRY_ASSERT (JERRY_CONTEXT (ecma_gc_new_objects) <= JERRY_CONTEXT (ecma_gc_objects_number));

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);

ecma_gc_set_object_next (object_p, ecma_gc_objects_lists[ECMA_GC_COLOR_WHITE_GRAY]);
ecma_gc_objects_lists[ECMA_GC_COLOR_WHITE_GRAY] = object_p;
ecma_gc_set_object_next (object_p, JERRY_CONTEXT (ecma_gc_objects_lists) [ECMA_GC_COLOR_WHITE_GRAY]);
JERRY_CONTEXT (ecma_gc_objects_lists) [ECMA_GC_COLOR_WHITE_GRAY] = object_p;

/* Should be set to false at the beginning of garbage collection */
ecma_gc_set_object_visited (object_p, false);
Expand Down Expand Up @@ -194,11 +166,11 @@ ecma_deref_object (ecma_object_t *object_p) /**< object */
void
ecma_gc_init (void)
{
ecma_gc_objects_lists[ECMA_GC_COLOR_WHITE_GRAY] = NULL;
ecma_gc_objects_lists[ECMA_GC_COLOR_BLACK] = NULL;
ecma_gc_visited_flip_flag = false;
ecma_gc_objects_number = 0;
ecma_gc_new_objects_since_last_gc = 0;
JERRY_CONTEXT (ecma_gc_objects_lists) [ECMA_GC_COLOR_WHITE_GRAY] = NULL;
JERRY_CONTEXT (ecma_gc_objects_lists) [ECMA_GC_COLOR_BLACK] = NULL;
JERRY_CONTEXT (ecma_gc_visited_flip_flag) = false;
JERRY_CONTEXT (ecma_gc_objects_number) = 0;
JERRY_CONTEXT (ecma_gc_new_objects) = 0;
} /* ecma_gc_init */

/**
Expand Down Expand Up @@ -474,8 +446,8 @@ ecma_gc_sweep (ecma_object_t *object_p) /**< object to free */
}
}

JERRY_ASSERT (ecma_gc_objects_number > 0);
ecma_gc_objects_number--;
JERRY_ASSERT (JERRY_CONTEXT (ecma_gc_objects_number) > 0);
JERRY_CONTEXT (ecma_gc_objects_number)--;

if (!ecma_is_lexical_environment (object_p))
{
Expand Down Expand Up @@ -508,12 +480,12 @@ ecma_gc_sweep (ecma_object_t *object_p) /**< object to free */
void
ecma_gc_run (jmem_free_unused_memory_severity_t severity) /**< gc severity */
{
ecma_gc_new_objects_since_last_gc = 0;
JERRY_CONTEXT (ecma_gc_new_objects) = 0;

JERRY_ASSERT (ecma_gc_objects_lists[ECMA_GC_COLOR_BLACK] == NULL);
JERRY_ASSERT (JERRY_CONTEXT (ecma_gc_objects_lists) [ECMA_GC_COLOR_BLACK] == NULL);

/* if some object is referenced from stack or globals (i.e. it is root), mark it */
for (ecma_object_t *obj_iter_p = ecma_gc_objects_lists[ECMA_GC_COLOR_WHITE_GRAY];
for (ecma_object_t *obj_iter_p = JERRY_CONTEXT (ecma_gc_objects_lists) [ECMA_GC_COLOR_WHITE_GRAY];
obj_iter_p != NULL;
obj_iter_p = ecma_gc_get_object_next (obj_iter_p))
{
Expand All @@ -531,17 +503,18 @@ ecma_gc_run (jmem_free_unused_memory_severity_t severity) /**< gc severity */
{
marked_anything_during_current_iteration = false;

for (ecma_object_t *obj_iter_p = ecma_gc_objects_lists[ECMA_GC_COLOR_WHITE_GRAY], *obj_prev_p = NULL, *obj_next_p;
obj_iter_p != NULL;
obj_iter_p = obj_next_p)
ecma_object_t *obj_prev_p = NULL;
ecma_object_t *obj_iter_p = JERRY_CONTEXT (ecma_gc_objects_lists) [ECMA_GC_COLOR_WHITE_GRAY];

while (obj_iter_p != NULL)
{
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);

if (ecma_gc_is_object_visited (obj_iter_p))
{
/* Moving the object to list of marked objects */
ecma_gc_set_object_next (obj_iter_p, ecma_gc_objects_lists[ECMA_GC_COLOR_BLACK]);
ecma_gc_objects_lists[ECMA_GC_COLOR_BLACK] = obj_iter_p;
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))
{
Expand All @@ -551,7 +524,7 @@ ecma_gc_run (jmem_free_unused_memory_severity_t severity) /**< gc severity */
}
else
{
ecma_gc_objects_lists[ECMA_GC_COLOR_WHITE_GRAY] = obj_next_p;
JERRY_CONTEXT (ecma_gc_objects_lists) [ECMA_GC_COLOR_WHITE_GRAY] = obj_next_p;
}

ecma_gc_mark (obj_iter_p);
Expand All @@ -561,47 +534,52 @@ ecma_gc_run (jmem_free_unused_memory_severity_t severity) /**< gc severity */
{
obj_prev_p = obj_iter_p;
}

obj_iter_p = obj_next_p;
}
}
while (marked_anything_during_current_iteration);

/* Sweeping objects that are currently unmarked */
for (ecma_object_t *obj_iter_p = ecma_gc_objects_lists[ECMA_GC_COLOR_WHITE_GRAY], *obj_next_p;
obj_iter_p != NULL;
obj_iter_p = obj_next_p)
ecma_object_t *obj_iter_p = JERRY_CONTEXT (ecma_gc_objects_lists) [ECMA_GC_COLOR_WHITE_GRAY];

while (obj_iter_p != NULL)
{
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 (!ecma_gc_is_object_visited (obj_iter_p));

ecma_gc_sweep (obj_iter_p);
obj_iter_p = obj_next_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);
obj_iter_p = JERRY_CONTEXT (ecma_gc_objects_lists) [ECMA_GC_COLOR_BLACK];

while (obj_iter_p != NULL)
{
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);
}

obj_iter_p = ecma_gc_get_object_next (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;
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;

ecma_gc_visited_flip_flag = !ecma_gc_visited_flip_flag;
JERRY_CONTEXT (ecma_gc_visited_flip_flag) = !JERRY_CONTEXT (ecma_gc_visited_flip_flag);

#ifndef CONFIG_ECMA_COMPACT_PROFILE_DISABLE_REGEXP_BUILTIN
/* Free RegExp bytecodes stored in cache */
Expand All @@ -621,7 +599,9 @@ ecma_free_unused_memory (jmem_free_unused_memory_severity_t severity) /**< sever
* If there is enough newly allocated objects since last GC, probably it is worthwhile to start GC now.
* Otherwise, probability to free sufficient space is considered to be low.
*/
if (ecma_gc_new_objects_since_last_gc * CONFIG_ECMA_GC_NEW_OBJECTS_SHARE_TO_START_GC > ecma_gc_objects_number)
size_t new_objects_share = CONFIG_ECMA_GC_NEW_OBJECTS_SHARE_TO_START_GC;

if (JERRY_CONTEXT (ecma_gc_new_objects) * new_objects_share > JERRY_CONTEXT (ecma_gc_objects_number))
{
ecma_gc_run (severity);
}
Expand Down
58 changes: 58 additions & 0 deletions jerry-core/ecma/base/ecma-globals.h
Original file line number Diff line number Diff line change
Expand Up @@ -911,6 +911,64 @@ typedef struct
* If regexp, the other flags must be RE_FLAG... */
} 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;

/**
* Number of values in a literal storage item
*/
#define ECMA_LIT_STORAGE_VALUE_COUNT 3

/**
* Literal storage item
*/
typedef struct
{
jmem_cpointer_t next_cp; /**< cpointer ot next item */
jmem_cpointer_t values[ECMA_LIT_STORAGE_VALUE_COUNT]; /**< list of values */
} ecma_lit_storage_item_t;

#ifndef CONFIG_ECMA_LCACHE_DISABLE

/**
* Entry of LCache hash table
*/
typedef struct
{
/** Pointer to a property of the object */
ecma_property_t *prop_p;

/** Compressed pointer to object (ECMA_NULL_POINTER marks record empty) */
jmem_cpointer_t object_cp;

/** Compressed pointer to property's name */
jmem_cpointer_t prop_name_cp;
} ecma_lcache_hash_entry_t;

/**
* Number of rows in LCache's hash table
*/
#define ECMA_LCACHE_HASH_ROWS_COUNT 128

/**
* Number of entries in a row of LCache's hash table
*/
#define ECMA_LCACHE_HASH_ROW_LENGTH 2

#endif /* !CONFIG_ECMA_LCACHE_DISABLE */

/**
* @}
* @}
Expand Down
4 changes: 2 additions & 2 deletions jerry-core/ecma/base/ecma-init-finalize.c
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ ecma_init (void)
ecma_init_builtins ();
ecma_lcache_init ();
ecma_init_lit_storage ();
ecma_init_environment ();
ecma_init_global_lex_env ();

jmem_register_free_unused_memory_callback (ecma_free_unused_memory);
} /* ecma_init */
Expand All @@ -52,7 +52,7 @@ ecma_finalize (void)
{
jmem_unregister_free_unused_memory_callback (ecma_free_unused_memory);

ecma_finalize_environment ();
ecma_finalize_global_lex_env ();
ecma_finalize_builtins ();
ecma_gc_run (JMEM_FREE_UNUSED_MEMORY_SEVERITY_LOW);
ecma_finalize_lit_storage ();
Expand Down
Loading