Example #1
0
/**
 * Delete the object's property.
 *
 * Warning: specified property must be owned by specified object.
 */
void
ecma_delete_property (ecma_object_t *object_p, /**< object */
                      ecma_property_t *prop_p) /**< property */
{
  ecma_property_header_t *cur_prop_p = ecma_get_property_list (object_p);
  ecma_property_header_t *prev_prop_p = NULL;

  while (true)
  {
    JERRY_ASSERT (cur_prop_p != NULL);
    JERRY_ASSERT (ECMA_PROPERTY_IS_PROPERTY_PAIR (cur_prop_p));

    ecma_property_pair_t *prop_pair_p = (ecma_property_pair_t *) cur_prop_p;

    for (int i = 0; i < ECMA_PROPERTY_PAIR_ITEM_COUNT; i++)
    {
      if ((cur_prop_p->types + i) == prop_p)
      {
        ecma_string_t *name_p = ECMA_GET_POINTER (ecma_string_t, prop_pair_p->names_cp[i]);

        ecma_free_property (object_p, name_p, cur_prop_p->types + i);

        prop_pair_p->names_cp[i] = ECMA_NULL_POINTER;

        if (name_p != NULL)
        {
          ecma_deref_ecma_string (name_p);
        }

        JERRY_ASSERT (ECMA_PROPERTY_PAIR_ITEM_COUNT == 2);

        if (cur_prop_p->types[1 - i].type_and_flags != ECMA_PROPERTY_TYPE_DELETED)
        {
          /* The other property is still valid. */
          return;
        }

        JERRY_ASSERT (cur_prop_p->types[i].type_and_flags == ECMA_PROPERTY_TYPE_DELETED);

        if (prev_prop_p == NULL)
        {
          object_p->property_list_or_bound_object_cp = cur_prop_p->next_property_cp;
        }
        else
        {
          prev_prop_p->next_property_cp = cur_prop_p->next_property_cp;
        }

        ecma_dealloc_property_pair ((ecma_property_pair_t *) cur_prop_p);
        return;
      }
    }

    prev_prop_p = cur_prop_p;
    cur_prop_p = ECMA_GET_POINTER (ecma_property_header_t,
                                   cur_prop_p->next_property_cp);
  }
} /* ecma_delete_property */
Example #2
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 */
Example #3
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)
                && object_p->type_flags_refs < ECMA_OBJECT_REF_ONE);

  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 && ((jerry_object_free_callback_t) freecb_p) != NULL)
    {
      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_DECLARATIVE)
  {
    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)
    {
      ecma_property_hashmap_free (object_p);
      prop_iter_p = ecma_get_property_list (object_p);
    }

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

      /* Both cannot be deleted. */
      JERRY_ASSERT (prop_iter_p->types[0] != ECMA_PROPERTY_TYPE_DELETED
                    || prop_iter_p->types[1] != ECMA_PROPERTY_TYPE_DELETED);

      ecma_property_pair_t *prop_pair_p = (ecma_property_pair_t *) prop_iter_p;

      for (int i = 0; i < ECMA_PROPERTY_PAIR_ITEM_COUNT; i++)
      {
        if (prop_iter_p->types[i] != ECMA_PROPERTY_TYPE_DELETED)
        {
          ecma_string_t *name_p = ECMA_GET_POINTER (ecma_string_t, prop_pair_p->names_cp[i]);

          ecma_free_property (object_p, name_p, prop_iter_p->types + i);

          if (name_p != NULL)
          {
            ecma_deref_ecma_string (name_p);
          }
        }
      }

      /* Both must be deleted. */
      JERRY_ASSERT (prop_iter_p->types[0] == ECMA_PROPERTY_TYPE_DELETED
                    && prop_iter_p->types[1] == ECMA_PROPERTY_TYPE_DELETED);

      prop_iter_p = ECMA_GET_POINTER (ecma_property_header_t,
                                      prop_iter_p->next_property_cp);

      ecma_dealloc_property_pair (prop_pair_p);
    }
  }

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

  if (!ecma_is_lexical_environment (object_p))
  {
    if (ecma_get_object_is_builtin (object_p)
        || ecma_get_object_type (object_p) == ECMA_OBJECT_TYPE_EXTERNAL_FUNCTION)
    {
      ecma_dealloc_extended_object ((ecma_extended_object_t *) object_p);
      return;
    }

    if (ecma_get_object_type (object_p) == ECMA_OBJECT_TYPE_FUNCTION)
    {
      /* Function with byte-code (not a built-in function). */
      ecma_extended_object_t *ext_func_p = (ecma_extended_object_t *) object_p;

      ecma_bytecode_deref (ECMA_GET_INTERNAL_VALUE_POINTER (ecma_compiled_code_t,
                                                            ext_func_p->u.function.bytecode_cp));

      ecma_dealloc_extended_object (ext_func_p);
      return;
    }
  }

  ecma_dealloc_object (object_p);
} /* ecma_gc_sweep */
Example #4
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)
                && object_p->type_flags_refs < ECMA_OBJECT_REF_ONE);

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

      /* Both cannot be deleted. */
      JERRY_ASSERT (prop_iter_p->types[0].type_and_flags != ECMA_PROPERTY_TYPE_DELETED
                    || prop_iter_p->types[1].type_and_flags != ECMA_PROPERTY_TYPE_DELETED);

      ecma_property_pair_t *prop_pair_p = (ecma_property_pair_t *) prop_iter_p;

      for (int i = 0; i < ECMA_PROPERTY_PAIR_ITEM_COUNT; i++)
      {
        if (prop_iter_p->types[i].type_and_flags != ECMA_PROPERTY_TYPE_DELETED)
        {
          ecma_string_t *name_p = ECMA_GET_POINTER (ecma_string_t, prop_pair_p->names_cp[i]);

          ecma_free_property (object_p, name_p, prop_iter_p->types + i);

          if (name_p != NULL)
          {
            ecma_deref_ecma_string (name_p);
          }
        }
      }

      /* Both must be deleted. */
      JERRY_ASSERT (prop_iter_p->types[0].type_and_flags == ECMA_PROPERTY_TYPE_DELETED
                    && prop_iter_p->types[1].type_and_flags == ECMA_PROPERTY_TYPE_DELETED);

      prop_iter_p = ECMA_GET_POINTER (ecma_property_header_t,
                                      prop_iter_p->next_property_cp);

      ecma_dealloc_property_pair (prop_pair_p);
    }
  }

  JERRY_ASSERT (ecma_gc_objects_number > 0);
  ecma_gc_objects_number--;

  ecma_dealloc_object (object_p);
} /* ecma_gc_sweep */
Example #5
0
/**
 * Low level delete of array items from new_length to old_length
 *
 * Note: new_length must be less than old_length
 *
 * @return the updated value of new_length
 */
