Files
ladybird/Libraries/LibJS/Runtime/InterpreterStack.h
Andreas Kling 0c5e4ebc18 LibJS: Add InterpreterStack bump allocator for execution contexts
Add a managed bump allocator backed by an 8 MB mmap region to replace
alloca-based execution context allocation. Pages are committed on
demand by the OS, so only the memory actually touched is resident.

The InterpreterStack is stored as a member of VM and provides simple
LIFO allocation and deallocation of ExecutionContext frames.
2026-03-04 18:53:12 +01:00

68 lines
1.7 KiB
C++

/*
* Copyright (c) 2026, the Ladybird developers.
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#pragma once
#include <AK/Noncopyable.h>
#include <AK/Platform.h>
#include <AK/Types.h>
#include <LibJS/Runtime/ExecutionContext.h>
namespace JS {
class InterpreterStack {
AK_MAKE_NONCOPYABLE(InterpreterStack);
AK_MAKE_NONMOVABLE(InterpreterStack);
public:
static constexpr size_t stack_size = 8 * MiB;
InterpreterStack();
~InterpreterStack();
[[nodiscard]] ALWAYS_INLINE void* top() const { return m_top; }
[[nodiscard]] ALWAYS_INLINE ExecutionContext* allocate(u32 registers_and_locals_count, u32 constants_count, u32 arguments_count)
{
auto tail_count = registers_and_locals_count + constants_count + arguments_count;
auto size = sizeof(ExecutionContext) + tail_count * sizeof(Value);
// Align up to alignof(ExecutionContext).
size = (size + alignof(ExecutionContext) - 1) & ~(alignof(ExecutionContext) - 1);
auto* new_top = static_cast<u8*>(m_top) + size;
if (new_top > m_limit) [[unlikely]]
return nullptr;
auto* result = new (m_top) ExecutionContext(registers_and_locals_count, constants_count, arguments_count);
m_top = new_top;
return result;
}
ALWAYS_INLINE void deallocate(void* mark)
{
VERIFY(mark >= m_base && mark <= m_top);
m_top = mark;
}
[[nodiscard]] ALWAYS_INLINE bool is_exhausted() const
{
return m_top >= m_limit;
}
[[nodiscard]] ALWAYS_INLINE size_t size_remaining() const
{
return static_cast<u8*>(m_limit) - static_cast<u8*>(m_top);
}
private:
void* m_base { nullptr };
void* m_top { nullptr };
void* m_limit { nullptr };
};
}