mirror of
				https://github.com/ethereum/solidity
				synced 2023-10-03 13:03:40 +00:00 
			
		
		
		
	Optimize constant optimization.
This commit is contained in:
		
							parent
							
								
									f1a4976ce6
								
							
						
					
					
						commit
						da5e171f3b
					
				| @ -38,6 +38,7 @@ unsigned ConstantOptimisationMethod::optimiseConstants( | ||||
| 	for (AssemblyItem const& item: _items) | ||||
| 		if (item.type() == Push) | ||||
| 			pushes[item]++; | ||||
| 	map<u256, AssemblyItems> pendingReplacements; | ||||
| 	for (auto it: pushes) | ||||
| 	{ | ||||
| 		AssemblyItem const& item = it.first; | ||||
| @ -53,17 +54,22 @@ unsigned ConstantOptimisationMethod::optimiseConstants( | ||||
| 		bigint copyGas = copy.gasNeeded(); | ||||
| 		ComputeMethod compute(params, item.data()); | ||||
| 		bigint computeGas = compute.gasNeeded(); | ||||
| 		AssemblyItems replacement; | ||||
| 		if (copyGas < literalGas && copyGas < computeGas) | ||||
| 		{ | ||||
| 			copy.execute(_assembly, _items); | ||||
| 			replacement = copy.execute(_assembly); | ||||
| 			optimisations++; | ||||
| 		} | ||||
| 		else if (computeGas < literalGas && computeGas < copyGas) | ||||
| 		{ | ||||
| 			compute.execute(_assembly, _items); | ||||
| 			replacement = compute.execute(_assembly); | ||||
| 			optimisations++; | ||||
| 		} | ||||
| 		if (!replacement.empty()) | ||||
| 			pendingReplacements[item.data()] = replacement; | ||||
| 	} | ||||
| 	if (!pendingReplacements.empty()) | ||||
| 		replaceConstants(_items, pendingReplacements); | ||||
| 	return optimisations; | ||||
| } | ||||
| 
 | ||||
| @ -101,18 +107,24 @@ size_t ConstantOptimisationMethod::bytesRequired(AssemblyItems const& _items) | ||||
| 
 | ||||
| void ConstantOptimisationMethod::replaceConstants( | ||||
| 	AssemblyItems& _items, | ||||
| 	AssemblyItems const& _replacement | ||||
| ) const | ||||
| 	map<u256, AssemblyItems> const& _replacements | ||||
| ) | ||||
| { | ||||
| 	assertThrow(_items.size() > 0, OptimizerException, ""); | ||||
| 	for (size_t i = 0; i < _items.size(); ++i) | ||||
| 	AssemblyItems replaced; | ||||
| 	for (AssemblyItem const& item: _items) | ||||
| 	{ | ||||
| 		if (_items.at(i) != AssemblyItem(m_value)) | ||||
| 			continue; | ||||
| 		_items[i] = _replacement[0]; | ||||
| 		_items.insert(_items.begin() + i + 1, _replacement.begin() + 1, _replacement.end()); | ||||
| 		i += _replacement.size() - 1; | ||||
| 		if (item.type() == Push) | ||||
| 		{ | ||||
| 			auto it = _replacements.find(item.data()); | ||||
| 			if (it != _replacements.end()) | ||||
| 			{ | ||||
| 				replaced += it->second; | ||||
| 				continue; | ||||
| 			} | ||||
| 		} | ||||
| 		replaced.push_back(item); | ||||
| 	} | ||||
| 	_items = std::move(replaced); | ||||
| } | ||||
| 
 | ||||
