[meta] Multithreaded JS runtime

RESOLVED FIXED

Status

()

Core
JavaScript Engine
RESOLVED FIXED
2 years ago
4 months ago

People

(Reporter: bhackett, Assigned: bhackett)

Tracking

(Blocks: 1 bug)

Trunk
Points:
---
Dependency tree / graph

Firefox Tracking Flags

(firefox53 affected)

Details

Attachments

(1 attachment)

(Assignee)

Description

2 years ago
I've outlined below ideas that have come up in discussions during the work week about how to rearchitect threading in the JS VM.  This is mainly for supporting Quantum DOM but I think this stuff is really good to do anyways.

The goal is to have a single runtime in the process, with which multiple threads can interact simultaneously.  Each zone is part of a group: there is a single system zone group, plus any number of content zone groups.  Cross zone group pointers may only be between the system group and other groups.  Each thread operating on a runtime has exclusive access to all the zones in a single content group plus --- if it takes a lock --- the system group.

Content zone groups are an abstraction corresponding to the TabGroup or DocGroup abstraction in Gecko.  Eventually we might want to flatten all the zones in a group into a single zone (so that zone group == zone), but that will depend on how things look once this stuff has actually been implemented.

We can reach this goal with the following steps:

1) Allow collecting atoms outside of full GCs

If each zone has a bitmap indicating the atoms which it might be using, then any atom which is not in the bitmap for any zone can be collected.  We can update the bitmap when the zone is GCed and when the mutator does a few things (like string atomization) while it is in the zone.

2) Stop doing full GCs

Doing 1) would remove the main reason why we still need to do full GCs, so we can rework the GC heuristics so that we never do full GCs.  Ideally we will only ever have to GC one zone group at a time.

3) Make nurseries per zone group

There are I think a couple different ways of doing this.  Either the chunk size can be reduced and a separate nursery given to each zone group, or we could have a single nursery memory pool in the runtime from which each zone group allocates smaller pieces.

4) Allow multiple threads per runtime

Other than nursery and GC issues there isn't a whole lot of data in the runtime which needs reworking for preemptively scheduled multithreaded access (in part because the runtime is already multithreaded in more limited ways).  One issue is what to do with all the callbacks in the JS engine that reenter Gecko.  As part of Quantum DOM Gecko will need to make sure these callbacks can be invoked off the main thread, and as part of this project the JS engine should have a lock to make sure no more than one thread is in one of these callbacks at once (this simplifies synchronization issues for Gecko).  We'll also want to be able to whitelist callbacks that are threadsafe and don't require the lock to be taken.

5) Fold worker runtimes into the main runtime

I don't think this would require any real work once 1)-4) are done. At this point we would only ever have a single runtime in the process, and could either make it a static variable or just dissolve the JSRuntime class and turn its members into static variables in suitable parts of the codebase.

Some additional issues:

- JSContext will I think be used to store the thread local data used by one of the threads operating on a runtime: activation data, caches, etc.  We'll go back to having multiple JSContexts in existence, but only one per thread.

- Code that tries to operate on multiple content zone groups at once will end up throwing an exception. This could happen if, say, content called into the system zone, which then called into a different content group.  There shouldn't be a reason why this needs to happen but adding the restriction here might break some addons.

