diff --git a/Libraries/LibJS/Bytecode/AsmInterpreter/AsmInterpreter.cpp b/Libraries/LibJS/Bytecode/AsmInterpreter/AsmInterpreter.cpp deleted file mode 100644 index 921b063e34..0000000000 --- a/Libraries/LibJS/Bytecode/AsmInterpreter/AsmInterpreter.cpp +++ /dev/null @@ -1,29 +0,0 @@ -/* - * Copyright (c) 2026, the Ladybird developers. - * - * SPDX-License-Identifier: BSD-2-Clause - */ - -#include -#include -#include -#include - -extern "C" void asm_register_slow_path_stats(); -namespace JS::Bytecode { - -// Defined in generated assembly (asmint_x86_64.S or asmint_aarch64.S) -extern "C" void asm_interpreter_entry(u8 const* bytecode, u32 entry_point, Value* values, VM* vm); - -void AsmInterpreter::run(VM& vm, size_t entry_point) -{ - asm_register_slow_path_stats(); - - auto& context = vm.running_execution_context(); - auto* bytecode = context.executable->bytecode.data(); - auto* values = context.registers_and_constants_and_locals_and_arguments_span().data(); - - asm_interpreter_entry(bytecode, static_cast(entry_point), values, &vm); -} - -} diff --git a/Libraries/LibJS/Bytecode/AsmInterpreter/AsmInterpreter.h b/Libraries/LibJS/Bytecode/AsmInterpreter/AsmInterpreter.h deleted file mode 100644 index 2c17c6d080..0000000000 --- a/Libraries/LibJS/Bytecode/AsmInterpreter/AsmInterpreter.h +++ /dev/null @@ -1,22 +0,0 @@ -/* - * Copyright (c) 2026, the Ladybird developers. - * - * SPDX-License-Identifier: BSD-2-Clause - */ - -#pragma once - -#include - -namespace JS { - -class VM; -namespace Bytecode { - -class AsmInterpreter { -public: - static void run(VM&, size_t entry_point); -}; - -} -} diff --git a/Libraries/LibJS/Bytecode/AsmInterpreter/AsmSlowPaths.cpp b/Libraries/LibJS/Bytecode/AsmInterpreter/AsmSlowPaths.cpp index 707cd4488c..8e92f5a63a 100644 --- a/Libraries/LibJS/Bytecode/AsmInterpreter/AsmSlowPaths.cpp +++ b/Libraries/LibJS/Bytecode/AsmInterpreter/AsmSlowPaths.cpp @@ -5,7 +5,7 @@ */ #include -#include +#include #include #include #include @@ -1534,7 +1534,10 @@ NEVER_INLINE static ThrowCompletionOr execute_asm_call( auto* callee_context = stack.allocate(registers_and_locals_count, constants, max(arguments.size(), argument_count)); if (!callee_context) [[unlikely]] return vm.throw_completion(ErrorType::CallStackSizeExceeded); - ScopeGuard deallocate_guard = [&stack, stack_mark] { stack.deallocate(stack_mark); }; + ScopeGuard deallocate_guard = [&stack, stack_mark] { + if (stack.top() > stack_mark) + stack.deallocate(stack_mark); + }; auto* callee_context_argument_values = callee_context->arguments_data(); auto const callee_context_argument_count = callee_context->argument_count; @@ -1652,7 +1655,10 @@ static ThrowCompletionOr call_with_argument_array( auto* callee_context = stack.allocate(registers_and_locals_count, constants, max(argument_array_length, argument_count)); if (!callee_context) [[unlikely]] return vm.throw_completion(ErrorType::CallStackSizeExceeded); - ScopeGuard deallocate_guard = [&stack, stack_mark] { stack.deallocate(stack_mark); }; + ScopeGuard deallocate_guard = [&stack, stack_mark] { + if (stack.top() > stack_mark) + stack.deallocate(stack_mark); + }; auto* callee_context_argument_values = callee_context->arguments_data(); auto const callee_context_argument_count = callee_context->argument_count; @@ -1977,7 +1983,10 @@ i64 asm_slow_path_super_call_with_argument_array(VM* vm, u32 pc) auto completion = vm->throw_completion(ErrorType::CallStackSizeExceeded); return handle_asm_exception(*vm, pc, completion.value()); } - ScopeGuard deallocate_guard = [&stack, stack_mark] { stack.deallocate(stack_mark); }; + ScopeGuard deallocate_guard = [&stack, stack_mark] { + if (stack.top() > stack_mark) + stack.deallocate(stack_mark); + }; auto* callee_context_argument_values = callee_context->arguments_data(); auto const callee_context_argument_count = callee_context->argument_count; diff --git a/Libraries/LibJS/Bytecode/AsmInterpreter/asmint.asm b/Libraries/LibJS/Bytecode/AsmInterpreter/asmint.asm index 06996ac8f2..751aeb04c9 100644 --- a/Libraries/LibJS/Bytecode/AsmInterpreter/asmint.asm +++ b/Libraries/LibJS/Bytecode/AsmInterpreter/asmint.asm @@ -2738,7 +2738,7 @@ handler Call # The native threw. Hand the thrown Value off to a C++ helper, which # unwinds the callee frame off the interpreter stack and calls through # to VM::handle_exception. Return value follows the standard asm - # slow-path convention (see AsmInterpreter.cpp:127): + # slow-path convention: # >= 0 : an enclosing handler was found; the result is the new # program counter to resume at inside the (post-unwind) # running execution context. diff --git a/Libraries/LibJS/Bytecode/Interpreter.cpp b/Libraries/LibJS/Bytecode/Interpreter.cpp index faad5281f7..87b81091c5 100644 --- a/Libraries/LibJS/Bytecode/Interpreter.cpp +++ b/Libraries/LibJS/Bytecode/Interpreter.cpp @@ -6,54 +6,35 @@ */ #include -#include -#include #include -#include -#include -#include -#include -#include -#include #include #include #include #include #include -#include -#include #include -#include -#include -#include -#include -#include -#include #include #include #include #include #include -#include #include #include -#include -#include -#include #include -#include -#include -#include #include #include #include #include -#include namespace JS { using namespace Bytecode; +extern "C" void asm_register_slow_path_stats(); + +// Defined in generated assembly (asmint_x86_64.S or asmint_aarch64.S) +extern "C" void asm_interpreter_entry(u8 const* bytecode, u32 entry_point, Value* values, VM* vm); + bool Bytecode::g_dump_bytecode = false; // 16.1.6 ScriptEvaluation ( scriptRecord ), https://tc39.es/ecma262/#sec-runtime-semantics-scriptevaluation @@ -279,16 +260,6 @@ NEVER_INLINE void VM::unwind_inline_frame_for_exception() m_running_execution_context = caller_frame; } -void VM::run_bytecode(size_t entry_point) -{ - if (vm().interpreter_stack().is_exhausted() || vm().did_reach_stack_space_limit()) [[unlikely]] { - reg(Register::exception()) = vm().throw_completion(ErrorType::CallStackSizeExceeded).value(); - return; - } - - AsmInterpreter::run(*this, entry_point); -} - Utf16FlyString const& VM::get_identifier(IdentifierTableIndex index) const { return m_running_execution_context->executable->get_identifier(index); @@ -327,7 +298,16 @@ ThrowCompletionOr VM::run_executable(ExecutionContext& context, Executabl if (reg(Register::this_value()).is_special_empty_value()) reg(Register::this_value()) = context.this_value.value_or(js_special_empty_value()); - run_bytecode(entry_point); + if (vm().interpreter_stack().is_exhausted() || vm().did_reach_stack_space_limit()) [[unlikely]] { + reg(Register::exception()) = vm().throw_completion(ErrorType::CallStackSizeExceeded).value(); + } else { + asm_register_slow_path_stats(); + + auto* bytecode = executable.bytecode.data(); + auto* values = context.registers_and_constants_and_locals_and_arguments_span().data(); + + asm_interpreter_entry(bytecode, entry_point, values, this); + } dbgln_if(JS_BYTECODE_DEBUG, "VM did run bytecode unit {}", context.executable); diff --git a/Libraries/LibJS/CMakeLists.txt b/Libraries/LibJS/CMakeLists.txt index d8cfef0c29..dc790893e3 100644 --- a/Libraries/LibJS/CMakeLists.txt +++ b/Libraries/LibJS/CMakeLists.txt @@ -1,7 +1,6 @@ include(libjs_generators) set(SOURCES - Bytecode/AsmInterpreter/AsmInterpreter.cpp Bytecode/AsmInterpreter/AsmSlowPaths.cpp Bytecode/BasicBlock.cpp Bytecode/Executable.cpp diff --git a/Libraries/LibJS/Runtime/VM.h b/Libraries/LibJS/Runtime/VM.h index 3fe7ac3fea..cf92a88ad3 100644 --- a/Libraries/LibJS/Runtime/VM.h +++ b/Libraries/LibJS/Runtime/VM.h @@ -513,7 +513,6 @@ private: void set_well_known_symbols(WellKnownSymbols well_known_symbols) { m_well_known_symbols = move(well_known_symbols); } void run_queued_promise_jobs_impl(); - void run_bytecode(size_t entry_point); static VM* s_the;