Parcourir la source

LibJS/Bytecode: Display local variable names in bytecode dumps

Instead of displaying locals as "locN", we now show them as "name~N".
This makes it a lot easier to follow bytecode dumps, especially in
longer functions.

Note that we keep displaying the local index, to avoid confusion in case
there are multiple separate locals with the same name in one executable.
Andreas Kling il y a 1 an
Parent
commit
0aa8cb7dac

+ 3 - 0
Userland/Libraries/LibJS/Bytecode/Executable.h

@@ -82,6 +82,9 @@ public:
 
 
     HashMap<size_t, SourceRecord> source_map;
     HashMap<size_t, SourceRecord> source_map;
 
 
+    Vector<DeprecatedFlyString> local_variable_names;
+    size_t local_index_base { 0 };
+
     ByteString const& get_string(StringTableIndex index) const { return string_table->get(index); }
     ByteString const& get_string(StringTableIndex index) const { return string_table->get(index); }
     DeprecatedFlyString const& get_identifier(IdentifierTableIndex index) const { return identifier_table->get(index); }
     DeprecatedFlyString const& get_identifier(IdentifierTableIndex index) const { return identifier_table->get(index); }
 
 

+ 8 - 3
Userland/Libraries/LibJS/Bytecode/Generator.cpp

@@ -199,7 +199,7 @@ CodeGenerationErrorOr<void> Generator::emit_function_declaration_instantiation(E
     return {};
     return {};
 }
 }
 
 
-CodeGenerationErrorOr<NonnullGCPtr<Executable>> Generator::compile(VM& vm, ASTNode const& node, FunctionKind enclosing_function_kind, GCPtr<ECMAScriptFunctionObject const> function, MustPropagateCompletion must_propagate_completion)
+CodeGenerationErrorOr<NonnullGCPtr<Executable>> Generator::compile(VM& vm, ASTNode const& node, FunctionKind enclosing_function_kind, GCPtr<ECMAScriptFunctionObject const> function, MustPropagateCompletion must_propagate_completion, Vector<DeprecatedFlyString> local_variable_names)
 {
 {
     Generator generator(vm, function, must_propagate_completion);
     Generator generator(vm, function, must_propagate_completion);
 
 
@@ -451,6 +451,8 @@ CodeGenerationErrorOr<NonnullGCPtr<Executable>> Generator::compile(VM& vm, ASTNo
     executable->exception_handlers = move(linked_exception_handlers);
     executable->exception_handlers = move(linked_exception_handlers);
     executable->basic_block_start_offsets = move(basic_block_start_offsets);
     executable->basic_block_start_offsets = move(basic_block_start_offsets);
     executable->source_map = move(source_map);
     executable->source_map = move(source_map);
+    executable->local_variable_names = move(local_variable_names);
+    executable->local_index_base = number_of_registers + number_of_constants;
 
 
     generator.m_finished = true;
     generator.m_finished = true;
 
 
@@ -459,12 +461,15 @@ CodeGenerationErrorOr<NonnullGCPtr<Executable>> Generator::compile(VM& vm, ASTNo
 
 
 CodeGenerationErrorOr<NonnullGCPtr<Executable>> Generator::generate_from_ast_node(VM& vm, ASTNode const& node, FunctionKind enclosing_function_kind)
 CodeGenerationErrorOr<NonnullGCPtr<Executable>> Generator::generate_from_ast_node(VM& vm, ASTNode const& node, FunctionKind enclosing_function_kind)
 {
 {
-    return compile(vm, node, enclosing_function_kind, {});
+    Vector<DeprecatedFlyString> local_variable_names;
+    if (is<ScopeNode>(node))
+        local_variable_names = static_cast<ScopeNode const&>(node).local_variables_names();
+    return compile(vm, node, enclosing_function_kind, {}, MustPropagateCompletion::Yes, move(local_variable_names));
 }
 }
 
 
 CodeGenerationErrorOr<NonnullGCPtr<Executable>> Generator::generate_from_function(VM& vm, ECMAScriptFunctionObject const& function)
 CodeGenerationErrorOr<NonnullGCPtr<Executable>> Generator::generate_from_function(VM& vm, ECMAScriptFunctionObject const& function)
 {
 {
-    return compile(vm, function.ecmascript_code(), function.kind(), &function, MustPropagateCompletion::No);
+    return compile(vm, function.ecmascript_code(), function.kind(), &function, MustPropagateCompletion::No, function.local_variables_names());
 }
 }
 
 
 void Generator::grow(size_t additional_size)
 void Generator::grow(size_t additional_size)

+ 1 - 1
Userland/Libraries/LibJS/Bytecode/Generator.h

@@ -343,7 +343,7 @@ public:
 private:
 private:
     VM& m_vm;
     VM& m_vm;
 
 
-    static CodeGenerationErrorOr<NonnullGCPtr<Executable>> compile(VM&, ASTNode const&, FunctionKind, GCPtr<ECMAScriptFunctionObject const>, MustPropagateCompletion = MustPropagateCompletion::Yes);
+    static CodeGenerationErrorOr<NonnullGCPtr<Executable>> compile(VM&, ASTNode const&, FunctionKind, GCPtr<ECMAScriptFunctionObject const>, MustPropagateCompletion, Vector<DeprecatedFlyString> local_variable_names);
 
 
     enum class JumpType {
     enum class JumpType {
         Continue,
         Continue,

+ 4 - 5
Userland/Libraries/LibJS/Bytecode/Interpreter.cpp

@@ -53,8 +53,7 @@ static ByteString format_operand(StringView name, Operand operand, Bytecode::Exe
         }
         }
         break;
         break;
     case Operand::Type::Local:
     case Operand::Type::Local:
-        // FIXME: Show local name.
-        builder.appendff("\033[34mloc{}\033[0m", operand.index());
+        builder.appendff("\033[34m{}~{}\033[0m", executable.local_variable_names[operand.index() - executable.local_index_base], operand.index() - executable.local_index_base);
         break;
         break;
     case Operand::Type::Constant: {
     case Operand::Type::Constant: {
         builder.append("\033[36m"sv);
         builder.append("\033[36m"sv);
@@ -708,9 +707,9 @@ Interpreter::ResultAndReturnRegister Interpreter::run_executable(Executable& exe
     VERIFY(!vm().execution_context_stack().is_empty());
     VERIFY(!vm().execution_context_stack().is_empty());
 
 
     auto& running_execution_context = vm().running_execution_context();
     auto& running_execution_context = vm().running_execution_context();
-    u32 registers_and_contants_count = executable.number_of_registers + executable.constants.size();
-    if (running_execution_context.registers_and_constants_and_locals.size() < registers_and_contants_count)
-        running_execution_context.registers_and_constants_and_locals.resize(registers_and_contants_count);
+    u32 registers_and_constants_and_locals_count = executable.number_of_registers + executable.constants.size() + executable.local_variable_names.size();
+    if (running_execution_context.registers_and_constants_and_locals.size() < registers_and_constants_and_locals_count)
+        running_execution_context.registers_and_constants_and_locals.resize(registers_and_constants_and_locals_count);
 
 
     TemporaryChange restore_running_execution_context { m_running_execution_context, &running_execution_context };
     TemporaryChange restore_running_execution_context { m_running_execution_context, &running_execution_context };
     TemporaryChange restore_arguments { m_arguments, running_execution_context.arguments.span() };
     TemporaryChange restore_arguments { m_arguments, running_execution_context.arguments.span() };