diff --git a/jerry-core/parser/js/js-lexer.c b/jerry-core/parser/js/js-lexer.c index 24e96d19c..4adc3ea9e 100644 --- a/jerry-core/parser/js/js-lexer.c +++ b/jerry-core/parser/js/js-lexer.c @@ -1870,117 +1870,6 @@ lexer_consume_generator (parser_context_t *context_p) /**< context */ #endif /* ENABLED (JERRY_ES2015) */ -/** - * Search or append the string to the literal pool. - */ -static void -lexer_process_char_literal (parser_context_t *context_p, /**< context */ - const uint8_t *char_p, /**< characters */ - size_t length, /**< length of string */ - uint8_t literal_type, /**< final literal type */ - bool has_escape) /**< has escape sequences */ -{ - parser_list_iterator_t literal_iterator; - lexer_literal_t *literal_p; - uint32_t literal_index = 0; - bool search_scope_stack = (literal_type == LEXER_IDENT_LITERAL); - - if (JERRY_UNLIKELY (literal_type == LEXER_NEW_IDENT_LITERAL)) - { - literal_type = LEXER_IDENT_LITERAL; - } - - JERRY_ASSERT (literal_type == LEXER_IDENT_LITERAL - || literal_type == LEXER_STRING_LITERAL); - - JERRY_ASSERT (literal_type != LEXER_IDENT_LITERAL || length <= PARSER_MAXIMUM_IDENT_LENGTH); - JERRY_ASSERT (literal_type != LEXER_STRING_LITERAL || length <= PARSER_MAXIMUM_STRING_LENGTH); - - 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 == literal_type - && literal_p->prop.length == length - && memcmp (literal_p->u.char_p, char_p, length) == 0) - { - context_p->lit_object.literal_p = literal_p; - context_p->lit_object.index = (uint16_t) literal_index; - - if (search_scope_stack) - { - parser_scope_stack *scope_stack_start_p = context_p->scope_stack_p; - parser_scope_stack *scope_stack_p = scope_stack_start_p + context_p->scope_stack_top; - - while (scope_stack_p > scope_stack_start_p) - { - scope_stack_p--; - -#if ENABLED (JERRY_ES2015) - bool cond = (scope_stack_p->map_from == literal_index - && scope_stack_p->map_to != PARSER_SCOPE_STACK_FUNC); -#else /* ENABLED (JERRY_ES2015) */ - bool cond = (scope_stack_p->map_from == literal_index); -#endif /* ENABLED (JERRY_ES2015) */ - - if (cond) - { - JERRY_ASSERT (scope_stack_p->map_to >= PARSER_REGISTER_START - || (literal_p->status_flags & LEXER_FLAG_USED)); - context_p->lit_object.index = scope_stack_p->map_to; - return; - } - } - - literal_p->status_flags |= LEXER_FLAG_USED; - } - return; - } - - literal_index++; - } - - JERRY_ASSERT (literal_index == context_p->literal_count); - - if (literal_index >= PARSER_MAXIMUM_NUMBER_OF_LITERALS) - { - parser_raise_error (context_p, PARSER_ERR_LITERAL_LIMIT_REACHED); - } - - if (length == 0) - { - has_escape = false; - } - - literal_p = (lexer_literal_t *) parser_list_append (context_p, &context_p->literal_pool); - literal_p->prop.length = (prop_length_t) length; - literal_p->type = literal_type; - - uint8_t status_flags = LEXER_FLAG_SOURCE_PTR; - - if (has_escape) - { - status_flags = 0; - literal_p->u.char_p = (uint8_t *) jmem_heap_alloc_block (length); - memcpy ((uint8_t *) literal_p->u.char_p, char_p, length); - } - else - { - literal_p->u.char_p = char_p; - } - - if (search_scope_stack) - { - status_flags |= LEXER_FLAG_USED; - } - - literal_p->status_flags = status_flags; - - context_p->lit_object.literal_p = literal_p; - context_p->lit_object.index = (uint16_t) literal_index; - context_p->literal_count++; -} /* lexer_process_char_literal */ - /** * Convert an ident with escapes to a utf8 string. */ @@ -2256,22 +2145,123 @@ lexer_convert_literal_to_chars (parser_context_t *context_p, /**< context */ */ void lexer_construct_literal_object (parser_context_t *context_p, /**< context */ - const lexer_lit_location_t *literal_p, /**< literal location */ + const lexer_lit_location_t *lit_location_p, /**< literal location */ uint8_t literal_type) /**< final literal type */ { uint8_t local_byte_array[LEXER_MAX_LITERAL_LOCAL_BUFFER_SIZE]; - const uint8_t *source_p = lexer_convert_literal_to_chars (context_p, - literal_p, - local_byte_array, - LEXER_STRING_NO_OPTS); - lexer_process_char_literal (context_p, - source_p, - literal_p->length, - literal_type, - literal_p->has_escape); + const uint8_t *char_p = lexer_convert_literal_to_chars (context_p, + lit_location_p, + local_byte_array, + LEXER_STRING_NO_OPTS); + + size_t length = lit_location_p->length; + parser_list_iterator_t literal_iterator; + lexer_literal_t *literal_p; + uint32_t literal_index = 0; + bool search_scope_stack = (literal_type == LEXER_IDENT_LITERAL); + + if (JERRY_UNLIKELY (literal_type == LEXER_NEW_IDENT_LITERAL)) + { + literal_type = LEXER_IDENT_LITERAL; + } + + JERRY_ASSERT (literal_type == LEXER_IDENT_LITERAL + || literal_type == LEXER_STRING_LITERAL); + + JERRY_ASSERT (literal_type != LEXER_IDENT_LITERAL || length <= PARSER_MAXIMUM_IDENT_LENGTH); + JERRY_ASSERT (literal_type != LEXER_STRING_LITERAL || length <= PARSER_MAXIMUM_STRING_LENGTH); + + 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 == literal_type + && literal_p->prop.length == length + && memcmp (literal_p->u.char_p, char_p, length) == 0) + { + context_p->lit_object.literal_p = literal_p; + context_p->lit_object.index = (uint16_t) literal_index; + + parser_free_allocated_buffer (context_p); + + if (search_scope_stack) + { + parser_scope_stack *scope_stack_start_p = context_p->scope_stack_p; + parser_scope_stack *scope_stack_p = scope_stack_start_p + context_p->scope_stack_top; + + while (scope_stack_p > scope_stack_start_p) + { + scope_stack_p--; + +#if ENABLED (JERRY_ES2015) + bool cond = (scope_stack_p->map_from == literal_index + && scope_stack_p->map_to != PARSER_SCOPE_STACK_FUNC); +#else /* ENABLED (JERRY_ES2015) */ + bool cond = (scope_stack_p->map_from == literal_index); +#endif /* ENABLED (JERRY_ES2015) */ + + if (cond) + { + JERRY_ASSERT (scope_stack_p->map_to >= PARSER_REGISTER_START + || (literal_p->status_flags & LEXER_FLAG_USED)); + context_p->lit_object.index = scope_stack_p->map_to; + return; + } + } + + literal_p->status_flags |= LEXER_FLAG_USED; + } + return; + } + + literal_index++; + } + + JERRY_ASSERT (literal_index == context_p->literal_count); + + if (literal_index >= PARSER_MAXIMUM_NUMBER_OF_LITERALS) + { + parser_raise_error (context_p, PARSER_ERR_LITERAL_LIMIT_REACHED); + } + + literal_p = (lexer_literal_t *) parser_list_append (context_p, &context_p->literal_pool); + literal_p->prop.length = (prop_length_t) length; + literal_p->type = literal_type; + + uint8_t status_flags = LEXER_FLAG_SOURCE_PTR; + + if (length > 0 && char_p == local_byte_array) + { + literal_p->u.char_p = (uint8_t *) jmem_heap_alloc_block (length); + memcpy ((uint8_t *) literal_p->u.char_p, char_p, length); + status_flags = 0; + } + else + { + literal_p->u.char_p = char_p; + + /* Buffer is taken over when a new literal is constructed. */ + if (context_p->u.allocated_buffer_p != NULL) + { + JERRY_ASSERT (char_p == context_p->u.allocated_buffer_p); + + context_p->u.allocated_buffer_p = NULL; + status_flags = 0; + } + } + + if (search_scope_stack) + { + status_flags |= LEXER_FLAG_USED; + } + + literal_p->status_flags = status_flags; + + context_p->lit_object.literal_p = literal_p; + context_p->lit_object.index = (uint16_t) literal_index; + context_p->literal_count++; - parser_free_allocated_buffer (context_p); JERRY_ASSERT (context_p->u.allocated_buffer_p == NULL); } /* lexer_construct_literal_object */ diff --git a/jerry-core/parser/js/js-parser-internal.h b/jerry-core/parser/js/js-parser-internal.h index 0d609a539..d830e4713 100644 --- a/jerry-core/parser/js/js-parser-internal.h +++ b/jerry-core/parser/js/js-parser-internal.h @@ -647,7 +647,7 @@ void lexer_convert_ident_to_cesu8 (uint8_t *destination_p, const uint8_t *source const uint8_t *lexer_convert_literal_to_chars (parser_context_t *context_p, const lexer_lit_location_t *literal_p, uint8_t *local_byte_array_p, lexer_string_options_t opts); void lexer_expect_object_literal_id (parser_context_t *context_p, uint32_t ident_opts); -void lexer_construct_literal_object (parser_context_t *context_p, const lexer_lit_location_t *literal_p, +void lexer_construct_literal_object (parser_context_t *context_p, const lexer_lit_location_t *lit_location_p, uint8_t literal_type); bool lexer_construct_number_object (parser_context_t *context_p, bool is_expr, bool is_negative_number); void lexer_convert_push_number_to_push_literal (parser_context_t *context_p); diff --git a/jerry-core/parser/js/js-parser-mem.c b/jerry-core/parser/js/js-parser-mem.c index 4e9c932f1..4dc87252c 100644 --- a/jerry-core/parser/js/js-parser-mem.c +++ b/jerry-core/parser/js/js-parser-mem.c @@ -92,7 +92,7 @@ parser_free_local (void *ptr, /**< pointer to free */ /** * Free the dynamically allocated buffer stored in the context */ -void +inline void JERRY_ATTR_ALWAYS_INLINE parser_free_allocated_buffer (parser_context_t *context_p) /**< context */ { if (context_p->u.allocated_buffer_p != NULL) diff --git a/tests/jerry/large_literal.js b/tests/jerry/large_literal.js new file mode 100644 index 000000000..78bd3616e --- /dev/null +++ b/tests/jerry/large_literal.js @@ -0,0 +1,34 @@ +// Copyright JS Foundation and other contributors, http://js.foundation +// +// 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. + +var literal = "a" + +for (var i = 0; i < 25; i++) + literal += "\\u0061bcdefghij" + +assert(eval("var " + literal + " = 42; " + literal) === 42) + +literal = undefined + +var str = "" +var expected = "" + +for (var i = 0; i < 1000; i++) +{ + str += "123456789\\n" + expected += "123456789\n" +} + +assert(eval('"' + str + '"') === expected); +