Dynamically choosing a register

Igor Stasenko siguctua at gmail.com
Wed Jul 25 16:37:16 UTC 2007


On 25/07/07, J J <azreal1977 at hotmail.com> wrote:
>
>  > Date: Tue, 24 Jul 2007 20:37:12 +0300
> > From: siguctua at gmail.com
> > To: exupery at lists.squeakfoundation.org
> > Subject: Re: Dynamically choosing a register
> >
> > as i understood, you want to do similar by telling a send oop, where
> > to store a result.
> > well, you may point to stack index, or point to address of memory with
> > given stack index.
> > but i'm unsure, is stack in squeak are subject for GC relocations. if
> > so, then better use index rather than pointers.
>
> Ok, I sent this mail in a rush because I didn't want to still be on the
> train when it left my station, so I figured it wouldn't end up making sense.
> :)
>
> What I mean is, right now MethodConext's have various fields in them
> (BlockContexts as well, but they point to MethodContexts for most
> information).  What I was thinking of doing was adding an addition field
> "returnLocation".  This way the compiler can simply ensure the value that is
> to be returned stores it's value to that area directly.
>
> Example (I means instance variable location, O means Object for the general
> purpose registers, S is a special and L is the literal frame):
>
> center
>   ^ origin + corner / 2
>
> might be translated to:
>
> send2 #+ I1 I2 O1         ; Send the message #+ with the first instance slot
> as the receiver (first object) and the second instance slot as the argument.
> Store results in GP register O1
> send2 #/ O1 S(2) RET   ; Send #/ with O1 as the receiver and the special
> number 2 as the argument.  store the result into what ever place *our
> caller* expects it to be stored
> ret                               ; Destroy this context
> and reactivate the previous one
>
Now take a look how bytecode will look like with using #result register.
Assuming that any message always puts evaluation result into this
register (not stack) we have:

push I1 (origin)
push I2 (corner)
send #+
push #result (after message sent, we have result in #result register)
push S(2)
send #/
ret (after #/ message sent, we have result in #result register, since
its already there, all we need is just return)

same as yours, but not caring about letting message know, where to store result,
because messages always store it in same register (#result).
It can be a simple global memory location or, if you insist, it can be
always an eax register on x86 architecture :)

> So note above that when the receiver in O1 receives the #/ message the RET
> field in *his* activation context will be the same as *ours (i.e.
> center's)*.  So when he stores the answer we don't have to do anything, as
> it is in the right place already.
>
> The complexity comes from the fact that RET might be an instance variable, a
> temp variable location, a GP register *or* it may be an actual hardware
> register.  But I'm not sure if that's even doable without making
> self-modifying code, which lead to my question:  Can I have some value that
> I pass around dynamically that "points" to a hardware register?
>
> I can easily have a special encoding that says "the 3rd general purpose
> hardware register" or even the literal x86 value that maps to e.g. "eax",
> but how would one use this value at runtime?  C, et al don't have this
> problem because the compiler explicitly states what values are going into
> which registers at build time.  I have never heard of passing around a
> register "address".
>
> Of course I could do something like (note: the following pseudo code is
> intended to be a low level lisp-like language that compiles directly to
> machine code):
>
> (def store-to-register (reg val)
>   (cond (reg)
>     ((number-that-means-eax) (store eax val)
>     .....
>
> But if it's going to be the expensive I may as well just store into memory.
> I was hoping I could do something like (example in pseudo assembly this
> time):
>

Yes, in this case, you need a self-modifying code, so you need to
write something to some memory location, before CPU gets to that code.
Then this is not faster than simply writing result to some well known
memory location rather than modifying code to store result into
particular machine register and executing it.
Also, consider that writing to code location invalidates a CPU
instruction cache for this location and forces it to reread
instructions from memory.


> movRegAt %ebx, $val   ; the ebx register somehow has a reference to another
> register and stores $val there instead of ebx or memory or anywhere else.
>
> I suppose, since I have to have different functions for each addressing mode
> anyway, I can just have the routine that detects the type overwrite the
> register in the register store routine directly every time. :)
>
> Hopefully that makes a little more sense. :)
>
I see, you want to make bytecode to use as many registers as it can to
reduce stack usage, so unary or binary send can be sent using machine
registers..

Well, you putting in RET some code , indicating where to store result.
What prevents you to translate it like bytecode? You can build a jump
table and perform different operations depending of RET code for
storing result at pointed place.

So, you can divide RET byte in two hexes, lower will indicate an
index, higher - place to store.
(00 << 4) + x   - store result in machine register , x - register index.
(01 << 4) + x  - store result to ivar of receiver of parent context, x
- ivar index
.... e.t.c



> Thanks,
> Jason
>
> ________________________________
> Don't get caught with egg on your face.    Play Chicktionary!
> _______________________________________________
> Exupery mailing list
> Exupery at lists.squeakfoundation.org
> http://lists.squeakfoundation.org/cgi-bin/mailman/listinfo/exupery
>
>

-- 
Best regards,
Igor Stasenko AKA sig.


More information about the Exupery mailing list