/**
 * Get value of external pointer stored in the object's property with specified identifier
 *
 * Note:
 *      property identifier should be one of the following:
 *        - ECMA_INTERNAL_PROPERTY_NATIVE_CODE;
 *        - ECMA_INTERNAL_PROPERTY_NATIVE_HANDLE;
 *        - ECMA_INTERNAL_PROPERTY_FREE_CALLBACK.
 *
 * @return true - if property exists and it's value is returned through out_pointer_p,
 *         false - otherwise (value returned through out_pointer_p is NULL).
 */
bool
ecma_get_external_pointer_value (ecma_object_t *obj_p, /**< object to get property value from */
                                 ecma_internal_property_id_t id, /**< identifier of internal property
                                                                  *   to get value from */
                                 ecma_external_pointer_t *out_pointer_p) /**< out: value of the external pointer */
{
  JERRY_ASSERT (id == ECMA_INTERNAL_PROPERTY_NATIVE_CODE
                || id == ECMA_INTERNAL_PROPERTY_NATIVE_HANDLE
                || id == ECMA_INTERNAL_PROPERTY_FREE_CALLBACK);

  ecma_property_t *prop_p = ecma_find_internal_property (obj_p, id);

  if (prop_p == NULL)
  {
    *out_pointer_p = (ecma_external_pointer_t) NULL;

    return false;
  }

  JERRY_STATIC_ASSERT (sizeof (uint32_t) <= sizeof (prop_p->u.internal_property.value));

  if (sizeof (ecma_external_pointer_t) == sizeof (uint32_t))
  {
    *out_pointer_p = (ecma_external_pointer_t) prop_p->u.internal_property.value;
  }
  else
  {
    ecma_external_pointer_t *handler_p = ECMA_GET_NON_NULL_POINTER (ecma_external_pointer_t,
                                                                    prop_p->u.internal_property.value);
    *out_pointer_p = *handler_p;
  }

  return true;
} /* ecma_get_external_pointer_value */
Пример #2
0
/**
 * Initialization of memory pool.
 *
 * Pool will be located in the segment [pool_start; pool_start + pool_size).
 * Part of pool space will be used for bitmap and the rest will store chunks.
 */
void
mem_pool_init (mem_pool_state_t *pool_p, /**< pool */
               size_t pool_size)         /**< pool size */
{
  JERRY_ASSERT (pool_p != NULL);
  JERRY_ASSERT ((size_t)MEM_POOL_SPACE_START (pool_p) % MEM_ALIGNMENT == 0);

  JERRY_STATIC_ASSERT (MEM_POOL_CHUNK_SIZE % MEM_ALIGNMENT == 0);
  JERRY_STATIC_ASSERT (MEM_POOL_MAX_CHUNKS_NUMBER_LOG <= sizeof (mem_pool_chunk_index_t) * JERRY_BITSINBYTE);
  JERRY_ASSERT (sizeof (mem_pool_chunk_index_t) <= MEM_POOL_CHUNK_SIZE);

  JERRY_ASSERT (MEM_POOL_SIZE == sizeof (mem_pool_state_t) + MEM_POOL_CHUNKS_NUMBER * MEM_POOL_CHUNK_SIZE);
  JERRY_ASSERT (MEM_POOL_CHUNKS_NUMBER >= CONFIG_MEM_LEAST_CHUNK_NUMBER_IN_POOL);

  JERRY_ASSERT (pool_size == MEM_POOL_SIZE);

  /*
   * All chunks are free right after initialization
   */
  pool_p->free_chunks_number = (mem_pool_chunk_index_t) MEM_POOL_CHUNKS_NUMBER;
  JERRY_ASSERT (pool_p->free_chunks_number == MEM_POOL_CHUNKS_NUMBER);

  /*
   * Chunk with zero index is first free chunk in the pool now
   */
  pool_p->first_free_chunk = 0;

  for (mem_pool_chunk_index_t chunk_index = 0;
       chunk_index < MEM_POOL_CHUNKS_NUMBER;
       chunk_index++)
  {
    mem_pool_chunk_index_t *next_free_chunk_index_p = (mem_pool_chunk_index_t*) MEM_POOL_CHUNK_ADDRESS (pool_p,
                                                                                                        chunk_index);

    *next_free_chunk_index_p = (mem_pool_chunk_index_t) (chunk_index + 1u);

    VALGRIND_NOACCESS_SPACE (next_free_chunk_index_p, MEM_POOL_CHUNK_SIZE);
  }

  mem_check_pool (pool_p);
} /* mem_pool_init */
/**
 * Create internal property with specified identifier and store external pointer in the property.
 *
 * Note:
 *      property identifier should be one of the following:
 *        - ECMA_INTERNAL_PROPERTY_NATIVE_CODE;
 *        - ECMA_INTERNAL_PROPERTY_NATIVE_HANDLE;
 *        - ECMA_INTERNAL_PROPERTY_FREE_CALLBACK.
 *
 * @return true - if property was just created with specified value,
 *         false - otherwise, if property existed before the call, it's value was updated.
 */
