mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
Merge pull request #2187 from ethereum/testOptimizer
Add recomputation check for number representation.
This commit is contained in:
commit
2c8b770062
@ -232,6 +232,54 @@ AssemblyItems ComputeMethod::findRepresentation(u256 const& _value)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool ComputeMethod::checkRepresentation(u256 const& _value, AssemblyItems const& _routine)
|
||||||
|
{
|
||||||
|
// This is a tiny EVM that can only evaluate some instructions.
|
||||||
|
vector<u256> stack;
|
||||||
|
for (AssemblyItem const& item: _routine)
|
||||||
|
{
|
||||||
|
switch (item.type())
|
||||||
|
{
|
||||||
|
case Operation:
|
||||||
|
{
|
||||||
|
if (stack.size() < size_t(item.arguments()))
|
||||||
|
return false;
|
||||||
|
u256* sp = &stack.back();
|
||||||
|
switch (item.instruction())
|
||||||
|
{
|
||||||
|
case Instruction::MUL:
|
||||||
|
sp[-1] = sp[0] * sp[-1];
|
||||||
|
break;
|
||||||
|
case Instruction::EXP:
|
||||||
|
if (sp[-1] > 0xff)
|
||||||
|
return false;
|
||||||
|
sp[-1] = boost::multiprecision::pow(sp[0], unsigned(sp[-1]));
|
||||||
|
break;
|
||||||
|
case Instruction::ADD:
|
||||||
|
sp[-1] = sp[0] + sp[-1];
|
||||||
|
break;
|
||||||
|
case Instruction::SUB:
|
||||||
|
sp[-1] = sp[0] - sp[-1];
|
||||||
|
break;
|
||||||
|
case Instruction::NOT:
|
||||||
|
sp[0] = ~sp[0];
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
stack.resize(stack.size() + item.deposit());
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case Push:
|
||||||
|
stack.push_back(item.data());
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return stack.size() == 1 && stack.front() == _value;
|
||||||
|
}
|
||||||
|
|
||||||
bigint ComputeMethod::gasNeeded(AssemblyItems const& _routine)
|
bigint ComputeMethod::gasNeeded(AssemblyItems const& _routine)
|
||||||
{
|
{
|
||||||
size_t numExps = count(_routine.begin(), _routine.end(), Instruction::EXP);
|
size_t numExps = count(_routine.begin(), _routine.end(), Instruction::EXP);
|
||||||
|
@ -21,10 +21,14 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <vector>
|
#include <libevmasm/Exceptions.h>
|
||||||
|
|
||||||
|
#include <libdevcore/Assertions.h>
|
||||||
#include <libdevcore/CommonData.h>
|
#include <libdevcore/CommonData.h>
|
||||||
#include <libdevcore/CommonIO.h>
|
#include <libdevcore/CommonIO.h>
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
namespace dev
|
namespace dev
|
||||||
{
|
{
|
||||||
namespace eth
|
namespace eth
|
||||||
@ -130,6 +134,11 @@ public:
|
|||||||
ConstantOptimisationMethod(_params, _value)
|
ConstantOptimisationMethod(_params, _value)
|
||||||
{
|
{
|
||||||
m_routine = findRepresentation(m_value);
|
m_routine = findRepresentation(m_value);
|
||||||
|
assertThrow(
|
||||||
|
checkRepresentation(m_value, m_routine),
|
||||||
|
OptimizerException,
|
||||||
|
"Invalid constant expression created."
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual bigint gasNeeded() override { return gasNeeded(m_routine); }
|
virtual bigint gasNeeded() override { return gasNeeded(m_routine); }
|
||||||
@ -141,6 +150,8 @@ public:
|
|||||||
protected:
|
protected:
|
||||||
/// Tries to recursively find a way to compute @a _value.
|
/// Tries to recursively find a way to compute @a _value.
|
||||||
AssemblyItems findRepresentation(u256 const& _value);
|
AssemblyItems findRepresentation(u256 const& _value);
|
||||||
|
/// Recomputes the value from the calculated representation and checks for correctness.
|
||||||
|
bool checkRepresentation(u256 const& _value, AssemblyItems const& _routine);
|
||||||
bigint gasNeeded(AssemblyItems const& _routine);
|
bigint gasNeeded(AssemblyItems const& _routine);
|
||||||
|
|
||||||
/// Counter for the complexity of optimization, will stop when it reaches zero.
|
/// Counter for the complexity of optimization, will stop when it reaches zero.
|
||||||
|
Loading…
Reference in New Issue
Block a user