Fix 'switch' bytecode generation. Remove __strtof. Fix opcodes pretty-printing.

This commit is contained in:
Ilmir Usmanov
2014-10-16 15:33:54 +04:00
parent 8a58e0b9d5
commit 16556eb830
7 changed files with 132 additions and 115 deletions
+7 -3
View File
@@ -21,6 +21,7 @@
#include "opcodes.h"
#include "parse-error.h"
#include "parser.h"
#include "ecma-helpers.h"
static token saved_token, prev_token, sent_token;
static token empty_token =
@@ -804,16 +805,19 @@ parse_number (void)
consume_char ();
}
tok_length = (size_t) (buffer - token_start);;
if (is_fp || is_exp)
{
ecma_number_t res = __strtof (token_start, NULL);
ecma_char_t *temp = mem_heap_alloc_block ((size_t) (tok_length + 1), MEM_HEAP_ALLOC_SHORT_TERM);
__strncpy ((char *) temp, token_start, (size_t) (tok_length));
temp[tok_length] = '\0';
ecma_number_t res = ecma_zt_string_to_number (temp);
mem_heap_free_block (temp);
known_token = convert_seen_num_to_token (res);
token_start = NULL;
return known_token;
}
tok_length = (size_t) (buffer - token_start);;
if (*token_start == '0' && tok_length != 1)
{
if (parser_strict_mode ())
+105 -97
View File
@@ -2890,84 +2890,17 @@ parse_with_statement (void)
STACK_CHECK_USAGE (IDX);
}
/* case_clause
: 'case' LT!* expression LT!* ':' LT!* statement*
; */
static void
parse_case_clause (void)
skip_case_clause_body (void)
{
STACK_DECLARE_USAGE (IDX)
assert_keyword (KW_CASE);
skip_newlines ();
parse_expression ();
token_after_newlines_must_be (TOK_COLON);
STACK_PUSH (IDX, next_temp_name ());
DUMP_OPCODE_3 (equal_value_type, ID (1), ID (2), ID (3));
STACK_PUSH (U16, OPCODE_COUNTER ());
DUMP_OPCODE_3 (is_false_jmp_down, ID (1), INVALID_VALUE, INVALID_VALUE);
STACK_SWAP (IDX);
STACK_DROP (IDX, 1);
skip_newlines ();
if (is_keyword (KW_CASE) || is_keyword (KW_DEFAULT))
{
lexer_save_token (TOK ());
goto cleanup;
}
else
{
parse_statement_list ();
}
cleanup:
STACK_CHECK_USAGE_LHS ();
}
static void
skip_default_clause (void)
{
assert_keyword (KW_DEFAULT);
token_after_newlines_must_be (TOK_COLON);
do
while (!is_keyword (KW_CASE) && !is_keyword (KW_DEFAULT) && !token_is (TOK_CLOSE_BRACE))
{
skip_newlines ();
if (is_keyword (KW_DEFAULT))
{
EMIT_ERROR ("Several 'default' clauses in sigle switch");
}
if (token_is (TOK_OPEN_BRACE))
{
skip_braces ();
}
}
while (!token_is (TOK_CLOSE_BRACE) && !is_keyword (KW_CASE));
lexer_save_token (TOK ());
}
/* default_clause
: 'default' LT!* ':' LT!* statement*
; */
static void
parse_default_clause (void)
{
assert_keyword (KW_DEFAULT);
token_after_newlines_must_be (TOK_COLON);
skip_newlines ();
if (is_keyword (KW_CASE))
{
return;
}
else if (is_keyword (KW_DEFAULT))
{
EMIT_ERROR ("Several 'default' clauses in sigle switch");
}
else
{
parse_statement_list ();
}
}
/* switch_statement
@@ -2976,7 +2909,10 @@ parse_default_clause (void)
case_block
: '{' LT!* case_clause* LT!* '}'
| '{' LT!* case_clause* LT!* default_clause LT!* case_clause* LT!* '}'
;*/
;
case_clause
: 'case' LT!* expression LT!* ':' LT!* statement*
; */
static void
parse_switch_statement (void)
{
@@ -2988,56 +2924,128 @@ parse_switch_statement (void)
assert_keyword (KW_SWITCH);
STACK_PUSH (U8, 0); // was default
STACK_PUSH (U8, 0);
STACK_PUSH (U8, 0);
STACK_PUSH (U8, STACK_SIZE (IDX));
STACK_PUSH (U8, STACK_SIZE (U16));
STACK_PUSH (U8, STACK_SIZE (rewritable_break));
parse_expression_inside_parens ();
token_after_newlines_must_be (TOK_OPEN_BRACE);
push_nesting (NESTING_SWITCH);
#define SWITCH_EXPR() STACK_ELEMENT (IDX, STACK_HEAD (U8, 3))
#define CURRENT_JUMP() STACK_HEAD (U8, 4)
#define INCR_CURRENT_JUMP() STACK_INCR_HEAD (U8, 4)
#define WAS_DEFAULT() STACK_HEAD (U8, 5)
#define SET_WAS_DEFAULT(S) STACK_SET_HEAD (U8, 5, S);
STACK_PUSH (locs, TOK ().loc);
// Fisrt, generate table of jumps
skip_newlines ();
while (is_keyword (KW_CASE) || is_keyword (KW_DEFAULT))
{
if (is_keyword (KW_CASE))
{
parse_case_clause ();
REWRITE_COND_JMP (STACK_TOP (U16), is_false_jmp_down, OPCODE_COUNTER () - STACK_TOP (U16));
NEXT (expression);
next_token_must_be (TOK_COLON);
STACK_PUSH (IDX, next_temp_name ());
DUMP_OPCODE_3 (equal_value_type, ID (1), ID (2), SWITCH_EXPR ());
STACK_SWAP (IDX);
STACK_DROP (IDX, 1);
STACK_DROP (U16, 1);
STACK_PUSH (U16, OPCODE_COUNTER ());
DUMP_OPCODE_3 (is_true_jmp_down, STACK_TOP (IDX), INVALID_VALUE, INVALID_VALUE);
skip_newlines ();
skip_case_clause_body ();
}
else if (is_keyword (KW_DEFAULT))
{
STACK_SET_HEAD (U8, 2, 1);
STACK_PUSH (locs, TOK ().loc);
skip_default_clause ();
SET_WAS_DEFAULT (1);
token_after_newlines_must_be (TOK_COLON);
skip_newlines ();
skip_case_clause_body ();
}
else
{
JERRY_UNREACHABLE ();
}
}
current_token_must_be (TOK_CLOSE_BRACE);
if (WAS_DEFAULT ())
{
STACK_PUSH (U16, OPCODE_COUNTER ());
DUMP_OPCODE_2 (jmp_down, INVALID_VALUE, INVALID_VALUE);
}
lexer_seek (STACK_TOP (locs));
next_token_must_be (TOK_OPEN_BRACE);
push_nesting (NESTING_SWITCH);
// Second, parse case clauses' bodies and rewrite jumps
skip_newlines ();
while (is_keyword (KW_CASE) || is_keyword (KW_DEFAULT))
{
if (is_keyword (KW_CASE))
{
while (!token_is (TOK_COLON))
{
skip_newlines ();
}
REWRITE_OPCODE_3 (STACK_ELEMENT (U16, STACK_HEAD (U8, 2) + CURRENT_JUMP ()),
is_true_jmp_down,
STACK_ELEMENT (IDX, STACK_HEAD (U8, 3) + CURRENT_JUMP () + 1),
(idx_t) ((OPCODE_COUNTER () - STACK_ELEMENT (
U16, STACK_HEAD (U8, 2) + CURRENT_JUMP ())) >> JERRY_BITSINBYTE),
(idx_t) ((OPCODE_COUNTER () - STACK_ELEMENT (
U16, STACK_HEAD (U8, 2) + CURRENT_JUMP ())) & ((1 << JERRY_BITSINBYTE) - 1)));
skip_newlines ();
if (is_keyword (KW_CASE) || is_keyword (KW_DEFAULT))
{
goto next;
}
parse_statement_list ();
}
else if (is_keyword (KW_DEFAULT))
{
token_after_newlines_must_be (TOK_COLON);
skip_newlines ();
if (is_keyword (KW_CASE) || is_keyword (KW_DEFAULT))
{
continue;
}
parse_statement_list ();
continue;
}
else
{
JERRY_UNREACHABLE ();
}
skip_newlines ();
}
// if was default
if (STACK_HEAD (U8, 2) == 1)
{
STACK_PUSH (locs, TOK ().loc);
lexer_seek (STACK_HEAD (locs, 2));
skip_token ();
parse_default_clause ();
lexer_seek (STACK_TOP (locs));
STACK_DROP (locs, 2);
skip_token ();
}
if (!token_is (TOK_CLOSE_BRACE))
{
EMIT_ERROR ("Expected '}' token");
next:
INCR_CURRENT_JUMP ();
}
current_token_must_be (TOK_CLOSE_BRACE);
skip_token ();
pop_nesting (NESTING_SWITCH);
rewrite_rewritable_opcodes (REWRITABLE_BREAK, STACK_TOP (U8), OPCODE_COUNTER ());
STACK_DROP (IDX, 1);
STACK_DROP (U8, 2);
// Finally, dump 'finally' jump
if (WAS_DEFAULT ())
{
REWRITE_JMP (STACK_TOP (U16), jmp_down, OPCODE_COUNTER () - STACK_TOP (U16));
}
rewrite_rewritable_opcodes (REWRITABLE_BREAK, STACK_TOP (U8), OPCODE_COUNTER ());
STACK_DROP (U16, STACK_SIZE (U16) - STACK_HEAD (U8, 2));
STACK_DROP (IDX, STACK_SIZE (IDX) - STACK_HEAD (U8, 3));
STACK_DROP (U8, 5);
STACK_DROP (locs, 1);
#undef WAS_DEFAULT
#undef SET_WAS_DEFAULT
#undef CURRENT_JUMP
#undef INCR_CURRENT_JUMP
#undef SWITCH_EXPR
STACK_CHECK_USAGE (locs);
STACK_CHECK_USAGE (IDX);
+3 -3
View File
@@ -59,14 +59,14 @@ serializer_dump_opcode (opcode_t opcode)
{
JERRY_ASSERT (scopes_tree_opcodes_num (current_scope) < MAX_OPCODES);
scopes_tree_add_opcode (current_scope, opcode);
#ifdef JERRY_ENABLE_PP
if (print_opcodes)
{
pp_opcode (scopes_tree_opcodes_num (current_scope), opcode, false);
pp_opcode ((opcode_counter_t) (scopes_tree_opcodes_num (current_scope) - 1), opcode, false);
}
#endif
scopes_tree_add_opcode (current_scope, opcode);
}
void
-10
View File
@@ -284,16 +284,6 @@ __strncpy (char *dest, const char *src, size_t n)
return dest;
}
/** Convert the initial portion of the string pointed to by nptr to float representation. */
float
__strtof (const char *nptr, char **endptr)
{
(void) nptr;
(void) endptr;
JERRY_UNIMPLEMENTED ();
} /* __strtof */
/** Calculate the length of a string. */
size_t
__strlen (const char *s)
+1 -1
View File
@@ -26,7 +26,7 @@ c = a * b;
assert(c == 210);
c = a / b;
assert(c == 2.1);
assert(c >= 2.1 - 0.000001 && c <= 2.1 + 0.000001);
c = a % b;
assert(c == 1);
+1 -1
View File
@@ -27,7 +27,7 @@ assert( very_close_to_1_but_greater > 1.0 );
assert( Math.log (very_close_to_1_but_greater) >= 0.0 );
assert( Math.log (very_close_to_1_but_greater) <= 0.000001 );
var very_close_to_1_but_less = 0.9999999;
var very_close_to_1_but_less = 0.999999;
assert( very_close_to_1_but_less < 1.0 );
assert( Math.log (very_close_to_1_but_less) <= 0.0 );
+15
View File
@@ -47,3 +47,18 @@ switch (a) {
case 3:
assert (0);
}
var counter = 0;
switch ("var") {
case "var":
counter++;
case "var1":
counter++;
case "var2":
counter++;
default:
counter++;
}
assert (counter === 4);