diff options
author | chriseth <c@ethdev.com> | 2015-03-20 19:54:36 +0800 |
---|---|---|
committer | chriseth <c@ethdev.com> | 2015-03-20 19:54:36 +0800 |
commit | 8f8e407306172ab75f5b200c1f1df87bb55fa2a6 (patch) | |
tree | e6ad2ca4d4662d280743eb23bd774dc5bcd20adb /Types.cpp | |
parent | 9e29d9797c75d6f3d3fbe0630d0af5e76fcf3afa (diff) | |
parent | dba9dd1169d0b8a02287434c0499ccc4a16d97bc (diff) | |
download | dexon-solidity-8f8e407306172ab75f5b200c1f1df87bb55fa2a6.tar.gz dexon-solidity-8f8e407306172ab75f5b200c1f1df87bb55fa2a6.tar.zst dexon-solidity-8f8e407306172ab75f5b200c1f1df87bb55fa2a6.zip |
Merge pull request #1341 from chriseth/sol_packedStorage
Packed storage for arrays.
Diffstat (limited to 'Types.cpp')
-rw-r--r-- | Types.cpp | 46 |
1 files changed, 38 insertions, 8 deletions
@@ -20,14 +20,14 @@ * Solidity data types */ +#include <libsolidity/Types.h> +#include <limits> +#include <boost/range/adaptor/reversed.hpp> #include <libdevcore/CommonIO.h> #include <libdevcore/CommonData.h> #include <libsolidity/Utils.h> -#include <libsolidity/Types.h> #include <libsolidity/AST.h> -#include <limits> - using namespace std; namespace dev @@ -184,6 +184,8 @@ TypePointer Type::fromArrayTypeName(TypeName& _baseTypeName, Expression* _length TypePointer baseType = _baseTypeName.toType(); if (!baseType) BOOST_THROW_EXCEPTION(_baseTypeName.createTypeError("Invalid type name.")); + if (baseType->getStorageBytes() == 0) + BOOST_THROW_EXCEPTION(_baseTypeName.createTypeError("Illegal base type of storage size zero for array.")); if (_length) { if (!_length->getType()) @@ -700,13 +702,21 @@ u256 ArrayType::getStorageSize() const { if (isDynamicallySized()) return 1; - else + + bigint size; + unsigned baseBytes = getBaseType()->getStorageBytes(); + if (baseBytes == 0) + size = 1; + else if (baseBytes < 32) { - bigint size = bigint(getLength()) * getBaseType()->getStorageSize(); - if (size >= bigint(1) << 256) - BOOST_THROW_EXCEPTION(TypeError() << errinfo_comment("Array too large for storage.")); - return max<u256>(1, u256(size)); + unsigned itemsPerSlot = 32 / baseBytes; + size = (bigint(getLength()) + (itemsPerSlot - 1)) / itemsPerSlot; } + else + size = bigint(getLength()) * getBaseType()->getStorageSize(); + if (size >= bigint(1) << 256) + BOOST_THROW_EXCEPTION(TypeError() << errinfo_comment("Array too large for storage.")); + return max<u256>(1, u256(size)); } unsigned ArrayType::getSizeOnStack() const @@ -806,6 +816,26 @@ u256 ContractType::getFunctionIdentifier(string const& _functionName) const return Invalid256; } +vector<tuple<VariableDeclaration const*, u256, unsigned>> ContractType::getStateVariables() const +{ + vector<VariableDeclaration const*> variables; + for (ContractDefinition const* contract: boost::adaptors::reverse(m_contract.getLinearizedBaseContracts())) + for (ASTPointer<VariableDeclaration> const& variable: contract->getStateVariables()) + if (!variable->isConstant()) + variables.push_back(variable.get()); + TypePointers types; + for (auto variable: variables) + types.push_back(variable->getType()); + StorageOffsets offsets; + offsets.computeOffsets(types); + + vector<tuple<VariableDeclaration const*, u256, unsigned>> variablesAndOffsets; + for (size_t index = 0; index < variables.size(); ++index) + if (auto const* offset = offsets.getOffset(index)) + variablesAndOffsets.push_back(make_tuple(variables[index], offset->first, offset->second)); + return variablesAndOffsets; +} + TypePointer StructType::unaryOperatorResult(Token::Value _operator) const { return _operator == Token::Delete ? make_shared<VoidType>() : TypePointer(); |