mirror of
https://github.com/RGBCube/serenity
synced 2025-07-27 00:27:45 +00:00
LibJS: Add file & line number to bytecode VM stack traces :^)
This works by adding source start/end offset to every bytecode instruction. In the future we can make this more efficient by keeping a map of bytecode ranges to source ranges in the Executable instead, but let's just get traces working first. Co-Authored-By: Andrew Kaster <akaster@serenityos.org>
This commit is contained in:
parent
0b66656ca9
commit
1c06111cbd
16 changed files with 157 additions and 26 deletions
|
@ -152,6 +152,7 @@ ThrowCompletionOr<Value> ECMAScriptFunctionObject::internal_call(Value this_argu
|
|||
|
||||
// Non-standard
|
||||
callee_context.arguments.extend(move(arguments_list));
|
||||
callee_context.instruction_stream_iterator = vm.bytecode_interpreter().instruction_stream_iterator();
|
||||
|
||||
// 2. Let calleeContext be PrepareForOrdinaryCall(F, undefined).
|
||||
// NOTE: We throw if the end of the native stack is reached, so unlike in the spec this _does_ need an exception check.
|
||||
|
@ -221,6 +222,7 @@ ThrowCompletionOr<NonnullGCPtr<Object>> ECMAScriptFunctionObject::internal_const
|
|||
|
||||
// Non-standard
|
||||
callee_context.arguments.extend(move(arguments_list));
|
||||
callee_context.instruction_stream_iterator = vm.bytecode_interpreter().instruction_stream_iterator();
|
||||
|
||||
// 4. Let calleeContext be PrepareForOrdinaryCall(F, newTarget).
|
||||
// NOTE: We throw if the end of the native stack is reached, so unlike in the spec this _does_ need an exception check.
|
||||
|
|
|
@ -83,9 +83,12 @@ void Error::populate_stack()
|
|||
if (function_name.is_empty())
|
||||
function_name = "<unknown>"sv;
|
||||
|
||||
UnrealizedSourceRange range = {};
|
||||
if (context->instruction_stream_iterator.has_value())
|
||||
range = context->instruction_stream_iterator->source_range();
|
||||
TracebackFrame frame {
|
||||
.function_name = move(function_name),
|
||||
.source_range_storage = context->source_range,
|
||||
.source_range_storage = range,
|
||||
};
|
||||
|
||||
m_traceback.append(move(frame));
|
||||
|
|
|
@ -33,7 +33,7 @@ ExecutionContext ExecutionContext::copy() const
|
|||
copy.lexical_environment = lexical_environment;
|
||||
copy.variable_environment = variable_environment;
|
||||
copy.private_environment = private_environment;
|
||||
copy.source_range = source_range;
|
||||
copy.instruction_stream_iterator = instruction_stream_iterator;
|
||||
copy.function_name = function_name;
|
||||
copy.this_value = this_value;
|
||||
copy.is_strict_mode = is_strict_mode;
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
|
||||
#include <AK/DeprecatedFlyString.h>
|
||||
#include <AK/WeakPtr.h>
|
||||
#include <LibJS/Bytecode/Instruction.h>
|
||||
#include <LibJS/Forward.h>
|
||||
#include <LibJS/Heap/MarkedVector.h>
|
||||
#include <LibJS/Module.h>
|
||||
|
@ -43,7 +44,7 @@ public:
|
|||
// Non-standard: This points at something that owns this ExecutionContext, in case it needs to be protected from GC.
|
||||
GCPtr<Cell> context_owner;
|
||||
|
||||
UnrealizedSourceRange source_range;
|
||||
Optional<Bytecode::InstructionStreamIterator&> instruction_stream_iterator;
|
||||
DeprecatedFlyString function_name;
|
||||
Value this_value;
|
||||
MarkedVector<Value> arguments;
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
*/
|
||||
|
||||
#include <LibJS/AST.h>
|
||||
#include <LibJS/Bytecode/Interpreter.h>
|
||||
#include <LibJS/Runtime/FunctionEnvironment.h>
|
||||
#include <LibJS/Runtime/GlobalObject.h>
|
||||
#include <LibJS/Runtime/NativeFunction.h>
|
||||
|
@ -128,9 +129,9 @@ ThrowCompletionOr<Value> NativeFunction::internal_call(Value this_argument, Mark
|
|||
// Note: This is already the default value.
|
||||
|
||||
// 8. Perform any necessary implementation-defined initialization of calleeContext.
|
||||
|
||||
callee_context.this_value = this_argument;
|
||||
callee_context.arguments.extend(move(arguments_list));
|
||||
callee_context.instruction_stream_iterator = vm.bytecode_interpreter().instruction_stream_iterator();
|
||||
|
||||
callee_context.lexical_environment = caller_context.lexical_environment;
|
||||
callee_context.variable_environment = caller_context.variable_environment;
|
||||
|
@ -192,8 +193,8 @@ ThrowCompletionOr<NonnullGCPtr<Object>> NativeFunction::internal_construct(Marke
|
|||
// Note: This is already the default value.
|
||||
|
||||
// 8. Perform any necessary implementation-defined initialization of calleeContext.
|
||||
|
||||
callee_context.arguments.extend(move(arguments_list));
|
||||
callee_context.instruction_stream_iterator = vm.bytecode_interpreter().instruction_stream_iterator();
|
||||
|
||||
callee_context.lexical_environment = caller_context.lexical_environment;
|
||||
callee_context.variable_environment = caller_context.variable_environment;
|
||||
|
|
|
@ -746,8 +746,8 @@ void VM::dump_backtrace() const
|
|||
{
|
||||
for (ssize_t i = m_execution_context_stack.size() - 1; i >= 0; --i) {
|
||||
auto& frame = m_execution_context_stack[i];
|
||||
if (frame->source_range.source_code) {
|
||||
auto source_range = frame->source_range.realize();
|
||||
if (frame->instruction_stream_iterator->source_code()) {
|
||||
auto source_range = frame->instruction_stream_iterator->source_range().realize();
|
||||
dbgln("-> {} @ {}:{},{}", frame->function_name, source_range.filename(), source_range.start.line, source_range.start.column);
|
||||
} else {
|
||||
dbgln("-> {}", frame->function_name);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue