mirror of
https://github.com/jerryscript-project/jerryscript.git
synced 2025-12-15 16:29:21 +00:00
[API] Introduce jerry_parse_and_save_literals() (#1500)
This function can be used to save literals into a specific file in a list or C format. These literals are valid identifiers, and doesn't match to any magic-string. The '--save-literals-list-format FILE' and '--save-literals-c-format FILE' options are used to save into the given file, when the snapshot-save is enabled. The saved literals are sorted by size and lexicographically. The C-format is useful for jerry_register_magic_strings() to generate the array of external magic strings. JerryScript-DCO-1.0-Signed-off-by: Zsolt Borbély zsborbely.u-szeged@partner.samsung.com
This commit is contained in:
parent
7d83293762
commit
f1ed5715e3
@ -299,6 +299,7 @@ jerry_register_magic_strings (const jerry_char_ptr_t *ex_str_items_p,
|
||||
|
||||
- [jerry_init](#jerry_init)
|
||||
- [jerry_cleanup](#jerry_cleanup)
|
||||
- [jerry_parse_and_save_literals](#jerry_parse_and_save_literals)
|
||||
|
||||
|
||||
## jerry_get_memory_limits
|
||||
@ -3250,3 +3251,67 @@ jerry_exec_snapshot (const void *snapshot_p,
|
||||
- [jerry_init](#jerry_init)
|
||||
- [jerry_cleanup](#jerry_cleanup)
|
||||
- [jerry_parse_and_save_snapshot](#jerry_parse_and_save_snapshot)
|
||||
|
||||
|
||||
## jerry_parse_and_save_literals
|
||||
|
||||
**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.
|
||||
|
||||
**Prototype**
|
||||
|
||||
```c
|
||||
size_t
|
||||
jerry_parse_and_save_literals (const jerry_char_t *source_p,
|
||||
size_t source_size,
|
||||
bool is_strict,
|
||||
uint8_t *buffer_p,
|
||||
size_t buffer_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.
|
||||
- `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,
|
||||
and literal-save support is enabled in current configuration through JERRY_ENABLE_SNAPSHOT_SAVE)
|
||||
- 0 otherwise.
|
||||
|
||||
**Example**
|
||||
|
||||
```c
|
||||
{
|
||||
jerry_init (JERRY_INIT_EMPTY);
|
||||
|
||||
static uint8_t save_literal_buffer[1024];
|
||||
const jerry_char_t *code_for_literal_save_p = "var obj = { a:'aa', bb:'Bb' }";
|
||||
|
||||
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),
|
||||
true);
|
||||
|
||||
if (literal_sizes != 0)
|
||||
{
|
||||
FILE *literal_file_p = fopen ("literals.txt", "w");
|
||||
fwrite (save_literal_buffer, sizeof (uint8_t), literal_sizes, literal_file_p);
|
||||
fclose (literal_file_p);
|
||||
}
|
||||
|
||||
jerry_cleanup ();
|
||||
}
|
||||
```
|
||||
|
||||
**See also**
|
||||
|
||||
- [jerry_init](#jerry_init)
|
||||
- [jerry_cleanup](#jerry_cleanup)
|
||||
- [jerry_register_magic_strings](#jerry_register_magic_strings)
|
||||
|
||||
@ -323,6 +323,8 @@ bool jerry_foreach_object_property (const jerry_value_t obj_val, jerry_object_pr
|
||||
size_t jerry_parse_and_save_snapshot (const jerry_char_t *source_p, size_t source_size, bool is_for_global,
|
||||
bool is_strict, uint8_t *buffer_p, size_t buffer_size);
|
||||
jerry_value_t jerry_exec_snapshot (const void *snapshot_p, size_t snapshot_size, bool copy_bytecode);
|
||||
size_t jerry_parse_and_save_literals (const jerry_char_t *source_p, size_t source_size, bool is_strict,
|
||||
uint8_t *buffer_p, size_t buffer_size, bool is_c_format);
|
||||
|
||||
/**
|
||||
* @}
|
||||
|
||||
@ -17,9 +17,11 @@
|
||||
#include "ecma-function-object.h"
|
||||
#include "ecma-helpers.h"
|
||||
#include "ecma-literal-storage.h"
|
||||
#include "jcontext.h"
|
||||
#include "jerry-api.h"
|
||||
#include "jerry-snapshot.h"
|
||||
#include "js-parser.h"
|
||||
#include "lit-char-helpers.h"
|
||||
#include "re-compiler.h"
|
||||
|
||||
#ifdef JERRY_ENABLE_SNAPSHOT_SAVE
|
||||
@ -630,3 +632,426 @@ jerry_exec_snapshot (const void *snapshot_p, /**< snapshot */
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
#ifdef JERRY_ENABLE_SNAPSHOT_SAVE
|
||||
|
||||
/**
|
||||
* ====================== Functions for literal saving ==========================
|
||||
*/
|
||||
|
||||
/**
|
||||
* Compare two ecma_strings by size, then lexicographically.
|
||||
*
|
||||
* @return true - if the first string is less than the second one,
|
||||
* false - otherwise.
|
||||
*/
|
||||
static bool
|
||||
jerry_save_literals_compare (ecma_string_t *literal1, /**< first literal */
|
||||
ecma_string_t *literal2) /**< second literal */
|
||||
{
|
||||
const lit_utf8_size_t lit1_size = ecma_string_get_size (literal1);
|
||||
const lit_utf8_size_t lit2_size = ecma_string_get_size (literal2);
|
||||
|
||||
if (lit1_size == lit2_size)
|
||||
{
|
||||
return ecma_compare_ecma_strings_relational (literal1, literal2);
|
||||
}
|
||||
|
||||
return (lit1_size < lit2_size);
|
||||
} /* jerry_save_literals_compare */
|
||||
|
||||
/**
|
||||
* Helper function for the heapsort algorithm.
|
||||
*
|
||||
* @return index of the maximum value
|
||||
*/
|
||||
static lit_utf8_size_t
|
||||
jerry_save_literals_heap_max (ecma_string_t *literals[], /**< array of literals */
|
||||
lit_utf8_size_t num_of_nodes, /**< number of nodes */
|
||||
lit_utf8_size_t node_idx, /**< index of parent node */
|
||||
lit_utf8_size_t child_idx1, /**< index of the first child */
|
||||
lit_utf8_size_t child_idx2) /**< index of the second child */
|
||||
{
|
||||
lit_utf8_size_t max_idx = node_idx;
|
||||
|
||||
if (child_idx1 < num_of_nodes
|
||||
&& jerry_save_literals_compare (literals[max_idx], literals[child_idx1]))
|
||||
{
|
||||
max_idx = child_idx1;
|
||||
}
|
||||
|
||||
if (child_idx2 < num_of_nodes
|
||||
&& jerry_save_literals_compare (literals[max_idx], literals[child_idx2]))
|
||||
{
|
||||
max_idx = child_idx2;
|
||||
}
|
||||
|
||||
return max_idx;
|
||||
} /* jerry_save_literals_heap_max */
|
||||
|
||||
/**
|
||||
* Helper function for the heapsort algorithm.
|
||||
*/
|
||||
static void
|
||||
jerry_save_literals_down_heap (ecma_string_t *literals[], /**< array of literals */
|
||||
lit_utf8_size_t num_of_nodes, /**< number of nodes */
|
||||
lit_utf8_size_t node_idx) /**< index of parent node */
|
||||
{
|
||||
while (true)
|
||||
{
|
||||
lit_utf8_size_t max_idx = jerry_save_literals_heap_max (literals,
|
||||
num_of_nodes,
|
||||
node_idx,
|
||||
2 * node_idx + 1,
|
||||
2 * node_idx + 2);
|
||||
if (max_idx == node_idx)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
ecma_string_t *tmp_str_p = literals[node_idx];
|
||||
literals[node_idx] = literals[max_idx];
|
||||
literals[max_idx] = tmp_str_p;
|
||||
|
||||
node_idx = max_idx;
|
||||
}
|
||||
} /* jerry_save_literals_down_heap */
|
||||
|
||||
/**
|
||||
* Helper function for a heapsort algorithm.
|
||||
*/
|
||||
static void
|
||||
jerry_save_literals_sort (ecma_string_t *literals[], /**< array of literals */
|
||||
lit_utf8_size_t num_of_literals) /**< number of literals */
|
||||
{
|
||||
if (num_of_literals < 2)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
lit_utf8_size_t lit_idx = (num_of_literals - 2) / 2;
|
||||
|
||||
while (lit_idx <= (num_of_literals - 2) / 2)
|
||||
{
|
||||
jerry_save_literals_down_heap (literals, num_of_literals, lit_idx--);
|
||||
}
|
||||
|
||||
for (lit_idx = 0; lit_idx < num_of_literals; lit_idx++)
|
||||
{
|
||||
const lit_utf8_size_t last_idx = num_of_literals - lit_idx - 1;
|
||||
|
||||
ecma_string_t *tmp_str_p = literals[last_idx];
|
||||
literals[last_idx] = literals[0];
|
||||
literals[0] = tmp_str_p;
|
||||
|
||||
jerry_save_literals_down_heap (literals, last_idx, 0);
|
||||
}
|
||||
} /* jerry_save_literals_sort */
|
||||
|
||||
/**
|
||||
* Append characters to the specified buffer.
|
||||
*
|
||||
* @return the position of the buffer pointer after copy.
|
||||
*/
|
||||
static uint8_t *
|
||||
jerry_append_chars_to_buffer (uint8_t *buffer_p, /**< buffer */
|
||||
uint8_t *buffer_end_p, /**< the end of the buffer */
|
||||
const char *chars, /**< string */
|
||||
lit_utf8_size_t string_size) /**< string size */
|
||||
{
|
||||
if (buffer_p > buffer_end_p)
|
||||
{
|
||||
return buffer_p;
|
||||
}
|
||||
|
||||
if (string_size == 0)
|
||||
{
|
||||
string_size = (lit_utf8_size_t) strlen (chars);
|
||||
}
|
||||
|
||||
if (buffer_p + string_size <= buffer_end_p)
|
||||
{
|
||||
memcpy ((char *) buffer_p, chars, string_size);
|
||||
|
||||
return buffer_p + string_size;
|
||||
}
|
||||
|
||||
/* Move the pointer behind the buffer to prevent further writes. */
|
||||
return buffer_end_p + 1;
|
||||
} /* jerry_append_chars_to_buffer */
|
||||
|
||||
/**
|
||||
* Append an ecma-string to the specified buffer.
|
||||
*
|
||||
* @return the position of the buffer pointer after copy.
|
||||
*/
|
||||
static uint8_t *
|
||||
jerry_append_ecma_string_to_buffer (uint8_t *buffer_p, /**< buffer */
|
||||
uint8_t *buffer_end_p, /**< the end of the buffer */
|
||||
ecma_string_t *string_p) /**< ecma-string */
|
||||
{
|
||||
uint8_t *new_buffer_p = NULL;
|
||||
|
||||
ECMA_STRING_TO_UTF8_STRING (string_p, str_buffer_p, str_buffer_size);
|
||||
|
||||
/* Append the string to the buffer. */
|
||||
new_buffer_p = jerry_append_chars_to_buffer (buffer_p,
|
||||
buffer_end_p,
|
||||
(const char *) str_buffer_p,
|
||||
str_buffer_size);
|
||||
|
||||
ECMA_FINALIZE_UTF8_STRING (str_buffer_p, str_buffer_size);
|
||||
|
||||
return new_buffer_p;
|
||||
} /* jerry_append_ecma_string_to_buffer */
|
||||
|
||||
/**
|
||||
* Append an unsigned number to the specified buffer.
|
||||
*
|
||||
* @return the position of the buffer pointer after copy.
|
||||
*/
|
||||
static uint8_t *
|
||||
jerry_append_number_to_buffer (uint8_t *buffer_p, /**< buffer */
|
||||
uint8_t *buffer_end_p, /**< the end of the buffer */
|
||||
lit_utf8_size_t number) /**< number */
|
||||
{
|
||||
lit_utf8_byte_t uint32_to_str_buffer[ECMA_MAX_CHARS_IN_STRINGIFIED_UINT32];
|
||||
lit_utf8_size_t utf8_str_size = ecma_uint32_to_utf8_string (number,
|
||||
uint32_to_str_buffer,
|
||||
ECMA_MAX_CHARS_IN_STRINGIFIED_UINT32);
|
||||
|
||||
JERRY_ASSERT (utf8_str_size <= ECMA_MAX_CHARS_IN_STRINGIFIED_UINT32);
|
||||
|
||||
return jerry_append_chars_to_buffer (buffer_p,
|
||||
buffer_end_p,
|
||||
(const char *) uint32_to_str_buffer,
|
||||
utf8_str_size);
|
||||
} /* jerry_append_number_to_buffer */
|
||||
|
||||
/**
|
||||
* Check whether the passed ecma-string is a valid identifier.
|
||||
*
|
||||
* @return true, if the ecma-string is a valid identifier,
|
||||
* false - otherwise.
|
||||
*/
|
||||
static bool
|
||||
ecma_string_is_valid_identifier (const ecma_string_t *string_p)
|
||||
{
|
||||
bool result = false;
|
||||
|
||||
ECMA_STRING_TO_UTF8_STRING (string_p, str_buffer_p, str_buffer_size);
|
||||
|
||||
if (lit_char_is_identifier_start (str_buffer_p))
|
||||
{
|
||||
const uint8_t *str_start_p = str_buffer_p;
|
||||
const uint8_t *str_end_p = str_buffer_p + str_buffer_size;
|
||||
|
||||
result = true;
|
||||
|
||||
while (str_start_p < str_end_p)
|
||||
{
|
||||
if (!lit_char_is_identifier_part (str_start_p))
|
||||
{
|
||||
result = false;
|
||||
break;
|
||||
}
|
||||
lit_utf8_incr (&str_start_p);
|
||||
}
|
||||
}
|
||||
|
||||
ECMA_FINALIZE_UTF8_STRING (str_buffer_p, str_buffer_size);
|
||||
|
||||
return result;
|
||||
} /* ecma_string_is_valid_identifier */
|
||||
|
||||
#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.
|
||||
*
|
||||
* @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,
|
||||
* 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 */
|
||||
uint8_t *buffer_p, /**< [out] buffer to save literals to */
|
||||
size_t buffer_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;
|
||||
parse_status = parser_parse_script (source_p,
|
||||
source_size,
|
||||
is_strict,
|
||||
&bytecode_data_p);
|
||||
|
||||
const bool error = ECMA_IS_VALUE_ERROR (parse_status);
|
||||
ecma_free_value (parse_status);
|
||||
|
||||
if (error)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
ecma_bytecode_deref (bytecode_data_p);
|
||||
|
||||
ecma_lit_storage_item_t *string_list_p = JERRY_CONTEXT (string_list_first_p);
|
||||
lit_utf8_size_t literal_count = 0;
|
||||
|
||||
/* Count the valid and non-magic identifiers in the list. */
|
||||
while (string_list_p != NULL)
|
||||
{
|
||||
for (int i = 0; i < ECMA_LIT_STORAGE_VALUE_COUNT; i++)
|
||||
{
|
||||
if (string_list_p->values[i] != JMEM_CP_NULL)
|
||||
{
|
||||
ecma_string_t *literal_p = JMEM_CP_GET_NON_NULL_POINTER (ecma_string_t,
|
||||
string_list_p->values[i]);
|
||||
/* We don't save a literal which isn't a valid identifier
|
||||
or it's a magic string. */
|
||||
if (ecma_get_string_magic (literal_p) == LIT_MAGIC_STRING__COUNT
|
||||
&& ecma_string_is_valid_identifier (literal_p))
|
||||
{
|
||||
literal_count++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
string_list_p = JMEM_CP_GET_POINTER (ecma_lit_storage_item_t, string_list_p->next_cp);
|
||||
}
|
||||
|
||||
if (literal_count == 0)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint8_t * const buffer_start_p = buffer_p;
|
||||
uint8_t * const buffer_end_p = buffer_p + buffer_size;
|
||||
|
||||
JMEM_DEFINE_LOCAL_ARRAY (literal_array, literal_count, ecma_string_t *);
|
||||
lit_utf8_size_t literal_idx = 0;
|
||||
|
||||
string_list_p = JERRY_CONTEXT (string_list_first_p);
|
||||
|
||||
while (string_list_p != NULL)
|
||||
{
|
||||
for (int i = 0; i < ECMA_LIT_STORAGE_VALUE_COUNT; i++)
|
||||
{
|
||||
if (string_list_p->values[i] != JMEM_CP_NULL)
|
||||
{
|
||||
ecma_string_t *literal_p = JMEM_CP_GET_NON_NULL_POINTER (ecma_string_t,
|
||||
string_list_p->values[i]);
|
||||
|
||||
if (ecma_get_string_magic (literal_p) == LIT_MAGIC_STRING__COUNT
|
||||
&& ecma_string_is_valid_identifier (literal_p))
|
||||
{
|
||||
literal_array[literal_idx++] = literal_p;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
string_list_p = JMEM_CP_GET_POINTER (ecma_lit_storage_item_t, string_list_p->next_cp);
|
||||
}
|
||||
|
||||
/* Sort the strings by size at first, then lexicographically. */
|
||||
jerry_save_literals_sort (literal_array, literal_count);
|
||||
|
||||
if (is_c_format)
|
||||
{
|
||||
/* Save literal count. */
|
||||
buffer_p = jerry_append_chars_to_buffer (buffer_p,
|
||||
buffer_end_p,
|
||||
(const char *) "jerry_length_t literal_count = ",
|
||||
0);
|
||||
|
||||
buffer_p = jerry_append_number_to_buffer (buffer_p, buffer_end_p, literal_count);
|
||||
|
||||
/* Save the array of literals. */
|
||||
buffer_p = jerry_append_chars_to_buffer (buffer_p,
|
||||
buffer_end_p,
|
||||
";\n\njerry_char_ptr_t literals[",
|
||||
0);
|
||||
|
||||
buffer_p = jerry_append_number_to_buffer (buffer_p, buffer_end_p, literal_count);
|
||||
buffer_p = jerry_append_chars_to_buffer (buffer_p, buffer_end_p, "] =\n{\n", 0);
|
||||
|
||||
for (lit_utf8_size_t i = 0; i < literal_count; i++)
|
||||
{
|
||||
buffer_p = jerry_append_chars_to_buffer (buffer_p, buffer_end_p, " \"", 0);
|
||||
buffer_p = jerry_append_ecma_string_to_buffer (buffer_p, buffer_end_p, literal_array[i]);
|
||||
buffer_p = jerry_append_chars_to_buffer (buffer_p, buffer_end_p, "\"", 0);
|
||||
|
||||
if (i < literal_count - 1)
|
||||
{
|
||||
buffer_p = jerry_append_chars_to_buffer (buffer_p, buffer_end_p, ",", 0);
|
||||
}
|
||||
|
||||
buffer_p = jerry_append_chars_to_buffer (buffer_p, buffer_end_p, "\n", 0);
|
||||
}
|
||||
|
||||
buffer_p = jerry_append_chars_to_buffer (buffer_p,
|
||||
buffer_end_p,
|
||||
(const char *) "};\n\njerry_length_t literal_sizes[",
|
||||
0);
|
||||
|
||||
buffer_p = jerry_append_number_to_buffer (buffer_p, buffer_end_p, literal_count);
|
||||
buffer_p = jerry_append_chars_to_buffer (buffer_p, buffer_end_p, "] =\n{\n", 0);
|
||||
}
|
||||
|
||||
/* Save the literal sizes respectively. */
|
||||
for (lit_utf8_size_t i = 0; i < literal_count; i++)
|
||||
{
|
||||
lit_utf8_size_t str_size = ecma_string_get_size (literal_array[i]);
|
||||
|
||||
if (is_c_format)
|
||||
{
|
||||
buffer_p = jerry_append_chars_to_buffer (buffer_p, buffer_end_p, " ", 0);
|
||||
}
|
||||
|
||||
buffer_p = jerry_append_number_to_buffer (buffer_p, buffer_end_p, str_size);
|
||||
buffer_p = jerry_append_chars_to_buffer (buffer_p, buffer_end_p, " ", 0);
|
||||
|
||||
if (is_c_format)
|
||||
{
|
||||
/* Show the given string as a comment. */
|
||||
buffer_p = jerry_append_chars_to_buffer (buffer_p, buffer_end_p, "/* ", 0);
|
||||
buffer_p = jerry_append_ecma_string_to_buffer (buffer_p, buffer_end_p, literal_array[i]);
|
||||
buffer_p = jerry_append_chars_to_buffer (buffer_p, buffer_end_p, " */", 0);
|
||||
|
||||
if (i < literal_count - 1)
|
||||
{
|
||||
buffer_p = jerry_append_chars_to_buffer (buffer_p, buffer_end_p, ",", 0);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
buffer_p = jerry_append_ecma_string_to_buffer (buffer_p, buffer_end_p, literal_array[i]);
|
||||
}
|
||||
|
||||
buffer_p = jerry_append_chars_to_buffer (buffer_p, buffer_end_p, "\n", 0);
|
||||
}
|
||||
|
||||
if (is_c_format)
|
||||
{
|
||||
buffer_p = jerry_append_chars_to_buffer (buffer_p, buffer_end_p, (const char *) "};\n", 0);
|
||||
}
|
||||
|
||||
JMEM_FINALIZE_LOCAL_ARRAY (literal_array);
|
||||
|
||||
return buffer_p <= buffer_end_p ? (size_t) (buffer_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 (is_c_format);
|
||||
|
||||
return 0;
|
||||
#endif /* JERRY_ENABLE_SNAPSHOT_SAVE */
|
||||
} /* jerry_parse_and_save_literals */
|
||||
|
||||
@ -126,6 +126,8 @@ print_help (char *name)
|
||||
" --show-regexp-opcodes\n"
|
||||
" --save-snapshot-for-global FILE\n"
|
||||
" --save-snapshot-for-eval FILE\n"
|
||||
" --save-literals-list-format FILE\n"
|
||||
" --save-literals-c-format FILE\n"
|
||||
" --exec-snapshot FILE\n"
|
||||
" --log-level [0-3]\n"
|
||||
" --abort-on-fail\n"
|
||||
@ -354,6 +356,10 @@ main (int argc,
|
||||
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 is_repl_mode = false;
|
||||
bool no_prompt = false;
|
||||
|
||||
@ -485,6 +491,38 @@ main (int argc,
|
||||
"Ignoring 'exec-snapshot' option because this feature isn't enabled!\n");
|
||||
}
|
||||
}
|
||||
else if (!strcmp ("--save-literals-list-format", argv[i])
|
||||
|| !strcmp ("--save-literals-c-format", argv[i]))
|
||||
{
|
||||
if (++i >= argc)
|
||||
{
|
||||
jerry_port_log (JERRY_LOG_LEVEL_ERROR, "Error: no file specified for %s\n", argv[i - 1]);
|
||||
print_usage (argv[0]);
|
||||
return JERRY_STANDALONE_EXIT_CODE_FAIL;
|
||||
}
|
||||
|
||||
if (jerry_is_feature_enabled (JERRY_FEATURE_SNAPSHOT_SAVE))
|
||||
{
|
||||
is_save_literals_mode = true;
|
||||
is_save_literals_mode_in_c_format_or_list = !strcmp ("--save-literals-c-format", argv[i - 1]);
|
||||
|
||||
if (save_literals_file_name_p != NULL)
|
||||
{
|
||||
jerry_port_log (JERRY_LOG_LEVEL_ERROR, "Error: literal file name already specified\n");
|
||||
print_usage (argv[0]);
|
||||
return JERRY_STANDALONE_EXIT_CODE_FAIL;
|
||||
}
|
||||
|
||||
save_literals_file_name_p = argv[i];
|
||||
}
|
||||
else
|
||||
{
|
||||
jerry_port_default_set_log_level (JERRY_LOG_LEVEL_WARNING);
|
||||
|
||||
jerry_port_log (JERRY_LOG_LEVEL_WARNING,
|
||||
"Ignoring 'save-literals' option because this feature is disabled!\n");
|
||||
}
|
||||
}
|
||||
else if (!strcmp ("--log-level", argv[i]))
|
||||
{
|
||||
if (++i >= argc)
|
||||
@ -544,6 +582,16 @@ main (int argc,
|
||||
}
|
||||
}
|
||||
|
||||
if (jerry_is_feature_enabled (JERRY_FEATURE_SNAPSHOT_SAVE) && is_save_literals_mode)
|
||||
{
|
||||
if (files_counter != 1)
|
||||
{
|
||||
jerry_port_log (JERRY_LOG_LEVEL_ERROR,
|
||||
"Error: --save-literals-* options work with exactly one script\n");
|
||||
return JERRY_STANDALONE_EXIT_CODE_FAIL;
|
||||
}
|
||||
}
|
||||
|
||||
if (files_counter == 0
|
||||
&& exec_snapshots_count == 0)
|
||||
{
|
||||
@ -610,25 +658,47 @@ main (int argc,
|
||||
break;
|
||||
}
|
||||
|
||||
if (jerry_is_feature_enabled (JERRY_FEATURE_SNAPSHOT_SAVE) && is_save_snapshot_mode)
|
||||
if (jerry_is_feature_enabled (JERRY_FEATURE_SNAPSHOT_SAVE) && (is_save_snapshot_mode || is_save_literals_mode))
|
||||
{
|
||||
static uint8_t snapshot_save_buffer[ JERRY_BUFFER_SIZE ];
|
||||
|
||||
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_BUFFER_SIZE);
|
||||
if (snapshot_size == 0)
|
||||
if (is_save_snapshot_mode)
|
||||
{
|
||||
ret_value = jerry_create_error (JERRY_ERROR_COMMON, (jerry_char_t *) "");
|
||||
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_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);
|
||||
}
|
||||
}
|
||||
else
|
||||
if (!jerry_value_has_error_flag (ret_value) && is_save_literals_mode)
|
||||
{
|
||||
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);
|
||||
const size_t literal_buffer_size = jerry_parse_and_save_literals ((jerry_char_t *) source_p,
|
||||
source_size,
|
||||
false,
|
||||
snapshot_save_buffer,
|
||||
JERRY_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
|
||||
|
||||
@ -950,5 +950,61 @@ main (void)
|
||||
jerry_cleanup ();
|
||||
}
|
||||
|
||||
/* Save literals */
|
||||
if (jerry_is_feature_enabled (JERRY_FEATURE_SNAPSHOT_SAVE))
|
||||
{
|
||||
/* C format generation */
|
||||
jerry_init (JERRY_INIT_EMPTY);
|
||||
|
||||
static jerry_char_t literal_buffer_c[256];
|
||||
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,
|
||||
sizeof (literal_buffer_c),
|
||||
true);
|
||||
TEST_ASSERT (literal_sizes_c_format == 203);
|
||||
|
||||
static const char *expected_c_format = (
|
||||
"jerry_length_t literal_count = 4;\n\n"
|
||||
"jerry_char_ptr_t literals[4] =\n"
|
||||
"{\n"
|
||||
" \"Bb\",\n"
|
||||
" \"aa\",\n"
|
||||
" \"aaa\",\n"
|
||||
" \"xzy0\"\n"
|
||||
"};\n\n"
|
||||
"jerry_length_t literal_sizes[4] =\n"
|
||||
"{\n"
|
||||
" 2 /* Bb */,\n"
|
||||
" 2 /* aa */,\n"
|
||||
" 3 /* aaa */,\n"
|
||||
" 4 /* xzy0 */\n"
|
||||
"};\n"
|
||||
);
|
||||
|
||||
TEST_ASSERT (!strncmp ((char *) literal_buffer_c, expected_c_format, literal_sizes_c_format));
|
||||
jerry_cleanup ();
|
||||
|
||||
/* List format generation */
|
||||
jerry_init (JERRY_INIT_EMPTY);
|
||||
|
||||
static jerry_char_t literal_buffer_list[256];
|
||||
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,
|
||||
sizeof (literal_buffer_list),
|
||||
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));
|
||||
|
||||
jerry_cleanup ();
|
||||
}
|
||||
|
||||
return 0;
|
||||
} /* main */
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user