Implement direct strings. (#2196)

Direct strings are a new type of direct ecma-values (no memory allocation
is needed for encoding them) in JerryScript. Currently magic strings,
external magic strings and uint values are encoded as direct strings.

The constant pool of JerryScript byte-code is changed to hold ecma-values
rather than cpointers to support direct strings.

JerryScript-DCO-1.0-Signed-off-by: Zoltan Herczeg zherczeg.u-szeged@partner.samsung.com
This commit is contained in:
Zoltan Herczeg
2018-02-23 00:21:46 +01:00
committed by yichoi
parent fbf5c32747
commit 51e3c4455a
37 changed files with 1493 additions and 1148 deletions
+3 -4
View File
@@ -637,9 +637,7 @@ typedef struct
uint16_t ident_end; /**< end position of the identifier group */
uint16_t const_literal_end; /**< end position of the const literal group */
uint16_t literal_end; /**< end position of the literal group */
#ifdef JERRY_CPOINTER_32_BIT
uint16_t padding; /**< an unused value */
#endif
} cbc_uint16_arguments_t;
/**
@@ -652,9 +650,10 @@ typedef enum
CBC_CODE_FLAGS_UINT16_ARGUMENTS = (1u << 2), /**< compiled code data is cbc_uint16_arguments_t */
CBC_CODE_FLAGS_STRICT_MODE = (1u << 3), /**< strict mode is enabled */
CBC_CODE_FLAGS_ARGUMENTS_NEEDED = (1u << 4), /**< arguments object must be constructed */
CBC_CODE_FLAGS_LEXICAL_ENV_NOT_NEEDED = (1u << 5), /**< no need to create a lexical environment */
CBC_CODE_FLAGS_DEBUGGER_IGNORE = (1u << 6), /**< this function should be ignored by debugger */
CBC_CODE_FLAGS_NON_STRICT_ARGUMENTS_NEEDED = (1u << 5), /**< non-strict arguments object must be constructed */
CBC_CODE_FLAGS_LEXICAL_ENV_NOT_NEEDED = (1u << 6), /**< no need to create a lexical environment */
CBC_CODE_FLAGS_ARROW_FUNCTION = (1u << 7), /**< this function is an arrow function */
CBC_CODE_FLAGS_DEBUGGER_IGNORE = (1u << 8), /**< this function should be ignored by debugger */
} cbc_code_flags;
#define CBC_OPCODE(arg1, arg2, arg3, arg4) arg1,
+1 -5
View File
@@ -107,12 +107,8 @@ util_print_literal (lexer_literal_t *literal_p) /**< literal */
}
else if (literal_p->type == LEXER_NUMBER_LITERAL)
{
ecma_string_t *value_p = JMEM_CP_GET_NON_NULL_POINTER (ecma_string_t, literal_p->u.value);
JERRY_ASSERT (ECMA_STRING_GET_CONTAINER (value_p) == ECMA_STRING_LITERAL_NUMBER);
JERRY_DEBUG_MSG ("number(");
util_print_number (ecma_get_number_from_value (value_p->u.lit_number));
util_print_number (ecma_get_number_from_value (literal_p->u.value));
}
else if (literal_p->type == LEXER_REGEXP_LITERAL)
{
+1 -1
View File
@@ -81,7 +81,7 @@ typedef struct
{
union
{
jmem_cpointer_t value; /**< literal value (not processed by the parser) */
ecma_value_t value; /**< literal value (not processed by the parser) */
const uint8_t *char_p; /**< character value */
ecma_compiled_code_t *bytecode_p; /**< compiled function or regexp pointer */
uint32_t source_data; /**< encoded source literal */
+3 -3
View File
@@ -1759,13 +1759,13 @@ lexer_construct_number_object (parser_context_t *context_p, /**< context */
num = -num;
}
jmem_cpointer_t lit_cp = ecma_find_or_create_literal_number (num);
ecma_value_t lit_value = ecma_find_or_create_literal_number (num);
parser_list_iterator_init (&context_p->literal_pool, &literal_iterator);
while ((literal_p = (lexer_literal_t *) parser_list_iterator_next (&literal_iterator)) != NULL)
{
if (literal_p->type == LEXER_NUMBER_LITERAL
&& literal_p->u.value == lit_cp)
&& literal_p->u.value == lit_value)
{
context_p->lit_object.literal_p = literal_p;
context_p->lit_object.index = (uint16_t) literal_index;
@@ -1790,7 +1790,7 @@ lexer_construct_number_object (parser_context_t *context_p, /**< context */
context_p->literal_count++;
literal_p->u.value = lit_cp;
literal_p->u.value = lit_value;
literal_p->type = LEXER_NUMBER_LITERAL;
context_p->lit_object.literal_p = literal_p;
+73 -35
View File
@@ -534,7 +534,7 @@ parser_encode_literal (uint8_t *dst_p, /**< destination buffer */
static uint8_t *
parser_generate_initializers (parser_context_t *context_p, /**< context */
uint8_t *dst_p, /**< destination buffer */
jmem_cpointer_t *literal_pool_p, /**< start of literal pool */
ecma_value_t *literal_pool_p, /**< start of literal pool */
uint16_t uninitialized_var_end, /**< end of the uninitialized var group */
uint16_t initialized_var_end, /**< end of the initialized var group */
uint16_t const_literal_end, /**< end of the const literal group */
@@ -543,7 +543,7 @@ parser_generate_initializers (parser_context_t *context_p, /**< context */
{
parser_list_iterator_t literal_iterator;
lexer_literal_t *literal_p;
uint16_t argument_count;
uint16_t argument_count, register_count;
if (uninitialized_var_end > context_p->register_count)
{
@@ -618,6 +618,7 @@ parser_generate_initializers (parser_context_t *context_p, /**< context */
parser_list_iterator_init (&context_p->literal_pool, &literal_iterator);
argument_count = 0;
register_count = context_p->register_count;
while ((literal_p = (lexer_literal_t *) parser_list_iterator_next (&literal_iterator)))
{
@@ -628,35 +629,42 @@ parser_generate_initializers (parser_context_t *context_p, /**< context */
if (literal_p->type == LEXER_IDENT_LITERAL
|| literal_p->type == LEXER_STRING_LITERAL)
{
if (literal_p->prop.index >= register_count)
{
#ifdef PARSER_DUMP_BYTE_CODE
if (!(literal_p->status_flags & LEXER_FLAG_UNUSED_IDENT))
{
jmem_cpointer_t lit_cp = ecma_find_or_create_literal_string (literal_p->u.char_p,
literal_p->prop.length);
literal_pool_p[literal_p->prop.index] = lit_cp;
}
if (!(literal_p->status_flags & LEXER_FLAG_UNUSED_IDENT))
{
ecma_value_t lit_value = ecma_find_or_create_literal_string (literal_p->u.char_p,
literal_p->prop.length);
literal_pool_p[literal_p->prop.index] = lit_value;
}
if (!context_p->is_show_opcodes
&& !(literal_p->status_flags & LEXER_FLAG_SOURCE_PTR))
{
jmem_heap_free_block ((void *) literal_p->u.char_p, literal_p->prop.length);
}
if (!context_p->is_show_opcodes
&& !(literal_p->status_flags & LEXER_FLAG_SOURCE_PTR))
{
jmem_heap_free_block ((void *) literal_p->u.char_p, literal_p->prop.length);
}
#else /* !PARSER_DUMP_BYTE_CODE */
if (!(literal_p->status_flags & LEXER_FLAG_UNUSED_IDENT))
{
literal_pool_p[literal_p->prop.index] = literal_p->u.value;
}
if (!(literal_p->status_flags & LEXER_FLAG_UNUSED_IDENT))
{
literal_pool_p[literal_p->prop.index] = literal_p->u.value;
}
#endif /* PARSER_DUMP_BYTE_CODE */
}
}
else if ((literal_p->type == LEXER_FUNCTION_LITERAL)
|| (literal_p->type == LEXER_REGEXP_LITERAL))
{
ECMA_SET_NON_NULL_POINTER (literal_pool_p[literal_p->prop.index],
literal_p->u.bytecode_p);
JERRY_ASSERT (literal_p->prop.index >= register_count);
ECMA_SET_INTERNAL_VALUE_POINTER (literal_pool_p[literal_p->prop.index],
literal_p->u.bytecode_p);
}
else
{
JERRY_ASSERT (literal_p->type == LEXER_NUMBER_LITERAL);
JERRY_ASSERT (literal_p->type == LEXER_NUMBER_LITERAL
&& literal_p->prop.index >= register_count);
literal_pool_p[literal_p->prop.index] = literal_p->u.value;
}
}
@@ -692,9 +700,12 @@ parser_generate_initializers (parser_context_t *context_p, /**< context */
JERRY_ASSERT (literal_p != NULL
&& literal_p->type == LEXER_FUNCTION_LITERAL);
init_index = literal_p->prop.index;
ECMA_SET_NON_NULL_POINTER (literal_pool_p[literal_p->prop.index],
literal_p->u.bytecode_p);
JERRY_ASSERT (init_index >= register_count);
ECMA_SET_INTERNAL_VALUE_POINTER (literal_pool_p[init_index],
literal_p->u.bytecode_p);
}
*dst_p++ = CBC_INITIALIZE_VAR;
@@ -1216,7 +1227,12 @@ parse_print_final_cbc (ecma_compiled_code_t *compiled_code_p, /**< compiled code
byte_code_start_p += sizeof (cbc_uint8_arguments_t);
}
byte_code_start_p += literal_end * sizeof (jmem_cpointer_t);
byte_code_start_p += (unsigned int) (literal_end - register_end) * sizeof (ecma_value_t);
if (unlikely (compiled_code_p->status_flags & CBC_CODE_FLAGS_NON_STRICT_ARGUMENTS_NEEDED))
{
byte_code_start_p += argument_end * sizeof (ecma_value_t);
}
byte_code_end_p = byte_code_start_p + length;
byte_code_p = byte_code_start_p;
@@ -1378,6 +1394,7 @@ parser_post_processing (parser_context_t *context_p) /**< context */
size_t last_position;
size_t offset;
size_t length;
size_t literal_length;
size_t total_size;
#ifdef JERRY_ENABLE_SNAPSHOT_SAVE
size_t total_size_used;
@@ -1388,7 +1405,7 @@ parser_post_processing (parser_context_t *context_p) /**< context */
bool needs_uint16_arguments;
cbc_opcode_t last_opcode = CBC_EXT_OPCODE;
ecma_compiled_code_t *compiled_code_p;
jmem_cpointer_t *literal_pool_p;
ecma_value_t *literal_pool_p;
uint8_t *dst_p;
if ((size_t) context_p->stack_limit + (size_t) context_p->register_count > PARSER_MAXIMUM_STACK_LIMIT)
@@ -1612,7 +1629,16 @@ parser_post_processing (parser_context_t *context_p) /**< context */
total_size = sizeof (cbc_uint16_arguments_t);
}
total_size += length + context_p->literal_count * sizeof (jmem_cpointer_t);
literal_length = (size_t) (context_p->literal_count - context_p->register_count) * sizeof (ecma_value_t);
total_size += literal_length + length;
if ((context_p->status_flags & PARSER_ARGUMENTS_NEEDED)
&& !(context_p->status_flags & PARSER_IS_STRICT))
{
total_size += context_p->argument_count * sizeof (ecma_value_t);
}
#ifdef JERRY_ENABLE_SNAPSHOT_SAVE
total_size_used = total_size;
#endif
@@ -1678,6 +1704,12 @@ parser_post_processing (parser_context_t *context_p) /**< context */
if (context_p->status_flags & PARSER_ARGUMENTS_NEEDED)
{
compiled_code_p->status_flags |= CBC_CODE_FLAGS_ARGUMENTS_NEEDED;
if (!(context_p->status_flags & PARSER_IS_STRICT))
{
compiled_code_p->status_flags |= CBC_CODE_FLAGS_NON_STRICT_ARGUMENTS_NEEDED;
}
/* Arguments is stored in the lexical environment. */
context_p->status_flags |= PARSER_LEXICAL_ENV_NEEDED;
}
@@ -1694,8 +1726,9 @@ parser_post_processing (parser_context_t *context_p) /**< context */
}
#endif /* !CONFIG_DISABLE_ES2015_ARROW_FUNCTION */
literal_pool_p = (jmem_cpointer_t *) byte_code_p;
byte_code_p += context_p->literal_count * sizeof (jmem_cpointer_t);
literal_pool_p = (ecma_value_t *) byte_code_p;
literal_pool_p -= context_p->register_count;
byte_code_p += literal_length;
dst_p = parser_generate_initializers (context_p,
byte_code_p,
@@ -1896,17 +1929,19 @@ parser_post_processing (parser_context_t *context_p) /**< context */
{
parser_list_iterator_t literal_iterator;
lexer_literal_t *literal_p;
uint16_t register_count = context_p->register_count;
parser_list_iterator_init (&context_p->literal_pool, &literal_iterator);
while ((literal_p = (lexer_literal_t *) parser_list_iterator_next (&literal_iterator)))
{
if (literal_p->status_flags & LEXER_FLAG_LATE_INIT)
if ((literal_p->status_flags & LEXER_FLAG_LATE_INIT)
&& literal_p->prop.index >= register_count)
{
uint32_t source_data = literal_p->u.source_data;
const uint8_t *char_p = context_p->source_end_p - (source_data & 0xfffff);
jmem_cpointer_t lit_cp = ecma_find_or_create_literal_string (char_p,
ecma_value_t lit_value = ecma_find_or_create_literal_string (char_p,
source_data >> 20);
literal_pool_p[literal_p->prop.index] = lit_cp;
literal_pool_p[literal_p->prop.index] = lit_value;
}
}
}
@@ -1917,6 +1952,9 @@ parser_post_processing (parser_context_t *context_p) /**< context */
{
parser_list_iterator_t literal_iterator;
uint16_t argument_count = 0;
uint16_t register_count = context_p->register_count;
ecma_value_t *argument_base_p = (ecma_value_t *) (((uint8_t *) compiled_code_p) + total_size);
argument_base_p -= context_p->argument_count;
parser_list_iterator_init (&context_p->literal_pool, &literal_iterator);
while (argument_count < context_p->argument_count)
@@ -1936,7 +1974,7 @@ parser_post_processing (parser_context_t *context_p) /**< context */
{
if (literal_p->u.char_p == NULL)
{
literal_pool_p[argument_count] = JMEM_CP_NULL;
argument_base_p[argument_count] = ECMA_VALUE_EMPTY;
argument_count++;
continue;
}
@@ -1949,17 +1987,17 @@ parser_post_processing (parser_context_t *context_p) /**< context */
JERRY_ASSERT (literal_p->type == LEXER_IDENT_LITERAL
&& (literal_p->status_flags & LEXER_FLAG_VAR));
JERRY_ASSERT (argument_count < literal_p->prop.index);
JERRY_ASSERT (literal_p->prop.index >= register_count);
literal_pool_p[argument_count] = literal_pool_p[literal_p->prop.index];
argument_base_p[argument_count] = literal_pool_p[literal_p->prop.index];
argument_count++;
}
}
if (context_p->status_flags & PARSER_NAMED_FUNCTION_EXP)
{
ECMA_SET_NON_NULL_POINTER (literal_pool_p[const_literal_end],
compiled_code_p);
ECMA_SET_INTERNAL_VALUE_POINTER (literal_pool_p[const_literal_end],
compiled_code_p);
}
#ifdef JERRY_DEBUGGER
+1 -1
View File
@@ -85,7 +85,7 @@ typedef enum
typedef struct
{
ecma_compiled_code_t header; /**< compiled code header */
jmem_cpointer_t pattern_cp; /**< original RegExp pattern */
ecma_value_t pattern; /**< original RegExp pattern */
uint32_t num_of_captures; /**< number of capturing brackets */
uint32_t num_of_non_captures; /**< number of non capturing brackets */
} re_compiled_code_t;
+2 -3
View File
@@ -468,8 +468,7 @@ re_find_bytecode_in_cache (ecma_string_t *pattern_str_p, /**< pattern string */
if (cached_bytecode_p != NULL)
{
ecma_string_t *cached_pattern_str_p;
cached_pattern_str_p = ECMA_GET_NON_NULL_POINTER (ecma_string_t, cached_bytecode_p->pattern_cp);
ecma_string_t *cached_pattern_str_p = ecma_get_string_from_value (cached_bytecode_p->pattern);
if ((cached_bytecode_p->header.status_flags & RE_FLAGS_MASK) == flags
&& ecma_compare_ecma_strings (cached_pattern_str_p, pattern_str_p))
@@ -580,7 +579,7 @@ re_compile_bytecode (const re_compiled_code_t **out_bytecode_p, /**< [out] point
re_compiled_code.header.refs = 1;
re_compiled_code.header.status_flags = re_ctx.flags;
ecma_ref_ecma_string (pattern_str_p);
ECMA_SET_NON_NULL_POINTER (re_compiled_code.pattern_cp, pattern_str_p);
re_compiled_code.pattern = ecma_make_string_value (pattern_str_p);
re_compiled_code.num_of_captures = re_ctx.num_of_captures * 2;
re_compiled_code.num_of_non_captures = re_ctx.num_of_non_captures;