예제 #1
0
/**
 * Compare ecma-string to ecma-string
 *
 * @return true - if strings are equal;
 *         false - otherwise.
 */
bool __attr_always_inline___
ecma_compare_ecma_strings (const ecma_string_t *string1_p, /* ecma-string */
                           const ecma_string_t *string2_p) /* ecma-string */
{
  JERRY_ASSERT (string1_p != NULL && string2_p != NULL);

  if (string1_p == string2_p)
  {
    return true;
  }

  if (string1_p->hash != string2_p->hash)
  {
    return false;
  }

  ecma_string_container_t string1_container = ECMA_STRING_GET_CONTAINER (string1_p);

  if (string1_container != ECMA_STRING_CONTAINER_HEAP_UTF8_STRING
      && string1_container == ECMA_STRING_GET_CONTAINER (string2_p))
  {
    return string1_p->u.common_field == string2_p->u.common_field;
  }

  return ecma_compare_ecma_strings_longpath (string1_p, string2_p);
} /* ecma_compare_ecma_strings */
예제 #2
0
/**
 * Get length of ecma-string
 *
 * @return number of characters in the string
 */
ecma_length_t
ecma_string_get_length (const ecma_string_t *string_p) /**< ecma-string */
{
  switch (ECMA_STRING_GET_CONTAINER (string_p))
  {
    case ECMA_STRING_CONTAINER_HEAP_UTF8_STRING:
    {
      return (ecma_length_t) (string_p->u.utf8_string.length);
    }
    case ECMA_STRING_CONTAINER_UINT32_IN_DESC:
    {
      return ecma_string_get_number_in_desc_size (string_p->u.uint32_number);
    }
    case ECMA_STRING_CONTAINER_MAGIC_STRING:
    {
      JERRY_ASSERT (ECMA_STRING_IS_ASCII (lit_get_magic_string_utf8 (string_p->u.magic_string_id),
                                          lit_get_magic_string_size (string_p->u.magic_string_id)));
      return lit_get_magic_string_size (string_p->u.magic_string_id);
    }
    default:
    {
      JERRY_ASSERT (ECMA_STRING_GET_CONTAINER (string_p) == ECMA_STRING_CONTAINER_MAGIC_STRING_EX);

      JERRY_ASSERT (ECMA_STRING_IS_ASCII (lit_get_magic_string_ex_utf8 (string_p->u.magic_string_ex_id),
                                          lit_get_magic_string_ex_size (string_p->u.magic_string_ex_id)));
      return lit_get_magic_string_ex_size (string_p->u.magic_string_ex_id);
    }
  }
} /* ecma_string_get_length */
예제 #3
0
/**
 * Lookup property in the LCache
 *
 * @return true - if (object, property name) pair is registered in LCache,
 *         false - probably, not registered.
 */
inline bool __attr_always_inline___
ecma_lcache_lookup (ecma_object_t *object_p, /**< object */
                    const ecma_string_t *prop_name_p, /**< property's name */
                    ecma_property_t **prop_p_p) /**< [out] if return value is true,
                                                 *         then here will be pointer to property,
                                                 *         if the object contains property with specified name,
                                                 *         or, otherwise - NULL;
                                                 *         if return value is false,
                                                 *         then the output parameter is not set */
{
#ifndef CONFIG_ECMA_LCACHE_DISABLE
  lit_string_hash_t hash_key = ecma_string_hash (prop_name_p);

  unsigned int object_cp;
  ECMA_SET_NON_NULL_POINTER (object_cp, object_p);

  for (uint32_t i = 0; i < ECMA_LCACHE_HASH_ROW_LENGTH; i++)
  {
    if (ecma_lcache_hash_table[hash_key][i].object_cp == object_cp)
    {
      ecma_string_t *entry_prop_name_p = ECMA_GET_NON_NULL_POINTER (ecma_string_t,
                                                                    ecma_lcache_hash_table[hash_key][i].prop_name_cp);

      JERRY_ASSERT (prop_name_p->hash == entry_prop_name_p->hash);

      if (ECMA_STRING_GET_CONTAINER (prop_name_p) == ECMA_STRING_GET_CONTAINER (entry_prop_name_p)
          && prop_name_p->u.common_field == entry_prop_name_p->u.common_field)
      {
        ecma_property_t *prop_p = ecma_lcache_hash_table[hash_key][i].prop_p;
        JERRY_ASSERT (prop_p == NULL || ecma_is_property_lcached (prop_p));

        *prop_p_p = prop_p;

        return true;
      }
      else
      {
        /* may be equal but it is long to compare it here */
      }
    }
  }
#else /* CONFIG_ECMA_LCACHE_DISABLE */
  (void) object_p;
  (void) prop_name_p;
  (void) prop_p_p;
#endif /* !CONFIG_ECMA_LCACHE_DISABLE */

  return false;
} /* ecma_lcache_lookup */
예제 #4
0
/**
 * Convert ecma-string's contents to a cesu-8 string and put it to the buffer.
 * It is the caller's responsibility to make sure that the string fits in the buffer.
 *
 * @return number of bytes, actually copied to the buffer.
 */
lit_utf8_size_t __attr_return_value_should_be_checked___
ecma_string_copy_to_utf8_buffer (const ecma_string_t *string_desc_p, /**< ecma-string descriptor */
                                 lit_utf8_byte_t *buffer_p, /**< destination buffer pointer
                                                             * (can be NULL if buffer_size == 0) */
                                 lit_utf8_size_t buffer_size) /**< size of buffer */
{
  JERRY_ASSERT (string_desc_p != NULL);
  JERRY_ASSERT (string_desc_p->refs_and_container >= ECMA_STRING_REF_ONE);
  JERRY_ASSERT (buffer_p != NULL || buffer_size == 0);
  JERRY_ASSERT (ecma_string_get_size (string_desc_p) <= buffer_size);

  lit_utf8_size_t size;

  switch (ECMA_STRING_GET_CONTAINER (string_desc_p))
  {
    case ECMA_STRING_CONTAINER_HEAP_UTF8_STRING:
    {
      size = string_desc_p->u.utf8_string.size;
      memcpy (buffer_p, string_desc_p + 1, size);
      break;
    }
    case ECMA_STRING_CONTAINER_UINT32_IN_DESC:
    {
      const uint32_t uint32_number = string_desc_p->u.uint32_number;
      size = ecma_uint32_to_utf8_string (uint32_number, buffer_p, buffer_size);
      break;
    }
    case ECMA_STRING_CONTAINER_MAGIC_STRING:
    {
      const lit_magic_string_id_t id = string_desc_p->u.magic_string_id;
      size = lit_get_magic_string_size (id);
      memcpy (buffer_p, lit_get_magic_string_utf8 (id), size);
      break;
    }
    default:
    {
      JERRY_ASSERT (ECMA_STRING_GET_CONTAINER (string_desc_p) == ECMA_STRING_CONTAINER_MAGIC_STRING_EX);

      const lit_magic_string_ex_id_t id = string_desc_p->u.magic_string_ex_id;
      size = lit_get_magic_string_ex_size (id);
      memcpy (buffer_p, lit_get_magic_string_ex_utf8 (id), size);
      break;
    }
  }

  JERRY_ASSERT (size <= buffer_size);
  return size;
} /* ecma_string_copy_to_utf8_buffer */
예제 #5
0
/**
 * Check if passed string equals to one of magic strings
 * and if equal magic string was found, return it's id in 'out_id_p' argument.
 *
 * @return true - if magic string equal to passed string was found,
 *         false - otherwise.
 */
bool
ecma_is_string_magic (const ecma_string_t *string_p, /**< ecma-string */
                      lit_magic_string_id_t *out_id_p) /**< [out] magic string's id */
{
  if (ECMA_STRING_GET_CONTAINER (string_p) == ECMA_STRING_CONTAINER_MAGIC_STRING)
  {
    JERRY_ASSERT (string_p->u.magic_string_id < LIT_MAGIC_STRING__COUNT);

    *out_id_p = (lit_magic_string_id_t) string_p->u.magic_string_id;

    return true;
  }
  else
  {
    /*
     * Any ecma-string constructor except ecma_concat_ecma_strings
     * should return ecma-string with ECMA_STRING_CONTAINER_MAGIC_STRING
     * container type if new ecma-string's content is equal to one of magic strings.
     */
#ifndef JERRY_NDEBUG
    JERRY_ASSERT (ecma_string_get_length (string_p) > LIT_MAGIC_STRING_LENGTH_LIMIT
                  || !ecma_is_string_magic_longpath (string_p, out_id_p));
#endif /* !JERRY_NDEBUG */

    return false;
  }
} /* ecma_is_string_magic */
예제 #6
0
/**
 * Lookup property in the LCache
 *
 * @return a pointer to an ecma_property_t if the lookup is successful
 *         NULL otherwise
 */
inline ecma_property_t * __attr_always_inline___
ecma_lcache_lookup (ecma_object_t *object_p, /**< object */
                    const ecma_string_t *prop_name_p) /**< property's name */
{
  JERRY_ASSERT (object_p != NULL);
  JERRY_ASSERT (prop_name_p != NULL);

#ifndef CONFIG_ECMA_LCACHE_DISABLE
  jmem_cpointer_t object_cp;
  ECMA_SET_NON_NULL_POINTER (object_cp, object_p);

  size_t row_index = ecma_lcache_row_index (object_cp, prop_name_p);
  ecma_lcache_hash_entry_t *entry_p = JERRY_HASH_TABLE_CONTEXT (table) [row_index];
  ecma_lcache_hash_entry_t *entry_end_p = entry_p + ECMA_LCACHE_HASH_ROW_LENGTH;
  ecma_string_container_t prop_container = ECMA_STRING_GET_CONTAINER (prop_name_p);

  while (entry_p < entry_end_p)
  {
    if (entry_p->object_cp == object_cp)
    {
      ecma_string_t *entry_prop_name_p = ECMA_GET_NON_NULL_POINTER (ecma_string_t,
                                                                    entry_p->prop_name_cp);

      JERRY_ASSERT ((prop_name_p->hash & ECMA_LCACHE_HASH_MASK) == (entry_prop_name_p->hash & ECMA_LCACHE_HASH_MASK));

      if (prop_name_p == entry_prop_name_p
          || (prop_container > ECMA_STRING_CONTAINER_HEAP_LONG_UTF8_STRING
              && prop_container == ECMA_STRING_GET_CONTAINER (entry_prop_name_p)
              && prop_name_p->u.common_field == entry_prop_name_p->u.common_field))
      {
        ecma_property_t *prop_p = entry_p->prop_p;
        JERRY_ASSERT (prop_p != NULL && ecma_is_property_lcached (prop_p));

        return prop_p;
      }
      else
      {
        /* They can be equal, but generic string comparison is too costly. */
      }
    }
    entry_p++;
  }
#endif /* !CONFIG_ECMA_LCACHE_DISABLE */

  return NULL;
} /* ecma_lcache_lookup */
예제 #7
0
/**
 * Get size of ecma-string
 *
 * @return number of bytes in the buffer needed to represent the string
 */
