Ejemplo n.º 1
0
/**
 * Invalidate LCache entries associated with given object and property name / property
 */
void
ecma_lcache_invalidate (ecma_object_t *object_p, /**< object */
                        jmem_cpointer_t name_cp, /**< property name */
                        ecma_property_t *prop_p) /**< property */
{
  JERRY_ASSERT (object_p != NULL);
  JERRY_ASSERT (prop_p != NULL && ecma_is_property_lcached (prop_p));
  JERRY_ASSERT (ECMA_PROPERTY_GET_TYPE (*prop_p) == ECMA_PROPERTY_TYPE_NAMEDDATA
                || ECMA_PROPERTY_GET_TYPE (*prop_p) == ECMA_PROPERTY_TYPE_NAMEDACCESSOR);

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

  lit_string_hash_t name_hash = ecma_string_get_property_name_hash (*prop_p, name_cp);
  size_t row_index = ecma_lcache_row_index (object_cp, name_hash);
  ecma_lcache_hash_entry_t *entry_p = JERRY_HASH_TABLE_CONTEXT (table) [row_index];

  for (uint32_t entry_index = 0; entry_index < ECMA_LCACHE_HASH_ROW_LENGTH; entry_index++)
  {
    if (entry_p->object_cp != ECMA_NULL_POINTER && entry_p->prop_p == prop_p)
    {
      JERRY_ASSERT (entry_p->object_cp == object_cp);

      ecma_lcache_invalidate_entry (entry_p);
      return;
    }
    entry_p++;
  }

  /* The property must be present. */
  JERRY_UNREACHABLE ();
#endif /* !CONFIG_ECMA_LCACHE_DISABLE */
} /* ecma_lcache_invalidate */
Ejemplo n.º 2
0
/**
 * Invalidate LCache entries associated with given object and property name / property
 *
 * Note:
 *      Either property name argument or property argument should be NULL,
 *      and another should be non-NULL.
 *      In case property name argument is NULL, property's name is taken
 *      from property's description.
 */
void
ecma_lcache_invalidate (ecma_object_t *object_p, /**< object */
                        ecma_string_t *prop_name_p, /**< property's name (See also: Note) */
                        ecma_property_t *prop_p) /**< property (See also: Note) */
{
  JERRY_ASSERT (object_p != NULL);
  JERRY_ASSERT (prop_name_p != NULL);

#ifndef CONFIG_ECMA_LCACHE_DISABLE
  if (prop_p != NULL)
  {
    JERRY_ASSERT (ECMA_PROPERTY_GET_TYPE (prop_p) == ECMA_PROPERTY_TYPE_NAMEDDATA
                  || ECMA_PROPERTY_GET_TYPE (prop_p) == ECMA_PROPERTY_TYPE_NAMEDACCESSOR);

    bool is_cached = ecma_is_property_lcached (prop_p);

    if (!is_cached)
    {
      return;
    }

    ecma_set_property_lcached (prop_p, false);
  }

  unsigned int object_cp;
  ECMA_SET_NON_NULL_POINTER (object_cp, object_p);

  lit_string_hash_t hash_key = ecma_string_hash (prop_name_p);

  /* Property's name has was computed.
   * Given (object, property name) pair should be in the row corresponding to computed hash.
   */
  ecma_lcache_invalidate_row_for_object_property_pair (hash_key, object_cp, prop_p);
#endif /* !CONFIG_ECMA_LCACHE_DISABLE */
} /* ecma_lcache_invalidate */
Ejemplo n.º 3
0
/**
 * Free property values and change their type to deleted.
 */
