diff --git a/jerry-core/vm/vm.c b/jerry-core/vm/vm.c index 6d92bbc51..12362bfbd 100644 --- a/jerry-core/vm/vm.c +++ b/jerry-core/vm/vm.c @@ -153,7 +153,7 @@ vm_init (ecma_compiled_code_t *program_p) /**< pointer to byte-code data */ /** * Decode table for opcodes. */ -static const uint32_t vm_decode_table[] = +static const uint16_t vm_decode_table[] = { CBC_OPCODE_LIST }; @@ -161,7 +161,7 @@ static const uint32_t vm_decode_table[] = /** * Decode table for extended opcodes. */ -static const uint32_t vm_ext_decode_table[] = +static const uint16_t vm_ext_decode_table[] = { CBC_EXT_OPCODE_LIST }; @@ -801,11 +801,11 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */ } free_flags = 0; - if (opcode_data & (VM_OC_GET_DATA_MASK << VM_OC_GET_DATA_SHIFT)) + if (VM_OC_HAS_GET_ARGS (opcode_data)) { - uint32_t operands = VM_OC_GET_DATA_GET_ID (opcode_data); + uint32_t operands = VM_OC_GET_ARGS_GET_INDEX (opcode_data); - if (operands >= VM_OC_GET_DATA_GET_ID (VM_OC_GET_LITERAL)) + if (operands >= VM_OC_GET_ARGS_GET_INDEX (VM_OC_GET_LITERAL)) { uint16_t literal_index; READ_LITERAL_INDEX (literal_index); @@ -815,7 +815,7 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */ switch (operands) { - case VM_OC_GET_DATA_GET_ID (VM_OC_GET_STACK_LITERAL): + case VM_OC_GET_ARGS_GET_INDEX (VM_OC_GET_STACK_LITERAL): { JERRY_ASSERT (stack_top_p > frame_ctx_p->registers_p + register_end); right_value = left_value; @@ -823,12 +823,12 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */ free_flags = (uint8_t) ((free_flags << 1) | VM_FREE_LEFT_VALUE); break; } - case VM_OC_GET_DATA_GET_ID (VM_OC_GET_LITERAL_BYTE): + case VM_OC_GET_ARGS_GET_INDEX (VM_OC_GET_LITERAL_BYTE): { right_value = *(byte_code_p++); break; } - case VM_OC_GET_DATA_GET_ID (VM_OC_GET_LITERAL_LITERAL): + case VM_OC_GET_ARGS_GET_INDEX (VM_OC_GET_LITERAL_LITERAL): { uint16_t literal_index; READ_LITERAL_INDEX (literal_index); @@ -837,7 +837,7 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */ free_flags |= VM_FREE_RIGHT_VALUE); break; } - case VM_OC_GET_DATA_GET_ID (VM_OC_GET_THIS_LITERAL): + case VM_OC_GET_ARGS_GET_INDEX (VM_OC_GET_THIS_LITERAL): { right_value = left_value; left_value = ecma_copy_value (frame_ctx_p->this_binding); @@ -846,7 +846,7 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */ } default: { - JERRY_ASSERT (operands == VM_OC_GET_DATA_GET_ID (VM_OC_GET_LITERAL)); + JERRY_ASSERT (operands == VM_OC_GET_ARGS_GET_INDEX (VM_OC_GET_LITERAL)); break; } } @@ -855,14 +855,14 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */ { switch (operands) { - case VM_OC_GET_DATA_GET_ID (VM_OC_GET_STACK): + case VM_OC_GET_ARGS_GET_INDEX (VM_OC_GET_STACK): { JERRY_ASSERT (stack_top_p > frame_ctx_p->registers_p + register_end); left_value = *(--stack_top_p); free_flags = VM_FREE_LEFT_VALUE; break; } - case VM_OC_GET_DATA_GET_ID (VM_OC_GET_STACK_STACK): + 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); @@ -870,7 +870,7 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */ free_flags = VM_FREE_LEFT_VALUE | VM_FREE_RIGHT_VALUE; break; } - case VM_OC_GET_DATA_GET_ID (VM_OC_GET_BYTE): + case VM_OC_GET_ARGS_GET_INDEX (VM_OC_GET_BYTE): { right_value = *(byte_code_p++); break; @@ -1227,7 +1227,7 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */ case VM_OC_POST_INCR: case VM_OC_POST_DECR: { - uint32_t base = VM_OC_GROUP_GET_INDEX (opcode_data) - VM_OC_PROP_PRE_INCR; + uint32_t opcode_flags = VM_OC_GROUP_GET_INDEX (opcode_data) - VM_OC_PROP_PRE_INCR; last_completion_value = ecma_op_to_number (left_value); @@ -1244,9 +1244,8 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */ ecma_integer_value_t int_value = (ecma_integer_value_t) result; ecma_integer_value_t int_increase; - if (base & 0x2) + if (opcode_flags & VM_OC_DECREMENT_OPERATOR_FLAG) { - /* For decrement operators */ if (int_value <= (ECMA_INTEGER_NUMBER_MIN << ECMA_DIRECT_SHIFT)) { int_increase = 0; @@ -1270,12 +1269,12 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */ if (int_increase != 0) { - /* Post operators require the unmodifed number value. */ - if (base & 0x4) + /* Postfix operators require the unmodifed number value. */ + if (opcode_flags & VM_OC_POST_INCR_DECR_OPERATOR_FLAG) { if (opcode_data & VM_OC_PUT_STACK) { - if (base & 0x1) + if (opcode_flags & VM_OC_IDENT_INCR_DECR_OPERATOR_FLAG) { JERRY_ASSERT (opcode == CBC_POST_INCR_IDENT_PUSH_RESULT || opcode == CBC_POST_DECR_IDENT_PUSH_RESULT); @@ -1313,18 +1312,18 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */ ecma_number_t increase = ECMA_NUMBER_ONE; ecma_number_t result_number = ecma_get_number_from_value (result); - if (base & 0x2) + if (opcode_flags & VM_OC_DECREMENT_OPERATOR_FLAG) { /* For decrement operators */ increase = ECMA_NUMBER_MINUS_ONE; } /* Post operators require the unmodifed number value. */ - if (base & 0x4) + if (opcode_flags & VM_OC_POST_INCR_DECR_OPERATOR_FLAG) { if (opcode_data & VM_OC_PUT_STACK) { - if (base & 0x1) + if (opcode_flags & VM_OC_IDENT_INCR_DECR_OPERATOR_FLAG) { JERRY_ASSERT (opcode == CBC_POST_INCR_IDENT_PUSH_RESULT || opcode == CBC_POST_DECR_IDENT_PUSH_RESULT); @@ -1433,7 +1432,7 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */ goto error; } - if (opcode_data & (VM_OC_PUT_DATA_MASK << VM_OC_PUT_DATA_SHIFT)) + if (VM_OC_HAS_PUT_RESULT (opcode_data)) { result = last_completion_value; } @@ -1465,7 +1464,7 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */ goto error; } - JERRY_ASSERT (opcode_data & (VM_OC_PUT_DATA_MASK << VM_OC_PUT_DATA_SHIFT)); + JERRY_ASSERT (VM_OC_HAS_PUT_RESULT (opcode_data)); result = last_completion_value; break; } @@ -1536,7 +1535,7 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */ case VM_OC_BRANCH_IF_LOGICAL_TRUE: case VM_OC_BRANCH_IF_LOGICAL_FALSE: { - uint32_t base = VM_OC_GROUP_GET_INDEX (opcode_data) - VM_OC_BRANCH_IF_TRUE; + uint32_t opcode_flags = VM_OC_GROUP_GET_INDEX (opcode_data) - VM_OC_BRANCH_IF_TRUE; last_completion_value = ecma_op_to_boolean (left_value); @@ -1546,11 +1545,14 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */ } JERRY_ASSERT (free_flags & VM_FREE_LEFT_VALUE); - if (last_completion_value == ecma_make_simple_value ((base & 0x1) ? ECMA_SIMPLE_VALUE_FALSE - : ECMA_SIMPLE_VALUE_TRUE)) + + 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 + : ECMA_SIMPLE_VALUE_TRUE)) { byte_code_p = byte_code_start_p + branch_offset; - if (base & 0x2) + if (opcode_flags & VM_OC_LOGICAL_BRANCH_FLAG) { free_flags = 0; ++stack_top_p; @@ -2170,7 +2172,7 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */ } } - if (opcode_data & (VM_OC_PUT_DATA_MASK << VM_OC_PUT_DATA_SHIFT)) + if (VM_OC_HAS_PUT_RESULT (opcode_data)) { if (opcode_data & VM_OC_PUT_IDENT) { diff --git a/jerry-core/vm/vm.h b/jerry-core/vm/vm.h index 8ec6fa5f1..919769ed3 100644 --- a/jerry-core/vm/vm.h +++ b/jerry-core/vm/vm.h @@ -29,33 +29,71 @@ * @{ */ -#define VM_OC_GET_DATA_SHIFT 24 -#define VM_OC_GET_DATA_MASK 0x1f -#define VM_OC_GET_DATA_CREATE_ID(V) \ - (((V) & VM_OC_GET_DATA_MASK) << VM_OC_GET_DATA_SHIFT) -#define VM_OC_GET_DATA_GET_ID(O) \ - (((O) >> VM_OC_GET_DATA_SHIFT) & VM_OC_GET_DATA_MASK) +/** + * Each CBC opcode is transformed to three vm opcodes: + * + * - first opcode is a "get arguments" opcode which specifies + * the type (register, literal, stack, etc.) and number + * (from 0 to 2) of input arguments + * - second opcode is a "group" opcode which specifies + * the actual operation (add, increment, call, etc.) + * - third opcode is a "put result" opcode which specifies + * the destination where the result is stored (register, + * stack, etc.) + */ + +/** + * Position of "get arguments" opcode. + */ +#define VM_OC_GET_ARGS_SHIFT 7 + +/** + * Mask of "get arguments" opcode. + */ +#define VM_OC_GET_ARGS_MASK 0x1f + +/** + * Generate the binary representation of a "get arguments" opcode. + */ +#define VM_OC_GET_ARGS_CREATE_INDEX(V) (((V) & VM_OC_GET_ARGS_MASK) << VM_OC_GET_ARGS_SHIFT) + +/** + * Extract the "get arguments" opcode. + */ +#define VM_OC_GET_ARGS_GET_INDEX(O) (((O) >> VM_OC_GET_ARGS_SHIFT) & VM_OC_GET_ARGS_MASK) + +/** + * Checks whether the result is stored somewhere. + */ +#define VM_OC_HAS_GET_ARGS(V) ((V) & (VM_OC_GET_ARGS_MASK << VM_OC_GET_ARGS_SHIFT)) /** * Argument getters that are part of the opcodes. */ typedef enum { - VM_OC_GET_NONE = VM_OC_GET_DATA_CREATE_ID (0), /**< do nothing */ - VM_OC_GET_STACK = VM_OC_GET_DATA_CREATE_ID (1), /**< pop one elemnet from the stack */ - VM_OC_GET_STACK_STACK = VM_OC_GET_DATA_CREATE_ID (2), /**< pop two elemnets from the stack */ - VM_OC_GET_BYTE = VM_OC_GET_DATA_CREATE_ID (3), /**< read a byte */ + 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_STACK = VM_OC_GET_ARGS_CREATE_INDEX (2), /**< pop two elemnets from the stack */ + VM_OC_GET_BYTE = VM_OC_GET_ARGS_CREATE_INDEX (3), /**< read a byte */ - VM_OC_GET_LITERAL = VM_OC_GET_DATA_CREATE_ID (4), /**< resolve literal */ - VM_OC_GET_STACK_LITERAL = VM_OC_GET_DATA_CREATE_ID (5), /**< pop one elemnet from the stack and resolve a literal*/ - VM_OC_GET_LITERAL_BYTE = VM_OC_GET_DATA_CREATE_ID (6), /**< pop one elemnet from stack and read a byte */ - VM_OC_GET_LITERAL_LITERAL = VM_OC_GET_DATA_CREATE_ID (7), /**< resolve two literals */ - VM_OC_GET_THIS_LITERAL = VM_OC_GET_DATA_CREATE_ID (8), /**< get this and resolve a literal */ + VM_OC_GET_LITERAL = VM_OC_GET_ARGS_CREATE_INDEX (4), /**< resolve literal */ + VM_OC_GET_STACK_LITERAL = VM_OC_GET_ARGS_CREATE_INDEX (5), /**< pop one elemnet from the stack + * 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_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; -#define VM_OC_GROUP_MASK 0xff -#define VM_OC_GROUP_GET_INDEX(O) \ - ((O) & VM_OC_GROUP_MASK) +/** + * Mask of "group" opcode. + */ +#define VM_OC_GROUP_MASK 0x7f + +/** + * Extract the "group" opcode. + */ +#define VM_OC_GROUP_GET_INDEX(O) ((O) & VM_OC_GROUP_MASK) /** * Opcodes. @@ -88,12 +126,12 @@ typedef enum /* These eight opcodes must be in this order. */ VM_OC_PROP_PRE_INCR, /**< prefix increment of a property */ - VM_OC_PRE_INCR, /**< prefix increment */ VM_OC_PROP_PRE_DECR, /**< prop prefix decrement of a property */ - VM_OC_PRE_DECR, /**< prefix decrement */ VM_OC_PROP_POST_INCR, /**< prop postfix increment of a property */ - VM_OC_POST_INCR, /**< postfix increment */ VM_OC_PROP_POST_DECR, /**< prop postfix decrement of a property */ + VM_OC_PRE_INCR, /**< prefix increment */ + VM_OC_PRE_DECR, /**< prefix decrement */ + VM_OC_POST_INCR, /**< postfix increment */ VM_OC_POST_DECR, /**< postfix decrement */ VM_OC_PROP_DELETE, /**< delete property */ @@ -163,20 +201,60 @@ typedef enum VM_OC_JUMP_AND_EXIT_CONTEXT, /**< jump and exit context */ } vm_oc_types; -#define VM_OC_PUT_DATA_SHIFT 12 -#define VM_OC_PUT_DATA_MASK 0xf -#define VM_OC_PUT_DATA_CREATE_FLAG(V) \ - (((V) & VM_OC_PUT_DATA_MASK) << VM_OC_PUT_DATA_SHIFT) +/** + * Decrement operator. + */ +#define VM_OC_DECREMENT_OPERATOR_FLAG 0x1 /** - * Result writers that are part of the opcodes. + * Postfix increment/decrement operator. + */ +#define VM_OC_POST_INCR_DECR_OPERATOR_FLAG 0x2 + +/** + * An named variable is updated by the increment/decrement operator. + */ +#define VM_OC_IDENT_INCR_DECR_OPERATOR_FLAG 0x4 + +/** + * Jump to target offset if input value is logical false. + */ +#define VM_OC_BRANCH_IF_FALSE_FLAG 0x1 + +/** + * Branch optimized for logical and/or opcodes. + */ +#define VM_OC_LOGICAL_BRANCH_FLAG 0x2 + +/** + * Position of "put result" opcode. + */ +#define VM_OC_PUT_RESULT_SHIFT 12 + +/** + * Mask of "put result" opcode. + */ +#define VM_OC_PUT_RESULT_MASK 0xf + +/** + * Generate a "put result" opcode flag bit. + */ +#define VM_OC_PUT_RESULT_CREATE_FLAG(V) (((V) & VM_OC_PUT_RESULT_MASK) << VM_OC_PUT_RESULT_SHIFT) + +/** + * Checks whether the result is stored somewhere. + */ +#define VM_OC_HAS_PUT_RESULT(V) ((V) & (VM_OC_PUT_RESULT_MASK << VM_OC_PUT_RESULT_SHIFT)) + +/** + * Specify where the result is stored */ typedef enum { - VM_OC_PUT_IDENT = VM_OC_PUT_DATA_CREATE_FLAG (0x1), - VM_OC_PUT_REFERENCE = VM_OC_PUT_DATA_CREATE_FLAG (0x2), - VM_OC_PUT_STACK = VM_OC_PUT_DATA_CREATE_FLAG (0x4), - VM_OC_PUT_BLOCK = VM_OC_PUT_DATA_CREATE_FLAG (0x8), + VM_OC_PUT_IDENT = VM_OC_PUT_RESULT_CREATE_FLAG (0x1), + VM_OC_PUT_REFERENCE = VM_OC_PUT_RESULT_CREATE_FLAG (0x2), + VM_OC_PUT_STACK = VM_OC_PUT_RESULT_CREATE_FLAG (0x4), + VM_OC_PUT_BLOCK = VM_OC_PUT_RESULT_CREATE_FLAG (0x8), } vm_oc_put_types; /**