lit_utf8_size_t
ecma_string_get_size (const ecma_string_t *string_p) /**< ecma-string */
{
  switch (ECMA_STRING_GET_CONTAINER (string_p))
  {
    case ECMA_STRING_CONTAINER_HEAP_UTF8_STRING:
    {
      return (lit_utf8_size_t) string_p->u.utf8_string.size;
    }
    case ECMA_STRING_CONTAINER_UINT32_IN_DESC:
    {
      return (lit_utf8_size_t) ecma_string_get_number_in_desc_size (string_p->u.uint32_number);
    }
    case ECMA_STRING_CONTAINER_MAGIC_STRING:
    {
      return lit_get_magic_string_size (string_p->u.magic_string_id);
    }
    default:
    {
      JERRY_ASSERT (ECMA_STRING_GET_CONTAINER (string_p) == ECMA_STRING_CONTAINER_MAGIC_STRING_EX);
      return lit_get_magic_string_ex_size (string_p->u.magic_string_ex_id);
    }
  }
} /* ecma_string_get_size */
예제 #8
0
/**
 * Print literal.
 */
void
util_print_literal (lexer_literal_t *literal_p) /**< literal */
{
  if (literal_p->type == LEXER_IDENT_LITERAL)
  {
    if (literal_p->status_flags & LEXER_FLAG_VAR)
    {
      printf ("var_ident(");
    }
    else
    {
      printf ("ident(");
    }
    util_print_chars (literal_p->u.char_p, literal_p->prop.length);
  }
  else if (literal_p->type == LEXER_FUNCTION_LITERAL)
  {
    printf ("function");
    return;
  }
  else if (literal_p->type == LEXER_STRING_LITERAL)
  {
    printf ("string(");
    util_print_chars (literal_p->u.char_p, literal_p->prop.length);
  }
  else if (literal_p->type == LEXER_NUMBER_LITERAL)
  {
    ecma_string_t *value_p = JMEM_CP_GET_NON_NULL_POINTER (ecma_string_t, literal_p->u.value);

    JERRY_ASSERT (ECMA_STRING_GET_CONTAINER (value_p) == ECMA_STRING_LITERAL_NUMBER);

    printf ("number(");
    util_print_number (ecma_get_number_from_value (value_p->u.lit_number));
  }
  else if (literal_p->type == LEXER_REGEXP_LITERAL)
  {
    printf ("regexp");
    return;
  }
  else
  {
    printf ("unknown");
    return;
  }

  printf (")");
} /* util_print_literal */
예제 #9
0
/**
 * Checks whether the string equals to "length".
 *
 * @return true if the string equals to "length"
 *         false otherwise
 */
inline bool __attr_always_inline___
ecma_string_is_length (const ecma_string_t *string_p) /**< property name */
{
  ecma_string_container_t container = ECMA_STRING_GET_CONTAINER (string_p);

  if (container == ECMA_STRING_CONTAINER_MAGIC_STRING)
  {
    return string_p->u.magic_string_id == LIT_MAGIC_STRING_LENGTH;
  }

  if (container != ECMA_STRING_CONTAINER_HEAP_UTF8_STRING
      || string_p->u.utf8_string.size != 6
      || string_p->hash != LIT_STRING_LENGTH_HASH)
  {
    return false;
  }

  return !strncmp ((char *) (string_p + 1), "length", 6);
} /* ecma_string_is_length */
예제 #10
0
/**
 * Decrease reference counter and deallocate ecma-string
 * if the counter becomes zero.
 */
void
ecma_deref_ecma_string (ecma_string_t *string_p) /**< ecma-string */
{
  JERRY_ASSERT (string_p != NULL);
  JERRY_ASSERT (string_p->refs_and_container >= ECMA_STRING_REF_ONE);

  /* Decrease reference counter. */
  string_p->refs_and_container = (uint16_t) (string_p->refs_and_container - ECMA_STRING_REF_ONE);

  if (string_p->refs_and_container >= ECMA_STRING_REF_ONE)
  {
    return;
  }

  switch (ECMA_STRING_GET_CONTAINER (string_p))
  {
    case ECMA_STRING_CONTAINER_HEAP_UTF8_STRING:
    {
      jmem_heap_free_block (string_p, string_p->u.utf8_string.size + sizeof (ecma_string_t));
      return;
    }
    case ECMA_STRING_CONTAINER_UINT32_IN_DESC:
    case ECMA_STRING_CONTAINER_MAGIC_STRING:
    case ECMA_STRING_CONTAINER_MAGIC_STRING_EX:
    {
      /* only the string descriptor itself should be freed */
      break;
    }
    case ECMA_STRING_LITERAL_NUMBER:
    {
      ecma_fast_free_value (string_p->u.lit_number);
      break;
    }
    default:
    {
      JERRY_UNREACHABLE ();
      break;
    }
  }

  ecma_dealloc_string (string_p);
} /* ecma_deref_ecma_string */
예제 #11
0
/**
 * Converts a string into a property name
 *
 * @return the compressed pointer part of the name
 */
static inline jmem_cpointer_t __attr_always_inline___
ecma_string_to_lcache_property_name (const ecma_string_t *prop_name_p, /**< property name */
                                     ecma_property_t *name_type_p) /**< [out] property name type */
{
  ecma_string_container_t container = ECMA_STRING_GET_CONTAINER (prop_name_p);

  switch (container)
  {
    case ECMA_STRING_CONTAINER_UINT32_IN_DESC:
    case ECMA_STRING_CONTAINER_MAGIC_STRING:
    case ECMA_STRING_CONTAINER_MAGIC_STRING_EX:
    {
#ifdef JERRY_CPOINTER_32_BIT

      *name_type_p = (ecma_property_t) container;
      return (jmem_cpointer_t) prop_name_p->u.uint32_number;

#else /* !JERRY_CPOINTER_32_BIT */

      if (prop_name_p->u.uint32_number < (UINT16_MAX + 1))
      {
        *name_type_p = (ecma_property_t) container;
        return (jmem_cpointer_t) prop_name_p->u.uint32_number;
      }

#endif /* JERRY_CPOINTER_32_BIT */

      break;
    }
    default:
    {
      break;
    }
  }

  *name_type_p = ECMA_PROPERTY_NAME_TYPE_STRING;

  jmem_cpointer_t prop_name_cp;
  ECMA_SET_NON_NULL_POINTER (prop_name_cp, prop_name_p);
  return prop_name_cp;
} /* ecma_string_to_lcache_property_name */
예제 #12
0
/**
 * Convert ecma-string to number
 */
