-
Notifications
You must be signed in to change notification settings - Fork 694
Global variables and atomics #314
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Comments
It'd be more work, but you're right there would be potential performance upsides to having unaliased memory locations with atomic access. Definitely worth considering.
One difference is that
I'm assuming you're referring to linear memory itself, not the aliased-stack-in-the-heap pointer. In that case, I don't understand the use case: linear memory is fundamentally shared between the main module and all dylibs that get linked in. Are you talking about sharing heaps between different (not dynamically linked) modules? If so, that raises the granularity-of-sharing questions in the middle of #304. |
On Thu, Aug 27, 2015 at 4:06 PM, Luke Wagner [email protected]
One difference is that load/store have an expression tree as operand for
|
Is a C++ compiler going to be smart enough to put a global std::atomic variable in a global instead of a data segment? |
With LTO, yes, it could see the address is never taken in the whole program and the symbol is not exported. |
@lukewagner said:
"into the global array" what do you mean? Globals are unaliased with anything else, including linear memory. What's the global array you refer to? The process' virtual address space? What I'm suggesting is that linear memory access could just be access to a global ( @lukewagner said:
Yes, linear memory. Yes it's shared, but what I'm suggesting is that this sharing isn't fundamental: the main module says This means that you can have multiple independent heap arrays if you so desire, and you can shared whichever ones you want. @AndrewScheidecker said:
Yes, though we don't even need LTO for this. Note that a C++ compiler can also leave everything in linear memory if it wants! C++ semantics make either choice acceptable, and the compiler chooses whether to use globals or not (but globals have nifty properties around security and performance, so using them is nice). |
Hang on, what? A pair of opcodes per unique global? That doesn't make any sense, the identity of the global being loaded/stored has to be an operand, otherwise a typical application would have a hundred unique opcodes filling up the opcode table. |
There's one LoadGlobal and one StoreGlobal opcode, followed by a byte On Thu, Aug 27, 2015 at 7:08 PM, Katelyn Gadd [email protected]
|
What @titzer said.
Ah, I see. I like the idea of trying to unify seemingly-similar things (especially when we start considering adding atomic ops for globals). However, there are a lot of sophisticated things we want to do with linear memory that I don't think would map very well to general array types (e.g., resizing, the mmap toolkit); it'd be sorta like the old Also, I wonder how common of a need this will be once we have dynamic linking and shmem: when do you want a separate linear memory (which means you can't easily mix pointers and so you're talking about really separate address spaces) but still want this load-time-fixed heap sharing? We've definitely seen cases where you want to shuffle memory between two big arrays in asm.js, but usually it's the heap and something dynamic (say, a canvas's array buffer) that wants GC integration. Global (and local) array types are definitely worth considering independently as a feature (not meant to replace linear memory). @sunfishcode pointed out that they could actually be slower than heap access when signal handlers are used to eliminate bounds checking for linear memory access (assuming each global array isn't given a 4GiB reservation :). So it'd be good to measure once we're farther along to see what the benefits would be in practice. |
@lukewagner agreed, the main point of this issue was to discuss globals + atomics. Asking questions about the rest is more of a self-sanity check: it does sound like we have good reasons to have gone the way we did! |
Extending conversation in #154 here: While there are definite use cases for unaliased thread-local variables (e.g., |
As discussed in #344, we no longer have globals in the MVP. |
We have globals again, and now we have the v1 threads proposal. Is this something we want to resurrect there? My assumption is that we'll want to postpone this until we start looking at pure WebAssembly threads. |
I think the main points are:
You can address 1. in the threads repo, and we can tackle 2. separately. Closing. |
Implementation of global variables for LLVM, and subsequent discussion with @ncbray led me to realize an interesting interaction with atomics which I think is worth pointing out and documenting as a "question".
Treat this a a brain dump. In particular, it doesn't require your attention now. Add to it if you wish, let's make sure we close it out before MVP, but let's keep focused on getting some basics working first.
Once we add threading to WebAssembly, are globals accessible atomically?
The answer to this may mean we diverge slightly from JavaScript Shared Memory that @lars-t-hansen is working on. This means that any theorem prover we use to validate the JavaScript memory model has to take global variables into account for WebAssembly.
If we follow LLVM's lead and simply tag
load
/store
withatomic
(and a memory order e.g.acquire
/release
/seq_cst
) then this extends quite easily toload_global
andstore_global
. If we create separate atomic opcodes fromload
/store
, then we must also duplicateload_global
/store_global
with atomic siblings.An interesting point about global variables is that none of them are address-taken. A code generator could decide to emit no global, and always put things in a heap. That opens up developer's code to heap object overflow, whereas globals are always "safe" (bugs in developers' code can't cause their app to get owned through globals being overwritten).
Globals also potentially lead to better optimization by the
.wasm
→machine code translator. Doubly so when dealing with atomics because it provides very precise type and pointer escape information.Global variables can also be exported to shared objects by name.
I'm now wondering: why isn't
global
an attribute onload
/store
the same wayatomic
could be?While we're there, why isn't
HEAP
a magical exported global, of byte-array type (assuming we allow array global variables, and force them to always be in bounds) which the main module can share with dynamically loaded libraries? This is going back to what Emscripten does, except it has these handy aliases that type-cast the byte array to other types.The text was updated successfully, but these errors were encountered: