We now have dedicated PMC* pointers in the context that hold current_cont, current_sub, and current_object. This is necessary to create traceback information. But subroutine and return opcodes are not adapted yet.

We have e.g.:

   invoke     # implicitely P0 and use P1 for return
              # could also be a method call
   invoke P1  # likely a return

The implicit usage of P0 in function and method calls is a PITA for the register allocator, all this implicit usage causes special handling n code, so that P0 gets properly tracked.

Additionally, P0 and especially P1 is first created in the callers registers. This implies that the old contents of P1 has to be preserved by copying to another register, which increases pressure on the register allocator. The same is done for P2 in method calls. This scheme just reduces the usable register count by 3 in methods and by 2 in functions.

To streamline that and take advantage of the current_* pointers in the context, I'd like to adapt call/return ops slightly:

  invoke PSub, PRet   # replaces implicit P0, P1 handling
  invokecc PSub       # replaces implicit invokecc [P0]
  callmethod Pobj, Smeth, Pret  # analog, no implicit S0
  callmethodcc Pobj, Smeth
  ret_cc              # replaces invoke P1

This gets rid of all hidden register semantics of these opcodes and makes it explicit for the register allocator (and when reading the code), which registers are used. As a minor improvement it also avoids the "set P0, PSub" and such opcodes, to move the needed registers in place.

In the called subroutine P2 remains "self". But P0 and P1 (current sub and continuation) are available only on demand, currently with the interpinfo opcode. Maybe two opcodes for that are in order too:

   get_sub Px   # simplifies coroutines
   get_cc  Px   # simplifies call/cc

leo



Reply via email to