ecma_number_t
ecma_string_to_number (const ecma_string_t *str_p) /**< ecma-string */
{
  JERRY_ASSERT (str_p != NULL);

  switch (ECMA_STRING_GET_CONTAINER (str_p))
  {
    case ECMA_STRING_CONTAINER_UINT32_IN_DESC:
    {
      return ((ecma_number_t) str_p->u.uint32_number);
    }

    case ECMA_STRING_CONTAINER_HEAP_UTF8_STRING:
    case ECMA_STRING_CONTAINER_MAGIC_STRING:
    case ECMA_STRING_CONTAINER_MAGIC_STRING_EX:
    {
      ecma_number_t num;

      ECMA_STRING_TO_UTF8_STRING (str_p, str_buffer_p, str_buffer_size);

      if (str_buffer_size == 0)
      {
        return ECMA_NUMBER_ZERO;
      }

      num = ecma_utf8_string_to_number (str_buffer_p, str_buffer_size);

      ECMA_FINALIZE_UTF8_STRING (str_buffer_p, str_buffer_size);

      return num;
    }

    default:
    {
      JERRY_UNREACHABLE ();
    }
  }
} /* ecma_string_to_number */
예제 #13
0
/**
 * Get character from specified position in the ecma-string.
 *
 * @return character value
 */
ecma_char_t
ecma_string_get_char_at_pos (const ecma_string_t *string_p, /**< ecma-string */
                             ecma_length_t index) /**< index of character */
{
  JERRY_ASSERT (index < ecma_string_get_length (string_p));

  lit_utf8_size_t buffer_size;
  bool is_ascii;
  const lit_utf8_byte_t *chars_p = ecma_string_raw_chars (string_p, &buffer_size, &is_ascii);

  if (chars_p != NULL)
  {
    if (is_ascii)
    {
      return chars_p[index];
    }

    return lit_utf8_string_code_unit_at (chars_p, buffer_size, index);
  }

  ecma_char_t ch;

  JMEM_DEFINE_LOCAL_ARRAY (utf8_str_p, buffer_size, lit_utf8_byte_t);

  ecma_string_to_utf8_bytes (string_p, utf8_str_p, buffer_size);

  JERRY_ASSERT (ECMA_STRING_GET_CONTAINER (string_p) == ECMA_STRING_CONTAINER_UINT32_IN_DESC);
  /* Both above must be ascii strings. */
  JERRY_ASSERT (is_ascii);

  ch = utf8_str_p[index];

  JMEM_FINALIZE_LOCAL_ARRAY (utf8_str_p);

  return ch;
} /* ecma_string_get_char_at_pos */
예제 #14
0
/**
 * Lazy instantation of non-builtin ecma function object's properties
 *
 * Warning:
 *         Only non-configurable properties could be instantiated lazily in this function,
 *         as configurable properties could be deleted and it would be incorrect
 *         to reinstantiate them in the function in second time.
 *
 * @return pointer to newly instantiated property, if a property was instantiated,
 *         NULL - otherwise
 */
ecma_property_t *
ecma_op_function_try_lazy_instantiate_property (ecma_object_t *object_p, /**< the function object */
                                                ecma_string_t *property_name_p) /**< property name */
{
  static const char prototype_str_p[] = "prototype";

  JERRY_ASSERT (!ecma_get_object_is_builtin (object_p));

  ecma_string_container_t container = ECMA_STRING_GET_CONTAINER (property_name_p);

  /* Check whether the property_name_p is prototype */
  if (container == ECMA_STRING_CONTAINER_MAGIC_STRING)
  {
    if (property_name_p->u.magic_string_id != LIT_MAGIC_STRING_PROTOTYPE)
    {
      return NULL;
    }
  }
  else if (container != ECMA_STRING_CONTAINER_HEAP_UTF8_STRING
           || property_name_p->u.utf8_string.size != (sizeof (prototype_str_p) - 1))
  {
    return NULL;
  }
  else
  {
    if (strncmp ((char *) (property_name_p + 1), prototype_str_p, (sizeof (prototype_str_p) - 1)) != 0)
    {
      return NULL;
    }
  }

  /* ECMA-262 v5, 13.2, 16-18 */

  /* 16. */
  ecma_object_t *proto_object_p = ecma_op_create_object_object_noarg ();

  /* 17. */
  ecma_string_t *magic_string_constructor_p = ecma_get_magic_string (LIT_MAGIC_STRING_CONSTRUCTOR);

  ecma_property_value_t *constructor_prop_value_p;
  constructor_prop_value_p = ecma_create_named_data_property (proto_object_p,
                                                              magic_string_constructor_p,
                                                              ECMA_PROPERTY_CONFIGURABLE_WRITABLE,
                                                              NULL);

  constructor_prop_value_p->value = ecma_make_object_value (object_p);

  ecma_deref_ecma_string (magic_string_constructor_p);

  /* 18. */
  ecma_property_t *prototype_prop_p;
  ecma_property_value_t *prototype_prop_value_p;
  prototype_prop_value_p = ecma_create_named_data_property (object_p,
                                                            property_name_p,
                                                            ECMA_PROPERTY_FLAG_WRITABLE,
                                                            &prototype_prop_p);

  prototype_prop_value_p->value = ecma_make_object_value (proto_object_p);

  ecma_deref_object (proto_object_p);

  return prototype_prop_p;
} /* ecma_op_function_try_lazy_instantiate_property */
예제 #15
0
/**
 * [[GetOwnProperty]] ecma String object's operation
 *
 * See also:
 *          ECMA-262 v5, 8.6.2; ECMA-262 v5, Table 8
 *          ECMA-262 v5, 15.5.5.2
 *
 * @return ecma value
 *         Returned value must be freed with ecma_free_value
 */
ecma_property_t *
ecma_op_string_object_get_own_property (ecma_object_t *obj_p, /**< a String object */
                                        ecma_string_t *property_name_p) /**< property name */
{
  JERRY_ASSERT (ecma_get_object_type (obj_p) == ECMA_OBJECT_TYPE_STRING);

  // 1.
  ecma_property_t *prop_p = ecma_op_general_object_get_own_property (obj_p, property_name_p);

  // 2.
  if (prop_p != NULL)
  {
    return prop_p;
  }

  // 3., 5.
  uint32_t uint32_index;
  ecma_string_t *new_prop_name_p;

  if (ECMA_STRING_GET_CONTAINER (property_name_p) == ECMA_STRING_CONTAINER_UINT32_IN_DESC)
  {
    uint32_index = property_name_p->u.uint32_number;

    new_prop_name_p = property_name_p;
    ecma_ref_ecma_string (new_prop_name_p);
  }
  else
  {
    ecma_number_t index = ecma_string_to_number (property_name_p);
    uint32_index = ecma_number_to_uint32 (index);

    ecma_string_t *to_str_p = ecma_new_ecma_string_from_uint32 (uint32_index);

    bool are_equal = ecma_compare_ecma_strings (to_str_p, property_name_p);

    if (!are_equal)
    {
      ecma_deref_ecma_string (to_str_p);

      return NULL;
    }
    else
    {
      new_prop_name_p = to_str_p;
    }
  }

  // 4.
  ecma_property_t *prim_value_prop_p = ecma_get_internal_property (obj_p,
                                                                   ECMA_INTERNAL_PROPERTY_ECMA_VALUE);
  ecma_string_t *prim_value_str_p;
  prim_value_str_p = ecma_get_string_from_value (ecma_get_internal_property_value (prim_value_prop_p));

  // 6.
  ecma_length_t length = ecma_string_get_length (prim_value_str_p);

  ecma_property_t *new_prop_p;

  if (uint32_index >= (uint32_t) length)
  {
    // 7.
    new_prop_p = NULL;
  }
  else
  {
    // 8.
    ecma_char_t c = ecma_string_get_char_at_pos (prim_value_str_p, uint32_index);

    // 9.
    ecma_string_t *new_prop_str_value_p = ecma_new_ecma_string_from_code_unit (c);

    new_prop_p = ecma_create_named_data_property (obj_p,
                                                  new_prop_name_p,
                                                  ECMA_PROPERTY_FLAG_ENUMERABLE);

    ecma_set_named_data_property_value (new_prop_p,
                                        ecma_make_string_value (new_prop_str_value_p));
  }

  ecma_deref_ecma_string (new_prop_name_p);

  return new_prop_p;
} /* ecma_op_string_object_get_own_property */
예제 #16
0
/**
 * Concatenate ecma-strings
 *
 * @return concatenation of two ecma-strings
 */