bool
ecma_create_external_pointer_property (ecma_object_t *obj_p, /**< object to create property in */
                                       ecma_internal_property_id_t id, /**< identifier of internal
                                                                        *   property to create */
                                       ecma_external_pointer_t ptr_value) /**< value to store in the property */
{
  JERRY_ASSERT (id == ECMA_INTERNAL_PROPERTY_NATIVE_CODE
                || id == ECMA_INTERNAL_PROPERTY_NATIVE_HANDLE
                || id == ECMA_INTERNAL_PROPERTY_FREE_CALLBACK);

  bool is_new;
  ecma_property_t *prop_p = ecma_find_internal_property (obj_p, id);

  if (prop_p == NULL)
  {
    prop_p = ecma_create_internal_property (obj_p, id);

    is_new = true;
  }
  else
  {
    is_new = false;
  }

  JERRY_STATIC_ASSERT (sizeof (uint32_t) <= sizeof (ECMA_PROPERTY_VALUE_PTR (prop_p)->value),
                       size_of_internal_property_value_must_be_greater_than_or_equal_to_4_bytes);

  if (sizeof (ecma_external_pointer_t) == sizeof (uint32_t))
  {
    ECMA_PROPERTY_VALUE_PTR (prop_p)->value = (uint32_t) ptr_value;
  }
  else
  {
    ecma_external_pointer_t *handler_p;

    if (is_new)
    {
      handler_p = ecma_alloc_external_pointer ();

      ECMA_SET_NON_NULL_POINTER (ECMA_PROPERTY_VALUE_PTR (prop_p)->value, handler_p);
    }
    else
    {
      handler_p = ECMA_GET_NON_NULL_POINTER (ecma_external_pointer_t,
                                             ECMA_PROPERTY_VALUE_PTR (prop_p)->value);
    }

    *handler_p = ptr_value;
  }

  return is_new;
} /* ecma_create_external_pointer_property */
/**
 * Create internal property with specified identifier and store external pointer in the property.
 *
 * Note:
 *      property identifier should be one of the following:
 *        - ECMA_INTERNAL_PROPERTY_NATIVE_HANDLE;
 *        - ECMA_INTERNAL_PROPERTY_FREE_CALLBACK.
 *
 * @return true - if property was just created with specified value,
 *         false - otherwise, if property existed before the call, it's value was updated.
 */
bool
ecma_create_external_pointer_property (ecma_object_t *obj_p, /**< object to create property in */
                                       ecma_internal_property_id_t id, /**< identifier of internal
                                                                        *   property to create */
                                       ecma_external_pointer_t ptr_value) /**< value to store in the property */
{
  JERRY_ASSERT (id == ECMA_INTERNAL_PROPERTY_NATIVE_HANDLE
                || id == ECMA_INTERNAL_PROPERTY_FREE_CALLBACK);

  ecma_value_t *prop_p = ecma_find_internal_property (obj_p, id);
  bool is_new = (prop_p == NULL);

  if (is_new)
  {
    prop_p = ecma_create_internal_property (obj_p, id);
  }

  JERRY_STATIC_ASSERT (sizeof (uint32_t) <= sizeof (ECMA_PROPERTY_VALUE_PTR (prop_p)->value),
                       size_of_internal_property_value_must_be_greater_than_or_equal_to_4_bytes);

#ifdef ECMA_VALUE_CAN_STORE_UINTPTR_VALUE_DIRECTLY

  *prop_p = (ecma_value_t) ptr_value;

#else /* !ECMA_VALUE_CAN_STORE_UINTPTR_VALUE_DIRECTLY */

  ecma_external_pointer_t *handler_p;

  if (is_new)
  {
    handler_p = ecma_alloc_external_pointer ();

    ECMA_SET_NON_NULL_POINTER (*prop_p, handler_p);
  }
  else
  {
    handler_p = ECMA_GET_NON_NULL_POINTER (ecma_external_pointer_t, *prop_p);
  }

  *handler_p = ptr_value;

#endif /* ECMA_VALUE_CAN_STORE_UINTPTR_VALUE_DIRECTLY */

  return is_new;
} /* ecma_create_external_pointer_property */
/**
 * Create internal property with specified identifier and store external pointer in the property.
 *
 * Note:
 *      property identifier should be one of the following:
 *        - ECMA_INTERNAL_PROPERTY_NATIVE_CODE;
 *        - ECMA_INTERNAL_PROPERTY_NATIVE_HANDLE;
 *        - ECMA_INTERNAL_PROPERTY_FREE_CALLBACK.
 *
 * @return true - if property was just created with specified value,
 *         false - otherwise, if property existed before the call, it's value was updated.
 */
