Closed Bug 1311020 Opened 8 years ago Closed 8 years ago

XDR off-main-thread.

Categories

(Core :: JavaScript Engine, defect)

defect
Not set
normal

Tracking

()

RESOLVED INVALID

People

(Reporter: nbp, Unassigned)

References

Details

As we are adding a start-up bytecode cache, we are replacing the Parser phase by a shorter one which decode a script and load the sources.  The XDR content is about the same magnitude as the source, and we would have the same problems.

We need to make it possible to move EncodeScript & DecodeScript out of the main thread.

We are facing multiple issues here:
 (1) XDR functions are using Rooted.  Rooted are expected to be only on the main thread.  The reason being that we are building a linked-list of rooted elements of the same type, such that our precise GC can mark the stack.  If we move XDR functions out of the main thread, we would need to root the stack elements differently.

 (2) Doing XDR encoding on another thread implies that we might have data races.   For example, a function can be delazyfied as we attempt to encode it.  So we would need to have a lock to prevent us from encoding at the same time as the JS is being executed.  Also, the reason we are going out of the main thread is to avoid blocking the main thread.  Thus, to avoid blocking the main thread we would have to add a mechanism to let the main thread steal the lock from the XDR thread, probably with some cooperative yields from the XDR thread.
Why does EncodeScript need to be off the main thread?

For decoding, you could look at how we do off thread parsing: the parser thread creates roots and such, but these are IIRC ignored by the GC.  Instead, the parser thread uses a compartment/zone which the main thread's GC does not collect anything from.  Once the parser finishes, the resulting data is moved into the target compartment/zone (GlobalHelperThreadState::mergeParseTaskCompartment).
(In reply to Nicolas B. Pierron [:nbp] from comment #0)

1) (Written before Brian's reply above) Rooting is fine to use off main thread if it's in a zone used by an exclusive thread.  The root stack for the zone is used and never marked because we don't GC these zones.  So I think we can do the same thing we do for off-main-thread parsing at the moment: decode into a separate zone and then merge.

2) For the conflict between encoding and relazification, there are several checks in JSFunction::maybeRelazify that prevent this.  One of these is whether the functions compartment has been entered, which I think would be true in this case (encoding on another thread with an ExclusiveContext).

Are there other pieces of script state that get encoded and can be mutated by JS after the script has been created?  There are a bunch of compilation hints but these don't seem to be encoded by XDR but there may be other things too.  I don't know how we'd handle that.

The lock stealing / yield thing sounds complicated and I'd like to avoid that if possible.

For a different approach, would it be possible to request encoding at the same time as the script is parsed?  We could do it before the script is exposed to the main JS environment and this situation would not arise.
(In reply to Jon Coppeard (:jonco) from comment #2)
> 2) For the conflict between encoding and relazification, there are several
> checks in JSFunction::maybeRelazify that prevent this.  One of these is
> whether the functions compartment has been entered, which I think would be
> true in this case (encoding on another thread with an ExclusiveContext).

The relazification problem is less of an issue, as my intent was to disable it until we finish/give-up encoding the bytecode.

The problem is the delazification, which converts a LazyScript into a JSScript.  Now, I recall you suggested capturing the state of all the JSScript/LazyScript ahead of time, and encode based on this original state instead of encoding based on the current state.  I guess this could work.

> Are there other pieces of script state that get encoded and can be mutated
> by JS after the script has been created?  There are a bunch of compilation
> hints but these don't seem to be encoded by XDR but there may be other
> things too.  I don't know how we'd handle that.

I think the LazyScript/JSScript is the only one which is allowed at the moment.

> For a different approach, would it be possible to request encoding at the
> same time as the script is parsed?  We could do it before the script is
> exposed to the main JS environment and this situation would not arise.

Interesting!

So instead of making the serialization happen as a post-processing phase, we do it as we generate the bytecode.  This will spread the cost to every parse phase which we expect to encode, sharing the cost with the parser.

In addition this removes the JSOP_OBJECT limitation, as we can encode the JSObject before we got a chance to mutate it.

There might be a few issues such as XDR optimization for sharing the encoding of atoms, but this should not be too hard to work-around.

I will think more about it!  Thanks.
Blocks: 1316081
I forked this bug into the decoding part (Bug 1316078) and its encoding part (Bug 1316081).
No longer blocks: 1316081
See Also: → 1316078, 1316081
Status: NEW → RESOLVED
Closed: 8 years ago
Resolution: --- → INVALID
You need to log in before you can comment on or make changes to this bug.