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_defs,
|
||||||
./oph_helpers,
|
./oph_helpers,
|
||||||
eth/common,
|
eth/common,
|
||||||
sequtils,
|
|
||||||
stint,
|
stint,
|
||||||
strformat
|
strformat
|
||||||
|
|
||||||
|
@ -34,29 +33,6 @@ import
|
||||||
when not defined(evmc_enabled):
|
when not defined(evmc_enabled):
|
||||||
import ../../state
|
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
|
# Private, op handlers implementation
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
|
@ -144,7 +120,7 @@ const
|
||||||
k.cpt.gasCosts[CallDataCopy].m_handler(k.cpt.memory.len, memPos, len),
|
k.cpt.gasCosts[CallDataCopy].m_handler(k.cpt.memory.len, memPos, len),
|
||||||
reason = "CallDataCopy fee")
|
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) =
|
codeSizeOp: Vm2OpFn = proc (k: var Vm2Ctx) =
|
||||||
|
@ -169,7 +145,7 @@ const
|
||||||
cpt.gasCosts[CodeCopy].m_handler(cpt.memory.len, memPos, len),
|
cpt.gasCosts[CodeCopy].m_handler(cpt.memory.len, memPos, len),
|
||||||
reason = "CodeCopy fee")
|
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) =
|
gasPriceOp: Vm2OpFn = proc (k: var Vm2Ctx) =
|
||||||
|
@ -215,7 +191,7 @@ const
|
||||||
reason = "ExtCodeCopy fee")
|
reason = "ExtCodeCopy fee")
|
||||||
|
|
||||||
let codeBytes = cpt.getCode(address)
|
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) =
|
extCodeCopyEIP2929Op: Vm2OpFn = proc (k: var Vm2Ctx) =
|
||||||
|
@ -233,7 +209,7 @@ const
|
||||||
cpt.opcodeGastCost(ExtCodeCopy, gasCost, reason = "ExtCodeCopy EIP2929")
|
cpt.opcodeGastCost(ExtCodeCopy, gasCost, reason = "ExtCodeCopy EIP2929")
|
||||||
|
|
||||||
let codeBytes = cpt.getCode(address)
|
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}. "&
|
&"for data from index {copyStartPos} to {copyStartPos + size}. "&
|
||||||
&"Return data is {k.cpt.returnData.len} in \n" &
|
&"Return data is {k.cpt.returnData.len} in \n" &
|
||||||
"length")
|
"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")
|
reason = "MSTORE8: GasVeryLow + memory expansion")
|
||||||
|
|
||||||
k.cpt.memory.extend(memPos, 1)
|
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:
|
for z, b in value:
|
||||||
memory.bytes[z + startPos] = b
|
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) =
|
proc copy*(memory: var Memory, dst, src, len: Natural) =
|
||||||
if len <= 0: return
|
if len <= 0: return
|
||||||
memory.extend(max(dst, src), len)
|
memory.extend(max(dst, src), len)
|
||||||
|
@ -65,3 +69,33 @@ proc copy*(memory: var Memory, dst, src, len: Natural) =
|
||||||
else: # src > dst
|
else: # src > dst
|
||||||
for i in countdown(len-1, 0):
|
for i in countdown(len-1, 0):
|
||||||
memory.bytes[dst+i] = memory.bytes[src+i]
|
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