[Python-3000] PEP 3107 - Function Annotations

Tony Lownds tony at pagedna.com
Sat Jan 6 20:05:51 CET 2007


On Jan 5, 2007, at 12:01 AM, Neal Norwitz wrote:

> On 12/28/06, Tony Lownds <tony at pagedna.com> wrote:
>>
>> >  * With the modification of MAKE_FUNCTION to be a 32-bit value,  
>> this
>> > means that EXTENDED_ARG is now used.  This means that the peephole
>> > optimizer won't work for the outer function.  I think we should
>> > correct this.
>>
>> Ok. Something like this should fix it in peephople.c. I can post a
>> patch.
>>
>> @@ -535,8 +535,13 @@
>>                                  break;
>>                          case EXTENDED_ARG:
>> -                               goto exitUnchanged;
>> +                               if (codestr[i+3] != MAKE_FUNCTION)
>> +                                       goto exitUnchanged;
>> +                               /* don't visit MAKE_FUNCTION as
>> GETARG will be wrong */
>> +                               i += 3;
>> +                               break;
>> +
>
> I'm not sure if it's not that simple or not.  The problem is the jump
> fix up code.  There are some assumptions that the code sizes are only
> 1 or 2.  It's possible that this is a very limited circumstance that
> doesn't screw up any of the assumptions.  IIRC there would be problems
> if a jump changed from 2 to 4 bytes (or vica versa).  Since the size
> can't change for MAKE_FUNCTION, it may be ok in this limited case, but
> I'm not sure without reviewing the code in detail.  (It probably is
> ok, but I'm not sure.)
>

The peephole code bails on code larger than 32767 . All of the peephole
optimizations make the code smaller. In practice that means EXTENDED_ARG
will not be encountered before jump opcodes. I believe the logic is  
fine even if
EXTENDED_ARG did pop up on any other opcode.

> Hmm, what would happen if the nested function contained more than 256
> args?  Might that mess up the annotation handling?

There is a limit for non-nested arguments, but apparently not for
nested arguments, and the handling does mess up:

 >>> s = "def f((%s)): pass"
 >>> s %= ', '.join('a%d' % i for i in xrange(70000))
 >>> d = {}
 >>> exec(s, d)
 >>> s = "def f((%s)): pass"
 >>> s %= ', '.join('a%d:%d' % (i,i) for i in xrange(70000))
 >>> exec(s, d)
python: Python/ceval.c:2307: PyEval_EvalFrameEx: Assertion  
`num_annotations == name_ix+1' failed.
Abort (core dumped)

compile.c happily compiled 70000 annotations; I think it should  
complain (SyntaxError) at 2^16-1.
I'll post a patch.

Thanks
-Tony




More information about the Python-3000 mailing list