- Similarly, the outline above requires that we know which content zone group we are operating on before we even enter JS.  This is mainly so that we don't need to have locks on each content group, but makes it trickier to deal with top level system code that might operate on any content group.  It's not clear if code like this exists (or needs to exist), but if it did Gecko could potentially handle this by managing event loops so that such system code only executes in a single threaded manner.
This sounds awesome! It also sounds like something Servo needs to be aware of, CC-ing a few people.
Do we even expect to have content and chrome groups in the same process?
(In reply to :Ms2ger (⌚ UTC+1/+2) from comment #2)
> Do we even expect to have content and chrome groups in the same process?

I don't think so, but it seems like it wouldn't matter too much if we did. WebExtensions content scripts probably go into the same group as the content they relate to, and other than that I can't think of a reason for a system group in Servo.
(Assignee)

Updated

2 years ago
Depends on: 1324002
(Assignee)

Updated

2 years ago
Depends on: 1325050
(Assignee)

Comment 4

a year ago
Created attachment 8828619 [details] [diff] [review]
partial patch

This patch has changes to allow off main thread parse threads to use separate zone groups from the runtime's main thread.  This is a more advanced version of the patch I posted in bug 1325050 (and alluded to in comment 4 of that bug).  Next week I'll be posting bugs with patches on top of bug 1325050 to get to this state, but I'm putting this patch up now in case my computer catches on fire or something.
Assignee: nobody → bhackett1024
(Assignee)

Updated

a year ago
Depends on: 1334194
(Assignee)

Updated

a year ago
Depends on: 1334212
(Assignee)

Updated

a year ago
Depends on: 1334837
(Assignee)

Updated

a year ago
Depends on: 1334845
(Assignee)

Updated

a year ago
Depends on: 1334880
(Assignee)

Updated

a year ago
Depends on: 1334885
(Assignee)

Updated

a year ago
Depends on: 1334927
(Assignee)

Updated

a year ago
Depends on: 1335095
(Assignee)

Updated

a year ago
Depends on: 1335130
(Assignee)

Updated

a year ago
Depends on: 1335846
(Assignee)

Updated

a year ago
Depends on: 1336603
This sounds great! I created an issue in Servo for this: https://github.com/servo/servo/issues/15373

One thing which would make this really great is if we could migrate compartments from one zone group to another; this would allow us to support mutating document.domain, but keep cross-origin objects in different zone groups. At the moment, Servo has to keep similar-origin content in the same script thread, and it would be nice if we could loosen that restriction.
(Assignee)

Updated

a year ago
Depends on: 1337070
(Assignee)

Updated

a year ago
Depends on: 1337084
(Assignee)

Updated

a year ago
Depends on: 1337106
(Assignee)

Updated

a year ago
Depends on: 1337109
(Assignee)

Updated

a year ago
Depends on: 1337112
(Assignee)

Updated

a year ago
Depends on: 1337117
(Assignee)

Comment 6

a year ago
(In reply to Alan Jeffrey [:ajeffrey] from comment #5)
> This sounds great! I created an issue in Servo for this:
> https://github.com/servo/servo/issues/15373
> 
> One thing which would make this really great is if we could migrate
> compartments from one zone group to another; this would allow us to support
> mutating document.domain, but keep cross-origin objects in different zone
> groups. At the moment, Servo has to keep similar-origin content in the same
> script thread, and it would be nice if we could loosen that restriction.

Would you be able to avoid having cross-compartment edges entering or leaving the compartment when its document.domain property was modified?  Comment 0 touches on this but we can't have cross-zone-group pointers between zone groups for content, as otherwise the effects of other threads would be visible to content scripts.

Migrating an arbitrary compartment from one zone or zone group to another isn't really something that can be done with the engine's current architecture without doing the same thing for all other compartments in the same zone.  Changing zone pointers in the GC thing arenas will change the zone for all other things in the arena, and if two compartments are in the same zone then the same arenas can be used to hold their GC things.  However, it might be possible to do a moving GC that basically reallocates all the content from one compartment into zones in a new zone group, though there may be restrictions in the compacting GC that would prevent this.
(In reply to Brian Hackett (:bhackett) from comment #6)
> (In reply to Alan Jeffrey [:ajeffrey] from comment #5)
> > This sounds great! I created an issue in Servo for this:
> > https://github.com/servo/servo/issues/15373
> > 
> > One thing which would make this really great is if we could migrate
> > compartments from one zone group to another; this would allow us to support
> > mutating document.domain, but keep cross-origin objects in different zone
> > groups. At the moment, Servo has to keep similar-origin content in the same
> > script thread, and it would be nice if we could loosen that restriction.
> 
> Would you be able to avoid having cross-compartment edges entering or
> leaving the compartment when its document.domain property was modified? 
> Comment 0 touches on this but we can't have cross-zone-group pointers
> between zone groups for content, as otherwise the effects of other threads
> would be visible to content scripts.

We can probably arrange for all cross-compartment edges to go via the system zone group (devil is in the details of course).

> Migrating an arbitrary compartment from one zone or zone group to another
> isn't really something that can be done with the engine's current
> architecture without doing the same thing for all other compartments in the
> same zone.  Changing zone pointers in the GC thing arenas will change the
> zone for all other things in the arena, and if two compartments are in the
> same zone then the same arenas can be used to hold their GC things. 
> However, it might be possible to do a moving GC that basically reallocates
> all the content from one compartment into zones in a new zone group, though
> there may be restrictions in the compacting GC that would prevent this.

Doing a moving gc would be fine, setting document.domain hopefully doesn't happen very often. We might be able to do one-zone-per-compartment if migrating zones is easier than migrating compartments.
Blocks: 1302270
(Assignee)

Updated

a year ago
Depends on: 1337491
(Assignee)

Updated

a year ago
Depends on: 1337968
(In reply to Alan Jeffrey [:ajeffrey] from comment #7)
> (In reply to Brian Hackett (:bhackett) from comment #6)
> > Would you be able to avoid having cross-compartment edges entering or
> > leaving the compartment when its document.domain property was modified? 
> > Comment 0 touches on this but we can't have cross-zone-group pointers
> > between zone groups for content, as otherwise the effects of other threads
> > would be visible to content scripts.
> 
> We can probably arrange for all cross-compartment edges to go via the system
> zone group (devil is in the details of course).

That doesn't sound right. In order to go "via" the system zone group, you would need an object in between. Is that what you mean? Normally there are lots of cross-compartment edges within a zone, so this seems weird to me. And I didn't think there were supposed to be paths between zone groups going through the system zone group anyway?

(You may know this, but: cross-compartment wrappers are determined by the source and target compartment only; if you wrapped something from compartment A into a system compartment, then wrapped that wrapper into compartment B, you would end up with exactly the same thing as wrapping the original object from A into B.)

I'm not sure what's required here, but moving zones between zone groups sounds more feasible than moving individual compartments.

> > Migrating an arbitrary compartment from one zone or zone group to another
> > isn't really something that can be done with the engine's current
> > architecture without doing the same thing for all other compartments in the
> > same zone.  Changing zone pointers in the GC thing arenas will change the
> > zone for all other things in the arena, and if two compartments are in the
> > same zone then the same arenas can be used to hold their GC things. 
> > However, it might be possible to do a moving GC that basically reallocates
> > all the content from one compartment into zones in a new zone group, though
> > there may be restrictions in the compacting GC that would prevent this.
> 
> Doing a moving gc would be fine, setting document.domain hopefully doesn't
> happen very often. We might be able to do one-zone-per-compartment if
> migrating zones is easier than migrating compartments.

Do you mean one-zone-per-tab? If you migrate zones, then you get intra-zone cross-compartment edges for free. And not everything is stored within a compartment; some is in the zone.
(Assignee)

Updated

a year ago
Depends on: 1340822
I think this is done, reopen if not.
Status: NEW → RESOLVED
Last Resolved: 4 months ago
Resolution: --- → FIXED
You need to log in before you can comment on or make changes to this bug.