Merge pull request #6002 from ethereum/arrayTypeStride

Add stride helpers to ArrayType.
This commit is contained in:
Daniel Kirchner 2019-02-14 14:30:57 +01:00 committed by GitHub
commit 690edc8bc9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 12 additions and 6 deletions

View File

@ -736,6 +736,13 @@ public:
TypePointer copyForLocation(DataLocation _location, bool _isPointer) const override; TypePointer copyForLocation(DataLocation _location, bool _isPointer) const override;
/// The offset to advance in calldata to move from one array element to the next.
unsigned calldataStride() const { return isByteArray() ? 1 : m_baseType->calldataEncodedSize(); }
/// The offset to advance in memory to move from one array element to the next.
unsigned memoryStride() const { return isByteArray() ? 1 : m_baseType->memoryHeadSize(); }
/// The offset to advance in storage to move from one array element to the next.
unsigned storageStride() const { return isByteArray() ? 1 : m_baseType->storageBytes(); }
private: private:
/// String is interpreted as a subtype of Bytes. /// String is interpreted as a subtype of Bytes.
enum class ArrayKind { Ordinary, Bytes, String }; enum class ArrayKind { Ordinary, Bytes, String };

View File

@ -623,7 +623,7 @@ void ArrayUtils::clearDynamicArray(ArrayType const& _type) const
m_context << Instruction::SWAP1 << Instruction::DUP2 << Instruction::ADD m_context << Instruction::SWAP1 << Instruction::DUP2 << Instruction::ADD
<< Instruction::SWAP1; << Instruction::SWAP1;
// stack: data_pos_end data_pos // stack: data_pos_end data_pos
if (_type.isByteArray() || _type.baseType()->storageBytes() < 32) if (_type.storageStride() < 32)
clearStorageLoop(make_shared<IntegerType>(256)); clearStorageLoop(make_shared<IntegerType>(256));
else else
clearStorageLoop(_type.baseType()); clearStorageLoop(_type.baseType());
@ -769,7 +769,7 @@ void ArrayUtils::resizeDynamicArray(ArrayType const& _typeIn) const
// stack: ref new_length data_pos new_size delete_end // stack: ref new_length data_pos new_size delete_end
_context << Instruction::SWAP2 << Instruction::ADD; _context << Instruction::SWAP2 << Instruction::ADD;
// stack: ref new_length delete_end delete_start // stack: ref new_length delete_end delete_start
if (_type.isByteArray() || _type.baseType()->storageBytes() < 32) if (_type.storageStride() < 32)
ArrayUtils(_context).clearStorageLoop(make_shared<IntegerType>(256)); ArrayUtils(_context).clearStorageLoop(make_shared<IntegerType>(256));
else else
ArrayUtils(_context).clearStorageLoop(_type.baseType()); ArrayUtils(_context).clearStorageLoop(_type.baseType());

View File

@ -243,7 +243,7 @@ void CompilerUtils::abiDecode(TypePointers const& _typeParameters, bool _fromMem
gt(add(array_data_start, mul(array_length, <item_size>)), input_end) gt(add(array_data_start, mul(array_length, <item_size>)), input_end)
) { revert(0, 0) } ) { revert(0, 0) }
})"); })");
templ("item_size", to_string(arrayType.isByteArray() ? 1 : arrayType.baseType()->calldataEncodedSize(true))); templ("item_size", to_string(arrayType.calldataStride()));
m_context.appendInlineAssembly(templ.render(), {"input_end", "base_offset", "offset", "ptr"}); m_context.appendInlineAssembly(templ.render(), {"input_end", "base_offset", "offset", "ptr"});
// stack: v1 v2 ... v(k-1) input_end base_offset current_offset v(k) // stack: v1 v2 ... v(k-1) input_end base_offset current_offset v(k)
moveIntoStack(3); moveIntoStack(3);
@ -279,11 +279,10 @@ void CompilerUtils::abiDecode(TypePointers const& _typeParameters, bool _fromMem
// stack: input_end base_offset next_pointer array_length data_pointer // stack: input_end base_offset next_pointer array_length data_pointer
m_context << Instruction::SWAP2; m_context << Instruction::SWAP2;
// stack: input_end base_offset data_pointer array_length next_pointer // stack: input_end base_offset data_pointer array_length next_pointer
unsigned itemSize = arrayType.isByteArray() ? 1 : arrayType.baseType()->calldataEncodedSize(true);
m_context.appendInlineAssembly(R"({ m_context.appendInlineAssembly(R"({
if or( if or(
gt(array_length, 0x100000000), gt(array_length, 0x100000000),
gt(add(data_ptr, mul(array_length, )" + to_string(itemSize) + R"()), input_end) gt(add(data_ptr, mul(array_length, )" + to_string(arrayType.calldataStride()) + R"()), input_end)
) { revert(0, 0) } ) { revert(0, 0) }
})", {"input_end", "base_offset", "data_ptr", "array_length", "next_ptr"}); })", {"input_end", "base_offset", "data_ptr", "array_length", "next_ptr"});
} }
@ -517,7 +516,7 @@ void CompilerUtils::zeroInitialiseMemoryArray(ArrayType const& _type)
codecopy(memptr, codesize(), size) codecopy(memptr, codesize(), size)
memptr := add(memptr, size) memptr := add(memptr, size)
})"); })");
templ("element_size", to_string(_type.isByteArray() ? 1 : _type.baseType()->memoryHeadSize())); templ("element_size", to_string(_type.memoryStride()));
m_context.appendInlineAssembly(templ.render(), {"length", "memptr"}); m_context.appendInlineAssembly(templ.render(), {"length", "memptr"});
} }
else else