mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-07-22 04:36:42 +00:00
Fix memory copy [Delivers #84703344]
This commit is contained in:
parent
43e08ea32d
commit
4254b3fec1
1 changed files with 20 additions and 14 deletions
|
|
@ -189,8 +189,6 @@ void Memory::require(llvm::Value* _offset, llvm::Value* _size)
|
||||||
void Memory::copyBytes(llvm::Value* _srcPtr, llvm::Value* _srcSize, llvm::Value* _srcIdx,
|
void Memory::copyBytes(llvm::Value* _srcPtr, llvm::Value* _srcSize, llvm::Value* _srcIdx,
|
||||||
llvm::Value* _destMemIdx, llvm::Value* _reqBytes)
|
llvm::Value* _destMemIdx, llvm::Value* _reqBytes)
|
||||||
{
|
{
|
||||||
auto zero256 = llvm::ConstantInt::get(Type::Word, 0);
|
|
||||||
|
|
||||||
require(_destMemIdx, _reqBytes);
|
require(_destMemIdx, _reqBytes);
|
||||||
|
|
||||||
// Additional copy cost
|
// Additional copy cost
|
||||||
|
|
@ -198,20 +196,28 @@ void Memory::copyBytes(llvm::Value* _srcPtr, llvm::Value* _srcSize, llvm::Value*
|
||||||
auto copyWords = m_builder.CreateUDiv(m_builder.CreateAdd(_reqBytes, Constant::get(31)), Constant::get(32));
|
auto copyWords = m_builder.CreateUDiv(m_builder.CreateAdd(_reqBytes, Constant::get(31)), Constant::get(32));
|
||||||
m_gasMeter.countCopy(copyWords);
|
m_gasMeter.countCopy(copyWords);
|
||||||
|
|
||||||
auto srcPtr = m_builder.CreateGEP(_srcPtr, _srcIdx, "src_idx");
|
// Algorithm:
|
||||||
|
// isOutsideData = idx256 >= size256
|
||||||
|
// idx64 = trunc idx256
|
||||||
|
// size64 = trunc size256
|
||||||
|
// dataLeftSize = size64 - idx64 // safe if not isOutsideData
|
||||||
|
// reqBytes64 = trunc _reqBytes // require() handles large values
|
||||||
|
// bytesToCopy0 = select(reqBytes64 > dataLeftSize, dataSizeLeft, reqBytes64) // min
|
||||||
|
// bytesToCopy = select(isOutsideData, 0, bytesToCopy0)
|
||||||
|
|
||||||
auto memPtr = getData();
|
auto isOutsideData = m_builder.CreateICmpUGE(_srcIdx, _srcSize);
|
||||||
auto destPtr = m_builder.CreateGEP(memPtr, _destMemIdx, "dest_mem_ptr");
|
auto idx64 = m_builder.CreateTrunc(_srcIdx, Type::lowPrecision);
|
||||||
|
auto size64 = m_builder.CreateTrunc(_srcSize, Type::lowPrecision);
|
||||||
|
auto dataLeftSize = m_builder.CreateSub(size64, idx64);
|
||||||
|
auto reqBytes64 = m_builder.CreateTrunc(_reqBytes, Type::lowPrecision);
|
||||||
|
auto outOfBound = m_builder.CreateICmpUGT(reqBytes64, dataLeftSize);
|
||||||
|
auto bytesToCopyInner = m_builder.CreateSelect(outOfBound, dataLeftSize, reqBytes64);
|
||||||
|
auto zero64 = llvm::ConstantInt::get(Type::lowPrecision, 0); // TODO: Cache common constants
|
||||||
|
auto bytesToCopy = m_builder.CreateSelect(isOutsideData, zero64, bytesToCopyInner);
|
||||||
|
|
||||||
// remaining source bytes:
|
auto src = m_builder.CreateGEP(_srcPtr, idx64, "src");
|
||||||
auto remSrcSize = m_builder.CreateSub(_srcSize, _srcIdx);
|
auto dst = m_builder.CreateGEP(getData(), _destMemIdx, "dst");
|
||||||
auto remSizeNegative = m_builder.CreateICmpSLT(remSrcSize, zero256);
|
m_builder.CreateMemCpy(dst, src, bytesToCopy, 0);
|
||||||
auto remSrcBytes = m_builder.CreateSelect(remSizeNegative, zero256, remSrcSize, "rem_src_bytes");
|
|
||||||
|
|
||||||
auto tooFewSrcBytes = m_builder.CreateICmpULT(remSrcBytes, _reqBytes);
|
|
||||||
auto bytesToCopy = m_builder.CreateSelect(tooFewSrcBytes, remSrcBytes, _reqBytes, "bytes_to_copy");
|
|
||||||
|
|
||||||
m_builder.CreateMemCpy(destPtr, srcPtr, bytesToCopy, 0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue