Example #1
0
/**
 * Mark objects as visited starting from specified object as root
 */
void
ecma_gc_mark (ecma_object_t *object_p) /**< object to mark from */
{
  JERRY_ASSERT (object_p != NULL);
  JERRY_ASSERT (ecma_gc_is_object_visited (object_p));

  bool traverse_properties = true;

  if (ecma_is_lexical_environment (object_p))
  {
    ecma_object_t *lex_env_p = ecma_get_lex_env_outer_reference (object_p);
    if (lex_env_p != NULL)
    {
      ecma_gc_set_object_visited (lex_env_p, true);
    }

    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_gc_set_object_visited (binding_object_p, true);

      traverse_properties = false;
    }
  }
  else
  {
    ecma_object_t *proto_p = ecma_get_object_prototype (object_p);
    if (proto_p != NULL)
    {
      ecma_gc_set_object_visited (proto_p, true);
    }
  }

  if (traverse_properties)
  {
    ecma_property_header_t *prop_iter_p = ecma_get_property_list (object_p);

    while (prop_iter_p != NULL)
    {
      JERRY_ASSERT (ECMA_PROPERTY_IS_PROPERTY_PAIR (prop_iter_p));

      if (prop_iter_p->types[0].type_and_flags != ECMA_PROPERTY_TYPE_DELETED)
      {
        ecma_gc_mark_property (prop_iter_p->types + 0);
      }

      if (prop_iter_p->types[1].type_and_flags != ECMA_PROPERTY_TYPE_DELETED)
      {
        ecma_gc_mark_property (prop_iter_p->types + 1);
      }

      prop_iter_p = ECMA_GET_POINTER (ecma_property_header_t,
                                      prop_iter_p->next_property_cp);
    }
  }
} /* ecma_gc_mark */
Example #2
0
/**
 * Initialize GC information for the object
 */
void
ecma_init_gc_info (ecma_object_t *object_p) /**< object */
{
  ecma_gc_set_object_refs (object_p, 1);

  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;

  /* Should be set to false at the beginning of garbage collection */
  ecma_gc_set_object_visited (object_p, false);
} /* ecma_init_gc_info */
Example #3
0
/**
 * Initialize GC information for the object
 */
void
ecma_init_gc_info (ecma_object_t *object_p) /**< object */
{
    ecma_gc_objects_number++;
    ecma_gc_new_objects_since_last_gc++;

    JERRY_ASSERT (ecma_gc_new_objects_since_last_gc <= ecma_gc_objects_number);

    ecma_gc_set_object_refs (object_p, 1);

    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;

    /* Should be set to false at the beginning of garbage collection */
    ecma_gc_set_object_visited (object_p, false);
} /* ecma_init_gc_info */
Example #4
0
/**
 * Initialize GC information for the object
 */
inline void
ecma_init_gc_info (ecma_object_t *object_p) /**< object */
{
  JERRY_CONTEXT (ecma_gc_objects_number)++;
  JERRY_CONTEXT (ecma_gc_new_objects)++;

  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, 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);
} /* ecma_init_gc_info */
Example #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);
        }
    }

    /* 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 */
Example #6
0
/**
 * Mark objects as visited starting from specified object as root
 */
