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/Bytecode/Executable.h> | ||||||
|  | #include <LibJS/SourceCode.h> | ||||||
| 
 | 
 | ||||||
| namespace JS::Bytecode { | 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 | void Executable::dump() const | ||||||
| { | { | ||||||
|     dbgln("\033[33;1mJS::Bytecode::Executable\033[0m ({})", name); |     dbgln("\033[33;1mJS::Bytecode::Executable\033[0m ({})", name); | ||||||
|  |  | ||||||
|  | @ -31,7 +31,21 @@ struct SourceRecord { | ||||||
|     u32 source_end_offset {}; |     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; |     DeprecatedFlyString name; | ||||||
|     Vector<PropertyLookupCache> property_lookup_caches; |     Vector<PropertyLookupCache> property_lookup_caches; | ||||||
|     Vector<GlobalVariableCache> global_variable_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 generator; | ||||||
|     generator.switch_to_basic_block(generator.make_block()); |     generator.switch_to_basic_block(generator.make_block()); | ||||||
|  | @ -56,24 +56,18 @@ CodeGenerationErrorOr<NonnullOwnPtr<Executable>> Generator::generate(ASTNode con | ||||||
|     else if (is<FunctionExpression>(node)) |     else if (is<FunctionExpression>(node)) | ||||||
|         is_strict_mode = static_cast<FunctionExpression const&>(node).is_strict_mode(); |         is_strict_mode = static_cast<FunctionExpression const&>(node).is_strict_mode(); | ||||||
| 
 | 
 | ||||||
|     Vector<PropertyLookupCache> property_lookup_caches; |     auto executable = adopt_ref(*new Executable( | ||||||
|     property_lookup_caches.resize(generator.m_next_property_lookup_cache); |         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; |     return executable; | ||||||
|     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, |  | ||||||
|     }); |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void Generator::grow(size_t additional_size) | void Generator::grow(size_t additional_size) | ||||||
|  |  | ||||||
|  | @ -30,7 +30,7 @@ public: | ||||||
|         Function, |         Function, | ||||||
|         Block, |         Block, | ||||||
|     }; |     }; | ||||||
|     static CodeGenerationErrorOr<NonnullOwnPtr<Executable>> generate(ASTNode const&, FunctionKind = FunctionKind::Normal); |     static CodeGenerationErrorOr<NonnullRefPtr<Executable>> generate(ASTNode const&, FunctionKind = FunctionKind::Normal); | ||||||
| 
 | 
 | ||||||
|     Register allocate_register(); |     Register allocate_register(); | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -178,13 +178,15 @@ public: | ||||||
|     UnrealizedSourceRange source_range() const; |     UnrealizedSourceRange source_range() const; | ||||||
|     RefPtr<SourceCode> source_code() const; |     RefPtr<SourceCode> source_code() const; | ||||||
| 
 | 
 | ||||||
|  |     Executable const* executable() const { return m_executable; } | ||||||
|  | 
 | ||||||
| private: | private: | ||||||
|     Instruction const& dereference() const { return *reinterpret_cast<Instruction const*>(m_ptr); } |     Instruction const& dereference() const { return *reinterpret_cast<Instruction const*>(m_ptr); } | ||||||
| 
 | 
 | ||||||
|     u8 const* m_begin { nullptr }; |     u8 const* m_begin { nullptr }; | ||||||
|     u8 const* m_end { nullptr }; |     u8 const* m_end { nullptr }; | ||||||
|     u8 const* m_ptr { 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(); |     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); |     auto executable_result = Bytecode::Generator::generate(node, kind); | ||||||
|     if (executable_result.is_error()) |     if (executable_result.is_error()) | ||||||
|  |  | ||||||
|  | @ -110,6 +110,6 @@ private: | ||||||
| 
 | 
 | ||||||
| extern bool g_dump_bytecode; | 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 { | namespace Bytecode { | ||||||
| class BasicBlock; | class BasicBlock; | ||||||
| struct Executable; | class Executable; | ||||||
| class Generator; | class Generator; | ||||||
| class Instruction; | class Instruction; | ||||||
| class Interpreter; | class Interpreter; | ||||||
|  |  | ||||||
|  | @ -111,8 +111,8 @@ private: | ||||||
|     ThrowCompletionOr<void> function_declaration_instantiation(); |     ThrowCompletionOr<void> function_declaration_instantiation(); | ||||||
| 
 | 
 | ||||||
|     DeprecatedFlyString m_name; |     DeprecatedFlyString m_name; | ||||||
|     OwnPtr<Bytecode::Executable> m_bytecode_executable; |     RefPtr<Bytecode::Executable> m_bytecode_executable; | ||||||
|     Vector<OwnPtr<Bytecode::Executable>> m_default_parameter_bytecode_executables; |     Vector<NonnullRefPtr<Bytecode::Executable>> m_default_parameter_bytecode_executables; | ||||||
|     i32 m_function_length { 0 }; |     i32 m_function_length { 0 }; | ||||||
|     Vector<DeprecatedFlyString> m_local_variables_names; |     Vector<DeprecatedFlyString> m_local_variables_names; | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Andreas Kling
						Andreas Kling