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:
@@ -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,
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user