| bigint LiteralMethod::gasNeeded() | ||||
| @ -128,7 +140,31 @@ bigint LiteralMethod::gasNeeded() | ||||
| CodeCopyMethod::CodeCopyMethod(Params const& _params, u256 const& _value): | ||||
| 	ConstantOptimisationMethod(_params, _value) | ||||
| { | ||||
| 	m_copyRoutine = AssemblyItems{ | ||||
| } | ||||
| 
 | ||||
| bigint CodeCopyMethod::gasNeeded() | ||||
| { | ||||
| 	return combineGas( | ||||
| 		// Run gas: we ignore memory increase costs
 | ||||
| 		simpleRunGas(copyRoutine()) + GasCosts::copyGas, | ||||
| 		// Data gas for copy routines: Some bytes are zero, but we ignore them.
 | ||||
| 		bytesRequired(copyRoutine()) * (m_params.isCreation ? GasCosts::txDataNonZeroGas : GasCosts::createDataGas), | ||||
| 		// Data gas for data itself
 | ||||
| 		dataGas(toBigEndian(m_value)) | ||||
| 	); | ||||
| } | ||||
| 
 | ||||
| AssemblyItems CodeCopyMethod::execute(Assembly& _assembly) | ||||
| { | ||||
| 	bytes data = toBigEndian(m_value); | ||||
| 	AssemblyItems actualCopyRoutine = copyRoutine(); | ||||
| 	actualCopyRoutine[4] = _assembly.newData(data); | ||||
| 	return actualCopyRoutine; | ||||
| } | ||||
| 
 | ||||
| AssemblyItems const& CodeCopyMethod::copyRoutine() const | ||||
| { | ||||
| 	AssemblyItems static copyRoutine{ | ||||
| 		u256(0), | ||||
| 		Instruction::DUP1, | ||||
| 		Instruction::MLOAD, // back up memory
 | ||||
| @ -141,25 +177,7 @@ CodeCopyMethod::CodeCopyMethod(Params const& _params, u256 const& _value): | ||||
| 		Instruction::SWAP2, | ||||
| 		Instruction::MSTORE | ||||
| 	}; | ||||
| } | ||||
| 
 | ||||
| bigint CodeCopyMethod::gasNeeded() | ||||
| { | ||||
| 	return combineGas( | ||||
| 		// Run gas: we ignore memory increase costs
 | ||||
| 		simpleRunGas(m_copyRoutine) + GasCosts::copyGas, | ||||
| 		// Data gas for copy routines: Some bytes are zero, but we ignore them.
 | ||||
| 		bytesRequired(m_copyRoutine) * (m_params.isCreation ? GasCosts::txDataNonZeroGas : GasCosts::createDataGas), | ||||
| 		// Data gas for data itself
 | ||||
| 		dataGas(toBigEndian(m_value)) | ||||
| 	); | ||||
| } | ||||
| 
 | ||||
| void CodeCopyMethod::execute(Assembly& _assembly, AssemblyItems& _items) | ||||
| { | ||||
| 	bytes data = toBigEndian(m_value); | ||||
| 	m_copyRoutine[4] = _assembly.newData(data); | ||||
| 	replaceConstants(_items, m_copyRoutine); | ||||
| 	return copyRoutine; | ||||
| } | ||||
| 
 | ||||
| AssemblyItems ComputeMethod::findRepresentation(u256 const& _value) | ||||
|  | ||||
| @ -60,7 +60,10 @@ public: | ||||
| 	explicit ConstantOptimisationMethod(Params const& _params, u256 const& _value): | ||||
| 		m_params(_params), m_value(_value) {} | ||||
| 	virtual bigint gasNeeded() = 0; | ||||
| 	virtual void execute(Assembly& _assembly, AssemblyItems& _items) = 0; | ||||
| 	/// Executes the method, potentially appending to the assembly and returns a vector of
 | ||||
| 	/// assembly items the constant should be relpaced with in one sweep.
 | ||||
| 	/// If the vector is empty, the constants will not be deleted.
 | ||||
| 	virtual AssemblyItems execute(Assembly& _assembly) = 0; | ||||
| 
 | ||||
| protected: | ||||
| 	size_t dataSize() const { return std::max<size_t>(1, dev::bytesRequired(m_value)); } | ||||
| @ -83,8 +86,8 @@ protected: | ||||
| 		return m_params.runs * _runGas + m_params.multiplicity * _repeatedDataGas + _uniqueDataGas; | ||||
| 	} | ||||
| 
 | ||||
| 	/// Replaces the constant by the code given in @a _replacement.
 | ||||
| 	void replaceConstants(AssemblyItems& _items, AssemblyItems const& _replacement) const; | ||||
| 	/// Replaces all constants i by the code given in @a _replacement[i].
 | ||||
| 	static void replaceConstants(AssemblyItems& _items, std::map<u256, AssemblyItems> const& _replacement); | ||||
| 
 | ||||
| 	Params m_params; | ||||
| 	u256 const& m_value; | ||||
| @ -100,7 +103,7 @@ public: | ||||
| 	explicit LiteralMethod(Params const& _params, u256 const& _value): | ||||
| 		ConstantOptimisationMethod(_params, _value) {} | ||||
| 	virtual bigint gasNeeded() override; | ||||
| 	virtual void execute(Assembly&, AssemblyItems&) override {} | ||||
| 	virtual AssemblyItems execute(Assembly&) override { return AssemblyItems{}; } | ||||
| }; | ||||
| 
 | ||||
| /**
 | ||||
| @ -111,10 +114,10 @@ class CodeCopyMethod: public ConstantOptimisationMethod | ||||
| public: | ||||
| 	explicit CodeCopyMethod(Params const& _params, u256 const& _value); | ||||
| 	virtual bigint gasNeeded() override; | ||||
| 	virtual void execute(Assembly& _assembly, AssemblyItems& _items) override; | ||||
| 	virtual AssemblyItems execute(Assembly& _assembly) override; | ||||
| 
 | ||||
| protected: | ||||
| 	AssemblyItems m_copyRoutine; | ||||
| 	AssemblyItems const& copyRoutine() const; | ||||
| }; | ||||
| 
 | ||||
| /**
 | ||||
| @ -130,9 +133,9 @@ public: | ||||
| 	} | ||||
| 
 | ||||
| 	virtual bigint gasNeeded() override { return gasNeeded(m_routine); } | ||||
| 	virtual void execute(Assembly&, AssemblyItems& _items) override | ||||
| 	virtual AssemblyItems execute(Assembly&) override | ||||
| 	{ | ||||
| 		replaceConstants(_items, m_routine); | ||||
| 		return m_routine; | ||||
| 	} | ||||
| 
 | ||||
| protected: | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user