bool
ecma_create_external_pointer_property (ecma_object_t *obj_p, /**< object to create property in */
                                       ecma_internal_property_id_t id, /**< identifier of internal
                                                                        *   property to create */
                                       ecma_external_pointer_t ptr_value) /**< value to store in the property */
{
  JERRY_ASSERT (id == ECMA_INTERNAL_PROPERTY_NATIVE_CODE
                || id == ECMA_INTERNAL_PROPERTY_NATIVE_HANDLE
                || id == ECMA_INTERNAL_PROPERTY_FREE_CALLBACK);

  bool ret_val;
  ecma_property_t *prop_p = ecma_find_internal_property (obj_p, id);

  if (prop_p == NULL)
  {
    prop_p = ecma_create_internal_property (obj_p, id);

    ret_val = true;
  }
  else
  {
    ret_val = false;
  }

  JERRY_STATIC_ASSERT (sizeof (uint32_t) <= sizeof (prop_p->u.internal_property.value));

  if (sizeof (ecma_external_pointer_t) == sizeof (uint32_t))
  {
    prop_p->u.internal_property.value = (uint32_t) ptr_value;
  }
  else
  {
    ecma_external_pointer_t *handler_p = ecma_alloc_external_pointer ();
    *handler_p = ptr_value;

    ECMA_SET_NON_NULL_POINTER (prop_p->u.internal_property.value, handler_p);
  }

  return ret_val;
} /* ecma_create_external_pointer_property */
Пример #6
0
/**
 * 'Native call' opcode handler.
 */
ecma_completion_value_t
opfunc_native_call (opcode_t opdata, /**< operation data */
                    int_data_t *int_data) /**< interpreter context */
{
  const idx_t dst_var_idx = opdata.data.native_call.lhs;
  const idx_t native_call_id_idx = opdata.data.native_call.name;
  const idx_t args_number = opdata.data.native_call.arg_list;
  const opcode_counter_t lit_oc = int_data->pos;

  JERRY_ASSERT (native_call_id_idx < OPCODE_NATIVE_CALL__COUNT);

  int_data->pos++;

  JERRY_STATIC_ASSERT (OPCODE_NATIVE_CALL__COUNT < (1u << (sizeof (native_call_id_idx) * JERRY_BITSINBYTE)));

  ecma_completion_value_t ret_value = ecma_make_empty_completion_value ();

  MEM_DEFINE_LOCAL_ARRAY (arg_values, args_number, ecma_value_t);

  ecma_length_t args_read;
  ecma_completion_value_t get_arg_completion = fill_varg_list (int_data,
                                                               args_number,
                                                               arg_values,
                                                               &args_read);

  if (ecma_is_completion_value_empty (get_arg_completion))
  {
    JERRY_ASSERT (args_read == args_number);

    switch ((opcode_native_call_t)native_call_id_idx)
    {
      case OPCODE_NATIVE_CALL_LED_TOGGLE:
      case OPCODE_NATIVE_CALL_LED_ON:
      case OPCODE_NATIVE_CALL_LED_OFF:
      case OPCODE_NATIVE_CALL_LED_ONCE:
      case OPCODE_NATIVE_CALL_WAIT:
      {
        JERRY_UNIMPLEMENTED ("Device operations are not implemented.");
      }

      case OPCODE_NATIVE_CALL_PRINT:
      {
        for (ecma_length_t arg_index = 0;
             ecma_is_completion_value_empty (ret_value) && arg_index < args_read;
             arg_index++)
        {
          ECMA_TRY_CATCH (str_value,
                          ecma_op_to_string (arg_values[arg_index]),
                          ret_value);

          ecma_string_t *str_p = ecma_get_string_from_value (str_value);

          lit_utf8_size_t bytes = ecma_string_get_size (str_p);

          ssize_t utf8_str_size = (ssize_t) (bytes + 1);
          lit_utf8_byte_t *utf8_str_p = (lit_utf8_byte_t*) mem_heap_alloc_block ((size_t) utf8_str_size,
                                                                               MEM_HEAP_ALLOC_SHORT_TERM);
          if (utf8_str_p == NULL)
          {
            jerry_fatal (ERR_OUT_OF_MEMORY);
          }

          ecma_string_to_utf8_string (str_p, utf8_str_p, utf8_str_size);
          utf8_str_p[utf8_str_size - 1] = 0;

          FIXME ("Support unicode in printf.");
          if (arg_index < args_read - 1)
          {
            printf ("%s ", (char*) utf8_str_p);
          }
          else
          {
            printf ("%s", (char*) utf8_str_p);
          }

          mem_heap_free_block (utf8_str_p);

          ret_value = set_variable_value (int_data, lit_oc, dst_var_idx,
                                          ecma_make_simple_value (ECMA_SIMPLE_VALUE_UNDEFINED));

          ECMA_FINALIZE (str_value);
        }
        printf ("\n");
        break;
      }

      case OPCODE_NATIVE_CALL__COUNT:
      {
        JERRY_UNREACHABLE ();
      }
    }
  }
  else
  {
    JERRY_ASSERT (!ecma_is_completion_value_normal (get_arg_completion));

    ret_value = get_arg_completion;
  }

  for (ecma_length_t arg_index = 0;
       arg_index < args_read;
       arg_index++)
  {
    ecma_free_value (arg_values[arg_index], true);
  }

  MEM_FINALIZE_LOCAL_ARRAY (arg_values);

  return ret_value;
} /* opfunc_native_call */
Пример #7
0
/**
 * If the property's name is one of built-in properties of the object
 * that is not instantiated yet, instantiate the property and
 * return pointer to the instantiated property.
 *
 * @return pointer property, if one was instantiated,
 *         NULL - otherwise.
 */
