mirror of
https://github.com/jerryscript-project/jerryscript.git
synced 2025-12-15 16:29:21 +00:00
Rework function.bind (#1406)
The new code does not use value collections which reduces the argument array size by half. JerryScript-DCO-1.0-Signed-off-by: Zoltan Herczeg zherczeg.u-szeged@partner.samsung.com
This commit is contained in:
parent
dc1e26933f
commit
945fbef110
@ -29,6 +29,9 @@ JERRY_STATIC_ASSERT (((sizeof (ecma_property_value_t) - 1) & sizeof (ecma_proper
|
||||
JERRY_STATIC_ASSERT (sizeof (ecma_string_t) == sizeof (uint64_t),
|
||||
size_of_ecma_string_t_must_be_less_than_or_equal_to_8_bytes);
|
||||
|
||||
JERRY_STATIC_ASSERT (sizeof (ecma_extended_object_t) - sizeof (ecma_object_t) <= sizeof (uint64_t),
|
||||
size_of_ecma_extended_object_part_must_be_less_than_or_equal_to_8_bytes);
|
||||
|
||||
/** \addtogroup ecma ECMA
|
||||
* @{
|
||||
*
|
||||
|
||||
@ -199,8 +199,6 @@ ecma_gc_mark_property (ecma_property_t *property_p) /**< property */
|
||||
}
|
||||
case ECMA_PROPERTY_TYPE_INTERNAL:
|
||||
{
|
||||
uint32_t property_value = ECMA_PROPERTY_VALUE_PTR (property_p)->value;
|
||||
|
||||
switch (ECMA_PROPERTY_GET_INTERNAL_PROPERTY_TYPE (property_p))
|
||||
{
|
||||
case ECMA_INTERNAL_PROPERTY_NATIVE_HANDLE: /* an external pointer */
|
||||
@ -210,52 +208,7 @@ ecma_gc_mark_property (ecma_property_t *property_p) /**< property */
|
||||
break;
|
||||
}
|
||||
|
||||
case ECMA_INTERNAL_PROPERTY_BOUND_FUNCTION_BOUND_THIS: /* an ecma value */
|
||||
{
|
||||
if (ecma_is_value_object (property_value))
|
||||
{
|
||||
ecma_object_t *obj_p = ecma_get_object_from_value (property_value);
|
||||
|
||||
ecma_gc_set_object_visited (obj_p, true);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case ECMA_INTERNAL_PROPERTY_BOUND_FUNCTION_BOUND_ARGS: /* a collection of ecma values */
|
||||
{
|
||||
ecma_collection_header_t *bound_arg_list_p = ECMA_GET_INTERNAL_VALUE_POINTER (ecma_collection_header_t,
|
||||
property_value);
|
||||
|
||||
ecma_collection_iterator_t bound_args_iterator;
|
||||
ecma_collection_iterator_init (&bound_args_iterator, bound_arg_list_p);
|
||||
|
||||
for (ecma_length_t i = 0; i < bound_arg_list_p->unit_number; i++)
|
||||
{
|
||||
bool is_moved = ecma_collection_iterator_next (&bound_args_iterator);
|
||||
JERRY_ASSERT (is_moved);
|
||||
|
||||
if (ecma_is_value_object (*bound_args_iterator.current_value_p))
|
||||
{
|
||||
ecma_object_t *obj_p = ecma_get_object_from_value (*bound_args_iterator.current_value_p);
|
||||
|
||||
ecma_gc_set_object_visited (obj_p, true);
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case ECMA_INTERNAL_PROPERTY_BOUND_FUNCTION_TARGET_FUNCTION: /* an object */
|
||||
{
|
||||
ecma_object_t *obj_p = ECMA_GET_INTERNAL_VALUE_POINTER (ecma_object_t, property_value);
|
||||
|
||||
ecma_gc_set_object_visited (obj_p, true);
|
||||
|
||||
break;
|
||||
}
|
||||
case ECMA_INTERNAL_PROPERTY__COUNT: /* not a real internal property type,
|
||||
* but number of the real internal property types */
|
||||
default:
|
||||
{
|
||||
JERRY_UNREACHABLE ();
|
||||
break;
|
||||
@ -306,24 +259,52 @@ ecma_gc_mark (ecma_object_t *object_p) /**< object to mark from */
|
||||
ecma_gc_set_object_visited (proto_p, true);
|
||||
}
|
||||
|
||||
if (ecma_get_object_type (object_p) == ECMA_OBJECT_TYPE_ARGUMENTS)
|
||||
switch (ecma_get_object_type (object_p))
|
||||
{
|
||||
ecma_extended_object_t *ext_object_p = (ecma_extended_object_t *) object_p;
|
||||
case 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_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;
|
||||
ecma_gc_set_object_visited (lex_env_p, true);
|
||||
break;
|
||||
}
|
||||
case ECMA_OBJECT_TYPE_BOUND_FUNCTION:
|
||||
{
|
||||
ecma_extended_object_t *ext_function_p = (ecma_extended_object_t *) object_p;
|
||||
ecma_length_t args_length = ext_function_p->u.bound_function.args_length;
|
||||
ecma_value_t *args_p = (ecma_value_t *) (ext_function_p + 1);
|
||||
|
||||
ecma_object_t *scope_p = ECMA_GET_INTERNAL_VALUE_POINTER (ecma_object_t,
|
||||
ext_func_p->u.function.scope_cp);
|
||||
JERRY_ASSERT (args_length > 0);
|
||||
|
||||
ecma_gc_set_object_visited (scope_p, true);
|
||||
for (ecma_length_t i = 0; i < args_length; i++)
|
||||
{
|
||||
if (ecma_is_value_object (args_p[i]))
|
||||
{
|
||||
ecma_gc_set_object_visited (ecma_get_object_from_value (args_p[i]), true);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case ECMA_OBJECT_TYPE_FUNCTION:
|
||||
{
|
||||
if (!ecma_get_object_is_builtin (object_p))
|
||||
{
|
||||
ecma_extended_object_t *ext_func_p = (ecma_extended_object_t *) object_p;
|
||||
|
||||
ecma_object_t *scope_p = ECMA_GET_INTERNAL_VALUE_POINTER (ecma_object_t,
|
||||
ext_func_p->u.function.scope_cp);
|
||||
|
||||
ecma_gc_set_object_visited (scope_p, true);
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -538,6 +519,22 @@ ecma_gc_sweep (ecma_object_t *object_p) /**< object to free */
|
||||
ecma_dealloc_extended_object (ext_object_p, sizeof (ecma_extended_object_t) + formal_params_size);
|
||||
return;
|
||||
}
|
||||
|
||||
if (object_type == ECMA_OBJECT_TYPE_BOUND_FUNCTION)
|
||||
{
|
||||
ecma_extended_object_t *ext_function_p = (ecma_extended_object_t *) object_p;
|
||||
ecma_length_t args_length = ext_function_p->u.bound_function.args_length;
|
||||
ecma_value_t *args_p = (ecma_value_t *) (ext_function_p + 1);
|
||||
|
||||
for (ecma_length_t i = 0; i < args_length; i++)
|
||||
{
|
||||
ecma_free_value_if_not_object (args_p[i]);
|
||||
}
|
||||
|
||||
size_t args_size = args_length * sizeof (ecma_value_t);
|
||||
ecma_dealloc_extended_object (ext_function_p, sizeof (ecma_extended_object_t) + args_size);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
ecma_dealloc_object (object_p);
|
||||
|
||||
@ -199,12 +199,6 @@ typedef enum
|
||||
{
|
||||
ECMA_INTERNAL_PROPERTY_NATIVE_HANDLE, /**< native handle associated with an object */
|
||||
ECMA_INTERNAL_PROPERTY_FREE_CALLBACK, /**< object's native free callback */
|
||||
|
||||
/** Bound function internal properties **/
|
||||
ECMA_INTERNAL_PROPERTY_BOUND_FUNCTION_TARGET_FUNCTION,
|
||||
ECMA_INTERNAL_PROPERTY_BOUND_FUNCTION_BOUND_THIS,
|
||||
ECMA_INTERNAL_PROPERTY_BOUND_FUNCTION_BOUND_ARGS,
|
||||
|
||||
ECMA_INTERNAL_PROPERTY_INSTANTIATED_MASK_32_63, /**< Bit-mask of non-instantiated
|
||||
* built-in's properties (bits 32-63) */
|
||||
|
||||
@ -612,6 +606,15 @@ typedef struct
|
||||
uint32_t length; /**< length of names */
|
||||
} arguments;
|
||||
|
||||
/*
|
||||
* Description of bound function object.
|
||||
*/
|
||||
struct
|
||||
{
|
||||
ecma_value_t target_function; /**< target function */
|
||||
ecma_length_t args_length; /**< length of arguments */
|
||||
} bound_function;
|
||||
|
||||
ecma_external_pointer_t external_function; /**< external function */
|
||||
} u;
|
||||
} ecma_extended_object_t;
|
||||
|
||||
@ -771,8 +771,6 @@ 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);
|
||||
|
||||
uint32_t property_value = ECMA_PROPERTY_VALUE_PTR (property_p)->value;
|
||||
|
||||
switch (ECMA_PROPERTY_GET_INTERNAL_PROPERTY_TYPE (property_p))
|
||||
{
|
||||
case ECMA_INTERNAL_PROPERTY_NATIVE_HANDLE: /* an external pointer */
|
||||
@ -784,30 +782,11 @@ ecma_free_internal_property (ecma_property_t *property_p) /**< the property */
|
||||
}
|
||||
|
||||
case ECMA_INTERNAL_PROPERTY_INSTANTIATED_MASK_32_63: /* an integer (bit-mask) */
|
||||
case ECMA_INTERNAL_PROPERTY_BOUND_FUNCTION_TARGET_FUNCTION:
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
case ECMA_INTERNAL_PROPERTY_BOUND_FUNCTION_BOUND_THIS:
|
||||
{
|
||||
ecma_free_value_if_not_object (property_value);
|
||||
break;
|
||||
}
|
||||
|
||||
case ECMA_INTERNAL_PROPERTY_BOUND_FUNCTION_BOUND_ARGS:
|
||||
{
|
||||
if (property_value != ECMA_NULL_POINTER)
|
||||
{
|
||||
ecma_free_values_collection (ECMA_GET_INTERNAL_VALUE_POINTER (ecma_collection_header_t, property_value),
|
||||
false);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case ECMA_INTERNAL_PROPERTY__COUNT: /* not a real internal property type,
|
||||
* but number of the real internal property types */
|
||||
default:
|
||||
{
|
||||
JERRY_UNREACHABLE ();
|
||||
break;
|
||||
|
||||
@ -237,42 +237,42 @@ ecma_builtin_function_prototype_object_bind (ecma_value_t this_arg, /**< this ar
|
||||
{
|
||||
/* 4. 11. 18. */
|
||||
ecma_object_t *prototype_obj_p = ecma_builtin_get (ECMA_BUILTIN_ID_FUNCTION_PROTOTYPE);
|
||||
|
||||
ecma_length_t args_length = (arguments_number >= 1) ? arguments_number : 1;
|
||||
|
||||
size_t obj_size = sizeof (ecma_extended_object_t) + (args_length * sizeof (ecma_value_t));
|
||||
|
||||
ecma_object_t *function_p = ecma_create_object (prototype_obj_p,
|
||||
0,
|
||||
obj_size,
|
||||
ECMA_OBJECT_TYPE_BOUND_FUNCTION);
|
||||
|
||||
ecma_deref_object (prototype_obj_p);
|
||||
|
||||
/* 7. */
|
||||
ecma_value_t *target_function_prop_p;
|
||||
target_function_prop_p = ecma_create_internal_property (function_p,
|
||||
ECMA_INTERNAL_PROPERTY_BOUND_FUNCTION_TARGET_FUNCTION);
|
||||
ecma_extended_object_t *ext_function_p = (ecma_extended_object_t *) function_p;
|
||||
|
||||
/* 7. */
|
||||
ecma_object_t *this_arg_obj_p = ecma_get_object_from_value (this_arg);
|
||||
ECMA_SET_INTERNAL_VALUE_POINTER (*target_function_prop_p, this_arg_obj_p);
|
||||
ECMA_SET_INTERNAL_VALUE_POINTER (ext_function_p->u.bound_function.target_function,
|
||||
this_arg_obj_p);
|
||||
|
||||
/* 8. */
|
||||
ecma_value_t *bound_this_prop_p;
|
||||
bound_this_prop_p = ecma_create_internal_property (function_p, ECMA_INTERNAL_PROPERTY_BOUND_FUNCTION_BOUND_THIS);
|
||||
const ecma_length_t arg_count = arguments_number;
|
||||
ext_function_p->u.bound_function.args_length = args_length;
|
||||
ecma_value_t *args_p = (ecma_value_t *) (ext_function_p + 1);
|
||||
|
||||
if (arg_count > 0)
|
||||
*args_p = ecma_make_simple_value (ECMA_SIMPLE_VALUE_UNDEFINED);
|
||||
|
||||
if (arguments_number > 0)
|
||||
{
|
||||
*bound_this_prop_p = ecma_copy_value_if_not_object (arguments_list_p[0]);
|
||||
}
|
||||
else
|
||||
{
|
||||
*bound_this_prop_p = ecma_make_simple_value (ECMA_SIMPLE_VALUE_UNDEFINED);
|
||||
*args_p = ecma_copy_value_if_not_object (arguments_list_p[0]);
|
||||
}
|
||||
|
||||
if (arg_count > 1)
|
||||
if (arguments_number > 1)
|
||||
{
|
||||
ecma_collection_header_t *bound_args_collection_p;
|
||||
bound_args_collection_p = ecma_new_values_collection (&arguments_list_p[1], arg_count - 1, false);
|
||||
|
||||
ecma_value_t *bound_args_prop_p;
|
||||
bound_args_prop_p = ecma_create_internal_property (function_p, ECMA_INTERNAL_PROPERTY_BOUND_FUNCTION_BOUND_ARGS);
|
||||
ECMA_SET_INTERNAL_VALUE_POINTER (*bound_args_prop_p, bound_args_collection_p);
|
||||
for (ecma_length_t i = 1; i < arguments_number; i++)
|
||||
{
|
||||
++args_p;
|
||||
*args_p = ecma_copy_value_if_not_object (arguments_list_p[i]);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
@ -292,10 +292,8 @@ ecma_builtin_function_prototype_object_bind (ecma_value_t this_arg, /**< this ar
|
||||
JERRY_ASSERT (!ECMA_IS_VALUE_ERROR (get_len_value));
|
||||
JERRY_ASSERT (ecma_is_value_number (get_len_value));
|
||||
|
||||
const ecma_length_t bound_arg_count = arg_count > 1 ? arg_count - 1 : 0;
|
||||
|
||||
/* 15.a */
|
||||
length = ecma_get_number_from_value (get_len_value) - ((ecma_number_t) bound_arg_count);
|
||||
length = ecma_get_number_from_value (get_len_value) - ((ecma_number_t) (args_length - 1));
|
||||
ecma_free_value (get_len_value);
|
||||
|
||||
/* 15.b */
|
||||
|
||||
@ -93,44 +93,6 @@ ecma_is_constructor (ecma_value_t value) /**< ecma value */
|
||||
|| ecma_get_object_type (obj_p) == ECMA_OBJECT_TYPE_EXTERNAL_FUNCTION);
|
||||
} /* ecma_is_constructor */
|
||||
|
||||
/**
|
||||
* Helper function to merge argument lists
|
||||
*
|
||||
* See also:
|
||||
* ECMA-262 v5, 15.3.4.5.1 step 4
|
||||
* ECMA-262 v5, 15.3.4.5.2 step 4
|
||||
*
|
||||
* Used by:
|
||||
* - [[Call]] implementation for Function objects.
|
||||
* - [[Construct]] implementation for Function objects.
|
||||
*/
|
||||
static void
|
||||
ecma_function_bind_merge_arg_lists (ecma_value_t *merged_args_list_p, /**< destination argument list */
|
||||
ecma_collection_header_t *bound_arg_list_p, /**< bound argument list */
|
||||
const ecma_value_t *arguments_list_p, /**< source arguments list */
|
||||
ecma_length_t arguments_list_len) /**< length of source arguments list */
|
||||
{
|
||||
/* Performance optimization: only the values are copied. This is
|
||||
* enough, since the original references keep these objects alive. */
|
||||
|
||||
ecma_collection_iterator_t bound_args_iterator;
|
||||
ecma_collection_iterator_init (&bound_args_iterator, bound_arg_list_p);
|
||||
|
||||
for (ecma_length_t i = bound_arg_list_p->unit_number; i > 0; i--)
|
||||
{
|
||||
bool is_moved = ecma_collection_iterator_next (&bound_args_iterator);
|
||||
JERRY_ASSERT (is_moved);
|
||||
|
||||
*merged_args_list_p++ = *bound_args_iterator.current_value_p;
|
||||
}
|
||||
|
||||
while (arguments_list_len > 0)
|
||||
{
|
||||
*merged_args_list_p++ = *arguments_list_p++;
|
||||
arguments_list_len--;
|
||||
}
|
||||
} /* ecma_function_bind_merge_arg_lists */
|
||||
|
||||
/**
|
||||
* Function object creation operation.
|
||||
*
|
||||
@ -467,11 +429,11 @@ ecma_op_function_has_instance (ecma_object_t *func_obj_p, /**< Function object *
|
||||
JERRY_ASSERT (ecma_get_object_type (func_obj_p) == ECMA_OBJECT_TYPE_BOUND_FUNCTION);
|
||||
|
||||
/* 1. */
|
||||
ecma_value_t *target_function_prop_p;
|
||||
target_function_prop_p = ecma_get_internal_property (func_obj_p,
|
||||
ECMA_INTERNAL_PROPERTY_BOUND_FUNCTION_TARGET_FUNCTION);
|
||||
ecma_extended_object_t *ext_function_p = (ecma_extended_object_t *) func_obj_p;
|
||||
|
||||
ecma_object_t *target_func_obj_p = ECMA_GET_INTERNAL_VALUE_POINTER (ecma_object_t, *target_function_prop_p);
|
||||
ecma_object_t *target_func_obj_p;
|
||||
target_func_obj_p = ECMA_GET_INTERNAL_VALUE_POINTER (ecma_object_t,
|
||||
ext_function_p->u.bound_function.target_function);
|
||||
|
||||
/* 3. */
|
||||
ret_value = ecma_op_object_has_instance (target_func_obj_p, value);
|
||||
@ -600,33 +562,29 @@ ecma_op_function_call (ecma_object_t *func_obj_p, /**< Function object */
|
||||
JERRY_CONTEXT (is_direct_eval_form_call) = false;
|
||||
|
||||
/* 2-3. */
|
||||
ecma_value_t *target_function_prop_p;
|
||||
target_function_prop_p = ecma_get_internal_property (func_obj_p,
|
||||
ECMA_INTERNAL_PROPERTY_BOUND_FUNCTION_TARGET_FUNCTION);
|
||||
ecma_extended_object_t *ext_function_p = (ecma_extended_object_t *) func_obj_p;
|
||||
|
||||
ecma_object_t *target_func_obj_p = ECMA_GET_INTERNAL_VALUE_POINTER (ecma_object_t, *target_function_prop_p);
|
||||
ecma_object_t *target_func_obj_p;
|
||||
target_func_obj_p = ECMA_GET_INTERNAL_VALUE_POINTER (ecma_object_t,
|
||||
ext_function_p->u.bound_function.target_function);
|
||||
|
||||
/* 4. */
|
||||
ecma_value_t *bound_args_prop_p = ecma_find_internal_property (func_obj_p,
|
||||
ECMA_INTERNAL_PROPERTY_BOUND_FUNCTION_BOUND_ARGS);
|
||||
ecma_value_t bound_this_value = *ecma_get_internal_property (func_obj_p,
|
||||
ECMA_INTERNAL_PROPERTY_BOUND_FUNCTION_BOUND_THIS);
|
||||
ecma_value_t *args_p = (ecma_value_t *) (ext_function_p + 1);
|
||||
|
||||
if (bound_args_prop_p != NULL)
|
||||
ecma_value_t bound_this_value = *args_p;
|
||||
ecma_length_t args_length = ext_function_p->u.bound_function.args_length;
|
||||
|
||||
JERRY_ASSERT (args_length > 0);
|
||||
|
||||
if (args_length > 1)
|
||||
{
|
||||
ecma_collection_header_t *bound_arg_list_p;
|
||||
bound_arg_list_p = ECMA_GET_INTERNAL_VALUE_POINTER (ecma_collection_header_t, *bound_args_prop_p);
|
||||
|
||||
JERRY_ASSERT (bound_arg_list_p->unit_number > 0);
|
||||
|
||||
ecma_length_t merged_args_list_len = bound_arg_list_p->unit_number + arguments_list_len;
|
||||
args_length--;
|
||||
ecma_length_t merged_args_list_len = args_length + arguments_list_len;
|
||||
|
||||
JMEM_DEFINE_LOCAL_ARRAY (merged_args_list_p, merged_args_list_len, ecma_value_t);
|
||||
|
||||
ecma_function_bind_merge_arg_lists (merged_args_list_p,
|
||||
bound_arg_list_p,
|
||||
arguments_list_p,
|
||||
arguments_list_len);
|
||||
memcpy (merged_args_list_p, args_p + 1, args_length * sizeof (ecma_value_t));
|
||||
memcpy (merged_args_list_p + args_length, arguments_list_p, arguments_list_len * sizeof (ecma_value_t));
|
||||
|
||||
/* 5. */
|
||||
ret_value = ecma_op_function_call (target_func_obj_p,
|
||||
@ -783,11 +741,11 @@ ecma_op_function_construct (ecma_object_t *func_obj_p, /**< Function object */
|
||||
JERRY_ASSERT (ecma_get_object_type (func_obj_p) == ECMA_OBJECT_TYPE_BOUND_FUNCTION);
|
||||
|
||||
/* 1. */
|
||||
ecma_value_t *target_function_prop_p;
|
||||
target_function_prop_p = ecma_get_internal_property (func_obj_p,
|
||||
ECMA_INTERNAL_PROPERTY_BOUND_FUNCTION_TARGET_FUNCTION);
|
||||
ecma_extended_object_t *ext_function_p = (ecma_extended_object_t *) func_obj_p;
|
||||
|
||||
ecma_object_t *target_func_obj_p = ECMA_GET_INTERNAL_VALUE_POINTER (ecma_object_t, *target_function_prop_p);
|
||||
ecma_object_t *target_func_obj_p;
|
||||
target_func_obj_p = ECMA_GET_INTERNAL_VALUE_POINTER (ecma_object_t,
|
||||
ext_function_p->u.bound_function.target_function);
|
||||
|
||||
/* 2. */
|
||||
if (!ecma_is_constructor (ecma_make_object_value (target_func_obj_p)))
|
||||
@ -797,24 +755,21 @@ ecma_op_function_construct (ecma_object_t *func_obj_p, /**< Function object */
|
||||
else
|
||||
{
|
||||
/* 4. */
|
||||
ecma_value_t *bound_args_prop_p;
|
||||
bound_args_prop_p = ecma_find_internal_property (func_obj_p, ECMA_INTERNAL_PROPERTY_BOUND_FUNCTION_BOUND_ARGS);
|
||||
ecma_length_t args_length = ext_function_p->u.bound_function.args_length;
|
||||
|
||||
if (bound_args_prop_p != NULL)
|
||||
JERRY_ASSERT (args_length > 0);
|
||||
|
||||
if (args_length > 1)
|
||||
{
|
||||
ecma_collection_header_t *bound_arg_list_p;
|
||||
bound_arg_list_p = ECMA_GET_INTERNAL_VALUE_POINTER (ecma_collection_header_t, *bound_args_prop_p);
|
||||
ecma_value_t *args_p = (ecma_value_t *) (ext_function_p + 1);
|
||||
|
||||
JERRY_ASSERT (bound_arg_list_p->unit_number > 0);
|
||||
|
||||
ecma_length_t merged_args_list_len = bound_arg_list_p->unit_number + arguments_list_len;
|
||||
args_length--;
|
||||
ecma_length_t merged_args_list_len = args_length + arguments_list_len;
|
||||
|
||||
JMEM_DEFINE_LOCAL_ARRAY (merged_args_list_p, merged_args_list_len, ecma_value_t);
|
||||
|
||||
ecma_function_bind_merge_arg_lists (merged_args_list_p,
|
||||
bound_arg_list_p,
|
||||
arguments_list_p,
|
||||
arguments_list_len);
|
||||
memcpy (merged_args_list_p, args_p + 1, args_length * sizeof (ecma_value_t));
|
||||
memcpy (merged_args_list_p + args_length, arguments_list_p, arguments_list_len * sizeof (ecma_value_t));
|
||||
|
||||
/* 5. */
|
||||
ret_value = ecma_op_function_construct (target_func_obj_p,
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user