diff --git a/jerry-core/ecma/base/ecma-alloc.c b/jerry-core/ecma/base/ecma-alloc.c index 47ad33709..7afabbdb6 100644 --- a/jerry-core/ecma/base/ecma-alloc.c +++ b/jerry-core/ecma/base/ecma-alloc.c @@ -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 * @{ * diff --git a/jerry-core/ecma/base/ecma-gc.c b/jerry-core/ecma/base/ecma-gc.c index 20240522d..52db59a96 100644 --- a/jerry-core/ecma/base/ecma-gc.c +++ b/jerry-core/ecma/base/ecma-gc.c @@ -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); diff --git a/jerry-core/ecma/base/ecma-globals.h b/jerry-core/ecma/base/ecma-globals.h index 0a88707bf..4093d4afd 100644 --- a/jerry-core/ecma/base/ecma-globals.h +++ b/jerry-core/ecma/base/ecma-globals.h @@ -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; diff --git a/jerry-core/ecma/base/ecma-helpers.c b/jerry-core/ecma/base/ecma-helpers.c index c3112534b..33a9878d3 100644 --- a/jerry-core/ecma/base/ecma-helpers.c +++ b/jerry-core/ecma/base/ecma-helpers.c @@ -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; diff --git a/jerry-core/ecma/builtin-objects/ecma-builtin-function-prototype.c b/jerry-core/ecma/builtin-objects/ecma-builtin-function-prototype.c index 408e68487..8b7e9ac58 100644 --- a/jerry-core/ecma/builtin-objects/ecma-builtin-function-prototype.c +++ b/jerry-core/ecma/builtin-objects/ecma-builtin-function-prototype.c @@ -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 */ diff --git a/jerry-core/ecma/operations/ecma-function-object.c b/jerry-core/ecma/operations/ecma-function-object.c index 08ddfb830..64ca1bee6 100644 --- a/jerry-core/ecma/operations/ecma-function-object.c +++ b/jerry-core/ecma/operations/ecma-function-object.c @@ -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,