ecma_string_t *
ecma_concat_ecma_strings (ecma_string_t *string1_p, /**< first ecma-string */
                          ecma_string_t *string2_p) /**< second ecma-string */
{
  JERRY_ASSERT (string1_p != NULL
                && string2_p != NULL);

  if (ecma_string_is_empty (string1_p))
  {
    ecma_ref_ecma_string (string2_p);
    return string2_p;
  }
  else if (ecma_string_is_empty (string2_p))
  {
    ecma_ref_ecma_string (string1_p);
    return string1_p;
  }

  const lit_utf8_byte_t *utf8_string1_p, *utf8_string2_p;
  lit_utf8_size_t utf8_string1_size, utf8_string2_size;
  lit_utf8_size_t utf8_string1_length, utf8_string2_length;

  lit_utf8_byte_t uint32_to_string_buffer1[ECMA_MAX_CHARS_IN_STRINGIFIED_UINT32];
  lit_utf8_byte_t uint32_to_string_buffer2[ECMA_MAX_CHARS_IN_STRINGIFIED_UINT32];

  switch (ECMA_STRING_GET_CONTAINER (string1_p))
  {
    case ECMA_STRING_CONTAINER_HEAP_UTF8_STRING:
    {
      utf8_string1_p = (lit_utf8_byte_t *) (string1_p + 1);
      utf8_string1_size = string1_p->u.utf8_string.size;
      utf8_string1_length = string1_p->u.utf8_string.length;
      break;
    }
    case ECMA_STRING_CONTAINER_UINT32_IN_DESC:
    {
      utf8_string1_size = ecma_uint32_to_utf8_string (string1_p->u.uint32_number,
                                                      uint32_to_string_buffer1,
                                                      ECMA_MAX_CHARS_IN_STRINGIFIED_UINT32);
      utf8_string1_p = uint32_to_string_buffer1;
      utf8_string1_length = utf8_string1_size;
      break;
    }
    case ECMA_STRING_CONTAINER_MAGIC_STRING:
    {
      utf8_string1_p = lit_get_magic_string_utf8 (string1_p->u.magic_string_id);
      utf8_string1_size = lit_get_magic_string_size (string1_p->u.magic_string_id);
      utf8_string1_length = utf8_string1_size;
      break;
    }
    default:
    {
      JERRY_ASSERT (ECMA_STRING_GET_CONTAINER (string1_p) == ECMA_STRING_CONTAINER_MAGIC_STRING_EX);

      utf8_string1_p = lit_get_magic_string_ex_utf8 (string1_p->u.magic_string_id);
      utf8_string1_size = lit_get_magic_string_ex_size (string1_p->u.magic_string_id);
      utf8_string1_length = utf8_string1_size;
      break;
    }
  }

  switch (ECMA_STRING_GET_CONTAINER (string2_p))
  {
    case ECMA_STRING_CONTAINER_HEAP_UTF8_STRING:
    {
      utf8_string2_p = (lit_utf8_byte_t *) (string2_p + 1);
      utf8_string2_size = string2_p->u.utf8_string.size;
      utf8_string2_length = string2_p->u.utf8_string.length;
      break;
    }
    case ECMA_STRING_CONTAINER_UINT32_IN_DESC:
    {
      utf8_string2_size = ecma_uint32_to_utf8_string (string2_p->u.uint32_number,
                                                      uint32_to_string_buffer2,
                                                      ECMA_MAX_CHARS_IN_STRINGIFIED_UINT32);
      utf8_string2_p = uint32_to_string_buffer2;
      utf8_string2_length = utf8_string2_size;
      break;
    }
    case ECMA_STRING_CONTAINER_MAGIC_STRING:
    {
      utf8_string2_p = lit_get_magic_string_utf8 (string2_p->u.magic_string_id);
      utf8_string2_size = lit_get_magic_string_size (string2_p->u.magic_string_id);
      utf8_string2_length = utf8_string2_size;
      break;
    }
    default:
    {
      JERRY_ASSERT (ECMA_STRING_GET_CONTAINER (string2_p) == ECMA_STRING_CONTAINER_MAGIC_STRING_EX);

      utf8_string2_p = lit_get_magic_string_ex_utf8 (string2_p->u.magic_string_id);
      utf8_string2_size = lit_get_magic_string_ex_size (string2_p->u.magic_string_id);
      utf8_string2_length = utf8_string2_size;
      break;
    }
  }

  JERRY_ASSERT (utf8_string1_size > 0);
  JERRY_ASSERT (utf8_string2_size > 0);
  JERRY_ASSERT (utf8_string1_length <= utf8_string1_size);
  JERRY_ASSERT (utf8_string2_length <= utf8_string2_size);

  lit_utf8_size_t new_size = utf8_string1_size + utf8_string2_size;

  JERRY_ASSERT (new_size <= UINT16_MAX);

  ecma_string_t *string_desc_p = jmem_heap_alloc_block (sizeof (ecma_string_t) + new_size);

  string_desc_p->refs_and_container = ECMA_STRING_CONTAINER_HEAP_UTF8_STRING | ECMA_STRING_REF_ONE;
  string_desc_p->hash = lit_utf8_string_hash_combine (string1_p->hash, utf8_string2_p, utf8_string2_size);
  string_desc_p->u.common_field = 0;
  string_desc_p->u.utf8_string.size = (uint16_t) new_size;
  string_desc_p->u.utf8_string.length = (uint16_t) (utf8_string1_length + utf8_string2_length);

  lit_utf8_byte_t *data_p = (lit_utf8_byte_t *) (string_desc_p + 1);
  memcpy (data_p, utf8_string1_p, utf8_string1_size);
  memcpy (data_p + utf8_string1_size, utf8_string2_p, utf8_string2_size);

  return string_desc_p;
} /* ecma_concat_ecma_strings */
예제 #17
0
/**
 * Long path part of ecma-string to ecma-string comparison routine
 *
 * See also:
 *          ecma_compare_ecma_strings
 *
 * @return true - if strings are equal;
 *         false - otherwise.
 */
static bool __attr_noinline___
ecma_compare_ecma_strings_longpath (const ecma_string_t *string1_p, /* ecma-string */
                                    const ecma_string_t *string2_p) /* ecma-string */
{
  if (ECMA_STRING_GET_CONTAINER (string1_p) == ECMA_STRING_GET_CONTAINER (string2_p))
  {
    switch (ECMA_STRING_GET_CONTAINER (string1_p))
    {
      case ECMA_STRING_CONTAINER_UINT32_IN_DESC:
      {
        JERRY_ASSERT (string1_p->u.uint32_number != string2_p->u.uint32_number);
        return false;
      }
      case ECMA_STRING_CONTAINER_MAGIC_STRING:
      {
        JERRY_ASSERT (string1_p->u.magic_string_id != string2_p->u.magic_string_id);
        return false;
      }
      case ECMA_STRING_CONTAINER_MAGIC_STRING_EX:
      {
        JERRY_ASSERT (string1_p->u.magic_string_ex_id != string2_p->u.magic_string_ex_id);
        return false;
      }
      default:
      {
        JERRY_ASSERT (ECMA_STRING_GET_CONTAINER (string1_p) == ECMA_STRING_CONTAINER_HEAP_UTF8_STRING);
        break;
      }
    }
  }

  const lit_utf8_byte_t *utf8_string1_p, *utf8_string2_p;
  lit_utf8_size_t utf8_string1_size, utf8_string2_size;

  lit_utf8_byte_t uint32_to_string_buffer1[ECMA_MAX_CHARS_IN_STRINGIFIED_UINT32];
  lit_utf8_byte_t uint32_to_string_buffer2[ECMA_MAX_CHARS_IN_STRINGIFIED_UINT32];

  switch (ECMA_STRING_GET_CONTAINER (string1_p))
  {
    case ECMA_STRING_CONTAINER_HEAP_UTF8_STRING:
    {
      utf8_string1_p = (lit_utf8_byte_t *) (string1_p + 1);
      utf8_string1_size = string1_p->u.utf8_string.size;
      break;
    }
    case ECMA_STRING_CONTAINER_UINT32_IN_DESC:
    {
      utf8_string1_size = ecma_uint32_to_utf8_string (string1_p->u.uint32_number,
                                                      uint32_to_string_buffer1,
                                                      ECMA_MAX_CHARS_IN_STRINGIFIED_UINT32);
      utf8_string1_p = uint32_to_string_buffer1;
      break;
    }
    case ECMA_STRING_CONTAINER_MAGIC_STRING:
    {
      utf8_string1_p = lit_get_magic_string_utf8 (string1_p->u.magic_string_id);
      utf8_string1_size = lit_get_magic_string_size (string1_p->u.magic_string_id);
      break;
    }
    default:
    {
      JERRY_ASSERT (ECMA_STRING_GET_CONTAINER (string1_p) == ECMA_STRING_CONTAINER_MAGIC_STRING_EX);

      utf8_string1_p = lit_get_magic_string_ex_utf8 (string1_p->u.magic_string_id);
      utf8_string1_size = lit_get_magic_string_ex_size (string1_p->u.magic_string_id);
      break;
    }
  }

  switch (ECMA_STRING_GET_CONTAINER (string2_p))
  {
    case ECMA_STRING_CONTAINER_HEAP_UTF8_STRING:
    {
      utf8_string2_p = (lit_utf8_byte_t *) (string2_p + 1);
      utf8_string2_size = string2_p->u.utf8_string.size;
      break;
    }
    case ECMA_STRING_CONTAINER_UINT32_IN_DESC:
    {
      utf8_string2_size = ecma_uint32_to_utf8_string (string2_p->u.uint32_number,
                                                      uint32_to_string_buffer2,
                                                      ECMA_MAX_CHARS_IN_STRINGIFIED_UINT32);
      utf8_string2_p = uint32_to_string_buffer2;
      break;
    }
    case ECMA_STRING_CONTAINER_MAGIC_STRING:
    {
      utf8_string2_p = lit_get_magic_string_utf8 (string2_p->u.magic_string_id);
      utf8_string2_size = lit_get_magic_string_size (string2_p->u.magic_string_id);
      break;
    }
    default:
    {
      JERRY_ASSERT (ECMA_STRING_GET_CONTAINER (string2_p) == ECMA_STRING_CONTAINER_MAGIC_STRING_EX);

      utf8_string2_p = lit_get_magic_string_ex_utf8 (string2_p->u.magic_string_id);
      utf8_string2_size = lit_get_magic_string_ex_size (string2_p->u.magic_string_id);
      break;
    }
  }

  if (utf8_string1_size != utf8_string2_size)
  {
    return false;
  }

  return !strncmp ((char *) utf8_string1_p, (char *) utf8_string2_p, utf8_string1_size);
} /* ecma_compare_ecma_strings_longpath */
예제 #18
0
/**
 * Check if string is array index.
 *
 * @return true - if string is valid array index
 *         false - otherwise
 */
