Introduce ExecutableBacking as the state machine for how a Script or SourceTextModule executable is backed. Keep construction and transitions private to the owning record types so transient cache-generation states cannot be created directly.
130 lines
3.3 KiB
C++
130 lines
3.3 KiB
C++
/*
|
|
* Copyright (c) 2026-present, the Ladybird developers.
|
|
*
|
|
* SPDX-License-Identifier: BSD-2-Clause
|
|
*/
|
|
|
|
#pragma once
|
|
|
|
#include <AK/Assertions.h>
|
|
|
|
namespace JS {
|
|
|
|
class Script;
|
|
class SourceTextModule;
|
|
|
|
// Tracks how a Script or SourceTextModule executable is backed. The owner keeps
|
|
// the concrete executable and shared-function-data storage; this object only
|
|
// owns backing state and transition rules.
|
|
class ExecutableBacking {
|
|
private:
|
|
enum class State {
|
|
Source,
|
|
HeapBytecode,
|
|
GeneratingFreshCacheFromSource,
|
|
GeneratingFreshCacheFromHeapBytecode,
|
|
MappedBytecodeCache,
|
|
};
|
|
|
|
explicit ExecutableBacking(State state)
|
|
: m_state(state)
|
|
{
|
|
}
|
|
|
|
static ExecutableBacking source()
|
|
{
|
|
return ExecutableBacking(State::Source);
|
|
}
|
|
|
|
static ExecutableBacking heap_bytecode()
|
|
{
|
|
return ExecutableBacking(State::HeapBytecode);
|
|
}
|
|
|
|
static ExecutableBacking mapped_bytecode_cache()
|
|
{
|
|
return ExecutableBacking(State::MappedBytecodeCache);
|
|
}
|
|
|
|
public:
|
|
[[nodiscard]] bool is_source() const
|
|
{
|
|
return m_state == State::Source
|
|
|| m_state == State::GeneratingFreshCacheFromSource;
|
|
}
|
|
|
|
[[nodiscard]] bool is_heap_bytecode() const
|
|
{
|
|
return m_state == State::HeapBytecode
|
|
|| m_state == State::GeneratingFreshCacheFromHeapBytecode;
|
|
}
|
|
|
|
[[nodiscard]] bool is_mapped_bytecode_cache() const { return m_state == State::MappedBytecodeCache; }
|
|
|
|
private:
|
|
friend class Script;
|
|
friend class SourceTextModule;
|
|
|
|
[[nodiscard]] bool can_generate_bytecode_cache() const
|
|
{
|
|
return m_state == State::Source
|
|
|| m_state == State::HeapBytecode;
|
|
}
|
|
|
|
[[nodiscard]] bool can_install_generated_bytecode_cache() const { return is_generating_bytecode_cache(); }
|
|
|
|
[[nodiscard]] bool requires_non_bytecode_cache_compile_inputs_to_be_cleared() const
|
|
{
|
|
return is_mapped_bytecode_cache();
|
|
}
|
|
|
|
[[nodiscard]] bool is_generating_bytecode_cache() const
|
|
{
|
|
return m_state == State::GeneratingFreshCacheFromSource
|
|
|| m_state == State::GeneratingFreshCacheFromHeapBytecode;
|
|
}
|
|
|
|
void begin_bytecode_cache_generation()
|
|
{
|
|
switch (m_state) {
|
|
case State::Source:
|
|
m_state = State::GeneratingFreshCacheFromSource;
|
|
return;
|
|
case State::HeapBytecode:
|
|
m_state = State::GeneratingFreshCacheFromHeapBytecode;
|
|
return;
|
|
case State::GeneratingFreshCacheFromSource:
|
|
case State::GeneratingFreshCacheFromHeapBytecode:
|
|
case State::MappedBytecodeCache:
|
|
VERIFY_NOT_REACHED();
|
|
}
|
|
VERIFY_NOT_REACHED();
|
|
}
|
|
|
|
void finish_bytecode_cache_generation_without_install()
|
|
{
|
|
switch (m_state) {
|
|
case State::GeneratingFreshCacheFromSource:
|
|
m_state = State::Source;
|
|
return;
|
|
case State::GeneratingFreshCacheFromHeapBytecode:
|
|
m_state = State::HeapBytecode;
|
|
return;
|
|
case State::Source:
|
|
case State::HeapBytecode:
|
|
case State::MappedBytecodeCache:
|
|
VERIFY_NOT_REACHED();
|
|
}
|
|
VERIFY_NOT_REACHED();
|
|
}
|
|
|
|
void finish_bytecode_cache_install()
|
|
{
|
|
VERIFY(!is_mapped_bytecode_cache());
|
|
m_state = State::MappedBytecodeCache;
|
|
}
|
|
|
|
State m_state { State::Source };
|
|
};
|
|
|
|
}
|