From 4e563932f198bfcb4e308c9283fff774f60c6ca4 Mon Sep 17 00:00:00 2001 From: Ruben Ayrapetyan Date: Fri, 19 Jun 2015 00:11:19 +0300 Subject: [PATCH] Remove parser_init / parser_free interfaces (corresponding actions are now performed in parser_parse_program); introduce boolean return value in parser invocation interfaces that would indicate whether SyntaxError was raised during parse. JerryScript-DCO-1.0-Signed-off-by: Ruben Ayrapetyan r.ayrapetyan@samsung.com --- .../builtin-objects/ecma-builtin-function.cpp | 82 +++++++------ jerry-core/ecma/operations/ecma-eval.cpp | 31 ++--- jerry-core/jerry.cpp | 20 +++- jerry-core/parser/js/parser.cpp | 113 +++++++++--------- jerry-core/parser/js/parser.h | 10 +- jerry-core/parser/js/serializer.cpp | 43 +++---- jerry-core/parser/js/serializer.h | 5 +- tests/unit/test-parser.cpp | 11 +- 8 files changed, 160 insertions(+), 155 deletions(-) diff --git a/jerry-core/ecma/builtin-objects/ecma-builtin-function.cpp b/jerry-core/ecma/builtin-objects/ecma-builtin-function.cpp index 04fddbe5e..57eb643e3 100644 --- a/jerry-core/ecma/builtin-objects/ecma-builtin-function.cpp +++ b/jerry-core/ecma/builtin-objects/ecma-builtin-function.cpp @@ -15,6 +15,7 @@ #include "ecma-alloc.h" #include "ecma-conversion.h" +#include "ecma-exceptions.h" #include "ecma-gc.h" #include "ecma-function-object.h" #include "ecma-lex-env.h" @@ -130,52 +131,55 @@ ecma_builtin_function_dispatch_construct (const ecma_value_t *arguments_list_p, zt_string_buffer_pos += sz; } - parser_init (); + const opcode_t* opcodes_p; + bool is_syntax_correct; - /* - * FIXME: - * Handle syntax errors - */ - parser_parse_new_function ((const char **) zt_string_params_p, params_count); - const opcode_t* opcodes_p = (const opcode_t*) serializer_get_bytecode (); - serializer_print_opcodes (); - parser_free (); + is_syntax_correct = parser_parse_new_function ((const char **) zt_string_params_p, + params_count, + &opcodes_p); - bool is_strict = false; - bool do_instantiate_arguments_object = true; - - opcode_scope_code_flags_t scope_flags = vm_get_scope_flags (opcodes_p, - 0); - - if (scope_flags & OPCODE_SCOPE_CODE_FLAGS_STRICT) + if (!is_syntax_correct) { - is_strict = true; + ret_value = ecma_make_throw_obj_completion_value (ecma_new_standard_error (ECMA_ERROR_SYNTAX)); } - - if ((scope_flags & OPCODE_SCOPE_CODE_FLAGS_NOT_REF_ARGUMENTS_IDENTIFIER) - && (scope_flags & OPCODE_SCOPE_CODE_FLAGS_NOT_REF_EVAL_IDENTIFIER)) + else { - /* the code doesn't use 'arguments' identifier - * and doesn't perform direct call to eval, - * so Arguments object can't be referenced */ - do_instantiate_arguments_object = false; + bool is_strict = false; + bool do_instantiate_arguments_object = true; + + opcode_scope_code_flags_t scope_flags = vm_get_scope_flags (opcodes_p, + 0); + + if (scope_flags & OPCODE_SCOPE_CODE_FLAGS_STRICT) + { + is_strict = true; + } + + if ((scope_flags & OPCODE_SCOPE_CODE_FLAGS_NOT_REF_ARGUMENTS_IDENTIFIER) + && (scope_flags & OPCODE_SCOPE_CODE_FLAGS_NOT_REF_EVAL_IDENTIFIER)) + { + /* the code doesn't use 'arguments' identifier + * and doesn't perform direct call to eval, + * so Arguments object can't be referenced */ + do_instantiate_arguments_object = false; + } + + /* 11. */ + ecma_object_t *glob_lex_env_p = ecma_get_global_environment (); + + ecma_object_t *func_obj_p = ecma_op_create_function_object (params_count > 1u ? string_params_p : NULL, + (ecma_length_t) (params_count - 1u), + glob_lex_env_p, + is_strict, + do_instantiate_arguments_object, + opcodes_p, + 1); + + ecma_deref_object (glob_lex_env_p); + + ret_value = ecma_make_normal_completion_value (ecma_make_object_value (func_obj_p)); } - /* 11. */ - ecma_object_t *glob_lex_env_p = ecma_get_global_environment (); - - ecma_object_t *func_obj_p = ecma_op_create_function_object (params_count > 1u ? string_params_p : NULL, - (ecma_length_t) (params_count - 1u), - glob_lex_env_p, - is_strict, - do_instantiate_arguments_object, - opcodes_p, - 1); - - ecma_deref_object (glob_lex_env_p); - - ret_value = ecma_make_normal_completion_value (ecma_make_object_value (func_obj_p)); - MEM_FINALIZE_LOCAL_ARRAY (zt_string_buffer_p); MEM_FINALIZE_LOCAL_ARRAY (zt_string_params_p); } diff --git a/jerry-core/ecma/operations/ecma-eval.cpp b/jerry-core/ecma/operations/ecma-eval.cpp index 85c777204..eaf38d566 100644 --- a/jerry-core/ecma/operations/ecma-eval.cpp +++ b/jerry-core/ecma/operations/ecma-eval.cpp @@ -86,22 +86,12 @@ ecma_op_eval_chars_buffer (const ecma_char_t *code_p, /**< code characters buffe ecma_completion_value_t completion; - parser_init (); - bool is_syntax_correct = parser_parse_eval ((const char *) code_p, code_buffer_size); - const opcode_t* opcodes_p = (const opcode_t*) serializer_get_bytecode (); - serializer_print_opcodes (); - parser_free (); + const opcode_t *opcodes_p; + bool is_syntax_correct; - opcode_counter_t first_opcode_index = 0u; - bool is_strict_prologue = false; - opcode_scope_code_flags_t scope_flags = vm_get_scope_flags (opcodes_p, - first_opcode_index++); - if (scope_flags & OPCODE_SCOPE_CODE_FLAGS_STRICT) - { - is_strict_prologue = true; - } - - bool is_strict = (is_strict_prologue || (is_direct && is_called_from_strict_mode_code)); + is_syntax_correct = parser_parse_eval ((const char *) code_p, + code_buffer_size, + &opcodes_p); if (!is_syntax_correct) { @@ -109,6 +99,17 @@ ecma_op_eval_chars_buffer (const ecma_char_t *code_p, /**< code characters buffe } else { + opcode_counter_t first_opcode_index = 0u; + bool is_strict_prologue = false; + opcode_scope_code_flags_t scope_flags = vm_get_scope_flags (opcodes_p, + first_opcode_index++); + if (scope_flags & OPCODE_SCOPE_CODE_FLAGS_STRICT) + { + is_strict_prologue = true; + } + + bool is_strict = (is_strict_prologue || (is_direct && is_called_from_strict_mode_code)); + ecma_value_t this_binding; ecma_object_t *lex_env_p; diff --git a/jerry-core/jerry.cpp b/jerry-core/jerry.cpp index 81f6a008e..4ca954b94 100644 --- a/jerry-core/jerry.cpp +++ b/jerry-core/jerry.cpp @@ -1244,6 +1244,9 @@ jerry_reg_err_callback (jerry_error_callback_t callback) /**< pointer to callbac /** * Parse script for specified context + * + * @return true - if script was parsed successfully, + * false - otherwise (SyntaxError was raised). */ bool jerry_parse (const char* source_p, /**< script source */ @@ -1254,13 +1257,18 @@ jerry_parse (const char* source_p, /**< script source */ bool is_show_opcodes = ((jerry_flags & JERRY_FLAG_SHOW_OPCODES) != 0); parser_set_show_opcodes (is_show_opcodes); - parser_init (); - parser_parse_script (source_p, source_size); - const opcode_t* opcodes = (const opcode_t*) serializer_get_bytecode (); + const opcode_t *opcodes_p; + bool is_syntax_correct; - serializer_print_opcodes (); - parser_free (); + is_syntax_correct = parser_parse_script (source_p, + source_size, + &opcodes_p); + + if (!is_syntax_correct) + { + return false; + } #ifdef MEM_STATS if (jerry_flags & JERRY_FLAG_MEM_STATS_SEPARATE) @@ -1272,7 +1280,7 @@ jerry_parse (const char* source_p, /**< script source */ bool is_show_mem_stats_per_opcode = ((jerry_flags & JERRY_FLAG_MEM_STATS_PER_OPCODE) != 0); - vm_init (opcodes, is_show_mem_stats_per_opcode); + vm_init (opcodes_p, is_show_mem_stats_per_opcode); return true; } /* jerry_parse */ diff --git a/jerry-core/parser/js/parser.cpp b/jerry-core/parser/js/parser.cpp index 011ef6d3c..3fcb0c0a7 100644 --- a/jerry-core/parser/js/parser.cpp +++ b/jerry-core/parser/js/parser.cpp @@ -2878,25 +2878,44 @@ parse_source_element_list (bool is_global) /**< flag indicating if we are parsin * program * : LT!* source_element_list LT!* EOF! * ; + * + * @return true - if parse finished successfully (no SyntaxError was raised); + * false - otherwise. */ -static void -parser_parse_program (const char *source, /**< source code buffer */ +static bool +parser_parse_program (const char *source_p, /**< source code buffer */ size_t source_size, /**< source code size in bytes */ - bool in_new_function) /**< flag indicating if we are parsing body of a function */ + bool in_function, /**< flag indicating if we are parsing body of a function */ + bool in_eval, /**< flag indicating if we are parsing body of eval code */ + const opcode_t **out_opcodes_p) /**< out: generated byte-code array + * (in case there were no syntax errors) */ { - lexer_init_source (source, source_size); + JERRY_ASSERT (out_opcodes_p != NULL); + inside_function = in_function; + inside_eval = in_eval; + + lexer_init (parser_show_opcodes); + lexer_init_source (source_p, source_size); + + serializer_set_show_opcodes (parser_show_opcodes); + dumper_init (); + syntax_init (); + + STACK_INIT (scopes); STACK_PUSH (scopes, scopes_tree_init (NULL)); serializer_set_scope (STACK_TOP (scopes)); lexer_set_strict_mode (scopes_tree_strict_mode (STACK_TOP (scopes))); + jsp_label_init (); + skip_newlines (); parse_source_element_list (true); skip_newlines (); JERRY_ASSERT (token_is (TOK_EOF)); - if (in_new_function) + if (in_function) { dump_ret (); } @@ -2909,41 +2928,50 @@ parser_parse_program (const char *source, /**< source code buffer */ dump_exit (); } - serializer_dump_literals (); - serializer_merge_scopes_into_bytecode (); - serializer_set_scope (NULL); + jsp_label_finalize (); + syntax_free (); + lexer_free (); + *out_opcodes_p = serializer_merge_scopes_into_bytecode (); + + dumper_free (); + + serializer_set_scope (NULL); scopes_tree_free (STACK_TOP (scopes)); STACK_DROP (scopes, 1); + STACK_FREE (scopes); + + return true; } /* parser_parse_program */ /** * Parse source script + * + * @return true - if parse finished successfully (no SyntaxError were raised); + * false - otherwise. */ -void +bool parser_parse_script (const char *source, /**< source script */ - size_t source_size) /**< source script size it bytes */ + size_t source_size, /**< source script size it bytes */ + const opcode_t **opcodes_p) /**< out: generated byte-code array + * (in case there were no syntax errors) */ { - inside_eval = false; - inside_function = false; - parser_parse_program (source, source_size, false); + return parser_parse_program (source, source_size, false, false, opcodes_p); } /* parser_parse_script */ /** * Parse string passed to eval() call * - * @return true if parse succeeds - * false otherwise + * @return true - if parse finished successfully (no SyntaxError were raised); + * false - otherwise. */ -bool parser_parse_eval (const char *source, /**< string passed to eval() */ - size_t source_size) /**< string size in bytes */ +bool +parser_parse_eval (const char *source, /**< string passed to eval() */ + size_t source_size, /**< string size in bytes */ + const opcode_t **opcodes_p) /**< out: generated byte-code array + * (in case there were no syntax errors) */ { - TODO (implement syntax error processing); - - inside_eval = true; - inside_function = false; - parser_parse_program (source, source_size, false); - return true; + return parser_parse_program (source, source_size, false, true, opcodes_p); } /* parser_parse_eval */ /** @@ -2952,14 +2980,16 @@ bool parser_parse_eval (const char *source, /**< string passed to eval() */ * NOTE: Array of arguments should contain at least one element. * In case of new Function() call without parameters, empty string should be passed as argument to this * function. + * + * @return true - if parse finished successfully (no SyntaxError were raised); + * false - otherwise. */ -void +bool parser_parse_new_function (const char **params, /**< array of arguments of new Function (p1, p2, ..., pn, body) call */ - size_t params_count) /**< total number of arguments passed to new Function (...) */ + size_t params_count, /**< total number of arguments passed to new Function (...) */ + const opcode_t **out_opcodes_p) /**< out: generated byte-code array + * (in case there were no syntax errors) */ { - inside_eval = false; - inside_function = true; - // Process arguments JERRY_ASSERT (params_count > 0); for (size_t i = 0; i < params_count - 1; ++i) @@ -2967,22 +2997,9 @@ parser_parse_new_function (const char **params, /**< array of arguments of new F FIXME ("check parameter's name for syntax errors"); lit_find_or_create_literal_from_charset ((ecma_char_t *) params[i], (ecma_length_t) strlen (params[i])); } - parser_parse_program (params[params_count - 1], strlen (params[params_count - 1]), true); + return parser_parse_program (params[params_count - 1], strlen (params[params_count - 1]), true, false, out_opcodes_p); } /* parser_parse_new_function */ -void -parser_init () -{ - lexer_init (parser_show_opcodes); - serializer_set_show_opcodes (parser_show_opcodes); - dumper_init (); - syntax_init (); - - STACK_INIT (scopes); - - jsp_label_init (); -} - /** * Tell parser to dump bytecode */ @@ -2991,15 +3008,3 @@ parser_set_show_opcodes (bool show_opcodes) /**< flag indicating if to dump byte { parser_show_opcodes = show_opcodes; } /* parser_set_show_opcodes */ - -void -parser_free (void) -{ - jsp_label_finalize (); - - STACK_FREE (scopes); - - syntax_free (); - dumper_free (); - lexer_free (); -} diff --git a/jerry-core/parser/js/parser.h b/jerry-core/parser/js/parser.h index 4792d9660..6bbfe6ae8 100644 --- a/jerry-core/parser/js/parser.h +++ b/jerry-core/parser/js/parser.h @@ -18,11 +18,9 @@ #include "jrt.h" -void parser_init (); void parser_set_show_opcodes (bool); -void parser_parse_script (const char *, size_t); -bool parser_parse_eval (const char *, size_t); -void parser_parse_new_function (const char **, size_t); -void parser_free (void); +bool parser_parse_script (const char *, size_t, const opcode_t **); +bool parser_parse_eval (const char *, size_t, const opcode_t **); +bool parser_parse_new_function (const char **, size_t, const opcode_t **); -#endif +#endif /* PARSER_H */ diff --git a/jerry-core/parser/js/serializer.cpp b/jerry-core/parser/js/serializer.cpp index 21b4bda1e..e65a111f0 100644 --- a/jerry-core/parser/js/serializer.cpp +++ b/jerry-core/parser/js/serializer.cpp @@ -23,6 +23,10 @@ static scopes_tree current_scope; static array_list bytecodes_cache; /**< storage of pointers to byetecodes */ static bool print_opcodes; +static void +serializer_print_opcodes (const opcode_t *opcodes_p, + size_t opcodes_count); + op_meta serializer_get_op_meta (opcode_counter_t oc) { @@ -63,13 +67,6 @@ serializer_get_literal_cp_by_uid (uint8_t id, /**< literal idx */ return lit_id_hash_table_lookup (lit_id_hash, id, oc); } /* serializer_get_literal_cp_by_uid */ -const void * -serializer_get_bytecode (void) -{ - JERRY_ASSERT (bytecode_data.opcodes != NULL); - return bytecode_data.opcodes; -} - void serializer_set_strings_buffer (const ecma_char_t *s) { @@ -82,7 +79,7 @@ serializer_set_scope (scopes_tree new_scope) current_scope = new_scope; } -void +const opcode_t * serializer_merge_scopes_into_bytecode (void) { bytecode_data.opcodes_count = scopes_tree_count_opcodes (current_scope); @@ -90,17 +87,14 @@ serializer_merge_scopes_into_bytecode (void) (size_t) bytecode_data.opcodes_count / BLOCK_SIZE + 1); bytecode_data.opcodes = scopes_tree_raw_data (current_scope, lit_id_hash); bytecodes_cache = array_list_append (bytecodes_cache, &bytecode_data.opcodes); -} -void -serializer_dump_literals (void) -{ -#ifdef JERRY_ENABLE_PRETTY_PRINTER if (print_opcodes) { lit_dump_literals (); + serializer_print_opcodes (bytecode_data.opcodes, bytecode_data.opcodes_count); } -#endif + + return bytecode_data.opcodes; } void @@ -149,24 +143,16 @@ serializer_rewrite_op_meta (const opcode_counter_t loc, op_meta op) #endif } -void -serializer_print_opcodes (void) +static void +serializer_print_opcodes (const opcode_t *opcodes_p, + size_t opcodes_count) { #ifdef JERRY_ENABLE_PRETTY_PRINTER - opcode_counter_t loc; - - if (!print_opcodes) - { - return; - } - - printf ("AFTER OPTIMIZER:\n"); - - for (loc = 0; loc < bytecode_data.opcodes_count; loc++) + for (opcode_counter_t loc = 0; loc < opcodes_count; loc++) { op_meta opm; - opm.op = bytecode_data.opcodes[loc]; + opm.op = opcodes_p[loc]; for (int i = 0; i < 3; i++) { opm.lit_id[i] = NOT_A_LITERAL; @@ -174,6 +160,9 @@ serializer_print_opcodes (void) pp_op_meta (loc, opm, false); } +#else + (void) opcodes_p; + (void) opcodes_count; #endif } diff --git a/jerry-core/parser/js/serializer.h b/jerry-core/parser/js/serializer.h index b62766eca..87331e3db 100644 --- a/jerry-core/parser/js/serializer.h +++ b/jerry-core/parser/js/serializer.h @@ -27,17 +27,14 @@ void serializer_set_show_opcodes (bool show_opcodes); op_meta serializer_get_op_meta (opcode_counter_t); opcode_t serializer_get_opcode (opcode_counter_t); lit_cpointer_t serializer_get_literal_cp_by_uid (uint8_t, const opcode_t*, opcode_counter_t); -const void *serializer_get_bytecode (void); void serializer_set_strings_buffer (const ecma_char_t *); -void serializer_dump_literals (); void serializer_set_scope (scopes_tree); -void serializer_merge_scopes_into_bytecode (void); +const opcode_t *serializer_merge_scopes_into_bytecode (void); void serializer_dump_op_meta (op_meta); opcode_counter_t serializer_get_current_opcode_counter (void); opcode_counter_t serializer_count_opcodes_in_subscopes (void); void serializer_set_writing_position (opcode_counter_t); void serializer_rewrite_op_meta (opcode_counter_t, op_meta); -void serializer_print_opcodes (void); void serializer_free (void); #endif // SERIALIZER_H diff --git a/tests/unit/test-parser.cpp b/tests/unit/test-parser.cpp index e30867a5e..5e83bfefc 100644 --- a/tests/unit/test-parser.cpp +++ b/tests/unit/test-parser.cpp @@ -74,12 +74,15 @@ main (int __attr_unused___ argc, char program[] = "a=1;var a;"; bool is_ok; + const opcode_t *opcodes_p; + bool is_syntax_correct; + mem_init (); serializer_init (); parser_set_show_opcodes (true); - parser_init (); - parser_parse_script (program, strlen (program)); - parser_free (); + is_syntax_correct = parser_parse_script (program, strlen (program), &opcodes_p); + + JERRY_ASSERT (is_syntax_correct); opcode_t opcodes[] = { @@ -94,7 +97,7 @@ main (int __attr_unused___ argc, getop_exitval (0) // exit 0; }; - if (!opcodes_equal ((const opcode_t *) serializer_get_bytecode (), opcodes, 5)) + if (!opcodes_equal (opcodes_p, opcodes, 5)) { is_ok = false; }