mirror of
				https://github.com/RGBCube/serenity
				synced 2025-10-31 11:22:45 +00:00 
			
		
		
		
	LibJS: Implement bytecode generation for UpdateExpression :^)
Added Increment and Decrement bytecode ops to support this. Postfix updates use a temporary register to preserve the original value. Note that this patch only implements Identifier updates. Member expression updates are a TODO.
This commit is contained in:
		
							parent
							
								
									5c98f979c6
								
							
						
					
					
						commit
						59eedd6de0
					
				
					 5 changed files with 88 additions and 1 deletions
				
			
		|  | @ -937,6 +937,7 @@ public: | |||
| 
 | ||||
|     virtual Value execute(Interpreter&, GlobalObject&) const override; | ||||
|     virtual void dump(int indent) const override; | ||||
|     virtual void generate_bytecode(Bytecode::Generator&) const override; | ||||
| 
 | ||||
| private: | ||||
|     UpdateOp m_op; | ||||
|  |  | |||
|  | @ -638,4 +638,32 @@ void TemplateLiteral::generate_bytecode(Bytecode::Generator& generator) const | |||
|         } | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| void UpdateExpression::generate_bytecode(Bytecode::Generator& generator) const | ||||
| { | ||||
|     if (is<Identifier>(*m_argument)) { | ||||
|         auto& identifier = static_cast<Identifier const&>(*m_argument); | ||||
|         generator.emit<Bytecode::Op::GetVariable>(identifier.string()); | ||||
| 
 | ||||
|         Optional<Bytecode::Register> previous_value_for_postfix_reg; | ||||
|         if (!m_prefixed) { | ||||
|             previous_value_for_postfix_reg = generator.allocate_register(); | ||||
|             generator.emit<Bytecode::Op::Store>(*previous_value_for_postfix_reg); | ||||
|         } | ||||
| 
 | ||||
|         if (m_op == UpdateOp::Increment) | ||||
|             generator.emit<Bytecode::Op::Increment>(); | ||||
|         else | ||||
|             generator.emit<Bytecode::Op::Decrement>(); | ||||
| 
 | ||||
|         generator.emit<Bytecode::Op::SetVariable>(identifier.string()); | ||||
| 
 | ||||
|         if (!m_prefixed) | ||||
|             generator.emit<Bytecode::Op::Load>(*previous_value_for_postfix_reg); | ||||
|         return; | ||||
|     } | ||||
| 
 | ||||
|     TODO(); | ||||
| } | ||||
| 
 | ||||
| } | ||||
|  |  | |||
|  | @ -54,7 +54,9 @@ | |||
|     O(UnsignedRightShift)         \ | ||||
|     O(In)                         \ | ||||
|     O(InstanceOf)                 \ | ||||
|     O(ConcatString) | ||||
|     O(ConcatString)               \ | ||||
|     O(Increment)                  \ | ||||
|     O(Decrement) | ||||
| 
 | ||||
| namespace JS::Bytecode { | ||||
| 
 | ||||
|  |  | |||
|  | @ -231,6 +231,30 @@ void Return::execute(Bytecode::Interpreter& interpreter) const | |||
|     interpreter.do_return(interpreter.accumulator().value_or(js_undefined())); | ||||
| } | ||||
| 
 | ||||
| void Increment::execute(Bytecode::Interpreter& interpreter) const | ||||
| { | ||||
|     auto old_value = interpreter.accumulator().to_numeric(interpreter.global_object()); | ||||
|     if (interpreter.vm().exception()) | ||||
|         return; | ||||
| 
 | ||||
|     if (old_value.is_number()) | ||||
|         interpreter.accumulator() = Value(old_value.as_double() + 1); | ||||
|     else | ||||
|         interpreter.accumulator() = js_bigint(interpreter.vm().heap(), old_value.as_bigint().big_integer().plus(Crypto::SignedBigInteger { 1 })); | ||||
| } | ||||
| 
 | ||||
| void Decrement::execute(Bytecode::Interpreter& interpreter) const | ||||
| { | ||||
|     auto old_value = interpreter.accumulator().to_numeric(interpreter.global_object()); | ||||
|     if (interpreter.vm().exception()) | ||||
|         return; | ||||
| 
 | ||||
|     if (old_value.is_number()) | ||||
|         interpreter.accumulator() = Value(old_value.as_double() - 1); | ||||
|     else | ||||
|         interpreter.accumulator() = js_bigint(interpreter.vm().heap(), old_value.as_bigint().big_integer().minus(Crypto::SignedBigInteger { 1 })); | ||||
| } | ||||
| 
 | ||||
| String Load::to_string() const | ||||
| { | ||||
|     return String::formatted("Load {}", m_src); | ||||
|  | @ -349,4 +373,14 @@ String Return::to_string() const | |||
|     return "Return"; | ||||
| } | ||||
| 
 | ||||
| String Increment::to_string() const | ||||
| { | ||||
|     return "Increment"; | ||||
| } | ||||
| 
 | ||||
| String Decrement::to_string() const | ||||
| { | ||||
|     return "Decrement"; | ||||
| } | ||||
| 
 | ||||
| } | ||||
|  |  | |||
|  | @ -373,6 +373,28 @@ public: | |||
|     String to_string() const; | ||||
| }; | ||||
| 
 | ||||
| class Increment final : public Instruction { | ||||
| public: | ||||
|     Increment() | ||||
|         : Instruction(Type::Increment) | ||||
|     { | ||||
|     } | ||||
| 
 | ||||
|     void execute(Bytecode::Interpreter&) const; | ||||
|     String to_string() const; | ||||
| }; | ||||
| 
 | ||||
| class Decrement final : public Instruction { | ||||
| public: | ||||
|     Decrement() | ||||
|         : Instruction(Type::Decrement) | ||||
|     { | ||||
|     } | ||||
| 
 | ||||
|     void execute(Bytecode::Interpreter&) const; | ||||
|     String to_string() const; | ||||
| }; | ||||
| 
 | ||||
| } | ||||
| 
 | ||||
| namespace JS::Bytecode { | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Andreas Kling
						Andreas Kling