Skip to content

Commit bc091e1

Browse files
author
Robert Fancsik
authored
Optimize ecma_op_function_call (jerryscript-project#4817)
Remove redundant isCallable checks JerryScript-DCO-1.0-Signed-off-by: Robert Fancsik [email protected]
1 parent 7ea0000 commit bc091e1

11 files changed

+317
-362
lines changed

jerry-core/api/jerry.c

Lines changed: 24 additions & 74 deletions
Original file line numberDiff line numberDiff line change
@@ -4080,61 +4080,6 @@ jerry_property_descriptor_free (const jerry_property_descriptor_t *prop_desc_p)
40804080
}
40814081
} /* jerry_property_descriptor_free */
40824082

4083-
/**
4084-
* Invoke function specified by a function value
4085-
*
4086-
* Note:
4087-
* - returned value must be freed with jerry_release_value, when it is no longer needed.
4088-
* - If function is invoked as constructor, it should support [[Construct]] method,
4089-
* otherwise, if function is simply called - it should support [[Call]] method.
4090-
*
4091-
* @return returned jerry value of the invoked function
4092-
*/
4093-
static jerry_value_t
4094-
jerry_invoke_function (bool is_invoke_as_constructor, /**< true - invoke function as constructor
4095-
* (this_arg_p should be NULL, as it is ignored),
4096-
* false - perform function call */
4097-
const jerry_value_t func_obj_val, /**< function object to call */
4098-
const jerry_value_t this_val, /**< object value of 'this' binding */
4099-
const jerry_value_t args_p[], /**< function's call arguments */
4100-
const jerry_size_t args_count) /**< number of the arguments */
4101-
{
4102-
JERRY_ASSERT (args_count == 0 || args_p != NULL);
4103-
4104-
if (ecma_is_value_error_reference (func_obj_val)
4105-
|| ecma_is_value_error_reference (this_val))
4106-
{
4107-
return jerry_throw (ecma_raise_type_error (ECMA_ERR_MSG (ecma_error_value_msg_p)));
4108-
}
4109-
4110-
for (uint32_t i = 0; i < args_count; i++)
4111-
{
4112-
if (ecma_is_value_error_reference (args_p[i]))
4113-
{
4114-
return jerry_throw (ecma_raise_type_error (ECMA_ERR_MSG (ecma_error_value_msg_p)));
4115-
}
4116-
}
4117-
4118-
if (is_invoke_as_constructor)
4119-
{
4120-
JERRY_ASSERT (jerry_value_is_constructor (func_obj_val));
4121-
4122-
return jerry_return (ecma_op_function_construct (ecma_get_object_from_value (func_obj_val),
4123-
ecma_get_object_from_value (func_obj_val),
4124-
args_p,
4125-
args_count));
4126-
}
4127-
else
4128-
{
4129-
JERRY_ASSERT (jerry_value_is_function (func_obj_val));
4130-
4131-
return jerry_return (ecma_op_function_call (ecma_get_object_from_value (func_obj_val),
4132-
this_val,
4133-
args_p,
4134-
args_count));
4135-
}
4136-
} /* jerry_invoke_function */
4137-
41384083
/**
41394084
* Call function specified by a function value
41404085
*
@@ -4152,20 +4097,23 @@ jerry_call_function (const jerry_value_t func_obj_val, /**< function object to c
41524097
{
41534098
jerry_assert_api_available ();
41544099

4155-
if (jerry_value_is_function (func_obj_val) && !ecma_is_value_error_reference (this_val))
4100+
if (ecma_is_value_error_reference (this_val))
4101+
{
4102+
return jerry_throw (ecma_raise_type_error (ECMA_ERR_MSG (ecma_error_wrong_args_msg_p)));
4103+
}
4104+
4105+
for (jerry_size_t i = 0; i < args_count; i++)
41564106
{
4157-
for (jerry_size_t i = 0; i < args_count; i++)
4107+
if (ecma_is_value_error_reference (args_p[i]))
41584108
{
4159-
if (ecma_is_value_error_reference (args_p[i]))
4160-
{
4161-
return jerry_throw (ecma_raise_type_error (ECMA_ERR_MSG (ecma_error_value_msg_p)));
4162-
}
4109+
return jerry_throw (ecma_raise_type_error (ECMA_ERR_MSG (ecma_error_value_msg_p)));
41634110
}
4164-
4165-
return jerry_invoke_function (false, func_obj_val, this_val, args_p, args_count);
41664111
}
41674112

4168-
return jerry_throw (ecma_raise_type_error (ECMA_ERR_MSG (ecma_error_wrong_args_msg_p)));
4113+
return jerry_return (ecma_op_function_validated_call (func_obj_val,
4114+
this_val,
4115+
args_p,
4116+
args_count));
41694117
} /* jerry_call_function */
41704118

