Skip to content

Commit f158dd4

Browse files
rerobikadbatyai
authored andcommitted
Use custom dispatcher for Object.prototype routines (#2965)
Binary size gain: - Intel: ~250B (gcc-7.3) - Arm: ~65B (arm-linux-gnueabi-gcc-7.3) Co-authored-by: Gabor Loki loki@inf.u-szeged.hu JerryScript-DCO-1.0-Signed-off-by: Robert Fancsik frobert@inf.u-szeged.hu
1 parent 603cd88 commit f158dd4

2 files changed

Lines changed: 156 additions & 104 deletions

File tree

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

Lines changed: 150 additions & 98 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,27 @@
3030
#define ECMA_BUILTINS_INTERNAL
3131
#include "ecma-builtins-internal.h"
3232

33+
/**
34+
* This object has a custom dispatch function.
35+
*/
36+
#define BUILTIN_CUSTOM_DISPATCH
37+
38+
/**
39+
* List of built-in routine identifiers.
40+
*/
41+
enum
42+
{
43+
/* Note: these 6 routines must be in this order */
44+
ECMA_OBJECT_PROTOTYPE_ROUTINE_START = ECMA_BUILTIN_ID__COUNT - 1,
45+
ECMA_OBJECT_PROTOTYPE_TO_STRING,
46+
ECMA_OBJECT_PROTOTYPE_VALUE_OF,
47+
ECMA_OBJECT_PROTOTYPE_TO_LOCALE_STRING,
48+
ECMA_OBJECT_PROTOTYPE_IS_PROTOTYPE_OF,
49+
ECMA_OBJECT_PROTOTYPE_HAS_OWN_PROPERTY,
50+
ECMA_OBJECT_PROTOTYPE_PROPERTY_IS_ENUMERABLE,
51+
};
52+
53+
3354
#define BUILTIN_INC_HEADER_NAME "ecma-builtin-object-prototype.inc.h"
3455
#define BUILTIN_UNDERSCORED_ID object_prototype
3556
#include "ecma-builtin-internal-routines-template.inc.h"
@@ -84,37 +105,30 @@ ecma_builtin_object_prototype_object_value_of (ecma_value_t this_arg) /**< this
84105
* Returned value must be freed with ecma_free_value.
85106
*/
86107
static ecma_value_t
87-
ecma_builtin_object_prototype_object_to_locale_string (ecma_value_t this_arg) /**< this argument */
108+
ecma_builtin_object_prototype_object_to_locale_string (ecma_object_t *obj_p) /**< this argument */
88109
{
89-
ecma_value_t return_value = ECMA_VALUE_EMPTY;
90-
/* 1. */
91-
ECMA_TRY_CATCH (obj_val,
92-
ecma_op_to_object (this_arg),
93-
return_value);
94-
95-
ecma_object_t *obj_p = ecma_get_object_from_value (obj_val);
96-
97110
/* 2. */
98-
ECMA_TRY_CATCH (to_string_val,
99-
ecma_op_object_get_by_magic_id (obj_p, LIT_MAGIC_STRING_TO_STRING_UL),
100-
return_value);
111+
ecma_value_t to_string_val = ecma_op_object_get_by_magic_id (obj_p, LIT_MAGIC_STRING_TO_STRING_UL);
101112

102-
/* 3. */
103-
if (!ecma_op_is_callable (to_string_val))
113+
if (ECMA_IS_VALUE_ERROR (to_string_val))
104114
{
105-
return_value = ecma_raise_type_error (ECMA_ERR_MSG ("'toString is missing or not a function.'"));
115+
return to_string_val;
106116
}
107-
else
117+
118+
/* 3. */
119+
if (!ecma_op_is_callable (to_string_val))
108120
{
109-
/* 4. */
110-
ecma_object_t *to_string_func_obj_p = ecma_get_object_from_value (to_string_val);
111-
return_value = ecma_op_function_call (to_string_func_obj_p, this_arg, NULL, 0);
121+
ecma_free_value (to_string_val);
122+
return ecma_raise_type_error (ECMA_ERR_MSG ("'toString is missing or not a function.'"));
112123
}
113124

114-
ECMA_FINALIZE (to_string_val);
115-
ECMA_FINALIZE (obj_val);
125+
/* 4. */
126+
ecma_object_t *to_string_func_obj_p = ecma_get_object_from_value (to_string_val);
127+
ecma_value_t ret_value = ecma_op_function_call (to_string_func_obj_p, ecma_make_object_value (obj_p), NULL, 0);
128+
129+
ecma_deref_object (to_string_func_obj_p);
116130

117-
return return_value;
131+
return ret_value;
118132
} /* ecma_builtin_object_prototype_object_to_locale_string */
119133

120134
/**
@@ -127,33 +141,10 @@ ecma_builtin_object_prototype_object_to_locale_string (ecma_value_t this_arg) /*
127141
* Returned value must be freed with ecma_free_value.
128142
*/
129143
static ecma_value_t
130-
ecma_builtin_object_prototype_object_has_own_property (ecma_value_t this_arg, /**< this argument */
131-
ecma_value_t arg) /**< first argument */
144+
ecma_builtin_object_prototype_object_has_own_property (ecma_object_t *obj_p, /**< this argument */
145+
ecma_string_t *prop_name_p) /**< first argument */
132146
{
133-
ecma_value_t return_value = ECMA_VALUE_EMPTY;
134-
135-
/* 1. */
136-
ECMA_TRY_CATCH (to_string_val,
137-
ecma_op_to_string (arg),
138-
return_value);
139-
140-
/* 2. */
141-
ECMA_TRY_CATCH (obj_val,
142-
ecma_op_to_object (this_arg),
143-
return_value);
144-
145-
ecma_string_t *property_name_string_p = ecma_get_string_from_value (to_string_val);
146-
147-
ecma_object_t *obj_p = ecma_get_object_from_value (obj_val);
148-
149-
/* 3. */
150-
return_value = ecma_make_boolean_value (ecma_op_object_has_own_property (obj_p, property_name_string_p));
151-
152-
ECMA_FINALIZE (obj_val);
153-
154-
ECMA_FINALIZE (to_string_val);
155-
156-
return return_value;
147+
return ecma_make_boolean_value (ecma_op_object_has_own_property (obj_p, prop_name_p));
157148
} /* ecma_builtin_object_prototype_object_has_own_property */
158149

159150
/**
@@ -166,38 +157,24 @@ ecma_builtin_object_prototype_object_has_own_property (ecma_value_t this_arg, /*
166157
* Returned value must be freed with ecma_free_value.
167158
*/
168159
static ecma_value_t
169-
ecma_builtin_object_prototype_object_is_prototype_of (ecma_value_t this_arg, /**< this argument */
160+
ecma_builtin_object_prototype_object_is_prototype_of (ecma_object_t *obj_p, /**< this argument */
170161
ecma_value_t arg) /**< routine's first argument */
171162
{
172-
/* 1. Is the argument an object? */
173-
if (!ecma_is_value_object (arg))
163+
/* 3. Compare prototype to object */
164+
ecma_value_t v_obj_value = ecma_op_to_object (arg);
165+
166+
if (ECMA_IS_VALUE_ERROR (v_obj_value))
174167
{
175-
return ECMA_VALUE_FALSE;
168+
return v_obj_value;
176169
}
177170

178-
ecma_value_t return_value = ECMA_VALUE_EMPTY;
179-
180-
/* 2. ToObject(this) */
181-
ECMA_TRY_CATCH (obj_value,
182-
ecma_op_to_object (this_arg),
183-
return_value);
184-
185-
ecma_object_t *obj_p = ecma_get_object_from_value (obj_value);
186-
187-
/* 3. Compare prototype to object */
188-
ECMA_TRY_CATCH (v_obj_value,
189-
ecma_op_to_object (arg),
190-
return_value);
191-
192171
ecma_object_t *v_obj_p = ecma_get_object_from_value (v_obj_value);
193172

194-
bool is_prototype_of = ecma_op_object_is_prototype_of (obj_p, v_obj_p);
195-
return_value = ecma_make_boolean_value (is_prototype_of);
196-
ECMA_FINALIZE (v_obj_value);
173+
ecma_value_t ret_value = ecma_make_boolean_value (ecma_op_object_is_prototype_of (obj_p, v_obj_p));
197174

198-
ECMA_FINALIZE (obj_value);
175+
ecma_deref_object (v_obj_p);
199176

200-
return return_value;
177+
return ret_value;
201178
} /* ecma_builtin_object_prototype_object_is_prototype_of */
202179

203180
/**
@@ -210,49 +187,124 @@ ecma_builtin_object_prototype_object_is_prototype_of (ecma_value_t this_arg, /**
210187
* Returned value must be freed with ecma_free_value.
211188
*/
212189
static ecma_value_t
213-
ecma_builtin_object_prototype_object_property_is_enumerable (ecma_value_t this_arg, /**< this argument */
214-
ecma_value_t arg) /**< routine's first argument */
190+
ecma_builtin_object_prototype_object_property_is_enumerable (ecma_object_t *obj_p, /**< this argument */
191+
ecma_string_t *prop_name_p) /**< first argument */
215192
{
216-
ecma_value_t return_value = ECMA_VALUE_EMPTY;
217-
218-
/* 1. */
219-
ECMA_TRY_CATCH (to_string_val,
220-
ecma_op_to_string (arg),
221-
return_value);
222-
223-
/* 2. */
224-
ECMA_TRY_CATCH (obj_val,
225-
ecma_op_to_object (this_arg),
226-
return_value);
227-
228-
ecma_string_t *property_name_string_p = ecma_get_string_from_value (to_string_val);
229-
230-
ecma_object_t *obj_p = ecma_get_object_from_value (obj_val);
231-
232193
/* 3. */
233194
ecma_property_t property = ecma_op_object_get_own_property (obj_p,
234-
property_name_string_p,
195+
prop_name_p,
235196
NULL,
236197
ECMA_PROPERTY_GET_NO_OPTIONS);
237198

238199
/* 4. */
239200
if (property != ECMA_PROPERTY_TYPE_NOT_FOUND && property != ECMA_PROPERTY_TYPE_NOT_FOUND_AND_STOP)
240201
{
241-
bool is_enumerable = ecma_is_property_enumerable (property);
202+
return ecma_make_boolean_value (ecma_is_property_enumerable (property));
203+
}
204+
205+
return ECMA_VALUE_FALSE;
206+
} /* ecma_builtin_object_prototype_object_property_is_enumerable */
207+
208+
/**
209+
* Dispatcher of the built-in's routines
210+
*
211+
* @return ecma value
212+
* Returned value must be freed with ecma_free_value.
213+
*/
214+
ecma_value_t
215+
ecma_builtin_object_prototype_dispatch_routine (uint16_t builtin_routine_id, /**< built-in wide routine
216+
* identifier */
217+
ecma_value_t this_arg, /**< 'this' argument value */
218+
const ecma_value_t arguments_list_p[], /**< list of arguments
219+
* passed to routine */
220+
ecma_length_t arguments_number) /**< length of arguments' list */
221+
{
222+
JERRY_UNUSED (arguments_number);
223+
224+
/* no specialization */
225+
if (builtin_routine_id <= ECMA_OBJECT_PROTOTYPE_VALUE_OF)
226+
{
227+
if (builtin_routine_id == ECMA_OBJECT_PROTOTYPE_TO_STRING)
228+
{
229+
return ecma_builtin_object_prototype_object_to_string (this_arg);
230+
}
242231

243-
return_value = ecma_make_boolean_value (is_enumerable);
232+
JERRY_ASSERT (builtin_routine_id <= ECMA_OBJECT_PROTOTYPE_VALUE_OF);
233+
234+
return ecma_builtin_object_prototype_object_value_of (this_arg);
244235
}
245-
else
236+
237+
if (builtin_routine_id <= ECMA_OBJECT_PROTOTYPE_IS_PROTOTYPE_OF)
246238
{
247-
return_value = ECMA_VALUE_FALSE;
239+
if (builtin_routine_id == ECMA_OBJECT_PROTOTYPE_IS_PROTOTYPE_OF)
240+
{
241+
/* 15.2.4.6.1. */
242+
if (!ecma_is_value_object (arguments_list_p[0]))
243+
{
244+
return ECMA_VALUE_FALSE;
245+
}
246+
}
247+
248+
ecma_value_t to_object = ecma_op_to_object (this_arg);
249+
250+
if (ECMA_IS_VALUE_ERROR (to_object))
251+
{
252+
return to_object;
253+
}
254+
255+
ecma_object_t *obj_p = ecma_get_object_from_value (to_object);
256+
257+
ecma_value_t ret_value;
258+
259+
if (builtin_routine_id == ECMA_OBJECT_PROTOTYPE_IS_PROTOTYPE_OF)
260+
{
261+
ret_value = ecma_builtin_object_prototype_object_is_prototype_of (obj_p, arguments_list_p[0]);
262+
}
263+
else
264+
{
265+
ret_value = ecma_builtin_object_prototype_object_to_locale_string (obj_p);
266+
}
267+
268+
ecma_deref_object (obj_p);
269+
270+
return ret_value;
248271
}
249272

250-
ECMA_FINALIZE (obj_val);
273+
JERRY_ASSERT (builtin_routine_id >= ECMA_OBJECT_PROTOTYPE_HAS_OWN_PROPERTY);
251274

252-
ECMA_FINALIZE (to_string_val);
275+
ecma_string_t *prop_name_p = ecma_op_to_prop_name (arguments_list_p[0]);
253276

254-
return return_value;
255-
} /* ecma_builtin_object_prototype_object_property_is_enumerable */
277+
if (prop_name_p == NULL)
278+
{
279+
return ECMA_VALUE_ERROR;
280+
}
281+
282+
ecma_value_t to_object = ecma_op_to_object (this_arg);
283+
284+
if (ECMA_IS_VALUE_ERROR (to_object))
285+
{
286+
ecma_deref_ecma_string (prop_name_p);
287+
return to_object;
288+
}
289+
290+
ecma_object_t *obj_p = ecma_get_object_from_value (to_object);
291+
292+
ecma_value_t ret_value;
293+
294+
if (builtin_routine_id == ECMA_OBJECT_PROTOTYPE_HAS_OWN_PROPERTY)
295+
{
296+
ret_value = ecma_builtin_object_prototype_object_has_own_property (obj_p, prop_name_p);
297+
}
298+
else
299+
{
300+
ret_value = ecma_builtin_object_prototype_object_property_is_enumerable (obj_p, prop_name_p);
301+
}
302+
303+
ecma_deref_ecma_string (prop_name_p);
304+
ecma_deref_object (obj_p);
305+
306+
return ret_value;
307+
} /* ecma_builtin_object_prototype_dispatch_routine */
256308

257309
/**
258310
* @}

jerry-core/ecma/builtin-objects/ecma-builtin-object-prototype.inc.h

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -29,11 +29,11 @@ OBJECT_VALUE (LIT_MAGIC_STRING_CONSTRUCTOR,
2929

3030
/* Routine properties:
3131
* (property name, C routine name, arguments number or NON_FIXED, value of the routine's length property) */
32-
ROUTINE (LIT_MAGIC_STRING_TO_STRING_UL, ecma_builtin_object_prototype_object_to_string, 0, 0)
33-
ROUTINE (LIT_MAGIC_STRING_VALUE_OF_UL, ecma_builtin_object_prototype_object_value_of, 0, 0)
34-
ROUTINE (LIT_MAGIC_STRING_TO_LOCALE_STRING_UL, ecma_builtin_object_prototype_object_to_locale_string, 0, 0)
35-
ROUTINE (LIT_MAGIC_STRING_HAS_OWN_PROPERTY_UL, ecma_builtin_object_prototype_object_has_own_property, 1, 1)
36-
ROUTINE (LIT_MAGIC_STRING_IS_PROTOTYPE_OF_UL, ecma_builtin_object_prototype_object_is_prototype_of, 1, 1)
37-
ROUTINE (LIT_MAGIC_STRING_PROPERTY_IS_ENUMERABLE_UL, ecma_builtin_object_prototype_object_property_is_enumerable, 1, 1)
32+
ROUTINE (LIT_MAGIC_STRING_TO_STRING_UL, ECMA_OBJECT_PROTOTYPE_TO_STRING, 0, 0)
33+
ROUTINE (LIT_MAGIC_STRING_VALUE_OF_UL, ECMA_OBJECT_PROTOTYPE_VALUE_OF, 0, 0)
34+
ROUTINE (LIT_MAGIC_STRING_TO_LOCALE_STRING_UL, ECMA_OBJECT_PROTOTYPE_TO_LOCALE_STRING, 0, 0)
35+
ROUTINE (LIT_MAGIC_STRING_HAS_OWN_PROPERTY_UL, ECMA_OBJECT_PROTOTYPE_HAS_OWN_PROPERTY, 1, 1)
36+
ROUTINE (LIT_MAGIC_STRING_IS_PROTOTYPE_OF_UL, ECMA_OBJECT_PROTOTYPE_IS_PROTOTYPE_OF, 1, 1)
37+
ROUTINE (LIT_MAGIC_STRING_PROPERTY_IS_ENUMERABLE_UL, ECMA_OBJECT_PROTOTYPE_PROPERTY_IS_ENUMERABLE, 1, 1)
3838

3939
#include "ecma-builtin-helpers-macro-undefs.inc.h"

0 commit comments

Comments
 (0)