diff --git a/docs/02.API-REFERENCE.md b/docs/02.API-REFERENCE.md index 8ca2c6225..307ef5321 100644 --- a/docs/02.API-REFERENCE.md +++ b/docs/02.API-REFERENCE.md @@ -59,6 +59,34 @@ Possible compile time enabled feature types: - JERRY_FEATURE_DATE - Date support - JERRY_FEATURE_REGEXP - RegExp support +## jerry_generate_snapshot_opts_t + +Flags for [jerry_generate_snapshot](#jerry_generate_snapshot) and +[jerry_generate_function_snapshot](#jerry_generate_function_snapshot) functions: + + - JERRY_SNAPSHOT_SAVE_STATIC - generate static snapshot (see below) + - JERRY_SNAPSHOT_SAVE_STRICT - strict source code provided + +**Generate static snapshots** +Snapshots contain literal pools, and these literal pools contain references +to constant literals (strings, numbers, etc.). When a snapshot is executed, +these literals are converted to jerry values and the literal pool entries +are changed to their corresponding jerry value. To support this conversion, +the literals and literal pools are copied into RAM even if the `copy_bytecode` +flag passed to [jerry_exec_snapshot_at](#jerry_exec_snapshot_at) is set to +`false`. This non-negligible memory consumption can be avoided by using +static snapshots. The literals of these snapshots are limited to magic +strings, and 28 bit signed integers, so their constant pools do not need +to be loaded into the memory. Hence these snapshots can be executed from +ROM. + +***Important note:*** the magic strings set by +[jerry_register_magic_strings](#jerry_register_magic_strings) must be the +same when the snapshot is generated and executed. Furthermore the +`copy_bytecode` flag of [jerry_exec_snapshot_at](#jerry_exec_snapshot_at) +must be set to `false`. + + ## jerry_char_t **Summary** @@ -4923,7 +4951,7 @@ main (void) # Snapshot functions -## jerry_parse_and_save_snapshot +## jerry_generate_snapshot **Summary** @@ -4932,26 +4960,28 @@ Generate snapshot from the specified source code. **Prototype** ```c -size_t -jerry_parse_and_save_snapshot (const jerry_char_t *source_p, - size_t source_size, - bool is_for_global, - bool is_strict, - uint32_t *buffer_p, - size_t buffer_size); +jerry_value_t +jerry_generate_snapshot (const jerry_char_t *resource_name_p, + size_t resource_name_length, + const jerry_char_t *source_p, + size_t source_size, + uint32_t generate_snapshot_opts, + uint32_t *buffer_p, + size_t buffer_size); ``` +- `resource_name_p` - resource (file) name of the source code. Currently unused, the debugger may use it in the future. +- `resource_name_length` - length of resource name. - `source_p` - script source, it must be a valid utf8 string. - `source_size` - script source size, in bytes. -- `is_for_global` - snapshot would be executed as global (true) or eval (false). -- `is_strict` - strict mode +- `generate_snapshot_opts` - any combination of [jerry_generate_snapshot_opts_t](#jerry_generate_snapshot_opts_t) flags. - `buffer_p` - buffer to save snapshot to. - `buffer_size` - the buffer's size. - return value - - the size of snapshot, if it was generated succesfully (i.e. there are no syntax errors in source - code, buffer size is sufficient, and snapshot support is enabled in current configuration through - JERRY_ENABLE_SNAPSHOT_SAVE) - - 0 otherwise. + - the size of the snapshot as a number value, if it was generated succesfully (i.e. there are no syntax + errors in source code, buffer size is sufficient, and snapshot support is enabled in current configuration + through JERRY_ENABLE_SNAPSHOT_SAVE) + - thrown error, otherwise. **Example** @@ -4969,12 +4999,17 @@ main (void) static uint32_t global_mode_snapshot_buffer[256]; const jerry_char_t *code_to_snapshot_p = (const jerry_char_t *) "(function () { return 'string from snapshot'; }) ();"; - size_t global_mode_snapshot_size = jerry_parse_and_save_snapshot (code_to_snapshot_p, - strlen ((const char *) code_to_snapshot_p), - true, - false, - global_mode_snapshot_buffer, - sizeof (global_mode_snapshot_buffer) / sizeof (uint32_t)); + jerry_value_t generate_result; + generate_result = jerry_generate_snapshot (NULL, + 0, + code_to_snapshot_p, + strlen ((const char *) code_to_snapshot_p), + 0, + global_mode_snapshot_buffer, + sizeof (global_mode_snapshot_buffer) / sizeof (uint32_t)); + + size_t snapshot_size = (size_t) jerry_get_number_value (generate_result); + jerry_release_value (generate_result); jerry_cleanup (); } @@ -4984,81 +5019,11 @@ main (void) - [jerry_init](#jerry_init) - [jerry_cleanup](#jerry_cleanup) +- [jerry_generate_function_snapshot](#jerry_generate_function_snapshot) - [jerry_exec_snapshot](#jerry_exec_snapshot) -- [jerry_parse_and_save_static_snapshot](#jerry_parse_and_save_static_snapshot) -## jerry_parse_and_save_static_snapshot - -**Summary** - -Generate static snapshot from the specified source code. - -Unlike normal snaphots static snaphots are fully executed from ROM. Not -even their header is loaded into the RAM. However they can only depend -on magic strings and 28 bit integer numbers. Regular expression literals -are not supported as well. - -**Prototype** - -```c -size_t -jerry_parse_and_save_static_snapshot (const jerry_char_t *source_p, - size_t source_size, - bool is_for_global, - bool is_strict, - uint32_t *buffer_p, - size_t buffer_size); -``` - -- `source_p` - script source, it must be a valid utf8 string. -- `source_size` - script source size, in bytes. -- `is_for_global` - snapshot would be executed as global (true) or eval (false). -- `is_strict` - strict mode -- `buffer_p` - buffer to save snapshot to. -- `buffer_size` - the buffer's size. -- return value - - the size of snapshot, if it was generated succesfully (i.e. there are no syntax errors in source - code, buffer size is sufficient, only magic strings are used by the snapshot, and snapshot support - is enabled in current configuration through JERRY_ENABLE_SNAPSHOT_SAVE) - - 0 otherwise. - -**Example** - -[doctest]: # () - -```c -#include -#include "jerryscript.h" - -int -main (void) -{ - jerry_init (JERRY_INIT_EMPTY); - - static uint32_t global_mode_snapshot_buffer[256]; - const jerry_char_t *code_to_snapshot_p = (const jerry_char_t *) "(function () { return 'string'; }) ();"; - - size_t global_mode_snapshot_size = jerry_parse_and_save_static_snapshot (code_to_snapshot_p, - strlen ((const char *) code_to_snapshot_p), - true, - false, - global_mode_snapshot_buffer, - sizeof (global_mode_snapshot_buffer) / sizeof (uint32_t)); - - jerry_cleanup (); -} -``` - -**See also** - -- [jerry_init](#jerry_init) -- [jerry_cleanup](#jerry_cleanup) -- [jerry_exec_snapshot](#jerry_exec_snapshot) -- [jerry_parse_and_save_snapshot](#jerry_parse_and_save_snapshot) - - -## jerry_parse_and_save_function_snapshot +## jerry_generate_function_snapshot **Summary** @@ -5071,28 +5036,32 @@ passed as separated arguments. **Prototype** ```c -size_t -jerry_parse_and_save_function_snapshot (const jerry_char_t *source_p, - size_t source_size, - const jerry_char_t *args_p, - size_t args_size, - bool is_strict, - uint32_t *buffer_p, - size_t buffer_size) +jerry_value_t +jerry_generate_function_snapshot (const jerry_char_t *resource_name_p, + size_t resource_name_length, + const jerry_char_t *source_p, + size_t source_size, + const jerry_char_t *args_p, + size_t args_size, + uint32_t generate_snapshot_opts, + uint32_t *buffer_p, + size_t buffer_size) ``` +- `resource_name_p` - resource (file) name of the source code. Currently unused, the debugger may use it in the future. +- `resource_name_length` - length of resource name. - `source_p` - script source, it must be a valid utf8 string. - `source_size` - script source size, in bytes. - `args_p` - function arguments, it must be a valid utf8 string. - `args_size` - function argument size, in bytes. -- `is_strict` - strict mode +- `generate_snapshot_opts` - any combination of [jerry_generate_snapshot_opts_t](#jerry_generate_snapshot_opts_t) flags. - `buffer_p` - buffer to save snapshot to. - `buffer_size` - the buffer's size. - return value - - the size of snapshot, if it was generated succesfully (i.e. there are no syntax errors in source - code, buffer size is sufficient, and snapshot support is enabled in current configuration through - JERRY_ENABLE_SNAPSHOT_SAVE) - - 0 otherwise. + - the size of the snapshot as a number value, if it was generated succesfully (i.e. there are no syntax + errors in source code, buffer size is sufficient, and snapshot support is enabled in current configuration + through JERRY_ENABLE_SNAPSHOT_SAVE) + - thrown error, otherwise. **Example** @@ -5111,13 +5080,19 @@ main (void) const jerry_char_t *args_p = (const jerry_char_t *) "a, b"; const jerry_char_t *src_p = (const jerry_char_t *) "return a + b;"; - size_t func_snapshot_size = jerry_parse_and_save_function_snapshot (src_p, - strlen ((const char *) src_p), - args_p, - strlen ((const char *) args_p), - false, - func_snapshot_buffer, - sizeof (func_snapshot_buffer) / sizeof (uint32_t)); + jerry_value_t generate_result; + generate_result = jerry_generate_function_snapshot (NULL, + 0, + src_p, + strlen ((const char *) src_p), + args_p, + strlen ((const char *) args_p), + 0, + func_snapshot_buffer, + sizeof (func_snapshot_buffer) / sizeof (uint32_t)); + + size_t snapshot_size = (size_t) jerry_get_number_value (generate_result); + jerry_release_value (generate_result); jerry_cleanup (); } @@ -5127,83 +5102,8 @@ main (void) - [jerry_init](#jerry_init) - [jerry_cleanup](#jerry_cleanup) +- [jerry_generate_snapshot](#jerry_generate_snapshot) - [jerry_load_function_snapshot_at](#jerry_load_function_snapshot_at) -- [jerry_parse_and_save_static_function_snapshot](#jerry_parse_and_save_static_function_snapshot) - - -## jerry_parse_and_save_static_function_snapshot - -**Summary** - -Generate static function snapshot from the specified source code -with the given function body and arguments. - -Unlike normal snaphots static snaphots are fully executed from ROM. Not -even their header is loaded into the RAM. However they can only depend -on magic strings and 28 bit integer numbers. Regular expression literals -are not supported as well. - -**Prototype** - -```c -size_t -jerry_parse_and_save_static_function_snapshot (const jerry_char_t *source_p, - size_t source_size, - const jerry_char_t *args_p, - size_t args_size, - bool is_strict, - uint32_t *buffer_p, - size_t buffer_size) -``` - -- `source_p` - script source, it must be a valid utf8 string. -- `source_size` - script source size, in bytes. -- `args_p` - function arguments, it must be a valid utf8 string. -- `args_size` - function argument size, in bytes. -- `is_strict` - strict mode -- `buffer_p` - buffer to save snapshot to. -- `buffer_size` - the buffer's size. -- return value - - the size of snapshot, if it was generated succesfully (i.e. there are no syntax errors in source - code, buffer size is sufficient, only magic strings are used by the snapshot, and snapshot support - is enabled in current configuration through JERRY_ENABLE_SNAPSHOT_SAVE) - - 0 otherwise. - -**Example** - -[doctest]: # () - -```c -#include -#include "jerryscript.h" - -int -main (void) -{ - jerry_init (JERRY_INIT_EMPTY); - - static uint32_t func_snapshot_buffer[256]; - const jerry_char_t *args_p = (const jerry_char_t *) "string, bind"; - const jerry_char_t *src_p = (const jerry_char_t *) "return bind(string)"; - - size_t func_snapshot_size = jerry_parse_and_save_static_function_snapshot (src_p, - strlen ((const char *) src_p), - args_p, - strlen ((const char *) args_p), - false, - func_snapshot_buffer, - sizeof (func_snapshot_buffer) / sizeof (uint32_t)); - - jerry_cleanup (); -} -``` - -**See also** - -- [jerry_init](#jerry_init) -- [jerry_cleanup](#jerry_cleanup) -- [jerry_load_function_snapshot_at](#jerry_load_function_snapshot_at) -- [jerry_parse_and_save_function_snapshot](#jerry_parse_and_save_function_snapshot) ## jerry_exec_snapshot @@ -5249,12 +5149,19 @@ main (void) const jerry_char_t *code_to_snapshot_p = (const jerry_char_t *) "(function () { return 'string from snapshot'; }) ();"; jerry_init (JERRY_INIT_EMPTY); - size_t global_mode_snapshot_size = jerry_parse_and_save_snapshot (code_to_snapshot_p, - strlen ((const char *) code_to_snapshot_p), - true, - false, - global_mode_snapshot_buffer, - sizeof (global_mode_snapshot_buffer) / sizeof (uint32_t)); + + jerry_value_t generate_result; + generate_result = jerry_generate_snapshot (NULL, + 0, + code_to_snapshot_p, + strlen ((const char *) code_to_snapshot_p), + 0, + global_mode_snapshot_buffer, + sizeof (global_mode_snapshot_buffer) / sizeof (uint32_t)); + + size_t global_mode_snapshot_size = (size_t) jerry_get_number_value (generate_result); + jerry_release_value (generate_result); + jerry_cleanup (); jerry_init (JERRY_INIT_EMPTY); @@ -5324,12 +5231,19 @@ main (void) const jerry_char_t *code_to_snapshot_p = (const jerry_char_t *) "(function () { return 'string from snapshot'; }) ();"; jerry_init (JERRY_INIT_EMPTY); - size_t global_mode_snapshot_size = jerry_parse_and_save_snapshot (code_to_snapshot_p, - strlen ((const char *) code_to_snapshot_p), - true, - false, - global_mode_snapshot_buffer, - sizeof (global_mode_snapshot_buffer) / sizeof (uint32_t)); + + jerry_value_t generate_result; + generate_result = jerry_generate_snapshot (NULL, + 0, + code_to_snapshot_p, + strlen ((const char *) code_to_snapshot_p), + 0, + global_mode_snapshot_buffer, + sizeof (global_mode_snapshot_buffer) / sizeof (uint32_t)); + + size_t global_mode_snapshot_size = (size_t) jerry_get_number_value (generate_result); + jerry_release_value (generate_result); + jerry_cleanup (); jerry_init (JERRY_INIT_EMPTY); @@ -5402,13 +5316,21 @@ main (void) const jerry_char_t *src_p = (const jerry_char_t *) "return a + b;"; jerry_init (JERRY_INIT_EMPTY); - size_t snapshot_size = jerry_parse_and_save_function_snapshot (src_p, - strlen ((const char *) src_p), - args_p, - strlen ((const char *) args_p), - false, - snapshot_buffer, - sizeof (snapshot_buffer) / sizeof (uint32_t)); + + jerry_value_t generate_result; + generate_result = jerry_generate_function_snapshot (NULL, + 0, + src_p, + strlen ((const char *) src_p), + args_p, + strlen ((const char *) args_p), + false, + snapshot_buffer, + sizeof (snapshot_buffer) / sizeof (uint32_t)); + + size_t snapshot_size = (size_t) jerry_get_number_value (generate_result); + jerry_release_value (generate_result); + jerry_cleanup (); jerry_init (JERRY_INIT_EMPTY); diff --git a/jerry-core/api/jerry-snapshot.c b/jerry-core/api/jerry-snapshot.c index 6c64a0cb5..c60294288 100644 --- a/jerry-core/api/jerry-snapshot.c +++ b/jerry-core/api/jerry-snapshot.c @@ -13,15 +13,16 @@ * limitations under the License. */ +#include "ecma-conversion.h" #include "ecma-exceptions.h" #include "ecma-function-object.h" #include "ecma-helpers.h" +#include "ecma-lex-env.h" #include "ecma-literal-storage.h" #include "jcontext.h" #include "jerryscript.h" #include "jerry-snapshot.h" #include "js-parser.h" -#include "ecma-lex-env.h" #include "lit-char-helpers.h" #include "re-compiler.h" @@ -74,7 +75,7 @@ snapshot_check_global_flags (uint32_t global_flags) /**< global flags */ typedef struct { size_t snapshot_buffer_write_offset; - bool snapshot_error_occured; + ecma_value_t snapshot_error; bool regex_found; } snapshot_globals_t; @@ -110,6 +111,15 @@ snapshot_write_to_buffer_by_offset (uint8_t *buffer_p, /**< buffer */ return true; } /* snapshot_write_to_buffer_by_offset */ +/** + * Maximum snapshot write buffer offset. + */ +#if CONFIG_ECMA_NUMBER_TYPE == CONFIG_ECMA_NUMBER_FLOAT32 +#define JERRY_SNAPSHOT_MAXIMUM_WRITE_OFFSET (0x7fffff >> 1) +#else +#define JERRY_SNAPSHOT_MAXIMUM_WRITE_OFFSET (UINT32_MAX >> 1) +#endif + /** * Save snapshot helper. * @@ -121,16 +131,19 @@ snapshot_add_compiled_code (ecma_compiled_code_t *compiled_code_p, /**< compiled size_t snapshot_buffer_size, /**< snapshot buffer size */ snapshot_globals_t *globals_p) /**< snapshot globals */ { - if (globals_p->snapshot_error_occured) + const jerry_char_t *error_buffer_too_small_p = (const jerry_char_t *) "Snapshot buffer too small."; + + if (!ecma_is_value_empty (globals_p->snapshot_error)) { return 0; } JERRY_ASSERT ((globals_p->snapshot_buffer_write_offset & (JMEM_ALIGNMENT - 1)) == 0); - if (globals_p->snapshot_buffer_write_offset > (UINT32_MAX >> 1)) + if (globals_p->snapshot_buffer_write_offset > JERRY_SNAPSHOT_MAXIMUM_WRITE_OFFSET) { - globals_p->snapshot_error_occured = true; + const char *error_message_p = "Maximum snapshot size reached."; + globals_p->snapshot_error = jerry_create_error (JERRY_ERROR_RANGE, (const jerry_char_t *) error_message_p); return 0; } @@ -147,7 +160,7 @@ snapshot_add_compiled_code (ecma_compiled_code_t *compiled_code_p, /**< compiled /* Regular expression. */ if (globals_p->snapshot_buffer_write_offset + sizeof (ecma_compiled_code_t) > snapshot_buffer_size) { - globals_p->snapshot_error_occured = true; + globals_p->snapshot_error = jerry_create_error (JERRY_ERROR_RANGE, error_buffer_too_small_p); return 0; } @@ -168,11 +181,17 @@ snapshot_add_compiled_code (ecma_compiled_code_t *compiled_code_p, /**< compiled buffer_p, buffer_size)) { - globals_p->snapshot_error_occured = true; + globals_p->snapshot_error = jerry_create_error (JERRY_ERROR_RANGE, error_buffer_too_small_p); + /* cannot return inside ECMA_FINALIZE_UTF8_STRING */ } ECMA_FINALIZE_UTF8_STRING (buffer_p, buffer_size); + if (!ecma_is_value_empty (globals_p->snapshot_error)) + { + return 0; + } + globals_p->regex_found = true; globals_p->snapshot_buffer_write_offset = JERRY_ALIGNUP (globals_p->snapshot_buffer_write_offset, JMEM_ALIGNMENT); @@ -197,7 +216,7 @@ snapshot_add_compiled_code (ecma_compiled_code_t *compiled_code_p, /**< compiled compiled_code_p, ((size_t) compiled_code_p->size) << JMEM_ALIGNMENT_LOG)) { - globals_p->snapshot_error_occured = true; + globals_p->snapshot_error = jerry_create_error (JERRY_ERROR_RANGE, error_buffer_too_small_p); return 0; } @@ -240,7 +259,7 @@ snapshot_add_compiled_code (ecma_compiled_code_t *compiled_code_p, /**< compiled snapshot_buffer_size, globals_p); - JERRY_ASSERT (globals_p->snapshot_error_occured || offset > start_offset); + JERRY_ASSERT (!ecma_is_value_empty (globals_p->snapshot_error) || offset > start_offset); literal_start_p[i] = offset - start_offset; } @@ -249,6 +268,31 @@ snapshot_add_compiled_code (ecma_compiled_code_t *compiled_code_p, /**< compiled return start_offset; } /* snapshot_add_compiled_code */ +/** + * Create unsupported literal error. + */ +static void +static_snapshot_error_unsupported_literal (snapshot_globals_t *globals_p, /**< snapshot globals */ + ecma_value_t literal) /**< literal form the literal pool */ +{ + const char *error_prefix_p = "Unsupported static snapshot literal: "; + + ecma_string_t *error_message_p = ecma_new_ecma_string_from_utf8 ((const lit_utf8_byte_t *) error_prefix_p, + (lit_utf8_size_t) strlen (error_prefix_p)); + + literal = ecma_op_to_string (literal); + JERRY_ASSERT (!ECMA_IS_VALUE_ERROR (literal)); + + ecma_string_t *literal_string_p = ecma_get_string_from_value (literal); + error_message_p = ecma_concat_ecma_strings (error_message_p, literal_string_p); + ecma_deref_ecma_string (literal_string_p); + + ecma_object_t *error_object_p = ecma_new_standard_error_with_message (ECMA_ERROR_RANGE, error_message_p); + ecma_deref_ecma_string (error_message_p); + + globals_p->snapshot_error = ecma_create_error_object_reference (error_object_p); +} /* static_snapshot_error_unsupported_literal */ + /** * Save static snapshot helper. * @@ -260,16 +304,17 @@ static_snapshot_add_compiled_code (ecma_compiled_code_t *compiled_code_p, /**< c size_t snapshot_buffer_size, /**< snapshot buffer size */ snapshot_globals_t *globals_p) /**< snapshot globals */ { - if (globals_p->snapshot_error_occured) + if (!ecma_is_value_empty (globals_p->snapshot_error)) { return 0; } JERRY_ASSERT ((globals_p->snapshot_buffer_write_offset & (JMEM_ALIGNMENT - 1)) == 0); - if (globals_p->snapshot_buffer_write_offset >= UINT32_MAX) + if (globals_p->snapshot_buffer_write_offset >= JERRY_SNAPSHOT_MAXIMUM_WRITE_OFFSET) { - globals_p->snapshot_error_occured = true; + const char *error_message_p = "Maximum snapshot size reached."; + globals_p->snapshot_error = jerry_create_error (JERRY_ERROR_RANGE, (const jerry_char_t *) error_message_p); return 0; } @@ -283,7 +328,8 @@ static_snapshot_add_compiled_code (ecma_compiled_code_t *compiled_code_p, /**< c if (!(compiled_code_p->status_flags & CBC_CODE_FLAGS_FUNCTION)) { /* Regular expression literals are not supported. */ - globals_p->snapshot_error_occured = true; + const char *error_message_p = "Regular expression literals are not supported."; + globals_p->snapshot_error = jerry_create_error (JERRY_ERROR_RANGE, (const jerry_char_t *) error_message_p); return 0; } @@ -293,7 +339,8 @@ static_snapshot_add_compiled_code (ecma_compiled_code_t *compiled_code_p, /**< c compiled_code_p, ((size_t) compiled_code_p->size) << JMEM_ALIGNMENT_LOG)) { - globals_p->snapshot_error_occured = true; + const char *error_message_p = "Snapshot buffer too small."; + globals_p->snapshot_error = jerry_create_error (JERRY_ERROR_RANGE, (const jerry_char_t *) error_message_p); return 0; } @@ -330,7 +377,7 @@ static_snapshot_add_compiled_code (ecma_compiled_code_t *compiled_code_p, /**< c if (!ecma_is_value_direct (literal_start_p[i]) && !ecma_is_value_direct_string (literal_start_p[i])) { - globals_p->snapshot_error_occured = true; + static_snapshot_error_unsupported_literal (globals_p, literal_start_p[i]); return 0; } } @@ -351,7 +398,7 @@ static_snapshot_add_compiled_code (ecma_compiled_code_t *compiled_code_p, /**< c snapshot_buffer_size, globals_p); - JERRY_ASSERT (globals_p->snapshot_error_occured || offset > start_offset); + JERRY_ASSERT (!ecma_is_value_empty (globals_p->snapshot_error) || offset > start_offset); literal_start_p[i] = offset - start_offset; } @@ -366,7 +413,7 @@ static_snapshot_add_compiled_code (ecma_compiled_code_t *compiled_code_p, /**< c { if (!ecma_is_value_direct_string (literal_start_p[i])) { - globals_p->snapshot_error_occured = true; + static_snapshot_error_unsupported_literal (globals_p, literal_start_p[i]); return 0; } } @@ -656,33 +703,29 @@ snapshot_load_compiled_code (const uint8_t *base_addr_p, /**< base address of th #ifdef JERRY_ENABLE_SNAPSHOT_SAVE -/** - * jerry_parse_and_save_snapshot_with_args flags. - */ -typedef enum -{ - JERRY_SNAPSHOT_SAVE_STATIC = (1u << 0), /**< static snapshot */ - JERRY_SNAPSHOT_SAVE_STRICT = (1u << 1), /**< strict mode code */ - JERRY_SNAPSHOT_SAVE_EVAL = (1u << 2), /**< eval context code */ -} jerry_parse_and_save_snapshot_flags_t; - /** * Generate snapshot from specified source and arguments * - * @return size of snapshot, if it was generated succesfully + * @return size of snapshot (a number value), if it was generated succesfully * (i.e. there are no syntax errors in source code, buffer size is sufficient, * and snapshot support is enabled in current configuration through JERRY_ENABLE_SNAPSHOT_SAVE), - * 0 - otherwise. + * error object otherwise */ -static size_t -jerry_parse_and_save_snapshot_with_args (const jerry_char_t *source_p, /**< script source */ - size_t source_size, /**< script source size */ - const jerry_char_t *args_p, /**< arguments string */ - size_t args_size, /**< arguments string size */ - uint32_t flags, /**< jerry_parse_and_save_snapshot_flags_t flags */ - uint32_t *buffer_p, /**< buffer to save snapshot to */ - size_t buffer_size) /**< the buffer's size */ +static jerry_value_t +jerry_generate_snapshot_with_args (const jerry_char_t *resource_name_p, /**< script resource name */ + size_t resource_name_length, /**< script resource name length */ + const jerry_char_t *source_p, /**< script source */ + size_t source_size, /**< script source size */ + const jerry_char_t *args_p, /**< arguments string */ + size_t args_size, /**< arguments string size */ + uint32_t generate_snapshot_opts, /**< jerry_generate_snapshot_opts_t option bits */ + uint32_t *buffer_p, /**< buffer to save snapshot to */ + size_t buffer_size) /**< the buffer's size */ { + /* Currently unused arguments. */ + JERRY_UNUSED (resource_name_p); + JERRY_UNUSED (resource_name_length); + snapshot_globals_t globals; ecma_value_t parse_status; ecma_compiled_code_t *bytecode_data_p; @@ -690,23 +733,22 @@ jerry_parse_and_save_snapshot_with_args (const jerry_char_t *source_p, /**< scri JMEM_ALIGNMENT); globals.snapshot_buffer_write_offset = aligned_header_size; - globals.snapshot_error_occured = false; + globals.snapshot_error = ECMA_VALUE_EMPTY; globals.regex_found = false; parse_status = parser_parse_script (args_p, args_size, source_p, source_size, - (flags & JERRY_SNAPSHOT_SAVE_STRICT) != 0, + (generate_snapshot_opts & JERRY_SNAPSHOT_SAVE_STRICT) != 0, &bytecode_data_p); if (ECMA_IS_VALUE_ERROR (parse_status)) { - ecma_free_value (JERRY_CONTEXT (error_value)); - return 0; + return ecma_create_error_reference (JERRY_CONTEXT (error_value), true); } - if (flags & JERRY_SNAPSHOT_SAVE_STATIC) + if (generate_snapshot_opts & JERRY_SNAPSHOT_SAVE_STATIC) { static_snapshot_add_compiled_code (bytecode_data_p, (uint8_t *) buffer_p, buffer_size, &globals); } @@ -715,9 +757,9 @@ jerry_parse_and_save_snapshot_with_args (const jerry_char_t *source_p, /**< scri snapshot_add_compiled_code (bytecode_data_p, (uint8_t *) buffer_p, buffer_size, &globals); } - if (globals.snapshot_error_occured) + if (!ecma_is_value_empty (globals.snapshot_error)) { - return 0; + return globals.snapshot_error; } jerry_snapshot_header_t header; @@ -728,15 +770,10 @@ jerry_parse_and_save_snapshot_with_args (const jerry_char_t *source_p, /**< scri header.number_of_funcs = 1; header.func_offsets[0] = aligned_header_size; - if (flags & JERRY_SNAPSHOT_SAVE_EVAL) - { - header.func_offsets[0] |= JERRY_SNAPSHOT_EVAL_CONTEXT; - } - lit_mem_to_snapshot_id_map_entry_t *lit_map_p = NULL; uint32_t literals_num = 0; - if (!(flags & JERRY_SNAPSHOT_SAVE_STATIC)) + if (!(generate_snapshot_opts & JERRY_SNAPSHOT_SAVE_STATIC)) { ecma_collection_header_t *lit_pool_p = ecma_new_values_collection (); @@ -750,7 +787,8 @@ jerry_parse_and_save_snapshot_with_args (const jerry_char_t *source_p, /**< scri &literals_num)) { JERRY_ASSERT (lit_map_p == NULL); - return 0; + const char *error_message_p = "Cannot allocate memory for literals."; + return jerry_create_error (JERRY_ERROR_COMMON, (const jerry_char_t *) error_message_p); } jerry_snapshot_set_offsets (buffer_p + (aligned_header_size / sizeof (uint32_t)), @@ -773,92 +811,58 @@ jerry_parse_and_save_snapshot_with_args (const jerry_char_t *source_p, /**< scri ecma_bytecode_deref (bytecode_data_p); - return globals.snapshot_buffer_write_offset; -} /* jerry_parse_and_save_snapshot_with_args */ + return ecma_make_number_value ((ecma_number_t) globals.snapshot_buffer_write_offset); +} /* jerry_generate_snapshot_with_args */ #endif /* JERRY_ENABLE_SNAPSHOT_SAVE */ /** - * Generate snapshot from specified source + * Generate snapshot from specified source and arguments * - * @return size of snapshot, if it was generated succesfully + * @return size of snapshot (a number value), if it was generated succesfully * (i.e. there are no syntax errors in source code, buffer size is sufficient, * and snapshot support is enabled in current configuration through JERRY_ENABLE_SNAPSHOT_SAVE), - * 0 - otherwise. + * error object otherwise */ -size_t -jerry_parse_and_save_snapshot (const jerry_char_t *source_p, /**< script source */ - size_t source_size, /**< script source size */ - bool is_for_global, /**< snapshot would be executed as global (true) - * or eval (false) */ - bool is_strict, /**< strict mode */ - uint32_t *buffer_p, /**< buffer to save snapshot to */ - size_t buffer_size) /**< the buffer's size */ +jerry_value_t +jerry_generate_snapshot (const jerry_char_t *resource_name_p, /**< script resource name */ + size_t resource_name_length, /**< script resource name length */ + const jerry_char_t *source_p, /**< script source */ + size_t source_size, /**< script source size */ + uint32_t generate_snapshot_opts, /**< jerry_generate_snapshot_opts_t option bits */ + uint32_t *buffer_p, /**< buffer to save snapshot to */ + size_t buffer_size) /**< the buffer's size */ { #ifdef JERRY_ENABLE_SNAPSHOT_SAVE - uint32_t flags = (!is_for_global ? JERRY_SNAPSHOT_SAVE_EVAL : 0); - flags |= (is_strict ? JERRY_SNAPSHOT_SAVE_STRICT : 0); + uint32_t allowed_opts = (JERRY_SNAPSHOT_SAVE_STATIC | JERRY_SNAPSHOT_SAVE_STRICT); - return jerry_parse_and_save_snapshot_with_args (source_p, - source_size, - NULL, - 0, - flags, - buffer_p, - buffer_size); + if ((generate_snapshot_opts & ~(allowed_opts)) != 0) + { + const char *error_message_p = "Unsupported generate snapshot flags specified."; + return jerry_create_error (JERRY_ERROR_RANGE, (const jerry_char_t *) error_message_p); + } + + return jerry_generate_snapshot_with_args (resource_name_p, + resource_name_length, + source_p, + source_size, + NULL, + 0, + generate_snapshot_opts, + buffer_p, + buffer_size); #else /* !JERRY_ENABLE_SNAPSHOT_SAVE */ + JERRY_UNUSED (resource_name_p); + JERRY_UNUSED (resource_name_length); JERRY_UNUSED (source_p); JERRY_UNUSED (source_size); - JERRY_UNUSED (is_for_global); - JERRY_UNUSED (is_strict); + JERRY_UNUSED (generate_snapshot_opts); JERRY_UNUSED (buffer_p); JERRY_UNUSED (buffer_size); return 0; #endif /* JERRY_ENABLE_SNAPSHOT_SAVE */ -} /* jerry_parse_and_save_snapshot */ - -/** - * Generate static snapshot from specified source - * - * @return size of snapshot, if it was generated succesfully - * (i.e. there are no syntax errors in source code, all static snapshot requirements - * are satisfied, buffer size is sufficient, and snapshot support is enabled in - * current configuration through JERRY_ENABLE_SNAPSHOT_SAVE), - * 0 - otherwise. - */ -size_t -jerry_parse_and_save_static_snapshot (const jerry_char_t *source_p, /**< script source */ - size_t source_size, /**< script source size */ - bool is_for_global, /**< snapshot would be executed as global (true) - * or eval (false) */ - bool is_strict, /**< strict mode */ - uint32_t *buffer_p, /**< buffer to save snapshot to */ - size_t buffer_size) /**< the buffer's size */ -{ -#ifdef JERRY_ENABLE_SNAPSHOT_SAVE - uint32_t flags = JERRY_SNAPSHOT_SAVE_STATIC; - flags |= (!is_for_global ? JERRY_SNAPSHOT_SAVE_EVAL : 0); - flags |= (is_strict ? JERRY_SNAPSHOT_SAVE_STRICT : 0); - - return jerry_parse_and_save_snapshot_with_args (source_p, - source_size, - NULL, - 0, - flags, - buffer_p, - buffer_size); -#else /* !JERRY_ENABLE_SNAPSHOT_SAVE */ - JERRY_UNUSED (source_p); - JERRY_UNUSED (source_size); - JERRY_UNUSED (is_for_global); - JERRY_UNUSED (is_strict); - JERRY_UNUSED (buffer_p); - JERRY_UNUSED (buffer_size); - - return 0; -#endif /* JERRY_ENABLE_SNAPSHOT_SAVE */ -} /* jerry_parse_and_save_static_snapshot */ +} /* jerry_generate_snapshot */ #ifdef JERRY_ENABLE_SNAPSHOT_EXEC /** @@ -918,7 +922,7 @@ jerry_snapshot_result_at (const uint32_t *snapshot_p, /**< snapshot */ JERRY_ASSERT ((header_p->lit_table_offset % sizeof (uint32_t)) == 0); - uint32_t func_offset = header_p->func_offsets[func_index] & ~JERRY_SNAPSHOT_EVAL_CONTEXT; + uint32_t func_offset = header_p->func_offsets[func_index]; ecma_compiled_code_t *bytecode_p = (ecma_compiled_code_t *) (snapshot_data_p + func_offset); if (bytecode_p->status_flags & CBC_CODE_FLAGS_STATIC_FUNCTION) @@ -957,10 +961,6 @@ jerry_snapshot_result_at (const uint32_t *snapshot_p, /**< snapshot */ } ret_val = ecma_make_object_value (func_obj_p); } - else if (header_p->func_offsets[func_index] & JERRY_SNAPSHOT_EVAL_CONTEXT) - { - ret_val = vm_run_eval (bytecode_p, false); - } else { ret_val = vm_run_global (bytecode_p); @@ -1256,7 +1256,7 @@ jerry_merge_snapshots (const uint32_t **inp_buffers_p, /**< array of (pointers t merged_global_flags |= header_p->global_flags; - uint32_t start_offset = header_p->func_offsets[0] & ~JERRY_SNAPSHOT_EVAL_CONTEXT; + uint32_t start_offset = header_p->func_offsets[0]; const uint8_t *data_p = (const uint8_t *) inp_buffers_p[i]; const uint8_t *literal_base_p = (uint8_t *) (data_p + header_p->lit_table_offset); @@ -1312,7 +1312,7 @@ jerry_merge_snapshots (const uint32_t **inp_buffers_p, /**< array of (pointers t { const jerry_snapshot_header_t *current_header_p = (const jerry_snapshot_header_t *) inp_buffers_p[i]; - uint32_t start_offset = current_header_p->func_offsets[0] & ~JERRY_SNAPSHOT_EVAL_CONTEXT; + uint32_t start_offset = current_header_p->func_offsets[0]; memcpy (dst_p, ((const uint8_t *) inp_buffers_p[i]) + start_offset, @@ -1781,84 +1781,56 @@ jerry_parse_and_save_literals (const jerry_char_t *source_p, /**< script source } /* jerry_parse_and_save_literals */ /** - * Generate snapshot from specified function source + * Generate snapshot function from specified source and arguments * - * @return size of snapshot, if it was generated succesfully + * @return size of snapshot (a number value), if it was generated succesfully * (i.e. there are no syntax errors in source code, buffer size is sufficient, * and snapshot support is enabled in current configuration through JERRY_ENABLE_SNAPSHOT_SAVE), - * 0 - otherwise. + * error object otherwise */ -size_t jerry_parse_and_save_function_snapshot (const jerry_char_t *source_p, /**< function body source */ - size_t source_size, /**< function body size */ - const jerry_char_t *args_p, /**< arguments string */ - size_t args_size, /**< arguments string size */ - bool is_strict, /**< strict mode */ - uint32_t *buffer_p, /**< buffer to save snapshot to */ - size_t buffer_size) /**< the buffer's size */ +jerry_value_t +jerry_generate_function_snapshot (const jerry_char_t *resource_name_p, /**< script resource name */ + size_t resource_name_length, /**< script resource name length */ + const jerry_char_t *source_p, /**< script source */ + size_t source_size, /**< script source size */ + const jerry_char_t *args_p, /**< arguments string */ + size_t args_size, /**< arguments string size */ + uint32_t generate_snapshot_opts, /**< jerry_generate_snapshot_opts_t option bits */ + uint32_t *buffer_p, /**< buffer to save snapshot to */ + size_t buffer_size) /**< the buffer's size */ { #ifdef JERRY_ENABLE_SNAPSHOT_SAVE - uint32_t flags = (is_strict ? JERRY_SNAPSHOT_SAVE_STRICT : 0); + uint32_t allowed_opts = (JERRY_SNAPSHOT_SAVE_STATIC | JERRY_SNAPSHOT_SAVE_STRICT); - return jerry_parse_and_save_snapshot_with_args (source_p, - source_size, - args_p, - args_size, - flags, - buffer_p, - buffer_size); + if ((generate_snapshot_opts & ~(allowed_opts)) != 0) + { + const char *error_message_p = "Unsupported generate snapshot flags specified."; + return jerry_create_error (JERRY_ERROR_RANGE, (const jerry_char_t *) error_message_p); + } + + return jerry_generate_snapshot_with_args (resource_name_p, + resource_name_length, + source_p, + source_size, + args_p, + args_size, + generate_snapshot_opts, + buffer_p, + buffer_size); #else /* !JERRY_ENABLE_SNAPSHOT_SAVE */ + JERRY_UNUSED (resource_name_p); + JERRY_UNUSED (resource_name_length); JERRY_UNUSED (source_p); JERRY_UNUSED (source_size); JERRY_UNUSED (args_p); JERRY_UNUSED (args_size); - JERRY_UNUSED (is_strict); + JERRY_UNUSED (generate_snapshot_opts); JERRY_UNUSED (buffer_p); JERRY_UNUSED (buffer_size); return 0; #endif /* JERRY_ENABLE_SNAPSHOT_SAVE */ -} /* jerry_parse_and_save_function_snapshot */ - -/** - * Generate static snapshot from specified function source - * - * @return size of snapshot, if it was generated succesfully - * (i.e. there are no syntax errors in source code, all static snapshot requirements - * are satisfied, buffer size is sufficient, and snapshot support is enabled in - * current configuration through JERRY_ENABLE_SNAPSHOT_SAVE), - * 0 - otherwise. - */ -size_t jerry_parse_and_save_static_function_snapshot (const jerry_char_t *source_p, /**< function body source */ - size_t source_size, /**< function body size */ - const jerry_char_t *args_p, /**< arguments string */ - size_t args_size, /**< arguments string size */ - bool is_strict, /**< strict mode */ - uint32_t *buffer_p, /**< buffer to save snapshot to */ - size_t buffer_size) /**< the buffer's size */ -{ -#ifdef JERRY_ENABLE_SNAPSHOT_SAVE - uint32_t flags = JERRY_SNAPSHOT_SAVE_STATIC; - flags |= (is_strict ? JERRY_SNAPSHOT_SAVE_STRICT : 0); - - return jerry_parse_and_save_snapshot_with_args (source_p, - source_size, - args_p, - args_size, - flags, - buffer_p, - buffer_size); -#else /* !JERRY_ENABLE_SNAPSHOT_SAVE */ - JERRY_UNUSED (source_p); - JERRY_UNUSED (source_size); - JERRY_UNUSED (args_p); - JERRY_UNUSED (args_size); - JERRY_UNUSED (is_strict); - JERRY_UNUSED (buffer_p); - JERRY_UNUSED (buffer_size); - - return 0; -#endif /* JERRY_ENABLE_SNAPSHOT_SAVE */ -} /* jerry_parse_and_save_static_function_snapshot */ +} /* jerry_generate_function_snapshot */ /** * Load function from specified snapshot buffer diff --git a/jerry-core/api/jerry-snapshot.h b/jerry-core/api/jerry-snapshot.h index 080d729d0..1fe60e5ec 100644 --- a/jerry-core/api/jerry-snapshot.h +++ b/jerry-core/api/jerry-snapshot.h @@ -33,11 +33,6 @@ typedef struct uint32_t func_offsets[1]; /**< function offsets (lowest bit: global(0) or eval(1) context) */ } jerry_snapshot_header_t; -/** - * Evaluate this function on the top of the scope chain. - */ -#define JERRY_SNAPSHOT_EVAL_CONTEXT 0x1u - /** * Jerry snapshot magic marker. */ @@ -46,7 +41,7 @@ typedef struct /** * Jerry snapshot format version. */ -#define JERRY_SNAPSHOT_VERSION (10u) +#define JERRY_SNAPSHOT_VERSION (11u) /** * Snapshot configuration flags. diff --git a/jerry-core/include/jerryscript-snapshot.h b/jerry-core/include/jerryscript-snapshot.h index df6e1ef37..d59e7f063 100644 --- a/jerry-core/include/jerryscript-snapshot.h +++ b/jerry-core/include/jerryscript-snapshot.h @@ -27,13 +27,27 @@ extern "C" * @{ */ +/** + * Flags for jerry_generate_snapshot and jerry_generate_function_snapshot. + */ +typedef enum +{ + JERRY_SNAPSHOT_SAVE_STATIC = (1u << 0), /**< static snapshot */ + JERRY_SNAPSHOT_SAVE_STRICT = (1u << 1), /**< strict mode code */ +} jerry_generate_snapshot_opts_t; + /** * Snapshot functions. */ -size_t jerry_parse_and_save_snapshot (const jerry_char_t *source_p, size_t source_size, bool is_for_global, - bool is_strict, uint32_t *buffer_p, size_t buffer_size); -size_t jerry_parse_and_save_static_snapshot (const jerry_char_t *source_p, size_t source_size, bool is_for_global, - bool is_strict, uint32_t *buffer_p, size_t buffer_size); +jerry_value_t jerry_generate_snapshot (const jerry_char_t *resource_name_p, size_t resource_name_length, + const jerry_char_t *source_p, size_t source_size, + uint32_t generate_snapshot_opts, uint32_t *buffer_p, size_t buffer_size); +jerry_value_t jerry_generate_function_snapshot (const jerry_char_t *resource_name_p, size_t resource_name_length, + const jerry_char_t *source_p, size_t source_size, + const jerry_char_t *args_p, size_t args_size, + uint32_t generate_snapshot_opts, uint32_t *buffer_p, + size_t buffer_size); + jerry_value_t jerry_exec_snapshot (const uint32_t *snapshot_p, size_t snapshot_size, bool copy_bytecode); jerry_value_t jerry_exec_snapshot_at (const uint32_t *snapshot_p, size_t snapshot_size, size_t func_index, bool copy_bytecode); @@ -41,13 +55,6 @@ size_t jerry_merge_snapshots (const uint32_t **inp_buffers_p, size_t *inp_buffer 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_parse_and_save_function_snapshot (const jerry_char_t *source_p, size_t source_size, - const jerry_char_t *args_p, size_t args_size, - bool is_strict, uint32_t *buffer_p, size_t buffer_size); -size_t jerry_parse_and_save_static_function_snapshot (const jerry_char_t *source_p, size_t source_size, - const jerry_char_t *args_p, size_t args_size, - bool is_strict, uint32_t *buffer_p, size_t buffer_size); jerry_value_t jerry_load_function_snapshot_at (const uint32_t *function_snapshot_p, const size_t function_snapshot_size, size_t func_index, diff --git a/jerry-main/main-unix-snapshot.c b/jerry-main/main-unix-snapshot.c index 94ee4c53c..ce425bf77 100644 --- a/jerry-main/main-unix-snapshot.c +++ b/jerry-main/main-unix-snapshot.c @@ -13,6 +13,7 @@ * limitations under the License. */ +#include #include #include "jerryscript.h" @@ -120,6 +121,42 @@ read_file (uint8_t *input_pos_p, /**< next position in the input buffer */ return bytes_read; } /* read_file */ +/** + * Print error value + */ +static void +print_unhandled_exception (jerry_value_t error_value) /**< error value */ +{ + assert (!jerry_value_has_error_flag (error_value)); + + jerry_value_t err_str_val = jerry_value_to_string (error_value); + + if (jerry_value_has_error_flag (err_str_val)) + { + /* Avoid recursive error throws. */ + jerry_port_log (JERRY_LOG_LEVEL_ERROR, "Snapshot error: [value cannot be converted to string]\n"); + jerry_release_value (err_str_val); + return; + } + + jerry_size_t err_str_size = jerry_get_string_size (err_str_val); + + if (err_str_size >= 256) + { + jerry_port_log (JERRY_LOG_LEVEL_ERROR, "Snapshot error: [value cannot be converted to string]\n"); + jerry_release_value (err_str_val); + return; + } + + jerry_char_t err_str_buf[256]; + jerry_size_t string_end = jerry_string_to_char_buffer (err_str_val, err_str_buf, err_str_size); + assert (string_end == err_str_size); + err_str_buf[string_end] = 0; + + jerry_port_log (JERRY_LOG_LEVEL_ERROR, "Snapshot error: %s\n", (char *) err_str_buf); + jerry_release_value (err_str_val); +} /* print_unhandled_exception */ + /** * Generate command line option IDs */ @@ -127,7 +164,6 @@ typedef enum { OPT_GENERATE_HELP, OPT_GENERATE_STATIC, - OPT_GENERATE_CONTEXT, OPT_GENERATE_LITERAL_LIST, OPT_GENERATE_LITERAL_C, OPT_GENERATE_SHOW_OP, @@ -143,10 +179,6 @@ static const cli_opt_t generate_opts[] = .help = "print this help and exit"), CLI_OPT_DEF (.id = OPT_GENERATE_STATIC, .opt = "s", .longopt = "static", .help = "generate static snapshot"), - 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)"), @@ -174,14 +206,13 @@ process_generate (cli_state_t *cli_state_p, /**< cli state */ (void) argc; bool is_save_literals_mode_in_c_format = false; - bool is_snapshot_mode_for_global = true; + uint32_t snapshot_flags = 0; jerry_init_flag_t flags = JERRY_INIT_EMPTY; - uint32_t number_of_files = 0; + const char *file_name_p = NULL; uint8_t *source_p = input_buffer; size_t source_length = 0; const char *save_literals_file_name_p = NULL; - bool static_snapshot = false; cli_change_opts (cli_state_p, generate_opts); @@ -196,31 +227,7 @@ process_generate (cli_state_t *cli_state_p, /**< cli state */ } case OPT_GENERATE_STATIC: { - static_snapshot = true; - 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; - } + snapshot_flags |= JERRY_SNAPSHOT_SAVE_STATIC; break; } case OPT_GENERATE_LITERAL_LIST: @@ -252,7 +259,13 @@ process_generate (cli_state_t *cli_state_p, /**< cli state */ } case CLI_OPT_DEFAULT: { - const char *file_name_p = cli_consume_string (cli_state_p); + if (file_name_p != NULL) + { + jerry_port_log (JERRY_LOG_LEVEL_ERROR, "Error: Exactly one input file must be specified\n"); + return JERRY_STANDALONE_EXIT_CODE_FAIL; + } + + file_name_p = cli_consume_string (cli_state_p); if (cli_state_p->error == NULL) { @@ -263,8 +276,6 @@ process_generate (cli_state_t *cli_state_p, /**< cli state */ jerry_port_log (JERRY_LOG_LEVEL_ERROR, "Input file is empty\n"); return JERRY_STANDALONE_EXIT_CODE_FAIL; } - - number_of_files++; } break; } @@ -281,7 +292,7 @@ process_generate (cli_state_t *cli_state_p, /**< cli state */ return JERRY_STANDALONE_EXIT_CODE_FAIL; } - if (number_of_files != 1) + if (file_name_p == NULL) { jerry_port_log (JERRY_LOG_LEVEL_ERROR, "Error: Exactly one input file must be specified\n"); return JERRY_STANDALONE_EXIT_CODE_FAIL; @@ -295,33 +306,31 @@ process_generate (cli_state_t *cli_state_p, /**< cli state */ return JERRY_STANDALONE_EXIT_CODE_FAIL; } - size_t snapshot_size; + jerry_value_t snapshot_result; - if (static_snapshot) - { - snapshot_size = jerry_parse_and_save_static_snapshot ((jerry_char_t *) source_p, - source_length, - is_snapshot_mode_for_global, - false, - output_buffer, - sizeof (output_buffer) / sizeof (uint32_t)); - } - else - { - 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)); - } + snapshot_result = jerry_generate_snapshot ((jerry_char_t *) file_name_p, + (size_t) strlen (file_name_p), + (jerry_char_t *) source_p, + source_length, + snapshot_flags, + output_buffer, + sizeof (output_buffer) / sizeof (uint32_t)); - if (snapshot_size == 0) + if (jerry_value_has_error_flag (snapshot_result)) { jerry_port_log (JERRY_LOG_LEVEL_ERROR, "Error: Generating snapshot failed!\n"); + + jerry_value_clear_error_flag (&snapshot_result); + + print_unhandled_exception (snapshot_result); + + jerry_release_value (snapshot_result); return JERRY_STANDALONE_EXIT_CODE_FAIL; } + size_t snapshot_size = (size_t) jerry_get_number_value (snapshot_result); + jerry_release_value (snapshot_result); + FILE *snapshot_file_p = fopen (output_file_name_p, "w"); if (snapshot_file_p == NULL) { diff --git a/jerry-main/main-unix.c b/jerry-main/main-unix.c index 8bc1ead97..2ced1b200 100644 --- a/jerry-main/main-unix.c +++ b/jerry-main/main-unix.c @@ -97,13 +97,13 @@ print_unhandled_exception (jerry_value_t error_value) /**< error value */ { const char msg[] = "[Error message too long]"; err_str_size = sizeof (msg) / sizeof (char) - 1; - memcpy (err_str_buf, msg, err_str_size); + memcpy (err_str_buf, msg, err_str_size + 1); } else { - jerry_size_t sz = jerry_string_to_char_buffer (err_str_val, err_str_buf, err_str_size); - assert (sz == err_str_size); - err_str_buf[err_str_size] = 0; + jerry_size_t string_end = jerry_string_to_char_buffer (err_str_val, err_str_buf, err_str_size); + assert (string_end == err_str_size); + err_str_buf[string_end] = 0; if (jerry_is_feature_enabled (JERRY_FEATURE_ERROR_MESSAGES) && jerry_get_error_type (error_value) == JERRY_ERROR_SYNTAX) @@ -112,7 +112,7 @@ print_unhandled_exception (jerry_value_t error_value) /**< error value */ unsigned int err_col = 0; /* 1. parse column and line information */ - for (jerry_size_t i = 0; i < sz; i++) + for (jerry_size_t i = 0; i < string_end; i++) { if (!strncmp ((char *) (err_str_buf + i), "[line: ", 7)) { @@ -121,7 +121,7 @@ print_unhandled_exception (jerry_value_t error_value) /**< error value */ char num_str[8]; unsigned int j = 0; - while (i < sz && err_str_buf[i] != ',') + while (i < string_end && err_str_buf[i] != ',') { num_str[j] = (char) err_str_buf[i]; j++; @@ -139,7 +139,7 @@ print_unhandled_exception (jerry_value_t error_value) /**< error value */ i += 10; j = 0; - while (i < sz && err_str_buf[i] != ']') + while (i < string_end && err_str_buf[i] != ']') { num_str[j] = (char) err_str_buf[i]; j++; diff --git a/tests/unit-core/test-snapshot.c b/tests/unit-core/test-snapshot.c index 30e9d2627..196e6398d 100644 --- a/tests/unit-core/test-snapshot.c +++ b/tests/unit-core/test-snapshot.c @@ -62,14 +62,22 @@ static void test_function_snapshot (void) const char *code_to_snapshot_p = "return a + b"; jerry_init (flags); - size_t function_snapshot_size = jerry_parse_and_save_function_snapshot ((jerry_char_t *) code_to_snapshot_p, - strlen (code_to_snapshot_p), - (jerry_char_t *) args_p, - strlen (args_p), - false, - function_snapshot_buffer, - SNAPSHOT_BUFFER_SIZE); - TEST_ASSERT (function_snapshot_size != 0); + jerry_value_t generate_result; + generate_result = jerry_generate_function_snapshot (NULL, + 0, + (const jerry_char_t *) code_to_snapshot_p, + strlen (code_to_snapshot_p), + (jerry_char_t *) args_p, + strlen (args_p), + 0, + function_snapshot_buffer, + SNAPSHOT_BUFFER_SIZE); + TEST_ASSERT (!jerry_value_has_error_flag (generate_result) + && jerry_value_is_number (generate_result)); + + size_t function_snapshot_size = (size_t) jerry_get_number_value (generate_result); + jerry_release_value (generate_result); + jerry_cleanup (); jerry_init (flags); @@ -122,8 +130,8 @@ static void test_function_arguments_snapshot (void) if (jerry_is_feature_enabled (JERRY_FEATURE_SNAPSHOT_SAVE) && jerry_is_feature_enabled (JERRY_FEATURE_SNAPSHOT_EXEC)) { - static uint32_t global_arguments_snapshot_buffer[SNAPSHOT_BUFFER_SIZE]; - static uint32_t eval_arguments_snapshot_buffer[SNAPSHOT_BUFFER_SIZE]; + static uint32_t arguments_snapshot_buffer[SNAPSHOT_BUFFER_SIZE]; + const char *code_to_snapshot_p = ("function f(a,b,c) {" " arguments[0]++;" " arguments[1]++;" @@ -132,30 +140,26 @@ static void test_function_arguments_snapshot (void) "}" "f(3,4,5);"); jerry_init (JERRY_INIT_EMPTY); - size_t global_mode_snapshot_size = jerry_parse_and_save_snapshot ((jerry_char_t *) code_to_snapshot_p, - strlen (code_to_snapshot_p), - true, - false, - global_arguments_snapshot_buffer, - SNAPSHOT_BUFFER_SIZE); - TEST_ASSERT (global_mode_snapshot_size != 0); + + jerry_value_t generate_result; + generate_result = jerry_generate_snapshot (NULL, + 0, + (jerry_char_t *) code_to_snapshot_p, + strlen (code_to_snapshot_p), + 0, + arguments_snapshot_buffer, + SNAPSHOT_BUFFER_SIZE); + + TEST_ASSERT (!jerry_value_has_error_flag (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); + jerry_cleanup (); - jerry_init (JERRY_INIT_EMPTY); - size_t eval_mode_snapshot_size = jerry_parse_and_save_snapshot ((jerry_char_t *) code_to_snapshot_p, - strlen (code_to_snapshot_p), - false, - false, - eval_arguments_snapshot_buffer, - SNAPSHOT_BUFFER_SIZE); - TEST_ASSERT (eval_mode_snapshot_size != 0); - jerry_cleanup (); - - arguments_test_exec_snapshot (eval_arguments_snapshot_buffer, eval_mode_snapshot_size, false); - arguments_test_exec_snapshot (eval_arguments_snapshot_buffer, eval_mode_snapshot_size, true); - - arguments_test_exec_snapshot (global_arguments_snapshot_buffer, global_mode_snapshot_size, false); - arguments_test_exec_snapshot (global_arguments_snapshot_buffer, global_mode_snapshot_size, true); + arguments_test_exec_snapshot (arguments_snapshot_buffer, snapshot_size, false); + arguments_test_exec_snapshot (arguments_snapshot_buffer, snapshot_size, true); } } /* test_function_arguments_snapshot */ @@ -188,8 +192,7 @@ static void test_exec_snapshot (uint32_t *snapshot_p, size_t snapshot_size, bool int main (void) { - static uint32_t global_mode_snapshot_buffer[SNAPSHOT_BUFFER_SIZE]; - static uint32_t eval_mode_snapshot_buffer[SNAPSHOT_BUFFER_SIZE]; + static uint32_t snapshot_buffer[SNAPSHOT_BUFFER_SIZE]; TEST_INIT (); @@ -200,18 +203,24 @@ main (void) const char *code_to_snapshot_p = "(function () { return 'string from snapshot'; }) ();"; jerry_init (JERRY_INIT_EMPTY); - size_t global_mode_snapshot_size = jerry_parse_and_save_snapshot ((jerry_char_t *) code_to_snapshot_p, - strlen (code_to_snapshot_p), - true, - false, - global_mode_snapshot_buffer, - SNAPSHOT_BUFFER_SIZE); - TEST_ASSERT (global_mode_snapshot_size != 0); + jerry_value_t generate_result; + generate_result = jerry_generate_snapshot (NULL, + 0, + (const jerry_char_t *) code_to_snapshot_p, + strlen (code_to_snapshot_p), + 0, + snapshot_buffer, + SNAPSHOT_BUFFER_SIZE); + TEST_ASSERT (!jerry_value_has_error_flag (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); /* Check the snapshot data. Unused bytes should be filled with zeroes */ const uint8_t expected_data[] = { - 0x4A, 0x52, 0x52, 0x59, 0x0A, 0x00, 0x00, 0x00, + 0x4A, 0x52, 0x52, 0x59, 0x0B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x03, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, @@ -224,36 +233,13 @@ main (void) 0x20, 0x66, 0x72, 0x6F, 0x6D, 0x20, 0x73, 0x6E, 0x61, 0x70, 0x73, 0x68, 0x6F, 0x74 }; - TEST_ASSERT (sizeof (expected_data) == global_mode_snapshot_size); - TEST_ASSERT (0 == memcmp (expected_data, global_mode_snapshot_buffer, sizeof (expected_data))); + TEST_ASSERT (sizeof (expected_data) == snapshot_size); + TEST_ASSERT (0 == memcmp (expected_data, snapshot_buffer, sizeof (expected_data))); jerry_cleanup (); - jerry_init (JERRY_INIT_EMPTY); - size_t eval_mode_snapshot_size = jerry_parse_and_save_snapshot ((jerry_char_t *) code_to_snapshot_p, - strlen (code_to_snapshot_p), - false, - false, - eval_mode_snapshot_buffer, - SNAPSHOT_BUFFER_SIZE); - TEST_ASSERT (eval_mode_snapshot_size != 0); - jerry_cleanup (); - - test_exec_snapshot (global_mode_snapshot_buffer, - global_mode_snapshot_size, - false); - - test_exec_snapshot (global_mode_snapshot_buffer, - global_mode_snapshot_size, - true); - - test_exec_snapshot (eval_mode_snapshot_buffer, - eval_mode_snapshot_size, - false); - - test_exec_snapshot (eval_mode_snapshot_buffer, - eval_mode_snapshot_size, - true); + test_exec_snapshot (snapshot_buffer, snapshot_size, false); + test_exec_snapshot (snapshot_buffer, snapshot_size, true); } /* Static snapshot */ @@ -271,19 +257,23 @@ main (void) sizeof (magic_string_lengths) / sizeof (jerry_length_t), magic_string_lengths); - size_t global_mode_snapshot_size = jerry_parse_and_save_static_snapshot ((jerry_char_t *) code_to_snapshot_p, - strlen (code_to_snapshot_p), - true, - false, - global_mode_snapshot_buffer, - SNAPSHOT_BUFFER_SIZE); - TEST_ASSERT (global_mode_snapshot_size != 0); + jerry_value_t generate_result; + generate_result = jerry_generate_snapshot (NULL, + 0, + (jerry_char_t *) code_to_snapshot_p, + strlen (code_to_snapshot_p), + JERRY_SNAPSHOT_SAVE_STATIC, + snapshot_buffer, + SNAPSHOT_BUFFER_SIZE); + TEST_ASSERT (!jerry_value_has_error_flag (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); jerry_cleanup (); - test_exec_snapshot (global_mode_snapshot_buffer, - global_mode_snapshot_size, - false); + test_exec_snapshot (snapshot_buffer, snapshot_size, false); } /* Merge snapshot */ @@ -298,25 +288,38 @@ main (void) const char *code_to_snapshot_p = "123"; jerry_init (JERRY_INIT_EMPTY); - snapshot_sizes[0] = jerry_parse_and_save_snapshot ((jerry_char_t *) code_to_snapshot_p, - strlen (code_to_snapshot_p), - true, - false, - snapshot_buffer_0, - SNAPSHOT_BUFFER_SIZE); - TEST_ASSERT (snapshot_sizes[0] != 0); + jerry_value_t generate_result; + generate_result = jerry_generate_snapshot (NULL, + 0, + (const jerry_char_t *) code_to_snapshot_p, + strlen (code_to_snapshot_p), + 0, + snapshot_buffer_0, + SNAPSHOT_BUFFER_SIZE); + TEST_ASSERT (!jerry_value_has_error_flag (generate_result) + && jerry_value_is_number (generate_result)); + + snapshot_sizes[0] = (size_t) jerry_get_number_value (generate_result); + jerry_release_value (generate_result); + jerry_cleanup (); code_to_snapshot_p = "456"; jerry_init (JERRY_INIT_EMPTY); - snapshot_sizes[1] = jerry_parse_and_save_snapshot ((jerry_char_t *) code_to_snapshot_p, - strlen (code_to_snapshot_p), - true, - false, - snapshot_buffer_1, - SNAPSHOT_BUFFER_SIZE); - TEST_ASSERT (snapshot_sizes[1] != 0); + generate_result = jerry_generate_snapshot (NULL, + 0, + (const jerry_char_t *) code_to_snapshot_p, + strlen (code_to_snapshot_p), + 0, + snapshot_buffer_1, + SNAPSHOT_BUFFER_SIZE); + TEST_ASSERT (!jerry_value_has_error_flag (generate_result) + && jerry_value_is_number (generate_result)); + + snapshot_sizes[1] = (size_t) jerry_get_number_value (generate_result); + jerry_release_value (generate_result); + jerry_cleanup (); jerry_init (JERRY_INIT_EMPTY); diff --git a/tools/runners/run-test-suite.sh b/tools/runners/run-test-suite.sh index a56d6a8d3..d10e8fc02 100755 --- a/tools/runners/run-test-suite.sh +++ b/tools/runners/run-test-suite.sh @@ -148,8 +148,8 @@ do # Testing snapshot SNAPSHOT_TEMP=`mktemp $(basename -s .js $test).snapshot.XXXXXXXXXX` - 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 + cmd_line="${SNAPSHOT_TOOL#$ROOT_DIR} generate -o $SNAPSHOT_TEMP ${full_test#$ROOT_DIR}" + $TIMEOUT_CMD $TIMEOUT $SNAPSHOT_TOOL generate -o $SNAPSHOT_TEMP $full_test &> $ENGINE_TEMP status_code=$? if [ $status_code -eq 0 ]