41714119
/**
@@ -4185,21 +4133,23 @@ jerry_construct_object (const jerry_value_t func_obj_val, /**< function object t
41854133
{
41864134
jerry_assert_api_available ();
41874135

4188-
if (jerry_value_is_constructor (func_obj_val))
4136+
if (!jerry_value_is_constructor (func_obj_val))
4137+
{
4138+
return jerry_throw (ecma_raise_type_error (ECMA_ERR_MSG (ecma_error_wrong_args_msg_p)));
4139+
}
4140+
4141+
for (jerry_size_t i = 0; i < args_count; i++)
41894142
{
4190-
for (jerry_size_t i = 0; i < args_count; i++)
4143+
if (ecma_is_value_error_reference (args_p[i]))
41914144
{
4192-
if (ecma_is_value_error_reference (args_p[i]))
4193-
{
4194-
return jerry_throw (ecma_raise_type_error (ECMA_ERR_MSG (ecma_error_value_msg_p)));
4195-
}
4145+
return jerry_throw (ecma_raise_type_error (ECMA_ERR_MSG (ecma_error_value_msg_p)));
41964146
}
4197-
4198-
ecma_value_t this_val = ECMA_VALUE_UNDEFINED;
4199-
return jerry_invoke_function (true, func_obj_val, this_val, args_p, args_count);
42004147
}
42014148

4202-
return jerry_throw (ecma_raise_type_error (ECMA_ERR_MSG (ecma_error_wrong_args_msg_p)));
4149+
return jerry_return (ecma_op_function_construct (ecma_get_object_from_value (func_obj_val),
4150+
ecma_get_object_from_value (func_obj_val),
4151+
args_p,
4152+
args_count));
42034153
} /* jerry_construct_object */
42044154

42054155
/**

jerry-core/ecma/builtin-objects/ecma-builtin-async-from-sync-iterator-prototype.c

Lines changed: 2 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -241,19 +241,8 @@ ecma_builtin_async_from_sync_iterator_prototype_do (ecma_async_from_sync_iterato
241241
}
242242

243243
/* 8. */
244-
ecma_value_t call_result;
245-
246-
if (!ecma_op_is_callable (method))
247-
{
248-
ecma_free_value (method);
249-
call_result = ecma_raise_type_error (ECMA_ERR_MSG (ecma_error_expected_a_function));
250-
}
251-
else
252-
{
253-
ecma_object_t *method_func_obj = ecma_get_object_from_value (method);
254-
call_result = ecma_op_function_call (method_func_obj, sync_iterator, &call_arg, arg_size);
255-
ecma_deref_object (method_func_obj);
256-
}
244+
ecma_value_t call_result = ecma_op_function_validated_call (method, sync_iterator, &call_arg, arg_size);
245+
ecma_free_value (method);
257246

258247
/* 9. */
259248
if (ECMA_IS_VALUE_ERROR (ecma_op_if_abrupt_reject_promise (&call_result, capability_obj_p)))

jerry-core/ecma/builtin-objects/ecma-builtin-string-prototype.c

