Skip to content

Commit 3192436

Browse files
committed
Small performance optimizations of the interpreter.
Short summary of the changes: - The ecma_reference_t is removed, and its helper functions a redeleted. - The delete operation does not depend on ecma_reference_t anymore. - A new resolve function is added which returns the current value of a named binding in the context chain. - The vm_op_set_value does not perform type conversions when its arguments has the appropriate types. JerryScript-DCO-1.0-Signed-off-by: Zoltan Herczeg zherczeg.u-szeged@partner.samsung.com
1 parent 5f7997d commit 3192436

File tree

5 files changed

+101
-132
lines changed

5 files changed

+101
-132
lines changed

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

Lines changed: 49 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -14,10 +14,12 @@
1414
* limitations under the License.
1515
*/
1616

17+
#include "ecma-exceptions.h"
1718
#include "ecma-gc.h"
1819
#include "ecma-globals.h"
1920
#include "ecma-helpers.h"
2021
#include "ecma-lex-env.h"
22+
#include "ecma-objects.h"
2123
#include "ecma-reference.h"
2224
#include "jrt.h"
2325

@@ -57,69 +59,64 @@ ecma_op_resolve_reference_base (ecma_object_t *lex_env_p, /**< starting lexical
5759
} /* ecma_op_resolve_reference_base */
5860

5961
/**
60-
* Resolve syntactic reference to ECMA-reference.
62+
* Resolve value corresponds to reference.
6163
*
62-
* @return ECMA-reference
63-
* Returned value must be freed through ecma_free_reference.
64+
* @return value of the reference
6465
*/
65-
ecma_reference_t
66-
ecma_op_get_identifier_reference (ecma_object_t *lex_env_p, /**< lexical environment */
67-
ecma_string_t *name_p, /**< identifier's name */
68-
bool is_strict) /**< strict reference flag */
66+
ecma_value_t
67+
ecma_op_resolve_reference_value (ecma_object_t *lex_env_p, /**< starting lexical environment */
68+
ecma_string_t *name_p, /**< identifier's name */
69+
bool is_strict) /**< strict mode */
6970
{
7071
JERRY_ASSERT (lex_env_p != NULL);
7172

72-
ecma_object_t *base_lex_env_p = ecma_op_resolve_reference_base (lex_env_p, name_p);
73-
74-
if (base_lex_env_p != NULL)
75-
{
76-
return ecma_make_reference (ecma_make_object_value (base_lex_env_p),
77-
name_p,
78-
is_strict);
79-
}
80-
else
73+
while (lex_env_p != NULL)
8174
{
82-
return ecma_make_reference (ecma_make_simple_value (ECMA_SIMPLE_VALUE_UNDEFINED),
83-
name_p,
84-
is_strict);
85-
}
86-
} /* ecma_op_get_identifier_reference */
75+
if (ecma_get_lex_env_type (lex_env_p) == ECMA_LEXICAL_ENVIRONMENT_DECLARATIVE)
76+
{
77+
ecma_property_t *property_p = ecma_find_named_property (lex_env_p, name_p);
78+
79+
if (property_p != NULL)
80+
{
81+
ecma_value_t prop_value = ecma_get_named_data_property_value (property_p);
82+
83+
/* is the binding mutable? */
84+
if (unlikely (!ecma_is_property_writable (property_p)
85+
&& ecma_is_value_empty (prop_value)))
86+
{
87+
/* unitialized mutable binding */
88+
if (is_strict)
89+
{
90+
return ecma_raise_reference_error (ECMA_ERR_MSG (""));
91+
}
92+
else
93+
{
94+
return ecma_make_simple_value (ECMA_SIMPLE_VALUE_UNDEFINED);
95+
}
96+
}
97+
return ecma_fast_copy_value (prop_value);
98+
}
99+
}
100+
else
101+
{
102+
JERRY_ASSERT (ecma_get_lex_env_type (lex_env_p) == ECMA_LEXICAL_ENVIRONMENT_OBJECT_BOUND
103+
|| ecma_get_lex_env_type (lex_env_p) == ECMA_LEXICAL_ENVIRONMENT_THIS_OBJECT_BOUND);
87104

88-
/**
89-
* ECMA-reference constructor.
90-
*
91-
* @return ECMA-reference
92-
* Returned value must be freed through ecma_free_reference.
93-
*/
94-
ecma_reference_t
95-
ecma_make_reference (ecma_value_t base, /**< base value */
96-
ecma_string_t *name_p, /**< referenced name */
97-
bool is_strict) /**< strict reference flag */
98-
{
99-
ecma_ref_ecma_string (name_p);
105+
ecma_object_t *binding_obj_p = ecma_get_lex_env_binding_object (lex_env_p);
100106

101-
ecma_reference_t ref;
102-
ref.base = ecma_copy_value (base);
103-
ref.is_strict = (is_strict != 0);
107+
ecma_property_t *property_p = ecma_op_object_get_property (binding_obj_p, name_p);
104108

105-
ECMA_SET_POINTER (ref.referenced_name_cp, name_p);
109+
if (property_p != NULL)
110+
{
111+
return ecma_op_object_get (binding_obj_p, name_p);
112+
}
113+
}
106114

107-
return ref;
108-
} /* ecma_make_reference */
115+
lex_env_p = ecma_get_lex_env_outer_reference (lex_env_p);
116+
}
109117

