mirror of
https://github.com/zebrajr/ladybird.git
synced 2025-12-06 00:19:53 +01:00
LibJS: Move ExecutionContext members with destructors to "rare data"
This makes ExecutionContext trivially destructible, which means less work to do on function exit.
This commit is contained in:
parent
9ded35f98f
commit
1e0b56586b
|
|
@ -311,8 +311,8 @@ NEVER_INLINE Interpreter::HandleExceptionResponse Interpreter::handle_exception(
|
||||||
auto& handler = handlers->handler_offset;
|
auto& handler = handlers->handler_offset;
|
||||||
auto& finalizer = handlers->finalizer_offset;
|
auto& finalizer = handlers->finalizer_offset;
|
||||||
|
|
||||||
VERIFY(!running_execution_context().unwind_contexts.is_empty());
|
auto& unwind_contexts = running_execution_context().ensure_rare_data()->unwind_contexts;
|
||||||
auto& unwind_context = running_execution_context().unwind_contexts.last();
|
auto& unwind_context = unwind_contexts.last();
|
||||||
VERIFY(unwind_context.executable == ¤t_executable());
|
VERIFY(unwind_context.executable == ¤t_executable());
|
||||||
|
|
||||||
if (handler.has_value()) {
|
if (handler.has_value()) {
|
||||||
|
|
@ -485,8 +485,8 @@ FLATTEN_ON_CLANG void Interpreter::run_bytecode(size_t entry_point)
|
||||||
do_return(saved_return_value());
|
do_return(saved_return_value());
|
||||||
if (auto handlers = executable.exception_handlers_for_offset(program_counter); handlers.has_value()) {
|
if (auto handlers = executable.exception_handlers_for_offset(program_counter); handlers.has_value()) {
|
||||||
if (auto finalizer = handlers.value().finalizer_offset; finalizer.has_value()) {
|
if (auto finalizer = handlers.value().finalizer_offset; finalizer.has_value()) {
|
||||||
VERIFY(!running_execution_context.unwind_contexts.is_empty());
|
auto& unwind_contexts = running_execution_context.ensure_rare_data()->unwind_contexts;
|
||||||
auto& unwind_context = running_execution_context.unwind_contexts.last();
|
auto& unwind_context = unwind_contexts.last();
|
||||||
VERIFY(unwind_context.executable == ¤t_executable());
|
VERIFY(unwind_context.executable == ¤t_executable());
|
||||||
reg(Register::saved_return_value()) = reg(Register::return_value());
|
reg(Register::saved_return_value()) = reg(Register::return_value());
|
||||||
reg(Register::return_value()) = js_special_empty_value();
|
reg(Register::return_value()) = js_special_empty_value();
|
||||||
|
|
@ -497,7 +497,7 @@ FLATTEN_ON_CLANG void Interpreter::run_bytecode(size_t entry_point)
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
auto const old_scheduled_jump = running_execution_context.previously_scheduled_jumps.take_last();
|
auto const old_scheduled_jump = running_execution_context.ensure_rare_data()->previously_scheduled_jumps.take_last();
|
||||||
if (m_running_execution_context->scheduled_jump.has_value()) {
|
if (m_running_execution_context->scheduled_jump.has_value()) {
|
||||||
program_counter = m_running_execution_context->scheduled_jump.value();
|
program_counter = m_running_execution_context->scheduled_jump.value();
|
||||||
m_running_execution_context->scheduled_jump = {};
|
m_running_execution_context->scheduled_jump = {};
|
||||||
|
|
@ -762,23 +762,23 @@ ThrowCompletionOr<Value> Interpreter::run_executable(ExecutionContext& context,
|
||||||
|
|
||||||
void Interpreter::enter_unwind_context()
|
void Interpreter::enter_unwind_context()
|
||||||
{
|
{
|
||||||
running_execution_context().unwind_contexts.empend(
|
running_execution_context().ensure_rare_data()->unwind_contexts.empend(
|
||||||
current_executable(),
|
current_executable(),
|
||||||
running_execution_context().lexical_environment);
|
running_execution_context().lexical_environment);
|
||||||
running_execution_context().previously_scheduled_jumps.append(m_running_execution_context->scheduled_jump);
|
running_execution_context().rare_data()->previously_scheduled_jumps.append(m_running_execution_context->scheduled_jump);
|
||||||
m_running_execution_context->scheduled_jump = {};
|
m_running_execution_context->scheduled_jump = {};
|
||||||
}
|
}
|
||||||
|
|
||||||
void Interpreter::leave_unwind_context()
|
void Interpreter::leave_unwind_context()
|
||||||
{
|
{
|
||||||
running_execution_context().unwind_contexts.take_last();
|
running_execution_context().rare_data()->unwind_contexts.take_last();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Interpreter::catch_exception(Operand dst)
|
void Interpreter::catch_exception(Operand dst)
|
||||||
{
|
{
|
||||||
set(dst, reg(Register::exception()));
|
set(dst, reg(Register::exception()));
|
||||||
reg(Register::exception()) = js_special_empty_value();
|
reg(Register::exception()) = js_special_empty_value();
|
||||||
auto& context = running_execution_context().unwind_contexts.last();
|
auto& context = running_execution_context().rare_data()->unwind_contexts.last();
|
||||||
VERIFY(!context.handler_called);
|
VERIFY(!context.handler_called);
|
||||||
VERIFY(context.executable == ¤t_executable());
|
VERIFY(context.executable == ¤t_executable());
|
||||||
context.handler_called = true;
|
context.handler_called = true;
|
||||||
|
|
@ -787,19 +787,19 @@ void Interpreter::catch_exception(Operand dst)
|
||||||
|
|
||||||
void Interpreter::restore_scheduled_jump()
|
void Interpreter::restore_scheduled_jump()
|
||||||
{
|
{
|
||||||
m_running_execution_context->scheduled_jump = running_execution_context().previously_scheduled_jumps.take_last();
|
m_running_execution_context->scheduled_jump = running_execution_context().rare_data()->previously_scheduled_jumps.take_last();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Interpreter::leave_finally()
|
void Interpreter::leave_finally()
|
||||||
{
|
{
|
||||||
reg(Register::exception()) = js_special_empty_value();
|
reg(Register::exception()) = js_special_empty_value();
|
||||||
m_running_execution_context->scheduled_jump = running_execution_context().previously_scheduled_jumps.take_last();
|
m_running_execution_context->scheduled_jump = running_execution_context().rare_data()->previously_scheduled_jumps.take_last();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Interpreter::enter_object_environment(Object& object)
|
void Interpreter::enter_object_environment(Object& object)
|
||||||
{
|
{
|
||||||
auto& old_environment = running_execution_context().lexical_environment;
|
auto& old_environment = running_execution_context().lexical_environment;
|
||||||
running_execution_context().saved_lexical_environments.append(old_environment);
|
running_execution_context().ensure_rare_data()->saved_lexical_environments.append(old_environment);
|
||||||
running_execution_context().lexical_environment = new_object_environment(object, true, old_environment);
|
running_execution_context().lexical_environment = new_object_environment(object, true, old_environment);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1593,7 +1593,7 @@ inline ThrowCompletionOr<ECMAScriptFunctionObject*> new_class(VM& vm, Value supe
|
||||||
|
|
||||||
// NOTE: NewClass expects classEnv to be active lexical environment
|
// NOTE: NewClass expects classEnv to be active lexical environment
|
||||||
auto* class_environment = vm.lexical_environment();
|
auto* class_environment = vm.lexical_environment();
|
||||||
vm.running_execution_context().lexical_environment = vm.running_execution_context().saved_lexical_environments.take_last();
|
vm.running_execution_context().lexical_environment = vm.running_execution_context().rare_data()->saved_lexical_environments.take_last();
|
||||||
|
|
||||||
Optional<Utf16FlyString> binding_name;
|
Optional<Utf16FlyString> binding_name;
|
||||||
Utf16FlyString class_name;
|
Utf16FlyString class_name;
|
||||||
|
|
@ -2416,7 +2416,7 @@ void CreateLexicalEnvironment::execute_impl(Bytecode::Interpreter& interpreter)
|
||||||
return environment;
|
return environment;
|
||||||
};
|
};
|
||||||
auto& running_execution_context = interpreter.running_execution_context();
|
auto& running_execution_context = interpreter.running_execution_context();
|
||||||
running_execution_context.saved_lexical_environments.append(make_and_swap_envs(running_execution_context.lexical_environment));
|
running_execution_context.ensure_rare_data()->saved_lexical_environments.append(make_and_swap_envs(running_execution_context.lexical_environment));
|
||||||
if (m_dst.has_value())
|
if (m_dst.has_value())
|
||||||
interpreter.set(*m_dst, running_execution_context.lexical_environment);
|
interpreter.set(*m_dst, running_execution_context.lexical_environment);
|
||||||
}
|
}
|
||||||
|
|
@ -3161,7 +3161,7 @@ ThrowCompletionOr<void> ThrowIfTDZ::execute_impl(Bytecode::Interpreter& interpre
|
||||||
void LeaveLexicalEnvironment::execute_impl(Bytecode::Interpreter& interpreter) const
|
void LeaveLexicalEnvironment::execute_impl(Bytecode::Interpreter& interpreter) const
|
||||||
{
|
{
|
||||||
auto& running_execution_context = interpreter.running_execution_context();
|
auto& running_execution_context = interpreter.running_execution_context();
|
||||||
running_execution_context.lexical_environment = running_execution_context.saved_lexical_environments.take_last();
|
running_execution_context.lexical_environment = running_execution_context.rare_data()->saved_lexical_environments.take_last();
|
||||||
}
|
}
|
||||||
|
|
||||||
void LeavePrivateEnvironment::execute_impl(Bytecode::Interpreter& interpreter) const
|
void LeavePrivateEnvironment::execute_impl(Bytecode::Interpreter& interpreter) const
|
||||||
|
|
|
||||||
|
|
@ -15,6 +15,7 @@
|
||||||
namespace JS {
|
namespace JS {
|
||||||
|
|
||||||
GC_DEFINE_ALLOCATOR(CachedSourceRange);
|
GC_DEFINE_ALLOCATOR(CachedSourceRange);
|
||||||
|
GC_DEFINE_ALLOCATOR(ExecutionContextRareData);
|
||||||
|
|
||||||
class ExecutionContextAllocator {
|
class ExecutionContextAllocator {
|
||||||
public:
|
public:
|
||||||
|
|
@ -110,10 +111,6 @@ ExecutionContext::ExecutionContext(u32 registers_and_constants_and_locals_count,
|
||||||
arguments = { registers_and_constants_and_locals_and_arguments + registers_and_constants_and_locals_count, arguments_count };
|
arguments = { registers_and_constants_and_locals_and_arguments + registers_and_constants_and_locals_count, arguments_count };
|
||||||
}
|
}
|
||||||
|
|
||||||
ExecutionContext::~ExecutionContext()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
NonnullOwnPtr<ExecutionContext> ExecutionContext::copy() const
|
NonnullOwnPtr<ExecutionContext> ExecutionContext::copy() const
|
||||||
{
|
{
|
||||||
auto copy = create(registers_and_constants_and_locals_and_arguments_count, arguments.size());
|
auto copy = create(registers_and_constants_and_locals_and_arguments_count, arguments.size());
|
||||||
|
|
@ -127,9 +124,12 @@ NonnullOwnPtr<ExecutionContext> ExecutionContext::copy() const
|
||||||
copy->this_value = this_value;
|
copy->this_value = this_value;
|
||||||
copy->executable = executable;
|
copy->executable = executable;
|
||||||
copy->passed_argument_count = passed_argument_count;
|
copy->passed_argument_count = passed_argument_count;
|
||||||
copy->unwind_contexts = unwind_contexts;
|
if (m_rare_data) {
|
||||||
copy->saved_lexical_environments = saved_lexical_environments;
|
auto copy_rare_data = copy->ensure_rare_data();
|
||||||
copy->previously_scheduled_jumps = previously_scheduled_jumps;
|
copy_rare_data->unwind_contexts = m_rare_data->unwind_contexts;
|
||||||
|
copy_rare_data->saved_lexical_environments = m_rare_data->saved_lexical_environments;
|
||||||
|
copy_rare_data->previously_scheduled_jumps = m_rare_data->previously_scheduled_jumps;
|
||||||
|
}
|
||||||
copy->registers_and_constants_and_locals_and_arguments_count = registers_and_constants_and_locals_and_arguments_count;
|
copy->registers_and_constants_and_locals_and_arguments_count = registers_and_constants_and_locals_and_arguments_count;
|
||||||
for (size_t i = 0; i < registers_and_constants_and_locals_and_arguments_count; ++i)
|
for (size_t i = 0; i < registers_and_constants_and_locals_and_arguments_count; ++i)
|
||||||
copy->registers_and_constants_and_locals_and_arguments()[i] = registers_and_constants_and_locals_and_arguments()[i];
|
copy->registers_and_constants_and_locals_and_arguments()[i] = registers_and_constants_and_locals_and_arguments()[i];
|
||||||
|
|
@ -146,14 +146,11 @@ void ExecutionContext::visit_edges(Cell::Visitor& visitor)
|
||||||
visitor.visit(private_environment);
|
visitor.visit(private_environment);
|
||||||
visitor.visit(context_owner);
|
visitor.visit(context_owner);
|
||||||
visitor.visit(cached_source_range);
|
visitor.visit(cached_source_range);
|
||||||
|
visitor.visit(m_rare_data);
|
||||||
if (this_value.has_value())
|
if (this_value.has_value())
|
||||||
visitor.visit(*this_value);
|
visitor.visit(*this_value);
|
||||||
visitor.visit(executable);
|
visitor.visit(executable);
|
||||||
visitor.visit(registers_and_constants_and_locals_and_arguments_span());
|
visitor.visit(registers_and_constants_and_locals_and_arguments_span());
|
||||||
for (auto& context : unwind_contexts) {
|
|
||||||
visitor.visit(context.lexical_environment);
|
|
||||||
}
|
|
||||||
visitor.visit(saved_lexical_environments);
|
|
||||||
script_or_module.visit(
|
script_or_module.visit(
|
||||||
[](Empty) {},
|
[](Empty) {},
|
||||||
[&](auto& script_or_module) {
|
[&](auto& script_or_module) {
|
||||||
|
|
@ -161,4 +158,21 @@ void ExecutionContext::visit_edges(Cell::Visitor& visitor)
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ExecutionContextRareData::visit_edges(Cell::Visitor& visitor)
|
||||||
|
{
|
||||||
|
Base::visit_edges(visitor);
|
||||||
|
for (auto& context : unwind_contexts) {
|
||||||
|
visitor.visit(context.lexical_environment);
|
||||||
|
}
|
||||||
|
visitor.visit(saved_lexical_environments);
|
||||||
|
}
|
||||||
|
|
||||||
|
GC::Ref<ExecutionContextRareData> ExecutionContext::ensure_rare_data()
|
||||||
|
{
|
||||||
|
if (!m_rare_data) {
|
||||||
|
m_rare_data = executable->heap().allocate<ExecutionContextRareData>();
|
||||||
|
}
|
||||||
|
return *m_rare_data;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -36,12 +36,25 @@ public:
|
||||||
Variant<UnrealizedSourceRange, SourceRange> source_range;
|
Variant<UnrealizedSourceRange, SourceRange> source_range;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class ExecutionContextRareData final : public GC::Cell {
|
||||||
|
GC_CELL(ExecutionContextRareData, GC::Cell);
|
||||||
|
GC_DECLARE_ALLOCATOR(ExecutionContextRareData);
|
||||||
|
|
||||||
|
public:
|
||||||
|
Vector<Bytecode::UnwindInfo> unwind_contexts;
|
||||||
|
Vector<Optional<size_t>> previously_scheduled_jumps;
|
||||||
|
Vector<GC::Ptr<Environment>> saved_lexical_environments;
|
||||||
|
|
||||||
|
private:
|
||||||
|
virtual void visit_edges(Cell::Visitor&) override;
|
||||||
|
};
|
||||||
|
|
||||||
// 9.4 Execution Contexts, https://tc39.es/ecma262/#sec-execution-contexts
|
// 9.4 Execution Contexts, https://tc39.es/ecma262/#sec-execution-contexts
|
||||||
struct JS_API ExecutionContext {
|
struct JS_API ExecutionContext {
|
||||||
static NonnullOwnPtr<ExecutionContext> create(u32 registers_and_constants_and_locals_count, u32 arguments_count);
|
static NonnullOwnPtr<ExecutionContext> create(u32 registers_and_constants_and_locals_count, u32 arguments_count);
|
||||||
[[nodiscard]] NonnullOwnPtr<ExecutionContext> copy() const;
|
[[nodiscard]] NonnullOwnPtr<ExecutionContext> copy() const;
|
||||||
|
|
||||||
~ExecutionContext();
|
~ExecutionContext() = default;
|
||||||
|
|
||||||
void visit_edges(Cell::Visitor&);
|
void visit_edges(Cell::Visitor&);
|
||||||
|
|
||||||
|
|
@ -51,6 +64,9 @@ private:
|
||||||
public:
|
public:
|
||||||
ExecutionContext(u32 registers_and_constants_and_locals_count, u32 arguments_count);
|
ExecutionContext(u32 registers_and_constants_and_locals_count, u32 arguments_count);
|
||||||
|
|
||||||
|
GC::Ptr<ExecutionContextRareData> rare_data() const { return m_rare_data; }
|
||||||
|
GC::Ref<ExecutionContextRareData> ensure_rare_data();
|
||||||
|
|
||||||
void operator delete(void* ptr);
|
void operator delete(void* ptr);
|
||||||
|
|
||||||
GC::Ptr<FunctionObject> function; // [[Function]]
|
GC::Ptr<FunctionObject> function; // [[Function]]
|
||||||
|
|
@ -105,9 +121,9 @@ public:
|
||||||
|
|
||||||
Span<Value> arguments;
|
Span<Value> arguments;
|
||||||
|
|
||||||
Vector<Bytecode::UnwindInfo> unwind_contexts;
|
// NOTE: Rarely used data members go here to keep the size of ExecutionContext down,
|
||||||
Vector<Optional<size_t>> previously_scheduled_jumps;
|
// and to avoid needing an ExecutionContext destructor in the common case.
|
||||||
Vector<GC::Ptr<Environment>> saved_lexical_environments;
|
GC::Ptr<ExecutionContextRareData> m_rare_data;
|
||||||
|
|
||||||
u32 passed_argument_count { 0 };
|
u32 passed_argument_count { 0 };
|
||||||
|
|
||||||
|
|
@ -122,21 +138,19 @@ private:
|
||||||
u32 registers_and_constants_and_locals_and_arguments_count { 0 };
|
u32 registers_and_constants_and_locals_and_arguments_count { 0 };
|
||||||
};
|
};
|
||||||
|
|
||||||
#define ALLOCATE_EXECUTION_CONTEXT_ON_NATIVE_STACK_WITHOUT_CLEARING_ARGS(execution_context, \
|
static_assert(IsTriviallyDestructible<ExecutionContext>);
|
||||||
registers_and_constants_and_locals_count, \
|
|
||||||
arguments_count) \
|
#define ALLOCATE_EXECUTION_CONTEXT_ON_NATIVE_STACK_WITHOUT_CLEARING_ARGS(execution_context, \
|
||||||
auto execution_context_size = sizeof(JS::ExecutionContext) \
|
registers_and_constants_and_locals_count, \
|
||||||
+ (((registers_and_constants_and_locals_count) + (arguments_count)) \
|
arguments_count) \
|
||||||
* sizeof(JS::Value)); \
|
auto execution_context_size = sizeof(JS::ExecutionContext) \
|
||||||
\
|
+ (((registers_and_constants_and_locals_count) + (arguments_count)) \
|
||||||
void* execution_context_memory = alloca(execution_context_size); \
|
* sizeof(JS::Value)); \
|
||||||
\
|
\
|
||||||
execution_context = new (execution_context_memory) \
|
void* execution_context_memory = alloca(execution_context_size); \
|
||||||
JS::ExecutionContext((registers_and_constants_and_locals_count), (arguments_count)); \
|
\
|
||||||
\
|
execution_context = new (execution_context_memory) \
|
||||||
ScopeGuard run_execution_context_destructor([execution_context] { \
|
JS::ExecutionContext((registers_and_constants_and_locals_count), (arguments_count));
|
||||||
execution_context->~ExecutionContext(); \
|
|
||||||
})
|
|
||||||
|
|
||||||
#define ALLOCATE_EXECUTION_CONTEXT_ON_NATIVE_STACK(execution_context, registers_and_constants_and_locals_count, \
|
#define ALLOCATE_EXECUTION_CONTEXT_ON_NATIVE_STACK(execution_context, registers_and_constants_and_locals_count, \
|
||||||
arguments_count) \
|
arguments_count) \
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user