| 
									
										
										
										
											2022-12-11 18:16:15 +00:00
										 |  |  | /*
 | 
					
						
							| 
									
										
										
										
											2024-10-04 13:19:50 +02:00
										 |  |  |  * Copyright (c) 2020-2024, Andreas Kling <andreas@ladybird.org> | 
					
						
							| 
									
										
										
										
											2022-12-11 18:16:15 +00:00
										 |  |  |  * Copyright (c) 2020-2021, Linus Groh <linusg@serenityos.org> | 
					
						
							|  |  |  |  * Copyright (c) 2022, Luke Wilde <lukew@serenityos.org> | 
					
						
							| 
									
										
										
										
											2025-04-23 19:44:54 +02:00
										 |  |  |  * Copyright (c) 2024-2025, Aliaksandr Kalenik <kalenik.aliaksandr@gmail.com> | 
					
						
							| 
									
										
										
										
											2022-12-11 18:16:15 +00:00
										 |  |  |  * | 
					
						
							|  |  |  |  * SPDX-License-Identifier: BSD-2-Clause | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-11-15 04:01:23 +13:00
										 |  |  | #include <LibGC/Heap.h>
 | 
					
						
							| 
									
										
										
										
											2023-11-27 13:23:59 +01:00
										 |  |  | #include <LibJS/Bytecode/Executable.h>
 | 
					
						
							| 
									
										
										
										
											2022-12-11 18:16:15 +00:00
										 |  |  | #include <LibJS/Runtime/ExecutionContext.h>
 | 
					
						
							| 
									
										
										
										
											2022-12-11 18:24:33 +00:00
										 |  |  | #include <LibJS/Runtime/FunctionObject.h>
 | 
					
						
							| 
									
										
										
										
											2022-12-11 18:16:15 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | namespace JS { | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-05-23 11:10:23 +01:00
										 |  |  | class ExecutionContextAllocator { | 
					
						
							|  |  |  | public: | 
					
						
							| 
									
										
										
										
											2025-04-23 19:44:54 +02:00
										 |  |  |     NonnullOwnPtr<ExecutionContext> allocate(u32 registers_and_constants_and_locals_count, u32 arguments_count) | 
					
						
							| 
									
										
										
										
											2024-05-23 11:10:23 +01:00
										 |  |  |     { | 
					
						
							| 
									
										
										
										
											2025-04-23 19:44:54 +02:00
										 |  |  |         auto tail_size = registers_and_constants_and_locals_count + arguments_count; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         void* slot = nullptr; | 
					
						
							|  |  |  |         if (tail_size <= 4 && !m_execution_contexts_with_4_tail.is_empty()) { | 
					
						
							|  |  |  |             slot = m_execution_contexts_with_4_tail.take_last(); | 
					
						
							|  |  |  |         } else if (tail_size <= 16 && !m_execution_contexts_with_16_tail.is_empty()) { | 
					
						
							|  |  |  |             slot = m_execution_contexts_with_16_tail.take_last(); | 
					
						
							|  |  |  |         } else if (tail_size <= 64 && !m_execution_contexts_with_64_tail.is_empty()) { | 
					
						
							|  |  |  |             slot = m_execution_contexts_with_64_tail.take_last(); | 
					
						
							|  |  |  |         } else if (tail_size <= 128 && !m_execution_contexts_with_128_tail.is_empty()) { | 
					
						
							|  |  |  |             slot = m_execution_contexts_with_128_tail.take_last(); | 
					
						
							|  |  |  |         } else if (tail_size <= 256 && !m_execution_contexts_with_256_tail.is_empty()) { | 
					
						
							|  |  |  |             slot = m_execution_contexts_with_256_tail.take_last(); | 
					
						
							|  |  |  |         } else if (tail_size <= 512 && !m_execution_contexts_with_512_tail.is_empty()) { | 
					
						
							|  |  |  |             slot = m_execution_contexts_with_512_tail.take_last(); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if (slot) { | 
					
						
							|  |  |  |             return adopt_own(*new (slot) ExecutionContext(registers_and_constants_and_locals_count, arguments_count)); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         auto tail_allocation_size = [tail_size] -> u32 { | 
					
						
							|  |  |  |             if (tail_size <= 4) | 
					
						
							|  |  |  |                 return 4; | 
					
						
							|  |  |  |             if (tail_size <= 16) | 
					
						
							|  |  |  |                 return 16; | 
					
						
							|  |  |  |             if (tail_size <= 64) | 
					
						
							|  |  |  |                 return 64; | 
					
						
							|  |  |  |             if (tail_size <= 128) | 
					
						
							|  |  |  |                 return 128; | 
					
						
							|  |  |  |             if (tail_size <= 256) | 
					
						
							|  |  |  |                 return 256; | 
					
						
							|  |  |  |             if (tail_size <= 512) | 
					
						
							|  |  |  |                 return 512; | 
					
						
							|  |  |  |             return tail_size; | 
					
						
							|  |  |  |         }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         auto* memory = ::operator new(sizeof(ExecutionContext) + tail_allocation_size() * sizeof(Value)); | 
					
						
							|  |  |  |         return adopt_own(*::new (memory) ExecutionContext(registers_and_constants_and_locals_count, arguments_count)); | 
					
						
							| 
									
										
										
										
											2024-05-23 11:10:23 +01:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2025-04-23 19:44:54 +02:00
										 |  |  |     void deallocate(void* ptr, u32 tail_size) | 
					
						
							| 
									
										
										
										
											2024-05-23 11:10:23 +01:00
										 |  |  |     { | 
					
						
							| 
									
										
										
										
											2025-04-23 19:44:54 +02:00
										 |  |  |         if (tail_size <= 4) { | 
					
						
							|  |  |  |             m_execution_contexts_with_4_tail.append(ptr); | 
					
						
							|  |  |  |         } else if (tail_size <= 16) { | 
					
						
							|  |  |  |             m_execution_contexts_with_16_tail.append(ptr); | 
					
						
							|  |  |  |         } else if (tail_size <= 64) { | 
					
						
							|  |  |  |             m_execution_contexts_with_64_tail.append(ptr); | 
					
						
							|  |  |  |         } else if (tail_size <= 128) { | 
					
						
							|  |  |  |             m_execution_contexts_with_128_tail.append(ptr); | 
					
						
							|  |  |  |         } else if (tail_size <= 256) { | 
					
						
							|  |  |  |             m_execution_contexts_with_256_tail.append(ptr); | 
					
						
							|  |  |  |         } else if (tail_size <= 512) { | 
					
						
							|  |  |  |             m_execution_contexts_with_512_tail.append(ptr); | 
					
						
							|  |  |  |         } else { | 
					
						
							|  |  |  |             ::operator delete(ptr); | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2024-05-23 11:10:23 +01:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | private: | 
					
						
							| 
									
										
										
										
											2025-04-23 19:44:54 +02:00
										 |  |  |     Vector<void*> m_execution_contexts_with_4_tail; | 
					
						
							|  |  |  |     Vector<void*> m_execution_contexts_with_16_tail; | 
					
						
							|  |  |  |     Vector<void*> m_execution_contexts_with_64_tail; | 
					
						
							|  |  |  |     Vector<void*> m_execution_contexts_with_128_tail; | 
					
						
							|  |  |  |     Vector<void*> m_execution_contexts_with_256_tail; | 
					
						
							|  |  |  |     Vector<void*> m_execution_contexts_with_512_tail; | 
					
						
							| 
									
										
										
										
											2024-05-23 11:10:23 +01:00
										 |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static NeverDestroyed<ExecutionContextAllocator> s_execution_context_allocator; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-04-23 00:57:07 +02:00
										 |  |  | NonnullOwnPtr<ExecutionContext> ExecutionContext::create(u32 registers_and_constants_and_locals_count, u32 arguments_count) | 
					
						
							| 
									
										
										
										
											2022-12-11 18:16:15 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2025-04-23 19:44:54 +02:00
										 |  |  |     return s_execution_context_allocator->allocate(registers_and_constants_and_locals_count, arguments_count); | 
					
						
							| 
									
										
										
										
											2024-05-23 11:10:23 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void ExecutionContext::operator delete(void* ptr) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2025-04-23 19:44:54 +02:00
										 |  |  |     auto const* execution_context = static_cast<ExecutionContext const*>(ptr); | 
					
						
							|  |  |  |     s_execution_context_allocator->deallocate(ptr, execution_context->registers_and_constants_and_locals_and_arguments_count); | 
					
						
							| 
									
										
										
										
											2022-12-11 18:16:15 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-04-23 19:44:54 +02:00
										 |  |  | ExecutionContext::ExecutionContext(u32 registers_and_constants_and_locals_count, u32 arguments_count) | 
					
						
							| 
									
										
										
										
											2022-12-11 18:16:15 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2025-04-23 19:44:54 +02:00
										 |  |  |     registers_and_constants_and_locals_and_arguments_count = registers_and_constants_and_locals_count + arguments_count; | 
					
						
							|  |  |  |     arguments_offset = registers_and_constants_and_locals_count; | 
					
						
							|  |  |  |     auto* registers_and_constants_and_locals_and_arguments = this->registers_and_constants_and_locals_and_arguments(); | 
					
						
							|  |  |  |     for (size_t i = 0; i < registers_and_constants_and_locals_count; ++i) | 
					
						
							|  |  |  |         registers_and_constants_and_locals_and_arguments[i] = js_special_empty_value(); | 
					
						
							| 
									
										
										
										
											2025-04-24 01:37:30 +02:00
										 |  |  |     arguments = { registers_and_constants_and_locals_and_arguments + arguments_offset, registers_and_constants_and_locals_and_arguments_count - arguments_offset }; | 
					
						
							| 
									
										
										
										
											2022-12-11 18:16:15 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-11-27 16:45:45 +01:00
										 |  |  | ExecutionContext::~ExecutionContext() | 
					
						
							| 
									
										
										
										
											2022-12-11 18:16:15 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2023-11-27 16:45:45 +01:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2022-12-11 18:16:15 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-11-27 16:45:45 +01:00
										 |  |  | NonnullOwnPtr<ExecutionContext> ExecutionContext::copy() const | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2025-04-24 01:37:30 +02:00
										 |  |  |     auto copy = create(registers_and_constants_and_locals_and_arguments_count, arguments.size()); | 
					
						
							| 
									
										
										
										
											2023-11-27 16:45:45 +01:00
										 |  |  |     copy->function = function; | 
					
						
							|  |  |  |     copy->realm = realm; | 
					
						
							|  |  |  |     copy->script_or_module = script_or_module; | 
					
						
							|  |  |  |     copy->lexical_environment = lexical_environment; | 
					
						
							|  |  |  |     copy->variable_environment = variable_environment; | 
					
						
							|  |  |  |     copy->private_environment = private_environment; | 
					
						
							| 
									
										
										
										
											2024-05-06 06:44:08 +02:00
										 |  |  |     copy->program_counter = program_counter; | 
					
						
							| 
									
										
										
										
											2023-11-27 16:45:45 +01:00
										 |  |  |     copy->function_name = function_name; | 
					
						
							|  |  |  |     copy->this_value = this_value; | 
					
						
							|  |  |  |     copy->is_strict_mode = is_strict_mode; | 
					
						
							|  |  |  |     copy->executable = executable; | 
					
						
							| 
									
										
										
										
											2025-04-23 00:57:07 +02:00
										 |  |  |     copy->arguments_offset = arguments_offset; | 
					
						
							| 
									
										
										
										
											2024-05-05 22:06:55 +02:00
										 |  |  |     copy->passed_argument_count = passed_argument_count; | 
					
						
							| 
									
										
										
										
											2024-05-01 19:33:49 +02:00
										 |  |  |     copy->unwind_contexts = unwind_contexts; | 
					
						
							|  |  |  |     copy->saved_lexical_environments = saved_lexical_environments; | 
					
						
							|  |  |  |     copy->previously_scheduled_jumps = previously_scheduled_jumps; | 
					
						
							| 
									
										
										
										
											2025-04-23 19:44:54 +02:00
										 |  |  |     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) | 
					
						
							|  |  |  |         copy->registers_and_constants_and_locals_and_arguments()[i] = registers_and_constants_and_locals_and_arguments()[i]; | 
					
						
							| 
									
										
										
										
											2025-04-24 01:37:30 +02:00
										 |  |  |     copy->arguments = { copy->registers_and_constants_and_locals_and_arguments() + copy->arguments_offset, arguments.size() }; | 
					
						
							| 
									
										
										
										
											2022-12-11 18:16:15 +00:00
										 |  |  |     return copy; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-12-11 18:24:33 +00:00
										 |  |  | void ExecutionContext::visit_edges(Cell::Visitor& visitor) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     visitor.visit(function); | 
					
						
							|  |  |  |     visitor.visit(realm); | 
					
						
							|  |  |  |     visitor.visit(variable_environment); | 
					
						
							|  |  |  |     visitor.visit(lexical_environment); | 
					
						
							|  |  |  |     visitor.visit(private_environment); | 
					
						
							|  |  |  |     visitor.visit(context_owner); | 
					
						
							| 
									
										
										
										
											2025-04-04 23:16:34 +02:00
										 |  |  |     if (this_value.has_value()) | 
					
						
							|  |  |  |         visitor.visit(*this_value); | 
					
						
							| 
									
										
										
										
											2023-11-27 16:45:45 +01:00
										 |  |  |     visitor.visit(executable); | 
					
						
							| 
									
										
										
										
											2023-11-27 13:38:19 +01:00
										 |  |  |     visitor.visit(function_name); | 
					
						
							| 
									
										
										
										
											2025-04-23 19:44:54 +02:00
										 |  |  |     visitor.visit(registers_and_constants_and_locals_and_arguments_span()); | 
					
						
							| 
									
										
										
										
											2024-05-01 19:33:49 +02:00
										 |  |  |     for (auto& context : unwind_contexts) { | 
					
						
							|  |  |  |         visitor.visit(context.lexical_environment); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     visitor.visit(saved_lexical_environments); | 
					
						
							| 
									
										
										
										
											2022-12-11 18:24:33 +00:00
										 |  |  |     script_or_module.visit( | 
					
						
							|  |  |  |         [](Empty) {}, | 
					
						
							|  |  |  |         [&](auto& script_or_module) { | 
					
						
							|  |  |  |             visitor.visit(script_or_module); | 
					
						
							|  |  |  |         }); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-12-11 18:16:15 +00:00
										 |  |  | } |