bool
ecma_string_get_array_index (const ecma_string_t *str_p, /**< ecma-string */
                             uint32_t *out_index_p) /**< [out] index */
{
  const ecma_string_container_t type = ECMA_STRING_GET_CONTAINER (str_p);

  if (type == ECMA_STRING_CONTAINER_UINT32_IN_DESC)
  {
    const uint32_t index = str_p->u.uint32_number;
    *out_index_p = index;
    return index != UINT32_MAX;
  }
  else if (type == ECMA_STRING_CONTAINER_MAGIC_STRING)
  {
    return false;
  }
  else
  {
    lit_utf8_size_t size;
    const lit_utf8_byte_t *raw_str_p;

    if (unlikely (type == ECMA_STRING_CONTAINER_MAGIC_STRING_EX))
    {
      size = lit_get_magic_string_ex_size (str_p->u.magic_string_ex_id);
      raw_str_p = lit_get_magic_string_ex_utf8 (str_p->u.magic_string_ex_id);
    }
    else
    {
      JERRY_ASSERT (type == ECMA_STRING_CONTAINER_HEAP_UTF8_STRING);

      size = str_p->u.utf8_string.size;
      raw_str_p = (const lit_utf8_byte_t *) (str_p + 1);
    }

    if (*raw_str_p == LIT_CHAR_0)
    {
      *out_index_p = 0;
      return size == 1;
    }

    if (size > 10)
    {
      return false;
    }

    uint32_t index = 0;
    const lit_utf8_size_t end = (size == 10) ? 9 : size;

    for (lit_utf8_size_t i = 0; i < end; i++)
    {
      if (raw_str_p[i] > LIT_CHAR_9 || raw_str_p[i] < LIT_CHAR_0)
      {
        return false;
      }

      index = (index * 10) + (uint32_t) (raw_str_p[i] - LIT_CHAR_0);
    }

    if (size == 10)
    {
      if (index > UINT32_MAX / 10
          || raw_str_p[9] > LIT_CHAR_9
          || raw_str_p[9] < LIT_CHAR_0)
      {
        return false;
      }

      index *= 10;
      const uint32_t digit = (uint32_t) (raw_str_p[9] - LIT_CHAR_0);

      if (index >= UINT32_MAX - digit)
      {
        return false;
      }

      index += digit;
    }

    *out_index_p = index;
    return true;
  }
} /* ecma_string_get_array_index */
예제 #19
0
/**
 * Checks whether ecma string is empty or not
 *
 * @return true  - if empty
 *         false - otherwise
 */
bool
ecma_string_is_empty (const ecma_string_t *str_p) /**< ecma-string */
{
  return (ECMA_STRING_GET_CONTAINER (str_p) == ECMA_STRING_CONTAINER_MAGIC_STRING
          && str_p->u.magic_string_id == LIT_MAGIC_STRING__EMPTY);
} /* ecma_string_is_empty */
예제 #20
0
/**
 * Returns with the raw byte array of the string, if it is available.
 *
 * @return byte array start - if the byte array of a string is available
 *         NULL - otherwise
 */
