diff options
author | chriseth <c@ethdev.com> | 2015-03-14 02:48:24 +0800 |
---|---|---|
committer | chriseth <c@ethdev.com> | 2015-03-17 01:07:14 +0800 |
commit | 02595abf6ac1c30c7c0125c5a705cd2c85974838 (patch) | |
tree | b824309b77c9be95bd81b50e6e4cc6b457b3b9a9 /Types.cpp | |
parent | 7f64584b7fb151459500ade84612d3cd48f13f18 (diff) | |
download | dexon-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.cpp | 99 |
1 files changed, 55 insertions, 44 deletions
@@ -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 |