void
ecma_gc_mark (ecma_object_t *object_p) /**< object to mark from */
{
    JERRY_ASSERT (object_p != NULL);
    JERRY_ASSERT (ecma_gc_is_object_visited (object_p));

    bool traverse_properties = true;

    if (ecma_is_lexical_environment (object_p))
    {
        ecma_object_t *lex_env_p = ecma_get_lex_env_outer_reference (object_p);
        if (lex_env_p != NULL)
        {
            ecma_gc_set_object_visited (lex_env_p, true);
        }

        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);
            ecma_gc_set_object_visited (binding_object_p, true);

            traverse_properties = false;
        }
    }
    else
    {
        ecma_object_t *proto_p = ecma_get_object_prototype (object_p);
        if (proto_p != NULL)
        {
            ecma_gc_set_object_visited (proto_p, true);
        }
    }

    if (traverse_properties)
    {
        for (ecma_property_t *property_p = ecma_get_property_list (object_p), *next_property_p;
                property_p != NULL;
                property_p = next_property_p)
        {
            next_property_p = ECMA_GET_POINTER (ecma_property_t,
                                                property_p->next_property_p);

            switch ((ecma_property_type_t) property_p->type)
            {
            case ECMA_PROPERTY_NAMEDDATA:
            {
                ecma_value_t value = ecma_get_named_data_property_value (property_p);

                if (ecma_is_value_object (value))
                {
                    ecma_object_t *value_obj_p = ecma_get_object_from_value (value);

                    ecma_gc_set_object_visited (value_obj_p, true);
                }

                break;
            }

            case ECMA_PROPERTY_NAMEDACCESSOR:
            {
                ecma_object_t *getter_obj_p = ecma_get_named_accessor_property_getter (property_p);
                ecma_object_t *setter_obj_p = ecma_get_named_accessor_property_setter (property_p);

                if (getter_obj_p != NULL)
                {
                    ecma_gc_set_object_visited (getter_obj_p, true);
                }

                if (setter_obj_p != NULL)
                {
                    ecma_gc_set_object_visited (setter_obj_p, true);
                }

                break;
            }

            case ECMA_PROPERTY_INTERNAL:
            {
                ecma_internal_property_id_t property_id = (ecma_internal_property_id_t) property_p->u.internal_property.type;
                uint32_t property_value = property_p->u.internal_property.value;

                switch (property_id)
                {
                case ECMA_INTERNAL_PROPERTY_NUMBER_INDEXED_ARRAY_VALUES: /* a collection of ecma-values */
                case ECMA_INTERNAL_PROPERTY_STRING_INDEXED_ARRAY_VALUES: /* a collection of ecma-values */
                {
                    JERRY_UNIMPLEMENTED ("Indexed array storage is not implemented yet.");
                }

                case ECMA_INTERNAL_PROPERTY_PROTOTYPE: /* the property's value is located in ecma_object_t
                                                    (see above in the routine) */
                case ECMA_INTERNAL_PROPERTY_EXTENSIBLE: /* the property's value is located in ecma_object_t
                                                     (see above in the routine) */
                case ECMA_INTERNAL_PROPERTY__COUNT: /* not a real internal property type,
                                             * but number of the real internal property types */
                {
                    JERRY_UNREACHABLE ();
                }

                case ECMA_INTERNAL_PROPERTY_FORMAL_PARAMETERS: /* a collection of strings */
                case ECMA_INTERNAL_PROPERTY_PRIMITIVE_STRING_VALUE: /* compressed pointer to a ecma_string_t */
                case ECMA_INTERNAL_PROPERTY_PRIMITIVE_NUMBER_VALUE: /* compressed pointer to a ecma_number_t */
                case ECMA_INTERNAL_PROPERTY_PRIMITIVE_BOOLEAN_VALUE: /* a simple boolean value */
                case ECMA_INTERNAL_PROPERTY_CLASS: /* an enum */
                case ECMA_INTERNAL_PROPERTY_CODE_BYTECODE: /* compressed pointer to a bytecode array */
                case ECMA_INTERNAL_PROPERTY_CODE_FLAGS_AND_OFFSET: /* an integer */
                case ECMA_INTERNAL_PROPERTY_NATIVE_CODE: /* an external pointer */
                case ECMA_INTERNAL_PROPERTY_NATIVE_HANDLE: /* an external pointer */
                case ECMA_INTERNAL_PROPERTY_FREE_CALLBACK: /* an object's native free callback */
                case ECMA_INTERNAL_PROPERTY_BUILT_IN_ID: /* an integer */
                case ECMA_INTERNAL_PROPERTY_BUILT_IN_ROUTINE_DESC: /* an integer */
                case ECMA_INTERNAL_PROPERTY_EXTENSION_ID: /* an integer */
                case ECMA_INTERNAL_PROPERTY_NON_INSTANTIATED_BUILT_IN_MASK_0_31: /* an integer (bit-mask) */
                case ECMA_INTERNAL_PROPERTY_NON_INSTANTIATED_BUILT_IN_MASK_32_63: /* an integer (bit-mask) */
                case ECMA_INTERNAL_PROPERTY_REGEXP_BYTECODE:
                case ECMA_INTERNAL_PROPERTY_BOUND_FUNCTION_TARGET_FUNCTION:
                case ECMA_INTERNAL_PROPERTY_BOUND_FUNCTION_BOUND_THIS:
                case ECMA_INTERNAL_PROPERTY_BOUND_FUNCTION_BOUND_ARGS:
                {
                    break;
                }

                case ECMA_INTERNAL_PROPERTY_SCOPE: /* a lexical environment */
                case ECMA_INTERNAL_PROPERTY_PARAMETERS_MAP: /* an object */
                {
                    ecma_object_t *obj_p = ECMA_GET_NON_NULL_POINTER (ecma_object_t, property_value);

                    ecma_gc_set_object_visited (obj_p, true);

                    break;
                }
                }

                break;
            }
            }
        }
    }
} /* ecma_gc_mark */
Example #7
0
/**
 * 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 */