uint32_t
ecma_delete_array_properties (ecma_object_t *object_p, /**< object */
                              uint32_t new_length, /**< new length */
                              uint32_t old_length) /**< old length */
{
  JERRY_ASSERT (new_length < old_length);

  /* First the minimum value of new_length is updated. */
  ecma_property_header_t *current_prop_p = ecma_get_property_list (object_p);

  if (current_prop_p == NULL)
  {
    return new_length;
  }

  if (current_prop_p->types[0] == ECMA_PROPERTY_TYPE_HASHMAP)
  {
    current_prop_p = ECMA_GET_POINTER (ecma_property_header_t,
                                       current_prop_p->next_property_cp);
  }

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

    ecma_property_pair_t *prop_pair_p = (ecma_property_pair_t *) current_prop_p;

    for (int i = 0; i < ECMA_PROPERTY_PAIR_ITEM_COUNT; i++)
    {
      if (ECMA_PROPERTY_IS_NAMED_PROPERTY (current_prop_p->types[i])
          && !ecma_is_property_configurable (current_prop_p->types[i]))
      {
        uint32_t index = ecma_string_get_property_index (current_prop_p->types[i],
                                                         prop_pair_p->names_cp[i]);

        if (index < old_length && index >= new_length)
        {
          JERRY_ASSERT (index != ECMA_STRING_NOT_ARRAY_INDEX);

          new_length = index + 1;

          if (new_length == old_length)
          {
            /* Early return. */
            return new_length;
          }
        }
      }
    }

    current_prop_p = ECMA_GET_POINTER (ecma_property_header_t,
                                       current_prop_p->next_property_cp);
  }

  /* Second all properties between new_length and old_length are deleted. */
  current_prop_p = ecma_get_property_list (object_p);
  ecma_property_header_t *prev_prop_p = NULL;
  ecma_property_hashmap_delete_status hashmap_status = ECMA_PROPERTY_HASHMAP_DELETE_NO_HASHMAP;

  if (current_prop_p->types[0] == ECMA_PROPERTY_TYPE_HASHMAP)
  {
    prev_prop_p = current_prop_p;
    current_prop_p = ECMA_GET_POINTER (ecma_property_header_t,
                                       current_prop_p->next_property_cp);
    hashmap_status = ECMA_PROPERTY_HASHMAP_DELETE_HAS_HASHMAP;
  }

  while (current_prop_p != NULL)
  {
    ecma_property_pair_t *prop_pair_p = (ecma_property_pair_t *) current_prop_p;

    for (int i = 0; i < ECMA_PROPERTY_PAIR_ITEM_COUNT; i++)
    {
      if (ECMA_PROPERTY_IS_NAMED_PROPERTY (current_prop_p->types[i])
          && ecma_is_property_configurable (current_prop_p->types[i]))
      {
        uint32_t index = ecma_string_get_property_index (current_prop_p->types[i],
                                                         prop_pair_p->names_cp[i]);

        if (index < old_length && index >= new_length)
        {
          JERRY_ASSERT (index != ECMA_STRING_NOT_ARRAY_INDEX);

          if (hashmap_status == ECMA_PROPERTY_HASHMAP_DELETE_HAS_HASHMAP)
          {
            hashmap_status = ecma_property_hashmap_delete (object_p,
                                                           prop_pair_p->names_cp[i],
                                                           current_prop_p->types + i);
          }

          ecma_free_property (object_p, prop_pair_p->names_cp[i], current_prop_p->types + i);

          JERRY_ASSERT (current_prop_p->types[i] == ECMA_PROPERTY_TYPE_DELETED);
        }
      }
    }

    if (current_prop_p->types[0] == ECMA_PROPERTY_TYPE_DELETED
        && current_prop_p->types[1] == ECMA_PROPERTY_TYPE_DELETED)
    {
      if (prev_prop_p == NULL)
      {
        object_p->property_list_or_bound_object_cp = current_prop_p->next_property_cp;
      }
      else
      {
        prev_prop_p->next_property_cp = current_prop_p->next_property_cp;
      }

      ecma_property_header_t *next_prop_p = ECMA_GET_POINTER (ecma_property_header_t,
                                                              current_prop_p->next_property_cp);
      ecma_dealloc_property_pair ((ecma_property_pair_t *) current_prop_p);
      current_prop_p = next_prop_p;
    }
    else
    {
      prev_prop_p = current_prop_p;
      current_prop_p = ECMA_GET_POINTER (ecma_property_header_t,
                                         current_prop_p->next_property_cp);
    }
  }

  if (hashmap_status == ECMA_PROPERTY_HASHMAP_DELETE_RECREATE_HASHMAP)
  {
    ecma_property_hashmap_free (object_p);
    ecma_property_hashmap_create (object_p);
  }

  return new_length;
} /* ecma_delete_array_properties */
Example #6
0
/**
 * Delete the object's property referenced by its value pointer.
 *
 * Note: specified property must be owned by specified object.
 */
