Bootstrapping on 64 bits won't be trivial as I've found two issues today:
1. It is not possible to do a call/jump with a 64 bits relative offset. It breaks the way we implemented static calls so far (by computing an offset between the destination address and the call site at linking time). We need this to call malloc/free/exit/puts because they are mapped too far in the address space of the process. Maxime suggested that we always do a move in a register before the call/jump. This way we can move a 64 bits absolute address into a 64 bits register, avoiding the relative offset problem. The function call protocol needs to be changed to support this.
2. We assumed sizeof(int) == sizeof(void *) in the d8 extensions we wrote and in the Tachyon C proxy generation. We will need to change it to adequately support 64 bits.
At this point, I don't know if those are the only issues we will encounter to allow bootstrapping on 64 bits in addition to debugging latent bugs. It might be faster to go the GC way and come back after for 64 bits support. What do you guys think?
Erick
Afficher les réponses par date
I think that technically, if we put the effort into it, we can be running in 64 bit mode some time next week. The issues relating to type size in the FFI code are not difficult to fix. There are other issues we are likely to run into, including:
1. I don't think we tested our instruction encodings as extensively on 64 bits. There could be a few latent bugs there. 2. The C calling conventions are different in 64 bit mode. This would require some more adjustments.
Personally, I've been working on preparing the current JavaScript code to support a GC. I think it's realistic to think we could have a copying GC working in two weeks. This will require some back-end modifications too. At the very least, the addition of GC maps and maps of the linked pointers inside compiled code blocks.
I think that getting a GC working is actually more work, but that the result will be worth it in the end. That being said, we also need to support 64 bit mode eventually.
- Maxime
On 11-03-04 04:40 PM, Erick Lavoie wrote:
Bootstrapping on 64 bits won't be trivial as I've found two issues today:
- It is not possible to do a call/jump with a 64 bits relative offset.
It breaks the way we implemented static calls so far (by computing an offset between the destination address and the call site at linking time). We need this to call malloc/free/exit/puts because they are mapped too far in the address space of the process. Maxime suggested that we always do a move in a register before the call/jump. This way we can move a 64 bits absolute address into a 64 bits register, avoiding the relative offset problem. The function call protocol needs to be changed to support this.
- We assumed sizeof(int) == sizeof(void *) in the d8 extensions we
wrote and in the Tachyon C proxy generation. We will need to change it to adequately support 64 bits.
At this point, I don't know if those are the only issues we will encounter to allow bootstrapping on 64 bits in addition to debugging latent bugs. It might be faster to go the GC way and come back after for 64 bits support. What do you guys think?
Erick _______________________________________________ Tachyon-list mailing list Tachyon-list@iro.umontreal.ca https://webmail.iro.umontreal.ca/mailman/listinfo/tachyon-list
On 2011-03-04, at 4:52 PM, Maxime Chevalier-Boisvert wrote:
I think that technically, if we put the effort into it, we can be running in 64 bit mode some time next week. The issues relating to type size in the FFI code are not difficult to fix. There are other issues we are likely to run into, including:
- I don't think we tested our instruction encodings as extensively on
64 bits. There could be a few latent bugs there.
The x86 encoding logic was tested when it was Scheme code for the Gambit back-end. So I don't think there will be many bugs here.
- The C calling conventions are different in 64 bit mode. This would
require some more adjustments.
True. But from what I have seen in the code generator, the C register usage convention is easy to modify. So here too I don't see much work.
Personally, I've been working on preparing the current JavaScript code to support a GC. I think it's realistic to think we could have a copying GC working in two weeks. This will require some back-end modifications too. At the very least, the addition of GC maps and maps of the linked pointers inside compiled code blocks.
I think that getting a GC working is actually more work, but that the result will be worth it in the end. That being said, we also need to support 64 bit mode eventually.
I agree.
Marc
On 2011-03-04, at 4:40 PM, Erick Lavoie wrote:
Bootstrapping on 64 bits won't be trivial as I've found two issues today:
- It is not possible to do a call/jump with a 64 bits relative offset.
It breaks the way we implemented static calls so far (by computing an offset between the destination address and the call site at linking time). We need this to call malloc/free/exit/puts because they are mapped too far in the address space of the process. Maxime suggested that we always do a move in a register before the call/jump. This way we can move a 64 bits absolute address into a 64 bits register, avoiding the relative offset problem. The function call protocol needs to be changed to support this.
I don't see a problem here. 32 bit relative addresses are sufficient. We can assume programs will never have more than 2 GB of code.
- We assumed sizeof(int) == sizeof(void *) in the d8 extensions we
wrote and in the Tachyon C proxy generation. We will need to change it to adequately support 64 bits.
That should be easy to fix.
At this point, I don't know if those are the only issues we will encounter to allow bootstrapping on 64 bits in addition to debugging latent bugs. It might be faster to go the GC way and come back after for 64 bits support. What do you guys think?
Do the 64 bit port first. I don't think it will be more than a day of work, and the changes needed will be fairly permanent (i.e. not just a quick workaround).
Marc
I don't see a problem here. 32 bit relative addresses are sufficient. We can assume programs will never have more than 2 GB of code.
I think that's a little restrictive. It requires a separate allocation method for code blocks than for regular data, as well as special handling in the GC, because we do want code to be garbage collected in the end. We also can't guarantee that C code is within that offset limit.
If speed is a concern, I would advise that we benchmark the speed difference of both methods. Considering all the overhead function calls incur, including the spills, I wonder if the difference in speed would be very visible. My instinct is that it might matter in fibonacci, but it probably won't be an issue in practice.
There's also the possibility that we could use both mechanisms at once. Relative calls for all calls that happen to fall within that 32-bit limit, absolute calls for the rest. We would just have to pad the shorter opcode sequence with noops so they both take the same space.
- We assumed sizeof(int) == sizeof(void *) in the d8 extensions we
wrote and in the Tachyon C proxy generation. We will need to change it to adequately support 64 bits.
That should be easy to fix.
I modified the v8 code to use intptr_t in places where that was assumed. It's an integer type guaranteed to be able to hold a pointer value. It could technically be bigger than a pointer, but likely never ever will be in practice.
Do the 64 bit port first. I don't think it will be more than a day of work, and the changes needed will be fairly permanent (i.e. not just a quick workaround).
I'll be at the lab on Monday to help with the FFI issues and debugging.
- Maxime
On 2011-03-04, at 10:47 PM, chevalma@iro.umontreal.ca wrote:
I don't see a problem here. 32 bit relative addresses are sufficient. We can assume programs will never have more than 2 GB of code.
I think that's a little restrictive. It requires a separate allocation method for code blocks than for regular data, as well as special handling in the GC, because we do want code to be garbage collected in the end. We also can't guarantee that C code is within that offset limit.
Code allocation will need to be treated specially in any case, in particular because it has to be in an area of memory where the execute bit is on (or at least we need to organize the system so this is an option). There is also a need (on most architectures) to flush the data caches when code objects are created, so that the instruction cache sees the new code. We can arrange things so that the Tachyon code is in an area that doesn't span more than 2 GB. The foreign code (C) can be anywhere if we use a trampoline in the Tachyon code area, in other words a 32 bit relative jump to a 64 bit jump.
If speed is a concern, I would advise that we benchmark the speed difference of both methods. Considering all the overhead function calls incur, including the spills, I wonder if the difference in speed would be very visible. My instinct is that it might matter in fibonacci, but it probably won't be an issue in practice.
It will be interesting to measure the speed difference, but as I say there is no strong reason to avoid the faster (and more compact) 32 bit relative jumps.
There's also the possibility that we could use both mechanisms at once. Relative calls for all calls that happen to fall within that 32-bit limit, absolute calls for the rest. We would just have to pad the shorter opcode sequence with noops so they both take the same space.
Unfortunately, in terms of code space it is just as inefficient, and it will be less efficient in terms of speed due to the additional padding (either noops or short relative jumps). But I'm curious to know by how much.
Marc