110-
/**
111-
* Free specified ECMA-reference.
112-
*
113-
* Warning:
114-
* freeing invalidates all copies of the reference.
115-
*/
116-
void
117-
ecma_free_reference (ecma_reference_t ref) /**< reference */
118-
{
119-
ecma_free_value (ref.base);
120-
ecma_deref_ecma_string (ECMA_GET_NON_NULL_POINTER (ecma_string_t,
121-
ref.referenced_name_cp));
122-
} /* ecma_free_reference */
118+
return ecma_raise_reference_error (ECMA_ERR_MSG (""));
119+
} /* ecma_op_resolve_reference_value */
123120

124121
/**
125122
* @}

jerry-core/ecma/operations/ecma-reference.h

Lines changed: 1 addition & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -26,26 +26,8 @@
2626
* @{
2727
*/
2828

29-
/**
30-
* ECMA-reference (see also: ECMA-262 v5, 8.7).
31-
*/
32-
typedef struct
33-
{
34-
/** base value */
35-
ecma_value_t base;
36-
37-
/** referenced name */
38-
__extension__ jmem_cpointer_t referenced_name_cp : ECMA_POINTER_FIELD_WIDTH;
39-
40-
/** strict reference flag */
41-
unsigned int is_strict : 1;
42-
} ecma_reference_t;
43-
4429
extern ecma_object_t *ecma_op_resolve_reference_base (ecma_object_t *, ecma_string_t *);
45-
46-
extern ecma_reference_t ecma_op_get_identifier_reference (ecma_object_t *, ecma_string_t *, bool);
47-
extern ecma_reference_t ecma_make_reference (ecma_value_t, ecma_string_t *, bool);
48-
extern void ecma_free_reference (ecma_reference_t);
30+
extern ecma_value_t ecma_op_resolve_reference_value (ecma_object_t *, ecma_string_t *, bool);
4931

