Skip to content

Small performance optimizations of the interpreter. #1186

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Jul 6, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
101 changes: 49 additions & 52 deletions jerry-core/ecma/operations/ecma-reference.c
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,12 @@
* limitations under the License.
*/

#include "ecma-exceptions.h"
#include "ecma-gc.h"
#include "ecma-globals.h"
#include "ecma-helpers.h"
#include "ecma-lex-env.h"
#include "ecma-objects.h"
#include "ecma-reference.h"
#include "jrt.h"

Expand Down Expand Up @@ -57,69 +59,64 @@ ecma_op_resolve_reference_base (ecma_object_t *lex_env_p, /**< starting lexical
} /* ecma_op_resolve_reference_base */

/**
* Resolve syntactic reference to ECMA-reference.
* Resolve value corresponding to reference.
*
* @return ECMA-reference
* Returned value must be freed through ecma_free_reference.
* @return value of the reference
*/
ecma_reference_t
ecma_op_get_identifier_reference (ecma_object_t *lex_env_p, /**< lexical environment */
ecma_string_t *name_p, /**< identifier's name */
bool is_strict) /**< strict reference flag */
ecma_value_t
ecma_op_resolve_reference_value (ecma_object_t *lex_env_p, /**< starting lexical environment */
ecma_string_t *name_p, /**< identifier's name */
bool is_strict) /**< strict mode */
{
JERRY_ASSERT (lex_env_p != NULL);

ecma_object_t *base_lex_env_p = ecma_op_resolve_reference_base (lex_env_p, name_p);

if (base_lex_env_p != NULL)
{
return ecma_make_reference (ecma_make_object_value (base_lex_env_p),
name_p,
is_strict);
}
else
while (lex_env_p != NULL)
{
return ecma_make_reference (ecma_make_simple_value (ECMA_SIMPLE_VALUE_UNDEFINED),
name_p,
is_strict);
}
} /* ecma_op_get_identifier_reference */
if (ecma_get_lex_env_type (lex_env_p) == ECMA_LEXICAL_ENVIRONMENT_DECLARATIVE)
{
ecma_property_t *property_p = ecma_find_named_property (lex_env_p, name_p);

if (property_p != NULL)
{
ecma_value_t prop_value = ecma_get_named_data_property_value (property_p);

/* is the binding mutable? */
if (unlikely (!ecma_is_property_writable (property_p)
&& ecma_is_value_empty (prop_value)))
{
/* unitialized mutable binding */
if (is_strict)
{
return ecma_raise_reference_error (ECMA_ERR_MSG (""));
}
else
{
return ecma_make_simple_value (ECMA_SIMPLE_VALUE_UNDEFINED);
}
}
return ecma_fast_copy_value (prop_value);
}
}
else
{
JERRY_ASSERT (ecma_get_lex_env_type (lex_env_p) == ECMA_LEXICAL_ENVIRONMENT_OBJECT_BOUND
|| ecma_get_lex_env_type (lex_env_p) == ECMA_LEXICAL_ENVIRONMENT_THIS_OBJECT_BOUND);

/**
* ECMA-reference constructor.
*
* @return ECMA-reference
* Returned value must be freed through ecma_free_reference.
*/
ecma_reference_t
ecma_make_reference (ecma_value_t base, /**< base value */
ecma_string_t *name_p, /**< referenced name */
bool is_strict) /**< strict reference flag */
{
ecma_ref_ecma_string (name_p);
ecma_object_t *binding_obj_p = ecma_get_lex_env_binding_object (lex_env_p);

ecma_reference_t ref;
ref.base = ecma_copy_value (base);
ref.is_strict = (is_strict != 0);
ecma_property_t *property_p = ecma_op_object_get_property (binding_obj_p, name_p);

ECMA_SET_POINTER (ref.referenced_name_cp, name_p);
if (property_p != NULL)
{
return ecma_op_object_get (binding_obj_p, name_p);
}
}

return ref;
} /* ecma_make_reference */
lex_env_p = ecma_get_lex_env_outer_reference (lex_env_p);
}

/**
* Free specified ECMA-reference.
*
* Warning:
* freeing invalidates all copies of the reference.
*/
void
ecma_free_reference (ecma_reference_t ref) /**< reference */
{
ecma_free_value (ref.base);
ecma_deref_ecma_string (ECMA_GET_NON_NULL_POINTER (ecma_string_t,
ref.referenced_name_cp));
} /* ecma_free_reference */
return ecma_raise_reference_error (ECMA_ERR_MSG (""));
} /* ecma_op_resolve_reference_value */

