mirror of
				https://github.com/RGBCube/serenity
				synced 2025-10-31 19:42:43 +00:00 
			
		
		
		
	LibJS/Bytecode: Dedicated instructions for postfix increment/decrement
Instead of splitting the postfix variants into ToNumeric + Inc/Dec, we now have dedicated PostfixIncrement and PostfixDecrement instructions that handle both outputs in one go.
This commit is contained in:
		
							parent
							
								
									c4f49e343a
								
							
						
					
					
						commit
						9d9b737a58
					
				
					 4 changed files with 96 additions and 27 deletions
				
			
		|  | @ -2373,15 +2373,22 @@ Bytecode::CodeGenerationErrorOr<Optional<Bytecode::Operand>> UpdateExpression::g | |||
|     auto reference = TRY(generator.emit_load_from_reference(*m_argument)); | ||||
| 
 | ||||
|     Optional<Bytecode::Operand> previous_value_for_postfix; | ||||
|     if (!m_prefixed) { | ||||
|         previous_value_for_postfix = Bytecode::Operand(generator.allocate_register()); | ||||
|         generator.emit<Bytecode::Op::ToNumeric>(*previous_value_for_postfix, *reference.loaded_value); | ||||
|     } | ||||
| 
 | ||||
|     if (m_op == UpdateOp::Increment) | ||||
|     if (m_op == UpdateOp::Increment) { | ||||
|         if (m_prefixed) { | ||||
|             generator.emit<Bytecode::Op::Increment>(*reference.loaded_value); | ||||
|     else | ||||
|         } else { | ||||
|             previous_value_for_postfix = Bytecode::Operand(generator.allocate_register()); | ||||
|             generator.emit<Bytecode::Op::PostfixIncrement>(*previous_value_for_postfix, *reference.loaded_value); | ||||
|         } | ||||
|     } else { | ||||
|         if (m_prefixed) { | ||||
|             generator.emit<Bytecode::Op::Decrement>(*reference.loaded_value); | ||||
|         } else { | ||||
|             previous_value_for_postfix = Bytecode::Operand(generator.allocate_register()); | ||||
|             generator.emit<Bytecode::Op::PostfixDecrement>(*previous_value_for_postfix, *reference.loaded_value); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     if (is<Identifier>(*m_argument)) | ||||
|         (void)TRY(generator.emit_store_to_reference(static_cast<Identifier const&>(*m_argument), *reference.loaded_value)); | ||||
|  |  | |||
|  | @ -91,6 +91,8 @@ | |||
|     O(NewString)                       \ | ||||
|     O(NewTypeError)                    \ | ||||
|     O(Not)                             \ | ||||
|     O(PostfixDecrement)                \ | ||||
|     O(PostfixIncrement)                \ | ||||
|     O(PutById)                         \ | ||||
|     O(PutByIdWithThis)                 \ | ||||
|     O(PutByValue)                      \ | ||||
|  | @ -111,7 +113,6 @@ | |||
|     O(ThrowIfNotObject)                \ | ||||
|     O(ThrowIfNullish)                  \ | ||||
|     O(ThrowIfTDZ)                      \ | ||||
|     O(ToNumeric)                       \ | ||||
|     O(Typeof)                          \ | ||||
|     O(TypeofVariable)                  \ | ||||
|     O(UnaryMinus)                      \ | ||||
|  |  | |||
|  | @ -1113,6 +1113,31 @@ ThrowCompletionOr<void> Increment::execute_impl(Bytecode::Interpreter& interpret | |||
|     return {}; | ||||
| } | ||||
| 
 | ||||
| ThrowCompletionOr<void> PostfixIncrement::execute_impl(Bytecode::Interpreter& interpreter) const | ||||
| { | ||||
|     auto& vm = interpreter.vm(); | ||||
|     auto old_value = interpreter.get(m_src); | ||||
| 
 | ||||
|     // OPTIMIZATION: Fast path for Int32 values.
 | ||||
|     if (old_value.is_int32()) { | ||||
|         auto integer_value = old_value.as_i32(); | ||||
|         if (integer_value != NumericLimits<i32>::max()) [[likely]] { | ||||
|             interpreter.set(m_dst, old_value); | ||||
|             interpreter.set(m_src, Value { integer_value + 1 }); | ||||
|             return {}; | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     old_value = TRY(old_value.to_numeric(vm)); | ||||
|     interpreter.set(m_dst, old_value); | ||||
| 
 | ||||
|     if (old_value.is_number()) | ||||
|         interpreter.set(m_src, Value(old_value.as_double() + 1)); | ||||
|     else | ||||
|         interpreter.set(m_src, BigInt::create(vm, old_value.as_bigint().big_integer().plus(Crypto::SignedBigInteger { 1 }))); | ||||
|     return {}; | ||||
| } | ||||
| 
 | ||||
| ThrowCompletionOr<void> Decrement::execute_impl(Bytecode::Interpreter& interpreter) const | ||||
| { | ||||
|     auto& vm = interpreter.vm(); | ||||
|  | @ -1127,6 +1152,21 @@ ThrowCompletionOr<void> Decrement::execute_impl(Bytecode::Interpreter& interpret | |||
|     return {}; | ||||
| } | ||||
| 
 | ||||
| ThrowCompletionOr<void> PostfixDecrement::execute_impl(Bytecode::Interpreter& interpreter) const | ||||
| { | ||||
|     auto& vm = interpreter.vm(); | ||||
|     auto old_value = interpreter.get(m_src); | ||||
| 
 | ||||
|     old_value = TRY(old_value.to_numeric(vm)); | ||||
|     interpreter.set(m_dst, old_value); | ||||
| 
 | ||||
|     if (old_value.is_number()) | ||||
|         interpreter.set(m_src, Value(old_value.as_double() - 1)); | ||||
|     else | ||||
|         interpreter.set(m_src, BigInt::create(vm, old_value.as_bigint().big_integer().minus(Crypto::SignedBigInteger { 1 }))); | ||||
|     return {}; | ||||
| } | ||||
| 
 | ||||
| ThrowCompletionOr<void> Throw::execute_impl(Bytecode::Interpreter& interpreter) const | ||||
| { | ||||
|     return throw_completion(interpreter.get(src())); | ||||
|  | @ -1356,12 +1396,6 @@ ThrowCompletionOr<void> TypeofVariable::execute_impl(Bytecode::Interpreter& inte | |||
|     return {}; | ||||
| } | ||||
| 
 | ||||
| ThrowCompletionOr<void> ToNumeric::execute_impl(Bytecode::Interpreter& interpreter) const | ||||
| { | ||||
|     interpreter.set(dst(), TRY(interpreter.get(src()).to_numeric(interpreter.vm()))); | ||||
|     return {}; | ||||
| } | ||||
| 
 | ||||
| ThrowCompletionOr<void> BlockDeclarationInstantiation::execute_impl(Bytecode::Interpreter& interpreter) const | ||||
| { | ||||
|     auto& vm = interpreter.vm(); | ||||
|  | @ -1763,9 +1797,23 @@ ByteString Increment::to_byte_string_impl(Bytecode::Executable const& executable | |||
|     return ByteString::formatted("Increment {}", format_operand("dst"sv, m_dst, executable)); | ||||
| } | ||||
| 
 | ||||
| ByteString Decrement::to_byte_string_impl(Bytecode::Executable const&) const | ||||
| ByteString PostfixIncrement::to_byte_string_impl(Bytecode::Executable const& executable) const | ||||
| { | ||||
|     return "Decrement"; | ||||
|     return ByteString::formatted("PostfixIncrement {}, {}", | ||||
|         format_operand("dst"sv, m_dst, executable), | ||||
|         format_operand("src"sv, m_dst, executable)); | ||||
| } | ||||
| 
 | ||||
| ByteString Decrement::to_byte_string_impl(Bytecode::Executable const& executable) const | ||||
| { | ||||
|     return ByteString::formatted("Decrement {}", format_operand("dst"sv, m_dst, executable)); | ||||
| } | ||||
| 
 | ||||
| ByteString PostfixDecrement::to_byte_string_impl(Bytecode::Executable const& executable) const | ||||
| { | ||||
|     return ByteString::formatted("PostfixDecrement {}, {}", | ||||
|         format_operand("dst"sv, m_dst, executable), | ||||
|         format_operand("src"sv, m_dst, executable)); | ||||
| } | ||||
| 
 | ||||
| ByteString Throw::to_byte_string_impl(Bytecode::Executable const& executable) const | ||||
|  | @ -1974,13 +2022,6 @@ ByteString TypeofVariable::to_byte_string_impl(Bytecode::Executable const& execu | |||
|         executable.identifier_table->get(m_identifier)); | ||||
| } | ||||
| 
 | ||||
| ByteString ToNumeric::to_byte_string_impl(Bytecode::Executable const& executable) const | ||||
| { | ||||
|     return ByteString::formatted("ToNumeric {}, {}", | ||||
|         format_operand("dst"sv, m_dst, executable), | ||||
|         format_operand("src"sv, m_src, executable)); | ||||
| } | ||||
| 
 | ||||
| ByteString BlockDeclarationInstantiation::to_byte_string_impl(Bytecode::Executable const&) const | ||||
| { | ||||
|     return "BlockDeclarationInstantiation"sv; | ||||
|  |  | |||
|  | @ -1347,6 +1347,26 @@ private: | |||
|     Operand m_dst; | ||||
| }; | ||||
| 
 | ||||
| class PostfixIncrement final : public Instruction { | ||||
| public: | ||||
|     explicit PostfixIncrement(Operand dst, Operand src) | ||||
|         : Instruction(Type::PostfixIncrement, sizeof(*this)) | ||||
|         , m_dst(dst) | ||||
|         , m_src(src) | ||||
|     { | ||||
|     } | ||||
| 
 | ||||
|     ThrowCompletionOr<void> execute_impl(Bytecode::Interpreter&) const; | ||||
|     ByteString to_byte_string_impl(Bytecode::Executable const&) const; | ||||
| 
 | ||||
|     Operand dst() const { return m_dst; } | ||||
|     Operand src() const { return m_src; } | ||||
| 
 | ||||
| private: | ||||
|     Operand m_dst; | ||||
|     Operand m_src; | ||||
| }; | ||||
| 
 | ||||
| class Decrement final : public Instruction { | ||||
| public: | ||||
|     explicit Decrement(Operand dst) | ||||
|  | @ -1364,10 +1384,10 @@ private: | |||
|     Operand m_dst; | ||||
| }; | ||||
| 
 | ||||
| class ToNumeric final : public Instruction { | ||||
| class PostfixDecrement final : public Instruction { | ||||
| public: | ||||
|     explicit ToNumeric(Operand dst, Operand src) | ||||
|         : Instruction(Type::ToNumeric, sizeof(*this)) | ||||
|     explicit PostfixDecrement(Operand dst, Operand src) | ||||
|         : Instruction(Type::PostfixDecrement, sizeof(*this)) | ||||
|         , m_dst(dst) | ||||
|         , m_src(src) | ||||
|     { | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Andreas Kling
						Andreas Kling