Rework storing the line/column/bytecode info (#4707)
This information is stored in a separate memory block instead of being part of the byte code. Snapshot does not supported. JerryScript-DCO-1.0-Signed-off-by: Zoltan Herczeg zherczeg.u-szeged@partner.samsung.com
This commit is contained in:
@@ -27,7 +27,7 @@ JERRY_STATIC_ASSERT ((sizeof (cbc_uint16_arguments_t) % sizeof (jmem_cpointer_t)
|
||||
*/
|
||||
JERRY_STATIC_ASSERT (CBC_END == 238,
|
||||
number_of_cbc_opcodes_changed);
|
||||
JERRY_STATIC_ASSERT (CBC_EXT_END == 147,
|
||||
JERRY_STATIC_ASSERT (CBC_EXT_END == 146,
|
||||
number_of_cbc_ext_opcodes_changed);
|
||||
|
||||
#if JERRY_PARSER || JERRY_PARSER_DUMP_BYTE_CODE
|
||||
|
||||
@@ -606,8 +606,6 @@
|
||||
VM_OC_STRING_CONCAT | VM_OC_GET_LITERAL_LITERAL | VM_OC_PUT_STACK) \
|
||||
CBC_OPCODE (CBC_EXT_GET_TAGGED_TEMPLATE_LITERAL, CBC_HAS_BYTE_ARG, 1, \
|
||||
VM_OC_GET_TEMPLATE_OBJECT | VM_OC_PUT_STACK) \
|
||||
CBC_OPCODE (CBC_EXT_LINE, CBC_NO_FLAG, 0, \
|
||||
VM_OC_LINE) \
|
||||
CBC_OPCODE (CBC_EXT_THROW_REFERENCE_ERROR, CBC_NO_FLAG, 1, \
|
||||
VM_OC_THROW_REFERENCE_ERROR) \
|
||||
CBC_OPCODE (CBC_EXT_THROW_ASSIGN_CONST_ERROR, CBC_NO_FLAG, 0, \
|
||||
@@ -889,9 +887,10 @@ typedef enum
|
||||
CBC_CODE_FLAGS_LEXICAL_ENV_NOT_NEEDED = (1u << 4), /**< no need to create a lexical environment */
|
||||
CBC_CODE_FLAGS_HAS_EXTENDED_INFO = (1u << 5), /**< this function has extended info block */
|
||||
CBC_CODE_FLAGS_HAS_TAGGED_LITERALS = (1u << 6), /**< this function has tagged template literal list */
|
||||
CBC_CODE_FLAGS_STATIC_FUNCTION = (1u << 7), /**< this function is a static snapshot function */
|
||||
CBC_CODE_FLAGS_DEBUGGER_IGNORE = (1u << 8), /**< this function should be ignored by debugger */
|
||||
CBC_CODE_FLAGS_LEXICAL_BLOCK_NEEDED = (1u << 9), /**< compiled code needs a lexical block */
|
||||
CBC_CODE_FLAGS_HAS_LINE_INFO = (1u << 7), /**< this function has line info block */
|
||||
CBC_CODE_FLAGS_STATIC_FUNCTION = (1u << 8), /**< this function is a static snapshot function */
|
||||
CBC_CODE_FLAGS_DEBUGGER_IGNORE = (1u << 9), /**< this function should be ignored by debugger */
|
||||
CBC_CODE_FLAGS_LEXICAL_BLOCK_NEEDED = (1u << 10), /**< compiled code needs a lexical block */
|
||||
|
||||
/* Bits from bit 12 is reserved for function types (see CBC_FUNCTION_TYPE_SHIFT).
|
||||
* Note: the last bits are used for type flags because < and >= operators can be used to
|
||||
|
||||
@@ -430,6 +430,11 @@ util_print_cbc (ecma_compiled_code_t *compiled_code_p) /**< compiled code */
|
||||
size -= sizeof (ecma_value_t);
|
||||
}
|
||||
|
||||
if (compiled_code_p->status_flags & CBC_CODE_FLAGS_HAS_LINE_INFO)
|
||||
{
|
||||
size -= sizeof (ecma_value_t);
|
||||
}
|
||||
|
||||
byte_code_end_p = ((uint8_t *) compiled_code_p) + size;
|
||||
byte_code_p = byte_code_start_p;
|
||||
|
||||
@@ -462,24 +467,6 @@ util_print_cbc (ecma_compiled_code_t *compiled_code_p) /**< compiled code */
|
||||
flags = cbc_ext_flags[ext_opcode];
|
||||
JERRY_DEBUG_MSG (" %3d : %s", (int) cbc_offset, cbc_ext_names[ext_opcode]);
|
||||
byte_code_p += 2;
|
||||
|
||||
#if JERRY_LINE_INFO
|
||||
if (ext_opcode == CBC_EXT_LINE)
|
||||
{
|
||||
uint32_t value = 0;
|
||||
uint8_t byte;
|
||||
|
||||
do
|
||||
{
|
||||
byte = *byte_code_p++;
|
||||
value = (value << 7) | (byte & CBC_LOWER_SEVEN_BIT_MASK);
|
||||
}
|
||||
while (byte & CBC_HIGHEST_BIT_MASK);
|
||||
|
||||
JERRY_DEBUG_MSG (" %d\n", (int) value);
|
||||
continue;
|
||||
}
|
||||
#endif /* JERRY_LINE_INFO */
|
||||
}
|
||||
|
||||
if (flags & (CBC_HAS_LITERAL_ARG | CBC_HAS_LITERAL_ARG2))
|
||||
|
||||
@@ -3388,13 +3388,6 @@ parser_pattern_form_assignment (parser_context_t *context_p, /**< context */
|
||||
context_p->last_breakpoint_line = ident_line_counter;
|
||||
}
|
||||
#endif /* JERRY_DEBUGGER */
|
||||
|
||||
#if JERRY_LINE_INFO
|
||||
if (ident_line_counter != context_p->last_line_info_line)
|
||||
{
|
||||
parser_emit_line_info (context_p, ident_line_counter, false);
|
||||
}
|
||||
#endif /* JERRY_LINE_INFO */
|
||||
} /* parser_pattern_form_assignment */
|
||||
|
||||
/**
|
||||
@@ -3483,6 +3476,9 @@ parser_pattern_process_assignment (parser_context_t *context_p, /**< context */
|
||||
}
|
||||
|
||||
parser_line_counter_t ident_line_counter = context_p->token.line;
|
||||
#if JERRY_LINE_INFO
|
||||
parser_line_counter_t ident_column_counter = context_p->token.column;
|
||||
#endif /* JERRY_LINE_INFO */
|
||||
|
||||
if (flags & PARSER_PATTERN_BINDING)
|
||||
{
|
||||
@@ -3538,6 +3534,9 @@ parser_pattern_process_assignment (parser_context_t *context_p, /**< context */
|
||||
}
|
||||
|
||||
parser_pattern_form_assignment (context_p, flags, rhs_opcode, literal_index, ident_line_counter);
|
||||
#if JERRY_LINE_INFO
|
||||
parser_line_info_append (context_p, ident_line_counter, ident_column_counter);
|
||||
#endif /* JERRY_LINE_INFO */
|
||||
return false;
|
||||
} /* parser_pattern_process_assignment */
|
||||
|
||||
@@ -3720,6 +3719,9 @@ parser_parse_object_initializer (parser_context_t *context_p, /**< context */
|
||||
|| context_p->token.type == LEXER_COMMA);
|
||||
|
||||
parser_pattern_form_assignment (context_p, flags, push_prop_opcode, prop_index, start_line);
|
||||
#if JERRY_LINE_INFO
|
||||
parser_line_info_append (context_p, start_line, start_column);
|
||||
#endif /* JERRY_LINE_INFO */
|
||||
}
|
||||
|
||||
if (context_p->token.type == LEXER_RIGHT_BRACE)
|
||||
|
||||
@@ -486,6 +486,19 @@ typedef struct
|
||||
|
||||
#endif /* JERRY_DEBUGGER */
|
||||
|
||||
#if JERRY_LINE_INFO
|
||||
|
||||
typedef struct
|
||||
{
|
||||
parser_mem_page_t *first_page_p; /**< first page of line info data */
|
||||
parser_mem_page_t *last_page_p; /**< last page of line info data */
|
||||
uint32_t byte_code_position; /**< last byte code position */
|
||||
parser_line_counter_t line; /**< last line */
|
||||
parser_line_counter_t column; /**< last column */
|
||||
} parser_line_info_data_t;
|
||||
|
||||
#endif /* JERRY_LINE_INFO */
|
||||
|
||||
/**
|
||||
* Those members of a context which needs
|
||||
* to be saved when a sub-function is parsed.
|
||||
@@ -523,6 +536,10 @@ typedef struct parser_saved_context_t
|
||||
#ifndef JERRY_NDEBUG
|
||||
uint16_t context_stack_depth; /**< current context stack depth */
|
||||
#endif /* !JERRY_NDEBUG */
|
||||
|
||||
#if JERRY_LINE_INFO
|
||||
parser_line_info_data_t line_info; /**< line info data */
|
||||
#endif /* JERRY_LINE_INFO */
|
||||
} parser_saved_context_t;
|
||||
|
||||
/**
|
||||
@@ -618,6 +635,7 @@ typedef struct
|
||||
#endif /* JERRY_RESOURCE_NAME */
|
||||
|
||||
#if JERRY_LINE_INFO
|
||||
parser_line_info_data_t line_info; /**< line info data */
|
||||
parser_line_counter_t last_line_info_line; /**< last line where line info has been inserted */
|
||||
#endif /* JERRY_LINE_INFO */
|
||||
} parser_context_t;
|
||||
@@ -875,6 +893,20 @@ void parser_module_add_names_to_node (parser_context_t *context_p,
|
||||
|
||||
#endif /* JERRY_MODULE_SYSTEM */
|
||||
|
||||
/*
|
||||
* @}
|
||||
*
|
||||
* \addtogroup jsparser_line_info_create Create line info data
|
||||
* @{
|
||||
*/
|
||||
|
||||
#if JERRY_LINE_INFO
|
||||
void parser_line_info_free (parser_line_info_data_t *line_info_p);
|
||||
void parser_line_info_append (parser_context_t *context_p,
|
||||
parser_line_counter_t line, parser_line_counter_t column);
|
||||
uint8_t *parser_line_info_generate (parser_context_t *context_p);
|
||||
#endif /* JERRY_LINE_INFO */
|
||||
|
||||
/**
|
||||
* @}
|
||||
*
|
||||
@@ -905,12 +937,6 @@ void parser_append_breakpoint_info (parser_context_t *context_p, jerry_debugger_
|
||||
|
||||
#endif /* JERRY_DEBUGGER */
|
||||
|
||||
#if JERRY_LINE_INFO
|
||||
|
||||
void parser_emit_line_info (parser_context_t *context_p, uint32_t line, bool flush_cbc);
|
||||
|
||||
#endif /* JERRY_LINE_INFO */
|
||||
|
||||
#if JERRY_PARSER_DUMP_BYTE_CODE
|
||||
void util_print_cbc (ecma_compiled_code_t *compiled_code_p);
|
||||
#endif /* JERRY_PARSER_DUMP_BYTE_CODE */
|
||||
|
||||
@@ -0,0 +1,577 @@
|
||||
/* Copyright JS Foundation and other contributors, http://js.foundation
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "ecma-line-info.h"
|
||||
#include "js-parser-internal.h"
|
||||
|
||||
#if JERRY_PARSER
|
||||
|
||||
#if JERRY_LINE_INFO
|
||||
|
||||
/* \addtogroup parser Parser
|
||||
* @{
|
||||
*
|
||||
* \addtogroup jsparser JavaScript
|
||||
* @{
|
||||
*
|
||||
* \addtogroup jsparser_line_info_create Create line info data
|
||||
* @{
|
||||
*/
|
||||
|
||||
/*
|
||||
* The line-info data structure uses two number encodings:
|
||||
*
|
||||
* Vlq (variable length quantity):
|
||||
* Each byte has 7 bit data and the highest bit is set for continuation.
|
||||
* The format is big endian.
|
||||
*
|
||||
* Small:
|
||||
* First byte can encode signed values between 127 and -125 in 1 byte.
|
||||
* Large values requires more bytes than vlq.
|
||||
*
|
||||
* The line-info data structure is a sequence of chunks:
|
||||
*
|
||||
* +------+--------------+------------+----------------+
|
||||
* | Line | StreamLength | StreamData | [ByteCodeSize] |
|
||||
* +------+--------------+------------+----------------+
|
||||
*
|
||||
* Line [Vlq encoding]:
|
||||
* Specifies the start line of this chunk, relative to its previous value.
|
||||
* The starting column is always ECMA_LINE_INFO_COLUMN_DEFAULT
|
||||
*
|
||||
* StreamLength [uint8_t]:
|
||||
* Length of the StreamData in bytes minus ECMA_LINE_INFO_STREAM_SIZE_MIN.
|
||||
* The 0 value represents the last chunk, which size is not specified
|
||||
* (Can be less than ECMA_LINE_INFO_STREAM_SIZE_MIN).
|
||||
*
|
||||
* StreamData [sequence of bytes]:
|
||||
* Sequence of the following items:
|
||||
*
|
||||
* +-----------+--------+--------+
|
||||
* | EndOffset | [Line] | Column |
|
||||
* +-----------+--------+--------+
|
||||
*
|
||||
* EndOffset [Small encoding]:
|
||||
* Specifies the EndOffset in the byte code, relative to the previous EndOffset.
|
||||
* The range of byte codes corresponding to the line/column position of this item
|
||||
* is between the EndOffset of the previous item (inclusive) and the EndOffset
|
||||
* of this item (exclusive). The last end offset of a stream is always 0, which
|
||||
* represents an unterminated range.
|
||||
*
|
||||
* Line [Small encoding] [Optional]:
|
||||
* If bit 1 of end offset is set, this specifies the line position of this item,
|
||||
* relative to the previous line position, and the column position is set to
|
||||
* ECMA_LINE_INFO_COLUMN_DEFAULT.
|
||||
*
|
||||
* Column [Small encoding]:
|
||||
* Specifies the current column position relative to the previous column position.
|
||||
*
|
||||
* ByteCodeSize [Vlq encoding] [Optional]:
|
||||
* If StreamLength is not 0, this specifies the byte code size of the whole range.
|
||||
* This value can be used to skip the byte codes which line info is stored
|
||||
* in this chunk. This information is not available for the last chunk.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Maximum number of bytes requires to encode a number.
|
||||
*/
|
||||
#define PARSER_LINE_INFO_BUFFER_MAX_SIZE 5
|
||||
|
||||
/**
|
||||
* Stream generation ends after this size is reached,
|
||||
* since there might be not enough place for the next item.
|
||||
*/
|
||||
#define PARSER_LINE_INFO_STREAM_SIZE_LIMIT \
|
||||
(ECMA_LINE_INFO_STREAM_SIZE_MIN + UINT8_MAX - ((2 * PARSER_LINE_INFO_BUFFER_MAX_SIZE) + 1))
|
||||
|
||||
/**
|
||||
* Free line info temporary data collected during parsing.
|
||||
*/
|
||||
void
|
||||
parser_line_info_free (parser_line_info_data_t *line_info_p)
|
||||
{
|
||||
parser_mem_page_t *current_page_p = line_info_p->first_page_p;
|
||||
|
||||
while (current_page_p != NULL)
|
||||
{
|
||||
parser_mem_page_t *next_p = current_page_p->next_p;
|
||||
|
||||
parser_free (current_page_p, sizeof (parser_mem_page_t *) + PARSER_STACK_PAGE_SIZE);
|
||||
current_page_p = next_p;
|
||||
}
|
||||
} /* parser_line_info_free */
|
||||
|
||||
/**
|
||||
* Encodes an uint32_t number into a buffer. Numbers expected to be larger values.
|
||||
*
|
||||
* @return the number of bytes written to the buffer
|
||||
*/
|
||||
static uint32_t
|
||||
parser_line_info_encode_vlq (uint8_t *buffer_p, /**< target buffer */
|
||||
uint32_t value) /**< encoded value */
|
||||
{
|
||||
if (value <= ECMA_LINE_INFO_VLQ_MASK)
|
||||
{
|
||||
*buffer_p = (uint8_t) value;
|
||||
return 1;
|
||||
}
|
||||
|
||||
uint32_t length = 0;
|
||||
uint32_t current_value = value;
|
||||
|
||||
do
|
||||
{
|
||||
current_value >>= ECMA_LINE_INFO_VLQ_SHIFT;
|
||||
length++;
|
||||
}
|
||||
while (current_value > 0);
|
||||
|
||||
buffer_p += length;
|
||||
|
||||
do
|
||||
{
|
||||
*(--buffer_p) = (uint8_t) (value | ECMA_LINE_INFO_VLQ_CONTINUE);
|
||||
value >>= ECMA_LINE_INFO_VLQ_SHIFT;
|
||||
}
|
||||
while (value > 0);
|
||||
|
||||
buffer_p[length - 1] &= ECMA_LINE_INFO_VLQ_MASK;
|
||||
return length;
|
||||
} /* parser_line_info_encode_vlq */
|
||||
|
||||
/**
|
||||
* Encodes an uint32_t number into a buffer. Numbers expected to be smaller values.
|
||||
*
|
||||
* @return the number of bytes written to the buffer
|
||||
*/
|
||||
static uint32_t
|
||||
parser_line_info_encode_small (uint8_t *buffer_p, /**< target buffer */
|
||||
uint32_t value) /**< encoded value */
|
||||
{
|
||||
if (value < ECMA_LINE_INFO_ENCODE_TWO_BYTE_MIN)
|
||||
{
|
||||
buffer_p[0] = (uint8_t) value;
|
||||
return 1;
|
||||
}
|
||||
|
||||
uint32_t length;
|
||||
|
||||
if (JERRY_LIKELY (value < ECMA_LINE_INFO_ENCODE_THREE_BYTE_MIN))
|
||||
{
|
||||
value -= ECMA_LINE_INFO_ENCODE_TWO_BYTE_MIN;
|
||||
buffer_p[0] = ECMA_LINE_INFO_ENCODE_TWO_BYTE;
|
||||
length = 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (value <= (ECMA_LINE_INFO_ENCODE_THREE_BYTE_MIN + UINT16_MAX))
|
||||
{
|
||||
value -= ECMA_LINE_INFO_ENCODE_THREE_BYTE_MIN;
|
||||
buffer_p[0] = ECMA_LINE_INFO_ENCODE_THREE_BYTE;
|
||||
length = 3;
|
||||
}
|
||||
else
|
||||
{
|
||||
buffer_p[0] = ECMA_LINE_INFO_ENCODE_FIVE_BYTE;
|
||||
buffer_p[3] = (uint8_t) (value >> 16);
|
||||
buffer_p[4] = (uint8_t) (value >> 24);
|
||||
length = 5;
|
||||
}
|
||||
|
||||
buffer_p[2] = (uint8_t) (value >> 8);
|
||||
}
|
||||
|
||||
buffer_p[1] = (uint8_t) value;
|
||||
return length;
|
||||
} /* parser_line_info_encode_small */
|
||||
|
||||
/**
|
||||
* Encodes the difference between two values.
|
||||
*
|
||||
* @return encoded difference
|
||||
*/
|
||||
static inline uint32_t JERRY_ATTR_ALWAYS_INLINE
|
||||
parser_line_info_difference_get (uint32_t current_value, /**< current value */
|
||||
uint32_t prev_value) /**< previous value */
|
||||
{
|
||||
uint32_t result = current_value - prev_value - 1;
|
||||
|
||||
if (result <= (UINT32_MAX >> 1))
|
||||
{
|
||||
return (result << 1) | ECMA_LINE_INFO_INCREASE;
|
||||
}
|
||||
|
||||
return ((UINT32_MAX - result) << 1) | ECMA_LINE_INFO_DECREASE;
|
||||
} /* parser_line_info_difference_get */
|
||||
|
||||
/**
|
||||
* Appends a value at the end of the line info stream.
|
||||
*/
|
||||
static void
|
||||
parser_line_info_append_number (parser_context_t *context_p, /**< context */
|
||||
uint32_t value) /**< value to be encoded */
|
||||
{
|
||||
uint8_t buffer[PARSER_LINE_INFO_BUFFER_MAX_SIZE];
|
||||
|
||||
uint32_t length = parser_line_info_encode_vlq (buffer, value);
|
||||
|
||||
if (context_p->line_info.last_page_p != NULL
|
||||
&& context_p->line_info.last_page_p->bytes[0] + length <= PARSER_STACK_PAGE_SIZE)
|
||||
{
|
||||
memcpy (context_p->line_info.last_page_p->bytes + context_p->line_info.last_page_p->bytes[0],
|
||||
buffer,
|
||||
length);
|
||||
|
||||
length += context_p->line_info.last_page_p->bytes[0];
|
||||
context_p->line_info.last_page_p->bytes[0] = (uint8_t) length;
|
||||
return;
|
||||
}
|
||||
|
||||
size_t size = sizeof (parser_mem_page_t *) + PARSER_STACK_PAGE_SIZE;
|
||||
parser_mem_page_t *new_page_p = (parser_mem_page_t *) parser_malloc (context_p, size);
|
||||
|
||||
new_page_p->next_p = NULL;
|
||||
|
||||
if (context_p->line_info.first_page_p == NULL)
|
||||
{
|
||||
context_p->line_info.first_page_p = new_page_p;
|
||||
context_p->line_info.last_page_p = new_page_p;
|
||||
}
|
||||
else
|
||||
{
|
||||
context_p->line_info.last_page_p->next_p = new_page_p;
|
||||
context_p->line_info.last_page_p = new_page_p;
|
||||
}
|
||||
|
||||
context_p->line_info.last_page_p->bytes[0] = (uint8_t) (length + 1);
|
||||
memcpy (new_page_p->bytes + 1, buffer, length);
|
||||
} /* parser_line_info_append_number */
|
||||
|
||||
/**
|
||||
* Updates the current line information data.
|
||||
*/
|
||||
void
|
||||
parser_line_info_append (parser_context_t *context_p, /**< context */
|
||||
parser_line_counter_t line, /**< line */
|
||||
parser_line_counter_t column) /**< column */
|
||||
{
|
||||
if (context_p->line_info.first_page_p != NULL
|
||||
&& (context_p->byte_code_size == context_p->line_info.byte_code_position
|
||||
|| (context_p->line_info.line == line
|
||||
&& context_p->line_info.column == column)))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
/* Sets ECMA_LINE_INFO_HAS_LINE bit. */
|
||||
uint32_t value = (((context_p->byte_code_size - context_p->line_info.byte_code_position) << 1)
|
||||
| (uint32_t) (context_p->line_info.line != line));
|
||||
|
||||
parser_line_info_append_number (context_p, value);
|
||||
context_p->line_info.byte_code_position = context_p->byte_code_size;
|
||||
|
||||
if (value & ECMA_LINE_INFO_HAS_LINE)
|
||||
{
|
||||
value = parser_line_info_difference_get (line, context_p->line_info.line);
|
||||
parser_line_info_append_number (context_p, value);
|
||||
context_p->line_info.line = line;
|
||||
}
|
||||
|
||||
value = parser_line_info_difference_get (column, context_p->line_info.column);
|
||||
parser_line_info_append_number (context_p, value);
|
||||
context_p->line_info.column = column;
|
||||
} /* parser_line_info_append */
|
||||
|
||||
/**
|
||||
* Line info iterator structure
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
parser_mem_page_t *current_page_p; /**< current page */
|
||||
uint32_t offset; /**< current offset */
|
||||
} parser_line_info_iterator_t;
|
||||
|
||||
/**
|
||||
* Decodes the next value from the iterator stream
|
||||
*/
|
||||
static uint32_t
|
||||
parser_line_info_iterator_get (parser_line_info_iterator_t *iterator_p) /**< iterator */
|
||||
{
|
||||
uint8_t *source_p = iterator_p->current_page_p->bytes + iterator_p->offset;
|
||||
uint32_t result = ecma_line_info_decode_vlq (&source_p);
|
||||
|
||||
iterator_p->offset = (uint32_t) (source_p - iterator_p->current_page_p->bytes);
|
||||
|
||||
JERRY_ASSERT (iterator_p->offset <= iterator_p->current_page_p->bytes[0]);
|
||||
|
||||
if (iterator_p->offset < iterator_p->current_page_p->bytes[0])
|
||||
{
|
||||
return result;
|
||||
}
|
||||
|
||||
iterator_p->current_page_p = iterator_p->current_page_p->next_p;
|
||||
iterator_p->offset = 1;
|
||||
return result;
|
||||
} /* parser_line_info_iterator_get */
|
||||
|
||||
/**
|
||||
* Generate line info data
|
||||
*
|
||||
* @return generated line info data
|
||||
*/
|
||||
uint8_t *
|
||||
parser_line_info_generate (parser_context_t *context_p) /**< context */
|
||||
{
|
||||
parser_line_info_iterator_t iterator;
|
||||
uint8_t *line_info_p = NULL;
|
||||
uint8_t *dst_p = NULL;
|
||||
uint32_t total_length = 0;
|
||||
uint32_t total_length_size = 0;
|
||||
|
||||
while (true)
|
||||
{
|
||||
/* The following code runs twice: first the size of the data,
|
||||
* is computed and the data is generated during the second run.
|
||||
* Note: line_info_p is NULL during the first run. */
|
||||
parser_mem_page_t *iterator_byte_code_page_p = context_p->byte_code.first_p;
|
||||
uint32_t iterator_byte_code_page_offset = 0;
|
||||
uint32_t iterator_byte_code_base = 0;
|
||||
uint32_t iterator_last_byte_code_offset = UINT32_MAX;
|
||||
uint32_t iterator_prev_line = 0;
|
||||
uint32_t iterator_prev_column = 0;
|
||||
uint32_t iterator_line = 1;
|
||||
uint32_t iterator_column = 1;
|
||||
uint8_t block_buffer[PARSER_LINE_INFO_BUFFER_MAX_SIZE];
|
||||
uint8_t line_column_buffer[PARSER_LINE_INFO_BUFFER_MAX_SIZE * 2];
|
||||
uint8_t *block_size_p = NULL;
|
||||
uint32_t block_byte_code_offset = 0;
|
||||
uint32_t block_prev_line = 1;
|
||||
uint32_t stream_byte_code_offset = 0;
|
||||
uint32_t stream_current_line = 1;
|
||||
uint32_t stream_current_column = ECMA_LINE_INFO_COLUMN_DEFAULT;
|
||||
uint32_t stream_prev_line = 1;
|
||||
uint32_t stream_prev_column = ECMA_LINE_INFO_COLUMN_DEFAULT;
|
||||
uint32_t stream_size = 0;
|
||||
uint32_t stream_value_count = 0;
|
||||
uint32_t value;
|
||||
|
||||
iterator.current_page_p = context_p->line_info.first_page_p;
|
||||
iterator.offset = 1;
|
||||
|
||||
do
|
||||
{
|
||||
/* Decode line information generated during parsing. */
|
||||
value = parser_line_info_iterator_get (&iterator);
|
||||
iterator_byte_code_page_offset += (value >> 1);
|
||||
|
||||
if (value & 0x1)
|
||||
{
|
||||
value = parser_line_info_iterator_get (&iterator);
|
||||
JERRY_ASSERT (value != ((0 << 1) | ECMA_LINE_INFO_DECREASE));
|
||||
iterator_line = ecma_line_info_difference_update (iterator_line, value);
|
||||
}
|
||||
|
||||
value = parser_line_info_iterator_get (&iterator);
|
||||
iterator_column = ecma_line_info_difference_update (iterator_column, value);
|
||||
|
||||
while (iterator_byte_code_page_offset >= PARSER_CBC_STREAM_PAGE_SIZE)
|
||||
{
|
||||
iterator_byte_code_base += iterator_byte_code_page_p->bytes[PARSER_CBC_STREAM_PAGE_SIZE - 1];
|
||||
iterator_byte_code_page_offset -= PARSER_CBC_STREAM_PAGE_SIZE;
|
||||
iterator_byte_code_page_p = iterator_byte_code_page_p->next_p;
|
||||
}
|
||||
|
||||
uint32_t iterator_byte_code_offset = iterator_byte_code_base;
|
||||
|
||||
if (iterator_byte_code_page_offset > 0)
|
||||
{
|
||||
uint8_t relative_offset = iterator_byte_code_page_p->bytes[iterator_byte_code_page_offset - 1];
|
||||
iterator_byte_code_offset += relative_offset & CBC_LOWER_SEVEN_BIT_MASK;
|
||||
}
|
||||
|
||||
/* Skip those line/column pairs which byte code was discarded during post processing
|
||||
* or does not change line/column (this is possible when multiple skips occures). */
|
||||
if (iterator_byte_code_offset == iterator_last_byte_code_offset
|
||||
|| (iterator_line == iterator_prev_line && iterator_column == iterator_prev_column))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
iterator_prev_line = iterator_line;
|
||||
iterator_prev_column = iterator_column;
|
||||
iterator_last_byte_code_offset = iterator_byte_code_offset;
|
||||
|
||||
if (block_size_p != NULL)
|
||||
{
|
||||
/* Sets ECMA_LINE_INFO_HAS_LINE bit. */
|
||||
value = (((iterator_byte_code_offset - stream_byte_code_offset) << 1)
|
||||
| (uint32_t) (stream_prev_line != stream_current_line));
|
||||
|
||||
uint32_t line_column_size = 0;
|
||||
uint32_t offset_size = parser_line_info_encode_small (block_buffer, value);
|
||||
stream_byte_code_offset = iterator_byte_code_offset;
|
||||
|
||||
if (value & ECMA_LINE_INFO_HAS_LINE)
|
||||
{
|
||||
value = parser_line_info_difference_get (stream_current_line, stream_prev_line);
|
||||
line_column_size = parser_line_info_encode_small (line_column_buffer, value);
|
||||
stream_prev_line = stream_current_line;
|
||||
stream_prev_column = ECMA_LINE_INFO_COLUMN_DEFAULT;
|
||||
}
|
||||
|
||||
value = parser_line_info_difference_get (stream_current_column, stream_prev_column);
|
||||
line_column_size += parser_line_info_encode_small (line_column_buffer + line_column_size, value);
|
||||
|
||||
stream_prev_column = stream_current_column;
|
||||
stream_current_line = iterator_line;
|
||||
stream_current_column = iterator_column;
|
||||
|
||||
stream_value_count++;
|
||||
|
||||
if (stream_value_count < ECMA_LINE_INFO_STREAM_VALUE_COUNT_MAX
|
||||
&& (stream_size + offset_size + line_column_size <= PARSER_LINE_INFO_STREAM_SIZE_LIMIT))
|
||||
{
|
||||
stream_size += offset_size + line_column_size;
|
||||
|
||||
if (line_info_p != NULL)
|
||||
{
|
||||
memcpy (dst_p, block_buffer, offset_size);
|
||||
dst_p += offset_size;
|
||||
memcpy (dst_p, line_column_buffer, line_column_size);
|
||||
dst_p += line_column_size;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Finalize the current chunk. The size of EndOffset is always 1. */
|
||||
stream_size += 1 + line_column_size;
|
||||
|
||||
JERRY_ASSERT (stream_size > ECMA_LINE_INFO_STREAM_SIZE_MIN
|
||||
&& (stream_size - ECMA_LINE_INFO_STREAM_SIZE_MIN) <= UINT8_MAX);
|
||||
|
||||
if (line_info_p != NULL)
|
||||
{
|
||||
*block_size_p = (uint8_t) (stream_size - ECMA_LINE_INFO_STREAM_SIZE_MIN);
|
||||
/* Set EndOffset to 0 and copy the has_line bit. */
|
||||
*dst_p++ = (uint8_t) (block_buffer[0] & ECMA_LINE_INFO_HAS_LINE);
|
||||
memcpy (dst_p, line_column_buffer, line_column_size);
|
||||
dst_p += line_column_size;
|
||||
}
|
||||
else
|
||||
{
|
||||
total_length += stream_size;
|
||||
dst_p = block_buffer;
|
||||
}
|
||||
|
||||
uint32_t byte_code_diff = iterator_last_byte_code_offset - block_byte_code_offset;
|
||||
dst_p += parser_line_info_encode_vlq (dst_p, byte_code_diff);
|
||||
block_byte_code_offset = iterator_last_byte_code_offset;
|
||||
|
||||
if (line_info_p == NULL)
|
||||
{
|
||||
total_length += (uint32_t) (dst_p - block_buffer);
|
||||
}
|
||||
}
|
||||
|
||||
/* Start a new chunk. */
|
||||
if (line_info_p == NULL)
|
||||
{
|
||||
dst_p = block_buffer;
|
||||
}
|
||||
|
||||
value = parser_line_info_difference_get (iterator_line, block_prev_line);
|
||||
|
||||
dst_p += parser_line_info_encode_vlq (dst_p, value);
|
||||
block_size_p = dst_p;
|
||||
dst_p++;
|
||||
|
||||
if (line_info_p == NULL)
|
||||
{
|
||||
total_length += (uint32_t) (dst_p - block_buffer);
|
||||
}
|
||||
|
||||
block_prev_line = iterator_line;
|
||||
stream_current_line = iterator_line;
|
||||
stream_current_column = iterator_column;
|
||||
stream_prev_line = iterator_line;
|
||||
stream_prev_column = ECMA_LINE_INFO_COLUMN_DEFAULT;
|
||||
stream_size = 0;
|
||||
stream_value_count = 0;
|
||||
}
|
||||
while (iterator.current_page_p != NULL);
|
||||
|
||||
value = (stream_prev_line != stream_current_line);
|
||||
|
||||
/* Finalize the last stream */
|
||||
if (line_info_p == NULL)
|
||||
{
|
||||
dst_p = line_column_buffer;
|
||||
total_length += stream_size + 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
*block_size_p = 0;
|
||||
/* Small encoded value of has_line bit. */
|
||||
*dst_p++ = (uint8_t) value;
|
||||
}
|
||||
|
||||
if (value)
|
||||
{
|
||||
value = parser_line_info_difference_get (stream_current_line, stream_prev_line);
|
||||
dst_p += parser_line_info_encode_small (dst_p, value);
|
||||
stream_prev_column = ECMA_LINE_INFO_COLUMN_DEFAULT;
|
||||
}
|
||||
|
||||
value = parser_line_info_difference_get (stream_current_column, stream_prev_column);
|
||||
dst_p += parser_line_info_encode_small (dst_p, value);
|
||||
|
||||
if (line_info_p == NULL)
|
||||
{
|
||||
total_length += (uint32_t) (dst_p - line_column_buffer);
|
||||
}
|
||||
|
||||
if (line_info_p != NULL)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
total_length_size = parser_line_info_encode_vlq (block_buffer, total_length);
|
||||
|
||||
/* TODO: Support allocation fail. */
|
||||
line_info_p = (uint8_t *) jmem_heap_alloc_block (total_length + total_length_size);
|
||||
dst_p = line_info_p + parser_line_info_encode_vlq (line_info_p, total_length);
|
||||
}
|
||||
|
||||
JERRY_ASSERT (line_info_p + total_length_size + total_length == dst_p);
|
||||
|
||||
#if JERRY_PARSER_DUMP_BYTE_CODE
|
||||
if (context_p->is_show_opcodes)
|
||||
{
|
||||
ecma_line_info_dump (line_info_p);
|
||||
}
|
||||
#endif /* JERRY_PARSER_DUMP_BYTE_CODE */
|
||||
|
||||
return line_info_p;
|
||||
} /* parser_line_info_generate */
|
||||
|
||||
#endif /* JERRY_LINE_INFO */
|
||||
|
||||
#endif /* JERRY_PARSER */
|
||||
|
||||
/**
|
||||
* @}
|
||||
* @}
|
||||
* @}
|
||||
*/
|
||||
@@ -485,6 +485,9 @@ parser_parse_var_statement (parser_context_t *context_p) /**< context */
|
||||
#if JERRY_DEBUGGER || JERRY_LINE_INFO
|
||||
parser_line_counter_t ident_line_counter = context_p->token.line;
|
||||
#endif /* JERRY_DEBUGGER || JERRY_LINE_INFO */
|
||||
#if JERRY_LINE_INFO
|
||||
parser_line_counter_t ident_column_counter = context_p->token.column;
|
||||
#endif /* JERRY_LINE_INFO */
|
||||
|
||||
#if JERRY_MODULE_SYSTEM
|
||||
parser_module_append_export_name (context_p);
|
||||
@@ -522,10 +525,7 @@ parser_parse_var_statement (parser_context_t *context_p) /**< context */
|
||||
#endif /* JERRY_DEBUGGER */
|
||||
|
||||
#if JERRY_LINE_INFO
|
||||
if (ident_line_counter != context_p->last_line_info_line)
|
||||
{
|
||||
parser_emit_line_info (context_p, ident_line_counter, false);
|
||||
}
|
||||
parser_line_info_append (context_p, ident_line_counter, ident_column_counter);
|
||||
#endif /* JERRY_LINE_INFO */
|
||||
|
||||
uint16_t index = context_p->lit_object.index;
|
||||
@@ -1866,10 +1866,7 @@ parser_parse_switch_statement_start (parser_context_t *context_p) /**< context *
|
||||
switch_case_was_found = true;
|
||||
|
||||
#if JERRY_LINE_INFO
|
||||
if (context_p->token.line != context_p->last_line_info_line)
|
||||
{
|
||||
parser_emit_line_info (context_p, context_p->token.line, true);
|
||||
}
|
||||
parser_line_info_append (context_p, context_p->token.line, context_p->token.column);
|
||||
#endif /* JERRY_LINE_INFO */
|
||||
|
||||
parser_parse_expression (context_p, PARSE_EXPR);
|
||||
@@ -2834,7 +2831,7 @@ parser_parse_statements (parser_context_t *context_p) /**< context */
|
||||
}
|
||||
#endif /* JERRY_DEBUGGER */
|
||||
#if JERRY_LINE_INFO
|
||||
parser_emit_line_info (context_p, context_p->token.line, false);
|
||||
parser_line_info_append (context_p, context_p->token.line, context_p->token.column);
|
||||
#endif /* JERRY_LINE_INFO */
|
||||
|
||||
lexer_construct_literal_object (context_p, &lit_location, LEXER_STRING_LITERAL);
|
||||
@@ -2919,8 +2916,7 @@ parser_parse_statements (parser_context_t *context_p) /**< context */
|
||||
#endif /* JERRY_DEBUGGER */
|
||||
|
||||
#if JERRY_LINE_INFO
|
||||
if (context_p->token.line != context_p->last_line_info_line
|
||||
&& context_p->token.type != LEXER_SEMICOLON
|
||||
if (context_p->token.type != LEXER_SEMICOLON
|
||||
&& context_p->token.type != LEXER_LEFT_BRACE
|
||||
&& context_p->token.type != LEXER_RIGHT_BRACE
|
||||
&& context_p->token.type != LEXER_KEYW_VAR
|
||||
@@ -2930,7 +2926,7 @@ parser_parse_statements (parser_context_t *context_p) /**< context */
|
||||
&& context_p->token.type != LEXER_KEYW_CASE
|
||||
&& context_p->token.type != LEXER_KEYW_DEFAULT)
|
||||
{
|
||||
parser_emit_line_info (context_p, context_p->token.line, true);
|
||||
parser_line_info_append (context_p, context_p->token.line, context_p->token.column);
|
||||
}
|
||||
#endif /* JERRY_LINE_INFO */
|
||||
|
||||
|
||||
@@ -453,60 +453,6 @@ parser_emit_cbc_push_number (parser_context_t *context_p, /**< context */
|
||||
context_p->last_cbc.value = (uint16_t) (value - 1);
|
||||
} /* parser_emit_cbc_push_number */
|
||||
|
||||
#if JERRY_LINE_INFO
|
||||
|
||||
/**
|
||||
* Append a line info data
|
||||
*/
|
||||
void
|
||||
parser_emit_line_info (parser_context_t *context_p, /**< context */
|
||||
uint32_t line, /**< current line */
|
||||
bool flush_cbc) /**< flush last byte code */
|
||||
{
|
||||
if (flush_cbc && context_p->last_cbc_opcode != PARSER_CBC_UNAVAILABLE)
|
||||
{
|
||||
parser_flush_cbc (context_p);
|
||||
}
|
||||
|
||||
#if JERRY_PARSER_DUMP_BYTE_CODE
|
||||
if (context_p->is_show_opcodes)
|
||||
{
|
||||
JERRY_DEBUG_MSG (" [%3d] CBC_EXT_LINE %d\n", (int) context_p->stack_depth, line);
|
||||
}
|
||||
#endif /* JERRY_PARSER_DUMP_BYTE_CODE */
|
||||
|
||||
parser_emit_two_bytes (context_p, CBC_EXT_OPCODE, CBC_EXT_LINE);
|
||||
context_p->byte_code_size += 2;
|
||||
|
||||
context_p->last_line_info_line = line;
|
||||
|
||||
const uint32_t max_shift_plus_7 = 7 * 5;
|
||||
uint32_t shift = 7;
|
||||
|
||||
while (shift < max_shift_plus_7 && (line >> shift) > 0)
|
||||
{
|
||||
shift += 7;
|
||||
}
|
||||
|
||||
do
|
||||
{
|
||||
shift -= 7;
|
||||
|
||||
uint8_t byte = (uint8_t) ((line >> shift) & CBC_LOWER_SEVEN_BIT_MASK);
|
||||
|
||||
if (shift > 0)
|
||||
{
|
||||
byte = (uint8_t) (byte | CBC_HIGHEST_BIT_MASK);
|
||||
}
|
||||
|
||||
PARSER_APPEND_TO_BYTE_CODE (context_p, byte);
|
||||
context_p->byte_code_size++;
|
||||
}
|
||||
while (shift > 0);
|
||||
} /* parser_emit_line_info */
|
||||
|
||||
#endif /* JERRY_LINE_INFO */
|
||||
|
||||
/**
|
||||
* Append a byte code with a branch argument
|
||||
*/
|
||||
|
||||
@@ -649,6 +649,13 @@ parser_post_processing (parser_context_t *context_p) /**< context */
|
||||
}
|
||||
#endif /* JERRY_ESNEXT */
|
||||
|
||||
#if JERRY_LINE_INFO
|
||||
if (context_p->line_info.first_page_p == NULL)
|
||||
{
|
||||
parser_line_info_append (context_p, context_p->token.line, context_p->token.column);
|
||||
}
|
||||
#endif /* JERRY_LINE_INFO */
|
||||
|
||||
JERRY_ASSERT (context_p->stack_depth == 0);
|
||||
#ifndef JERRY_NDEBUG
|
||||
JERRY_ASSERT (context_p->context_stack_depth == 0);
|
||||
@@ -730,23 +737,6 @@ parser_post_processing (parser_context_t *context_p) /**< context */
|
||||
flags = cbc_ext_flags[ext_opcode];
|
||||
PARSER_NEXT_BYTE (page_p, offset);
|
||||
length++;
|
||||
|
||||
#if JERRY_LINE_INFO
|
||||
if (ext_opcode == CBC_EXT_LINE)
|
||||
{
|
||||
uint8_t last_byte = 0;
|
||||
|
||||
do
|
||||
{
|
||||
last_byte = page_p->bytes[offset];
|
||||
PARSER_NEXT_BYTE (page_p, offset);
|
||||
length++;
|
||||
}
|
||||
while (last_byte & CBC_HIGHEST_BIT_MASK);
|
||||
|
||||
continue;
|
||||
}
|
||||
#endif /* JERRY_LINE_INFO */
|
||||
break;
|
||||
}
|
||||
case CBC_POST_DECR:
|
||||
@@ -941,6 +931,10 @@ parser_post_processing (parser_context_t *context_p) /**< context */
|
||||
}
|
||||
#endif /* JERRY_ESNEXT */
|
||||
|
||||
#if JERRY_LINE_INFO
|
||||
total_size += sizeof (ecma_value_t);
|
||||
#endif /* JERRY_LINE_INFO */
|
||||
|
||||
total_size = JERRY_ALIGNUP (total_size, JMEM_ALIGNMENT);
|
||||
|
||||
compiled_code_p = (ecma_compiled_code_t *) parser_malloc (context_p, total_size);
|
||||
@@ -1087,6 +1081,10 @@ parser_post_processing (parser_context_t *context_p) /**< context */
|
||||
|
||||
compiled_code_p->status_flags |= function_type;
|
||||
|
||||
#if JERRY_LINE_INFO
|
||||
compiled_code_p->status_flags |= CBC_CODE_FLAGS_HAS_LINE_INFO;
|
||||
#endif /* JERRY_LINE_INFO */
|
||||
|
||||
literal_pool_p = ((ecma_value_t *) byte_code_p) - context_p->register_count;
|
||||
byte_code_p += literal_length;
|
||||
dst_p = byte_code_p;
|
||||
@@ -1157,25 +1155,6 @@ parser_post_processing (parser_context_t *context_p) /**< context */
|
||||
opcode_p++;
|
||||
real_offset++;
|
||||
PARSER_NEXT_BYTE_UPDATE (page_p, offset, real_offset);
|
||||
|
||||
#if JERRY_LINE_INFO
|
||||
if (ext_opcode == CBC_EXT_LINE)
|
||||
{
|
||||
uint8_t last_byte = 0;
|
||||
|
||||
do
|
||||
{
|
||||
last_byte = page_p->bytes[offset];
|
||||
*dst_p++ = last_byte;
|
||||
|
||||
real_offset++;
|
||||
PARSER_NEXT_BYTE_UPDATE (page_p, offset, real_offset);
|
||||
}
|
||||
while (last_byte & CBC_HIGHEST_BIT_MASK);
|
||||
|
||||
continue;
|
||||
}
|
||||
#endif /* JERRY_LINE_INFO */
|
||||
}
|
||||
|
||||
/* Only literal and call arguments can be combined. */
|
||||
@@ -1291,6 +1270,10 @@ parser_post_processing (parser_context_t *context_p) /**< context */
|
||||
}
|
||||
JERRY_ASSERT (dst_p == byte_code_p + length);
|
||||
|
||||
#if JERRY_LINE_INFO
|
||||
uint8_t *line_info_p = parser_line_info_generate (context_p);
|
||||
#endif /* JERRY_LINE_INFO */
|
||||
|
||||
parse_update_branches (context_p, byte_code_p);
|
||||
|
||||
parser_cbc_stream_free (&context_p->byte_code);
|
||||
@@ -1371,9 +1354,16 @@ parser_post_processing (parser_context_t *context_p) /**< context */
|
||||
{
|
||||
compiled_code_p->status_flags |= CBC_CODE_FLAGS_HAS_TAGGED_LITERALS;
|
||||
base_p[-1] = (ecma_value_t) context_p->tagged_template_literal_cp;
|
||||
#if JERRY_LINE_INFO
|
||||
--base_p;
|
||||
#endif /* JERRY_LINE_INFO */
|
||||
}
|
||||
#endif /* JERRY_ESNEXT */
|
||||
|
||||
#if JERRY_LINE_INFO
|
||||
ECMA_SET_INTERNAL_VALUE_POINTER (base_p[-1], line_info_p);
|
||||
#endif /* JERRY_LINE_INFO */
|
||||
|
||||
#if JERRY_PARSER_DUMP_BYTE_CODE
|
||||
if (context_p->is_show_opcodes)
|
||||
{
|
||||
@@ -1896,6 +1886,14 @@ parser_parse_source (const uint8_t *arg_list_p, /**< function argument list */
|
||||
context.context_stack_depth = 0;
|
||||
#endif /* !JERRY_NDEBUG */
|
||||
|
||||
#if JERRY_LINE_INFO
|
||||
context.line_info.first_page_p = NULL;
|
||||
context.line_info.last_page_p = NULL;
|
||||
context.line_info.byte_code_position = 0;
|
||||
context.line_info.line = 1;
|
||||
context.line_info.column = 1;
|
||||
#endif /* JERRY_LINE_INFO */
|
||||
|
||||
#if JERRY_PARSER_DUMP_BYTE_CODE
|
||||
context.is_show_opcodes = (JERRY_CONTEXT (jerry_init_flags) & JERRY_INIT_SHOW_OPCODES);
|
||||
context.total_byte_code_size = 0;
|
||||
@@ -2074,6 +2072,10 @@ parser_parse_source (const uint8_t *arg_list_p, /**< function argument list */
|
||||
parser_free (context.scope_stack_p, context.scope_stack_size * sizeof (parser_scope_stack_t));
|
||||
}
|
||||
|
||||
#if JERRY_LINE_INFO
|
||||
parser_line_info_free (&context.line_info);
|
||||
#endif /* JERRY_LINE_INFO */
|
||||
|
||||
#if JERRY_PARSER_DUMP_BYTE_CODE
|
||||
if (context.is_show_opcodes)
|
||||
{
|
||||
@@ -2206,6 +2208,10 @@ parser_save_context (parser_context_t *context_p, /**< context */
|
||||
saved_context_p->context_stack_depth = context_p->context_stack_depth;
|
||||
#endif /* !JERRY_NDEBUG */
|
||||
|
||||
#if JERRY_LINE_INFO
|
||||
saved_context_p->line_info = context_p->line_info;
|
||||
#endif /* JERRY_LINE_INFO */
|
||||
|
||||
/* Reset private part of the context. */
|
||||
|
||||
context_p->status_flags &= PARSER_IS_STRICT;
|
||||
@@ -2236,6 +2242,14 @@ parser_save_context (parser_context_t *context_p, /**< context */
|
||||
#ifndef JERRY_NDEBUG
|
||||
context_p->context_stack_depth = 0;
|
||||
#endif /* !JERRY_NDEBUG */
|
||||
|
||||
#if JERRY_LINE_INFO
|
||||
context_p->line_info.first_page_p = NULL;
|
||||
context_p->line_info.last_page_p = NULL;
|
||||
context_p->line_info.byte_code_position = 0;
|
||||
context_p->line_info.line = 1;
|
||||
context_p->line_info.column = 1;
|
||||
#endif /* JERRY_LINE_INFO */
|
||||
} /* parser_save_context */
|
||||
|
||||
/**
|
||||
@@ -2252,6 +2266,10 @@ parser_restore_context (parser_context_t *context_p, /**< context */
|
||||
parser_free (context_p->scope_stack_p, context_p->scope_stack_size * sizeof (parser_scope_stack_t));
|
||||
}
|
||||
|
||||
#if JERRY_LINE_INFO
|
||||
parser_line_info_free (&context_p->line_info);
|
||||
#endif /* JERRY_LINE_INFO */
|
||||
|
||||
/* Restore private part of the context. */
|
||||
|
||||
JERRY_ASSERT (context_p->last_cbc_opcode == PARSER_CBC_UNAVAILABLE);
|
||||
@@ -2284,6 +2302,10 @@ parser_restore_context (parser_context_t *context_p, /**< context */
|
||||
#ifndef JERRY_NDEBUG
|
||||
context_p->context_stack_depth = saved_context_p->context_stack_depth;
|
||||
#endif /* !JERRY_NDEBUG */
|
||||
|
||||
#if JERRY_LINE_INFO
|
||||
context_p->line_info = saved_context_p->line_info;
|
||||
#endif /* JERRY_LINE_INFO */
|
||||
} /* parser_restore_context */
|
||||
|
||||
/**
|
||||
@@ -2579,10 +2601,7 @@ parser_parse_class_fields (parser_context_t *context_p) /**< context */
|
||||
}
|
||||
|
||||
#if JERRY_LINE_INFO
|
||||
if (context_p->token.line != context_p->last_line_info_line)
|
||||
{
|
||||
parser_emit_line_info (context_p, context_p->token.line, true);
|
||||
}
|
||||
parser_line_info_append (context_p, context_p->token.line, context_p->token.column);
|
||||
#endif /* JERRY_LINE_INFO */
|
||||
|
||||
context_p->source_end_p = range.source_end_p;
|
||||
@@ -2822,6 +2841,10 @@ parser_raise_error (parser_context_t *context_p, /**< context */
|
||||
}
|
||||
#endif /* JERRY_ESNEXT */
|
||||
|
||||
#if JERRY_LINE_INFO
|
||||
parser_line_info_free (&saved_context_p->line_info);
|
||||
#endif /* JERRY_LINE_INFO */
|
||||
|
||||
saved_context_p = saved_context_p->prev_context_p;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user