Skip to content

Commit fabb668

Browse files
committed
Improve arguments object
- Enhancement: Arguments object properties are now lazy instantiated - Bugfix: Mapped arguments object instantiated properties cannot be lcached - Bugfix: Mapped arguments should be constructed even if 0 formal parameters or arguments are provided - Update: remove 'caller' property of unmapped arguments object JerryScript-DCO-1.0-Signed-off-by: Robert Fancsik [email protected]
1 parent 9d586fe commit fabb668

File tree

14 files changed

+745
-484
lines changed

14 files changed

+745
-484
lines changed

jerry-core/ecma/base/ecma-gc.c

Lines changed: 65 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -148,6 +148,36 @@ ecma_deref_object (ecma_object_t *object_p) /**< object */
148148
object_p->type_flags_refs = (uint16_t) (object_p->type_flags_refs - ECMA_OBJECT_REF_ONE);
149149
} /* ecma_deref_object */
150150

151+
/**
152+
* Mark objects referenced by arguments object
153+
*/
154+
static void
155+
ecma_gc_mark_arguments_object (ecma_extended_object_t *ext_object_p) /**< arguments object */
156+
{
157+
JERRY_ASSERT (ecma_get_object_type ((ecma_object_t *) ext_object_p) == ECMA_OBJECT_TYPE_PSEUDO_ARRAY);
158+
159+
ecma_unmapped_arguments_t *arguments_p = (ecma_unmapped_arguments_t *) ext_object_p;
160+
ecma_value_t *argv_p = (ecma_value_t *) (arguments_p + 1);
161+
162+
if (ext_object_p->u.pseudo_array.extra_info & ECMA_ARGUMENTS_OBJECT_MAPPED)
163+
{
164+
ecma_mapped_arguments_t *mapped_arguments_p = (ecma_mapped_arguments_t *) ext_object_p;
165+
argv_p = (ecma_value_t *) (mapped_arguments_p + 1);
166+
167+
ecma_gc_set_object_visited (ECMA_GET_INTERNAL_VALUE_POINTER (ecma_object_t, mapped_arguments_p->lex_env));
168+
}
169+
170+
uint32_t arguments_number = arguments_p->header.u.pseudo_array.u2.arguments_number;
171+
172+
for (uint32_t i = 0; i < arguments_number; i++)
173+
{
174+
if (ecma_is_value_object (argv_p[i]))
175+
{
176+
ecma_gc_set_object_visited (ecma_get_object_from_value (argv_p[i]));
177+
}
178+
}
179+
} /* ecma_gc_mark_arguments_object */
180+
151181
/**
152182
* Mark referenced object from property
153183
*/
@@ -695,10 +725,7 @@ ecma_gc_mark (ecma_object_t *object_p) /**< object to mark from */
695725
{
696726
JERRY_ASSERT (ext_object_p->u.pseudo_array.type == ECMA_PSEUDO_ARRAY_ARGUMENTS);
697727

698-
ecma_object_t *lex_env_p = ECMA_GET_INTERNAL_VALUE_POINTER (ecma_object_t,
699-
ext_object_p->u.pseudo_array.u2.lex_env_cp);
700-
701-
ecma_gc_set_object_visited (lex_env_p);
728+
ecma_gc_mark_arguments_object (ext_object_p);
702729
break;
703730
}
704731
}
@@ -880,6 +907,39 @@ ecma_gc_free_native_pointer (ecma_property_t *property_p) /**< property */
880907
}
881908
} /* ecma_gc_free_native_pointer */
882909

