Dead code in Python-generated bytecode

So I’ve made a couple of changes to Papaya (yeah, it’s called Papaya now):

So, due to my use of BytecodeAssembler, I get free stack size calculations, but I get another feature which is somewhat annoying: dead-code prevention.

Why is this annoying? Because the Python compiler generates dead code all the time.

What this means is, if you decompile any non-trivial (and some quite-trivial) .pyc files created by Python, and then try to recompile then, then it will fail with an “AssertionError: Unknown stack size at this location” message.

For example, take the following, very simple .py file:

    while True:
    	if True:
    		continue
    	break

This is disassembled into the following:

    SETUP_LOOP 
      label0:
        LOAD_NAME True
        JUMP_IF_FALSE label3
        POP_TOP 
        LOAD_NAME True
        JUMP_IF_FALSE label1
        POP_TOP 
        JUMP_ABSOLUTE label0
        JUMP_FORWARD label2
      label1:
        POP_TOP 
      label2:
        BREAK_LOOP 
        JUMP_ABSOLUTE label0
      label3:
        POP_TOP 
        POP_BLOCK 
        LOAD_CONST None
        RETURN_VALUE

Note the double JUMP. This is generated any time you have a continue statement, despite the fact that the second jump cannot ever be run. Also unecessary is the JUMP_ABSOLUTE after BREAK_LOOP.

Both of these cause an error in BytecodeAssembler because it has no context from which to determine the stack size at that point. Of course, that doesn’t really matter since the code will never be run.

I’m currently stumped as to the best way to solve this issue, and I’m tired and don’t want to think about it any more. :(

blog comments powered by Disqus