aboutsummaryrefslogtreecommitdiffstats
path: root/libevmasm
diff options
context:
space:
mode:
authorchriseth <c@ethdev.com>2016-11-11 18:41:50 +0800
committerchriseth <c@ethdev.com>2016-11-16 21:37:18 +0800
commite51f852504556f952ae1350c070409e3c4981cc0 (patch)
tree245a5605753ceca004513945a88f33fbc8fed81b /libevmasm
parente543bd34c0b4884b5a27555f698f50af6a1c0b81 (diff)
downloaddexon-solidity-e51f852504556f952ae1350c070409e3c4981cc0.tar
dexon-solidity-e51f852504556f952ae1350c070409e3c4981cc0.tar.gz
dexon-solidity-e51f852504556f952ae1350c070409e3c4981cc0.tar.bz2
dexon-solidity-e51f852504556f952ae1350c070409e3c4981cc0.tar.lz
dexon-solidity-e51f852504556f952ae1350c070409e3c4981cc0.tar.xz
dexon-solidity-e51f852504556f952ae1350c070409e3c4981cc0.tar.zst
dexon-solidity-e51f852504556f952ae1350c070409e3c4981cc0.zip
Converted sub assembly to smart pointer.
Diffstat (limited to 'libevmasm')
-rw-r--r--libevmasm/Assembly.cpp54
-rw-r--r--libevmasm/Assembly.h33
-rw-r--r--libevmasm/AssemblyItem.cpp12
3 files changed, 62 insertions, 37 deletions
diff --git a/libevmasm/Assembly.cpp b/libevmasm/Assembly.cpp
index 23a8180b..0ee3f421 100644
--- a/libevmasm/Assembly.cpp
+++ b/libevmasm/Assembly.cpp
@@ -75,17 +75,17 @@ string Assembly::out() const
return ret.str();
}
-unsigned Assembly::bytesRequired() const
+unsigned Assembly::bytesRequired(unsigned subTagSize) const
{
- for (unsigned br = 1;; ++br)
+ for (unsigned tagSize = subTagSize;; ++tagSize)
{
unsigned ret = 1;
for (auto const& i: m_data)
ret += i.second.size();
for (AssemblyItem const& i: m_items)
- ret += i.bytesRequired(br);
- if (dev::bytesRequired(ret) <= br)
+ ret += i.bytesRequired(tagSize);
+ if (dev::bytesRequired(ret) <= tagSize)
return ret;
}
}
@@ -132,13 +132,19 @@ ostream& Assembly::streamAsm(ostream& _out, string const& _prefix, StringMap con
if (i.data() == 0)
_out << " PUSH [ErrorTag]";
else
- _out << " PUSH [tag" << dec << i.data() << "]";
+ {
+ size_t subId = i.splitForeignPushTag().first;
+ if (subId == size_t(-1))
+ _out << " PUSH [tag" << dec << i.splitForeignPushTag().second << "]";
+ else
+ _out << " PUSH [tag" << dec << subId << ":" << i.splitForeignPushTag().second << "]";
+ }
break;
case PushSub:
- _out << " PUSH [$" << h256(i.data()).abridgedMiddle() << "]";
+ _out << " PUSH [$" << size_t(i.data()) << "]";
break;
case PushSubSize:
- _out << " PUSH #[$" << h256(i.data()).abridgedMiddle() << "]";
+ _out << " PUSH #[$" << size_t(i.data()) << "]";
break;
case PushProgramSize:
_out << " PUSHSIZE";
@@ -167,7 +173,7 @@ ostream& Assembly::streamAsm(ostream& _out, string const& _prefix, StringMap con
for (size_t i = 0; i < m_subs.size(); ++i)
{
_out << _prefix << " " << hex << i << ": " << endl;
- m_subs[i].stream(_out, _prefix + " ", _sourceCodes);
+ m_subs[i]->stream(_out, _prefix + " ", _sourceCodes);
}
}
return _out;
@@ -266,7 +272,7 @@ Json::Value Assembly::streamAsmJson(ostream& _out, StringMap const& _sourceCodes
{
std::stringstream hexStr;
hexStr << hex << i;
- data[hexStr.str()] = m_subs[i].stream(_out, "", _sourceCodes, true);
+ data[hexStr.str()] = m_subs[i]->stream(_out, "", _sourceCodes, true);
}
root[".data"] = data;
_out << root;
@@ -317,7 +323,7 @@ map<u256, u256> Assembly::optimiseInternal(bool _isCreation, size_t _runs)
{
for (size_t subId = 0; subId < m_subs.size(); ++subId)
{
- map<u256, u256> subTagReplacements = m_subs[subId].optimiseInternal(false, _runs);
+ map<u256, u256> subTagReplacements = m_subs[subId]->optimiseInternal(false, _runs);
BlockDeduplicator::applyTagReplacement(m_items, subTagReplacements, subId);
}
@@ -385,7 +391,11 @@ map<u256, u256> Assembly::optimiseInternal(bool _isCreation, size_t _runs)
}
iter = end;
}
-
+ if (optimisedItems.size() < m_items.size())
+ {
+ m_items = move(optimisedItems);
+ count++;
+ }
}
}
@@ -404,20 +414,28 @@ LinkerObject const& Assembly::assemble() const
if (!m_assembledObject.bytecode.empty())
return m_assembledObject;
+ size_t subTagSize = 1;
+ for (auto const& sub: m_subs)
+ {
+ sub->assemble();
+ if (!sub->m_tagPositionsInBytecode.empty())
+ subTagSize = max(subTagSize, *max_element(sub->m_tagPositionsInBytecode.begin(), sub->m_tagPositionsInBytecode.end()));
+ }
+
LinkerObject& ret = m_assembledObject;
- unsigned totalBytes = bytesRequired();
+ size_t bytesRequiredForCode = bytesRequired(subTagSize);
m_tagPositionsInBytecode = vector<size_t>(m_usedTags, -1);
map<size_t, pair<size_t, size_t>> tagRef;
multimap<h256, unsigned> dataRef;
multimap<size_t, size_t> subRef;
vector<unsigned> sizeRef; ///< Pointers to code locations where the size of the program is inserted
- unsigned bytesPerTag = dev::bytesRequired(totalBytes);
+ unsigned bytesPerTag = dev::bytesRequired(bytesRequiredForCode);
byte tagPush = (byte)Instruction::PUSH1 - 1 + bytesPerTag;
- unsigned bytesRequiredIncludingData = bytesRequired();
+ unsigned bytesRequiredIncludingData = bytesRequiredForCode + 1;
for (auto const& sub: m_subs)
- bytesRequiredIncludingData += sub.assemble().bytecode.size();
+ bytesRequiredIncludingData += sub->assemble().bytecode.size();
unsigned bytesPerDataRef = dev::bytesRequired(bytesRequiredIncludingData);
byte dataRefPush = (byte)Instruction::PUSH1 - 1 + bytesPerDataRef;
@@ -475,7 +493,7 @@ LinkerObject const& Assembly::assemble() const
break;
case PushSubSize:
{
- auto s = m_subs.at(size_t(i.data())).assemble().bytecode.size();
+ auto s = m_subs.at(size_t(i.data()))->assemble().bytecode.size();
i.setPushedValue(u256(s));
byte b = max<unsigned>(1, dev::bytesRequired(s));
ret.bytecode.push_back((byte)Instruction::PUSH1 - 1 + b);
@@ -520,7 +538,7 @@ LinkerObject const& Assembly::assemble() const
bytesRef r(ret.bytecode.data() + ref->second, bytesPerDataRef);
toBigEndian(ret.bytecode.size(), r);
}
- ret.append(m_subs[i].assemble());
+ ret.append(m_subs[i]->assemble());
}
for (auto const& i: tagRef)
{
@@ -531,7 +549,7 @@ LinkerObject const& Assembly::assemble() const
std::vector<size_t> const& tagPositions =
subId == size_t(-1) ?
m_tagPositionsInBytecode :
- m_subs[subId].m_tagPositionsInBytecode;
+ m_subs[subId]->m_tagPositionsInBytecode;
assertThrow(tagId < tagPositions.size(), AssemblyException, "Reference to non-existing tag.");
size_t pos = tagPositions[tagId];
assertThrow(pos != size_t(-1), AssemblyException, "Reference to tag without position.");
diff --git a/libevmasm/Assembly.h b/libevmasm/Assembly.h
index 0ae81e1d..3ce82cce 100644
--- a/libevmasm/Assembly.h
+++ b/libevmasm/Assembly.h
@@ -14,30 +14,32 @@
You should have received a copy of the GNU General Public License
along with cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
*/
-/** @file Assembly.h
- * @author Gav Wood <i@gavwood.com>
- * @date 2014
- */
#pragma once
-#include <iostream>
-#include <sstream>
-#include <libdevcore/Common.h>
-#include <libdevcore/Assertions.h>
-#include <libdevcore/SHA3.h>
#include <libevmasm/Instruction.h>
#include <libevmasm/SourceLocation.h>
#include <libevmasm/AssemblyItem.h>
#include <libevmasm/LinkerObject.h>
-#include "Exceptions.h"
+#include <libevmasm/Exceptions.h>
+
+#include <libdevcore/Common.h>
+#include <libdevcore/Assertions.h>
+#include <libdevcore/SHA3.h>
+
#include <json/json.h>
+#include <iostream>
+#include <sstream>
+#include <memory>
+
namespace dev
{
namespace eth
{
+using AssemblyPointer = std::shared_ptr<Assembly>;
+
class Assembly
{
public:
@@ -46,9 +48,9 @@ public:
AssemblyItem newTag() { return AssemblyItem(Tag, m_usedTags++); }
AssemblyItem newPushTag() { return AssemblyItem(PushTag, m_usedTags++); }
AssemblyItem newData(bytes const& _data) { h256 h(dev::keccak256(asString(_data))); m_data[h] = _data; return AssemblyItem(PushData, h); }
- AssemblyItem newSub(Assembly const& _sub) { m_subs.push_back(_sub); return AssemblyItem(PushSub, m_subs.size() - 1); }
- Assembly const& sub(size_t _sub) const { return m_subs.at(_sub); }
- Assembly& sub(size_t _sub) { return m_subs.at(_sub); }
+ AssemblyItem newSub(AssemblyPointer const& _sub) { m_subs.push_back(_sub); return AssemblyItem(PushSub, m_subs.size() - 1); }
+ Assembly const& sub(size_t _sub) const { return *m_subs.at(_sub); }
+ Assembly& sub(size_t _sub) { return *m_subs.at(_sub); }
AssemblyItem newPushString(std::string const& _data) { h256 h(dev::keccak256(_data)); m_strings[h] = _data; return AssemblyItem(PushString, h); }
AssemblyItem newPushSubSize(u256 const& _subId) { return AssemblyItem(PushSubSize, _subId); }
AssemblyItem newPushLibraryAddress(std::string const& _identifier);
@@ -58,7 +60,6 @@ public:
AssemblyItem const& append(AssemblyItem const& _i);
AssemblyItem const& append(std::string const& _data) { return append(newPushString(_data)); }
AssemblyItem const& append(bytes const& _data) { return append(newData(_data)); }
- AssemblyItem appendSubSize(Assembly const& _a) { auto ret = newSub(_a); append(newPushSubSize(ret.data())); return ret; }
/// Pushes the final size of the current assembly itself. Use this when the code is modified
/// after compilation and CODESIZE is not an option.
void appendProgramSize() { append(AssemblyItem(PushProgramSize)); }
@@ -115,7 +116,7 @@ protected:
std::string locationFromSources(StringMap const& _sourceCodes, SourceLocation const& _location) const;
void donePath() { if (m_totalDeposit != INT_MAX && m_totalDeposit != m_deposit) BOOST_THROW_EXCEPTION(InvalidDeposit()); }
- unsigned bytesRequired() const;
+ unsigned bytesRequired(unsigned subTagSize) const;
private:
Json::Value streamAsmJson(std::ostream& _out, StringMap const& _sourceCodes) const;
@@ -127,7 +128,7 @@ protected:
unsigned m_usedTags = 1;
AssemblyItems m_items;
std::map<h256, bytes> m_data;
- std::vector<Assembly> m_subs;
+ std::vector<std::shared_ptr<Assembly>> m_subs;
std::map<h256, std::string> m_strings;
std::map<h256, std::string> m_libraries; ///< Identifiers of libraries to be linked.
diff --git a/libevmasm/AssemblyItem.cpp b/libevmasm/AssemblyItem.cpp
index 2eae20af..bc8c87aa 100644
--- a/libevmasm/AssemblyItem.cpp
+++ b/libevmasm/AssemblyItem.cpp
@@ -127,8 +127,14 @@ ostream& dev::eth::operator<<(ostream& _out, AssemblyItem const& _item)
_out << " PushString" << hex << (unsigned)_item.data();
break;
case PushTag:
- _out << " PushTag " << _item.data();
+ {
+ size_t subId = _item.splitForeignPushTag().first;
+ if (subId == size_t(-1))
+ _out << " PushTag " << _item.splitForeignPushTag().second;
+ else
+ _out << " PushTag " << subId << ":" << _item.splitForeignPushTag().second;
break;
+ }
case Tag:
_out << " Tag " << _item.data();
break;
@@ -136,10 +142,10 @@ ostream& dev::eth::operator<<(ostream& _out, AssemblyItem const& _item)
_out << " PushData " << hex << (unsigned)_item.data();
break;
case PushSub:
- _out << " PushSub " << hex << h256(_item.data()).abridgedMiddle();
+ _out << " PushSub " << hex << size_t(_item.data());
break;
case PushSubSize:
- _out << " PushSubSize " << hex << h256(_item.data()).abridgedMiddle();
+ _out << " PushSubSize " << hex << size_t(_item.data());
break;
case PushProgramSize:
_out << " PushProgramSize";