-
Notifications
You must be signed in to change notification settings - Fork 19
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
The case for dropping JUMPF and non-returning functions #42
Comments
what is the current requirement for |
No such requirement for So if we replaced |
hmm. it seems |
Asked this in discord, but sharing it here for archives |
One of the main arguments for In any case, it seems like the latest spec mitigates some of these very strong points in favour of
That being said, I haven't had the time yet for a full analysis of the impact of |
i think this is mitigated by changing the validation rules for non-returning code sections. so if you have a code section
yes -- one currently useful case for
this is one thing i'm not convinced is super useful about JUMPF. tail call optimization can be implemented in compilers using regular jumps (at least for functions which recurse into themselves -- for corecursive, i haven't analyzed it yet but i think it is the same).
i agree fully here. actually i think there is a strong case to be made for bringing back a single global code section a la EIP-2315. i have been told that EIP-2315 was infeasible or doesn't address certain use cases, but i don't fully understand what the issues are here. |
Well, that restricts you to a single function frame, so it would require to inline the entire graph of any corecursion. And tail calls are not necessarily recursive - in the end it's just the more general case of "shared cleanup blocks" for cases in which more logic is shared among functions. In any case: just to be clear about that: at least for us in Solidity, assuming the weakened stack validations that the current version of the spec now involves, our last implementation of a previous in these aspects very similar specification overall still resulted in a net win not only in gas, but also in code size due to independent savings e.g. of jumpdests. So I don't think there is a strong case for a radical change as towards a single global code section, especially since a clear split into function sections does have advantages in terms of simpler analyzability. What we're talking about here with |
JUMPF imo is the only EIP that is questionable, other EIP's have a stronger purpose and the reason is obvious as they solve the problem. This seems not the case for JUMPF. We of course don't want to introduce regression but on the other hand we don't want to include something that pans up not useful or can be done in a different maybe simpler way. What I would like to know is what are we optimizing for, it is not that clear to me. Few comments/questions: tail-call-optimizations are mostly useful for recursion at least in ordinary CPU's, how much are recursions found inside solidity/vyper code? Isn't JUMPF just a CALLF that does RETURN, is code/stack validation problem here? @ekpyron @charles-cooper thank you for discussing this |
It is not, it can also RETF, but since JUMPF didn't push to the return stack, it acts as if it RETFed from the JUMPF caller section. The As an aside note, there was an error I slipped into the megaspec's write-up of relaxed stack validation. That possibly might have caused confusion, apologies if that was the case. See #44 fixing the error. |
I thought of another argument in favor of having non-returning flag and JUMPF: without them, some code after CALLF to non-returning function is non-reachable in practice, but will be considered reachable by the validation. In other words In this way non-returning flag really makes EOF Functions spec complete. Without it some functions that are non-returning in practice, but are not declared as such, will cause some quirks like this. |
I mean this is actually kind of a strong argument for a global code section, right? |
Vyper actually disallows recursion entirely. Even if it allowed recursion, I think generally getting to a recursion depth where tail call optimization is needed is a code smell. |
On the EOF Implementers Call #31 we have agreed to keep JUMPF and non-returning functions in the specification for now. It can be easily dropped later, should we decide closer to deployment, but re-adding it would be not possible. We do want to get actual measurements from the Solidity and/or Vyper implementation in the upcoming months to validate this question, and ultimately keep or remove this feature. Given the above discussion the call felt there's a slight leaning towards JUMPF being useful, but it is to be validated via actual compiler feedback. |
Main use case for
JUMPF
was being able to call a non-returning helper without the requirement to have equal stack height at each call site and without the need toPOP
extra items before calling.In the current spec:
If such helper is implemented inside caller section (without
CALLF
/JUMPF
), it is allowed to call it from different stack heights.If such helper is in a separate section, we can make it work without the need for non-returning flag and
JUMPF
: non-returning functions are declared with 0 outputs, and the requirement to notPOP
extra items is achieved withCALLF STOP
orCALLF INVALID
sequence.The difference with
JUMPF
would be 4 bytes of code instead of 3 bytes and an item pushed into call stack at run-time.cc @ekpyron @charles-cooper
The text was updated successfully, but these errors were encountered: