diff --git a/jerry-core/ecma/base/ecma-globals.h b/jerry-core/ecma/base/ecma-globals.h index 735a1cf698..72a28ab73a 100644 --- a/jerry-core/ecma/base/ecma-globals.h +++ b/jerry-core/ecma/base/ecma-globals.h @@ -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 - /** * @} */ diff --git a/jerry-core/ecma/base/ecma-helpers.c b/jerry-core/ecma/base/ecma-helpers.c index bad893b6b9..dd57ec27b1 100644 --- a/jerry-core/ecma/base/ecma-helpers.c +++ b/jerry-core/ecma/base/ecma-helpers.c @@ -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 */ /** diff --git a/jerry-core/ecma/operations/ecma-regexp-object.c b/jerry-core/ecma/operations/ecma-regexp-object.c index 48a6447cff..4ceba1ef45 100644 --- a/jerry-core/ecma/operations/ecma-regexp-object.c +++ b/jerry-core/ecma/operations/ecma-regexp-object.c @@ -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) { diff --git a/jerry-core/jerry-snapshot.h b/jerry-core/jerry-snapshot.h index 9c9ce316b4..01df96c2a2 100644 --- a/jerry-core/jerry-snapshot.h +++ b/jerry-core/jerry-snapshot.h @@ -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 */ diff --git a/jerry-core/jerry.c b/jerry-core/jerry.c index eb6343341d..3e003907ea 100644 --- a/jerry-core/jerry.c +++ b/jerry-core/jerry.c @@ -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)); + copied_compiled_code_p = (ecma_compiled_code_t *) (snapshot_buffer_p + snapshot_buffer_write_offset); - if (new_entry == NULL) + if (!(compiled_code_p->status_flags & CBC_CODE_FLAGS_FUNCTION)) { - 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); +#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; + } - new_entry->offset = (uint16_t) (snapshot_buffer_write_offset >> MEM_ALIGNMENT_LOG); - snapshot_map_entries_p = new_entry; + snapshot_buffer_write_offset += sizeof (ecma_compiled_code_t); - const void *data_p = (const void *) compiled_code_p; + 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); - if (!(compiled_code_p->status_flags & CBC_CODE_FLAGS_FUNCTION)) - { - size += (uint32_t) sizeof (uint16_t); - } - else - { - JERRY_ASSERT (regexp_pattern == NULL); - } + ecma_length_t pattern_size = ecma_string_get_size (pattern_string_p); - 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; - } + MEM_DEFINE_LOCAL_ARRAY (buffer_p, pattern_size, lit_utf8_byte_t); - if (!(compiled_code_p->status_flags & CBC_CODE_FLAGS_FUNCTION)) - { - size -= (uint32_t) sizeof (uint16_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; + return 0; + } - lit_mem_to_snapshot_id_map_entry_t *lit_map_p = NULL; - uint32_t literals_num; + snapshot_add_compiled_code (bytecode_data_p); - 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); + if (snapshot_error_occured) + { + return 0; + } - jrt_write_to_buffer_by_offset (buffer_p, - buffer_size, - &header_offset, - &header, - sizeof (header)); + 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; - mem_heap_free_block_size_stored (lit_map_p); - } + lit_mem_to_snapshot_id_map_entry_t *lit_map_p = NULL; + uint32_t literals_num; - ecma_bytecode_deref (bytecode_data_p); - } - else + if (!lit_dump_literals_for_snapshot (buffer_p, + buffer_size, + &snapshot_buffer_write_offset, + &lit_map_p, + &literals_num, + &header.lit_table_size)) { - snapshot_buffer_write_offset = 0; + JERRY_ASSERT (lit_map_p == NULL); + return 0; } - compiled_code_map_entry_t *current_p = snapshot_map_entries_p; + 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; - while (current_p != NULL) + jrt_write_to_buffer_by_offset (buffer_p, + buffer_size, + &header_offset, + &header, + sizeof (header)); + + if (lit_map_p != NULL) { - 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; + 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); diff --git a/jerry-core/jrt/jrt.h b/jerry-core/jrt/jrt.h index 5b0a496de4..99090c25e6 100644 --- a/jerry-core/jrt/jrt.h +++ b/jerry-core/jrt/jrt.h @@ -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 diff --git a/jerry-core/parser/js/byte-code.h b/jerry-core/parser/js/byte-code.h index f01c39263f..8a6c471de1 100644 --- a/jerry-core/parser/js/byte-code.h +++ b/jerry-core/parser/js/byte-code.h @@ -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 */ diff --git a/jerry-core/parser/js/common.c b/jerry-core/parser/js/common.c index e17e995db4..6adf3ef023 100644 --- a/jerry-core/parser/js/common.c +++ b/jerry-core/parser/js/common.c @@ -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) diff --git a/jerry-core/parser/js/common.h b/jerry-core/parser/js/common.h index 51df8a8c25..ae7e015907 100644 --- a/jerry-core/parser/js/common.h +++ b/jerry-core/parser/js/common.h @@ -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. */ diff --git a/jerry-core/parser/js/js-lexer.c b/jerry-core/parser/js/js-lexer.c index c155bef426..c99dcb1ecc 100644 --- a/jerry-core/parser/js/js-lexer.c +++ b/jerry-core/parser/js/js-lexer.c @@ -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; diff --git a/jerry-core/parser/js/js-parser-internal.h b/jerry-core/parser/js/js-parser-internal.h index 57c971fa5b..a9fb1f37ee 100644 --- a/jerry-core/parser/js/js-parser-internal.h +++ b/jerry-core/parser/js/js-parser-internal.h @@ -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. */ diff --git a/jerry-core/parser/js/js-parser-limits.h b/jerry-core/parser/js/js-parser-limits.h index c95497f320..f2ea21666b 100644 --- a/jerry-core/parser/js/js-parser-limits.h +++ b/jerry-core/parser/js/js-parser-limits.h @@ -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. diff --git a/jerry-core/parser/js/js-parser-mem.c b/jerry-core/parser/js/js-parser-mem.c index 950e3abe74..90abb59697 100644 --- a/jerry-core/parser/js/js-parser-mem.c +++ b/jerry-core/parser/js/js-parser-mem.c @@ -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 */ diff --git a/jerry-core/parser/js/js-parser-statm.c b/jerry-core/parser/js/js-parser-statm.c index e81166a406..d5949194fc 100644 --- a/jerry-core/parser/js/js-parser-statm.c +++ b/jerry-core/parser/js/js-parser-statm.c @@ -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; } } diff --git a/jerry-core/parser/js/js-parser-util.c b/jerry-core/parser/js/js-parser-util.c index 5c870061b3..14ae1d896e 100644 --- a/jerry-core/parser/js/js-parser-util.c +++ b/jerry-core/parser/js/js-parser-util.c @@ -619,7 +619,7 @@ parser_set_breaks_to_current_position (parser_context_t *context_p, /**< context { parser_set_branch_to_current_position (context_p, ¤t_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 */ diff --git a/jerry-core/parser/js/js-parser.c b/jerry-core/parser/js/js-parser.c index d37c06e5d4..1cbe78171e 100644 --- a/jerry-core/parser/js/js-parser.c +++ b/jerry-core/parser/js/js-parser.c @@ -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) diff --git a/jerry-core/parser/regexp/re-bytecode.c b/jerry-core/parser/regexp/re-bytecode.c index 5def85a58e..e9047f30b0 100644 --- a/jerry-core/parser/regexp/re-bytecode.c +++ b/jerry-core/parser/regexp/re-bytecode.c @@ -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); diff --git a/jerry-core/parser/regexp/re-bytecode.h b/jerry-core/parser/regexp/re-bytecode.h index 7c8df26667..2607e5fa99 100644 --- a/jerry-core/parser/regexp/re-bytecode.h +++ b/jerry-core/parser/regexp/re-bytecode.h @@ -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 */ diff --git a/jerry-core/parser/regexp/re-compiler.c b/jerry-core/parser/regexp/re-compiler.c index b6062c256f..6e5db4d28c 100644 --- a/jerry-core/parser/regexp/re-compiler.c +++ b/jerry-core/parser/regexp/re-compiler.c @@ -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)