forked from DecentralizedClimateFoundation/DCIPs
105 lines
4.6 KiB
Markdown
105 lines
4.6 KiB
Markdown
|
---
|
||
|
eip: 5656
|
||
|
title: Memory copying instruction
|
||
|
description: An efficient EVM instruction for copying memory areas
|
||
|
author: Alex Beregszaszi (@axic), Paul Dworzanski (@poemm), Jared Wasinger (@jwasinger), Casey Detrio (@cdetrio), Pawel Bylica (@chfast), Charles Cooper (@charles-cooper)
|
||
|
discussions-to: https://ethereum-magicians.org/t/eip-5656-mcopy-instruction/10890
|
||
|
status: Draft
|
||
|
type: Standards Track
|
||
|
category: Core
|
||
|
created: 2021-02-01
|
||
|
---
|
||
|
|
||
|
## Abstract
|
||
|
|
||
|
Provide an efficient EVM instruction for copying memory areas.
|
||
|
|
||
|
## Motivation
|
||
|
|
||
|
Memory copying is a basic operation, yet implementing it on the EVM comes with overhead.
|
||
|
|
||
|
This was recognised and alleviated early on with the introduction of the "identity" precompile, which accomplishes
|
||
|
memory copying by the use of `CALL`'s input and output memory offsets. Its cost is `15 + 3 * (length / 32)` gas, plus
|
||
|
the call overhead. The identity precompile was rendered ineffective by the raise of the cost of `CALL` to 700, but subsequently
|
||
|
the reduction by [EIP-2929](./eip-2929.md) made it slightly more economical.
|
||
|
|
||
|
Copying exact words can be accomplished with `<offset> MLOAD <offset> MSTORE` or `<offset> DUP1 MLOAD DUP2 MSTORE`,
|
||
|
at a cost of at least 12 gas per word. This is fairly efficient if the offsets are known upfront and the copying can be unrolled.
|
||
|
In case copying is implemented at runtime with arbitrary starting offsets, besides the control flow overhead, the offset
|
||
|
will need to be incremented using `32 ADD`, adding at least 6 gas per word.
|
||
|
|
||
|
Copying non-exact words is more tricky, as for the last partial word, both the source and destination needs to be loaded,
|
||
|
masked, or'd, and stored again. This overhead is significant. One edge case is if the last "partial word" is a single byte,
|
||
|
it can be efficiently stored using `MSTORE8`.
|
||
|
|
||
|
As example use case, copying 256 bytes costs:
|
||
|
- at least 757 gas pre-EIP-2929 using the identity precompile
|
||
|
- at least 157 gas post-EIP-2929 using the identity precompile
|
||
|
- at least 96 gas using unrolled `MLOAD`/`MSTORE` instructions
|
||
|
- 27 gas using this EIP
|
||
|
|
||
|
According to an analysis of blocks 10537502 to 10538702, roughly 10.5% of memory copies would have had improved performance with the
|
||
|
availability of an `MCOPY` instruction.
|
||
|
|
||
|
Memory copying is used by languages like Solidity and Vyper, where we expect this improvement to provide efficient means of building
|
||
|
data structures, including efficient sliced access and copies of memory objects. Having a dedicated `MCOPY` instruction would also add
|
||
|
forward protection against future gas cost changes to `CALL` instructions in general.
|
||
|
|
||
|
Having a special `MCOPY` instruction makes the job of static analyzers and optimizers easier, since the effects of a `CALL` in general
|
||
|
have to be fenced, whereas an `MCOPY` instruction would be known to only have memory effects. Even if special cases are added
|
||
|
for precompiles, a future hard fork could change `CALL` effects, and so any analysis of code using the identity precompile would only
|
||
|
be valid for a certain range of blocks.
|
||
|
|
||
|
Finally, we expect memory copying to be immensely useful for various computationally heavy operations, such as EVM384,
|
||
|
where it is identified as a significant overhead.
|
||
|
|
||
|
## Specification
|
||
|
|
||
|
The instruction `MCOPY` is introduced at `0x5c`.
|
||
|
|
||
|
### Input stack
|
||
|
|
||
|
| Stack | Value |
|
||
|
|-------|-------|
|
||
|
| top - 0 | `dst` |
|
||
|
| top - 1 | `src` |
|
||
|
| top - 2 | `length` |
|
||
|
|
||
|
This ordering matches the other copying instructions, i.e. `CALLDATACOPY`, `RETURNDATACOPY`.
|
||
|
|
||
|
### Output stack
|
||
|
|
||
|
This instructions returns no stack items.
|
||
|
|
||
|
### Semantics
|
||
|
|
||
|
It copies `length` bytes from the offset pointed at `src` to the offset pointed at `dst` in memory.
|
||
|
Copying takes place as if an intermediate buffer were used, allowing the destination and source to overlap.
|
||
|
|
||
|
If `length > 0` and (`src + length` or `dst + length`) is beyond the current memory length, the memory is extended with respective gas cost applied.
|
||
|
|
||
|
The gas cost of this instruction mirrors that of other `Wcopy` instructions and is `Gverylow + Gcopy * ceil(length / 32)`.
|
||
|
|
||
|
## Rationale
|
||
|
|
||
|
Production implementation of exact-word memory copying and partial-word memory copying can be found in the Solidity, Vyper and Fe compilers.
|
||
|
|
||
|
With [EIP-2929](./eip-2929.md) the call overhead using the identity precompile was reduced from 700 to 100 gas.
|
||
|
This is still prohibitive for making the precompile a reasonable alternative again.
|
||
|
|
||
|
## Backwards Compatibility
|
||
|
|
||
|
This EIP introduces a new instruction which did not exists previously. Already deployed contracts using this instruction could change their behaviour after this EIP.
|
||
|
|
||
|
## Test Cases
|
||
|
|
||
|
TBA
|
||
|
|
||
|
## Security Considerations
|
||
|
|
||
|
TBA
|
||
|
|
||
|
## Copyright
|
||
|
|
||
|
Copyright and related rights waived via [CC0](../LICENSE.md).
|