/**
* @}
Expand Down
20 changes: 1 addition & 19 deletions jerry-core/ecma/operations/ecma-reference.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,26 +26,8 @@
* @{
*/

/**
* ECMA-reference (see also: ECMA-262 v5, 8.7).
*/
typedef struct
{
/** base value */
ecma_value_t base;

/** referenced name */
__extension__ jmem_cpointer_t referenced_name_cp : ECMA_POINTER_FIELD_WIDTH;

/** strict reference flag */
unsigned int is_strict : 1;
} ecma_reference_t;

extern ecma_object_t *ecma_op_resolve_reference_base (ecma_object_t *, ecma_string_t *);

extern ecma_reference_t ecma_op_get_identifier_reference (ecma_object_t *, ecma_string_t *, bool);
extern ecma_reference_t ecma_make_reference (ecma_value_t, ecma_string_t *, bool);
extern void ecma_free_reference (ecma_reference_t);
extern ecma_value_t ecma_op_resolve_reference_value (ecma_object_t *, ecma_string_t *, bool);

/**
* @}
Expand Down
26 changes: 4 additions & 22 deletions jerry-core/vm/opcodes.c
Original file line number Diff line number Diff line change
Expand Up @@ -260,43 +260,25 @@ vm_op_delete_prop (ecma_value_t object, /**< base object */
*/
ecma_value_t
vm_op_delete_var (jmem_cpointer_t name_literal, /**< name literal */
ecma_object_t *lex_env_p, /**< lexical environment */
bool is_strict) /**< strict mode */
ecma_object_t *lex_env_p) /**< lexical environment */
{
ecma_value_t completion_value = ecma_make_simple_value (ECMA_SIMPLE_VALUE_EMPTY);

ecma_string_t *var_name_str_p = JMEM_CP_GET_NON_NULL_POINTER (ecma_string_t, name_literal);

ecma_reference_t ref = ecma_op_get_identifier_reference (lex_env_p,
var_name_str_p,
is_strict);
ecma_object_t *ref_base_lex_env_p = ecma_op_resolve_reference_base (lex_env_p, var_name_str_p);

JERRY_ASSERT (!ref.is_strict);

if (ecma_is_value_undefined (ref.base))
if (ref_base_lex_env_p == NULL)
{
completion_value = ecma_make_simple_value (ECMA_SIMPLE_VALUE_TRUE);
}
else
{
ecma_object_t *ref_base_lex_env_p = ecma_op_resolve_reference_base (lex_env_p, var_name_str_p);

JERRY_ASSERT (ecma_is_lexical_environment (ref_base_lex_env_p));

ECMA_TRY_CATCH (delete_op_ret_val,
ecma_op_delete_binding (ref_base_lex_env_p,
ECMA_GET_NON_NULL_POINTER (ecma_string_t,
ref.referenced_name_cp)),
completion_value);

completion_value = delete_op_ret_val;

ECMA_FINALIZE (delete_op_ret_val);

completion_value = ecma_op_delete_binding (ref_base_lex_env_p, var_name_str_p);
}

ecma_free_reference (ref);

return completion_value;
} /* vm_op_delete_var */

Expand Down
2 changes: 1 addition & 1 deletion jerry-core/vm/opcodes.h
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@ ecma_value_t
vm_op_delete_prop (ecma_value_t, ecma_value_t, bool);

ecma_value_t
vm_op_delete_var (jmem_cpointer_t, ecma_object_t *, bool);
vm_op_delete_var (jmem_cpointer_t, ecma_object_t *);

