/** * Create named accessor property with given name, attributes, getter and setter. * * @return pointer to the newly created property value */ ecma_property_value_t * ecma_create_named_accessor_property (ecma_object_t *object_p, /**< object */ ecma_string_t *name_p, /**< property name */ ecma_object_t *get_p, /**< getter */ ecma_object_t *set_p, /**< setter */ uint8_t prop_attributes, /**< property attributes */ ecma_property_t **out_prop_p) /**< [out] the property is also returned * if this field is non-NULL */ { JERRY_ASSERT (object_p != NULL && name_p != NULL); JERRY_ASSERT (ecma_find_named_property (object_p, name_p) == NULL); JERRY_ASSERT ((prop_attributes & ~ECMA_PROPERTY_CONFIGURABLE_ENUMERABLE) == 0); uint8_t type_and_flags = ECMA_PROPERTY_TYPE_NAMEDACCESSOR | prop_attributes; ecma_property_value_t value; #ifdef JERRY_CPOINTER_32_BIT ecma_getter_setter_pointers_t *getter_setter_pair_p; getter_setter_pair_p = jmem_pools_alloc (sizeof (ecma_getter_setter_pointers_t)); ECMA_SET_POINTER (getter_setter_pair_p->getter_p, get_p); ECMA_SET_POINTER (getter_setter_pair_p->setter_p, set_p); ECMA_SET_POINTER (value.getter_setter_pair_cp, getter_setter_pair_p); #else /* !JERRY_CPOINTER_32_BIT */ ECMA_SET_POINTER (value.getter_setter_pair.getter_p, get_p); ECMA_SET_POINTER (value.getter_setter_pair.setter_p, set_p); #endif /* JERRY_CPOINTER_32_BIT */ return ecma_create_property (object_p, name_p, type_and_flags, value, out_prop_p); } /* ecma_create_named_accessor_property */
/** * Create a property in an object and link it into * the object's properties' linked-list (at start of the list). * * @return pointer to newly created property */ static ecma_property_t * ecma_create_property (ecma_object_t *object_p, /**< the object */ ecma_string_t *name_p, /**< property name */ uint8_t type_and_flags) /**< type and flags, see ecma_property_info_t */ { JERRY_ASSERT (ECMA_PROPERTY_PAIR_ITEM_COUNT == 2); if (object_p->property_list_or_bound_object_cp != ECMA_NULL_POINTER) { /* If the first entry is free (deleted), we simply use its value. */ ecma_property_header_t *first_property_p = ECMA_GET_NON_NULL_POINTER (ecma_property_header_t, object_p->property_list_or_bound_object_cp); JERRY_ASSERT (ECMA_PROPERTY_IS_PROPERTY_PAIR (first_property_p)); if (first_property_p->types[0].type_and_flags == ECMA_PROPERTY_TYPE_DELETED) { first_property_p->types[0].type_and_flags = type_and_flags; ecma_property_pair_t *first_property_pair_p = (ecma_property_pair_t *) first_property_p; ECMA_SET_POINTER (first_property_pair_p->names_cp[0], name_p); ecma_property_t *property_p = first_property_p->types + 0; JERRY_ASSERT (ECMA_PROPERTY_VALUE_PTR (property_p) == first_property_pair_p->values + 0); return property_p; } } /* Otherwise we create a new property pair and use its second value. */ ecma_property_pair_t *first_property_pair_p = ecma_alloc_property_pair (); /* Just copy the previous value (no need to decompress, compress). */ first_property_pair_p->header.next_property_cp = object_p->property_list_or_bound_object_cp; first_property_pair_p->header.types[0].type_and_flags = ECMA_PROPERTY_TYPE_DELETED; first_property_pair_p->header.types[1].type_and_flags = type_and_flags; first_property_pair_p->names_cp[0] = ECMA_NULL_POINTER; ECMA_SET_POINTER (first_property_pair_p->names_cp[1], name_p); ecma_set_property_list (object_p, &first_property_pair_p->header); ecma_property_t *property_p = first_property_pair_p->header.types + 1; JERRY_ASSERT (ECMA_PROPERTY_VALUE_PTR (property_p) == first_property_pair_p->values + 1); return property_p; } /* ecma_create_property */
/** * Create an object with specified prototype object * (or NULL prototype if there is not prototype for the object) * and value of 'Extensible' attribute. * * Reference counter's value will be set to one. * * @return pointer to the object's descriptor */ ecma_object_t * ecma_create_object (ecma_object_t *prototype_object_p, /**< pointer to prototybe of the object (or NULL) */ bool is_extensible, /**< value of extensible attribute */ ecma_object_type_t type) /**< object type */ { ecma_object_t *new_object_p = ecma_alloc_object (); uint16_t type_flags = (uint16_t) type; if (is_extensible) { type_flags = (uint16_t) (type_flags | ECMA_OBJECT_FLAG_EXTENSIBLE); } new_object_p->type_flags_refs = type_flags; ecma_init_gc_info (new_object_p); new_object_p->property_list_or_bound_object_cp = JMEM_CP_NULL; ECMA_SET_POINTER (new_object_p->prototype_or_outer_reference_cp, prototype_object_p); return new_object_p; } /* ecma_create_object */
/** * Create an object with specified prototype object * (or NULL prototype if there is not prototype for the object) * and value of 'Extensible' attribute. * * Reference counter's value will be set to one. * * @return pointer to the object's descriptor */ ecma_object_t * ecma_create_object (ecma_object_t *prototype_object_p, /**< pointer to prototybe of the object (or NULL) */ size_t ext_object_size, /**< size of extended objects */ ecma_object_type_t type) /**< object type */ { ecma_object_t *new_object_p; if (ext_object_size > 0) { new_object_p = (ecma_object_t *) ecma_alloc_extended_object (ext_object_size); } else { new_object_p = ecma_alloc_object (); } new_object_p->type_flags_refs = (uint16_t) (type | ECMA_OBJECT_FLAG_EXTENSIBLE); ecma_init_gc_info (new_object_p); new_object_p->property_list_or_bound_object_cp = JMEM_CP_NULL; ECMA_SET_POINTER (new_object_p->prototype_or_outer_reference_cp, prototype_object_p); return new_object_p; } /* ecma_create_object */
/** * Set setter of named accessor property */ void ecma_set_named_accessor_property_setter (ecma_object_t *object_p, /**< the property's container */ ecma_property_value_t *prop_value_p, /**< property value reference */ ecma_object_t *setter_p) /**< setter object */ { ecma_assert_object_contains_the_property (object_p, prop_value_p, 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, prop_value_p->getter_setter_pair_cp); ECMA_SET_POINTER (getter_setter_pair_p->setter_p, setter_p); #else /* !JERRY_CPOINTER_32_BIT */ ECMA_SET_POINTER (prop_value_p->getter_setter_pair.setter_p, setter_p); #endif /* JERRY_CPOINTER_32_BIT */ } /* ecma_set_named_accessor_property_setter */
/** * Number object creation operation. * * See also: ECMA-262 v5, 15.7.2.1 * * @return completion value * Returned value must be freed with ecma_free_completion_value */ ecma_completion_value_t ecma_op_create_number_object (ecma_value_t arg) /**< argument passed to the Number constructor */ { ecma_completion_value_t conv_to_num_completion = ecma_op_to_number (arg); if (!ecma_is_completion_value_normal (conv_to_num_completion)) { return conv_to_num_completion; } ecma_number_t *prim_value_p = ecma_get_number_from_completion_value (conv_to_num_completion); #ifndef CONFIG_ECMA_COMPACT_PROFILE_DISABLE_NUMBER_BUILTIN ecma_object_t *prototype_obj_p = ecma_builtin_get (ECMA_BUILTIN_ID_NUMBER_PROTOTYPE); #else /* !CONFIG_ECMA_COMPACT_PROFILE_DISABLE_NUMBER_BUILTIN */ ecma_object_t *prototype_obj_p = ecma_builtin_get (ECMA_BUILTIN_ID_OBJECT_PROTOTYPE); #endif /* CONFIG_ECMA_COMPACT_PROFILE_DISABLE_NUMBER_BUILTIN */ ecma_object_t *obj_p = ecma_create_object (prototype_obj_p, true, ECMA_OBJECT_TYPE_GENERAL); ecma_deref_object (prototype_obj_p); ecma_property_t *class_prop_p = ecma_create_internal_property (obj_p, ECMA_INTERNAL_PROPERTY_CLASS); class_prop_p->u.internal_property.value = LIT_MAGIC_STRING_NUMBER_UL; ecma_property_t *prim_value_prop_p = ecma_create_internal_property (obj_p, ECMA_INTERNAL_PROPERTY_PRIMITIVE_NUMBER_VALUE); ECMA_SET_POINTER (prim_value_prop_p->u.internal_property.value, prim_value_p); return ecma_make_normal_completion_value (ecma_make_object_value (obj_p)); } /* ecma_op_create_number_object */
/** * Create a object lexical environment with specified outer lexical environment * (or NULL if the environment is not nested), binding object and provideThis flag. * * See also: ECMA-262 v5, 10.2.1.2 * * Reference counter's value will be set to one. * * @return pointer to the descriptor of lexical environment */ ecma_object_t * ecma_create_object_lex_env (ecma_object_t *outer_lexical_environment_p, /**< outer lexical environment */ ecma_object_t *binding_obj_p, /**< binding object */ bool provide_this) /**< provideThis flag */ { JERRY_ASSERT (binding_obj_p != NULL && !ecma_is_lexical_environment (binding_obj_p)); ecma_object_t *new_lexical_environment_p = ecma_alloc_object (); uint16_t type; if (provide_this) { type = ECMA_OBJECT_FLAG_BUILT_IN_OR_LEXICAL_ENV | ECMA_LEXICAL_ENVIRONMENT_THIS_OBJECT_BOUND; } else { type = ECMA_OBJECT_FLAG_BUILT_IN_OR_LEXICAL_ENV | ECMA_LEXICAL_ENVIRONMENT_OBJECT_BOUND; } new_lexical_environment_p->type_flags_refs = type; ecma_init_gc_info (new_lexical_environment_p); ECMA_SET_NON_NULL_POINTER (new_lexical_environment_p->property_list_or_bound_object_cp, binding_obj_p); ECMA_SET_POINTER (new_lexical_environment_p->prototype_or_outer_reference_cp, outer_lexical_environment_p); return new_lexical_environment_p; } /* ecma_create_object_lex_env */
/** * Set next object in list of objects with same generation. */ static inline void ecma_gc_set_object_next (ecma_object_t *object_p, /**< object */ ecma_object_t *next_object_p) /**< next object */ { JERRY_ASSERT (object_p != NULL); ECMA_SET_POINTER (object_p->gc_next_cp, next_object_p); } /* ecma_gc_set_object_next */
/** * Allocate a collection of ecma-values. * * @return pointer to the collection's header */ ecma_collection_header_t * ecma_new_values_collection (const ecma_value_t values_buffer[], /**< ecma-values */ ecma_length_t values_number, /**< number of ecma-values */ bool do_ref_if_object) /**< if the value is object value, increase reference counter of the object */ { JERRY_ASSERT (values_buffer != NULL || values_number == 0); const size_t values_in_chunk = sizeof (ecma_collection_chunk_t::data) / sizeof (ecma_value_t); ecma_collection_header_t *header_p = ecma_alloc_collection_header (); header_p->unit_number = values_number; mem_cpointer_t *next_chunk_cp_p = &header_p->first_chunk_cp; ecma_collection_chunk_t *last_chunk_p = NULL; ecma_value_t *cur_value_buf_iter_p = NULL; ecma_value_t *cur_value_buf_end_p = NULL; for (ecma_length_t value_index = 0; value_index < values_number; value_index++) { if (cur_value_buf_iter_p == cur_value_buf_end_p) { ecma_collection_chunk_t *chunk_p = ecma_alloc_collection_chunk (); ECMA_SET_POINTER (*next_chunk_cp_p, chunk_p); next_chunk_cp_p = &chunk_p->next_chunk_cp; cur_value_buf_iter_p = (ecma_value_t *) chunk_p->data; cur_value_buf_end_p = cur_value_buf_iter_p + values_in_chunk; last_chunk_p = chunk_p; } JERRY_ASSERT (cur_value_buf_iter_p + 1 <= cur_value_buf_end_p); *cur_value_buf_iter_p++ = ecma_copy_value (values_buffer[value_index], do_ref_if_object); } *next_chunk_cp_p = ECMA_NULL_POINTER; ECMA_SET_POINTER (header_p->last_chunk_cp, last_chunk_p); return header_p; } /* ecma_new_values_collection */
/** * Set setter of named accessor property */ void ecma_set_named_accessor_property_setter (ecma_object_t *object_p, /**< the property's container */ ecma_property_t *prop_p, /**< named accessor property */ ecma_object_t *setter_p) /**< setter object */ { JERRY_ASSERT (ECMA_PROPERTY_GET_TYPE (prop_p) == ECMA_PROPERTY_TYPE_NAMEDACCESSOR); ecma_assert_object_contains_the_property (object_p, prop_p); ECMA_SET_POINTER (ECMA_PROPERTY_VALUE_PTR (prop_p)->getter_setter_pair.setter_p, setter_p); } /* ecma_set_named_accessor_property_setter */
/** * Set object's/lexical environment's property list. * * See also: * ecma_op_object_get_property_names */ static inline void ecma_set_property_list (ecma_object_t *object_p, /**< object or lexical environment */ ecma_property_header_t *property_list_p) /**< properties' list */ { JERRY_ASSERT (object_p != NULL); JERRY_ASSERT (!ecma_is_lexical_environment (object_p) || ecma_get_lex_env_type (object_p) == ECMA_LEXICAL_ENVIRONMENT_DECLARATIVE); ECMA_SET_POINTER (object_p->property_list_or_bound_object_cp, property_list_p); } /* ecma_set_property_list */
/** * Create named accessor property with given name, attributes, getter and setter. * * @return pointer to newly created property */ ecma_property_t * ecma_create_named_accessor_property (ecma_object_t *object_p, /**< object */ ecma_string_t *name_p, /**< property name */ ecma_object_t *get_p, /**< getter */ ecma_object_t *set_p, /**< setter */ uint8_t prop_attributes) /**< property attributes */ { JERRY_ASSERT (object_p != NULL && name_p != NULL); JERRY_ASSERT (ecma_find_named_property (object_p, name_p) == NULL); JERRY_ASSERT ((prop_attributes & ~ECMA_PROPERTY_CONFIGURABLE_ENUMERABLE) == 0); uint8_t type_and_flags = ECMA_PROPERTY_TYPE_NAMEDACCESSOR | prop_attributes; name_p = ecma_copy_or_ref_ecma_string (name_p); ecma_property_value_t value; ECMA_SET_POINTER (value.getter_setter_pair.getter_p, get_p); ECMA_SET_POINTER (value.getter_setter_pair.setter_p, set_p); return ecma_create_property (object_p, name_p, type_and_flags, value); } /* ecma_create_named_accessor_property */
/** * 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_arg_p, /**< property's name (See also: Note) */ ecma_property_t *prop_p) /**< property (See also: Note) */ { JERRY_ASSERT (object_p != NULL); JERRY_ASSERT (prop_p != NULL || prop_name_arg_p != NULL); #ifndef CONFIG_ECMA_LCACHE_DISABLE ecma_string_t *prop_name_p = NULL; if (prop_p != NULL) { JERRY_ASSERT (prop_p->flags & (ECMA_PROPERTY_FLAG_NAMEDDATA | ECMA_PROPERTY_FLAG_NAMEDACCESSOR)); bool is_cached = ecma_is_property_lcached (prop_p); if (!is_cached) { return; } ecma_set_property_lcached (prop_p, false); if (prop_p->flags & ECMA_PROPERTY_FLAG_NAMEDDATA) { prop_name_p = ECMA_GET_NON_NULL_POINTER (ecma_string_t, prop_p->v.named_data_property.name_p); } else { prop_name_p = ECMA_GET_NON_NULL_POINTER (ecma_string_t, prop_p->v.named_accessor_property.name_p); } } else { prop_name_p = prop_name_arg_p; } unsigned int object_cp, prop_cp; ECMA_SET_NON_NULL_POINTER (object_cp, object_p); ECMA_SET_POINTER (prop_cp, prop_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_cp); #endif /* !CONFIG_ECMA_LCACHE_DISABLE */ } /* ecma_lcache_invalidate */
/** * RegExp object creation operation. * * See also: ECMA-262 v5, 15.10.4.1 * * @return completion value * Returned value must be freed with ecma_free_completion_value */ ecma_completion_value_t ecma_op_create_regexp_object (ecma_string_t *pattern_p, /**< input pattern */ ecma_string_t *flags_str_p) /**< flags */ { JERRY_ASSERT (pattern_p != NULL); ecma_completion_value_t ret_value = ecma_make_empty_completion_value (); uint8_t flags = 0; if (flags_str_p != NULL) { ECMA_TRY_CATCH (empty, re_parse_regexp_flags (flags_str_p, &flags), ret_value); ECMA_FINALIZE (empty); if (!ecma_is_completion_value_empty (ret_value)) { return ret_value; } } ecma_object_t *re_prototype_obj_p = ecma_builtin_get (ECMA_BUILTIN_ID_REGEXP_PROTOTYPE); ecma_object_t *obj_p = ecma_create_object (re_prototype_obj_p, true, ECMA_OBJECT_TYPE_GENERAL); ecma_deref_object (re_prototype_obj_p); /* Set the internal [[Class]] property */ ecma_property_t *class_prop_p = ecma_create_internal_property (obj_p, ECMA_INTERNAL_PROPERTY_CLASS); class_prop_p->u.internal_property.value = LIT_MAGIC_STRING_REGEXP_UL; re_initialize_props (obj_p, pattern_p, flags); /* Set bytecode internal property. */ ecma_property_t *bytecode_prop_p; bytecode_prop_p = ecma_create_internal_property (obj_p, ECMA_INTERNAL_PROPERTY_REGEXP_BYTECODE); /* Compile bytecode. */ re_bytecode_t *bc_p = NULL; ECMA_TRY_CATCH (empty, re_compile_bytecode (&bc_p, pattern_p, flags), ret_value); ECMA_SET_POINTER (bytecode_prop_p->u.internal_property.value, bc_p); ret_value = ecma_make_normal_completion_value (ecma_make_object_value (obj_p)); ECMA_FINALIZE (empty); if (ecma_is_completion_value_throw (ret_value)) { ecma_deref_object (obj_p); } return ret_value; } /* ecma_op_create_regexp_object */
/** * Set next object in list of objects with same generation. */ static void ecma_gc_set_object_next (ecma_object_t *object_p, /**< object */ ecma_object_t *next_object_p) /**< next object */ { JERRY_ASSERT (object_p != NULL); uintptr_t next_cp; ECMA_SET_POINTER (next_cp, next_object_p); JERRY_ASSERT (sizeof (uintptr_t) * JERRY_BITSINBYTE >= ECMA_OBJECT_GC_NEXT_CP_WIDTH); object_p->container = jrt_set_bit_field_value (object_p->container, next_cp, ECMA_OBJECT_GC_NEXT_CP_POS, ECMA_OBJECT_GC_NEXT_CP_WIDTH); } /* ecma_gc_set_object_next */
/** * ECMA-reference constructor. * * @return ECMA-reference * Returned value must be freed through ecma_free_reference. */ ecma_reference_t ecma_make_reference (ecma_value_t base, /**< base value */ ecma_string_t *name_p, /**< referenced name */ bool is_strict) /**< strict reference flag */ { ecma_ref_ecma_string (name_p); ecma_reference_t ref; ref.base = ecma_copy_value (base); ref.is_strict = (is_strict != 0); ECMA_SET_POINTER (ref.referenced_name_cp, name_p); return ref; } /* ecma_make_reference */
/** * Create a declarative lexical environment with specified outer lexical environment * (or NULL if the environment is not nested). * * See also: ECMA-262 v5, 10.2.1.1 * * Reference counter's value will be set to one. * * @return pointer to the descriptor of lexical environment */ ecma_object_t * ecma_create_decl_lex_env (ecma_object_t *outer_lexical_environment_p) /**< outer lexical environment */ { ecma_object_t *new_lexical_environment_p = ecma_alloc_object (); uint16_t type = ECMA_OBJECT_FLAG_BUILT_IN_OR_LEXICAL_ENV | ECMA_LEXICAL_ENVIRONMENT_DECLARATIVE; new_lexical_environment_p->type_flags_refs = type; ecma_init_gc_info (new_lexical_environment_p); new_lexical_environment_p->property_list_or_bound_object_cp = JMEM_CP_NULL; ECMA_SET_POINTER (new_lexical_environment_p->prototype_or_outer_reference_cp, outer_lexical_environment_p); return new_lexical_environment_p; } /* ecma_create_decl_lex_env */
/** * Initialize specified built-in object. * * Warning: * the routine should be called only from ecma_init_builtins * * @return pointer to the object */ static ecma_object_t * ecma_builtin_init_object (ecma_builtin_id_t obj_builtin_id, /**< built-in ID */ ecma_object_t *prototype_obj_p, /**< prototype object */ ecma_object_type_t obj_type, /**< object's type */ bool is_extensible) /**< value of object's [[Extensible]] property */ { ecma_object_t *object_obj_p = ecma_create_object (prototype_obj_p, is_extensible, obj_type); /* * [[Class]] property of built-in object is not stored explicitly. * * See also: ecma_object_get_class_name */ ecma_property_t *built_in_id_prop_p = ecma_create_internal_property (object_obj_p, ECMA_INTERNAL_PROPERTY_BUILT_IN_ID); built_in_id_prop_p->u.internal_property.value = obj_builtin_id; ecma_set_object_is_builtin (object_obj_p, true); /** Initializing [[PrimitiveValue]] properties of built-in prototype objects */ switch (obj_builtin_id) { #ifndef CONFIG_ECMA_COMPACT_PROFILE_DISABLE_STRING_BUILTIN case ECMA_BUILTIN_ID_STRING_PROTOTYPE: { ecma_string_t *prim_prop_str_value_p = ecma_get_magic_string (LIT_MAGIC_STRING__EMPTY); ecma_property_t *prim_value_prop_p; prim_value_prop_p = ecma_create_internal_property (object_obj_p, ECMA_INTERNAL_PROPERTY_PRIMITIVE_STRING_VALUE); ECMA_SET_POINTER (prim_value_prop_p->u.internal_property.value, prim_prop_str_value_p); break; } #endif /* !CONFIG_ECMA_COMPACT_PROFILE_DISABLE_STRING_BUILTIN */ #ifndef CONFIG_ECMA_COMPACT_PROFILE_DISABLE_NUMBER_BUILTIN case ECMA_BUILTIN_ID_NUMBER_PROTOTYPE: { ecma_number_t *prim_prop_num_value_p = ecma_alloc_number (); *prim_prop_num_value_p = ECMA_NUMBER_ZERO; ecma_property_t *prim_value_prop_p; prim_value_prop_p = ecma_create_internal_property (object_obj_p, ECMA_INTERNAL_PROPERTY_PRIMITIVE_NUMBER_VALUE); ECMA_SET_POINTER (prim_value_prop_p->u.internal_property.value, prim_prop_num_value_p); break; } #endif /* !CONFIG_ECMA_COMPACT_PROFILE_DISABLE_NUMBER_BUILTIN */ #ifndef CONFIG_ECMA_COMPACT_PROFILE_DISABLE_BOOLEAN_BUILTIN case ECMA_BUILTIN_ID_BOOLEAN_PROTOTYPE: { ecma_property_t *prim_value_prop_p; prim_value_prop_p = ecma_create_internal_property (object_obj_p, ECMA_INTERNAL_PROPERTY_PRIMITIVE_BOOLEAN_VALUE); prim_value_prop_p->u.internal_property.value = ECMA_SIMPLE_VALUE_FALSE; break; } #endif /* !CONFIG_ECMA_COMPACT_PROFILE_DISABLE_BOOLEAN_BUILTIN */ #ifndef CONFIG_ECMA_COMPACT_PROFILE_DISABLE_DATE_BUILTIN case ECMA_BUILTIN_ID_DATE_PROTOTYPE: { ecma_number_t *prim_prop_num_value_p = ecma_alloc_number (); *prim_prop_num_value_p = ecma_number_make_nan (); ecma_property_t *prim_value_prop_p; prim_value_prop_p = ecma_create_internal_property (object_obj_p, ECMA_INTERNAL_PROPERTY_PRIMITIVE_NUMBER_VALUE); ECMA_SET_POINTER (prim_value_prop_p->u.internal_property.value, prim_prop_num_value_p); break; } #endif /* !CONFIG_ECMA_COMPACT_PROFILE_DISABLE_DATE_BUILTIN */ #ifndef CONFIG_ECMA_COMPACT_PROFILE_DISABLE_REGEXP_BUILTIN case ECMA_BUILTIN_ID_REGEXP_PROTOTYPE: { ecma_property_t *bytecode_prop_p; bytecode_prop_p = ecma_create_internal_property (object_obj_p, ECMA_INTERNAL_PROPERTY_REGEXP_BYTECODE); bytecode_prop_p->u.internal_property.value = ECMA_NULL_POINTER; break; } #endif /* !CONFIG_ECMA_COMPACT_PROFILE_DISABLE_REGEXP_BUILTIN */ default: { break; } } return object_obj_p; } /* ecma_builtin_init_object */
/** * The RegExp.prototype object's 'compile' routine * * See also: * ECMA-262 v5, B.2.5.1 * * @return completion value * Returned value must be freed with ecma_free_completion_value. */ static ecma_completion_value_t ecma_builtin_regexp_prototype_compile (ecma_value_t this_arg, /**< this argument */ ecma_value_t pattern_arg, /**< pattern or RegExp object */ ecma_value_t flags_arg) /**< flags */ { ecma_completion_value_t ret_value = ecma_make_empty_completion_value (); ecma_object_t *this_obj_p = ecma_get_object_from_value (this_arg); if (ecma_object_get_class_name (this_obj_p) != LIT_MAGIC_STRING_REGEXP_UL) { /* Compile can only be called on RegExp objects. */ ret_value = ecma_make_throw_obj_completion_value (ecma_new_standard_error (ECMA_ERROR_TYPE)); } else { ecma_string_t *pattern_string_p = NULL; uint16_t flags = 0; if (ecma_is_value_object (pattern_arg) && ecma_object_get_class_name (ecma_get_object_from_value (pattern_arg)) == LIT_MAGIC_STRING_REGEXP_UL) { if (!ecma_is_value_undefined (flags_arg)) { ret_value = ecma_raise_type_error ("Invalid argument of RegExp compile."); } else { /* Compile from existing RegExp pbject. */ ecma_object_t *target_p = ecma_get_object_from_value (pattern_arg); /* Get source. */ ecma_string_t *magic_string_p = ecma_get_magic_string (LIT_MAGIC_STRING_SOURCE); ecma_property_t *prop_p = ecma_get_named_data_property (target_p, magic_string_p); pattern_string_p = ecma_get_string_from_value (ecma_get_named_data_property_value (prop_p)); ecma_deref_ecma_string (magic_string_p); /* Get flags. */ magic_string_p = ecma_get_magic_string (LIT_MAGIC_STRING_GLOBAL); prop_p = ecma_get_named_data_property (target_p, magic_string_p); if (ecma_is_value_true (ecma_get_named_data_property_value (prop_p))) { flags |= RE_FLAG_GLOBAL; } ecma_deref_ecma_string (magic_string_p); magic_string_p = ecma_get_magic_string (LIT_MAGIC_STRING_IGNORECASE_UL); prop_p = ecma_get_named_data_property (target_p, magic_string_p); if (ecma_is_value_true (ecma_get_named_data_property_value (prop_p))) { flags |= RE_FLAG_IGNORE_CASE; } ecma_deref_ecma_string (magic_string_p); magic_string_p = ecma_get_magic_string (LIT_MAGIC_STRING_MULTILINE); prop_p = ecma_get_named_data_property (target_p, magic_string_p); if (ecma_is_value_true (ecma_get_named_data_property_value (prop_p))) { flags |= RE_FLAG_MULTILINE; } ecma_deref_ecma_string (magic_string_p); /* Get bytecode property. */ ecma_property_t *bc_prop_p = ecma_get_internal_property (this_obj_p, ECMA_INTERNAL_PROPERTY_REGEXP_BYTECODE); /* FIXME: "We currently have to re-compile the bytecode, because * we can't copy it without knowing its length." */ re_compiled_code_t *new_bc_p = NULL; ecma_completion_value_t bc_comp = re_compile_bytecode (&new_bc_p, pattern_string_p, flags); /* Should always succeed, since we're compiling from a source that has been compiled previously. */ JERRY_ASSERT (ecma_is_completion_value_empty (bc_comp)); re_compiled_code_t *old_bc_p = ECMA_GET_POINTER (re_compiled_code_t, bc_prop_p->u.internal_property.value); if (old_bc_p != NULL) { /* Free the old bytecode */ ecma_bytecode_deref ((ecma_compiled_code_t *) old_bc_p); } ECMA_SET_POINTER (bc_prop_p->u.internal_property.value, new_bc_p); re_initialize_props (this_obj_p, pattern_string_p, flags); ret_value = ecma_make_normal_completion_value (ecma_make_simple_value (ECMA_SIMPLE_VALUE_UNDEFINED)); } } else { /* Get source string. */ if (!ecma_is_value_undefined (pattern_arg)) { ECMA_TRY_CATCH (regexp_str_value, ecma_op_to_string (pattern_arg), ret_value); if (ecma_string_get_length (ecma_get_string_from_value (regexp_str_value)) == 0) { pattern_string_p = ecma_get_magic_string (LIT_MAGIC_STRING_EMPTY_NON_CAPTURE_GROUP); } else { pattern_string_p = ecma_copy_or_ref_ecma_string (ecma_get_string_from_value (regexp_str_value)); } ECMA_FINALIZE (regexp_str_value); } else { pattern_string_p = ecma_get_magic_string (LIT_MAGIC_STRING_EMPTY_NON_CAPTURE_GROUP); } /* Parse flags. */ if (ecma_is_completion_value_empty (ret_value) && !ecma_is_value_undefined (flags_arg)) { ECMA_TRY_CATCH (flags_str_value, ecma_op_to_string (flags_arg), ret_value); ECMA_TRY_CATCH (flags_dummy, re_parse_regexp_flags (ecma_get_string_from_value (flags_str_value), &flags), ret_value); ECMA_FINALIZE (flags_dummy); ECMA_FINALIZE (flags_str_value); } if (ecma_is_completion_value_empty (ret_value)) { ecma_property_t *bc_prop_p = ecma_get_internal_property (this_obj_p, ECMA_INTERNAL_PROPERTY_REGEXP_BYTECODE); /* Try to compile bytecode from new source. */ re_compiled_code_t *new_bc_p = NULL; ECMA_TRY_CATCH (bc_dummy, re_compile_bytecode (&new_bc_p, pattern_string_p, flags), ret_value); re_compiled_code_t *old_bc_p = ECMA_GET_POINTER (re_compiled_code_t, bc_prop_p->u.internal_property.value); if (old_bc_p != NULL) { /* Free the old bytecode */ ecma_bytecode_deref ((ecma_compiled_code_t *) old_bc_p); } ECMA_SET_POINTER (bc_prop_p->u.internal_property.value, new_bc_p); re_initialize_props (this_obj_p, pattern_string_p, flags); ret_value = ecma_make_normal_completion_value (ecma_make_simple_value (ECMA_SIMPLE_VALUE_UNDEFINED)); ECMA_FINALIZE (bc_dummy); } if (pattern_string_p != NULL) { ecma_deref_ecma_string (pattern_string_p); } } } return ret_value; } /* ecma_builtin_regexp_prototype_compile */
/** * Function object creation operation. * * See also: ECMA-262 v5, 13.2 * * @return pointer to newly created Function object */ ecma_object_t* ecma_op_create_function_object (ecma_string_t* formal_parameter_list_p[], /**< formal parameters list */ ecma_length_t formal_parameters_number, /**< formal parameters list's length */ ecma_object_t *scope_p, /**< function's scope */ bool is_strict, /**< 'strict' flag */ bool do_instantiate_arguments_object, /**< should an Arguments object be instantiated * for the function object upon call */ const vm_instr_t *instrs_p, /**< byte-code array */ vm_instr_counter_t first_instr_pos) /**< position of first instruction * of function's body */ { // 1., 4., 13. ecma_object_t *prototype_obj_p = ecma_builtin_get (ECMA_BUILTIN_ID_FUNCTION_PROTOTYPE); ecma_object_t *f = ecma_create_object (prototype_obj_p, true, ECMA_OBJECT_TYPE_FUNCTION); ecma_deref_object (prototype_obj_p); // 2., 6., 7., 8. /* * We don't setup [[Get]], [[Call]], [[Construct]], [[HasInstance]] for each function object. * Instead we set the object's type to ECMA_OBJECT_TYPE_FUNCTION * that defines which version of the routine should be used on demand. */ // 3. /* * [[Class]] property is not stored explicitly for objects of ECMA_OBJECT_TYPE_FUNCTION type. * * See also: ecma_object_get_class_name */ // 9. ecma_property_t *scope_prop_p = ecma_create_internal_property (f, ECMA_INTERNAL_PROPERTY_SCOPE); ECMA_SET_POINTER (scope_prop_p->u.internal_property.value, scope_p); // 10., 11. ecma_property_t *formal_parameters_prop_p = ecma_create_internal_property (f, ECMA_INTERNAL_PROPERTY_FORMAL_PARAMETERS); if (formal_parameters_number != 0) { /* * Reverse formal parameter list */ for (ecma_length_t i = 0; i < formal_parameters_number / 2; i++) { ecma_string_t *tmp_p = formal_parameter_list_p[i]; formal_parameter_list_p[i] = formal_parameter_list_p[formal_parameters_number - 1u - i]; formal_parameter_list_p[formal_parameters_number - 1u - i] = tmp_p; } ecma_collection_header_t *formal_parameters_collection_p = ecma_new_strings_collection (formal_parameter_list_p, formal_parameters_number); ECMA_SET_POINTER (formal_parameters_prop_p->u.internal_property.value, formal_parameters_collection_p); } else { JERRY_ASSERT (formal_parameters_prop_p->u.internal_property.value == ECMA_NULL_POINTER); } // 12. ecma_property_t *bytecode_prop_p = ecma_create_internal_property (f, ECMA_INTERNAL_PROPERTY_CODE_BYTECODE); MEM_CP_SET_NON_NULL_POINTER (bytecode_prop_p->u.internal_property.value, instrs_p); ecma_property_t *code_prop_p = ecma_create_internal_property (f, ECMA_INTERNAL_PROPERTY_CODE_FLAGS_AND_OFFSET); code_prop_p->u.internal_property.value = ecma_pack_code_internal_property_value (is_strict, do_instantiate_arguments_object, first_instr_pos); // 14. ecma_number_t* len_p = ecma_alloc_number (); *len_p = ecma_uint32_to_number (formal_parameters_number); // 15. ecma_property_descriptor_t length_prop_desc = ecma_make_empty_property_descriptor (); length_prop_desc.is_value_defined = true; length_prop_desc.value = ecma_make_number_value (len_p); ecma_string_t* magic_string_length_p = ecma_get_magic_string (LIT_MAGIC_STRING_LENGTH); ecma_completion_value_t completion = ecma_op_object_define_own_property (f, magic_string_length_p, &length_prop_desc, false); ecma_deref_ecma_string (magic_string_length_p); JERRY_ASSERT (ecma_is_completion_value_normal_true (completion) || ecma_is_completion_value_normal_false (completion)); ecma_dealloc_number (len_p); len_p = NULL; // 16. ecma_object_t *proto_p = ecma_op_create_object_object_noarg (); // 17. ecma_property_descriptor_t prop_desc = ecma_make_empty_property_descriptor (); { prop_desc.is_value_defined = true; prop_desc.value = ecma_make_object_value (f); prop_desc.is_writable_defined = true; prop_desc.is_writable = true; prop_desc.is_enumerable_defined = true; prop_desc.is_enumerable = false; prop_desc.is_configurable_defined = true; prop_desc.is_configurable = true; } ecma_string_t *magic_string_constructor_p = ecma_get_magic_string (LIT_MAGIC_STRING_CONSTRUCTOR); ecma_op_object_define_own_property (proto_p, magic_string_constructor_p, &prop_desc, false); ecma_deref_ecma_string (magic_string_constructor_p); // 18. prop_desc.value = ecma_make_object_value (proto_p); prop_desc.is_configurable = false; ecma_string_t *magic_string_prototype_p = ecma_get_magic_string (LIT_MAGIC_STRING_PROTOTYPE); ecma_op_object_define_own_property (f, magic_string_prototype_p, &prop_desc, false); ecma_deref_ecma_string (magic_string_prototype_p); ecma_deref_object (proto_p); // 19. if (is_strict) { ecma_object_t *thrower_p = ecma_builtin_get (ECMA_BUILTIN_ID_TYPE_ERROR_THROWER); prop_desc = ecma_make_empty_property_descriptor (); { prop_desc.is_enumerable_defined = true; prop_desc.is_enumerable = false; prop_desc.is_configurable_defined = true; prop_desc.is_configurable = false; prop_desc.is_get_defined = true; prop_desc.get_p = thrower_p; prop_desc.is_set_defined = true; prop_desc.set_p = thrower_p; } ecma_string_t *magic_string_caller_p = ecma_get_magic_string (LIT_MAGIC_STRING_CALLER); ecma_op_object_define_own_property (f, magic_string_caller_p, &prop_desc, false); ecma_deref_ecma_string (magic_string_caller_p); ecma_string_t *magic_string_arguments_p = ecma_get_magic_string (LIT_MAGIC_STRING_ARGUMENTS); ecma_op_object_define_own_property (f, magic_string_arguments_p, &prop_desc, false); ecma_deref_ecma_string (magic_string_arguments_p); ecma_deref_object (thrower_p); } return f; } /* ecma_op_create_function_object */
/** * Arguments object creation operation. * * See also: ECMA-262 v5, 10.6 */ void ecma_op_create_arguments_object (ecma_object_t *func_obj_p, /**< callee function */ ecma_object_t *lex_env_p, /**< lexical environment the Arguments object is created for */ const ecma_value_t *arguments_list_p, /**< arguments list */ ecma_length_t arguments_number, /**< length of arguments list */ const ecma_compiled_code_t *bytecode_data_p) /**< byte code */ { // 2., 3., 6. ecma_object_t *prototype_p = ecma_builtin_get (ECMA_BUILTIN_ID_OBJECT_PROTOTYPE); ecma_object_t *obj_p = ecma_create_object (prototype_p, true, ECMA_OBJECT_TYPE_GENERAL); ecma_deref_object (prototype_p); // 11.a, 11.b for (ecma_length_t indx = 0; indx < arguments_number; indx++) { ecma_value_t completion; ecma_string_t *indx_string_p = ecma_new_ecma_string_from_uint32 (indx); completion = ecma_builtin_helper_def_prop (obj_p, indx_string_p, arguments_list_p[indx], true, /* Writable */ true, /* Enumerable */ true, /* Configurable */ false); /* Failure handling */ JERRY_ASSERT (ecma_is_value_true (completion)); ecma_deref_ecma_string (indx_string_p); } bool is_strict = (bytecode_data_p->status_flags & CBC_CODE_FLAGS_STRICT_MODE) != 0; // 1. ecma_number_t *len_p = ecma_alloc_number (); *len_p = ecma_uint32_to_number (arguments_number); // 4. ecma_property_t *class_prop_p = ecma_create_internal_property (obj_p, ECMA_INTERNAL_PROPERTY_CLASS); class_prop_p->u.internal_property.value = LIT_MAGIC_STRING_ARGUMENTS_UL; // 7. ecma_string_t *length_magic_string_p = ecma_get_magic_string (LIT_MAGIC_STRING_LENGTH); ecma_value_t completion = ecma_builtin_helper_def_prop (obj_p, length_magic_string_p, ecma_make_number_value (len_p), true, /* Writable */ false, /* Enumerable */ true, /* Configurable */ false); /* Failure handling */ JERRY_ASSERT (ecma_is_value_true (completion)); ecma_deref_ecma_string (length_magic_string_p); ecma_dealloc_number (len_p); ecma_property_descriptor_t prop_desc = ecma_make_empty_property_descriptor (); if (bytecode_data_p != NULL) { ecma_length_t formal_params_number; lit_cpointer_t *literal_p; if (bytecode_data_p->status_flags & CBC_CODE_FLAGS_UINT16_ARGUMENTS) { cbc_uint16_arguments_t *args_p = (cbc_uint16_arguments_t *) bytecode_data_p; uint8_t *byte_p = (uint8_t *) bytecode_data_p; formal_params_number = args_p->argument_end; literal_p = (lit_cpointer_t *) (byte_p + sizeof (cbc_uint16_arguments_t)); } else { cbc_uint8_arguments_t *args_p = (cbc_uint8_arguments_t *) bytecode_data_p; uint8_t *byte_p = (uint8_t *) bytecode_data_p; formal_params_number = args_p->argument_end; literal_p = (lit_cpointer_t *) (byte_p + sizeof (cbc_uint8_arguments_t)); } if (!is_strict && arguments_number > 0 && formal_params_number > 0) { // 8. ecma_object_t *map_p = ecma_op_create_object_object_noarg (); // 11.c for (uint32_t indx = 0; indx < formal_params_number; indx++) { // i. if (literal_p[indx].u.packed_value == MEM_CP_NULL) { continue; } ecma_string_t *name_p = ecma_new_ecma_string_from_lit_cp (literal_p[indx]); ecma_string_t *indx_string_p = ecma_new_ecma_string_from_uint32 ((uint32_t) indx); prop_desc.is_value_defined = true; prop_desc.value = ecma_make_string_value (name_p); prop_desc.is_configurable_defined = true; prop_desc.is_configurable = true; completion = ecma_op_object_define_own_property (map_p, indx_string_p, &prop_desc, false); JERRY_ASSERT (ecma_is_value_true (completion)); ecma_deref_ecma_string (indx_string_p); ecma_deref_ecma_string (name_p); } // 12. ecma_set_object_type (obj_p, ECMA_OBJECT_TYPE_ARGUMENTS); /* * [[Class]] property is not stored explicitly for objects of ECMA_OBJECT_TYPE_ARGUMENTS type. * * See also: ecma_object_get_class_name */ ecma_delete_property (obj_p, class_prop_p); ecma_property_t *parameters_map_prop_p = ecma_create_internal_property (obj_p, ECMA_INTERNAL_PROPERTY_PARAMETERS_MAP); ECMA_SET_POINTER (parameters_map_prop_p->u.internal_property.value, map_p); ecma_property_t *scope_prop_p = ecma_create_internal_property (map_p, ECMA_INTERNAL_PROPERTY_SCOPE); ECMA_SET_POINTER (scope_prop_p->u.internal_property.value, lex_env_p); ecma_deref_object (map_p); } } // 13. if (!is_strict) { ecma_string_t *callee_magic_string_p = ecma_get_magic_string (LIT_MAGIC_STRING_CALLEE); completion = ecma_builtin_helper_def_prop (obj_p, callee_magic_string_p, ecma_make_object_value (func_obj_p), true, /* Writable */ false, /* Enumerable */ true, /* Configurable */ false); /* Failure handling */ JERRY_ASSERT (ecma_is_value_true (completion)); ecma_deref_ecma_string (callee_magic_string_p); } else { ecma_object_t *thrower_p = ecma_builtin_get (ECMA_BUILTIN_ID_TYPE_ERROR_THROWER); // 14. prop_desc = ecma_make_empty_property_descriptor (); { prop_desc.is_get_defined = true; prop_desc.get_p = thrower_p; prop_desc.is_set_defined = true; prop_desc.set_p = thrower_p; prop_desc.is_enumerable_defined = true; prop_desc.is_enumerable = false; prop_desc.is_configurable_defined = true; prop_desc.is_configurable = false; } ecma_string_t *callee_magic_string_p = ecma_get_magic_string (LIT_MAGIC_STRING_CALLEE); completion = ecma_op_object_define_own_property (obj_p, callee_magic_string_p, &prop_desc, false); JERRY_ASSERT (ecma_is_value_true (completion)); ecma_deref_ecma_string (callee_magic_string_p); ecma_string_t *caller_magic_string_p = ecma_get_magic_string (LIT_MAGIC_STRING_CALLER); completion = ecma_op_object_define_own_property (obj_p, caller_magic_string_p, &prop_desc, false); JERRY_ASSERT (ecma_is_value_true (completion)); ecma_deref_ecma_string (caller_magic_string_p); ecma_deref_object (thrower_p); } ecma_string_t *arguments_string_p = ecma_get_magic_string (LIT_MAGIC_STRING_ARGUMENTS); if (is_strict) { ecma_op_create_immutable_binding (lex_env_p, arguments_string_p); ecma_op_initialize_immutable_binding (lex_env_p, arguments_string_p, ecma_make_object_value (obj_p)); } else { ecma_value_t completion = ecma_op_create_mutable_binding (lex_env_p, arguments_string_p, false); JERRY_ASSERT (ecma_is_value_empty (completion)); completion = ecma_op_set_mutable_binding (lex_env_p, arguments_string_p, ecma_make_object_value (obj_p), false); JERRY_ASSERT (ecma_is_value_empty (completion)); } ecma_deref_ecma_string (arguments_string_p); ecma_deref_object (obj_p); } /* ecma_op_create_arguments_object */
/** * String object creation operation. * * See also: ECMA-262 v5, 15.5.2.1 * * @return ecma value * Returned value must be freed with ecma_free_value */ ecma_value_t ecma_op_create_string_object (const ecma_value_t *arguments_list_p, /**< list of arguments that are passed to String constructor */ ecma_length_t arguments_list_len) /**< length of the arguments' list */ { JERRY_ASSERT (arguments_list_len == 0 || arguments_list_p != NULL); ecma_string_t *prim_prop_str_value_p; ecma_number_t length_value; if (arguments_list_len == 0) { prim_prop_str_value_p = ecma_new_ecma_string_from_magic_string_id (LIT_MAGIC_STRING__EMPTY); length_value = ECMA_NUMBER_ZERO; } else { ecma_value_t to_str_arg_value = ecma_op_to_string (arguments_list_p[0]); if (ecma_is_value_error (to_str_arg_value)) { return to_str_arg_value; } else { JERRY_ASSERT (!ecma_is_value_error (to_str_arg_value)); JERRY_ASSERT (ecma_is_value_string (to_str_arg_value)); prim_prop_str_value_p = ecma_get_string_from_value (to_str_arg_value); ecma_length_t string_len = ecma_string_get_length (prim_prop_str_value_p); length_value = ((ecma_number_t) (uint32_t) string_len); } } #ifndef CONFIG_ECMA_COMPACT_PROFILE_DISABLE_STRING_BUILTIN ecma_object_t *prototype_obj_p = ecma_builtin_get (ECMA_BUILTIN_ID_STRING_PROTOTYPE); #else /* !CONFIG_ECMA_COMPACT_PROFILE_DISABLE_STRING_BUILTIN */ ecma_object_t *prototype_obj_p = ecma_builtin_get (ECMA_BUILTIN_ID_OBJECT_PROTOTYPE); #endif /* CONFIG_ECMA_COMPACT_PROFILE_DISABLE_STRING_BUILTIN */ ecma_object_t *obj_p = ecma_create_object (prototype_obj_p, true, ECMA_OBJECT_TYPE_STRING); ecma_deref_object (prototype_obj_p); /* * [[Class]] property is not stored explicitly for objects of ECMA_OBJECT_TYPE_STRING type. * * See also: ecma_object_get_class_name */ ecma_property_t *prim_value_prop_p = ecma_create_internal_property (obj_p, ECMA_INTERNAL_PROPERTY_PRIMITIVE_STRING_VALUE); ECMA_SET_POINTER (ECMA_PROPERTY_VALUE_PTR (prim_value_prop_p)->value, prim_prop_str_value_p); // 15.5.5.1 ecma_string_t *length_magic_string_p = ecma_get_magic_string (LIT_MAGIC_STRING_LENGTH); ecma_property_t *length_prop_p = ecma_create_named_data_property (obj_p, length_magic_string_p, false, false, false); ecma_number_t *length_prop_value_p = ecma_alloc_number (); *length_prop_value_p = length_value; ecma_set_named_data_property_value (length_prop_p, ecma_make_number_value (length_prop_value_p)); ecma_deref_ecma_string (length_magic_string_p); return ecma_make_object_value (obj_p); } /* ecma_op_create_string_object */
/** * Create a property in an object and link it into * the object's properties' linked-list (at start of the list). * * @return pointer to newly created property */ static ecma_property_t * ecma_create_property (ecma_object_t *object_p, /**< the object */ ecma_string_t *name_p, /**< property name */ uint8_t type_and_flags, /**< type and flags, see ecma_property_info_t */ ecma_property_value_t value) /**< property value */ { JERRY_ASSERT (ECMA_PROPERTY_PAIR_ITEM_COUNT == 2); jmem_cpointer_t *property_list_head_p = &object_p->property_list_or_bound_object_cp; bool has_hashmap = false; if (*property_list_head_p != ECMA_NULL_POINTER) { /* If the first entry is a hashmap, it is skipped. */ ecma_property_header_t *first_property_p = ECMA_GET_NON_NULL_POINTER (ecma_property_header_t, *property_list_head_p); if (ECMA_PROPERTY_GET_TYPE (first_property_p->types + 0) == ECMA_PROPERTY_TYPE_HASHMAP) { property_list_head_p = &first_property_p->next_property_cp; has_hashmap = true; } } if (*property_list_head_p != ECMA_NULL_POINTER) { /* If the first entry is free (deleted), it is reused. */ ecma_property_header_t *first_property_p = ECMA_GET_NON_NULL_POINTER (ecma_property_header_t, *property_list_head_p); JERRY_ASSERT (ECMA_PROPERTY_IS_PROPERTY_PAIR (first_property_p)); if (first_property_p->types[0].type_and_flags == ECMA_PROPERTY_TYPE_DELETED) { first_property_p->types[0].type_and_flags = type_and_flags; ecma_property_pair_t *first_property_pair_p = (ecma_property_pair_t *) first_property_p; ECMA_SET_POINTER (first_property_pair_p->names_cp[0], name_p); ecma_property_t *property_p = first_property_p->types + 0; JERRY_ASSERT (ECMA_PROPERTY_VALUE_PTR (property_p) == first_property_pair_p->values + 0); first_property_pair_p->values[0] = value; /* The property must be fully initialized before ecma_property_hashmap_insert * is called, because the insert operation may reallocate the hashmap, and * that triggers garbage collection which scans all properties of all objects. * A not fully initialized but queued property may cause a crash. */ if (has_hashmap && name_p != NULL) { ecma_property_hashmap_insert (object_p, name_p, first_property_pair_p, 0); } return property_p; } } /* Otherwise we create a new property pair and use its second value. */ ecma_property_pair_t *first_property_pair_p = ecma_alloc_property_pair (); /* Just copy the previous value (no need to decompress, compress). */ first_property_pair_p->header.next_property_cp = *property_list_head_p; first_property_pair_p->header.types[0].type_and_flags = ECMA_PROPERTY_TYPE_DELETED; first_property_pair_p->header.types[1].type_and_flags = type_and_flags; first_property_pair_p->names_cp[0] = ECMA_NULL_POINTER; ECMA_SET_POINTER (first_property_pair_p->names_cp[1], name_p); ECMA_SET_NON_NULL_POINTER (*property_list_head_p, &first_property_pair_p->header); ecma_property_t *property_p = first_property_pair_p->header.types + 1; JERRY_ASSERT (ECMA_PROPERTY_VALUE_PTR (property_p) == first_property_pair_p->values + 1); first_property_pair_p->values[1] = value; /* See the comment before the other ecma_property_hashmap_insert above. */ if (has_hashmap && name_p != NULL) { ecma_property_hashmap_insert (object_p, name_p, first_property_pair_p, 1); } return property_p; } /* ecma_create_property */
/** * 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))) { mem_cpointer_t prop_cp; ECMA_SET_NON_NULL_POINTER (prop_cp, 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_cp == prop_cp) { #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_SET_POINTER (ecma_lcache_hash_table[ hash_key ][ entry_index ].prop_cp, prop_p); #else /* CONFIG_ECMA_LCACHE_DISABLE */ (void) prop_p; #endif /* CONFIG_ECMA_LCACHE_DISABLE */ } /* ecma_lcache_insert */