-
-
Notifications
You must be signed in to change notification settings - Fork 1.1k
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
Inert "raw pointer" for JsValue #999
Comments
Thanks for the report, this is definitely an interesting idea! It's definitely possible that we could do something like this today, but I'm also not entirely sure if we want to. I believe this is specifically empowered by the representation strategy of That being said maybe it's not a bad idea to expose what we have today? It's not clear if we'll be able to switch to a different representation any time soon, in which case providing the raw accessors may make sense. |
It would certainly help me, but I'd also understand not wanting to set up wasm-bindgen for a breaking change (although after studying the WASM proposals I suspect there's a good chance that taking full advantage of these might break the current API anyway?). From my perspective, the worst case post- I'd be happy to make a PR. |
This is already possible today: https://developer.mozilla.org/en-US/docs/Web/API/OffscreenCanvas You can render to an offscreen canvas in a worker and then send the bitmap to the main thread (transferring the bitmap doesn't copy anything, so it's very fast).
I'm not an expert, but my understanding is that threads can only share linear memory, they cannot share tables, and However, I don't think all is lost: it is possible to use the shared linear memory to synchronize between threads. The basic idea would be something like this:
We still have a lot of work to do to make all this synchronization stuff work, but I think it's possible, at least in theory. Note: these tables are wasm tables, not JS tables. They're not hash tables, they're more like As for adding new methods to However! I think it's reasonable to provide this functionality with a new type, perhaps called |
Thanks @Pauan! Yes! The offscreen canvas API is exciting! Unfortunately, browser support doesn't seem great yet, but hopefully the day comes sooner rather than later. You may well be right about the shareabilty of What you outline is pretty much exactly my current plan:
Your outline also seems pretty analogous to the current wasm-bindgen situation, except rather than a thread-local wasm-bindgen hashtable, there'd be a thread-local WASM table, and rather than a key into the wasm-bindgen hashtable,
I'm not sure I completely understand. I don't think |
Basically, yeah, except it would have to be thread-aware (with synchronization), whereas the current implementation is not.
I don't see any mention of "global memory". There are mentions of globals, but those are basically just thread-local variables. (Technically they're instance-local, not thread-local, but in practice it will be one instance per thread, so it's the same thing.) In any case, globals are completely different from linear memory, and globals are not shared between threads. Only linear memory is shared.
Sure, there's no performance cost with the current implementation. But it looks like Right now, wasm-bindgen stores JS values in a slab. This is necessary because of the lack of When But with your proposal, we would still need to store things in a slab, even with That's why I suggested a new type: single-threaded usage will continue to use |
Ah, that makes sense!
I guess my confusion is around what The other thing I don't quite understand yet is: if |
That's a good question! I think @alexcrichton can probably answer that better. But I imagine it would be a magical struct which is translated by wasm-bindgen into
Yes, or by calling an imported function which returns an
So tables are only needed if you want the Though I know some languages (like C and C++, maybe also Rust?) use a shadow stack in linear memory to make pointers work, so perhaps there will need to be a similar "shadow table" for To be clear, the linear memory is primarily for the heap (and a few other things, but mostly the heap). The stack is automatically managed by the wasm engine, it's separate from the linear memory. In other words, the linear memory is for heap allocated bytes, tables are for heap allocated The linear memory is just a chunk of bytes, so if it was possible to store That's why The stack doesn't have that problem, because the stack is automatically managed by the wasm engine (wasm programs don't have access to it), so it can't leak internal details.
Probably not, since an
You can cast an So the only way that wasm could convert Both of those options imply some performance overhead (it's probably faster to keep My understanding is that most of those low-level details will be handled by LLVM (Rust compiles into LLVM, and LLVM then compiles into wasm). I don't know anything about the wasm implementation of LLVM, so I can't answer about what LLVM will do. I assume that when heap allocating an
If you're creating the bindings yourself (using the For static types, perhaps we could have a That does have some complications, since right now everything is designed under the assumption that it uses For bindings created by other people, we could provide conversions, such as When the conversion is run, it would take the Since |
See also: #1002 |
Sort of! I think you're right that taking advantage of future wasm feature "in their fullest" is likely a breaking change, but what I was hoping for is that it's a largely cosmetic breaking change rather than "rewrite the world" breaking change. For example switching some types around is pretty easy, but losing a fundamental capability (like "O(1) conversion to an integer from JsValue") runs the risk of making it much harder to migrate in the future. Also FWIW, I can help clarify a few things about the upcoming wasm proposals as well:
Also, I can try to help clarify the current state of affairs with
@fitzgen and I have discussed a future where It's clear to me, though, that supporting |
Thanks a lot for the detailed replies @Pauan and @alexcrichton, I think I'm finally getting how all the pieces fit together! I suppose then a lot it is going to depend on how I understand then that it's a bit early to tell what sort of API would end up working, if anything can work at all. I can resort to some transmute hacking for now to rip the |
Ok that seems reasonable to me, I think I'd personally prefer to not provide a public stable API for this, but we can't stop you from transmuting! In the meantime as well I can't imagine how we'd change the representation of @RSSchermer do you think this issue is good enough to close now perhaps? |
@alexcrichton Closing would be fine, although given that somehow allocating a |
I'm working on an abstraction around the WebGl2/OpenGL ES3 interface that I'm hoping to make thread-/worker-safe. The core concept revolves around secondary threads/workers constructing monadic
Task
objects which are then submitted back to the main thread (or hopefully, one day, an offscreen-canvas thread/worker). For the ergonomics of the API it's important that certain resource handles (buffers, textures, programs, etc.) can live in these secondary threads, and this is where I run into problems.These resource handles need to be associated with the actual OpenGL GPU resources they represent. In OpenGL I can do this by storing the actual
GLUint
s in a resource handle. Of course, the web platform chose to integrate the deletion of GPU resources with JS garbage collection by wrapping them in JS objects, which makes this not an option for WebGl.JsValue
is - understandably - notSend
/Sync
, which means I also cannot store theJsValue
in my resource handles. With the current public wasm-bindgen interface, the only option this seems to leave is to maintain a hashtable on the main thread which maps my own identifiers toJsValue
s. That would however kind of duplicate wasm-bindgen's own internal hashtable lookup, which I'd rather avoid.Given wasm-bindgen's current implementation, it seems that perhaps the
idx
stored inside aJsValue
would be the ideal way to associate my resource handles with the WebGl objects. This left me wondering if perhaps an analogue toBox
'sinto_raw
andfrom_raw
would be possible/desirable:The caller of
into_raw
would then be responsible for freeing theJsValue
entry in wasm-bindgen's hashtable by callingfrom_raw
at a later time. The documentation forfrom_raw
would mention that it is only safe to call it on aJsId
in the same thread/worker that originally created theJsId
. TheJsId
would be otherwise inert, it simply serves as a thread-safe identifier until its converted back into aJsValue
.Would something like this be considered? Also, would there be an alternative after the host-bindings proposal lands? Would
JsValue
'sidx
then be replaced with some sort ofanyref
as mentioned in the reference-types proposal? I've looked at the host-bindings, threads and reference-types proposals, but I can't quite evaluate whether or not there will be a mechanism that would prevent theseanyref
s from being shared/passed between threads/workers. Perhaps someone here is more intimately involved with the inner workings of current and future WASM and knows this?The text was updated successfully, but these errors were encountered: