mirror of
				https://github.com/RGBCube/serenity
				synced 2025-10-31 19:42:43 +00:00 
			
		
		
		
	LibJS/Bytecode: Move environment coordinate caches to Executable
Moving them out of the respective instructions allows the bytecode stream to be immutable.
This commit is contained in:
		
							parent
							
								
									5c7e5cc738
								
							
						
					
					
						commit
						2e23f00a2f
					
				
					 7 changed files with 31 additions and 20 deletions
				
			
		|  | @ -314,7 +314,7 @@ Bytecode::CodeGenerationErrorOr<void> Identifier::generate_bytecode(Bytecode::Ge | |||
|     } else if (is_local()) { | ||||
|         generator.emit<Bytecode::Op::GetLocal>(local_variable_index()); | ||||
|     } else { | ||||
|         generator.emit<Bytecode::Op::GetVariable>(generator.intern_identifier(m_string)); | ||||
|         generator.emit<Bytecode::Op::GetVariable>(generator.intern_identifier(m_string), generator.next_environment_variable_cache()); | ||||
|     } | ||||
|     return {}; | ||||
| } | ||||
|  | @ -1061,7 +1061,7 @@ Bytecode::CodeGenerationErrorOr<void> FunctionDeclaration::generate_bytecode(Byt | |||
|     if (m_is_hoisted) { | ||||
|         Bytecode::Generator::SourceLocationScope scope(generator, *this); | ||||
|         auto index = generator.intern_identifier(name()); | ||||
|         generator.emit<Bytecode::Op::GetVariable>(index); | ||||
|         generator.emit<Bytecode::Op::GetVariable>(index, generator.next_environment_variable_cache()); | ||||
|         generator.emit<Bytecode::Op::SetVariable>(index, Bytecode::Op::SetVariable::InitializationMode::Set, Bytecode::Op::EnvironmentMode::Var); | ||||
|     } | ||||
|     return {}; | ||||
|  | @ -1534,7 +1534,7 @@ Bytecode::CodeGenerationErrorOr<void> CallExpression::generate_bytecode(Bytecode | |||
|         //       a `with` binding, so we can skip this.
 | ||||
|         auto& identifier = static_cast<Identifier const&>(*m_callee); | ||||
|         if (!identifier.is_local() && !identifier.is_global()) { | ||||
|             generator.emit<Bytecode::Op::GetCalleeAndThisFromEnvironment>(generator.intern_identifier(identifier.string()), callee_reg, this_reg); | ||||
|             generator.emit<Bytecode::Op::GetCalleeAndThisFromEnvironment>(generator.intern_identifier(identifier.string()), callee_reg, this_reg, generator.next_environment_variable_cache()); | ||||
|         } else { | ||||
|             TRY(m_callee->generate_bytecode(generator)); | ||||
|             generator.emit<Bytecode::Op::Store>(callee_reg); | ||||
|  |  | |||
|  | @ -18,6 +18,7 @@ Executable::Executable( | |||
|     NonnullRefPtr<SourceCode const> source_code, | ||||
|     size_t number_of_property_lookup_caches, | ||||
|     size_t number_of_global_variable_caches, | ||||
|     size_t number_of_environment_variable_caches, | ||||
|     size_t number_of_registers, | ||||
|     Vector<NonnullOwnPtr<BasicBlock>> basic_blocks, | ||||
|     bool is_strict_mode) | ||||
|  | @ -31,6 +32,7 @@ Executable::Executable( | |||
| { | ||||
|     property_lookup_caches.resize(number_of_property_lookup_caches); | ||||
|     global_variable_caches.resize(number_of_global_variable_caches); | ||||
|     environment_variable_caches.resize(number_of_environment_variable_caches); | ||||
| } | ||||
| 
 | ||||
| Executable::~Executable() = default; | ||||
|  |  | |||
|  | @ -12,6 +12,7 @@ | |||
| #include <LibJS/Bytecode/IdentifierTable.h> | ||||
| #include <LibJS/Bytecode/StringTable.h> | ||||
| #include <LibJS/Forward.h> | ||||
| #include <LibJS/Runtime/EnvironmentCoordinate.h> | ||||
| 
 | ||||
| namespace JS::Bytecode { | ||||
| 
 | ||||
|  | @ -39,6 +40,7 @@ public: | |||
|         NonnullRefPtr<SourceCode const>, | ||||
|         size_t number_of_property_lookup_caches, | ||||
|         size_t number_of_global_variable_caches, | ||||
|         size_t number_of_environment_variable_caches, | ||||
|         size_t number_of_registers, | ||||
|         Vector<NonnullOwnPtr<BasicBlock>>, | ||||
|         bool is_strict_mode); | ||||
|  | @ -48,6 +50,7 @@ public: | |||
|     DeprecatedFlyString name; | ||||
|     Vector<PropertyLookupCache> property_lookup_caches; | ||||
|     Vector<GlobalVariableCache> global_variable_caches; | ||||
|     Vector<Optional<EnvironmentCoordinate>> environment_variable_caches; | ||||
|     Vector<NonnullOwnPtr<BasicBlock>> basic_blocks; | ||||
|     NonnullOwnPtr<StringTable> string_table; | ||||
|     NonnullOwnPtr<IdentifierTable> identifier_table; | ||||
|  |  | |||
|  | @ -63,6 +63,7 @@ CodeGenerationErrorOr<NonnullRefPtr<Executable>> Generator::generate(ASTNode con | |||
|         node.source_code(), | ||||
|         generator.m_next_property_lookup_cache, | ||||
|         generator.m_next_global_variable_cache, | ||||
|         generator.m_next_environment_variable_cache, | ||||
|         generator.m_next_register, | ||||
|         move(generator.m_root_basic_blocks), | ||||
|         is_strict_mode)); | ||||
|  |  | |||
|  | @ -206,6 +206,7 @@ public: | |||
|     void emit_get_by_id_with_this(IdentifierTableIndex, Register); | ||||
| 
 | ||||
|     [[nodiscard]] size_t next_global_variable_cache() { return m_next_global_variable_cache++; } | ||||
|     [[nodiscard]] size_t next_environment_variable_cache() { return m_next_environment_variable_cache++; } | ||||
| 
 | ||||
| private: | ||||
|     enum class JumpType { | ||||
|  | @ -236,6 +237,7 @@ private: | |||
|     u32 m_next_block { 1 }; | ||||
|     u32 m_next_property_lookup_cache { 0 }; | ||||
|     u32 m_next_global_variable_cache { 0 }; | ||||
|     u32 m_next_environment_variable_cache { 0 }; | ||||
|     FunctionKind m_enclosing_function_kind { FunctionKind::Normal }; | ||||
|     Vector<LabelableScope> m_continuable_scopes; | ||||
|     Vector<LabelableScope> m_breakable_scopes; | ||||
|  |  | |||
|  | @ -812,23 +812,24 @@ ThrowCompletionOr<void> GetVariable::execute_impl(Bytecode::Interpreter& interpr | |||
| { | ||||
|     auto& vm = interpreter.vm(); | ||||
| 
 | ||||
|     if (m_cached_environment_coordinate.has_value()) { | ||||
|     auto& cached_environment_coordinate = interpreter.current_executable().environment_variable_caches[m_cache_index]; | ||||
|     if (cached_environment_coordinate.has_value()) { | ||||
|         auto environment = vm.running_execution_context().lexical_environment; | ||||
|         for (size_t i = 0; i < m_cached_environment_coordinate->hops; ++i) | ||||
|         for (size_t i = 0; i < cached_environment_coordinate->hops; ++i) | ||||
|             environment = environment->outer_environment(); | ||||
|         VERIFY(environment); | ||||
|         VERIFY(environment->is_declarative_environment()); | ||||
|         if (!environment->is_permanently_screwed_by_eval()) { | ||||
|             interpreter.accumulator() = TRY(verify_cast<DeclarativeEnvironment>(*environment).get_binding_value_direct(vm, m_cached_environment_coordinate.value().index, vm.in_strict_mode())); | ||||
|             interpreter.accumulator() = TRY(verify_cast<DeclarativeEnvironment>(*environment).get_binding_value_direct(vm, cached_environment_coordinate.value().index, vm.in_strict_mode())); | ||||
|             return {}; | ||||
|         } | ||||
|         m_cached_environment_coordinate = {}; | ||||
|         cached_environment_coordinate = {}; | ||||
|     } | ||||
| 
 | ||||
|     auto const& string = interpreter.current_executable().get_identifier(m_identifier); | ||||
|     auto reference = TRY(vm.resolve_binding(string)); | ||||
|     if (reference.environment_coordinate().has_value()) | ||||
|         m_cached_environment_coordinate = reference.environment_coordinate(); | ||||
|         cached_environment_coordinate = reference.environment_coordinate(); | ||||
|     interpreter.accumulator() = TRY(reference.get_value(vm)); | ||||
|     return {}; | ||||
| } | ||||
|  | @ -837,27 +838,28 @@ ThrowCompletionOr<void> GetCalleeAndThisFromEnvironment::execute_impl(Bytecode:: | |||
| { | ||||
|     auto& vm = interpreter.vm(); | ||||
| 
 | ||||
|     if (m_cached_environment_coordinate.has_value()) { | ||||
|     auto& cached_environment_coordinate = interpreter.current_executable().environment_variable_caches[m_cache_index]; | ||||
|     if (cached_environment_coordinate.has_value()) { | ||||
|         auto environment = vm.running_execution_context().lexical_environment; | ||||
|         for (size_t i = 0; i < m_cached_environment_coordinate->hops; ++i) | ||||
|         for (size_t i = 0; i < cached_environment_coordinate->hops; ++i) | ||||
|             environment = environment->outer_environment(); | ||||
|         VERIFY(environment); | ||||
|         VERIFY(environment->is_declarative_environment()); | ||||
|         if (!environment->is_permanently_screwed_by_eval()) { | ||||
|             interpreter.reg(m_callee_reg) = TRY(verify_cast<DeclarativeEnvironment>(*environment).get_binding_value_direct(vm, m_cached_environment_coordinate.value().index, vm.in_strict_mode())); | ||||
|             interpreter.reg(m_callee_reg) = TRY(verify_cast<DeclarativeEnvironment>(*environment).get_binding_value_direct(vm, cached_environment_coordinate.value().index, vm.in_strict_mode())); | ||||
|             Value this_value = js_undefined(); | ||||
|             if (auto base_object = environment->with_base_object()) | ||||
|                 this_value = base_object; | ||||
|             interpreter.reg(m_this_reg) = this_value; | ||||
|             return {}; | ||||
|         } | ||||
|         m_cached_environment_coordinate = {}; | ||||
|         cached_environment_coordinate = {}; | ||||
|     } | ||||
| 
 | ||||
|     auto const& string = interpreter.current_executable().get_identifier(m_identifier); | ||||
|     auto reference = TRY(vm.resolve_binding(string)); | ||||
|     if (reference.environment_coordinate().has_value()) | ||||
|         m_cached_environment_coordinate = reference.environment_coordinate(); | ||||
|         cached_environment_coordinate = reference.environment_coordinate(); | ||||
| 
 | ||||
|     interpreter.reg(m_callee_reg) = TRY(reference.get_value(vm)); | ||||
| 
 | ||||
|  |  | |||
|  | @ -18,7 +18,6 @@ | |||
| #include <LibJS/Bytecode/StringTable.h> | ||||
| #include <LibJS/Heap/Cell.h> | ||||
| #include <LibJS/Runtime/Environment.h> | ||||
| #include <LibJS/Runtime/EnvironmentCoordinate.h> | ||||
| #include <LibJS/Runtime/Iterator.h> | ||||
| #include <LibJS/Runtime/Value.h> | ||||
| #include <LibJS/Runtime/ValueTraits.h> | ||||
|  | @ -451,11 +450,12 @@ private: | |||
| 
 | ||||
| class GetCalleeAndThisFromEnvironment final : public Instruction { | ||||
| public: | ||||
|     explicit GetCalleeAndThisFromEnvironment(IdentifierTableIndex identifier, Register callee_reg, Register this_reg) | ||||
|     explicit GetCalleeAndThisFromEnvironment(IdentifierTableIndex identifier, Register callee_reg, Register this_reg, u32 cache_index) | ||||
|         : Instruction(Type::GetCalleeAndThisFromEnvironment, sizeof(*this)) | ||||
|         , m_identifier(identifier) | ||||
|         , m_callee_reg(callee_reg) | ||||
|         , m_this_reg(this_reg) | ||||
|         , m_cache_index(cache_index) | ||||
|     { | ||||
|     } | ||||
| 
 | ||||
|  | @ -463,20 +463,21 @@ public: | |||
|     DeprecatedString to_deprecated_string_impl(Bytecode::Executable const&) const; | ||||
| 
 | ||||
|     IdentifierTableIndex identifier() const { return m_identifier; } | ||||
|     u32 cache_index() const { return m_cache_index; } | ||||
| 
 | ||||
| private: | ||||
|     IdentifierTableIndex m_identifier; | ||||
|     Register m_callee_reg; | ||||
|     Register m_this_reg; | ||||
| 
 | ||||
|     Optional<EnvironmentCoordinate> mutable m_cached_environment_coordinate; | ||||
|     u32 m_cache_index { 0 }; | ||||
| }; | ||||
| 
 | ||||
| class GetVariable final : public Instruction { | ||||
| public: | ||||
|     explicit GetVariable(IdentifierTableIndex identifier) | ||||
|     explicit GetVariable(IdentifierTableIndex identifier, u32 cache_index) | ||||
|         : Instruction(Type::GetVariable, sizeof(*this)) | ||||
|         , m_identifier(identifier) | ||||
|         , m_cache_index(cache_index) | ||||
|     { | ||||
|     } | ||||
| 
 | ||||
|  | @ -484,11 +485,11 @@ public: | |||
|     DeprecatedString to_deprecated_string_impl(Bytecode::Executable const&) const; | ||||
| 
 | ||||
|     IdentifierTableIndex identifier() const { return m_identifier; } | ||||
|     u32 cache_index() const { return m_cache_index; } | ||||
| 
 | ||||
| private: | ||||
|     IdentifierTableIndex m_identifier; | ||||
| 
 | ||||
|     Optional<EnvironmentCoordinate> mutable m_cached_environment_coordinate; | ||||
|     u32 m_cache_index { 0 }; | ||||
| }; | ||||
| 
 | ||||
| class GetGlobal final : public Instruction { | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Andreas Kling
						Andreas Kling