提交 99c9a22b 编写于 作者: L László Langó 提交者: Akos Kiss

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
上级 054717fd
......@@ -678,7 +678,7 @@ main (void)
- [jerry_init](#jerry_init)
- [jerry_cleanup](#jerry_cleanup)
- [jerry_parse_and_save_literals](#jerry_parse_and_save_literals)
- [jerry_get_literals_from_snapshot](#jerry_get_literals_from_snapshot)
## jerry_get_memory_stats
......@@ -5349,30 +5349,28 @@ main (void)
- [jerry_parse_and_save_function_snapshot](#jerry_parse_and_save_function_snapshot)
## jerry_parse_and_save_literals
## jerry_get_literals_from_snapshot
**Summary**
Collect the used literals from the given source code and save them into a specific file in a list or C format.
These literals are generated by the parser, they are valid identifiers and none of them are magic string.
Collect the used literals from the given snapshot and save them into a buffer in list or C format.
None of these literals are magic strings. In C format only valid identifiers are collected.
**Prototype**
```c
size_t
jerry_parse_and_save_literals (const jerry_char_t *source_p,
size_t source_size,
bool is_strict,
uint32_t *buffer_p,
size_t buffer_size,
bool is_c_format);
jerry_get_literals_from_snapshot (const uint32_t *snapshot_p,
size_t snapshot_size,
jerry_char_t *lit_buf_p,
size_t lit_buf_size,
bool is_c_format);
```
- `source_p` - script source, it must be a valid utf8 string.
- `source_size` - script source size, in bytes.
- `is_strict` - strict mode.
- `buffer_p` - buffer to save literals to.
- `buffer_size` - the buffer's size.
- `snapshot_p` - input snapshot buffer.
- `snapshot_size` - snapshot size, in bytes.
- `lit_buf_p` - buffer to save literals to.
- `lit_buf_size` - the buffer's size.
- `is_c_format` - the output format would be C-style (true) or a simple list (false).
- return value
- the size of the literal-list, if it was generated succesfully (i.e. the list of literals isn't empty,
......@@ -5393,20 +5391,31 @@ main (void)
{
jerry_init (JERRY_INIT_EMPTY);
static uint32_t save_literal_buffer[256];
static jerry_char_t literal_buffer[256];
static uint32_t snapshot_buffer[256];
const jerry_char_t *code_for_literal_save_p = (const jerry_char_t *) "var obj = { a:'aa', bb:'Bb' }";
size_t code_for_literal_save_size = strlen ((const char *) code_for_literal_save_p);
jerry_value_t generate_result = jerry_generate_snapshot (NULL,
0,
code_for_literal_save_p,
code_for_literal_save_size,
0,
snapshot_buffer,
256);
size_t snapshot_size = (size_t) jerry_get_number_value (generate_result);
jerry_release_value (generate_result);
size_t literal_sizes = jerry_parse_and_save_literals (code_for_literal_save_p,
strlen ((const char *) code_for_literal_save_p),
false,
save_literal_buffer,
sizeof (save_literal_buffer) / sizeof (uint32_t),
true);
const size_t literal_size = jerry_get_literals_from_snapshot (snapshot_buffer,
snapshot_size,
literal_buffer,
256,
true);
if (literal_sizes != 0)
if (literal_size != 0)
{
FILE *literal_file_p = fopen ("literals.txt", "w");
fwrite (save_literal_buffer, sizeof (uint8_t), literal_sizes, literal_file_p);
FILE *literal_file_p = fopen ("literals.h", "wb");
fwrite (literal_buffer, sizeof (uint8_t), literal_size, literal_file_p);
fclose (literal_file_p);
}
......
......@@ -1259,7 +1259,7 @@ jerry_merge_snapshots (const uint32_t **inp_buffers_p, /**< array of (pointers t
functions_size += header_p->lit_table_offset - start_offset;
scan_snapshot_functions (data_p + start_offset,
data_p + header_p->lit_table_offset,
literal_base_p,
lit_pool_p,
literal_base_p);
}
......@@ -1582,48 +1582,44 @@ ecma_string_is_valid_identifier (const ecma_string_t *string_p)
#endif /* JERRY_ENABLE_SNAPSHOT_SAVE */
/**
* Copy certain string literals into the given buffer in a specified format,
* which are valid identifiers and none of them are magic string.
* Get the literals from a snapshot. Copies certain string literals into the given
* buffer in a specified format.
*
* Note:
* Only valid identifiers are saved in C format.
*
* @return size of the literal-list in bytes, at most equal to the buffer size,
* if the source parsed successfully and the list of the literals isn't empty,
* if the list of the literals isn't empty,
* 0 - otherwise.
*/
size_t
jerry_parse_and_save_literals (const jerry_char_t *source_p, /**< script source */
size_t source_size, /**< script source size */
bool is_strict, /**< strict mode */
uint32_t *buffer_p, /**< [out] buffer to save literals to */
size_t buffer_size, /**< the buffer's size */
bool is_c_format) /**< format-flag */
jerry_get_literals_from_snapshot (const uint32_t *snapshot_p, /**< input snapshot buffer */
size_t snapshot_size, /**< size of the input snapshot buffer */
jerry_char_t *lit_buf_p, /**< [out] buffer to save literals to */
size_t lit_buf_size, /**< the buffer's size */
bool is_c_format) /**< format-flag */
{
#ifdef JERRY_ENABLE_SNAPSHOT_SAVE
ecma_value_t parse_status;
ecma_compiled_code_t *bytecode_data_p;
#ifdef JERRY_ENABLE_LINE_INFO
JERRY_CONTEXT (resource_name) = ECMA_VALUE_UNDEFINED;
#endif /* JERRY_ENABLE_LINE_INFO */
parse_status = parser_parse_script (NULL,
0,
source_p,
source_size,
is_strict,
&bytecode_data_p);
const uint8_t *snapshot_data_p = (uint8_t *) snapshot_p;
const jerry_snapshot_header_t *header_p = (const jerry_snapshot_header_t *) snapshot_data_p;
if (ECMA_IS_VALUE_ERROR (parse_status))
if (snapshot_size <= sizeof (jerry_snapshot_header_t)
|| header_p->magic != JERRY_SNAPSHOT_MAGIC
|| header_p->version != JERRY_SNAPSHOT_VERSION
|| !snapshot_check_global_flags (header_p->global_flags))
{
ecma_free_value (JERRY_CONTEXT (error_value));
/* Invalid snapshot format */
return 0;
}
ecma_free_value (parse_status);
JERRY_ASSERT ((header_p->lit_table_offset % sizeof (uint32_t)) == 0);
const uint8_t *literal_base_p = snapshot_data_p + header_p->lit_table_offset;
ecma_collection_header_t *lit_pool_p = ecma_new_values_collection ();
ecma_save_literals_add_compiled_code (bytecode_data_p, lit_pool_p);
ecma_bytecode_deref (bytecode_data_p);
scan_snapshot_functions (snapshot_data_p + header_p->func_offsets[0],
literal_base_p,
lit_pool_p,
literal_base_p);
lit_utf8_size_t literal_count = 0;
ecma_value_t *iterator_p = ecma_collection_iterator_init (lit_pool_p);
......@@ -1657,10 +1653,8 @@ jerry_parse_and_save_literals (const jerry_char_t *source_p, /**< script source
return 0;
}
uint8_t *destination_p = (uint8_t *) buffer_p;
uint8_t *const buffer_start_p = destination_p;
uint8_t *const buffer_end_p = destination_p + buffer_size;
jerry_char_t *const buffer_start_p = lit_buf_p;
jerry_char_t *const buffer_end_p = lit_buf_p + lit_buf_size;
JMEM_DEFINE_LOCAL_ARRAY (literal_array, literal_count, ecma_string_t *);
lit_utf8_size_t literal_idx = 0;
......@@ -1697,43 +1691,43 @@ jerry_parse_and_save_literals (const jerry_char_t *source_p, /**< script source
if (is_c_format)
{
/* Save literal count. */
destination_p = jerry_append_chars_to_buffer (destination_p,
buffer_end_p,
"jerry_length_t literal_count = ",
0);
lit_buf_p = jerry_append_chars_to_buffer (lit_buf_p,
buffer_end_p,
"jerry_length_t literal_count = ",
0);
destination_p = jerry_append_number_to_buffer (destination_p, buffer_end_p, literal_count);
lit_buf_p = jerry_append_number_to_buffer (lit_buf_p, buffer_end_p, literal_count);
/* Save the array of literals. */
destination_p = jerry_append_chars_to_buffer (destination_p,
buffer_end_p,
";\n\njerry_char_t *literals[",
0);
lit_buf_p = jerry_append_chars_to_buffer (lit_buf_p,
buffer_end_p,
";\n\njerry_char_t *literals[",
0);
destination_p = jerry_append_number_to_buffer (destination_p, buffer_end_p, literal_count);
destination_p = jerry_append_chars_to_buffer (destination_p, buffer_end_p, "] =\n{\n", 0);
lit_buf_p = jerry_append_number_to_buffer (lit_buf_p, buffer_end_p, literal_count);
lit_buf_p = jerry_append_chars_to_buffer (lit_buf_p, buffer_end_p, "] =\n{\n", 0);
for (lit_utf8_size_t i = 0; i < literal_count; i++)
{
destination_p = jerry_append_chars_to_buffer (destination_p, buffer_end_p, " \"", 0);
destination_p = jerry_append_ecma_string_to_buffer (destination_p, buffer_end_p, literal_array[i]);
destination_p = jerry_append_chars_to_buffer (destination_p, buffer_end_p, "\"", 0);
lit_buf_p = jerry_append_chars_to_buffer (lit_buf_p, buffer_end_p, " \"", 0);
lit_buf_p = jerry_append_ecma_string_to_buffer (lit_buf_p, buffer_end_p, literal_array[i]);
lit_buf_p = jerry_append_chars_to_buffer (lit_buf_p, buffer_end_p, "\"", 0);
if (i < literal_count - 1)
{
destination_p = jerry_append_chars_to_buffer (destination_p, buffer_end_p, ",", 0);
lit_buf_p = jerry_append_chars_to_buffer (lit_buf_p, buffer_end_p, ",", 0);
}
destination_p = jerry_append_chars_to_buffer (destination_p, buffer_end_p, "\n", 0);
lit_buf_p = jerry_append_chars_to_buffer (lit_buf_p, buffer_end_p, "\n", 0);
}
destination_p = jerry_append_chars_to_buffer (destination_p,
buffer_end_p,
"};\n\njerry_length_t literal_sizes[",
0);
lit_buf_p = jerry_append_chars_to_buffer (lit_buf_p,
buffer_end_p,
"};\n\njerry_length_t literal_sizes[",
0);
destination_p = jerry_append_number_to_buffer (destination_p, buffer_end_p, literal_count);
destination_p = jerry_append_chars_to_buffer (destination_p, buffer_end_p, "] =\n{\n", 0);
lit_buf_p = jerry_append_number_to_buffer (lit_buf_p, buffer_end_p, literal_count);
lit_buf_p = jerry_append_chars_to_buffer (lit_buf_p, buffer_end_p, "] =\n{\n", 0);
}
/* Save the literal sizes respectively. */
......@@ -1743,51 +1737,51 @@ jerry_parse_and_save_literals (const jerry_char_t *source_p, /**< script source
if (is_c_format)
{
destination_p = jerry_append_chars_to_buffer (destination_p, buffer_end_p, " ", 0);
lit_buf_p = jerry_append_chars_to_buffer (lit_buf_p, buffer_end_p, " ", 0);
}
destination_p = jerry_append_number_to_buffer (destination_p, buffer_end_p, str_size);
destination_p = jerry_append_chars_to_buffer (destination_p, buffer_end_p, " ", 0);
lit_buf_p = jerry_append_number_to_buffer (lit_buf_p, buffer_end_p, str_size);
lit_buf_p = jerry_append_chars_to_buffer (lit_buf_p, buffer_end_p, " ", 0);
if (is_c_format)
{
/* Show the given string as a comment. */
destination_p = jerry_append_chars_to_buffer (destination_p, buffer_end_p, "/* ", 0);
destination_p = jerry_append_ecma_string_to_buffer (destination_p, buffer_end_p, literal_array[i]);
destination_p = jerry_append_chars_to_buffer (destination_p, buffer_end_p, " */", 0);
lit_buf_p = jerry_append_chars_to_buffer (lit_buf_p, buffer_end_p, "/* ", 0);
lit_buf_p = jerry_append_ecma_string_to_buffer (lit_buf_p, buffer_end_p, literal_array[i]);
lit_buf_p = jerry_append_chars_to_buffer (lit_buf_p, buffer_end_p, " */", 0);
if (i < literal_count - 1)
{
destination_p = jerry_append_chars_to_buffer (destination_p, buffer_end_p, ",", 0);
lit_buf_p = jerry_append_chars_to_buffer (lit_buf_p, buffer_end_p, ",", 0);
}
}
else
{
destination_p = jerry_append_ecma_string_to_buffer (destination_p, buffer_end_p, literal_array[i]);
lit_buf_p = jerry_append_ecma_string_to_buffer (lit_buf_p, buffer_end_p, literal_array[i]);
}
destination_p = jerry_append_chars_to_buffer (destination_p, buffer_end_p, "\n", 0);
lit_buf_p = jerry_append_chars_to_buffer (lit_buf_p, buffer_end_p, "\n", 0);
}
if (is_c_format)
{
destination_p = jerry_append_chars_to_buffer (destination_p, buffer_end_p, "};\n", 0);
lit_buf_p = jerry_append_chars_to_buffer (lit_buf_p, buffer_end_p, "};\n", 0);
}
JMEM_FINALIZE_LOCAL_ARRAY (literal_array);
return destination_p <= buffer_end_p ? (size_t) (destination_p - buffer_start_p) : 0;
return lit_buf_p <= buffer_end_p ? (size_t) (lit_buf_p - buffer_start_p) : 0;
#else /* !JERRY_ENABLE_SNAPSHOT_SAVE */
JERRY_UNUSED (source_p);
JERRY_UNUSED (source_size);
JERRY_UNUSED (is_strict);
JERRY_UNUSED (buffer_p);
JERRY_UNUSED (buffer_size);
JERRY_UNUSED (snapshot_p);
JERRY_UNUSED (snapshot_size);
JERRY_UNUSED (lit_buf_p);
JERRY_UNUSED (lit_buf_size);
JERRY_UNUSED (is_c_format);
return 0;
#endif /* JERRY_ENABLE_SNAPSHOT_SAVE */
} /* jerry_parse_and_save_literals */
} /* jerry_get_literals_from_snapshot */
/**
* Generate snapshot function from specified source and arguments
......
......@@ -65,8 +65,8 @@ jerry_value_t jerry_load_function_snapshot (const uint32_t *function_snapshot_p,
size_t jerry_merge_snapshots (const uint32_t **inp_buffers_p, size_t *inp_buffer_sizes_p, size_t number_of_snapshots,
uint32_t *out_buffer_p, size_t out_buffer_size, const char **error_p);
size_t jerry_parse_and_save_literals (const jerry_char_t *source_p, size_t source_size, bool is_strict,
uint32_t *buffer_p, size_t buffer_size, bool is_c_format);
size_t jerry_get_literals_from_snapshot (const uint32_t *snapshot_p, size_t snapshot_size,
jerry_char_t *lit_buf_p, size_t lit_buf_size, bool is_c_format);
/**
* @}
*/
......
......@@ -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 (check_cli_error (cli_state_p))
{
return JERRY_STANDALONE_EXIT_CODE_FAIL;
}
if (literal_file_p == NULL)
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: Unable to write literal file: '%s'\n", literals_file_name_p);
jerry_port_log (JERRY_LOG_LEVEL_ERROR, "Error: %s\n", error_p);
jerry_cleanup ();
return JERRY_STANDALONE_EXIT_CODE_FAIL;
}
fwrite (output_buffer, sizeof (uint8_t), literal_buffer_size, literal_file_p);
fclose (literal_file_p);
printf ("Successfully merged the input snapshots (%lu bytes).\n", merged_snapshot_size);
printf ("Created literal file: '%s' (%lu bytes)\n", literals_file_name_p, (unsigned long) literal_buffer_size);
lit_buf_sz = jerry_get_literals_from_snapshot (output_buffer,
merged_snapshot_size,
literal_buffer,
JERRY_BUFFER_SIZE,
is_c_format);
}
return 0;
} /* process_generate */
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);
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 (size == 0)
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]);
......
......@@ -23,6 +23,11 @@
*/
#define SNAPSHOT_BUFFER_SIZE (256)
/**
* Maximum size of literal buffer
*/
#define LITERAL_BUFFER_SIZE (256)
/**
* Magic strings
*/
......@@ -370,16 +375,32 @@ main (void)
/* C format generation */
jerry_init (JERRY_INIT_EMPTY);
static uint32_t literal_buffer_c[SNAPSHOT_BUFFER_SIZE];
static jerry_char_t literal_buffer_c[LITERAL_BUFFER_SIZE];
static uint32_t literal_snapshot_buffer[SNAPSHOT_BUFFER_SIZE];
static const char *code_for_c_format_p = "var object = { aa:'fo o', Bb:'max', aaa:'xzy0' };";
size_t literal_sizes_c_format = jerry_parse_and_save_literals ((jerry_char_t *) code_for_c_format_p,
strlen (code_for_c_format_p),
false,
literal_buffer_c,
SNAPSHOT_BUFFER_SIZE,
true);
TEST_ASSERT (literal_sizes_c_format == 200);
jerry_value_t generate_result;
generate_result = jerry_generate_snapshot (NULL,
0,
(const jerry_char_t *) code_for_c_format_p,
strlen (code_for_c_format_p),
0,
literal_snapshot_buffer,
SNAPSHOT_BUFFER_SIZE);
TEST_ASSERT (!jerry_value_is_error (generate_result)
&& jerry_value_is_number (generate_result));
size_t snapshot_size = (size_t) jerry_get_number_value (generate_result);
jerry_release_value (generate_result);
TEST_ASSERT (snapshot_size == 120);
const size_t lit_c_buf_sz = jerry_get_literals_from_snapshot (literal_snapshot_buffer,
snapshot_size,
literal_buffer_c,
LITERAL_BUFFER_SIZE,
true);
TEST_ASSERT (lit_c_buf_sz == 200);
static const char *expected_c_format = (
"jerry_length_t literal_count = 4;\n\n"
......@@ -399,24 +420,18 @@ main (void)
"};\n"
);
TEST_ASSERT (!strncmp ((char *) literal_buffer_c, expected_c_format, literal_sizes_c_format));
jerry_cleanup ();
TEST_ASSERT (!strncmp ((char *) literal_buffer_c, expected_c_format, lit_c_buf_sz));
/* List format generation */
jerry_init (JERRY_INIT_EMPTY);
static uint32_t literal_buffer_list[SNAPSHOT_BUFFER_SIZE];
static const char *code_for_list_format_p = "var obj = { a:'aa', bb:'Bb' };";
size_t literal_sizes_list_format = jerry_parse_and_save_literals ((jerry_char_t *) code_for_list_format_p,
strlen (code_for_list_format_p),
false,
literal_buffer_list,
SNAPSHOT_BUFFER_SIZE,
false);
TEST_ASSERT (literal_sizes_list_format == 25);
TEST_ASSERT (!strncmp ((char *) literal_buffer_list, "1 a\n2 Bb\n2 aa\n2 bb\n3 obj\n", literal_sizes_list_format));
static jerry_char_t literal_buffer_list[LITERAL_BUFFER_SIZE];
const size_t lit_list_buf_sz = jerry_get_literals_from_snapshot (literal_snapshot_buffer,
snapshot_size,
literal_buffer_list,
LITERAL_BUFFER_SIZE,
false);
TEST_ASSERT (lit_list_buf_sz == 30);
TEST_ASSERT (!strncmp ((char *) literal_buffer_list, "2 Bb\n2 aa\n3 aaa\n4 fo o\n4 xzy0\n", lit_list_buf_sz));
jerry_cleanup ();
}
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册