aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorchriseth <chris@ethereum.org>2018-03-27 21:28:08 +0800
committerGitHub <noreply@github.com>2018-03-27 21:28:08 +0800
commit59538e9a04da1761f3a71f2181c1812fc23a5cb8 (patch)
tree659c3c710f551fbb02085711514332b3923e831f
parentaf26228159d6fbf3240291d356878505ba42e33a (diff)
parentfab527c4146f08971938c63074c8c92e6ff241bc (diff)
downloaddexon-solidity-59538e9a04da1761f3a71f2181c1812fc23a5cb8.tar.gz
dexon-solidity-59538e9a04da1761f3a71f2181c1812fc23a5cb8.tar.zst
dexon-solidity-59538e9a04da1761f3a71f2181c1812fc23a5cb8.zip
Merge pull request #3686 from ethereum/doNotIncludeItnernal
Do not include internal functions only used by constructor
-rw-r--r--Changelog.md1
-rw-r--r--libsolidity/codegen/CompilerUtils.cpp9
-rw-r--r--libsolidity/codegen/CompilerUtils.h3
-rw-r--r--libsolidity/codegen/ExpressionCompiler.cpp22
-rw-r--r--test/libsolidity/SolidityCompiler.cpp60
5 files changed, 89 insertions, 6 deletions
diff --git a/Changelog.md b/Changelog.md
index c5577b86..aa1554f5 100644
--- a/Changelog.md
+++ b/Changelog.md
@@ -5,6 +5,7 @@ Features:
Bugfixes:
* Code Generator: Allow ``block.blockhash`` without being called.
+ * Code Generator: Do not include internal functions in the runtime bytecode which are only referenced in the constructor.
* Code Generator: Properly skip unneeded storage array cleanup when not reducing length.
* Code Generator: Bugfix in modifier lookup in libraries.
* Commandline interface: Support ``--evm-version constantinople`` properly.
diff --git a/libsolidity/codegen/CompilerUtils.cpp b/libsolidity/codegen/CompilerUtils.cpp
index 1bd1103b..68f0b3a1 100644
--- a/libsolidity/codegen/CompilerUtils.cpp
+++ b/libsolidity/codegen/CompilerUtils.cpp
@@ -585,7 +585,7 @@ void CompilerUtils::combineExternalFunctionType(bool _leftAligned)
leftShiftNumberOnStack(64);
}
-void CompilerUtils::pushCombinedFunctionEntryLabel(Declaration const& _function)
+void CompilerUtils::pushCombinedFunctionEntryLabel(Declaration const& _function, bool _runtimeOnly)
{
m_context << m_context.functionEntryLabel(_function).pushTag();
// If there is a runtime context, we have to merge both labels into the same
@@ -593,9 +593,10 @@ void CompilerUtils::pushCombinedFunctionEntryLabel(Declaration const& _function)
if (CompilerContext* rtc = m_context.runtimeContext())
{
leftShiftNumberOnStack(32);
- m_context <<
- rtc->functionEntryLabel(_function).toSubAssemblyTag(m_context.runtimeSub()) <<
- Instruction::OR;
+ if (_runtimeOnly)
+ m_context <<
+ rtc->functionEntryLabel(_function).toSubAssemblyTag(m_context.runtimeSub()) <<
+ Instruction::OR;
}
}
diff --git a/libsolidity/codegen/CompilerUtils.h b/libsolidity/codegen/CompilerUtils.h
index 76670d47..389673ef 100644
--- a/libsolidity/codegen/CompilerUtils.h
+++ b/libsolidity/codegen/CompilerUtils.h
@@ -188,7 +188,8 @@ public:
/// Appends code that combines the construction-time (if available) and runtime function
/// entry label of the given function into a single stack slot.
/// Note: This might cause the compilation queue of the runtime context to be extended.
- void pushCombinedFunctionEntryLabel(Declaration const& _function);
+ /// If @a _runtimeOnly, the entry label will include the runtime assembly tag.
+ void pushCombinedFunctionEntryLabel(Declaration const& _function, bool _runtimeOnly = true);
/// Appends code for an implicit or explicit type conversion. This includes erasing higher
/// order bits (@see appendHighBitCleanup) when widening integer but also copy to memory
diff --git a/libsolidity/codegen/ExpressionCompiler.cpp b/libsolidity/codegen/ExpressionCompiler.cpp
index 37069c3e..9e2d30d5 100644
--- a/libsolidity/codegen/ExpressionCompiler.cpp
+++ b/libsolidity/codegen/ExpressionCompiler.cpp
@@ -518,7 +518,23 @@ bool ExpressionCompiler::visit(FunctionCall const& _functionCall)
arguments[i]->accept(*this);
utils().convertType(*arguments[i]->annotation().type, *function.parameterTypes()[i]);
}
- _functionCall.expression().accept(*this);
+
+ {
+ bool shortcutTaken = false;
+ if (auto identifier = dynamic_cast<Identifier const*>(&_functionCall.expression()))
+ if (auto functionDef = dynamic_cast<FunctionDefinition const*>(identifier->annotation().referencedDeclaration))
+ {
+ // Do not directly visit the identifier, because this way, we can avoid
+ // the runtime entry label to be created at the creation time context.
+ CompilerContext::LocationSetter locationSetter2(m_context, *identifier);
+ utils().pushCombinedFunctionEntryLabel(m_context.resolveVirtualFunction(*functionDef), false);
+ shortcutTaken = true;
+ }
+
+ if (!shortcutTaken)
+ _functionCall.expression().accept(*this);
+ }
+
unsigned parameterSize = CompilerUtils::sizeOnStack(function.parameterTypes());
if (function.bound())
{
@@ -1359,6 +1375,10 @@ void ExpressionCompiler::endVisit(Identifier const& _identifier)
}
}
else if (FunctionDefinition const* functionDef = dynamic_cast<FunctionDefinition const*>(declaration))
+ // If the identifier is called right away, this code is executed in visit(FunctionCall...), because
+ // we want to avoid having a reference to the runtime function entry point in the
+ // constructor context, since this would force the compiler to include unreferenced
+ // internal functions in the runtime contex.
utils().pushCombinedFunctionEntryLabel(m_context.resolveVirtualFunction(*functionDef));
else if (auto variable = dynamic_cast<VariableDeclaration const*>(declaration))
appendVariable(*variable, static_cast<Expression const&>(_identifier));
diff --git a/test/libsolidity/SolidityCompiler.cpp b/test/libsolidity/SolidityCompiler.cpp
new file mode 100644
index 00000000..e87ab603
--- /dev/null
+++ b/test/libsolidity/SolidityCompiler.cpp
@@ -0,0 +1,60 @@
+/*
+ This file is part of solidity.
+
+ solidity is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ solidity is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with solidity. If not, see <http://www.gnu.org/licenses/>.
+ */
+/**
+ * Unit tests for the compiler itself.
+ */
+
+#include <test/libsolidity/AnalysisFramework.h>
+
+#include <test/Options.h>
+
+using namespace std;
+
+namespace dev
+{
+namespace solidity
+{
+namespace test
+{
+
+BOOST_FIXTURE_TEST_SUITE(Compiler, AnalysisFramework)
+
+BOOST_AUTO_TEST_CASE(does_not_include_creation_time_only_internal_functions)
+{
+ char const* sourceCode = R"(
+ contract C {
+ uint x;
+ function C() { f(); }
+ function f() internal { for (uint i = 0; i < 10; ++i) x += 3 + i; }
+ }
+ )";
+ BOOST_REQUIRE(success(sourceCode));
+ m_compiler.setOptimiserSettings(dev::test::Options::get().optimize);
+ BOOST_REQUIRE_MESSAGE(m_compiler.compile(), "Compiling contract failed");
+ bytes const& creationBytecode = m_compiler.object("C").bytecode;
+ bytes const& runtimeBytecode = m_compiler.runtimeObject("C").bytecode;
+ BOOST_CHECK(creationBytecode.size() >= 120);
+ BOOST_CHECK(creationBytecode.size() <= 150);
+ BOOST_CHECK(runtimeBytecode.size() >= 50);
+ BOOST_CHECK(runtimeBytecode.size() <= 70);
+}
+
+BOOST_AUTO_TEST_SUITE_END()
+
+}
+}
+}