910+
/**
911+
* Free specified arguments object.
912+
*/
913+
static size_t
914+
ecma_free_arguments_object (ecma_extended_object_t *ext_object_p) /**< arguments object */
915+
{
916+
JERRY_ASSERT (ecma_get_object_type ((ecma_object_t *) ext_object_p) == ECMA_OBJECT_TYPE_PSEUDO_ARRAY);
917+
918+
size_t object_size = sizeof (ecma_unmapped_arguments_t);
919+
920+
if (ext_object_p->u.pseudo_array.extra_info & ECMA_ARGUMENTS_OBJECT_MAPPED)
921+
{
922+
ecma_mapped_arguments_t *mapped_arguments_p = (ecma_mapped_arguments_t *) ext_object_p;
923+
object_size = sizeof (ecma_mapped_arguments_t);
924+
925+
ecma_compiled_code_t *byte_code_p = ECMA_GET_INTERNAL_VALUE_POINTER (ecma_compiled_code_t,
926+
mapped_arguments_p->byte_code);
927+
928+
ecma_bytecode_deref (byte_code_p);
929+
}
930+
931+
ecma_value_t *argv_p = (ecma_value_t *) (((uint8_t *) ext_object_p) + object_size);
932+
ecma_unmapped_arguments_t *arguments_p = (ecma_unmapped_arguments_t *) ext_object_p;
933+
uint32_t arguments_number = arguments_p->header.u.pseudo_array.u2.arguments_number;
934+
935+
for (uint32_t i = 0; i < arguments_number; i++)
936+
{
937+
ecma_free_value_if_not_object (argv_p[i]);
938+
}
939+
940+
return object_size + (arguments_number * sizeof (ecma_value_t));
941+
} /* ecma_free_arguments_object */
942+
883943
/**
884944
* Free specified fast access mode array object.
885945
*/
@@ -1372,22 +1432,7 @@ ecma_gc_free_object (ecma_object_t *object_p) /**< object to free */
13721432
{
13731433
case ECMA_PSEUDO_ARRAY_ARGUMENTS:
13741434
{
1375-
JERRY_ASSERT (ext_object_p->u.pseudo_array.type == ECMA_PSEUDO_ARRAY_ARGUMENTS);
1376-
1377-
uint32_t formal_params_number = ext_object_p->u.pseudo_array.u1.length;
1378-
ecma_value_t *arg_literal_p = (ecma_value_t *) (ext_object_p + 1);
1379-
1380-
for (uint32_t i = 0; i < formal_params_number; i++)
1381-
{
1382-
if (arg_literal_p[i] != ECMA_VALUE_EMPTY)
1383-
{
1384-
ecma_string_t *name_p = ecma_get_string_from_value (arg_literal_p[i]);
1385-
ecma_deref_ecma_string (name_p);
1386-
}
1387-
}
1388-
1389-
size_t formal_params_size = formal_params_number * sizeof (ecma_value_t);
1390-
ext_object_size += formal_params_size;
1435+
ext_object_size = ecma_free_arguments_object (ext_object_p);
13911436
break;
13921437
}
13931438
#if ENABLED (JERRY_BUILTIN_TYPEDARRAY)

jerry-core/ecma/base/ecma-globals.h

Lines changed: 38 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -211,6 +211,7 @@ enum
211211
* or function call argument list */
212212
ECMA_VALUE_SYNC_ITERATOR = ECMA_MAKE_VALUE (12), /**< option for ecma_op_get_iterator: sync iterator is requested */
213213
ECMA_VALUE_ASYNC_ITERATOR = ECMA_MAKE_VALUE (13), /**< option for ecma_op_get_iterator: async iterator is requested */
214+
ECMA_VALUE_LAZY_INITIALIZED = ECMA_MAKE_VALUE (14), /**< represents initialized mapped arguments formal parameter */
214215
};
215216

216217
#if !ENABLED (JERRY_NUMBER_TYPE_FLOAT64)
@@ -644,7 +645,6 @@ typedef enum
644645
ECMA_PROPERTY_GET_NO_OPTIONS = 0, /**< no option flags for ecma_op_object_get_property */
645646
ECMA_PROPERTY_GET_VALUE = 1u << 0, /**< fill virtual_value field for virtual properties */
646647
ECMA_PROPERTY_GET_EXT_REFERENCE = 1u << 1, /**< get extended reference to the property */
647-
ECMA_PROPERTY_GET_HAS_OWN_PROP = 1u << 2, /**< internal [[HasOwnProperty]] method */
648648
} ecma_property_get_option_bits_t;
649649

