Storing byte code size in the byte code header. This reduces the

memory consumption, because the new allocator uses less memory if
the size as available when a block is freed. Snapshot generation
is also simplified.

JerryScript-DCO-1.0-Signed-off-by: Zoltan Herczeg zherczeg.u-szeged@partner.samsung.com
This commit is contained in:
Zoltan Herczeg
2016-03-16 02:57:28 -07:00
parent 2a5d17e736
commit d190ca44ae
19 changed files with 265 additions and 338 deletions
+7 -9
View File
@@ -741,17 +741,15 @@ typedef uintptr_t ecma_external_pointer_t;
*/
typedef struct
{
uint16_t status_flags; /**< various status flags */
uint16_t size; /**< real size >> MEM_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;
/**
* Shift value for byte code reference counting.
* The last 10 bit of the first uint16_t value
* of compact byte code or regexp byte code
* is reserved for reference counting.
*/
#define ECMA_BYTECODE_REF_SHIFT 6
/**
* @}
*/
+7 -6
View File
@@ -1316,12 +1316,12 @@ void
ecma_bytecode_ref (ecma_compiled_code_t *bytecode_p) /**< byte code pointer */
{
/* Abort program if maximum reference number is reached. */
if ((bytecode_p->status_flags >> ECMA_BYTECODE_REF_SHIFT) >= 0x3ff)
if (bytecode_p->refs >= UINT16_MAX)
{
jerry_fatal (ERR_REF_COUNT_LIMIT);
}
bytecode_p->status_flags = (uint16_t) (bytecode_p->status_flags + (1u << ECMA_BYTECODE_REF_SHIFT));
bytecode_p->refs++;
} /* ecma_bytecode_ref */
/**
@@ -1331,11 +1331,11 @@ ecma_bytecode_ref (ecma_compiled_code_t *bytecode_p) /**< byte code pointer */
void
ecma_bytecode_deref (ecma_compiled_code_t *bytecode_p) /**< byte code pointer */
{
JERRY_ASSERT ((bytecode_p->status_flags >> ECMA_BYTECODE_REF_SHIFT) > 0);
JERRY_ASSERT (bytecode_p->refs > 0);
bytecode_p->status_flags = (uint16_t) (bytecode_p->status_flags - (1u << ECMA_BYTECODE_REF_SHIFT));
bytecode_p->refs--;
if (bytecode_p->status_flags >= (1u << ECMA_BYTECODE_REF_SHIFT))
if (bytecode_p->refs > 0)
{
/* Non-zero reference counter. */
return;
@@ -1388,7 +1388,8 @@ ecma_bytecode_deref (ecma_compiled_code_t *bytecode_p) /**< byte code pointer */
#endif /* !CONFIG_ECMA_COMPACT_PROFILE_DISABLE_REGEXP_BUILTIN */
}
mem_heap_free_block_size_stored (bytecode_p);
mem_heap_free_block (bytecode_p,
((size_t) bytecode_p->size) << MEM_ALIGNMENT_LOG);
} /* ecma_bytecode_deref */
/**
@@ -256,7 +256,7 @@ ecma_op_create_regexp_object_from_bytecode (re_compiled_code_t *bytecode_p) /**<
/* Initialize RegExp object properties */
re_initialize_props (obj_p,
ECMA_GET_NON_NULL_POINTER (ecma_string_t, bytecode_p->pattern_cp),
bytecode_p->flags);
bytecode_p->header.status_flags);
return ecma_make_object_value (obj_p);
} /* ecma_op_create_regexp_object_from_bytecode */
@@ -1298,7 +1298,7 @@ ecma_regexp_exec_helper (ecma_value_t regexp_value, /**< RegExp object */
re_ctx.input_end_p = input_end_p;
/* 1. Read bytecode header and init regexp matcher context. */
re_ctx.flags = bc_p->flags;
re_ctx.flags = bc_p->header.status_flags;
if (ignore_global)
{
+8 -16
View File
@@ -24,27 +24,19 @@
*/
typedef struct
{
uint32_t last_compiled_code_offset; /**< offset of the last compiled code */
/* The size of this structure is recommended to be divisible by
* MEM_ALIGNMENT. Otherwise some bytes after the header are wasted. */
uint32_t version; /**< version number */
uint32_t lit_table_offset; /**< offset of the literal table */
uint32_t lit_table_size; /**< size of literal table */
__extension__ uint32_t is_run_global : 1; /**< flag, indicating whether the snapshot
* was dumped as 'Global scope'-mode code (true)
* or as eval-mode code (false) */
uint32_t is_run_global; /**< flag, indicating whether the snapshot
* was dumped as 'Global scope'-mode code (true)
* or as eval-mode code (false) */
} jerry_snapshot_header_t;
/**
* Jerry snapshot format version
*/
#define JERRY_SNAPSHOT_VERSION (3u)
#ifdef JERRY_ENABLE_SNAPSHOT_SAVE
/* Snapshot support functions */
extern bool snapshot_report_byte_code_compilation;
extern void
snapshot_add_compiled_code (ecma_compiled_code_t *, const uint8_t *, uint32_t);
#endif /* JERRY_ENABLE_SNAPSHOT_SAVE */
#define JERRY_SNAPSHOT_VERSION (4u)
#endif /* !JERRY_SNAPSHOT_H */
+174 -216
View File
@@ -1831,42 +1831,25 @@ jerry_register_external_magic_strings (const jerry_api_char_ptr_t *ex_str_items,
#ifdef JERRY_ENABLE_SNAPSHOT_SAVE
/*
* Tells whether snapshot taking is in progress.
*/
bool snapshot_report_byte_code_compilation = false;
/*
* Mapping snapshot to offset.
*/
typedef struct
{
mem_cpointer_t next_cp;
mem_cpointer_t compiled_code_cp;
uint16_t offset;
} compiled_code_map_entry_t;
/*
* Variables required to take a snapshot.
*/
static size_t snapshot_buffer_write_offset;
static size_t snapshot_last_compiled_code_offset;
static bool snapshot_error_occured;
static size_t snapshot_buffer_write_offset;
static uint8_t *snapshot_buffer_p;
static size_t snapshot_buffer_size;
static compiled_code_map_entry_t *snapshot_map_entries_p;
/**
* Snapshot callback for byte codes.
*
* @return start offset
*/
void
snapshot_add_compiled_code (ecma_compiled_code_t *compiled_code_p, /**< compiled code */
const uint8_t *regexp_pattern, /**< regular expression pattern */
uint32_t size) /**< compiled code or regular expression size */
static uint16_t
snapshot_add_compiled_code (ecma_compiled_code_t *compiled_code_p) /**< compiled code */
{
if (snapshot_error_occured)
{
return;
return 0;
}
JERRY_ASSERT ((snapshot_buffer_write_offset & (MEM_ALIGNMENT - 1)) == 0);
@@ -1874,81 +1857,117 @@ snapshot_add_compiled_code (ecma_compiled_code_t *compiled_code_p, /**< compiled
if ((snapshot_buffer_write_offset >> MEM_ALIGNMENT_LOG) > 0xffffu)
{
snapshot_error_occured = true;
return;
return 0;
}
snapshot_last_compiled_code_offset = snapshot_buffer_write_offset;
uint16_t start_offset = (uint16_t) (snapshot_buffer_write_offset >> MEM_ALIGNMENT_LOG);
ecma_compiled_code_t *copied_compiled_code_p;
compiled_code_map_entry_t *new_entry;
new_entry = (compiled_code_map_entry_t *) mem_heap_alloc_block (sizeof (compiled_code_map_entry_t));
if (new_entry == NULL)
{
snapshot_error_occured = true;
return;
}
ECMA_SET_POINTER (new_entry->next_cp, snapshot_map_entries_p);
ECMA_SET_POINTER (new_entry->compiled_code_cp, compiled_code_p);
new_entry->offset = (uint16_t) (snapshot_buffer_write_offset >> MEM_ALIGNMENT_LOG);
snapshot_map_entries_p = new_entry;
const void *data_p = (const void *) compiled_code_p;
copied_compiled_code_p = (ecma_compiled_code_t *) (snapshot_buffer_p + snapshot_buffer_write_offset);
if (!(compiled_code_p->status_flags & CBC_CODE_FLAGS_FUNCTION))
{
size += (uint32_t) sizeof (uint16_t);
}
else
{
JERRY_ASSERT (regexp_pattern == NULL);
}
#ifndef CONFIG_ECMA_COMPACT_PROFILE_DISABLE_REGEXP_BUILTIN
/* Regular expression. */
if (snapshot_buffer_write_offset + sizeof (ecma_compiled_code_t) > snapshot_buffer_size)
{
snapshot_error_occured = true;
return 0;
}
if (!jrt_write_to_buffer_by_offset (snapshot_buffer_p,
snapshot_buffer_size,
&snapshot_buffer_write_offset,
&size,
sizeof (uint32_t)))
{
snapshot_error_occured = true;
return;
}
snapshot_buffer_write_offset += sizeof (ecma_compiled_code_t);
if (!(compiled_code_p->status_flags & CBC_CODE_FLAGS_FUNCTION))
{
size -= (uint32_t) sizeof (uint16_t);
mem_cpointer_t pattern_cp = ((re_compiled_code_t *) compiled_code_p)->pattern_cp;
ecma_string_t *pattern_string_p = ECMA_GET_NON_NULL_POINTER (ecma_string_t,
pattern_cp);
ecma_length_t pattern_size = ecma_string_get_size (pattern_string_p);
MEM_DEFINE_LOCAL_ARRAY (buffer_p, pattern_size, lit_utf8_byte_t);
lit_utf8_size_t sz = ecma_string_to_utf8_string (pattern_string_p, buffer_p, pattern_size);
JERRY_ASSERT (sz == pattern_size);
if (!jrt_write_to_buffer_by_offset (snapshot_buffer_p,
snapshot_buffer_size,
&snapshot_buffer_write_offset,
&compiled_code_p->status_flags,
sizeof (uint16_t)))
buffer_p,
pattern_size))
{
snapshot_error_occured = true;
return;
}
data_p = regexp_pattern;
MEM_FINALIZE_LOCAL_ARRAY (buffer_p);
snapshot_buffer_write_offset = JERRY_ALIGNUP (snapshot_buffer_write_offset, MEM_ALIGNMENT);
/* Regexp character size is stored in refs. */
copied_compiled_code_p->refs = (uint16_t) pattern_size;
pattern_size += (ecma_length_t) sizeof (ecma_compiled_code_t);
copied_compiled_code_p->size = (uint16_t) ((pattern_size + MEM_ALIGNMENT - 1) >> MEM_ALIGNMENT_LOG);
copied_compiled_code_p->status_flags = compiled_code_p->status_flags;
#else
JERRY_UNIMPLEMENTED ("RegExp is not supported in compact profile.");
#endif /* !CONFIG_ECMA_COMPACT_PROFILE_DISABLE_REGEXP_BUILTIN */
return start_offset;
}
if (!jrt_write_to_buffer_by_offset (snapshot_buffer_p,
snapshot_buffer_size,
&snapshot_buffer_write_offset,
data_p,
size))
compiled_code_p,
((size_t) compiled_code_p->size) << MEM_ALIGNMENT_LOG))
{
snapshot_error_occured = true;
return;
return 0;
}
snapshot_buffer_write_offset = JERRY_ALIGNUP (snapshot_buffer_write_offset, MEM_ALIGNMENT);
/* 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_compiled_code_p;
lit_cpointer_t *src_literal_start_p;
uint16_t *dst_literal_start_p;
uint32_t const_literal_end;
uint32_t literal_end;
if (snapshot_buffer_write_offset > snapshot_buffer_size)
if (compiled_code_p->status_flags & CBC_CODE_FLAGS_UINT16_ARGUMENTS)
{
snapshot_error_occured = true;
return;
src_literal_start_p = (lit_cpointer_t *) (src_buffer_p + sizeof (cbc_uint16_arguments_t));
dst_literal_start_p = (uint16_t *) (dst_buffer_p + sizeof (cbc_uint16_arguments_t));
cbc_uint16_arguments_t *args_p = (cbc_uint16_arguments_t *) src_buffer_p;
literal_end = args_p->literal_end;
const_literal_end = args_p->const_literal_end;
}
else
{
src_literal_start_p = (lit_cpointer_t *) (src_buffer_p + sizeof (cbc_uint8_arguments_t));
dst_literal_start_p = (uint16_t *) (dst_buffer_p + sizeof (cbc_uint8_arguments_t));
cbc_uint8_arguments_t *args_p = (cbc_uint8_arguments_t *) src_buffer_p;
literal_end = args_p->literal_end;
const_literal_end = args_p->const_literal_end;
}
for (uint32_t i = const_literal_end; i < literal_end; i++)
{
ecma_compiled_code_t *bytecode_p = ECMA_GET_NON_NULL_POINTER (ecma_compiled_code_t,
src_literal_start_p[i]);
if (bytecode_p == compiled_code_p)
{
dst_literal_start_p[i] = start_offset;
}
else
{
dst_literal_start_p[i] = snapshot_add_compiled_code (bytecode_p);
}
}
return start_offset;
} /* snapshot_add_compiled_code */
/**
@@ -1963,20 +1982,12 @@ jerry_snapshot_set_offsets (uint8_t *buffer_p, /**< buffer */
do
{
uint32_t code_size = *(uint32_t *) buffer_p;
buffer_p += sizeof (uint32_t);
ecma_compiled_code_t *bytecode_p = (ecma_compiled_code_t *) buffer_p;
/* Set reference counter to 1. */
bytecode_p->status_flags &= (1u << ECMA_BYTECODE_REF_SHIFT) - 1;
bytecode_p->status_flags |= 1u << ECMA_BYTECODE_REF_SHIFT;
uint32_t code_size = ((uint32_t) bytecode_p->size) << MEM_ALIGNMENT_LOG;
if (bytecode_p->status_flags & CBC_CODE_FLAGS_FUNCTION)
{
lit_cpointer_t *literal_start_p;
uint32_t literal_end;
uint32_t const_literal_end;
if (bytecode_p->status_flags & CBC_CODE_FLAGS_UINT16_ARGUMENTS)
@@ -1984,7 +1995,6 @@ jerry_snapshot_set_offsets (uint8_t *buffer_p, /**< buffer */
literal_start_p = (lit_cpointer_t *) (buffer_p + sizeof (cbc_uint16_arguments_t));
cbc_uint16_arguments_t *args_p = (cbc_uint16_arguments_t *) buffer_p;
literal_end = args_p->literal_end;
const_literal_end = args_p->const_literal_end;
}
else
@@ -1992,7 +2002,6 @@ jerry_snapshot_set_offsets (uint8_t *buffer_p, /**< buffer */
literal_start_p = (lit_cpointer_t *) (buffer_p + sizeof (cbc_uint8_arguments_t));
cbc_uint8_arguments_t *args_p = (cbc_uint8_arguments_t *) buffer_p;
literal_end = args_p->literal_end;
const_literal_end = args_p->const_literal_end;
}
@@ -2011,24 +2020,11 @@ jerry_snapshot_set_offsets (uint8_t *buffer_p, /**< buffer */
}
}
for (uint32_t i = const_literal_end; i < literal_end; i++)
{
compiled_code_map_entry_t *current_p = snapshot_map_entries_p;
while (current_p->compiled_code_cp != literal_start_p[i])
{
current_p = ECMA_GET_NON_NULL_POINTER (compiled_code_map_entry_t,
current_p->next_cp);
}
literal_start_p[i] = (uint16_t) current_p->offset;
}
/* Set reference counter to 1. */
bytecode_p->refs = 1;
}
code_size += (uint32_t) sizeof (uint32_t);
code_size = JERRY_ALIGNUP (code_size, MEM_ALIGNMENT);
buffer_p += code_size - sizeof (uint32_t);
buffer_p += code_size;
size -= code_size;
}
while (size > 0);
@@ -2056,42 +2052,19 @@ jerry_parse_and_save_snapshot (const jerry_api_char_t *source_p, /**< script sou
jsp_status_t parse_status;
ecma_compiled_code_t *bytecode_data_p;
snapshot_buffer_write_offset = 0;
snapshot_last_compiled_code_offset = 0;
snapshot_buffer_write_offset = JERRY_ALIGNUP (sizeof (jerry_snapshot_header_t),
MEM_ALIGNMENT);
snapshot_error_occured = false;
snapshot_buffer_p = buffer_p;
snapshot_buffer_size = buffer_size;
snapshot_map_entries_p = NULL;
uint64_t version = JERRY_SNAPSHOT_VERSION;
if (!jrt_write_to_buffer_by_offset (buffer_p,
buffer_size,
&snapshot_buffer_write_offset,
&version,
sizeof (version)))
{
return 0;
}
snapshot_buffer_write_offset = JERRY_ALIGNUP (snapshot_buffer_write_offset, MEM_ALIGNMENT);
size_t header_offset = snapshot_buffer_write_offset;
snapshot_buffer_write_offset += JERRY_ALIGNUP (sizeof (jerry_snapshot_header_t), MEM_ALIGNMENT);
if (snapshot_buffer_write_offset > buffer_size)
{
return 0;
}
size_t compiled_code_start = snapshot_buffer_write_offset;
snapshot_report_byte_code_compilation = true;
jerry_api_object_t *error_obj_p = NULL;
if (is_for_global)
{
parse_status = parser_parse_script (source_p, source_size, &bytecode_data_p, &error_obj_p);
parse_status = parser_parse_script (source_p,
source_size,
&bytecode_data_p,
&error_obj_p);
}
else
{
@@ -2108,64 +2081,56 @@ jerry_parse_and_save_snapshot (const jerry_api_char_t *source_p, /**< script sou
ecma_deref_object (error_obj_p);
}
snapshot_report_byte_code_compilation = false;
if (parse_status == JSP_STATUS_OK
&& !snapshot_error_occured)
if (parse_status != JSP_STATUS_OK)
{
JERRY_ASSERT (snapshot_last_compiled_code_offset != 0);
jerry_snapshot_header_t header;
header.last_compiled_code_offset = (uint32_t) snapshot_last_compiled_code_offset;
header.is_run_global = is_for_global;
size_t compiled_code_size = snapshot_buffer_write_offset - compiled_code_start;
lit_mem_to_snapshot_id_map_entry_t *lit_map_p = NULL;
uint32_t literals_num;
if (!lit_dump_literals_for_snapshot (buffer_p,
buffer_size,
&snapshot_buffer_write_offset,
&lit_map_p,
&literals_num,
&header.lit_table_size))
{
JERRY_ASSERT (lit_map_p == NULL);
snapshot_buffer_write_offset = 0;
}
else
{
jerry_snapshot_set_offsets (buffer_p + compiled_code_start,
(uint32_t) compiled_code_size,
lit_map_p);
jrt_write_to_buffer_by_offset (buffer_p,
buffer_size,
&header_offset,
&header,
sizeof (header));
mem_heap_free_block_size_stored (lit_map_p);
}
ecma_bytecode_deref (bytecode_data_p);
}
else
{
snapshot_buffer_write_offset = 0;
return 0;
}
compiled_code_map_entry_t *current_p = snapshot_map_entries_p;
snapshot_add_compiled_code (bytecode_data_p);
while (current_p != NULL)
if (snapshot_error_occured)
{
compiled_code_map_entry_t *next_p = ECMA_GET_POINTER (compiled_code_map_entry_t,
current_p->next_cp);
mem_heap_free_block (current_p, sizeof (compiled_code_map_entry_t));
current_p = next_p;
return 0;
}
jerry_snapshot_header_t header;
header.version = JERRY_SNAPSHOT_VERSION;
header.lit_table_offset = (uint32_t) snapshot_buffer_write_offset;
header.is_run_global = is_for_global;
lit_mem_to_snapshot_id_map_entry_t *lit_map_p = NULL;
uint32_t literals_num;
if (!lit_dump_literals_for_snapshot (buffer_p,
buffer_size,
&snapshot_buffer_write_offset,
&lit_map_p,
&literals_num,
&header.lit_table_size))
{
JERRY_ASSERT (lit_map_p == NULL);
return 0;
}
jerry_snapshot_set_offsets (buffer_p + JERRY_ALIGNUP (sizeof (jerry_snapshot_header_t), MEM_ALIGNMENT),
(uint32_t) (header.lit_table_offset - sizeof (jerry_snapshot_header_t)),
lit_map_p);
size_t header_offset = 0;
jrt_write_to_buffer_by_offset (buffer_p,
buffer_size,
&header_offset,
&header,
sizeof (header));
if (lit_map_p != NULL)
{
mem_heap_free_block_size_stored (lit_map_p);
}
ecma_bytecode_deref (bytecode_data_p);
return snapshot_buffer_write_offset;
#else /* JERRY_ENABLE_SNAPSHOT_SAVE */
(void) source_p;
@@ -2180,6 +2145,13 @@ jerry_parse_and_save_snapshot (const jerry_api_char_t *source_p, /**< script sou
#ifdef JERRY_ENABLE_SNAPSHOT_EXEC
/**
* Byte code blocks shorter than this treshold are always copied into the memory.
* The memory / performance trade-of of byte code redirection does not worth
* in such cases.
*/
#define BYTECODE_NO_COPY_TRESHOLD 8
/**
* Load byte code from snapshot.
*
@@ -2191,23 +2163,19 @@ snapshot_load_compiled_code (const uint8_t *snapshot_data_p, /**< snapshot data
lit_mem_to_snapshot_id_map_entry_t *lit_map_p, /**< literal map */
bool copy_bytecode) /**< byte code should be copied to memory */
{
uint32_t code_size = *(uint32_t *) (snapshot_data_p + offset);
ecma_compiled_code_t *bytecode_p;
bytecode_p = (ecma_compiled_code_t *) (snapshot_data_p + offset + sizeof (uint32_t));
ecma_compiled_code_t *bytecode_p = (ecma_compiled_code_t *) (snapshot_data_p + offset);
uint32_t code_size = ((uint32_t) bytecode_p->size) << MEM_ALIGNMENT_LOG;
if (!(bytecode_p->status_flags & CBC_CODE_FLAGS_FUNCTION))
{
#ifndef CONFIG_ECMA_COMPACT_PROFILE_DISABLE_REGEXP_BUILTIN
const re_compiled_code_t *re_bytecode_p = NULL;
const uint8_t *regex_start_p = ((const uint8_t *) bytecode_p) + sizeof (uint16_t);
code_size -= (uint32_t) sizeof (uint16_t);
const uint8_t *regex_start_p = ((const uint8_t *) bytecode_p) + sizeof (ecma_compiled_code_t);
/* Real size is stored in refs. */
ecma_string_t *pattern_str_p = ecma_new_ecma_string_from_utf8 (regex_start_p,
code_size);
bytecode_p->refs);
re_compile_bytecode (&re_bytecode_p,
pattern_str_p,
@@ -2242,21 +2210,25 @@ snapshot_load_compiled_code (const uint8_t *snapshot_data_p, /**< snapshot data
header_size = sizeof (cbc_uint8_arguments_t);
}
if (copy_bytecode)
if (copy_bytecode
|| (header_size + (literal_end * sizeof (uint16_t)) + BYTECODE_NO_COPY_TRESHOLD > code_size))
{
bytecode_p = (ecma_compiled_code_t *) mem_heap_alloc_block_store_size (code_size);
bytecode_p = (ecma_compiled_code_t *) mem_heap_alloc_block (code_size);
memcpy (bytecode_p, snapshot_data_p + offset + sizeof (uint32_t), code_size);
memcpy (bytecode_p, snapshot_data_p + offset, code_size);
}
else
{
code_size = (uint32_t) (header_size + literal_end * sizeof (lit_cpointer_t));
uint8_t *real_bytecode_p = ((uint8_t *) bytecode_p) + code_size;
uint32_t total_size = JERRY_ALIGNUP (code_size + 1 + sizeof (uint8_t *), MEM_ALIGNMENT);
bytecode_p = (ecma_compiled_code_t *) mem_heap_alloc_block_store_size (code_size + 1 + sizeof (uint8_t *));
bytecode_p = (ecma_compiled_code_t *) mem_heap_alloc_block (total_size);
memcpy (bytecode_p, snapshot_data_p + offset + sizeof (uint32_t), code_size);
memcpy (bytecode_p, snapshot_data_p + offset, code_size);
bytecode_p->size = (uint16_t) (total_size >> MEM_ALIGNMENT_LOG);
uint8_t *instructions_p = ((uint8_t *) bytecode_p);
@@ -2264,7 +2236,7 @@ snapshot_load_compiled_code (const uint8_t *snapshot_data_p, /**< snapshot data
memcpy (instructions_p + code_size + 1, &real_bytecode_p, sizeof (uint8_t *));
}
JERRY_ASSERT ((bytecode_p->status_flags >> ECMA_BYTECODE_REF_SHIFT) == 1);
JERRY_ASSERT (bytecode_p->refs == 1);
lit_cpointer_t *literal_start_p = (lit_cpointer_t *) (((uint8_t *) bytecode_p) + header_size);
@@ -2335,39 +2307,28 @@ jerry_exec_snapshot (const void *snapshot_p, /**< snapshot */
JERRY_ASSERT (snapshot_p != NULL);
const uint8_t *snapshot_data_p = (uint8_t *) snapshot_p;
size_t snapshot_read = 0;
uint64_t version;
if (!jrt_read_from_buffer_by_offset (snapshot_data_p,
snapshot_size,
&snapshot_read,
&version,
sizeof (version)))
if (snapshot_size <= sizeof (jerry_snapshot_header_t))
{
return JERRY_COMPLETION_CODE_INVALID_SNAPSHOT_FORMAT;
}
if (version != JERRY_SNAPSHOT_VERSION)
const jerry_snapshot_header_t *header_p = (const jerry_snapshot_header_t *) snapshot_data_p;
if (header_p->version != JERRY_SNAPSHOT_VERSION)
{
return JERRY_COMPLETION_CODE_INVALID_SNAPSHOT_VERSION;
}
const jerry_snapshot_header_t *header_p = (const jerry_snapshot_header_t *) (snapshot_data_p + snapshot_read);
snapshot_read = header_p->last_compiled_code_offset;
JERRY_ASSERT (snapshot_read == JERRY_ALIGNUP (snapshot_read, MEM_ALIGNMENT));
uint32_t last_code_size = *(uint32_t *) (snapshot_data_p + snapshot_read);
snapshot_read += JERRY_ALIGNUP (last_code_size + sizeof (uint32_t), MEM_ALIGNMENT);
lit_mem_to_snapshot_id_map_entry_t *lit_map_p = NULL;
uint32_t literals_num;
JERRY_ASSERT (snapshot_read + header_p->lit_table_size <= snapshot_size);
if (header_p->lit_table_offset >= snapshot_size)
{
return JERRY_COMPLETION_CODE_INVALID_SNAPSHOT_VERSION;
}
if (!lit_load_literals_from_snapshot (snapshot_data_p + snapshot_read,
if (!lit_load_literals_from_snapshot (snapshot_data_p + header_p->lit_table_offset,
header_p->lit_table_size,
&lit_map_p,
&literals_num))
@@ -2377,11 +2338,8 @@ jerry_exec_snapshot (const void *snapshot_p, /**< snapshot */
}
ecma_compiled_code_t *bytecode_p;
snapshot_read = header_p->last_compiled_code_offset;
bytecode_p = snapshot_load_compiled_code (snapshot_data_p,
snapshot_read,
sizeof (jerry_snapshot_header_t),
lit_map_p,
copy_bytecode);
+2 -2
View File
@@ -200,11 +200,11 @@ extern void __noreturn jerry_fatal (jerry_fatal_code_t);
*/
/**
* Aligns @a value to @a alignment.
* Aligns @a value to @a alignment. @a must be the power of 2.
*
* Returns minimum positive value, that divides @a alignment and is more than or equal to @a value
*/
#define JERRY_ALIGNUP(value, alignment) ((alignment) * (((value) + (alignment) - 1) / (alignment)))
#define JERRY_ALIGNUP(value, alignment) (((value) + ((alignment) - 1)) & ~((alignment) - 1))
/**
* min, max
+2 -2
View File
@@ -617,7 +617,7 @@
*/
typedef struct
{
uint16_t status_flags; /**< various status flags */
ecma_compiled_code_t header; /**< compiled code header */
uint8_t stack_limit; /**< maximum number of values stored on the stack */
uint8_t argument_end; /**< number of arguments expected by the function */
uint8_t register_end; /**< end position of the register group */
@@ -631,7 +631,7 @@ typedef struct
*/
typedef struct
{
uint16_t status_flags; /**< various status flags */
ecma_compiled_code_t header; /**< compiled code header */
uint16_t stack_limit; /**< maximum number of values stored on the stack */
uint16_t argument_end; /**< number of arguments expected by the function */
uint16_t register_end; /**< end position of the register group */
+1 -1
View File
@@ -165,7 +165,7 @@ util_free_literal (lexer_literal_t *literal_p) /**< literal */
{
if (!(literal_p->status_flags & LEXER_FLAG_SOURCE_PTR))
{
PARSER_FREE ((uint8_t *) literal_p->u.char_p);
mem_heap_free_block_size_stored ((void *) literal_p->u.char_p);
}
}
else if ((literal_p->type == LEXER_FUNCTION_LITERAL)
-11
View File
@@ -47,17 +47,6 @@
#include "lit-literal.h"
#include "mem-heap.h"
/* The utilites here are just for compiling purposes, JS
* engines should have an optimized version for them. */
/* Malloc functions. */
#define PARSER_MALLOC(size) mem_heap_alloc_block_store_size (size)
#define PARSER_FREE(ptr) mem_heap_free_block_size_stored ((void *) ptr)
#define PARSER_MALLOC_LOCAL(size) mem_heap_alloc_block_store_size (size)
#define PARSER_FREE_LOCAL(ptr) mem_heap_free_block_size_stored (ptr)
/* UTF character management. Only ASCII characters are
* supported for simplicity. */
+4 -11
View File
@@ -1203,7 +1203,7 @@ lexer_process_char_literal (parser_context_t *context_p, /**< context */
if (has_escape)
{
literal_p->u.char_p = (uint8_t *) PARSER_MALLOC (length);
literal_p->u.char_p = (uint8_t *) mem_heap_alloc_block_store_size (length);
memcpy ((uint8_t *) literal_p->u.char_p, char_p, length);
}
else
@@ -1245,6 +1245,7 @@ lexer_construct_literal_object (parser_context_t *context_p, /**< context */
{
destination_start_p = (uint8_t *) parser_malloc_local (context_p, literal_p->length);
context_p->allocated_buffer_p = destination_start_p;
context_p->allocated_buffer_size = literal_p->length;
}
destination_p = destination_start_p;
@@ -1502,7 +1503,8 @@ lexer_construct_literal_object (parser_context_t *context_p, /**< context */
JERRY_ASSERT (context_p->allocated_buffer_p == destination_start_p);
context_p->allocated_buffer_p = NULL;
parser_free_local (destination_start_p);
parser_free_local (destination_start_p,
context_p->allocated_buffer_size);
}
JERRY_ASSERT (context_p->allocated_buffer_p == NULL);
@@ -1826,15 +1828,6 @@ lexer_construct_regexp_object (parser_context_t *context_p, /**< context */
parser_raise_error (context_p, PARSER_ERR_INVALID_REGEXP);
}
#ifdef JERRY_ENABLE_SNAPSHOT_SAVE
if (snapshot_report_byte_code_compilation)
{
snapshot_add_compiled_code ((ecma_compiled_code_t *) re_bytecode_p,
regex_start_p,
length);
}
#endif /* JERRY_ENABLE_SNAPSHOT_SAVE */
literal_p->type = LEXER_REGEXP_LITERAL;
literal_p->u.bytecode_p = (ecma_compiled_code_t *) re_bytecode_p;
+3 -2
View File
@@ -236,6 +236,7 @@ typedef struct
parser_error_t error; /**< error code */
void *allocated_buffer_p; /**< dinamically allocated buffer
* which needs to be freed on error */
uint32_t allocated_buffer_size; /**< size of the dinamically allocated buffer */
/* Parser members. */
uint32_t status_flags; /**< status flags */
@@ -283,9 +284,9 @@ typedef struct
/* Memory management.
* Note: throws an error if unsuccessful. */
void *parser_malloc (parser_context_t *, size_t);
void parser_free (void *);
void parser_free (void *, size_t);
void *parser_malloc_local (parser_context_t *, size_t);
void parser_free_local (void *);
void parser_free_local (void *, size_t);
/* Parser byte stream. */
+1 -1
View File
@@ -54,7 +54,7 @@
/* Maximum code size.
* Limit: 16777215. Recommended: 65535, 16777215. */
#ifndef PARSER_MAXIMUM_CODE_SIZE
#define PARSER_MAXIMUM_CODE_SIZE 16777215
#define PARSER_MAXIMUM_CODE_SIZE (65535 << (MEM_ALIGNMENT_LOG))
#endif
/* Maximum number of values pushed onto the stack by a function.
+24 -16
View File
@@ -34,12 +34,12 @@
*/
void *
parser_malloc (parser_context_t *context_p, /**< context */
size_t size) /**< size of the memory */
size_t size) /**< size of the memory block */
{
void *result;
JERRY_ASSERT (size > 0);
result = PARSER_MALLOC (size);
result = mem_heap_alloc_block (size);
if (result == 0)
{
parser_raise_error (context_p, PARSER_ERR_OUT_OF_MEMORY);
@@ -50,9 +50,10 @@ parser_malloc (parser_context_t *context_p, /**< context */
/**
* Free memory allocated by parser_malloc.
*/
void parser_free (void *ptr) /**< pointer to free */
void parser_free (void *ptr, /**< pointer to free */
size_t size) /**< size of the memory block */
{
PARSER_FREE (ptr);
mem_heap_free_block (ptr, size);
} /* parser_free */
/**
@@ -67,7 +68,7 @@ parser_malloc_local (parser_context_t *context_p, /**< context */
void *result;
JERRY_ASSERT (size > 0);
result = PARSER_MALLOC_LOCAL (size);
result = mem_heap_alloc_block (size);
if (result == 0)
{
parser_raise_error (context_p, PARSER_ERR_OUT_OF_MEMORY);
@@ -78,9 +79,10 @@ parser_malloc_local (parser_context_t *context_p, /**< context */
/**
* Free memory allocated by parser_malloc_local.
*/
void parser_free_local (void *ptr) /**< pointer to free */
void parser_free_local (void *ptr, /**< pointer to free */
size_t size) /**< size of the memory */
{
PARSER_FREE_LOCAL (ptr);
mem_heap_free_block (ptr, size);
} /* parser_free_local */
/**********************************************************************/
@@ -103,7 +105,8 @@ parser_data_init (parser_mem_data_t *data_p, /**< memory manager */
* Free parse data.
*/
static void
parser_data_free (parser_mem_data_t *data_p) /**< memory manager */
parser_data_free (parser_mem_data_t *data_p, /**< memory manager */
uint32_t page_size) /**< size of each page */
{
parser_mem_page_t *page_p = data_p->first_p;
@@ -111,7 +114,7 @@ parser_data_free (parser_mem_data_t *data_p) /**< memory manager */
{
parser_mem_page_t *next_p = page_p->next_p;
parser_free (page_p);
parser_free (page_p, page_size);
page_p = next_p;
}
} /* parser_data_free */
@@ -135,7 +138,8 @@ parser_cbc_stream_init (parser_mem_data_t *data_p) /**< memory manager */
void
parser_cbc_stream_free (parser_mem_data_t *data_p) /**< memory manager */
{
parser_data_free (data_p);
parser_data_free (data_p,
sizeof (parser_mem_page_t *) + PARSER_CBC_STREAM_PAGE_SIZE);
} /* parser_cbc_stream_free */
/**
@@ -188,7 +192,8 @@ parser_list_init (parser_list_t *list_p, /**< parser list */
void
parser_list_free (parser_list_t *list_p) /**< parser list */
{
parser_data_free (&list_p->data);
parser_data_free (&list_p->data,
(uint32_t) (sizeof (parser_mem_page_t *) + list_p->page_size));
} /* parser_list_free */
/**
@@ -330,11 +335,13 @@ parser_stack_init (parser_context_t *context_p) /**< context */
void
parser_stack_free (parser_context_t *context_p) /**< context */
{
parser_data_free (&context_p->stack);
parser_data_free (&context_p->stack,
sizeof (parser_mem_page_t *) + PARSER_STACK_PAGE_SIZE);
if (context_p->free_page_p != NULL)
{
parser_free (context_p->free_page_p);
parser_free (context_p->free_page_p,
sizeof (parser_mem_page_t *) + PARSER_STACK_PAGE_SIZE);
}
} /* parser_stack_free */
@@ -363,7 +370,6 @@ parser_stack_push_uint8 (parser_context_t *context_p, /**< context */
else
{
size_t size = sizeof (parser_mem_page_t *) + PARSER_STACK_PAGE_SIZE;
page_p = (parser_mem_page_t *) parser_malloc (context_p, size);
}
@@ -400,7 +406,8 @@ parser_stack_pop_uint8 (parser_context_t *context_p) /**< context */
}
else
{
parser_free (page_p);
parser_free (page_p,
sizeof (parser_mem_page_t *) + PARSER_STACK_PAGE_SIZE);
}
page_p = context_p->stack.first_p;
@@ -575,7 +582,8 @@ parser_stack_pop (parser_context_t *context_p, /**< context */
}
else
{
parser_free (page_p);
parser_free (page_p,
sizeof (parser_mem_page_t *) + PARSER_STACK_PAGE_SIZE);
}
} /* parser_stack_pop */
+3 -3
View File
@@ -1285,7 +1285,7 @@ parser_parse_case_statement (parser_context_t *context_p) /**< context */
parser_stack_iterator_write (&iterator, &switch_statement, sizeof (parser_switch_statement_t));
parser_set_branch_to_current_position (context_p, &branch_p->branch);
parser_free (branch_p);
parser_free (branch_p, sizeof (parser_branch_node_t));
} /* parser_parse_case_statement */
/**
@@ -2102,7 +2102,7 @@ parser_free_jumps (parser_stack_iterator_t iterator) /**< iterator position */
while (branch_list_p != NULL)
{
parser_branch_node_t *next_p = branch_list_p->next_p;
parser_free (branch_list_p);
parser_free (branch_list_p, sizeof (parser_branch_node_t));
branch_list_p = next_p;
}
branch_list_p = loop.branch_list_p;
@@ -2133,7 +2133,7 @@ parser_free_jumps (parser_stack_iterator_t iterator) /**< iterator position */
while (branch_list_p != NULL)
{
parser_branch_node_t *next_p = branch_list_p->next_p;
parser_free (branch_list_p);
parser_free (branch_list_p, sizeof (parser_branch_node_t));
branch_list_p = next_p;
}
}
+1 -1
View File
@@ -619,7 +619,7 @@ parser_set_breaks_to_current_position (parser_context_t *context_p, /**< context
{
parser_set_branch_to_current_position (context_p, &current_p->branch);
}
parser_free (current_p);
parser_free (current_p, sizeof (parser_branch_node_t));
current_p = next_p;
}
} /* parser_set_breaks_to_current_position */
+10 -28
View File
@@ -105,7 +105,7 @@ parser_compute_indicies (parser_context_t *context_p, /**< context */
if (!(literal_p->status_flags & LEXER_FLAG_SOURCE_PTR))
{
PARSER_FREE ((uint8_t *) char_p);
mem_heap_free_block_size_stored ((void *) char_p);
}
}
}
@@ -527,7 +527,7 @@ parser_generate_initializers (parser_context_t *context_p, /**< context */
if (!context_p->is_show_opcodes
&& !(literal_p->status_flags & LEXER_FLAG_SOURCE_PTR))
{
PARSER_FREE (literal_p->u.char_p);
mem_heap_free_block_size_stored ((void *) literal_p->u.char_p);
}
#else /* PARSER_DUMP_BYTE_CODE */
literal_pool_p[literal_p->prop.index] = literal_p->u.value;
@@ -1460,10 +1460,14 @@ parser_post_processing (parser_context_t *context_p) /**< context */
}
total_size += length + context_p->literal_count * sizeof (lit_cpointer_t);
total_size = JERRY_ALIGNUP (total_size, MEM_ALIGNMENT);
compiled_code_p = (ecma_compiled_code_t *) parser_malloc (context_p, total_size);
byte_code_p = (uint8_t *) compiled_code_p;
compiled_code_p->status_flags = CBC_CODE_FLAGS_FUNCTION | (1u << ECMA_BYTECODE_REF_SHIFT);
compiled_code_p->size = (uint16_t) (total_size >> MEM_ALIGNMENT_LOG);
compiled_code_p->refs = 1;
compiled_code_p->status_flags = CBC_CODE_FLAGS_FUNCTION;
if (needs_uint16_arguments)
{
@@ -1518,20 +1522,6 @@ parser_post_processing (parser_context_t *context_p) /**< context */
literal_pool_p = (lit_cpointer_t *) byte_code_p;
byte_code_p += context_p->literal_count * sizeof (lit_cpointer_t);
#ifdef JERRY_ENABLE_SNAPSHOT_SAVE
if (snapshot_report_byte_code_compilation
&& context_p->argument_count > 0)
{
/* Reset all arguments to NULL. */
for (offset = 0; offset < context_p->argument_count; offset++)
{
literal_pool_p[offset] = NOT_A_LITERAL;
}
}
#endif
dst_p = parser_generate_initializers (context_p,
byte_code_p,
literal_pool_p,
@@ -1705,7 +1695,7 @@ parser_post_processing (parser_context_t *context_p) /**< context */
if ((literal_p->type == LEXER_IDENT_LITERAL || literal_p->type == LEXER_STRING_LITERAL)
&& !(literal_p->status_flags & LEXER_FLAG_SOURCE_PTR))
{
PARSER_FREE (literal_p->u.char_p);
mem_heap_free_block_size_stored ((void *) literal_p->u.char_p);
}
}
}
@@ -1780,15 +1770,6 @@ parser_post_processing (parser_context_t *context_p) /**< context */
compiled_code_p);
}
#ifdef JERRY_ENABLE_SNAPSHOT_SAVE
if (snapshot_report_byte_code_compilation)
{
snapshot_add_compiled_code (compiled_code_p, NULL, (uint32_t) total_size);
}
#endif
return compiled_code_p;
} /* parser_post_processing */
@@ -1924,7 +1905,8 @@ parser_parse_source (const uint8_t *source_p, /**< valid UTF-8 source code */
if (context.allocated_buffer_p != NULL)
{
parser_free_local (context.allocated_buffer_p);
parser_free_local (context.allocated_buffer_p,
context.allocated_buffer_size);
}
if (error_location != NULL)
+4 -4
View File
@@ -54,11 +54,11 @@ re_realloc_regexp_bytecode_block (re_bytecode_ctx_t *bc_ctx_p) /**< RegExp bytec
JERRY_ASSERT (bc_ctx_p->current_p >= bc_ctx_p->block_start_p);
size_t current_ptr_offset = (size_t) (bc_ctx_p->current_p - bc_ctx_p->block_start_p);
uint8_t *new_block_start_p = (uint8_t *) mem_heap_alloc_block_store_size (new_block_size);
uint8_t *new_block_start_p = (uint8_t *) mem_heap_alloc_block (new_block_size);
if (bc_ctx_p->current_p)
{
memcpy (new_block_start_p, bc_ctx_p->block_start_p, (size_t) (current_ptr_offset));
mem_heap_free_block_size_stored (bc_ctx_p->block_start_p);
mem_heap_free_block (bc_ctx_p->block_start_p, old_size);
}
bc_ctx_p->block_start_p = new_block_start_p;
bc_ctx_p->block_end_p = new_block_start_p + new_block_size;
@@ -109,10 +109,10 @@ re_bytecode_list_insert (re_bytecode_ctx_t *bc_ctx_p, /**< RegExp bytecode conte
{
uint8_t *dest_p = src_p + length;
uint8_t *tmp_block_start_p;
tmp_block_start_p = (uint8_t *) mem_heap_alloc_block_store_size (re_get_bytecode_length (bc_ctx_p) - offset);
tmp_block_start_p = (uint8_t *) mem_heap_alloc_block (re_get_bytecode_length (bc_ctx_p) - offset);
memcpy (tmp_block_start_p, src_p, (size_t) (re_get_bytecode_length (bc_ctx_p) - offset));
memcpy (dest_p, tmp_block_start_p, (size_t) (re_get_bytecode_length (bc_ctx_p) - offset));
mem_heap_free_block_size_stored (tmp_block_start_p);
mem_heap_free_block (tmp_block_start_p, re_get_bytecode_length (bc_ctx_p) - offset);
}
memcpy (src_p, bytecode_p, length);
+1 -1
View File
@@ -85,7 +85,7 @@ typedef enum
*/
typedef struct
{
uint16_t flags; /**< RegExp flags */
ecma_compiled_code_t header; /**< compiled code header */
mem_cpointer_t pattern_cp; /**< original RegExp pattern */
uint32_t num_of_captures; /**< number of capturing brackets */
uint32_t num_of_non_captures; /**< number of non capturing brackets */
+11 -6
View File
@@ -468,7 +468,7 @@ re_find_bytecode_in_cache (ecma_string_t *pattern_str_p, /**< pattern string */
ecma_string_t *cached_pattern_str_p;
cached_pattern_str_p = ECMA_GET_NON_NULL_POINTER (ecma_string_t, cached_bytecode_p->pattern_cp);
if ((cached_bytecode_p->flags & RE_FLAGS_MASK) == flags
if ((cached_bytecode_p->header.status_flags & RE_FLAGS_MASK) == flags
&& ecma_compare_ecma_strings (cached_pattern_str_p, pattern_str_p))
{
JERRY_DDLOG ("RegExp is found in cache\n");
@@ -497,9 +497,9 @@ re_cache_gc_run ()
const re_compiled_code_t *cached_bytecode_p = re_cache[i];
if (cached_bytecode_p != NULL
&& (cached_bytecode_p->flags >> ECMA_BYTECODE_REF_SHIFT) == 1)
{ /* Only the cache has reference for the bytecode */
&& cached_bytecode_p->header.refs == 1)
{
/* Only the cache has reference for the bytecode */
ecma_bytecode_deref ((ecma_compiled_code_t *) cached_bytecode_p);
re_cache[i] = NULL;
}
@@ -578,7 +578,8 @@ re_compile_bytecode (const re_compiled_code_t **out_bytecode_p, /**< [out] point
/* 3. Insert extra informations for bytecode header */
re_compiled_code_t re_compiled_code;
re_compiled_code.flags = re_ctx.flags | (1u << ECMA_BYTECODE_REF_SHIFT);
re_compiled_code.header.refs = 1;
re_compiled_code.header.status_flags = re_ctx.flags;
ECMA_SET_NON_NULL_POINTER (re_compiled_code.pattern_cp,
ecma_copy_or_ref_ecma_string (pattern_str_p));
re_compiled_code.num_of_captures = re_ctx.num_of_captures * 2;
@@ -594,11 +595,13 @@ re_compile_bytecode (const re_compiled_code_t **out_bytecode_p, /**< [out] point
MEM_FINALIZE_LOCAL_ARRAY (pattern_start_p);
size_t byte_code_size = (size_t) (bc_ctx.block_end_p - bc_ctx.block_start_p);
if (!ecma_is_value_empty (ret_value))
{
/* Compilation failed, free bytecode. */
JERRY_DDLOG ("RegExp compilation failed!\n");
mem_heap_free_block_size_stored (bc_ctx.block_start_p);
mem_heap_free_block (bc_ctx.block_start_p, byte_code_size);
*out_bytecode_p = NULL;
}
else
@@ -611,6 +614,8 @@ re_compile_bytecode (const re_compiled_code_t **out_bytecode_p, /**< [out] point
JERRY_ASSERT (bc_ctx.block_start_p != NULL);
*out_bytecode_p = (re_compiled_code_t *) bc_ctx.block_start_p;
((re_compiled_code_t *) bc_ctx.block_start_p)->header.size = (uint16_t) (byte_code_size >> MEM_ALIGNMENT_LOG);
if (cache_idx == RE_CACHE_SIZE)
{
if (re_cache_idx == 0u)