I'd like to access the contents of a JSString from another thread

NEW
Unassigned

Status

()

Core
JavaScript Engine
P3
normal
5 months ago
2 months ago

People

(Reporter: Yoric, Unassigned)

Tracking

({triage-deferred})

Firefox Tracking Flags

(Not tracked)

Details

In bug 1063635, we are porting bits of OS.File to C++. The following scenario is pretty common:

1. on the main thread, user creates a very long string;
2. on the main thread, user calls OS.File.writeAtomic(..., myLongString, ...);
3. on the main thread, implementation **copies the contents** of `myLongString` to worker thread;
4. worker receives contents;
5. thread encodes data;
6. thread writes data to disk;
7. worker posts response to main thread.

Ideally, I would like to get rid of the copy in 3. and get the following scenario:

3'. on the main thread, implementation pins `myLongString`, informing the GC that the data should not be moved until further notice;
4'. worker accesses contents of `myLongString` without copy;
5'. once encoding is complete, unpin `myLongString`

Note that there are also applications to optimizing `postMessage` between threads.

Could we have an API for this?

Comment 1

5 months ago
Rather than pinning we probably want to add an API to transfer strings between runtimes like we have for array buffers.

CC'ing Steve since he's working on strings right now.
For the use case in comment 0, I can live with string transfer. Ideally, I'd like to have a JS-accessible API for that, too.

For the use case of `postMessage`, ... well, it is worth trying.
Immediate thoughts:

Pinning is pretty scary. I do not trust users to guarantee that things will definitely be unpinned. But it is still a fair fallback solution.

Transferring would make strings mutable where right now they're pretty much constant. I don't know exactly what this sort of mutation might break, but it definitely feels like it has potential for issues.

(And Transferring probably isn't quite the right thing, since it's a spec thing that's user-visible, but I think we're just talking about reusing the internals of Transferring here.)

I keep thinking it would be nice to have a sort of JSExternalString variant that atomically ref counted its chars pointer. That seems like it would fit very well here. I'm not sure how problematic it would be to implement. Our strings for the most part just have space for three words, and JSExternalString already uses all of them: 1 for length+flags, 1 for the chars pointer, and 1 for the finalizer function pointer. So we would either have to allocate an extra structure for finalizer + refcount, or we could use a larger allockind like JSFatInlineString does. The former might actually be easier, since it would make it easier to nursery allocate and compact strings if the refcount didn't wander around in memory. (Though maybe that doesn't matter, if only the GC is doing that and it blocks all threads anyway?)
(In reply to Steve Fink [:sfink] [:s:] from comment #3)
> Transferring would make strings mutable where right now they're pretty much
> constant. I don't know exactly what this sort of mutation might break, but
> it definitely feels like it has potential for issues.

Transferring would break dependent strings. Also we can't really change the length because Ion likely assumes a string's length can't change, so it could break bounds checks etc.
Keywords: triage-deferred
Priority: -- → P3
You need to log in before you can comment on or make changes to this bug.