ecma_property_t *
ecma_builtin_try_to_instantiate_property (ecma_object_t *object_p, /**< object */
                                          ecma_string_t *string_p) /**< property's name */
{
  JERRY_ASSERT (ecma_get_object_is_builtin (object_p));

  const ecma_object_type_t type = ecma_get_object_type (object_p);

  if (type == ECMA_OBJECT_TYPE_BUILT_IN_FUNCTION)
  {
    ecma_string_t *magic_string_length_p = ecma_get_magic_string (LIT_MAGIC_STRING_LENGTH);

    bool is_length_property = ecma_compare_ecma_strings (string_p, magic_string_length_p);

    ecma_deref_ecma_string (magic_string_length_p);

    if (is_length_property)
    {
      /*
       * Lazy instantiation of 'length' property
       *
       * Note:
       *      We don't need to mark that the property was already lazy instantiated,
       *      as it is non-configurable and so can't be deleted
       */

      ecma_property_t *desc_prop_p = ecma_get_internal_property (object_p,
                                                               ECMA_INTERNAL_PROPERTY_BUILT_IN_ROUTINE_DESC);
      uint64_t builtin_routine_desc = desc_prop_p->u.internal_property.value;

      JERRY_STATIC_ASSERT (sizeof (uint8_t) * JERRY_BITSINBYTE == ECMA_BUILTIN_ROUTINE_ID_LENGTH_VALUE_WIDTH,
                           bits_in_uint8_t_must_be_equal_to_ECMA_BUILTIN_ROUTINE_ID_LENGTH_VALUE_WIDTH);
      uint8_t length_prop_value = (uint8_t) jrt_extract_bit_field (builtin_routine_desc,
                                                                   ECMA_BUILTIN_ROUTINE_ID_LENGTH_VALUE_POS,
                                                                   ECMA_BUILTIN_ROUTINE_ID_LENGTH_VALUE_WIDTH);

      ecma_property_t *len_prop_p = ecma_create_named_data_property (object_p,
                                                                     string_p,
                                                                     false, false, false);


      ecma_number_t *len_p = ecma_alloc_number ();
      *len_p = length_prop_value;

      ecma_set_named_data_property_value (len_prop_p, ecma_make_number_value (len_p));

      JERRY_ASSERT (!ecma_is_property_configurable (len_prop_p));
      return len_prop_p;
    }

    return NULL;
  }
  else
  {
    ecma_property_t *built_in_id_prop_p = ecma_get_internal_property (object_p,
                                                                      ECMA_INTERNAL_PROPERTY_BUILT_IN_ID);
    ecma_builtin_id_t builtin_id = (ecma_builtin_id_t) built_in_id_prop_p->u.internal_property.value;

    JERRY_ASSERT (ecma_builtin_is (object_p, builtin_id));

    switch (builtin_id)
    {
#define BUILTIN(builtin_id, \
                object_type, \
                object_prototype_builtin_id, \
                is_extensible, \
                is_static, \
                lowercase_name) \
      case builtin_id: \
      { \
        return ecma_builtin_ ## lowercase_name ## _try_to_instantiate_property (object_p, \
                                                                                string_p); \
      }
#include "ecma-builtins.inc.h"

      case ECMA_BUILTIN_ID__COUNT:
      {
        JERRY_UNREACHABLE ();
      }

      default:
      {
#ifdef CONFIG_ECMA_COMPACT_PROFILE
        JERRY_UNREACHABLE ();
#else /* CONFIG_ECMA_COMPACT_PROFILE */
        JERRY_UNIMPLEMENTED ("The built-in is not implemented.");
#endif /* !CONFIG_ECMA_COMPACT_PROFILE */
      }
    }

    JERRY_UNREACHABLE ();
  }
} /* ecma_builtin_try_to_instantiate_property */