I have an variant of the proposal.
- A
subroutinemay only start at PCs divisable by 32:0,32, 64` etc. - The
BEGINSUB, if executed at some other position, causes error. - If a
BEGINSUBis atPC % 32 == 0, then we say that a newsubroutinestarts there.
With these changes, the following effects happen:
- We keep the old
code/databitmap. Sizecodelen / 8. (A) - We create one more bitmap during jumpdest-analysis. Bit
0representsPC=0, bit1representsPC=32. If a new subroutine starts there, we place a1in the bitmap. (B). Size ofBiscodelen/ 32 /8
Now, whenever we need to check if a JUMP is valid, we do
- Check
Aas before, - Check
LOC is JUMPDESTas before, - Seek through
BfromPCtoLOC. This seek operation effectively covers 32 bytes per check. On a64-bit platform, large large jumps can be checked with 64 bits at a time, effectively covering32*64bytes of code per check. A jump across1MBgigantic subroutine can be performed with~490checks.
This means that compilers will have to be smart about allocating the subroutines, and use some padding here and there, and maybe inline small stuff instead of subroutining it.
For code merklization, that might be a good thing too, since it puts a floor on the size of a code chunk.
Furthermore:
- this decreases the chance of causing backward compatibility problems: any non-32
BEGINSUBop is still ājust an invalid opcodeā, and the only case that would cause problems would be- A jump across a data-section, where a
BEGINSUBis atPC %32 ==0.
- A jump across a data-section, where a
PS: The choice of 32 is pretty arbitrary.