/** * Run garbage collecting */ void ecma_gc_run (void) { ecma_gc_new_objects_since_last_gc = 0; JERRY_ASSERT (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]; obj_iter_p != NULL; obj_iter_p = ecma_gc_get_object_next (obj_iter_p)) { JERRY_ASSERT (!ecma_gc_is_object_visited (obj_iter_p)); if (ecma_gc_get_object_refs (obj_iter_p) > 0) { ecma_gc_set_object_visited (obj_iter_p, true); } } /* if some object is referenced from a register variable (i.e. it is root), * start recursive marking traverse from the object */ for (vm_stack_frame_t *frame_iter_p = vm_stack_get_top_frame (); frame_iter_p != NULL; frame_iter_p = frame_iter_p->prev_frame_p) { for (int32_t reg_index = 0; reg_index < frame_iter_p->regs_number; reg_index++) { ecma_value_t reg_value = vm_stack_frame_get_reg_value (frame_iter_p, reg_index); if (ecma_is_value_object (reg_value)) { ecma_object_t *obj_p = ecma_get_object_from_value (reg_value); ecma_gc_set_object_visited (obj_p, true); } } } bool marked_anything_during_current_iteration = false; do { 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) { 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; if (likely (obj_prev_p != NULL)) { JERRY_ASSERT (ecma_gc_get_object_next (obj_prev_p) == obj_iter_p); ecma_gc_set_object_next (obj_prev_p, obj_next_p); } else { ecma_gc_objects_lists[ECMA_GC_COLOR_WHITE_GRAY] = obj_next_p; } ecma_gc_mark (obj_iter_p); marked_anything_during_current_iteration = true; } else { obj_prev_p = obj_iter_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) { 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); } /* 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_gc_visited_flip_flag = !ecma_gc_visited_flip_flag; } /* ecma_gc_run */
/** * Run garbage collecting */ void ecma_gc_run (void) { ecma_gc_new_objects_since_last_gc = 0; JERRY_ASSERT (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]; obj_iter_p != NULL; obj_iter_p = ecma_gc_get_object_next (obj_iter_p)) { JERRY_ASSERT (!ecma_gc_is_object_visited (obj_iter_p)); if (ecma_gc_get_object_refs (obj_iter_p) > 0) { ecma_gc_set_object_visited (obj_iter_p, true); } } bool marked_anything_during_current_iteration = false; do { 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) { 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; if (likely (obj_prev_p != NULL)) { JERRY_ASSERT (ecma_gc_get_object_next (obj_prev_p) == obj_iter_p); ecma_gc_set_object_next (obj_prev_p, obj_next_p); } else { ecma_gc_objects_lists[ECMA_GC_COLOR_WHITE_GRAY] = obj_next_p; } ecma_gc_mark (obj_iter_p); marked_anything_during_current_iteration = true; } else { obj_prev_p = obj_iter_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) { 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); } /* 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_gc_visited_flip_flag = !ecma_gc_visited_flip_flag; } /* ecma_gc_run */
/** * Run garbage collection */ void ecma_gc_run (jmem_free_unused_memory_severity_t severity) /**< gc severity */ { JERRY_CONTEXT (ecma_gc_new_objects) = 0; 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 = 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)) { JERRY_ASSERT (!ecma_gc_is_object_visited (obj_iter_p)); if (obj_iter_p->type_flags_refs >= ECMA_OBJECT_REF_ONE) { ecma_gc_set_object_visited (obj_iter_p, true); } } bool marked_anything_during_current_iteration = false; do { marked_anything_during_current_iteration = false; 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) { 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, 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)) { JERRY_ASSERT (ecma_gc_get_object_next (obj_prev_p) == obj_iter_p); ecma_gc_set_object_next (obj_prev_p, obj_next_p); } else { JERRY_CONTEXT (ecma_gc_objects_lists) [ECMA_GC_COLOR_WHITE_GRAY] = obj_next_p; } ecma_gc_mark (obj_iter_p); marked_anything_during_current_iteration = true; } else { obj_prev_p = obj_iter_p; } obj_iter_p = obj_next_p; } } while (marked_anything_during_current_iteration); /* Sweeping objects that are currently unmarked */ ecma_object_t *obj_iter_p = JERRY_CONTEXT (ecma_gc_objects_lists) [ECMA_GC_COLOR_WHITE_GRAY]; while (obj_iter_p != NULL) { 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 */ 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)); if (!ecma_is_lexical_environment (obj_iter_p) || ecma_get_lex_env_type (obj_iter_p) == ECMA_LEXICAL_ENVIRONMENT_DECLARATIVE) { 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_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 /* Free RegExp bytecodes stored in cache */ re_cache_gc_run (); #endif /* !CONFIG_DISABLE_REGEXP_BUILTIN */ } /* ecma_gc_run */
/** * Run garbage collecting */ void ecma_gc_run (void) { ecma_gc_new_objects_since_last_gc = 0; JERRY_ASSERT (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]; obj_iter_p != NULL; obj_iter_p = ecma_gc_get_object_next (obj_iter_p)) { JERRY_ASSERT (!ecma_gc_is_object_visited (obj_iter_p)); if (obj_iter_p->type_flags_refs >= ECMA_OBJECT_REF_ONE) { ecma_gc_set_object_visited (obj_iter_p, true); } } bool marked_anything_during_current_iteration = false; do { 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) { 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; if (likely (obj_prev_p != NULL)) { JERRY_ASSERT (ecma_gc_get_object_next (obj_prev_p) == obj_iter_p); ecma_gc_set_object_next (obj_prev_p, obj_next_p); } else { ecma_gc_objects_lists[ECMA_GC_COLOR_WHITE_GRAY] = obj_next_p; } ecma_gc_mark (obj_iter_p); marked_anything_during_current_iteration = true; } else { obj_prev_p = obj_iter_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) { 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); } /* 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_gc_visited_flip_flag = !ecma_gc_visited_flip_flag; #ifndef CONFIG_ECMA_COMPACT_PROFILE_DISABLE_REGEXP_BUILTIN /* Free RegExp bytecodes stored in cache */ re_cache_gc_run (); #endif /* !CONFIG_ECMA_COMPACT_PROFILE_DISABLE_REGEXP_BUILTIN */ } /* ecma_gc_run */