aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRJ Catalano <rj@erisindustries.com>2017-01-25 03:05:51 +0800
committerGitHub <noreply@github.com>2017-01-25 03:05:51 +0800
commitba9a04500217e301bec63cab4e0c0f1d9322646d (patch)
tree27f954262b0a12670ac0780e8e19da08c204b3fb
parent3dc83aa34e83d668cde82953f9efa94ebb7de8ed (diff)
parentead1a3b33fae83ad65210d6f82b2ca12150bf2bb (diff)
downloaddexon-solidity-ba9a04500217e301bec63cab4e0c0f1d9322646d.tar.gz
dexon-solidity-ba9a04500217e301bec63cab4e0c0f1d9322646d.tar.zst
dexon-solidity-ba9a04500217e301bec63cab4e0c0f1d9322646d.zip
Merge pull request #1595 from ethereum/noDuplicatedContracts
Include bytecode of created contracts only once.
-rw-r--r--libsolidity/codegen/ExpressionCompiler.cpp32
-rw-r--r--test/libsolidity/SolidityEndToEndTest.cpp29
2 files changed, 47 insertions, 14 deletions
diff --git a/libsolidity/codegen/ExpressionCompiler.cpp b/libsolidity/codegen/ExpressionCompiler.cpp
index 81d3409e..fe0eeb1c 100644
--- a/libsolidity/codegen/ExpressionCompiler.cpp
+++ b/libsolidity/codegen/ExpressionCompiler.cpp
@@ -556,20 +556,24 @@ bool ExpressionCompiler::visit(FunctionCall const& _functionCall)
arg->accept(*this);
argumentTypes.push_back(arg->annotation().type);
}
- ContractDefinition const& contract =
- dynamic_cast<ContractType const&>(*function.returnParameterTypes().front()).contractDefinition();
- // copy the contract's code into memory
- eth::Assembly const& assembly = m_context.compiledContract(contract);
- utils().fetchFreeMemoryPointer();
- // TODO we create a copy here, which is actually what we want.
- // This should be revisited at the point where we fix
- // https://github.com/ethereum/solidity/issues/1092
- // pushes size
- auto subroutine = m_context.addSubroutine(make_shared<eth::Assembly>(assembly));
- m_context << Instruction::DUP1 << subroutine;
- m_context << Instruction::DUP4 << Instruction::CODECOPY;
-
- m_context << Instruction::ADD;
+ ContractDefinition const* contract =
+ &dynamic_cast<ContractType const&>(*function.returnParameterTypes().front()).contractDefinition();
+ m_context.callLowLevelFunction(
+ "$copyContractCreationCodeToMemory_" + contract->type()->identifier(),
+ 0,
+ 1,
+ [contract](CompilerContext& _context)
+ {
+ // copy the contract's code into memory
+ eth::Assembly const& assembly = _context.compiledContract(*contract);
+ CompilerUtils(_context).fetchFreeMemoryPointer();
+ // pushes size
+ auto subroutine = _context.addSubroutine(make_shared<eth::Assembly>(assembly));
+ _context << Instruction::DUP1 << subroutine;
+ _context << Instruction::DUP4 << Instruction::CODECOPY;
+ _context << Instruction::ADD;
+ }
+ );
utils().encodeToMemory(argumentTypes, function.parameterTypes());
// now on stack: memory_end_ptr
// need: size, offset, endowment
diff --git a/test/libsolidity/SolidityEndToEndTest.cpp b/test/libsolidity/SolidityEndToEndTest.cpp
index e8e5ced1..646017fb 100644
--- a/test/libsolidity/SolidityEndToEndTest.cpp
+++ b/test/libsolidity/SolidityEndToEndTest.cpp
@@ -8992,6 +8992,35 @@ BOOST_AUTO_TEST_CASE(contracts_separated_with_comment)
compileAndRun(sourceCode, 0, "C2");
}
+BOOST_AUTO_TEST_CASE(include_creation_bytecode_only_once)
+{
+ char const* sourceCode = R"(
+ contract D {
+ bytes a = hex"1237651237125387136581271652831736512837126583171583712358126123765123712538713658127165283173651283712658317158371235812612376512371253871365812716528317365128371265831715837123581261237651237125387136581271652831736512837126583171583712358126";
+ bytes b = hex"1237651237125327136581271252831736512837126583171383712358126123765125712538713658127165253173651283712658357158371235812612376512371a5387136581271652a317365128371265a317158371235812612a765123712538a13658127165a83173651283712a58317158371235a126";
+ function D(uint) {}
+ }
+ contract Double {
+ function f() {
+ new D(2);
+ }
+ function g() {
+ new D(3);
+ }
+ }
+ contract Single {
+ function f() {
+ new D(2);
+ }
+ }
+ )";
+ compileAndRun(sourceCode);
+ BOOST_CHECK_LE(
+ double(m_compiler.object("Double").bytecode.size()),
+ 1.1 * double(m_compiler.object("Single").bytecode.size())
+ );
+}
+
BOOST_AUTO_TEST_CASE(recursive_structs)
{
char const* sourceCode = R"(