From dcaec22c0c09bd2f64bb3e51efec49001a0f4622 Mon Sep 17 00:00:00 2001 From: Zoltan Herczeg Date: Mon, 19 Sep 2016 00:32:38 -0700 Subject: [PATCH] Major property rework: introducing virtual properties. Properties are changed to a type and value pair instead of a pointer to an internal representation. Functions such as ecma_op_object_get_[own_]property do not return with property pointers anymore. JerryScript-DCO-1.0-Signed-off-by: Zoltan Herczeg zherczeg.u-szeged@partner.samsung.com --- jerry-core/ecma/base/ecma-gc.c | 29 +- jerry-core/ecma/base/ecma-globals.h | 39 +- jerry-core/ecma/base/ecma-helpers-string.c | 6 +- jerry-core/ecma/base/ecma-helpers.c | 327 ++++++-------- jerry-core/ecma/base/ecma-helpers.h | 31 +- jerry-core/ecma/base/ecma-lcache.c | 8 +- jerry-core/ecma/base/ecma-property-hashmap.c | 22 +- .../ecma/builtin-objects/ecma-builtin-json.c | 27 +- .../ecma-builtin-object-prototype.c | 12 +- .../builtin-objects/ecma-builtin-object.c | 56 +-- .../ecma-builtin-string-prototype.c | 22 +- .../ecma/builtin-objects/ecma-builtins.c | 32 +- .../ecma/operations/ecma-array-object.c | 22 +- jerry-core/ecma/operations/ecma-exceptions.c | 14 +- .../ecma/operations/ecma-function-object.c | 142 ++---- .../ecma/operations/ecma-function-object.h | 3 - .../ecma/operations/ecma-get-put-value.c | 21 +- jerry-core/ecma/operations/ecma-lex-env.c | 77 +--- jerry-core/ecma/operations/ecma-lex-env.h | 3 +- .../ecma/operations/ecma-objects-arguments.c | 17 +- .../ecma/operations/ecma-objects-general.c | 127 +++--- .../ecma/operations/ecma-objects-general.h | 1 - jerry-core/ecma/operations/ecma-objects.c | 406 ++++++++++++------ jerry-core/ecma/operations/ecma-objects.h | 8 +- jerry-core/ecma/operations/ecma-reference.c | 21 +- jerry-core/ecma/operations/ecma-reference.h | 2 +- .../ecma/operations/ecma-regexp-object.c | 123 +++--- .../ecma/operations/ecma-string-object.c | 107 +---- .../ecma/operations/ecma-string-object.h | 3 - jerry-core/jerry.c | 9 +- jerry-core/vm/opcodes.c | 9 +- jerry-core/vm/vm.c | 57 +-- 32 files changed, 852 insertions(+), 931 deletions(-) diff --git a/jerry-core/ecma/base/ecma-gc.c b/jerry-core/ecma/base/ecma-gc.c index 8f2c004d4..a1361fbe5 100644 --- a/jerry-core/ecma/base/ecma-gc.c +++ b/jerry-core/ecma/base/ecma-gc.c @@ -166,11 +166,11 @@ ecma_deref_object (ecma_object_t *object_p) /**< object */ static void ecma_gc_mark_property (ecma_property_t *property_p) /**< property */ { - switch (ECMA_PROPERTY_GET_TYPE (property_p)) + switch (ECMA_PROPERTY_GET_TYPE (*property_p)) { case ECMA_PROPERTY_TYPE_NAMEDDATA: { - ecma_value_t value = ecma_get_named_data_property_value (property_p); + ecma_value_t value = ECMA_PROPERTY_VALUE_PTR (property_p)->value; if (ecma_is_value_object (value)) { @@ -182,8 +182,9 @@ ecma_gc_mark_property (ecma_property_t *property_p) /**< property */ } case ECMA_PROPERTY_TYPE_NAMEDACCESSOR: { - ecma_object_t *getter_obj_p = ecma_get_named_accessor_property_getter (property_p); - ecma_object_t *setter_obj_p = ecma_get_named_accessor_property_setter (property_p); + ecma_property_value_t *prop_value_p = ECMA_PROPERTY_VALUE_PTR (property_p); + ecma_object_t *getter_obj_p = ecma_get_named_accessor_property_getter (prop_value_p); + ecma_object_t *setter_obj_p = ecma_get_named_accessor_property_setter (prop_value_p); if (getter_obj_p != NULL) { @@ -328,7 +329,7 @@ ecma_gc_mark (ecma_object_t *object_p) /**< object to mark from */ ecma_property_header_t *prop_iter_p = ecma_get_property_list (object_p); if (prop_iter_p != NULL - && ECMA_PROPERTY_GET_TYPE (prop_iter_p->types + 0) == ECMA_PROPERTY_TYPE_HASHMAP) + && ECMA_PROPERTY_GET_TYPE (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); @@ -338,12 +339,12 @@ ecma_gc_mark (ecma_object_t *object_p) /**< object to mark from */ { JERRY_ASSERT (ECMA_PROPERTY_IS_PROPERTY_PAIR (prop_iter_p)); - if (prop_iter_p->types[0].type_and_flags != ECMA_PROPERTY_TYPE_DELETED) + if (prop_iter_p->types[0] != ECMA_PROPERTY_TYPE_DELETED) { ecma_gc_mark_property (prop_iter_p->types + 0); } - if (prop_iter_p->types[1].type_and_flags != ECMA_PROPERTY_TYPE_DELETED) + if (prop_iter_p->types[1] != ECMA_PROPERTY_TYPE_DELETED) { ecma_gc_mark_property (prop_iter_p->types + 1); } @@ -392,7 +393,7 @@ ecma_gc_sweep (ecma_object_t *object_p) /**< object to free */ ecma_property_header_t *prop_iter_p = ecma_get_property_list (object_p); if (prop_iter_p != NULL - && ECMA_PROPERTY_GET_TYPE (prop_iter_p->types + 0) == ECMA_PROPERTY_TYPE_HASHMAP) + && ECMA_PROPERTY_GET_TYPE (prop_iter_p->types[0]) == ECMA_PROPERTY_TYPE_HASHMAP) { ecma_property_hashmap_free (object_p); prop_iter_p = ecma_get_property_list (object_p); @@ -403,14 +404,14 @@ ecma_gc_sweep (ecma_object_t *object_p) /**< object to free */ JERRY_ASSERT (ECMA_PROPERTY_IS_PROPERTY_PAIR (prop_iter_p)); /* Both cannot be deleted. */ - JERRY_ASSERT (prop_iter_p->types[0].type_and_flags != ECMA_PROPERTY_TYPE_DELETED - || prop_iter_p->types[1].type_and_flags != ECMA_PROPERTY_TYPE_DELETED); + JERRY_ASSERT (prop_iter_p->types[0] != ECMA_PROPERTY_TYPE_DELETED + || prop_iter_p->types[1] != ECMA_PROPERTY_TYPE_DELETED); 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_iter_p->types[i].type_and_flags != ECMA_PROPERTY_TYPE_DELETED) + if (prop_iter_p->types[i] != ECMA_PROPERTY_TYPE_DELETED) { ecma_string_t *name_p = ECMA_GET_POINTER (ecma_string_t, prop_pair_p->names_cp[i]); @@ -424,8 +425,8 @@ ecma_gc_sweep (ecma_object_t *object_p) /**< object to free */ } /* Both must be deleted. */ - JERRY_ASSERT (prop_iter_p->types[0].type_and_flags == ECMA_PROPERTY_TYPE_DELETED - && prop_iter_p->types[1].type_and_flags == ECMA_PROPERTY_TYPE_DELETED); + JERRY_ASSERT (prop_iter_p->types[0] == ECMA_PROPERTY_TYPE_DELETED + && prop_iter_p->types[1] == ECMA_PROPERTY_TYPE_DELETED); prop_iter_p = ECMA_GET_POINTER (ecma_property_header_t, prop_iter_p->next_property_cp); @@ -555,7 +556,7 @@ ecma_gc_run (jmem_free_unused_memory_severity_t severity) /**< gc severity */ { ecma_property_header_t *prop_iter_p = ecma_get_property_list (obj_iter_p); if (prop_iter_p != NULL - && ECMA_PROPERTY_GET_TYPE (prop_iter_p->types + 0) == ECMA_PROPERTY_TYPE_HASHMAP) + && ECMA_PROPERTY_GET_TYPE (prop_iter_p->types[0]) == ECMA_PROPERTY_TYPE_HASHMAP) { ecma_property_hashmap_free (obj_iter_p); } diff --git a/jerry-core/ecma/base/ecma-globals.h b/jerry-core/ecma/base/ecma-globals.h index 99f4eeda2..e1c8fc60c 100644 --- a/jerry-core/ecma/base/ecma-globals.h +++ b/jerry-core/ecma/base/ecma-globals.h @@ -273,6 +273,10 @@ typedef enum ECMA_PROPERTY_TYPE_HASHMAP, /**< hash map for fast property access */ ECMA_PROPERTY_TYPE__MAX = ECMA_PROPERTY_TYPE_HASHMAP, /**< highest value for property types. */ + + /* Property type aliases. */ + ECMA_PROPERTY_TYPE_NOT_FOUND = ECMA_PROPERTY_TYPE_DELETED, /**< property is not found */ + ECMA_PROPERTY_TYPE_VIRTUAL = ECMA_PROPERTY_TYPE_HASHMAP, /**< property is virtual */ } ecma_property_types_t; /** @@ -347,10 +351,7 @@ typedef enum * from the property address. However, property pointers cannot be compressed * anymore. */ -typedef struct -{ - uint8_t type_and_flags; /**< ecma_property_types_t (3 bit) and ecma_property_flags_t */ -} ecma_property_t; +typedef uint8_t ecma_property_t; /**< ecma_property_types_t (3 bit) and ecma_property_flags_t */ /** * Number of items in a property pair. @@ -409,20 +410,20 @@ typedef struct /** * Get property type. */ -#define ECMA_PROPERTY_GET_TYPE(property_p) \ - ((ecma_property_types_t) ((property_p)->type_and_flags & ECMA_PROPERTY_TYPE_MASK)) +#define ECMA_PROPERTY_GET_TYPE(property) \ + ((ecma_property_types_t) ((property) & ECMA_PROPERTY_TYPE_MASK)) /** * Returns true if the property pointer is a property pair. */ #define ECMA_PROPERTY_IS_PROPERTY_PAIR(property_header_p) \ - (ECMA_PROPERTY_GET_TYPE ((property_header_p)->types + 0) <= ECMA_PROPERTY_TYPE_PROPERTY_PAIR__MAX) + (ECMA_PROPERTY_GET_TYPE ((property_header_p)->types[0]) <= ECMA_PROPERTY_TYPE_PROPERTY_PAIR__MAX) /** * Returns the internal property type */ #define ECMA_PROPERTY_GET_INTERNAL_PROPERTY_TYPE(property_p) \ - ((ecma_internal_property_id_t) ((property_p)->type_and_flags >> ECMA_PROPERTY_FLAG_SHIFT)) + ((ecma_internal_property_id_t) (*(property_p) >> ECMA_PROPERTY_FLAG_SHIFT)) /** * Computing the data offset of a property. @@ -442,13 +443,31 @@ typedef struct #define ECMA_PROPERTY_VALUE_PTR(property_p) \ (ECMA_PROPERTY_VALUE_BASE_PTR (property_p) + ECMA_PROPERTY_VALUE_OFFSET (property_p)) +/** + * Property reference. + */ +typedef union +{ + ecma_property_value_t *value_p; /**< direct pointer to property value */ + ecma_value_t virtual_value; /**< property value */ +} ecma_property_ref_t; + +/** + * Option flags for ecma_op_object_get_property + */ +typedef enum +{ + ECMA_PROPERTY_GET_NO_OPTIONS = 0, /**< no option flags for ecma_op_object_get_property */ + ECMA_PROPERTY_GET_VALUE = 1u << 0, /**< fill virtual_value field for virtual properties */ +} ecma_property_get_option_bits_t; + /** * Internal object types */ typedef enum { - ECMA_OBJECT_TYPE_GENERAL = 0, /**< all objects that are not String (15.5), Function (15.3), - Arguments (10.6), Array (15.4) specification-defined objects */ + ECMA_OBJECT_TYPE_GENERAL = 0, /**< all objects that are not String (15.5), + * Function (15.3), Arguments (10.6), Array (15.4) objects */ ECMA_OBJECT_TYPE_FUNCTION = 1, /**< Function objects (15.3), created through 13.2 routine */ ECMA_OBJECT_TYPE_EXTERNAL_FUNCTION = 2, /**< External (host) function object */ ECMA_OBJECT_TYPE_ARRAY = 3, /**< Array object (15.4) */ diff --git a/jerry-core/ecma/base/ecma-helpers-string.c b/jerry-core/ecma/base/ecma-helpers-string.c index aa3b3bb53..1f14053b4 100644 --- a/jerry-core/ecma/base/ecma-helpers-string.c +++ b/jerry-core/ecma/base/ecma-helpers-string.c @@ -913,6 +913,8 @@ ecma_string_is_empty (const ecma_string_t *str_p) /**< ecma-string */ inline bool __attr_always_inline___ ecma_string_is_length (const ecma_string_t *string_p) /**< property name */ { + static const char length_str_p[] = "length"; + ecma_string_container_t container = ECMA_STRING_GET_CONTAINER (string_p); if (container == ECMA_STRING_CONTAINER_MAGIC_STRING) @@ -921,13 +923,13 @@ ecma_string_is_length (const ecma_string_t *string_p) /**< property name */ } if (container != ECMA_STRING_CONTAINER_HEAP_UTF8_STRING - || string_p->u.utf8_string.size != 6 + || string_p->u.utf8_string.size != (sizeof (length_str_p) - 1) || string_p->hash != LIT_STRING_LENGTH_HASH) { return false; } - return !strncmp ((char *) (string_p + 1), "length", 6); + return !strncmp ((char *) (string_p + 1), length_str_p, (sizeof (length_str_p) - 1)); } /* ecma_string_is_length */ /** diff --git a/jerry-core/ecma/base/ecma-helpers.c b/jerry-core/ecma/base/ecma-helpers.c index 2395bca48..0b7f97e08 100644 --- a/jerry-core/ecma/base/ecma-helpers.c +++ b/jerry-core/ecma/base/ecma-helpers.c @@ -373,13 +373,15 @@ ecma_get_lex_env_binding_object (const ecma_object_t *object_p) /**< object-boun * 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 + * @return pointer to the newly created property value */ -static ecma_property_t * +static ecma_property_value_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 */ + ecma_property_value_t value, /**< property value */ + ecma_property_t **out_prop_p) /**< [out] the property is also returned + * if this field is non-NULL */ { JERRY_ASSERT (ECMA_PROPERTY_PAIR_ITEM_COUNT == 2); @@ -392,7 +394,7 @@ ecma_create_property (ecma_object_t *object_p, /**< the object */ *property_list_head_p); bool has_hashmap = false; - if (ECMA_PROPERTY_GET_TYPE (first_property_p->types + 0) == ECMA_PROPERTY_TYPE_HASHMAP) + if (ECMA_PROPERTY_GET_TYPE (first_property_p->types[0]) == ECMA_PROPERTY_TYPE_HASHMAP) { property_list_head_p = &first_property_p->next_property_cp; first_property_p = ECMA_GET_NON_NULL_POINTER (ecma_property_header_t, @@ -402,9 +404,9 @@ ecma_create_property (ecma_object_t *object_p, /**< the object */ JERRY_ASSERT (ECMA_PROPERTY_IS_PROPERTY_PAIR (first_property_p)); - if (first_property_p->types[0].type_and_flags == ECMA_PROPERTY_TYPE_DELETED) + if (first_property_p->types[0] == ECMA_PROPERTY_TYPE_DELETED) { - first_property_p->types[0].type_and_flags = type_and_flags; + first_property_p->types[0] = 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); @@ -413,6 +415,11 @@ ecma_create_property (ecma_object_t *object_p, /**< the object */ JERRY_ASSERT (ECMA_PROPERTY_VALUE_PTR (property_p) == first_property_pair_p->values + 0); + if (out_prop_p != NULL) + { + *out_prop_p = property_p; + } + first_property_pair_p->values[0] = value; /* The property must be fully initialized before ecma_property_hashmap_insert @@ -428,7 +435,7 @@ ecma_create_property (ecma_object_t *object_p, /**< the object */ 0); } - return property_p; + return first_property_pair_p->values + 0; } } @@ -445,7 +452,7 @@ ecma_create_property (ecma_object_t *object_p, /**< the object */ 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) + 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; @@ -454,8 +461,8 @@ ecma_create_property (ecma_object_t *object_p, /**< the object */ /* 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->header.types[0] = ECMA_PROPERTY_TYPE_DELETED; + first_property_pair_p->header.types[1] = 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); @@ -465,6 +472,11 @@ ecma_create_property (ecma_object_t *object_p, /**< the object */ JERRY_ASSERT (ECMA_PROPERTY_VALUE_PTR (property_p) == first_property_pair_p->values + 1); + if (out_prop_p != NULL) + { + *out_prop_p = property_p; + } + first_property_pair_p->values[1] = value; /* See the comment before the other ecma_property_hashmap_insert above. */ @@ -477,14 +489,14 @@ ecma_create_property (ecma_object_t *object_p, /**< the object */ 1); } - return property_p; + return first_property_pair_p->values + 1; } /* ecma_create_property */ /** * Create internal 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 + * @return pointer to the newly created property value */ ecma_value_t * ecma_create_internal_property (ecma_object_t *object_p, /**< the object */ @@ -498,8 +510,8 @@ ecma_create_internal_property (ecma_object_t *object_p, /**< the object */ ecma_property_value_t value; value.value = ECMA_NULL_POINTER; - ecma_property_t *property_p = ecma_create_property (object_p, NULL, type_and_flags, value); - return &ECMA_PROPERTY_VALUE_PTR (property_p)->value; + ecma_property_value_t *prop_value_p = ecma_create_property (object_p, NULL, type_and_flags, value, NULL); + return &prop_value_p->value; } /* ecma_create_internal_property */ /** @@ -517,7 +529,7 @@ ecma_find_internal_property (ecma_object_t *object_p, /**< object descriptor */ ecma_property_header_t *prop_iter_p = ecma_get_property_list (object_p); if (prop_iter_p != NULL - && ECMA_PROPERTY_GET_TYPE (prop_iter_p->types + 0) == ECMA_PROPERTY_TYPE_HASHMAP) + && ECMA_PROPERTY_GET_TYPE (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); @@ -527,14 +539,14 @@ ecma_find_internal_property (ecma_object_t *object_p, /**< object descriptor */ { JERRY_ASSERT (ECMA_PROPERTY_IS_PROPERTY_PAIR (prop_iter_p)); - if (ECMA_PROPERTY_GET_TYPE (&prop_iter_p->types[0]) == ECMA_PROPERTY_TYPE_INTERNAL + if (ECMA_PROPERTY_GET_TYPE (prop_iter_p->types[0]) == ECMA_PROPERTY_TYPE_INTERNAL && ECMA_PROPERTY_GET_INTERNAL_PROPERTY_TYPE (prop_iter_p->types + 0) == property_id) { ecma_property_pair_t *prop_pair_p = (ecma_property_pair_t *) prop_iter_p; return &prop_pair_p->values[0].value; } - if (ECMA_PROPERTY_GET_TYPE (&prop_iter_p->types[1]) == ECMA_PROPERTY_TYPE_INTERNAL + if (ECMA_PROPERTY_GET_TYPE (prop_iter_p->types[1]) == ECMA_PROPERTY_TYPE_INTERNAL && ECMA_PROPERTY_GET_INTERNAL_PROPERTY_TYPE (prop_iter_p->types + 1) == property_id) { ecma_property_pair_t *prop_pair_p = (ecma_property_pair_t *) prop_iter_p; @@ -571,12 +583,14 @@ ecma_get_internal_property (ecma_object_t *object_p, /**< object descriptor */ * Create named data property with given name, attributes and undefined value * in the specified object. * - * @return pointer to newly created property + * @return pointer to the newly created property value */ -ecma_property_t * +ecma_property_value_t * ecma_create_named_data_property (ecma_object_t *object_p, /**< object */ ecma_string_t *name_p, /**< property name */ - uint8_t prop_attributes) /**< property attributes (See: ecma_property_flags_t) */ + uint8_t prop_attributes, /**< property attributes (See: ecma_property_flags_t) */ + 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); @@ -589,15 +603,15 @@ ecma_create_named_data_property (ecma_object_t *object_p, /**< object */ ecma_property_value_t value; value.value = ecma_make_simple_value (ECMA_SIMPLE_VALUE_UNDEFINED); - return ecma_create_property (object_p, name_p, type_and_flags, value); + return ecma_create_property (object_p, name_p, type_and_flags, value, out_prop_p); } /* ecma_create_named_data_property */ /** * Create named accessor property with given name, attributes, getter and setter. * - * @return pointer to newly created property + * @return pointer to the newly created property value */ -ecma_property_t * +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 */ @@ -624,7 +638,7 @@ ecma_create_named_accessor_property (ecma_object_t *object_p, /**< object */ 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); + return ecma_create_property (object_p, name_p, type_and_flags, value, NULL); } /* ecma_create_named_accessor_property */ /** @@ -651,7 +665,7 @@ ecma_find_named_property (ecma_object_t *obj_p, /**< object to find property in #ifndef CONFIG_ECMA_PROPERTY_HASHMAP_DISABLE if (prop_iter_p != NULL - && ECMA_PROPERTY_GET_TYPE (prop_iter_p->types + 0) == ECMA_PROPERTY_TYPE_HASHMAP) + && ECMA_PROPERTY_GET_TYPE (prop_iter_p->types[0]) == ECMA_PROPERTY_TYPE_HASHMAP) { ecma_string_t *property_real_name_p; property_p = ecma_property_hashmap_find ((ecma_property_hashmap_t *) prop_iter_p, @@ -734,30 +748,7 @@ ecma_find_named_property (ecma_object_t *obj_p, /**< object to find property in * @return pointer to the property, if it is found, * NULL - otherwise. */ -ecma_property_t * -ecma_get_named_property (ecma_object_t *obj_p, /**< object to find property in */ - ecma_string_t *name_p) /**< property's name */ -{ - JERRY_ASSERT (obj_p != NULL); - JERRY_ASSERT (name_p != NULL); - - ecma_property_t *property_p = ecma_find_named_property (obj_p, name_p); - - JERRY_ASSERT (property_p != NULL); - - return property_p; -} /* ecma_get_named_property */ - -/** - * Get named data property in specified object. - * - * Warning: - * the property must exist and be named data property - * - * @return pointer to the property, if it is found, - * NULL - otherwise. - */ -ecma_property_t * +ecma_property_value_t * ecma_get_named_data_property (ecma_object_t *obj_p, /**< object to find property in */ ecma_string_t *name_p) /**< property's name */ { @@ -766,9 +757,10 @@ ecma_get_named_data_property (ecma_object_t *obj_p, /**< object to find property ecma_property_t *property_p = ecma_find_named_property (obj_p, name_p); - JERRY_ASSERT (property_p != NULL && ECMA_PROPERTY_GET_TYPE (property_p) == ECMA_PROPERTY_TYPE_NAMEDDATA); + JERRY_ASSERT (property_p != NULL + && ECMA_PROPERTY_GET_TYPE (*property_p) == ECMA_PROPERTY_TYPE_NAMEDDATA); - return property_p; + return ECMA_PROPERTY_VALUE_PTR (property_p); } /* ecma_get_named_data_property */ /** @@ -777,7 +769,7 @@ ecma_get_named_data_property (ecma_object_t *obj_p, /**< object to find property static void ecma_free_internal_property (ecma_property_t *property_p) /**< the property */ { - JERRY_ASSERT (property_p != NULL && ECMA_PROPERTY_GET_TYPE (property_p) == ECMA_PROPERTY_TYPE_INTERNAL); + JERRY_ASSERT (property_p != NULL && ECMA_PROPERTY_GET_TYPE (*property_p) == ECMA_PROPERTY_TYPE_INTERNAL); uint32_t property_value = ECMA_PROPERTY_VALUE_PTR (property_p)->value; @@ -863,11 +855,11 @@ ecma_free_property (ecma_object_t *object_p, /**< object the property belongs to { JERRY_ASSERT (object_p != NULL && property_p != NULL); - switch (ECMA_PROPERTY_GET_TYPE (property_p)) + switch (ECMA_PROPERTY_GET_TYPE (*property_p)) { case ECMA_PROPERTY_TYPE_NAMEDDATA: { - ecma_free_value_if_not_object (ecma_get_named_data_property_value (property_p)); + ecma_free_value_if_not_object (ECMA_PROPERTY_VALUE_PTR (property_p)->value); if (ecma_is_property_lcached (property_p)) { @@ -903,24 +895,24 @@ ecma_free_property (ecma_object_t *object_p, /**< object the property belongs to } } - property_p->type_and_flags = ECMA_PROPERTY_TYPE_DELETED; + *property_p = ECMA_PROPERTY_TYPE_DELETED; } /* ecma_free_property */ /** - * Delete the object's property. + * Delete the object's property referenced by its value pointer. * - * Warning: specified property must be owned by specified object. + * Note: specified property must be owned by specified object. */ void ecma_delete_property (ecma_object_t *object_p, /**< object */ - ecma_property_t *prop_p) /**< property */ + ecma_property_value_t *prop_value_p) /**< property value reference */ { ecma_property_header_t *cur_prop_p = ecma_get_property_list (object_p); ecma_property_header_t *prev_prop_p = NULL; bool has_hashmap = false; if (cur_prop_p != NULL - && ECMA_PROPERTY_GET_TYPE (cur_prop_p->types + 0) == ECMA_PROPERTY_TYPE_HASHMAP) + && ECMA_PROPERTY_GET_TYPE (cur_prop_p->types[0]) == ECMA_PROPERTY_TYPE_HASHMAP) { prev_prop_p = cur_prop_p; cur_prop_p = ECMA_GET_POINTER (ecma_property_header_t, @@ -937,7 +929,7 @@ ecma_delete_property (ecma_object_t *object_p, /**< object */ for (int i = 0; i < ECMA_PROPERTY_PAIR_ITEM_COUNT; i++) { - if ((cur_prop_p->types + i) == prop_p) + if ((prop_pair_p->values + i) == prop_value_p) { ecma_string_t *name_p = ECMA_GET_POINTER (ecma_string_t, prop_pair_p->names_cp[i]); @@ -949,7 +941,7 @@ ecma_delete_property (ecma_object_t *object_p, /**< object */ { ecma_property_hashmap_delete (object_p, name_p, - prop_p); + cur_prop_p->types + i); } ecma_deref_ecma_string (name_p); @@ -959,13 +951,13 @@ ecma_delete_property (ecma_object_t *object_p, /**< object */ JERRY_ASSERT (ECMA_PROPERTY_PAIR_ITEM_COUNT == 2); - if (cur_prop_p->types[1 - i].type_and_flags != ECMA_PROPERTY_TYPE_DELETED) + if (cur_prop_p->types[1 - i] != ECMA_PROPERTY_TYPE_DELETED) { /* The other property is still valid. */ return; } - JERRY_ASSERT (cur_prop_p->types[i].type_and_flags == ECMA_PROPERTY_TYPE_DELETED); + JERRY_ASSERT (cur_prop_p->types[i] == ECMA_PROPERTY_TYPE_DELETED); if (prev_prop_p == NULL) { @@ -992,14 +984,15 @@ ecma_delete_property (ecma_object_t *object_p, /**< object */ */ static void ecma_assert_object_contains_the_property (const ecma_object_t *object_p, /**< ecma-object */ - const ecma_property_t *prop_p) /**< ecma-property */ + 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 (ECMA_PROPERTY_GET_TYPE (prop_iter_p->types + 0) == ECMA_PROPERTY_TYPE_HASHMAP) + if (ECMA_PROPERTY_GET_TYPE (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); @@ -1013,8 +1006,9 @@ ecma_assert_object_contains_the_property (const ecma_object_t *object_p, /**< ec for (int i = 0; i < ECMA_PROPERTY_PAIR_ITEM_COUNT; i++) { - if ((prop_pair_p->header.types + i) == prop_p) + if ((prop_pair_p->values + i) == prop_value_p) { + JERRY_ASSERT (ECMA_PROPERTY_GET_TYPE (prop_pair_p->header.types[i]) == type); return; } } @@ -1027,50 +1021,23 @@ ecma_assert_object_contains_the_property (const ecma_object_t *object_p, /**< ec #else /* JERRY_NDEBUG */ JERRY_UNUSED (object_p); - JERRY_UNUSED (prop_p); + JERRY_UNUSED (prop_value_p); + JERRY_UNUSED (type); #endif /* !JERRY_NDEBUG */ } /* ecma_assert_object_contains_the_property */ -/** - * Get value field of named data property - * - * @return ecma value - */ -inline ecma_value_t __attr_always_inline___ -ecma_get_named_data_property_value (const ecma_property_t *prop_p) /**< property */ -{ - JERRY_ASSERT (ECMA_PROPERTY_GET_TYPE (prop_p) == ECMA_PROPERTY_TYPE_NAMEDDATA); - - return ECMA_PROPERTY_VALUE_PTR (prop_p)->value; -} /* ecma_get_named_data_property_value */ - -/** - * Set value field of named data property - */ -inline void __attr_always_inline___ -ecma_set_named_data_property_value (ecma_property_t *prop_p, /**< property */ - ecma_value_t value) /**< value to set */ -{ - JERRY_ASSERT (ECMA_PROPERTY_GET_TYPE (prop_p) == ECMA_PROPERTY_TYPE_NAMEDDATA); - - ECMA_PROPERTY_VALUE_PTR (prop_p)->value = value; -} /* ecma_set_named_data_property_value */ - /** * Assign value to named data property * * Note: * value previously stored in the property is freed */ -void +inline void __attr_always_inline___ ecma_named_data_property_assign_value (ecma_object_t *obj_p, /**< object */ - ecma_property_t *prop_p, /**< property */ + ecma_property_value_t *prop_value_p, /**< property value reference */ ecma_value_t value) /**< value to assign */ { - JERRY_ASSERT (ECMA_PROPERTY_GET_TYPE (prop_p) == ECMA_PROPERTY_TYPE_NAMEDDATA); - ecma_assert_object_contains_the_property (obj_p, prop_p); - - ecma_property_value_t *prop_value_p = ECMA_PROPERTY_VALUE_PTR (prop_p); + ecma_assert_object_contains_the_property (obj_p, prop_value_p, ECMA_PROPERTY_TYPE_NAMEDDATA); ecma_value_assign_value (&prop_value_p->value, value); } /* ecma_named_data_property_assign_value */ @@ -1081,17 +1048,15 @@ ecma_named_data_property_assign_value (ecma_object_t *obj_p, /**< object */ * @return pointer to object - getter of the property */ ecma_object_t * -ecma_get_named_accessor_property_getter (const ecma_property_t *prop_p) /**< named accessor property */ +ecma_get_named_accessor_property_getter (const ecma_property_value_t *prop_value_p) /**< property value reference */ { - JERRY_ASSERT (ECMA_PROPERTY_GET_TYPE (prop_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, - ECMA_PROPERTY_VALUE_PTR (prop_p)->getter_setter_pair_cp); + prop_value_p->getter_setter_pair_cp); return ECMA_GET_POINTER (ecma_object_t, getter_setter_pair_p->getter_p); #else /* !JERRY_CPOINTER_32_BIT */ - return ECMA_GET_POINTER (ecma_object_t, ECMA_PROPERTY_VALUE_PTR (prop_p)->getter_setter_pair.getter_p); + return ECMA_GET_POINTER (ecma_object_t, prop_value_p->getter_setter_pair.getter_p); #endif /* JERRY_CPOINTER_32_BIT */ } /* ecma_get_named_accessor_property_getter */ @@ -1101,17 +1066,15 @@ ecma_get_named_accessor_property_getter (const ecma_property_t *prop_p) /**< nam * @return pointer to object - setter of the property */ ecma_object_t * -ecma_get_named_accessor_property_setter (const ecma_property_t *prop_p) /**< named accessor property */ +ecma_get_named_accessor_property_setter (const ecma_property_value_t *prop_value_p) /**< property value reference */ { - JERRY_ASSERT (ECMA_PROPERTY_GET_TYPE (prop_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, - ECMA_PROPERTY_VALUE_PTR (prop_p)->getter_setter_pair_cp); + prop_value_p->getter_setter_pair_cp); return ECMA_GET_POINTER (ecma_object_t, getter_setter_pair_p->setter_p); #else /* !JERRY_CPOINTER_32_BIT */ - return ECMA_GET_POINTER (ecma_object_t, ECMA_PROPERTY_VALUE_PTR (prop_p)->getter_setter_pair.setter_p); + return ECMA_GET_POINTER (ecma_object_t, prop_value_p->getter_setter_pair.setter_p); #endif /* JERRY_CPOINTER_32_BIT */ } /* ecma_get_named_accessor_property_setter */ @@ -1120,19 +1083,18 @@ ecma_get_named_accessor_property_setter (const ecma_property_t *prop_p) /**< nam */ void ecma_set_named_accessor_property_getter (ecma_object_t *object_p, /**< the property's container */ - ecma_property_t *prop_p, /**< named accessor property */ + ecma_property_value_t *prop_value_p, /**< property value reference */ ecma_object_t *getter_p) /**< getter object */ { - JERRY_ASSERT (ECMA_PROPERTY_GET_TYPE (prop_p) == ECMA_PROPERTY_TYPE_NAMEDACCESSOR); - ecma_assert_object_contains_the_property (object_p, prop_p); + 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, - ECMA_PROPERTY_VALUE_PTR (prop_p)->getter_setter_pair_cp); + prop_value_p->getter_setter_pair_cp); ECMA_SET_POINTER (getter_setter_pair_p->getter_p, getter_p); #else /* !JERRY_CPOINTER_32_BIT */ - ECMA_SET_POINTER (ECMA_PROPERTY_VALUE_PTR (prop_p)->getter_setter_pair.getter_p, getter_p); + ECMA_SET_POINTER (prop_value_p->getter_setter_pair.getter_p, getter_p); #endif /* JERRY_CPOINTER_32_BIT */ } /* ecma_set_named_accessor_property_getter */ @@ -1141,19 +1103,18 @@ ecma_set_named_accessor_property_getter (ecma_object_t *object_p, /**< the prope */ 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_property_value_t *prop_value_p, /**< property value reference */ 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_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, - ECMA_PROPERTY_VALUE_PTR (prop_p)->getter_setter_pair_cp); + 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 (ECMA_PROPERTY_VALUE_PTR (prop_p)->getter_setter_pair.setter_p, setter_p); + ECMA_SET_POINTER (prop_value_p->getter_setter_pair.setter_p, setter_p); #endif /* JERRY_CPOINTER_32_BIT */ } /* ecma_set_named_accessor_property_setter */ @@ -1164,30 +1125,30 @@ ecma_set_named_accessor_property_setter (ecma_object_t *object_p, /**< the prope * false - otherwise. */ inline bool __attr_always_inline___ -ecma_is_property_writable (ecma_property_t *prop_p) /**< property */ +ecma_is_property_writable (ecma_property_t property) /**< property */ { - JERRY_ASSERT (ECMA_PROPERTY_GET_TYPE (prop_p) == ECMA_PROPERTY_TYPE_NAMEDDATA); + JERRY_ASSERT (ECMA_PROPERTY_GET_TYPE (property) == ECMA_PROPERTY_TYPE_NAMEDDATA + || ECMA_PROPERTY_GET_TYPE (property) == ECMA_PROPERTY_TYPE_VIRTUAL); - return (prop_p->type_and_flags & ECMA_PROPERTY_FLAG_WRITABLE) != 0; + return (property & ECMA_PROPERTY_FLAG_WRITABLE) != 0; } /* ecma_is_property_writable */ /** * Set property's 'Writable' attribute value */ void -ecma_set_property_writable_attr (ecma_property_t *prop_p, /**< property */ - bool is_writable) /**< should the property - * be writable? */ +ecma_set_property_writable_attr (ecma_property_t *property_p, /**< [in,out] property */ + bool is_writable) /**< new value for writable flag */ { - JERRY_ASSERT (ECMA_PROPERTY_GET_TYPE (prop_p) == ECMA_PROPERTY_TYPE_NAMEDDATA); + JERRY_ASSERT (ECMA_PROPERTY_GET_TYPE (*property_p) == ECMA_PROPERTY_TYPE_NAMEDDATA); if (is_writable) { - prop_p->type_and_flags = (uint8_t) (prop_p->type_and_flags | ECMA_PROPERTY_FLAG_WRITABLE); + *property_p = (uint8_t) (*property_p | ECMA_PROPERTY_FLAG_WRITABLE); } else { - prop_p->type_and_flags = (uint8_t) (prop_p->type_and_flags & ~ECMA_PROPERTY_FLAG_WRITABLE); + *property_p = (uint8_t) (*property_p & ~ECMA_PROPERTY_FLAG_WRITABLE); } } /* ecma_set_property_writable_attr */ @@ -1198,32 +1159,32 @@ ecma_set_property_writable_attr (ecma_property_t *prop_p, /**< property */ * false - otherwise. */ inline bool __attr_always_inline___ -ecma_is_property_enumerable (ecma_property_t *prop_p) /**< property */ +ecma_is_property_enumerable (ecma_property_t property) /**< property */ { - JERRY_ASSERT (ECMA_PROPERTY_GET_TYPE (prop_p) == ECMA_PROPERTY_TYPE_NAMEDDATA - || ECMA_PROPERTY_GET_TYPE (prop_p) == ECMA_PROPERTY_TYPE_NAMEDACCESSOR); + JERRY_ASSERT (ECMA_PROPERTY_GET_TYPE (property) == ECMA_PROPERTY_TYPE_NAMEDDATA + || ECMA_PROPERTY_GET_TYPE (property) == ECMA_PROPERTY_TYPE_NAMEDACCESSOR + || ECMA_PROPERTY_GET_TYPE (property) == ECMA_PROPERTY_TYPE_VIRTUAL); - return (prop_p->type_and_flags & ECMA_PROPERTY_FLAG_ENUMERABLE) != 0; + return (property & ECMA_PROPERTY_FLAG_ENUMERABLE) != 0; } /* ecma_is_property_enumerable */ /** * Set property's 'Enumerable' attribute value */ void -ecma_set_property_enumerable_attr (ecma_property_t *prop_p, /**< property */ - bool is_enumerable) /**< should the property - * be enumerable? */ +ecma_set_property_enumerable_attr (ecma_property_t *property_p, /**< [in,out] property */ + bool is_enumerable) /**< new value for enumerable flag */ { - JERRY_ASSERT (ECMA_PROPERTY_GET_TYPE (prop_p) == ECMA_PROPERTY_TYPE_NAMEDDATA - || ECMA_PROPERTY_GET_TYPE (prop_p) == ECMA_PROPERTY_TYPE_NAMEDACCESSOR); + JERRY_ASSERT (ECMA_PROPERTY_GET_TYPE (*property_p) == ECMA_PROPERTY_TYPE_NAMEDDATA + || ECMA_PROPERTY_GET_TYPE (*property_p) == ECMA_PROPERTY_TYPE_NAMEDACCESSOR); if (is_enumerable) { - prop_p->type_and_flags = (uint8_t) (prop_p->type_and_flags | ECMA_PROPERTY_FLAG_ENUMERABLE); + *property_p = (uint8_t) (*property_p | ECMA_PROPERTY_FLAG_ENUMERABLE); } else { - prop_p->type_and_flags = (uint8_t) (prop_p->type_and_flags & ~ECMA_PROPERTY_FLAG_ENUMERABLE); + *property_p = (uint8_t) (*property_p & ~ECMA_PROPERTY_FLAG_ENUMERABLE); } } /* ecma_set_property_enumerable_attr */ @@ -1234,32 +1195,32 @@ ecma_set_property_enumerable_attr (ecma_property_t *prop_p, /**< property */ * false - otherwise. */ inline bool __attr_always_inline___ -ecma_is_property_configurable (ecma_property_t *prop_p) /**< property */ +ecma_is_property_configurable (ecma_property_t property) /**< property */ { - JERRY_ASSERT (ECMA_PROPERTY_GET_TYPE (prop_p) == ECMA_PROPERTY_TYPE_NAMEDDATA - || ECMA_PROPERTY_GET_TYPE (prop_p) == ECMA_PROPERTY_TYPE_NAMEDACCESSOR); + JERRY_ASSERT (ECMA_PROPERTY_GET_TYPE (property) == ECMA_PROPERTY_TYPE_NAMEDDATA + || ECMA_PROPERTY_GET_TYPE (property) == ECMA_PROPERTY_TYPE_NAMEDACCESSOR + || ECMA_PROPERTY_GET_TYPE (property) == ECMA_PROPERTY_TYPE_VIRTUAL); - return (prop_p->type_and_flags & ECMA_PROPERTY_FLAG_CONFIGURABLE) != 0; + return (property & ECMA_PROPERTY_FLAG_CONFIGURABLE) != 0; } /* ecma_is_property_configurable */ /** * Set property's 'Configurable' attribute value */ void -ecma_set_property_configurable_attr (ecma_property_t *prop_p, /**< property */ - bool is_configurable) /**< should the property - * be configurable? */ +ecma_set_property_configurable_attr (ecma_property_t *property_p, /**< [in,out] property */ + bool is_configurable) /**< new value for configurable flag */ { - JERRY_ASSERT (ECMA_PROPERTY_GET_TYPE (prop_p) == ECMA_PROPERTY_TYPE_NAMEDDATA - || ECMA_PROPERTY_GET_TYPE (prop_p) == ECMA_PROPERTY_TYPE_NAMEDACCESSOR); + JERRY_ASSERT (ECMA_PROPERTY_GET_TYPE (*property_p) == ECMA_PROPERTY_TYPE_NAMEDDATA + || ECMA_PROPERTY_GET_TYPE (*property_p) == ECMA_PROPERTY_TYPE_NAMEDACCESSOR); if (is_configurable) { - prop_p->type_and_flags = (uint8_t) (prop_p->type_and_flags | ECMA_PROPERTY_FLAG_CONFIGURABLE); + *property_p = (uint8_t) (*property_p | ECMA_PROPERTY_FLAG_CONFIGURABLE); } else { - prop_p->type_and_flags = (uint8_t) (prop_p->type_and_flags & ~ECMA_PROPERTY_FLAG_CONFIGURABLE); + *property_p = (uint8_t) (*property_p & ~ECMA_PROPERTY_FLAG_CONFIGURABLE); } } /* ecma_set_property_configurable_attr */ @@ -1269,31 +1230,31 @@ ecma_set_property_configurable_attr (ecma_property_t *prop_p, /**< property */ * @return true / false */ inline bool __attr_always_inline___ -ecma_is_property_lcached (ecma_property_t *prop_p) /**< property */ +ecma_is_property_lcached (ecma_property_t *property_p) /**< property */ { - JERRY_ASSERT (ECMA_PROPERTY_GET_TYPE (prop_p) == ECMA_PROPERTY_TYPE_NAMEDDATA - || ECMA_PROPERTY_GET_TYPE (prop_p) == ECMA_PROPERTY_TYPE_NAMEDACCESSOR); + JERRY_ASSERT (ECMA_PROPERTY_GET_TYPE (*property_p) == ECMA_PROPERTY_TYPE_NAMEDDATA + || ECMA_PROPERTY_GET_TYPE (*property_p) == ECMA_PROPERTY_TYPE_NAMEDACCESSOR); - return (prop_p->type_and_flags & ECMA_PROPERTY_FLAG_LCACHED) != 0; + return (*property_p & ECMA_PROPERTY_FLAG_LCACHED) != 0; } /* ecma_is_property_lcached */ /** * Set value of flag indicating whether the property is registered in LCache */ inline void __attr_always_inline___ -ecma_set_property_lcached (ecma_property_t *prop_p, /**< property */ - bool is_lcached) /**< contained (true) or not (false) */ +ecma_set_property_lcached (ecma_property_t *property_p, /**< property */ + bool is_lcached) /**< new value for lcached flag */ { - JERRY_ASSERT (ECMA_PROPERTY_GET_TYPE (prop_p) == ECMA_PROPERTY_TYPE_NAMEDDATA - || ECMA_PROPERTY_GET_TYPE (prop_p) == ECMA_PROPERTY_TYPE_NAMEDACCESSOR); + JERRY_ASSERT (ECMA_PROPERTY_GET_TYPE (*property_p) == ECMA_PROPERTY_TYPE_NAMEDDATA + || ECMA_PROPERTY_GET_TYPE (*property_p) == ECMA_PROPERTY_TYPE_NAMEDACCESSOR); if (is_lcached) { - prop_p->type_and_flags = (uint8_t) (prop_p->type_and_flags | ECMA_PROPERTY_FLAG_LCACHED); + *property_p = (uint8_t) (*property_p | ECMA_PROPERTY_FLAG_LCACHED); } else { - prop_p->type_and_flags = (uint8_t) (prop_p->type_and_flags & ~ECMA_PROPERTY_FLAG_LCACHED); + *property_p = (uint8_t) (*property_p & ~ECMA_PROPERTY_FLAG_LCACHED); } } /* ecma_set_property_lcached */ @@ -1349,54 +1310,6 @@ ecma_free_property_descriptor (ecma_property_descriptor_t *prop_desc_p) /**< pro *prop_desc_p = ecma_make_empty_property_descriptor (); } /* ecma_free_property_descriptor */ -/** - * Construct property descriptor from specified property - * - * @return property descriptor, corresponding to type and content of the specified property, i.e.: - * - for named data properties: { [Value], [Writable], [Enumerable], [Configurable] }; - * - for named accessor properties: { [Get] - if defined, - * [Set] - if defined, - * [Enumerable], [Configurable] - * }. - */ -ecma_property_descriptor_t -ecma_get_property_descriptor_from_property (ecma_property_t *prop_p) /**< property */ -{ - ecma_property_descriptor_t prop_desc = ecma_make_empty_property_descriptor (); - - prop_desc.is_enumerable = ecma_is_property_enumerable (prop_p); - prop_desc.is_enumerable_defined = true; - prop_desc.is_configurable = ecma_is_property_configurable (prop_p); - prop_desc.is_configurable_defined = true; - - if (ECMA_PROPERTY_GET_TYPE (prop_p) == ECMA_PROPERTY_TYPE_NAMEDDATA) - { - prop_desc.value = ecma_copy_value (ecma_get_named_data_property_value (prop_p)); - prop_desc.is_value_defined = true; - prop_desc.is_writable = ecma_is_property_writable (prop_p); - prop_desc.is_writable_defined = true; - } - else - { - JERRY_ASSERT (ECMA_PROPERTY_GET_TYPE (prop_p) == ECMA_PROPERTY_TYPE_NAMEDACCESSOR); - prop_desc.get_p = ecma_get_named_accessor_property_getter (prop_p); - prop_desc.is_get_defined = true; - if (prop_desc.get_p != NULL) - { - ecma_ref_object (prop_desc.get_p); - } - - prop_desc.set_p = ecma_get_named_accessor_property_setter (prop_p); - prop_desc.is_set_defined = true; - if (prop_desc.set_p != NULL) - { - ecma_ref_object (prop_desc.set_p); - } - } - - return prop_desc; -} /* ecma_get_property_descriptor_from_property */ - /** * Increase reference counter of Compact * Byte Code or regexp byte code. diff --git a/jerry-core/ecma/base/ecma-helpers.h b/jerry-core/ecma/base/ecma-helpers.h index 655727d71..43461540d 100644 --- a/jerry-core/ecma/base/ecma-helpers.h +++ b/jerry-core/ecma/base/ecma-helpers.h @@ -271,34 +271,30 @@ extern ecma_value_t *ecma_create_internal_property (ecma_object_t *, ecma_intern extern ecma_value_t *ecma_find_internal_property (ecma_object_t *, ecma_internal_property_id_t); extern ecma_value_t *ecma_get_internal_property (ecma_object_t *, ecma_internal_property_id_t); -extern ecma_property_t * -ecma_create_named_data_property (ecma_object_t *, ecma_string_t *, uint8_t); -extern ecma_property_t * +extern ecma_property_value_t * +ecma_create_named_data_property (ecma_object_t *, ecma_string_t *, uint8_t, ecma_property_t **); +extern ecma_property_value_t * ecma_create_named_accessor_property (ecma_object_t *, ecma_string_t *, ecma_object_t *, ecma_object_t *, uint8_t); extern ecma_property_t * ecma_find_named_property (ecma_object_t *, ecma_string_t *); -extern ecma_property_t * -ecma_get_named_property (ecma_object_t *, ecma_string_t *); -extern ecma_property_t * +extern ecma_property_value_t * ecma_get_named_data_property (ecma_object_t *, ecma_string_t *); extern void ecma_free_property (ecma_object_t *, ecma_string_t *, ecma_property_t *); -extern void ecma_delete_property (ecma_object_t *, ecma_property_t *); +extern void ecma_delete_property (ecma_object_t *, ecma_property_value_t *); -extern ecma_value_t ecma_get_named_data_property_value (const ecma_property_t *); -extern void ecma_set_named_data_property_value (ecma_property_t *, ecma_value_t); -extern void ecma_named_data_property_assign_value (ecma_object_t *, ecma_property_t *, ecma_value_t); +extern void ecma_named_data_property_assign_value (ecma_object_t *, ecma_property_value_t *, ecma_value_t); -extern ecma_object_t *ecma_get_named_accessor_property_getter (const ecma_property_t *); -extern ecma_object_t *ecma_get_named_accessor_property_setter (const ecma_property_t *); -extern void ecma_set_named_accessor_property_getter (ecma_object_t *, ecma_property_t *, ecma_object_t *); -extern void ecma_set_named_accessor_property_setter (ecma_object_t *, ecma_property_t *, ecma_object_t *); -extern bool ecma_is_property_writable (ecma_property_t *); +extern ecma_object_t *ecma_get_named_accessor_property_getter (const ecma_property_value_t *); +extern ecma_object_t *ecma_get_named_accessor_property_setter (const ecma_property_value_t *); +extern void ecma_set_named_accessor_property_getter (ecma_object_t *, ecma_property_value_t *, ecma_object_t *); +extern void ecma_set_named_accessor_property_setter (ecma_object_t *, ecma_property_value_t *, ecma_object_t *); +extern bool ecma_is_property_writable (ecma_property_t); extern void ecma_set_property_writable_attr (ecma_property_t *, bool); -extern bool ecma_is_property_enumerable (ecma_property_t *); +extern bool ecma_is_property_enumerable (ecma_property_t); extern void ecma_set_property_enumerable_attr (ecma_property_t *, bool); -extern bool ecma_is_property_configurable (ecma_property_t *); +extern bool ecma_is_property_configurable (ecma_property_t); extern void ecma_set_property_configurable_attr (ecma_property_t *, bool); extern bool ecma_is_property_lcached (ecma_property_t *); @@ -306,7 +302,6 @@ extern void ecma_set_property_lcached (ecma_property_t *, bool); extern ecma_property_descriptor_t ecma_make_empty_property_descriptor (void); extern void ecma_free_property_descriptor (ecma_property_descriptor_t *); -extern ecma_property_descriptor_t ecma_get_property_descriptor_from_property (ecma_property_t *); extern ecma_property_t *ecma_get_next_property_pair (ecma_property_pair_t *); diff --git a/jerry-core/ecma/base/ecma-lcache.c b/jerry-core/ecma/base/ecma-lcache.c index d4e38df55..0387f1516 100644 --- a/jerry-core/ecma/base/ecma-lcache.c +++ b/jerry-core/ecma/base/ecma-lcache.c @@ -89,8 +89,8 @@ ecma_lcache_insert (ecma_object_t *object_p, /**< object */ JERRY_ASSERT (object_p != NULL); JERRY_ASSERT (prop_name_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); + 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; @@ -196,8 +196,8 @@ ecma_lcache_invalidate (ecma_object_t *object_p, /**< object */ JERRY_ASSERT (object_p != NULL); JERRY_ASSERT (prop_name_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); + 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; diff --git a/jerry-core/ecma/base/ecma-property-hashmap.c b/jerry-core/ecma/base/ecma-property-hashmap.c index df53fc05a..667a70df9 100644 --- a/jerry-core/ecma/base/ecma-property-hashmap.c +++ b/jerry-core/ecma/base/ecma-property-hashmap.c @@ -88,7 +88,7 @@ ecma_property_hashmap_create (ecma_object_t *object_p) /**< object */ for (int i = 0; i < ECMA_PROPERTY_PAIR_ITEM_COUNT; i++) { - ecma_property_types_t type = ECMA_PROPERTY_GET_TYPE (prop_iter_p->types + i); + ecma_property_types_t type = ECMA_PROPERTY_GET_TYPE (prop_iter_p->types[i]); if (type == ECMA_PROPERTY_TYPE_NAMEDDATA || type == ECMA_PROPERTY_TYPE_NAMEDACCESSOR) { @@ -119,7 +119,7 @@ ecma_property_hashmap_create (ecma_object_t *object_p) /**< object */ memset (hashmap_p, 0, total_size); - hashmap_p->header.types[0].type_and_flags = ECMA_PROPERTY_TYPE_HASHMAP; + hashmap_p->header.types[0] = ECMA_PROPERTY_TYPE_HASHMAP; hashmap_p->header.next_property_cp = object_p->property_list_or_bound_object_cp; hashmap_p->max_property_count = max_property_count; hashmap_p->null_count = max_property_count - named_property_count; @@ -132,7 +132,7 @@ ecma_property_hashmap_create (ecma_object_t *object_p) /**< object */ if (max_property_count <= LIT_STRING_HASH_LIMIT) { - hashmap_p->header.types[1].type_and_flags = 0; + hashmap_p->header.types[1] = 0; } else { @@ -143,7 +143,7 @@ ecma_property_hashmap_create (ecma_object_t *object_p) /**< object */ } } - hashmap_p->header.types[1].type_and_flags = shift_counter; + hashmap_p->header.types[1] = shift_counter; prop_iter_p = ecma_get_property_list (object_p); ECMA_SET_POINTER (object_p->property_list_or_bound_object_cp, hashmap_p); @@ -154,7 +154,7 @@ ecma_property_hashmap_create (ecma_object_t *object_p) /**< object */ for (int i = 0; i < ECMA_PROPERTY_PAIR_ITEM_COUNT; i++) { - ecma_property_types_t type = ECMA_PROPERTY_GET_TYPE (prop_iter_p->types + i); + ecma_property_types_t type = ECMA_PROPERTY_GET_TYPE (prop_iter_p->types[i]); if (!(type == ECMA_PROPERTY_TYPE_NAMEDDATA || type == ECMA_PROPERTY_TYPE_NAMEDACCESSOR)) { @@ -225,7 +225,7 @@ ecma_property_hashmap_free (ecma_object_t *object_p) /**< object */ ecma_property_header_t *property_p = ecma_get_property_list (object_p); JERRY_ASSERT (property_p != NULL - && ECMA_PROPERTY_GET_TYPE (property_p->types + 0) == ECMA_PROPERTY_TYPE_HASHMAP); + && ECMA_PROPERTY_GET_TYPE (property_p->types[0]) == ECMA_PROPERTY_TYPE_HASHMAP); ecma_property_hashmap_t *hashmap_p = (ecma_property_hashmap_t *) property_p; @@ -251,7 +251,7 @@ ecma_property_hashmap_insert (ecma_object_t *object_p, /**< object */ ecma_property_hashmap_t *hashmap_p = ECMA_GET_NON_NULL_POINTER (ecma_property_hashmap_t, object_p->property_list_or_bound_object_cp); - JERRY_ASSERT (ECMA_PROPERTY_GET_TYPE (hashmap_p->header.types + 0) == ECMA_PROPERTY_TYPE_HASHMAP); + JERRY_ASSERT (ECMA_PROPERTY_GET_TYPE (hashmap_p->header.types[0]) == ECMA_PROPERTY_TYPE_HASHMAP); /* The NULLs are reduced below 1/8 of the hashmap. */ if (hashmap_p->null_count < (hashmap_p->max_property_count >> 3)) @@ -273,7 +273,7 @@ ecma_property_hashmap_insert (ecma_object_t *object_p, /**< object */ } else { - entry_index <<= hashmap_p->header.types[1].type_and_flags; + entry_index <<= hashmap_p->header.types[1]; } #ifndef JERRY_NDEBUG @@ -334,7 +334,7 @@ ecma_property_hashmap_delete (ecma_object_t *object_p, /**< object */ ecma_property_hashmap_t *hashmap_p = ECMA_GET_NON_NULL_POINTER (ecma_property_hashmap_t, object_p->property_list_or_bound_object_cp); - JERRY_ASSERT (ECMA_PROPERTY_GET_TYPE (hashmap_p->header.types + 0) == ECMA_PROPERTY_TYPE_HASHMAP); + JERRY_ASSERT (ECMA_PROPERTY_GET_TYPE (hashmap_p->header.types[0]) == ECMA_PROPERTY_TYPE_HASHMAP); uint32_t entry_index = name_p->hash; uint32_t step = ecma_property_hashmap_steps[entry_index & (ECMA_PROPERTY_HASHMAP_NUMBER_OF_STEPS - 1)]; @@ -348,7 +348,7 @@ ecma_property_hashmap_delete (ecma_object_t *object_p, /**< object */ } else { - entry_index <<= hashmap_p->header.types[1].type_and_flags; + entry_index <<= hashmap_p->header.types[1]; JERRY_ASSERT (entry_index <= mask); } @@ -458,7 +458,7 @@ ecma_property_hashmap_find (ecma_property_hashmap_t *hashmap_p, /**< hashmap */ } else { - entry_index <<= hashmap_p->header.types[1].type_and_flags; + entry_index <<= hashmap_p->header.types[1]; JERRY_ASSERT (entry_index <= mask); } diff --git a/jerry-core/ecma/builtin-objects/ecma-builtin-json.c b/jerry-core/ecma/builtin-objects/ecma-builtin-json.c index b9db484e3..5f5522e89 100644 --- a/jerry-core/ecma/builtin-objects/ecma-builtin-json.c +++ b/jerry-core/ecma/builtin-objects/ecma-builtin-json.c @@ -668,9 +668,9 @@ ecma_builtin_json_walk (ecma_object_t *reviver_p, /**< reviver function */ arguments_list[0] = ecma_make_string_value (name_p); arguments_list[1] = value_get; - /* - * The completion value can be anything including exceptions. - */ + /* + * The completion value can be anything including exceptions. + */ ret_value = ecma_op_function_call (reviver_p, ecma_make_object_value (holder_p), arguments_list, @@ -746,12 +746,13 @@ ecma_builtin_json_parse (ecma_value_t this_arg, /**< 'this' argument */ ecma_object_t *object_p = ecma_op_create_object_object_noarg (); ecma_string_t *name_p = ecma_get_magic_string (LIT_MAGIC_STRING__EMPTY); - ecma_property_t *property_p; - property_p = ecma_create_named_data_property (object_p, - name_p, - ECMA_PROPERTY_CONFIGURABLE_ENUMERABLE_WRITABLE); + ecma_property_value_t *prop_value_p; + prop_value_p = ecma_create_named_data_property (object_p, + name_p, + ECMA_PROPERTY_CONFIGURABLE_ENUMERABLE_WRITABLE, + NULL); - ecma_named_data_property_assign_value (object_p, property_p, final_result); + ecma_named_data_property_assign_value (object_p, prop_value_p, final_result); ecma_free_value (final_result); ret_value = ecma_builtin_json_walk (ecma_get_object_from_value (arg2), @@ -1445,11 +1446,15 @@ ecma_builtin_json_object (ecma_object_t *obj_p, /**< the object*/ while (ecma_collection_iterator_next (&iter)) { ecma_string_t *property_name_p = ecma_get_string_from_value (*iter.current_value_p); - ecma_property_t *property_p = ecma_op_object_get_own_property (obj_p, property_name_p); - JERRY_ASSERT (ecma_is_property_enumerable (property_p)); + ecma_property_t property = ecma_op_object_get_own_property (obj_p, + property_name_p, + NULL, + ECMA_PROPERTY_GET_NO_OPTIONS); - if (ECMA_PROPERTY_GET_TYPE (property_p) == ECMA_PROPERTY_TYPE_NAMEDDATA) + JERRY_ASSERT (ecma_is_property_enumerable (property)); + + if (ECMA_PROPERTY_GET_TYPE (property) == ECMA_PROPERTY_TYPE_NAMEDDATA) { ecma_append_to_values_collection (property_keys_p, *iter.current_value_p, true); } diff --git a/jerry-core/ecma/builtin-objects/ecma-builtin-object-prototype.c b/jerry-core/ecma/builtin-objects/ecma-builtin-object-prototype.c index fb90b26c3..7dc29acee 100644 --- a/jerry-core/ecma/builtin-objects/ecma-builtin-object-prototype.c +++ b/jerry-core/ecma/builtin-objects/ecma-builtin-object-prototype.c @@ -242,15 +242,17 @@ ecma_builtin_object_prototype_object_property_is_enumerable (ecma_value_t this_a ecma_object_t *obj_p = ecma_get_object_from_value (obj_val); /* 3. */ - ecma_property_t *property_p = ecma_op_object_get_own_property (obj_p, property_name_string_p); + ecma_property_t property = ecma_op_object_get_own_property (obj_p, + property_name_string_p, + NULL, + ECMA_PROPERTY_GET_NO_OPTIONS); /* 4. */ - if (property_p != NULL) + if (property != ECMA_PROPERTY_TYPE_NOT_FOUND) { - bool is_enumerable = ecma_is_property_enumerable (property_p); + bool is_enumerable = ecma_is_property_enumerable (property); - return_value = ecma_make_simple_value (is_enumerable ? ECMA_SIMPLE_VALUE_TRUE - : ECMA_SIMPLE_VALUE_FALSE); + return_value = ecma_make_boolean_value (is_enumerable); } else { diff --git a/jerry-core/ecma/builtin-objects/ecma-builtin-object.c b/jerry-core/ecma/builtin-objects/ecma-builtin-object.c index 3a022dea0..8a54b1d3d 100644 --- a/jerry-core/ecma/builtin-objects/ecma-builtin-object.c +++ b/jerry-core/ecma/builtin-objects/ecma-builtin-object.c @@ -202,16 +202,17 @@ ecma_builtin_object_object_seal (ecma_value_t this_arg, /**< 'this' argument */ && ecma_is_value_empty (ret_value)) { ecma_string_t *property_name_p = ecma_get_string_from_value (*iter.current_value_p); - ecma_property_t *property_p = ecma_op_object_get_own_property (obj_p, property_name_p); // 2.a - ecma_property_descriptor_t prop_desc = ecma_get_property_descriptor_from_property (property_p); + ecma_property_descriptor_t prop_desc; + + if (!ecma_op_object_get_own_property_descriptor (obj_p, property_name_p, &prop_desc)) + { + continue; + } // 2.b - if (ecma_is_property_configurable (property_p)) - { - prop_desc.is_configurable = false; - } + prop_desc.is_configurable = false; // 2.c ECMA_TRY_CATCH (define_own_prop_ret, @@ -276,23 +277,23 @@ ecma_builtin_object_object_freeze (ecma_value_t this_arg, /**< 'this' argument * && ecma_is_value_empty (ret_value)) { ecma_string_t *property_name_p = ecma_get_string_from_value (*iter.current_value_p); - ecma_property_t *property_p = ecma_op_object_get_own_property (obj_p, property_name_p); // 2.a - ecma_property_descriptor_t prop_desc = ecma_get_property_descriptor_from_property (property_p); + ecma_property_descriptor_t prop_desc; + + if (!ecma_op_object_get_own_property_descriptor (obj_p, property_name_p, &prop_desc)) + { + continue; + } // 2.b - if (ECMA_PROPERTY_GET_TYPE (property_p) == ECMA_PROPERTY_TYPE_NAMEDDATA - && ecma_is_property_writable (property_p)) + if (prop_desc.is_writable_defined && prop_desc.is_writable) { prop_desc.is_writable = false; } // 2.c - if (ecma_is_property_configurable (property_p)) - { - prop_desc.is_configurable = false; - } + prop_desc.is_configurable = false; // 2.d ECMA_TRY_CATCH (define_own_prop_ret, @@ -400,10 +401,13 @@ ecma_builtin_object_object_is_sealed (ecma_value_t this_arg, /**< 'this' argumen ecma_string_t *property_name_p = ecma_get_string_from_value (*iter.current_value_p); // 2.a - ecma_property_t *property_p = ecma_op_object_get_own_property (obj_p, property_name_p); + ecma_property_t property = ecma_op_object_get_own_property (obj_p, + property_name_p, + NULL, + ECMA_PROPERTY_GET_NO_OPTIONS); // 2.b - if (ecma_is_property_configurable (property_p)) + if (ecma_is_property_configurable (property)) { is_sealed = false; break; @@ -468,21 +472,21 @@ ecma_builtin_object_object_is_frozen (ecma_value_t this_arg, /**< 'this' argumen ecma_string_t *property_name_p = ecma_get_string_from_value (*iter.current_value_p); // 2.a - ecma_property_t *property_p = ecma_op_object_get_own_property (obj_p, property_name_p); - - JERRY_ASSERT (ECMA_PROPERTY_GET_TYPE (property_p) == ECMA_PROPERTY_TYPE_NAMEDDATA - || ECMA_PROPERTY_GET_TYPE (property_p) == ECMA_PROPERTY_TYPE_NAMEDACCESSOR); + ecma_property_t property = ecma_op_object_get_own_property (obj_p, + property_name_p, + NULL, + ECMA_PROPERTY_GET_NO_OPTIONS); // 2.b - if (ECMA_PROPERTY_GET_TYPE (property_p) == ECMA_PROPERTY_TYPE_NAMEDDATA - && ecma_is_property_writable (property_p)) + if (ECMA_PROPERTY_GET_TYPE (property) != ECMA_PROPERTY_TYPE_NAMEDACCESSOR + && ecma_is_property_writable (property)) { is_frozen = false; break; } // 2.c - if (ecma_is_property_configurable (property_p)) + if (ecma_is_property_configurable (property)) { is_frozen = false; break; @@ -598,12 +602,10 @@ ecma_builtin_object_object_get_own_property_descriptor (ecma_value_t this_arg, / ecma_string_t *name_str_p = ecma_get_string_from_value (name_str_value); // 3. - ecma_property_t *prop_p = ecma_op_object_get_own_property (obj_p, name_str_p); + ecma_property_descriptor_t prop_desc; - if (prop_p != NULL) + if (ecma_op_object_get_own_property_descriptor (obj_p, name_str_p, &prop_desc)) { - ecma_property_descriptor_t prop_desc = ecma_get_property_descriptor_from_property (prop_p); - // 4. ecma_object_t *desc_obj_p = ecma_op_from_property_descriptor (&prop_desc); diff --git a/jerry-core/ecma/builtin-objects/ecma-builtin-string-prototype.c b/jerry-core/ecma/builtin-objects/ecma-builtin-string-prototype.c index acd0b70c1..899592bb2 100644 --- a/jerry-core/ecma/builtin-objects/ecma-builtin-string-prototype.c +++ b/jerry-core/ecma/builtin-objects/ecma-builtin-string-prototype.c @@ -1517,10 +1517,10 @@ ecma_builtin_helper_split_match (ecma_value_t input_string, /**< first argument { ecma_object_t *obj_p = ecma_get_object_from_value (ret_value); ecma_string_t *magic_index_str_p = ecma_get_magic_string (LIT_MAGIC_STRING_INDEX); - ecma_property_t *index_prop_p = ecma_get_named_property (obj_p, magic_index_str_p); + ecma_property_value_t *index_prop_value_p = ecma_get_named_data_property (obj_p, magic_index_str_p); - ecma_number_t index_num = ecma_get_number_from_value (ecma_get_named_data_property_value (index_prop_p)); - ecma_value_assign_number (&ECMA_PROPERTY_VALUE_PTR (index_prop_p)->value, index_num + start_idx); + ecma_number_t index_num = ecma_get_number_from_value (index_prop_value_p->value); + ecma_value_assign_number (&index_prop_value_p->value, index_num + start_idx); ecma_deref_ecma_string (magic_index_str_p); } @@ -1578,13 +1578,15 @@ ecma_builtin_helper_split_match (ecma_value_t input_string, /**< first argument JERRY_ASSERT (ecma_is_value_true (put_comp)); ecma_string_t *magic_index_str_p = ecma_get_magic_string (LIT_MAGIC_STRING_INDEX); - ecma_property_t *index_prop_p = ecma_create_named_data_property (match_array_p, - magic_index_str_p, - ECMA_PROPERTY_FLAG_WRITABLE); + ecma_property_value_t *index_prop_value_p; + index_prop_value_p = ecma_create_named_data_property (match_array_p, + magic_index_str_p, + ECMA_PROPERTY_FLAG_WRITABLE, + NULL); ecma_deref_ecma_string (magic_index_str_p); ecma_named_data_property_assign_value (match_array_p, - index_prop_p, + index_prop_value_p, ecma_make_uint32_value (start_idx)); ret_value = match_array; @@ -1787,10 +1789,10 @@ ecma_builtin_string_prototype_object_split (ecma_value_t this_arg, /**< this arg ecma_deref_ecma_string (zero_str_p); ecma_string_t *magic_index_str_p = ecma_get_magic_string (LIT_MAGIC_STRING_INDEX); - ecma_property_t *index_prop_p = ecma_get_named_property (match_array_obj_p, magic_index_str_p); + ecma_property_value_t *index_prop_value_p = ecma_get_named_data_property (match_array_obj_p, + magic_index_str_p); - ecma_value_t index_value = ecma_get_named_data_property_value (index_prop_p); - ecma_number_t index_num = ecma_get_number_from_value (index_value); + ecma_number_t index_num = ecma_get_number_from_value (index_prop_value_p->value); JERRY_ASSERT (index_num >= 0); uint32_t end_pos = ecma_number_to_uint32 (index_num); diff --git a/jerry-core/ecma/builtin-objects/ecma-builtins.c b/jerry-core/ecma/builtin-objects/ecma-builtins.c index 7d69910f7..37c559aaa 100644 --- a/jerry-core/ecma/builtin-objects/ecma-builtins.c +++ b/jerry-core/ecma/builtin-objects/ecma-builtins.c @@ -127,11 +127,13 @@ ecma_builtin_init_object (ecma_builtin_id_t obj_builtin_id, /**< built-in ID */ { ecma_string_t *length_str_p = ecma_new_ecma_length_string (); - ecma_property_t *length_prop_p = ecma_create_named_data_property (obj_p, - length_str_p, - ECMA_PROPERTY_FLAG_WRITABLE); + ecma_property_value_t *length_prop_value_p; + length_prop_value_p = ecma_create_named_data_property (obj_p, + length_str_p, + ECMA_PROPERTY_FLAG_WRITABLE, + NULL); - ecma_set_named_data_property_value (length_prop_p, ecma_make_integer_value (0)); + length_prop_value_p->value = ecma_make_integer_value (0); ecma_deref_ecma_string (length_str_p); break; @@ -346,14 +348,14 @@ ecma_builtin_try_to_instantiate_property (ecma_object_t *object_p, /**< object * * as it is non-configurable and so can't be deleted */ - ecma_property_t *len_prop_p = ecma_create_named_data_property (object_p, - string_p, - ECMA_PROPERTY_FIXED); + ecma_property_t *len_prop_p; + ecma_property_value_t *len_prop_value_p = ecma_create_named_data_property (object_p, + string_p, + ECMA_PROPERTY_FIXED, + &len_prop_p); - ecma_set_named_data_property_value (len_prop_p, - ecma_make_integer_value (ext_obj_p->u.built_in.length)); + len_prop_value_p->value = ecma_make_integer_value (ext_obj_p->u.built_in.length); - JERRY_ASSERT (!ecma_is_property_configurable (len_prop_p)); return len_prop_p; } @@ -519,11 +521,13 @@ ecma_builtin_try_to_instantiate_property (ecma_object_t *object_p, /**< object * } } - ecma_property_t *prop_p = ecma_create_named_data_property (object_p, - string_p, - curr_property_p->attributes); + ecma_property_t *prop_p; + ecma_property_value_t *prop_value_p = ecma_create_named_data_property (object_p, + string_p, + curr_property_p->attributes, + &prop_p); - ecma_set_named_data_property_value (prop_p, value); + prop_value_p->value = value; /* Reference count of objects must be decreased. */ if (ecma_is_value_object (value)) diff --git a/jerry-core/ecma/operations/ecma-array-object.c b/jerry-core/ecma/operations/ecma-array-object.c index 8e2b8a0f1..6d1bb5136 100644 --- a/jerry-core/ecma/operations/ecma-array-object.c +++ b/jerry-core/ecma/operations/ecma-array-object.c @@ -105,11 +105,13 @@ ecma_op_create_array_object (const ecma_value_t *arguments_list_p, /**< list of ecma_string_t *length_magic_string_p = ecma_new_ecma_length_string (); - ecma_property_t *length_prop_p = ecma_create_named_data_property (obj_p, - length_magic_string_p, - ECMA_PROPERTY_FLAG_WRITABLE); + ecma_property_value_t *length_prop_value_p; + length_prop_value_p = ecma_create_named_data_property (obj_p, + length_magic_string_p, + ECMA_PROPERTY_FLAG_WRITABLE, + NULL); - ecma_set_named_data_property_value (length_prop_p, ecma_make_number_value ((ecma_number_t) length)); + length_prop_value_p->value = ecma_make_number_value ((ecma_number_t) length); ecma_deref_ecma_string (length_magic_string_p); @@ -158,11 +160,13 @@ ecma_op_array_object_define_own_property (ecma_object_t *obj_p, /**< the array o // 1. ecma_string_t *magic_string_length_p = ecma_new_ecma_length_string (); - ecma_property_t *len_prop_p = ecma_op_object_get_own_property (obj_p, magic_string_length_p); - JERRY_ASSERT (len_prop_p != NULL && ECMA_PROPERTY_GET_TYPE (len_prop_p) == ECMA_PROPERTY_TYPE_NAMEDDATA); + ecma_property_t *len_prop_p = ecma_find_named_property (obj_p, magic_string_length_p); + + JERRY_ASSERT (len_prop_p != NULL + && ECMA_PROPERTY_GET_TYPE (*len_prop_p) == ECMA_PROPERTY_TYPE_NAMEDDATA); // 2. - ecma_value_t old_len_value = ecma_get_named_data_property_value (len_prop_p); + ecma_value_t old_len_value = ECMA_PROPERTY_VALUE_PTR (len_prop_p)->value; uint32_t old_len_uint32 = ecma_get_uint32_from_value (old_len_value); @@ -231,7 +235,7 @@ ecma_op_array_object_define_own_property (ecma_object_t *obj_p, /**< the array o else { // g. - if (!ecma_is_property_writable (len_prop_p)) + if (!ecma_is_property_writable (*len_prop_p)) { ret_value = ecma_reject (is_throw); } @@ -410,7 +414,7 @@ ecma_op_array_object_define_own_property (ecma_object_t *obj_p, /**< the array o // b. if (index >= old_len_uint32 - && !ecma_is_property_writable (len_prop_p)) + && !ecma_is_property_writable (*len_prop_p)) { return ecma_reject (is_throw); } diff --git a/jerry-core/ecma/operations/ecma-exceptions.c b/jerry-core/ecma/operations/ecma-exceptions.c index 8806559ec..7356c5b1a 100644 --- a/jerry-core/ecma/operations/ecma-exceptions.c +++ b/jerry-core/ecma/operations/ecma-exceptions.c @@ -118,14 +118,16 @@ ecma_new_standard_error_with_message (ecma_standard_error_t error_type, /**< nat ecma_object_t *new_error_obj_p = ecma_new_standard_error (error_type); ecma_string_t *message_magic_string_p = ecma_get_magic_string (LIT_MAGIC_STRING_MESSAGE); - ecma_property_t *prop_p = ecma_create_named_data_property (new_error_obj_p, - message_magic_string_p, - ECMA_PROPERTY_CONFIGURABLE_WRITABLE); + + ecma_property_value_t *prop_value_p; + prop_value_p = ecma_create_named_data_property (new_error_obj_p, + message_magic_string_p, + ECMA_PROPERTY_CONFIGURABLE_WRITABLE, + NULL); + ecma_deref_ecma_string (message_magic_string_p); ecma_ref_ecma_string (message_string_p); - ecma_set_named_data_property_value (prop_p, - ecma_make_string_value (message_string_p)); - ecma_deref_ecma_string (message_magic_string_p); + prop_value_p->value = ecma_make_string_value (message_string_p); return new_error_obj_p; } /* ecma_new_standard_error_with_message */ diff --git a/jerry-core/ecma/operations/ecma-function-object.c b/jerry-core/ecma/operations/ecma-function-object.c index 7003a329a..fd16eb165 100644 --- a/jerry-core/ecma/operations/ecma-function-object.c +++ b/jerry-core/ecma/operations/ecma-function-object.c @@ -184,8 +184,7 @@ ecma_op_create_function_object (ecma_object_t *scope_p, /**< function's scope */ /* * 'length' and 'prototype' properties are instantiated lazily * - * See also: ecma_op_function_object_get_own_property - * ecma_op_function_try_lazy_instantiate_property + * See also: ecma_op_function_try_lazy_instantiate_property */ // 19. @@ -278,124 +277,69 @@ ecma_op_function_list_lazy_property_names (bool separate_enumerable, /**< true - * NULL - otherwise */ ecma_property_t * -ecma_op_function_try_lazy_instantiate_property (ecma_object_t *obj_p, /**< the function object */ +ecma_op_function_try_lazy_instantiate_property (ecma_object_t *object_p, /**< the function object */ ecma_string_t *property_name_p) /**< property name */ { - JERRY_ASSERT (!ecma_get_object_is_builtin (obj_p)); + static const char prototype_str_p[] = "prototype"; - if (ecma_string_is_length (property_name_p)) + JERRY_ASSERT (!ecma_get_object_is_builtin (object_p)); + + ecma_string_container_t container = ECMA_STRING_GET_CONTAINER (property_name_p); + + /* Check whether the property_name_p is prototype */ + if (container == ECMA_STRING_CONTAINER_MAGIC_STRING) { - /* ECMA-262 v5, 13.2, 14-15 */ - ecma_extended_object_t *ext_func_p = (ecma_extended_object_t *) obj_p; - - const ecma_compiled_code_t *bytecode_data_p; - bytecode_data_p = ECMA_GET_INTERNAL_VALUE_POINTER (const ecma_compiled_code_t, - ext_func_p->u.function.bytecode_cp); - - // 14 - uint32_t len; - if (bytecode_data_p->status_flags & CBC_CODE_FLAGS_UINT16_ARGUMENTS) + if (property_name_p->u.magic_string_id != LIT_MAGIC_STRING_PROTOTYPE) { - cbc_uint16_arguments_t *args_p = (cbc_uint16_arguments_t *) bytecode_data_p; - len = args_p->argument_end; + return NULL; } - else + } + else if (container != ECMA_STRING_CONTAINER_HEAP_UTF8_STRING + || property_name_p->u.utf8_string.size != (sizeof (prototype_str_p) - 1)) + { + return NULL; + } + else + { + if (strncmp ((char *) (property_name_p + 1), prototype_str_p, (sizeof (prototype_str_p) - 1)) != 0) { - cbc_uint8_arguments_t *args_p = (cbc_uint8_arguments_t *) bytecode_data_p; - len = args_p->argument_end; + return NULL; } - - // 15 - ecma_property_t *length_prop_p = ecma_create_named_data_property (obj_p, - property_name_p, - ECMA_PROPERTY_FIXED); - - ecma_named_data_property_assign_value (obj_p, length_prop_p, ecma_make_uint32_value (len)); - - JERRY_ASSERT (!ecma_is_property_configurable (length_prop_p)); - return length_prop_p; } - ecma_string_t *magic_string_prototype_p = ecma_get_magic_string (LIT_MAGIC_STRING_PROTOTYPE); + /* ECMA-262 v5, 13.2, 16-18 */ - bool is_prototype_property = ecma_compare_ecma_strings (magic_string_prototype_p, property_name_p); + /* 16. */ + ecma_object_t *proto_object_p = ecma_op_create_object_object_noarg (); - ecma_deref_ecma_string (magic_string_prototype_p); + /* 17. */ + ecma_string_t *magic_string_constructor_p = ecma_get_magic_string (LIT_MAGIC_STRING_CONSTRUCTOR); - if (is_prototype_property) - { - /* ECMA-262 v5, 13.2, 16-18 */ + ecma_property_value_t *constructor_prop_value_p; + constructor_prop_value_p = ecma_create_named_data_property (proto_object_p, + magic_string_constructor_p, + ECMA_PROPERTY_CONFIGURABLE_WRITABLE, + NULL); - // 16. - ecma_object_t *proto_p = ecma_op_create_object_object_noarg (); + constructor_prop_value_p->value = ecma_make_object_value (object_p); - // 17. - ecma_string_t *magic_string_constructor_p = ecma_get_magic_string (LIT_MAGIC_STRING_CONSTRUCTOR); - ecma_builtin_helper_def_prop (proto_p, - magic_string_constructor_p, - ecma_make_object_value (obj_p), - true, /* Writable */ - false, /* Enumerable */ - true, /* Configurable */ - false); /* Failure handling */ + ecma_deref_ecma_string (magic_string_constructor_p); - ecma_deref_ecma_string (magic_string_constructor_p); + /* 18. */ + ecma_property_t *prototype_prop_p; + ecma_property_value_t *prototype_prop_value_p; + prototype_prop_value_p = ecma_create_named_data_property (object_p, + property_name_p, + ECMA_PROPERTY_FLAG_WRITABLE, + &prototype_prop_p); - // 18. - ecma_property_t *prototype_prop_p = ecma_create_named_data_property (obj_p, - property_name_p, - ECMA_PROPERTY_FLAG_WRITABLE); + prototype_prop_value_p->value = ecma_make_object_value (proto_object_p); - ecma_named_data_property_assign_value (obj_p, prototype_prop_p, ecma_make_object_value (proto_p)); + ecma_deref_object (proto_object_p); - ecma_deref_object (proto_p); - - JERRY_ASSERT (!ecma_is_property_configurable (prototype_prop_p)); - return prototype_prop_p; - } - - return NULL; + return prototype_prop_p; } /* ecma_op_function_try_lazy_instantiate_property */ -/** - * Implementation-defined extension of [[GetOwnProperty]] ecma function object's operation - * - * Note: - * The [[GetOwnProperty]] is used only for lazy property instantiation, - * i.e. externally visible behaviour of [[GetOwnProperty]] is specification-defined - * - * @return pointer to a property - if it already existed - * or was lazy instantiated in context of - * current invocation, - * NULL (i.e. ecma-undefined) - otherwise. - */ -ecma_property_t * -ecma_op_function_object_get_own_property (ecma_object_t *obj_p, /**< the function object */ - ecma_string_t *property_name_p) /**< property name */ -{ - JERRY_ASSERT (ecma_get_object_type (obj_p) == ECMA_OBJECT_TYPE_FUNCTION); - - ecma_property_t *prop_p = ecma_op_general_object_get_own_property (obj_p, property_name_p); - - if (prop_p != NULL) - { - return prop_p; - } - else if (!ecma_get_object_is_builtin (obj_p)) - { - prop_p = ecma_op_function_try_lazy_instantiate_property (obj_p, property_name_p); - - /* - * Only non-configurable properties could be instantiated lazily in the function, - * as configurable properties could be deleted and it would be incorrect - * to reinstantiate them in the function in second time. - */ - JERRY_ASSERT (prop_p == NULL || !ecma_is_property_configurable (prop_p)); - } - - return prop_p; -} /* ecma_op_function_object_get_own_property */ - /** * External function object creation operation. * diff --git a/jerry-core/ecma/operations/ecma-function-object.h b/jerry-core/ecma/operations/ecma-function-object.h index 5c4205435..f1a9d00c6 100644 --- a/jerry-core/ecma/operations/ecma-function-object.h +++ b/jerry-core/ecma/operations/ecma-function-object.h @@ -47,9 +47,6 @@ extern ecma_value_t ecma_op_function_call (ecma_object_t *, ecma_value_t, const ecma_value_t *, ecma_length_t); -extern ecma_property_t * -ecma_op_function_object_get_own_property (ecma_object_t *, ecma_string_t *); - extern ecma_value_t ecma_op_function_construct (ecma_object_t *, const ecma_value_t *, ecma_length_t); diff --git a/jerry-core/ecma/operations/ecma-get-put-value.c b/jerry-core/ecma/operations/ecma-get-put-value.c index b6feee401..a5e148b65 100644 --- a/jerry-core/ecma/operations/ecma-get-put-value.c +++ b/jerry-core/ecma/operations/ecma-get-put-value.c @@ -104,24 +104,33 @@ ecma_op_get_value_object_base (ecma_value_t base, /**< base value */ && !ecma_is_lexical_environment (obj_p)); // 2. - ecma_property_t *prop_p = ecma_op_object_get_property (obj_p, property_name_p); + ecma_property_ref_t property_ref; + ecma_property_t property = ecma_op_object_get_property (obj_p, + property_name_p, + &property_ref, + ECMA_PROPERTY_GET_VALUE); - if (prop_p == NULL) + if (property == ECMA_PROPERTY_TYPE_NOT_FOUND) { // 3. ret_value = ecma_make_simple_value (ECMA_SIMPLE_VALUE_UNDEFINED); } - else if (ECMA_PROPERTY_GET_TYPE (prop_p) == ECMA_PROPERTY_TYPE_NAMEDDATA) + else if (ECMA_PROPERTY_GET_TYPE (property) == ECMA_PROPERTY_TYPE_NAMEDDATA) { // 4. - ret_value = ecma_copy_value (ecma_get_named_data_property_value (prop_p)); + ret_value = ecma_copy_value (property_ref.value_p->value); + } + else if (ECMA_PROPERTY_GET_TYPE (property) == ECMA_PROPERTY_TYPE_VIRTUAL) + { + // 4. + ret_value = property_ref.virtual_value; } else { // 5. - JERRY_ASSERT (ECMA_PROPERTY_GET_TYPE (prop_p) == ECMA_PROPERTY_TYPE_NAMEDACCESSOR); + JERRY_ASSERT (ECMA_PROPERTY_GET_TYPE (property) == ECMA_PROPERTY_TYPE_NAMEDACCESSOR); - ecma_object_t *obj_p = ecma_get_named_accessor_property_getter (prop_p); + ecma_object_t *obj_p = ecma_get_named_accessor_property_getter (property_ref.value_p); // 6. if (obj_p == NULL) diff --git a/jerry-core/ecma/operations/ecma-lex-env.c b/jerry-core/ecma/operations/ecma-lex-env.c index 8461a7873..7489dd748 100644 --- a/jerry-core/ecma/operations/ecma-lex-env.c +++ b/jerry-core/ecma/operations/ecma-lex-env.c @@ -136,7 +136,8 @@ ecma_op_create_mutable_binding (ecma_object_t *lex_env_p, /**< lexical environme ecma_create_named_data_property (lex_env_p, name_p, - prop_attributes); + prop_attributes, + NULL); } else { @@ -187,11 +188,14 @@ ecma_op_set_mutable_binding (ecma_object_t *lex_env_p, /**< lexical environment if (ecma_get_lex_env_type (lex_env_p) == ECMA_LEXICAL_ENVIRONMENT_DECLARATIVE) { - ecma_property_t *property_p = ecma_get_named_data_property (lex_env_p, name_p); + ecma_property_t *property_p = ecma_find_named_property (lex_env_p, name_p); - if (ecma_is_property_writable (property_p)) + JERRY_ASSERT (property_p != NULL + && ECMA_PROPERTY_GET_TYPE (*property_p) == ECMA_PROPERTY_TYPE_NAMEDDATA); + + if (ecma_is_property_writable (*property_p)) { - ecma_named_data_property_assign_value (lex_env_p, property_p, value); + ecma_named_data_property_assign_value (lex_env_p, ECMA_PROPERTY_VALUE_PTR (property_p), value); } else if (is_strict) { @@ -242,26 +246,9 @@ ecma_op_get_binding_value (ecma_object_t *lex_env_p, /**< lexical environment */ if (ecma_get_lex_env_type (lex_env_p) == ECMA_LEXICAL_ENVIRONMENT_DECLARATIVE) { - ecma_property_t *property_p = ecma_get_named_data_property (lex_env_p, name_p); + ecma_property_value_t *prop_value_p = ecma_get_named_data_property (lex_env_p, name_p); - ecma_value_t prop_value = ecma_get_named_data_property_value (property_p); - - /* is the binding mutable? */ - if (!ecma_is_property_writable (property_p) - && ecma_is_value_empty (prop_value)) - { - /* unitialized immutable binding */ - if (is_strict) - { - return ecma_raise_reference_error (ECMA_ERR_MSG ("")); - } - else - { - return ecma_make_simple_value (ECMA_SIMPLE_VALUE_UNDEFINED); - } - } - - return ecma_copy_value (prop_value); + return ecma_copy_value (prop_value_p->value); } else { @@ -317,15 +304,15 @@ ecma_op_delete_binding (ecma_object_t *lex_env_p, /**< lexical environment */ } else { - JERRY_ASSERT (ECMA_PROPERTY_GET_TYPE (prop_p) == ECMA_PROPERTY_TYPE_NAMEDDATA); + JERRY_ASSERT (ECMA_PROPERTY_GET_TYPE (*prop_p) == ECMA_PROPERTY_TYPE_NAMEDDATA); - if (!ecma_is_property_configurable (prop_p)) + if (!ecma_is_property_configurable (*prop_p)) { ret_val = ECMA_SIMPLE_VALUE_FALSE; } else { - ecma_delete_property (lex_env_p, prop_p); + ecma_delete_property (lex_env_p, ECMA_PROPERTY_VALUE_PTR (prop_p)); ret_val = ECMA_SIMPLE_VALUE_TRUE; } @@ -388,7 +375,8 @@ ecma_op_implicit_this_value (ecma_object_t *lex_env_p) /**< lexical environment */ void ecma_op_create_immutable_binding (ecma_object_t *lex_env_p, /**< lexical environment */ - ecma_string_t *name_p) /**< argument N */ + ecma_string_t *name_p, /**< argument N */ + ecma_value_t value) /**< argument V */ { JERRY_ASSERT (lex_env_p != NULL && ecma_is_lexical_environment (lex_env_p)); @@ -398,39 +386,14 @@ ecma_op_create_immutable_binding (ecma_object_t *lex_env_p, /**< lexical environ * Warning: * Whether immutable bindings are deletable seems not to be defined by ECMA v5. */ - ecma_property_t *prop_p = ecma_create_named_data_property (lex_env_p, - name_p, - ECMA_PROPERTY_FIXED); + ecma_property_value_t *prop_value_p = ecma_create_named_data_property (lex_env_p, + name_p, + ECMA_PROPERTY_FIXED, + NULL); - JERRY_ASSERT (ecma_is_value_undefined (ecma_get_named_data_property_value (prop_p))); - - ecma_set_named_data_property_value (prop_p, - ecma_make_simple_value (ECMA_SIMPLE_VALUE_EMPTY)); + prop_value_p->value = ecma_copy_value_if_not_object (value); } /* ecma_op_create_immutable_binding */ -/** - * InitializeImmutableBinding operation. - * - * See also: ECMA-262 v5, 10.2.1 - */ -void -ecma_op_initialize_immutable_binding (ecma_object_t *lex_env_p, /**< lexical environment */ - ecma_string_t *name_p, /**< argument N */ - ecma_value_t value) /**< argument V */ -{ - JERRY_ASSERT (lex_env_p != NULL - && ecma_is_lexical_environment (lex_env_p)); - JERRY_ASSERT (ecma_get_lex_env_type (lex_env_p) == ECMA_LEXICAL_ENVIRONMENT_DECLARATIVE); - - ecma_property_t *prop_p = ecma_get_named_data_property (lex_env_p, name_p); - - /* The binding must be unitialized immutable binding */ - JERRY_ASSERT (!ecma_is_property_writable (prop_p) - && ecma_is_value_empty (ecma_get_named_data_property_value (prop_p))); - - ecma_named_data_property_assign_value (lex_env_p, prop_p, value); -} /* ecma_op_initialize_immutable_binding */ - /** * @} * @} diff --git a/jerry-core/ecma/operations/ecma-lex-env.h b/jerry-core/ecma/operations/ecma-lex-env.h index 7f0ef1de2..7698af5c3 100644 --- a/jerry-core/ecma/operations/ecma-lex-env.h +++ b/jerry-core/ecma/operations/ecma-lex-env.h @@ -52,8 +52,7 @@ extern ecma_value_t ecma_op_delete_binding (ecma_object_t *, ecma_string_t *); extern ecma_value_t ecma_op_implicit_this_value (ecma_object_t *); /* ECMA-262 v5, Table 18. Additional methods of Declarative Environment Records */ -extern void ecma_op_create_immutable_binding (ecma_object_t *, ecma_string_t *); -extern void ecma_op_initialize_immutable_binding (ecma_object_t *, ecma_string_t *, ecma_value_t); +extern void ecma_op_create_immutable_binding (ecma_object_t *, ecma_string_t *, ecma_value_t); extern ecma_object_t *ecma_op_create_global_environment (ecma_object_t *); diff --git a/jerry-core/ecma/operations/ecma-objects-arguments.c b/jerry-core/ecma/operations/ecma-objects-arguments.c index f3feb6d8e..742fb84e3 100644 --- a/jerry-core/ecma/operations/ecma-objects-arguments.c +++ b/jerry-core/ecma/operations/ecma-objects-arguments.c @@ -233,10 +233,9 @@ ecma_op_create_arguments_object (ecma_object_t *func_obj_p, /**< callee function 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)); + ecma_op_create_immutable_binding (lex_env_p, + arguments_string_p, + ecma_make_object_value (obj_p)); } else { @@ -293,7 +292,7 @@ ecma_arguments_update_mapped_arg_value (ecma_object_t *object_p, /**< the object JERRY_ASSERT (!ECMA_IS_VALUE_ERROR (value)); - ecma_named_data_property_assign_value (object_p, property_p, value); + ecma_named_data_property_assign_value (object_p, ECMA_PROPERTY_VALUE_PTR (property_p), value); ecma_free_value (value); /* These properties cannot be cached. This is a temporary @@ -362,15 +361,13 @@ ecma_op_arguments_object_define_own_property (ecma_object_t *obj_p, /**< the obj ecma_value_t *scope_prop_p = ecma_get_internal_property (map_p, ECMA_INTERNAL_PROPERTY_SCOPE); ecma_object_t *lex_env_p = ECMA_GET_INTERNAL_VALUE_POINTER (ecma_object_t, *scope_prop_p); - ecma_property_t *mapped_prop_p = ecma_op_object_get_own_property (map_p, property_name_p); - ecma_value_t arg_name_prop_value = ecma_get_named_data_property_value (mapped_prop_p); - - ecma_string_t *arg_name_p = ecma_get_string_from_value (arg_name_prop_value); + ecma_property_value_t *arg_name_value_p = ecma_get_named_data_property (map_p, property_name_p); completion = ecma_op_set_mutable_binding (lex_env_p, - arg_name_p, + ecma_get_string_from_value (arg_name_value_p->value), property_desc_p->value, true); + JERRY_ASSERT (ecma_is_value_empty (completion)); } diff --git a/jerry-core/ecma/operations/ecma-objects-general.c b/jerry-core/ecma/operations/ecma-objects-general.c index 64ee236b9..b922edbaf 100644 --- a/jerry-core/ecma/operations/ecma-objects-general.c +++ b/jerry-core/ecma/operations/ecma-objects-general.c @@ -128,27 +128,6 @@ ecma_op_create_object_object_noarg_and_set_prototype (ecma_object_t *object_prot return obj_p; } /* ecma_op_create_object_object_noarg_and_set_prototype */ -/** - * [[GetOwnProperty]] ecma general object's operation - * - * See also: - * ECMA-262 v5, 8.6.2; ECMA-262 v5, Table 8 - * ECMA-262 v5, 8.12.2 - * - * @return pointer to a property - if it exists, - * NULL (i.e. ecma-undefined) - otherwise. - */ -ecma_property_t * -ecma_op_general_object_get_own_property (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); - - return ecma_find_named_property (obj_p, property_name_p); -} /* ecma_op_general_object_get_own_property */ - /** * [[Delete]] ecma general object's operation * @@ -169,19 +148,24 @@ ecma_op_general_object_delete (ecma_object_t *obj_p, /**< the object */ JERRY_ASSERT (property_name_p != NULL); // 1. - ecma_property_t *desc_p = ecma_op_object_get_own_property (obj_p, property_name_p); + ecma_property_ref_t property_ref; + + ecma_property_t property = ecma_op_object_get_own_property (obj_p, + property_name_p, + &property_ref, + ECMA_PROPERTY_GET_NO_OPTIONS); // 2. - if (desc_p == NULL) + if (property == ECMA_PROPERTY_TYPE_NOT_FOUND) { return ecma_make_simple_value (ECMA_SIMPLE_VALUE_TRUE); } // 3. - if (ecma_is_property_configurable (desc_p)) + if (ecma_is_property_configurable (property)) { // a. - ecma_delete_property (obj_p, desc_p); + ecma_delete_property (obj_p, property_ref.value_p); // b. return ecma_make_simple_value (ECMA_SIMPLE_VALUE_TRUE); @@ -330,9 +314,14 @@ ecma_op_general_object_define_own_property (ecma_object_t *obj_p, /**< the objec JERRY_ASSERT (property_desc_p->is_writable_defined || !property_desc_p->is_writable); // 1. - ecma_property_t *current_p = ecma_op_object_get_own_property (obj_p, property_name_p); + ecma_property_ref_t property_ref; - if (current_p == NULL) + ecma_property_t current_prop = ecma_op_object_get_own_property (obj_p, + property_name_p, + &property_ref, + ECMA_PROPERTY_GET_VALUE); + + if (current_prop == ECMA_PROPERTY_TYPE_NOT_FOUND) { // 3. if (!ecma_get_object_extensible (obj_p)) @@ -365,14 +354,15 @@ ecma_op_general_object_define_own_property (ecma_object_t *obj_p, /**< the objec prop_attributes = (uint8_t) (prop_attributes | ECMA_PROPERTY_FLAG_WRITABLE); } - ecma_property_t *new_prop_p = ecma_create_named_data_property (obj_p, - property_name_p, - prop_attributes); + ecma_property_value_t *new_prop_value_p = ecma_create_named_data_property (obj_p, + property_name_p, + prop_attributes, + NULL); JERRY_ASSERT (property_desc_p->is_value_defined || ecma_is_value_undefined (property_desc_p->value)); - ecma_named_data_property_assign_value (obj_p, new_prop_p, property_desc_p->value); + new_prop_value_p->value = ecma_copy_value_if_not_object (property_desc_p->value); } else { @@ -400,21 +390,45 @@ ecma_op_general_object_define_own_property (ecma_object_t *obj_p, /**< the objec } // 6. - ecma_property_types_t current_property_type = ECMA_PROPERTY_GET_TYPE (current_p); - const bool is_current_configurable = ecma_is_property_configurable (current_p); + ecma_property_types_t current_property_type = ECMA_PROPERTY_GET_TYPE (current_prop); + const bool is_current_configurable = ecma_is_property_configurable (current_prop); JERRY_ASSERT (current_property_type == ECMA_PROPERTY_TYPE_NAMEDDATA - || current_property_type == ECMA_PROPERTY_TYPE_NAMEDACCESSOR); + || current_property_type == ECMA_PROPERTY_TYPE_NAMEDACCESSOR + || current_property_type == ECMA_PROPERTY_TYPE_VIRTUAL); // 7. a., b. if (!is_current_configurable && (property_desc_p->is_configurable || (property_desc_p->is_enumerable_defined - && (property_desc_p->is_enumerable != ecma_is_property_enumerable (current_p))))) + && (property_desc_p->is_enumerable != ecma_is_property_enumerable (current_prop))))) { + if (current_property_type == ECMA_PROPERTY_TYPE_VIRTUAL) + { + ecma_free_value (property_ref.virtual_value); + } return ecma_reject (is_throw); } + if (current_property_type == ECMA_PROPERTY_TYPE_VIRTUAL) + { + JERRY_ASSERT (!is_current_configurable && !ecma_is_property_writable (current_prop)); + + ecma_value_t result = ecma_make_simple_value (ECMA_SIMPLE_VALUE_TRUE); + + if (property_desc_type == ECMA_PROPERTY_TYPE_NAMEDACCESSOR + || property_desc_p->is_writable + || (property_desc_p->is_value_defined + && !ecma_op_same_value (property_desc_p->value, + property_ref.virtual_value))) + { + result = ecma_reject (is_throw); + } + + ecma_free_value (property_ref.virtual_value); + return result; + } + // 8. if (property_desc_type == ECMA_PROPERTY_TYPE_GENERIC) { @@ -428,11 +442,11 @@ ecma_op_general_object_define_own_property (ecma_object_t *obj_p, /**< the objec if (property_desc_type == ECMA_PROPERTY_TYPE_NAMEDDATA) { // 10. a. i. & ii. - if (!ecma_is_property_writable (current_p) + if (!ecma_is_property_writable (current_prop) && (property_desc_p->is_writable || (property_desc_p->is_value_defined && !ecma_op_same_value (property_desc_p->value, - ecma_get_named_data_property_value (current_p))))) + property_ref.value_p->value)))) { return ecma_reject (is_throw); } @@ -443,9 +457,9 @@ ecma_op_general_object_define_own_property (ecma_object_t *obj_p, /**< the objec // a. if ((property_desc_p->is_get_defined - && property_desc_p->get_p != ecma_get_named_accessor_property_getter (current_p)) + && property_desc_p->get_p != ecma_get_named_accessor_property_getter (property_ref.value_p)) || (property_desc_p->is_set_defined - && property_desc_p->set_p != ecma_get_named_accessor_property_setter (current_p))) + && property_desc_p->set_p != ecma_get_named_accessor_property_setter (property_ref.value_p))) { // i., ii. return ecma_reject (is_throw); @@ -466,41 +480,46 @@ ecma_op_general_object_define_own_property (ecma_object_t *obj_p, /**< the objec * the fields of current_p if this code path is performance critical. */ uint8_t prop_attributes = ECMA_PROPERTY_FLAG_CONFIGURABLE; - if (ecma_is_property_enumerable (current_p)) + if (ecma_is_property_enumerable (current_prop)) { prop_attributes = (uint8_t) (prop_attributes | ECMA_PROPERTY_FLAG_ENUMERABLE); } - ecma_delete_property (obj_p, current_p); + ecma_delete_property (obj_p, property_ref.value_p); if (property_desc_type == ECMA_PROPERTY_TYPE_NAMEDACCESSOR) { // b. - current_p = ecma_create_named_accessor_property (obj_p, - property_name_p, - NULL, - NULL, - prop_attributes); + property_ref.value_p = ecma_create_named_accessor_property (obj_p, + property_name_p, + NULL, + NULL, + prop_attributes); } else { // c. - current_p = ecma_create_named_data_property (obj_p, - property_name_p, - prop_attributes); + property_ref.value_p = ecma_create_named_data_property (obj_p, + property_name_p, + prop_attributes, + NULL); } } + ecma_property_t *current_p = ecma_find_named_property (obj_p, property_name_p); + + JERRY_ASSERT (ECMA_PROPERTY_VALUE_PTR (current_p) == property_ref.value_p); + // 12. if (property_desc_type == ECMA_PROPERTY_TYPE_NAMEDDATA) { - JERRY_ASSERT (ECMA_PROPERTY_GET_TYPE (current_p) == ECMA_PROPERTY_TYPE_NAMEDDATA); + JERRY_ASSERT (ECMA_PROPERTY_GET_TYPE (*current_p) == ECMA_PROPERTY_TYPE_NAMEDDATA); if (property_desc_p->is_value_defined) { - ecma_named_data_property_assign_value (obj_p, current_p, property_desc_p->value); + ecma_named_data_property_assign_value (obj_p, property_ref.value_p, property_desc_p->value); } if (property_desc_p->is_writable_defined) @@ -510,16 +529,16 @@ ecma_op_general_object_define_own_property (ecma_object_t *obj_p, /**< the objec } else if (property_desc_type == ECMA_PROPERTY_TYPE_NAMEDACCESSOR) { - JERRY_ASSERT (ECMA_PROPERTY_GET_TYPE (current_p) == ECMA_PROPERTY_TYPE_NAMEDACCESSOR); + JERRY_ASSERT (ECMA_PROPERTY_GET_TYPE (*current_p) == ECMA_PROPERTY_TYPE_NAMEDACCESSOR); if (property_desc_p->is_get_defined) { - ecma_set_named_accessor_property_getter (obj_p, current_p, property_desc_p->get_p); + ecma_set_named_accessor_property_getter (obj_p, property_ref.value_p, property_desc_p->get_p); } if (property_desc_p->is_set_defined) { - ecma_set_named_accessor_property_setter (obj_p, current_p, property_desc_p->set_p); + ecma_set_named_accessor_property_setter (obj_p, property_ref.value_p, property_desc_p->set_p); } } diff --git a/jerry-core/ecma/operations/ecma-objects-general.h b/jerry-core/ecma/operations/ecma-objects-general.h index 6ce7c5cf6..22da877e4 100644 --- a/jerry-core/ecma/operations/ecma-objects-general.h +++ b/jerry-core/ecma/operations/ecma-objects-general.h @@ -31,7 +31,6 @@ extern ecma_object_t *ecma_op_create_object_object_noarg (void); extern ecma_value_t ecma_op_create_object_object_arg (ecma_value_t); extern ecma_object_t *ecma_op_create_object_object_noarg_and_set_prototype (ecma_object_t *); -extern ecma_property_t *ecma_op_general_object_get_own_property (ecma_object_t *, ecma_string_t *); extern ecma_value_t ecma_op_general_object_delete (ecma_object_t *, ecma_string_t *, bool); extern ecma_value_t ecma_op_general_object_default_value (ecma_object_t *, ecma_preferred_type_hint_t); extern ecma_value_t ecma_op_general_object_define_own_property (ecma_object_t *, ecma_string_t *, diff --git a/jerry-core/ecma/operations/ecma-objects.c b/jerry-core/ecma/operations/ecma-objects.c index df4dca728..7ad68bbeb 100644 --- a/jerry-core/ecma/operations/ecma-objects.c +++ b/jerry-core/ecma/operations/ecma-objects.c @@ -18,6 +18,7 @@ #include "ecma-builtins.h" #include "ecma-builtin-helpers.h" #include "ecma-exceptions.h" +#include "ecma-gc.h" #include "ecma-globals.h" #include "ecma-function-object.h" #include "ecma-lcache.h" @@ -57,76 +58,6 @@ #define JERRY_ASSERT_OBJECT_TYPE_IS_VALID(type) #endif /* !JERRY_NDEBUG */ -/** - * Long path for ecma_op_object_get_own_property - * - * @return pointer to a property - if it exists, - * NULL (i.e. ecma-undefined) - otherwise. - */ -static ecma_property_t * __attr_noinline___ -ecma_op_object_get_own_property_longpath (ecma_object_t *obj_p, /**< the object */ - ecma_string_t *property_name_p) /**< property name */ -{ - const ecma_object_type_t type = ecma_get_object_type (obj_p); - const bool is_builtin = ecma_get_object_is_builtin (obj_p); - - ecma_property_t *prop_p = NULL; - - switch (type) - { - case ECMA_OBJECT_TYPE_GENERAL: - case ECMA_OBJECT_TYPE_EXTERNAL_FUNCTION: - case ECMA_OBJECT_TYPE_ARRAY: - case ECMA_OBJECT_TYPE_BOUND_FUNCTION: - { - prop_p = ecma_op_general_object_get_own_property (obj_p, property_name_p); - - break; - } - - case ECMA_OBJECT_TYPE_FUNCTION: - { - prop_p = ecma_op_function_object_get_own_property (obj_p, property_name_p); - - break; - } - - case ECMA_OBJECT_TYPE_STRING: - { - prop_p = ecma_op_string_object_get_own_property (obj_p, property_name_p); - - break; - } - - case ECMA_OBJECT_TYPE_ARGUMENTS: - { - prop_p = ecma_op_general_object_get_own_property (obj_p, property_name_p); - - if (prop_p != NULL) - { - ecma_arguments_update_mapped_arg_value (obj_p, property_name_p, prop_p); - } - break; - } - - default: - { - JERRY_UNREACHABLE (); - break; - } - } - - if (unlikely (prop_p == NULL)) - { - if (is_builtin) - { - prop_p = ecma_builtin_try_to_instantiate_property (obj_p, property_name_p); - } - } - - return prop_p; -} /* ecma_op_object_get_own_property_longpath */ - /** * [[GetOwnProperty]] ecma object's operation * @@ -136,22 +67,123 @@ ecma_op_object_get_own_property_longpath (ecma_object_t *obj_p, /**< the object * @return pointer to a property - if it exists, * NULL (i.e. ecma-undefined) - otherwise. */ -ecma_property_t * -ecma_op_object_get_own_property (ecma_object_t *obj_p, /**< the object */ - ecma_string_t *property_name_p) /**< property name */ +ecma_property_t +ecma_op_object_get_own_property (ecma_object_t *object_p, /**< the object */ + ecma_string_t *property_name_p, /**< property name */ + ecma_property_ref_t *property_ref_p, /**< property reference */ + uint32_t options) /**< option bits */ { - JERRY_ASSERT (obj_p != NULL - && !ecma_is_lexical_environment (obj_p)); + JERRY_ASSERT (object_p != NULL + && !ecma_is_lexical_environment (object_p)); JERRY_ASSERT (property_name_p != NULL); - ecma_property_t *prop_p = ecma_lcache_lookup (obj_p, property_name_p); + ecma_object_type_t type = ecma_get_object_type (object_p); - if (likely (prop_p != NULL)) + ecma_property_t *property_p = ecma_find_named_property (object_p, property_name_p); + + if (property_p == NULL) { - return prop_p; + if (type == ECMA_OBJECT_TYPE_STRING) + { + uint32_t index; + + if (ecma_string_get_array_index (property_name_p, &index)) + { + ecma_value_t *prim_value_p = ecma_get_internal_property (object_p, + ECMA_INTERNAL_PROPERTY_ECMA_VALUE); + + ecma_string_t *prim_value_str_p = ecma_get_string_from_value (*prim_value_p); + + if (index < ecma_string_get_length (prim_value_str_p)) + { + if (options & ECMA_PROPERTY_GET_VALUE) + { + ecma_char_t char_at_idx = ecma_string_get_char_at_pos (prim_value_str_p, index); + ecma_string_t *char_str_p = ecma_new_ecma_string_from_code_unit (char_at_idx); + property_ref_p->virtual_value = ecma_make_string_value (char_str_p); + } + + return ECMA_PROPERTY_FLAG_ENUMERABLE | ECMA_PROPERTY_TYPE_VIRTUAL; + } + } + } + + if (ecma_get_object_is_builtin (object_p)) + { + property_p = ecma_builtin_try_to_instantiate_property (object_p, property_name_p); + } + else if (type == ECMA_OBJECT_TYPE_FUNCTION) + { + if (ecma_string_is_length (property_name_p)) + { + if (options & ECMA_PROPERTY_GET_VALUE) + { + /* Get length virtual property. */ + ecma_extended_object_t *ext_func_p = (ecma_extended_object_t *) object_p; + + const ecma_compiled_code_t *bytecode_data_p; + bytecode_data_p = ECMA_GET_INTERNAL_VALUE_POINTER (const ecma_compiled_code_t, + ext_func_p->u.function.bytecode_cp); + + uint32_t len; + if (bytecode_data_p->status_flags & CBC_CODE_FLAGS_UINT16_ARGUMENTS) + { + cbc_uint16_arguments_t *args_p = (cbc_uint16_arguments_t *) bytecode_data_p; + len = args_p->argument_end; + } + else + { + cbc_uint8_arguments_t *args_p = (cbc_uint8_arguments_t *) bytecode_data_p; + len = args_p->argument_end; + } + + property_ref_p->virtual_value = ecma_make_uint32_value (len); + } + + return ECMA_PROPERTY_TYPE_VIRTUAL; + } + + /* Get prototype physical property. */ + property_p = ecma_op_function_try_lazy_instantiate_property (object_p, property_name_p); + } + + if (property_p == NULL) + { + return ECMA_PROPERTY_TYPE_NOT_FOUND; + } + } + else if (type == ECMA_OBJECT_TYPE_ARGUMENTS) + { + ecma_value_t *map_prop_p = ecma_get_internal_property (object_p, ECMA_INTERNAL_PROPERTY_PARAMETERS_MAP); + ecma_object_t *map_p = ECMA_GET_INTERNAL_VALUE_POINTER (ecma_object_t, *map_prop_p); + + ecma_value_t arg_name = ecma_op_object_find_own (*map_prop_p, map_p, property_name_p); + + if (ecma_is_value_found (arg_name)) + { + ecma_value_t *scope_prop_p = ecma_get_internal_property (map_p, ECMA_INTERNAL_PROPERTY_SCOPE); + ecma_object_t *lex_env_p = ECMA_GET_INTERNAL_VALUE_POINTER (ecma_object_t, *scope_prop_p); + + JERRY_ASSERT (lex_env_p != NULL + && ecma_is_lexical_environment (lex_env_p)); + + ecma_string_t *arg_name_p = ecma_get_string_from_value (arg_name); + ecma_value_t binding_value = ecma_op_get_binding_value (lex_env_p, arg_name_p, true); + ecma_deref_ecma_string (arg_name_p); + + ecma_named_data_property_assign_value (object_p, + ECMA_PROPERTY_VALUE_PTR (property_p), + binding_value); + ecma_free_value (binding_value); + } } - return ecma_op_object_get_own_property_longpath (obj_p, property_name_p); + if (property_ref_p != NULL) + { + property_ref_p->value_p = ECMA_PROPERTY_VALUE_PTR (property_p); + } + + return *property_p; } /* ecma_op_object_get_own_property */ /** @@ -163,20 +195,25 @@ ecma_op_object_get_own_property (ecma_object_t *obj_p, /**< the object */ * @return pointer to a property - if it exists, * NULL (i.e. ecma-undefined) - otherwise. */ -ecma_property_t * +ecma_property_t ecma_op_object_get_property (ecma_object_t *object_p, /**< the object */ - ecma_string_t *property_name_p) /**< property name */ + ecma_string_t *property_name_p, /**< property name */ + ecma_property_ref_t *property_ref_p, /**< property reference */ + uint32_t options) /**< option bits */ { /* Circular reference is possible in JavaScript and testing it is complicated. */ int max_depth = 128; do { - ecma_property_t *property_p = ecma_op_object_get_own_property (object_p, property_name_p); + ecma_property_t property = ecma_op_object_get_own_property (object_p, + property_name_p, + property_ref_p, + options); - if (property_p != NULL) + if (property != ECMA_PROPERTY_TYPE_NOT_FOUND) { - return property_p; + return property; } if (--max_depth == 0) @@ -188,7 +225,7 @@ ecma_op_object_get_property (ecma_object_t *object_p, /**< the object */ } while (object_p != NULL); - return NULL; + return ECMA_PROPERTY_TYPE_NOT_FOUND; } /* ecma_op_object_get_property */ /** @@ -201,7 +238,11 @@ inline bool __attr_always_inline___ ecma_op_object_has_own_property (ecma_object_t *object_p, /**< the object */ ecma_string_t *property_name_p) /**< property name */ { - return ecma_op_object_get_own_property (object_p, property_name_p) != NULL; + ecma_property_t property = ecma_op_object_get_own_property (object_p, + property_name_p, + NULL, + ECMA_PROPERTY_GET_NO_OPTIONS); + return property != ECMA_PROPERTY_TYPE_NOT_FOUND; } /* ecma_op_object_has_own_property */ /** @@ -214,7 +255,11 @@ inline bool __attr_always_inline___ ecma_op_object_has_property (ecma_object_t *object_p, /**< the object */ ecma_string_t *property_name_p) /**< property name */ { - return ecma_op_object_get_property (object_p, property_name_p) != NULL; + ecma_property_t property = ecma_op_object_get_property (object_p, + property_name_p, + NULL, + ECMA_PROPERTY_GET_NO_OPTIONS); + return property != ECMA_PROPERTY_TYPE_NOT_FOUND; } /* ecma_op_object_has_property */ /** @@ -322,12 +367,16 @@ ecma_op_object_find_own (ecma_value_t base_value, /**< base value */ } } - if (ECMA_PROPERTY_GET_TYPE (property_p) == ECMA_PROPERTY_TYPE_NAMEDDATA) + ecma_property_value_t *prop_value_p = ECMA_PROPERTY_VALUE_PTR (property_p); + + if (ECMA_PROPERTY_GET_TYPE (*property_p) == ECMA_PROPERTY_TYPE_NAMEDDATA) { - return ecma_fast_copy_value (ecma_get_named_data_property_value (property_p)); + return ecma_fast_copy_value (prop_value_p->value); } - ecma_object_t *getter_p = ecma_get_named_accessor_property_getter (property_p); + JERRY_ASSERT (ECMA_PROPERTY_GET_TYPE (*property_p) == ECMA_PROPERTY_TYPE_NAMEDACCESSOR); + + ecma_object_t *getter_p = ecma_get_named_accessor_property_getter (prop_value_p); if (getter_p == NULL) { @@ -387,15 +436,22 @@ inline ecma_value_t __attr_always_inline___ ecma_op_object_get_own_data_prop (ecma_object_t *object_p, /**< the object */ ecma_string_t *property_name_p) /**< property name */ { + ecma_value_t result = ecma_op_object_find_own (ecma_make_object_value (object_p), + object_p, + property_name_p); + #ifndef JERRY_NDEBUG - ecma_property_t *property_p = ecma_op_object_get_own_property (object_p, property_name_p); + /* Because ecma_op_object_find_own might create a property + * this check is executed after the function return. */ + ecma_property_t *property_p = ecma_find_named_property (object_p, + property_name_p); JERRY_ASSERT (property_p != NULL - && ECMA_PROPERTY_GET_TYPE (property_p) == ECMA_PROPERTY_TYPE_NAMEDDATA - && !ecma_is_property_configurable (property_p)); + && ECMA_PROPERTY_GET_TYPE (*property_p) == ECMA_PROPERTY_TYPE_NAMEDDATA + && !ecma_is_property_configurable (*property_p)); #endif /* !JERRY_NDEBUG */ - return ecma_op_object_find (object_p, property_name_p); + return result; } /* ecma_op_object_get_own_data_prop */ /** @@ -411,14 +467,29 @@ ecma_value_t ecma_op_object_get (ecma_object_t *object_p, /**< the object */ ecma_string_t *property_name_p) /**< property name */ { - ecma_value_t value = ecma_op_object_find (object_p, property_name_p); + /* Circular reference is possible in JavaScript and testing it is complicated. */ + int max_depth = 128; - if (!ecma_is_value_found (value)) + ecma_value_t base_value = ecma_make_object_value (object_p); + do { - value = ecma_make_simple_value (ECMA_SIMPLE_VALUE_UNDEFINED); - } + ecma_value_t value = ecma_op_object_find_own (base_value, object_p, property_name_p); - return value; + if (ecma_is_value_found (value)) + { + return value; + } + + if (--max_depth == 0) + { + break; + } + + object_p = ecma_get_object_prototype (object_p); + } + while (object_p != NULL); + + return ecma_make_simple_value (ECMA_SIMPLE_VALUE_UNDEFINED); } /* ecma_op_object_get */ /** @@ -514,9 +585,9 @@ ecma_op_object_put (ecma_object_t *object_p, /**< the object */ if (property_p != NULL) { - if (ECMA_PROPERTY_GET_TYPE (property_p) == ECMA_PROPERTY_TYPE_NAMEDDATA) + if (ECMA_PROPERTY_GET_TYPE (*property_p) == ECMA_PROPERTY_TYPE_NAMEDDATA) { - if (ecma_is_property_writable (property_p)) + if (ecma_is_property_writable (*property_p)) { if (type == ECMA_OBJECT_TYPE_ARRAY && ecma_string_is_length (property_name_p)) { @@ -534,15 +605,17 @@ ecma_op_object_put (ecma_object_t *object_p, /**< the object */ /* There is no need for special casing arrays here because changing the * value of an existing property never changes the length of an array. */ - ecma_named_data_property_assign_value (object_p, property_p, value); + ecma_named_data_property_assign_value (object_p, + ECMA_PROPERTY_VALUE_PTR (property_p), + value); return ecma_make_simple_value (ECMA_SIMPLE_VALUE_TRUE); } } else { - JERRY_ASSERT (ECMA_PROPERTY_GET_TYPE (property_p) == ECMA_PROPERTY_TYPE_NAMEDACCESSOR); + JERRY_ASSERT (ECMA_PROPERTY_GET_TYPE (*property_p) == ECMA_PROPERTY_TYPE_NAMEDACCESSOR); - setter_p = ecma_get_named_accessor_property_setter (property_p); + setter_p = ecma_get_named_accessor_property_setter (ECMA_PROPERTY_VALUE_PTR (property_p)); } } else @@ -552,18 +625,23 @@ ecma_op_object_put (ecma_object_t *object_p, /**< the object */ if (proto_p != NULL) { - ecma_property_t *inherited_property_p = ecma_op_object_get_property (proto_p, property_name_p); + ecma_property_ref_t property_ref; - if (inherited_property_p != NULL) + ecma_property_t inherited_property = ecma_op_object_get_property (proto_p, + property_name_p, + &property_ref, + ECMA_PROPERTY_GET_NO_OPTIONS); + + if (inherited_property != ECMA_PROPERTY_TYPE_NOT_FOUND) { - if (ECMA_PROPERTY_GET_TYPE (inherited_property_p) == ECMA_PROPERTY_TYPE_NAMEDACCESSOR) + if (ECMA_PROPERTY_GET_TYPE (inherited_property) == ECMA_PROPERTY_TYPE_NAMEDACCESSOR) { - setter_p = ecma_get_named_accessor_property_setter (inherited_property_p); + setter_p = ecma_get_named_accessor_property_setter (property_ref.value_p); create_new_property = false; } else { - create_new_property = ecma_is_property_writable (inherited_property_p); + create_new_property = ecma_is_property_writable (inherited_property); } } } @@ -597,33 +675,34 @@ ecma_op_object_put (ecma_object_t *object_p, /**< the object */ ecma_string_t magic_string_length; ecma_init_ecma_length_string (&magic_string_length); - ecma_property_t *len_prop_p = ecma_op_object_get_own_property (object_p, &magic_string_length); + ecma_property_t *len_prop_p = ecma_find_named_property (object_p, &magic_string_length); JERRY_ASSERT (len_prop_p != NULL - && ECMA_PROPERTY_GET_TYPE (len_prop_p) == ECMA_PROPERTY_TYPE_NAMEDDATA); + && ECMA_PROPERTY_GET_TYPE (*len_prop_p) == ECMA_PROPERTY_TYPE_NAMEDDATA); - uint32_t old_len = ecma_get_uint32_from_value (ecma_get_named_data_property_value (len_prop_p)); + ecma_property_value_t *len_prop_value_p = ECMA_PROPERTY_VALUE_PTR (len_prop_p); + uint32_t old_len = ecma_get_uint32_from_value (len_prop_value_p->value); if (index < UINT32_MAX && index >= old_len) { - if (!ecma_is_property_writable (len_prop_p)) + if (!ecma_is_property_writable (*len_prop_p)) { return ecma_reject (is_throw); } - ecma_property_value_t *len_prop_value_p = ECMA_PROPERTY_VALUE_PTR (len_prop_p); ecma_value_assign_uint32 (&len_prop_value_p->value, index + 1); } } - ecma_property_t *new_prop_p; - new_prop_p = ecma_create_named_data_property (object_p, - property_name_p, - ECMA_PROPERTY_CONFIGURABLE_ENUMERABLE_WRITABLE); + ecma_property_value_t *new_prop_value_p; + new_prop_value_p = ecma_create_named_data_property (object_p, + property_name_p, + ECMA_PROPERTY_CONFIGURABLE_ENUMERABLE_WRITABLE, + NULL); - JERRY_ASSERT (ecma_is_value_undefined (ecma_get_named_data_property_value (new_prop_p))); - ecma_set_named_data_property_value (new_prop_p, ecma_copy_value_if_not_object (value)); + JERRY_ASSERT (ecma_is_value_undefined (new_prop_value_p->value)); + new_prop_value_p->value = ecma_copy_value_if_not_object (value); return ecma_make_simple_value (ECMA_SIMPLE_VALUE_TRUE); } } @@ -796,6 +875,83 @@ ecma_op_object_define_own_property (ecma_object_t *obj_p, /**< the object */ } } /* ecma_op_object_define_own_property */ +/** + * Get property descriptor from specified property + * + * depending on the property type the following fields are set: + * - for named data properties: { [Value], [Writable], [Enumerable], [Configurable] }; + * - for named accessor properties: { [Get] - if defined, + * [Set] - if defined, + * [Enumerable], [Configurable] + * }. + * + * @return true if property found + * false otherwise + */ +bool +ecma_op_object_get_own_property_descriptor (ecma_object_t *object_p, /**< the object */ + ecma_string_t *property_name_p, /**< property name */ + ecma_property_descriptor_t *prop_desc_p) /**< property descriptor */ +{ + ecma_property_ref_t property_ref; + + ecma_property_t property = ecma_op_object_get_own_property (object_p, + property_name_p, + &property_ref, + ECMA_PROPERTY_GET_VALUE); + + if (property == ECMA_PROPERTY_TYPE_NOT_FOUND) + { + return false; + } + + *prop_desc_p = ecma_make_empty_property_descriptor (); + + prop_desc_p->is_enumerable = ecma_is_property_enumerable (property); + prop_desc_p->is_enumerable_defined = true; + prop_desc_p->is_configurable = ecma_is_property_configurable (property); + prop_desc_p->is_configurable_defined = true; + + ecma_property_types_t type = ECMA_PROPERTY_GET_TYPE (property); + + if (type != ECMA_PROPERTY_TYPE_NAMEDACCESSOR) + { + if (type == ECMA_PROPERTY_TYPE_NAMEDDATA) + { + prop_desc_p->value = ecma_copy_value (property_ref.value_p->value); + } + else + { + JERRY_ASSERT (type == ECMA_PROPERTY_TYPE_VIRTUAL); + prop_desc_p->value = property_ref.virtual_value; + } + + prop_desc_p->is_value_defined = true; + prop_desc_p->is_writable = ecma_is_property_writable (property); + prop_desc_p->is_writable_defined = true; + } + else + { + prop_desc_p->get_p = ecma_get_named_accessor_property_getter (property_ref.value_p); + prop_desc_p->is_get_defined = true; + + if (prop_desc_p->get_p != NULL) + { + ecma_ref_object (prop_desc_p->get_p); + } + + prop_desc_p->set_p = ecma_get_named_accessor_property_setter (property_ref.value_p); + prop_desc_p->is_set_defined = true; + + if (prop_desc_p->set_p != NULL) + { + ecma_ref_object (prop_desc_p->set_p); + } + } + + return true; +} /* ecma_op_object_get_own_property_descriptor */ + /** * [[HasInstance]] ecma object's operation * @@ -976,7 +1132,7 @@ ecma_op_object_get_property_names (ecma_object_t *obj_p, /**< object */ ecma_property_header_t *prop_iter_p = ecma_get_property_list (prototype_chain_iter_p); if (prop_iter_p != NULL - && ECMA_PROPERTY_GET_TYPE (prop_iter_p->types + 0) == ECMA_PROPERTY_TYPE_HASHMAP) + && ECMA_PROPERTY_GET_TYPE (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); @@ -990,13 +1146,13 @@ ecma_op_object_get_property_names (ecma_object_t *obj_p, /**< object */ { ecma_property_t *property_p = prop_iter_p->types + i; - if (ECMA_PROPERTY_GET_TYPE (property_p) == ECMA_PROPERTY_TYPE_NAMEDDATA - || ECMA_PROPERTY_GET_TYPE (property_p) == ECMA_PROPERTY_TYPE_NAMEDACCESSOR) + if (ECMA_PROPERTY_GET_TYPE (*property_p) == ECMA_PROPERTY_TYPE_NAMEDDATA + || ECMA_PROPERTY_GET_TYPE (*property_p) == ECMA_PROPERTY_TYPE_NAMEDACCESSOR) { ecma_property_pair_t *prop_pair_p = (ecma_property_pair_t *) prop_iter_p; ecma_string_t *name_p = ECMA_GET_NON_NULL_POINTER (ecma_string_t, prop_pair_p->names_cp[i]); - if (!(is_enumerable_only && !ecma_is_property_enumerable (property_p))) + if (!(is_enumerable_only && !ecma_is_property_enumerable (*property_p))) { uint8_t hash = (uint8_t) name_p->hash; uint32_t bitmap_row = (uint32_t) (hash / bitmap_row_size); @@ -1031,7 +1187,7 @@ ecma_op_object_get_property_names (ecma_object_t *obj_p, /**< object */ } else { - JERRY_ASSERT (is_enumerable_only && !ecma_is_property_enumerable (property_p)); + JERRY_ASSERT (is_enumerable_only && !ecma_is_property_enumerable (*property_p)); ecma_append_to_values_collection (skipped_non_enumerable_p, ecma_make_string_value (name_p), diff --git a/jerry-core/ecma/operations/ecma-objects.h b/jerry-core/ecma/operations/ecma-objects.h index 5408e847d..c65004d9f 100644 --- a/jerry-core/ecma/operations/ecma-objects.h +++ b/jerry-core/ecma/operations/ecma-objects.h @@ -26,8 +26,10 @@ * @{ */ -extern ecma_property_t *ecma_op_object_get_own_property (ecma_object_t *, ecma_string_t *); -extern ecma_property_t *ecma_op_object_get_property (ecma_object_t *, ecma_string_t *); +extern ecma_property_t ecma_op_object_get_own_property (ecma_object_t *, ecma_string_t *, + ecma_property_ref_t *, uint32_t); +extern ecma_property_t ecma_op_object_get_property (ecma_object_t *, ecma_string_t *, + ecma_property_ref_t *, uint32_t); extern bool ecma_op_object_has_own_property (ecma_object_t *, ecma_string_t *); extern bool ecma_op_object_has_property (ecma_object_t *, ecma_string_t *); extern ecma_value_t ecma_op_object_find_own (ecma_value_t, ecma_object_t *, ecma_string_t *); @@ -39,6 +41,8 @@ extern ecma_value_t ecma_op_object_delete (ecma_object_t *, ecma_string_t *, boo extern ecma_value_t ecma_op_object_default_value (ecma_object_t *, ecma_preferred_type_hint_t); extern ecma_value_t ecma_op_object_define_own_property (ecma_object_t *, ecma_string_t *, const ecma_property_descriptor_t *, bool); +extern bool ecma_op_object_get_own_property_descriptor (ecma_object_t *, ecma_string_t *, + ecma_property_descriptor_t *); extern ecma_value_t ecma_op_object_has_instance (ecma_object_t *, ecma_value_t); extern bool ecma_op_object_is_prototype_of (ecma_object_t *, ecma_object_t *); extern ecma_collection_header_t * ecma_op_object_get_property_names (ecma_object_t *, bool, bool, bool); diff --git a/jerry-core/ecma/operations/ecma-reference.c b/jerry-core/ecma/operations/ecma-reference.c index 68db5bf7b..8af64984d 100644 --- a/jerry-core/ecma/operations/ecma-reference.c +++ b/jerry-core/ecma/operations/ecma-reference.c @@ -66,8 +66,7 @@ ecma_op_resolve_reference_base (ecma_object_t *lex_env_p, /**< starting lexical */ ecma_value_t ecma_op_resolve_reference_value (ecma_object_t *lex_env_p, /**< starting lexical environment */ - ecma_string_t *name_p, /**< identifier's name */ - bool is_strict) /**< strict mode */ + ecma_string_t *name_p) /**< identifier's name */ { JERRY_ASSERT (lex_env_p != NULL); @@ -79,23 +78,7 @@ ecma_op_resolve_reference_value (ecma_object_t *lex_env_p, /**< starting lexical if (property_p != NULL) { - ecma_value_t prop_value = ecma_get_named_data_property_value (property_p); - - /* is the binding mutable? */ - if (unlikely (!ecma_is_property_writable (property_p) - && ecma_is_value_empty (prop_value))) - { - /* unitialized mutable binding */ - if (is_strict) - { - return ecma_raise_reference_error (ECMA_ERR_MSG ("")); - } - else - { - return ecma_make_simple_value (ECMA_SIMPLE_VALUE_UNDEFINED); - } - } - return ecma_fast_copy_value (prop_value); + return ecma_fast_copy_value (ECMA_PROPERTY_VALUE_PTR (property_p)->value); } } else diff --git a/jerry-core/ecma/operations/ecma-reference.h b/jerry-core/ecma/operations/ecma-reference.h index e44ff7334..003578f64 100644 --- a/jerry-core/ecma/operations/ecma-reference.h +++ b/jerry-core/ecma/operations/ecma-reference.h @@ -27,7 +27,7 @@ */ extern ecma_object_t *ecma_op_resolve_reference_base (ecma_object_t *, ecma_string_t *); -extern ecma_value_t ecma_op_resolve_reference_value (ecma_object_t *, ecma_string_t *, bool); +extern ecma_value_t ecma_op_resolve_reference_value (ecma_object_t *, ecma_string_t *); /** * @} diff --git a/jerry-core/ecma/operations/ecma-regexp-object.c b/jerry-core/ecma/operations/ecma-regexp-object.c index c09bf1c08..735fd4846 100644 --- a/jerry-core/ecma/operations/ecma-regexp-object.c +++ b/jerry-core/ecma/operations/ecma-regexp-object.c @@ -126,90 +126,86 @@ re_parse_regexp_flags (ecma_string_t *flags_str_p, /**< Input string with flags return ret_value; } /* re_parse_regexp_flags */ +/** + * Set a data property value for a regexp object. + */ +static void +re_set_data_property (ecma_object_t *re_object_p, /**< RegExp object */ + ecma_string_t *property_name_p, /**< property name */ + uint8_t prop_attributes, /**< property attributes */ + ecma_value_t value) /**< property value */ +{ + ecma_property_ref_t property_ref; + ecma_property_t property = ecma_op_object_get_own_property (re_object_p, + property_name_p, + &property_ref, + ECMA_PROPERTY_GET_VALUE); + + if (property == ECMA_PROPERTY_TYPE_NOT_FOUND) + { + property_ref.value_p = ecma_create_named_data_property (re_object_p, + property_name_p, + prop_attributes, + NULL); + } + else + { + JERRY_ASSERT (ECMA_PROPERTY_GET_TYPE (property) == ECMA_PROPERTY_TYPE_NAMEDDATA + && !ecma_is_property_configurable (property)); + } + + ecma_named_data_property_assign_value (re_object_p, property_ref.value_p, value); +} /* re_set_data_property */ + /** * Initializes the source, global, ignoreCase, multiline, and lastIndex properties of RegExp instance. */ void -re_initialize_props (ecma_object_t *re_obj_p, /**< RegExp obejct */ +re_initialize_props (ecma_object_t *re_obj_p, /**< RegExp object */ ecma_string_t *source_p, /**< source string */ uint16_t flags) /**< flags */ { /* Set source property. ECMA-262 v5, 15.10.7.1 */ - ecma_string_t *magic_string_p = ecma_get_magic_string (LIT_MAGIC_STRING_SOURCE); - ecma_property_t *prop_p = ecma_find_named_property (re_obj_p, magic_string_p); - - if (prop_p == NULL) - { - prop_p = ecma_create_named_data_property (re_obj_p, - magic_string_p, - ECMA_PROPERTY_FIXED); - } + ecma_string_t *magic_string_p; + magic_string_p = ecma_get_magic_string (LIT_MAGIC_STRING_SOURCE); + re_set_data_property (re_obj_p, + magic_string_p, + ECMA_PROPERTY_FIXED, + ecma_make_string_value (source_p)); ecma_deref_ecma_string (magic_string_p); - JERRY_ASSERT (ECMA_PROPERTY_GET_TYPE (prop_p) == ECMA_PROPERTY_TYPE_NAMEDDATA); - ecma_named_data_property_assign_value (re_obj_p, - prop_p, - ecma_make_string_value (source_p)); /* Set global property. ECMA-262 v5, 15.10.7.2 */ magic_string_p = ecma_get_magic_string (LIT_MAGIC_STRING_GLOBAL); - prop_p = ecma_find_named_property (re_obj_p, magic_string_p); - - if (prop_p == NULL) - { - prop_p = ecma_create_named_data_property (re_obj_p, - magic_string_p, - ECMA_PROPERTY_FIXED); - } - + re_set_data_property (re_obj_p, + magic_string_p, + ECMA_PROPERTY_FIXED, + ecma_make_boolean_value (flags & RE_FLAG_GLOBAL)); ecma_deref_ecma_string (magic_string_p); - JERRY_ASSERT (ECMA_PROPERTY_GET_TYPE (prop_p) == ECMA_PROPERTY_TYPE_NAMEDDATA); - ecma_set_named_data_property_value (prop_p, ecma_make_boolean_value (flags & RE_FLAG_GLOBAL)); /* Set ignoreCase property. ECMA-262 v5, 15.10.7.3 */ magic_string_p = ecma_get_magic_string (LIT_MAGIC_STRING_IGNORECASE_UL); - prop_p = ecma_find_named_property (re_obj_p, magic_string_p); - - if (prop_p == NULL) - { - prop_p = ecma_create_named_data_property (re_obj_p, - magic_string_p, - ECMA_PROPERTY_FIXED); - } - + re_set_data_property (re_obj_p, + magic_string_p, + ECMA_PROPERTY_FIXED, + ecma_make_boolean_value (flags & RE_FLAG_IGNORE_CASE)); ecma_deref_ecma_string (magic_string_p); - JERRY_ASSERT (ECMA_PROPERTY_GET_TYPE (prop_p) == ECMA_PROPERTY_TYPE_NAMEDDATA); - ecma_set_named_data_property_value (prop_p, ecma_make_boolean_value (flags & RE_FLAG_IGNORE_CASE)); /* Set multiline property. ECMA-262 v5, 15.10.7.4 */ magic_string_p = ecma_get_magic_string (LIT_MAGIC_STRING_MULTILINE); - prop_p = ecma_find_named_property (re_obj_p, magic_string_p); - - if (prop_p == NULL) - { - prop_p = ecma_create_named_data_property (re_obj_p, - magic_string_p, - ECMA_PROPERTY_FIXED); - } - + re_set_data_property (re_obj_p, + magic_string_p, + ECMA_PROPERTY_FIXED, + ecma_make_boolean_value (flags & RE_FLAG_MULTILINE)); ecma_deref_ecma_string (magic_string_p); - JERRY_ASSERT (ECMA_PROPERTY_GET_TYPE (prop_p) == ECMA_PROPERTY_TYPE_NAMEDDATA); - ecma_set_named_data_property_value (prop_p, ecma_make_boolean_value (flags & RE_FLAG_MULTILINE)); /* Set lastIndex property. ECMA-262 v5, 15.10.7.5 */ magic_string_p = ecma_get_magic_string (LIT_MAGIC_STRING_LASTINDEX_UL); - prop_p = ecma_find_named_property (re_obj_p, magic_string_p); - - if (prop_p == NULL) - { - prop_p = ecma_create_named_data_property (re_obj_p, - magic_string_p, - ECMA_PROPERTY_FLAG_WRITABLE); - } - + re_set_data_property (re_obj_p, + magic_string_p, + ECMA_PROPERTY_FLAG_WRITABLE, + ecma_make_integer_value (0)); ecma_deref_ecma_string (magic_string_p); - - ecma_named_data_property_assign_value (re_obj_p, prop_p, ecma_make_integer_value (0)); } /* re_initialize_props */ /** @@ -1432,11 +1428,12 @@ ecma_regexp_exec_helper (ecma_value_t regexp_value, /**< RegExp object */ capture_value = ecma_make_string_value (capture_str_p); } - ecma_property_t *prop_p; - prop_p = ecma_create_named_data_property (result_array_obj_p, - index_str_p, - ECMA_PROPERTY_CONFIGURABLE_ENUMERABLE_WRITABLE); - ecma_set_named_data_property_value (prop_p, capture_value); + ecma_property_value_t *prop_value_p; + prop_value_p = ecma_create_named_data_property (result_array_obj_p, + index_str_p, + ECMA_PROPERTY_CONFIGURABLE_ENUMERABLE_WRITABLE, + NULL); + prop_value_p->value = capture_value; JERRY_ASSERT (!ecma_is_value_object (capture_value)); ecma_deref_ecma_string (index_str_p); diff --git a/jerry-core/ecma/operations/ecma-string-object.c b/jerry-core/ecma/operations/ecma-string-object.c index 87994f8fc..a24b485b4 100644 --- a/jerry-core/ecma/operations/ecma-string-object.c +++ b/jerry-core/ecma/operations/ecma-string-object.c @@ -100,115 +100,20 @@ ecma_op_create_string_object (const ecma_value_t *arguments_list_p, /**< list of // 15.5.5.1 ecma_string_t *length_magic_string_p = ecma_new_ecma_length_string (); - ecma_property_t *length_prop_p = ecma_create_named_data_property (obj_p, - length_magic_string_p, - ECMA_PROPERTY_FIXED); - - ecma_set_named_data_property_value (length_prop_p, ecma_make_number_value (length_value)); + ecma_property_value_t *length_prop_value_p = ecma_create_named_data_property (obj_p, + length_magic_string_p, + ECMA_PROPERTY_FIXED, + NULL); ecma_deref_ecma_string (length_magic_string_p); + length_prop_value_p->value = ecma_make_number_value (length_value); + return ecma_make_object_value (obj_p); } /* ecma_op_create_string_object */ -/** - * [[GetOwnProperty]] ecma String object's operation - * - * See also: - * ECMA-262 v5, 8.6.2; ECMA-262 v5, Table 8 - * ECMA-262 v5, 15.5.5.2 - * - * @return ecma value - * Returned value must be freed with ecma_free_value - */ -ecma_property_t * -ecma_op_string_object_get_own_property (ecma_object_t *obj_p, /**< a String object */ - ecma_string_t *property_name_p) /**< property name */ -{ - JERRY_ASSERT (ecma_get_object_type (obj_p) == ECMA_OBJECT_TYPE_STRING); - - // 1. - ecma_property_t *prop_p = ecma_op_general_object_get_own_property (obj_p, property_name_p); - - // 2. - if (prop_p != NULL) - { - return prop_p; - } - - // 3., 5. - uint32_t uint32_index; - ecma_string_t *new_prop_name_p; - - if (ECMA_STRING_GET_CONTAINER (property_name_p) == ECMA_STRING_CONTAINER_UINT32_IN_DESC) - { - uint32_index = property_name_p->u.uint32_number; - - new_prop_name_p = property_name_p; - ecma_ref_ecma_string (new_prop_name_p); - } - else - { - ecma_number_t index = ecma_string_to_number (property_name_p); - uint32_index = ecma_number_to_uint32 (index); - - ecma_string_t *to_str_p = ecma_new_ecma_string_from_uint32 (uint32_index); - - bool are_equal = ecma_compare_ecma_strings (to_str_p, property_name_p); - - if (!are_equal) - { - ecma_deref_ecma_string (to_str_p); - - return NULL; - } - else - { - new_prop_name_p = to_str_p; - } - } - - // 4. - ecma_value_t *prim_value_p = ecma_get_internal_property (obj_p, - ECMA_INTERNAL_PROPERTY_ECMA_VALUE); - ecma_string_t *prim_value_str_p = ecma_get_string_from_value (*prim_value_p); - - // 6. - ecma_length_t length = ecma_string_get_length (prim_value_str_p); - - ecma_property_t *new_prop_p; - - if (uint32_index >= (uint32_t) length) - { - // 7. - new_prop_p = NULL; - } - else - { - // 8. - ecma_char_t c = ecma_string_get_char_at_pos (prim_value_str_p, uint32_index); - - // 9. - ecma_string_t *new_prop_str_value_p = ecma_new_ecma_string_from_code_unit (c); - - new_prop_p = ecma_create_named_data_property (obj_p, - new_prop_name_p, - ECMA_PROPERTY_FLAG_ENUMERABLE); - - ecma_set_named_data_property_value (new_prop_p, - ecma_make_string_value (new_prop_str_value_p)); - } - - ecma_deref_ecma_string (new_prop_name_p); - - return new_prop_p; -} /* ecma_op_string_object_get_own_property */ - /** * List names of a String object's lazy instantiated properties * - * See also: - * ecma_op_string_object_get_own_property - * * @return string values collection */ void diff --git a/jerry-core/ecma/operations/ecma-string-object.h b/jerry-core/ecma/operations/ecma-string-object.h index 55c358042..1c87e4757 100644 --- a/jerry-core/ecma/operations/ecma-string-object.h +++ b/jerry-core/ecma/operations/ecma-string-object.h @@ -28,9 +28,6 @@ extern ecma_value_t ecma_op_create_string_object (const ecma_value_t *, ecma_length_t); -extern ecma_property_t * -ecma_op_string_object_get_own_property (ecma_object_t *, ecma_string_t *); - extern void ecma_op_string_list_lazy_property_names (ecma_object_t *, bool, diff --git a/jerry-core/jerry.c b/jerry-core/jerry.c index fef3de487..d5ee45af3 100644 --- a/jerry-core/jerry.c +++ b/jerry-core/jerry.c @@ -1390,16 +1390,15 @@ jerry_get_own_property_descriptor (const jerry_value_t obj_val, /**< object val return false; } - ecma_property_t *property_p = ecma_op_object_get_property (ecma_get_object_from_value (obj_val), - ecma_get_string_from_value (prop_name_val)); + ecma_property_descriptor_t prop_desc; - if (property_p == NULL) + if (!ecma_op_object_get_own_property_descriptor (ecma_get_object_from_value (obj_val), + ecma_get_string_from_value (prop_name_val), + &prop_desc)) { return false; } - ecma_property_descriptor_t prop_desc = ecma_get_property_descriptor_from_property (property_p); - prop_desc_p->is_configurable_defined = true; prop_desc_p->is_configurable = prop_desc.is_configurable; prop_desc_p->is_enumerable_defined = true; diff --git a/jerry-core/vm/opcodes.c b/jerry-core/vm/opcodes.c index 3ab83300f..2d0d99bad 100644 --- a/jerry-core/vm/opcodes.c +++ b/jerry-core/vm/opcodes.c @@ -157,9 +157,10 @@ opfunc_set_accessor (bool is_getter, /**< is getter accessor */ ecma_string_t *accessor_name_p = ecma_get_string_from_value (ecma_op_to_string (accessor_name)); ecma_property_t *property_p = ecma_find_named_property (object_p, accessor_name_p); - if (property_p != NULL && ECMA_PROPERTY_GET_TYPE (property_p) != ECMA_PROPERTY_TYPE_NAMEDACCESSOR) + if (property_p != NULL + && ECMA_PROPERTY_GET_TYPE (*property_p) != ECMA_PROPERTY_TYPE_NAMEDACCESSOR) { - ecma_delete_property (object_p, property_p); + ecma_delete_property (object_p, ECMA_PROPERTY_VALUE_PTR (property_p)); property_p = NULL; } @@ -188,7 +189,7 @@ opfunc_set_accessor (bool is_getter, /**< is getter accessor */ ecma_object_t *getter_func_p = ecma_get_object_from_value (accessor); ecma_set_named_accessor_property_getter (object_p, - property_p, + ECMA_PROPERTY_VALUE_PTR (property_p), getter_func_p); } else @@ -196,7 +197,7 @@ opfunc_set_accessor (bool is_getter, /**< is getter accessor */ ecma_object_t *setter_func_p = ecma_get_object_from_value (accessor); ecma_set_named_accessor_property_setter (object_p, - property_p, + ECMA_PROPERTY_VALUE_PTR (property_p), setter_func_p); } diff --git a/jerry-core/vm/vm.c b/jerry-core/vm/vm.c index 49a07116a..b56545e30 100644 --- a/jerry-core/vm/vm.c +++ b/jerry-core/vm/vm.c @@ -79,9 +79,9 @@ vm_op_get_value (ecma_value_t object, /**< base object */ ecma_property_t *property_p = ecma_lcache_lookup (object_p, property_name_p); if (property_p != NULL && - ECMA_PROPERTY_GET_TYPE (property_p) == ECMA_PROPERTY_TYPE_NAMEDDATA) + ECMA_PROPERTY_GET_TYPE (*property_p) == ECMA_PROPERTY_TYPE_NAMEDDATA) { - return ecma_fast_copy_value (ecma_get_named_data_property_value (property_p)); + return ecma_fast_copy_value (ECMA_PROPERTY_VALUE_PTR (property_p)->value); } /* There is no need to free the name. */ @@ -481,8 +481,7 @@ opfunc_construct (vm_frame_ctx_t *frame_ctx_p) /**< frame context */ ecma_string_t *name_p = JMEM_CP_GET_NON_NULL_POINTER (ecma_string_t, \ literal_start_p[literal_index]); \ result = ecma_op_resolve_reference_value (frame_ctx_p->lex_env_p, \ - name_p, \ - is_strict); \ + name_p); \ \ if (ECMA_IS_VALUE_ERROR (result)) \ { \ @@ -618,10 +617,7 @@ vm_init_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */ if (self_reference == literal_start_p[value_index]) { - ecma_op_create_immutable_binding (frame_ctx_p->lex_env_p, name_p); - ecma_op_initialize_immutable_binding (frame_ctx_p->lex_env_p, - name_p, - lit_value); + ecma_op_create_immutable_binding (frame_ctx_p->lex_env_p, name_p, lit_value); } else { @@ -947,20 +943,28 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */ property_p = ecma_find_named_property (object_p, prop_name_p); - if (property_p != NULL && ECMA_PROPERTY_GET_TYPE (property_p) != ECMA_PROPERTY_TYPE_NAMEDDATA) + if (property_p != NULL + && ECMA_PROPERTY_GET_TYPE (*property_p) != ECMA_PROPERTY_TYPE_NAMEDDATA) { - ecma_delete_property (object_p, property_p); + ecma_delete_property (object_p, ECMA_PROPERTY_VALUE_PTR (property_p)); property_p = NULL; } + ecma_property_value_t *prop_value_p; + if (property_p == NULL) { - property_p = ecma_create_named_data_property (object_p, - prop_name_p, - ECMA_PROPERTY_CONFIGURABLE_ENUMERABLE_WRITABLE); + prop_value_p = ecma_create_named_data_property (object_p, + prop_name_p, + ECMA_PROPERTY_CONFIGURABLE_ENUMERABLE_WRITABLE, + NULL); + } + else + { + prop_value_p = ECMA_PROPERTY_VALUE_PTR (property_p); } - ecma_named_data_property_assign_value (object_p, property_p, left_value); + ecma_named_data_property_assign_value (object_p, prop_value_p, left_value); if (!ecma_is_value_string (right_value)) { @@ -1000,7 +1004,7 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */ { ecma_object_t *array_obj_p; ecma_string_t length_str; - ecma_property_t *length_prop_p; + ecma_property_value_t *length_prop_value_p; uint32_t length_num; uint32_t values_length = *byte_code_p++; @@ -1008,11 +1012,9 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */ array_obj_p = ecma_get_object_from_value (stack_top_p[-1]); ecma_init_ecma_length_string (&length_str); - length_prop_p = ecma_get_named_property (array_obj_p, &length_str); + length_prop_value_p = ecma_get_named_data_property (array_obj_p, &length_str); - JERRY_ASSERT (length_prop_p != NULL); - - left_value = ecma_get_named_data_property_value (length_prop_p); + left_value = length_prop_value_p->value; length_num = ecma_get_uint32_from_value (left_value); for (uint32_t i = 0; i < values_length; i++) @@ -1021,14 +1023,14 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */ { ecma_string_t *index_str_p = ecma_new_ecma_string_from_uint32 (length_num); - ecma_property_t *prop_p; - prop_p = ecma_create_named_data_property (array_obj_p, - index_str_p, - ECMA_PROPERTY_CONFIGURABLE_ENUMERABLE_WRITABLE); + ecma_property_value_t *prop_value_p; + prop_value_p = ecma_create_named_data_property (array_obj_p, + index_str_p, + ECMA_PROPERTY_CONFIGURABLE_ENUMERABLE_WRITABLE, + NULL); - JERRY_ASSERT (ecma_is_value_undefined (ecma_get_named_data_property_value (prop_p))); - - ecma_set_named_data_property_value (prop_p, stack_top_p[i]); + JERRY_ASSERT (ecma_is_value_undefined (prop_value_p->value)); + prop_value_p->value = stack_top_p[i]; /* The reference is moved so no need to free stack_top_p[i] except for objects. */ if (ecma_is_value_object (stack_top_p[i])) @@ -1042,8 +1044,7 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */ length_num++; } - ecma_value_assign_uint32 (&ECMA_PROPERTY_VALUE_PTR (length_prop_p)->value, - length_num); + ecma_value_assign_uint32 (&length_prop_value_p->value, length_num); continue; } case VM_OC_PUSH_UNDEFINED_BASE: