diff --git a/src/libcoreint/opcodes.c b/src/libcoreint/opcodes.c index 0847e785c..11b9ff971 100644 --- a/src/libcoreint/opcodes.c +++ b/src/libcoreint/opcodes.c @@ -1162,94 +1162,6 @@ opfunc_logical_not (opcode_t opdata, /**< operation data */ return ret_value; } /* opfunc_logical_not */ -/** - * 'Logical OR Operator' opcode handler. - * - * See also: ECMA-262 v5, 11.11 - * - * @return completion value - * Returned value must be freed with ecma_free_completion_value - */ -ecma_completion_value_t -opfunc_logical_or (opcode_t opdata, /**< operation data */ - int_data_t *int_data) /**< interpreter context */ -{ - const idx_t dst_var_idx = opdata.data.logical_or.dst; - const idx_t left_var_idx = opdata.data.logical_or.var_left; - const idx_t right_var_idx = opdata.data.logical_or.var_right; - - int_data->pos++; - - ecma_completion_value_t ret_value; - - ECMA_TRY_CATCH (left_value, get_variable_value (int_data, left_var_idx, false), ret_value); - ECMA_TRY_CATCH (right_value, get_variable_value (int_data, right_var_idx, false), ret_value); - - ecma_completion_value_t to_bool_value = ecma_op_to_boolean (left_value.u.value); - - if (ecma_is_value_true (to_bool_value.u.value)) - { - ret_value = set_variable_value (int_data, - dst_var_idx, - left_value.u.value); - } - else - { - ret_value = set_variable_value (int_data, - dst_var_idx, - right_value.u.value); - } - - ECMA_FINALIZE (right_value); - ECMA_FINALIZE (left_value); - - return ret_value; -} /* opfunc_logical_or */ - -/** - * 'Logical AND Operator' opcode handler. - * - * See also: ECMA-262 v5, 11.11 - * - * @return completion value - * Returned value must be freed with ecma_free_completion_value - */ -ecma_completion_value_t -opfunc_logical_and (opcode_t opdata, /**< operation data */ - int_data_t *int_data) /**< interpreter context */ -{ - const idx_t dst_var_idx = opdata.data.logical_and.dst; - const idx_t left_var_idx = opdata.data.logical_and.var_left; - const idx_t right_var_idx = opdata.data.logical_and.var_right; - - int_data->pos++; - - ecma_completion_value_t ret_value; - - ECMA_TRY_CATCH (left_value, get_variable_value (int_data, left_var_idx, false), ret_value); - ECMA_TRY_CATCH (right_value, get_variable_value (int_data, right_var_idx, false), ret_value); - - ecma_completion_value_t to_bool_value = ecma_op_to_boolean (left_value.u.value); - - if (ecma_is_value_true (to_bool_value.u.value) == false) - { - ret_value = set_variable_value (int_data, - dst_var_idx, - left_value.u.value); - } - else - { - ret_value = set_variable_value (int_data, - dst_var_idx, - right_value.u.value); - } - - ECMA_FINALIZE (right_value); - ECMA_FINALIZE (left_value); - - return ret_value; -} /* opfunc_logical_and */ - /** * 'This' opcode handler. * diff --git a/src/libcoreint/opcodes.h b/src/libcoreint/opcodes.h index 66d306818..f3f0e65f1 100644 --- a/src/libcoreint/opcodes.h +++ b/src/libcoreint/opcodes.h @@ -133,8 +133,6 @@ opcode_counter_t read_meta_opcode_counter (opcode_meta_type expected_type, int_d p##_2 (a, b_not, dst, var_right) #define OP_B_LOGICAL(p, a) \ - p##_3 (a, logical_and, dst, var_left, var_right) \ - p##_3 (a, logical_or, dst, var_left, var_right) \ p##_2 (a, logical_not, dst, var_right) #define OP_EQUALITY(p, a) \ diff --git a/src/libjsparser/parser.c b/src/libjsparser/parser.c index bdcabd2d3..c4fc4c4e1 100644 --- a/src/libjsparser/parser.c +++ b/src/libjsparser/parser.c @@ -319,6 +319,7 @@ static void parse_assignment_expression (void); static void parse_source_element_list (bool); static uint8_t parse_argument_list (argument_list_type, idx_t); static void skip_braces (void); +static void parse_logical_expression (bool); static uint8_t lp_string_hash (lp_string str) @@ -2157,92 +2158,96 @@ PARSE_OF (bitwise_xor_expression, bitwise_and_expression, XOR, b_xor) ; */ PARSE_OF (bitwise_or_expression, bitwise_xor_expression, OR, b_or) -/* logical_and_expression - : bitwise_or_expression (LT!* '&&' LT!* bitwise_or_expression)* - ; */ static void -parse_logical_and_expression (void) +dump_logical_check_and_op (bool logical_or) { - STACK_DECLARE_USAGE (IDX) - STACK_DECLARE_USAGE (U16) - STACK_DECLARE_USAGE (U8) + STACK_DECLARE_USAGE (IDX); - STACK_PUSH (U8, STACK_SIZE (U16)); - - parse_bitwise_or_expression (); - - skip_newlines (); - while (true) + STACK_PUSH (U16, OPCODE_COUNTER ()); + if (logical_or) { - if (token_is (TOK_DOUBLE_AND)) - { - STACK_PUSH (U16, OPCODE_COUNTER ()); - DUMP_OPCODE_3 (is_false_jmp_down, ID (1), INVALID_VALUE, INVALID_VALUE); - NEXT (bitwise_or_expression); - DUMP_OPCODE_3 (logical_and, ID (2), ID (2), ID (1)); - STACK_DROP (IDX, 1); - } - else - { - lexer_save_token (TOK ()); - break; - } + DUMP_OPCODE_3 (is_true_jmp_down, ID (1), INVALID_VALUE, INVALID_VALUE); skip_newlines (); + parse_logical_expression (false); } - - for (uint8_t i = STACK_TOP (U8); i < STACK_SIZE (U16); i++) + else { - REWRITE_COND_JMP (STACK_ELEMENT (U16, i), is_false_jmp_down, OPCODE_COUNTER () - STACK_ELEMENT (U16, i)); + DUMP_OPCODE_3 (is_false_jmp_down, ID (1), INVALID_VALUE, INVALID_VALUE); + NEXT (bitwise_or_expression); } + DUMP_OPCODE_3 (assignment, ID(2), OPCODE_ARG_TYPE_VARIABLE, ID (1)); + STACK_DROP (IDX, 1); - STACK_DROP (U16, STACK_SIZE (U16) - STACK_TOP (U8)); - STACK_DROP (U8, 1); - - STACK_CHECK_USAGE (U16); - STACK_CHECK_USAGE (U8); - STACK_CHECK_USAGE_LHS (); + STACK_CHECK_USAGE (IDX); } -/* logical_or_expression +static void +rewrite_logical_check (bool logical_or, uint8_t elem) +{ + if (logical_or) + { + REWRITE_COND_JMP (STACK_ELEMENT (U16, elem), is_true_jmp_down, + OPCODE_COUNTER () - STACK_ELEMENT (U16, elem)); + } + else + { + REWRITE_COND_JMP (STACK_ELEMENT (U16, elem), is_false_jmp_down, + OPCODE_COUNTER () - STACK_ELEMENT (U16, elem)); + } +} + +/* logical_and_expression + : bitwise_or_expression (LT!* '&&' LT!* bitwise_or_expression)* + ; + logical_or_expression : logical_and_expression (LT!* '||' LT!* logical_and_expression)* ; */ static void -parse_logical_or_expression (void) +parse_logical_expression (bool logical_or) { STACK_DECLARE_USAGE (IDX) STACK_DECLARE_USAGE (U16) STACK_DECLARE_USAGE (U8) + STACK_PUSH (U8, logical_or ? TOK_DOUBLE_OR : TOK_DOUBLE_AND); STACK_PUSH (U8, STACK_SIZE (U16)); - parse_logical_and_expression (); - - skip_newlines (); - while (true) + if (logical_or) { - if (token_is (TOK_DOUBLE_OR)) - { - STACK_PUSH (U16, OPCODE_COUNTER ()); - DUMP_OPCODE_3 (is_true_jmp_down, ID (1), INVALID_VALUE, INVALID_VALUE); - NEXT (logical_and_expression); - DUMP_OPCODE_3 (logical_or, ID (2), ID (2), ID (1)); - STACK_DROP (IDX, 1); - } - else - { - lexer_save_token (TOK ()); - break; - } - skip_newlines (); + parse_logical_expression (false); + } + else + { + parse_bitwise_or_expression (); } - for (uint8_t i = STACK_TOP (U8); i < STACK_SIZE (U16); i++) + skip_newlines (); + if (token_is (STACK_HEAD (U8, 2))) { - REWRITE_COND_JMP (STACK_ELEMENT (U16, i), is_true_jmp_down, OPCODE_COUNTER () - STACK_ELEMENT (U16, i)); + STACK_PUSH (IDX, next_temp_name ()); + DUMP_OPCODE_3 (assignment, ID(1), OPCODE_ARG_TYPE_VARIABLE, ID (2)); + dump_logical_check_and_op (logical_or); + skip_newlines (); + } + while (token_is (STACK_HEAD (U8, 2))) + { + dump_logical_check_and_op (logical_or); + skip_newlines (); + } + lexer_save_token (TOK ()); + + if (STACK_TOP (U8) != STACK_SIZE (U16)) + { + for (uint8_t i = STACK_TOP (U8); i < STACK_SIZE (U16); i++) + { + rewrite_logical_check (logical_or, i); + } + STACK_SWAP (IDX); + STACK_DROP (IDX, 1); } STACK_DROP (U16, STACK_SIZE (U16) - STACK_TOP (U8)); - STACK_DROP (U8, 1); + STACK_DROP (U8, 2); STACK_CHECK_USAGE (U16); STACK_CHECK_USAGE (U8); @@ -2260,7 +2265,7 @@ parse_conditional_expression (void) STACK_DECLARE_USAGE (U16) STACK_DECLARE_USAGE (U8) - parse_logical_or_expression (); + parse_logical_expression (true); skip_newlines (); if (token_is (TOK_QUERY)) diff --git a/src/liboptimizer/pretty-printer.c b/src/liboptimizer/pretty-printer.c index 4308ac973..278f27c7f 100644 --- a/src/liboptimizer/pretty-printer.c +++ b/src/liboptimizer/pretty-printer.c @@ -224,8 +224,6 @@ pp_opcode (opcode_counter_t oc, opcode_t opcode, bool is_rewrite) PP_OP_3 (b_or, "%s = %s | %s;", dst, var_left, var_right); PP_OP_3 (b_xor, "%s = %s ^ %s;", dst, var_left, var_right); PP_OP_2 (b_not, "%s = ~ %s;", dst, var_right); - PP_OP_3 (logical_and, "%s = %s && %s;", dst, var_left, var_right); - PP_OP_3 (logical_or, "%s = %s || %s;", dst, var_left, var_right); PP_OP_2 (logical_not, "%s = ! %s;", dst, var_right); PP_OP_3 (equal_value, "%s = %s == %s;", dst, var_left, var_right); PP_OP_3 (not_equal_value, "%s = %s != %s;", dst, var_left, var_right);