/**
 * Remove last element of the collection
 *
 * Warning:
 *         the function invalidates all iterators that are configured to access the passed collection
 */
void
ecma_remove_last_value_from_values_collection (ecma_collection_header_t *header_p, /**< collection's header */
                                               bool do_deref_if_object) /**< if the value to remove
                                                                         *   is object value, decrement
                                                                         *   reference counter of the object */
{
  JERRY_ASSERT (header_p != NULL && header_p->unit_number > 0);

  const size_t values_in_chunk = sizeof (ecma_collection_chunk_t::data) / sizeof (ecma_value_t);
  size_t values_number = header_p->unit_number;
  size_t pos_of_value_to_remove_in_chunk = (values_number - 1u) % values_in_chunk;

  ecma_collection_chunk_t *last_chunk_p = ECMA_GET_NON_NULL_POINTER (ecma_collection_chunk_t,
                                                                     header_p->last_chunk_cp);

  ecma_value_t *values_p = (ecma_value_t *) last_chunk_p->data;
  JERRY_ASSERT ((uint8_t *) (values_p + pos_of_value_to_remove_in_chunk + 1) <= (uint8_t *) (last_chunk_p + 1));

  ecma_value_t value_to_remove = values_p[pos_of_value_to_remove_in_chunk];

  ecma_free_value (value_to_remove, do_deref_if_object);

  header_p->unit_number--;

  if (pos_of_value_to_remove_in_chunk == 0)
  {
    ecma_collection_chunk_t *chunk_to_remove_p = last_chunk_p;

    /* free last chunk */
    if (header_p->first_chunk_cp == header_p->last_chunk_cp)
    {
      header_p->first_chunk_cp = ECMA_NULL_POINTER;
      header_p->last_chunk_cp = ECMA_NULL_POINTER;
    }
    else
    {
      ecma_collection_chunk_t *chunk_iter_p = ECMA_GET_NON_NULL_POINTER (ecma_collection_chunk_t,
                                                                         header_p->first_chunk_cp);

      while (chunk_iter_p->next_chunk_cp != header_p->last_chunk_cp)
      {
        chunk_iter_p = ECMA_GET_NON_NULL_POINTER (ecma_collection_chunk_t,
                                                  chunk_iter_p->next_chunk_cp);
      }

      ecma_collection_chunk_t *new_last_chunk_p = chunk_iter_p;

      JERRY_ASSERT (ECMA_GET_NON_NULL_POINTER (ecma_collection_chunk_t,
                                               new_last_chunk_p->next_chunk_cp) == chunk_to_remove_p);

      ECMA_SET_NON_NULL_POINTER (header_p->last_chunk_cp, new_last_chunk_p);
      new_last_chunk_p->next_chunk_cp = ECMA_NULL_POINTER;
    }

    ecma_dealloc_collection_chunk (chunk_to_remove_p);
  }
} /* ecma_remove_last_value_from_values_collection */
/**
 * Remove last element of the collection
 *
 * Warning:
 *         the function invalidates all iterators that are configured to access the passed collection
 */
void
ecma_remove_last_value_from_values_collection (ecma_collection_header_t *header_p) /**< collection's header */
{
  JERRY_ASSERT (header_p != NULL && header_p->unit_number > 0);

  const size_t values_in_chunk = JERRY_SIZE_OF_STRUCT_MEMBER (ecma_collection_chunk_t, data) / sizeof (ecma_value_t);
  size_t values_number = header_p->unit_number;
  size_t pos_of_value_to_remove_in_chunk = (values_number - 1u) % values_in_chunk;

  ecma_collection_chunk_t *last_chunk_p = ECMA_GET_NON_NULL_POINTER (ecma_collection_chunk_t,
                                                                     header_p->last_chunk_cp);

  ecma_value_t *values_p = (ecma_value_t *) last_chunk_p->data;
  JERRY_ASSERT ((uint8_t *) (values_p + pos_of_value_to_remove_in_chunk + 1) <= (uint8_t *) (last_chunk_p + 1));

  ecma_value_t value_to_remove = values_p[pos_of_value_to_remove_in_chunk];

  ecma_free_value (value_to_remove);

  header_p->unit_number--;

  if (pos_of_value_to_remove_in_chunk == 0)
  {
    ecma_collection_chunk_t *chunk_to_remove_p = last_chunk_p;

    /* free last chunk */
    if (header_p->first_chunk_cp == header_p->last_chunk_cp)
    {
      header_p->first_chunk_cp = ECMA_NULL_POINTER;
      header_p->last_chunk_cp = ECMA_NULL_POINTER;
    }
    else
    {
      ecma_collection_chunk_t *chunk_iter_p = ECMA_GET_NON_NULL_POINTER (ecma_collection_chunk_t,
                                                                         header_p->first_chunk_cp);

      while (chunk_iter_p->next_chunk_cp != header_p->last_chunk_cp)
      {
        chunk_iter_p = ECMA_GET_NON_NULL_POINTER (ecma_collection_chunk_t,
                                                  chunk_iter_p->next_chunk_cp);
      }

      ecma_collection_chunk_t *new_last_chunk_p = chunk_iter_p;

      JERRY_ASSERT (ECMA_GET_NON_NULL_POINTER (ecma_collection_chunk_t,
                                               new_last_chunk_p->next_chunk_cp) == chunk_to_remove_p);

      ECMA_SET_NON_NULL_POINTER (header_p->last_chunk_cp, new_last_chunk_p);
      new_last_chunk_p->next_chunk_cp = ECMA_NULL_POINTER;
    }

    ecma_dealloc_collection_chunk (chunk_to_remove_p);
  }
} /* ecma_remove_last_value_from_values_collection */
/**
 * Free the collection of ecma values.
 */
