diff options
Diffstat (limited to 'libevmasm/ConstantOptimiser.cpp')
-rw-r--r-- | libevmasm/ConstantOptimiser.cpp | 76 |
1 files changed, 47 insertions, 29 deletions
diff --git a/libevmasm/ConstantOptimiser.cpp b/libevmasm/ConstantOptimiser.cpp index f4a50c2d..601ce812 100644 --- a/libevmasm/ConstantOptimiser.cpp +++ b/libevmasm/ConstantOptimiser.cpp @@ -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,38 +140,44 @@ bigint LiteralMethod::gasNeeded() CodeCopyMethod::CodeCopyMethod(Params const& _params, u256 const& _value): ConstantOptimisationMethod(_params, _value) { - m_copyRoutine = AssemblyItems{ - u256(0), - Instruction::DUP1, - Instruction::MLOAD, // back up memory - u256(32), - AssemblyItem(PushData, u256(1) << 16), // has to be replaced - Instruction::DUP4, - Instruction::CODECOPY, - Instruction::DUP2, - Instruction::MLOAD, - Instruction::SWAP2, - Instruction::MSTORE - }; } bigint CodeCopyMethod::gasNeeded() { return combineGas( // Run gas: we ignore memory increase costs - simpleRunGas(m_copyRoutine) + GasCosts::copyGas, + simpleRunGas(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), + bytesRequired(copyRoutine()) * (m_params.isCreation ? GasCosts::txDataNonZeroGas : GasCosts::createDataGas), // Data gas for data itself dataGas(toBigEndian(m_value)) ); } -void CodeCopyMethod::execute(Assembly& _assembly, AssemblyItems& _items) +AssemblyItems CodeCopyMethod::execute(Assembly& _assembly) { bytes data = toBigEndian(m_value); - m_copyRoutine[4] = _assembly.newData(data); - replaceConstants(_items, m_copyRoutine); + 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 + u256(32), + AssemblyItem(PushData, u256(1) << 16), // has to be replaced + Instruction::DUP4, + Instruction::CODECOPY, + Instruction::DUP2, + Instruction::MLOAD, + Instruction::SWAP2, + Instruction::MSTORE + }; + return copyRoutine; } AssemblyItems ComputeMethod::findRepresentation(u256 const& _value) |