I don't know how many "objects from the low-level Javascript
library" Maxime was referring to but as long as it is 10-100 references, it still seems reasonable.
Probably less than 30. The global object prototype, string prototype, prototypes for the error classes, the error constructors, etc.
However, we should not plan on supporting something like 100 000
user-level threads, each with their own RC, using this scheme.
I think that a < 1KB overhead per thread is extremely reasonable. The biggest overhead will be maintaining a stack and a GC pool for each thread. However, if the context size ever turns out to be a problem, then we could decompose the context into multiple objects. The things that need to be different, per-thread, are things like the heap pointer, and possibly the performance counters, but the JavaScript objects we keep in there will be shared among threads, at least if we stick to a Java-like memory model.
In the second case, I see two ways of handling the problem. My first
idea is that we might identify which calls might result in a context switch (like eval) and add the necessary code on the caller side. My second idea is that we might use an "expected context" on the callee side.
I think the problem is "where do you store your expected context?". If you're storing it somewhere, and loading it in a register to compare it to the current one, you're already wasting CPU cycles by performing a memory access.
Marc suggested annotating functions requiring a context change, or performing the change manually. I think that this could work, but since I also think we need to avoid shooting ourselves in the foot, I think that perhaps we could code an assertion/debug mechanism into this... We could store a flag in the context header to say whether it is a Tachyon or user-level context... And all the tachyon code we generate, when compiled in debug mode, could have a test to make sure that the context has been appropriately switched. This test would disappear in release mode.
- Maxime