void
ecma_free_values_collection (ecma_collection_header_t *header_p, /**< collection's header */
                             bool do_deref_if_object) /**< if the value is object value,
                                                           decrement reference counter of the object */
{
  JERRY_ASSERT (header_p != NULL);

  const size_t values_in_chunk = JERRY_SIZE_OF_STRUCT_MEMBER (ecma_collection_chunk_t, data) / sizeof (ecma_value_t);

  ecma_collection_chunk_t *chunk_p = ECMA_GET_POINTER (ecma_collection_chunk_t,
                                                       header_p->first_chunk_cp);
  ecma_length_t value_index = 0;

  while (chunk_p != NULL)
  {
    JERRY_ASSERT (value_index < header_p->unit_number);

    ecma_value_t *cur_value_buf_iter_p = (ecma_value_t *) chunk_p->data;
    ecma_value_t *cur_value_buf_end_p = cur_value_buf_iter_p + values_in_chunk;

    while (cur_value_buf_iter_p != cur_value_buf_end_p
           && value_index < header_p->unit_number)
    {
      JERRY_ASSERT (cur_value_buf_iter_p < cur_value_buf_end_p);

      if (do_deref_if_object)
      {
        ecma_free_value (*cur_value_buf_iter_p);
      }
      else
      {
        ecma_free_value_if_not_object (*cur_value_buf_iter_p);
      }

      cur_value_buf_iter_p++;
      value_index++;
    }

    ecma_collection_chunk_t *next_chunk_p = ECMA_GET_POINTER (ecma_collection_chunk_t,
                                                              chunk_p->next_chunk_cp);
    ecma_dealloc_collection_chunk (chunk_p);
    chunk_p = next_chunk_p;
  }

  ecma_dealloc_collection_header (header_p);
} /* ecma_free_values_collection */
Esempio n. 4
0
/**
 * Abort (finalize) the current stack context, and remove it.
 *
 * @return new stack top
 */
ecma_value_t *
vm_stack_context_abort (vm_frame_ctx_t *frame_ctx_p, /**< frame context */
                        ecma_value_t *vm_stack_top_p) /**< current stack top */
{
    switch (VM_GET_CONTEXT_TYPE (vm_stack_top_p[-1]))
    {
    case VM_CONTEXT_FINALLY_THROW:
    case VM_CONTEXT_FINALLY_RETURN:
    {
        ecma_free_value (vm_stack_top_p[-2]);

        VM_MINUS_EQUAL_U16 (frame_ctx_p->context_depth, PARSER_TRY_CONTEXT_STACK_ALLOCATION);
        vm_stack_top_p -= PARSER_TRY_CONTEXT_STACK_ALLOCATION;
        break;
    }
    case VM_CONTEXT_FINALLY_JUMP:
    case VM_CONTEXT_TRY:
    {
        VM_MINUS_EQUAL_U16 (frame_ctx_p->context_depth, PARSER_TRY_CONTEXT_STACK_ALLOCATION);
        vm_stack_top_p -= PARSER_TRY_CONTEXT_STACK_ALLOCATION;
        break;
    }
    case VM_CONTEXT_CATCH:
    case VM_CONTEXT_WITH:
    {
        ecma_deref_object (frame_ctx_p->lex_env_p);
        frame_ctx_p->lex_env_p = ecma_get_object_from_value (vm_stack_top_p[-2]);

        JERRY_ASSERT (PARSER_TRY_CONTEXT_STACK_ALLOCATION == PARSER_WITH_CONTEXT_STACK_ALLOCATION);

        VM_MINUS_EQUAL_U16 (frame_ctx_p->context_depth, PARSER_TRY_CONTEXT_STACK_ALLOCATION);
        vm_stack_top_p -= PARSER_TRY_CONTEXT_STACK_ALLOCATION;
        break;
    }
    case VM_CONTEXT_FOR_IN:
    {
        jmem_cpointer_t current = (jmem_cpointer_t) vm_stack_top_p[-2];

        while (current != JMEM_CP_NULL)
        {
            ecma_collection_chunk_t *chunk_p = JMEM_CP_GET_NON_NULL_POINTER (ecma_collection_chunk_t,
                                               current);

            lit_utf8_byte_t *data_ptr = chunk_p->data;
            ecma_free_value (*(ecma_value_t *) data_ptr);

            current = chunk_p->next_chunk_cp;
            ecma_dealloc_collection_chunk (chunk_p);
        }

        ecma_free_value (vm_stack_top_p[-3]);

        VM_MINUS_EQUAL_U16 (frame_ctx_p->context_depth, PARSER_FOR_IN_CONTEXT_STACK_ALLOCATION);
        vm_stack_top_p -= PARSER_FOR_IN_CONTEXT_STACK_ALLOCATION;
        break;
    }
    default:
    {
        JERRY_UNREACHABLE ();
        break;
    }
    }

    return vm_stack_top_p;
} /* vm_stack_context_abort */