const lit_utf8_byte_t *
ecma_string_raw_chars (const ecma_string_t *string_p, /**< ecma-string */
                       lit_utf8_size_t *size_p, /**< [out] size of the ecma string */
                       bool *is_ascii_p) /**< [out] true, if the string is an ascii
                                          *               character sequence (size == length)
                                          *         false, otherwise */
{
  ecma_length_t length;
  lit_utf8_size_t size;
  const lit_utf8_byte_t *result_p;

  switch (ECMA_STRING_GET_CONTAINER (string_p))
  {
    case ECMA_STRING_CONTAINER_HEAP_UTF8_STRING:
    {
      size = string_p->u.utf8_string.size;
      length = string_p->u.utf8_string.length;
      result_p = (const lit_utf8_byte_t *) (string_p + 1);
      break;
    }
    case ECMA_STRING_CONTAINER_UINT32_IN_DESC:
    {
      size = (lit_utf8_size_t) ecma_string_get_number_in_desc_size (string_p->u.uint32_number);

      /* All numbers must be ascii strings. */
      JERRY_ASSERT (ecma_string_get_length (string_p) == size);

      length = size;
      result_p = NULL;
      break;
    }
    case ECMA_STRING_CONTAINER_MAGIC_STRING:
    {
      size = lit_get_magic_string_size (string_p->u.magic_string_id);

      length = size;
      result_p = lit_get_magic_string_utf8 (string_p->u.magic_string_id);

      /* All magic strings must be ascii strings. */
      JERRY_ASSERT (ECMA_STRING_IS_ASCII (result_p, size));
      break;
    }
    default:
    {
      JERRY_ASSERT (ECMA_STRING_GET_CONTAINER (string_p) == ECMA_STRING_CONTAINER_MAGIC_STRING_EX);

      size = lit_get_magic_string_ex_size (string_p->u.magic_string_ex_id);
      length = size;

      result_p = lit_get_magic_string_ex_utf8 (string_p->u.magic_string_ex_id);

      /* All extended magic strings must be ascii strings. */
      JERRY_ASSERT (ECMA_STRING_IS_ASCII (result_p, size));
      break;
    }
  }

  *size_p = size;
  *is_ascii_p = (length == size);
  return result_p;
} /* ecma_string_raw_chars */
예제 #21
0
/**
 * Relational compare of ecma-strings.
 *
 * First string is less than second string if:
 *  - strings are not equal;
 *  - first string is prefix of second or is lexicographically less than second.
 *
 * @return true - if first string is less than second string,
 *         false - otherwise.
 */
bool
ecma_compare_ecma_strings_relational (const ecma_string_t *string1_p, /**< ecma-string */
                                      const ecma_string_t *string2_p) /**< ecma-string */
{
  if (ecma_compare_ecma_strings (string1_p,
                                 string2_p))
  {
    return false;
  }

  const lit_utf8_byte_t *utf8_string1_p, *utf8_string2_p;
  lit_utf8_size_t utf8_string1_size, utf8_string2_size;

  lit_utf8_byte_t uint32_to_string_buffer1[ECMA_MAX_CHARS_IN_STRINGIFIED_UINT32];
  lit_utf8_byte_t uint32_to_string_buffer2[ECMA_MAX_CHARS_IN_STRINGIFIED_UINT32];

  switch (ECMA_STRING_GET_CONTAINER (string1_p))
  {
    case ECMA_STRING_CONTAINER_HEAP_UTF8_STRING:
    {
      utf8_string1_p = (lit_utf8_byte_t *) (string1_p + 1);
      utf8_string1_size = string1_p->u.utf8_string.size;
      break;
    }
    case ECMA_STRING_CONTAINER_UINT32_IN_DESC:
    {
      utf8_string1_size = ecma_uint32_to_utf8_string (string1_p->u.uint32_number,
                                                      uint32_to_string_buffer1,
                                                      ECMA_MAX_CHARS_IN_STRINGIFIED_UINT32);
      utf8_string1_p = uint32_to_string_buffer1;
      break;
    }
    case ECMA_STRING_CONTAINER_MAGIC_STRING:
    {
      utf8_string1_p = lit_get_magic_string_utf8 (string1_p->u.magic_string_id);
      utf8_string1_size = lit_get_magic_string_size (string1_p->u.magic_string_id);
      break;
    }
    default:
    {
      JERRY_ASSERT (ECMA_STRING_GET_CONTAINER (string1_p) == ECMA_STRING_CONTAINER_MAGIC_STRING_EX);

      utf8_string1_p = lit_get_magic_string_ex_utf8 (string1_p->u.magic_string_id);
      utf8_string1_size = lit_get_magic_string_ex_size (string1_p->u.magic_string_id);
      break;
    }
  }

  switch (ECMA_STRING_GET_CONTAINER (string2_p))
  {
    case ECMA_STRING_CONTAINER_HEAP_UTF8_STRING:
    {
      utf8_string2_p = (lit_utf8_byte_t *) (string2_p + 1);
      utf8_string2_size = string2_p->u.utf8_string.size;
      break;
    }
    case ECMA_STRING_CONTAINER_UINT32_IN_DESC:
    {
      utf8_string2_size = ecma_uint32_to_utf8_string (string2_p->u.uint32_number,
                                                      uint32_to_string_buffer2,
                                                      ECMA_MAX_CHARS_IN_STRINGIFIED_UINT32);
      utf8_string2_p = uint32_to_string_buffer2;
      break;
    }
    case ECMA_STRING_CONTAINER_MAGIC_STRING:
    {
      utf8_string2_p = lit_get_magic_string_utf8 (string2_p->u.magic_string_id);
      utf8_string2_size = lit_get_magic_string_size (string2_p->u.magic_string_id);
      break;
    }
    default:
    {
      JERRY_ASSERT (ECMA_STRING_GET_CONTAINER (string2_p) == ECMA_STRING_CONTAINER_MAGIC_STRING_EX);

      utf8_string2_p = lit_get_magic_string_ex_utf8 (string2_p->u.magic_string_id);
      utf8_string2_size = lit_get_magic_string_ex_size (string2_p->u.magic_string_id);
      break;
    }
  }

  return lit_compare_utf8_strings_relational (utf8_string1_p,
                                              utf8_string1_size,
                                              utf8_string2_p,
                                              utf8_string2_size);
} /* ecma_compare_ecma_strings_relational */