Lines changed: 6 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -584,18 +584,10 @@ ecma_builtin_string_prototype_object_replace_helper (ecma_value_t this_value, /*
584584

585585
if (!ecma_is_value_undefined (replace_symbol) && !ecma_is_value_null (replace_symbol))
586586
{
587-
if (!ecma_op_is_callable (replace_symbol))
588-
{
589-
ecma_free_value (replace_symbol);
590-
return ecma_raise_type_error (ECMA_ERR_MSG ("@@replace is not callable"));
591-
}
592-
593-
ecma_object_t *replace_method = ecma_get_object_from_value (replace_symbol);
594-
595587
ecma_value_t arguments[] = { this_value, replace_value };
596-
ecma_value_t replace_result = ecma_op_function_call (replace_method, search_value, arguments, 2);
588+
ecma_value_t replace_result = ecma_op_function_validated_call (replace_symbol, search_value, arguments, 2);
589+
ecma_free_value (replace_symbol);
597590

598-
ecma_deref_object (replace_method);
599591
return replace_result;
600592
}
601593
}
@@ -800,16 +792,8 @@ ecma_builtin_string_prototype_object_search (ecma_value_t this_value, /**< this
800792

801793
if (!ecma_is_value_undefined (search_symbol) && !ecma_is_value_null (search_symbol))
802794
{
803-
if (!ecma_op_is_callable (search_symbol))
804-
{
805-
ecma_free_value (search_symbol);
806-
return ecma_raise_type_error (ECMA_ERR_MSG ("@@search is not callable"));
807-
}
808-
809-
ecma_object_t *search_method = ecma_get_object_from_value (search_symbol);
810-
ecma_value_t search_result = ecma_op_function_call (search_method, regexp_value, &this_value, 1);
811-
812-
ecma_deref_object (search_method);
795+
ecma_value_t search_result = ecma_op_function_validated_call (search_symbol, regexp_value, &this_value, 1);
796+
ecma_free_value (search_symbol);
813797
return search_result;
814798
}
815799
}
@@ -977,18 +961,10 @@ ecma_builtin_string_prototype_object_split (ecma_value_t this_value, /**< this a
977961

978962
if (!ecma_is_value_undefined (split_symbol) && !ecma_is_value_null (split_symbol))
979963
{
980-
if (!ecma_op_is_callable (split_symbol))
981-
{
982-
ecma_free_value (split_symbol);
983-
return ecma_raise_type_error (ECMA_ERR_MSG ("@@split is not callable"));
984-
}
985-
986-
ecma_object_t *split_method_p = ecma_get_object_from_value (split_symbol);
987-
988964
ecma_value_t arguments[] = { this_value, limit_value };
989-
ecma_value_t split_result = ecma_op_function_call (split_method_p, separator_value, arguments, 2);
965+
ecma_value_t split_result = ecma_op_function_validated_call (split_symbol, separator_value, arguments, 2);
966+
ecma_free_value (split_symbol);
990967

991-
ecma_deref_object (split_method_p);
992968
return split_result;
993969
}
994970
}

jerry-core/ecma/operations/ecma-async-generator-object.c

Lines changed: 7 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -97,29 +97,21 @@ ecma_async_generator_enqueue (vm_executable_object_t *async_generator_object_p,
9797
static ecma_value_t
9898
ecma_async_yield_call (ecma_value_t function, /**< function (takes reference) */
9999
vm_executable_object_t *async_generator_object_p, /**< async generator */
100-
ecma_value_t argument, /**< argument passed to the function */
101-
const char *error_msg_p) /**< error message when the function is not callable */
100+
ecma_value_t argument) /**< argument passed to the function */
102101
{
103-
if (!ecma_is_value_object (function) || !ecma_op_is_callable (function))
104-
{
105-
ecma_free_value (function);
106-
return ecma_raise_type_error (error_msg_p);
107-
}
108-
109-
ecma_object_t *return_obj_p = ecma_get_object_from_value (function);
110102
ecma_value_t iterator = async_generator_object_p->iterator;
111103
ecma_value_t result;
112104

113105
if (argument == ECMA_VALUE_EMPTY)
114106
{
115-
result = ecma_op_function_call (return_obj_p, iterator, NULL, 0);
107+
result = ecma_op_function_validated_call (function, iterator, NULL, 0);
116108
}
117109
else
118110
{
119-
result = ecma_op_function_call (return_obj_p, iterator, &argument, 1);
111+
result = ecma_op_function_validated_call (function, iterator, &argument, 1);
120112
}
121113

122-
ecma_deref_object (return_obj_p);
114+
ecma_free_value (function);
123115

124116
if (ECMA_IS_VALUE_ERROR (result))
125117
{
@@ -155,8 +147,7 @@ ecma_async_yield_throw (vm_executable_object_t *async_generator_object_p, /**< a
155147

156148
result = ecma_async_yield_call (result,
157149
async_generator_object_p,
158-
ECMA_VALUE_EMPTY,
159-
ECMA_ERR_MSG ("Iterator 'return' is not callable"));
150+
ECMA_VALUE_EMPTY);
160151

161152
if (ECMA_IS_VALUE_ERROR (result))
162153
{
@@ -169,8 +160,7 @@ ecma_async_yield_throw (vm_executable_object_t *async_generator_object_p, /**< a
169160

170161
result = ecma_async_yield_call (result,
171162
async_generator_object_p,
172-
value,
173-
ECMA_ERR_MSG ("Iterator 'throw' is not callable"));
163+
value);
174164

175165
if (ECMA_IS_VALUE_ERROR (result))
176166
{
@@ -419,8 +409,7 @@ ecma_await_continue (vm_executable_object_t *executable_object_p, /**< executabl
419409

420410
result = ecma_async_yield_call (result,
421411
executable_object_p,
422-
value,
423-
ECMA_ERR_MSG ("Iterator 'return' is not callable"));
412+
value);
424413
ecma_free_value (value);
425414

426415
if (ECMA_IS_VALUE_ERROR (result))

0 commit comments

Comments
 (0)