ecma_collection_header_t *
opfunc_for_in (ecma_value_t, ecma_value_t *);
Expand Down
90 changes: 51 additions & 39 deletions jerry-core/vm/vm.c
Original file line number Diff line number Diff line change
Expand Up @@ -128,44 +128,67 @@ vm_op_get_value (ecma_value_t object, /**< base object */
/**
* Set the value of object[property].
*
* @return ecma value
* Note:
* this function frees its object and property arguments
*
* @return an ecma value which contains an error
* if the property setting is unsuccessful
*/
static ecma_value_t
vm_op_set_value (ecma_value_t object, /**< base object */
ecma_value_t property, /**< property name */
ecma_value_t value, /**< ecma value */
bool is_strict) /**< strict mode */
{
ecma_value_t completion_value = ecma_make_simple_value (ECMA_SIMPLE_VALUE_EMPTY);

ECMA_TRY_CATCH (obj_val,
ecma_op_to_object (object),
completion_value);
if (unlikely (!ecma_is_value_object (object)))
{
ecma_value_t to_object = ecma_op_to_object (object);
ecma_free_value (object);

ECMA_TRY_CATCH (property_val,
ecma_op_to_string (property),
completion_value);
if (ECMA_IS_VALUE_ERROR (to_object))
{
ecma_free_value (property);
return to_object;
}

ecma_object_t *object_p = ecma_get_object_from_value (obj_val);
ecma_string_t *property_p = ecma_get_string_from_value (property_val);
object = to_object;
}

if (ecma_is_lexical_environment (object_p))
if (!ecma_is_value_string (property))
{
completion_value = ecma_op_put_value_lex_env_base (object_p,
property_p,
is_strict,
value);
ecma_value_t to_string = ecma_op_to_string (property);
ecma_fast_free_value (property);

if (ECMA_IS_VALUE_ERROR (property))
{
ecma_free_value (object);
return to_string;
}

property = to_string;
}
else

ecma_object_t *object_p = ecma_get_object_from_value (object);
ecma_string_t *property_p = ecma_get_string_from_value (property);
ecma_value_t completion_value = ecma_make_simple_value (ECMA_SIMPLE_VALUE_EMPTY);

if (!ecma_is_lexical_environment (object_p))
{
completion_value = ecma_op_object_put (object_p,
property_p,
value,
is_strict);
}
else
{
completion_value = ecma_op_set_mutable_binding (object_p,
property_p,
value,
is_strict);
}

ECMA_FINALIZE (property_val);
ECMA_FINALIZE (obj_val);
ecma_free_value (object);
ecma_free_value (property);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you please add a note saying that the object and property arguments will be freed by the function, and caller doesn't have to?


return completion_value;
} /* vm_op_set_value */
Expand Down Expand Up @@ -505,18 +528,9 @@ opfunc_construct (vm_frame_ctx_t *frame_ctx_p) /**< frame context */
{ \
ecma_string_t *name_p = JMEM_CP_GET_NON_NULL_POINTER (ecma_string_t, \
literal_start_p[literal_index]); \
ecma_object_t *ref_base_lex_env_p = ecma_op_resolve_reference_base (frame_ctx_p->lex_env_p, \
name_p); \
if (ref_base_lex_env_p != NULL) \
{ \
result = ecma_op_get_value_lex_env_base (ref_base_lex_env_p, \
name_p, \
is_strict); \
} \
else \
{ \
result = ecma_raise_reference_error (ECMA_ERR_MSG ("")); \
} \
result = ecma_op_resolve_reference_value (frame_ctx_p->lex_env_p, \
name_p, \
is_strict); \
\
if (ECMA_IS_VALUE_ERROR (result)) \
{ \
Expand Down Expand Up @@ -1103,7 +1117,7 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */
{
*stack_top_p++ = ecma_make_simple_value (ECMA_SIMPLE_VALUE_REGISTER_REF);
*stack_top_p++ = literal_index;
*stack_top_p++ = ecma_copy_value (frame_ctx_p->registers_p[literal_index]);
*stack_top_p++ = ecma_fast_copy_value (frame_ctx_p->registers_p[literal_index]);
}
else
{
Expand Down Expand Up @@ -1486,8 +1500,7 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */
}

result = vm_op_delete_var (literal_start_p[literal_index],
frame_ctx_p->lex_env_p,
is_strict);
frame_ctx_p->lex_env_p);

if (ECMA_IS_VALUE_ERROR (result))
{
Expand Down Expand Up @@ -2406,10 +2419,11 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */

frame_ctx_p->registers_p[property] = result;

if (opcode_data & (VM_OC_PUT_STACK | VM_OC_PUT_BLOCK))
if (!(opcode_data & (VM_OC_PUT_STACK | VM_OC_PUT_BLOCK)))
{
result = ecma_fast_copy_value (result);
goto free_both_values;
}
result = ecma_fast_copy_value (result);
}
else
{
Expand All @@ -2418,9 +2432,6 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */
result,
is_strict);

ecma_free_value (object);
ecma_free_value (property);

if (ECMA_IS_VALUE_ERROR (set_value_result))
{
ecma_free_value (result);
Expand All @@ -2431,6 +2442,7 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */
if (!(opcode_data & (VM_OC_PUT_STACK | VM_OC_PUT_BLOCK)))
{
ecma_fast_free_value (result);
goto free_both_values;
}
}
}
Expand Down