On 2010-09-02, at 9:46 PM, Maxime Chevalier-Boisvert wrote:
In today's meeting, Marc suggested that we should put pointers to objects that are needed by the runtime inside the context object. It seemed like a rational thing to do.
...
Marc, you argued that using a context register is faster than directly embedding pointers in the machine code. I'm wondering if it wouldn't be a better performance choice to do the latter, however, if it could eliminate the need to always maintain a context register live and handle context register switches.
Don't worry too much about register pressure on x86-32. First, C/C++ compilers generate decent code on x86-32 even though they normally reserve 2 registers for the stack (%ebp and %esp). We only reserve %ebp for the stack. So if we take an additional register for the context we are no worse off. Moreover, we need a register to put the argument count and we can reuse the lower bits of the context register for this. Finally, the x86-32 is almost dead (of all the Intel processors currently offered by Intel, only the Atom still has a 32 bit version available). Long live x86-64 (which has 16 general purpose registers). I still think we can do a good job on x86-32, and by living with the constraints of x86-32 we can develop a nimble design that will work well on x86-64 as well.
I should add that this too (the use of a dedicated context register) is something we can evaluate. Let's make sure that the code generator can work with a context register, and with a statically allocated context object (so absolute addressing could be used to access the fields instead of a register indirection with offset). In the IR you can express accesses to the context abstractly and the code generator can implement this one way or the other depending on a switch.
There is one thing I'm not clear about, however: how will the context register be switched when non-tachyon code calls tachyon code and vice versa? How can this be implemented efficiently? Does the caller always have to check if the callee belongs to the same context? Where is the new context register value read?
In a browser, the context switch would occur when the browser's scheduler suspends the execution of one page to resume the execution of another page.
In our system, we might want a context switch to occur when the user program calls the tachyon compiler and vice versa. This could be achieved by having (some) closures which close over the context pointer. We could annotate the functions which need to do this in the tachyon compiler (I assume there would be a fairly small number of functions which the user program can call). Of course this technique would not work if we allocate the context object statically. For statically allocated context objects, the code would have to be patched with references to the appropriate context object. As I said before, this means that JavaScript code which is shared by the compiler and user program would have to be duplicated (think of a library that both the compiler and user program need, such as for sorting, i/o, ...). When the library code is executed, you need the global object to be different depending on who is executing the library (the compiler or the user program).
Marc