Skip to content

Commit f24be95

Browse files
committed
Optimize conditional jumps.
The ecma_op_to_boolean return value is changed to bool for faster evaluation, and no need to swap operandos of relational compare. JerryScript-DCO-1.0-Signed-off-by: Zoltan Herczeg zherczeg.u-szeged@partner.samsung.com
1 parent 08c312b commit f24be95

File tree

12 files changed

+146
-190
lines changed

12 files changed

+146
-190
lines changed

jerry-core/ecma/base/ecma-globals.h

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -73,12 +73,12 @@ typedef enum
7373
* - immutable binding values
7474
* - special register or stack values for vm
7575
*/
76-
ECMA_SIMPLE_VALUE_EMPTY,
77-
ECMA_SIMPLE_VALUE_UNDEFINED, /**< undefined value */
78-
ECMA_SIMPLE_VALUE_NULL, /**< null value */
76+
ECMA_SIMPLE_VALUE_EMPTY, /**< uninitialized value */
77+
ECMA_SIMPLE_VALUE_ARRAY_HOLE, /**< array hole, used for initialization of an array literal */
7978
ECMA_SIMPLE_VALUE_FALSE, /**< boolean false */
8079
ECMA_SIMPLE_VALUE_TRUE, /**< boolean true */
81-
ECMA_SIMPLE_VALUE_ARRAY_HOLE, /**< array hole, used for initialization of an array literal */
80+
ECMA_SIMPLE_VALUE_UNDEFINED, /**< undefined value */
81+
ECMA_SIMPLE_VALUE_NULL, /**< null value */
8282
ECMA_SIMPLE_VALUE_REGISTER_REF, /**< register reference, a special "base" value for vm */
8383
ECMA_SIMPLE_VALUE__COUNT /** count of simple ecma values */
8484
} ecma_simple_value_t;

jerry-core/ecma/base/ecma-helpers-value.c

Lines changed: 39 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,10 @@ JERRY_STATIC_ASSERT (sizeof (uintptr_t) > sizeof (ecma_value_t),
5959

6060
#endif /* ECMA_VALUE_CAN_STORE_UINTPTR_VALUE_DIRECTLY */
6161

62+
JERRY_STATIC_ASSERT ((ECMA_SIMPLE_VALUE_FALSE | 0x1) == ECMA_SIMPLE_VALUE_TRUE
63+
&& ECMA_SIMPLE_VALUE_FALSE != ECMA_SIMPLE_VALUE_TRUE,
64+
only_the_lowest_bit_must_be_different_for_simple_value_true_and_false);
65+
6266
/**
6367
* Get type field of ecma value
6468
*
@@ -109,6 +113,18 @@ ecma_get_pointer_from_ecma_value (ecma_value_t value) /**< value */
109113
#endif /* ECMA_VALUE_CAN_STORE_UINTPTR_VALUE_DIRECTLY */
110114
} /* ecma_get_pointer_from_ecma_value */
111115

116+
/**
117+
* Check if the value is simple ecma-value.
118+
*
119+
* @return true - if the value is a simple value,
120+
* false - otherwise.
121+
*/
122+
inline bool __attr_pure___ __attr_always_inline___
123+
ecma_is_value_simple (ecma_value_t value) /**< ecma value */
124+
{
125+
return (value & ECMA_DIRECT_TYPE_MASK) == ECMA_DIRECT_TYPE_SIMPLE_VALUE;
126+
} /* ecma_is_value_simple */
127+
112128
/**
113129
* Check whether the value is a given simple value.
114130
*
@@ -167,7 +183,7 @@ ecma_is_value_null (ecma_value_t value) /**< ecma value */
167183
inline bool __attr_pure___ __attr_always_inline___
168184
ecma_is_value_boolean (ecma_value_t value) /**< ecma value */
169185
{
170-
return ecma_is_value_true (value) || ecma_is_value_false (value);
186+
return ecma_is_value_true (value | (1 << ECMA_DIRECT_SHIFT));
171187
} /* ecma_is_value_boolean */
172188

173189
/**
@@ -500,6 +516,14 @@ ecma_get_integer_from_value (ecma_value_t value) /**< ecma value */
500516
return ((ecma_integer_value_t) value) >> ECMA_DIRECT_SHIFT;
501517
} /* ecma_get_integer_from_value */
502518