5032
/**
5133
* @}

jerry-core/vm/opcodes.c

Lines changed: 4 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -260,43 +260,25 @@ vm_op_delete_prop (ecma_value_t object, /**< base object */
260260
*/
261261
ecma_value_t
262262
vm_op_delete_var (jmem_cpointer_t name_literal, /**< name literal */
263-
ecma_object_t *lex_env_p, /**< lexical environment */
264-
bool is_strict) /**< strict mode */
263+
ecma_object_t *lex_env_p) /**< lexical environment */
265264
{
266265
ecma_value_t completion_value = ecma_make_simple_value (ECMA_SIMPLE_VALUE_EMPTY);
267266

268267
ecma_string_t *var_name_str_p = JMEM_CP_GET_NON_NULL_POINTER (ecma_string_t, name_literal);
269268

270-
ecma_reference_t ref = ecma_op_get_identifier_reference (lex_env_p,
271-
var_name_str_p,
272-
is_strict);
269+
ecma_object_t *ref_base_lex_env_p = ecma_op_resolve_reference_base (lex_env_p, var_name_str_p);
273270

274-
JERRY_ASSERT (!ref.is_strict);
275-
276-
if (ecma_is_value_undefined (ref.base))
271+
if (ref_base_lex_env_p == NULL)
277272
{
278273
completion_value = ecma_make_simple_value (ECMA_SIMPLE_VALUE_TRUE);
279274
}
280275
else
281276
{
282-
ecma_object_t *ref_base_lex_env_p = ecma_op_resolve_reference_base (lex_env_p, var_name_str_p);
283-
284277
JERRY_ASSERT (ecma_is_lexical_environment (ref_base_lex_env_p));
285278

286-
ECMA_TRY_CATCH (delete_op_ret_val,
287-
ecma_op_delete_binding (ref_base_lex_env_p,
288-
ECMA_GET_NON_NULL_POINTER (ecma_string_t,
289-
ref.referenced_name_cp)),
290-
completion_value);
291-
292-
completion_value = delete_op_ret_val;
293-
294-
ECMA_FINALIZE (delete_op_ret_val);
295-
279+
completion_value = ecma_op_delete_binding (ref_base_lex_env_p, var_name_str_p);
296280
}
297281

298-
ecma_free_reference (ref);
299-
300282
return completion_value;
301283
} /* vm_op_delete_var */
302284

jerry-core/vm/opcodes.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,7 @@ ecma_value_t
107107
vm_op_delete_prop (ecma_value_t, ecma_value_t, bool);
108108

109109
ecma_value_t
110-
vm_op_delete_var (jmem_cpointer_t, ecma_object_t *, bool);
110+
vm_op_delete_var (jmem_cpointer_t, ecma_object_t *);
111111

112112
ecma_collection_header_t *
113113
opfunc_for_in (ecma_value_t, ecma_value_t *);

jerry-core/vm/vm.c

