Improve API of literal save and the snapshot (command line) tool (#2507)
Removed 'jerry_parse_and_save_literals' and introduced 'jerry_get_literals_from_snapshot' instead which works on snapshot buffers rather than source code. Added literal saving feature to snapshot merge in the snapshot command line tool. Also added missing 'jerry_cleanup()' calls to the snapshot tool. Improved the console messages of the snapshot tool. Based on previous work of Tamas Zakor <ztamas@inf.u-szeged.hu> JerryScript-DCO-1.0-Signed-off-by: László Langó llango.u-szeged@partner.samsung.com
This commit is contained in:
+220
-64
@@ -41,6 +41,7 @@
|
||||
|
||||
static uint8_t input_buffer[JERRY_BUFFER_SIZE];
|
||||
static uint32_t output_buffer[JERRY_BUFFER_SIZE / 4];
|
||||
static jerry_char_t literal_buffer[JERRY_BUFFER_SIZE];
|
||||
static const char *output_file_name_p = "js.snapshot";
|
||||
static jerry_length_t magic_string_lengths[JERRY_LITERAL_LENGTH];
|
||||
static const jerry_char_t *magic_string_items[JERRY_LITERAL_LENGTH];
|
||||
@@ -125,7 +126,7 @@ read_file (uint8_t *input_pos_p, /**< next position in the input buffer */
|
||||
return 0;
|
||||
}
|
||||
|
||||
printf ("Input file '%s' (%d bytes) loaded.\n", file_name, (int) bytes_read);
|
||||
printf ("Input file '%s' (%lu bytes) loaded.\n", file_name, bytes_read);
|
||||
return bytes_read;
|
||||
} /* read_file */
|
||||
|
||||
@@ -172,8 +173,6 @@ typedef enum
|
||||
{
|
||||
OPT_GENERATE_HELP,
|
||||
OPT_GENERATE_STATIC,
|
||||
OPT_GENERATE_LITERAL_LIST,
|
||||
OPT_GENERATE_LITERAL_C,
|
||||
OPT_GENERATE_SHOW_OP,
|
||||
OPT_GENERATE_OUT,
|
||||
OPT_IMPORT_LITERAL_LIST
|
||||
@@ -191,12 +190,6 @@ static const cli_opt_t generate_opts[] =
|
||||
CLI_OPT_DEF (.id = OPT_IMPORT_LITERAL_LIST, .longopt = "load-literals-list-format",
|
||||
.meta = "FILE",
|
||||
.help = "import literals from list format (for static snapshots)"),
|
||||
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_SHOW_OP, .longopt = "show-opcodes",
|
||||
.help = "print generated opcodes"),
|
||||
CLI_OPT_DEF (.id = OPT_GENERATE_OUT, .opt = "o", .meta="FILE",
|
||||
@@ -217,8 +210,6 @@ process_generate (cli_state_t *cli_state_p, /**< cli state */
|
||||
{
|
||||
(void) argc;
|
||||
|
||||
bool is_save_literals_mode_in_c_format = false;
|
||||
bool is_import_literals = false;
|
||||
uint32_t snapshot_flags = 0;
|
||||
jerry_init_flag_t flags = JERRY_INIT_EMPTY;
|
||||
|
||||
@@ -243,18 +234,8 @@ process_generate (cli_state_t *cli_state_p, /**< cli state */
|
||||
snapshot_flags |= JERRY_SNAPSHOT_SAVE_STATIC;
|
||||
break;
|
||||
}
|
||||
case OPT_GENERATE_LITERAL_C:
|
||||
case OPT_GENERATE_LITERAL_LIST:
|
||||
case OPT_IMPORT_LITERAL_LIST:
|
||||
{
|
||||
if (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_import_literals = (id == OPT_IMPORT_LITERAL_LIST);
|
||||
is_save_literals_mode_in_c_format = (id == OPT_GENERATE_LITERAL_C);
|
||||
literals_file_name_p = cli_consume_string (cli_state_p);
|
||||
break;
|
||||
}
|
||||
@@ -318,11 +299,13 @@ process_generate (cli_state_t *cli_state_p, /**< cli state */
|
||||
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");
|
||||
jerry_cleanup ();
|
||||
return JERRY_STANDALONE_EXIT_CODE_FAIL;
|
||||
}
|
||||
|
||||
if (is_import_literals)
|
||||
if (literals_file_name_p != NULL)
|
||||
{
|
||||
/* Import literal list */
|
||||
uint8_t *sp_buffer_start_p = source_p + source_length + 1;
|
||||
size_t sp_buffer_size = read_file (sp_buffer_start_p, literals_file_name_p);
|
||||
|
||||
@@ -371,6 +354,7 @@ process_generate (cli_state_t *cli_state_p, /**< cli state */
|
||||
print_unhandled_exception (snapshot_result);
|
||||
|
||||
jerry_release_value (snapshot_result);
|
||||
jerry_cleanup ();
|
||||
return JERRY_STANDALONE_EXIT_CODE_FAIL;
|
||||
}
|
||||
|
||||
@@ -381,6 +365,7 @@ process_generate (cli_state_t *cli_state_p, /**< cli state */
|
||||
if (snapshot_file_p == NULL)
|
||||
{
|
||||
jerry_port_log (JERRY_LOG_LEVEL_ERROR, "Error: Unable to write snapshot file: '%s'\n", output_file_name_p);
|
||||
jerry_cleanup ();
|
||||
return JERRY_STANDALONE_EXIT_CODE_FAIL;
|
||||
}
|
||||
|
||||
@@ -389,36 +374,197 @@ process_generate (cli_state_t *cli_state_p, /**< cli state */
|
||||
|
||||
printf ("Created snapshot file: '%s' (%lu bytes)\n", output_file_name_p, (unsigned long) snapshot_size);
|
||||
|
||||
if (literals_file_name_p != NULL && !is_import_literals)
|
||||
jerry_cleanup ();
|
||||
return JERRY_STANDALONE_EXIT_CODE_OK;
|
||||
} /* process_generate */
|
||||
|
||||
/**
|
||||
* Literal dump command line option IDs
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
OPT_LITERAL_DUMP_HELP,
|
||||
OPT_LITERAL_DUMP_FORMAT,
|
||||
OPT_LITERAL_DUMP_OUT,
|
||||
} literal_dump_opt_id_t;
|
||||
|
||||
/**
|
||||
* Literal dump command line options
|
||||
*/
|
||||
static const cli_opt_t literal_dump_opts[] =
|
||||
{
|
||||
CLI_OPT_DEF (.id = OPT_LITERAL_DUMP_HELP, .opt = "h", .longopt = "help",
|
||||
.help = "print this help and exit"),
|
||||
CLI_OPT_DEF (.id = OPT_LITERAL_DUMP_FORMAT, .longopt = "format",
|
||||
.meta = "[c|list]",
|
||||
.help = "specify output format (default: list)"),
|
||||
CLI_OPT_DEF (.id = OPT_LITERAL_DUMP_OUT, .opt = "o",
|
||||
.help = "specify output file name (default: literals.[h|list])"),
|
||||
CLI_OPT_DEF (.id = CLI_OPT_DEFAULT, .meta = "FILE(S)",
|
||||
.help = "input snapshot files")
|
||||
};
|
||||
|
||||
/**
|
||||
* Process 'litdump' command.
|
||||
*
|
||||
* @return error code (0 - no error)
|
||||
*/
|
||||
static int
|
||||
process_literal_dump (cli_state_t *cli_state_p, /**< cli state */
|
||||
int argc, /**< number of arguments */
|
||||
char *prog_name_p) /**< program name */
|
||||
{
|
||||
uint8_t *input_pos_p = input_buffer;
|
||||
|
||||
cli_change_opts (cli_state_p, literal_dump_opts);
|
||||
|
||||
JERRY_VLA (const uint32_t *, snapshot_buffers, argc);
|
||||
JERRY_VLA (size_t, snapshot_buffer_sizes, argc);
|
||||
uint32_t number_of_files = 0;
|
||||
const char *literals_file_name_p = NULL;
|
||||
bool is_c_format = false;
|
||||
|
||||
for (int id = cli_consume_option (cli_state_p); id != CLI_OPT_END; id = cli_consume_option (cli_state_p))
|
||||
{
|
||||
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)
|
||||
switch (id)
|
||||
{
|
||||
jerry_port_log (JERRY_LOG_LEVEL_ERROR, "Error: Literal saving failed!\n");
|
||||
return JERRY_STANDALONE_EXIT_CODE_FAIL;
|
||||
case OPT_LITERAL_DUMP_HELP:
|
||||
{
|
||||
cli_help (prog_name_p, "litdump", literal_dump_opts);
|
||||
return JERRY_STANDALONE_EXIT_CODE_OK;
|
||||
}
|
||||
case OPT_LITERAL_DUMP_FORMAT:
|
||||
{
|
||||
const char *fromat_str_p = cli_consume_string (cli_state_p);
|
||||
if (!strcmp ("c", fromat_str_p))
|
||||
{
|
||||
is_c_format = true;
|
||||
}
|
||||
else if (!strcmp ("list", fromat_str_p))
|
||||
{
|
||||
is_c_format = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
jerry_port_log (JERRY_LOG_LEVEL_ERROR, "Error: Unsupported literal dump format.");
|
||||
return JERRY_STANDALONE_EXIT_CODE_FAIL;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case OPT_LITERAL_DUMP_OUT:
|
||||
{
|
||||
literals_file_name_p = cli_consume_string (cli_state_p);
|
||||
break;
|
||||
}
|
||||
case CLI_OPT_DEFAULT:
|
||||
{
|
||||
const char *file_name_p = cli_consume_string (cli_state_p);
|
||||
|
||||
if (cli_state_p->error == NULL)
|
||||
{
|
||||
size_t size = read_file (input_pos_p, file_name_p);
|
||||
|
||||
if (size == 0)
|
||||
{
|
||||
return JERRY_STANDALONE_EXIT_CODE_FAIL;
|
||||
}
|
||||
|
||||
snapshot_buffers[number_of_files] = (const uint32_t *) input_pos_p;
|
||||
snapshot_buffer_sizes[number_of_files] = size;
|
||||
|
||||
number_of_files++;
|
||||
const uintptr_t mask = sizeof (uint32_t) - 1;
|
||||
input_pos_p = (uint8_t *) ((((uintptr_t) input_pos_p) + size + mask) & ~mask);
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
cli_state_p->error = "Internal error";
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
FILE *literal_file_p = fopen (literals_file_name_p, "wb");
|
||||
|
||||
if (literal_file_p == NULL)
|
||||
{
|
||||
jerry_port_log (JERRY_LOG_LEVEL_ERROR, "Error: Unable to write literal file: '%s'\n", 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", literals_file_name_p, (unsigned long) literal_buffer_size);
|
||||
}
|
||||
|
||||
return 0;
|
||||
} /* process_generate */
|
||||
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: at least one input file must be specified.\n");
|
||||
return JERRY_STANDALONE_EXIT_CODE_FAIL;
|
||||
}
|
||||
|
||||
jerry_init (JERRY_INIT_EMPTY);
|
||||
|
||||
size_t lit_buf_sz = 0;
|
||||
if (number_of_files == 1)
|
||||
{
|
||||
lit_buf_sz = jerry_get_literals_from_snapshot (snapshot_buffers[0],
|
||||
snapshot_buffer_sizes[0],
|
||||
literal_buffer,
|
||||
JERRY_BUFFER_SIZE,
|
||||
is_c_format);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* The input contains more than one input snapshot file, so we must merge them first. */
|
||||
const char *error_p = NULL;
|
||||
size_t merged_snapshot_size = jerry_merge_snapshots (snapshot_buffers,
|
||||
snapshot_buffer_sizes,
|
||||
number_of_files,
|
||||
output_buffer,
|
||||
JERRY_BUFFER_SIZE,
|
||||
&error_p);
|
||||
|
||||
if (merged_snapshot_size == 0)
|
||||
{
|
||||
jerry_port_log (JERRY_LOG_LEVEL_ERROR, "Error: %s\n", error_p);
|
||||
jerry_cleanup ();
|
||||
return JERRY_STANDALONE_EXIT_CODE_FAIL;
|
||||
}
|
||||
|
||||
printf ("Successfully merged the input snapshots (%lu bytes).\n", merged_snapshot_size);
|
||||
|
||||
lit_buf_sz = jerry_get_literals_from_snapshot (output_buffer,
|
||||
merged_snapshot_size,
|
||||
literal_buffer,
|
||||
JERRY_BUFFER_SIZE,
|
||||
is_c_format);
|
||||
}
|
||||
|
||||
if (lit_buf_sz == 0)
|
||||
{
|
||||
jerry_port_log (JERRY_LOG_LEVEL_ERROR,
|
||||
"Error: Literal saving failed! No literals were found in the input snapshot(s).\n");
|
||||
jerry_cleanup ();
|
||||
return JERRY_STANDALONE_EXIT_CODE_FAIL;
|
||||
}
|
||||
|
||||
if (literals_file_name_p == NULL)
|
||||
{
|
||||
literals_file_name_p = is_c_format ? "literals.h" : "literals.list";
|
||||
}
|
||||
|
||||
FILE *file_p = fopen (literals_file_name_p, "wb");
|
||||
|
||||
if (file_p == NULL)
|
||||
{
|
||||
jerry_port_log (JERRY_LOG_LEVEL_ERROR, "Error: cannot open file: '%s'\n", literals_file_name_p);
|
||||
jerry_cleanup ();
|
||||
return JERRY_STANDALONE_EXIT_CODE_FAIL;
|
||||
}
|
||||
|
||||
fwrite (literal_buffer, sizeof (uint8_t), lit_buf_sz, file_p);
|
||||
fclose (file_p);
|
||||
|
||||
printf ("Literals are saved into '%s' (%lu bytes).\n", literals_file_name_p, lit_buf_sz);
|
||||
|
||||
jerry_cleanup ();
|
||||
return JERRY_STANDALONE_EXIT_CODE_OK;
|
||||
} /* process_literal_dump */
|
||||
|
||||
/**
|
||||
* Merge command line option IDs
|
||||
@@ -452,8 +598,6 @@ process_merge (cli_state_t *cli_state_p, /**< cli state */
|
||||
int argc, /**< number of arguments */
|
||||
char *prog_name_p) /**< program name */
|
||||
{
|
||||
jerry_init (JERRY_INIT_EMPTY);
|
||||
|
||||
uint8_t *input_pos_p = input_buffer;
|
||||
|
||||
cli_change_opts (cli_state_p, merge_opts);
|
||||
@@ -514,36 +658,43 @@ process_merge (cli_state_t *cli_state_p, /**< cli state */
|
||||
if (number_of_files < 2)
|
||||
{
|
||||
jerry_port_log (JERRY_LOG_LEVEL_ERROR, "Error: at least two input files must be passed.\n");
|
||||
|
||||
return JERRY_STANDALONE_EXIT_CODE_FAIL;
|
||||
}
|
||||
|
||||
const char *error_p;
|
||||
size_t size = jerry_merge_snapshots (merge_buffers,
|
||||
merge_buffer_sizes,
|
||||
number_of_files,
|
||||
output_buffer,
|
||||
JERRY_BUFFER_SIZE,
|
||||
&error_p);
|
||||
jerry_init (JERRY_INIT_EMPTY);
|
||||
|
||||
if (size == 0)
|
||||
const char *error_p = NULL;
|
||||
size_t merged_snapshot_size = jerry_merge_snapshots (merge_buffers,
|
||||
merge_buffer_sizes,
|
||||
number_of_files,
|
||||
output_buffer,
|
||||
JERRY_BUFFER_SIZE,
|
||||
&error_p);
|
||||
|
||||
if (merged_snapshot_size == 0)
|
||||
{
|
||||
jerry_port_log (JERRY_LOG_LEVEL_ERROR, "Error: %s\n", error_p);
|
||||
jerry_cleanup ();
|
||||
return JERRY_STANDALONE_EXIT_CODE_FAIL;
|
||||
}
|
||||
|
||||
FILE *file_p = fopen (output_file_name_p, "wb");
|
||||
|
||||
if (file_p != NULL)
|
||||
{
|
||||
fwrite (output_buffer, 1u, size, file_p);
|
||||
fclose (file_p);
|
||||
}
|
||||
else
|
||||
if (file_p == NULL)
|
||||
{
|
||||
jerry_port_log (JERRY_LOG_LEVEL_ERROR, "Error: cannot open file: '%s'\n", output_file_name_p);
|
||||
jerry_cleanup ();
|
||||
return JERRY_STANDALONE_EXIT_CODE_FAIL;
|
||||
}
|
||||
|
||||
fwrite (output_buffer, 1u, merged_snapshot_size, file_p);
|
||||
fclose (file_p);
|
||||
|
||||
printf ("Merge is completed. Merged snapshot is saved into '%s' (%lu bytes).\n",
|
||||
output_file_name_p,
|
||||
merged_snapshot_size);
|
||||
|
||||
jerry_cleanup ();
|
||||
return JERRY_STANDALONE_EXIT_CODE_OK;
|
||||
} /* process_merge */
|
||||
|
||||
@@ -576,6 +727,7 @@ print_commands (char *prog_name_p) /**< program name */
|
||||
|
||||
printf ("\nAvailable commands:\n"
|
||||
" generate\n"
|
||||
" litdump\n"
|
||||
" merge\n"
|
||||
"\nPassing -h or --help after a command displays its help.\n");
|
||||
} /* print_commands */
|
||||
@@ -613,6 +765,10 @@ main (int argc, /**< number of arguments */
|
||||
{
|
||||
return process_merge (&cli_state, argc, argv[0]);
|
||||
}
|
||||
else if (!strcmp ("litdump", command_p))
|
||||
{
|
||||
return process_literal_dump (&cli_state, argc, argv[0]);
|
||||
}
|
||||
else if (!strcmp ("generate", command_p))
|
||||
{
|
||||
return process_generate (&cli_state, argc, argv[0]);
|
||||
|
||||
Reference in New Issue
Block a user