519+
inline ecma_number_t __attr_pure___ __attr_always_inline___
520+
ecma_get_float_from_value (ecma_value_t value) /**< ecma value */
521+
{
522+
JERRY_ASSERT (ecma_get_value_type_field (value) == ECMA_TYPE_FLOAT);
523+
524+
return *(ecma_number_t *) ecma_get_pointer_from_ecma_value (value);
525+
} /* ecma_get_float_from_value */
526+
503527
/**
504528
* Get floating point value from an ecma value
505529
*
@@ -513,9 +537,7 @@ ecma_get_number_from_value (ecma_value_t value) /**< ecma value */
513537
return (ecma_number_t) ecma_get_integer_from_value (value);
514538
}
515539

516-
JERRY_ASSERT (ecma_get_value_type_field (value) == ECMA_TYPE_FLOAT);
517-
518-
return *(ecma_number_t *) ecma_get_pointer_from_ecma_value (value);
540+
return ecma_get_float_from_value (value);
519541
} /* ecma_get_number_from_value */
520542

521543
/**
@@ -563,6 +585,19 @@ ecma_get_object_from_value (ecma_value_t value) /**< ecma value */
563585
return (ecma_object_t *) ecma_get_pointer_from_ecma_value (value);
564586
} /* ecma_get_object_from_value */
565587

588+
/**
589+
* Invert a boolean value
590+
*
591+
* @return ecma value
592+
*/
593+
inline ecma_value_t __attr_pure___ __attr_always_inline___
594+
ecma_invert_boolean_value (ecma_value_t value) /**< ecma value */
595+
{
596+
JERRY_ASSERT (ecma_is_value_boolean (value));
597+
598+
return (value ^ (1 << ECMA_DIRECT_SHIFT));
599+
} /* ecma_invert_boolean_value */
600+
566601
/**
567602
* Get the value from an error ecma value
568603
*

jerry-core/ecma/base/ecma-helpers.h

Lines changed: 21 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -114,26 +114,27 @@
114114
}
115115

116116
/* ecma-helpers-value.c */
117-
extern bool ecma_is_value_empty (ecma_value_t);
118-
extern bool ecma_is_value_undefined (ecma_value_t);
119-
extern bool ecma_is_value_null (ecma_value_t);
120-
extern bool ecma_is_value_boolean (ecma_value_t);
121-
extern bool ecma_is_value_true (ecma_value_t);
122-
extern bool ecma_is_value_false (ecma_value_t);
123-
extern bool ecma_is_value_array_hole (ecma_value_t);
124-
125-
extern bool ecma_is_value_integer_number (ecma_value_t);
126-
extern bool ecma_are_values_integer_numbers (ecma_value_t, ecma_value_t);
127-
extern bool ecma_is_value_float_number (ecma_value_t);
128-
extern bool ecma_is_value_number (ecma_value_t);
129-
extern bool ecma_is_value_string (ecma_value_t);
130-
extern bool ecma_is_value_object (ecma_value_t);
131-
extern bool ecma_is_value_error (ecma_value_t);
117+
extern bool ecma_is_value_simple (ecma_value_t) __attr_pure___;
118+
extern bool ecma_is_value_empty (ecma_value_t) __attr_pure___;
119+
extern bool ecma_is_value_undefined (ecma_value_t) __attr_pure___;
120+
extern bool ecma_is_value_null (ecma_value_t) __attr_pure___;
121+
extern bool ecma_is_value_boolean (ecma_value_t) __attr_pure___;
122+
extern bool ecma_is_value_true (ecma_value_t) __attr_pure___;
123+
extern bool ecma_is_value_false (ecma_value_t) __attr_pure___;
124+
extern bool ecma_is_value_array_hole (ecma_value_t) __attr_pure___;
125+
126+
extern bool ecma_is_value_integer_number (ecma_value_t) __attr_pure___;
127+
extern bool ecma_are_values_integer_numbers (ecma_value_t, ecma_value_t) __attr_pure___;
128+
extern bool ecma_is_value_float_number (ecma_value_t) __attr_pure___;
129+
extern bool ecma_is_value_number (ecma_value_t) __attr_pure___;
130+
extern bool ecma_is_value_string (ecma_value_t) __attr_pure___;
131+
extern bool ecma_is_value_object (ecma_value_t) __attr_pure___;
132+
extern bool ecma_is_value_error (ecma_value_t) __attr_pure___;
132133

