Rework literal storage.
The new literal storage keeps ecma strings rather than having a custom string implementation which duplicates the string management routines. Conversions between string implementations are eliminated which improved the performance by 4%. JerryScript-DCO-1.0-Signed-off-by: Zoltan Herczeg zherczeg.u-szeged@partner.samsung.com
This commit is contained in:
@@ -809,7 +809,6 @@ typedef struct
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
ECMA_STRING_CONTAINER_LIT_TABLE, /**< actual data is in literal table */
|
||||
ECMA_STRING_CONTAINER_HEAP_ASCII_STRING, /**< actual data is on the heap as an ascii string */
|
||||
ECMA_STRING_CONTAINER_HEAP_UTF8_STRING, /**< actual data is on the heap as an utf-8 string */
|
||||
ECMA_STRING_CONTAINER_UINT32_IN_DESC, /**< actual data is UInt32-represeneted Number
|
||||
@@ -817,7 +816,11 @@ typedef enum
|
||||
ECMA_STRING_CONTAINER_MAGIC_STRING, /**< the ecma-string is equal to one of ECMA magic strings */
|
||||
ECMA_STRING_CONTAINER_MAGIC_STRING_EX, /**< the ecma-string is equal to one of external magic strings */
|
||||
|
||||
ECMA_STRING_CONTAINER__MAX = ECMA_STRING_CONTAINER_MAGIC_STRING_EX /**< maximum value */
|
||||
ECMA_STRING_LITERAL_NUMBER, /**< a literal number which is used solely by the literal storage
|
||||
* so no string processing function supports this type except
|
||||
* the ecma_deref_ecma_string function. */
|
||||
|
||||
ECMA_STRING_CONTAINER__MAX = ECMA_STRING_LITERAL_NUMBER /**< maximum value */
|
||||
} ecma_string_container_t;
|
||||
|
||||
/**
|
||||
@@ -847,6 +850,12 @@ typedef enum
|
||||
#define ECMA_STRING_GET_CONTAINER(string_desc_p) \
|
||||
((ecma_string_container_t) ((string_desc_p)->refs_and_container & ECMA_STRING_CONTAINER_MASK))
|
||||
|
||||
/**
|
||||
* Checks whether the reference counter is 1.
|
||||
*/
|
||||
#define ECMA_STRING_IS_REF_EQUALS_TO_ONE(string_desc_p) \
|
||||
(((string_desc_p)->refs_and_container >> 3) == 1)
|
||||
|
||||
/**
|
||||
* ECMA string-value descriptor
|
||||
*/
|
||||
@@ -892,6 +901,9 @@ typedef struct ecma_string_t
|
||||
/** Identifier of external magic string */
|
||||
lit_magic_string_ex_id_t magic_string_ex_id;
|
||||
|
||||
/** Literal number */
|
||||
ecma_value_t lit_number;
|
||||
|
||||
/** For zeroing and comparison in some cases */
|
||||
uint32_t common_field;
|
||||
} u;
|
||||
|
||||
@@ -22,10 +22,7 @@
|
||||
#include "jrt.h"
|
||||
#include "jrt-libc-includes.h"
|
||||
#include "lit-char-helpers.h"
|
||||
#include "lit-literal.h"
|
||||
#include "lit-magic-strings.h"
|
||||
#include "lit-literal-storage.h"
|
||||
#include "vm.h"
|
||||
|
||||
/** \addtogroup ecma ECMA
|
||||
* @{
|
||||
@@ -72,9 +69,6 @@ typedef struct
|
||||
uint16_t length; /* Number of characters in the string */
|
||||
} ecma_string_heap_header_t;
|
||||
|
||||
static void
|
||||
ecma_init_ecma_string_from_lit_cp (ecma_string_t *string_p,
|
||||
lit_cpointer_t lit_index);
|
||||
static void
|
||||
ecma_init_ecma_string_from_magic_string_id (ecma_string_t *string_p,
|
||||
lit_magic_string_id_t magic_string_id);
|
||||
@@ -83,39 +77,6 @@ static void
|
||||
ecma_init_ecma_string_from_magic_string_ex_id (ecma_string_t *string_p,
|
||||
lit_magic_string_ex_id_t magic_string_ex_id);
|
||||
|
||||
/**
|
||||
* Initialize ecma-string descriptor with string described by index in literal table
|
||||
*/
|
||||
static void
|
||||
ecma_init_ecma_string_from_lit_cp (ecma_string_t *string_p, /**< descriptor to initialize */
|
||||
lit_cpointer_t lit_cp) /**< compressed pointer to literal */
|
||||
{
|
||||
lit_literal_t lit = lit_cpointer_decompress (lit_cp);
|
||||
|
||||
if (LIT_RECORD_IS_MAGIC_STR (lit))
|
||||
{
|
||||
ecma_init_ecma_string_from_magic_string_id (string_p,
|
||||
lit_magic_literal_get_magic_str_id (lit));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (LIT_RECORD_IS_MAGIC_STR_EX (lit))
|
||||
{
|
||||
ecma_init_ecma_string_from_magic_string_ex_id (string_p,
|
||||
lit_magic_literal_get_magic_str_ex_id (lit));
|
||||
return;
|
||||
}
|
||||
|
||||
JERRY_ASSERT (LIT_RECORD_IS_CHARSET (lit));
|
||||
|
||||
string_p->refs_and_container = ECMA_STRING_CONTAINER_LIT_TABLE | ECMA_STRING_REF_ONE;
|
||||
string_p->hash = lit_charset_literal_get_hash (lit);
|
||||
|
||||
string_p->u.common_field = 0;
|
||||
string_p->u.lit_cp = lit_cp;
|
||||
} /* ecma_init_ecma_string_from_lit_cp */
|
||||
|
||||
/**
|
||||
* Initialize ecma-string descriptor with specified magic string
|
||||
*/
|
||||
@@ -320,21 +281,6 @@ ecma_new_ecma_string_from_number (ecma_number_t num) /**< ecma-number */
|
||||
return string_desc_p;
|
||||
} /* ecma_new_ecma_string_from_number */
|
||||
|
||||
/**
|
||||
* Allocate new ecma-string and fill it with reference to string literal
|
||||
*
|
||||
* @return pointer to ecma-string descriptor
|
||||
*/
|
||||
ecma_string_t *
|
||||
ecma_new_ecma_string_from_lit_cp (lit_cpointer_t lit_cp) /**< index in the literal table */
|
||||
{
|
||||
ecma_string_t *string_desc_p = ecma_alloc_string ();
|
||||
|
||||
ecma_init_ecma_string_from_lit_cp (string_desc_p, lit_cp);
|
||||
|
||||
return string_desc_p;
|
||||
} /* ecma_new_ecma_string_from_lit_cp */
|
||||
|
||||
/**
|
||||
* Allocate new ecma-string and fill it with reference to ECMA magic string
|
||||
*
|
||||
@@ -502,7 +448,6 @@ ecma_deref_ecma_string (ecma_string_t *string_p) /**< ecma-string */
|
||||
|
||||
break;
|
||||
}
|
||||
case ECMA_STRING_CONTAINER_LIT_TABLE:
|
||||
case ECMA_STRING_CONTAINER_UINT32_IN_DESC:
|
||||
case ECMA_STRING_CONTAINER_MAGIC_STRING:
|
||||
case ECMA_STRING_CONTAINER_MAGIC_STRING_EX:
|
||||
@@ -510,6 +455,15 @@ ecma_deref_ecma_string (ecma_string_t *string_p) /**< ecma-string */
|
||||
/* only the string descriptor itself should be freed */
|
||||
break;
|
||||
}
|
||||
case ECMA_STRING_LITERAL_NUMBER:
|
||||
{
|
||||
ecma_fast_free_value (string_p->u.lit_number);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
JERRY_UNREACHABLE ();
|
||||
}
|
||||
}
|
||||
|
||||
ecma_dealloc_string (string_p);
|
||||
@@ -532,7 +486,6 @@ ecma_string_to_number (const ecma_string_t *str_p) /**< ecma-string */
|
||||
return ((ecma_number_t) uint32_number);
|
||||
}
|
||||
|
||||
case ECMA_STRING_CONTAINER_LIT_TABLE:
|
||||
case ECMA_STRING_CONTAINER_HEAP_UTF8_STRING:
|
||||
case ECMA_STRING_CONTAINER_HEAP_ASCII_STRING:
|
||||
case ECMA_STRING_CONTAINER_MAGIC_STRING:
|
||||
@@ -553,9 +506,12 @@ ecma_string_to_number (const ecma_string_t *str_p) /**< ecma-string */
|
||||
|
||||
return num;
|
||||
}
|
||||
}
|
||||
|
||||
JERRY_UNREACHABLE ();
|
||||
default:
|
||||
{
|
||||
JERRY_UNREACHABLE ();
|
||||
}
|
||||
}
|
||||
} /* ecma_string_to_number */
|
||||
|
||||
/**
|
||||
@@ -628,14 +584,6 @@ ecma_string_copy_to_utf8_buffer (const ecma_string_t *string_desc_p, /**< ecma-s
|
||||
memcpy (buffer_p, data_p, size);
|
||||
break;
|
||||
}
|
||||
case ECMA_STRING_CONTAINER_LIT_TABLE:
|
||||
{
|
||||
const lit_literal_t lit = lit_get_literal_by_cp (string_desc_p->u.lit_cp);
|
||||
JERRY_ASSERT (LIT_RECORD_IS_CHARSET (lit));
|
||||
size = lit_charset_literal_get_size (lit);
|
||||
memcpy (buffer_p, lit_charset_literal_get_charset (lit), size);
|
||||
break;
|
||||
}
|
||||
case ECMA_STRING_CONTAINER_UINT32_IN_DESC:
|
||||
{
|
||||
const uint32_t uint32_number = string_desc_p->u.uint32_number;
|
||||
@@ -762,16 +710,6 @@ ecma_string_raw_chars (const ecma_string_t *string_p, /**< ecma-string */
|
||||
|
||||
switch (ECMA_STRING_GET_CONTAINER (string_p))
|
||||
{
|
||||
case ECMA_STRING_CONTAINER_LIT_TABLE:
|
||||
{
|
||||
lit_literal_t lit = lit_get_literal_by_cp (string_p->u.lit_cp);
|
||||
JERRY_ASSERT (LIT_RECORD_IS_CHARSET (lit));
|
||||
|
||||
length = lit_charset_literal_get_length (lit);
|
||||
size = lit_charset_literal_get_size (lit);
|
||||
result_p = lit_charset_literal_get_charset (lit);
|
||||
break;
|
||||
}
|
||||
case ECMA_STRING_CONTAINER_HEAP_UTF8_STRING:
|
||||
{
|
||||
const ecma_string_heap_header_t *data_p = ECMA_GET_NON_NULL_POINTER (ecma_string_heap_header_t,
|
||||
@@ -861,11 +799,6 @@ ecma_compare_ecma_strings_longpath (const ecma_string_t *string1_p, /* ecma-stri
|
||||
{
|
||||
switch (ECMA_STRING_GET_CONTAINER (string1_p))
|
||||
{
|
||||
case ECMA_STRING_CONTAINER_LIT_TABLE:
|
||||
{
|
||||
JERRY_ASSERT (string1_p->u.lit_cp != string2_p->u.lit_cp);
|
||||
return false;
|
||||
}
|
||||
case ECMA_STRING_CONTAINER_MAGIC_STRING:
|
||||
{
|
||||
JERRY_ASSERT (string1_p->u.magic_string_id != string2_p->u.magic_string_id);
|
||||
@@ -958,13 +891,6 @@ ecma_compare_ecma_strings_longpath (const ecma_string_t *string1_p, /* ecma-stri
|
||||
|
||||
utf8_string1_p = data_p;
|
||||
}
|
||||
else if (ECMA_STRING_GET_CONTAINER (string1_p) == ECMA_STRING_CONTAINER_LIT_TABLE)
|
||||
{
|
||||
const lit_literal_t lit = lit_get_literal_by_cp (string1_p->u.lit_cp);
|
||||
JERRY_ASSERT (LIT_RECORD_IS_CHARSET (lit));
|
||||
|
||||
utf8_string1_p = (lit_utf8_byte_t *) lit_charset_literal_get_charset (lit);
|
||||
}
|
||||
else
|
||||
{
|
||||
utf8_string1_p = (lit_utf8_byte_t *) jmem_heap_alloc_block ((size_t) strings_size);
|
||||
@@ -988,13 +914,6 @@ ecma_compare_ecma_strings_longpath (const ecma_string_t *string1_p, /* ecma-stri
|
||||
|
||||
utf8_string2_p = data_p;
|
||||
}
|
||||
else if (ECMA_STRING_GET_CONTAINER (string2_p) == ECMA_STRING_CONTAINER_LIT_TABLE)
|
||||
{
|
||||
const lit_literal_t lit = lit_get_literal_by_cp (string2_p->u.lit_cp);
|
||||
JERRY_ASSERT (LIT_RECORD_IS_CHARSET (lit));
|
||||
|
||||
utf8_string2_p = (lit_utf8_byte_t *) lit_charset_literal_get_charset (lit);
|
||||
}
|
||||
else
|
||||
{
|
||||
utf8_string2_p = (lit_utf8_byte_t *) jmem_heap_alloc_block ((size_t) strings_size);
|
||||
@@ -1088,14 +1007,6 @@ ecma_compare_ecma_strings_relational (const ecma_string_t *string1_p, /**< ecma-
|
||||
utf8_string1_p = data_p;
|
||||
utf8_string1_size = (lit_utf8_size_t) string1_p->u.ascii_string.size;
|
||||
}
|
||||
else if (ECMA_STRING_GET_CONTAINER (string1_p) == ECMA_STRING_CONTAINER_LIT_TABLE)
|
||||
{
|
||||
const lit_literal_t lit = lit_get_literal_by_cp (string1_p->u.lit_cp);
|
||||
JERRY_ASSERT (LIT_RECORD_IS_CHARSET (lit));
|
||||
|
||||
utf8_string1_p = (lit_utf8_byte_t *) lit_charset_literal_get_charset (lit);
|
||||
utf8_string1_size = (lit_utf8_size_t) lit_charset_literal_get_size (lit);
|
||||
}
|
||||
else
|
||||
{
|
||||
utf8_string1_size = ecma_string_get_size (string1_p);
|
||||
@@ -1129,14 +1040,6 @@ ecma_compare_ecma_strings_relational (const ecma_string_t *string1_p, /**< ecma-
|
||||
utf8_string2_p = data_p;
|
||||
utf8_string2_size = (lit_utf8_size_t) string2_p->u.ascii_string.size;
|
||||
}
|
||||
else if (ECMA_STRING_GET_CONTAINER (string2_p) == ECMA_STRING_CONTAINER_LIT_TABLE)
|
||||
{
|
||||
const lit_literal_t lit = lit_get_literal_by_cp (string2_p->u.lit_cp);
|
||||
JERRY_ASSERT (LIT_RECORD_IS_CHARSET (lit));
|
||||
|
||||
utf8_string2_p = (lit_utf8_byte_t *) lit_charset_literal_get_charset (lit);
|
||||
utf8_string2_size = (lit_utf8_size_t) lit_charset_literal_get_size (lit);
|
||||
}
|
||||
else
|
||||
{
|
||||
utf8_string2_size = ecma_string_get_size (string2_p);
|
||||
@@ -1182,12 +1085,6 @@ ecma_string_get_length (const ecma_string_t *string_p) /**< ecma-string */
|
||||
{
|
||||
switch (ECMA_STRING_GET_CONTAINER (string_p))
|
||||
{
|
||||
case ECMA_STRING_CONTAINER_LIT_TABLE:
|
||||
{
|
||||
lit_literal_t lit = lit_get_literal_by_cp (string_p->u.lit_cp);
|
||||
JERRY_ASSERT (LIT_RECORD_IS_CHARSET (lit));
|
||||
return lit_charset_literal_get_length (lit);
|
||||
}
|
||||
case ECMA_STRING_CONTAINER_MAGIC_STRING:
|
||||
{
|
||||
JERRY_ASSERT (ECMA_STRING_IS_ASCII (lit_get_magic_string_utf8 (string_p->u.magic_string_id),
|
||||
@@ -1229,13 +1126,6 @@ ecma_string_get_size (const ecma_string_t *string_p) /**< ecma-string */
|
||||
{
|
||||
switch (ECMA_STRING_GET_CONTAINER (string_p))
|
||||
{
|
||||
case ECMA_STRING_CONTAINER_LIT_TABLE:
|
||||
{
|
||||
lit_literal_t lit = lit_get_literal_by_cp (string_p->u.lit_cp);
|
||||
JERRY_ASSERT (LIT_RECORD_IS_CHARSET (lit));
|
||||
|
||||
return lit_charset_literal_get_size (lit);
|
||||
}
|
||||
case ECMA_STRING_CONTAINER_MAGIC_STRING:
|
||||
{
|
||||
return lit_get_magic_string_size (string_p->u.magic_string_id);
|
||||
|
||||
@@ -1429,14 +1429,14 @@ ecma_bytecode_deref (ecma_compiled_code_t *bytecode_p) /**< byte code pointer */
|
||||
|
||||
if (bytecode_p->status_flags & CBC_CODE_FLAGS_FUNCTION)
|
||||
{
|
||||
lit_cpointer_t *literal_start_p = NULL;
|
||||
jmem_cpointer_t *literal_start_p = NULL;
|
||||
uint32_t literal_end;
|
||||
uint32_t const_literal_end;
|
||||
|
||||
if (bytecode_p->status_flags & CBC_CODE_FLAGS_UINT16_ARGUMENTS)
|
||||
{
|
||||
uint8_t *byte_p = (uint8_t *) bytecode_p;
|
||||
literal_start_p = (lit_cpointer_t *) (byte_p + sizeof (cbc_uint16_arguments_t));
|
||||
literal_start_p = (jmem_cpointer_t *) (byte_p + sizeof (cbc_uint16_arguments_t));
|
||||
|
||||
cbc_uint16_arguments_t *args_p = (cbc_uint16_arguments_t *) bytecode_p;
|
||||
literal_end = args_p->literal_end;
|
||||
@@ -1445,7 +1445,7 @@ ecma_bytecode_deref (ecma_compiled_code_t *bytecode_p) /**< byte code pointer */
|
||||
else
|
||||
{
|
||||
uint8_t *byte_p = (uint8_t *) bytecode_p;
|
||||
literal_start_p = (lit_cpointer_t *) (byte_p + sizeof (cbc_uint8_arguments_t));
|
||||
literal_start_p = (jmem_cpointer_t *) (byte_p + sizeof (cbc_uint8_arguments_t));
|
||||
|
||||
cbc_uint8_arguments_t *args_p = (cbc_uint8_arguments_t *) bytecode_p;
|
||||
literal_end = args_p->literal_end;
|
||||
|
||||
@@ -19,7 +19,6 @@
|
||||
|
||||
#include "ecma-globals.h"
|
||||
#include "jmem-allocator.h"
|
||||
#include "lit-cpointer.h"
|
||||
#include "lit-strings.h"
|
||||
|
||||
/** \addtogroup ecma ECMA
|
||||
@@ -165,7 +164,6 @@ extern ecma_string_t *ecma_new_ecma_string_from_utf8 (const lit_utf8_byte_t *, l
|
||||
extern ecma_string_t *ecma_new_ecma_string_from_code_unit (ecma_char_t);
|
||||
extern ecma_string_t *ecma_new_ecma_string_from_uint32 (uint32_t);
|
||||
extern ecma_string_t *ecma_new_ecma_string_from_number (ecma_number_t);
|
||||
extern ecma_string_t *ecma_new_ecma_string_from_lit_cp (lit_cpointer_t);
|
||||
extern ecma_string_t *ecma_new_ecma_string_from_magic_string_id (lit_magic_string_id_t);
|
||||
extern ecma_string_t *ecma_new_ecma_string_from_magic_string_ex_id (lit_magic_string_ex_id_t);
|
||||
extern ecma_string_t *ecma_concat_ecma_strings (ecma_string_t *, ecma_string_t *);
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
#include "ecma-init-finalize.h"
|
||||
#include "ecma-lcache.h"
|
||||
#include "ecma-lex-env.h"
|
||||
#include "ecma-literal-storage.h"
|
||||
#include "jmem-allocator.h"
|
||||
|
||||
/** \addtogroup ecma ECMA
|
||||
@@ -37,6 +38,7 @@ ecma_init (void)
|
||||
ecma_gc_init ();
|
||||
ecma_init_builtins ();
|
||||
ecma_lcache_init ();
|
||||
ecma_init_lit_storage ();
|
||||
ecma_init_environment ();
|
||||
|
||||
jmem_register_free_unused_memory_callback (ecma_free_unused_memory);
|
||||
@@ -53,6 +55,7 @@ ecma_finalize (void)
|
||||
ecma_finalize_environment ();
|
||||
ecma_finalize_builtins ();
|
||||
ecma_gc_run ();
|
||||
ecma_finalize_lit_storage ();
|
||||
} /* ecma_finalize */
|
||||
|
||||
/**
|
||||
|
||||
@@ -0,0 +1,541 @@
|
||||
/* Copyright 2016 Samsung Electronics Co., Ltd.
|
||||
* Copyright 2016 University of Szeged.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "ecma-literal-storage.h"
|
||||
#include "ecma-helpers.h"
|
||||
|
||||
/** \addtogroup ecma ECMA
|
||||
* @{
|
||||
*
|
||||
* \addtogroup ecmalitstorage Literal storage
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* Number of values in a literal storage item
|
||||
*/
|
||||
#define ECMA_LIT_STORAGE_VALUE_COUNT 3
|
||||
|
||||
/**
|
||||
* Literal storage item
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
jmem_cpointer_t next_cp; /**< cpointer ot next item */
|
||||
jmem_cpointer_t values[ECMA_LIT_STORAGE_VALUE_COUNT]; /**< list of values */
|
||||
} ecma_lit_storage_item_t;
|
||||
|
||||
JERRY_STATIC_ASSERT (sizeof (ecma_lit_storage_item_t) <= sizeof (uint64_t),
|
||||
size_of_ecma_lit_storage_item_t_must_be_less_than_or_equal_to_8_bytes);
|
||||
|
||||
static ecma_lit_storage_item_t *string_list_first_p;
|
||||
static ecma_lit_storage_item_t *number_list_first_p;
|
||||
|
||||
/**
|
||||
* Initialize literal storage
|
||||
*/
|
||||
void
|
||||
ecma_init_lit_storage (void)
|
||||
{
|
||||
string_list_first_p = NULL;
|
||||
number_list_first_p = NULL;
|
||||
} /* ecma_init_lit_storage */
|
||||
|
||||
/**
|
||||
* Free string list
|
||||
*/
|
||||
static void
|
||||
ecma_free_string_list (ecma_lit_storage_item_t *string_list_p) /**< string list */
|
||||
{
|
||||
while (string_list_p != NULL)
|
||||
{
|
||||
for (int i = 0; i < ECMA_LIT_STORAGE_VALUE_COUNT; i++)
|
||||
{
|
||||
if (string_list_p->values[i] != JMEM_CP_NULL)
|
||||
{
|
||||
ecma_string_t *string_p = JMEM_CP_GET_NON_NULL_POINTER (ecma_string_t,
|
||||
string_list_p->values[i]);
|
||||
|
||||
JERRY_ASSERT (ECMA_STRING_IS_REF_EQUALS_TO_ONE (string_p));
|
||||
ecma_deref_ecma_string (string_p);
|
||||
}
|
||||
}
|
||||
|
||||
ecma_lit_storage_item_t *prev_item = string_list_p;
|
||||
string_list_p = JMEM_CP_GET_POINTER (ecma_lit_storage_item_t, string_list_p->next_cp);
|
||||
jmem_pools_free (prev_item);
|
||||
}
|
||||
} /* ecma_free_string_list */
|
||||
|
||||
/**
|
||||
* Finalize literal storage
|
||||
*/
|
||||
void
|
||||
ecma_finalize_lit_storage (void)
|
||||
{
|
||||
ecma_free_string_list (string_list_first_p);
|
||||
ecma_free_string_list (number_list_first_p);
|
||||
} /* ecma_finalize_lit_storage */
|
||||
|
||||
/**
|
||||
* Find or create a literal string.
|
||||
*
|
||||
* @return ecma_string_t compressed pointer
|
||||
*/
|
||||
jmem_cpointer_t
|
||||
ecma_find_or_create_literal_string (const lit_utf8_byte_t *chars_p, /**< string to be searched */
|
||||
lit_utf8_size_t size) /**< size of the string */
|
||||
{
|
||||
ecma_string_t *string_p = ecma_new_ecma_string_from_utf8 (chars_p, size);
|
||||
|
||||
ecma_lit_storage_item_t *string_list_p = string_list_first_p;
|
||||
jmem_cpointer_t *empty_cpointer_p = NULL;
|
||||
|
||||
while (string_list_p != NULL)
|
||||
{
|
||||
for (int i = 0; i < ECMA_LIT_STORAGE_VALUE_COUNT; i++)
|
||||
{
|
||||
if (string_list_p->values[i] == JMEM_CP_NULL)
|
||||
{
|
||||
if (empty_cpointer_p == NULL)
|
||||
{
|
||||
empty_cpointer_p = string_list_p->values + i;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ecma_string_t *value_p = JMEM_CP_GET_NON_NULL_POINTER (ecma_string_t,
|
||||
string_list_p->values[i]);
|
||||
|
||||
if (ecma_compare_ecma_strings (string_p, value_p))
|
||||
{
|
||||
/* Return with string if found in the list. */
|
||||
ecma_deref_ecma_string (string_p);
|
||||
return string_list_p->values[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
string_list_p = JMEM_CP_GET_POINTER (ecma_lit_storage_item_t, string_list_p->next_cp);
|
||||
}
|
||||
|
||||
jmem_cpointer_t result;
|
||||
JMEM_CP_SET_NON_NULL_POINTER (result, string_p);
|
||||
|
||||
if (empty_cpointer_p != NULL)
|
||||
{
|
||||
*empty_cpointer_p = result;
|
||||
return result;
|
||||
}
|
||||
|
||||
ecma_lit_storage_item_t *new_item_p = (ecma_lit_storage_item_t *) jmem_pools_alloc ();
|
||||
|
||||
new_item_p->values[0] = result;
|
||||
for (int i = 1; i < ECMA_LIT_STORAGE_VALUE_COUNT; i++)
|
||||
{
|
||||
new_item_p->values[i] = JMEM_CP_NULL;
|
||||
}
|
||||
|
||||
JMEM_CP_SET_POINTER (new_item_p->next_cp, string_list_first_p);
|
||||
string_list_first_p = new_item_p;
|
||||
|
||||
return result;
|
||||
} /* ecma_find_or_create_literal_string */
|
||||
|
||||
/**
|
||||
* Find or create a literal number.
|
||||
*
|
||||
* @return ecma_string_t compressed pointer
|
||||
*/
|
||||
jmem_cpointer_t
|
||||
ecma_find_or_create_literal_number (ecma_number_t number_arg) /**< number to be searched */
|
||||
{
|
||||
ecma_value_t num = ecma_make_number_value (number_arg);
|
||||
|
||||
ecma_lit_storage_item_t *number_list_p = number_list_first_p;
|
||||
jmem_cpointer_t *empty_cpointer_p = NULL;
|
||||
|
||||
while (number_list_p != NULL)
|
||||
{
|
||||
for (int i = 0; i < ECMA_LIT_STORAGE_VALUE_COUNT; i++)
|
||||
{
|
||||
if (number_list_p->values[i] == JMEM_CP_NULL)
|
||||
{
|
||||
if (empty_cpointer_p == NULL)
|
||||
{
|
||||
empty_cpointer_p = number_list_p->values + i;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ecma_string_t *value_p = JMEM_CP_GET_NON_NULL_POINTER (ecma_string_t,
|
||||
number_list_p->values[i]);
|
||||
|
||||
JERRY_ASSERT (ECMA_STRING_GET_CONTAINER (value_p) == ECMA_STRING_LITERAL_NUMBER);
|
||||
|
||||
if (ecma_is_value_integer_number (num))
|
||||
{
|
||||
if (value_p->u.lit_number == num)
|
||||
{
|
||||
return number_list_p->values[i];
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (ecma_is_value_float_number (value_p->u.lit_number)
|
||||
&& ecma_get_float_from_value (value_p->u.lit_number) == ecma_get_float_from_value (num))
|
||||
{
|
||||
ecma_free_value (num);
|
||||
return number_list_p->values[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
number_list_p = JMEM_CP_GET_POINTER (ecma_lit_storage_item_t, number_list_p->next_cp);
|
||||
}
|
||||
|
||||
ecma_string_t *string_p = (ecma_string_t *) jmem_pools_alloc ();
|
||||
string_p->refs_and_container = ECMA_STRING_REF_ONE | ECMA_STRING_LITERAL_NUMBER;
|
||||
string_p->u.lit_number = num;
|
||||
|
||||
jmem_cpointer_t result;
|
||||
JMEM_CP_SET_NON_NULL_POINTER (result, string_p);
|
||||
|
||||
if (empty_cpointer_p != NULL)
|
||||
{
|
||||
*empty_cpointer_p = result;
|
||||
return result;
|
||||
}
|
||||
|
||||
ecma_lit_storage_item_t *new_item_p = (ecma_lit_storage_item_t *) jmem_pools_alloc ();
|
||||
|
||||
new_item_p->values[0] = result;
|
||||
for (int i = 1; i < ECMA_LIT_STORAGE_VALUE_COUNT; i++)
|
||||
{
|
||||
new_item_p->values[i] = JMEM_CP_NULL;
|
||||
}
|
||||
|
||||
JMEM_CP_SET_POINTER (new_item_p->next_cp, number_list_first_p);
|
||||
number_list_first_p = new_item_p;
|
||||
|
||||
return result;
|
||||
} /* ecma_find_or_create_literal_number */
|
||||
|
||||
/**
|
||||
* Log2 of snapshot literal alignment.
|
||||
*/
|
||||
#define JERRY_SNAPSHOT_LITERAL_ALIGNMENT_LOG 2
|
||||
|
||||
/**
|
||||
* Snapshot literal alignment.
|
||||
*/
|
||||
#define JERRY_SNAPSHOT_LITERAL_ALIGNMENT (1u << JERRY_SNAPSHOT_LITERAL_ALIGNMENT_LOG)
|
||||
|
||||
#ifdef JERRY_ENABLE_SNAPSHOT_SAVE
|
||||
|
||||
/**
|
||||
* Save literals to specified snapshot buffer.
|
||||
*
|
||||
* @return true, if save was performed successfully (i.e. buffer size is sufficient),
|
||||
* false - otherwise.
|
||||
*/
|
||||
bool
|
||||
ecma_save_literals_for_snapshot (uint8_t *buffer_p, /**< [out] output snapshot buffer */
|
||||
size_t buffer_size, /**< size of the buffer */
|
||||
size_t *in_out_buffer_offset_p, /**< [in,out] write position in the buffer */
|
||||
lit_mem_to_snapshot_id_map_entry_t **out_map_p, /**< [out] map from literal identifiers
|
||||
* to the literal offsets
|
||||
* in snapshot */
|
||||
uint32_t *out_map_len_p, /**< [out] number of literals */
|
||||
uint32_t *out_lit_table_size_p) /**< [out] number of bytes, saved to snapshot buffer */
|
||||
{
|
||||
/* Count literals and literal space. */
|
||||
uint32_t string_count = 0;
|
||||
uint32_t number_count = 0;
|
||||
uint32_t lit_table_size = 2 * sizeof (uint32_t);
|
||||
|
||||
ecma_lit_storage_item_t *string_list_p = string_list_first_p;
|
||||
|
||||
while (string_list_p != NULL)
|
||||
{
|
||||
for (int i = 0; i < ECMA_LIT_STORAGE_VALUE_COUNT; i++)
|
||||
{
|
||||
if (string_list_p->values[i] != JMEM_CP_NULL)
|
||||
{
|
||||
ecma_string_t *string_p = JMEM_CP_GET_NON_NULL_POINTER (ecma_string_t,
|
||||
string_list_p->values[i]);
|
||||
|
||||
lit_table_size += (uint32_t) JERRY_ALIGNUP (sizeof (uint16_t) + ecma_string_get_size (string_p),
|
||||
JERRY_SNAPSHOT_LITERAL_ALIGNMENT);
|
||||
string_count++;
|
||||
}
|
||||
}
|
||||
|
||||
string_list_p = JMEM_CP_GET_POINTER (ecma_lit_storage_item_t, string_list_p->next_cp);
|
||||
}
|
||||
|
||||
ecma_lit_storage_item_t *number_list_p = number_list_first_p;
|
||||
|
||||
while (number_list_p != NULL)
|
||||
{
|
||||
for (int i = 0; i < ECMA_LIT_STORAGE_VALUE_COUNT; i++)
|
||||
{
|
||||
if (number_list_p->values[i] != JMEM_CP_NULL)
|
||||
{
|
||||
lit_table_size += (uint32_t) sizeof (ecma_number_t);
|
||||
number_count++;
|
||||
}
|
||||
}
|
||||
|
||||
number_list_p = JMEM_CP_GET_POINTER (ecma_lit_storage_item_t, number_list_p->next_cp);
|
||||
}
|
||||
|
||||
/* Check whether enough space is available. */
|
||||
if (*in_out_buffer_offset_p + lit_table_size > buffer_size)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Check whether the maximum literal table size is reached. */
|
||||
if ((lit_table_size >> JERRY_SNAPSHOT_LITERAL_ALIGNMENT_LOG) > UINT16_MAX)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
uint32_t total_count = string_count + number_count;
|
||||
lit_mem_to_snapshot_id_map_entry_t *map_p;
|
||||
|
||||
map_p = jmem_heap_alloc_block (total_count * sizeof (lit_mem_to_snapshot_id_map_entry_t));
|
||||
|
||||
/* Set return values (no error is possible from here). */
|
||||
buffer_p += *in_out_buffer_offset_p;
|
||||
*in_out_buffer_offset_p += lit_table_size;
|
||||
*out_map_p = map_p;
|
||||
*out_map_len_p = total_count;
|
||||
*out_lit_table_size_p = lit_table_size;
|
||||
|
||||
/* Write data into the buffer. */
|
||||
|
||||
/* The zero value is reserved for NULL (no literal)
|
||||
* constant so the first literal must have offset one. */
|
||||
uint32_t literal_offset = JERRY_SNAPSHOT_LITERAL_ALIGNMENT;
|
||||
|
||||
((uint32_t *) buffer_p)[0] = string_count;
|
||||
((uint32_t *) buffer_p)[1] = number_count;
|
||||
buffer_p += 2 * sizeof (uint32_t);
|
||||
|
||||
string_list_p = string_list_first_p;
|
||||
|
||||
while (string_list_p != NULL)
|
||||
{
|
||||
for (int i = 0; i < ECMA_LIT_STORAGE_VALUE_COUNT; i++)
|
||||
{
|
||||
if (string_list_p->values[i] != JMEM_CP_NULL)
|
||||
{
|
||||
map_p->literal_id = string_list_p->values[i];
|
||||
map_p->literal_offset = (jmem_cpointer_t) (literal_offset >> JERRY_SNAPSHOT_LITERAL_ALIGNMENT_LOG);
|
||||
map_p++;
|
||||
|
||||
ecma_string_t *string_p = JMEM_CP_GET_NON_NULL_POINTER (ecma_string_t,
|
||||
string_list_p->values[i]);
|
||||
|
||||
ecma_length_t length = ecma_string_get_size (string_p);
|
||||
|
||||
*((uint16_t *) buffer_p) = (uint16_t) length;
|
||||
ecma_string_to_utf8_bytes (string_p, buffer_p + sizeof (uint16_t), length);
|
||||
|
||||
length = JERRY_ALIGNUP (sizeof (uint16_t) + length,
|
||||
JERRY_SNAPSHOT_LITERAL_ALIGNMENT);
|
||||
|
||||
buffer_p += length;
|
||||
literal_offset += length;
|
||||
}
|
||||
}
|
||||
|
||||
string_list_p = JMEM_CP_GET_POINTER (ecma_lit_storage_item_t, string_list_p->next_cp);
|
||||
}
|
||||
|
||||
number_list_p = number_list_first_p;
|
||||
|
||||
while (number_list_p != NULL)
|
||||
{
|
||||
for (int i = 0; i < ECMA_LIT_STORAGE_VALUE_COUNT; i++)
|
||||
{
|
||||
if (number_list_p->values[i] != JMEM_CP_NULL)
|
||||
{
|
||||
map_p->literal_id = number_list_p->values[i];
|
||||
map_p->literal_offset = (jmem_cpointer_t) (literal_offset >> JERRY_SNAPSHOT_LITERAL_ALIGNMENT_LOG);
|
||||
map_p++;
|
||||
|
||||
ecma_string_t *value_p = JMEM_CP_GET_NON_NULL_POINTER (ecma_string_t,
|
||||
number_list_p->values[i]);
|
||||
|
||||
JERRY_ASSERT (ECMA_STRING_GET_CONTAINER (value_p) == ECMA_STRING_LITERAL_NUMBER);
|
||||
|
||||
ecma_number_t num = ecma_get_number_from_value (value_p->u.lit_number);
|
||||
memcpy (buffer_p, &num, sizeof (ecma_number_t));
|
||||
|
||||
ecma_length_t length = JERRY_ALIGNUP (sizeof (ecma_number_t),
|
||||
JERRY_SNAPSHOT_LITERAL_ALIGNMENT);
|
||||
|
||||
buffer_p += length;
|
||||
literal_offset += length;
|
||||
}
|
||||
}
|
||||
|
||||
number_list_p = JMEM_CP_GET_POINTER (ecma_lit_storage_item_t, number_list_p->next_cp);
|
||||
}
|
||||
|
||||
return true;
|
||||
} /* ecma_save_literals_for_snapshot */
|
||||
|
||||
#endif /* JERRY_ENABLE_SNAPSHOT_SAVE */
|
||||
|
||||
#ifdef JERRY_ENABLE_SNAPSHOT_EXEC
|
||||
|
||||
/**
|
||||
* Helper function for ecma_load_literals_from_snapshot.
|
||||
*
|
||||
* Note: always inline because it is used only once.
|
||||
*
|
||||
* @return true, if load was performed successfully
|
||||
* false - otherwise (i.e. buffer length is incorrect).
|
||||
*/
|
||||
static inline bool __attr_always_inline___
|
||||
ecma_load_literals_from_buffer (const uint8_t *buffer_p, /**< buffer with literal table in snapshot */
|
||||
uint32_t lit_table_size, /**< size of literal table in snapshot */
|
||||
lit_mem_to_snapshot_id_map_entry_t *map_p, /**< literal map */
|
||||
uint32_t string_count, /**< number of strings */
|
||||
uint32_t number_count) /**< number of numbers */
|
||||
{
|
||||
/* The zero value is reserved for NULL (no literal)
|
||||
* constant so the first literal must have offset one. */
|
||||
uint32_t literal_offset = JERRY_SNAPSHOT_LITERAL_ALIGNMENT;
|
||||
|
||||
/* Load strings first. */
|
||||
while (string_count > 0)
|
||||
{
|
||||
if (lit_table_size < literal_offset + sizeof (uint32_t))
|
||||
{
|
||||
/* Buffer is not sufficent. */
|
||||
return false;
|
||||
}
|
||||
|
||||
lit_utf8_size_t length = *((uint16_t *) buffer_p);
|
||||
lit_utf8_size_t aligned_length = JERRY_ALIGNUP (sizeof (uint16_t) + length,
|
||||
JERRY_SNAPSHOT_LITERAL_ALIGNMENT);
|
||||
|
||||
if (lit_table_size < literal_offset + aligned_length)
|
||||
{
|
||||
/* Buffer is not sufficent. */
|
||||
return false;
|
||||
}
|
||||
|
||||
map_p->literal_id = ecma_find_or_create_literal_string (buffer_p + sizeof (uint16_t), length);
|
||||
map_p->literal_offset = (jmem_cpointer_t) (literal_offset >> JERRY_SNAPSHOT_LITERAL_ALIGNMENT_LOG);
|
||||
map_p++;
|
||||
|
||||
buffer_p += aligned_length;
|
||||
literal_offset += aligned_length;
|
||||
|
||||
string_count--;
|
||||
}
|
||||
|
||||
/* Load numbers. */
|
||||
while (number_count > 0)
|
||||
{
|
||||
if (lit_table_size < literal_offset + sizeof (ecma_number_t))
|
||||
{
|
||||
/* Buffer is not sufficent. */
|
||||
return false;
|
||||
}
|
||||
|
||||
ecma_number_t num;
|
||||
memcpy (&num, buffer_p, sizeof (ecma_number_t));
|
||||
|
||||
map_p->literal_id = ecma_find_or_create_literal_number (num);
|
||||
map_p->literal_offset = (jmem_cpointer_t) (literal_offset >> JERRY_SNAPSHOT_LITERAL_ALIGNMENT_LOG);
|
||||
map_p++;
|
||||
|
||||
ecma_length_t length = JERRY_ALIGNUP (sizeof (ecma_number_t),
|
||||
JERRY_SNAPSHOT_LITERAL_ALIGNMENT);
|
||||
|
||||
buffer_p += length;
|
||||
literal_offset += length;
|
||||
|
||||
number_count--;
|
||||
}
|
||||
|
||||
return (lit_table_size == (literal_offset + 2 * sizeof (uint32_t) - JERRY_SNAPSHOT_LITERAL_ALIGNMENT));
|
||||
} /* ecma_load_literals_from_buffer */
|
||||
|
||||
/**
|
||||
* Load literals from snapshot.
|
||||
*
|
||||
* @return true, if load was performed successfully (i.e. literals saved in the snapshot are consistent),
|
||||
* false - otherwise (i.e. snapshot is incorrect).
|
||||
*/
|
||||
bool
|
||||
ecma_load_literals_from_snapshot (const uint8_t *buffer_p, /**< buffer with literal table in snapshot */
|
||||
uint32_t lit_table_size, /**< size of literal table in snapshot */
|
||||
lit_mem_to_snapshot_id_map_entry_t **out_map_p, /**< [out] map from literal offsets
|
||||
* in snapshot to identifiers
|
||||
* of loaded literals in literal
|
||||
* storage */
|
||||
uint32_t *out_map_len_p) /**< [out] literals number */
|
||||
{
|
||||
*out_map_p = NULL;
|
||||
|
||||
if (lit_table_size < 2 * sizeof (uint32_t))
|
||||
{
|
||||
/* Buffer is not sufficent. */
|
||||
return false;
|
||||
}
|
||||
|
||||
uint32_t string_count = ((uint32_t *) buffer_p)[0];
|
||||
uint32_t number_count = ((uint32_t *) buffer_p)[1];
|
||||
buffer_p += 2 * sizeof (uint32_t);
|
||||
|
||||
uint32_t total_count = string_count + number_count;
|
||||
lit_mem_to_snapshot_id_map_entry_t *map_p;
|
||||
|
||||
*out_map_len_p = total_count;
|
||||
|
||||
if (total_count == 0)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
map_p = jmem_heap_alloc_block (total_count * sizeof (lit_mem_to_snapshot_id_map_entry_t));
|
||||
*out_map_p = map_p;
|
||||
|
||||
if (ecma_load_literals_from_buffer (buffer_p, lit_table_size, map_p, string_count, number_count))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
jmem_heap_free_block (map_p, total_count * sizeof (lit_mem_to_snapshot_id_map_entry_t));
|
||||
*out_map_p = NULL;
|
||||
return false;
|
||||
} /* ecma_load_literals_from_snapshot */
|
||||
|
||||
#endif /* JERRY_ENABLE_SNAPSHOT_EXEC */
|
||||
|
||||
/**
|
||||
* @}
|
||||
* @}
|
||||
*/
|
||||
@@ -0,0 +1,63 @@
|
||||
/* Copyright 2016 Samsung Electronics Co., Ltd.
|
||||
* Copyright 2016 University of Szeged.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef ECMA_LIT_STORAGE_H
|
||||
#define ECMA_LIT_STORAGE_H
|
||||
|
||||
#include "ecma-globals.h"
|
||||
#include "jmem-allocator.h"
|
||||
#include "lit-globals.h"
|
||||
|
||||
/** \addtogroup ecma ECMA
|
||||
* @{
|
||||
*
|
||||
* \addtogroup ecmalitstorage Literal storage
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* Snapshot literal - offset map
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
jmem_cpointer_t literal_id; /**< literal id */
|
||||
jmem_cpointer_t literal_offset; /**< literal offset */
|
||||
} lit_mem_to_snapshot_id_map_entry_t;
|
||||
|
||||
extern void ecma_init_lit_storage (void);
|
||||
extern void ecma_finalize_lit_storage (void);
|
||||
|
||||
extern jmem_cpointer_t ecma_find_or_create_literal_string (const lit_utf8_byte_t *, lit_utf8_size_t);
|
||||
extern jmem_cpointer_t ecma_find_or_create_literal_number (ecma_number_t);
|
||||
|
||||
#ifdef JERRY_ENABLE_SNAPSHOT_SAVE
|
||||
extern bool
|
||||
ecma_save_literals_for_snapshot (uint8_t *, size_t, size_t *,
|
||||
lit_mem_to_snapshot_id_map_entry_t **, uint32_t *, uint32_t *);
|
||||
#endif /* JERRY_ENABLE_SNAPSHOT_SAVE */
|
||||
|
||||
#ifdef JERRY_ENABLE_SNAPSHOT_EXEC
|
||||
extern bool
|
||||
ecma_load_literals_from_snapshot (const uint8_t *, uint32_t,
|
||||
lit_mem_to_snapshot_id_map_entry_t **, uint32_t *);
|
||||
#endif /* JERRY_ENABLE_SNAPSHOT_EXEC */
|
||||
|
||||
/**
|
||||
* @}
|
||||
* @}
|
||||
*/
|
||||
|
||||
#endif /* !ECMA_LIT_STORAGE_H */
|
||||
Reference in New Issue
Block a user