Create function variables using the data produced by the pre-scanner. (#3199)

The pre-scanner now is able to track all variable declarations and produces a compressed
stream which store this data for each function and catch block. When a function or
catch block is parsed, this information is decoded and the appropriate variables are
created. Furthermore a stack scope is created which contains the currently available
local variables and their register or literal index.

JerryScript-DCO-1.0-Signed-off-by: Zoltan Herczeg zherczeg.u-szeged@partner.samsung.com
This commit is contained in:
Zoltan Herczeg
2019-10-17 15:20:04 +02:00
committed by GitHub
parent fd1f7eab9f
commit 7df87b7778
20 changed files with 2098 additions and 1219 deletions
+1 -1
View File
@@ -30,7 +30,7 @@ extern "C"
/**
* Jerry snapshot format version.
*/
#define JERRY_SNAPSHOT_VERSION (24u)
#define JERRY_SNAPSHOT_VERSION (25u)
/**
* Flags for jerry_generate_snapshot and jerry_generate_function_snapshot.
+2 -4
View File
@@ -298,11 +298,9 @@
VM_OC_NEW | VM_OC_PUT_STACK) \
CBC_OPCODE (CBC_EVAL, CBC_NO_FLAG, 0, \
VM_OC_EVAL) \
CBC_OPCODE (CBC_DEFINE_VARS, CBC_HAS_LITERAL_ARG, 0, \
CBC_OPCODE (CBC_CREATE_VAR, CBC_HAS_LITERAL_ARG, 0, \
VM_OC_NONE) \
CBC_OPCODE (CBC_INITIALIZE_VAR, CBC_HAS_LITERAL_ARG | CBC_HAS_LITERAL_ARG2, 0, \
VM_OC_NONE) \
CBC_OPCODE (CBC_INITIALIZE_VARS, CBC_HAS_LITERAL_ARG | CBC_HAS_LITERAL_ARG2, 0, \
CBC_OPCODE (CBC_INIT_LOCAL, CBC_HAS_LITERAL_ARG | CBC_HAS_LITERAL_ARG2, 0, \
VM_OC_NONE) \
CBC_OPCODE (CBC_SET_BYTECODE_PTR, CBC_NO_FLAG, 0, \
VM_OC_NONE) \
+1 -8
View File
@@ -85,14 +85,7 @@ util_print_literal (lexer_literal_t *literal_p) /**< literal */
{
if (literal_p->type == LEXER_IDENT_LITERAL)
{
if (literal_p->status_flags & LEXER_FLAG_VAR)
{
JERRY_DEBUG_MSG ("var_ident(");
}
else
{
JERRY_DEBUG_MSG ("ident(");
}
JERRY_DEBUG_MSG ("ident(");
util_print_chars (literal_p->u.char_p, literal_p->prop.length);
}
else if (literal_p->type == LEXER_FUNCTION_LITERAL)
+6 -8
View File
@@ -55,6 +55,8 @@ typedef enum
LEXER_REGEXP_LITERAL = 4, /**< regexp literal */
LEXER_UNUSED_LITERAL = 5, /**< unused literal, can only be
used by the byte code generator. */
LEXER_NEW_IDENT_LITERAL = 6, /**< new local variable, can only be
used by the byte code generator. */
} lexer_literal_type_t;
/**
@@ -67,15 +69,11 @@ typedef enum
*/
typedef enum
{
LEXER_FLAG_VAR = (1 << 0), /**< local identifier (var, function arg) */
LEXER_FLAG_NO_REG_STORE = (1 << 1), /**< this local identifier cannot be stored in register */
LEXER_FLAG_INITIALIZED = (1 << 2), /**< this local identifier is initialized with a value */
LEXER_FLAG_FUNCTION_ARGUMENT = (1 << 3), /**< this local identifier is a function argument */
LEXER_FLAG_UNUSED_IDENT = (1 << 4), /**< this identifier is referenced by sub-functions,
* but not referenced by the currently parsed function */
LEXER_FLAG_SOURCE_PTR = (1 << 5), /**< the literal is directly referenced in the source code
LEXER_FLAG_USED = (1 << 0), /**< this local identifier needs to be stored in the constant pool */
LEXER_FLAG_FUNCTION_ARGUMENT = (1 << 1), /**< this local identifier is a function argument */
LEXER_FLAG_SOURCE_PTR = (1 << 2), /**< the literal is directly referenced in the source code
* (no need to allocate memory) */
LEXER_FLAG_LATE_INIT = (1 << 6), /**< initialize this variable after the byte code is freed */
LEXER_FLAG_LATE_INIT = (1 << 3), /**< initialize this variable after the byte code is freed */
} lexer_literal_status_flags_t;
/**
+91 -62
View File
@@ -1387,7 +1387,7 @@ lexer_next_token (parser_context_t *context_p) /**< context */
#undef LEXER_TYPE_D_TOKEN
/**
* Checks whether the next token is the specified character.
* Checks whether the next token starts with the specified character.
*
* @return true - if the next is the specified character
* false - otherwise
@@ -1443,6 +1443,12 @@ lexer_process_char_literal (parser_context_t *context_p, /**< context */
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);
@@ -1460,7 +1466,27 @@ lexer_process_char_literal (parser_context_t *context_p, /**< context */
{
context_p->lit_object.literal_p = literal_p;
context_p->lit_object.index = (uint16_t) literal_index;
literal_p->status_flags = (uint8_t) (literal_p->status_flags & ~LEXER_FLAG_UNUSED_IDENT);
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 (scope_stack_p->map_from == literal_index)
{
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;
}
@@ -1482,10 +1508,12 @@ lexer_process_char_literal (parser_context_t *context_p, /**< context */
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;
literal_p->status_flags = has_escape ? 0 : LEXER_FLAG_SOURCE_PTR;
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);
}
@@ -1494,6 +1522,13 @@ lexer_process_char_literal (parser_context_t *context_p, /**< context */
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++;
@@ -1509,7 +1544,7 @@ lexer_process_char_literal (parser_context_t *context_p, /**< context */
*/
void
lexer_construct_literal_object (parser_context_t *context_p, /**< context */
lexer_lit_location_t *literal_p, /**< literal location */
const lexer_lit_location_t *literal_p, /**< literal location */
uint8_t literal_type) /**< final literal type */
{
uint8_t *destination_start_p;
@@ -1518,7 +1553,7 @@ lexer_construct_literal_object (parser_context_t *context_p, /**< context */
JERRY_ASSERT (literal_p->type == LEXER_IDENT_LITERAL
|| literal_p->type == LEXER_STRING_LITERAL);
JERRY_ASSERT (context_p->allocated_buffer_p == NULL);
JERRY_ASSERT (context_p->u.allocated_buffer_p == NULL);
destination_start_p = local_byte_array;
source_p = literal_p->char_p;
@@ -1530,7 +1565,7 @@ lexer_construct_literal_object (parser_context_t *context_p, /**< context */
if (literal_p->length > LEXER_MAX_LITERAL_LOCAL_BUFFER_SIZE)
{
destination_start_p = (uint8_t *) parser_malloc_local (context_p, literal_p->length);
context_p->allocated_buffer_p = destination_start_p;
context_p->u.allocated_buffer_p = destination_start_p;
context_p->allocated_buffer_size = literal_p->length;
}
@@ -1764,16 +1799,8 @@ lexer_construct_literal_object (parser_context_t *context_p, /**< context */
literal_type,
literal_p->has_escape);
JERRY_ASSERT (literal_type == context_p->lit_object.literal_p->type);
context_p->lit_object.type = LEXER_LITERAL_OBJECT_ANY;
if (literal_type == LEXER_IDENT_LITERAL
&& (context_p->status_flags & PARSER_INSIDE_WITH))
{
context_p->lit_object.literal_p->status_flags |= LEXER_FLAG_NO_REG_STORE;
}
if (literal_p->length == 4
&& source_p[0] == LIT_CHAR_LOWERCASE_E
&& source_p[3] == LIT_CHAR_LOWERCASE_L
@@ -1789,24 +1816,18 @@ lexer_construct_literal_object (parser_context_t *context_p, /**< context */
&& memcmp (source_p + 1, "rgument", 7) == 0)
{
context_p->lit_object.type = LEXER_LITERAL_OBJECT_ARGUMENTS;
if (!(context_p->status_flags & PARSER_ARGUMENTS_NOT_NEEDED)
&& literal_type == LEXER_IDENT_LITERAL)
{
context_p->status_flags |= PARSER_ARGUMENTS_NEEDED | PARSER_LEXICAL_ENV_NEEDED;
context_p->lit_object.literal_p->status_flags |= LEXER_FLAG_NO_REG_STORE;
}
}
if (destination_start_p != local_byte_array)
{
JERRY_ASSERT (context_p->allocated_buffer_p == destination_start_p);
JERRY_ASSERT (context_p->u.allocated_buffer_p == destination_start_p);
context_p->allocated_buffer_p = NULL;
context_p->u.allocated_buffer_p = NULL;
parser_free_local (destination_start_p,
context_p->allocated_buffer_size);
}
JERRY_ASSERT (context_p->allocated_buffer_p == NULL);
JERRY_ASSERT (context_p->u.allocated_buffer_p == NULL);
} /* lexer_construct_literal_object */
#undef LEXER_MAX_LITERAL_LOCAL_BUFFER_SIZE
@@ -2251,7 +2272,8 @@ lexer_expect_identifier (parser_context_t *context_p, /**< context */
uint8_t literal_type) /**< literal type */
{
JERRY_ASSERT (literal_type == LEXER_STRING_LITERAL
|| literal_type == LEXER_IDENT_LITERAL);
|| literal_type == LEXER_IDENT_LITERAL
|| literal_type == LEXER_NEW_IDENT_LITERAL);
lexer_skip_spaces (context_p);
context_p->token.line = context_p->line;
@@ -2264,11 +2286,13 @@ lexer_expect_identifier (parser_context_t *context_p, /**< context */
if (context_p->token.type == LEXER_LITERAL)
{
JERRY_ASSERT (context_p->token.lit_location.type == LEXER_IDENT_LITERAL);
lexer_construct_literal_object (context_p,
&context_p->token.lit_location,
literal_type);
if (literal_type == LEXER_IDENT_LITERAL
if (literal_type != LEXER_STRING_LITERAL
&& (context_p->status_flags & PARSER_IS_STRICT)
&& context_p->lit_object.type != LEXER_LITERAL_OBJECT_ANY)
{
@@ -2286,8 +2310,6 @@ lexer_expect_identifier (parser_context_t *context_p, /**< context */
parser_raise_error (context_p, error);
}
context_p->token.lit_location.type = literal_type;
return;
}
}
@@ -2300,9 +2322,7 @@ lexer_expect_identifier (parser_context_t *context_p, /**< context */
context_p->token.literal_is_reserved = false;
context_p->token.lit_location.type = LEXER_IDENT_LITERAL;
context_p->token.lit_location.has_escape = false;
lexer_construct_literal_object (context_p,
(lexer_lit_location_t *) &lexer_default_literal,
lexer_default_literal.type);
lexer_construct_literal_object (context_p, &lexer_default_literal, lexer_default_literal.type);
context_p->status_flags &= (uint32_t) ~(PARSER_MODULE_DEFAULT_CLASS_OR_FUNC);
return;
}
@@ -2519,43 +2539,23 @@ lexer_scan_identifier (parser_context_t *context_p, /**< context */
} /* lexer_scan_identifier */
/**
* Compares the current identifier in the context to the parameter identifier
* Compares two identifiers.
*
* Note:
* Escape sequences are allowed.
* Escape sequences are allowed, size must be the same.
*
* @return true if the input identifiers are the same
* @return true if the two identifiers are the same
*/
bool
lexer_compare_identifier_to_current (parser_context_t *context_p, /**< context */
const lexer_lit_location_t *right_ident_p) /**< identifier */
lexer_compare_identifiers (const uint8_t *left_p, /**< left identifier */
const uint8_t *right_p, /**< right identifier */
size_t size) /**< byte size of the two identifiers */
{
lexer_lit_location_t *left_ident_p = &context_p->token.lit_location;
const uint8_t *left_p;
const uint8_t *right_p;
size_t count;
JERRY_ASSERT (left_ident_p->length > 0 && right_ident_p->length > 0);
if (left_ident_p->length != right_ident_p->length)
{
return 0;
}
if (!left_ident_p->has_escape && !right_ident_p->has_escape)
{
return memcmp (left_ident_p->char_p, right_ident_p->char_p, left_ident_p->length) == 0;
}
left_p = left_ident_p->char_p;
right_p = right_ident_p->char_p;
count = left_ident_p->length;
uint8_t utf8_buf[3];
size_t utf8_len, offset;
do
{
uint8_t utf8_buf[3];
size_t utf8_len, offset;
/* Backslash cannot be part of a multibyte UTF-8 character. */
if (*left_p != LIT_CHAR_BACKSLASH && *right_p != LIT_CHAR_BACKSLASH)
{
@@ -2563,7 +2563,7 @@ lexer_compare_identifier_to_current (parser_context_t *context_p, /**< context *
{
return false;
}
count--;
size--;
continue;
}
@@ -2578,7 +2578,7 @@ lexer_compare_identifier_to_current (parser_context_t *context_p, /**< context *
left_p += 6;
right_p += 6;
count += lit_char_get_utf8_length (left_chr);
size -= lit_char_get_utf8_length (left_chr);
continue;
}
@@ -2593,7 +2593,7 @@ lexer_compare_identifier_to_current (parser_context_t *context_p, /**< context *
utf8_len = lit_char_to_utf8_bytes (utf8_buf, lexer_unchecked_hex_to_character (left_p + 2, 4));
JERRY_ASSERT (utf8_len > 0);
count -= utf8_len;
size -= utf8_len;
offset = 0;
do
@@ -2608,9 +2608,38 @@ lexer_compare_identifier_to_current (parser_context_t *context_p, /**< context *
left_p += 6;
}
while (count > 0);
while (size > 0);
return true;
} /* lexer_compare_identifiers */
/**
* Compares the current identifier in the context to the parameter identifier
*
* Note:
* Escape sequences are allowed.
*
* @return true if the input identifiers are the same
*/
bool
lexer_compare_identifier_to_current (parser_context_t *context_p, /**< context */
const lexer_lit_location_t *right_ident_p) /**< identifier */
{
lexer_lit_location_t *left_ident_p = &context_p->token.lit_location;
JERRY_ASSERT (left_ident_p->length > 0 && right_ident_p->length > 0);
if (left_ident_p->length != right_ident_p->length)
{
return 0;
}
if (!left_ident_p->has_escape && !right_ident_p->has_escape)
{
return memcmp (left_ident_p->char_p, right_ident_p->char_p, left_ident_p->length) == 0;
}
return lexer_compare_identifiers (left_ident_p->char_p, right_ident_p->char_p, left_ident_p->length);
} /* lexer_compare_identifier_to_current */
/**
+12 -15
View File
@@ -601,7 +601,6 @@ parser_parse_class (parser_context_t *context_p, /**< context */
&& context_p->token.lit_location.type == LEXER_IDENT_LITERAL);
class_ident_index = context_p->lit_object.index;
context_p->lit_object.literal_p->status_flags |= LEXER_FLAG_VAR;
#if ENABLED (JERRY_ES2015_MODULE_SYSTEM)
if (context_p->status_flags & PARSER_MODULE_STORE_IDENT)
@@ -1167,7 +1166,7 @@ parser_parse_unary_expression (parser_context_t *context_p, /**< context */
#if ENABLED (JERRY_ES2015_ARROW_FUNCTION)
if (context_p->next_scanner_info_p->source_p == context_p->source_p)
{
JERRY_ASSERT (context_p->next_scanner_info_p->type == SCANNER_TYPE_ARROW);
JERRY_ASSERT (context_p->next_scanner_info_p->type == SCANNER_TYPE_FUNCTION);
break;
}
#endif /* ENABLED (JERRY_ES2015_ARROW_FUNCTION) */
@@ -1209,8 +1208,7 @@ parser_parse_unary_expression (parser_context_t *context_p, /**< context */
#if ENABLED (JERRY_ES2015_ARROW_FUNCTION)
if (context_p->next_scanner_info_p->source_p == context_p->source_p)
{
JERRY_ASSERT (context_p->next_scanner_info_p->type == SCANNER_TYPE_ARROW);
scanner_release_next (context_p, sizeof (scanner_info_t));
JERRY_ASSERT (context_p->next_scanner_info_p->type == SCANNER_TYPE_FUNCTION);
parser_parse_function_expression (context_p,
PARSER_IS_FUNCTION | PARSER_IS_ARROW_FUNCTION);
@@ -1218,23 +1216,24 @@ parser_parse_unary_expression (parser_context_t *context_p, /**< context */
}
#endif /* ENABLED (JERRY_ES2015_ARROW_FUNCTION) */
if (context_p->token.lit_location.type == LEXER_IDENT_LITERAL
|| context_p->token.lit_location.type == LEXER_STRING_LITERAL)
uint8_t type = context_p->token.lit_location.type;
if (type == LEXER_IDENT_LITERAL || type == LEXER_STRING_LITERAL)
{
lexer_construct_literal_object (context_p,
&context_p->token.lit_location,
context_p->token.lit_location.type);
#if ENABLED (JERRY_ES2015_MODULE_SYSTEM)
if (context_p->status_flags & PARSER_MODULE_STORE_IDENT
&& context_p->token.lit_location.type == LEXER_IDENT_LITERAL)
if ((context_p->status_flags & PARSER_MODULE_STORE_IDENT)
&& type == LEXER_IDENT_LITERAL)
{
context_p->lit_object.literal_p->status_flags |= LEXER_FLAG_VAR;
context_p->module_identifier_lit_p = context_p->lit_object.literal_p;
context_p->status_flags &= (uint32_t) ~(PARSER_MODULE_STORE_IDENT);
}
#endif /* ENABLED (JERRY_ES2015_MODULE_SYSTEM) */
}
else if (context_p->token.lit_location.type == LEXER_NUMBER_LITERAL)
else if (type == LEXER_NUMBER_LITERAL)
{
bool is_negative_number = false;
@@ -1418,8 +1417,7 @@ parser_parse_unary_expression (parser_context_t *context_p, /**< context */
case LEXER_LEFT_PAREN:
{
JERRY_ASSERT (context_p->next_scanner_info_p->source_p == context_p->source_p
&& context_p->next_scanner_info_p->type == SCANNER_TYPE_ARROW);
scanner_release_next (context_p, sizeof (scanner_info_t));
&& context_p->next_scanner_info_p->type == SCANNER_TYPE_FUNCTION);
lexer_next_token (context_p);
parser_parse_function_expression (context_p,
@@ -1479,7 +1477,8 @@ parser_process_unary_expression (parser_context_t *context_p) /**< context */
lexer_expect_identifier (context_p, LEXER_STRING_LITERAL);
JERRY_ASSERT (context_p->token.type == LEXER_LITERAL
&& context_p->token.lit_location.type == LEXER_STRING_LITERAL);
&& context_p->lit_object.literal_p->type == LEXER_STRING_LITERAL);
context_p->token.lit_location.type = LEXER_STRING_LITERAL;
if (context_p->last_cbc_opcode == CBC_PUSH_LITERAL)
{
@@ -1543,7 +1542,6 @@ parser_process_unary_expression (parser_context_t *context_p) /**< context */
&& context_p->last_cbc.literal_object_type == LEXER_LITERAL_OBJECT_EVAL
&& context_p->last_cbc.literal_type == LEXER_IDENT_LITERAL)
{
context_p->status_flags |= PARSER_ARGUMENTS_NEEDED | PARSER_LEXICAL_ENV_NEEDED | PARSER_NO_REG_STORE;
is_eval = true;
}
@@ -1796,7 +1794,6 @@ parser_append_binary_token (parser_context_t *context_p) /**< context */
parser_stack_push_uint8 (context_p, CBC_ASSIGN);
context_p->last_cbc_opcode = PARSER_CBC_UNAVAILABLE;
}
else if (context_p->last_cbc_opcode == CBC_PUSH_PROP_LITERAL)
{
if (context_p->last_cbc.literal_type != LEXER_IDENT_LITERAL)
+43 -5
View File
@@ -56,8 +56,6 @@ typedef enum
PARSER_ARGUMENTS_NEEDED = (1u << 8), /**< arguments object must be created */
PARSER_ARGUMENTS_NOT_NEEDED = (1u << 9), /**< arguments object must NOT be created */
PARSER_LEXICAL_ENV_NEEDED = (1u << 10), /**< lexical environment object must be created */
PARSER_NO_REG_STORE = (1u << 11), /**< all local variables must be stored
* in the lexical environment object */
PARSER_INSIDE_WITH = (1u << 12), /**< code block is inside a with statement */
PARSER_RESOLVE_BASE_FOR_CALLS = (1u << 13), /**< the this object must be resolved when
* a function without a base object is called */
@@ -313,6 +311,29 @@ typedef struct parser_branch_node_t
parser_branch_t branch; /**< branch */
} parser_branch_node_t;
/**
* Items of scope stack.
*/
typedef struct
{
uint16_t map_from; /**< original literal index */
uint16_t map_to; /**< register or literal index */
} parser_scope_stack;
/**
* This item represents a function literal in the scope stack.
*/
#define PARSER_SCOPE_STACK_FUNC 0xffff
/**
* Starting literal index for registers.
*/
#define PARSER_REGISTER_START 0x8000
/* Forward definitions for js-scanner-internal.h. */
struct scanner_context_t;
typedef struct scanner_context_t scanner_context_t;
#if ENABLED (JERRY_DEBUGGER)
/**
* Extra information for each breakpoint.
@@ -352,6 +373,10 @@ typedef struct parser_saved_context_t
parser_mem_data_t byte_code; /**< byte code buffer */
uint32_t byte_code_size; /**< byte code size for branches */
parser_mem_data_t literal_pool_data; /**< literal list */
parser_scope_stack *scope_stack_p; /**< scope stack */
uint16_t scope_stack_size; /**< size of scope stack */
uint16_t scope_stack_top; /**< current top of scope stack */
uint16_t scope_stack_reg_top; /**< current top register of scope stack */
#ifndef JERRY_NDEBUG
uint16_t context_stack_depth; /**< current context stack depth */
@@ -365,8 +390,13 @@ typedef struct
{
PARSER_TRY_CONTEXT (try_buffer); /**< try_buffer */
parser_error_t error; /**< error code */
void *allocated_buffer_p; /**< dinamically allocated buffer
/** Union for rarely used members. */
union
{
void *allocated_buffer_p; /**< dinamically allocated buffer
* which needs to be freed on error */
scanner_context_t *scanner_context_p; /**< scanner context for the pre-scanner */
} u;
uint32_t allocated_buffer_size; /**< size of the dinamically allocated buffer */
/* Parser members. */
@@ -409,7 +439,11 @@ typedef struct
uint32_t byte_code_size; /**< current byte code size for branches */
parser_list_t literal_pool; /**< literal list */
parser_mem_data_t stack; /**< storage space */
parser_scope_stack *scope_stack_p; /**< scope stack */
parser_mem_page_t *free_page_p; /**< space for fast allocation */
uint16_t scope_stack_size; /**< size of scope stack */
uint16_t scope_stack_top; /**< current top of scope stack */
uint16_t scope_stack_reg_top; /**< current top register of scope stack */
uint8_t stack_top_uint8; /**< top byte stored on the stack */
#ifndef JERRY_NDEBUG
@@ -502,6 +536,8 @@ void parser_stack_iterator_write (parser_stack_iterator_t *iterator, const void
void parser_flush_cbc (parser_context_t *context_p);
void parser_emit_cbc (parser_context_t *context_p, uint16_t opcode);
void parser_emit_cbc_literal (parser_context_t *context_p, uint16_t opcode, uint16_t literal_index);
void parser_emit_cbc_literal_value (parser_context_t *context_p, uint16_t opcode, uint16_t literal_index,
uint16_t value);
void parser_emit_cbc_literal_from_token (parser_context_t *context_p, uint16_t opcode);
void parser_emit_cbc_call (parser_context_t *context_p, uint16_t opcode, size_t call_arguments);
void parser_emit_cbc_push_number (parser_context_t *context_p, bool is_negative_number);
@@ -547,12 +583,13 @@ void lexer_expect_identifier (parser_context_t *context_p, uint8_t literal_type)
void lexer_scan_identifier (parser_context_t *context_p, uint32_t ident_opts);
ecma_char_t lexer_hex_to_character (parser_context_t *context_p, const uint8_t *source_p, int length);
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, lexer_lit_location_t *literal_p,
void lexer_construct_literal_object (parser_context_t *context_p, const lexer_lit_location_t *literal_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);
uint16_t lexer_construct_function_object (parser_context_t *context_p, uint32_t extra_status_flags);
void lexer_construct_regexp_object (parser_context_t *context_p, bool parse_only);
bool lexer_compare_identifiers (const uint8_t *left_p, const uint8_t *right_p, size_t size);
bool lexer_compare_identifier_to_current (parser_context_t *context_p, const lexer_lit_location_t *right_ident_p);
bool lexer_compare_literal_to_identifier (parser_context_t *context_p, const char *identifier_p,
size_t identifier_length);
@@ -588,7 +625,6 @@ void scanner_raise_error (parser_context_t *context_p);
void *scanner_malloc (parser_context_t *context_p, size_t size);
void scanner_free (void *ptr, size_t size);
scanner_info_t *scanner_insert_info (parser_context_t *context_p, const uint8_t *source_p, size_t size);
void scanner_release_next (parser_context_t *context_p, size_t size);
void scanner_set_active (parser_context_t *context_p);
void scanner_release_active (parser_context_t *context_p, size_t size);
@@ -597,6 +633,8 @@ void scanner_seek (parser_context_t *context_p);
void scanner_reverse_info_list (parser_context_t *context_p);
void scanner_cleanup (parser_context_t *context_p);
void scanner_create_variables (parser_context_t *context_p, size_t size);
void scanner_get_location (scanner_location_t *location_p, parser_context_t *context_p);
void scanner_set_location (parser_context_t *context_p, scanner_location_t *location_p);
+27 -13
View File
@@ -52,22 +52,30 @@
#define PARSER_MAXIMUM_STRING_LENGTH PARSER_MAXIMUM_STRING_LIMIT
#endif /* !PARSER_MAXIMUM_STRING_LENGTH */
/**
* Maximum number of literals.
* Limit: 32767. Recommended: 510, 32767
*/
#ifndef PARSER_MAXIMUM_NUMBER_OF_LITERALS
#define PARSER_MAXIMUM_NUMBER_OF_LITERALS 32767
#endif /* !PARSER_MAXIMUM_NUMBER_OF_LITERALS */
/**
* Maximum number of registers.
* Limit: PARSER_MAXIMUM_NUMBER_OF_LITERALS
* Limit: min: 256, max: PARSER_MAXIMUM_NUMBER_OF_LITERALS / 2
*/
#ifndef PARSER_MAXIMUM_NUMBER_OF_REGISTERS
#define PARSER_MAXIMUM_NUMBER_OF_REGISTERS 256
#endif /* !PARSER_MAXIMUM_NUMBER_OF_REGISTERS */
/**
* Maximum number of literals.
* Limit: 32767 - PARSER_MAXIMUM_NUMBER_OF_REGISTERS. Recommended: 32767 - PARSER_MAXIMUM_NUMBER_OF_REGISTERS.
*/
#ifndef PARSER_MAXIMUM_NUMBER_OF_LITERALS
#define PARSER_MAXIMUM_NUMBER_OF_LITERALS (32767 - PARSER_MAXIMUM_NUMBER_OF_REGISTERS)
#endif /* !PARSER_MAXIMUM_NUMBER_OF_LITERALS */
/**
* Maximum depth of scope stack.
* Limit: 32767. Recommended: 32767
*/
#ifndef PARSER_MAXIMUM_DEPTH_OF_SCOPE_STACK
#define PARSER_MAXIMUM_DEPTH_OF_SCOPE_STACK 32767
#endif /* !PARSER_MAXIMUM_DEPTH_OF_SCOPE_STACK */
/**
* Maximum code size.
* Limit: 16777215. Recommended: 65535, 16777215.
@@ -95,13 +103,19 @@
#error "Maximum identifier length is not within range."
#endif /* (PARSER_MAXIMUM_IDENT_LENGTH < 1) || (PARSER_MAXIMUM_IDENT_LENGTH > PARSER_MAXIMUM_STRING_LENGTH) */
#if (PARSER_MAXIMUM_NUMBER_OF_LITERALS < 1) || (PARSER_MAXIMUM_NUMBER_OF_LITERALS > 32767)
#if ((PARSER_MAXIMUM_NUMBER_OF_LITERALS < 1) \
|| (PARSER_MAXIMUM_NUMBER_OF_LITERALS + PARSER_MAXIMUM_NUMBER_OF_REGISTERS > 32767))
#error "Maximum number of literals is not within range."
#endif /* (PARSER_MAXIMUM_NUMBER_OF_LITERALS < 1) || (PARSER_MAXIMUM_NUMBER_OF_LITERALS > 32767) */
#endif /* ((PARSER_MAXIMUM_NUMBER_OF_LITERALS < 1) \
|| (PARSER_MAXIMUM_NUMBER_OF_LITERALS > 32767)) */
#if (PARSER_MAXIMUM_NUMBER_OF_REGISTERS > PARSER_MAXIMUM_NUMBER_OF_LITERALS)
#if (PARSER_MAXIMUM_DEPTH_OF_SCOPE_STACK < 1) || (PARSER_MAXIMUM_DEPTH_OF_SCOPE_STACK > 32767)
#error "Maximum depth of scope stack is not within range."
#endif /* (PARSER_MAXIMUM_DEPTH_OF_SCOPE_STACK < 1) || (PARSER_MAXIMUM_DEPTH_OF_SCOPE_STACK > 32767) */
#if ((PARSER_MAXIMUM_NUMBER_OF_REGISTERS * 2) > PARSER_MAXIMUM_NUMBER_OF_LITERALS)
#error "Maximum number of registers is not within range."
#endif /* (PARSER_MAXIMUM_NUMBER_OF_REGISTERS > PARSER_MAXIMUM_NUMBER_OF_LITERALS) */
#endif /* ((PARSER_MAXIMUM_NUMBER_OF_REGISTERS * 2) > PARSER_MAXIMUM_NUMBER_OF_LITERALS) */
#if (PARSER_MAXIMUM_CODE_SIZE < 4096) || (PARSER_MAXIMUM_CODE_SIZE > 16777215)
#error "Maximum code size is not within range."
+54 -61
View File
@@ -181,6 +181,8 @@ typedef enum
typedef struct
{
parser_try_block_type_t type; /**< current block type */
uint16_t scope_stack_top; /**< current top of scope stack */
uint16_t scope_stack_reg_top; /**< current top register of scope stack */
parser_branch_t branch; /**< branch to the end of the current block */
} parser_try_statement_t;
@@ -310,8 +312,6 @@ parser_parse_var_statement (parser_context_t *context_p) /**< context */
parser_line_counter_t ident_line_counter = context_p->token.line;
#endif /* ENABLED (JERRY_DEBUGGER) || ENABLED (JERRY_LINE_INFO) */
context_p->lit_object.literal_p->status_flags |= LEXER_FLAG_VAR;
#if ENABLED (JERRY_ES2015_MODULE_SYSTEM)
if (context_p->status_flags & PARSER_MODULE_STORE_IDENT)
{
@@ -362,9 +362,7 @@ static void
parser_parse_function_statement (parser_context_t *context_p) /**< context */
{
uint32_t status_flags;
lexer_literal_t *name_p;
lexer_literal_t *literal_p;
uint8_t no_reg_store;
JERRY_ASSERT (context_p->token.type == LEXER_KEYW_FUNCTION);
@@ -373,7 +371,7 @@ parser_parse_function_statement (parser_context_t *context_p) /**< context */
parser_line_counter_t debugger_column = context_p->token.column;
#endif /* ENABLED (JERRY_DEBUGGER) */
lexer_expect_identifier (context_p, LEXER_IDENT_LITERAL);
lexer_expect_identifier (context_p, LEXER_NEW_IDENT_LITERAL);
JERRY_ASSERT (context_p->token.type == LEXER_LITERAL
&& context_p->token.lit_location.type == LEXER_IDENT_LITERAL);
@@ -382,8 +380,6 @@ parser_parse_function_statement (parser_context_t *context_p) /**< context */
context_p->status_flags |= PARSER_ARGUMENTS_NOT_NEEDED;
}
name_p = context_p->lit_object.literal_p;
#if ENABLED (JERRY_ES2015_MODULE_SYSTEM)
if (context_p->status_flags & PARSER_MODULE_STORE_IDENT)
{
@@ -403,6 +399,7 @@ parser_parse_function_statement (parser_context_t *context_p) /**< context */
#if ENABLED (JERRY_DEBUGGER)
if (JERRY_CONTEXT (debugger_flags) & JERRY_DEBUGGER_CONNECTED)
{
lexer_literal_t *name_p = context_p->lit_object.literal_p;
jerry_debugger_send_string (JERRY_DEBUGGER_FUNCTION_NAME,
JERRY_DEBUGGER_NO_SUBTYPE,
name_p->u.char_p,
@@ -414,55 +411,35 @@ parser_parse_function_statement (parser_context_t *context_p) /**< context */
}
#endif /* ENABLED (JERRY_DEBUGGER) */
if (name_p->status_flags & LEXER_FLAG_INITIALIZED)
JERRY_ASSERT (context_p->scope_stack_top >= 2);
parser_scope_stack *scope_stack_p = context_p->scope_stack_p + context_p->scope_stack_top - 2;
uint16_t literal_index = context_p->lit_object.index;
while (literal_index != scope_stack_p->map_from)
{
if (!(name_p->status_flags & LEXER_FLAG_FUNCTION_ARGUMENT))
{
/* Overwrite the previous initialization. */
ecma_compiled_code_t *compiled_code_p;
scope_stack_p--;
literal_p = PARSER_GET_LITERAL ((size_t) (context_p->lit_object.index + 1));
JERRY_ASSERT (literal_p->type == LEXER_FUNCTION_LITERAL
&& literal_p->status_flags == 0);
compiled_code_p = parser_parse_function (context_p, status_flags);
util_free_literal (literal_p);
literal_p->u.bytecode_p = compiled_code_p;
lexer_next_token (context_p);
return;
}
}
else if (context_p->lit_object.index + 1 == context_p->literal_count)
{
/* The most common case: the literal is the last literal. */
name_p->status_flags |= LEXER_FLAG_VAR | LEXER_FLAG_INITIALIZED;
lexer_construct_function_object (context_p, status_flags);
lexer_next_token (context_p);
return;
JERRY_ASSERT (scope_stack_p >= context_p->scope_stack_p);
}
/* Clone the literal at the end. */
if (context_p->literal_count >= PARSER_MAXIMUM_NUMBER_OF_LITERALS)
JERRY_ASSERT (scope_stack_p[1].map_from == PARSER_SCOPE_STACK_FUNC);
literal_p = PARSER_GET_LITERAL ((size_t) scope_stack_p[1].map_to);
JERRY_ASSERT ((literal_p->type == LEXER_UNUSED_LITERAL || literal_p->type == LEXER_FUNCTION_LITERAL)
&& literal_p->status_flags == 0);
ecma_compiled_code_t *compiled_code_p = parser_parse_function (context_p, status_flags);
if (literal_p->type == LEXER_FUNCTION_LITERAL)
{
parser_raise_error (context_p, PARSER_ERR_LITERAL_LIMIT_REACHED);
ecma_bytecode_deref (literal_p->u.bytecode_p);
}
literal_p = (lexer_literal_t *) parser_list_append (context_p, &context_p->literal_pool);
*literal_p = *name_p;
no_reg_store = name_p->status_flags & (LEXER_FLAG_NO_REG_STORE | LEXER_FLAG_SOURCE_PTR);
literal_p->status_flags = LEXER_FLAG_VAR | LEXER_FLAG_INITIALIZED | no_reg_store;
literal_p->u.bytecode_p = compiled_code_p;
literal_p->type = LEXER_FUNCTION_LITERAL;
name_p->type = LEXER_UNUSED_LITERAL;
name_p->status_flags &= LEXER_FLAG_FUNCTION_ARGUMENT | LEXER_FLAG_SOURCE_PTR;
/* Byte code references to this literal are
* redirected to the newly allocated literal. */
name_p->prop.index = context_p->literal_count;
context_p->literal_count++;
lexer_construct_function_object (context_p, status_flags);
lexer_next_token (context_p);
} /* parser_parse_function_statement */
@@ -967,8 +944,6 @@ parser_parse_for_statement_start (parser_context_t *context_p) /**< context */
JERRY_ASSERT (context_p->token.type == LEXER_LITERAL
&& context_p->token.lit_location.type == LEXER_IDENT_LITERAL);
context_p->lit_object.literal_p->status_flags |= LEXER_FLAG_VAR;
literal_index = context_p->lit_object.index;
lexer_next_token (context_p);
@@ -1400,6 +1375,9 @@ parser_parse_try_statement_end (parser_context_t *context_p) /**< context */
if (try_statement.type == parser_catch_block)
{
context_p->scope_stack_top = try_statement.scope_stack_top;
context_p->scope_stack_reg_top = try_statement.scope_stack_reg_top;
if (context_p->token.type != LEXER_KEYW_FINALLY)
{
parser_flush_cbc (context_p);
@@ -1410,6 +1388,7 @@ parser_parse_try_statement_end (parser_context_t *context_p) /**< context */
parser_emit_cbc (context_p, CBC_CONTEXT_END);
parser_flush_cbc (context_p);
try_statement.type = parser_finally_block;
}
}
@@ -1439,12 +1418,34 @@ parser_parse_try_statement_end (parser_context_t *context_p) /**< context */
parser_raise_error (context_p, PARSER_ERR_LEFT_PAREN_EXPECTED);
}
try_statement.type = parser_catch_block;
parser_emit_cbc_ext_forward_branch (context_p,
CBC_EXT_CATCH,
&try_statement.branch);
try_statement.scope_stack_top = context_p->scope_stack_top;
try_statement.scope_stack_reg_top = context_p->scope_stack_reg_top;
#ifndef JERRY_NDEBUG
bool block_found = false;
#endif /* !JERRY_NDEBUG */
if (context_p->next_scanner_info_p->source_p == context_p->source_p
&& context_p->next_scanner_info_p->type == SCANNER_TYPE_BLOCK)
{
#ifndef JERRY_NDEBUG
block_found = true;
#endif /* !JERRY_NDEBUG */
scanner_create_variables (context_p, sizeof (scanner_info_t));
}
lexer_expect_identifier (context_p, LEXER_IDENT_LITERAL);
JERRY_ASSERT (context_p->token.type == LEXER_LITERAL
&& context_p->token.lit_location.type == LEXER_IDENT_LITERAL);
context_p->lit_object.literal_p->status_flags |= LEXER_FLAG_NO_REG_STORE;
context_p->status_flags |= PARSER_LEXICAL_ENV_NEEDED;
#ifndef JERRY_NDEBUG
JERRY_ASSERT (block_found);
#endif /* !JERRY_NDEBUG */
literal_index = context_p->lit_object.index;
@@ -1462,11 +1463,6 @@ parser_parse_try_statement_end (parser_context_t *context_p) /**< context */
parser_raise_error (context_p, PARSER_ERR_LEFT_BRACE_EXPECTED);
}
try_statement.type = parser_catch_block;
parser_emit_cbc_ext_forward_branch (context_p,
CBC_EXT_CATCH,
&try_statement.branch);
parser_emit_cbc_literal (context_p, CBC_ASSIGN_SET_IDENT, literal_index);
parser_flush_cbc (context_p);
}
@@ -1960,10 +1956,7 @@ parser_parse_export_statement (parser_context_t *context_p) /**< context */
scanner_set_location (context_p, &location);
/* 15.2.3.5 Use the synthetic name '*default*' as the identifier. */
lexer_construct_literal_object (context_p,
(lexer_lit_location_t *) &lexer_default_literal,
lexer_default_literal.type);
context_p->lit_object.literal_p->status_flags |= LEXER_FLAG_VAR;
lexer_construct_literal_object (context_p, &lexer_default_literal, lexer_default_literal.type);
context_p->token.lit_location.type = LEXER_IDENT_LITERAL;
parser_emit_cbc_literal_from_token (context_p, CBC_PUSH_LITERAL);
+75 -17
View File
@@ -85,6 +85,51 @@ parser_emit_two_bytes (parser_context_t *context_p, /**< context */
} \
(context_p)->byte_code.last_p->bytes[(context_p)->byte_code.last_position++] = (uint8_t) (byte)
#if ENABLED (JERRY_PARSER_DUMP_BYTE_CODE)
/**
* Print literal corresponding to the current index
*/
static void
parser_print_literal (parser_context_t *context_p, /**< context */
uint16_t literal_index) /**< index of literal */
{
parser_scope_stack *scope_stack_p = context_p->scope_stack_p;
parser_scope_stack *scope_stack_end_p = scope_stack_p + context_p->scope_stack_top;
int32_t scope_literal_index = -1;
while (scope_stack_p < scope_stack_end_p)
{
scope_stack_end_p--;
if (literal_index == scope_stack_end_p->map_to)
{
scope_literal_index = scope_stack_end_p->map_from;
}
}
if (literal_index < PARSER_REGISTER_START)
{
JERRY_DEBUG_MSG (scope_literal_index != -1 ? " IDX:%d->" : " idx:%d->", literal_index);
lexer_literal_t *literal_p = PARSER_GET_LITERAL (literal_index);
util_print_literal (literal_p);
return;
}
if (scope_literal_index == -1)
{
JERRY_DEBUG_MSG (" reg:%d", (int) (literal_index - PARSER_REGISTER_START));
return;
}
JERRY_DEBUG_MSG (" REG:%d->", (int) (literal_index - PARSER_REGISTER_START));
lexer_literal_t *literal_p = PARSER_GET_LITERAL (scope_stack_end_p->map_from);
util_print_literal (literal_p);
} /* parser_print_literal */
#endif /* ENABLED (JERRY_PARSER_DUMP_BYTE_CODE) */
/**
* Append the current byte code to the stream
*/
@@ -181,26 +226,16 @@ parser_flush_cbc (parser_context_t *context_p) /**< context */
if (flags & (CBC_HAS_LITERAL_ARG | CBC_HAS_LITERAL_ARG2))
{
uint16_t literal_index = context_p->last_cbc.literal_index;
lexer_literal_t *literal_p = PARSER_GET_LITERAL (literal_index);
JERRY_DEBUG_MSG (" idx:%d->", literal_index);
util_print_literal (literal_p);
parser_print_literal (context_p, context_p->last_cbc.literal_index);
}
if (flags & CBC_HAS_LITERAL_ARG2)
{
uint16_t literal_index = context_p->last_cbc.value;
lexer_literal_t *literal_p = PARSER_GET_LITERAL (literal_index);
JERRY_DEBUG_MSG (" idx:%d->", literal_index);
util_print_literal (literal_p);
parser_print_literal (context_p, context_p->last_cbc.value);
if (!(flags & CBC_HAS_LITERAL_ARG))
{
literal_index = context_p->last_cbc.third_literal_index;
literal_p = PARSER_GET_LITERAL (literal_index);
JERRY_DEBUG_MSG (" idx:%d->", literal_index);
util_print_literal (literal_p);
parser_print_literal (context_p, context_p->last_cbc.third_literal_index);
}
}
@@ -276,6 +311,29 @@ parser_emit_cbc_literal (parser_context_t *context_p, /**< context */
context_p->last_cbc.literal_object_type = LEXER_LITERAL_OBJECT_ANY;
} /* parser_emit_cbc_literal */
/**
* Append a byte code with a literal and value argument
*/
void
parser_emit_cbc_literal_value (parser_context_t *context_p, /**< context */
uint16_t opcode, /**< opcode */
uint16_t literal_index, /**< literal index */
uint16_t value) /**< value */
{
JERRY_ASSERT (PARSER_ARGS_EQ (opcode, CBC_HAS_LITERAL_ARG | CBC_HAS_LITERAL_ARG2));
if (context_p->last_cbc_opcode != PARSER_CBC_UNAVAILABLE)
{
parser_flush_cbc (context_p);
}
context_p->last_cbc_opcode = opcode;
context_p->last_cbc.literal_index = literal_index;
context_p->last_cbc.literal_type = LEXER_UNUSED_LITERAL;
context_p->last_cbc.literal_object_type = LEXER_LITERAL_OBJECT_ANY;
context_p->last_cbc.value = value;
} /* parser_emit_cbc_literal_value */
/**
* Append a byte code with the current literal argument
*/
@@ -754,6 +812,10 @@ parser_error_to_string (parser_error_t error) /**< error code */
{
return "Maximum number of literals reached.";
}
case PARSER_ERR_SCOPE_STACK_LIMIT_REACHED:
{
return "Maximum depth of scope stack reached.";
}
case PARSER_ERR_ARGUMENT_LIMIT_REACHED:
{
return "Maximum number of function arguments reached.";
@@ -762,10 +824,6 @@ parser_error_to_string (parser_error_t error) /**< error code */
{
return "Maximum function stack size reached.";
}
case PARSER_ERR_REGISTER_LIMIT_REACHED:
{
return "Maximum number of registers is reached.";
}
case PARSER_ERR_INVALID_CHARACTER:
{
return "Invalid (unexpected) character.";
File diff suppressed because it is too large Load Diff
+1 -1
View File
@@ -37,9 +37,9 @@ typedef enum
PARSER_ERR_OUT_OF_MEMORY, /**< out of memory */
PARSER_ERR_LITERAL_LIMIT_REACHED, /**< maximum number of literals reached */
PARSER_ERR_SCOPE_STACK_LIMIT_REACHED, /**< maximum depth of scope stack reached */
PARSER_ERR_ARGUMENT_LIMIT_REACHED, /**< maximum number of function arguments reached */
PARSER_ERR_STACK_LIMIT_REACHED, /**< maximum function stack size reached */
PARSER_ERR_REGISTER_LIMIT_REACHED, /**< maximum register size reached */
PARSER_ERR_INVALID_CHARACTER, /**< unexpected character */
PARSER_ERR_INVALID_HEX_DIGIT, /**< invalid hexadecimal digit */
+66 -3
View File
@@ -16,7 +16,7 @@
#ifndef JS_SCANNER_INTERNAL_H
#define JS_SCANNER_INTERNAL_H
/** \addtogroup parser Parser
/* \addtogroup parser Parser
* @{
*
* \addtogroup jsparser JavaScript
@@ -34,6 +34,19 @@ typedef struct
const uint8_t *source_p; /**< start source byte */
} scanner_source_start_t;
/**
* Flags for type member of lexer_lit_location_t structure in the literal pool.
*/
typedef enum
{
SCANNER_LITERAL_IS_ARG = (1 << 0), /**< literal is argument */
SCANNER_LITERAL_IS_LOCAL = (1 << 1), /**< literal is local (similar to let,
* but var is allowed with the same identifier) */
SCANNER_LITERAL_IS_VAR = (1 << 2), /**< literal is var */
SCANNER_LITERAL_IS_FUNC = (1 << 3), /**< literal is function */
SCANNER_LITERAL_NO_REG = (1 << 4), /**< literal cannot be stored in register */
} scanner_literal_type_flags_t;
/**
* For statement descriptor.
*/
@@ -55,14 +68,64 @@ typedef struct
scanner_case_info_t **last_case_p; /**< last case info */
} scanner_switch_statement_t;
/**
* Flags for scanner_literal_pool_t structure.
*/
typedef enum
{
SCANNER_LITERAL_POOL_FUNCTION = (1 << 0), /**< literal pool represents a function */
SCANNER_LITERAL_POOL_BLOCK = (1 << 1), /**< literal pool represents a code block */
SCANNER_LITERAL_POOL_NO_REG = (1 << 2), /**< variable declarations cannot be kept in registers */
SCANNER_LITERAL_POOL_NO_ARGUMENTS = (1 << 3), /**< arguments object should not be constructed */
SCANNER_LITERAL_POOL_IN_WITH = (1 << 4), /**< literal pool is in a with statement */
} scanner_literal_pool_flags_t;
/**
* Define a function where no arguments are allowed.
*/
#define SCANNER_LITERAL_POOL_FUNCTION_WITHOUT_ARGUMENTS \
(SCANNER_LITERAL_POOL_FUNCTION | SCANNER_LITERAL_POOL_NO_ARGUMENTS)
/**
* Local literal pool.
*/
typedef struct scanner_literal_pool_t
{
struct scanner_literal_pool_t *prev_p; /**< previous literal pool */
const uint8_t *source_p; /**< source position where the final data needs to be inserted */
parser_list_t literal_pool; /**< list of literal */
uint16_t status_flags; /**< combination of scanner_literal_pool_flags_t flags */
uint16_t no_declarations; /**< size of scope stack required during parsing */
} scanner_literal_pool_t;
/**
* Scanner context.
*/
typedef struct
struct scanner_context_t
{
uint8_t mode; /**< scanner mode */
#if ENABLED (JERRY_DEBUGGER)
uint8_t debugger_enabled; /**< debugger is enabled */
#endif /* ENABLED (JERRY_DEBUGGER) */
scanner_literal_pool_t *active_literal_pool_p; /**< currently active literal pool */
scanner_switch_statement_t active_switch_statement; /**< currently active switch statement */
} scanner_context_t;
scanner_info_t *end_arguments_p; /**< position of end arguments */
};
size_t scanner_get_stream_size (scanner_info_t *info_p, size_t size);
scanner_info_t *scanner_insert_info (parser_context_t *context_p, const uint8_t *source_p, size_t size);
scanner_info_t *scanner_insert_info_before (parser_context_t *context_p, const uint8_t *source_p,
scanner_info_t *start_info_p, size_t size);
scanner_literal_pool_t *scanner_push_literal_pool (parser_context_t *context_p, scanner_context_t *scanner_context_p,
uint16_t status_flags);
void scanner_pop_literal_pool (parser_context_t *context_p, scanner_context_t *scanner_context_p);
void scanner_filter_arguments (parser_context_t *context_p, scanner_context_t *scanner_context_p);
lexer_lit_location_t *scanner_add_custom_literal (parser_context_t *context_p, scanner_literal_pool_t *literal_pool_p,
const lexer_lit_location_t *literal_location_p);
lexer_lit_location_t *scanner_add_literal (parser_context_t *context_p, scanner_context_t *scanner_context_p);
void scanner_add_reference (parser_context_t *context_p, scanner_context_t *scanner_context_p);
void scanner_append_argument (parser_context_t *context_p, scanner_context_t *scanner_context_p);
void scanner_detect_eval_call (parser_context_t *context_p, scanner_context_t *scanner_context_p);
/**
* @}
+913 -5
View File
@@ -15,6 +15,7 @@
#include "js-parser-internal.h"
#include "js-scanner-internal.h"
#include "lit-char-helpers.h"
#if ENABLED (JERRY_PARSER)
@@ -28,6 +29,9 @@
* @{
*/
JERRY_STATIC_ASSERT (PARSER_MAXIMUM_NUMBER_OF_LITERALS + PARSER_MAXIMUM_NUMBER_OF_REGISTERS < PARSER_REGISTER_START,
maximum_number_of_literals_plus_registers_must_be_less_than_register_start);
/**
* Raise a scanner error.
*/
@@ -74,6 +78,52 @@ scanner_free (void *ptr, /**< pointer to free */
jmem_heap_free_block (ptr, size);
} /* scanner_free */
/**
* Count the size of a stream after an info block.
*
* @return the size in bytes
*/
size_t
scanner_get_stream_size (scanner_info_t *info_p, /**< scanner info block */
size_t size) /**< size excluding the stream */
{
const uint8_t *data_p = ((const uint8_t *) info_p) + size;
const uint8_t *data_p_start = data_p;
while (data_p[0] != SCANNER_STREAM_TYPE_END)
{
switch (data_p[0] & SCANNER_STREAM_TYPE_MASK)
{
case SCANNER_STREAM_TYPE_ARG:
case SCANNER_STREAM_TYPE_ARG_FUNC:
case SCANNER_STREAM_TYPE_VAR:
case SCANNER_STREAM_TYPE_FUNC:
{
break;
}
default:
{
JERRY_ASSERT ((data_p[0] & SCANNER_STREAM_TYPE_MASK) == SCANNER_STREAM_TYPE_HOLE);
data_p++;
continue;
}
}
data_p += 3;
if (data_p[-3] & SCANNER_STREAM_UINT16_DIFF)
{
data_p++;
}
else if (data_p[-1] == 0)
{
data_p += sizeof (const uint8_t *);
}
}
return size + 1 + (size_t) (data_p - data_p_start);
} /* scanner_get_stream_size */
/**
* Insert a scanner info block into the scanner info chain.
*
@@ -89,6 +139,7 @@ scanner_insert_info (parser_context_t *context_p, /**< context */
scanner_info_t *prev_scanner_info_p = NULL;
JERRY_ASSERT (scanner_info_p != NULL);
JERRY_ASSERT (source_p != NULL);
new_scanner_info_p->source_p = source_p;
@@ -117,6 +168,42 @@ scanner_insert_info (parser_context_t *context_p, /**< context */
return new_scanner_info_p;
} /* scanner_insert_info */
/**
* Insert a scanner info block into the scanner info chain before a given info block.
*
* @return newly allocated scanner info
*/
scanner_info_t *
scanner_insert_info_before (parser_context_t *context_p, /**< context */
const uint8_t *source_p, /**< triggering position */
scanner_info_t *start_info_p, /**< first info position */
size_t size) /**< size of the memory block */
{
JERRY_ASSERT (start_info_p != NULL);
scanner_info_t *new_scanner_info_p = (scanner_info_t *) scanner_malloc (context_p, size);
scanner_info_t *scanner_info_p = start_info_p->next_p;
scanner_info_t *prev_scanner_info_p = start_info_p;
new_scanner_info_p->source_p = source_p;
while (source_p < scanner_info_p->source_p)
{
prev_scanner_info_p = scanner_info_p;
scanner_info_p = scanner_info_p->next_p;
JERRY_ASSERT (scanner_info_p != NULL);
}
/* Multiple scanner info blocks cannot be assigned to the same position. */
JERRY_ASSERT (source_p != scanner_info_p->source_p);
new_scanner_info_p->next_p = scanner_info_p;
prev_scanner_info_p->next_p = new_scanner_info_p;
return new_scanner_info_p;
} /* scanner_insert_info_before */
/**
* Release the next scanner info.
*/
@@ -225,6 +312,577 @@ scanner_seek (parser_context_t *context_p) /**< context */
context_p->next_scanner_info_p = prev_p->next_p;
} /* scanner_seek */
/**
* Push a new literal pool.
*
* @return the newly created literal pool
*/
scanner_literal_pool_t *
scanner_push_literal_pool (parser_context_t *context_p, /**< context */
scanner_context_t *scanner_context_p, /**< scanner context */
uint16_t status_flags) /**< combination of scanner_literal_pool_flags_t flags */
{
scanner_literal_pool_t *prev_literal_pool_p = scanner_context_p->active_literal_pool_p;
scanner_literal_pool_t *literal_pool_p;
literal_pool_p = (scanner_literal_pool_t *) scanner_malloc (context_p, sizeof (scanner_literal_pool_t));
if (!(status_flags & SCANNER_LITERAL_POOL_FUNCTION))
{
JERRY_ASSERT (prev_literal_pool_p != NULL);
if (prev_literal_pool_p->status_flags & SCANNER_LITERAL_POOL_IN_WITH)
{
status_flags |= SCANNER_LITERAL_POOL_IN_WITH;
}
}
parser_list_init (&literal_pool_p->literal_pool,
sizeof (lexer_lit_location_t),
(uint32_t) ((128 - sizeof (void *)) / sizeof (lexer_lit_location_t)));
literal_pool_p->source_p = NULL;
literal_pool_p->status_flags = status_flags;
literal_pool_p->no_declarations = 0;
literal_pool_p->prev_p = prev_literal_pool_p;
scanner_context_p->active_literal_pool_p = literal_pool_p;
return literal_pool_p;
} /* scanner_push_literal_pool */
JERRY_STATIC_ASSERT (PARSER_MAXIMUM_IDENT_LENGTH <= UINT8_MAX,
maximum_ident_length_must_fit_in_a_byte);
/**
* Pop the last literal pool from the end.
*/
void
scanner_pop_literal_pool (parser_context_t *context_p, /**< context */
scanner_context_t *scanner_context_p) /**< scanner context */
{
scanner_literal_pool_t *literal_pool_p = scanner_context_p->active_literal_pool_p;
scanner_literal_pool_t *prev_literal_pool_p = literal_pool_p->prev_p;
parser_list_iterator_t literal_iterator;
lexer_lit_location_t *literal_p;
bool is_function = (literal_pool_p->status_flags & SCANNER_LITERAL_POOL_FUNCTION) != 0;
bool no_reg = (literal_pool_p->status_flags & SCANNER_LITERAL_POOL_NO_REG) != 0;
bool search_arguments = is_function && (literal_pool_p->status_flags & SCANNER_LITERAL_POOL_NO_ARGUMENTS) == 0;
bool arguments_required = (no_reg && search_arguments);
if (no_reg && prev_literal_pool_p != NULL)
{
prev_literal_pool_p->status_flags |= SCANNER_LITERAL_POOL_NO_REG;
}
#if ENABLED (JERRY_DEBUGGER)
if (scanner_context_p->debugger_enabled)
{
/* When debugger is enabled, identifiers are not stored in registers. However,
* this does not affect 'eval' detection, so 'arguments' object is not created. */
no_reg = true;
}
#endif /* ENABLED (JERRY_DEBUGGER) */
parser_list_iterator_init (&literal_pool_p->literal_pool, &literal_iterator);
const uint8_t *prev_source_p = literal_pool_p->source_p - 1;
size_t compressed_size = 1;
uint32_t no_declarations = literal_pool_p->no_declarations;
while ((literal_p = (lexer_lit_location_t *) parser_list_iterator_next (&literal_iterator)) != NULL)
{
uint8_t type = literal_p->type;
if (JERRY_UNLIKELY (no_declarations > PARSER_MAXIMUM_DEPTH_OF_SCOPE_STACK))
{
continue;
}
if (search_arguments
&& literal_p->length == 9
&& lexer_compare_identifiers (literal_p->char_p, (const uint8_t *) "arguments", 9))
{
search_arguments = false;
if (type & (SCANNER_LITERAL_IS_ARG | SCANNER_LITERAL_IS_FUNC))
{
arguments_required = false;
}
else
{
literal_p->type = 0;
arguments_required = true;
continue;
}
}
if (((type & (SCANNER_LITERAL_IS_VAR | SCANNER_LITERAL_IS_ARG)) && is_function)
|| (type & SCANNER_LITERAL_IS_LOCAL))
{
JERRY_ASSERT (is_function || !(literal_p->type & SCANNER_LITERAL_IS_ARG));
if (literal_p->length == 0)
{
compressed_size += 1;
continue;
}
no_declarations++;
if (type & SCANNER_LITERAL_IS_FUNC)
{
no_declarations++;
}
if (no_reg)
{
type |= SCANNER_LITERAL_NO_REG;
literal_p->type = type;
}
intptr_t diff = (intptr_t) (literal_p->char_p - prev_source_p);
if (diff >= 1 && diff <= UINT8_MAX)
{
compressed_size += 2 + 1;
}
else if (diff >= -UINT8_MAX && diff <= UINT16_MAX)
{
compressed_size += 2 + 2;
}
else
{
compressed_size += 2 + 1 + sizeof (const uint8_t *);
}
prev_source_p = literal_p->char_p + literal_p->length;
if (is_function || !(type & SCANNER_LITERAL_IS_VAR))
{
continue;
}
}
if (prev_literal_pool_p != NULL && literal_p->length > 0)
{
/* Propagate literal to upper level. */
lexer_lit_location_t *literal_location_p = scanner_add_custom_literal (context_p,
prev_literal_pool_p,
literal_p);
if (is_function || (type & SCANNER_LITERAL_NO_REG))
{
literal_location_p->type |= SCANNER_LITERAL_NO_REG;
}
type = (type & (SCANNER_LITERAL_IS_VAR | SCANNER_LITERAL_IS_FUNC));
JERRY_ASSERT (type == 0 || !is_function);
literal_location_p->type = (uint8_t) (literal_location_p->type | type);
}
}
if (is_function || (compressed_size > 1))
{
compressed_size += is_function ? sizeof (scanner_function_info_t) : sizeof (scanner_info_t);
scanner_info_t *info_p;
if (prev_literal_pool_p != NULL || scanner_context_p->end_arguments_p == NULL)
{
info_p = scanner_insert_info (context_p, literal_pool_p->source_p, compressed_size);
}
else
{
scanner_info_t *start_info_p = scanner_context_p->end_arguments_p;
info_p = scanner_insert_info_before (context_p, literal_pool_p->source_p, start_info_p, compressed_size);
}
if (no_declarations > PARSER_MAXIMUM_DEPTH_OF_SCOPE_STACK)
{
no_declarations = PARSER_MAXIMUM_DEPTH_OF_SCOPE_STACK;
}
uint8_t *data_p = (uint8_t *) info_p;
if (is_function)
{
info_p->type = SCANNER_TYPE_FUNCTION;
data_p += sizeof (scanner_function_info_t);
scanner_function_info_t *function_info_p = (scanner_function_info_t *) info_p;
uint8_t status_flags = 0;
if (arguments_required)
{
status_flags |= SCANNER_FUNCTION_ARGUMENTS_NEEDED;
if (no_declarations < PARSER_MAXIMUM_DEPTH_OF_SCOPE_STACK)
{
no_declarations++;
}
}
function_info_p->info.u8_arg = status_flags;
function_info_p->info.u16_arg = (uint16_t) no_declarations;
}
else
{
info_p->type = SCANNER_TYPE_BLOCK;
data_p += sizeof (scanner_info_t);
JERRY_ASSERT (prev_literal_pool_p != NULL);
if (prev_literal_pool_p->no_declarations < no_declarations)
{
prev_literal_pool_p->no_declarations = (uint16_t) no_declarations;
}
}
parser_list_iterator_init (&literal_pool_p->literal_pool, &literal_iterator);
prev_source_p = literal_pool_p->source_p - 1;
no_declarations = 0;
while ((literal_p = (lexer_lit_location_t *) parser_list_iterator_next (&literal_iterator)) != NULL)
{
if (JERRY_UNLIKELY (no_declarations > PARSER_MAXIMUM_DEPTH_OF_SCOPE_STACK)
|| (!((literal_p->type & (SCANNER_LITERAL_IS_VAR | SCANNER_LITERAL_IS_ARG)) && is_function)
&& !(literal_p->type & SCANNER_LITERAL_IS_LOCAL)))
{
continue;
}
if (literal_p->length == 0)
{
*data_p++ = SCANNER_STREAM_TYPE_HOLE;
continue;
}
no_declarations++;
uint8_t type = SCANNER_STREAM_TYPE_VAR;
if (literal_p->type & SCANNER_LITERAL_IS_FUNC)
{
no_declarations++;
type = SCANNER_STREAM_TYPE_FUNC;
if (literal_p->type & SCANNER_LITERAL_IS_ARG)
{
type = SCANNER_STREAM_TYPE_ARG_FUNC;
}
}
else if (literal_p->type & SCANNER_LITERAL_IS_ARG)
{
type = SCANNER_STREAM_TYPE_ARG;
}
if (literal_p->has_escape)
{
type |= SCANNER_STREAM_HAS_ESCAPE;
}
if ((literal_p->type & SCANNER_LITERAL_NO_REG)
|| (arguments_required && (literal_p->type & SCANNER_LITERAL_IS_ARG)))
{
type |= SCANNER_STREAM_NO_REG;
}
data_p[0] = type;
data_p[1] = (uint8_t) literal_p->length;
data_p += 3;
intptr_t diff = (intptr_t) (literal_p->char_p - prev_source_p);
if (diff >= 1 && diff <= UINT8_MAX)
{
data_p[-1] = (uint8_t) diff;
}
else if (diff >= -UINT8_MAX && diff <= UINT16_MAX)
{
if (diff < 0)
{
diff = -diff;
}
data_p[-3] |= SCANNER_STREAM_UINT16_DIFF;
data_p[-1] = (uint8_t) diff;
data_p[0] = (uint8_t) (diff >> 8);
data_p += 1;
}
else
{
data_p[-1] = 0;
memcpy (data_p, &literal_p->char_p, sizeof (const uint8_t *));
data_p += sizeof (const uint8_t *);
}
prev_source_p = literal_p->char_p + literal_p->length;
}
data_p[0] = SCANNER_STREAM_TYPE_END;
JERRY_ASSERT (((uint8_t *) info_p) + compressed_size == data_p + 1);
}
scanner_context_p->active_literal_pool_p = literal_pool_p->prev_p;
parser_list_free (&literal_pool_p->literal_pool);
scanner_free (literal_pool_p, sizeof (scanner_literal_pool_t));
} /* scanner_pop_literal_pool */
/**
* Filter out the arguments from a literal pool.
*/
void
scanner_filter_arguments (parser_context_t *context_p, /**< context */
scanner_context_t *scanner_context_p) /**< scanner context */
{
/* Fast case: check whether all literals are arguments. */
scanner_literal_pool_t *literal_pool_p = scanner_context_p->active_literal_pool_p;
scanner_literal_pool_t *prev_literal_pool_p = literal_pool_p->prev_p;
parser_list_iterator_t literal_iterator;
lexer_lit_location_t *literal_p;
bool no_reg = (literal_pool_p->status_flags & SCANNER_LITERAL_POOL_NO_REG) != 0;
if (no_reg && prev_literal_pool_p != NULL)
{
prev_literal_pool_p->status_flags |= SCANNER_LITERAL_POOL_NO_REG;
}
literal_pool_p->status_flags &= (uint16_t) ~SCANNER_LITERAL_POOL_NO_REG;
parser_list_iterator_init (&literal_pool_p->literal_pool, &literal_iterator);
while ((literal_p = (lexer_lit_location_t *) parser_list_iterator_next (&literal_iterator)) != NULL)
{
if (no_reg)
{
literal_p->type |= SCANNER_LITERAL_NO_REG;
}
if (!(literal_p->type & SCANNER_LITERAL_IS_ARG))
{
break;
}
}
if (literal_p == NULL)
{
return;
}
scanner_literal_pool_t *new_literal_pool_p;
new_literal_pool_p = (scanner_literal_pool_t *) scanner_malloc (context_p, sizeof (scanner_literal_pool_t));
new_literal_pool_p->prev_p = literal_pool_p;
scanner_context_p->active_literal_pool_p = new_literal_pool_p;
*new_literal_pool_p = *literal_pool_p;
parser_list_init (&new_literal_pool_p->literal_pool,
sizeof (lexer_lit_location_t),
(uint32_t) ((128 - sizeof (void *)) / sizeof (lexer_lit_location_t)));
parser_list_iterator_init (&literal_pool_p->literal_pool, &literal_iterator);
while ((literal_p = (lexer_lit_location_t *) parser_list_iterator_next (&literal_iterator)) != NULL)
{
if (literal_p->type & SCANNER_LITERAL_IS_ARG)
{
lexer_lit_location_t *new_literal_p;
new_literal_p = (lexer_lit_location_t *) parser_list_append (context_p, &new_literal_pool_p->literal_pool);
*new_literal_p = *literal_p;
if (no_reg)
{
new_literal_p->type |= SCANNER_LITERAL_NO_REG;
}
}
else
{
/* Propagate literal to upper level. */
lexer_lit_location_t *literal_location_p = scanner_add_custom_literal (context_p,
prev_literal_pool_p,
literal_p);
if (literal_p->type & SCANNER_LITERAL_NO_REG)
{
literal_location_p->type |= SCANNER_LITERAL_NO_REG;
}
}
}
new_literal_pool_p->prev_p = prev_literal_pool_p;
parser_list_free (&literal_pool_p->literal_pool);
scanner_free (literal_pool_p, sizeof (scanner_literal_pool_t));
} /* scanner_filter_arguments */
/**
* Add any literal to the specified literal pool.
*
* @return pointer to the literal
*/
lexer_lit_location_t *
scanner_add_custom_literal (parser_context_t *context_p, /**< context */
scanner_literal_pool_t *literal_pool_p, /**< literal pool */
const lexer_lit_location_t *literal_location_p) /**< literal */
{
parser_list_iterator_t literal_iterator;
parser_list_iterator_init (&literal_pool_p->literal_pool, &literal_iterator);
lexer_lit_location_t *literal_p;
const uint8_t *char_p = literal_location_p->char_p;
prop_length_t length = literal_location_p->length;
if (JERRY_LIKELY (!literal_location_p->has_escape))
{
while ((literal_p = (lexer_lit_location_t *) parser_list_iterator_next (&literal_iterator)) != NULL)
{
if (literal_p->length == length)
{
if (JERRY_LIKELY (!literal_p->has_escape))
{
if (memcmp (literal_p->char_p, char_p, length) == 0)
{
return literal_p;
}
}
else if (lexer_compare_identifiers (literal_p->char_p, char_p, length))
{
/* The non-escaped version is preferred. */
literal_p->char_p = char_p;
literal_p->has_escape = 0;
return literal_p;
}
}
}
}
else
{
while ((literal_p = (lexer_lit_location_t *) parser_list_iterator_next (&literal_iterator)) != NULL)
{
if (literal_p->length == length
&& lexer_compare_identifiers (literal_p->char_p, char_p, length))
{
return literal_p;
}
}
}
literal_p = (lexer_lit_location_t *) parser_list_append (context_p, &literal_pool_p->literal_pool);
*literal_p = *literal_location_p;
literal_p->type = 0;
return literal_p;
} /* scanner_add_custom_literal */
/**
* Add the current literal token to the current literal pool.
*
* @return pointer to the literal
*/
inline lexer_lit_location_t * JERRY_ATTR_ALWAYS_INLINE
scanner_add_literal (parser_context_t *context_p, /**< context */
scanner_context_t *scanner_context_p) /**< scanner context */
{
return scanner_add_custom_literal (context_p,
scanner_context_p->active_literal_pool_p,
&context_p->token.lit_location);
} /* scanner_add_literal */
/**
* Add the current literal token to the current literal pool and
* set SCANNER_LITERAL_NO_REG if it is inside a with statement.
*
* @return pointer to the literal
*/
inline void JERRY_ATTR_ALWAYS_INLINE
scanner_add_reference (parser_context_t *context_p, /**< context */
scanner_context_t *scanner_context_p) /**< scanner context */
{
lexer_lit_location_t *lit_location_p = scanner_add_custom_literal (context_p,
scanner_context_p->active_literal_pool_p,
&context_p->token.lit_location);
if (scanner_context_p->active_literal_pool_p->status_flags & SCANNER_LITERAL_POOL_IN_WITH)
{
lit_location_p->type |= SCANNER_LITERAL_NO_REG;
}
scanner_detect_eval_call (context_p, scanner_context_p);
} /* scanner_add_reference */
/**
* Append an argument to the literal pool. If the argument is already present, make it a "hole".
*/
void
scanner_append_argument (parser_context_t *context_p, /**< context */
scanner_context_t *scanner_context_p) /**< scanner context */
{
scanner_literal_pool_t *literal_pool_p = scanner_context_p->active_literal_pool_p;
parser_list_iterator_t literal_iterator;
parser_list_iterator_init (&literal_pool_p->literal_pool, &literal_iterator);
lexer_lit_location_t *literal_p;
const uint8_t *char_p = context_p->token.lit_location.char_p;
prop_length_t length = context_p->token.lit_location.length;
if (JERRY_LIKELY (!context_p->token.lit_location.has_escape))
{
while ((literal_p = (lexer_lit_location_t *) parser_list_iterator_next (&literal_iterator)) != NULL)
{
if (literal_p->length == length)
{
if (JERRY_LIKELY (!literal_p->has_escape))
{
if (memcmp (literal_p->char_p, char_p, length) == 0)
{
literal_p->length = 0;
break;
}
}
else if (lexer_compare_identifiers (literal_p->char_p, char_p, length))
{
literal_p->length = 0;
break;
}
}
}
}
else
{
while ((literal_p = (lexer_lit_location_t *) parser_list_iterator_next (&literal_iterator)) != NULL)
{
if (literal_p->length == length
&& lexer_compare_identifiers (literal_p->char_p, char_p, length))
{
literal_p->length = 0;
break;
}
}
}
literal_p = (lexer_lit_location_t *) parser_list_append (context_p, &literal_pool_p->literal_pool);
*literal_p = context_p->token.lit_location;
literal_p->type = SCANNER_LITERAL_IS_ARG;
} /* scanner_append_argument */
/**
* Check whether an eval call is performed and update the status flags accordingly.
*/
void
scanner_detect_eval_call (parser_context_t *context_p, /**< context */
scanner_context_t *scanner_context_p) /**< scanner context */
{
if (context_p->token.lit_location.length == 4
&& lexer_compare_identifiers (context_p->token.lit_location.char_p, (const uint8_t *) "eval", 4)
&& lexer_check_next_character (context_p, LIT_CHAR_LEFT_PAREN))
{
scanner_context_p->active_literal_pool_p->status_flags |= SCANNER_LITERAL_POOL_NO_REG;
}
} /* scanner_detect_eval_call */
/**
* Reverse the scanner info chain after the scanning is completed.
*/
@@ -282,6 +940,16 @@ scanner_cleanup (parser_context_t *context_p) /**< context */
scanner_info_p = context_p->active_scanner_info_p;
continue;
}
case SCANNER_TYPE_FUNCTION:
{
size = scanner_get_stream_size (scanner_info_p, sizeof (scanner_function_info_t));
break;
}
case SCANNER_TYPE_BLOCK:
{
size = scanner_get_stream_size (scanner_info_p, sizeof (scanner_info_t));
break;
}
case SCANNER_TYPE_WHILE:
case SCANNER_TYPE_FOR_IN:
#if ENABLED (JERRY_ES2015_FOR_OF)
@@ -305,12 +973,7 @@ scanner_cleanup (parser_context_t *context_p) /**< context */
}
default:
{
#if ENABLED (JERRY_ES2015_ARROW_FUNCTION)
JERRY_ASSERT (scanner_info_p->type == SCANNER_TYPE_END_ARGUMENTS
|| scanner_info_p->type == SCANNER_TYPE_ARROW);
#else /* !ENABLED (JERRY_ES2015_ARROW_FUNCTION) */
JERRY_ASSERT (scanner_info_p->type == SCANNER_TYPE_END_ARGUMENTS);
#endif /* ENABLED (JERRY_ES2015_ARROW_FUNCTION) */
break;
}
}
@@ -323,6 +986,251 @@ scanner_cleanup (parser_context_t *context_p) /**< context */
context_p->active_scanner_info_p = NULL;
} /* scanner_cleanup */
/**
* Description of "arguments" literal string.
*/
const lexer_lit_location_t lexer_arguments_literal =
{
(const uint8_t *) "arguments", 9, LEXER_IDENT_LITERAL, false
};
/**
* Create and/or initialize var/let/const/function/etc. variables.
*/
void
scanner_create_variables (parser_context_t *context_p, /**< context */
size_t size) /**< size excluding the stream */
{
scanner_info_t *info_p = context_p->next_scanner_info_p;
const uint8_t *data_p = ((const uint8_t *) info_p) + size;
uint8_t info_type = info_p->type;
lexer_lit_location_t literal;
parser_scope_stack *scope_stack_p;
parser_scope_stack *scope_stack_end_p;
JERRY_ASSERT (info_type == SCANNER_TYPE_FUNCTION || info_type == SCANNER_TYPE_BLOCK);
if (info_type == SCANNER_TYPE_FUNCTION)
{
JERRY_ASSERT (context_p->scope_stack_p == NULL);
size_t stack_size = info_p->u16_arg * sizeof (parser_scope_stack);
context_p->scope_stack_size = info_p->u16_arg;
if (stack_size == 0)
{
scanner_release_next (context_p, size + 1);
return;
}
scope_stack_p = (parser_scope_stack *) parser_malloc (context_p, stack_size);
context_p->scope_stack_p = scope_stack_p;
scope_stack_end_p = scope_stack_p + context_p->scope_stack_size;
}
else
{
JERRY_ASSERT (context_p->scope_stack_p != NULL);
scope_stack_p = context_p->scope_stack_p;
scope_stack_end_p = scope_stack_p + context_p->scope_stack_size;
scope_stack_p += context_p->scope_stack_top;
}
uint32_t scope_stack_reg_top = context_p->scope_stack_reg_top;
literal.char_p = info_p->source_p - 1;
while (data_p[0] != SCANNER_STREAM_TYPE_END)
{
uint32_t type = data_p[0] & SCANNER_STREAM_TYPE_MASK;
if (JERRY_UNLIKELY (scope_stack_p >= scope_stack_end_p))
{
JERRY_ASSERT (context_p->scope_stack_size == PARSER_MAXIMUM_DEPTH_OF_SCOPE_STACK);
parser_raise_error (context_p, PARSER_ERR_SCOPE_STACK_LIMIT_REACHED);
}
if (type == SCANNER_STREAM_TYPE_HOLE)
{
data_p++;
JERRY_ASSERT (info_type == SCANNER_TYPE_FUNCTION);
if (info_p->u8_arg & SCANNER_FUNCTION_ARGUMENTS_NEEDED)
{
if (JERRY_UNLIKELY (context_p->literal_count >= PARSER_MAXIMUM_NUMBER_OF_LITERALS))
{
parser_raise_error (context_p, PARSER_ERR_LITERAL_LIMIT_REACHED);
}
lexer_literal_t *literal_p = (lexer_literal_t *) parser_list_append (context_p, &context_p->literal_pool);
literal_p->type = LEXER_UNUSED_LITERAL;
literal_p->status_flags = LEXER_FLAG_FUNCTION_ARGUMENT;
context_p->literal_count++;
}
if (scope_stack_reg_top < PARSER_MAXIMUM_NUMBER_OF_REGISTERS)
{
scope_stack_reg_top++;
}
continue;
}
size_t length;
if (!(data_p[0] & SCANNER_STREAM_UINT16_DIFF))
{
if (data_p[2] != 0)
{
literal.char_p += data_p[2];
length = 2 + 1;
}
else
{
memcpy (&literal.char_p, data_p + 2 + 1, sizeof (const uint8_t *));
length = 2 + 1 + sizeof (const uint8_t *);
}
}
else
{
int32_t diff = ((int32_t) data_p[2]) | ((int32_t) data_p[3]) << 8;
if (diff <= UINT8_MAX)
{
diff = -diff;
}
literal.char_p += diff;
length = 2 + 2;
}
literal.length = data_p[1];
literal.type = LEXER_IDENT_LITERAL;
literal.has_escape = (data_p[0] & SCANNER_STREAM_HAS_ESCAPE) ? 1 : 0;
lexer_construct_literal_object (context_p, &literal, LEXER_NEW_IDENT_LITERAL);
uint16_t map_to;
if (!(data_p[0] & SCANNER_STREAM_NO_REG)
&& scope_stack_reg_top < PARSER_MAXIMUM_NUMBER_OF_REGISTERS)
{
map_to = (uint16_t) (PARSER_REGISTER_START + scope_stack_reg_top);
scope_stack_p->map_from = context_p->lit_object.index;
scope_stack_p->map_to = map_to;
scope_stack_reg_top++;
}
else
{
context_p->lit_object.literal_p->status_flags |= LEXER_FLAG_USED;
map_to = context_p->lit_object.index;
scope_stack_p->map_from = map_to;
scope_stack_p->map_to = map_to;
if (info_type == SCANNER_TYPE_FUNCTION)
{
context_p->status_flags |= PARSER_LEXICAL_ENV_NEEDED;
}
if (type == SCANNER_STREAM_TYPE_VAR)
{
#if ENABLED (JERRY_PARSER_DUMP_BYTE_CODE)
context_p->scope_stack_top = (uint16_t) (scope_stack_p - context_p->scope_stack_p);
#endif /* ENABLED (JERRY_PARSER_DUMP_BYTE_CODE) */
parser_emit_cbc_literal (context_p, CBC_CREATE_VAR, map_to);
}
else if (type == SCANNER_STREAM_TYPE_ARG || type == SCANNER_STREAM_TYPE_ARG_FUNC)
{
if (type == SCANNER_STREAM_TYPE_ARG)
{
#if ENABLED (JERRY_PARSER_DUMP_BYTE_CODE)
context_p->scope_stack_top = (uint16_t) (scope_stack_p - context_p->scope_stack_p);
#endif /* ENABLED (JERRY_PARSER_DUMP_BYTE_CODE) */
parser_emit_cbc_literal_value (context_p,
CBC_INIT_LOCAL,
(uint16_t) (PARSER_REGISTER_START + scope_stack_reg_top),
map_to);
}
if (scope_stack_reg_top < PARSER_MAXIMUM_NUMBER_OF_REGISTERS)
{
scope_stack_reg_top++;
}
}
}
scope_stack_p++;
literal.char_p += data_p[1];
data_p += length;
if (type != SCANNER_STREAM_TYPE_ARG_FUNC && type != SCANNER_STREAM_TYPE_FUNC)
{
continue;
}
if (JERRY_UNLIKELY (scope_stack_p >= scope_stack_end_p))
{
JERRY_ASSERT (context_p->scope_stack_size == PARSER_MAXIMUM_DEPTH_OF_SCOPE_STACK);
parser_raise_error (context_p, PARSER_ERR_SCOPE_STACK_LIMIT_REACHED);
}
if (JERRY_UNLIKELY (context_p->literal_count >= PARSER_MAXIMUM_NUMBER_OF_LITERALS))
{
parser_raise_error (context_p, PARSER_ERR_LITERAL_LIMIT_REACHED);
}
#if ENABLED (JERRY_PARSER_DUMP_BYTE_CODE)
context_p->scope_stack_top = (uint16_t) (scope_stack_p - context_p->scope_stack_p);
#endif /* ENABLED (JERRY_PARSER_DUMP_BYTE_CODE) */
parser_emit_cbc_literal_value (context_p, CBC_INIT_LOCAL, context_p->literal_count, map_to);
scope_stack_p->map_from = PARSER_SCOPE_STACK_FUNC;
scope_stack_p->map_to = context_p->literal_count;
scope_stack_p++;
lexer_literal_t *literal_p = (lexer_literal_t *) parser_list_append (context_p, &context_p->literal_pool);
literal_p->type = LEXER_UNUSED_LITERAL;
literal_p->status_flags = 0;
context_p->literal_count++;
}
if (info_type == SCANNER_TYPE_FUNCTION && (info_p->u8_arg & SCANNER_FUNCTION_ARGUMENTS_NEEDED))
{
if (JERRY_UNLIKELY (scope_stack_p >= scope_stack_end_p))
{
JERRY_ASSERT (context_p->scope_stack_size == PARSER_MAXIMUM_DEPTH_OF_SCOPE_STACK);
parser_raise_error (context_p, PARSER_ERR_SCOPE_STACK_LIMIT_REACHED);
}
context_p->status_flags |= PARSER_ARGUMENTS_NEEDED | PARSER_LEXICAL_ENV_NEEDED;
lexer_construct_literal_object (context_p, &lexer_arguments_literal, lexer_arguments_literal.type);
scope_stack_p->map_from = context_p->lit_object.index;
scope_stack_p->map_to = context_p->lit_object.index;
scope_stack_p++;
}
context_p->scope_stack_top = (uint16_t) (scope_stack_p - context_p->scope_stack_p);
context_p->scope_stack_reg_top = (uint16_t) scope_stack_reg_top;
if (context_p->register_count < scope_stack_reg_top)
{
context_p->register_count = (uint16_t) scope_stack_reg_top;
}
scanner_release_next (context_p, (size_t) (data_p + 1 - ((const uint8_t *) info_p)));
parser_flush_cbc (context_p);
} /* scanner_create_variables */
/**
* Get location from context.
*/
+447 -64
View File
@@ -13,6 +13,7 @@
* limitations under the License.
*/
#include "jcontext.h"
#include "js-parser-internal.h"
#include "js-scanner-internal.h"
#include "lit-char-helpers.h"
@@ -59,13 +60,15 @@ typedef enum
typedef enum
{
SCAN_STACK_SCRIPT, /**< script */
SCAN_STACK_EVAL_FUNCTION, /**< evaluated function */
SCAN_STACK_SCRIPT_FUNCTION, /**< script is a function body */
SCAN_STACK_BLOCK_STATEMENT, /**< block statement group */
SCAN_STACK_FUNCTION_STATEMENT, /**< function statement */
SCAN_STACK_FUNCTION_EXPRESSION, /**< function expression */
SCAN_STACK_FUNCTION_PROPERTY, /**< function expression in an object literal or class */
SCAN_STACK_SWITCH_BLOCK, /**< block part of "switch" statement */
SCAN_STACK_IF_STATEMENT, /**< statement part of "if" statements */
SCAN_STACK_WITH_STATEMENT, /**< statement part of "with" statements */
SCAN_STACK_WITH_EXPRESSION, /**< expression part of "with" statements */
SCAN_STACK_DO_STATEMENT, /**< statement part of "do" statements */
SCAN_STACK_DO_EXPRESSION, /**< expression part of "do" statements */
SCAN_STACK_WHILE_EXPRESSION, /**< expression part of "while" iterator */
@@ -158,10 +161,7 @@ static void
scanner_process_arrow (parser_context_t *context_p, /**< context */
scanner_context_t *scanner_context_p) /**< scanner context */
{
scanner_source_start_t source_start;
parser_stack_pop_uint8 (context_p);
parser_stack_pop (context_p, &source_start, sizeof (scanner_source_start_t));
lexer_next_token (context_p);
@@ -169,11 +169,16 @@ scanner_process_arrow (parser_context_t *context_p, /**< context */
|| (context_p->token.flags & LEXER_WAS_NEWLINE))
{
scanner_context_p->mode = SCAN_MODE_POST_PRIMARY_EXPRESSION;
scanner_pop_literal_pool (context_p, scanner_context_p);
return;
}
scanner_info_t *info_p = scanner_insert_info (context_p, source_start.source_p, sizeof (scanner_info_t));
info_p->type = SCANNER_TYPE_ARROW;
scanner_literal_pool_t *literal_pool_p = scanner_context_p->active_literal_pool_p;
literal_pool_p->status_flags |= SCANNER_LITERAL_POOL_FUNCTION_WITHOUT_ARGUMENTS;
literal_pool_p->status_flags &= (uint16_t) ~SCANNER_LITERAL_POOL_IN_WITH;
scanner_filter_arguments (context_p, scanner_context_p);
scanner_check_arrow_body (context_p, scanner_context_p);
} /* scanner_process_arrow */
@@ -186,8 +191,14 @@ scanner_process_simple_arrow (parser_context_t *context_p, /**< context */
scanner_context_t *scanner_context_p, /**< scanner context */
const uint8_t *source_p) /**< identifier end position */
{
scanner_info_t *info_p = scanner_insert_info (context_p, source_p, sizeof (scanner_info_t));
info_p->type = SCANNER_TYPE_ARROW;
scanner_literal_pool_t *literal_pool_p;
literal_pool_p = scanner_push_literal_pool (context_p,
scanner_context_p,
SCANNER_LITERAL_POOL_FUNCTION_WITHOUT_ARGUMENTS);
literal_pool_p->source_p = source_p;
lexer_lit_location_t *location_p = scanner_add_literal (context_p, scanner_context_p);
location_p->type |= SCANNER_LITERAL_IS_ARG;
/* Skip the => token, which size is two. */
context_p->source_p += 2;
@@ -197,6 +208,64 @@ scanner_process_simple_arrow (parser_context_t *context_p, /**< context */
scanner_check_arrow_body (context_p, scanner_context_p);
} /* scanner_process_simple_arrow */
/**
* Process the next argument of a might-be arrow function.
*/
static void
scanner_process_arrow_arg (parser_context_t *context_p, /**< context */
scanner_context_t *scanner_context_p) /**< scanner context */
{
JERRY_ASSERT (context_p->stack_top_uint8 == SCAN_STACK_ARROW_ARGUMENTS);
const uint8_t *source_p = context_p->source_p;
bool process_arrow = false;
scanner_context_p->mode = SCAN_MODE_PRIMARY_EXPRESSION;
#if ENABLED (JERRY_ES2015_FUNCTION_REST_PARAMETER)
if (context_p->token.type == LEXER_THREE_DOTS)
{
lexer_next_token (context_p);
}
#endif /* ENABLED (JERRY_ES2015_FUNCTION_REST_PARAMETER) */
if (context_p->token.type == LEXER_LITERAL
&& context_p->token.lit_location.type == LEXER_IDENT_LITERAL)
{
scanner_context_p->mode = SCAN_MODE_POST_PRIMARY_EXPRESSION;
if (lexer_check_arrow (context_p))
{
process_arrow = true;
}
else
{
scanner_append_argument (context_p, scanner_context_p);
scanner_detect_eval_call (context_p, scanner_context_p);
lexer_next_token (context_p);
if (context_p->token.type == LEXER_ASSIGN
|| context_p->token.type == LEXER_COMMA
|| context_p->token.type == LEXER_RIGHT_PAREN)
{
return;
}
}
}
scanner_pop_literal_pool (context_p, scanner_context_p);
parser_stack_pop_uint8 (context_p);
parser_stack_push_uint8 (context_p, SCAN_STACK_PAREN_EXPRESSION);
if (process_arrow)
{
scanner_process_simple_arrow (context_p, scanner_context_p, source_p);
}
} /* scanner_process_arrow_arg */
#endif /* ENABLED (JERRY_ES2015_ARROW_FUNCTION) */
/**
@@ -226,6 +295,8 @@ scanner_scan_primary_expression (parser_context_t *context_p, /**< context */
}
case LEXER_KEYW_FUNCTION:
{
scanner_push_literal_pool (context_p, scanner_context_p, SCANNER_LITERAL_POOL_FUNCTION);
lexer_next_token (context_p);
if (context_p->token.type == LEXER_LITERAL
&& context_p->token.lit_location.type == LEXER_IDENT_LITERAL)
@@ -240,15 +311,26 @@ scanner_scan_primary_expression (parser_context_t *context_p, /**< context */
case LEXER_LEFT_PAREN:
{
#if ENABLED (JERRY_ES2015_ARROW_FUNCTION)
scanner_source_start_t source_start;
source_start.source_p = context_p->source_p;
parser_stack_push (context_p, &source_start, sizeof (scanner_source_start_t));
parser_stack_push_uint8 (context_p, SCAN_STACK_ARROW_ARGUMENTS);
scanner_literal_pool_t *literal_pool_p;
literal_pool_p = scanner_push_literal_pool (context_p, scanner_context_p, 0);
literal_pool_p->source_p = context_p->source_p;
lexer_next_token (context_p);
if (context_p->token.type == LEXER_RIGHT_PAREN)
{
scanner_context_p->mode = SCAN_MODE_POST_PRIMARY_EXPRESSION;
return SCAN_KEEP_TOKEN;
}
scanner_process_arrow_arg (context_p, scanner_context_p);
return SCAN_KEEP_TOKEN;
#else
parser_stack_push_uint8 (context_p, SCAN_STACK_PAREN_EXPRESSION);
#endif /* ENABLED (JERRY_ES2015_ARROW_FUNCTION) */
scanner_context_p->mode = SCAN_MODE_PRIMARY_EXPRESSION;
#endif /* ENABLED (JERRY_ES2015_ARROW_FUNCTION) */
break;
}
case LEXER_LEFT_SQUARE:
@@ -278,8 +360,8 @@ scanner_scan_primary_expression (parser_context_t *context_p, /**< context */
}
#endif /* ENABLED (JERRY_ES2015_TEMPLATE_STRINGS) */
case LEXER_LITERAL:
#if ENABLED (JERRY_ES2015_ARROW_FUNCTION)
{
#if ENABLED (JERRY_ES2015_ARROW_FUNCTION)
const uint8_t *source_p = context_p->source_p;
if (context_p->token.lit_location.type == LEXER_IDENT_LITERAL
@@ -288,9 +370,14 @@ scanner_scan_primary_expression (parser_context_t *context_p, /**< context */
scanner_process_simple_arrow (context_p, scanner_context_p, source_p);
return SCAN_KEEP_TOKEN;
}
#endif /* ENABLED (JERRY_ES2015_ARROW_FUNCTION) */
if (context_p->token.lit_location.type == LEXER_IDENT_LITERAL)
{
scanner_add_reference (context_p, scanner_context_p);
}
/* FALLTHRU */
}
#endif /* ENABLED (JERRY_ES2015_ARROW_FUNCTION) */
case LEXER_KEYW_THIS:
case LEXER_KEYW_SUPER:
case LEXER_LIT_TRUE:
@@ -305,6 +392,13 @@ scanner_scan_primary_expression (parser_context_t *context_p, /**< context */
{
parser_stack_push_uint8 (context_p, SCAN_STACK_CLASS_EXPRESSION);
scanner_context_p->mode = SCAN_MODE_CLASS_DECLARATION;
lexer_next_token (context_p);
if (context_p->token.type != LEXER_LITERAL || context_p->token.lit_location.type != LEXER_IDENT_LITERAL)
{
return SCAN_KEEP_TOKEN;
}
break;
}
#endif /* ENABLED (JERRY_ES2015_CLASS) */
@@ -335,13 +429,6 @@ scanner_scan_primary_expression (parser_context_t *context_p, /**< context */
parser_stack_pop_uint8 (context_p);
break;
}
#if ENABLED (JERRY_ES2015_ARROW_FUNCTION)
if (stack_top == SCAN_STACK_ARROW_ARGUMENTS)
{
scanner_process_arrow (context_p, scanner_context_p);
return SCAN_KEEP_TOKEN;
}
#endif /* ENABLED (JERRY_ES2015_ARROW_FUNCTION) */
/* FALLTHRU */
}
default:
@@ -440,6 +527,12 @@ scanner_scan_primary_expression_end (parser_context_t *context_p, /**< context *
break;
}
#if ENABLED (JERRY_ES2015_ARROW_FUNCTION)
case SCAN_STACK_ARROW_ARGUMENTS:
{
lexer_next_token (context_p);
scanner_process_arrow_arg (context_p, scanner_context_p);
return SCAN_KEEP_TOKEN;
}
case SCAN_STACK_ARROW_EXPRESSION:
{
break;
@@ -476,30 +569,22 @@ scanner_scan_primary_expression_end (parser_context_t *context_p, /**< context *
switch (stack_top)
{
case SCAN_STACK_VAR:
{
parser_stack_pop_uint8 (context_p);
return SCAN_KEEP_TOKEN;
}
case SCAN_STACK_PAREN_EXPRESSION:
{
if (type != LEXER_RIGHT_PAREN)
{
break;
}
scanner_context_p->mode = SCAN_MODE_POST_PRIMARY_EXPRESSION;
parser_stack_pop_uint8 (context_p);
return SCAN_NEXT_TOKEN;
}
case SCAN_STACK_STATEMENT_WITH_EXPR:
case SCAN_STACK_WITH_EXPRESSION:
{
if (type != LEXER_RIGHT_PAREN)
{
break;
}
scanner_context_p->mode = SCAN_MODE_STATEMENT;
parser_stack_pop_uint8 (context_p);
uint16_t status_flags = scanner_context_p->active_literal_pool_p->status_flags;
parser_stack_push_uint8 (context_p, (status_flags & SCANNER_LITERAL_POOL_IN_WITH) ? 1 : 0);
parser_stack_push_uint8 (context_p, SCAN_STACK_WITH_STATEMENT);
status_flags |= SCANNER_LITERAL_POOL_IN_WITH;
scanner_context_p->active_literal_pool_p->status_flags = status_flags;
scanner_context_p->mode = SCAN_MODE_STATEMENT;
return SCAN_NEXT_TOKEN;
}
case SCAN_STACK_DO_EXPRESSION:
@@ -535,6 +620,32 @@ scanner_scan_primary_expression_end (parser_context_t *context_p, /**< context *
scanner_context_p->mode = SCAN_MODE_STATEMENT;
return SCAN_NEXT_TOKEN;
}
case SCAN_STACK_PAREN_EXPRESSION:
{
if (type != LEXER_RIGHT_PAREN)
{
break;
}
scanner_context_p->mode = SCAN_MODE_POST_PRIMARY_EXPRESSION;
parser_stack_pop_uint8 (context_p);
return SCAN_NEXT_TOKEN;
}
case SCAN_STACK_STATEMENT_WITH_EXPR:
{
if (type != LEXER_RIGHT_PAREN)
{
break;
}
scanner_context_p->mode = SCAN_MODE_STATEMENT;
parser_stack_pop_uint8 (context_p);
return SCAN_NEXT_TOKEN;
}
case SCAN_STACK_VAR:
{
parser_stack_pop_uint8 (context_p);
return SCAN_KEEP_TOKEN;
}
case SCAN_STACK_FOR_VAR_START:
case SCAN_STACK_FOR_START:
{
@@ -750,6 +861,8 @@ scanner_scan_primary_expression_end (parser_context_t *context_p, /**< context *
if (stack_top == SCAN_STACK_FUNCTION_PROPERTY)
{
scanner_push_literal_pool (context_p, scanner_context_p, SCANNER_LITERAL_POOL_FUNCTION);
scanner_context_p->mode = SCAN_MODE_FUNCTION_ARGUMENTS;
return SCAN_KEEP_TOKEN;
}
@@ -758,6 +871,8 @@ scanner_scan_primary_expression_end (parser_context_t *context_p, /**< context *
if (context_p->token.type == LEXER_LEFT_PAREN)
{
scanner_push_literal_pool (context_p, scanner_context_p, SCANNER_LITERAL_POOL_FUNCTION);
parser_stack_push_uint8 (context_p, SCAN_STACK_FUNCTION_PROPERTY);
scanner_context_p->mode = SCAN_MODE_FUNCTION_ARGUMENTS;
return SCAN_KEEP_TOKEN;
@@ -809,6 +924,7 @@ scanner_scan_primary_expression_end (parser_context_t *context_p, /**< context *
}
case SCAN_STACK_ARROW_EXPRESSION:
{
scanner_pop_literal_pool (context_p, scanner_context_p);
parser_stack_pop_uint8 (context_p);
scanner_context_p->mode = SCAN_MODE_POST_PRIMARY_EXPRESSION;
return SCAN_KEEP_TOKEN;
@@ -832,7 +948,7 @@ scanner_scan_primary_expression_end (parser_context_t *context_p, /**< context *
parser_stack_pop_uint8 (context_p);
if (type != LEXER_RIGHT_PAREN
&& (type != LEXER_EOS || context_p->stack_top_uint8 != SCAN_STACK_EVAL_FUNCTION))
&& (type != LEXER_EOS || context_p->stack_top_uint8 != SCAN_STACK_SCRIPT_FUNCTION))
{
break;
}
@@ -916,6 +1032,10 @@ scanner_scan_statement (parser_context_t *context_p, /**< context */
{
parser_stack_push_uint8 (context_p, SCAN_STACK_IF_STATEMENT);
}
else if (type == LEXER_KEYW_WITH)
{
mode = SCAN_STACK_WITH_EXPRESSION;
}
else if (type == LEXER_KEYW_SWITCH)
{
mode = SCAN_STACK_SWITCH_EXPRESSION;
@@ -1065,6 +1185,11 @@ scanner_scan_statement (parser_context_t *context_p, /**< context */
scanner_raise_error (context_p);
}
lexer_lit_location_t *location_p = scanner_add_literal (context_p, scanner_context_p);
location_p->type |= SCANNER_LITERAL_IS_VAR | SCANNER_LITERAL_IS_FUNC;
scanner_push_literal_pool (context_p, scanner_context_p, SCANNER_LITERAL_POOL_FUNCTION);
scanner_context_p->mode = SCAN_MODE_FUNCTION_ARGUMENTS;
parser_stack_push_uint8 (context_p, SCAN_STACK_FUNCTION_STATEMENT);
return SCAN_NEXT_TOKEN;
@@ -1072,6 +1197,16 @@ scanner_scan_statement (parser_context_t *context_p, /**< context */
#if ENABLED (JERRY_ES2015_CLASS)
case LEXER_KEYW_CLASS:
{
lexer_next_token (context_p);
if (context_p->token.type != LEXER_LITERAL || context_p->token.lit_location.type != LEXER_IDENT_LITERAL)
{
scanner_raise_error (context_p);
}
lexer_lit_location_t *location_p = scanner_add_literal (context_p, scanner_context_p);
location_p->type |= SCANNER_LITERAL_IS_VAR;
scanner_context_p->mode = SCAN_MODE_CLASS_DECLARATION;
parser_stack_push_uint8 (context_p, SCAN_STACK_CLASS_STATEMENT);
return SCAN_NEXT_TOKEN;
@@ -1099,6 +1234,9 @@ scanner_scan_statement (parser_context_t *context_p, /**< context */
if (context_p->token.type == LEXER_LITERAL
&& context_p->token.lit_location.type == LEXER_IDENT_LITERAL)
{
lexer_lit_location_t *location_p = scanner_add_literal (context_p, scanner_context_p);
location_p->type |= SCANNER_LITERAL_IS_VAR;
lexer_next_token (context_p);
if (context_p->token.type == LEXER_COMMA)
@@ -1129,6 +1267,9 @@ scanner_scan_statement (parser_context_t *context_p, /**< context */
scanner_raise_error (context_p);
}
lexer_lit_location_t *location_p = scanner_add_literal (context_p, scanner_context_p);
location_p->type |= SCANNER_LITERAL_IS_VAR;
lexer_next_token (context_p);
}
else if (context_p->token.type == LEXER_LEFT_BRACE)
@@ -1143,21 +1284,29 @@ scanner_scan_statement (parser_context_t *context_p, /**< context */
scanner_raise_error (context_p);
}
lexer_next_token (context_p);
if (lexer_compare_literal_to_identifier (context_p, "as", 2))
if (lexer_check_next_character (context_p, LIT_CHAR_LOWERCASE_A))
{
lexer_next_token (context_p);
if (!lexer_compare_literal_to_identifier (context_p, "as", 2))
{
scanner_raise_error (context_p);
}
lexer_next_token (context_p);
if (context_p->token.type != LEXER_LITERAL
&& context_p->token.lit_location.type == LEXER_IDENT_LITERAL)
{
scanner_raise_error (context_p);
}
lexer_next_token (context_p);
}
lexer_lit_location_t *location_p = scanner_add_literal (context_p, scanner_context_p);
location_p->type |= SCANNER_LITERAL_IS_VAR;
lexer_next_token (context_p);
if (context_p->token.type != LEXER_RIGHT_BRACE)
{
if (context_p->token.type != LEXER_COMMA)
@@ -1211,8 +1360,21 @@ scanner_scan_statement (parser_context_t *context_p, /**< context */
if (context_p->token.type == LEXER_LITERAL
&& context_p->token.lit_location.type == LEXER_IDENT_LITERAL)
{
lexer_lit_location_t *location_p = scanner_add_literal (context_p, scanner_context_p);
location_p->type |= SCANNER_LITERAL_IS_VAR | SCANNER_LITERAL_IS_FUNC;
lexer_next_token (context_p);
}
else
{
lexer_lit_location_t *location_p;
location_p = scanner_add_custom_literal (context_p,
scanner_context_p->active_literal_pool_p,
&lexer_default_literal);
location_p->type |= SCANNER_LITERAL_IS_VAR | SCANNER_LITERAL_IS_FUNC;
}
scanner_push_literal_pool (context_p, scanner_context_p, SCANNER_LITERAL_POOL_FUNCTION);
parser_stack_push_uint8 (context_p, SCAN_STACK_FUNCTION_STATEMENT);
scanner_context_p->mode = SCAN_MODE_FUNCTION_ARGUMENTS;
@@ -1221,13 +1383,44 @@ scanner_scan_statement (parser_context_t *context_p, /**< context */
#if ENABLED (JERRY_ES2015_CLASS)
if (context_p->token.type == LEXER_KEYW_CLASS)
{
scanner_context_p->mode = SCAN_MODE_STATEMENT;
scanner_context_p->mode = SCAN_MODE_CLASS_DECLARATION;
parser_stack_push_uint8 (context_p, SCAN_STACK_CLASS_STATEMENT);
lexer_next_token (context_p);
if (context_p->token.type == LEXER_LITERAL && context_p->token.lit_location.type == LEXER_IDENT_LITERAL)
{
lexer_lit_location_t *location_p = scanner_add_literal (context_p, scanner_context_p);
location_p->type |= SCANNER_LITERAL_IS_VAR;
return SCAN_NEXT_TOKEN;
}
lexer_lit_location_t *location_p;
location_p = scanner_add_custom_literal (context_p,
scanner_context_p->active_literal_pool_p,
&lexer_default_literal);
location_p->type |= SCANNER_LITERAL_IS_VAR;
return SCAN_KEEP_TOKEN;
}
#endif /* ENABLED (JERRY_ES2015_CLASS) */
/* Assignment expression. */
lexer_lit_location_t *location_p;
location_p = scanner_add_custom_literal (context_p,
scanner_context_p->active_literal_pool_p,
&lexer_default_literal);
location_p->type |= SCANNER_LITERAL_IS_VAR;
scanner_context_p->mode = SCAN_MODE_PRIMARY_EXPRESSION;
return SCAN_KEEP_TOKEN;
if (context_p->token.type != LEXER_LITERAL || context_p->token.lit_location.type != LEXER_IDENT_LITERAL)
{
return SCAN_KEEP_TOKEN;
}
location_p = scanner_add_literal (context_p, scanner_context_p);
location_p->type |= SCANNER_LITERAL_IS_VAR;
scanner_context_p->mode = SCAN_MODE_POST_PRIMARY_EXPRESSION;
return SCAN_NEXT_TOKEN;
}
scanner_context_p->mode = SCAN_MODE_STATEMENT_END;
@@ -1342,6 +1535,8 @@ scanner_scan_statement (parser_context_t *context_p, /**< context */
}
#endif /* ENABLED (JERRY_ES2015_ARROW_FUNCTION) */
scanner_add_reference (context_p, scanner_context_p);
scanner_context_p->mode = SCAN_MODE_POST_PRIMARY_EXPRESSION;
return SCAN_NEXT_TOKEN;
}
@@ -1374,7 +1569,7 @@ scanner_scan_statement_end (parser_context_t *context_p, /**< context */
switch (context_p->stack_top_uint8)
{
case SCAN_STACK_SCRIPT:
case SCAN_STACK_EVAL_FUNCTION:
case SCAN_STACK_SCRIPT_FUNCTION:
{
if (type == LEXER_EOS)
{
@@ -1393,6 +1588,11 @@ scanner_scan_statement_end (parser_context_t *context_p, /**< context */
break;
}
if (context_p->stack_top_uint8 == SCAN_STACK_FUNCTION_STATEMENT)
{
scanner_pop_literal_pool (context_p, scanner_context_p);
}
terminator_found = true;
parser_stack_pop_uint8 (context_p);
lexer_next_token (context_p);
@@ -1405,6 +1605,8 @@ scanner_scan_statement_end (parser_context_t *context_p, /**< context */
break;
}
scanner_pop_literal_pool (context_p, scanner_context_p);
scanner_context_p->mode = SCAN_MODE_POST_PRIMARY_EXPRESSION;
parser_stack_pop_uint8 (context_p);
return SCAN_NEXT_TOKEN;
@@ -1416,6 +1618,7 @@ scanner_scan_statement_end (parser_context_t *context_p, /**< context */
break;
}
scanner_pop_literal_pool (context_p, scanner_context_p);
parser_stack_pop_uint8 (context_p);
#if ENABLED (JERRY_ES2015_CLASS)
@@ -1475,6 +1678,22 @@ scanner_scan_statement_end (parser_context_t *context_p, /**< context */
}
continue;
}
case SCAN_STACK_WITH_STATEMENT:
{
scanner_literal_pool_t *literal_pool_p = scanner_context_p->active_literal_pool_p;
JERRY_ASSERT (literal_pool_p->status_flags & SCANNER_LITERAL_POOL_IN_WITH);
parser_stack_pop_uint8 (context_p);
if (context_p->stack_top_uint8 == 0)
{
literal_pool_p->status_flags &= (uint16_t) ~SCANNER_LITERAL_POOL_IN_WITH;
}
parser_stack_pop_uint8 (context_p);
continue;
}
case SCAN_STACK_DO_STATEMENT:
{
parser_stack_pop_uint8 (context_p);
@@ -1515,6 +1734,11 @@ scanner_scan_statement_end (parser_context_t *context_p, /**< context */
parser_stack_pop_uint8 (context_p);
lexer_next_token (context_p);
if (stack_top == SCAN_STACK_CATCH_STATEMENT)
{
scanner_pop_literal_pool (context_p, scanner_context_p);
}
/* A finally statement is optional after a try or catch statement. */
if (context_p->token.type == LEXER_KEYW_FINALLY)
{
@@ -1549,6 +1773,8 @@ scanner_scan_statement_end (parser_context_t *context_p, /**< context */
scanner_raise_error (context_p);
}
const uint8_t *source_p = context_p->source_p;
lexer_next_token (context_p);
if (context_p->token.type != LEXER_LITERAL
@@ -1557,6 +1783,13 @@ scanner_scan_statement_end (parser_context_t *context_p, /**< context */
scanner_raise_error (context_p);
}
scanner_literal_pool_t *literal_pool_p;
literal_pool_p = scanner_push_literal_pool (context_p, scanner_context_p, SCANNER_LITERAL_POOL_BLOCK);
literal_pool_p->source_p = source_p;
lexer_lit_location_t *lit_location_p = scanner_add_literal (context_p, scanner_context_p);
lit_location_p->type |= SCANNER_LITERAL_IS_LOCAL;
lexer_next_token (context_p);
if (context_p->token.type != LEXER_RIGHT_PAREN)
@@ -1606,7 +1839,15 @@ scanner_scan_all (parser_context_t *context_p, /**< context */
}
#endif /* ENABLED (JERRY_PARSER_DUMP_BYTE_CODE) */
#if ENABLED (JERRY_DEBUGGER)
scanner_context.debugger_enabled = (JERRY_CONTEXT (debugger_flags) & JERRY_DEBUGGER_CONNECTED) ? 1 : 0;
#endif /* ENABLED (JERRY_DEBUGGER) */
scanner_context.active_literal_pool_p = NULL;
scanner_context.active_switch_statement.last_case_p = NULL;
scanner_context.end_arguments_p = NULL;
/* This assignment must be here because of Apple compilers. */
context_p->u.scanner_context_p = &scanner_context;
parser_stack_init (context_p);
@@ -1620,6 +1861,10 @@ scanner_scan_all (parser_context_t *context_p, /**< context */
context_p->source_p = source_p;
context_p->source_end_p = source_end_p;
uint16_t status_flags = SCANNER_LITERAL_POOL_FUNCTION_WITHOUT_ARGUMENTS | SCANNER_LITERAL_POOL_NO_REG;
scanner_literal_pool_t *literal_pool_p = scanner_push_literal_pool (context_p, &scanner_context, status_flags);
literal_pool_p->source_p = source_p;
scanner_context.mode = SCAN_MODE_STATEMENT_OR_TERMINATOR;
parser_stack_push_uint8 (context_p, SCAN_STACK_SCRIPT);
@@ -1629,8 +1874,10 @@ scanner_scan_all (parser_context_t *context_p, /**< context */
{
context_p->source_p = arg_list_p;
context_p->source_end_p = arg_list_end_p;
scanner_push_literal_pool (context_p, &scanner_context, SCANNER_LITERAL_POOL_FUNCTION);
scanner_context.mode = SCAN_MODE_FUNCTION_ARGUMENTS;
parser_stack_push_uint8 (context_p, SCAN_STACK_EVAL_FUNCTION);
parser_stack_push_uint8 (context_p, SCAN_STACK_SCRIPT_FUNCTION);
/* Faking the first token. */
context_p->token.type = LEXER_LEFT_PAREN;
@@ -1664,11 +1911,6 @@ scanner_scan_all (parser_context_t *context_p, /**< context */
#if ENABLED (JERRY_ES2015_CLASS)
case SCAN_MODE_CLASS_DECLARATION:
{
if (context_p->token.type == LEXER_LITERAL && context_p->token.lit_location.type == LEXER_IDENT_LITERAL)
{
lexer_next_token (context_p);
}
if (context_p->token.type == LEXER_KEYW_EXTENDS)
{
parser_stack_push_uint8 (context_p, SCAN_STACK_CLASS_EXTENDS);
@@ -1719,6 +1961,7 @@ scanner_scan_all (parser_context_t *context_p, /**< context */
if (context_p->token.type == LEXER_LEFT_PAREN)
{
scanner_push_literal_pool (context_p, &scanner_context, SCANNER_LITERAL_POOL_FUNCTION);
continue;
}
}
@@ -1732,6 +1975,7 @@ scanner_scan_all (parser_context_t *context_p, /**< context */
}
#endif /* ENABLED (JERRY_ES2015_OBJECT_INITIALIZER) */
scanner_push_literal_pool (context_p, &scanner_context, SCANNER_LITERAL_POOL_FUNCTION);
lexer_next_token (context_p);
continue;
}
@@ -1791,6 +2035,14 @@ scanner_scan_all (parser_context_t *context_p, /**< context */
scanner_raise_error (context_p);
}
lexer_lit_location_t *location_p = scanner_add_literal (context_p, &scanner_context);
location_p->type |= SCANNER_LITERAL_IS_VAR;
if (scanner_context.active_literal_pool_p->status_flags & SCANNER_LITERAL_POOL_IN_WITH)
{
location_p->type |= SCANNER_LITERAL_NO_REG;
}
lexer_next_token (context_p);
switch (context_p->token.type)
@@ -1828,11 +2080,16 @@ scanner_scan_all (parser_context_t *context_p, /**< context */
}
case SCAN_MODE_FUNCTION_ARGUMENTS:
{
JERRY_ASSERT (stack_top == SCAN_STACK_EVAL_FUNCTION
JERRY_ASSERT (stack_top == SCAN_STACK_SCRIPT_FUNCTION
|| stack_top == SCAN_STACK_FUNCTION_STATEMENT
|| stack_top == SCAN_STACK_FUNCTION_EXPRESSION
|| stack_top == SCAN_STACK_FUNCTION_PROPERTY);
JERRY_ASSERT (scanner_context.active_literal_pool_p != NULL
&& (scanner_context.active_literal_pool_p->status_flags & SCANNER_LITERAL_POOL_FUNCTION));
scanner_context.active_literal_pool_p->source_p = context_p->source_p;
if (type != LEXER_LEFT_PAREN)
{
scanner_raise_error (context_p);
@@ -1862,6 +2119,9 @@ scanner_scan_all (parser_context_t *context_p, /**< context */
{
scanner_raise_error (context_p);
}
scanner_append_argument (context_p, &scanner_context);
lexer_next_token (context_p);
if (context_p->token.type != LEXER_COMMA)
@@ -1881,13 +2141,14 @@ scanner_scan_all (parser_context_t *context_p, /**< context */
}
#endif /* ENABLED (JERRY_ES2015_FUNCTION_PARAMETER_INITIALIZER) */
if (context_p->token.type == LEXER_EOS && stack_top == SCAN_STACK_EVAL_FUNCTION)
if (context_p->token.type == LEXER_EOS && stack_top == SCAN_STACK_SCRIPT_FUNCTION)
{
/* End of argument parsing. */
scanner_info_t *scanner_info_p = (scanner_info_t *) scanner_malloc (context_p, sizeof (scanner_info_t));
scanner_info_p->next_p = context_p->next_scanner_info_p;
scanner_info_p->source_p = NULL;
scanner_info_p->type = SCANNER_TYPE_END_ARGUMENTS;
scanner_context.end_arguments_p = scanner_info_p;
context_p->next_scanner_info_p = scanner_info_p;
context_p->source_p = source_p;
@@ -1911,6 +2172,8 @@ scanner_scan_all (parser_context_t *context_p, /**< context */
{
scanner_raise_error (context_p);
}
scanner_filter_arguments (context_p, &scanner_context);
scanner_context.mode = SCAN_MODE_STATEMENT_OR_TERMINATOR;
break;
}
@@ -1957,6 +2220,7 @@ scanner_scan_all (parser_context_t *context_p, /**< context */
scanner_raise_error (context_p);
}
scanner_push_literal_pool (context_p, &scanner_context, SCANNER_LITERAL_POOL_FUNCTION);
scanner_context.mode = SCAN_MODE_FUNCTION_ARGUMENTS;
break;
}
@@ -1974,6 +2238,8 @@ scanner_scan_all (parser_context_t *context_p, /**< context */
#if ENABLED (JERRY_ES2015_OBJECT_INITIALIZER)
if (context_p->token.type == LEXER_LEFT_PAREN)
{
scanner_push_literal_pool (context_p, &scanner_context, SCANNER_LITERAL_POOL_FUNCTION);
parser_stack_push_uint8 (context_p, SCAN_STACK_FUNCTION_PROPERTY);
scanner_context.mode = SCAN_MODE_FUNCTION_ARGUMENTS;
continue;
@@ -1996,6 +2262,8 @@ scanner_scan_all (parser_context_t *context_p, /**< context */
scanner_raise_error (context_p);
}
scanner_add_literal (context_p, &scanner_context);
lexer_next_token (context_p);
if (context_p->token.type == LEXER_COMMA)
@@ -2026,11 +2294,13 @@ scanner_scan_all (parser_context_t *context_p, /**< context */
scan_completed:
if (context_p->stack_top_uint8 != SCAN_STACK_SCRIPT
&& context_p->stack_top_uint8 != SCAN_STACK_EVAL_FUNCTION)
&& context_p->stack_top_uint8 != SCAN_STACK_SCRIPT_FUNCTION)
{
scanner_raise_error (context_p);
}
scanner_pop_literal_pool (context_p, &scanner_context);
#ifndef JERRY_NDEBUG
context_p->status_flags |= PARSER_SCANNING_SUCCESSFUL;
#endif /* !JERRY_NDEBUG */
@@ -2042,6 +2312,30 @@ scan_completed:
{
context_p->error = PARSER_ERR_NO_ERROR;
}
/* The following loop may allocate memory, so it is enclosed in a try/catch. */
PARSER_TRY (context_p->try_buffer)
{
while (scanner_context.active_literal_pool_p != NULL)
{
scanner_pop_literal_pool (context_p, &scanner_context);
}
}
PARSER_CATCH
{
JERRY_ASSERT (context_p->error == PARSER_ERR_NO_ERROR);
while (scanner_context.active_literal_pool_p != NULL)
{
scanner_literal_pool_t *literal_pool_p = scanner_context.active_literal_pool_p;
scanner_context.active_literal_pool_p = literal_pool_p->prev_p;
parser_list_free (&literal_pool_p->literal_pool);
scanner_free (literal_pool_p, sizeof (scanner_literal_pool_t));
}
}
PARSER_TRY_END
}
PARSER_TRY_END
@@ -2066,6 +2360,102 @@ scan_completed:
source_start_p = source_p;
break;
}
case SCANNER_TYPE_FUNCTION:
case SCANNER_TYPE_BLOCK:
{
const uint8_t *prev_source_p = info_p->source_p - 1;
const uint8_t *data_p;
if (info_p->type == SCANNER_TYPE_FUNCTION)
{
scanner_function_info_t *function_info_p = (scanner_function_info_t *) info_p;
data_p = (const uint8_t *) (function_info_p + 1);
JERRY_DEBUG_MSG (" FUNCTION: flags: 0x%x declarations: %d",
(int) function_info_p->info.u8_arg,
(int) function_info_p->info.u16_arg);
}
else
{
data_p = (const uint8_t *) (info_p + 1);
JERRY_DEBUG_MSG (" BLOCK:");
}
JERRY_DEBUG_MSG (" source:%d\n", (int) (info_p->source_p - source_start_p));
while (data_p[0] != SCANNER_STREAM_TYPE_END)
{
switch (data_p[0] & SCANNER_STREAM_TYPE_MASK)
{
case SCANNER_STREAM_TYPE_ARG:
{
JERRY_DEBUG_MSG (" ARG ");
break;
}
case SCANNER_STREAM_TYPE_ARG_FUNC:
{
JERRY_DEBUG_MSG (" ARG_FUNC ");
break;
}
case SCANNER_STREAM_TYPE_VAR:
{
JERRY_DEBUG_MSG (" VAR ");
break;
}
case SCANNER_STREAM_TYPE_FUNC:
{
JERRY_DEBUG_MSG (" FUNC ");
break;
}
default:
{
JERRY_ASSERT ((data_p[0] & SCANNER_STREAM_TYPE_MASK) == SCANNER_STREAM_TYPE_HOLE);
JERRY_DEBUG_MSG (" HOLE\n");
data_p++;
continue;
}
}
size_t length;
if (!(data_p[0] & SCANNER_STREAM_UINT16_DIFF))
{
if (data_p[2] != 0)
{
prev_source_p += data_p[2];
length = 2 + 1;
}
else
{
memcpy (&prev_source_p, data_p + 2 + 1, sizeof (const uint8_t *));
length = 2 + 1 + sizeof (const uint8_t *);
}
}
else
{
int32_t diff = ((int32_t) data_p[2]) | ((int32_t) data_p[3]) << 8;
if (diff <= UINT8_MAX)
{
diff = -diff;
}
prev_source_p += diff;
length = 2 + 2;
}
if (data_p[0] & SCANNER_STREAM_NO_REG)
{
JERRY_DEBUG_MSG ("* ");
}
JERRY_DEBUG_MSG ("'%.*s'\n", data_p[1], (char *) prev_source_p);
prev_source_p += data_p[1];
data_p += length;
}
break;
}
case SCANNER_TYPE_WHILE:
{
name_p = "WHILE";
@@ -2123,13 +2513,6 @@ scan_completed:
print_location = true;
break;
}
#if ENABLED (JERRY_ES2015_ARROW_FUNCTION)
case SCANNER_TYPE_ARROW:
{
JERRY_DEBUG_MSG (" ARROW: source:%d\n", (int) (info_p->source_p - source_start_p));
break;
}
#endif /* ENABLED (JERRY_ES2015_ARROW_FUNCTION) */
}
if (print_location)
+62 -3
View File
@@ -34,6 +34,8 @@ typedef enum
SCANNER_TYPE_END, /**< mark the last info block */
SCANNER_TYPE_END_ARGUMENTS, /**< mark the end of function arguments
* (only present if a function script is parsed) */
SCANNER_TYPE_FUNCTION, /**< declarations in a function */
SCANNER_TYPE_BLOCK, /**< declarations in a code block (usually enclosed in {}) */
SCANNER_TYPE_WHILE, /**< while statement */
SCANNER_TYPE_FOR, /**< for statement */
SCANNER_TYPE_FOR_IN, /**< for-in statement */
@@ -42,9 +44,6 @@ typedef enum
#endif /* ENABLED (JERRY_ES2015_FOR_OF) */
SCANNER_TYPE_SWITCH, /**< switch statement */
SCANNER_TYPE_CASE, /**< case statement */
#if ENABLED (JERRY_ES2015_ARROW_FUNCTION)
SCANNER_TYPE_ARROW, /**< arrow function */
#endif /* ENABLED (JERRY_ES2015_ARROW_FUNCTION) */
} scanner_info_type_t;
/**
@@ -65,6 +64,8 @@ typedef struct scanner_info_t
struct scanner_info_t *next_p; /**< next info structure */
const uint8_t *source_p; /**< triggering position of this scanner info */
uint8_t type; /**< type of the scanner info */
uint8_t u8_arg; /**< custom 8-bit value */
uint16_t u16_arg; /**< custom 16-bit value */
} scanner_info_t;
/**
@@ -104,6 +105,64 @@ typedef struct
scanner_case_info_t *case_p; /**< list of switch cases */
} scanner_switch_info_t;
/*
* Description of compressed streams.
*
* The stream is a sequence of commands which encoded as bytes. The first byte
* contains the type of the command (see scanner_function_compressed_stream_types_t).
*
* The variable declaration commands has two arguments:
* - The first represents the length of the declared identifier
* - The second contains the relative distance from the end of the previous declaration
* Usually the distance is between 1 and 255, and represented as a single byte
* Distances between -256 and 65535 are encoded as two bytes
* Larger distances are encoded as pointers
*/
/**
* Constants for compressed streams.
*/
typedef enum
{
SCANNER_STREAM_UINT16_DIFF = (1 << 7), /**< relative distance is between -256 and 65535 */
SCANNER_STREAM_HAS_ESCAPE = (1 << 6), /**< literal has escape */
SCANNER_STREAM_NO_REG = (1 << 5), /**< identifier cannot be stored in register */
} scanner_compressed_stream_flags_t;
/**
* Types for compressed streams.
*/
typedef enum
{
SCANNER_STREAM_TYPE_END, /**< end of scanner data */
SCANNER_STREAM_TYPE_HOLE, /**< no name is assigned to this argument */
SCANNER_STREAM_TYPE_ARG, /**< argument declaration */
SCANNER_STREAM_TYPE_ARG_FUNC, /**< argument declaration which is later initialized with a function */
SCANNER_STREAM_TYPE_VAR, /**< var declaration */
SCANNER_STREAM_TYPE_FUNC, /**< function declaration */
} scanner_compressed_stream_types_t;
/**
* Mask for decoding the type from the compressed stream.
*/
#define SCANNER_STREAM_TYPE_MASK 0xf
/**
* Constants for u8_arg flags in scanner_function_info_t.
*/
typedef enum
{
SCANNER_FUNCTION_ARGUMENTS_NEEDED = (1 << 0), /**< arguments object needs to be created */
} scanner_function_flags_t;
/**
* Scanner info for function statements.
*/
typedef struct
{
scanner_info_t info; /**< header */
} scanner_function_info_t;
/**
* @}
* @}
+46 -78
View File
@@ -797,90 +797,69 @@ vm_init_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */
{
switch (*byte_code_p)
{
case CBC_DEFINE_VARS:
case CBC_CREATE_VAR:
{
uint32_t literal_index_end;
uint32_t literal_index = register_end;
byte_code_p++;
READ_LITERAL_INDEX (literal_index_end);
while (literal_index <= literal_index_end)
{
ecma_string_t *name_p = ecma_get_string_from_value (literal_start_p[literal_index]);
vm_var_decl (frame_ctx_p, name_p);
literal_index++;
}
break;
}
case CBC_INITIALIZE_VAR:
case CBC_INITIALIZE_VARS:
{
uint8_t type = *byte_code_p;
uint32_t literal_index;
uint32_t literal_index_end;
byte_code_p++;
READ_LITERAL_INDEX (literal_index);
if (type == CBC_INITIALIZE_VAR)
ecma_string_t *name_p = ecma_get_string_from_value (literal_start_p[literal_index]);
vm_var_decl (frame_ctx_p, name_p);
break;
}
case CBC_INIT_LOCAL:
{
uint32_t literal_index, value_index;
ecma_value_t lit_value;
byte_code_p++;
READ_LITERAL_INDEX (value_index);
READ_LITERAL_INDEX (literal_index);
JERRY_ASSERT (value_index != literal_index);
JERRY_ASSERT (value_index >= register_end || literal_index >= register_end);
if (value_index < register_end)
{
literal_index_end = literal_index;
lit_value = frame_ctx_p->registers_p[value_index];
}
else
{
READ_LITERAL_INDEX (literal_index_end);
lit_value = vm_construct_literal_object (frame_ctx_p,
literal_start_p[value_index]);
}
while (literal_index <= literal_index_end)
if (literal_index < register_end)
{
uint32_t value_index;
ecma_value_t lit_value;
ecma_fast_free_value (frame_ctx_p->registers_p[literal_index]);
frame_ctx_p->registers_p[literal_index] = lit_value;
}
else
{
ecma_string_t *name_p = ecma_get_string_from_value (literal_start_p[literal_index]);
READ_LITERAL_INDEX (value_index);
vm_var_decl (frame_ctx_p, name_p);
if (value_index < register_end)
ecma_value_t put_value_result = ecma_op_put_value_lex_env_base (frame_ctx_p->lex_env_p,
name_p,
is_strict,
lit_value);
JERRY_ASSERT (ecma_is_value_boolean (put_value_result)
|| ecma_is_value_empty (put_value_result)
|| ECMA_IS_VALUE_ERROR (put_value_result));
if (ECMA_IS_VALUE_ERROR (put_value_result))
{
lit_value = frame_ctx_p->registers_p[value_index];
}
else
{
lit_value = vm_construct_literal_object (frame_ctx_p,
literal_start_p[value_index]);
ecma_free_value (JERRY_CONTEXT (error_value));
}
if (literal_index < register_end)
if (value_index >= register_end)
{
frame_ctx_p->registers_p[literal_index] = lit_value;
ecma_free_value (lit_value);
}
else
{
ecma_string_t *name_p = ecma_get_string_from_value (literal_start_p[literal_index]);
vm_var_decl (frame_ctx_p, name_p);
ecma_value_t put_value_result = ecma_op_put_value_lex_env_base (frame_ctx_p->lex_env_p,
name_p,
is_strict,
lit_value);
JERRY_ASSERT (ecma_is_value_boolean (put_value_result)
|| ecma_is_value_empty (put_value_result)
|| ECMA_IS_VALUE_ERROR (put_value_result));
if (ECMA_IS_VALUE_ERROR (put_value_result))
{
ecma_free_value (JERRY_CONTEXT (error_value));
}
if (value_index >= register_end)
{
ecma_free_value (lit_value);
}
}
literal_index++;
}
break;
}
@@ -3492,30 +3471,18 @@ error:
JERRY_DEBUGGER_CLEAR_FLAGS (JERRY_DEBUGGER_VM_EXCEPTION_THROWN);
#endif /* ENABLED (JERRY_DEBUGGER) */
byte_code_p = frame_ctx_p->byte_code_p;
if (VM_GET_CONTEXT_TYPE (stack_top_p[-1]) == VM_CONTEXT_CATCH)
{
*stack_top_p++ = JERRY_CONTEXT (error_value);
JERRY_ASSERT (byte_code_p[0] == CBC_ASSIGN_SET_IDENT);
uint32_t literal_index = byte_code_p[1];
if (literal_index >= encoding_limit)
{
literal_index = ((literal_index << 8) | byte_code_p[2]) - encoding_delta;
}
ecma_object_t *catch_env_p = ecma_create_decl_lex_env (frame_ctx_p->lex_env_p);
#if ENABLED (JERRY_DEBUGGER)
catch_env_p->type_flags_refs |= (uint16_t) ECMA_OBJECT_FLAG_NON_CLOSURE;
#endif /* ENABLED (JERRY_DEBUGGER) */
ecma_string_t *catch_name_p = ecma_get_string_from_value (literal_start_p[literal_index]);
ecma_op_create_mutable_binding (catch_env_p, catch_name_p, false);
frame_ctx_p->lex_env_p = catch_env_p;
vm_init_loop (frame_ctx_p);
}
else
{
@@ -3523,6 +3490,7 @@ error:
stack_top_p[-2] = JERRY_CONTEXT (error_value);
}
byte_code_p = frame_ctx_p->byte_code_p;
continue;
}
}
+1 -1
View File
@@ -34,8 +34,8 @@ level | type
2 | global
(jerry-debugger) variables 0
name | type | value
n | Number | 9
b | undefined | undefined
n | Number | 9
(jerry-debugger) variables 1
name | type | value
x | Number | 3
+1 -1
View File
@@ -14,7 +14,7 @@
var src = "var a = 0; while(a) { switch(a) {";
/* The += operation has a longer opcode. */
for (var i = 0; i < 3500; i++)
for (var i = 0; i < 3300; i++)
src += "case " + i + ": a += a += a; break; ";
src += "} }";
+4 -4
View File
@@ -223,15 +223,15 @@ main (void)
/* Check the snapshot data. Unused bytes should be filled with zeroes */
const uint8_t expected_data[] =
{
0x4A, 0x52, 0x52, 0x59, 0x18, 0x00, 0x00, 0x00,
0x4A, 0x52, 0x52, 0x59, 0x19, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00,
0x01, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00,
0x03, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00,
0x03, 0x00, 0x01, 0x00, 0x21, 0x00, 0x01, 0x00,
0x00, 0x00, 0x00, 0x01, 0x18, 0x00, 0x00, 0x00,
0x28, 0x00, 0xB8, 0x46, 0x00, 0x00, 0x00, 0x00,
0x28, 0x00, 0xB7, 0x45, 0x00, 0x00, 0x00, 0x00,
0x03, 0x00, 0x01, 0x00, 0x21, 0x00, 0x00, 0x00,
0x00, 0x00, 0x01, 0x01, 0x07, 0x00, 0x00, 0x00,
0x47, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x46, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x14, 0x00, 0x73, 0x74, 0x72, 0x69, 0x6E, 0x67,
0x20, 0x66, 0x72, 0x6F, 0x6D, 0x20, 0x73, 0x6E,
0x61, 0x70, 0x73, 0x68, 0x6F, 0x74