void
ecma_delete_property (ecma_object_t *object_p, /**< object */
                      ecma_property_value_t *prop_value_p) /**< property value reference */
{
  ecma_property_header_t *cur_prop_p = ecma_get_property_list (object_p);
  ecma_property_header_t *prev_prop_p = NULL;
  ecma_property_hashmap_delete_status hashmap_status = ECMA_PROPERTY_HASHMAP_DELETE_NO_HASHMAP;

  if (cur_prop_p != NULL && cur_prop_p->types[0] == ECMA_PROPERTY_TYPE_HASHMAP)
  {
    prev_prop_p = cur_prop_p;
    cur_prop_p = ECMA_GET_POINTER (ecma_property_header_t,
                                   cur_prop_p->next_property_cp);
    hashmap_status = ECMA_PROPERTY_HASHMAP_DELETE_HAS_HASHMAP;
  }

  while (true)
  {
    JERRY_ASSERT (cur_prop_p != NULL);
    JERRY_ASSERT (ECMA_PROPERTY_IS_PROPERTY_PAIR (cur_prop_p));

    ecma_property_pair_t *prop_pair_p = (ecma_property_pair_t *) cur_prop_p;

    for (int i = 0; i < ECMA_PROPERTY_PAIR_ITEM_COUNT; i++)
    {
      if ((prop_pair_p->values + i) == prop_value_p)
      {
        JERRY_ASSERT (ECMA_PROPERTY_GET_TYPE (cur_prop_p->types[i]) != ECMA_PROPERTY_TYPE_SPECIAL);

        if (hashmap_status == ECMA_PROPERTY_HASHMAP_DELETE_HAS_HASHMAP)
        {
          hashmap_status = ecma_property_hashmap_delete (object_p,
                                                         prop_pair_p->names_cp[i],
                                                         cur_prop_p->types + i);
        }

        ecma_free_property (object_p, prop_pair_p->names_cp[i], cur_prop_p->types + i);

        JERRY_ASSERT (ECMA_PROPERTY_PAIR_ITEM_COUNT == 2);

        if (cur_prop_p->types[1 - i] != ECMA_PROPERTY_TYPE_DELETED)
        {
          /* The other property is still valid. */
          if (hashmap_status == ECMA_PROPERTY_HASHMAP_DELETE_RECREATE_HASHMAP)
          {
            ecma_property_hashmap_free (object_p);
            ecma_property_hashmap_create (object_p);
          }
          return;
        }

        JERRY_ASSERT (cur_prop_p->types[i] == ECMA_PROPERTY_TYPE_DELETED);

        if (prev_prop_p == NULL)
        {
          object_p->property_list_or_bound_object_cp = cur_prop_p->next_property_cp;
        }
        else
        {
          prev_prop_p->next_property_cp = cur_prop_p->next_property_cp;
        }

        ecma_dealloc_property_pair ((ecma_property_pair_t *) cur_prop_p);

        if (hashmap_status == ECMA_PROPERTY_HASHMAP_DELETE_RECREATE_HASHMAP)
        {
          ecma_property_hashmap_free (object_p);
          ecma_property_hashmap_create (object_p);
        }
        return;
      }
    }

    prev_prop_p = cur_prop_p;
    cur_prop_p = ECMA_GET_POINTER (ecma_property_header_t,
                                   cur_prop_p->next_property_cp);
  }
} /* ecma_delete_property */