Micro optimizations of the virtual machine:

- Branch argument information is encoded in the vm byte
   code data, so CBC flags are not loaded anymore
 - The free_flags variable is removed from the vm_loop
 - Two cases are removed from "get arguments", argument
   processing is simplified
 - The two opcode tables are merged to one
 - The VM_OC_POP opcode has no result, so the break is changed to continue.
 - The VM_OC_PUSH_NUMBER can use ecma_make_integer_value.

JerryScript-DCO-1.0-Signed-off-by: Zoltan Herczeg zherczeg.u-szeged@partner.samsung.com
This commit is contained in:
Zoltan Herczeg
2016-05-24 01:14:23 -07:00
parent be273d874f
commit ac3aa30c82
3 changed files with 130 additions and 170 deletions
+14 -14
View File
@@ -173,19 +173,19 @@
#define CBC_FORWARD_BRANCH(name, stack, vm_oc) \ #define CBC_FORWARD_BRANCH(name, stack, vm_oc) \
CBC_OPCODE (name, CBC_HAS_BRANCH_ARG | CBC_FORWARD_BRANCH_ARG, stack, \ CBC_OPCODE (name, CBC_HAS_BRANCH_ARG | CBC_FORWARD_BRANCH_ARG, stack, \
(vm_oc)) \ (vm_oc) | VM_OC_HAS_BRANCH_ARG) \
CBC_OPCODE (name ## _2, CBC_HAS_BRANCH_ARG | CBC_FORWARD_BRANCH_ARG, stack, \ CBC_OPCODE (name ## _2, CBC_HAS_BRANCH_ARG | CBC_FORWARD_BRANCH_ARG, stack, \
(vm_oc)) \ (vm_oc) | VM_OC_HAS_BRANCH_ARG) \
CBC_OPCODE (name ## _3, CBC_HAS_BRANCH_ARG | CBC_FORWARD_BRANCH_ARG, stack, \ CBC_OPCODE (name ## _3, CBC_HAS_BRANCH_ARG | CBC_FORWARD_BRANCH_ARG, stack, \
(vm_oc)) (vm_oc) | VM_OC_HAS_BRANCH_ARG)
#define CBC_BACKWARD_BRANCH(name, stack, vm_oc) \ #define CBC_BACKWARD_BRANCH(name, stack, vm_oc) \
CBC_OPCODE (name, CBC_HAS_BRANCH_ARG, stack, \ CBC_OPCODE (name, CBC_HAS_BRANCH_ARG, stack, \
(vm_oc)) \ (vm_oc) | VM_OC_HAS_BRANCH_ARG | VM_OC_BACKWARD_BRANCH) \
CBC_OPCODE (name ## _2, CBC_HAS_BRANCH_ARG, stack, \ CBC_OPCODE (name ## _2, CBC_HAS_BRANCH_ARG, stack, \
(vm_oc)) \ (vm_oc) | VM_OC_HAS_BRANCH_ARG | VM_OC_BACKWARD_BRANCH) \
CBC_OPCODE (name ## _3, CBC_HAS_BRANCH_ARG, stack, \ CBC_OPCODE (name ## _3, CBC_HAS_BRANCH_ARG, stack, \
(vm_oc)) (vm_oc) | VM_OC_HAS_BRANCH_ARG | VM_OC_BACKWARD_BRANCH)
#define CBC_BRANCH_OFFSET_LENGTH(opcode) \ #define CBC_BRANCH_OFFSET_LENGTH(opcode) \
((opcode) & 0x3) ((opcode) & 0x3)
@@ -243,7 +243,7 @@
CBC_FORWARD_BRANCH (CBC_BRANCH_IF_LOGICAL_TRUE, -1, \ CBC_FORWARD_BRANCH (CBC_BRANCH_IF_LOGICAL_TRUE, -1, \
VM_OC_BRANCH_IF_LOGICAL_TRUE | VM_OC_GET_STACK) \ VM_OC_BRANCH_IF_LOGICAL_TRUE | VM_OC_GET_STACK) \
CBC_OPCODE (CBC_ARRAY_APPEND, CBC_HAS_POP_STACK_BYTE_ARG, 0, \ CBC_OPCODE (CBC_ARRAY_APPEND, CBC_HAS_POP_STACK_BYTE_ARG, 0, \
VM_OC_APPEND_ARRAY | VM_OC_GET_BYTE) \ VM_OC_APPEND_ARRAY) \
CBC_FORWARD_BRANCH (CBC_BRANCH_IF_LOGICAL_FALSE, -1, \ CBC_FORWARD_BRANCH (CBC_BRANCH_IF_LOGICAL_FALSE, -1, \
VM_OC_BRANCH_IF_LOGICAL_FALSE | VM_OC_GET_STACK) \ VM_OC_BRANCH_IF_LOGICAL_FALSE | VM_OC_GET_STACK) \
CBC_OPCODE (CBC_PUSH_ELISION, CBC_NO_FLAG, 1, \ CBC_OPCODE (CBC_PUSH_ELISION, CBC_NO_FLAG, 1, \
@@ -293,7 +293,7 @@
CBC_OPCODE (CBC_PUSH_PROP_THIS_LITERAL_REFERENCE, CBC_HAS_LITERAL_ARG, 3, \ CBC_OPCODE (CBC_PUSH_PROP_THIS_LITERAL_REFERENCE, CBC_HAS_LITERAL_ARG, 3, \
VM_OC_PROP_REFERENCE | VM_OC_GET_THIS_LITERAL | VM_OC_PUT_STACK) \ VM_OC_PROP_REFERENCE | VM_OC_GET_THIS_LITERAL | VM_OC_PUT_STACK) \
CBC_OPCODE (CBC_NEW, CBC_HAS_POP_STACK_BYTE_ARG, 0, \ CBC_OPCODE (CBC_NEW, CBC_HAS_POP_STACK_BYTE_ARG, 0, \
VM_OC_NEW | VM_OC_GET_BYTE | VM_OC_PUT_STACK) \ VM_OC_NEW | VM_OC_PUT_STACK) \
CBC_OPCODE (CBC_NEW0, CBC_NO_FLAG, 0, \ CBC_OPCODE (CBC_NEW0, CBC_NO_FLAG, 0, \
VM_OC_NEW | VM_OC_PUT_STACK) \ VM_OC_NEW | VM_OC_PUT_STACK) \
CBC_OPCODE (CBC_NEW1, CBC_NO_FLAG, -1, \ CBC_OPCODE (CBC_NEW1, CBC_NO_FLAG, -1, \
@@ -399,17 +399,17 @@
\ \
/* Call opcodes. */ \ /* Call opcodes. */ \
CBC_OPCODE (CBC_CALL, CBC_HAS_POP_STACK_BYTE_ARG, -1, \ CBC_OPCODE (CBC_CALL, CBC_HAS_POP_STACK_BYTE_ARG, -1, \
VM_OC_CALL | VM_OC_GET_BYTE) \ VM_OC_CALL) \
CBC_OPCODE (CBC_CALL_PUSH_RESULT, CBC_HAS_POP_STACK_BYTE_ARG, 0, \ CBC_OPCODE (CBC_CALL_PUSH_RESULT, CBC_HAS_POP_STACK_BYTE_ARG, 0, \
VM_OC_CALL | VM_OC_GET_BYTE | VM_OC_PUT_STACK) \ VM_OC_CALL | VM_OC_PUT_STACK) \
CBC_OPCODE (CBC_CALL_BLOCK, CBC_HAS_POP_STACK_BYTE_ARG, -1, \ CBC_OPCODE (CBC_CALL_BLOCK, CBC_HAS_POP_STACK_BYTE_ARG, -1, \
VM_OC_CALL | VM_OC_GET_BYTE | VM_OC_PUT_BLOCK) \ VM_OC_CALL | VM_OC_PUT_BLOCK) \
CBC_OPCODE (CBC_CALL_PROP, CBC_HAS_POP_STACK_BYTE_ARG, -3, \ CBC_OPCODE (CBC_CALL_PROP, CBC_HAS_POP_STACK_BYTE_ARG, -3, \
VM_OC_CALL | VM_OC_GET_BYTE) \ VM_OC_CALL) \
CBC_OPCODE (CBC_CALL_PROP_PUSH_RESULT, CBC_HAS_POP_STACK_BYTE_ARG, -2, \ CBC_OPCODE (CBC_CALL_PROP_PUSH_RESULT, CBC_HAS_POP_STACK_BYTE_ARG, -2, \
VM_OC_CALL | VM_OC_GET_BYTE | VM_OC_PUT_STACK) \ VM_OC_CALL | VM_OC_PUT_STACK) \
CBC_OPCODE (CBC_CALL_PROP_BLOCK, CBC_HAS_POP_STACK_BYTE_ARG, -3, \ CBC_OPCODE (CBC_CALL_PROP_BLOCK, CBC_HAS_POP_STACK_BYTE_ARG, -3, \
VM_OC_CALL | VM_OC_GET_BYTE | VM_OC_PUT_BLOCK) \ VM_OC_CALL | VM_OC_PUT_BLOCK) \
CBC_OPCODE (CBC_CALL0, CBC_NO_FLAG, -1, \ CBC_OPCODE (CBC_CALL0, CBC_NO_FLAG, -1, \
VM_OC_CALL) \ VM_OC_CALL) \
CBC_OPCODE (CBC_CALL0_PUSH_RESULT, CBC_NO_FLAG, 0, \ CBC_OPCODE (CBC_CALL0_PUSH_RESULT, CBC_NO_FLAG, 0, \
+97 -145
View File
@@ -151,18 +151,11 @@ vm_init (ecma_compiled_code_t *program_p) /**< pointer to byte-code data */
#define CBC_OPCODE(arg1, arg2, arg3, arg4) arg4, #define CBC_OPCODE(arg1, arg2, arg3, arg4) arg4,
/** /**
* Decode table for opcodes. * Decode table for both opcodes and extended opcodes.
*/ */
static const uint16_t vm_decode_table[] = static const uint16_t vm_decode_table[] =
{ {
CBC_OPCODE_LIST CBC_OPCODE_LIST
};
/**
* Decode table for extended opcodes.
*/
static const uint16_t vm_ext_decode_table[] =
{
CBC_EXT_OPCODE_LIST CBC_EXT_OPCODE_LIST
}; };
@@ -451,15 +444,6 @@ opfunc_construct (vm_frame_ctx_t *frame_ctx_p) /**< frame context */
frame_ctx_p->stack_top_p = stack_top_p; frame_ctx_p->stack_top_p = stack_top_p;
} /* opfunc_construct */ } /* opfunc_construct */
/**
* Indicate which value should be freed.
*/
enum
{
VM_FREE_LEFT_VALUE = 0x1,
VM_FREE_RIGHT_VALUE = 0x2,
};
#define READ_LITERAL_INDEX(destination) \ #define READ_LITERAL_INDEX(destination) \
do \ do \
{ \ { \
@@ -474,7 +458,7 @@ enum
/* TODO: For performance reasons, we define this as a macro. /* TODO: For performance reasons, we define this as a macro.
* When we are able to construct a function with similar speed, * When we are able to construct a function with similar speed,
* we can remove this macro. */ * we can remove this macro. */
#define READ_LITERAL(literal_index, target_value, target_free_op) \ #define READ_LITERAL(literal_index, target_value) \
do \ do \
{ \ { \
if ((literal_index) < ident_end) \ if ((literal_index) < ident_end) \
@@ -483,7 +467,6 @@ enum
{ \ { \
/* Note: There should be no specialization for arguments. */ \ /* Note: There should be no specialization for arguments. */ \
(target_value) = ecma_fast_copy_value (frame_ctx_p->registers_p[literal_index]); \ (target_value) = ecma_fast_copy_value (frame_ctx_p->registers_p[literal_index]); \
target_free_op; \
} \ } \
else \ else \
{ \ { \
@@ -508,7 +491,6 @@ enum
goto error; \ goto error; \
} \ } \
(target_value) = last_completion_value; \ (target_value) = last_completion_value; \
target_free_op; \
} \ } \
} \ } \
else if (literal_index < const_literal_end) \ else if (literal_index < const_literal_end) \
@@ -525,13 +507,11 @@ enum
ecma_string_t *string_p = ecma_new_ecma_string_from_lit_cp (lit_cpointer); \ ecma_string_t *string_p = ecma_new_ecma_string_from_lit_cp (lit_cpointer); \
(target_value) = ecma_make_string_value (string_p); \ (target_value) = ecma_make_string_value (string_p); \
} \ } \
target_free_op; \
} \ } \
else \ else \
{ \ { \
/* Object construction. */ \ /* Object construction. */ \
(target_value) = vm_construct_literal_object (frame_ctx_p, literal_start_p[literal_index]); \ (target_value) = vm_construct_literal_object (frame_ctx_p, literal_start_p[literal_index]); \
target_free_op; \
} \ } \
} \ } \
while (0) while (0)
@@ -710,11 +690,10 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */
uint16_t ident_end; uint16_t ident_end;
uint16_t const_literal_end; uint16_t const_literal_end;
int32_t branch_offset = 0; int32_t branch_offset = 0;
ecma_value_t left_value = 0; ecma_value_t left_value;
ecma_value_t right_value = 0; ecma_value_t right_value;
ecma_value_t result = 0; ecma_value_t result = 0;
ecma_value_t block_result = ecma_make_simple_value (ECMA_SIMPLE_VALUE_UNDEFINED); ecma_value_t block_result = ecma_make_simple_value (ECMA_SIMPLE_VALUE_UNDEFINED);
uint8_t free_flags = 0;
bool is_strict = ((frame_ctx_p->bytecode_header_p->status_flags & CBC_CODE_FLAGS_STRICT_MODE) != 0); bool is_strict = ((frame_ctx_p->bytecode_header_p->status_flags & CBC_CODE_FLAGS_STRICT_MODE) != 0);
/* Prepare for byte code execution. */ /* Prepare for byte code execution. */
@@ -754,23 +733,19 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */
{ {
uint8_t *byte_code_start_p = byte_code_p; uint8_t *byte_code_start_p = byte_code_p;
uint8_t opcode; uint8_t opcode;
uint8_t opcode_flags;
uint32_t opcode_data; uint32_t opcode_data;
opcode = *byte_code_p++; opcode = *byte_code_p++;
opcode_data = opcode;
if (opcode == CBC_EXT_OPCODE) if (opcode == CBC_EXT_OPCODE)
{ {
opcode = *byte_code_p++; opcode = *byte_code_p++;
opcode_flags = cbc_ext_flags[opcode]; opcode_data = (uint32_t) ((CBC_END + 1) + opcode);
opcode_data = vm_ext_decode_table[opcode];
}
else
{
opcode_flags = cbc_flags[opcode];
opcode_data = vm_decode_table[opcode];
} }
if (opcode_flags & CBC_HAS_BRANCH_ARG) opcode_data = vm_decode_table[opcode_data];
if (opcode_data & VM_OC_HAS_BRANCH_ARG)
{ {
branch_offset = 0; branch_offset = 0;
switch (CBC_BRANCH_OFFSET_LENGTH (opcode)) switch (CBC_BRANCH_OFFSET_LENGTH (opcode))
@@ -794,92 +769,69 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */
break; break;
} }
} }
if (CBC_BRANCH_IS_BACKWARD (opcode_flags))
if (opcode_data & VM_OC_BACKWARD_BRANCH)
{ {
branch_offset = -branch_offset; branch_offset = -branch_offset;
} }
} }
free_flags = 0; left_value = ecma_make_simple_value (ECMA_SIMPLE_VALUE_UNDEFINED);
right_value = ecma_make_simple_value (ECMA_SIMPLE_VALUE_UNDEFINED);
if (VM_OC_HAS_GET_ARGS (opcode_data)) if (VM_OC_HAS_GET_ARGS (opcode_data))
{ {
uint32_t operands = VM_OC_GET_ARGS_GET_INDEX (opcode_data); uint32_t operands = VM_OC_GET_ARGS_INDEX (opcode_data);
if (operands >= VM_OC_GET_ARGS_GET_INDEX (VM_OC_GET_LITERAL)) if (operands >= VM_OC_GET_LITERAL)
{ {
uint16_t literal_index; uint16_t literal_index;
READ_LITERAL_INDEX (literal_index); READ_LITERAL_INDEX (literal_index);
READ_LITERAL (literal_index, READ_LITERAL (literal_index,
left_value, left_value);
free_flags = VM_FREE_LEFT_VALUE);
switch (operands) if (operands != VM_OC_GET_LITERAL)
{ {
case VM_OC_GET_ARGS_GET_INDEX (VM_OC_GET_STACK_LITERAL): switch (operands)
{ {
JERRY_ASSERT (stack_top_p > frame_ctx_p->registers_p + register_end); case VM_OC_GET_LITERAL_LITERAL:
right_value = left_value; {
left_value = *(--stack_top_p); uint16_t literal_index;
free_flags = (uint8_t) ((free_flags << 1) | VM_FREE_LEFT_VALUE); READ_LITERAL_INDEX (literal_index);
break; READ_LITERAL (literal_index,
} right_value);
case VM_OC_GET_ARGS_GET_INDEX (VM_OC_GET_LITERAL_BYTE): break;
{ }
right_value = *(byte_code_p++); case VM_OC_GET_STACK_LITERAL:
break; {
} JERRY_ASSERT (stack_top_p > frame_ctx_p->registers_p + register_end);
case VM_OC_GET_ARGS_GET_INDEX (VM_OC_GET_LITERAL_LITERAL): right_value = left_value;
{ left_value = *(--stack_top_p);
uint16_t literal_index; break;
READ_LITERAL_INDEX (literal_index); }
READ_LITERAL (literal_index, default:
right_value, {
free_flags |= VM_FREE_RIGHT_VALUE); JERRY_ASSERT (operands == VM_OC_GET_THIS_LITERAL);
break; right_value = left_value;
} left_value = ecma_copy_value (frame_ctx_p->this_binding);
case VM_OC_GET_ARGS_GET_INDEX (VM_OC_GET_THIS_LITERAL): break;
{ }
right_value = left_value;
left_value = ecma_copy_value (frame_ctx_p->this_binding);
free_flags = (uint8_t) ((free_flags << 1) | VM_FREE_LEFT_VALUE);
break;
}
default:
{
JERRY_ASSERT (operands == VM_OC_GET_ARGS_GET_INDEX (VM_OC_GET_LITERAL));
break;
} }
} }
} }
else else
{ {
switch (operands) JERRY_ASSERT (operands == VM_OC_GET_STACK
|| operands == VM_OC_GET_STACK_STACK);
JERRY_ASSERT (stack_top_p > frame_ctx_p->registers_p + register_end);
left_value = *(--stack_top_p);
if (operands == VM_OC_GET_STACK_STACK)
{ {
case VM_OC_GET_ARGS_GET_INDEX (VM_OC_GET_STACK): JERRY_ASSERT (stack_top_p > frame_ctx_p->registers_p + register_end);
{ right_value = left_value;
JERRY_ASSERT (stack_top_p > frame_ctx_p->registers_p + register_end); left_value = *(--stack_top_p);
left_value = *(--stack_top_p);
free_flags = VM_FREE_LEFT_VALUE;
break;
}
case VM_OC_GET_ARGS_GET_INDEX (VM_OC_GET_STACK_STACK):
{
JERRY_ASSERT (stack_top_p > frame_ctx_p->registers_p + register_end + 1);
right_value = *(--stack_top_p);
left_value = *(--stack_top_p);
free_flags = VM_FREE_LEFT_VALUE | VM_FREE_RIGHT_VALUE;
break;
}
case VM_OC_GET_ARGS_GET_INDEX (VM_OC_GET_BYTE):
{
right_value = *(byte_code_p++);
break;
}
default:
{
JERRY_UNREACHABLE ();
break;
}
} }
} }
} }
@@ -895,7 +847,7 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */
{ {
JERRY_ASSERT (stack_top_p > frame_ctx_p->registers_p + register_end); JERRY_ASSERT (stack_top_p > frame_ctx_p->registers_p + register_end);
ecma_free_value (*(--stack_top_p)); ecma_free_value (*(--stack_top_p));
break; continue;
} }
case VM_OC_POP_BLOCK: case VM_OC_POP_BLOCK:
{ {
@@ -918,13 +870,13 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */
uint16_t literal_index; uint16_t literal_index;
*(stack_top_p++) = left_value; *(stack_top_p++) = left_value;
*(stack_top_p++) = right_value; left_value = ecma_make_simple_value (ECMA_SIMPLE_VALUE_UNDEFINED);
free_flags = 0;
READ_LITERAL_INDEX (literal_index); READ_LITERAL_INDEX (literal_index);
READ_LITERAL (literal_index, READ_LITERAL (literal_index,
left_value, left_value);
(void) 0);
*(stack_top_p++) = right_value;
*(stack_top_p++) = left_value; *(stack_top_p++) = left_value;
continue; continue;
} }
@@ -956,7 +908,7 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */
} }
case VM_OC_PUSH_NUMBER: case VM_OC_PUSH_NUMBER:
{ {
int32_t number; ecma_integer_value_t number;
if (opcode == CBC_PUSH_NUMBER_0) if (opcode == CBC_PUSH_NUMBER_0)
{ {
@@ -974,7 +926,7 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */
} }
} }
result = ecma_make_int32_value (number); result = ecma_make_integer_value (number);
break; break;
} }
case VM_OC_PUSH_OBJECT: case VM_OC_PUSH_OBJECT:
@@ -1065,6 +1017,7 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */
ecma_string_t *length_str_p; ecma_string_t *length_str_p;
ecma_property_t *length_prop_p; ecma_property_t *length_prop_p;
uint32_t length_num; uint32_t length_num;
uint32_t values_length = *byte_code_p++;
ecma_property_descriptor_t prop_desc; ecma_property_descriptor_t prop_desc;
prop_desc = ecma_make_empty_property_descriptor (); prop_desc = ecma_make_empty_property_descriptor ();
@@ -1079,7 +1032,7 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */
prop_desc.is_configurable_defined = true; prop_desc.is_configurable_defined = true;
prop_desc.is_configurable = true; prop_desc.is_configurable = true;
stack_top_p -= right_value; stack_top_p -= values_length;
array_obj_p = ecma_get_object_from_value (stack_top_p[-1]); array_obj_p = ecma_get_object_from_value (stack_top_p[-1]);
length_str_p = ecma_get_magic_string (LIT_MAGIC_STRING_LENGTH); length_str_p = ecma_get_magic_string (LIT_MAGIC_STRING_LENGTH);
@@ -1092,7 +1045,7 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */
ecma_deref_ecma_string (length_str_p); ecma_deref_ecma_string (length_str_p);
for (uint32_t i = 0; i < right_value; i++) for (uint32_t i = 0; i < values_length; i++)
{ {
if (!ecma_is_value_array_hole (stack_top_p[i])) if (!ecma_is_value_array_hole (stack_top_p[i]))
{ {
@@ -1184,14 +1137,13 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */
*stack_top_p++ = left_value; *stack_top_p++ = left_value;
right_value = left_value; right_value = left_value;
left_value = stack_top_p[-2]; left_value = stack_top_p[-2];
free_flags = 0;
} }
else else
{ {
JERRY_ASSERT (opcode == CBC_PUSH_PROP_LITERAL_LITERAL_REFERENCE JERRY_ASSERT (opcode == CBC_PUSH_PROP_LITERAL_LITERAL_REFERENCE
|| opcode == CBC_PUSH_PROP_THIS_LITERAL_REFERENCE); || opcode == CBC_PUSH_PROP_THIS_LITERAL_REFERENCE);
*stack_top_p++ = ecma_copy_value (left_value); *stack_top_p++ = left_value;
*stack_top_p++ = ecma_copy_value (right_value); *stack_top_p++ = right_value;
} }
/* FALLTHRU */ /* FALLTHRU */
} }
@@ -1207,6 +1159,11 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */
if (ecma_is_value_error (last_completion_value)) if (ecma_is_value_error (last_completion_value))
{ {
if (opcode >= CBC_PUSH_PROP_REFERENCE && opcode < CBC_PRE_INCR)
{
left_value = ecma_make_simple_value (ECMA_SIMPLE_VALUE_UNDEFINED);
right_value = ecma_make_simple_value (ECMA_SIMPLE_VALUE_UNDEFINED);
}
goto error; goto error;
} }
@@ -1214,12 +1171,17 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */
if (opcode < CBC_PRE_INCR) if (opcode < CBC_PRE_INCR)
{ {
if (opcode >= CBC_PUSH_PROP_REFERENCE)
{
left_value = ecma_make_simple_value (ECMA_SIMPLE_VALUE_UNDEFINED);
right_value = ecma_make_simple_value (ECMA_SIMPLE_VALUE_UNDEFINED);
}
break; break;
} }
stack_top_p += 2; stack_top_p += 2;
left_value = result; left_value = result;
free_flags = VM_FREE_LEFT_VALUE; right_value = ecma_make_simple_value (ECMA_SIMPLE_VALUE_UNDEFINED);
/* FALLTHRU */ /* FALLTHRU */
} }
case VM_OC_PRE_INCR: case VM_OC_PRE_INCR:
@@ -1359,14 +1321,14 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */
case VM_OC_ASSIGN: case VM_OC_ASSIGN:
{ {
result = left_value; result = left_value;
free_flags = 0; left_value = ecma_make_simple_value (ECMA_SIMPLE_VALUE_UNDEFINED);
break; break;
} }
case VM_OC_ASSIGN_PROP: case VM_OC_ASSIGN_PROP:
{ {
result = stack_top_p[-1]; result = stack_top_p[-1];
stack_top_p[-1] = left_value; stack_top_p[-1] = left_value;
free_flags = 0; left_value = ecma_make_simple_value (ECMA_SIMPLE_VALUE_UNDEFINED);
break; break;
} }
case VM_OC_ASSIGN_PROP_THIS: case VM_OC_ASSIGN_PROP_THIS:
@@ -1374,7 +1336,7 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */
result = stack_top_p[-1]; result = stack_top_p[-1];
stack_top_p[-1] = ecma_copy_value (frame_ctx_p->this_binding); stack_top_p[-1] = ecma_copy_value (frame_ctx_p->this_binding);
*stack_top_p++ = left_value; *stack_top_p++ = left_value;
free_flags = 0; left_value = ecma_make_simple_value (ECMA_SIMPLE_VALUE_UNDEFINED);
break; break;
} }
case VM_OC_RET: case VM_OC_RET:
@@ -1390,13 +1352,13 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */
} }
last_completion_value = left_value; last_completion_value = left_value;
free_flags = 0; left_value = ecma_make_simple_value (ECMA_SIMPLE_VALUE_UNDEFINED);
goto error; goto error;
} }
case VM_OC_THROW: case VM_OC_THROW:
{ {
last_completion_value = ecma_make_error_value (left_value); last_completion_value = ecma_make_error_value (left_value);
free_flags = 0; left_value = ecma_make_simple_value (ECMA_SIMPLE_VALUE_UNDEFINED);
goto error; goto error;
} }
case VM_OC_THROW_REFERENCE_ERROR: case VM_OC_THROW_REFERENCE_ERROR:
@@ -1412,8 +1374,6 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */
} }
case VM_OC_CALL: case VM_OC_CALL:
{ {
JERRY_ASSERT (free_flags == 0);
if (frame_ctx_p->call_operation == VM_NO_EXEC_OP) if (frame_ctx_p->call_operation == VM_NO_EXEC_OP)
{ {
frame_ctx_p->call_operation = VM_EXEC_CALL; frame_ctx_p->call_operation = VM_EXEC_CALL;
@@ -1422,6 +1382,12 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */
frame_ctx_p->call_block_result = block_result; frame_ctx_p->call_block_result = block_result;
return ecma_make_simple_value (ECMA_SIMPLE_VALUE_UNDEFINED); return ecma_make_simple_value (ECMA_SIMPLE_VALUE_UNDEFINED);
} }
if (opcode < CBC_CALL0)
{
byte_code_p++;
}
frame_ctx_p->call_operation = VM_NO_EXEC_OP; frame_ctx_p->call_operation = VM_NO_EXEC_OP;
last_completion_value = *(--stack_top_p); last_completion_value = *(--stack_top_p);
@@ -1438,14 +1404,12 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */
} }
else else
{ {
ecma_free_value (last_completion_value); left_value = last_completion_value;
} }
break; break;
} }
case VM_OC_NEW: case VM_OC_NEW:
{ {
JERRY_ASSERT (free_flags == 0);
if (frame_ctx_p->call_operation == VM_NO_EXEC_OP) if (frame_ctx_p->call_operation == VM_NO_EXEC_OP)
{ {
frame_ctx_p->call_operation = VM_EXEC_CONSTRUCT; frame_ctx_p->call_operation = VM_EXEC_CONSTRUCT;
@@ -1454,6 +1418,12 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */
frame_ctx_p->call_block_result = block_result; frame_ctx_p->call_block_result = block_result;
return ecma_make_simple_value (ECMA_SIMPLE_VALUE_UNDEFINED); return ecma_make_simple_value (ECMA_SIMPLE_VALUE_UNDEFINED);
} }
if (opcode < CBC_NEW0)
{
byte_code_p++;
}
frame_ctx_p->call_operation = VM_NO_EXEC_OP; frame_ctx_p->call_operation = VM_NO_EXEC_OP;
last_completion_value = *(--stack_top_p); last_completion_value = *(--stack_top_p);
@@ -1544,8 +1514,6 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */
goto error; goto error;
} }
JERRY_ASSERT (free_flags & VM_FREE_LEFT_VALUE);
bool branch_if_false = (opcode_flags & VM_OC_BRANCH_IF_FALSE_FLAG); bool branch_if_false = (opcode_flags & VM_OC_BRANCH_IF_FALSE_FLAG);
if (last_completion_value == ecma_make_simple_value (branch_if_false ? ECMA_SIMPLE_VALUE_FALSE if (last_completion_value == ecma_make_simple_value (branch_if_false ? ECMA_SIMPLE_VALUE_FALSE
@@ -1554,7 +1522,7 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */
byte_code_p = byte_code_start_p + branch_offset; byte_code_p = byte_code_start_p + branch_offset;
if (opcode_flags & VM_OC_LOGICAL_BRANCH_FLAG) if (opcode_flags & VM_OC_LOGICAL_BRANCH_FLAG)
{ {
free_flags = 0; left_value = ecma_make_simple_value (ECMA_SIMPLE_VALUE_UNDEFINED);
++stack_top_p; ++stack_top_p;
} }
} }
@@ -1621,7 +1589,6 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */
if (literal_index < register_end) if (literal_index < register_end)
{ {
left_value = ecma_copy_value (frame_ctx_p->registers_p[literal_index]); left_value = ecma_copy_value (frame_ctx_p->registers_p[literal_index]);
free_flags = VM_FREE_LEFT_VALUE;
} }
else else
{ {
@@ -1650,7 +1617,6 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */
} }
left_value = last_completion_value; left_value = last_completion_value;
free_flags = VM_FREE_LEFT_VALUE;
} }
/* FALLTHRU */ /* FALLTHRU */
} }
@@ -2269,27 +2235,13 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */
} }
} }
if (free_flags & VM_FREE_LEFT_VALUE) ecma_fast_free_value (left_value);
{ ecma_fast_free_value (right_value);
ecma_fast_free_value (left_value);
}
if (free_flags & VM_FREE_RIGHT_VALUE)
{
ecma_fast_free_value (right_value);
}
} }
error: error:
if (free_flags & VM_FREE_LEFT_VALUE) ecma_fast_free_value (left_value);
{ ecma_fast_free_value (right_value);
ecma_fast_free_value (left_value);
}
if (free_flags & VM_FREE_RIGHT_VALUE)
{
ecma_fast_free_value (right_value);
}
if (unlikely (ecma_is_value_error (last_completion_value))) if (unlikely (ecma_is_value_error (last_completion_value)))
{ {
+19 -11
View File
@@ -42,6 +42,16 @@
* stack, etc.) * stack, etc.)
*/ */
/**
* Opcode has branch argument
*/
#define VM_OC_HAS_BRANCH_ARG 0x8000
/**
* Branch argument is a backward branch
*/
#define VM_OC_BACKWARD_BRANCH 0x4000
/** /**
* Position of "get arguments" opcode. * Position of "get arguments" opcode.
*/ */
@@ -50,7 +60,7 @@
/** /**
* Mask of "get arguments" opcode. * Mask of "get arguments" opcode.
*/ */
#define VM_OC_GET_ARGS_MASK 0x1f #define VM_OC_GET_ARGS_MASK 0x7
/** /**
* Generate the binary representation of a "get arguments" opcode. * Generate the binary representation of a "get arguments" opcode.
@@ -60,7 +70,7 @@
/** /**
* Extract the "get arguments" opcode. * Extract the "get arguments" opcode.
*/ */
#define VM_OC_GET_ARGS_GET_INDEX(O) (((O) >> VM_OC_GET_ARGS_SHIFT) & VM_OC_GET_ARGS_MASK) #define VM_OC_GET_ARGS_INDEX(O) ((O) & (VM_OC_GET_ARGS_MASK << VM_OC_GET_ARGS_SHIFT))
/** /**
* Checks whether the result is stored somewhere. * Checks whether the result is stored somewhere.
@@ -73,16 +83,14 @@
typedef enum typedef enum
{ {
VM_OC_GET_NONE = VM_OC_GET_ARGS_CREATE_INDEX (0), /**< do nothing */ VM_OC_GET_NONE = VM_OC_GET_ARGS_CREATE_INDEX (0), /**< do nothing */
VM_OC_GET_STACK = VM_OC_GET_ARGS_CREATE_INDEX (1), /**< pop one elemnet from the stack */ VM_OC_GET_STACK = VM_OC_GET_ARGS_CREATE_INDEX (1), /**< pop one element from the stack */
VM_OC_GET_STACK_STACK = VM_OC_GET_ARGS_CREATE_INDEX (2), /**< pop two elemnets from the stack */ VM_OC_GET_STACK_STACK = VM_OC_GET_ARGS_CREATE_INDEX (2), /**< pop two elements from the stack */
VM_OC_GET_BYTE = VM_OC_GET_ARGS_CREATE_INDEX (3), /**< read a byte */
VM_OC_GET_LITERAL = VM_OC_GET_ARGS_CREATE_INDEX (4), /**< resolve literal */ VM_OC_GET_LITERAL = VM_OC_GET_ARGS_CREATE_INDEX (3), /**< resolve literal */
VM_OC_GET_STACK_LITERAL = VM_OC_GET_ARGS_CREATE_INDEX (5), /**< pop one elemnet from the stack VM_OC_GET_LITERAL_LITERAL = VM_OC_GET_ARGS_CREATE_INDEX (4), /**< resolve two literals */
VM_OC_GET_STACK_LITERAL = VM_OC_GET_ARGS_CREATE_INDEX (5), /**< pop one element from the stack
* and resolve a literal */ * and resolve a literal */
VM_OC_GET_LITERAL_BYTE = VM_OC_GET_ARGS_CREATE_INDEX (6), /**< pop one elemnet from stack and read a byte */ VM_OC_GET_THIS_LITERAL = VM_OC_GET_ARGS_CREATE_INDEX (6), /**< get this and resolve a literal */
VM_OC_GET_LITERAL_LITERAL = VM_OC_GET_ARGS_CREATE_INDEX (7), /**< resolve two literals */
VM_OC_GET_THIS_LITERAL = VM_OC_GET_ARGS_CREATE_INDEX (8), /**< get this and resolve a literal */
} vm_oc_get_types; } vm_oc_get_types;
/** /**
@@ -229,7 +237,7 @@ typedef enum
/** /**
* Position of "put result" opcode. * Position of "put result" opcode.
*/ */
#define VM_OC_PUT_RESULT_SHIFT 12 #define VM_OC_PUT_RESULT_SHIFT 10
/** /**
* Mask of "put result" opcode. * Mask of "put result" opcode.