133134
extern void ecma_check_value_type_is_spec_defined (ecma_value_t);
134135

135-
extern ecma_value_t ecma_make_simple_value (const ecma_simple_value_t value);
136-
extern ecma_value_t ecma_make_integer_value (ecma_integer_value_t);
136+
extern ecma_value_t ecma_make_simple_value (const ecma_simple_value_t value) __attr_const___;
137+
extern ecma_value_t ecma_make_integer_value (ecma_integer_value_t) __attr_const___;
137138
extern ecma_value_t ecma_make_nan_value (void);
138139
extern ecma_value_t ecma_make_number_value (ecma_number_t);
139140
extern ecma_value_t ecma_make_int32_value (int32_t);
@@ -142,12 +143,14 @@ extern ecma_value_t ecma_make_string_value (const ecma_string_t *);
142143
extern ecma_value_t ecma_make_object_value (const ecma_object_t *);
143144
extern ecma_value_t ecma_make_error_value (ecma_value_t);
144145
extern ecma_value_t ecma_make_error_obj_value (const ecma_object_t *);
145-
extern ecma_integer_value_t ecma_get_integer_from_value (ecma_value_t);
146+
extern ecma_integer_value_t ecma_get_integer_from_value (ecma_value_t) __attr_pure___;
147+
extern ecma_number_t ecma_get_float_from_value (ecma_value_t value) __attr_pure___;
146148
extern ecma_number_t ecma_get_number_from_value (ecma_value_t) __attr_pure___;
147149
extern uint32_t ecma_get_uint32_from_value (ecma_value_t) __attr_pure___;
148150
extern ecma_string_t *ecma_get_string_from_value (ecma_value_t) __attr_pure___;
149151
extern ecma_object_t *ecma_get_object_from_value (ecma_value_t) __attr_pure___;
150152
extern ecma_value_t ecma_get_value_from_error_value (ecma_value_t) __attr_pure___;
153+
extern ecma_value_t ecma_invert_boolean_value (ecma_value_t) __attr_pure___;
151154
extern ecma_value_t ecma_copy_value (ecma_value_t);
152155
extern ecma_value_t ecma_fast_copy_value (ecma_value_t);
153156
extern ecma_value_t ecma_copy_value_if_not_object (ecma_value_t);

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

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2027,8 +2027,8 @@ ecma_builtin_array_prototype_object_every (ecma_value_t this_arg, /**< this argu
20272027
/* 7.c.ii */
20282028
ECMA_TRY_CATCH (call_value, ecma_op_function_call (func_object_p, arg2, call_args, 3), ret_value);
20292029

2030-
/* 7.c.iii, ecma_op_to_boolean always returns a simple value, so no need to free. */
2031-
if (ecma_is_value_false (ecma_op_to_boolean (call_value)))
2030+
/* 7.c.iii */
2031+
if (!ecma_op_to_boolean (call_value))
20322032
{
20332033
ret_value = ecma_make_simple_value (ECMA_SIMPLE_VALUE_FALSE);
20342034
}
@@ -2125,8 +2125,8 @@ ecma_builtin_array_prototype_object_some (ecma_value_t this_arg, /**< this argum
21252125
/* 7.c.ii */
21262126
ECMA_TRY_CATCH (call_value, ecma_op_function_call (func_object_p, arg2, call_args, 3), ret_value);
21272127

2128-
/* 7.c.iii, ecma_op_to_boolean always returns a simple value, so no need to free. */
2129-
if (ecma_is_value_true (ecma_op_to_boolean (call_value)))
2128+
/* 7.c.iii */
2129+
if (ecma_op_to_boolean (call_value))
21302130
{
21312131
ret_value = ecma_make_simple_value (ECMA_SIMPLE_VALUE_TRUE);
21322132
}
@@ -2430,8 +2430,8 @@ ecma_builtin_array_prototype_object_filter (ecma_value_t this_arg, /**< this arg
24302430
/* 9.c.ii */
24312431
ECMA_TRY_CATCH (call_value, ecma_op_function_call (func_object_p, arg2, call_args, 3), ret_value);
24322432

2433-
/* 9.c.iii, ecma_op_to_boolean always returns a simple value, so no need to free. */
2434-
if (ecma_is_value_true (ecma_op_to_boolean (call_value)))
2433+
/* 9.c.iii */
2434+
if (ecma_op_to_boolean (call_value))
24352435
{
24362436
ecma_string_t *to_index_string_p = ecma_new_ecma_string_from_uint32 (new_array_index);
24372437

jerry-core/ecma/builtin-objects/ecma-builtin-boolean.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,8 @@ ecma_builtin_boolean_dispatch_call (const ecma_value_t *arguments_list_p, /**< a
6666
arg_value = arguments_list_p[0];
6767
}
6868

69-
return ecma_op_to_boolean (arg_value);
69+
return ecma_make_simple_value (ecma_op_to_boolean (arg_value) ? ECMA_SIMPLE_VALUE_TRUE
70+
: ECMA_SIMPLE_VALUE_FALSE);
7071
} /* ecma_builtin_boolean_dispatch_call */
7172

7273
/**

jerry-core/ecma/operations/ecma-boolean-object.c

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -41,12 +41,7 @@
4141
ecma_value_t
4242
ecma_op_create_boolean_object (ecma_value_t arg) /**< argument passed to the Boolean constructor */
4343
{
44-
ecma_value_t conv_to_boolean_completion = ecma_op_to_boolean (arg);
45-
46-
if (ecma_is_value_error (conv_to_boolean_completion))
47-
{
48-
return conv_to_boolean_completion;
49-
}
44+
bool boolean_value = ecma_op_to_boolean (arg);
5045

5146
#ifndef CONFIG_ECMA_COMPACT_PROFILE_DISABLE_BOOLEAN_BUILTIN
5247
ecma_object_t *prototype_obj_p = ecma_builtin_get (ECMA_BUILTIN_ID_BOOLEAN_PROTOTYPE);
@@ -64,7 +59,11 @@ ecma_op_create_boolean_object (ecma_value_t arg) /**< argument passed to the Boo
6459

6560
ecma_property_t *prim_value_prop_p = ecma_create_internal_property (obj_p,
6661
ECMA_INTERNAL_PROPERTY_ECMA_VALUE);
67-
ecma_set_internal_property_value (prim_value_prop_p, conv_to_boolean_completion);
62+
63+
ecma_value_t prim_value = ecma_make_simple_value (boolean_value ? ECMA_SIMPLE_VALUE_TRUE
64+
: ECMA_SIMPLE_VALUE_FALSE);
65+
66+
ecma_set_internal_property_value (prim_value_prop_p, prim_value);
6867

6968
return ecma_make_object_value (obj_p);
7069
} /* ecma_op_create_boolean_object */

jerry-core/ecma/operations/ecma-comparison.c

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -334,15 +334,12 @@ ecma_op_abstract_relational_compare (ecma_value_t x, /**< first operand */
334334
{
335335
ecma_value_t ret_value = ecma_make_simple_value (ECMA_SIMPLE_VALUE_EMPTY);
336336

337-
ecma_value_t first_converted_value = left_first ? x : y;
338-
ecma_value_t second_converted_value = left_first ? y : x;
339-
340337
// 1., 2.
341338
ECMA_TRY_CATCH (prim_first_converted_value,
342-
ecma_op_to_primitive (first_converted_value, ECMA_PREFERRED_TYPE_NUMBER),
339+
ecma_op_to_primitive (x, ECMA_PREFERRED_TYPE_NUMBER),
343340
ret_value);
344341
ECMA_TRY_CATCH (prim_second_converted_value,
345-
ecma_op_to_primitive (second_converted_value, ECMA_PREFERRED_TYPE_NUMBER),
342+
ecma_op_to_primitive (y, ECMA_PREFERRED_TYPE_NUMBER),
346343
ret_value);
347344

348345
const ecma_value_t px = left_first ? prim_first_converted_value : prim_second_converted_value;

0 commit comments

Comments
 (0)