/** * 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 */
/** * 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 */
/** * '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 */
/** * 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 */