650650
/**
@@ -933,13 +933,13 @@ typedef struct
933933
* [[IterationKind]] property for %Iterator% */
934934
union
935935
{
936-
uint16_t length; /**< for arguments: length of names */
936+
uint16_t formal_params_number; /**< for arguments: formal parameters number */
937937
uint16_t class_id; /**< for typedarray: the specific class name id */
938938
uint16_t iterator_index; /**< for %Iterator%: [[%Iterator%NextIndex]] property */
939939
} u1;
940940
union
941941
{
942-
ecma_value_t lex_env_cp; /**< for arguments: lexical environment */
942+
uint32_t arguments_number; /**< for arguments: arguments number */
943943
ecma_value_t arraybuffer; /**< for typedarray: internal arraybuffer */
944944
ecma_value_t iterated_value; /**< for %Iterator%: [[IteratedObject]] property */
945945
ecma_value_t spread_value; /**< for spread object: spreaded element */
@@ -2148,6 +2148,41 @@ typedef struct
21482148
uint32_t lazy_string_named_props; /**< number of lazy instantiated properties */
21492149
} ecma_property_counter_t;
21502150

2151+
/**
2152+
* Arguments object related status flags.
2153+
*/
2154+
typedef enum
2155+
{
2156+
ECMA_ARGUMENTS_OBJECT_NO_FLAGS = 0, /* unmapped arguments object */
2157+
ECMA_ARGUMENTS_OBJECT_MAPPED = (1 << 0), /* mapped arguments object */
2158+
ECMA_ARGUMENTS_OBJECT_CALLEE_INITIALIZED = (1 << 1), /* 'callee' property has been lazy initialized */
2159+
ECMA_ARGUMENTS_OBJECT_CALLER_INITIALIZED = (1 << 2), /* 'caller' property has been lazy initialized */
2160+
ECMA_ARGUMENTS_OBJECT_LENGTH_INITIALIZED = (1 << 3), /* 'length' property has been lazy initialized */
2161+
ECMA_ARGUMENTS_OBJECT_ITERATOR_INITIALIZED = (1 << 4), /* 'Symbol.iterator' property has been lazy initialized */
2162+
} ecma_arguments_object_flags_t;
2163+
2164+
/**
2165+
* Definition of unmapped arguments object
2166+
*/
2167+
typedef struct
2168+
{
2169+
ecma_extended_object_t header; /**< object header */
2170+
ecma_value_t callee; /**< 'callee' property */
2171+
} ecma_unmapped_arguments_t;
2172+
2173+
/**
2174+
* Definition of mapped arguments object.
2175+
*
2176+
* Note: this structure must be kept in sync with `ecma_unmapped_arguments_t`
2177+
*/
2178+
typedef struct
2179+
{
2180+
ecma_extended_object_t header; /**< object header */
2181+
ecma_value_t callee; /**< 'callee' property */
2182+
ecma_value_t byte_code; /**< callee's compiled code */
2183+
ecma_value_t lex_env; /**< environment reference */
2184+
} ecma_mapped_arguments_t;
2185+
21512186
/**
21522187
* @}
21532188
* @}

jerry-core/ecma/base/ecma-helpers.c

Lines changed: 17 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1497,23 +1497,6 @@ ecma_bytecode_deref (ecma_compiled_code_t *bytecode_p) /**< byte code pointer */
14971497
((size_t) bytecode_p->size) << JMEM_ALIGNMENT_LOG);
14981498
} /* ecma_bytecode_deref */
14991499

