Optimize put result phase in the interpreter.

Skip put result phase for opcodes which put their
result onto the stack or they don't have result at all.

JerryScript-DCO-1.0-Signed-off-by: Zoltan Herczeg zherczeg.u-szeged@partner.samsung.com
This commit is contained in:
Zoltan Herczeg 2016-06-10 00:26:59 -07:00
parent eed84a7dd9
commit 495b24eebc

View File

@ -846,7 +846,7 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */
case VM_OC_NONE:
{
JERRY_ASSERT (opcode == CBC_EXT_DEBUGGER);
break;
continue;
}
case VM_OC_POP:
{
@ -856,59 +856,59 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */
}
case VM_OC_POP_BLOCK:
{
result = *(--stack_top_p);
break;
ecma_fast_free_value (block_result);
block_result = *(--stack_top_p);
continue;
}
case VM_OC_PUSH:
{
*(stack_top_p++) = left_value;
*stack_top_p++ = left_value;
continue;
}
case VM_OC_PUSH_TWO:
{
*(stack_top_p++) = left_value;
*(stack_top_p++) = right_value;
*stack_top_p++ = left_value;
*stack_top_p++ = right_value;
continue;
}
case VM_OC_PUSH_THREE:
{
uint16_t literal_index;
*(stack_top_p++) = left_value;
*stack_top_p++ = left_value;
left_value = ecma_make_simple_value (ECMA_SIMPLE_VALUE_UNDEFINED);
READ_LITERAL_INDEX (literal_index);
READ_LITERAL (literal_index, left_value);
*(stack_top_p++) = right_value;
*(stack_top_p++) = left_value;
*stack_top_p++ = right_value;
*stack_top_p++ = left_value;
continue;
}
case VM_OC_PUSH_UNDEFINED:
case VM_OC_VOID:
{
result = ecma_make_simple_value (ECMA_SIMPLE_VALUE_UNDEFINED);
break;
*stack_top_p++ = ecma_make_simple_value (ECMA_SIMPLE_VALUE_UNDEFINED);
continue;
}
case VM_OC_PUSH_TRUE:
{
result = ecma_make_simple_value (ECMA_SIMPLE_VALUE_TRUE);
break;
*stack_top_p++ = ecma_make_simple_value (ECMA_SIMPLE_VALUE_TRUE);
continue;
}
case VM_OC_PUSH_FALSE:
{
result = ecma_make_simple_value (ECMA_SIMPLE_VALUE_FALSE);
break;
*stack_top_p++ = ecma_make_simple_value (ECMA_SIMPLE_VALUE_FALSE);
continue;
}
case VM_OC_PUSH_NULL:
{
result = ecma_make_simple_value (ECMA_SIMPLE_VALUE_NULL);
break;
*stack_top_p++ = ecma_make_simple_value (ECMA_SIMPLE_VALUE_NULL);
continue;
}
case VM_OC_PUSH_THIS:
{
result = ecma_copy_value (frame_ctx_p->this_binding);
break;
*stack_top_p++ = ecma_copy_value (frame_ctx_p->this_binding);
continue;
}
case VM_OC_PUSH_NUMBER_0:
{
@ -933,9 +933,9 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */
ecma_object_t *obj_p = ecma_create_object (prototype_p,
true,
ECMA_OBJECT_TYPE_GENERAL);
result = ecma_make_object_value (obj_p);
ecma_deref_object (prototype_p);
break;
*stack_top_p++ = ecma_make_object_value (obj_p);
continue;
}
case VM_OC_SET_PROPERTY:
{
@ -946,7 +946,6 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */
if (ecma_is_value_string (right_value))
{
prop_name_p = ecma_get_string_from_value (right_value);
property_p = ecma_find_named_property (object_p, prop_name_p);
}
else
{
@ -958,9 +957,10 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */
}
prop_name_p = ecma_get_string_from_value (result);
property_p = ecma_find_named_property (object_p, prop_name_p);
}
property_p = ecma_find_named_property (object_p, prop_name_p);
if (property_p != NULL && ECMA_PROPERTY_GET_TYPE (property_p) != ECMA_PROPERTY_TYPE_NAMEDDATA)
{
ecma_delete_property (object_p, property_p);
@ -980,7 +980,8 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */
{
ecma_deref_ecma_string (prop_name_p);
}
break;
goto free_both_values;
}
case VM_OC_SET_GETTER:
case VM_OC_SET_SETTER:
@ -989,7 +990,8 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */
stack_top_p[-1],
left_value,
right_value);
break;
goto free_both_values;
}
case VM_OC_PUSH_ARRAY:
{
@ -999,12 +1001,14 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */
{
goto error;
}
break;
*stack_top_p++ = result;
continue;
}
case VM_OC_PUSH_ELISON:
{
result = ecma_make_simple_value (ECMA_SIMPLE_VALUE_ARRAY_HOLE);
break;
*stack_top_p++ = ecma_make_simple_value (ECMA_SIMPLE_VALUE_ARRAY_HOLE);
continue;
}
case VM_OC_APPEND_ARRAY:
{
@ -1056,13 +1060,14 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */
ecma_value_assign_uint32 (&ECMA_PROPERTY_VALUE_PTR (length_prop_p)->value,
length_num);
break;
continue;
}
case VM_OC_PUSH_UNDEFINED_BASE:
{
result = stack_top_p[-1];
stack_top_p[0] = stack_top_p[-1];
stack_top_p[-1] = ecma_make_simple_value (ECMA_SIMPLE_VALUE_UNDEFINED);
break;
stack_top_p++;
continue;
}
case VM_OC_IDENT_REFERENCE:
{
@ -1076,7 +1081,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;
result = ecma_copy_value (frame_ctx_p->registers_p[literal_index]);
*stack_top_p++ = ecma_copy_value (frame_ctx_p->registers_p[literal_index]);
}
else
{
@ -1106,8 +1111,9 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */
ecma_ref_object (ref_base_lex_env_p);
*stack_top_p++ = ecma_make_object_value (ref_base_lex_env_p);
*stack_top_p++ = ecma_make_string_value (name_p);
*stack_top_p++ = result;
}
break;
continue;
}
case VM_OC_PROP_REFERENCE:
{
@ -1380,12 +1386,19 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */
goto error;
}
if (VM_OC_HAS_PUT_RESULT (opcode_data))
if (!(opcode_data & (VM_OC_PUT_STACK | VM_OC_PUT_BLOCK)))
{
break;
ecma_fast_free_value (result);
}
else if (opcode_data & VM_OC_PUT_STACK)
{
*stack_top_p++ = result;
}
else
{
ecma_fast_free_value (block_result);
block_result = result;
}
ecma_fast_free_value (result);
continue;
}
case VM_OC_NEW:
@ -1414,8 +1427,8 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */
goto error;
}
JERRY_ASSERT (VM_OC_HAS_PUT_RESULT (opcode_data));
break;
*stack_top_p++ = result;
continue;
}
case VM_OC_PROP_DELETE:
{
@ -1425,7 +1438,11 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */
{
goto error;
}
break;
JERRY_ASSERT (ecma_is_value_boolean (result));
*stack_top_p++ = result;
goto free_both_values;
}
case VM_OC_DELETE:
{
@ -1435,8 +1452,8 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */
if (literal_index < register_end)
{
result = ecma_make_simple_value (ECMA_SIMPLE_VALUE_FALSE);
break;
*stack_top_p++ = ecma_make_simple_value (ECMA_SIMPLE_VALUE_FALSE);
continue;
}
result = vm_op_delete_var (literal_start_p[literal_index],
@ -1447,7 +1464,11 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */
{
goto error;
}
break;
JERRY_ASSERT (ecma_is_value_boolean (result));
*stack_top_p++ = result;
continue;
}
case VM_OC_JUMP:
{
@ -1505,7 +1526,9 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */
{
goto error;
}
break;
*stack_top_p++ = result;
goto free_left_value;
}
case VM_OC_MINUS:
{
@ -1515,7 +1538,9 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */
{
goto error;
}
break;
*stack_top_p++ = result;
goto free_left_value;
}
case VM_OC_NOT:
{
@ -1525,7 +1550,9 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */
{
goto error;
}
break;
*stack_top_p++ = result;
goto free_left_value;
}
case VM_OC_BIT_NOT:
{
@ -1537,7 +1564,14 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */
{
goto error;
}
break;
*stack_top_p++ = result;
goto free_left_value;
}
case VM_OC_VOID:
{
*stack_top_p++ = ecma_make_simple_value (ECMA_SIMPLE_VALUE_UNDEFINED);
goto free_left_value;
}
case VM_OC_TYPEOF_IDENT:
{
@ -1559,16 +1593,15 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */
if (ref_base_lex_env_p == NULL)
{
ecma_deref_ecma_string (name_p);
ecma_string_t *string_p = ecma_get_magic_string (LIT_MAGIC_STRING_UNDEFINED);
result = ecma_make_string_value (string_p);
break;
result = ecma_make_simple_value (ECMA_SIMPLE_VALUE_UNDEFINED);
}
else
{
result = ecma_op_get_value_lex_env_base (ref_base_lex_env_p,
name_p,
is_strict);
result = ecma_op_get_value_lex_env_base (ref_base_lex_env_p,
name_p,
is_strict);
}
ecma_deref_ecma_string (name_p);
@ -1589,7 +1622,9 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */
{
goto error;
}
break;
*stack_top_p++ = result;
goto free_left_value;
}
case VM_OC_ADD:
{
@ -1657,7 +1692,9 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */
{
goto error;
}
break;
*stack_top_p++ = result;
goto free_both_values;
}
case VM_OC_NOT_EQUAL:
{
@ -1667,7 +1704,9 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */
{
goto error;
}
break;
*stack_top_p++ = result;
goto free_both_values;
}
case VM_OC_STRICT_EQUAL:
{
@ -1675,7 +1714,9 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */
result = ecma_make_simple_value (is_equal ? ECMA_SIMPLE_VALUE_TRUE
: ECMA_SIMPLE_VALUE_FALSE);
break;
*stack_top_p++ = result;
goto free_both_values;
}
case VM_OC_STRICT_NOT_EQUAL:
{
@ -1683,7 +1724,9 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */
result = ecma_make_simple_value (is_equal ? ECMA_SIMPLE_VALUE_FALSE
: ECMA_SIMPLE_VALUE_TRUE);
break;
*stack_top_p++ = result;
goto free_both_values;
}
case VM_OC_BIT_OR:
{
@ -1765,7 +1808,9 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */
{
goto error;
}
break;
*stack_top_p++ = result;
goto free_both_values;
}
case VM_OC_GREATER:
{
@ -1775,7 +1820,9 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */
{
goto error;
}
break;
*stack_top_p++ = result;
goto free_both_values;
}
case VM_OC_LESS_EQUAL:
{
@ -1785,7 +1832,9 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */
{
goto error;
}
break;
*stack_top_p++ = result;
goto free_both_values;
}
case VM_OC_GREATER_EQUAL:
{
@ -1795,7 +1844,9 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */
{
goto error;
}
break;
*stack_top_p++ = result;
goto free_both_values;
}
case VM_OC_IN:
{
@ -1805,7 +1856,9 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */
{
goto error;
}
break;
*stack_top_p++ = result;
goto free_both_values;
}
case VM_OC_INSTANCEOF:
{
@ -1815,7 +1868,9 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */
{
goto error;
}
break;
*stack_top_p++ = result;
goto free_both_values;
}
case VM_OC_WITH:
{
@ -1891,7 +1946,9 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */
context_top_p[-2] = chunk_p->next_chunk_cp;
ecma_dealloc_collection_chunk (chunk_p);
break;
*stack_top_p++ = result;
continue;
}
case VM_OC_FOR_IN_HAS_NEXT:
{
@ -2024,7 +2081,7 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */
}
JERRY_ASSERT (frame_ctx_p->registers_p + register_end + frame_ctx_p->context_depth == stack_top_p);
break;
continue;
}
case VM_OC_JUMP_AND_EXIT_CONTEXT:
{
@ -2052,111 +2109,112 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */
default:
{
JERRY_UNREACHABLE ();
break;
continue;
}
}
if (VM_OC_HAS_PUT_RESULT (opcode_data))
JERRY_ASSERT (VM_OC_HAS_PUT_RESULT (opcode_data));
if (opcode_data & VM_OC_PUT_IDENT)
{
if (opcode_data & VM_OC_PUT_IDENT)
uint16_t literal_index;
READ_LITERAL_INDEX (literal_index);
if (literal_index < register_end)
{
uint16_t literal_index;
ecma_fast_free_value (frame_ctx_p->registers_p[literal_index]);
READ_LITERAL_INDEX (literal_index);
frame_ctx_p->registers_p[literal_index] = result;
if (literal_index < register_end)
if (opcode_data & (VM_OC_PUT_STACK | VM_OC_PUT_BLOCK))
{
ecma_fast_free_value (frame_ctx_p->registers_p[literal_index]);
frame_ctx_p->registers_p[literal_index] = result;
if (opcode_data & (VM_OC_PUT_STACK | VM_OC_PUT_BLOCK))
{
result = ecma_fast_copy_value (result);
}
}
else
{
ecma_string_t *var_name_str_p;
ecma_object_t *ref_base_lex_env_p;
var_name_str_p = ecma_new_ecma_string_from_lit_cp (literal_start_p[literal_index]);
ref_base_lex_env_p = ecma_op_resolve_reference_base (frame_ctx_p->lex_env_p,
var_name_str_p);
ecma_value_t put_value_result = ecma_op_put_value_lex_env_base (ref_base_lex_env_p,
var_name_str_p,
is_strict,
result);
ecma_deref_ecma_string (var_name_str_p);
if (ecma_is_value_error (put_value_result))
{
ecma_free_value (result);
result = put_value_result;
goto error;
}
if (!(opcode_data & (VM_OC_PUT_STACK | VM_OC_PUT_BLOCK)))
{
ecma_fast_free_value (result);
}
result = ecma_fast_copy_value (result);
}
}
else if (opcode_data & VM_OC_PUT_REFERENCE)
else
{
ecma_value_t property = *(--stack_top_p);
ecma_value_t object = *(--stack_top_p);
ecma_string_t *var_name_str_p;
ecma_object_t *ref_base_lex_env_p;
if (object == ecma_make_simple_value (ECMA_SIMPLE_VALUE_REGISTER_REF))
var_name_str_p = ecma_new_ecma_string_from_lit_cp (literal_start_p[literal_index]);
ref_base_lex_env_p = ecma_op_resolve_reference_base (frame_ctx_p->lex_env_p,
var_name_str_p);
ecma_value_t put_value_result = ecma_op_put_value_lex_env_base (ref_base_lex_env_p,
var_name_str_p,
is_strict,
result);
ecma_deref_ecma_string (var_name_str_p);
if (ecma_is_value_error (put_value_result))
{
ecma_fast_free_value (frame_ctx_p->registers_p[property]);
frame_ctx_p->registers_p[property] = result;
if (opcode_data & (VM_OC_PUT_STACK | VM_OC_PUT_BLOCK))
{
result = ecma_fast_copy_value (result);
}
ecma_free_value (result);
result = put_value_result;
goto error;
}
else
if (!(opcode_data & (VM_OC_PUT_STACK | VM_OC_PUT_BLOCK)))
{
ecma_value_t set_value_result = vm_op_set_value (object,
property,
result,
is_strict);
ecma_free_value (object);
ecma_free_value (property);
if (ecma_is_value_error (set_value_result))
{
ecma_free_value (result);
result = set_value_result;
goto error;
}
if (!(opcode_data & (VM_OC_PUT_STACK | VM_OC_PUT_BLOCK)))
{
ecma_fast_free_value (result);
}
ecma_fast_free_value (result);
}
}
}
else if (opcode_data & VM_OC_PUT_REFERENCE)
{
ecma_value_t property = *(--stack_top_p);
ecma_value_t object = *(--stack_top_p);
if (opcode_data & VM_OC_PUT_STACK)
if (object == ecma_make_simple_value (ECMA_SIMPLE_VALUE_REGISTER_REF))
{
*stack_top_p++ = result;
ecma_fast_free_value (frame_ctx_p->registers_p[property]);
frame_ctx_p->registers_p[property] = result;
if (opcode_data & (VM_OC_PUT_STACK | VM_OC_PUT_BLOCK))
{
result = ecma_fast_copy_value (result);
}
}
else if (opcode_data & VM_OC_PUT_BLOCK)
else
{
ecma_fast_free_value (block_result);
block_result = result;
ecma_value_t set_value_result = vm_op_set_value (object,
property,
result,
is_strict);
ecma_free_value (object);
ecma_free_value (property);
if (ecma_is_value_error (set_value_result))
{
ecma_free_value (result);
result = set_value_result;
goto error;
}
if (!(opcode_data & (VM_OC_PUT_STACK | VM_OC_PUT_BLOCK)))
{
ecma_fast_free_value (result);
}
}
}
ecma_fast_free_value (left_value);
if (opcode_data & VM_OC_PUT_STACK)
{
*stack_top_p++ = result;
}
else if (opcode_data & VM_OC_PUT_BLOCK)
{
ecma_fast_free_value (block_result);
block_result = result;
}
free_both_values:
ecma_fast_free_value (right_value);
free_left_value:
ecma_fast_free_value (left_value);
}
error: