[Vm-dev] JIT stack discipline from caller's POV

Eliot Miranda eliot.miranda at gmail.com
Thu Mar 21 22:33:33 UTC 2013


On Thu, Mar 21, 2013 at 10:31 AM, Igor Stasenko <siguctua at gmail.com> wrote:

>
> On 21 March 2013 18:04, Eliot Miranda <eliot.miranda at gmail.com> wrote:
> >
> >
> >
> > On Thu, Mar 21, 2013 at 7:19 AM, Igor Stasenko <siguctua at gmail.com>
> wrote:
> >>
> >>
> >> Hi, Eliot & all
> >>
> >> i just want to summarize the SimpleStackBasedCogIt stack discipline,
> >> please correct me if i wrong.
> >>
> >> On call:
> >>
> >> If number of arguments is 0 or 1 (just receiver or receiver + 1 arg),
> >> caller uses registers to pass them:
> >> EDX for receiver
> >> ESI for arg1
> >>
> >> If number of arguments is > 1
> >> then caller pushes all arguments on stack.
> >>
> >> After return:
> >> - caller expecting result in EDX
> >> - the stack is cleaned by callee (by popping args from stack), but
> >> only for those which was pushed (so in case of <=1 arguments there's
> >> nothing to pop)
> >>
> >>
> >> Am i correct?
> >
> >
> > Nearly ;)  First of all you're describing the Smalltalk-to-Smalltalk
> calling convention of StackToRegisterMappingCogit.
> >
> > The st-to-st calling convention for SimpleStackBasedCogIt is
> >
> > on call ReceiverResultReg (edx on x86) contains the receiver, and the
> receiver and arguments are all on the stack, receiver furthest from
> top-of-stack.
> > If the number of arguments is 3 or greater then the argument count is
> passed in SendNumArgsReg (this is for the linking run-time routine; it is
> ignored in linked sends).
> > on return result is in ReceiverResultReg.  The callee removes arguments
> from the stack.
> >
> > The st-to-st calling convention for StackToRegisterMappingCogit is:
> >
> > - if the number of arguments is less than or equal to numRegArgs then
> the receiver and arguments are passed in registers.  numRegArgs is
> currently 1, but will become 2 once the code generator generates machine
> code primitives which take 2 arguments (i.e. once the object representation
> makes it feasible to implement at:put: in machine code numRegArgs will be
> raised to 2).  The receiver is passed in ReceiverResultReg, the first
> argument in Arg0Reg (esi on x86) and the second argument (if numRegArgs =
> 2) in Arg1Reg (edi on x86).
> >
> > - if the number of arguments is greater than numRegArgs then the calling
> convention is as for SimpleStackBasedCogIt; ReceiverResultReg contains the
> receiver, and the receiver and arguments are all on the stack, receiver
> furthest from top-of-stack.  If the argument count is > 2 then argument
> count is passed in SendNumArgsReg.
> >
> > On return the result is in ReceiverResultReg.  The callee removes
> arguments from the stack.
> >
> > Note that if a machine code method contains a call to an interpreter
> primitive it will push any register arguments on the stack before calling
> the primitive so that to the primitive the stack looks the same as it does
> in the interpreter.
> >
> > Note that this *is not* the calling convention used to call routines in
> the interpreter; the Cogits use the C calling convention for those.
> >
> > Note that what you say above "- the stack is cleaned by callee (by
> popping args from stack), but only for those which was pushed (so in case
> of <=1 arguments there's nothing to pop)" is not really correct.  The
> prolog of a method will push register arguments on the stack if the method
> builds a frame.  Frameless methods (certain simple methods that don't
> contain sends or any bytecode that can provoke a send) won't push anything
> and will operate on their register arguments.  Methods containing a machine
> code primitive (e.g. SmallInteger>>#+) will operate on the register
> arguments and return their result in ReceiverResultReg unless the primitive
> fails, in which case the arguments will be pushed in the post-primitive
> prolog.  So once a method is activated its frame layout does not depend on
> whether it has register arguments.
> >
> > Clear?
> Yes.
>
> I was interested to see from caller's perspective (what to expect at
> primitive section of Cog method)..
> because i was playing with ret:4 / ret:8 for method which takes one
> argument, and i figured that correct instruction is 'ret'
> because the primitive section of Cogged method runs before
> "activation" and therefore there is no frame built yet,
> and so, i only should worry how caller passed args to me.
> If primitive fails, my code simply sets prim fail code and jumps to
> the end of code (where JIT-generated section for method activation
> is).
>

Right.


> My main point of interest was to be sure that primitive section of
> cogged method do not mess with frame(s),
> and gets everything in a state like caller passed. And since caller
> cannot know whether callee uses frame or not, i can rely on such
> invariant
> for generating correct code.
>

And that's right for pure machine-code primitives (except block value).
 But (as you know) not so for interpreter primitives because they require
everything on the stack.
BlockClosure value is an exception.  For simplicity the machine code
primitive pushes the register arguments before doing anything else.  This
allows me to re

-- 
best,
Eliot
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://lists.squeakfoundation.org/pipermail/vm-dev/attachments/20130321/817c999d/attachment.htm


More information about the Vm-dev mailing list