/** * Get the contents of the literal as a zero-terminated string. * If literal is a magic string record, the corresponding string is not copied to the buffer, * but is returned directly. * * @return pointer to the zero-terminated string. */ const lit_utf8_byte_t * lit_literal_to_utf8_string (literal_t lit, /**< literal to be processed */ lit_utf8_byte_t *buff_p, /**< buffer to use as a string storage */ size_t size) /**< size of the buffer */ { JERRY_ASSERT (buff_p != NULL && size > 0); rcs_record_t::type_t type = lit->get_type (); switch (type) { case LIT_STR_T: { lit_charset_record_t *ch_rec_p = static_cast<lit_charset_record_t *> (lit); ch_rec_p->get_charset (buff_p, size); return buff_p; } case LIT_MAGIC_STR_T: { return lit_get_magic_string_utf8 (lit_magic_record_get_magic_str_id (lit)); } case LIT_MAGIC_STR_EX_T: { return lit_get_magic_string_ex_utf8 (lit_magic_record_ex_get_magic_str_id (lit)); } case LIT_NUMBER_T: { ecma_number_to_utf8_string (static_cast<lit_number_record_t *> (lit)->get_number (), buff_p, (ssize_t)size); return buff_p; } default: JERRY_UNREACHABLE (); } JERRY_UNREACHABLE (); } /* lit_literal_to_utf8_string */
/** * Handle calling [[Call]] of built-in object * * @return ecma value */ ecma_value_t ecma_builtin_dispatch_call (ecma_object_t *obj_p, /**< built-in object */ ecma_value_t this_arg_value, /**< 'this' argument value */ const ecma_value_t *arguments_list_p, /**< arguments list */ ecma_length_t arguments_list_len) /**< arguments list length */ { JERRY_ASSERT (ecma_get_object_is_builtin (obj_p)); ecma_value_t ret_value = ecma_make_simple_value (ECMA_SIMPLE_VALUE_EMPTY); ecma_extended_object_t *ext_obj_p = (ecma_extended_object_t *) obj_p; if (ecma_builtin_function_is_routine (obj_p)) { ret_value = ecma_builtin_dispatch_routine (ext_obj_p->u.built_in.id, ext_obj_p->u.built_in.routine_id, this_arg_value, arguments_list_p, arguments_list_len); } else { JERRY_ASSERT (ecma_get_object_type (obj_p) == ECMA_OBJECT_TYPE_FUNCTION); switch ((ecma_builtin_id_t) ext_obj_p->u.built_in.id) { #define BUILTIN(builtin_id, \ object_type, \ object_prototype_builtin_id, \ is_extensible, \ is_static, \ lowercase_name) \ case builtin_id: \ { \ if (object_type == ECMA_OBJECT_TYPE_FUNCTION) \ { \ ret_value = ecma_builtin_ ## lowercase_name ## _dispatch_call (arguments_list_p, \ arguments_list_len); \ } \ break; \ } #include "ecma-builtins.inc.h" case ECMA_BUILTIN_ID__COUNT: { JERRY_UNREACHABLE (); } default: { JERRY_UNREACHABLE (); /* The built-in is not implemented. */ } } } JERRY_ASSERT (!ecma_is_value_empty (ret_value)); return ret_value; } /* ecma_builtin_dispatch_call */
/** * Handle calling [[Construct]] of built-in object * * @return ecma value */ ecma_value_t ecma_builtin_dispatch_construct (ecma_object_t *obj_p, /**< built-in object */ const ecma_value_t *arguments_list_p, /**< arguments list */ ecma_length_t arguments_list_len) /**< arguments list length */ { JERRY_ASSERT (ecma_get_object_type (obj_p) == ECMA_OBJECT_TYPE_FUNCTION); JERRY_ASSERT (ecma_get_object_is_builtin (obj_p)); ecma_value_t ret_value = ecma_make_simple_value (ECMA_SIMPLE_VALUE_EMPTY); ecma_property_t *built_in_id_prop_p = ecma_get_internal_property (obj_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 (obj_p, builtin_id)); JERRY_ASSERT (ecma_get_object_type (obj_p) == ECMA_OBJECT_TYPE_FUNCTION); switch (builtin_id) { #define BUILTIN(builtin_id, \ object_type, \ object_prototype_builtin_id, \ is_extensible, \ is_static, \ lowercase_name) \ case builtin_id: \ { \ if (object_type == ECMA_OBJECT_TYPE_FUNCTION) \ { \ ret_value = ecma_builtin_ ## lowercase_name ## _dispatch_construct (arguments_list_p, \ arguments_list_len); \ } \ break; \ } #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_ASSERT (!ecma_is_value_empty (ret_value)); return ret_value; } /* ecma_builtin_dispatch_construct */
/** * 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 */
/** * Check if literal equals to charset record * * @return true if equal * false otherwise */ static bool lit_literal_equal_charset_rec (literal_t lit, /**< literal to compare */ lit_charset_record_t *record) /**< charset record to compare */ { switch (lit->get_type ()) { case LIT_STR_T: { return static_cast<lit_charset_record_t *>(lit)->equal (record); } case LIT_MAGIC_STR_T: { return record->equal_zt (ecma_get_magic_string_zt (lit_magic_record_get_magic_str_id (lit))); } case LIT_MAGIC_STR_EX_T: { return record->equal_zt (ecma_get_magic_string_ex_zt (lit_magic_record_ex_get_magic_str_id (lit))); } case LIT_NUMBER_T: { ecma_char_t buff[ECMA_MAX_CHARS_IN_STRINGIFIED_NUMBER]; ecma_number_to_zt_string (static_cast<lit_number_record_t *>(lit)->get_number (), buff, ECMA_MAX_CHARS_IN_STRINGIFIED_NUMBER); return record->equal_zt (buff); } default: { JERRY_UNREACHABLE (); } } } /* lit_literal_equal_charset_rec */
/** * Check if two literals are equal * * @return true if equal * false otherwise */ bool lit_literal_equal (literal_t lit1, /**< first literal */ literal_t lit2) /**< second literal */ { switch (lit2->get_type ()) { case lit_literal_storage_t::LIT_STR: { return lit_literal_equal_charset_rec (lit1, static_cast<lit_charset_record_t *>(lit2)); } case lit_literal_storage_t::LIT_MAGIC_STR: { lit_magic_string_id_t magic_str_id = lit_magic_record_get_magic_str_id (lit2); return lit_literal_equal_utf8 (lit1, lit_get_magic_string_utf8 (magic_str_id), lit_get_magic_string_size (magic_str_id)); } case lit_literal_storage_t::LIT_MAGIC_STR_EX: { lit_magic_string_ex_id_t magic_str_ex_id = lit_magic_record_ex_get_magic_str_id (lit2); return lit_literal_equal_utf8 (lit1, lit_get_magic_string_ex_utf8 (magic_str_ex_id), lit_get_magic_string_ex_size (magic_str_ex_id)); } case lit_literal_storage_t::LIT_NUMBER: { return lit_literal_equal_num (lit1, static_cast<lit_number_record_t *>(lit2)->get_number ()); } default: { JERRY_UNREACHABLE (); } } } /* lit_literal_equal */
/** * Check if literal equals to zero-terminated string * * @return true if equal * false otherwise */ bool lit_literal_equal_zt (literal_t lit, /**< literal to compare */ const ecma_char_t *str) /**< zero-terminated string to compare */ { switch (lit->get_type ()) { case LIT_STR_T: { return static_cast<lit_charset_record_t *>(lit)->equal_zt (str); } case LIT_MAGIC_STR_T: { ecma_magic_string_id_t magic_id = lit_magic_record_get_magic_str_id (lit); return ecma_compare_zt_strings (str, ecma_get_magic_string_zt (magic_id)); } case LIT_MAGIC_STR_EX_T: { ecma_magic_string_ex_id_t magic_id = lit_magic_record_ex_get_magic_str_id (lit); return ecma_compare_zt_strings (str, ecma_get_magic_string_ex_zt (magic_id)); } case LIT_NUMBER_T: { ecma_char_t buff[ECMA_MAX_CHARS_IN_STRINGIFIED_NUMBER]; ecma_number_to_zt_string (static_cast<lit_number_record_t *>(lit)->get_number (), buff, ECMA_MAX_CHARS_IN_STRINGIFIED_NUMBER); return ecma_compare_zt_strings (str, buff); } default: { JERRY_UNREACHABLE (); } } } /* lit_literal_equal_zt */
/** * Free the chunk */ inline void __attr_hot___ __attr_always_inline___ jmem_pools_free (void *chunk_p, /**< pointer to the chunk */ size_t size) /**< size of the chunk */ { JERRY_ASSERT (chunk_p != NULL); jmem_pools_chunk_t *const chunk_to_free_p = (jmem_pools_chunk_t *) chunk_p; VALGRIND_DEFINED_SPACE (chunk_to_free_p, size); if (size <= 8) { chunk_to_free_p->next_p = JERRY_CONTEXT (jmem_free_8_byte_chunk_p); JERRY_CONTEXT (jmem_free_8_byte_chunk_p) = chunk_to_free_p; } else { #ifdef JERRY_CPOINTER_32_BIT JERRY_ASSERT (size <= 16); chunk_to_free_p->next_p = JERRY_CONTEXT (jmem_free_16_byte_chunk_p); JERRY_CONTEXT (jmem_free_16_byte_chunk_p) = chunk_to_free_p; #else /* !JERRY_CPOINTER_32_BIT */ JERRY_UNREACHABLE (); #endif /* JERRY_CPOINTER_32_BIT */ } VALGRIND_NOACCESS_SPACE (chunk_to_free_p, size); JMEM_POOLS_STAT_FREE_POOL (); } /* jmem_pools_free */
/** * [[HasInstance]] ecma object's operation * * See also: * ECMA-262 v5, 8.6.2; ECMA-262 v5, Table 9 */ ecma_completion_value_t ecma_op_object_has_instance (ecma_object_t *obj_p, /**< the object */ ecma_value_t value) /**< argument 'V' */ { JERRY_ASSERT (obj_p != NULL && !ecma_is_lexical_environment (obj_p)); const ecma_object_type_t type = ecma_get_object_type (obj_p); ecma_assert_object_type_is_valid (type); switch (type) { case ECMA_OBJECT_TYPE_ARRAY: case ECMA_OBJECT_TYPE_GENERAL: case ECMA_OBJECT_TYPE_STRING: case ECMA_OBJECT_TYPE_ARGUMENTS: { return ecma_make_throw_obj_completion_value (ecma_new_standard_error (ECMA_ERROR_TYPE)); } case ECMA_OBJECT_TYPE_FUNCTION: case ECMA_OBJECT_TYPE_BOUND_FUNCTION: case ECMA_OBJECT_TYPE_EXTERNAL_FUNCTION: case ECMA_OBJECT_TYPE_BUILT_IN_FUNCTION: { return ecma_op_function_has_instance (obj_p, value); } } JERRY_UNREACHABLE (); } /* ecma_op_object_has_instance */
/** * Get size of stored literal * * @return size of literal */ size_t __attr_pure___ lit_get_literal_size (const lit_record_t *lit_p) /**< literal record */ { const lit_record_type_t type = (const lit_record_type_t) lit_p->type; size_t size = 0; switch (type) { case LIT_RECORD_TYPE_NUMBER: { size = sizeof (lit_number_record_t); break; } case LIT_RECORD_TYPE_CHARSET: { const lit_charset_record_t *const rec_p = (const lit_charset_record_t *) lit_p; size = rec_p->size + LIT_CHARSET_HEADER_SIZE; break; } case LIT_RECORD_TYPE_MAGIC_STR: case LIT_RECORD_TYPE_MAGIC_STR_EX: { size = sizeof (lit_magic_record_t); break; } default: { JERRY_UNREACHABLE (); break; } } JERRY_ASSERT (size > 0); return size; } /* lit_get_literal_size */
/** * Check that */ static void ecma_assert_object_contains_the_property (const ecma_object_t *object_p, /**< ecma-object */ const ecma_property_t *prop_p) /**< ecma-property */ { #ifndef JERRY_NDEBUG ecma_property_header_t *prop_iter_p = ecma_get_property_list (object_p); 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; for (int i = 0; i < ECMA_PROPERTY_PAIR_ITEM_COUNT; i++) { if ((prop_pair_p->header.types + i) == prop_p) { return; } } prop_iter_p = ECMA_GET_POINTER (ecma_property_header_t, prop_iter_p->next_property_cp); } JERRY_UNREACHABLE (); #else /* JERRY_NDEBUG */ (void) object_p; (void) prop_p; #endif /* JERRY_NDEBUG */ } /* ecma_assert_object_contains_the_property */
/** * 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); ecma_lcache_invalidate (object_p, name_p, property_p); break; } case ECMA_PROPERTY_TYPE_NAMEDACCESSOR: { 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 */
const char * lexer_keyword_to_string (keyword kw) { switch (kw) { case KW_BREAK: return "break"; case KW_CASE: return "case"; case KW_CATCH: return "catch"; case KW_CLASS: return "class"; case KW_CONST: return "const"; case KW_CONTINUE: return "continue"; case KW_DEBUGGER: return "debugger"; case KW_DEFAULT: return "default"; case KW_DELETE: return "delete"; case KW_DO: return "do"; case KW_ELSE: return "else"; case KW_ENUM: return "enum"; case KW_EXPORT: return "export"; case KW_EXTENDS: return "extends"; case KW_FINALLY: return "finally"; case KW_FOR: return "for"; case KW_FUNCTION: return "function"; case KW_IF: return "if"; case KW_IN: return "in"; case KW_INSTANCEOF: return "instanceof"; case KW_INTERFACE: return "interface"; case KW_IMPORT: return "import"; case KW_IMPLEMENTS: return "implements"; case KW_LET: return "let"; case KW_NEW: return "new"; case KW_PACKAGE: return "package"; case KW_PRIVATE: return "private"; case KW_PROTECTED: return "protected"; case KW_PUBLIC: return "public"; case KW_RETURN: return "return"; case KW_STATIC: return "static"; case KW_SUPER: return "super"; case KW_SWITCH: return "switch"; case KW_THIS: return "this"; case KW_THROW: return "throw"; case KW_TRY: return "try"; case KW_TYPEOF: return "typeof"; case KW_VAR: return "var"; case KW_VOID: return "void"; case KW_WHILE: return "while"; case KW_WITH: return "with"; case KW_YIELD: return "yield"; default: JERRY_UNREACHABLE (); } }
/** * Allocate a chunk of specified size * * @return pointer to allocated chunk, if allocation was successful, * or NULL - if not enough memory. */ void * __attr_hot___ __attr_always_inline___ jmem_pools_alloc (size_t size) /**< size of the chunk */ { #ifdef JMEM_GC_BEFORE_EACH_ALLOC jmem_run_free_unused_memory_callbacks (JMEM_FREE_UNUSED_MEMORY_SEVERITY_HIGH); #endif /* JMEM_GC_BEFORE_EACH_ALLOC */ if (size <= 8) { if (JERRY_CONTEXT (jmem_free_8_byte_chunk_p) != NULL) { const jmem_pools_chunk_t *const chunk_p = JERRY_CONTEXT (jmem_free_8_byte_chunk_p); JMEM_POOLS_STAT_REUSE (); VALGRIND_DEFINED_SPACE (chunk_p, sizeof (jmem_pools_chunk_t)); JERRY_CONTEXT (jmem_free_8_byte_chunk_p) = chunk_p->next_p; VALGRIND_UNDEFINED_SPACE (chunk_p, sizeof (jmem_pools_chunk_t)); return (void *) chunk_p; } else { JMEM_POOLS_STAT_NEW_ALLOC (); return (void *) jmem_heap_alloc_block (8); } } #ifdef JERRY_CPOINTER_32_BIT JERRY_ASSERT (size <= 16); if (JERRY_CONTEXT (jmem_free_16_byte_chunk_p) != NULL) { const jmem_pools_chunk_t *const chunk_p = JERRY_CONTEXT (jmem_free_16_byte_chunk_p); JMEM_POOLS_STAT_REUSE (); VALGRIND_DEFINED_SPACE (chunk_p, sizeof (jmem_pools_chunk_t)); JERRY_CONTEXT (jmem_free_16_byte_chunk_p) = chunk_p->next_p; VALGRIND_UNDEFINED_SPACE (chunk_p, sizeof (jmem_pools_chunk_t)); return (void *) chunk_p; } else { JMEM_POOLS_STAT_NEW_ALLOC (); return (void *) jmem_heap_alloc_block (16); } #else /* !JERRY_CPOINTER_32_BIT */ JERRY_UNREACHABLE (); return NULL; #endif } /* jmem_pools_alloc */
/** * 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)); 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 */
/** * Dispatcher of built-in routines * * @return ecma value * Returned value must be freed with ecma_free_value. */ static ecma_value_t ecma_builtin_dispatch_routine (ecma_builtin_id_t builtin_object_id, /**< built-in object' identifier */ uint16_t builtin_routine_id, /**< builtin-wide identifier * of the built-in object's * routine property */ ecma_value_t this_arg_value, /**< 'this' argument value */ const ecma_value_t arguments_list[], /**< list of arguments passed to routine */ ecma_length_t arguments_number) /**< length of arguments' list */ { switch (builtin_object_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 ## _dispatch_routine (builtin_routine_id, \ this_arg_value, \ arguments_list, \ arguments_number); \ } #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_dispatch_routine */
/** * Get specified magic string as zero-terminated string from external table * * @return pointer to zero-terminated magic string */ const lit_utf8_byte_t * lit_get_magic_string_ex_utf8 (lit_magic_string_ex_id_t id) /**< extern magic string id */ { if (lit_magic_string_ex_array && id < lit_magic_string_ex_count) { return lit_magic_string_ex_array[id]; } JERRY_UNREACHABLE (); } /* lit_get_magic_string_ex_utf8 */
/** * Get the contents of the literal as a zero-terminated string. * If literal is a magic string record, the corresponding string is not copied to the buffer, * but is returned directly. * * @return pointer to the zero-terminated string. */ const ecma_char_t * lit_literal_to_charset (literal_t lit, /**< literal to be processed */ ecma_char_t *buff, /**< buffer to use as a string storage */ size_t size) /**< size of the buffer */ { JERRY_ASSERT (buff != NULL && size > sizeof (ecma_char_t)); rcs_record_t::type_t type = lit->get_type (); switch (type) { case LIT_STR_T: { lit_charset_record_t *ch_rec_p = static_cast<lit_charset_record_t *> (lit); ecma_length_t index = ch_rec_p->get_charset (buff, size); if (index != 0 && ((size_t)index + 1) * sizeof (ecma_char_t) > size) { index--; } buff[index] = '\0'; return buff; } case LIT_MAGIC_STR_T: { return ecma_get_magic_string_zt (lit_magic_record_get_magic_str_id (lit)); } case LIT_MAGIC_STR_EX_T: { return ecma_get_magic_string_ex_zt (lit_magic_record_ex_get_magic_str_id (lit)); } case LIT_NUMBER_T: { ecma_number_to_zt_string (static_cast<lit_number_record_t *> (lit)->get_number (), buff, (ssize_t)size); return buff; } default: JERRY_UNREACHABLE (); } JERRY_UNREACHABLE (); } /* lit_literal_to_charset */
/** * 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 */
/** * Check if two literals are equal * * @return true if equal * false otherwise */ bool lit_literal_equal (lit_literal_t lit1, /**< first literal */ lit_literal_t lit2) /**< second literal */ { switch (lit2->type) { case LIT_RECORD_TYPE_CHARSET: { return lit_literal_equal_charset_rec (lit1, lit2); } case LIT_RECORD_TYPE_MAGIC_STR: { lit_magic_string_id_t magic_str_id = lit_magic_literal_get_magic_str_id (lit2); return lit_literal_equal_utf8 (lit1, lit_get_magic_string_utf8 (magic_str_id), lit_get_magic_string_size (magic_str_id)); } case LIT_RECORD_TYPE_MAGIC_STR_EX: { lit_magic_string_ex_id_t magic_str_ex_id = lit_magic_literal_get_magic_str_ex_id (lit2); return lit_literal_equal_utf8 (lit1, lit_get_magic_string_ex_utf8 (magic_str_ex_id), lit_get_magic_string_ex_size (magic_str_ex_id)); } case LIT_RECORD_TYPE_NUMBER: { ecma_number_t num = lit_number_literal_get_number (lit2); return lit_literal_equal_num (lit1, num); } default: { JERRY_UNREACHABLE (); break; } } JERRY_UNREACHABLE (); return 0; } /* lit_literal_equal */
/** * Get specified magic string as zero-terminated string * * @return pointer to zero-terminated magic string */ const lit_utf8_byte_t * lit_get_magic_string_utf8 (lit_magic_string_id_t id) /**< magic string id */ { switch (id) { #define LIT_MAGIC_STRING_DEF(id, utf8_string) \ case id: return (lit_utf8_byte_t*) utf8_string; #include "lit-magic-strings.inc.h" #undef LIT_MAGIC_STRING_DEF case LIT_MAGIC_STRING__COUNT: break; } JERRY_UNREACHABLE (); } /* lit_get_magic_string_utf8 */
/** * Instantiate specified ECMA built-in object */ static void ecma_instantiate_builtin (ecma_builtin_id_t id) /**< built-in id */ { switch (id) { #define BUILTIN(builtin_id, \ object_type, \ object_prototype_builtin_id, \ is_extensible, \ is_static, \ lowercase_name) \ case builtin_id: \ { \ JERRY_ASSERT (JERRY_CONTEXT (ecma_builtin_objects)[builtin_id] == NULL); \ \ ecma_object_t *prototype_obj_p; \ if (object_prototype_builtin_id == ECMA_BUILTIN_ID__COUNT) \ { \ prototype_obj_p = NULL; \ } \ else \ { \ if (JERRY_CONTEXT (ecma_builtin_objects)[object_prototype_builtin_id] == NULL) \ { \ ecma_instantiate_builtin (object_prototype_builtin_id); \ } \ prototype_obj_p = JERRY_CONTEXT (ecma_builtin_objects)[object_prototype_builtin_id]; \ JERRY_ASSERT (prototype_obj_p != NULL); \ } \ \ ecma_object_t *builtin_obj_p = ecma_builtin_init_object (builtin_id, \ prototype_obj_p, \ object_type, \ is_extensible); \ JERRY_CONTEXT (ecma_builtin_objects)[builtin_id] = builtin_obj_p; \ \ break; \ } #include "ecma-builtins.inc.h" default: { JERRY_ASSERT (id < ECMA_BUILTIN_ID__COUNT); JERRY_UNREACHABLE (); /* The built-in is not implemented. */ } } } /* ecma_instantiate_builtin */
linked_list linked_list_init (uint16_t element_size) { size_t size = sizeof (linked_list_header) + linked_list_block_size (element_size); linked_list list = (linked_list) mem_heap_alloc_block (size, MEM_HEAP_ALLOC_SHORT_TERM); if (list == null_list) { printf ("Out of memory"); JERRY_UNREACHABLE (); } memset (list, 0, size); linked_list_header* header = (linked_list_header *) list; header->next = null_list; header->element_size = element_size; return list; }
linked_list linked_list_init (uint16_t element_size) { JERRY_ASSERT (element_size <= linked_list_block_size ()); size_t size = sizeof (linked_list_header) + linked_list_block_size (); linked_list list = (linked_list) jsp_mm_alloc (size); if (list == null_list) { printf ("Out of memory"); JERRY_UNREACHABLE (); } memset (list, 0, size); linked_list_header* header = (linked_list_header *) list; header->next = null_list; header->element_size = element_size; return list; }
/** * Check if literal equals to charset record * * @return true if is_equal * false otherwise */ static bool lit_literal_equal_charset_rec (lit_literal_t lit, /**< literal to compare */ lit_literal_t record) /**< charset record to compare */ { switch (lit->type) { case LIT_RECORD_TYPE_CHARSET: { return lit_literal_equal_charset (lit, lit_charset_literal_get_charset (record), lit_charset_literal_get_size (record)); } case LIT_RECORD_TYPE_MAGIC_STR: { lit_magic_string_id_t magic_string_id = lit_magic_literal_get_magic_str_id (lit); return lit_literal_equal_charset (record, lit_get_magic_string_utf8 (magic_string_id), lit_get_magic_string_size (magic_string_id)); } case LIT_RECORD_TYPE_MAGIC_STR_EX: { lit_magic_string_ex_id_t magic_string_id = lit_magic_literal_get_magic_str_ex_id (lit); return lit_literal_equal_charset (record, lit_get_magic_string_ex_utf8 (magic_string_id), lit_get_magic_string_ex_size (magic_string_id)); } case LIT_RECORD_TYPE_NUMBER: { ecma_number_t num = lit_number_literal_get_number (lit); lit_utf8_byte_t buff[ECMA_MAX_CHARS_IN_STRINGIFIED_NUMBER]; lit_utf8_size_t copied = ecma_number_to_utf8_string (num, buff, sizeof (buff)); return lit_literal_equal_charset (record, buff, copied); } default: { JERRY_UNREACHABLE (); return false; } } } /* lit_literal_equal_charset_rec */
/** * Check whether the object contains a property */ static void ecma_assert_object_contains_the_property (const ecma_object_t *object_p, /**< ecma-object */ const ecma_property_value_t *prop_value_p, /**< property value */ ecma_property_types_t type) /**< expected property type */ { #ifndef JERRY_NDEBUG ecma_property_header_t *prop_iter_p = ecma_get_property_list (object_p); JERRY_ASSERT (prop_iter_p != NULL); if (prop_iter_p->types[0] == ECMA_PROPERTY_TYPE_HASHMAP) { prop_iter_p = ECMA_GET_POINTER (ecma_property_header_t, prop_iter_p->next_property_cp); } 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; for (int i = 0; i < ECMA_PROPERTY_PAIR_ITEM_COUNT; i++) { if ((prop_pair_p->values + i) == prop_value_p) { JERRY_ASSERT (ECMA_PROPERTY_GET_TYPE (prop_pair_p->header.types[i]) == type); return; } } prop_iter_p = ECMA_GET_POINTER (ecma_property_header_t, prop_iter_p->next_property_cp); } JERRY_UNREACHABLE (); #else /* JERRY_NDEBUG */ JERRY_UNUSED (object_p); JERRY_UNUSED (prop_value_p); JERRY_UNUSED (type); #endif /* !JERRY_NDEBUG */ } /* ecma_assert_object_contains_the_property */
/** * [[Get]] ecma general object's operation * * See also: * ECMA-262 v5, 8.6.2; ECMA-262 v5, Table 8 * ECMA-262 v5, 8.12.3 * * @return completion value * Returned value must be freed with ecma_free_completion_value */ ecma_completion_value_t ecma_op_general_object_get (ecma_object_t *obj_p, /**< the object */ ecma_string_t *property_name_p) /**< property name */ { JERRY_ASSERT (obj_p != NULL && !ecma_is_lexical_environment (obj_p)); JERRY_ASSERT (property_name_p != NULL); // 1. const ecma_property_t *prop_p = ecma_op_object_get_property (obj_p, property_name_p); // 2. if (prop_p == NULL) { return ecma_make_simple_completion_value (ECMA_SIMPLE_VALUE_UNDEFINED); } // 3. if (prop_p->type == ECMA_PROPERTY_NAMEDDATA) { return ecma_make_normal_completion_value (ecma_copy_value (ecma_get_named_data_property_value (prop_p), true)); } else { // 4. ecma_object_t *getter_p = ecma_get_named_accessor_property_getter (prop_p); // 5. if (getter_p == NULL) { return ecma_make_simple_completion_value (ECMA_SIMPLE_VALUE_UNDEFINED); } else { return ecma_op_function_call (getter_p, ecma_make_object_value (obj_p), NULL); } } JERRY_UNREACHABLE (); } /* ecma_op_general_object_get */
/** * 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 */
/** * Check if literal equals to utf-8 string * * @return true if equal * false otherwise */ bool lit_literal_equal_utf8 (lit_literal_t lit, /**< literal to compare */ const lit_utf8_byte_t *str_p, /**< utf-8 string to compare */ lit_utf8_size_t str_size) /**< string size in bytes */ { switch (lit->type) { case LIT_RECORD_TYPE_CHARSET: { if (lit_charset_literal_get_size (lit) != str_size) { return 0; } return !strncmp ((const char *) lit_charset_literal_get_charset (lit), (const char *) str_p, str_size); } case LIT_RECORD_TYPE_MAGIC_STR: { lit_magic_string_id_t magic_id = lit_magic_literal_get_magic_str_id (lit); return lit_compare_utf8_string_and_magic_string (str_p, str_size, magic_id); } case LIT_RECORD_TYPE_MAGIC_STR_EX: { lit_magic_string_ex_id_t magic_id = lit_magic_literal_get_magic_str_ex_id (lit); return lit_compare_utf8_string_and_magic_string_ex (str_p, str_size, magic_id); } case LIT_RECORD_TYPE_NUMBER: { ecma_number_t num = lit_number_literal_get_number (lit); lit_utf8_byte_t num_buf[ECMA_MAX_CHARS_IN_STRINGIFIED_NUMBER]; lit_utf8_size_t num_size = ecma_number_to_utf8_string (num, num_buf, sizeof (num_buf)); return lit_compare_utf8_strings (str_p, str_size, num_buf, num_size); } default: { JERRY_UNREACHABLE (); } } } /* lit_literal_equal_utf8 */
/** * [[Delete]] ecma general object's operation * * See also: * ECMA-262 v5, 8.6.2; ECMA-262 v5, Table 8 * ECMA-262 v5, 8.12.7 * * @return completion value * Returned value must be freed with ecma_free_completion_value */ ecma_completion_value_t ecma_op_general_object_delete (ecma_object_t *obj_p, /**< the object */ ecma_string_t *property_name_p, /**< property name */ bool is_throw) /**< flag that controls failure handling */ { JERRY_ASSERT (obj_p != NULL && !ecma_is_lexical_environment (obj_p)); JERRY_ASSERT (property_name_p != NULL); // 1. ecma_property_t *desc_p = ecma_op_object_get_own_property (obj_p, property_name_p); // 2. if (desc_p == NULL) { return ecma_make_simple_completion_value (ECMA_SIMPLE_VALUE_TRUE); } // 3. if (ecma_is_property_configurable (desc_p)) { // a. ecma_delete_property (obj_p, desc_p); // b. return ecma_make_simple_completion_value (ECMA_SIMPLE_VALUE_TRUE); } else if (is_throw) { // 4. return ecma_make_throw_obj_completion_value (ecma_new_standard_error (ECMA_ERROR_TYPE)); } else { // 5. return ecma_make_simple_completion_value (ECMA_SIMPLE_VALUE_FALSE); } JERRY_UNREACHABLE (); } /* ecma_op_general_object_delete */