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:
parent
80aec9ccd9
commit
00262a1d48
|
@ -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)
|
||||
|
||||
# ---------------
|
||||
|
||||
|
|
|
@ -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])
|
||||
|
||||
# -------
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue