Improve arguments object (#4145)
- 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 frobert@inf.u-szeged.hu
This commit is contained in:
@@ -149,6 +149,36 @@ ecma_deref_object (ecma_object_t *object_p) /**< object */
|
||||
object_p->type_flags_refs = (uint16_t) (object_p->type_flags_refs - ECMA_OBJECT_REF_ONE);
|
||||
} /* ecma_deref_object */
|
||||
|
||||
/**
|
||||
* Mark objects referenced by arguments object
|
||||
*/
|
||||
static void
|
||||
ecma_gc_mark_arguments_object (ecma_extended_object_t *ext_object_p) /**< arguments object */
|
||||
{
|
||||
JERRY_ASSERT (ecma_get_object_type ((ecma_object_t *) ext_object_p) == ECMA_OBJECT_TYPE_PSEUDO_ARRAY);
|
||||
|
||||
ecma_unmapped_arguments_t *arguments_p = (ecma_unmapped_arguments_t *) ext_object_p;
|
||||
ecma_value_t *argv_p = (ecma_value_t *) (arguments_p + 1);
|
||||
|
||||
if (ext_object_p->u.pseudo_array.extra_info & ECMA_ARGUMENTS_OBJECT_MAPPED)
|
||||
{
|
||||
ecma_mapped_arguments_t *mapped_arguments_p = (ecma_mapped_arguments_t *) ext_object_p;
|
||||
argv_p = (ecma_value_t *) (mapped_arguments_p + 1);
|
||||
|
||||
ecma_gc_set_object_visited (ECMA_GET_INTERNAL_VALUE_POINTER (ecma_object_t, mapped_arguments_p->lex_env));
|
||||
}
|
||||
|
||||
uint32_t arguments_number = arguments_p->header.u.pseudo_array.u2.arguments_number;
|
||||
|
||||
for (uint32_t i = 0; i < arguments_number; i++)
|
||||
{
|
||||
if (ecma_is_value_object (argv_p[i]))
|
||||
{
|
||||
ecma_gc_set_object_visited (ecma_get_object_from_value (argv_p[i]));
|
||||
}
|
||||
}
|
||||
} /* ecma_gc_mark_arguments_object */
|
||||
|
||||
/**
|
||||
* Mark referenced object from property
|
||||
*/
|
||||
@@ -706,10 +736,7 @@ ecma_gc_mark (ecma_object_t *object_p) /**< object to mark from */
|
||||
{
|
||||
JERRY_ASSERT (ext_object_p->u.pseudo_array.type == ECMA_PSEUDO_ARRAY_ARGUMENTS);
|
||||
|
||||
ecma_object_t *lex_env_p = ECMA_GET_INTERNAL_VALUE_POINTER (ecma_object_t,
|
||||
ext_object_p->u.pseudo_array.u2.lex_env_cp);
|
||||
|
||||
ecma_gc_set_object_visited (lex_env_p);
|
||||
ecma_gc_mark_arguments_object (ext_object_p);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -915,6 +942,49 @@ ecma_gc_free_native_pointer (ecma_property_t *property_p) /**< property */
|
||||
}
|
||||
} /* ecma_gc_free_native_pointer */
|
||||
|
||||
/**
|
||||
* Free specified arguments object.
|
||||
*
|
||||
* @return allocated object's size
|
||||
*/
|
||||
static size_t
|
||||
ecma_free_arguments_object (ecma_extended_object_t *ext_object_p) /**< arguments object */
|
||||
{
|
||||
JERRY_ASSERT (ecma_get_object_type ((ecma_object_t *) ext_object_p) == ECMA_OBJECT_TYPE_PSEUDO_ARRAY);
|
||||
|
||||
size_t object_size = sizeof (ecma_unmapped_arguments_t);
|
||||
|
||||
if (ext_object_p->u.pseudo_array.extra_info & ECMA_ARGUMENTS_OBJECT_MAPPED)
|
||||
{
|
||||
ecma_mapped_arguments_t *mapped_arguments_p = (ecma_mapped_arguments_t *) ext_object_p;
|
||||
object_size = sizeof (ecma_mapped_arguments_t);
|
||||
|
||||
#if ENABLED (JERRY_SNAPSHOT_EXEC)
|
||||
if (!(mapped_arguments_p->unmapped.header.u.pseudo_array.extra_info & ECMA_ARGUMENTS_OBJECT_STATIC_BYTECODE))
|
||||
#endif /* ENABLED (JERRY_SNAPSHOT_EXEC) */
|
||||
{
|
||||
ecma_compiled_code_t *byte_code_p = ECMA_GET_INTERNAL_VALUE_POINTER (ecma_compiled_code_t,
|
||||
mapped_arguments_p->u.byte_code);
|
||||
|
||||
ecma_bytecode_deref (byte_code_p);
|
||||
}
|
||||
}
|
||||
|
||||
ecma_value_t *argv_p = (ecma_value_t *) (((uint8_t *) ext_object_p) + object_size);
|
||||
ecma_unmapped_arguments_t *arguments_p = (ecma_unmapped_arguments_t *) ext_object_p;
|
||||
uint32_t arguments_number = arguments_p->header.u.pseudo_array.u2.arguments_number;
|
||||
|
||||
for (uint32_t i = 0; i < arguments_number; i++)
|
||||
{
|
||||
ecma_free_value_if_not_object (argv_p[i]);
|
||||
}
|
||||
|
||||
uint32_t saved_argument_count = JERRY_MAX (arguments_number,
|
||||
arguments_p->header.u.pseudo_array.u1.formal_params_number);
|
||||
|
||||
return object_size + (saved_argument_count * sizeof (ecma_value_t));
|
||||
} /* ecma_free_arguments_object */
|
||||
|
||||
/**
|
||||
* Free specified fast access mode array object.
|
||||
*/
|
||||
@@ -1444,22 +1514,7 @@ ecma_gc_free_object (ecma_object_t *object_p) /**< object to free */
|
||||
{
|
||||
case ECMA_PSEUDO_ARRAY_ARGUMENTS:
|
||||
{
|
||||
JERRY_ASSERT (ext_object_p->u.pseudo_array.type == ECMA_PSEUDO_ARRAY_ARGUMENTS);
|
||||
|
||||
uint32_t formal_params_number = ext_object_p->u.pseudo_array.u1.length;
|
||||
ecma_value_t *arg_literal_p = (ecma_value_t *) (ext_object_p + 1);
|
||||
|
||||
for (uint32_t i = 0; i < formal_params_number; i++)
|
||||
{
|
||||
if (arg_literal_p[i] != ECMA_VALUE_EMPTY)
|
||||
{
|
||||
ecma_string_t *name_p = ecma_get_string_from_value (arg_literal_p[i]);
|
||||
ecma_deref_ecma_string (name_p);
|
||||
}
|
||||
}
|
||||
|
||||
size_t formal_params_size = formal_params_number * sizeof (ecma_value_t);
|
||||
ext_object_size += formal_params_size;
|
||||
ext_object_size = ecma_free_arguments_object (ext_object_p);
|
||||
break;
|
||||
}
|
||||
#if ENABLED (JERRY_BUILTIN_TYPEDARRAY)
|
||||
|
||||
@@ -215,6 +215,7 @@ enum
|
||||
* or function call argument list */
|
||||
ECMA_VALUE_SYNC_ITERATOR = ECMA_MAKE_VALUE (12), /**< option for ecma_op_get_iterator: sync iterator is requested */
|
||||
ECMA_VALUE_ASYNC_ITERATOR = ECMA_MAKE_VALUE (13), /**< option for ecma_op_get_iterator: async iterator is requested */
|
||||
ECMA_VALUE_INITIALIZED = ECMA_MAKE_VALUE (14), /**< represents initialized mapped arguments formal parameter */
|
||||
};
|
||||
|
||||
#if !ENABLED (JERRY_NUMBER_TYPE_FLOAT64)
|
||||
@@ -648,7 +649,6 @@ 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_EXT_REFERENCE = 1u << 1, /**< get extended reference to the property */
|
||||
ECMA_PROPERTY_GET_HAS_OWN_PROP = 1u << 2, /**< internal [[HasOwnProperty]] method */
|
||||
} ecma_property_get_option_bits_t;
|
||||
|
||||
/**
|
||||
@@ -937,13 +937,13 @@ typedef struct
|
||||
* [[IterationKind]] property for %Iterator% */
|
||||
union
|
||||
{
|
||||
uint16_t length; /**< for arguments: length of names */
|
||||
uint16_t formal_params_number; /**< for arguments: formal parameters number */
|
||||
uint16_t class_id; /**< for typedarray: the specific class name id */
|
||||
uint16_t iterator_index; /**< for %Iterator%: [[%Iterator%NextIndex]] property */
|
||||
} u1;
|
||||
union
|
||||
{
|
||||
ecma_value_t lex_env_cp; /**< for arguments: lexical environment */
|
||||
uint32_t arguments_number; /**< for arguments: arguments number */
|
||||
ecma_value_t arraybuffer; /**< for typedarray: internal arraybuffer */
|
||||
ecma_value_t iterated_value; /**< for %Iterator%: [[IteratedObject]] property */
|
||||
ecma_value_t spread_value; /**< for spread object: spreaded element */
|
||||
@@ -2183,6 +2183,45 @@ typedef struct
|
||||
uint32_t lazy_string_named_props; /**< number of lazy instantiated properties */
|
||||
} ecma_property_counter_t;
|
||||
|
||||
/**
|
||||
* Arguments object related status flags
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
ECMA_ARGUMENTS_OBJECT_NO_FLAGS = 0, /* unmapped arguments object */
|
||||
ECMA_ARGUMENTS_OBJECT_MAPPED = (1 << 0), /* mapped arguments object */
|
||||
ECMA_ARGUMENTS_OBJECT_STATIC_BYTECODE = (1 << 1), /* static mapped arguments object */
|
||||
ECMA_ARGUMENTS_OBJECT_CALLEE_INITIALIZED = (1 << 2), /* 'callee' property has been lazy initialized */
|
||||
ECMA_ARGUMENTS_OBJECT_CALLER_INITIALIZED = (1 << 3), /* 'caller' property has been lazy initialized */
|
||||
ECMA_ARGUMENTS_OBJECT_LENGTH_INITIALIZED = (1 << 4), /* 'length' property has been lazy initialized */
|
||||
ECMA_ARGUMENTS_OBJECT_ITERATOR_INITIALIZED = (1 << 5), /* 'Symbol.iterator' property has been lazy initialized */
|
||||
} ecma_arguments_object_flags_t;
|
||||
|
||||
/**
|
||||
* Definition of unmapped arguments object
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
ecma_extended_object_t header; /**< object header */
|
||||
ecma_value_t callee; /**< 'callee' property */
|
||||
} ecma_unmapped_arguments_t;
|
||||
|
||||
/**
|
||||
* Definition of mapped arguments object
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
ecma_unmapped_arguments_t unmapped; /**< unmapped arguments object header */
|
||||
ecma_value_t lex_env; /**< environment reference */
|
||||
union
|
||||
{
|
||||
ecma_value_t byte_code; /**< callee's compiled code */
|
||||
#if ENABLED (JERRY_SNAPSHOT_EXEC)
|
||||
ecma_compiled_code_t *byte_code_p; /**< real byte code pointer */
|
||||
#endif /* ENABLED (JERRY_SNAPSHOT_EXEC) */
|
||||
} u;
|
||||
} ecma_mapped_arguments_t;
|
||||
|
||||
/**
|
||||
* @}
|
||||
* @}
|
||||
|
||||
@@ -1498,23 +1498,6 @@ ecma_bytecode_deref (ecma_compiled_code_t *bytecode_p) /**< byte code pointer */
|
||||
((size_t) bytecode_p->size) << JMEM_ALIGNMENT_LOG);
|
||||
} /* ecma_bytecode_deref */
|
||||
|
||||
#if ENABLED (JERRY_ESNEXT)
|
||||
/**
|
||||
* Get the tagged template collection of the compiled code
|
||||
*
|
||||
* @return pointer to the tagged template collection
|
||||
*/
|
||||
ecma_collection_t *
|
||||
ecma_compiled_code_get_tagged_template_collection (const ecma_compiled_code_t *bytecode_header_p) /**< compiled code */
|
||||
{
|
||||
JERRY_ASSERT (bytecode_header_p != NULL);
|
||||
JERRY_ASSERT (bytecode_header_p->status_flags & CBC_CODE_FLAGS_HAS_TAGGED_LITERALS);
|
||||
|
||||
ecma_value_t *base_p = ecma_compiled_code_resolve_function_name (bytecode_header_p);
|
||||
|
||||
return ECMA_GET_INTERNAL_VALUE_POINTER (ecma_collection_t, base_p[-1]);
|
||||
} /* ecma_compiled_code_get_tagged_template_collection */
|
||||
|
||||
/**
|
||||
* Get the number of formal parameters of the compiled code
|
||||
*
|
||||
@@ -1552,6 +1535,23 @@ ecma_compiled_code_resolve_arguments_start (const ecma_compiled_code_t *bytecode
|
||||
return ((ecma_value_t *) byte_p) - ecma_compiled_code_get_formal_params (bytecode_header_p);
|
||||
} /* ecma_compiled_code_resolve_arguments_start */
|
||||
|
||||
#if ENABLED (JERRY_ESNEXT)
|
||||
/**
|
||||
* Get the tagged template collection of the compiled code
|
||||
*
|
||||
* @return pointer to the tagged template collection
|
||||
*/
|
||||
ecma_collection_t *
|
||||
ecma_compiled_code_get_tagged_template_collection (const ecma_compiled_code_t *bytecode_header_p) /**< compiled code */
|
||||
{
|
||||
JERRY_ASSERT (bytecode_header_p != NULL);
|
||||
JERRY_ASSERT (bytecode_header_p->status_flags & CBC_CODE_FLAGS_HAS_TAGGED_LITERALS);
|
||||
|
||||
ecma_value_t *base_p = ecma_compiled_code_resolve_function_name (bytecode_header_p);
|
||||
|
||||
return ECMA_GET_INTERNAL_VALUE_POINTER (ecma_collection_t, base_p[-1]);
|
||||
} /* ecma_compiled_code_get_tagged_template_collection */
|
||||
|
||||
/**
|
||||
* Resolve the position of the function name of the compiled code
|
||||
*
|
||||
|
||||
@@ -536,12 +536,10 @@ void ecma_raise_error_from_error_reference (ecma_value_t value);
|
||||
|
||||
void ecma_bytecode_ref (ecma_compiled_code_t *bytecode_p);
|
||||
void ecma_bytecode_deref (ecma_compiled_code_t *bytecode_p);
|
||||
#if ENABLED (JERRY_ESNEXT)
|
||||
ecma_collection_t *ecma_compiled_code_get_tagged_template_collection (const ecma_compiled_code_t *bytecode_header_p);
|
||||
#endif /* ENABLED (JERRY_ESNEXT) */
|
||||
#if ENABLED (JERRY_ESNEXT)
|
||||
uint32_t ecma_compiled_code_get_formal_params (const ecma_compiled_code_t *bytecode_p);
|
||||
ecma_value_t *ecma_compiled_code_resolve_arguments_start (const ecma_compiled_code_t *bytecode_header_p);
|
||||
#if ENABLED (JERRY_ESNEXT)
|
||||
ecma_collection_t *ecma_compiled_code_get_tagged_template_collection (const ecma_compiled_code_t *bytecode_header_p);
|
||||
ecma_value_t *ecma_compiled_code_resolve_function_name (const ecma_compiled_code_t *bytecode_header_p);
|
||||
#endif /* ENABLED (JERRY_ESNEXT) */
|
||||
ecma_value_t ecma_get_resource_name (const ecma_compiled_code_t *bytecode_p);
|
||||
|
||||
Reference in New Issue
Block a user