Lines changed: 46 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -136,36 +136,55 @@ vm_op_set_value (ecma_value_t object, /**< base object */
136136
ecma_value_t value, /**< ecma value */
137137
bool is_strict) /**< strict mode */
138138
{
139-
ecma_value_t completion_value = ecma_make_simple_value (ECMA_SIMPLE_VALUE_EMPTY);
140-
141-
ECMA_TRY_CATCH (obj_val,
142-
ecma_op_to_object (object),
143-
completion_value);
139+
if (unlikely (!ecma_is_value_object (object)))
140+
{
141+
ecma_value_t to_object = ecma_op_to_object (object);
142+
ecma_free_value (object);
144143

145-
ECMA_TRY_CATCH (property_val,
146-
ecma_op_to_string (property),
147-
completion_value);
144+
if (ECMA_IS_VALUE_ERROR (to_object))
145+
{
146+
ecma_free_value (property);
147+
return to_object;
148+
}
148149

149-
ecma_object_t *object_p = ecma_get_object_from_value (obj_val);
150-
ecma_string_t *property_p = ecma_get_string_from_value (property_val);
150+
object = to_object;
151+
}
151152

152-
if (ecma_is_lexical_environment (object_p))
153+
if (!ecma_is_value_string (property))
153154
{
154-
completion_value = ecma_op_put_value_lex_env_base (object_p,
155-
property_p,
156-
is_strict,
157-
value);
155+
ecma_value_t to_string = ecma_op_to_string (property);
156+
ecma_fast_free_value (property);
157+
158+
if (ECMA_IS_VALUE_ERROR (property))
159+
{
160+
ecma_free_value (object);
161+
return to_string;
162+
}
163+
164+
property = to_string;
158165
}
159-
else
166+
167+
ecma_object_t *object_p = ecma_get_object_from_value (object);
168+
ecma_string_t *property_p = ecma_get_string_from_value (property);
169+
ecma_value_t completion_value = ecma_make_simple_value (ECMA_SIMPLE_VALUE_EMPTY);
170+
171+
if (!ecma_is_lexical_environment (object_p))
160172
{
161173
completion_value = ecma_op_object_put (object_p,
162174
property_p,
163175
value,
164176
is_strict);
165177
}
178+
else
179+
{
180+
completion_value = ecma_op_set_mutable_binding (object_p,
181+
property_p,
182+
value,
183+
is_strict);
184+
}
166185

167-
ECMA_FINALIZE (property_val);
168-
ECMA_FINALIZE (obj_val);
186+
ecma_free_value (object);
187+
ecma_free_value (property);
169188

170189
return completion_value;
171190
} /* vm_op_set_value */
@@ -505,18 +524,9 @@ opfunc_construct (vm_frame_ctx_t *frame_ctx_p) /**< frame context */
505524
{ \
506525
ecma_string_t *name_p = JMEM_CP_GET_NON_NULL_POINTER (ecma_string_t, \
507526
literal_start_p[literal_index]); \
508-
ecma_object_t *ref_base_lex_env_p = ecma_op_resolve_reference_base (frame_ctx_p->lex_env_p, \
509-
name_p); \
510-
if (ref_base_lex_env_p != NULL) \
511-
{ \
512-
result = ecma_op_get_value_lex_env_base (ref_base_lex_env_p, \
513-
name_p, \
514-
is_strict); \
515-
} \
516-
else \
517-
{ \
518-
result = ecma_raise_reference_error (ECMA_ERR_MSG ("")); \
519-
} \
527+
result = ecma_op_resolve_reference_value (frame_ctx_p->lex_env_p, \
528+
name_p, \
529+
is_strict); \
520530
\
521531
if (ECMA_IS_VALUE_ERROR (result)) \
522532
{ \
@@ -1103,7 +1113,7 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */
11031113
{
11041114
*stack_top_p++ = ecma_make_simple_value (ECMA_SIMPLE_VALUE_REGISTER_REF);
11051115
*stack_top_p++ = literal_index;
1106-
*stack_top_p++ = ecma_copy_value (frame_ctx_p->registers_p[literal_index]);
1116+
*stack_top_p++ = ecma_fast_copy_value (frame_ctx_p->registers_p[literal_index]);
11071117
}
11081118
else
11091119
{
@@ -1486,8 +1496,7 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */
14861496
}
14871497

14881498
result = vm_op_delete_var (literal_start_p[literal_index],
1489-
frame_ctx_p->lex_env_p,
1490-
is_strict);
1499+
frame_ctx_p->lex_env_p);
14911500

14921501
if (ECMA_IS_VALUE_ERROR (result))
14931502
{
@@ -2406,10 +2415,11 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */
24062415

24072416
frame_ctx_p->registers_p[property] = result;
24082417

2409-
if (opcode_data & (VM_OC_PUT_STACK | VM_OC_PUT_BLOCK))
2418+
if (!(opcode_data & (VM_OC_PUT_STACK | VM_OC_PUT_BLOCK)))
24102419
{
2411-
result = ecma_fast_copy_value (result);
2420+
goto free_both_values;
24122421
}
2422+
result = ecma_fast_copy_value (result);
24132423
}
24142424
else
24152425
{
@@ -2418,9 +2428,6 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */
24182428
result,
24192429
is_strict);
24202430

2421-
ecma_free_value (object);
2422-
ecma_free_value (property);
2423-
24242431
if (ECMA_IS_VALUE_ERROR (set_value_result))
24252432
{
24262433
ecma_free_value (result);
@@ -2431,6 +2438,7 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */
24312438
if (!(opcode_data & (VM_OC_PUT_STACK | VM_OC_PUT_BLOCK)))
24322439
{
24332440
ecma_fast_free_value (result);
2441+
goto free_both_values;
24342442
}
24352443
}
24362444
}

0 commit comments

Comments
 (0)