mirror of
				https://github.com/RGBCube/serenity
				synced 2025-10-31 17:52:45 +00:00 
			
		
		
		
	LibJS: Make Executable ref-counted and let instruction iterator co-own it
This ensures that the instruction stream pointed at by the instruction iterator remains valid as long as the iterator exists.
This commit is contained in:
		
							parent
							
								
									b1ee5c8738
								
							
						
					
					
						commit
						c14db6ab12
					
				
					 9 changed files with 61 additions and 26 deletions
				
			
		|  | @ -5,9 +5,34 @@ | |||
|  */ | ||||
| 
 | ||||
| #include <LibJS/Bytecode/Executable.h> | ||||
| #include <LibJS/SourceCode.h> | ||||
| 
 | ||||
| namespace JS::Bytecode { | ||||
| 
 | ||||
| Executable::Executable( | ||||
|     NonnullOwnPtr<IdentifierTable> identifier_table, | ||||
|     NonnullOwnPtr<StringTable> string_table, | ||||
|     NonnullOwnPtr<RegexTable> regex_table, | ||||
|     NonnullRefPtr<SourceCode const> source_code, | ||||
|     size_t number_of_property_lookup_caches, | ||||
|     size_t number_of_global_variable_caches, | ||||
|     size_t number_of_registers, | ||||
|     Vector<NonnullOwnPtr<BasicBlock>> basic_blocks, | ||||
|     bool is_strict_mode) | ||||
|     : basic_blocks(move(basic_blocks)) | ||||
|     , string_table(move(string_table)) | ||||
|     , identifier_table(move(identifier_table)) | ||||
|     , regex_table(move(regex_table)) | ||||
|     , source_code(move(source_code)) | ||||
|     , number_of_registers(number_of_registers) | ||||
|     , is_strict_mode(is_strict_mode) | ||||
| { | ||||
|     property_lookup_caches.resize(number_of_property_lookup_caches); | ||||
|     global_variable_caches.resize(number_of_global_variable_caches); | ||||
| } | ||||
| 
 | ||||
| Executable::~Executable() = default; | ||||
| 
 | ||||
| void Executable::dump() const | ||||
| { | ||||
|     dbgln("\033[33;1mJS::Bytecode::Executable\033[0m ({})", name); | ||||
|  |  | |||
|  | @ -31,7 +31,21 @@ struct SourceRecord { | |||
|     u32 source_end_offset {}; | ||||
| }; | ||||
| 
 | ||||
| struct Executable { | ||||
| class Executable final : public RefCounted<Executable> { | ||||
| public: | ||||
|     Executable( | ||||
|         NonnullOwnPtr<IdentifierTable>, | ||||
|         NonnullOwnPtr<StringTable>, | ||||
|         NonnullOwnPtr<RegexTable>, | ||||
|         NonnullRefPtr<SourceCode const>, | ||||
|         size_t number_of_property_lookup_caches, | ||||
|         size_t number_of_global_variable_caches, | ||||
|         size_t number_of_registers, | ||||
|         Vector<NonnullOwnPtr<BasicBlock>>, | ||||
|         bool is_strict_mode); | ||||
| 
 | ||||
|     ~Executable(); | ||||
| 
 | ||||
|     DeprecatedFlyString name; | ||||
|     Vector<PropertyLookupCache> property_lookup_caches; | ||||
|     Vector<GlobalVariableCache> global_variable_caches; | ||||
|  |  | |||
|  | @ -20,7 +20,7 @@ Generator::Generator() | |||
| { | ||||
| } | ||||
| 
 | ||||
| CodeGenerationErrorOr<NonnullOwnPtr<Executable>> Generator::generate(ASTNode const& node, FunctionKind enclosing_function_kind) | ||||
| CodeGenerationErrorOr<NonnullRefPtr<Executable>> Generator::generate(ASTNode const& node, FunctionKind enclosing_function_kind) | ||||
| { | ||||
|     Generator generator; | ||||
|     generator.switch_to_basic_block(generator.make_block()); | ||||
|  | @ -56,24 +56,18 @@ CodeGenerationErrorOr<NonnullOwnPtr<Executable>> Generator::generate(ASTNode con | |||
|     else if (is<FunctionExpression>(node)) | ||||
|         is_strict_mode = static_cast<FunctionExpression const&>(node).is_strict_mode(); | ||||
| 
 | ||||
|     Vector<PropertyLookupCache> property_lookup_caches; | ||||
|     property_lookup_caches.resize(generator.m_next_property_lookup_cache); | ||||
|     auto executable = adopt_ref(*new Executable( | ||||
|         move(generator.m_identifier_table), | ||||
|         move(generator.m_string_table), | ||||
|         move(generator.m_regex_table), | ||||
|         node.source_code(), | ||||
|         generator.m_next_property_lookup_cache, | ||||
|         generator.m_next_global_variable_cache, | ||||
|         generator.m_next_register, | ||||
|         move(generator.m_root_basic_blocks), | ||||
|         is_strict_mode)); | ||||
| 
 | ||||
|     Vector<GlobalVariableCache> global_variable_caches; | ||||
|     global_variable_caches.resize(generator.m_next_global_variable_cache); | ||||
| 
 | ||||
|     return adopt_own(*new Executable { | ||||
|         .name = {}, | ||||
|         .property_lookup_caches = move(property_lookup_caches), | ||||
|         .global_variable_caches = move(global_variable_caches), | ||||
|         .basic_blocks = move(generator.m_root_basic_blocks), | ||||
|         .string_table = move(generator.m_string_table), | ||||
|         .identifier_table = move(generator.m_identifier_table), | ||||
|         .regex_table = move(generator.m_regex_table), | ||||
|         .source_code = node.source_code(), | ||||
|         .number_of_registers = generator.m_next_register, | ||||
|         .is_strict_mode = is_strict_mode, | ||||
|     }); | ||||
|     return executable; | ||||
| } | ||||
| 
 | ||||
| void Generator::grow(size_t additional_size) | ||||
|  |  | |||
|  | @ -30,7 +30,7 @@ public: | |||
|         Function, | ||||
|         Block, | ||||
|     }; | ||||
|     static CodeGenerationErrorOr<NonnullOwnPtr<Executable>> generate(ASTNode const&, FunctionKind = FunctionKind::Normal); | ||||
|     static CodeGenerationErrorOr<NonnullRefPtr<Executable>> generate(ASTNode const&, FunctionKind = FunctionKind::Normal); | ||||
| 
 | ||||
|     Register allocate_register(); | ||||
| 
 | ||||
|  |  | |||
|  | @ -178,13 +178,15 @@ public: | |||
|     UnrealizedSourceRange source_range() const; | ||||
|     RefPtr<SourceCode> source_code() const; | ||||
| 
 | ||||
|     Executable const* executable() const { return m_executable; } | ||||
| 
 | ||||
| private: | ||||
|     Instruction const& dereference() const { return *reinterpret_cast<Instruction const*>(m_ptr); } | ||||
| 
 | ||||
|     u8 const* m_begin { nullptr }; | ||||
|     u8 const* m_end { nullptr }; | ||||
|     u8 const* m_ptr { nullptr }; | ||||
|     Executable const* m_executable { nullptr }; | ||||
|     RefPtr<Executable const> m_executable; | ||||
| }; | ||||
| 
 | ||||
| } | ||||
|  |  | |||
|  | @ -407,7 +407,7 @@ void Interpreter::leave_unwind_context() | |||
|     unwind_contexts().take_last(); | ||||
| } | ||||
| 
 | ||||
| ThrowCompletionOr<NonnullOwnPtr<Bytecode::Executable>> compile(VM& vm, ASTNode const& node, FunctionKind kind, DeprecatedFlyString const& name) | ||||
| ThrowCompletionOr<NonnullRefPtr<Bytecode::Executable>> compile(VM& vm, ASTNode const& node, FunctionKind kind, DeprecatedFlyString const& name) | ||||
| { | ||||
|     auto executable_result = Bytecode::Generator::generate(node, kind); | ||||
|     if (executable_result.is_error()) | ||||
|  |  | |||
|  | @ -110,6 +110,6 @@ private: | |||
| 
 | ||||
| extern bool g_dump_bytecode; | ||||
| 
 | ||||
| ThrowCompletionOr<NonnullOwnPtr<Bytecode::Executable>> compile(VM&, ASTNode const& no, JS::FunctionKind kind, DeprecatedFlyString const& name); | ||||
| ThrowCompletionOr<NonnullRefPtr<Bytecode::Executable>> compile(VM&, ASTNode const& no, JS::FunctionKind kind, DeprecatedFlyString const& name); | ||||
| 
 | ||||
| } | ||||
|  |  | |||
|  | @ -302,7 +302,7 @@ class MarkedVector; | |||
| 
 | ||||
| namespace Bytecode { | ||||
| class BasicBlock; | ||||
| struct Executable; | ||||
| class Executable; | ||||
| class Generator; | ||||
| class Instruction; | ||||
| class Interpreter; | ||||
|  |  | |||
|  | @ -111,8 +111,8 @@ private: | |||
|     ThrowCompletionOr<void> function_declaration_instantiation(); | ||||
| 
 | ||||
|     DeprecatedFlyString m_name; | ||||
|     OwnPtr<Bytecode::Executable> m_bytecode_executable; | ||||
|     Vector<OwnPtr<Bytecode::Executable>> m_default_parameter_bytecode_executables; | ||||
|     RefPtr<Bytecode::Executable> m_bytecode_executable; | ||||
|     Vector<NonnullRefPtr<Bytecode::Executable>> m_default_parameter_bytecode_executables; | ||||
|     i32 m_function_length { 0 }; | ||||
|     Vector<DeprecatedFlyString> m_local_variables_names; | ||||
| 
 | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Andreas Kling
						Andreas Kling