Add line info support. (#2286)

Add line info data to byte, which allows getting a backtrace info directly
from the engine. Snapshots are not supported.

JerryScript-DCO-1.0-Signed-off-by: Zoltan Herczeg zherczeg.u-szeged@partner.samsung.com
This commit is contained in:
Zoltan Herczeg
2018-04-19 02:12:54 +02:00
committed by yichoi
parent 095b730f9d
commit 5e097dc354
24 changed files with 773 additions and 52 deletions
+7
View File
@@ -22,6 +22,7 @@ set(FEATURE_DEBUGGER OFF CACHE BOOL "Enable JerryScript debugger
set(FEATURE_ERROR_MESSAGES OFF CACHE BOOL "Enable error messages?")
set(FEATURE_EXTERNAL_CONTEXT OFF CACHE BOOL "Enable external context?")
set(FEATURE_JS_PARSER ON CACHE BOOL "Enable js-parser?")
set(FEATURE_LINE_INFO OFF CACHE BOOL "Enable line info?")
set(FEATURE_MEM_STATS OFF CACHE BOOL "Enable memory statistics?")
set(FEATURE_MEM_STRESS_TEST OFF CACHE BOOL "Enable mem-stress test?")
set(FEATURE_PARSER_DUMP OFF CACHE BOOL "Enable parser byte-code dumps?")
@@ -63,6 +64,7 @@ message(STATUS "FEATURE_DEBUGGER " ${FEATURE_DEBUGGER})
message(STATUS "FEATURE_ERROR_MESSAGES " ${FEATURE_ERROR_MESSAGES})
message(STATUS "FEATURE_EXTERNAL_CONTEXT " ${FEATURE_EXTERNAL_CONTEXT})
message(STATUS "FEATURE_JS_PARSER " ${FEATURE_JS_PARSER})
message(STATUS "FEATURE_LINE_INFO " ${FEATURE_LINE_INFO})
message(STATUS "FEATURE_MEM_STATS " ${FEATURE_MEM_STATS})
message(STATUS "FEATURE_MEM_STRESS_TEST " ${FEATURE_MEM_STRESS_TEST})
message(STATUS "FEATURE_PARSER_DUMP " ${FEATURE_PARSER_DUMP} ${FEATURE_PARSER_DUMP_MESSAGE})
@@ -174,6 +176,11 @@ if(NOT FEATURE_JS_PARSER)
set(DEFINES_JERRY ${DEFINES_JERRY} JERRY_DISABLE_JS_PARSER)
endif()
# JS line info
if(FEATURE_LINE_INFO)
set(DEFINES_JERRY ${DEFINES_JERRY} JERRY_ENABLE_LINE_INFO)
endif()
# Memory statistics
if(FEATURE_MEM_STATS)
set(DEFINES_JERRY ${DEFINES_JERRY} JMEM_STATS)
+9
View File
@@ -726,6 +726,10 @@ jerry_generate_snapshot_with_args (const jerry_char_t *resource_name_p, /**< scr
JERRY_UNUSED (resource_name_p);
JERRY_UNUSED (resource_name_length);
#ifdef JERRY_ENABLE_LINE_INFO
JERRY_CONTEXT (resource_name) = ECMA_VALUE_UNDEFINED;
#endif /* JERRY_ENABLE_LINE_INFO */
snapshot_globals_t globals;
ecma_value_t parse_status;
ecma_compiled_code_t *bytecode_data_p;
@@ -1579,6 +1583,11 @@ jerry_parse_and_save_literals (const jerry_char_t *source_p, /**< script source
#ifdef JERRY_ENABLE_SNAPSHOT_SAVE
ecma_value_t parse_status;
ecma_compiled_code_t *bytecode_data_p;
#ifdef JERRY_ENABLE_LINE_INFO
JERRY_CONTEXT (resource_name) = ECMA_VALUE_UNDEFINED;
#endif /* JERRY_ENABLE_LINE_INFO */
parse_status = parser_parse_script (NULL,
0,
source_p,
+1 -1
View File
@@ -41,7 +41,7 @@ typedef struct
/**
* Jerry snapshot format version.
*/
#define JERRY_SNAPSHOT_VERSION (11u)
#define JERRY_SNAPSHOT_VERSION (12u)
/**
* Snapshot configuration flags.
+25
View File
@@ -415,6 +415,11 @@ jerry_parse (const jerry_char_t *resource_name_p, /**< resource name (usually a
#ifndef JERRY_DISABLE_JS_PARSER
jerry_assert_api_available ();
#if defined JERRY_ENABLE_LINE_INFO && !defined JERRY_DISABLE_JS_PARSER
JERRY_CONTEXT (resource_name) = ecma_find_or_create_literal_string (resource_name_p,
(lit_utf8_size_t) resource_name_length);
#endif /* JERRY_ENABLE_LINE_INFO && !JERRY_DISABLE_JS_PARSER */
ecma_compiled_code_t *bytecode_data_p;
ecma_value_t parse_status;
@@ -482,6 +487,11 @@ jerry_parse_function (const jerry_char_t *resource_name_p, /**< resource name (u
ecma_compiled_code_t *bytecode_data_p;
ecma_value_t parse_status;
#ifdef JERRY_ENABLE_LINE_INFO
JERRY_CONTEXT (resource_name) = ecma_find_or_create_literal_string (resource_name_p,
(lit_utf8_size_t) resource_name_length);
#endif /* JERRY_ENABLE_LINE_INFO */
if (arg_list_p == NULL)
{
/* Must not be a NULL value. */
@@ -874,6 +884,9 @@ bool jerry_is_feature_enabled (const jerry_feature_t feature)
#ifndef CONFIG_DISABLE_REGEXP_BUILTIN
|| feature == JERRY_FEATURE_REGEXP
#endif /* !CONFIG_DISABLE_REGEXP_BUILTIN */
#ifdef JERRY_ENABLE_LINE_INFO
|| feature == JERRY_FEATURE_LINE_INFO
#endif /* JERRY_ENABLE_LINE_INFO */
);
} /* jerry_is_feature_enabled */
@@ -2845,6 +2858,18 @@ jerry_set_vm_exec_stop_callback (jerry_vm_exec_stop_callback_t stop_cb, /**< per
#endif /* JERRY_VM_EXEC_STOP */
} /* jerry_set_vm_exec_stop_callback */
/**
* Get backtrace. The backtrace is an array of strings where
* each string contains the position of the corresponding frame.
* The array length is zero if the backtrace is not available.
*
* @return array value
*/
jerry_value_t
jerry_get_backtrace (uint32_t max_depth)
{
return vm_get_backtrace (max_depth);
} /* jerry_get_backtrace */
/**
* Check if the given value is an ArrayBuffer object.
@@ -21,8 +21,12 @@
#include "ecma-function-object.h"
#include "ecma-lex-env.h"
#include "ecma-try-catch-macro.h"
#include "lit-magic-strings.h"
#include "js-parser.h"
#include "lit-magic-strings.h"
#ifdef JERRY_ENABLE_LINE_INFO
#include "jcontext.h"
#endif /* JERRY_ENABLE_LINE_INFO */
#define ECMA_BUILTINS_INTERNAL
#include "ecma-builtins-internal.h"
@@ -155,6 +159,10 @@ ecma_builtin_function_dispatch_construct (const ecma_value_t *arguments_list_p,
ECMA_STRING_TO_UTF8_STRING (arguments_str_p, arguments_buffer_p, arguments_buffer_size);
ECMA_STRING_TO_UTF8_STRING (function_body_str_p, function_body_buffer_p, function_body_buffer_size);
#ifdef JERRY_ENABLE_LINE_INFO
JERRY_CONTEXT (resource_name) = ecma_make_magic_string_value (LIT_MAGIC_STRING__EMPTY);
#endif /* JERRY_ENABLE_LINE_INFO */
ecma_compiled_code_t *bytecode_data_p = NULL;
ecma_value_t ret_value = parser_parse_script (arguments_buffer_p,
+8
View File
@@ -23,6 +23,10 @@
#include "js-parser.h"
#include "vm.h"
#ifdef JERRY_ENABLE_LINE_INFO
#include "jcontext.h"
#endif /* JERRY_ENABLE_LINE_INFO */
/** \addtogroup ecma ECMA
* @{
*
@@ -88,6 +92,10 @@ ecma_op_eval_chars_buffer (const lit_utf8_byte_t *code_p, /**< code characters b
bool is_strict_call = (is_direct && is_called_from_strict_mode_code);
#ifdef JERRY_ENABLE_LINE_INFO
JERRY_CONTEXT (resource_name) = ecma_make_magic_string_value (LIT_MAGIC_STRING__EMPTY);
#endif /* JERRY_ENABLE_LINE_INFO */
ecma_value_t parse_status = parser_parse_script (NULL,
0,
code_p,
@@ -24,6 +24,10 @@
#include "jcontext.h"
#include "jrt.h"
#ifdef JERRY_ENABLE_LINE_INFO
#include "vm.h"
#endif /* JERRY_ENABLE_LINE_INFO */
/** \addtogroup ecma ECMA
* @{
*
@@ -134,6 +138,24 @@ ecma_new_standard_error (ecma_standard_error_t error_type) /**< native error typ
((ecma_extended_object_t *) new_error_obj_p)->u.class_prop.class_id = LIT_MAGIC_STRING_ERROR_UL;
#ifdef JERRY_ENABLE_LINE_INFO
/* The "stack" identifier is not a magic string. */
const char *stack_id_p = "stack";
ecma_string_t *stack_str_p = ecma_new_ecma_string_from_utf8 ((const lit_utf8_byte_t *) stack_id_p, 5);
ecma_property_value_t *prop_value_p = ecma_create_named_data_property (new_error_obj_p,
stack_str_p,
ECMA_PROPERTY_CONFIGURABLE_WRITABLE,
NULL);
ecma_deref_ecma_string (stack_str_p);
ecma_value_t backtrace_value = vm_get_backtrace (0);
prop_value_p->value = backtrace_value;
ecma_deref_object (ecma_get_object_from_value (backtrace_value));
#endif /* JERRY_ENABLE_LINE_INFO */
return new_error_obj_p;
} /* ecma_new_standard_error */
+3 -1
View File
@@ -95,6 +95,7 @@ typedef enum
JERRY_FEATURE_TYPEDARRAY, /**< Typedarray support */
JERRY_FEATURE_DATE, /**< Date support */
JERRY_FEATURE_REGEXP, /**< Regexp support */
JERRY_FEATURE_LINE_INFO, /**< line info available */
JERRY_FEATURE__COUNT /**< number of features. NOTE: must be at the end of the list */
} jerry_feature_t;
@@ -465,7 +466,7 @@ bool jerry_delete_property (const jerry_value_t obj_val, const jerry_value_t pro
bool jerry_delete_property_by_index (const jerry_value_t obj_val, uint32_t index);
jerry_value_t jerry_get_property (const jerry_value_t obj_val, const jerry_value_t prop_name_val);
jerry_value_t jerry_get_property_by_index (const jerry_value_t obj_val, uint32_t index);
jerry_value_t jerry_get_property_by_index (const jerry_value_t obj_val, uint32_t index);
jerry_value_t jerry_set_property (const jerry_value_t obj_val, const jerry_value_t prop_name_val,
const jerry_value_t value_to_set);
jerry_value_t jerry_set_property_by_index (const jerry_value_t obj_val, uint32_t index,
@@ -531,6 +532,7 @@ jerry_instance_t *jerry_create_instance (uint32_t heap_size, jerry_instance_allo
* Miscellaneous functions.
*/
void jerry_set_vm_exec_stop_callback (jerry_vm_exec_stop_callback_t stop_cb, void *user_p, uint32_t frequency);
jerry_value_t jerry_get_backtrace (uint32_t max_depth);
/**
* Array buffer components.
+4
View File
@@ -124,6 +124,10 @@ typedef struct
int debugger_connection; /**< holds the file descriptor of the socket communication */
#endif /* JERRY_DEBUGGER */
#ifdef JERRY_ENABLE_LINE_INFO
ecma_value_t resource_name; /**< resource name (usually a file name) */
#endif /* JERRY_ENABLE_LINE_INFO */
#ifdef JMEM_STATS
jmem_heap_stats_t jmem_heap_stats; /**< heap's memory usage statistics */
#endif /* JMEM_STATS */
+4
View File
@@ -539,6 +539,10 @@
/* Basic opcodes. */ \
CBC_OPCODE (CBC_EXT_DEBUGGER, CBC_NO_FLAG, 0, \
VM_OC_NONE) \
CBC_OPCODE (CBC_EXT_RESOURCE_NAME, CBC_NO_FLAG, 0, \
VM_OC_RESOURCE_NAME) \
CBC_OPCODE (CBC_EXT_LINE, CBC_NO_FLAG, 0, \
VM_OC_LINE) \
\
/* Binary compound assignment opcodes with pushing the result. */ \
CBC_EXT_BINARY_LVALUE_OPERATION (CBC_EXT_ASSIGN_ADD, \
+11 -1
View File
@@ -308,8 +308,12 @@ typedef struct
/** extra data for each breakpoint */
parser_breakpoint_info_t breakpoint_info[JERRY_DEBUGGER_MAX_BUFFER_SIZE / sizeof (parser_breakpoint_info_t)];
uint16_t breakpoint_info_count; /**< current breakpoint index */
parser_line_counter_t last_breakpoint_line; /**< last line where breakpoint was inserted */
parser_line_counter_t last_breakpoint_line; /**< last line where breakpoint has been inserted */
#endif /* JERRY_DEBUGGER */
#ifdef JERRY_ENABLE_LINE_INFO
parser_line_counter_t last_line_info_line; /**< last line where line info has been inserted */
#endif /* JERRY_ENABLE_LINE_INFO */
} parser_context_t;
/**
@@ -485,6 +489,12 @@ void parser_send_breakpoints (parser_context_t *context_p, jerry_debugger_header
#endif /* JERRY_DEBUGGER */
#ifdef JERRY_ENABLE_LINE_INFO
void parser_emit_line_info (parser_context_t *context_p, uint32_t line, bool flush_cbc);
#endif /* JERRY_ENABLE_LINE_INFO */
/**
* @}
* @}
+52 -4
View File
@@ -17,9 +17,9 @@
#ifndef JERRY_DISABLE_JS_PARSER
#ifdef JERRY_DEBUGGER
#if defined (JERRY_DEBUGGER) || defined (JERRY_ENABLE_LINE_INFO)
#include "jcontext.h"
#endif /*JERRY_DEBUGGER */
#endif /* JERRY_DEBUGGER || JERRY_ENABLE_LINE_INFO */
/** \addtogroup parser Parser
* @{
@@ -314,9 +314,9 @@ parser_parse_var_statement (parser_context_t *context_p) /**< context */
JERRY_ASSERT (context_p->token.type == LEXER_LITERAL
&& context_p->token.lit_location.type == LEXER_IDENT_LITERAL);
#ifdef JERRY_DEBUGGER
#if defined (JERRY_DEBUGGER) || defined (JERRY_ENABLE_LINE_INFO)
parser_line_counter_t ident_line_counter = context_p->token.line;
#endif /* JERRY_DEBUGGER */
#endif /* JERRY_DEBUGGER || JERRY_ENABLE_LINE_INFO */
context_p->lit_object.literal_p->status_flags |= LEXER_FLAG_VAR;
@@ -347,6 +347,13 @@ parser_parse_var_statement (parser_context_t *context_p) /**< context */
}
#endif /* JERRY_DEBUGGER */
#ifdef JERRY_ENABLE_LINE_INFO
if (ident_line_counter != context_p->last_line_info_line)
{
parser_emit_line_info (context_p, ident_line_counter, false);
}
#endif /* JERRY_ENABLE_LINE_INFO */
parser_parse_expression (context_p,
PARSE_EXPR_STATEMENT | PARSE_EXPR_NO_COMMA | PARSE_EXPR_HAS_LITERAL);
}
@@ -1080,6 +1087,10 @@ parser_parse_switch_statement_start (parser_context_t *context_p) /**< context *
switch_case_was_found = false;
default_case_was_found = false;
#ifdef JERRY_ENABLE_LINE_INFO
uint32_t last_line_info_line = context_p->last_line_info_line;
#endif /* JERRY_ENABLE_LINE_INFO */
while (true)
{
parser_scan_until (context_p, &unused_range, LEXER_KEYW_CASE);
@@ -1134,6 +1145,13 @@ parser_parse_switch_statement_start (parser_context_t *context_p) /**< context *
lexer_next_token (context_p);
#ifdef JERRY_ENABLE_LINE_INFO
if (context_p->token.line != context_p->last_line_info_line)
{
parser_emit_line_info (context_p, context_p->token.line, true);
}
#endif /* JERRY_ENABLE_LINE_INFO */
parser_parse_expression (context_p, PARSE_EXPR);
if (context_p->token.type != LEXER_COLON)
@@ -1148,6 +1166,10 @@ parser_parse_switch_statement_start (parser_context_t *context_p) /**< context *
JERRY_ASSERT (switch_case_was_found || default_case_was_found);
#ifdef JERRY_ENABLE_LINE_INFO
context_p->last_line_info_line = last_line_info_line;
#endif /* JERRY_ENABLE_LINE_INFO */
if (!switch_case_was_found)
{
/* There was no case statement, so the expression result
@@ -1634,6 +1656,15 @@ parser_parse_statements (parser_context_t *context_p) /**< context */
}
#endif /* JERRY_DEBUGGER */
#ifdef JERRY_ENABLE_LINE_INFO
if (JERRY_CONTEXT (resource_name) != ECMA_VALUE_UNDEFINED)
{
parser_emit_cbc_ext (context_p, CBC_EXT_RESOURCE_NAME);
parser_flush_cbc (context_p);
}
context_p->last_line_info_line = 0;
#endif /* JERRY_ENABLE_LINE_INFO */
while (context_p->token.type == LEXER_LITERAL
&& context_p->token.lit_location.type == LEXER_STRING_LITERAL)
{
@@ -1685,6 +1716,9 @@ parser_parse_statements (parser_context_t *context_p) /**< context */
context_p->last_breakpoint_line = context_p->token.line;
}
#endif /* JERRY_DEBUGGER */
#ifdef JERRY_ENABLE_LINE_INFO
parser_emit_line_info (context_p, context_p->token.line, false);
#endif /* JERRY_ENABLE_LINE_INFO */
lexer_construct_literal_object (context_p, &lit_location, LEXER_STRING_LITERAL);
parser_emit_cbc_literal_from_token (context_p, CBC_PUSH_LITERAL);
@@ -1755,6 +1789,20 @@ parser_parse_statements (parser_context_t *context_p) /**< context */
}
#endif /* JERRY_DEBUGGER */
#ifdef JERRY_ENABLE_LINE_INFO
if (context_p->token.line != context_p->last_line_info_line
&& 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
&& context_p->token.type != LEXER_KEYW_FUNCTION
&& 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);
}
#endif /* JERRY_ENABLE_LINE_INFO */
switch (context_p->token.type)
{
case LEXER_SEMICOLON:
+55
View File
@@ -17,6 +17,10 @@
#ifndef JERRY_DISABLE_JS_PARSER
#ifdef JERRY_ENABLE_LINE_INFO
#include "jcontext.h"
#endif /* JERRY_ENABLE_LINE_INFO */
/** \addtogroup parser Parser
* @{
*
@@ -352,6 +356,57 @@ parser_emit_cbc_push_number (parser_context_t *context_p, /**< context */
}
} /* parser_emit_cbc_push_number */
#ifdef JERRY_ENABLE_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 (JERRY_CONTEXT (resource_name) == ECMA_VALUE_UNDEFINED)
{
return;
}
if (flush_cbc && context_p->last_cbc_opcode != PARSER_CBC_UNAVAILABLE)
{
parser_flush_cbc (context_p);
}
#ifdef 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 /* 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;
do
{
uint8_t byte = (uint8_t) (line & CBC_LOWER_SEVEN_BIT_MASK);
line >>= 7;
if (line > 0)
{
byte = (uint8_t) (byte | CBC_HIGHEST_BIT_MASK);
}
PARSER_APPEND_TO_BYTE_CODE (context_p, byte);
context_p->byte_code_size++;
}
while (line > 0);
} /* parser_emit_line_info */
#endif /* JERRY_ENABLE_LINE_INFO */
/**
* Append a byte code with a branch argument
*/
+76
View File
@@ -1292,6 +1292,24 @@ parse_print_final_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;
#ifdef JERRY_ENABLE_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_ENABLE_LINE_INFO */
}
if (flags & (CBC_HAS_LITERAL_ARG | CBC_HAS_LITERAL_ARG2))
@@ -1488,6 +1506,23 @@ parser_post_processing (parser_context_t *context_p) /**< context */
flags = cbc_ext_flags[ext_opcode];
PARSER_NEXT_BYTE (page_p, offset);
length++;
#ifdef JERRY_ENABLE_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_ENABLE_LINE_INFO */
}
while (flags & (CBC_HAS_LITERAL_ARG | CBC_HAS_LITERAL_ARG2))
@@ -1639,6 +1674,13 @@ parser_post_processing (parser_context_t *context_p) /**< context */
total_size += context_p->argument_count * sizeof (ecma_value_t);
}
#ifdef JERRY_ENABLE_LINE_INFO
if (JERRY_CONTEXT (resource_name) != ECMA_VALUE_UNDEFINED)
{
total_size += sizeof (ecma_value_t);
}
#endif /* JERRY_ENABLE_LINE_INFO */
#ifdef JERRY_ENABLE_SNAPSHOT_SAVE
total_size_used = total_size;
#endif
@@ -1802,6 +1844,25 @@ parser_post_processing (parser_context_t *context_p) /**< context */
opcode_p++;
real_offset++;
PARSER_NEXT_BYTE_UPDATE (page_p, offset, real_offset);
#ifdef JERRY_ENABLE_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_ENABLE_LINE_INFO */
}
if (flags & CBC_HAS_BRANCH_ARG)
@@ -1994,6 +2055,21 @@ parser_post_processing (parser_context_t *context_p) /**< context */
}
}
#ifdef JERRY_ENABLE_LINE_INFO
if (JERRY_CONTEXT (resource_name) != ECMA_VALUE_UNDEFINED)
{
ecma_value_t *resource_name_p = (ecma_value_t *) (((uint8_t *) compiled_code_p) + total_size);
if ((context_p->status_flags & PARSER_ARGUMENTS_NEEDED)
&& !(context_p->status_flags & PARSER_IS_STRICT))
{
resource_name_p -= context_p->argument_count;
}
resource_name_p[-1] = JERRY_CONTEXT (resource_name);
}
#endif /* JERRY_ENABLE_LINE_INFO */
if (context_p->status_flags & PARSER_NAMED_FUNCTION_EXP)
{
ECMA_SET_INTERNAL_VALUE_POINTER (literal_pool_p[const_literal_end],
+4
View File
@@ -51,6 +51,10 @@ typedef struct vm_frame_ctx_t
struct vm_frame_ctx_t *prev_context_p; /**< previous context */
ecma_value_t this_binding; /**< this binding */
ecma_value_t call_block_result; /**< preserve block result during a call */
#ifdef JERRY_ENABLE_LINE_INFO
ecma_value_t resource_name; /**< current resource name (usually a file name) */
uint32_t current_line; /**< currently executed line */
#endif /* JERRY_ENABLE_LINE_INFO */
uint16_t context_depth; /**< current context depth */
uint8_t is_eval_code; /**< eval mode flag */
uint8_t call_operation; /**< perform a call or construct operation */
+133
View File
@@ -0,0 +1,133 @@
/* 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-array-object.h"
#include "ecma-helpers.h"
#include "jcontext.h"
#include "vm.h"
/**
* Check whether currently executed code is strict mode code
*
* @return true - current code is executed in strict mode,
* false - otherwise
*/
bool
vm_is_strict_mode (void)
{
JERRY_ASSERT (JERRY_CONTEXT (vm_top_context_p) != NULL);
return JERRY_CONTEXT (vm_top_context_p)->bytecode_header_p->status_flags & CBC_CODE_FLAGS_STRICT_MODE;
} /* vm_is_strict_mode */
/**
* Check whether currently performed call (on top of call-stack) is performed in form,
* meeting conditions of 'Direct Call to Eval' (see also: ECMA-262 v5, 15.1.2.1.1)
*
* Warning:
* the function should only be called from implementation
* of built-in 'eval' routine of Global object
*
* @return true - currently performed call is performed through 'eval' identifier,
* without 'this' argument,
* false - otherwise
*/
inline bool __attr_always_inline___
vm_is_direct_eval_form_call (void)
{
return (JERRY_CONTEXT (status_flags) & ECMA_STATUS_DIRECT_EVAL) != 0;
} /* vm_is_direct_eval_form_call */
/**
* Get backtrace. The backtrace is an array of strings where
* each string contains the position of the corresponding frame.
* The array length is zero if the backtrace is not available.
*
* @return array ecma value
*/
ecma_value_t
vm_get_backtrace (uint32_t max_depth) /**< maximum backtrace depth, 0 = unlimited */
{
#ifdef JERRY_ENABLE_LINE_INFO
ecma_value_t result_array = ecma_op_create_array_object (NULL, 0, false);
if (max_depth == 0)
{
max_depth = UINT32_MAX;
}
vm_frame_ctx_t *context_p = JERRY_CONTEXT (vm_top_context_p);
ecma_object_t *array_p = ecma_get_object_from_value (result_array);
uint32_t index = 0;
while (context_p != NULL)
{
if (context_p->resource_name == ECMA_VALUE_UNDEFINED)
{
context_p = context_p->prev_context_p;
continue;
}
ecma_string_t *str_p = ecma_get_string_from_value (context_p->resource_name);
if (ecma_string_is_empty (str_p))
{
const char *unknown_str_p = "<unknown>:";
str_p = ecma_new_ecma_string_from_utf8 ((const lit_utf8_byte_t *) unknown_str_p,
(lit_utf8_size_t) strlen (unknown_str_p));
}
else
{
ecma_ref_ecma_string (str_p);
str_p = ecma_append_magic_string_to_string (str_p, LIT_MAGIC_STRING_COLON_CHAR);
}
ecma_string_t *line_str_p = ecma_new_ecma_string_from_uint32 (context_p->current_line);
str_p = ecma_concat_ecma_strings (str_p, line_str_p);
ecma_deref_ecma_string (line_str_p);
ecma_string_t *index_str_p = ecma_new_ecma_string_from_uint32 (index);
ecma_property_value_t *prop_value_p;
prop_value_p = ecma_create_named_data_property (array_p,
index_str_p,
ECMA_PROPERTY_CONFIGURABLE_ENUMERABLE_WRITABLE,
NULL);
ecma_deref_ecma_string (index_str_p);
prop_value_p->value = ecma_make_string_value (str_p);
context_p = context_p->prev_context_p;
index++;
if (index >= max_depth)
{
break;
}
}
if (index > 0)
{
JERRY_ASSERT (ecma_get_object_type (array_p) == ECMA_OBJECT_TYPE_ARRAY);
((ecma_extended_object_t *) array_p)->u.array.length = index;
}
return result_array;
#else /* !JERRY_ENABLE_LINE_INFO */
JERRY_UNUSED (max_depth);
return ecma_op_create_array_object (NULL, 0, false);
#endif /* JERRY_ENABLE_LINE_INFO */
} /* vm_get_backtrace */
+50 -32
View File
@@ -2596,6 +2596,52 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */
#endif /* JERRY_DEBUGGER */
continue;
}
#ifdef JERRY_ENABLE_LINE_INFO
case VM_OC_RESOURCE_NAME:
{
ecma_length_t formal_params_number = 0;
if (bytecode_header_p->status_flags & CBC_CODE_FLAGS_NON_STRICT_ARGUMENTS_NEEDED)
{
if (bytecode_header_p->status_flags & CBC_CODE_FLAGS_UINT16_ARGUMENTS)
{
cbc_uint16_arguments_t *args_p = (cbc_uint16_arguments_t *) bytecode_header_p;
formal_params_number = args_p->argument_end;
}
else
{
cbc_uint8_arguments_t *args_p = (cbc_uint8_arguments_t *) bytecode_header_p;
formal_params_number = args_p->argument_end;
}
}
uint8_t *byte_p = (uint8_t *) bytecode_header_p;
byte_p += ((size_t) bytecode_header_p->size) << JMEM_ALIGNMENT_LOG;
ecma_value_t *resource_name_p = (ecma_value_t *) byte_p;
resource_name_p -= formal_params_number;
frame_ctx_p->resource_name = resource_name_p[-1];
continue;
}
case VM_OC_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);
frame_ctx_p->current_line = value;
continue;
}
#endif /* JERRY_ENABLE_LINE_INFO */
default:
{
JERRY_UNREACHABLE ();
@@ -2990,6 +3036,10 @@ vm_run (const ecma_compiled_code_t *bytecode_header_p, /**< byte-code data heade
frame_ctx.lex_env_p = lex_env_p;
frame_ctx.prev_context_p = JERRY_CONTEXT (vm_top_context_p);
frame_ctx.this_binding = this_binding_value;
#ifdef JERRY_ENABLE_LINE_INFO
frame_ctx.resource_name = ECMA_VALUE_UNDEFINED;
frame_ctx.current_line = 0;
#endif /* JERRY_ENABLE_LINE_INFO */
frame_ctx.context_depth = 0;
frame_ctx.is_eval_code = is_eval_code;
frame_ctx.call_operation = VM_NO_EXEC_OP;
@@ -3001,38 +3051,6 @@ vm_run (const ecma_compiled_code_t *bytecode_header_p, /**< byte-code data heade
return vm_execute (&frame_ctx, arg_list_p, arg_list_len);
} /* vm_run */
/**
* Check whether currently executed code is strict mode code
*
* @return true - current code is executed in strict mode,
* false - otherwise
*/
bool
vm_is_strict_mode (void)
{
JERRY_ASSERT (JERRY_CONTEXT (vm_top_context_p) != NULL);
return JERRY_CONTEXT (vm_top_context_p)->bytecode_header_p->status_flags & CBC_CODE_FLAGS_STRICT_MODE;
} /* vm_is_strict_mode */
/**
* Check whether currently performed call (on top of call-stack) is performed in form,
* meeting conditions of 'Direct Call to Eval' (see also: ECMA-262 v5, 15.1.2.1.1)
*
* Warning:
* the function should only be called from implementation
* of built-in 'eval' routine of Global object
*
* @return true - currently performed call is performed through 'eval' identifier,
* without 'this' argument,
* false - otherwise
*/
inline bool __attr_always_inline___
vm_is_direct_eval_form_call (void)
{
return (JERRY_CONTEXT (status_flags) & ECMA_STATUS_DIRECT_EVAL) != 0;
} /* vm_is_direct_eval_form_call */
/**
* @}
* @}
+6 -2
View File
@@ -203,8 +203,10 @@ typedef enum
VM_OC_FINALLY, /**< finally */
VM_OC_CONTEXT_END, /**< context end */
VM_OC_JUMP_AND_EXIT_CONTEXT, /**< jump and exit context */
VM_OC_BREAKPOINT_ENABLED, /**< enabled breakpoint for debugger */
VM_OC_BREAKPOINT_DISABLED, /**< disabled breakpoint for debugger */
VM_OC_BREAKPOINT_ENABLED, /**< enabled breakpoint for debugger */
VM_OC_BREAKPOINT_DISABLED, /**< disabled breakpoint for debugger */
VM_OC_RESOURCE_NAME, /**< resource name of the current function */
VM_OC_LINE, /**< line number of the next statement */
} vm_oc_types;
/**
@@ -286,6 +288,8 @@ ecma_value_t vm_run (const ecma_compiled_code_t *bytecode_header_p, ecma_value_t
bool vm_is_strict_mode (void);
bool vm_is_direct_eval_form_call (void);
ecma_value_t vm_get_backtrace (uint32_t max_depth);
/**
* @}
* @}