void
ecma_free_property (ecma_object_t *object_p, /**< object the property belongs to */
                    jmem_cpointer_t name_cp, /**< name of the property or ECMA_NULL_POINTER */
                    ecma_property_t *property_p) /**< property */
{
  JERRY_ASSERT (object_p != NULL && property_p != NULL);

  switch (ECMA_PROPERTY_GET_TYPE (*property_p))
  {
    case ECMA_PROPERTY_TYPE_NAMEDDATA:
    {
      if (ECMA_PROPERTY_GET_NAME_TYPE (*property_p) == ECMA_STRING_CONTAINER_MAGIC_STRING)
      {
        if (name_cp == LIT_INTERNAL_MAGIC_STRING_NATIVE_HANDLE
            || name_cp == LIT_INTERNAL_MAGIC_STRING_NATIVE_POINTER)
        {
          ecma_free_native_pointer (property_p);
          break;
        }
      }

      ecma_free_value_if_not_object (ECMA_PROPERTY_VALUE_PTR (property_p)->value);
      break;
    }
    case ECMA_PROPERTY_TYPE_NAMEDACCESSOR:
    {
#ifdef JERRY_CPOINTER_32_BIT
      ecma_getter_setter_pointers_t *getter_setter_pair_p;
      getter_setter_pair_p = ECMA_GET_POINTER (ecma_getter_setter_pointers_t,
                                               ECMA_PROPERTY_VALUE_PTR (property_p)->getter_setter_pair_cp);
      jmem_pools_free (getter_setter_pair_p, sizeof (ecma_getter_setter_pointers_t));
#endif /* JERRY_CPOINTER_32_BIT */
      break;
    }
    default:
    {
      JERRY_UNREACHABLE ();
      return;
    }
  }

  if (ecma_is_property_lcached (property_p))
  {
    ecma_lcache_invalidate (object_p, name_cp, property_p);
  }

  if (ECMA_PROPERTY_GET_NAME_TYPE (*property_p) == ECMA_PROPERTY_NAME_TYPE_STRING)
  {
    ecma_string_t *prop_name_p = ECMA_GET_NON_NULL_POINTER (ecma_string_t, name_cp);
    ecma_deref_ecma_string (prop_name_p);
  }

  *property_p = ECMA_PROPERTY_TYPE_DELETED;
} /* ecma_free_property */
Ejemplo n.º 4
0
/**
 * Free property values and change their type to deleted.
 */
void
ecma_free_property (ecma_object_t *object_p, /**< object the property belongs to */
                    ecma_string_t *name_p, /**< name of the property or NULL */
                    ecma_property_t *property_p) /**< property */
{
  JERRY_ASSERT (object_p != NULL && property_p != NULL);

  switch (ECMA_PROPERTY_GET_TYPE (property_p))
  {
    case ECMA_PROPERTY_TYPE_NAMEDDATA:
    {
      ecma_free_named_data_property (object_p, property_p);
      if (ecma_is_property_lcached (property_p))
      {
        ecma_lcache_invalidate (object_p, name_p, property_p);
      }
      break;
    }
    case ECMA_PROPERTY_TYPE_NAMEDACCESSOR:
    {
      if (ecma_is_property_lcached (property_p))
      {
        ecma_lcache_invalidate (object_p, name_p, property_p);
      }
      break;
    }
    case ECMA_PROPERTY_TYPE_INTERNAL:
    {
      JERRY_ASSERT (name_p == NULL);
      ecma_free_internal_property (property_p);
      break;
    }
    default:
    {
      JERRY_UNREACHABLE ();
      break;
    }
  }

  property_p->type_and_flags = ECMA_PROPERTY_TYPE_DELETED;
} /* ecma_free_property */
Ejemplo n.º 5
0
/**
 * Insert an entry into LCache
 */
