Skip to content
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

fix[venom]: invalid jump error #4214

Merged
merged 25 commits into from
Sep 18, 2024

Conversation

HodanPlodky
Copy link
Collaborator

@HodanPlodky HodanPlodky commented Aug 27, 2024

What I did

Fixed the issue that caused the invalid jump when that occurred when remove_unused_variables could not remove instruction with output value because it is volatile.

How I did it

Allowed to remove mload instruction in remove_unused_variables and insert POP instruction if needed in asm generation.

How to verify it

I used vyper tests and tests in snekmate which originally exhibited error.

Commit message

fix an issue where `ret` would generate a jump to an invalid location
because the stack is not clean. the solution is to always pop
instruction outputs which are not used.

note this leads to a slight performance regression (roughly 0.07%
bytecode size), since `POP`s are always generated, even in cases when the
stack does not need to be cleaned (e.g. before `STOP`).

Description for the changelog

Cute Animal Picture

Put a link to a cute animal picture inside the parenthesis-->

Copy link
Member

@charles-cooper charles-cooper left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is kind of a weird fix. isn't the real fix to change line 540 of venom_to_assembly.py to read if inst.output not in next_liveness?

@HodanPlodky
Copy link
Collaborator Author

this is kind of a weird fix. isn't the real fix to change line 540 of venom_to_assembly.py to read if inst.output not in next_liveness?

I was wondering about this and it should be fix but the problem was that I wanted to minimize the number of the PUSH instructions so that was the reason to do this. I will try it just to check it will some problem. But I dont think it will be problem to add the mload to instruction that could be removed by remove_unused_variables pass and that would help with the number of POP instruction that would be needed otherwise.

Just as a possibility I was playing with idea to clear up the stack at the end of the function before return but I think that would introduce more instruction then clearing the stack right after.

@HodanPlodky HodanPlodky changed the title fix[venom]: Invalid jump error fix[venom]: invalid jump error Aug 28, 2024
Copy link

codecov bot commented Aug 28, 2024

Codecov Report

All modified and coverable lines are covered by tests ✅

Project coverage is 88.34%. Comparing base (9a208a6) to head (8b8dda7).
Report is 1 commits behind head on master.

Additional details and impacted files
@@            Coverage Diff             @@
##           master    #4214      +/-   ##
==========================================
- Coverage   91.35%   88.34%   -3.01%     
==========================================
  Files         109      109              
  Lines       15637    15628       -9     
  Branches     3443     3437       -6     
==========================================
- Hits        14285    13807     -478     
- Misses        920     1295     +375     
- Partials      432      526      +94     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

@HodanPlodky HodanPlodky marked this pull request as ready for review September 3, 2024 14:11
Comment on lines 302 to 303
for i, inst in enumerate(all_inst):
next_liveness = all_inst[i + 1].liveness if i + 1 < len(all_inst) else OrderedSet()
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
for i, inst in enumerate(all_inst):
next_liveness = all_inst[i + 1].liveness if i + 1 < len(all_inst) else OrderedSet()
for i, inst in enumerate(all_insts):
next_liveness = all_insts[i + 1].liveness if i + 1 < len(all_insts) else OrderedSet()

if "call" in inst.opcode and inst.output not in next_liveness:
if cleanup_needed and inst.output not in next_liveness:
depth = stack.get_depth(inst.output)
if depth != 0:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can this branch ever be hit? 😱


self._generate_evm_for_basicblock_r(asm, fn.entry, StackModel(), cleanup_needed)
self._generate_evm_for_basicblock_r(
asm, fn.entry, StackModel(), fn.is_cleanup_needed()
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

has to re-iterate over all basic blocks for every basic block no?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ah, never mind, it gets passed thru in the recursion

@@ -118,6 +119,13 @@ def apply_line_numbers(inst: IRInstruction, asm) -> list[str]:
return ret # type: ignore


def _is_cleanup_needed(fn: IRFunction) -> bool:
for bb in fn.get_basic_blocks():
if bb.is_terminated and bb.instructions[-1].opcode == "ret":
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is_terminated and then checking for ret seems superfluous. Just a check if instructions not empty.

@charles-cooper charles-cooper merged commit f7b8e93 into vyperlang:master Sep 18, 2024
156 checks passed
charles-cooper added a commit to charles-cooper/vyper that referenced this pull request Oct 5, 2024
fix an issue where `ret` would generate a jump to an invalid location
because the stack is not clean. the solution is to always pop
instruction outputs which are not used.

note this leads to a slight performance regression (roughly 0.07%
bytecode size), since `POP`s are always generated, even in cases when the
stack does not need to be cleaned (e.g. before `STOP`).

---------

Co-authored-by: Charles Cooper <cooper.charles.m@gmail.com>
Co-authored-by: Harry Kalogirou <harkal@nlogn.eu>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants