solidity
solidity copied to clipboard
Allow for unchecked function pointer jumps
Abstract
With viaIR
& 0.8.13
, there is an internal function dispatcher. This is quite the hefty gas overhead without anyway to breakout of it to do unchecked internal function calls.
Motivation
It would be nice to be able to use the old version of direct jumps via unchecked
or something in yul, even with viaIR
enabled.
Specification
One solution may be something like the following:
contract T {
function intoPtr(function(uint256 a) internal view returns (uint256 b) op) internal pure returns (uint256 ptr) {
assembly ("memory-safe") {
ptr := op
}
}
function intoOp(uint256 ptr) internal pure returns (function(uint256 a) internal view returns (uint256 b) op) {
assembly ("memory-safe") {
op := ptr
}
}
function addOne(uint256 a) internal pure returns(uint256 b) {
b = a + 1;
}
function exec(uint256 c) public returns (uint256 d) {
uint256 ptr = intoPtr(addOne);
// would not do the internal function dispatch checking.
unchecked { d = intoOp(ptr)(c); }
}
}
Alternatively, could do something like:
contract T {
/// snip ....
function exec(uint256 c) public returns (uint256 d) {
uint256 ptr = intoPtr(addOne);
// would not do the internal function dispatch checking.
assembly ("memory-safe") {
/// by specifying 1 output, the compiler implies that its a 1-in-1-out stack affecting function
d := goto(ptr)
}
}
}
Note: The change made to restrict function pointers to a known set makes sense, but there is no escape hatch for more optimized usage. The yul approach I think actually makes more sense long term as the optimizer could likely eventually recognize it doesn't need to do the internal function dispatching and can directly jump in certain cases.
Further alternative: finally allow verbatim
in solidity contracts
Backwards Compatibility
Fully compatible to my knowledge
The main reason for having a dispatch function in Yul (rather than direct jumps like in the legacy codegen) is the expectation that the support for dynamic jumps in the EVM will eventually be removed. There's ongoing work on this and at some point we're likely to get some alternative mechanism, e.g. some opcodes for managing jump tables with a set of predefined destinations. Or a new variant of the jump opcode.
This is actually a deeper discussion and @chfast, @axic, @ekpyron and @chriseth would probably like to chime in on this. I think that adding the old mechanism back through unchecked
is unlikely.
Also #12650 is a bit related to this.
The reason we do not allow "goto" is more that we would otherwise have to remove some optimizations we are currently able to do.
i guess i'm running into this
i'm not sure how to check whether i am or not, but my gas costs go up noticeably when i enable viaIR and i make heavy use of calling functions by their pointer, so i assume this is at least contributing
for me at least it seems these additional optimizations that @chriseth is pointing to (no pun intended) are less impactful overall than the cost of the slower dispatch
also i'd be willing to measure whether this is indeed the gas problem i'm facing with viaIR if i could get some pointers (no pun intended) on how to do that
This issue has been marked as stale due to inactivity for the last 90 days. It will be automatically closed in 7 days.
Hi everyone! This issue has been automatically closed due to inactivity. If you think this issue is still relevant in the latest Solidity version and you have something to contribute, feel free to reopen. However, unless the issue is a concrete proposal that can be implemented, we recommend starting a language discussion on the forum instead.