void
ecma_lcache_insert (ecma_object_t *object_p, /**< object */
                    jmem_cpointer_t name_cp, /**< property name */
                    ecma_property_t *prop_p) /**< property */
{
  JERRY_ASSERT (object_p != NULL);
  JERRY_ASSERT (prop_p != NULL && !ecma_is_property_lcached (prop_p));
  JERRY_ASSERT (ECMA_PROPERTY_GET_TYPE (*prop_p) == ECMA_PROPERTY_TYPE_NAMEDDATA
                || ECMA_PROPERTY_GET_TYPE (*prop_p) == ECMA_PROPERTY_TYPE_NAMEDACCESSOR);

#ifndef CONFIG_ECMA_LCACHE_DISABLE
  jmem_cpointer_t object_cp;

  ECMA_SET_NON_NULL_POINTER (object_cp, object_p);

  lit_string_hash_t name_hash = ecma_string_get_property_name_hash (*prop_p, name_cp);
  size_t row_index = ecma_lcache_row_index (object_cp, name_hash);
  ecma_lcache_hash_entry_t *entries_p = JERRY_HASH_TABLE_CONTEXT (table)[row_index];

  int32_t entry_index;
  for (entry_index = 0; entry_index < ECMA_LCACHE_HASH_ROW_LENGTH; entry_index++)
  {
    if (entries_p[entry_index].object_cp == ECMA_NULL_POINTER)
    {
      break;
    }
  }

  if (entry_index == ECMA_LCACHE_HASH_ROW_LENGTH)
  {
    /* Invalidate the last entry. */
    ecma_lcache_invalidate_entry (entries_p + ECMA_LCACHE_HASH_ROW_LENGTH - 1);

    /* Shift other entries towards the end. */
    for (uint32_t i = ECMA_LCACHE_HASH_ROW_LENGTH - 1; i > 0; i--)
    {
      entries_p[i] = entries_p[i - 1];
    }

    entry_index = 0;
  }

  ecma_lcache_hash_entry_t *entry_p = entries_p + entry_index;
  ECMA_SET_NON_NULL_POINTER (entry_p->object_cp, object_p);
  entry_p->prop_name_cp = name_cp;
  entry_p->prop_p = prop_p;

  ecma_set_property_lcached (entry_p->prop_p, true);
#endif /* !CONFIG_ECMA_LCACHE_DISABLE */
} /* ecma_lcache_insert */
Ejemplo n.º 6
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 */
Ejemplo n.º 7
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 */
Ejemplo n.º 8
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, ecma_string_hash (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_property_t prop_name_type;
  jmem_cpointer_t prop_name_cp = ecma_string_to_lcache_property_name (prop_name_p, &prop_name_type);

  while (entry_p < entry_end_p)
  {
    if (entry_p->object_cp == object_cp
        && entry_p->prop_name_cp == prop_name_cp)
    {
      ecma_property_t *prop_p = entry_p->prop_p;

      JERRY_ASSERT (prop_p != NULL && ecma_is_property_lcached (prop_p));

      if (ECMA_PROPERTY_GET_NAME_TYPE (*prop_p) == prop_name_type)
      {
        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 */
Ejemplo n.º 9
0
/**
 * Get value of function's argument mapped to index of Arguments object.
 *
 * Note:
 *      The procedure emulates execution of function described by MakeArgGetter
 *
 * @return ecma value
 *         Returned value must be freed with ecma_free_value
 */
void
ecma_arguments_update_mapped_arg_value (ecma_object_t *object_p, /**< the object */
                                        ecma_string_t *property_name_p, /**< property name */
                                        ecma_property_t *property_p) /**< property value */
{
  ecma_value_t *map_prop_p = ecma_get_internal_property (object_p, ECMA_INTERNAL_PROPERTY_PARAMETERS_MAP);
  ecma_object_t *map_p = ECMA_GET_INTERNAL_VALUE_POINTER (ecma_object_t, *map_prop_p);

  ecma_value_t arg_name = ecma_op_object_find (map_p, property_name_p);

  if (!ecma_is_value_found (arg_name))
  {
    return;
  }

  ecma_value_t *scope_prop_p = ecma_get_internal_property (map_p, ECMA_INTERNAL_PROPERTY_SCOPE);
  ecma_object_t *lex_env_p = ECMA_GET_INTERNAL_VALUE_POINTER (ecma_object_t, *scope_prop_p);

  JERRY_ASSERT (lex_env_p != NULL
                && ecma_is_lexical_environment (lex_env_p));

  ecma_string_t *arg_name_p = ecma_get_string_from_value (arg_name);
  ecma_value_t value = ecma_op_get_binding_value (lex_env_p, arg_name_p, true);
  ecma_deref_ecma_string (arg_name_p);

  JERRY_ASSERT (!ECMA_IS_VALUE_ERROR (value));

  ecma_named_data_property_assign_value (object_p, property_p, value);
  ecma_free_value (value);

  /* These properties cannot be cached. This is a temporary
   * workaround until the property management is fully rewritten. */
  if (ecma_is_property_lcached (property_p))
  {
    ecma_lcache_invalidate (object_p, property_name_p, property_p);
  }
} /* ecma_arguments_update_mapped_arg_value */
Ejemplo n.º 10
0
/**
 * Insert an entry into LCache
 */
void
ecma_lcache_insert (ecma_object_t *object_p, /**< object */
                    ecma_string_t *prop_name_p, /**< property's name */
                    ecma_property_t *prop_p) /**< pointer to associated property or NULL
                                              *   (NULL indicates that the object doesn't have property
                                              *   with the name specified) */
{
  JERRY_ASSERT (object_p != NULL);
  JERRY_ASSERT (prop_name_p != NULL);

#ifndef CONFIG_ECMA_LCACHE_DISABLE
  prop_name_p = ecma_copy_or_ref_ecma_string (prop_name_p);

  lit_string_hash_t hash_key = ecma_string_hash (prop_name_p);

  if (prop_p != NULL)
  {
    if (unlikely (ecma_is_property_lcached (prop_p)))
    {
      int32_t entry_index;
      for (entry_index = 0; entry_index < ECMA_LCACHE_HASH_ROW_LENGTH; entry_index++)
      {
        if (ecma_lcache_hash_table[hash_key][entry_index].object_cp != ECMA_NULL_POINTER
            && ecma_lcache_hash_table[hash_key][entry_index].prop_p == prop_p)
        {
#ifndef JERRY_NDEBUG
          ecma_object_t *obj_in_entry_p;
          obj_in_entry_p = ECMA_GET_NON_NULL_POINTER (ecma_object_t,
                                                      ecma_lcache_hash_table[hash_key][entry_index].object_cp);
          JERRY_ASSERT (obj_in_entry_p == object_p);
#endif /* !JERRY_NDEBUG */
          break;
        }
      }

      JERRY_ASSERT (entry_index != ECMA_LCACHE_HASH_ROW_LENGTH);
      ecma_lcache_invalidate_entry (&ecma_lcache_hash_table[hash_key][entry_index]);
    }

    JERRY_ASSERT (!ecma_is_property_lcached (prop_p));
    ecma_set_property_lcached (prop_p, true);
  }

  int32_t entry_index;
  for (entry_index = 0; entry_index < ECMA_LCACHE_HASH_ROW_LENGTH; entry_index++)
  {
    if (ecma_lcache_hash_table[hash_key][entry_index].object_cp == ECMA_NULL_POINTER)
    {
      break;
    }
  }

  if (entry_index == ECMA_LCACHE_HASH_ROW_LENGTH)
  {
    /* No empty entry was found, invalidating the whole row */
    for (uint32_t i = 0; i < ECMA_LCACHE_HASH_ROW_LENGTH; i++)
    {
      ecma_lcache_invalidate_entry (&ecma_lcache_hash_table[hash_key][i]);
    }

    entry_index = 0;
  }

  ecma_ref_object (object_p);
  ECMA_SET_NON_NULL_POINTER (ecma_lcache_hash_table[ hash_key ][ entry_index ].object_cp, object_p);
  ECMA_SET_NON_NULL_POINTER (ecma_lcache_hash_table[ hash_key ][ entry_index ].prop_name_cp, prop_name_p);
  ecma_lcache_hash_table[ hash_key ][ entry_index ].prop_p = prop_p;
#else /* CONFIG_ECMA_LCACHE_DISABLE */
  (void) prop_p;
#endif /* !CONFIG_ECMA_LCACHE_DISABLE */
} /* ecma_lcache_insert */
Ejemplo n.º 11
0
/**
 * Find named data property or named access property in specified object.
 *
 * @return pointer to the property, if it is found,
 *         NULL - otherwise.
 */
ecma_property_t *
ecma_find_named_property (ecma_object_t *obj_p, /**< object to find property in */
                          ecma_string_t *name_p) /**< property's name */
{
  JERRY_ASSERT (obj_p != NULL);
  JERRY_ASSERT (name_p != NULL);

  ecma_property_t *property_p = ecma_lcache_lookup (obj_p, name_p);

  if (property_p != NULL)
  {
    return property_p;
  }

  ecma_property_header_t *prop_iter_p = ecma_get_property_list (obj_p);

#ifndef CONFIG_ECMA_PROPERTY_HASHMAP_DISABLE
  if (prop_iter_p != NULL
      && ECMA_PROPERTY_GET_TYPE (prop_iter_p->types + 0) == ECMA_PROPERTY_TYPE_HASHMAP)
  {
    ecma_string_t *property_real_name_p;
    property_p = ecma_property_hashmap_find ((ecma_property_hashmap_t *) prop_iter_p,
                                             name_p,
                                             &property_real_name_p);

    if (property_p != NULL
        && !ecma_is_property_lcached (property_p))
    {
      ecma_lcache_insert (obj_p, property_real_name_p, property_p);
    }

    return property_p;
  }
#endif /* !CONFIG_ECMA_PROPERTY_HASHMAP_DISABLE */

  property_p = NULL;
  ecma_string_t *property_name_p = NULL;

  uint32_t steps = 0;

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

    ecma_property_pair_t *prop_pair_p = (ecma_property_pair_t *) prop_iter_p;

    JERRY_ASSERT (ECMA_PROPERTY_PAIR_ITEM_COUNT == 2);

    if (prop_pair_p->names_cp[0] != ECMA_NULL_POINTER)
    {
      property_name_p = ECMA_GET_NON_NULL_POINTER (ecma_string_t,
                                                   prop_pair_p->names_cp[0]);

      if (ecma_compare_ecma_strings (name_p, property_name_p))
      {
        property_p = prop_iter_p->types + 0;
        break;
      }
    }

    if (prop_pair_p->names_cp[1] != ECMA_NULL_POINTER)
    {
      property_name_p = ECMA_GET_NON_NULL_POINTER (ecma_string_t,
                                                   prop_pair_p->names_cp[1]);

      if (ecma_compare_ecma_strings (name_p, property_name_p))
      {
        property_p = prop_iter_p->types + 1;
        break;
      }
    }

    steps++;

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

  if (steps > (ECMA_PROPERTY_HASMAP_MINIMUM_SIZE / 4))
  {
    ecma_property_hashmap_create (obj_p);
  }

  if (property_p != NULL
      && !ecma_is_property_lcached (property_p))
  {
    ecma_lcache_insert (obj_p, property_name_p, property_p);
  }

  return property_p;
} /* ecma_find_named_property */