1500-
#if ENABLED (JERRY_ESNEXT)
1501-
/**
1502-
* Get the tagged template collection of the compiled code
1503-
*
1504-
* @return pointer to the tagged template collection
1505-
*/
1506-
ecma_collection_t *
1507-
ecma_compiled_code_get_tagged_template_collection (const ecma_compiled_code_t *bytecode_header_p) /**< compiled code */
1508-
{
1509-
JERRY_ASSERT (bytecode_header_p != NULL);
1510-
JERRY_ASSERT (bytecode_header_p->status_flags & CBC_CODE_FLAGS_HAS_TAGGED_LITERALS);
1511-
1512-
ecma_value_t *base_p = ecma_compiled_code_resolve_function_name (bytecode_header_p);
1513-
1514-
return ECMA_GET_INTERNAL_VALUE_POINTER (ecma_collection_t, base_p[-1]);
1515-
} /* ecma_compiled_code_get_tagged_template_collection */
1516-
15171500
/**
15181501
* Get the number of formal parameters of the compiled code
15191502
*
@@ -1551,6 +1534,23 @@ ecma_compiled_code_resolve_arguments_start (const ecma_compiled_code_t *bytecode
15511534
return ((ecma_value_t *) byte_p) - ecma_compiled_code_get_formal_params (bytecode_header_p);
15521535
} /* ecma_compiled_code_resolve_arguments_start */
15531536

1537+
#if ENABLED (JERRY_ESNEXT)
1538+
/**
1539+
* Get the tagged template collection of the compiled code
1540+
*
1541+
* @return pointer to the tagged template collection
1542+
*/
1543+
ecma_collection_t *
1544+
ecma_compiled_code_get_tagged_template_collection (const ecma_compiled_code_t *bytecode_header_p) /**< compiled code */
1545+
{
1546+
JERRY_ASSERT (bytecode_header_p != NULL);
1547+
JERRY_ASSERT (bytecode_header_p->status_flags & CBC_CODE_FLAGS_HAS_TAGGED_LITERALS);
1548+
1549+
ecma_value_t *base_p = ecma_compiled_code_resolve_function_name (bytecode_header_p);
1550+
1551+
return ECMA_GET_INTERNAL_VALUE_POINTER (ecma_collection_t, base_p[-1]);
1552+
} /* ecma_compiled_code_get_tagged_template_collection */
1553+
15541554
/**
15551555
* Resolve the position of the function name of the compiled code
15561556
*

jerry-core/ecma/base/ecma-helpers.h

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -529,12 +529,10 @@ void ecma_raise_error_from_error_reference (ecma_value_t value);
529529

530530
void ecma_bytecode_ref (ecma_compiled_code_t *bytecode_p);
531531
void ecma_bytecode_deref (ecma_compiled_code_t *bytecode_p);
532-
#if ENABLED (JERRY_ESNEXT)
533-
ecma_collection_t *ecma_compiled_code_get_tagged_template_collection (const ecma_compiled_code_t *bytecode_header_p);
534-
#endif /* ENABLED (JERRY_ESNEXT) */
535-
#if ENABLED (JERRY_ESNEXT)
536532
uint32_t ecma_compiled_code_get_formal_params (const ecma_compiled_code_t *bytecode_p);
537533
ecma_value_t *ecma_compiled_code_resolve_arguments_start (const ecma_compiled_code_t *bytecode_header_p);
534+
#if ENABLED (JERRY_ESNEXT)
535+
ecma_collection_t *ecma_compiled_code_get_tagged_template_collection (const ecma_compiled_code_t *bytecode_header_p);
538536
ecma_value_t *ecma_compiled_code_resolve_function_name (const ecma_compiled_code_t *bytecode_header_p);
539537
#endif /* ENABLED (JERRY_ESNEXT) */
540538
ecma_value_t ecma_get_resource_name (const ecma_compiled_code_t *bytecode_p);

0 commit comments

Comments
 (0)