Repository: jerryscript-project/jerryscript
File: jerry-core/ecma/builtin-objects/ecma-builtin-array-prototype.c (C)

Code before:

#if ENABLED (JERRY_ES2015)
  ecma_value_t new_array = ecma_op_array_species_create (obj_p, 0);

  if (ECMA_IS_VALUE_ERROR (new_array))
  {
    return new_array;
  }
#else /* !ENABLED (JERRY_ES2015) */
  ecma_value_t new_array = ecma_op_create_array_object (NULL, 0, false);
  JERRY_ASSERT (!ECMA_IS_VALUE_ERROR (new_array));
#endif /* ENABLED (JERRY_ES2015) */

  ecma_object_t *new_array_p = ecma_get_object_from_value (new_array);

  /* 9. */
  uint32_t n = 0;

  if (ecma_op_object_is_fast_array (obj_p))
  {
    ecma_extended_object_t *ext_from_obj_p = (ecma_extended_object_t *) obj_p;

    if (ext_from_obj_p->u.array.u.hole_count < ECMA_FAST_ARRAY_HOLE_ONE
        && len != 0
        && start < end
        && end - start > len)
    {
      uint32_t length = end - start;
      ecma_extended_object_t *ext_to_obj_p = (ecma_extended_object_t *) new_array_p;
      ecma_value_t *to_buffer_p = ecma_fast_array_extend (new_array_p, length);
      ecma_value_t *from_buffer_p = ECMA_GET_NON_NULL_POINTER (ecma_value_t, obj_p->u1.property_list_cp);

      for (uint32_t k = start; k < end; k++, n++)
      {
        to_buffer_p[n] = ecma_copy_value_if_not_object (from_buffer_p[k]);
      }

      ext_to_obj_p->u.array.u.hole_count -= length * ECMA_FAST_ARRAY_HOLE_ONE;

      return new_array;
    }
  }

  /* 10. */
  for (uint32_t k = start; k < end; k++, n++)
  {
    /* 10.c */
    ecma_value_t get_value = ecma_op_object_find_by_uint32_index (obj_p, k);

    if (ECMA_IS_VALUE_ERROR (get_value))
    {

Review comment (bug):
Correct me if I'm wrong, but both `start` and `end` are in the [0, len] range, and we know that `start < end` from the condition, which means `end - start` will allways be `<= len`.

So essentially this just disables the fast path entirely.

Code after:

  bool use_fast_path = ecma_op_object_is_fast_array (obj_p);
  uint32_t copied_length = (end > start) ? end - start : 0;
#if ENABLED (JERRY_ES2015)
  ecma_value_t new_array = ecma_op_array_species_create (obj_p, copied_length);

  if (ECMA_IS_VALUE_ERROR (new_array))
  {
    return new_array;
  }
  use_fast_path &= ecma_op_object_is_fast_array (ecma_get_object_from_value (new_array));
#else /* !ENABLED (JERRY_ES2015) */
  ecma_value_t new_array = ecma_op_create_array_object (NULL, 0, false);
  JERRY_ASSERT (!ECMA_IS_VALUE_ERROR (new_array));
#endif /* ENABLED (JERRY_ES2015) */

  ecma_object_t *new_array_p = ecma_get_object_from_value (new_array);

  /* 9. */
  uint32_t n = 0;

  if (use_fast_path && copied_length > 0)
  {
    ecma_extended_object_t *ext_from_obj_p = (ecma_extended_object_t *) obj_p;

    if (ext_from_obj_p->u.array.u.hole_count < ECMA_FAST_ARRAY_HOLE_ONE)
    {
      ecma_extended_object_t *ext_to_obj_p = (ecma_extended_object_t *) new_array_p;

#if ENABLED (JERRY_ES2015)
      uint32_t target_length = ext_to_obj_p->u.array.length;
      ecma_value_t *to_buffer_p;
      if (copied_length == target_length)
      {
        to_buffer_p = ECMA_GET_NON_NULL_POINTER (ecma_value_t, new_array_p->u1.property_list_cp);
      }
      else if (copied_length > target_length)
      {
        to_buffer_p = ecma_fast_array_extend (new_array_p, copied_length);
      }
      else
      {
        ecma_delete_fast_array_properties (new_array_p, copied_length);
        to_buffer_p = ECMA_GET_NON_NULL_POINTER (ecma_value_t, new_array_p->u1.property_list_cp);
      }
#else /* !ENABLED (JERRY_ES2015) */
      ecma_value_t *to_buffer_p = ecma_fast_array_extend (new_array_p, copied_length);
#endif /* ENABLED (JERRY_ES2015) */

      ecma_value_t *from_buffer_p = ECMA_GET_NON_NULL_POINTER (ecma_value_t, obj_p->u1.property_list_cp);