From 7e3d8051eac1d7797adbb7aea4c169fa40c11bf2 Mon Sep 17 00:00:00 2001 From: Peter Gal Date: Mon, 16 Oct 2017 18:27:12 +0200 Subject: [PATCH] Move snapshot generation function to the snapshot tool Now there is a snapshot tool which can merge snapshots but was unable to generate snapshots by itself. This change moves the snapshot generation utilities to the snapshot tool. JerryScript-DCO-1.0-Signed-off-by: Peter Gal pgal.u-szeged@partner.samsung.com --- jerry-main/main-unix-snapshot.c | 298 +++++++++++++++++++++++++++++--- jerry-main/main-unix.c | 122 +------------ tools/run-tests.py | 12 +- tools/runners/run-test-suite.sh | 13 +- 4 files changed, 301 insertions(+), 144 deletions(-) diff --git a/jerry-main/main-unix-snapshot.c b/jerry-main/main-unix-snapshot.c index b4c12888db..e5faaf5b67 100644 --- a/jerry-main/main-unix-snapshot.c +++ b/jerry-main/main-unix-snapshot.c @@ -17,6 +17,7 @@ #include "jerryscript.h" #include "jerryscript-port.h" +#include "jerryscript-port-default.h" #include "cli.h" @@ -33,6 +34,52 @@ static uint8_t input_buffer[ JERRY_BUFFER_SIZE ]; static uint32_t output_buffer[ JERRY_BUFFER_SIZE / 4 ]; +static const char *output_file_name_p = "js.snapshot"; + +/** + * Check whether JerryScript has a requested feature enabled or not. If not, + * print a warning message. + * + * @return the status of the feature. + */ +static bool +check_feature (jerry_feature_t feature, /**< feature to check */ + const char *option) /**< command line option that triggered this check */ +{ + if (!jerry_is_feature_enabled (feature)) + { + jerry_port_default_set_log_level (JERRY_LOG_LEVEL_WARNING); + jerry_port_log (JERRY_LOG_LEVEL_WARNING, "Ignoring '%s' option because this feature is disabled!\n", option); + return false; + } + return true; +} /* check_feature */ + +/** + * Utility method to check and print error in the given cli state. + * + * @return true - if any error is detected + * false - if there is no error in the cli state + */ +static bool +check_cli_error (const cli_state_t *const cli_state_p) +{ + if (cli_state_p->error != NULL) + { + if (cli_state_p->arg != NULL) + { + jerry_port_log (JERRY_LOG_LEVEL_ERROR, "Error: %s %s\n", cli_state_p->error, cli_state_p->arg); + } + else + { + jerry_port_log (JERRY_LOG_LEVEL_ERROR, "Error: %s\n", cli_state_p->error); + } + + return true; + } + + return false; +} /* check_cli_error */ /** * Loading a single file into the memory. @@ -73,6 +120,227 @@ read_file (uint8_t *input_pos_p, /**< next position in the input buffer */ return bytes_read; } /* read_file */ +/** + * Generate command line option IDs + */ +typedef enum +{ + OPT_GENERATE_HELP, + OPT_GENERATE_CONTEXT, + OPT_GENERATE_SHOW_OP, + OPT_GENERATE_LITERAL_LIST, + OPT_GENERATE_LITERAL_C, + OPT_GENERATE_OUT, +} generate_opt_id_t; + +/** + * Generate command line options + */ +static const cli_opt_t generate_opts[] = +{ + CLI_OPT_DEF (.id = OPT_GENERATE_HELP, .opt = "h", .longopt = "help", + .help = "print this help and exit"), + CLI_OPT_DEF (.id = OPT_GENERATE_SHOW_OP, .longopt = "show-opcodes", + .help = "print generated opcodes"), + CLI_OPT_DEF (.id = OPT_GENERATE_CONTEXT, .opt = "c", .longopt = "context", + .meta = "MODE", + .help = "specify the execution context of the snapshot: " + "global or eval (default: global)."), + CLI_OPT_DEF (.id = OPT_GENERATE_LITERAL_LIST, .longopt = "save-literals-list-format", + .meta = "FILE", + .help = "export literals found in parsed JS input (in list format)"), + CLI_OPT_DEF (.id = OPT_GENERATE_LITERAL_C, .longopt = "save-literals-c-format", + .meta = "FILE", + .help = "export literals found in parsed JS input (in C source format)"), + CLI_OPT_DEF (.id = OPT_GENERATE_OUT, .opt = "o", .meta="FILE", + .help = "specify output file name (default: js.snapshot)"), + CLI_OPT_DEF (.id = CLI_OPT_DEFAULT, .meta = "FILE", + .help = "input snapshot file") +}; + +/** + * Process 'generate' command. + * + * @return error code (0 - no error) + */ +static int +process_generate (cli_state_t *cli_state_p, /**< cli state */ + int argc, /**< number of arguments */ + char *prog_name_p) /**< program name */ +{ + (void) argc; + + bool is_save_literals_mode_in_c_format = false; + bool is_snapshot_mode_for_global = true; + jerry_init_flag_t flags = JERRY_INIT_EMPTY; + + uint32_t number_of_files = 0; + uint8_t *source_p = input_buffer; + size_t source_length = 0; + const char *save_literals_file_name_p = NULL; + + cli_change_opts (cli_state_p, generate_opts); + + for (int id = cli_consume_option (cli_state_p); id != CLI_OPT_END; id = cli_consume_option (cli_state_p)) + { + switch (id) + { + case OPT_GENERATE_HELP: + { + cli_help (prog_name_p, "generate", generate_opts); + return JERRY_STANDALONE_EXIT_CODE_OK; + } + case OPT_GENERATE_OUT: + { + output_file_name_p = cli_consume_string (cli_state_p); + break; + } + case OPT_GENERATE_LITERAL_LIST: + case OPT_GENERATE_LITERAL_C: + { + if (save_literals_file_name_p != NULL) + { + jerry_port_log (JERRY_LOG_LEVEL_ERROR, "Error: literal file name already specified"); + return JERRY_STANDALONE_EXIT_CODE_FAIL; + } + + is_save_literals_mode_in_c_format = (id == OPT_GENERATE_LITERAL_C); + save_literals_file_name_p = cli_consume_string (cli_state_p); + break; + } + case OPT_GENERATE_SHOW_OP: + { + if (check_feature (JERRY_FEATURE_PARSER_DUMP, cli_state_p->arg)) + { + jerry_port_default_set_log_level (JERRY_LOG_LEVEL_DEBUG); + flags |= JERRY_INIT_SHOW_OPCODES; + } + break; + } + case OPT_GENERATE_CONTEXT: + { + const char *mode_str_p = cli_consume_string (cli_state_p); + + if (cli_state_p->error != NULL) + { + break; + } + + if (!strcmp ("global", mode_str_p)) + { + is_snapshot_mode_for_global = true; + } + else if (!strcmp ("eval", mode_str_p)) + { + is_snapshot_mode_for_global = false; + } + else + { + jerry_port_log (JERRY_LOG_LEVEL_ERROR, "Incorrect argument for context mode: %s\n", mode_str_p); + return JERRY_STANDALONE_EXIT_CODE_FAIL; + } + break; + } + case CLI_OPT_DEFAULT: + { + const char *file_name_p = cli_consume_string (cli_state_p); + + if (cli_state_p->error == NULL) + { + source_length = read_file (source_p, file_name_p); + + if (source_length == 0) + { + jerry_port_log (JERRY_LOG_LEVEL_ERROR, "Input file is empty\n"); + return JERRY_STANDALONE_EXIT_CODE_FAIL; + } + + number_of_files++; + } + break; + } + default: + { + cli_state_p->error = "Internal error"; + break; + } + } + } + + if (check_cli_error (cli_state_p)) + { + return JERRY_STANDALONE_EXIT_CODE_FAIL; + } + + if (number_of_files != 1) + { + jerry_port_log (JERRY_LOG_LEVEL_ERROR, "Error: No input file specified!\n"); + return JERRY_STANDALONE_EXIT_CODE_FAIL; + } + + jerry_init (flags); + + if (!jerry_is_valid_utf8_string (source_p, (jerry_size_t) source_length)) + { + jerry_port_log (JERRY_LOG_LEVEL_ERROR, "Error: Input must be a valid UTF-8 string.\n"); + return JERRY_STANDALONE_EXIT_CODE_FAIL; + } + + size_t snapshot_size = jerry_parse_and_save_snapshot ((jerry_char_t *) source_p, + source_length, + is_snapshot_mode_for_global, + false, + output_buffer, + sizeof (output_buffer) / sizeof (uint32_t)); + if (snapshot_size == 0) + { + jerry_port_log (JERRY_LOG_LEVEL_ERROR, "Error: Generating snapshot failed!\n"); + return JERRY_STANDALONE_EXIT_CODE_FAIL; + } + + FILE *snapshot_file_p = fopen (output_file_name_p, "w"); + if (snapshot_file_p == NULL) + { + jerry_port_log (JERRY_LOG_LEVEL_ERROR, "Error: Unable to write snapshot file: '%s'\n", output_file_name_p); + return JERRY_STANDALONE_EXIT_CODE_FAIL; + } + + fwrite (output_buffer, sizeof (uint8_t), snapshot_size, snapshot_file_p); + fclose (snapshot_file_p); + + printf ("Created snapshot file: '%s' (%lu bytes)\n", output_file_name_p, (unsigned long) snapshot_size); + + if (save_literals_file_name_p != NULL) + { + const size_t literal_buffer_size = jerry_parse_and_save_literals ((jerry_char_t *) source_p, + source_length, + false, + output_buffer, + sizeof (output_buffer) / sizeof (uint32_t), + is_save_literals_mode_in_c_format); + if (literal_buffer_size == 0) + { + jerry_port_log (JERRY_LOG_LEVEL_ERROR, "Error: Literal saving failed!\n"); + return JERRY_STANDALONE_EXIT_CODE_FAIL; + } + + FILE *literal_file_p = fopen (save_literals_file_name_p, "w"); + + if (literal_file_p == NULL) + { + jerry_port_log (JERRY_LOG_LEVEL_ERROR, "Error: Unable to write literal file: '%s'\n", save_literals_file_name_p); + return JERRY_STANDALONE_EXIT_CODE_FAIL; + } + + fwrite (output_buffer, sizeof (uint8_t), literal_buffer_size, literal_file_p); + fclose (literal_file_p); + + printf ("Created literal file: '%s' (%lu bytes)\n", save_literals_file_name_p, (unsigned long) literal_buffer_size); + } + + return 0; +} /* process_generate */ + /** * Merge command line option IDs */ @@ -90,7 +358,7 @@ static const cli_opt_t merge_opts[] = CLI_OPT_DEF (.id = OPT_MERGE_HELP, .opt = "h", .longopt = "help", .help = "print this help and exit"), CLI_OPT_DEF (.id = OPT_MERGE_OUT, .opt = "o", - .help = "specify output file name (default: merged.snapshot)"), + .help = "specify output file name (default: js.snapshot)"), CLI_OPT_DEF (.id = CLI_OPT_DEFAULT, .meta = "FILE", .help = "input snapshot files, minimum two") }; @@ -111,7 +379,6 @@ process_merge (cli_state_t *cli_state_p, /**< cli state */ cli_change_opts (cli_state_p, merge_opts); - const char *output_file_name_p = "merged.snapshot"; const uint32_t *merge_buffers[argc]; size_t merge_buffer_sizes[argc]; uint32_t number_of_files = 0; @@ -160,17 +427,8 @@ process_merge (cli_state_t *cli_state_p, /**< cli state */ } } - if (cli_state_p->error != NULL) + if (check_cli_error (cli_state_p)) { - if (cli_state_p->arg != NULL) - { - jerry_port_log (JERRY_LOG_LEVEL_ERROR, "Error: %s %s\n", cli_state_p->error, cli_state_p->arg); - } - else - { - jerry_port_log (JERRY_LOG_LEVEL_ERROR, "Error: %s\n", cli_state_p->error); - } - return JERRY_STANDALONE_EXIT_CODE_FAIL; } @@ -238,6 +496,7 @@ print_commands (char *prog_name_p) /**< program name */ cli_help (prog_name_p, NULL, main_opts); printf ("\nAvailable commands:\n" + " generate\n" " merge\n" "\nPassing -h or --help after a command displays its help.\n"); } /* print_commands */ @@ -275,6 +534,10 @@ main (int argc, /**< number of arguments */ { return process_merge (&cli_state, argc, argv[0]); } + else if (!strcmp ("generate", command_p)) + { + return process_generate (&cli_state, argc, argv[0]); + } jerry_port_log (JERRY_LOG_LEVEL_ERROR, "Error: unknown command: %s\n\n", command_p); print_commands (argv[0]); @@ -289,17 +552,8 @@ main (int argc, /**< number of arguments */ } } - if (cli_state.error != NULL) + if (check_cli_error (&cli_state)) { - if (cli_state.arg != NULL) - { - jerry_port_log (JERRY_LOG_LEVEL_ERROR, "Error: %s %s\n", cli_state.error, cli_state.arg); - } - else - { - jerry_port_log (JERRY_LOG_LEVEL_ERROR, "Error: %s\n", cli_state.error); - } - return JERRY_STANDALONE_EXIT_CODE_FAIL; } diff --git a/jerry-main/main-unix.c b/jerry-main/main-unix.c index e1590d007d..9a159d2816 100644 --- a/jerry-main/main-unix.c +++ b/jerry-main/main-unix.c @@ -314,10 +314,6 @@ typedef enum OPT_DEBUG_SERVER, OPT_DEBUG_PORT, OPT_DEBUGGER_WAIT_SOURCE, - OPT_SAVE_SNAP_GLOBAL, - OPT_SAVE_SNAP_EVAL, - OPT_SAVE_LIT_LIST, - OPT_SAVE_LIT_C, OPT_EXEC_SNAP, OPT_EXEC_SNAP_FUNC, OPT_LOG_LEVEL, @@ -348,14 +344,6 @@ static const cli_opt_t main_opts[] = .help = "debug server port (default: 5001)"), CLI_OPT_DEF (.id = OPT_DEBUGGER_WAIT_SOURCE, .longopt = "debugger-wait-source", .help = "wait for an executable source from the client"), - CLI_OPT_DEF (.id = OPT_SAVE_SNAP_GLOBAL, .longopt = "save-snapshot-for-global", .meta = "FILE", - .help = "save binary snapshot of parsed JS input (for execution in global context)"), - CLI_OPT_DEF (.id = OPT_SAVE_SNAP_EVAL, .longopt = "save-snapshot-for-eval", .meta = "FILE", - .help = "save binary snapshot of parsed JS input (for execution in local context by eval)"), - CLI_OPT_DEF (.id = OPT_SAVE_LIT_LIST, .longopt = "save-literals-list-format", .meta = "FILE", - .help = "export literals found in parsed JS input (in list format)"), - CLI_OPT_DEF (.id = OPT_SAVE_LIT_C, .longopt = "save-literals-c-format", .meta = "FILE", - .help = "export literals found in parsed JS input (in C source format)"), CLI_OPT_DEF (.id = OPT_EXEC_SNAP, .longopt = "exec-snapshot", .meta = "FILE", .help = "execute input snapshot file(s)"), CLI_OPT_DEF (.id = OPT_EXEC_SNAP_FUNC, .longopt = "exec-snapshot-func", .meta = "FILE NUM", @@ -434,13 +422,6 @@ main (int argc, int exec_snapshots_count = 0; bool is_parse_only = false; - bool is_save_snapshot_mode = false; - bool is_save_snapshot_mode_for_global_or_eval = false; - const char *save_snapshot_file_name_p = NULL; - - bool is_save_literals_mode = false; - bool is_save_literals_mode_in_c_format_or_list = false; - const char *save_literals_file_name_p = NULL; bool start_debug_server = false; uint16_t debug_port = 5001; @@ -520,30 +501,6 @@ main (int argc, } break; } - case OPT_SAVE_SNAP_GLOBAL: - case OPT_SAVE_SNAP_EVAL: - { - check_usage (save_snapshot_file_name_p == NULL, argv[0], "Error: snapshot file name already specified", NULL); - if (check_feature (JERRY_FEATURE_SNAPSHOT_SAVE, cli_state.arg)) - { - is_save_snapshot_mode = true; - is_save_snapshot_mode_for_global_or_eval = (id == OPT_SAVE_SNAP_GLOBAL); - } - save_snapshot_file_name_p = cli_consume_string (&cli_state); - break; - } - case OPT_SAVE_LIT_LIST: - case OPT_SAVE_LIT_C: - { - check_usage (save_literals_file_name_p == NULL, argv[0], "Error: literal file name already specified", NULL); - if (check_feature (JERRY_FEATURE_SNAPSHOT_SAVE, cli_state.arg)) - { - is_save_literals_mode = true; - is_save_literals_mode_in_c_format_or_list = (id == OPT_SAVE_LIT_C); - } - save_literals_file_name_p = cli_consume_string (&cli_state); - break; - } case OPT_EXEC_SNAP: { if (check_feature (JERRY_FEATURE_SNAPSHOT_EXEC, cli_state.arg)) @@ -616,20 +573,6 @@ main (int argc, return JERRY_STANDALONE_EXIT_CODE_FAIL; } - if (is_save_snapshot_mode) - { - check_usage (files_counter == 1, - argv[0], "Error: --save-snapshot-* options work with exactly one script", NULL); - check_usage (exec_snapshots_count == 0, - argv[0], "Error: --save-snapshot-* and --exec-snapshot options can't be passed simultaneously", NULL); - } - - if (is_save_literals_mode) - { - check_usage (files_counter == 1, - argv[0], "Error: --save-literals-* options work with exactly one script", NULL); - } - if (files_counter == 0 && exec_snapshots_count == 0) { @@ -700,64 +643,17 @@ main (int argc, break; } - if (is_save_snapshot_mode || is_save_literals_mode) - { - static uint32_t snapshot_save_buffer[ JERRY_SNAPSHOT_BUFFER_SIZE ]; - - if (is_save_snapshot_mode) - { - size_t snapshot_size = jerry_parse_and_save_snapshot ((jerry_char_t *) source_p, - source_size, - is_save_snapshot_mode_for_global_or_eval, - false, - snapshot_save_buffer, - JERRY_SNAPSHOT_BUFFER_SIZE); - if (snapshot_size == 0) - { - ret_value = jerry_create_error (JERRY_ERROR_COMMON, (jerry_char_t *) "Snapshot saving failed!"); - } - else - { - FILE *snapshot_file_p = fopen (save_snapshot_file_name_p, "w"); - fwrite (snapshot_save_buffer, sizeof (uint8_t), snapshot_size, snapshot_file_p); - fclose (snapshot_file_p); - } - } + ret_value = jerry_parse_named_resource ((jerry_char_t *) file_names[i], + strlen (file_names[i]), + source_p, + source_size, + false); - if (!jerry_value_has_error_flag (ret_value) && is_save_literals_mode) - { - const size_t literal_buffer_size = jerry_parse_and_save_literals ((jerry_char_t *) source_p, - source_size, - false, - snapshot_save_buffer, - JERRY_SNAPSHOT_BUFFER_SIZE, - is_save_literals_mode_in_c_format_or_list); - if (literal_buffer_size == 0) - { - ret_value = jerry_create_error (JERRY_ERROR_COMMON, (jerry_char_t *) "Literal saving failed!"); - } - else - { - FILE *literal_file_p = fopen (save_literals_file_name_p, "w"); - fwrite (snapshot_save_buffer, sizeof (uint8_t), literal_buffer_size, literal_file_p); - fclose (literal_file_p); - } - } - } - else + if (!jerry_value_has_error_flag (ret_value) && !is_parse_only) { - ret_value = jerry_parse_named_resource ((jerry_char_t *) file_names[i], - strlen (file_names[i]), - source_p, - source_size, - false); - - if (!jerry_value_has_error_flag (ret_value) && !is_parse_only) - { - jerry_value_t func_val = ret_value; - ret_value = jerry_run (func_val); - jerry_release_value (func_val); - } + jerry_value_t func_val = ret_value; + ret_value = jerry_run (func_val); + jerry_release_value (func_val); } if (jerry_value_has_error_flag (ret_value)) diff --git a/tools/run-tests.py b/tools/run-tests.py index 516c32bc14..780de10c26 100755 --- a/tools/run-tests.py +++ b/tools/run-tests.py @@ -59,10 +59,10 @@ def get_binary_path(bin_dir_path): Options('jerry_tests-debug-cpointer_32bit', ['--debug', '--cpointer-32bit=on', '--mem-heap=1024']), Options('jerry_tests-snapshot', - ['--snapshot-save=on', '--snapshot-exec=on'], + ['--snapshot-save=on', '--snapshot-exec=on', '--jerry-cmdline-snapshot=on'], ['--snapshot']), Options('jerry_tests-debug-snapshot', - ['--debug', '--snapshot-save=on', '--snapshot-exec=on'], + ['--debug', '--snapshot-save=on', '--snapshot-exec=on', '--jerry-cmdline-snapshot=on'], ['--snapshot']), Options('jerry_tests-es2015-subset-debug', ['--debug', '--profile=es2015-subset']), @@ -76,20 +76,20 @@ def get_binary_path(bin_dir_path): Options('jerry_test_suite-minimal', ['--profile=minimal']), Options('jerry_test_suite-minimal-snapshot', - ['--profile=minimal', '--snapshot-save=on', '--snapshot-exec=on'], + ['--profile=minimal', '--snapshot-save=on', '--snapshot-exec=on', '--jerry-cmdline-snapshot=on'], ['--snapshot']), Options('jerry_test_suite-minimal-debug', ['--debug', '--profile=minimal']), Options('jerry_test_suite-minimal-debug-snapshot', - ['--debug', '--profile=minimal', '--snapshot-save=on', '--snapshot-exec=on'], + ['--debug', '--profile=minimal', '--snapshot-save=on', '--snapshot-exec=on', '--jerry-cmdline-snapshot=on'], ['--snapshot']), Options('jerry_test_suite-es2015-subset', ['--profile=es2015-subset']), Options('jerry_test_suite-es2015-subset-snapshot', - ['--profile=es2015-subset', '--snapshot-save=on', '--snapshot-exec=on'], + ['--profile=es2015-subset', '--snapshot-save=on', '--snapshot-exec=on', '--jerry-cmdline-snapshot=on'], ['--snapshot']), Options('jerry_test_suite-es2015-subset-debug-snapshot', - ['--debug', '--profile=es2015-subset', '--snapshot-save=on', '--snapshot-exec=on'], + ['--debug', '--profile=es2015-subset', '--snapshot-save=on', '--snapshot-exec=on', '--jerry-cmdline-snapshot=on'], ['--snapshot']) ]) diff --git a/tools/runners/run-test-suite.sh b/tools/runners/run-test-suite.sh index 0875141642..be71f7cbcf 100755 --- a/tools/runners/run-test-suite.sh +++ b/tools/runners/run-test-suite.sh @@ -49,7 +49,14 @@ then TEST_FILES="$TEST_FILES.snapshot" TEST_FAILED="$TEST_FAILED.snapshot" TEST_PASSED="$TEST_PASSED.snapshot" - IS_SNAPSHOT=true; + IS_SNAPSHOT=true + + SNAPSHOT_TOOL=${ENGINE}-snapshot + if [ ! -x $SNAPSHOT_TOOL ] + then + echo "$0: $SNAPSHOT_TOOL: not an executable" + exit 1 + fi shift fi @@ -134,8 +141,8 @@ do # Testing snapshot SNAPSHOT_TEMP=`mktemp $(basename -s .js $test).snapshot.XXXXXXXXXX` - cmd_line="${ENGINE#$ROOT_DIR} $ENGINE_ARGS --save-snapshot-for-global $SNAPSHOT_TEMP ${full_test#$ROOT_DIR}" - $TIMEOUT_CMD $TIMEOUT $ENGINE $ENGINE_ARGS --save-snapshot-for-global $SNAPSHOT_TEMP $full_test &> $ENGINE_TEMP + cmd_line="${SNAPSHOT_TOOL#$ROOT_DIR} generate --context global -o $SNAPSHOT_TEMP ${full_test#$ROOT_DIR}" + $TIMEOUT_CMD $TIMEOUT $SNAPSHOT_TOOL generate --context global -o $SNAPSHOT_TEMP $full_test &> $ENGINE_TEMP status_code=$? if [ $status_code -eq 0 ]