mirror of
https://github.com/jerryscript-project/jerryscript.git
synced 2025-12-15 16:29:21 +00:00
Support static snapshots. (#2239)
Unlike normal snapshots, no part of a static snapshot is loaded into the RAM when executed from ROM. Static snapshots rely heavily on external magic strings. JerryScript-DCO-1.0-Signed-off-by: Zoltan Herczeg zherczeg.u-szeged@partner.samsung.com
This commit is contained in:
parent
dde09cc4b6
commit
bb84466fcf
@ -4736,6 +4736,77 @@ main (void)
|
||||
- [jerry_init](#jerry_init)
|
||||
- [jerry_cleanup](#jerry_cleanup)
|
||||
- [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 <string.h>
|
||||
#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
|
||||
@ -4808,6 +4879,82 @@ main (void)
|
||||
- [jerry_init](#jerry_init)
|
||||
- [jerry_cleanup](#jerry_cleanup)
|
||||
- [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 <string.h>
|
||||
#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
|
||||
|
||||
@ -111,11 +111,11 @@ snapshot_write_to_buffer_by_offset (uint8_t *buffer_p, /**< buffer */
|
||||
} /* snapshot_write_to_buffer_by_offset */
|
||||
|
||||
/**
|
||||
* Snapshot callback for byte codes.
|
||||
* Save snapshot helper.
|
||||
*
|
||||
* @return start offset
|
||||
*/
|
||||
static uint16_t
|
||||
static uint32_t
|
||||
snapshot_add_compiled_code (ecma_compiled_code_t *compiled_code_p, /**< compiled code */
|
||||
uint8_t *snapshot_buffer_p, /**< snapshot buffer */
|
||||
size_t snapshot_buffer_size, /**< snapshot buffer size */
|
||||
@ -128,7 +128,7 @@ snapshot_add_compiled_code (ecma_compiled_code_t *compiled_code_p, /**< compiled
|
||||
|
||||
JERRY_ASSERT ((globals_p->snapshot_buffer_write_offset & (JMEM_ALIGNMENT - 1)) == 0);
|
||||
|
||||
if ((globals_p->snapshot_buffer_write_offset >> JMEM_ALIGNMENT_LOG) > 0xffffu)
|
||||
if (globals_p->snapshot_buffer_write_offset > (UINT32_MAX >> 1))
|
||||
{
|
||||
globals_p->snapshot_error_occured = true;
|
||||
return 0;
|
||||
@ -136,8 +136,7 @@ snapshot_add_compiled_code (ecma_compiled_code_t *compiled_code_p, /**< compiled
|
||||
|
||||
/* The snapshot generator always parses a single file,
|
||||
* so the base always starts right after the snapshot header. */
|
||||
size_t buffer_offset = globals_p->snapshot_buffer_write_offset - sizeof (jerry_snapshot_header_t);
|
||||
uint16_t start_offset = (uint16_t) (buffer_offset >> JMEM_ALIGNMENT_LOG);
|
||||
uint32_t start_offset = (uint32_t) (globals_p->snapshot_buffer_write_offset - sizeof (jerry_snapshot_header_t));
|
||||
|
||||
uint8_t *copied_code_start_p = snapshot_buffer_p + globals_p->snapshot_buffer_write_offset;
|
||||
ecma_compiled_code_t *copied_code_p = (ecma_compiled_code_t *) copied_code_start_p;
|
||||
@ -203,28 +202,24 @@ snapshot_add_compiled_code (ecma_compiled_code_t *compiled_code_p, /**< compiled
|
||||
}
|
||||
|
||||
/* Sub-functions and regular expressions are stored recursively. */
|
||||
uint8_t *src_buffer_p = (uint8_t *) compiled_code_p;
|
||||
uint8_t *dst_buffer_p = (uint8_t *) copied_code_p;
|
||||
ecma_value_t *src_literal_start_p;
|
||||
ecma_value_t *dst_literal_start_p;
|
||||
uint8_t *buffer_p = (uint8_t *) copied_code_p;
|
||||
ecma_value_t *literal_start_p;
|
||||
uint32_t const_literal_end;
|
||||
uint32_t literal_end;
|
||||
|
||||
if (compiled_code_p->status_flags & CBC_CODE_FLAGS_UINT16_ARGUMENTS)
|
||||
{
|
||||
src_literal_start_p = (ecma_value_t *) (src_buffer_p + sizeof (cbc_uint16_arguments_t));
|
||||
dst_literal_start_p = (ecma_value_t *) (dst_buffer_p + sizeof (cbc_uint16_arguments_t));
|
||||
literal_start_p = (ecma_value_t *) (buffer_p + sizeof (cbc_uint16_arguments_t));
|
||||
|
||||
cbc_uint16_arguments_t *args_p = (cbc_uint16_arguments_t *) src_buffer_p;
|
||||
cbc_uint16_arguments_t *args_p = (cbc_uint16_arguments_t *) buffer_p;
|
||||
literal_end = (uint32_t) (args_p->literal_end - args_p->register_end);
|
||||
const_literal_end = (uint32_t) (args_p->const_literal_end - args_p->register_end);
|
||||
}
|
||||
else
|
||||
{
|
||||
src_literal_start_p = (ecma_value_t *) (src_buffer_p + sizeof (cbc_uint8_arguments_t));
|
||||
dst_literal_start_p = (ecma_value_t *) (dst_buffer_p + sizeof (cbc_uint8_arguments_t));
|
||||
literal_start_p = (ecma_value_t *) (buffer_p + sizeof (cbc_uint8_arguments_t));
|
||||
|
||||
cbc_uint8_arguments_t *args_p = (cbc_uint8_arguments_t *) src_buffer_p;
|
||||
cbc_uint8_arguments_t *args_p = (cbc_uint8_arguments_t *) buffer_p;
|
||||
literal_end = (uint32_t) (args_p->literal_end - args_p->register_end);
|
||||
const_literal_end = (uint32_t) (args_p->const_literal_end - args_p->register_end);
|
||||
}
|
||||
@ -232,24 +227,154 @@ snapshot_add_compiled_code (ecma_compiled_code_t *compiled_code_p, /**< compiled
|
||||
for (uint32_t i = const_literal_end; i < literal_end; i++)
|
||||
{
|
||||
ecma_compiled_code_t *bytecode_p = ECMA_GET_INTERNAL_VALUE_POINTER (ecma_compiled_code_t,
|
||||
src_literal_start_p[i]);
|
||||
literal_start_p[i]);
|
||||
|
||||
if (bytecode_p == compiled_code_p)
|
||||
{
|
||||
dst_literal_start_p[i] = start_offset;
|
||||
literal_start_p[i] = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
dst_literal_start_p[i] = snapshot_add_compiled_code (bytecode_p,
|
||||
snapshot_buffer_p,
|
||||
snapshot_buffer_size,
|
||||
globals_p);
|
||||
uint32_t offset = snapshot_add_compiled_code (bytecode_p,
|
||||
snapshot_buffer_p,
|
||||
snapshot_buffer_size,
|
||||
globals_p);
|
||||
|
||||
JERRY_ASSERT (globals_p->snapshot_error_occured || offset > start_offset);
|
||||
|
||||
literal_start_p[i] = offset - start_offset;
|
||||
}
|
||||
}
|
||||
|
||||
return start_offset;
|
||||
} /* snapshot_add_compiled_code */
|
||||
|
||||
/**
|
||||
* Save static snapshot helper.
|
||||
*
|
||||
* @return start offset
|
||||
*/
|
||||
static uint32_t
|
||||
static_snapshot_add_compiled_code (ecma_compiled_code_t *compiled_code_p, /**< compiled code */
|
||||
uint8_t *snapshot_buffer_p, /**< snapshot buffer */
|
||||
size_t snapshot_buffer_size, /**< snapshot buffer size */
|
||||
snapshot_globals_t *globals_p) /**< snapshot globals */
|
||||
{
|
||||
if (globals_p->snapshot_error_occured)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
JERRY_ASSERT ((globals_p->snapshot_buffer_write_offset & (JMEM_ALIGNMENT - 1)) == 0);
|
||||
|
||||
if (globals_p->snapshot_buffer_write_offset >= UINT32_MAX)
|
||||
{
|
||||
globals_p->snapshot_error_occured = true;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* The snapshot generator always parses a single file,
|
||||
* so the base always starts right after the snapshot header. */
|
||||
uint32_t start_offset = (uint32_t) (globals_p->snapshot_buffer_write_offset - sizeof (jerry_snapshot_header_t));
|
||||
|
||||
uint8_t *copied_code_start_p = snapshot_buffer_p + globals_p->snapshot_buffer_write_offset;
|
||||
ecma_compiled_code_t *copied_code_p = (ecma_compiled_code_t *) copied_code_start_p;
|
||||
|
||||
if (!(compiled_code_p->status_flags & CBC_CODE_FLAGS_FUNCTION))
|
||||
{
|
||||
/* Regular expression literals are not supported. */
|
||||
globals_p->snapshot_error_occured = true;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!snapshot_write_to_buffer_by_offset (snapshot_buffer_p,
|
||||
snapshot_buffer_size,
|
||||
&globals_p->snapshot_buffer_write_offset,
|
||||
compiled_code_p,
|
||||
((size_t) compiled_code_p->size) << JMEM_ALIGNMENT_LOG))
|
||||
{
|
||||
globals_p->snapshot_error_occured = true;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Sub-functions and regular expressions are stored recursively. */
|
||||
uint8_t *buffer_p = (uint8_t *) copied_code_p;
|
||||
ecma_value_t *literal_start_p;
|
||||
uint32_t argument_end;
|
||||
uint32_t const_literal_end;
|
||||
uint32_t literal_end;
|
||||
|
||||
((ecma_compiled_code_t *) copied_code_p)->status_flags |= CBC_CODE_FLAGS_STATIC_FUNCTION;
|
||||
|
||||
if (compiled_code_p->status_flags & CBC_CODE_FLAGS_UINT16_ARGUMENTS)
|
||||
{
|
||||
literal_start_p = (ecma_value_t *) (buffer_p + sizeof (cbc_uint16_arguments_t));
|
||||
|
||||
cbc_uint16_arguments_t *args_p = (cbc_uint16_arguments_t *) buffer_p;
|
||||
argument_end = args_p->argument_end;
|
||||
literal_end = (uint32_t) (args_p->literal_end - args_p->register_end);
|
||||
const_literal_end = (uint32_t) (args_p->const_literal_end - args_p->register_end);
|
||||
}
|
||||
else
|
||||
{
|
||||
literal_start_p = (ecma_value_t *) (buffer_p + sizeof (cbc_uint8_arguments_t));
|
||||
|
||||
cbc_uint8_arguments_t *args_p = (cbc_uint8_arguments_t *) buffer_p;
|
||||
argument_end = args_p->argument_end;
|
||||
literal_end = (uint32_t) (args_p->literal_end - args_p->register_end);
|
||||
const_literal_end = (uint32_t) (args_p->const_literal_end - args_p->register_end);
|
||||
}
|
||||
|
||||
for (uint32_t i = 0; i < const_literal_end; i++)
|
||||
{
|
||||
if (!ecma_is_value_direct (literal_start_p[i])
|
||||
&& !ecma_is_value_direct_string (literal_start_p[i]))
|
||||
{
|
||||
globals_p->snapshot_error_occured = true;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
for (uint32_t i = const_literal_end; i < literal_end; i++)
|
||||
{
|
||||
ecma_compiled_code_t *bytecode_p = ECMA_GET_INTERNAL_VALUE_POINTER (ecma_compiled_code_t,
|
||||
literal_start_p[i]);
|
||||
|
||||
if (bytecode_p == compiled_code_p)
|
||||
{
|
||||
literal_start_p[i] = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
uint32_t offset = static_snapshot_add_compiled_code (bytecode_p,
|
||||
snapshot_buffer_p,
|
||||
snapshot_buffer_size,
|
||||
globals_p);
|
||||
|
||||
JERRY_ASSERT (globals_p->snapshot_error_occured || offset > start_offset);
|
||||
|
||||
literal_start_p[i] = offset - start_offset;
|
||||
}
|
||||
}
|
||||
|
||||
if (compiled_code_p->status_flags & CBC_CODE_FLAGS_NON_STRICT_ARGUMENTS_NEEDED)
|
||||
{
|
||||
buffer_p += ((size_t) compiled_code_p->size) << JMEM_ALIGNMENT_LOG;
|
||||
literal_start_p = ((ecma_value_t *) buffer_p) - argument_end;
|
||||
|
||||
for (uint32_t i = 0; i < argument_end; i++)
|
||||
{
|
||||
if (!ecma_is_value_direct_string (literal_start_p[i]))
|
||||
{
|
||||
globals_p->snapshot_error_occured = true;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return start_offset;
|
||||
} /* static_snapshot_add_compiled_code */
|
||||
|
||||
/**
|
||||
* Set the uint16_t offsets in the code area.
|
||||
*/
|
||||
@ -358,11 +483,10 @@ jerry_snapshot_set_offsets (uint32_t *buffer_p, /**< buffer */
|
||||
static ecma_compiled_code_t *
|
||||
snapshot_load_compiled_code (const uint8_t *base_addr_p, /**< base address of the
|
||||
* current primary function */
|
||||
size_t offset, /**< byte code offset */
|
||||
const uint8_t *literal_base_p, /**< literal start */
|
||||
bool copy_bytecode) /**< byte code should be copied to memory */
|
||||
{
|
||||
ecma_compiled_code_t *bytecode_p = (ecma_compiled_code_t *) (base_addr_p + offset);
|
||||
ecma_compiled_code_t *bytecode_p = (ecma_compiled_code_t *) base_addr_p;
|
||||
uint32_t code_size = ((uint32_t) bytecode_p->size) << JMEM_ALIGNMENT_LOG;
|
||||
|
||||
if (!(bytecode_p->status_flags & CBC_CODE_FLAGS_FUNCTION))
|
||||
@ -431,7 +555,7 @@ snapshot_load_compiled_code (const uint8_t *base_addr_p, /**< base address of th
|
||||
jmem_stats_allocate_byte_code_bytes (code_size);
|
||||
#endif /* JMEM_STATS */
|
||||
|
||||
memcpy (bytecode_p, base_addr_p + offset, code_size);
|
||||
memcpy (bytecode_p, base_addr_p, code_size);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -453,7 +577,7 @@ snapshot_load_compiled_code (const uint8_t *base_addr_p, /**< base address of th
|
||||
jmem_stats_allocate_byte_code_bytes (new_code_size);
|
||||
#endif /* JMEM_STATS */
|
||||
|
||||
memcpy (bytecode_p, base_addr_p + offset, start_offset);
|
||||
memcpy (bytecode_p, base_addr_p, start_offset);
|
||||
|
||||
bytecode_p->size = (uint16_t) (new_code_size >> JMEM_ALIGNMENT_LOG);
|
||||
|
||||
@ -463,7 +587,7 @@ snapshot_load_compiled_code (const uint8_t *base_addr_p, /**< base address of th
|
||||
{
|
||||
uint32_t argument_size = (uint32_t) (argument_end * sizeof (ecma_value_t));
|
||||
memcpy (byte_p + new_code_size - argument_size,
|
||||
base_addr_p + offset + code_size - argument_size,
|
||||
base_addr_p + code_size - argument_size,
|
||||
argument_size);
|
||||
}
|
||||
|
||||
@ -491,9 +615,9 @@ snapshot_load_compiled_code (const uint8_t *base_addr_p, /**< base address of th
|
||||
|
||||
for (uint32_t i = const_literal_end; i < literal_end; i++)
|
||||
{
|
||||
size_t literal_offset = ((size_t) literal_start_p[i]) << JMEM_ALIGNMENT_LOG;
|
||||
size_t literal_offset = (size_t) literal_start_p[i];
|
||||
|
||||
if (literal_offset == offset)
|
||||
if (literal_offset == 0)
|
||||
{
|
||||
/* Self reference */
|
||||
ECMA_SET_INTERNAL_VALUE_POINTER (literal_start_p[i],
|
||||
@ -502,8 +626,7 @@ snapshot_load_compiled_code (const uint8_t *base_addr_p, /**< base address of th
|
||||
else
|
||||
{
|
||||
ecma_compiled_code_t *literal_bytecode_p;
|
||||
literal_bytecode_p = snapshot_load_compiled_code (base_addr_p,
|
||||
literal_offset,
|
||||
literal_bytecode_p = snapshot_load_compiled_code (base_addr_p + literal_offset,
|
||||
literal_base_p,
|
||||
copy_bytecode);
|
||||
|
||||
@ -532,6 +655,17 @@ snapshot_load_compiled_code (const uint8_t *base_addr_p, /**< base address of th
|
||||
#endif /* JERRY_ENABLE_SNAPSHOT_EXEC */
|
||||
|
||||
#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
|
||||
*
|
||||
@ -545,9 +679,7 @@ jerry_parse_and_save_snapshot_with_args (const jerry_char_t *source_p, /**< scri
|
||||
size_t source_size, /**< script source size */
|
||||
const jerry_char_t *args_p, /**< arguments string */
|
||||
size_t args_size, /**< arguments string size */
|
||||
bool is_for_global, /**< snapshot would be executed as global (true)
|
||||
* or eval (false) */
|
||||
bool is_strict, /**< strict mode */
|
||||
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 */
|
||||
{
|
||||
@ -565,7 +697,7 @@ jerry_parse_and_save_snapshot_with_args (const jerry_char_t *source_p, /**< scri
|
||||
args_size,
|
||||
source_p,
|
||||
source_size,
|
||||
is_strict,
|
||||
(flags & JERRY_SNAPSHOT_SAVE_STRICT) != 0,
|
||||
&bytecode_data_p);
|
||||
|
||||
if (ECMA_IS_VALUE_ERROR (parse_status))
|
||||
@ -574,7 +706,14 @@ jerry_parse_and_save_snapshot_with_args (const jerry_char_t *source_p, /**< scri
|
||||
return 0;
|
||||
}
|
||||
|
||||
snapshot_add_compiled_code (bytecode_data_p, (uint8_t *) buffer_p, buffer_size, &globals);
|
||||
if (flags & JERRY_SNAPSHOT_SAVE_STATIC)
|
||||
{
|
||||
static_snapshot_add_compiled_code (bytecode_data_p, (uint8_t *) buffer_p, buffer_size, &globals);
|
||||
}
|
||||
else
|
||||
{
|
||||
snapshot_add_compiled_code (bytecode_data_p, (uint8_t *) buffer_p, buffer_size, &globals);
|
||||
}
|
||||
|
||||
if (globals.snapshot_error_occured)
|
||||
{
|
||||
@ -589,32 +728,35 @@ 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 (!is_for_global)
|
||||
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;
|
||||
uint32_t literals_num = 0;
|
||||
|
||||
ecma_collection_header_t *lit_pool_p = ecma_new_values_collection ();
|
||||
|
||||
ecma_save_literals_add_compiled_code (bytecode_data_p, lit_pool_p);
|
||||
|
||||
if (!ecma_save_literals_for_snapshot (lit_pool_p,
|
||||
buffer_p,
|
||||
buffer_size,
|
||||
&globals.snapshot_buffer_write_offset,
|
||||
&lit_map_p,
|
||||
&literals_num))
|
||||
if (!(flags & JERRY_SNAPSHOT_SAVE_STATIC))
|
||||
{
|
||||
JERRY_ASSERT (lit_map_p == NULL);
|
||||
return 0;
|
||||
}
|
||||
ecma_collection_header_t *lit_pool_p = ecma_new_values_collection ();
|
||||
|
||||
jerry_snapshot_set_offsets (buffer_p + (aligned_header_size / sizeof (uint32_t)),
|
||||
(uint32_t) (header.lit_table_offset - aligned_header_size),
|
||||
lit_map_p);
|
||||
ecma_save_literals_add_compiled_code (bytecode_data_p, lit_pool_p);
|
||||
|
||||
if (!ecma_save_literals_for_snapshot (lit_pool_p,
|
||||
buffer_p,
|
||||
buffer_size,
|
||||
&globals.snapshot_buffer_write_offset,
|
||||
&lit_map_p,
|
||||
&literals_num))
|
||||
{
|
||||
JERRY_ASSERT (lit_map_p == NULL);
|
||||
return 0;
|
||||
}
|
||||
|
||||
jerry_snapshot_set_offsets (buffer_p + (aligned_header_size / sizeof (uint32_t)),
|
||||
(uint32_t) (header.lit_table_offset - aligned_header_size),
|
||||
lit_map_p);
|
||||
}
|
||||
|
||||
size_t header_offset = 0;
|
||||
|
||||
@ -633,6 +775,7 @@ jerry_parse_and_save_snapshot_with_args (const jerry_char_t *source_p, /**< scri
|
||||
|
||||
return globals.snapshot_buffer_write_offset;
|
||||
} /* jerry_parse_and_save_snapshot_with_args */
|
||||
|
||||
#endif /* JERRY_ENABLE_SNAPSHOT_SAVE */
|
||||
|
||||
/**
|
||||
@ -653,12 +796,14 @@ jerry_parse_and_save_snapshot (const jerry_char_t *source_p, /**< script source
|
||||
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);
|
||||
|
||||
return jerry_parse_and_save_snapshot_with_args (source_p,
|
||||
source_size,
|
||||
NULL,
|
||||
0,
|
||||
is_for_global,
|
||||
is_strict,
|
||||
flags,
|
||||
buffer_p,
|
||||
buffer_size);
|
||||
#else /* !JERRY_ENABLE_SNAPSHOT_SAVE */
|
||||
@ -673,6 +818,48 @@ jerry_parse_and_save_snapshot (const jerry_char_t *source_p, /**< script source
|
||||
#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 */
|
||||
|
||||
#ifdef JERRY_ENABLE_SNAPSHOT_EXEC
|
||||
/**
|
||||
* Execute/load snapshot from specified buffer
|
||||
@ -731,18 +918,29 @@ jerry_snapshot_result_at (const uint32_t *snapshot_p, /**< snapshot */
|
||||
|
||||
JERRY_ASSERT ((header_p->lit_table_offset % sizeof (uint32_t)) == 0);
|
||||
|
||||
const uint8_t *literal_base_p = (uint8_t *) (snapshot_data_p + header_p->lit_table_offset);
|
||||
ecma_compiled_code_t *bytecode_p;
|
||||
|
||||
uint32_t func_offset = header_p->func_offsets[func_index] & ~JERRY_SNAPSHOT_EVAL_CONTEXT;
|
||||
bytecode_p = snapshot_load_compiled_code (snapshot_data_p + func_offset,
|
||||
0,
|
||||
literal_base_p,
|
||||
copy_bytecode);
|
||||
ecma_compiled_code_t *bytecode_p = (ecma_compiled_code_t *) (snapshot_data_p + func_offset);
|
||||
|
||||
if (bytecode_p == NULL)
|
||||
if (bytecode_p->status_flags & CBC_CODE_FLAGS_STATIC_FUNCTION)
|
||||
{
|
||||
return ecma_raise_type_error (invalid_format_error_p);
|
||||
if (copy_bytecode)
|
||||
{
|
||||
ecma_raise_common_error (ECMA_ERR_MSG ("Static snapshots cannot be copied into memory"));
|
||||
return ecma_create_error_reference_from_context ();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
const uint8_t *literal_base_p = (uint8_t *) (snapshot_data_p + header_p->lit_table_offset);
|
||||
|
||||
bytecode_p = snapshot_load_compiled_code ((const uint8_t *) bytecode_p,
|
||||
literal_base_p,
|
||||
copy_bytecode);
|
||||
|
||||
if (bytecode_p == NULL)
|
||||
{
|
||||
return ecma_raise_type_error (invalid_format_error_p);
|
||||
}
|
||||
}
|
||||
|
||||
ecma_value_t ret_val;
|
||||
@ -752,8 +950,11 @@ jerry_snapshot_result_at (const uint32_t *snapshot_p, /**< snapshot */
|
||||
ecma_object_t *lex_env_p = ecma_get_global_environment ();
|
||||
ecma_object_t *func_obj_p = ecma_op_create_function_object (lex_env_p,
|
||||
bytecode_p);
|
||||
ecma_bytecode_deref (bytecode_p);
|
||||
|
||||
if (!(bytecode_p->status_flags & CBC_CODE_FLAGS_STATIC_FUNCTION))
|
||||
{
|
||||
ecma_bytecode_deref (bytecode_p);
|
||||
}
|
||||
ret_val = ecma_make_object_value (func_obj_p);
|
||||
}
|
||||
else if (header_p->func_offsets[func_index] & JERRY_SNAPSHOT_EVAL_CONTEXT)
|
||||
@ -763,7 +964,10 @@ jerry_snapshot_result_at (const uint32_t *snapshot_p, /**< snapshot */
|
||||
else
|
||||
{
|
||||
ret_val = vm_run_global (bytecode_p);
|
||||
ecma_bytecode_deref (bytecode_p);
|
||||
if (!(bytecode_p->status_flags & CBC_CODE_FLAGS_STATIC_FUNCTION))
|
||||
{
|
||||
ecma_bytecode_deref (bytecode_p);
|
||||
}
|
||||
}
|
||||
|
||||
if (ECMA_IS_VALUE_ERROR (ret_val))
|
||||
@ -861,7 +1065,8 @@ scan_snapshot_functions (const uint8_t *buffer_p, /**< snapshot buffer start */
|
||||
ecma_compiled_code_t *bytecode_p = (ecma_compiled_code_t *) buffer_p;
|
||||
uint32_t code_size = ((uint32_t) bytecode_p->size) << JMEM_ALIGNMENT_LOG;
|
||||
|
||||
if (bytecode_p->status_flags & CBC_CODE_FLAGS_FUNCTION)
|
||||
if ((bytecode_p->status_flags & CBC_CODE_FLAGS_FUNCTION)
|
||||
&& !(bytecode_p->status_flags & CBC_CODE_FLAGS_STATIC_FUNCTION))
|
||||
{
|
||||
ecma_value_t *literal_start_p;
|
||||
uint32_t argument_end;
|
||||
@ -932,7 +1137,8 @@ update_literal_offsets (uint8_t *buffer_p, /**< snapshot buffer start */
|
||||
ecma_compiled_code_t *bytecode_p = (ecma_compiled_code_t *) buffer_p;
|
||||
uint32_t code_size = ((uint32_t) bytecode_p->size) << JMEM_ALIGNMENT_LOG;
|
||||
|
||||
if (bytecode_p->status_flags & CBC_CODE_FLAGS_FUNCTION)
|
||||
if ((bytecode_p->status_flags & CBC_CODE_FLAGS_FUNCTION)
|
||||
&& !(bytecode_p->status_flags & CBC_CODE_FLAGS_STATIC_FUNCTION))
|
||||
{
|
||||
ecma_value_t *literal_start_p;
|
||||
uint32_t argument_end;
|
||||
@ -1574,6 +1780,14 @@ jerry_parse_and_save_literals (const jerry_char_t *source_p, /**< script source
|
||||
#endif /* JERRY_ENABLE_SNAPSHOT_SAVE */
|
||||
} /* jerry_parse_and_save_literals */
|
||||
|
||||
/**
|
||||
* Generate snapshot from specified function source
|
||||
*
|
||||
* @return 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.
|
||||
*/
|
||||
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 */
|
||||
@ -1583,12 +1797,13 @@ size_t jerry_parse_and_save_function_snapshot (const jerry_char_t *source_p, /**
|
||||
size_t buffer_size) /**< the buffer's size */
|
||||
{
|
||||
#ifdef JERRY_ENABLE_SNAPSHOT_SAVE
|
||||
uint32_t flags = (is_strict ? JERRY_SNAPSHOT_SAVE_STRICT : 0);
|
||||
|
||||
return jerry_parse_and_save_snapshot_with_args (source_p,
|
||||
source_size,
|
||||
args_p,
|
||||
args_size,
|
||||
true,
|
||||
is_strict,
|
||||
flags,
|
||||
buffer_p,
|
||||
buffer_size);
|
||||
#else /* !JERRY_ENABLE_SNAPSHOT_SAVE */
|
||||
@ -1604,6 +1819,56 @@ size_t jerry_parse_and_save_function_snapshot (const jerry_char_t *source_p, /**
|
||||
#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 */
|
||||
|
||||
/**
|
||||
* Load function from specified snapshot 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_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 */
|
||||
|
||||
@ -46,7 +46,7 @@ typedef struct
|
||||
/**
|
||||
* Jerry snapshot format version.
|
||||
*/
|
||||
#define JERRY_SNAPSHOT_VERSION (9u)
|
||||
#define JERRY_SNAPSHOT_VERSION (10u)
|
||||
|
||||
/**
|
||||
* Snapshot configuration flags.
|
||||
|
||||
@ -558,11 +558,7 @@ jerry_run (const jerry_value_t func_val) /**< function to run */
|
||||
return jerry_throw (ecma_raise_type_error (ECMA_ERR_MSG (wrong_args_msg_p)));
|
||||
}
|
||||
|
||||
const ecma_compiled_code_t *bytecode_data_p;
|
||||
bytecode_data_p = ECMA_GET_INTERNAL_VALUE_POINTER (const ecma_compiled_code_t,
|
||||
ext_func_p->u.function.bytecode_cp);
|
||||
|
||||
return jerry_return (vm_run_global (bytecode_data_p));
|
||||
return jerry_return (vm_run_global (ecma_op_function_get_compiled_code (ext_func_p)));
|
||||
} /* jerry_run */
|
||||
|
||||
/**
|
||||
|
||||
@ -631,10 +631,22 @@ ecma_gc_free_object (ecma_object_t *object_p) /**< object to free */
|
||||
/* Function with byte-code (not a built-in function). */
|
||||
ecma_extended_object_t *ext_func_p = (ecma_extended_object_t *) object_p;
|
||||
|
||||
#ifdef JERRY_ENABLE_SNAPSHOT_EXEC
|
||||
if (ext_func_p->u.function.bytecode_cp != ECMA_NULL_POINTER)
|
||||
{
|
||||
ecma_bytecode_deref (ECMA_GET_INTERNAL_VALUE_POINTER (ecma_compiled_code_t,
|
||||
ext_func_p->u.function.bytecode_cp));
|
||||
ecma_dealloc_extended_object (object_p, sizeof (ecma_extended_object_t));
|
||||
}
|
||||
else
|
||||
{
|
||||
ecma_dealloc_extended_object (object_p, sizeof (ecma_static_function_t));
|
||||
}
|
||||
#else /* !JERRY_ENABLE_SNAPSHOT_EXEC */
|
||||
ecma_bytecode_deref (ECMA_GET_INTERNAL_VALUE_POINTER (ecma_compiled_code_t,
|
||||
ext_func_p->u.function.bytecode_cp));
|
||||
|
||||
ecma_dealloc_extended_object (object_p, sizeof (ecma_extended_object_t));
|
||||
#endif /* JERRY_ENABLE_SNAPSHOT_EXEC */
|
||||
return;
|
||||
}
|
||||
|
||||
@ -643,12 +655,24 @@ ecma_gc_free_object (ecma_object_t *object_p) /**< object to free */
|
||||
{
|
||||
ecma_arrow_function_t *arrow_func_p = (ecma_arrow_function_t *) object_p;
|
||||
|
||||
ecma_bytecode_deref (ECMA_GET_NON_NULL_POINTER (ecma_compiled_code_t,
|
||||
arrow_func_p->bytecode_cp));
|
||||
|
||||
ecma_free_value_if_not_object (arrow_func_p->this_binding);
|
||||
|
||||
#ifdef JERRY_ENABLE_SNAPSHOT_EXEC
|
||||
if (arrow_func_p->bytecode_cp != ECMA_NULL_POINTER)
|
||||
{
|
||||
ecma_bytecode_deref (ECMA_GET_NON_NULL_POINTER (ecma_compiled_code_t,
|
||||
arrow_func_p->bytecode_cp));
|
||||
ecma_dealloc_extended_object (object_p, sizeof (ecma_arrow_function_t));
|
||||
}
|
||||
else
|
||||
{
|
||||
ecma_dealloc_extended_object (object_p, sizeof (ecma_static_arrow_function_t));
|
||||
}
|
||||
#else /* !JERRY_ENABLE_SNAPSHOT_EXEC */
|
||||
ecma_bytecode_deref (ECMA_GET_NON_NULL_POINTER (ecma_compiled_code_t,
|
||||
arrow_func_p->bytecode_cp));
|
||||
ecma_dealloc_extended_object (object_p, sizeof (ecma_arrow_function_t));
|
||||
#endif /* JERRY_ENABLE_SNAPSHOT_EXEC */
|
||||
return;
|
||||
}
|
||||
#endif /* !CONFIG_DISABLE_ES2015_ARROW_FUNCTION */
|
||||
|
||||
@ -797,6 +797,33 @@ typedef struct
|
||||
ecma_built_in_props_t built_in; /**< built-in object part */
|
||||
} ecma_extended_built_in_object_t;
|
||||
|
||||
/**
|
||||
* Compiled byte code data.
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
uint16_t size; /**< real size >> JMEM_ALIGNMENT_LOG */
|
||||
uint16_t refs; /**< reference counter for the byte code */
|
||||
uint16_t status_flags; /**< various status flags:
|
||||
* CBC_CODE_FLAGS_FUNCTION flag tells whether
|
||||
* the byte code is function or regular expression.
|
||||
* If function, the other flags must be CBC_CODE_FLAGS...
|
||||
* If regexp, the other flags must be RE_FLAG... */
|
||||
} ecma_compiled_code_t;
|
||||
|
||||
#ifdef JERRY_ENABLE_SNAPSHOT_EXEC
|
||||
|
||||
/**
|
||||
* Description of static function objects.
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
ecma_extended_object_t header;
|
||||
const ecma_compiled_code_t *bytecode_p;
|
||||
} ecma_static_function_t;
|
||||
|
||||
#endif /* JERRY_ENABLE_SNAPSHOT_EXEC */
|
||||
|
||||
#ifndef CONFIG_DISABLE_ES2015_ARROW_FUNCTION
|
||||
|
||||
/**
|
||||
@ -810,6 +837,19 @@ typedef struct
|
||||
jmem_cpointer_t bytecode_cp; /**< function byte code */
|
||||
} ecma_arrow_function_t;
|
||||
|
||||
#ifdef JERRY_ENABLE_SNAPSHOT_EXEC
|
||||
|
||||
/**
|
||||
* Description of static arrow function objects.
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
ecma_arrow_function_t header;
|
||||
const ecma_compiled_code_t *bytecode_p;
|
||||
} ecma_static_arrow_function_t;
|
||||
|
||||
#endif /* JERRY_ENABLE_SNAPSHOT_EXEC */
|
||||
|
||||
#endif /* !CONFIG_DISABLE_ES2015_ARROW_FUNCTION */
|
||||
|
||||
/**
|
||||
@ -1276,20 +1316,6 @@ typedef struct
|
||||
ecma_value_t value; /**< referenced value */
|
||||
} ecma_error_reference_t;
|
||||
|
||||
/**
|
||||
* Compiled byte code data.
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
uint16_t size; /**< real size >> JMEM_ALIGNMENT_LOG */
|
||||
uint16_t refs; /**< reference counter for the byte code */
|
||||
uint16_t status_flags; /**< various status flags:
|
||||
* CBC_CODE_FLAGS_FUNCTION flag tells whether
|
||||
* the byte code is function or regular expression.
|
||||
* If function, the other flags must be CBC_CODE_FLAGS...
|
||||
* If regexp, the other flags must be RE_FLAG... */
|
||||
} ecma_compiled_code_t;
|
||||
|
||||
#ifndef CONFIG_ECMA_PROPERTY_HASHMAP_DISABLE
|
||||
|
||||
/**
|
||||
|
||||
@ -311,6 +311,18 @@ ecma_is_value_string (ecma_value_t value) /**< ecma value */
|
||||
return ((value & (ECMA_VALUE_TYPE_MASK - 0x4)) == ECMA_TYPE_STRING);
|
||||
} /* ecma_is_value_string */
|
||||
|
||||
/**
|
||||
* Check if the value is direct_ecma-string.
|
||||
*
|
||||
* @return true - if the value contains ecma-string value,
|
||||
* false - otherwise
|
||||
*/
|
||||
inline bool __attr_const___ __attr_always_inline___
|
||||
ecma_is_value_direct_string (ecma_value_t value) /**< ecma value */
|
||||
{
|
||||
return (ecma_get_value_type_field (value) == ECMA_TYPE_DIRECT_STRING);
|
||||
} /* ecma_is_value_direct_string */
|
||||
|
||||
/**
|
||||
* Check if the value is object.
|
||||
*
|
||||
|
||||
@ -1487,6 +1487,7 @@ void
|
||||
ecma_bytecode_deref (ecma_compiled_code_t *bytecode_p) /**< byte code pointer */
|
||||
{
|
||||
JERRY_ASSERT (bytecode_p->refs > 0);
|
||||
JERRY_ASSERT (!(bytecode_p->status_flags & CBC_CODE_FLAGS_STATIC_FUNCTION));
|
||||
|
||||
bytecode_p->refs--;
|
||||
|
||||
|
||||
@ -154,6 +154,7 @@ bool ecma_are_values_integer_numbers (ecma_value_t first_value, ecma_value_t sec
|
||||
bool ecma_is_value_float_number (ecma_value_t value) __attr_const___;
|
||||
bool ecma_is_value_number (ecma_value_t value) __attr_const___;
|
||||
bool ecma_is_value_string (ecma_value_t value) __attr_const___;
|
||||
bool ecma_is_value_direct_string (ecma_value_t value) __attr_const___;
|
||||
bool ecma_is_value_object (ecma_value_t value) __attr_const___;
|
||||
bool ecma_is_value_error_reference (ecma_value_t value) __attr_const___;
|
||||
bool ecma_is_value_collection_chunk (ecma_value_t value) __attr_const___;
|
||||
|
||||
@ -124,8 +124,17 @@ ecma_op_create_function_object (ecma_object_t *scope_p, /**< function's scope */
|
||||
/* 1., 4., 13. */
|
||||
ecma_object_t *prototype_obj_p = ecma_builtin_get (ECMA_BUILTIN_ID_FUNCTION_PROTOTYPE);
|
||||
|
||||
size_t function_object_size = sizeof (ecma_extended_object_t);
|
||||
|
||||
#ifdef JERRY_ENABLE_SNAPSHOT_EXEC
|
||||
if (bytecode_data_p->status_flags & CBC_CODE_FLAGS_STATIC_FUNCTION)
|
||||
{
|
||||
function_object_size = sizeof (ecma_static_function_t);
|
||||
}
|
||||
#endif
|
||||
|
||||
ecma_object_t *func_p = ecma_create_object (prototype_obj_p,
|
||||
sizeof (ecma_extended_object_t),
|
||||
function_object_size,
|
||||
ECMA_OBJECT_TYPE_FUNCTION);
|
||||
|
||||
ecma_deref_object (prototype_obj_p);
|
||||
@ -150,8 +159,22 @@ ecma_op_create_function_object (ecma_object_t *scope_p, /**< function's scope */
|
||||
ECMA_SET_INTERNAL_VALUE_POINTER (ext_func_p->u.function.scope_cp, scope_p);
|
||||
|
||||
/* 10., 11., 12. */
|
||||
|
||||
#ifdef JERRY_ENABLE_SNAPSHOT_EXEC
|
||||
if (!(bytecode_data_p->status_flags & CBC_CODE_FLAGS_STATIC_FUNCTION))
|
||||
{
|
||||
ECMA_SET_INTERNAL_VALUE_POINTER (ext_func_p->u.function.bytecode_cp, bytecode_data_p);
|
||||
ecma_bytecode_ref ((ecma_compiled_code_t *) bytecode_data_p);
|
||||
}
|
||||
else
|
||||
{
|
||||
ext_func_p->u.function.bytecode_cp = ECMA_NULL_POINTER;
|
||||
((ecma_static_function_t *) func_p)->bytecode_p = bytecode_data_p;
|
||||
}
|
||||
#else /* !JERRY_ENABLE_SNAPSHOT_EXEC */
|
||||
ECMA_SET_INTERNAL_VALUE_POINTER (ext_func_p->u.function.bytecode_cp, bytecode_data_p);
|
||||
ecma_bytecode_ref ((ecma_compiled_code_t *) bytecode_data_p);
|
||||
#endif
|
||||
|
||||
/* 14., 15., 16., 17., 18. */
|
||||
/*
|
||||
@ -179,8 +202,17 @@ ecma_op_create_arrow_function_object (ecma_object_t *scope_p, /**< function's sc
|
||||
{
|
||||
ecma_object_t *prototype_obj_p = ecma_builtin_get (ECMA_BUILTIN_ID_FUNCTION_PROTOTYPE);
|
||||
|
||||
size_t arrow_function_object_size = sizeof (ecma_arrow_function_t);
|
||||
|
||||
#ifdef JERRY_ENABLE_SNAPSHOT_EXEC
|
||||
if (bytecode_data_p->status_flags & CBC_CODE_FLAGS_STATIC_FUNCTION)
|
||||
{
|
||||
arrow_function_object_size = sizeof (ecma_static_arrow_function_t);
|
||||
}
|
||||
#endif
|
||||
|
||||
ecma_object_t *func_p = ecma_create_object (prototype_obj_p,
|
||||
sizeof (ecma_arrow_function_t),
|
||||
arrow_function_object_size,
|
||||
ECMA_OBJECT_TYPE_ARROW_FUNCTION);
|
||||
|
||||
ecma_deref_object (prototype_obj_p);
|
||||
@ -190,8 +222,21 @@ ecma_op_create_arrow_function_object (ecma_object_t *scope_p, /**< function's sc
|
||||
|
||||
ECMA_SET_NON_NULL_POINTER (arrow_func_p->scope_cp, scope_p);
|
||||
|
||||
#ifdef JERRY_ENABLE_SNAPSHOT_EXEC
|
||||
if (!(bytecode_data_p->status_flags & CBC_CODE_FLAGS_STATIC_FUNCTION))
|
||||
{
|
||||
ECMA_SET_NON_NULL_POINTER (arrow_func_p->bytecode_cp, bytecode_data_p);
|
||||
ecma_bytecode_ref ((ecma_compiled_code_t *) bytecode_data_p);
|
||||
}
|
||||
else
|
||||
{
|
||||
arrow_func_p->bytecode_cp = ECMA_NULL_POINTER;
|
||||
((ecma_static_arrow_function_t *) func_p)->bytecode_p = bytecode_data_p;
|
||||
}
|
||||
#else /* !JERRY_ENABLE_SNAPSHOT_EXEC */
|
||||
ECMA_SET_NON_NULL_POINTER (arrow_func_p->bytecode_cp, bytecode_data_p);
|
||||
ecma_bytecode_ref ((ecma_compiled_code_t *) bytecode_data_p);
|
||||
#endif
|
||||
|
||||
arrow_func_p->this_binding = ecma_copy_value_if_not_object (this_binding);
|
||||
return func_p;
|
||||
@ -232,6 +277,58 @@ ecma_op_create_external_function_object (ecma_external_handler_t handler_cb) /**
|
||||
return function_obj_p;
|
||||
} /* ecma_op_create_external_function_object */
|
||||
|
||||
/**
|
||||
* Get compiled code of a function object.
|
||||
*
|
||||
* @return compiled code
|
||||
*/
|
||||
inline const ecma_compiled_code_t * __attr_always_inline___
|
||||
ecma_op_function_get_compiled_code (ecma_extended_object_t *function_p) /**< function pointer */
|
||||
{
|
||||
#ifdef JERRY_ENABLE_SNAPSHOT_EXEC
|
||||
if (function_p->u.function.bytecode_cp != ECMA_NULL_POINTER)
|
||||
{
|
||||
return ECMA_GET_INTERNAL_VALUE_POINTER (const ecma_compiled_code_t,
|
||||
function_p->u.function.bytecode_cp);
|
||||
}
|
||||
else
|
||||
{
|
||||
return ((ecma_static_function_t *) function_p)->bytecode_p;
|
||||
}
|
||||
#else /* !JERRY_ENABLE_SNAPSHOT_EXEC */
|
||||
return ECMA_GET_INTERNAL_VALUE_POINTER (const ecma_compiled_code_t,
|
||||
function_p->u.function.bytecode_cp);
|
||||
#endif /* JERRY_ENABLE_SNAPSHOT_EXEC */
|
||||
} /* ecma_op_function_get_compiled_code */
|
||||
|
||||
#ifndef CONFIG_DISABLE_ES2015_ARROW_FUNCTION
|
||||
|
||||
/**
|
||||
* Get compiled code of an arrow function object.
|
||||
*
|
||||
* @return compiled code
|
||||
*/
|
||||
inline const ecma_compiled_code_t * __attr_always_inline___
|
||||
ecma_op_arrow_function_get_compiled_code (ecma_arrow_function_t *arrow_function_p) /**< arrow function pointer */
|
||||
{
|
||||
#ifdef JERRY_ENABLE_SNAPSHOT_EXEC
|
||||
if (arrow_function_p->bytecode_cp != ECMA_NULL_POINTER)
|
||||
{
|
||||
return ECMA_GET_NON_NULL_POINTER (const ecma_compiled_code_t,
|
||||
arrow_function_p->bytecode_cp);
|
||||
}
|
||||
else
|
||||
{
|
||||
return ((ecma_static_arrow_function_t *) arrow_function_p)->bytecode_p;
|
||||
}
|
||||
#else /* !JERRY_ENABLE_SNAPSHOT_EXEC */
|
||||
return ECMA_GET_NON_NULL_POINTER (const ecma_compiled_code_t,
|
||||
arrow_function_p->bytecode_cp);
|
||||
#endif /* JERRY_ENABLE_SNAPSHOT_EXEC */
|
||||
} /* ecma_op_arrow_function_get_compiled_code */
|
||||
|
||||
#endif /* !CONFIG_DISABLE_ES2015_ARROW_FUNCTION */
|
||||
|
||||
/**
|
||||
* [[Call]] implementation for Function objects,
|
||||
* created through 13.2 (ECMA_OBJECT_TYPE_FUNCTION)
|
||||
@ -357,9 +454,7 @@ ecma_op_function_call (ecma_object_t *func_obj_p, /**< Function object */
|
||||
bool is_strict;
|
||||
bool is_no_lex_env;
|
||||
|
||||
const ecma_compiled_code_t *bytecode_data_p;
|
||||
bytecode_data_p = ECMA_GET_INTERNAL_VALUE_POINTER (const ecma_compiled_code_t,
|
||||
ext_func_p->u.function.bytecode_cp);
|
||||
const ecma_compiled_code_t *bytecode_data_p = ecma_op_function_get_compiled_code (ext_func_p);
|
||||
|
||||
is_strict = (bytecode_data_p->status_flags & CBC_CODE_FLAGS_STRICT_MODE) ? true : false;
|
||||
is_no_lex_env = (bytecode_data_p->status_flags & CBC_CODE_FLAGS_LEXICAL_ENV_NOT_NEEDED) ? true : false;
|
||||
@ -428,9 +523,7 @@ ecma_op_function_call (ecma_object_t *func_obj_p, /**< Function object */
|
||||
|
||||
bool is_no_lex_env;
|
||||
|
||||
const ecma_compiled_code_t *bytecode_data_p;
|
||||
bytecode_data_p = ECMA_GET_NON_NULL_POINTER (const ecma_compiled_code_t,
|
||||
arrow_func_p->bytecode_cp);
|
||||
const ecma_compiled_code_t *bytecode_data_p = ecma_op_arrow_function_get_compiled_code (arrow_func_p);
|
||||
|
||||
is_no_lex_env = (bytecode_data_p->status_flags & CBC_CODE_FLAGS_LEXICAL_ENV_NOT_NEEDED) ? true : false;
|
||||
|
||||
@ -782,15 +875,13 @@ ecma_op_function_try_to_lazy_instantiate_property (ecma_object_t *object_p, /**<
|
||||
if (ecma_get_object_type (object_p) == ECMA_OBJECT_TYPE_ARROW_FUNCTION)
|
||||
{
|
||||
ecma_arrow_function_t *arrow_func_p = (ecma_arrow_function_t *) object_p;
|
||||
bytecode_data_p = ECMA_GET_NON_NULL_POINTER (const ecma_compiled_code_t,
|
||||
arrow_func_p->bytecode_cp);
|
||||
bytecode_data_p = ecma_op_arrow_function_get_compiled_code (arrow_func_p);
|
||||
}
|
||||
else
|
||||
{
|
||||
#endif /* CONFIG_DISABLE_ES2015_ARROW_FUNCTION */
|
||||
ecma_extended_object_t *ext_func_p = (ecma_extended_object_t *) object_p;
|
||||
bytecode_data_p = ECMA_GET_INTERNAL_VALUE_POINTER (const ecma_compiled_code_t,
|
||||
ext_func_p->u.function.bytecode_cp);
|
||||
bytecode_data_p = ecma_op_function_get_compiled_code (ext_func_p);
|
||||
#ifndef CONFIG_DISABLE_ES2015_ARROW_FUNCTION
|
||||
}
|
||||
#endif /* CONFIG_DISABLE_ES2015_ARROW_FUNCTION */
|
||||
@ -961,11 +1052,8 @@ ecma_op_function_list_lazy_property_names (ecma_object_t *object_p, /**< functio
|
||||
ecma_make_magic_string_value (LIT_MAGIC_STRING_PROTOTYPE),
|
||||
0);
|
||||
|
||||
ecma_extended_object_t *ext_func_p = (ecma_extended_object_t *) object_p;
|
||||
|
||||
const ecma_compiled_code_t *bytecode_data_p;
|
||||
bytecode_data_p = ECMA_GET_INTERNAL_VALUE_POINTER (const ecma_compiled_code_t,
|
||||
ext_func_p->u.function.bytecode_cp);
|
||||
bytecode_data_p = ecma_op_function_get_compiled_code ((ecma_extended_object_t *) object_p);
|
||||
|
||||
if (bytecode_data_p->status_flags & CBC_CODE_FLAGS_STRICT_MODE)
|
||||
{
|
||||
|
||||
@ -43,6 +43,17 @@ ecma_op_create_arrow_function_object (ecma_object_t *scope_p, const ecma_compile
|
||||
ecma_object_t *
|
||||
ecma_op_create_external_function_object (ecma_external_handler_t handler_cb);
|
||||
|
||||
const ecma_compiled_code_t *
|
||||
ecma_op_function_get_compiled_code (ecma_extended_object_t *function_p);
|
||||
|
||||
#ifndef CONFIG_DISABLE_ES2015_ARROW_FUNCTION
|
||||
const ecma_compiled_code_t *
|
||||
ecma_op_arrow_function_get_compiled_code (ecma_arrow_function_t *arrow_function_p);
|
||||
#endif /* !CONFIG_DISABLE_ES2015_ARROW_FUNCTION */
|
||||
|
||||
ecma_value_t
|
||||
ecma_op_function_has_instance (ecma_object_t *func_obj_p, ecma_value_t value);
|
||||
|
||||
ecma_value_t
|
||||
ecma_op_function_call (ecma_object_t *func_obj_p, ecma_value_t this_arg_value,
|
||||
const ecma_value_t *arguments_list_p, ecma_length_t arguments_list_len);
|
||||
@ -51,9 +62,6 @@ ecma_value_t
|
||||
ecma_op_function_construct (ecma_object_t *func_obj_p, const ecma_value_t *arguments_list_p,
|
||||
ecma_length_t arguments_list_len);
|
||||
|
||||
ecma_value_t
|
||||
ecma_op_function_has_instance (ecma_object_t *func_obj_p, ecma_value_t value);
|
||||
|
||||
ecma_property_t *
|
||||
ecma_op_function_try_to_lazy_instantiate_property (ecma_object_t *object_p, ecma_string_t *property_name_p);
|
||||
|
||||
|
||||
@ -208,19 +208,16 @@ ecma_op_object_get_own_property (ecma_object_t *object_p, /**< the object */
|
||||
if (type != ECMA_OBJECT_TYPE_ARROW_FUNCTION)
|
||||
{
|
||||
ecma_extended_object_t *ext_func_p = (ecma_extended_object_t *) object_p;
|
||||
bytecode_data_p = ECMA_GET_INTERNAL_VALUE_POINTER (const ecma_compiled_code_t,
|
||||
ext_func_p->u.function.bytecode_cp);
|
||||
bytecode_data_p = ecma_op_function_get_compiled_code (ext_func_p);
|
||||
}
|
||||
else
|
||||
{
|
||||
ecma_arrow_function_t *arrow_func_p = (ecma_arrow_function_t *) object_p;
|
||||
bytecode_data_p = ECMA_GET_NON_NULL_POINTER (const ecma_compiled_code_t,
|
||||
arrow_func_p->bytecode_cp);
|
||||
bytecode_data_p = ecma_op_arrow_function_get_compiled_code (arrow_func_p);
|
||||
}
|
||||
#else /* CONFIG_DISABLE_ES2015_ARROW_FUNCTION */
|
||||
ecma_extended_object_t *ext_func_p = (ecma_extended_object_t *) object_p;
|
||||
bytecode_data_p = ECMA_GET_INTERNAL_VALUE_POINTER (const ecma_compiled_code_t,
|
||||
ext_func_p->u.function.bytecode_cp);
|
||||
bytecode_data_p = ecma_op_function_get_compiled_code (ext_func_p);
|
||||
#endif /* !CONFIG_DISABLE_ES2015_ARROW_FUNCTION */
|
||||
|
||||
uint32_t len;
|
||||
@ -532,19 +529,16 @@ ecma_op_object_find_own (ecma_value_t base_value, /**< base value */
|
||||
if (type != ECMA_OBJECT_TYPE_ARROW_FUNCTION)
|
||||
{
|
||||
ecma_extended_object_t *ext_func_p = (ecma_extended_object_t *) object_p;
|
||||
bytecode_data_p = ECMA_GET_INTERNAL_VALUE_POINTER (const ecma_compiled_code_t,
|
||||
ext_func_p->u.function.bytecode_cp);
|
||||
bytecode_data_p = ecma_op_function_get_compiled_code (ext_func_p);
|
||||
}
|
||||
else
|
||||
{
|
||||
ecma_arrow_function_t *arrow_func_p = (ecma_arrow_function_t *) object_p;
|
||||
bytecode_data_p = ECMA_GET_NON_NULL_POINTER (const ecma_compiled_code_t,
|
||||
arrow_func_p->bytecode_cp);
|
||||
bytecode_data_p = ecma_op_arrow_function_get_compiled_code (arrow_func_p);
|
||||
}
|
||||
#else /* CONFIG_DISABLE_ES2015_ARROW_FUNCTION */
|
||||
ecma_extended_object_t *ext_func_p = (ecma_extended_object_t *) object_p;
|
||||
bytecode_data_p = ECMA_GET_INTERNAL_VALUE_POINTER (const ecma_compiled_code_t,
|
||||
ext_func_p->u.function.bytecode_cp);
|
||||
bytecode_data_p = ecma_op_function_get_compiled_code (ext_func_p);
|
||||
#endif /* !CONFIG_DISABLE_ES2015_ARROW_FUNCTION */
|
||||
|
||||
uint32_t len;
|
||||
|
||||
@ -32,6 +32,8 @@ extern "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);
|
||||
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_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);
|
||||
@ -43,6 +45,9 @@ size_t jerry_parse_and_save_literals (const jerry_char_t *source_p, size_t sourc
|
||||
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,
|
||||
|
||||
@ -653,7 +653,8 @@ typedef enum
|
||||
CBC_CODE_FLAGS_NON_STRICT_ARGUMENTS_NEEDED = (1u << 5), /**< non-strict arguments object must be constructed */
|
||||
CBC_CODE_FLAGS_LEXICAL_ENV_NOT_NEEDED = (1u << 6), /**< no need to create a lexical environment */
|
||||
CBC_CODE_FLAGS_ARROW_FUNCTION = (1u << 7), /**< this function is an arrow function */
|
||||
CBC_CODE_FLAGS_DEBUGGER_IGNORE = (1u << 8), /**< this function should be ignored by debugger */
|
||||
CBC_CODE_FLAGS_STATIC_FUNCTION = (1u << 8), /**< this function is a static snapshot function */
|
||||
CBC_CODE_FLAGS_DEBUGGER_IGNORE = (1u << 9), /**< this function should be ignored by debugger */
|
||||
} cbc_code_flags;
|
||||
|
||||
#define CBC_OPCODE(arg1, arg2, arg3, arg4) arg1,
|
||||
|
||||
@ -275,7 +275,15 @@ vm_run_eval (ecma_compiled_code_t *bytecode_data_p, /**< byte-code data */
|
||||
|
||||
ecma_deref_object (lex_env_p);
|
||||
ecma_free_value (this_binding);
|
||||
|
||||
#ifdef JERRY_ENABLE_SNAPSHOT_EXEC
|
||||
if (!(bytecode_data_p->status_flags & CBC_CODE_FLAGS_STATIC_FUNCTION))
|
||||
{
|
||||
ecma_bytecode_deref (bytecode_data_p);
|
||||
}
|
||||
#else /* !JERRY_ENABLE_SNAPSHOT_EXEC */
|
||||
ecma_bytecode_deref (bytecode_data_p);
|
||||
#endif /* JERRY_ENABLE_SNAPSHOT_EXEC */
|
||||
|
||||
return completion_value;
|
||||
} /* vm_run_eval */
|
||||
@ -289,8 +297,24 @@ static ecma_value_t
|
||||
vm_construct_literal_object (vm_frame_ctx_t *frame_ctx_p, /**< frame context */
|
||||
ecma_value_t lit_value) /**< literal */
|
||||
{
|
||||
#ifdef JERRY_ENABLE_SNAPSHOT_EXEC
|
||||
ecma_compiled_code_t *bytecode_p;
|
||||
|
||||
if (likely (!(frame_ctx_p->bytecode_header_p->status_flags & CBC_CODE_FLAGS_STATIC_FUNCTION)))
|
||||
{
|
||||
bytecode_p = ECMA_GET_INTERNAL_VALUE_POINTER (ecma_compiled_code_t,
|
||||
lit_value);
|
||||
}
|
||||
else
|
||||
{
|
||||
uint8_t *byte_p = ((uint8_t *) frame_ctx_p->bytecode_header_p) + lit_value;
|
||||
bytecode_p = (ecma_compiled_code_t *) byte_p;
|
||||
}
|
||||
#else /* !JERRY_ENABLE_SNAPSHOT_EXEC */
|
||||
ecma_compiled_code_t *bytecode_p = ECMA_GET_INTERNAL_VALUE_POINTER (ecma_compiled_code_t,
|
||||
lit_value);
|
||||
#endif /* JERRY_ENABLE_SNAPSHOT_EXEC */
|
||||
|
||||
bool is_function = ((bytecode_p->status_flags & CBC_CODE_FLAGS_FUNCTION) != 0);
|
||||
|
||||
if (is_function)
|
||||
@ -556,7 +580,16 @@ vm_init_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */
|
||||
ecma_value_t *literal_start_p = frame_ctx_p->literal_start_p;
|
||||
bool is_strict = ((frame_ctx_p->bytecode_header_p->status_flags & CBC_CODE_FLAGS_STRICT_MODE) != 0);
|
||||
ecma_value_t self_reference;
|
||||
|
||||
#ifdef JERRY_ENABLE_SNAPSHOT_EXEC
|
||||
self_reference = 0;
|
||||
if (!(bytecode_header_p->status_flags & CBC_CODE_FLAGS_STATIC_FUNCTION))
|
||||
{
|
||||
ECMA_SET_INTERNAL_VALUE_POINTER (self_reference, bytecode_header_p);
|
||||
}
|
||||
#else /* !JERRY_ENABLE_SNAPSHOT_EXEC */
|
||||
ECMA_SET_INTERNAL_VALUE_POINTER (self_reference, bytecode_header_p);
|
||||
#endif
|
||||
|
||||
/* Prepare. */
|
||||
if (!(bytecode_header_p->status_flags & CBC_CODE_FLAGS_FULL_LITERAL_ENCODING))
|
||||
@ -625,6 +658,7 @@ vm_init_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */
|
||||
{
|
||||
uint32_t value_index;
|
||||
ecma_value_t lit_value;
|
||||
bool is_immutable_binding = false;
|
||||
|
||||
READ_LITERAL_INDEX (value_index);
|
||||
|
||||
@ -634,6 +668,7 @@ vm_init_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */
|
||||
}
|
||||
else
|
||||
{
|
||||
is_immutable_binding = (self_reference == literal_start_p[value_index]);
|
||||
lit_value = vm_construct_literal_object (frame_ctx_p,
|
||||
literal_start_p[value_index]);
|
||||
}
|
||||
@ -646,7 +681,7 @@ vm_init_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */
|
||||
{
|
||||
ecma_string_t *name_p = ecma_get_string_from_value (literal_start_p[literal_index]);
|
||||
|
||||
if (likely (value_index < register_end || self_reference != literal_start_p[value_index]))
|
||||
if (likely (!is_immutable_binding))
|
||||
{
|
||||
vm_var_decl (frame_ctx_p, name_p);
|
||||
|
||||
|
||||
@ -126,10 +126,11 @@ read_file (uint8_t *input_pos_p, /**< next position in the input buffer */
|
||||
typedef enum
|
||||
{
|
||||
OPT_GENERATE_HELP,
|
||||
OPT_GENERATE_STATIC,
|
||||
OPT_GENERATE_CONTEXT,
|
||||
OPT_GENERATE_SHOW_OP,
|
||||
OPT_GENERATE_LITERAL_LIST,
|
||||
OPT_GENERATE_LITERAL_C,
|
||||
OPT_GENERATE_SHOW_OP,
|
||||
OPT_GENERATE_OUT,
|
||||
} generate_opt_id_t;
|
||||
|
||||
@ -140,8 +141,8 @@ static const cli_opt_t generate_opts[] =
|
||||
{
|
||||
CLI_OPT_DEF (.id = OPT_GENERATE_HELP, .opt = "h", .longopt = "help",
|
||||
.help = "print this help and exit"),
|
||||
CLI_OPT_DEF (.id = OPT_GENERATE_SHOW_OP, .longopt = "show-opcodes",
|
||||
.help = "print generated opcodes"),
|
||||
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: "
|
||||
@ -152,6 +153,8 @@ static const cli_opt_t generate_opts[] =
|
||||
CLI_OPT_DEF (.id = OPT_GENERATE_LITERAL_C, .longopt = "save-literals-c-format",
|
||||
.meta = "FILE",
|
||||
.help = "export literals found in parsed JS input (in C source format)"),
|
||||
CLI_OPT_DEF (.id = OPT_GENERATE_SHOW_OP, .longopt = "show-opcodes",
|
||||
.help = "print generated opcodes"),
|
||||
CLI_OPT_DEF (.id = OPT_GENERATE_OUT, .opt = "o", .meta="FILE",
|
||||
.help = "specify output file name (default: js.snapshot)"),
|
||||
CLI_OPT_DEF (.id = CLI_OPT_DEFAULT, .meta = "FILE",
|
||||
@ -178,6 +181,7 @@ process_generate (cli_state_t *cli_state_p, /**< cli state */
|
||||
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);
|
||||
|
||||
@ -190,31 +194,9 @@ process_generate (cli_state_t *cli_state_p, /**< cli state */
|
||||
cli_help (prog_name_p, "generate", generate_opts);
|
||||
return JERRY_STANDALONE_EXIT_CODE_OK;
|
||||
}
|
||||
case OPT_GENERATE_OUT:
|
||||
case OPT_GENERATE_STATIC:
|
||||
{
|
||||
output_file_name_p = cli_consume_string (cli_state_p);
|
||||
break;
|
||||
}
|
||||
case OPT_GENERATE_LITERAL_LIST:
|
||||
case OPT_GENERATE_LITERAL_C:
|
||||
{
|
||||
if (save_literals_file_name_p != NULL)
|
||||
{
|
||||
jerry_port_log (JERRY_LOG_LEVEL_ERROR, "Error: literal file name already specified");
|
||||
return JERRY_STANDALONE_EXIT_CODE_FAIL;
|
||||
}
|
||||
|
||||
is_save_literals_mode_in_c_format = (id == OPT_GENERATE_LITERAL_C);
|
||||
save_literals_file_name_p = cli_consume_string (cli_state_p);
|
||||
break;
|
||||
}
|
||||
case OPT_GENERATE_SHOW_OP:
|
||||
{
|
||||
if (check_feature (JERRY_FEATURE_PARSER_DUMP, cli_state_p->arg))
|
||||
{
|
||||
jerry_port_default_set_log_level (JERRY_LOG_LEVEL_DEBUG);
|
||||
flags |= JERRY_INIT_SHOW_OPCODES;
|
||||
}
|
||||
static_snapshot = true;
|
||||
break;
|
||||
}
|
||||
case OPT_GENERATE_CONTEXT:
|
||||
@ -241,6 +223,33 @@ process_generate (cli_state_t *cli_state_p, /**< cli state */
|
||||
}
|
||||
break;
|
||||
}
|
||||
case OPT_GENERATE_LITERAL_LIST:
|
||||
case OPT_GENERATE_LITERAL_C:
|
||||
{
|
||||
if (save_literals_file_name_p != NULL)
|
||||
{
|
||||
jerry_port_log (JERRY_LOG_LEVEL_ERROR, "Error: literal file name already specified");
|
||||
return JERRY_STANDALONE_EXIT_CODE_FAIL;
|
||||
}
|
||||
|
||||
is_save_literals_mode_in_c_format = (id == OPT_GENERATE_LITERAL_C);
|
||||
save_literals_file_name_p = cli_consume_string (cli_state_p);
|
||||
break;
|
||||
}
|
||||
case OPT_GENERATE_SHOW_OP:
|
||||
{
|
||||
if (check_feature (JERRY_FEATURE_PARSER_DUMP, cli_state_p->arg))
|
||||
{
|
||||
jerry_port_default_set_log_level (JERRY_LOG_LEVEL_DEBUG);
|
||||
flags |= JERRY_INIT_SHOW_OPCODES;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case OPT_GENERATE_OUT:
|
||||
{
|
||||
output_file_name_p = cli_consume_string (cli_state_p);
|
||||
break;
|
||||
}
|
||||
case CLI_OPT_DEFAULT:
|
||||
{
|
||||
const char *file_name_p = cli_consume_string (cli_state_p);
|
||||
@ -274,7 +283,7 @@ process_generate (cli_state_t *cli_state_p, /**< cli state */
|
||||
|
||||
if (number_of_files != 1)
|
||||
{
|
||||
jerry_port_log (JERRY_LOG_LEVEL_ERROR, "Error: No input file specified!\n");
|
||||
jerry_port_log (JERRY_LOG_LEVEL_ERROR, "Error: Exactly one input file must be specified\n");
|
||||
return JERRY_STANDALONE_EXIT_CODE_FAIL;
|
||||
}
|
||||
|
||||
@ -286,12 +295,27 @@ process_generate (cli_state_t *cli_state_p, /**< cli state */
|
||||
return JERRY_STANDALONE_EXIT_CODE_FAIL;
|
||||
}
|
||||
|
||||
size_t 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));
|
||||
size_t snapshot_size;
|
||||
|
||||
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));
|
||||
}
|
||||
|
||||
if (snapshot_size == 0)
|
||||
{
|
||||
jerry_port_log (JERRY_LOG_LEVEL_ERROR, "Error: Generating snapshot failed!\n");
|
||||
|
||||
@ -23,6 +23,29 @@
|
||||
*/
|
||||
#define SNAPSHOT_BUFFER_SIZE (256)
|
||||
|
||||
/**
|
||||
* Magic strings
|
||||
*/
|
||||
static const jerry_char_ptr_t magic_strings[] =
|
||||
{
|
||||
(const jerry_char_ptr_t) " ",
|
||||
(const jerry_char_ptr_t) "a",
|
||||
(const jerry_char_ptr_t) "b",
|
||||
(const jerry_char_ptr_t) "c",
|
||||
(const jerry_char_ptr_t) "from",
|
||||
(const jerry_char_ptr_t) "func",
|
||||
(const jerry_char_ptr_t) "string",
|
||||
(const jerry_char_ptr_t) "snapshot"
|
||||
};
|
||||
|
||||
/**
|
||||
* Magic string lengths
|
||||
*/
|
||||
static const jerry_length_t magic_string_lengths[] =
|
||||
{
|
||||
1, 1, 1, 1, 4, 4, 6, 8
|
||||
};
|
||||
|
||||
static void test_function_snapshot (void)
|
||||
{
|
||||
/* function to snapshot */
|
||||
@ -142,6 +165,10 @@ static void test_exec_snapshot (uint32_t *snapshot_p, size_t snapshot_size, bool
|
||||
|
||||
jerry_init (JERRY_INIT_EMPTY);
|
||||
|
||||
jerry_register_magic_strings (magic_strings,
|
||||
sizeof (magic_string_lengths) / sizeof (jerry_length_t),
|
||||
magic_string_lengths);
|
||||
|
||||
jerry_value_t res = jerry_exec_snapshot (snapshot_p,
|
||||
snapshot_size,
|
||||
copy_bytecode);
|
||||
@ -161,15 +188,15 @@ 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];
|
||||
|
||||
TEST_INIT ();
|
||||
|
||||
/* Dump / execute snapshot */
|
||||
if (jerry_is_feature_enabled (JERRY_FEATURE_SNAPSHOT_SAVE)
|
||||
&& jerry_is_feature_enabled (JERRY_FEATURE_SNAPSHOT_EXEC))
|
||||
{
|
||||
static uint32_t global_mode_snapshot_buffer[SNAPSHOT_BUFFER_SIZE];
|
||||
static uint32_t eval_mode_snapshot_buffer[SNAPSHOT_BUFFER_SIZE];
|
||||
|
||||
const char *code_to_snapshot_p = "(function () { return 'string from snapshot'; }) ();";
|
||||
|
||||
jerry_init (JERRY_INIT_EMPTY);
|
||||
@ -184,11 +211,11 @@ main (void)
|
||||
/* Check the snapshot data. Unused bytes should be filled with zeroes */
|
||||
const uint8_t expected_data[] =
|
||||
{
|
||||
0x4A, 0x52, 0x52, 0x59, 0x09, 0x00, 0x00, 0x00,
|
||||
0x4A, 0x52, 0x52, 0x59, 0x0A, 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,
|
||||
0x00, 0x00, 0x00, 0x01, 0x03, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x01, 0x18, 0x00, 0x00, 0x00,
|
||||
0x28, 0x00, 0xB7, 0x46, 0x00, 0x00, 0x00, 0x00,
|
||||
0x03, 0x00, 0x01, 0x00, 0x41, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x01, 0x01, 0x07, 0x00, 0x00, 0x00,
|
||||
@ -229,6 +256,36 @@ main (void)
|
||||
true);
|
||||
}
|
||||
|
||||
/* Static snapshot */
|
||||
if (jerry_is_feature_enabled (JERRY_FEATURE_SNAPSHOT_SAVE)
|
||||
&& jerry_is_feature_enabled (JERRY_FEATURE_SNAPSHOT_EXEC))
|
||||
{
|
||||
const char *code_to_snapshot_p = ("function func(a, b, c) {"
|
||||
" c = 'snapshot';"
|
||||
" return arguments[0] + ' ' + b + ' ' + arguments[2];"
|
||||
"};"
|
||||
"func('string', 'from');");
|
||||
|
||||
jerry_init (JERRY_INIT_EMPTY);
|
||||
jerry_register_magic_strings (magic_strings,
|
||||
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_cleanup ();
|
||||
|
||||
test_exec_snapshot (global_mode_snapshot_buffer,
|
||||
global_mode_snapshot_size,
|
||||
false);
|
||||
}
|
||||
|
||||
/* Merge snapshot */
|
||||
if (jerry_is_feature_enabled (JERRY_FEATURE_SNAPSHOT_SAVE)
|
||||
&& jerry_is_feature_enabled (JERRY_FEATURE_SNAPSHOT_EXEC))
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user