aboutsummaryrefslogtreecommitdiffstats
path: root/Types.cpp
diff options
context:
space:
mode:
authorchriseth <c@ethdev.com>2015-03-14 02:48:24 +0800
committerchriseth <c@ethdev.com>2015-03-17 01:07:14 +0800
commit02595abf6ac1c30c7c0125c5a705cd2c85974838 (patch)
treeb824309b77c9be95bd81b50e6e4cc6b457b3b9a9 /Types.cpp
parent7f64584b7fb151459500ade84612d3cd48f13f18 (diff)
downloaddexon-solidity-02595abf6ac1c30c7c0125c5a705cd2c85974838.tar.gz
dexon-solidity-02595abf6ac1c30c7c0125c5a705cd2c85974838.tar.zst
dexon-solidity-02595abf6ac1c30c7c0125c5a705cd2c85974838.zip
Fetch and store packed values.
Diffstat (limited to 'Types.cpp')
-rw-r--r--Types.cpp99
1 files changed, 55 insertions, 44 deletions
diff --git a/Types.cpp b/Types.cpp
index 500ae9b0..147eff1e 100644
--- a/Types.cpp
+++ b/Types.cpp
@@ -35,54 +35,72 @@ namespace dev
namespace solidity
{
-std::pair<u256, unsigned> const* MemberList::getMemberStorageOffset(string const& _name) const
+void StorageOffsets::computeOffsets(TypePointers const& _types)
{
- if (!m_storageOffsets)
+ bigint slotOffset = 0;
+ unsigned byteOffset = 0;
+ map<size_t, pair<u256, unsigned>> offsets;
+ for (size_t i = 0; i < _types.size(); ++i)
{
- bigint slotOffset = 0;
- unsigned byteOffset = 0;
- map<string, pair<u256, unsigned>> offsets;
- for (auto const& nameAndType: m_memberTypes)
+ TypePointer const& type = _types[i];
+ if (!type->canBeStored())
+ continue;
+ if (byteOffset + type->getStorageBytes() > 32)
{
- TypePointer const& type = nameAndType.second;
- if (!type->canBeStored())
- continue;
- if (byteOffset + type->getStorageBytes() > 32)
- {
- // would overflow, go to next slot
- ++slotOffset;
- byteOffset = 0;
- }
- if (slotOffset >= bigint(1) << 256)
- BOOST_THROW_EXCEPTION(TypeError() << errinfo_comment("Object too large for storage."));
- offsets[nameAndType.first] = make_pair(u256(slotOffset), byteOffset);
- solAssert(type->getStorageSize() >= 1, "Invalid storage size.");
- if (type->getStorageSize() == 1 && byteOffset + type->getStorageBytes() <= 32)
- byteOffset += type->getStorageBytes();
- else
- {
- slotOffset += type->getStorageSize();
- byteOffset = 0;
- }
- }
- if (byteOffset > 0)
+ // would overflow, go to next slot
++slotOffset;
+ byteOffset = 0;
+ }
if (slotOffset >= bigint(1) << 256)
BOOST_THROW_EXCEPTION(TypeError() << errinfo_comment("Object too large for storage."));
- m_storageSize = u256(slotOffset);
- m_storageOffsets.reset(new decltype(offsets)(move(offsets)));
+ offsets[i] = make_pair(u256(slotOffset), byteOffset);
+ solAssert(type->getStorageSize() >= 1, "Invalid storage size.");
+ if (type->getStorageSize() == 1 && byteOffset + type->getStorageBytes() <= 32)
+ byteOffset += type->getStorageBytes();
+ else
+ {
+ slotOffset += type->getStorageSize();
+ byteOffset = 0;
+ }
}
- if (m_storageOffsets->count(_name))
- return &((*m_storageOffsets)[_name]);
+ if (byteOffset > 0)
+ ++slotOffset;
+ if (slotOffset >= bigint(1) << 256)
+ BOOST_THROW_EXCEPTION(TypeError() << errinfo_comment("Object too large for storage."));
+ m_storageSize = u256(slotOffset);
+ swap(m_offsets, offsets);
+}
+
+pair<u256, unsigned> const* StorageOffsets::getOffset(size_t _index) const
+{
+ if (m_offsets.count(_index))
+ return &m_offsets.at(_index);
else
return nullptr;
}
+std::pair<u256, unsigned> const* MemberList::getMemberStorageOffset(string const& _name) const
+{
+ if (!m_storageOffsets)
+ {
+ TypePointers memberTypes;
+ memberTypes.reserve(m_memberTypes.size());
+ for (auto const& nameAndType: m_memberTypes)
+ memberTypes.push_back(nameAndType.second);
+ m_storageOffsets.reset(new StorageOffsets());
+ m_storageOffsets->computeOffsets(memberTypes);
+ }
+ for (size_t index = 0; index < m_memberTypes.size(); ++index)
+ if (m_memberTypes[index].first == _name)
+ return m_storageOffsets->getOffset(index);
+ return nullptr;
+}
+
u256 const& MemberList::getStorageSize() const
{
// trigger lazy computation
getMemberStorageOffset("");
- return m_storageSize;
+ return m_storageOffsets->getStorageSize();
}
TypePointer Type::fromElementaryTypeName(Token::Value _typeToken)
@@ -830,18 +848,11 @@ MemberList const& StructType::getMembers() const
return *m_members;
}
-u256 StructType::getStorageOffsetOfMember(string const& _name) const
+pair<u256, unsigned> const& StructType::getStorageOffsetsOfMember(string const& _name) const
{
-
- //@todo cache member offset?
- u256 offset;
- for (ASTPointer<VariableDeclaration> const& variable: m_struct.getMembers())
- {
- if (variable->getName() == _name)
- return offset;
- offset += variable->getType()->getStorageSize();
- }
- BOOST_THROW_EXCEPTION(InternalCompilerError() << errinfo_comment("Storage offset of non-existing member requested."));
+ auto const* offsets = getMembers().getMemberStorageOffset(_name);
+ solAssert(offsets, "Storage offset of non-existing member requested.");
+ return *offsets;
}
TypePointer EnumType::unaryOperatorResult(Token::Value _operator) const