Date: Tue, 24 Jul 2007 20:37:12 +0300> From: siguctua@gmail.com> To: exupery@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 / 2might 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 O1send2 #/ 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 storedret ; Destroy this context and reactivate the previous oneSo 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):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. :)Thanks,Jason
_________________________________________________________________ Don't get caught with egg on your face. Play Chicktionary! http://club.live.com/chicktionary.aspx?icid=chick_wlmailtextlink
On 25/07/07, J J azreal1977@hotmail.com wrote:
Date: Tue, 24 Jul 2007 20:37:12 +0300 From: siguctua@gmail.com To: exupery@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@lists.squeakfoundation.org http://lists.squeakfoundation.org/cgi-bin/mailman/listinfo/exupery
Do you mean for the cond to be evaluated at compile time in the following?
(def store-to-register (reg val) (cond (reg) ((number-that-means-eax) (store eax val)
If so you could just generate: (mov t1 eax)
Then the register allocator will try to allocate t1 in eax and remove that move.
Bryce
exupery@lists.squeakfoundation.org