Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
166 changes: 49 additions & 117 deletions docs/02.API-REFERENCE.md
Original file line number Diff line number Diff line change
Expand Up @@ -72,19 +72,40 @@ 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.
the literals and literal pools are copied into RAM even if the
`JERRY_SNAPSHOT_EXEC_COPY_DATA` option is passed to
[jerry_exec_snapshot](#jerry_exec_snapshot). 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`.
***Important note:*** The [jerry_exec_snapshot](#jerry_exec_snapshot)
function rejects static snaphots unless the `JERRY_SNAPSHOT_EXEC_ALLOW_STATIC`
option bit is set. The caller must also ensure that the same magic
strings are set by [jerry_register_magic_strings](#jerry_register_magic_strings)
when the snapshot is generated and executed. Furthermore the
`JERRY_SNAPSHOT_EXEC_COPY_DATA` option is not allowed.

## jerry_exec_snapshot_opts_t

Flags for [jerry_exec_snapshot](#jerry_exec_snapshot) and
[jerry_load_function_snapshot](#jerry_load_function_snapshot) functions:

- JERRY_SNAPSHOT_EXEC_COPY_DATA - copy snapshot data into memory (see below)
- JERRY_SNAPSHOT_EXEC_ALLOW_STATIC - allow executing static snapshots

**Copy snapshot data into memory**

By default the snapshot buffer is expected to be present in memory until
[jerry_cleanup](#jerry_cleanup) is called. For example `static const` buffers
compiled into the application binary satisfy this requirement.

If the snapshot buffer is freed after [jerry_exec_snapshot](#jerry_exec_snapshot)
is called the `JERRY_SNAPSHOT_EXEC_COPY_DATA` must be passed to copy the necessary
parts of the snapshot buffer into memory.

The `JERRY_SNAPSHOT_EXEC_COPY_DATA` option is not allowed for static snapshots.


## jerry_char_t
Expand Down Expand Up @@ -5121,15 +5142,14 @@ is no longer needed.
jerry_value_t
jerry_exec_snapshot (const uint32_t *snapshot_p,
size_t snapshot_size,
bool copy_bytecode);
size_t func_index,
uint32_t exec_snapshot_opts);
```

- `snapshot_p` - pointer to snapshot
- `snapshot_size` - size of snapshot
- `copy_bytecode` - flag, indicating whether the passed snapshot buffer should be copied to the
engine's memory. If set the engine should not reference the buffer after the function returns
(in this case, the passed buffer could be freed after the call). Otherwise (if the flag is not
set) - the buffer could only be freed after the engine stops (i.e. after call to jerry_cleanup).
- `func_index` - index of executed function
- `exec_snapshot_opts` - any combination of [jerry_exec_snapshot_opts_t](#jerry_exec_snapshot_opts_t) flags.
- return value
- result of bytecode, if run was successful
- thrown error, otherwise
Expand Down Expand Up @@ -5168,7 +5188,8 @@ main (void)

jerry_value_t res = jerry_exec_snapshot (global_mode_snapshot_buffer,
global_mode_snapshot_size,
false);
0,
0);
jerry_release_value (res);

jerry_cleanup ();
Expand All @@ -5179,96 +5200,10 @@ main (void)

- [jerry_init](#jerry_init)
- [jerry_cleanup](#jerry_cleanup)
- [jerry_exec_snapshot_at](#jerry_exec_snapshot_at)
- [jerry_parse_and_save_snapshot](#jerry_parse_and_save_snapshot)


## jerry_exec_snapshot_at

**Summary**

Execute the selected snapshot function from the specified buffer.

Same function as [jerry_exec_snapshot](#jerry_exec_snapshot) except
the executed function index can be specified.

*Note*: Returned value must be freed with [jerry_release_value](#jerry_release_value) when it
is no longer needed.

**Prototype**

```c
jerry_value_t
jerry_exec_snapshot_at (const uint32_t *snapshot_p,
size_t snapshot_size,
size_t func_index,
bool copy_bytecode);
```

- `snapshot_p` - pointer to snapshot
- `snapshot_size` - size of snapshot
- `func_index` - index of executed function
- `copy_bytecode` - flag, indicating whether the passed snapshot buffer should be copied to the
engine's memory. If set the engine should not reference the buffer after the function returns
(in this case, the passed buffer could be freed after the call). Otherwise (if the flag is not
set) - the buffer could only be freed after the engine stops (i.e. after call to jerry_cleanup).
- return value
- result of bytecode, if run was successful
- thrown error, otherwise

**Example**

[doctest]: # ()

```c
#include <string.h>
#include "jerryscript.h"

int
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'; }) ();";

jerry_init (JERRY_INIT_EMPTY);

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);

jerry_value_t res = jerry_exec_snapshot_at (global_mode_snapshot_buffer,
global_mode_snapshot_size,
0,
false);

jerry_release_value (res);

jerry_cleanup ();
return 0;
}
```

**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_load_function_snapshot_at
## jerry_load_function_snapshot

**Summary**

Expand All @@ -5283,19 +5218,16 @@ is no longer needed.

```c
jerry_value_t
jerry_load_function_snapshot_at (const uint32_t *snapshot_p,
size_t snapshot_size,
size_t func_index,
bool copy_bytecode);
jerry_load_function_snapshot (const uint32_t *snapshot_p,
size_t snapshot_size,
size_t func_index,
uint32_t exec_snapshot_opts);
```

- `snapshot_p` - pointer to snapshot
- `snapshot_size` - size of snapshot
- `func_index` - index of function to load
- `copy_bytecode` - flag, indicating whether the passed snapshot buffer should be copied to the
engine's memory. If set the engine should not reference the buffer after the function returns
(in this case, the passed buffer could be freed after the call). Otherwise (if the flag is not
set) - the buffer could only be freed after the engine stops (i.e. after call to jerry_cleanup).
- `exec_snapshot_opts` - any combination of [jerry_exec_snapshot_opts_t](#jerry_exec_snapshot_opts_t) flags.
- return value
- function object built from the snapshot
- thrown error, otherwise
Expand Down Expand Up @@ -5335,10 +5267,10 @@ main (void)

jerry_init (JERRY_INIT_EMPTY);

jerry_value_t func = jerry_load_function_snapshot_at (snapshot_buffer,
snapshot_size,
0,
false);
jerry_value_t func = jerry_load_function_snapshot (snapshot_buffer,
snapshot_size,
0,
0);
/* 'func' can be used now as a function object */

jerry_value_t this_value = jerry_create_undefined ();
Expand Down
109 changes: 37 additions & 72 deletions jerry-core/api/jerry-snapshot.c
Original file line number Diff line number Diff line change
Expand Up @@ -875,27 +875,30 @@ jerry_generate_snapshot (const jerry_char_t *resource_name_p, /**< script resour
* thrown error - otherwise
*/
static jerry_value_t
jerry_snapshot_result_at (const uint32_t *snapshot_p, /**< snapshot */
size_t snapshot_size, /**< size of snapshot */
size_t func_index, /**< index of primary function */
bool copy_bytecode, /**< flag, indicating whether the passed snapshot
* buffer should be copied to the engine's memory.
* If set the engine should not reference the buffer
* after the function returns (in this case, the passed
* buffer could be freed after the call).
* Otherwise (if the flag is not set) - the buffer could only be
* freed after the engine stops (i.e. after call to jerry_cleanup). */
bool as_function) /** < specify if the loaded snapshot should be returned as a function */
jerry_snapshot_result (const uint32_t *snapshot_p, /**< snapshot */
size_t snapshot_size, /**< size of snapshot */
size_t func_index, /**< index of primary function */
uint32_t exec_snapshot_opts, /**< jerry_exec_snapshot_opts_t option bits */
bool as_function) /** < specify if the loaded snapshot should be returned as a function */
{
JERRY_ASSERT (snapshot_p != NULL);

uint32_t allowed_opts = (JERRY_SNAPSHOT_EXEC_COPY_DATA | JERRY_SNAPSHOT_EXEC_ALLOW_STATIC);

if ((exec_snapshot_opts & ~(allowed_opts)) != 0)
{
ecma_raise_range_error (ECMA_ERR_MSG ("Unsupported exec snapshot flags specified."));
return ecma_create_error_reference_from_context ();
}

static const char * const invalid_version_error_p = "Invalid snapshot version or unsupported features present";
static const char * const invalid_format_error_p = "Invalid snapshot format";
const uint8_t *snapshot_data_p = (uint8_t *) snapshot_p;

if (snapshot_size <= sizeof (jerry_snapshot_header_t))
{
return ecma_raise_type_error (invalid_format_error_p);
ecma_raise_type_error (invalid_format_error_p);
return ecma_create_error_reference_from_context ();
}

const jerry_snapshot_header_t *header_p = (const jerry_snapshot_header_t *) snapshot_data_p;
Expand Down Expand Up @@ -927,7 +930,13 @@ jerry_snapshot_result_at (const uint32_t *snapshot_p, /**< snapshot */

if (bytecode_p->status_flags & CBC_CODE_FLAGS_STATIC_FUNCTION)
{
if (copy_bytecode)
if (!(exec_snapshot_opts & JERRY_SNAPSHOT_EXEC_ALLOW_STATIC))
{
ecma_raise_common_error (ECMA_ERR_MSG ("Static snapshots not allowed"));
return ecma_create_error_reference_from_context ();
}

if (exec_snapshot_opts & JERRY_SNAPSHOT_EXEC_COPY_DATA)
{
ecma_raise_common_error (ECMA_ERR_MSG ("Static snapshots cannot be copied into memory"));
return ecma_create_error_reference_from_context ();
Expand All @@ -939,7 +948,7 @@ jerry_snapshot_result_at (const uint32_t *snapshot_p, /**< snapshot */

bytecode_p = snapshot_load_compiled_code ((const uint8_t *) bytecode_p,
literal_base_p,
copy_bytecode);
(exec_snapshot_opts & JERRY_SNAPSHOT_EXEC_COPY_DATA) != 0);

if (bytecode_p == NULL)
{
Expand Down Expand Up @@ -976,41 +985,8 @@ jerry_snapshot_result_at (const uint32_t *snapshot_p, /**< snapshot */
}

return ret_val;
} /* jerry_snapshot_result_at */
#endif /* JERRY_ENABLE_SNAPSHOT_EXEC */

/**
* Execute snapshot from specified buffer
*
* Note:
* returned value must be freed with jerry_release_value, when it is no longer needed.
*
* @return result of bytecode - if run was successful
* thrown error - otherwise
*/
jerry_value_t
jerry_exec_snapshot_at (const uint32_t *snapshot_p, /**< snapshot */
size_t snapshot_size, /**< size of snapshot */
size_t func_index, /**< index of primary function */
bool copy_bytecode) /**< flag, indicating whether the passed snapshot
* buffer should be copied to the engine's memory.
* If set the engine should not reference the buffer
* after the function returns (in this case, the passed
* buffer could be freed after the call).
* Otherwise (if the flag is not set) - the buffer could only be
* freed after the engine stops (i.e. after call to jerry_cleanup). */
{
#ifdef JERRY_ENABLE_SNAPSHOT_EXEC
return jerry_snapshot_result_at (snapshot_p, snapshot_size, func_index, copy_bytecode, false);
#else /* !JERRY_ENABLE_SNAPSHOT_EXEC */
JERRY_UNUSED (snapshot_p);
JERRY_UNUSED (snapshot_size);
JERRY_UNUSED (func_index);
JERRY_UNUSED (copy_bytecode);

return ECMA_VALUE_FALSE;
} /* jerry_snapshot_result */
#endif /* JERRY_ENABLE_SNAPSHOT_EXEC */
} /* jerry_exec_snapshot_at */

/**
* Execute snapshot from specified buffer
Expand All @@ -1024,20 +1000,16 @@ jerry_exec_snapshot_at (const uint32_t *snapshot_p, /**< snapshot */
jerry_value_t
jerry_exec_snapshot (const uint32_t *snapshot_p, /**< snapshot */
size_t snapshot_size, /**< size of snapshot */
bool copy_bytecode) /**< flag, indicating whether the passed snapshot
* buffer should be copied to the engine's memory.
* If set the engine should not reference the buffer
* after the function returns (in this case, the passed
* buffer could be freed after the call).
* Otherwise (if the flag is not set) - the buffer could only be
* freed after the engine stops (i.e. after call to jerry_cleanup). */
size_t func_index, /**< index of primary function */
uint32_t exec_snapshot_opts) /**< jerry_exec_snapshot_opts_t option bits */
{
#ifdef JERRY_ENABLE_SNAPSHOT_EXEC
return jerry_exec_snapshot_at (snapshot_p, snapshot_size, 0, copy_bytecode);
return jerry_snapshot_result (snapshot_p, snapshot_size, func_index, exec_snapshot_opts, false);
#else /* !JERRY_ENABLE_SNAPSHOT_EXEC */
JERRY_UNUSED (snapshot_p);
JERRY_UNUSED (snapshot_size);
JERRY_UNUSED (copy_bytecode);
JERRY_UNUSED (func_index);
JERRY_UNUSED (exec_snapshot_opts);

return ECMA_VALUE_FALSE;
#endif /* JERRY_ENABLE_SNAPSHOT_EXEC */
Expand Down Expand Up @@ -1841,27 +1813,20 @@ jerry_generate_function_snapshot (const jerry_char_t *resource_name_p, /**< scri
* @return result of bytecode - if run was successful
* thrown error - otherwise
*/
jerry_value_t jerry_load_function_snapshot_at (const uint32_t *function_snapshot_p, /**< snapshot of the function(s) */
const size_t function_snapshot_size, /**< size of the snapshot */
size_t func_index, /**< index of the function to load */
bool copy_bytecode) /**< flag, indicating whether the passed snapshot
* buffer should be copied to the engine's memory.
* If set the engine should not reference
* the buffer after the function returns
* (in this case, the passed buffer could be freed
* after the call).
* Otherwise (if the flag is not set) - the buffer
* could only be freed after the engine stops
* (i.e. after call to jerry_cleanup). */
jerry_value_t
jerry_load_function_snapshot (const uint32_t *function_snapshot_p, /**< snapshot of the function(s) */
const size_t function_snapshot_size, /**< size of the snapshot */
size_t func_index, /**< index of the function to load */
uint32_t exec_snapshot_opts) /**< jerry_exec_snapshot_opts_t option bits */
{
#ifdef JERRY_ENABLE_SNAPSHOT_EXEC
return jerry_snapshot_result_at (function_snapshot_p, function_snapshot_size, func_index, copy_bytecode, true);
return jerry_snapshot_result (function_snapshot_p, function_snapshot_size, func_index, exec_snapshot_opts, true);
#else /* !JERRY_ENABLE_SNAPSHOT_EXEC */
JERRY_UNUSED (function_snapshot_p);
JERRY_UNUSED (function_snapshot_size);
JERRY_UNUSED (func_index);
JERRY_UNUSED (copy_bytecode);
JERRY_UNUSED (exec_snapshot_opts);

return ECMA_VALUE_FALSE;
#endif /* JERRY_ENABLE_SNAPSHOT_EXEC */
} /* jerry_load_function_snapshot_at */
} /* jerry_load_function_snapshot */
Loading