From 406d3199d02eed9f969f698d0f0f9ae07dba7253 Mon Sep 17 00:00:00 2001 From: Andreas Kling Date: Sun, 3 Oct 2021 14:52:53 +0200 Subject: [PATCH] LibJS: Add a way to save/restore the entire execution context stack This will be used by LibWeb to squirrel away the stack while performing a microtask checkpoint in some cases. VM will simply consider saved execution context stacks as GC roots as well. --- Userland/Libraries/LibJS/Runtime/VM.cpp | 36 ++++++++++++++++++------- Userland/Libraries/LibJS/Runtime/VM.h | 5 ++++ 2 files changed, 31 insertions(+), 10 deletions(-) diff --git a/Userland/Libraries/LibJS/Runtime/VM.cpp b/Userland/Libraries/LibJS/Runtime/VM.cpp index 4155f90cb9c..52d1472e781 100644 --- a/Userland/Libraries/LibJS/Runtime/VM.cpp +++ b/Userland/Libraries/LibJS/Runtime/VM.cpp @@ -99,17 +99,23 @@ void VM::gather_roots(HashTable& roots) if (m_last_value.is_cell()) roots.set(&m_last_value.as_cell()); - for (auto& execution_context : m_execution_context_stack) { - if (execution_context->this_value.is_cell()) - roots.set(&execution_context->this_value.as_cell()); - roots.set(execution_context->arguments_object); - for (auto& argument : execution_context->arguments) { - if (argument.is_cell()) - roots.set(&argument.as_cell()); + auto gather_roots_from_execution_context_stack = [&roots](Vector const& stack) { + for (auto& execution_context : stack) { + if (execution_context->this_value.is_cell()) + roots.set(&execution_context->this_value.as_cell()); + roots.set(execution_context->arguments_object); + for (auto& argument : execution_context->arguments) { + if (argument.is_cell()) + roots.set(&argument.as_cell()); + } + roots.set(execution_context->lexical_environment); + roots.set(execution_context->variable_environment); } - roots.set(execution_context->lexical_environment); - roots.set(execution_context->variable_environment); - } + }; + + gather_roots_from_execution_context_stack(m_execution_context_stack); + for (auto& saved_stack : m_saved_execution_context_stacks) + gather_roots_from_execution_context_stack(saved_stack); #define __JS_ENUMERATE(SymbolName, snake_name) \ roots.set(well_known_symbol_##snake_name()); @@ -828,4 +834,14 @@ VM::CustomData::~CustomData() { } +void VM::save_execution_context_stack() +{ + m_saved_execution_context_stacks.append(move(m_execution_context_stack)); +} + +void VM::restore_execution_context_stack() +{ + m_execution_context_stack = m_saved_execution_context_stacks.take_last(); +} + } diff --git a/Userland/Libraries/LibJS/Runtime/VM.h b/Userland/Libraries/LibJS/Runtime/VM.h index 0a5cf65985f..ccdd9c2b539 100644 --- a/Userland/Libraries/LibJS/Runtime/VM.h +++ b/Userland/Libraries/LibJS/Runtime/VM.h @@ -280,6 +280,9 @@ public: ThrowCompletionOr named_evaluation_if_anonymous_function(GlobalObject& global_object, ASTNode const& expression, FlyString const& name); + void save_execution_context_stack(); + void restore_execution_context_stack(); + private: explicit VM(OwnPtr); @@ -302,6 +305,8 @@ private: Vector m_execution_context_stack; + Vector> m_saved_execution_context_stacks; + Value m_last_value; ScopeType m_unwind_until { ScopeType::None }; FlyString m_unwind_until_label;