Rework arguments object. (#1401)
Instead of allocating a helper object, argument names are appended right after the arguments objects. This reduces memory consumption and improve performance as well. In the future this could be further improved by a bitfield, but that would require a reference to the byte code which might increase memory consumption in a few corner cases. JerryScript-DCO-1.0-Signed-off-by: Zoltan Herczeg zherczeg.u-szeged@partner.samsung.com
This commit is contained in:
@@ -247,8 +247,6 @@ ecma_gc_mark_property (ecma_property_t *property_p) /**< property */
|
||||
}
|
||||
|
||||
case ECMA_INTERNAL_PROPERTY_BOUND_FUNCTION_TARGET_FUNCTION: /* an object */
|
||||
case ECMA_INTERNAL_PROPERTY_SCOPE: /* a lexical environment */
|
||||
case ECMA_INTERNAL_PROPERTY_PARAMETERS_MAP: /* an object */
|
||||
{
|
||||
ecma_object_t *obj_p = ECMA_GET_INTERNAL_VALUE_POINTER (ecma_object_t, property_value);
|
||||
|
||||
@@ -308,8 +306,17 @@ ecma_gc_mark (ecma_object_t *object_p) /**< object to mark from */
|
||||
ecma_gc_set_object_visited (proto_p, true);
|
||||
}
|
||||
|
||||
if (!ecma_get_object_is_builtin (object_p)
|
||||
&& ecma_get_object_type (object_p) == ECMA_OBJECT_TYPE_FUNCTION)
|
||||
if (ecma_get_object_type (object_p) == ECMA_OBJECT_TYPE_ARGUMENTS)
|
||||
{
|
||||
ecma_extended_object_t *ext_object_p = (ecma_extended_object_t *) object_p;
|
||||
|
||||
ecma_object_t *lex_env_p = ECMA_GET_INTERNAL_VALUE_POINTER (ecma_object_t,
|
||||
ext_object_p->u.arguments.lex_env_cp);
|
||||
|
||||
ecma_gc_set_object_visited (lex_env_p, true);
|
||||
}
|
||||
else if (!ecma_get_object_is_builtin (object_p)
|
||||
&& ecma_get_object_type (object_p) == ECMA_OBJECT_TYPE_FUNCTION)
|
||||
{
|
||||
ecma_extended_object_t *ext_func_p = (ecma_extended_object_t *) object_p;
|
||||
|
||||
@@ -436,7 +443,9 @@ ecma_gc_sweep (ecma_object_t *object_p) /**< object to free */
|
||||
|
||||
if (!ecma_is_lexical_environment (object_p))
|
||||
{
|
||||
if (ecma_get_object_type (object_p) == ECMA_OBJECT_TYPE_CLASS)
|
||||
ecma_object_type_t object_type = ecma_get_object_type (object_p);
|
||||
|
||||
if (object_type == ECMA_OBJECT_TYPE_CLASS)
|
||||
{
|
||||
ecma_extended_object_t *ext_object_p = (ecma_extended_object_t *) object_p;
|
||||
|
||||
@@ -491,13 +500,13 @@ ecma_gc_sweep (ecma_object_t *object_p) /**< object to free */
|
||||
}
|
||||
|
||||
if (ecma_get_object_is_builtin (object_p)
|
||||
|| ecma_get_object_type (object_p) == ECMA_OBJECT_TYPE_EXTERNAL_FUNCTION)
|
||||
|| object_type == ECMA_OBJECT_TYPE_EXTERNAL_FUNCTION)
|
||||
{
|
||||
ecma_dealloc_extended_object ((ecma_extended_object_t *) object_p, sizeof (ecma_extended_object_t));
|
||||
return;
|
||||
}
|
||||
|
||||
if (ecma_get_object_type (object_p) == ECMA_OBJECT_TYPE_FUNCTION)
|
||||
if (object_type == ECMA_OBJECT_TYPE_FUNCTION)
|
||||
{
|
||||
/* Function with byte-code (not a built-in function). */
|
||||
ecma_extended_object_t *ext_func_p = (ecma_extended_object_t *) object_p;
|
||||
@@ -508,6 +517,27 @@ ecma_gc_sweep (ecma_object_t *object_p) /**< object to free */
|
||||
ecma_dealloc_extended_object (ext_func_p, sizeof (ecma_extended_object_t));
|
||||
return;
|
||||
}
|
||||
|
||||
if (object_type == ECMA_OBJECT_TYPE_ARGUMENTS)
|
||||
{
|
||||
ecma_extended_object_t *ext_object_p = (ecma_extended_object_t *) object_p;
|
||||
|
||||
ecma_length_t formal_params_number = ext_object_p->u.arguments.length;
|
||||
jmem_cpointer_t *arg_Literal_p = (jmem_cpointer_t *) (ext_object_p + 1);
|
||||
|
||||
for (ecma_length_t i = 0; i < formal_params_number; i++)
|
||||
{
|
||||
if (arg_Literal_p[i] != JMEM_CP_NULL)
|
||||
{
|
||||
ecma_string_t *name_p = JMEM_CP_GET_NON_NULL_POINTER (ecma_string_t, arg_Literal_p[i]);
|
||||
ecma_deref_ecma_string (name_p);
|
||||
}
|
||||
}
|
||||
|
||||
size_t formal_params_size = formal_params_number * sizeof (jmem_cpointer_t);
|
||||
ecma_dealloc_extended_object (ext_object_p, sizeof (ecma_extended_object_t) + formal_params_size);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
ecma_dealloc_object (object_p);
|
||||
|
||||
@@ -197,9 +197,6 @@ typedef uintptr_t ecma_external_pointer_t;
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
ECMA_INTERNAL_PROPERTY_SCOPE, /**< [[Scope]] */
|
||||
ECMA_INTERNAL_PROPERTY_PARAMETERS_MAP, /**< [[ParametersMap]] */
|
||||
|
||||
ECMA_INTERNAL_PROPERTY_NATIVE_HANDLE, /**< native handle associated with an object */
|
||||
ECMA_INTERNAL_PROPERTY_FREE_CALLBACK, /**< object's native free callback */
|
||||
|
||||
@@ -606,6 +603,15 @@ typedef struct
|
||||
ecma_value_t bytecode_cp; /**< function byte code */
|
||||
} function;
|
||||
|
||||
/*
|
||||
* Description of arguments objects.
|
||||
*/
|
||||
struct
|
||||
{
|
||||
ecma_value_t lex_env_cp; /**< lexical environment */
|
||||
uint32_t length; /**< length of names */
|
||||
} arguments;
|
||||
|
||||
ecma_external_pointer_t external_function; /**< external function */
|
||||
} u;
|
||||
} ecma_extended_object_t;
|
||||
|
||||
@@ -783,8 +783,6 @@ ecma_free_internal_property (ecma_property_t *property_p) /**< the property */
|
||||
break;
|
||||
}
|
||||
|
||||
case ECMA_INTERNAL_PROPERTY_SCOPE: /* a lexical environment */
|
||||
case ECMA_INTERNAL_PROPERTY_PARAMETERS_MAP: /* an object */
|
||||
case ECMA_INTERNAL_PROPERTY_INSTANTIATED_MASK_32_63: /* an integer (bit-mask) */
|
||||
case ECMA_INTERNAL_PROPERTY_BOUND_FUNCTION_TARGET_FUNCTION:
|
||||
{
|
||||
|
||||
@@ -71,16 +71,36 @@ ecma_op_create_arguments_object (ecma_object_t *func_obj_p, /**< callee function
|
||||
literal_p = (jmem_cpointer_t *) (byte_p + sizeof (cbc_uint8_arguments_t));
|
||||
}
|
||||
|
||||
bool class_not_required = (!is_strict && arguments_number > 0 && formal_params_number > 0);
|
||||
|
||||
// 2., 3., 6.
|
||||
ecma_object_t *prototype_p = ecma_builtin_get (ECMA_BUILTIN_ID_OBJECT_PROTOTYPE);
|
||||
|
||||
ecma_object_t *obj_p;
|
||||
|
||||
if (class_not_required)
|
||||
if (!is_strict && arguments_number > 0 && formal_params_number > 0)
|
||||
{
|
||||
obj_p = ecma_create_object (prototype_p, 0, ECMA_OBJECT_TYPE_GENERAL);
|
||||
size_t formal_params_size = formal_params_number * sizeof (jmem_cpointer_t);
|
||||
|
||||
obj_p = ecma_create_object (prototype_p,
|
||||
sizeof (ecma_extended_object_t) + formal_params_size,
|
||||
ECMA_OBJECT_TYPE_ARGUMENTS);
|
||||
|
||||
ecma_extended_object_t *ext_object_p = (ecma_extended_object_t *) obj_p;
|
||||
|
||||
ECMA_SET_INTERNAL_VALUE_POINTER (ext_object_p->u.arguments.lex_env_cp, lex_env_p);
|
||||
|
||||
ext_object_p->u.arguments.length = formal_params_number;
|
||||
|
||||
jmem_cpointer_t *arg_Literal_p = (jmem_cpointer_t *) (ext_object_p + 1);
|
||||
|
||||
memcpy (arg_Literal_p, literal_p, formal_params_size);
|
||||
|
||||
for (ecma_length_t i = 0; i < formal_params_number; i++)
|
||||
{
|
||||
if (arg_Literal_p[i] != JMEM_CP_NULL)
|
||||
{
|
||||
ecma_string_t *name_p = JMEM_CP_GET_NON_NULL_POINTER (ecma_string_t, arg_Literal_p[i]);
|
||||
ecma_ref_ecma_string (name_p);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -92,104 +112,50 @@ ecma_op_create_arguments_object (ecma_object_t *func_obj_p, /**< callee function
|
||||
|
||||
ecma_deref_object (prototype_p);
|
||||
|
||||
ecma_property_value_t *prop_value_p;
|
||||
|
||||
// 11.a, 11.b
|
||||
for (ecma_length_t indx = 0;
|
||||
indx < arguments_number;
|
||||
indx++)
|
||||
{
|
||||
ecma_value_t completion;
|
||||
ecma_string_t *indx_string_p = ecma_new_ecma_string_from_uint32 (indx);
|
||||
|
||||
completion = ecma_builtin_helper_def_prop (obj_p,
|
||||
indx_string_p,
|
||||
arguments_list_p[indx],
|
||||
true, /* Writable */
|
||||
true, /* Enumerable */
|
||||
true, /* Configurable */
|
||||
false); /* Failure handling */
|
||||
prop_value_p = ecma_create_named_data_property (obj_p,
|
||||
indx_string_p,
|
||||
ECMA_PROPERTY_CONFIGURABLE_ENUMERABLE_WRITABLE,
|
||||
NULL);
|
||||
|
||||
JERRY_ASSERT (ecma_is_value_true (completion));
|
||||
prop_value_p->value = ecma_copy_value_if_not_object (arguments_list_p[indx]);
|
||||
|
||||
ecma_deref_ecma_string (indx_string_p);
|
||||
}
|
||||
|
||||
// 7.
|
||||
ecma_string_t *length_magic_string_p = ecma_new_ecma_length_string ();
|
||||
ecma_value_t completion = ecma_builtin_helper_def_prop (obj_p,
|
||||
length_magic_string_p,
|
||||
ecma_make_uint32_value (arguments_number),
|
||||
true, /* Writable */
|
||||
false, /* Enumerable */
|
||||
true, /* Configurable */
|
||||
false); /* Failure handling */
|
||||
|
||||
JERRY_ASSERT (ecma_is_value_true (completion));
|
||||
prop_value_p = ecma_create_named_data_property (obj_p,
|
||||
length_magic_string_p,
|
||||
ECMA_PROPERTY_CONFIGURABLE_WRITABLE,
|
||||
NULL);
|
||||
|
||||
prop_value_p->value = ecma_make_uint32_value (arguments_number);
|
||||
|
||||
ecma_deref_ecma_string (length_magic_string_p);
|
||||
|
||||
ecma_property_descriptor_t prop_desc = ecma_make_empty_property_descriptor ();
|
||||
|
||||
if (class_not_required)
|
||||
{
|
||||
// 8.
|
||||
ecma_object_t *map_p = ecma_op_create_object_object_noarg ();
|
||||
|
||||
// 11.c
|
||||
for (uint32_t indx = 0;
|
||||
indx < formal_params_number;
|
||||
indx++)
|
||||
{
|
||||
// i.
|
||||
if (literal_p[indx] == JMEM_CP_NULL)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
ecma_string_t *name_p = JMEM_CP_GET_NON_NULL_POINTER (ecma_string_t, literal_p[indx]);
|
||||
ecma_string_t *indx_string_p = ecma_new_ecma_string_from_uint32 ((uint32_t) indx);
|
||||
|
||||
prop_desc.is_value_defined = true;
|
||||
prop_desc.value = ecma_make_string_value (name_p);
|
||||
|
||||
prop_desc.is_configurable_defined = true;
|
||||
prop_desc.is_configurable = true;
|
||||
|
||||
completion = ecma_op_object_define_own_property (map_p,
|
||||
indx_string_p,
|
||||
&prop_desc,
|
||||
false);
|
||||
JERRY_ASSERT (ecma_is_value_true (completion));
|
||||
|
||||
ecma_deref_ecma_string (indx_string_p);
|
||||
}
|
||||
|
||||
// 12.
|
||||
ecma_set_object_type (obj_p, ECMA_OBJECT_TYPE_ARGUMENTS);
|
||||
|
||||
ecma_value_t *parameters_map_prop_p = ecma_create_internal_property (obj_p,
|
||||
ECMA_INTERNAL_PROPERTY_PARAMETERS_MAP);
|
||||
ECMA_SET_INTERNAL_VALUE_POINTER (*parameters_map_prop_p, map_p);
|
||||
|
||||
ecma_value_t *scope_prop_p = ecma_create_internal_property (map_p,
|
||||
ECMA_INTERNAL_PROPERTY_SCOPE);
|
||||
ECMA_SET_INTERNAL_VALUE_POINTER (*scope_prop_p, lex_env_p);
|
||||
|
||||
ecma_deref_object (map_p);
|
||||
}
|
||||
|
||||
// 13.
|
||||
if (!is_strict)
|
||||
{
|
||||
ecma_string_t *callee_magic_string_p = ecma_get_magic_string (LIT_MAGIC_STRING_CALLEE);
|
||||
|
||||
completion = ecma_builtin_helper_def_prop (obj_p,
|
||||
callee_magic_string_p,
|
||||
ecma_make_object_value (func_obj_p),
|
||||
true, /* Writable */
|
||||
false, /* Enumerable */
|
||||
true, /* Configurable */
|
||||
false); /* Failure handling */
|
||||
prop_value_p = ecma_create_named_data_property (obj_p,
|
||||
callee_magic_string_p,
|
||||
ECMA_PROPERTY_CONFIGURABLE_WRITABLE,
|
||||
NULL);
|
||||
|
||||
JERRY_ASSERT (ecma_is_value_true (completion));
|
||||
prop_value_p->value = ecma_make_object_value (func_obj_p);
|
||||
|
||||
ecma_deref_ecma_string (callee_magic_string_p);
|
||||
}
|
||||
@@ -215,10 +181,11 @@ ecma_op_create_arguments_object (ecma_object_t *func_obj_p, /**< callee function
|
||||
|
||||
ecma_string_t *callee_magic_string_p = ecma_get_magic_string (LIT_MAGIC_STRING_CALLEE);
|
||||
|
||||
completion = ecma_op_object_define_own_property (obj_p,
|
||||
callee_magic_string_p,
|
||||
&prop_desc,
|
||||
false);
|
||||
ecma_value_t completion = ecma_op_object_define_own_property (obj_p,
|
||||
callee_magic_string_p,
|
||||
&prop_desc,
|
||||
false);
|
||||
|
||||
JERRY_ASSERT (ecma_is_value_true (completion));
|
||||
ecma_deref_ecma_string (callee_magic_string_p);
|
||||
|
||||
@@ -260,53 +227,6 @@ ecma_op_create_arguments_object (ecma_object_t *func_obj_p, /**< callee function
|
||||
ecma_deref_object (obj_p);
|
||||
} /* ecma_op_create_arguments_object */
|
||||
|
||||
/**
|
||||
* Get value of function's argument mapped to index of Arguments object.
|
||||
*
|
||||
* Note:
|
||||
* The procedure emulates execution of function described by MakeArgGetter
|
||||
*
|
||||
* @return ecma value
|
||||
* Returned value must be freed with ecma_free_value
|
||||
*/
|
||||
void
|
||||
ecma_arguments_update_mapped_arg_value (ecma_object_t *object_p, /**< the object */
|
||||
ecma_string_t *property_name_p, /**< property name */
|
||||
ecma_property_t *property_p) /**< property value */
|
||||
{
|
||||
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 (map_p, property_name_p);
|
||||
|
||||
if (!ecma_is_value_found (arg_name))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
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 value = ecma_op_get_binding_value (lex_env_p, arg_name_p, true);
|
||||
ecma_deref_ecma_string (arg_name_p);
|
||||
|
||||
JERRY_ASSERT (!ECMA_IS_VALUE_ERROR (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
|
||||
* workaround until the property management is fully rewritten. */
|
||||
if (ecma_is_property_lcached (property_p))
|
||||
{
|
||||
ecma_lcache_invalidate (object_p, property_name_p, property_p);
|
||||
}
|
||||
} /* ecma_arguments_update_mapped_arg_value */
|
||||
|
||||
/**
|
||||
* [[DefineOwnProperty]] ecma Arguments object's operation
|
||||
*
|
||||
@@ -318,84 +238,75 @@ ecma_arguments_update_mapped_arg_value (ecma_object_t *object_p, /**< the object
|
||||
* Returned value must be freed with ecma_free_value
|
||||
*/
|
||||
ecma_value_t
|
||||
ecma_op_arguments_object_define_own_property (ecma_object_t *obj_p, /**< the object */
|
||||
ecma_op_arguments_object_define_own_property (ecma_object_t *object_p, /**< the object */
|
||||
ecma_string_t *property_name_p, /**< property name */
|
||||
const ecma_property_descriptor_t *property_desc_p, /**< property
|
||||
* descriptor */
|
||||
bool is_throw) /**< flag that controls failure handling */
|
||||
{
|
||||
// 1.
|
||||
ecma_value_t *map_prop_p = ecma_get_internal_property (obj_p, ECMA_INTERNAL_PROPERTY_PARAMETERS_MAP);
|
||||
ecma_object_t *map_p = ECMA_GET_INTERNAL_VALUE_POINTER (ecma_object_t, *map_prop_p);
|
||||
|
||||
// 3.
|
||||
ecma_value_t ret_value = ecma_make_simple_value (ECMA_SIMPLE_VALUE_EMPTY);
|
||||
ecma_value_t ret_value = ecma_op_general_object_define_own_property (object_p,
|
||||
property_name_p,
|
||||
property_desc_p,
|
||||
is_throw);
|
||||
|
||||
ECMA_TRY_CATCH (defined,
|
||||
ecma_op_general_object_define_own_property (obj_p,
|
||||
property_name_p,
|
||||
property_desc_p,
|
||||
is_throw),
|
||||
ret_value);
|
||||
|
||||
// 5.
|
||||
if (ecma_op_object_has_own_property (map_p, property_name_p))
|
||||
if (ECMA_IS_VALUE_ERROR (ret_value))
|
||||
{
|
||||
// a.
|
||||
if (property_desc_p->is_get_defined
|
||||
|| property_desc_p->is_set_defined)
|
||||
{
|
||||
ecma_value_t completion = ecma_op_object_delete (map_p, property_name_p, false);
|
||||
return ret_value;
|
||||
}
|
||||
|
||||
JERRY_ASSERT (ecma_is_value_true (completion));
|
||||
uint32_t index;
|
||||
|
||||
// 6.
|
||||
ret_value = ecma_make_simple_value (ECMA_SIMPLE_VALUE_TRUE);
|
||||
}
|
||||
else
|
||||
{
|
||||
// b.
|
||||
if (!ecma_string_get_array_index (property_name_p, &index))
|
||||
{
|
||||
return ret_value;
|
||||
}
|
||||
|
||||
ecma_value_t completion = ecma_make_simple_value (ECMA_SIMPLE_VALUE_EMPTY);
|
||||
ecma_extended_object_t *ext_object_p = (ecma_extended_object_t *) object_p;
|
||||
|
||||
// i.
|
||||
if (property_desc_p->is_value_defined)
|
||||
{
|
||||
/* emulating execution of function described by MakeArgSetter */
|
||||
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);
|
||||
if (index >= ext_object_p->u.arguments.length)
|
||||
{
|
||||
return ret_value;
|
||||
}
|
||||
|
||||
ecma_property_value_t *arg_name_value_p = ecma_get_named_data_property (map_p, property_name_p);
|
||||
jmem_cpointer_t *arg_Literal_p = (jmem_cpointer_t *) (ext_object_p + 1);
|
||||
|
||||
completion = ecma_op_set_mutable_binding (lex_env_p,
|
||||
ecma_get_string_from_value (arg_name_value_p->value),
|
||||
property_desc_p->value,
|
||||
true);
|
||||
if (arg_Literal_p[index] == JMEM_CP_NULL)
|
||||
{
|
||||
return ret_value;
|
||||
}
|
||||
|
||||
JERRY_ASSERT (ecma_is_value_empty (completion));
|
||||
}
|
||||
ecma_string_t *name_p = JMEM_CP_GET_NON_NULL_POINTER (ecma_string_t, arg_Literal_p[index]);
|
||||
|
||||
// ii.
|
||||
if (property_desc_p->is_writable_defined
|
||||
&& !property_desc_p->is_writable)
|
||||
{
|
||||
completion = ecma_op_object_delete (map_p,
|
||||
property_name_p,
|
||||
false);
|
||||
|
||||
JERRY_ASSERT (ecma_is_value_true (completion));
|
||||
}
|
||||
|
||||
// 6.
|
||||
ret_value = ecma_make_simple_value (ECMA_SIMPLE_VALUE_TRUE);
|
||||
}
|
||||
if (property_desc_p->is_get_defined
|
||||
|| property_desc_p->is_set_defined)
|
||||
{
|
||||
ecma_deref_ecma_string (name_p);
|
||||
arg_Literal_p[index] = JMEM_CP_NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
ret_value = ecma_make_simple_value (ECMA_SIMPLE_VALUE_TRUE);
|
||||
}
|
||||
if (property_desc_p->is_value_defined)
|
||||
{
|
||||
/* emulating execution of function described by MakeArgSetter */
|
||||
ecma_object_t *lex_env_p = ECMA_GET_INTERNAL_VALUE_POINTER (ecma_object_t,
|
||||
ext_object_p->u.arguments.lex_env_cp);
|
||||
|
||||
ECMA_FINALIZE (defined);
|
||||
ecma_value_t completion = ecma_op_set_mutable_binding (lex_env_p,
|
||||
name_p,
|
||||
property_desc_p->value,
|
||||
true);
|
||||
|
||||
JERRY_ASSERT (ecma_is_value_empty (completion));
|
||||
}
|
||||
|
||||
if (property_desc_p->is_writable_defined
|
||||
&& !property_desc_p->is_writable)
|
||||
{
|
||||
ecma_deref_ecma_string (name_p);
|
||||
arg_Literal_p[index] = JMEM_CP_NULL;
|
||||
}
|
||||
}
|
||||
|
||||
return ret_value;
|
||||
} /* ecma_op_arguments_object_define_own_property */
|
||||
@@ -411,41 +322,43 @@ ecma_op_arguments_object_define_own_property (ecma_object_t *obj_p, /**< the obj
|
||||
* Returned value must be freed with ecma_free_value
|
||||
*/
|
||||
ecma_value_t
|
||||
ecma_op_arguments_object_delete (ecma_object_t *obj_p, /**< the object */
|
||||
ecma_op_arguments_object_delete (ecma_object_t *object_p, /**< the object */
|
||||
ecma_string_t *property_name_p, /**< property name */
|
||||
bool is_throw) /**< flag that controls failure handling */
|
||||
{
|
||||
// 1.
|
||||
ecma_value_t *map_prop_p = ecma_get_internal_property (obj_p, ECMA_INTERNAL_PROPERTY_PARAMETERS_MAP);
|
||||
ecma_object_t *map_p = ECMA_GET_INTERNAL_VALUE_POINTER (ecma_object_t, *map_prop_p);
|
||||
|
||||
// 3.
|
||||
ecma_value_t ret_value = ecma_make_simple_value (ECMA_SIMPLE_VALUE_EMPTY);
|
||||
ecma_value_t ret_value = ecma_op_general_object_delete (object_p, property_name_p, is_throw);
|
||||
|
||||
ECMA_TRY_CATCH (delete_in_args_ret,
|
||||
ecma_op_general_object_delete (obj_p,
|
||||
property_name_p,
|
||||
is_throw),
|
||||
ret_value);
|
||||
|
||||
if (ecma_is_value_true (delete_in_args_ret))
|
||||
if (ECMA_IS_VALUE_ERROR (ret_value))
|
||||
{
|
||||
if (ecma_op_object_has_own_property (map_p, property_name_p))
|
||||
return ret_value;
|
||||
}
|
||||
|
||||
JERRY_ASSERT (ecma_is_value_boolean (ret_value));
|
||||
|
||||
if (ecma_is_value_true (ret_value))
|
||||
{
|
||||
uint32_t index;
|
||||
|
||||
if (ecma_string_get_array_index (property_name_p, &index))
|
||||
{
|
||||
ecma_value_t delete_in_map_completion = ecma_op_object_delete (map_p, property_name_p, false);
|
||||
JERRY_ASSERT (ecma_is_value_true (delete_in_map_completion));
|
||||
ecma_extended_object_t *ext_object_p = (ecma_extended_object_t *) object_p;
|
||||
|
||||
if (index < ext_object_p->u.arguments.length)
|
||||
{
|
||||
jmem_cpointer_t *arg_Literal_p = (jmem_cpointer_t *) (ext_object_p + 1);
|
||||
|
||||
if (arg_Literal_p[index] != JMEM_CP_NULL)
|
||||
{
|
||||
ecma_string_t *name_p = JMEM_CP_GET_NON_NULL_POINTER (ecma_string_t, arg_Literal_p[index]);
|
||||
ecma_deref_ecma_string (name_p);
|
||||
arg_Literal_p[index] = JMEM_CP_NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ret_value = ecma_make_simple_value (ECMA_SIMPLE_VALUE_TRUE);
|
||||
}
|
||||
else
|
||||
{
|
||||
JERRY_ASSERT (ecma_is_value_boolean (delete_in_args_ret));
|
||||
|
||||
ret_value = ecma_make_simple_value (ECMA_SIMPLE_VALUE_FALSE);
|
||||
}
|
||||
|
||||
ECMA_FINALIZE (delete_in_args_ret);
|
||||
|
||||
return ret_value;
|
||||
} /* ecma_op_arguments_object_delete */
|
||||
|
||||
@@ -23,8 +23,6 @@ extern void
|
||||
ecma_op_create_arguments_object (ecma_object_t *, ecma_object_t *, const ecma_value_t *,
|
||||
ecma_length_t, const ecma_compiled_code_t *);
|
||||
|
||||
extern void
|
||||
ecma_arguments_update_mapped_arg_value (ecma_object_t *, ecma_string_t *, ecma_property_t *);
|
||||
extern ecma_value_t
|
||||
ecma_op_arguments_object_delete (ecma_object_t *, ecma_string_t *, bool);
|
||||
extern ecma_value_t
|
||||
|
||||
@@ -170,29 +170,38 @@ ecma_op_object_get_own_property (ecma_object_t *object_p, /**< the object */
|
||||
return ECMA_PROPERTY_TYPE_NOT_FOUND;
|
||||
}
|
||||
}
|
||||
else if (type == ECMA_OBJECT_TYPE_ARGUMENTS)
|
||||
else if (type == ECMA_OBJECT_TYPE_ARGUMENTS
|
||||
&& property_ref_p != NULL)
|
||||
{
|
||||
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);
|
||||
uint32_t index;
|
||||
|
||||
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))
|
||||
if (ecma_string_get_array_index (property_name_p, &index))
|
||||
{
|
||||
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_extended_object_t *ext_object_p = (ecma_extended_object_t *) object_p;
|
||||
|
||||
JERRY_ASSERT (lex_env_p != NULL
|
||||
&& ecma_is_lexical_environment (lex_env_p));
|
||||
if (index < ext_object_p->u.arguments.length)
|
||||
{
|
||||
jmem_cpointer_t *arg_Literal_p = (jmem_cpointer_t *) (ext_object_p + 1);
|
||||
|
||||
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);
|
||||
if (arg_Literal_p[index] != JMEM_CP_NULL)
|
||||
{
|
||||
ecma_string_t *arg_name_p = JMEM_CP_GET_NON_NULL_POINTER (ecma_string_t,
|
||||
arg_Literal_p[index]);
|
||||
|
||||
ecma_named_data_property_assign_value (object_p,
|
||||
ECMA_PROPERTY_VALUE_PTR (property_p),
|
||||
binding_value);
|
||||
ecma_free_value (binding_value);
|
||||
ecma_object_t *lex_env_p = ECMA_GET_INTERNAL_VALUE_POINTER (ecma_object_t,
|
||||
ext_object_p->u.arguments.lex_env_cp);
|
||||
|
||||
JERRY_ASSERT (lex_env_p != NULL
|
||||
&& ecma_is_lexical_environment (lex_env_p));
|
||||
|
||||
ecma_value_t binding_value = ecma_op_get_binding_value (lex_env_p, arg_name_p, true);
|
||||
|
||||
ecma_named_data_property_assign_value (object_p,
|
||||
ECMA_PROPERTY_VALUE_PTR (property_p),
|
||||
binding_value);
|
||||
ecma_free_value (binding_value);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -307,23 +316,30 @@ ecma_op_object_find_own (ecma_value_t base_value, /**< base value */
|
||||
|
||||
if (unlikely (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);
|
||||
uint32_t index;
|
||||
|
||||
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))
|
||||
if (ecma_string_get_array_index (property_name_p, &index))
|
||||
{
|
||||
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_extended_object_t *ext_object_p = (ecma_extended_object_t *) object_p;
|
||||
|
||||
JERRY_ASSERT (lex_env_p != NULL
|
||||
&& ecma_is_lexical_environment (lex_env_p));
|
||||
if (index < ext_object_p->u.arguments.length)
|
||||
{
|
||||
jmem_cpointer_t *arg_Literal_p = (jmem_cpointer_t *) (ext_object_p + 1);
|
||||
|
||||
ecma_string_t *arg_name_p = ecma_get_string_from_value (arg_name);
|
||||
ecma_value_t result = ecma_op_get_binding_value (lex_env_p, arg_name_p, true);
|
||||
ecma_deref_ecma_string (arg_name_p);
|
||||
return result;
|
||||
if (arg_Literal_p[index] != JMEM_CP_NULL)
|
||||
{
|
||||
ecma_string_t *arg_name_p = JMEM_CP_GET_NON_NULL_POINTER (ecma_string_t,
|
||||
arg_Literal_p[index]);
|
||||
|
||||
ecma_object_t *lex_env_p = ECMA_GET_INTERNAL_VALUE_POINTER (ecma_object_t,
|
||||
ext_object_p->u.arguments.lex_env_cp);
|
||||
|
||||
JERRY_ASSERT (lex_env_p != NULL
|
||||
&& ecma_is_lexical_environment (lex_env_p));
|
||||
|
||||
return ecma_op_get_binding_value (lex_env_p, arg_name_p, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -562,23 +578,31 @@ ecma_op_object_put (ecma_object_t *object_p, /**< the object */
|
||||
|
||||
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);
|
||||
uint32_t index;
|
||||
|
||||
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))
|
||||
if (ecma_string_get_array_index (property_name_p, &index))
|
||||
{
|
||||
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_extended_object_t *ext_object_p = (ecma_extended_object_t *) object_p;
|
||||
|
||||
JERRY_ASSERT (lex_env_p != NULL
|
||||
&& ecma_is_lexical_environment (lex_env_p));
|
||||
if (index < ext_object_p->u.arguments.length)
|
||||
{
|
||||
jmem_cpointer_t *arg_Literal_p = (jmem_cpointer_t *) (ext_object_p + 1);
|
||||
|
||||
ecma_string_t *arg_name_p = ecma_get_string_from_value (arg_name);
|
||||
ecma_op_set_mutable_binding (lex_env_p, arg_name_p, value, true);
|
||||
ecma_deref_ecma_string (arg_name_p);
|
||||
return ecma_make_simple_value (ECMA_SIMPLE_VALUE_TRUE);
|
||||
if (arg_Literal_p[index] != JMEM_CP_NULL)
|
||||
{
|
||||
ecma_string_t *arg_name_p = JMEM_CP_GET_NON_NULL_POINTER (ecma_string_t,
|
||||
arg_Literal_p[index]);
|
||||
|
||||
ecma_object_t *lex_env_p = ECMA_GET_INTERNAL_VALUE_POINTER (ecma_object_t,
|
||||
ext_object_p->u.arguments.lex_env_cp);
|
||||
|
||||
JERRY_ASSERT (lex_env_p != NULL
|
||||
&& ecma_is_lexical_environment (lex_env_p));
|
||||
|
||||
ecma_op_set_mutable_binding (lex_env_p, arg_name_p, value, true);
|
||||
return ecma_make_simple_value (ECMA_SIMPLE_VALUE_TRUE);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user