mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
Do not allocate memory on reverts with small errors.
This commit is contained in:
parent
21caa43f2c
commit
87ce29542c
@ -15,6 +15,7 @@ Compiler Features:
|
||||
* SMTChecker: Properties that are proved safe are now reported explicitly at the end of the analysis. By default, only the number of safe properties is shown. The CLI option ``--model-checker-show-proved-safe`` and the JSON option ``settings.modelChecker.showProvedSafe`` can be enabled to show the full list of safe properties.
|
||||
* SMTChecker: Group all messages about unsupported language features in a single warning. The CLI option ``--model-checker-show-unsupported`` and the JSON option ``settings.modelChecker.showUnsupported`` can be enabled to show the full list.
|
||||
* Yul EVM Code Transform: If available, use ``push0`` instead of ``codesize`` to produce an arbitrary value on stack in order to create equal stack heights between branches.
|
||||
* Yul IR Code Generation: Cheaper code for reverting with errors of a static small encoding size.
|
||||
|
||||
|
||||
Bugfixes:
|
||||
|
@ -47,6 +47,7 @@
|
||||
#include <libsolutil/FunctionSelector.h>
|
||||
#include <libsolutil/Visitor.h>
|
||||
|
||||
#include <range/v3/algorithm/all_of.hpp>
|
||||
#include <range/v3/view/transform.hpp>
|
||||
|
||||
using namespace std;
|
||||
@ -58,6 +59,18 @@ using namespace std::string_literals;
|
||||
namespace
|
||||
{
|
||||
|
||||
optional<size_t> staticEncodingSize(vector<Type const*> const& _parameterTypes)
|
||||
{
|
||||
size_t encodedSize = 0;
|
||||
for (auto const* type: _parameterTypes)
|
||||
{
|
||||
if (type->isDynamicallyEncoded())
|
||||
return nullopt;
|
||||
encodedSize += type->calldataHeadSize();
|
||||
}
|
||||
return encodedSize;
|
||||
}
|
||||
|
||||
struct CopyTranslate: public yul::ASTCopier
|
||||
{
|
||||
using ExternalRefsMap = std::map<yul::Identifier const*, InlineAssemblyAnnotation::ExternalIdentifierInfo>;
|
||||
@ -3363,8 +3376,16 @@ void IRGeneratorForStatements::revertWithError(
|
||||
vector<ASTPointer<Expression const>> const& _errorArguments
|
||||
)
|
||||
{
|
||||
bool needsAllocation = true;
|
||||
if (optional<size_t> size = staticEncodingSize(_parameterTypes))
|
||||
if (ranges::all_of(_parameterTypes, [](auto const* type) { return type && type->isValueType(); }))
|
||||
needsAllocation = *size + 4 > CompilerUtils::generalPurposeMemoryStart;
|
||||
Whiskers templ(R"({
|
||||
<?needsAllocation>
|
||||
let <pos> := <allocateUnbounded>()
|
||||
<!needsAllocation>
|
||||
let <pos> := 0
|
||||
</needsAllocation>
|
||||
mstore(<pos>, <hash>)
|
||||
let <end> := <encode>(add(<pos>, 4) <argumentVars>)
|
||||
revert(<pos>, sub(<end>, <pos>))
|
||||
@ -3372,7 +3393,9 @@ void IRGeneratorForStatements::revertWithError(
|
||||
templ("pos", m_context.newYulVariable());
|
||||
templ("end", m_context.newYulVariable());
|
||||
templ("hash", util::selectorFromSignatureU256(_signature).str());
|
||||
templ("allocateUnbounded", m_utils.allocateUnboundedFunction());
|
||||
templ("needsAllocation", needsAllocation);
|
||||
if (needsAllocation)
|
||||
templ("allocateUnbounded", m_utils.allocateUnboundedFunction());
|
||||
|
||||
vector<string> errorArgumentVars;
|
||||
vector<Type const*> errorArgumentTypes;
|
||||
|
@ -14,6 +14,6 @@ contract B {
|
||||
}
|
||||
// ----
|
||||
// f() -> FAILURE, hex"92bbf6e8"
|
||||
// gas irOptimized: 274265
|
||||
// gas irOptimized: 270934
|
||||
// gas legacy: 310592
|
||||
// gas legacyOptimized: 273662
|
||||
|
Loading…
Reference in New Issue
Block a user