Example #8
0
/**
 * Mark objects as visited starting from specified object as root
 */
void
ecma_gc_mark (ecma_object_t *object_p) /**< object to mark from */
{
  JERRY_ASSERT (object_p != NULL);
  JERRY_ASSERT (ecma_gc_is_object_visited (object_p));

  bool traverse_properties = true;

  if (ecma_is_lexical_environment (object_p))
  {
    ecma_object_t *lex_env_p = ecma_get_lex_env_outer_reference (object_p);
    if (lex_env_p != NULL)
    {
      ecma_gc_set_object_visited (lex_env_p, true);
    }

    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_gc_set_object_visited (binding_object_p, true);

      traverse_properties = false;
    }
  }
  else
  {
    ecma_object_t *proto_p = ecma_get_object_prototype (object_p);
    if (proto_p != NULL)
    {
      ecma_gc_set_object_visited (proto_p, true);
    }

    if (!ecma_get_object_is_builtin (object_p)
        && ecma_get_object_type (object_p) == ECMA_OBJECT_TYPE_FUNCTION)
    {
      ecma_extended_object_t *ext_func_p = (ecma_extended_object_t *) object_p;

      ecma_object_t *scope_p = ECMA_GET_INTERNAL_VALUE_POINTER (ecma_object_t,
                                                                ext_func_p->u.function.scope_cp);

      ecma_gc_set_object_visited (scope_p, true);
    }
  }

  if (traverse_properties)
  {
    ecma_property_header_t *prop_iter_p = ecma_get_property_list (object_p);

    if (prop_iter_p != NULL
        && ECMA_PROPERTY_GET_TYPE (prop_iter_p->types[0]) == ECMA_PROPERTY_TYPE_HASHMAP)
    {
      prop_iter_p = ECMA_GET_POINTER (ecma_property_header_t,
                                      prop_iter_p->next_property_cp);
    }

    while (prop_iter_p != NULL)
    {
      JERRY_ASSERT (ECMA_PROPERTY_IS_PROPERTY_PAIR (prop_iter_p));

      if (prop_iter_p->types[0] != ECMA_PROPERTY_TYPE_DELETED)
      {
        ecma_gc_mark_property (prop_iter_p->types + 0);
      }

      if (prop_iter_p->types[1] != ECMA_PROPERTY_TYPE_DELETED)
      {
        ecma_gc_mark_property (prop_iter_p->types + 1);
      }

      prop_iter_p = ECMA_GET_POINTER (ecma_property_header_t,
                                      prop_iter_p->next_property_cp);
    }
  }
} /* ecma_gc_mark */
Example #9
0
/**
 * Mark referenced object from property
 */
