LibJS: Add alternative source-to-bytecode pipeline in Rust

Implement a complete Rust reimplementation of the LibJS frontend:
lexer, parser, AST, scope collector, and bytecode code generator.

The Rust pipeline is built via Corrosion (CMake-Cargo bridge) and
linked into LibJS as a static library. It is gated behind a build
flag (ENABLE_RUST, on by default except on Windows) and two runtime
environment variables:

- LIBJS_CPP: Use the C++ pipeline instead of Rust
- LIBJS_COMPARE_PIPELINES=1: Run both pipelines in lockstep,
  aborting on any difference in AST or bytecode generated.

The C++ side communicates with Rust through a C FFI layer
(RustIntegration.cpp/h) that passes source text to Rust and receives
a populated Executable back via a BytecodeFactory interface.
This commit is contained in:
Andreas Kling
2026-02-23 11:50:46 +01:00
committed by Andreas Kling
parent 8bf1d749a1
commit 6cdfbd01a6
Notes: github-actions[bot] 2026-02-24 08:41:00 +00:00
43 changed files with 28402 additions and 148 deletions

View File

@@ -50,9 +50,11 @@ class FunctionNode;
class JS_API SharedFunctionInstanceData final : public GC::Cell {
GC_CELL(SharedFunctionInstanceData, GC::Cell);
GC_DECLARE_ALLOCATOR(SharedFunctionInstanceData);
static constexpr bool OVERRIDES_FINALIZE = true;
public:
virtual ~SharedFunctionInstanceData() override;
virtual void finalize() override;
static GC::Ref<SharedFunctionInstanceData> create_for_function_node(VM&, FunctionNode const&);
static GC::Ref<SharedFunctionInstanceData> create_for_function_node(VM&, FunctionNode const&, Utf16FlyString name);
@@ -70,6 +72,21 @@ public:
FunctionParsingInsights const&,
Vector<LocalVariable> local_variables_names);
// NB: Constructor for the Rust pipeline. Takes pre-computed metadata
// instead of a C++ AST. FDI fields are populated later during
// lazy compilation by rust_compile_function.
SharedFunctionInstanceData(
VM& vm,
FunctionKind,
Utf16FlyString name,
i32 function_length,
u32 formal_parameter_count,
bool strict,
bool is_arrow_function,
bool has_simple_parameter_list,
Vector<Utf16FlyString> parameter_names_for_mapped_arguments,
void* rust_function_ast);
mutable GC::Ptr<Bytecode::Executable> m_executable;
RefPtr<FunctionParameters const> m_formal_parameters; // [[FormalParameters]]
@@ -113,7 +130,7 @@ public:
No,
Yes,
};
HashMap<Utf16FlyString, ParameterIsLocal> m_parameter_names;
OrderedHashMap<Utf16FlyString, ParameterIsLocal> m_parameter_names;
struct FunctionToInitialize {
GC::Ref<SharedFunctionInstanceData> shared_data;
Utf16FlyString name;
@@ -142,6 +159,11 @@ public:
ConstructorKind m_constructor_kind : 1 { ConstructorKind::Base }; // [[ConstructorKind]]
bool m_is_class_constructor : 1 { false }; // [[IsClassConstructor]]
// NB: When non-null, points to a Rust Box<FunctionData> used for
// lazy compilation through the Rust pipeline.
void* m_rust_function_ast { nullptr };
bool m_use_rust_compilation { false };
void clear_compile_inputs();
private: