Exemple #1
0
/**
 * Free specified object
 */
void
ecma_gc_sweep (ecma_object_t *object_p) /**< object to free */
{
    JERRY_ASSERT (object_p != NULL
                  && !ecma_gc_is_object_visited (object_p)
                  && ecma_gc_get_object_refs (object_p) == 0);

    if (!ecma_is_lexical_environment (object_p))
    {
        /* if the object provides free callback, invoke it with handle stored in the object */

        ecma_external_pointer_t freecb_p;
        ecma_external_pointer_t native_p;

        bool is_retrieved = ecma_get_external_pointer_value (object_p,
                            ECMA_INTERNAL_PROPERTY_FREE_CALLBACK,
                            &freecb_p);
        if (is_retrieved)
        {
            is_retrieved = ecma_get_external_pointer_value (object_p,
                           ECMA_INTERNAL_PROPERTY_NATIVE_HANDLE,
                           &native_p);
            JERRY_ASSERT (is_retrieved);

            jerry_dispatch_object_free_callback (freecb_p, native_p);
        }
    }

    if (!ecma_is_lexical_environment (object_p) ||
            ecma_get_lex_env_type (object_p) != ECMA_LEXICAL_ENVIRONMENT_OBJECTBOUND)
    {
        for (ecma_property_t *property = ecma_get_property_list (object_p), *next_property_p;
                property != NULL;
                property = next_property_p)
        {
            next_property_p = ECMA_GET_POINTER (ecma_property_t,
                                                property->next_property_p);

            ecma_free_property (object_p, property);
        }
    }

    JERRY_ASSERT (ecma_gc_objects_number > 0);
    ecma_gc_objects_number--;

    ecma_dealloc_object (object_p);
} /* ecma_gc_sweep */
Exemple #2
0
/**
 * 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 */
Exemple #3
0
/**
 * Increase reference counter of an object
 */
void
ecma_ref_object (ecma_object_t *object_p) /**< object */
{
    ecma_gc_set_object_refs (object_p, ecma_gc_get_object_refs (object_p) + 1);
} /* ecma_ref_object */
Exemple #4
0
/**
 * Decrease reference counter of an object
 */
void
ecma_deref_object (ecma_object_t *object_p) /**< object */
{
    JERRY_ASSERT (ecma_gc_get_object_refs (object_p) > 0);
    ecma_gc_set_object_refs (object_p, ecma_gc_get_object_refs (object_p) - 1);
} /* ecma_deref_object */
Exemple #5
0
/**
 * 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 */