static void
ecma_gc_mark_property (ecma_property_t *property_p) /**< property */
{
  switch (ECMA_PROPERTY_GET_TYPE (*property_p))
  {
    case ECMA_PROPERTY_TYPE_NAMEDDATA:
    {
      ecma_value_t value = ECMA_PROPERTY_VALUE_PTR (property_p)->value;

      if (ecma_is_value_object (value))
      {
        ecma_object_t *value_obj_p = ecma_get_object_from_value (value);

        ecma_gc_set_object_visited (value_obj_p, true);
      }
      break;
    }
    case ECMA_PROPERTY_TYPE_NAMEDACCESSOR:
    {
      ecma_property_value_t *prop_value_p = ECMA_PROPERTY_VALUE_PTR (property_p);
      ecma_object_t *getter_obj_p = ecma_get_named_accessor_property_getter (prop_value_p);
      ecma_object_t *setter_obj_p = ecma_get_named_accessor_property_setter (prop_value_p);

      if (getter_obj_p != NULL)
      {
        ecma_gc_set_object_visited (getter_obj_p, true);
      }

      if (setter_obj_p != NULL)
      {
        ecma_gc_set_object_visited (setter_obj_p, true);
      }
      break;
    }
    case ECMA_PROPERTY_TYPE_INTERNAL:
    {
      uint32_t property_value = ECMA_PROPERTY_VALUE_PTR (property_p)->value;

      switch (ECMA_PROPERTY_GET_INTERNAL_PROPERTY_TYPE (property_p))
      {
        case ECMA_INTERNAL_PROPERTY_ECMA_VALUE: /* an ecma_value_t except object */
        case ECMA_INTERNAL_PROPERTY_DATE_FLOAT: /* pointer to a ecma_number_t */
        case ECMA_INTERNAL_PROPERTY_CLASS: /* an enum */
        case ECMA_INTERNAL_PROPERTY_REGEXP_BYTECODE: /* pointer to a regexp bytecode array */
        case ECMA_INTERNAL_PROPERTY_NATIVE_HANDLE: /* an external pointer */
        case ECMA_INTERNAL_PROPERTY_FREE_CALLBACK: /* an object's native free callback */
        case ECMA_INTERNAL_PROPERTY_INSTANTIATED_MASK_32_63: /* an integer (bit-mask) */
        {
          break;
        }

        case ECMA_INTERNAL_PROPERTY_BOUND_FUNCTION_BOUND_THIS: /* an ecma value */
        {
          if (ecma_is_value_object (property_value))
          {
            ecma_object_t *obj_p = ecma_get_object_from_value (property_value);

            ecma_gc_set_object_visited (obj_p, true);
          }

          break;
        }

        case ECMA_INTERNAL_PROPERTY_BOUND_FUNCTION_BOUND_ARGS: /* a collection of ecma values */
        {
          ecma_collection_header_t *bound_arg_list_p = ECMA_GET_INTERNAL_VALUE_POINTER (ecma_collection_header_t,
                                                                                        property_value);

          ecma_collection_iterator_t bound_args_iterator;
          ecma_collection_iterator_init (&bound_args_iterator, bound_arg_list_p);

          for (ecma_length_t i = 0; i < bound_arg_list_p->unit_number; i++)
          {
            bool is_moved = ecma_collection_iterator_next (&bound_args_iterator);
            JERRY_ASSERT (is_moved);

            if (ecma_is_value_object (*bound_args_iterator.current_value_p))
            {
              ecma_object_t *obj_p = ecma_get_object_from_value (*bound_args_iterator.current_value_p);

              ecma_gc_set_object_visited (obj_p, true);
            }
          }

          break;
        }

        case ECMA_INTERNAL_PROPERTY_BOUND_FUNCTION_TARGET_FUNCTION: /* an object */
        case ECMA_INTERNAL_PROPERTY_SCOPE: /* a lexical environment */
        case ECMA_INTERNAL_PROPERTY_PARAMETERS_MAP: /* an object */
        {
          ecma_object_t *obj_p = ECMA_GET_INTERNAL_VALUE_POINTER (ecma_object_t, property_value);

          ecma_gc_set_object_visited (obj_p, true);

          break;
        }
        case ECMA_INTERNAL_PROPERTY__COUNT: /* not a real internal property type,
                                             * but number of the real internal property types */
        {
          JERRY_UNREACHABLE ();
          break;
        }
      }
      break;
    }
    default:
    {
      JERRY_UNREACHABLE ();
      break;
    }
  }
} /* ecma_gc_mark_property */
Example #10
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 */
Example #11
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 (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 */
Example #12
0
/**
 * Mark referenced object from property
 */
static void
ecma_gc_mark_property (ecma_property_t *property_p) /**< property */
{
  switch (ECMA_PROPERTY_GET_TYPE (property_p))
  {
    case ECMA_PROPERTY_TYPE_NAMEDDATA:
    {
      ecma_value_t value = ecma_get_named_data_property_value (property_p);

      if (ecma_is_value_object (value))
      {
        ecma_object_t *value_obj_p = ecma_get_object_from_value (value);

        ecma_gc_set_object_visited (value_obj_p, true);
      }
      break;
    }
    case ECMA_PROPERTY_TYPE_NAMEDACCESSOR:
    {
      ecma_object_t *getter_obj_p = ecma_get_named_accessor_property_getter (property_p);
      ecma_object_t *setter_obj_p = ecma_get_named_accessor_property_setter (property_p);

      if (getter_obj_p != NULL)
      {
        ecma_gc_set_object_visited (getter_obj_p, true);
      }

      if (setter_obj_p != NULL)
      {
        ecma_gc_set_object_visited (setter_obj_p, true);
      }
      break;
    }
    case ECMA_PROPERTY_TYPE_INTERNAL:
    {
      uint32_t property_value = ECMA_PROPERTY_VALUE_PTR (property_p)->value;

      switch (ECMA_PROPERTY_GET_INTERNAL_PROPERTY_TYPE (property_p))
      {
        case ECMA_INTERNAL_PROPERTY_NUMBER_INDEXED_ARRAY_VALUES: /* a collection of ecma values */
        case ECMA_INTERNAL_PROPERTY_STRING_INDEXED_ARRAY_VALUES: /* a collection of ecma values */
        {
          JERRY_UNIMPLEMENTED ("Indexed array storage is not implemented yet.");
        }

        case ECMA_INTERNAL_PROPERTY_PROTOTYPE: /* the property's value is located in ecma_object_t
                                                * (see above in the routine) */
        case ECMA_INTERNAL_PROPERTY_EXTENSIBLE: /* the property's value is located in ecma_object_t
                                                 * (see above in the routine) */
        case ECMA_INTERNAL_PROPERTY__COUNT: /* not a real internal property type,
                                             * but number of the real internal property types */
        {
          JERRY_UNREACHABLE ();
        }

        case ECMA_INTERNAL_PROPERTY_PRIMITIVE_STRING_VALUE: /* compressed pointer to a ecma_string_t */
        case ECMA_INTERNAL_PROPERTY_PRIMITIVE_NUMBER_VALUE: /* compressed pointer to a ecma_number_t */
        case ECMA_INTERNAL_PROPERTY_PRIMITIVE_BOOLEAN_VALUE: /* a simple boolean value */
        case ECMA_INTERNAL_PROPERTY_CLASS: /* an enum */
        case ECMA_INTERNAL_PROPERTY_CODE_BYTECODE: /* compressed pointer to a bytecode array */
        case ECMA_INTERNAL_PROPERTY_NATIVE_CODE: /* an external pointer */
        case ECMA_INTERNAL_PROPERTY_NATIVE_HANDLE: /* an external pointer */
        case ECMA_INTERNAL_PROPERTY_FREE_CALLBACK: /* an object's native free callback */
        case ECMA_INTERNAL_PROPERTY_BUILT_IN_ID: /* an integer */
        case ECMA_INTERNAL_PROPERTY_BUILT_IN_ROUTINE_DESC: /* an integer */
        case ECMA_INTERNAL_PROPERTY_EXTENSION_ID: /* an integer */
        case ECMA_INTERNAL_PROPERTY_NON_INSTANTIATED_BUILT_IN_MASK_0_31: /* an integer (bit-mask) */
        case ECMA_INTERNAL_PROPERTY_NON_INSTANTIATED_BUILT_IN_MASK_32_63: /* an integer (bit-mask) */
        case ECMA_INTERNAL_PROPERTY_REGEXP_BYTECODE:
        {
          break;
        }

        case ECMA_INTERNAL_PROPERTY_BOUND_FUNCTION_BOUND_THIS: /* an ecma value */
        {
          if (ecma_is_value_object (property_value))
          {
            ecma_object_t *obj_p = ecma_get_object_from_value (property_value);

            ecma_gc_set_object_visited (obj_p, true);
          }

          break;
        }

        case ECMA_INTERNAL_PROPERTY_BOUND_FUNCTION_BOUND_ARGS: /* a collection of ecma values */
        {
          ecma_collection_header_t *bound_arg_list_p = ECMA_GET_NON_NULL_POINTER (ecma_collection_header_t,
                                                                                  property_value);

          ecma_collection_iterator_t bound_args_iterator;
          ecma_collection_iterator_init (&bound_args_iterator, bound_arg_list_p);

          for (ecma_length_t i = 0; i < bound_arg_list_p->unit_number; i++)
          {
            bool is_moved = ecma_collection_iterator_next (&bound_args_iterator);
            JERRY_ASSERT (is_moved);

            if (ecma_is_value_object (*bound_args_iterator.current_value_p))
            {
              ecma_object_t *obj_p = ecma_get_object_from_value (*bound_args_iterator.current_value_p);

              ecma_gc_set_object_visited (obj_p, true);
            }
          }

          break;
        }

        case ECMA_INTERNAL_PROPERTY_BOUND_FUNCTION_TARGET_FUNCTION: /* an object */
        case ECMA_INTERNAL_PROPERTY_SCOPE: /* a lexical environment */
        case ECMA_INTERNAL_PROPERTY_PARAMETERS_MAP: /* an object */
        {
          ecma_object_t *obj_p = ECMA_GET_NON_NULL_POINTER (ecma_object_t, property_value);

          ecma_gc_set_object_visited (obj_p, true);

          break;
        }
      }
      break;
    }
    default:
    {
      JERRY_UNREACHABLE ();
      break;
    }
  }
} /* ecma_gc_mark_property */