Optimize EVM Mstore8 and memory.writePadded

- mstore8 operation is simplified using one byte writer
- refactor writePadded and avoid unecessary allocations
This commit is contained in:
jangko 2023-08-28 18:04:22 +07:00
parent 80aec9ccd9
commit 00262a1d48
No known key found for this signature in database
GPG Key ID: 31702AE10541E6B9
3 changed files with 40 additions and 30 deletions

View File

@ -25,7 +25,6 @@ import
./oph_defs,
./oph_helpers,
eth/common,
sequtils,
stint,
strformat
@ -34,29 +33,6 @@ import
when not defined(evmc_enabled):
import ../../state
# ------------------------------------------------------------------------------
# Private helpers
# ------------------------------------------------------------------------------
proc writePaddedResult(mem: var Memory,
data: openArray[byte],
memPos, dataPos, len: Natural,
paddingValue = 0.byte) =
mem.extend(memPos, len)
let dataEndPosition = dataPos.int64 + len - 1
let sourceBytes =
data[min(dataPos, data.len) .. min(data.len - 1, dataEndPosition)]
mem.write(memPos, sourceBytes)
# Don't duplicate zero-padding of mem.extend
let paddingOffset = min(memPos + sourceBytes.len, mem.len)
let numPaddingBytes = min(mem.len - paddingOffset, len - sourceBytes.len)
if numPaddingBytes > 0:
# TODO: avoid unnecessary memory allocation
mem.write(paddingOffset, repeat(paddingValue, numPaddingBytes))
# ------------------------------------------------------------------------------
# Private, op handlers implementation
# ------------------------------------------------------------------------------
@ -144,7 +120,7 @@ const
k.cpt.gasCosts[CallDataCopy].m_handler(k.cpt.memory.len, memPos, len),
reason = "CallDataCopy fee")
k.cpt.memory.writePaddedResult(k.cpt.msg.data, memPos, copyPos, len)
k.cpt.memory.writePadded(k.cpt.msg.data, memPos, copyPos, len)
codeSizeOp: Vm2OpFn = proc (k: var Vm2Ctx) =
@ -169,7 +145,7 @@ const
cpt.gasCosts[CodeCopy].m_handler(cpt.memory.len, memPos, len),
reason = "CodeCopy fee")
cpt.memory.writePaddedResult(cpt.code.bytes, memPos, copyPos, len)
cpt.memory.writePadded(cpt.code.bytes, memPos, copyPos, len)
gasPriceOp: Vm2OpFn = proc (k: var Vm2Ctx) =
@ -215,7 +191,7 @@ const
reason = "ExtCodeCopy fee")
let codeBytes = cpt.getCode(address)
cpt.memory.writePaddedResult(codeBytes, memPos, codePos, len)
cpt.memory.writePadded(codeBytes, memPos, codePos, len)
extCodeCopyEIP2929Op: Vm2OpFn = proc (k: var Vm2Ctx) =
@ -233,7 +209,7 @@ const
cpt.opcodeGastCost(ExtCodeCopy, gasCost, reason = "ExtCodeCopy EIP2929")
let codeBytes = cpt.getCode(address)
cpt.memory.writePaddedResult(codeBytes, memPos, codePos, len)
cpt.memory.writePadded(codeBytes, memPos, codePos, len)
# -----------
@ -262,7 +238,7 @@ const
&"for data from index {copyStartPos} to {copyStartPos + size}. "&
&"Return data is {k.cpt.returnData.len} in \n" &
"length")
k.cpt.memory.writePaddedResult(k.cpt.returnData, memPos, copyPos, len)
k.cpt.memory.writePadded(k.cpt.returnData, memPos, copyPos, len)
# ---------------

View File

@ -158,7 +158,7 @@ const
reason = "MSTORE8: GasVeryLow + memory expansion")
k.cpt.memory.extend(memPos, 1)
k.cpt.memory.write(memPos, [value.toByteArrayBE[31]])
k.cpt.memory.write(memPos, value.toByteArrayBE[31])
# -------

View File

@ -54,6 +54,10 @@ proc write*(memory: var Memory, startPos: Natural, value: openArray[byte]) =
for z, b in value:
memory.bytes[z + startPos] = b
proc write*(memory: var Memory, startPos: Natural, value: byte) =
validateLte(startPos + 1, memory.len)
memory.bytes[startPos] = value
proc copy*(memory: var Memory, dst, src, len: Natural) =
if len <= 0: return
memory.extend(max(dst, src), len)
@ -65,3 +69,33 @@ proc copy*(memory: var Memory, dst, src, len: Natural) =
else: # src > dst
for i in countdown(len-1, 0):
memory.bytes[dst+i] = memory.bytes[src+i]
proc writePadded*(memory: var Memory, data: openArray[byte],
memPos, dataPos, len: Natural) =
memory.extend(memPos, len)
let
dataEndPos = dataPos.int64 + len
dataStart = min(dataPos, data.len)
dataEnd = min(data.len, dataEndPos)
dataLen = dataEnd - dataStart
padStart = min(memPos + dataLen, memory.len)
numPad = min(memory.len - padStart, len - dataLen)
padEnd = padStart + numPad
var
di = dataStart
mi = memPos
while di < dataEnd:
memory.bytes[mi] = data[di]
inc di
inc mi
# although memory.extend already pad new block of memory
# with zeros, it can be rewrite by some opcode
# so we need to clean the garbage if current op supply us with
# `data` shorter than `len`
while mi < padEnd:
memory.bytes[mi] = 0.byte
inc mi