[Webkit-unassigned] [Bug 224077] New: Make environments safe for space

bugzilla-daemon at webkit.org bugzilla-daemon at webkit.org
Thu Apr 1 14:32:28 PDT 2021


https://bugs.webkit.org/show_bug.cgi?id=224077

            Bug ID: 224077
           Summary: Make environments safe for space
           Product: WebKit
           Version: WebKit Nightly Build
          Hardware: Unspecified
                OS: Unspecified
            Status: NEW
          Severity: Normal
          Priority: P2
         Component: JavaScriptCore
          Assignee: webkit-unassigned at lists.webkit.org
          Reporter: sbarati at apple.com
                CC: fpizlo at apple.com

Our environments aren't safe for space because we retain all values in a scope if the scope itself is alive.

Let's consider a test program:

```
function a() {
    let a = {};
    let b = {};
    function foo() { return a; }
    return function bar() { return b; }
}
let f = a();
```

In the above program, we'll keep alive both "a" and "b" in the environment, even though bar is the only function that's alive, and it only references "b". To be safe for space, bar should only retain "b", and foo should only retain "a".

Each closure should only retain the variables it might access.

In practice, this is a bit tricky to implement. I started on it, and ran into some snags that'll require being worked out. 

An implementation sketch with some open questions:
- Each function (or executable, to be more precise), knows which variables it'll keep alive. JSFunction, when marking, won't just append its scope to the slot visitor. Instead, it'll have a special form of a "partial" visit that marks the values or corresponding values' bits inside lexical environment. Lexical environment, will need to be visited in such a way that it'll only append objects with corresponding set bits.
- Lexical environment might also get marked strongly, not just partially (e.g, it's a root for some reason), it'll then have to mark every slot that isn't dead (e.g, died in some prior GC).
- These two things above can happen in the same cycle. So we can't just set the mark bit of a lexical environment after partially visiting it, because it may cause it to not be fully visited (e.g, when it's a root).
- Phil's idea was that maybe we could repurpose the newly allocated bits such that we set it so the JSScope doesn't get swept. And we set that when partially visiting instead of the mark bit.
- Lexical environment probably has two bit vectors. One will tell you if any object has ever died, and another will tell you in the current marking cycle what needs to be marked. You likely also need a version number for the bit vector so we know when to transfer over the bits of dead objects so we never visit their slots in the future.
- We need some way of partially visiting the environments after setting new bits in its alive bit vector.
- We might need to keep alive parent scopes to some degree even if we don't rely on them, because an environment might get fully marked in a future GC cycle (e.g, again, let's say it's a root somehow), and it'll need a valid "next" scope. Or maybe we can play some games here where a dead "next" becomes the global object or something. Or we just pretend there is no "next" if we proved we didn't need after some time. Just need to make sure we don't rely on  being able to traverse the next() chain indefinitely till we hit the global object, or something similar.
- We need to make sure everything stays alive for Eval. Maybe also "with"? Easy enough to do.
- It would be nice if a write barrier during concurrent GC or before a full GC didn't cause the environment to get fully marked via being in the remembered set. But maybe that's fine, or at least fine for a v1.

-- 
You are receiving this mail because:
You are the assignee for the bug.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.webkit.org/pipermail/webkit-unassigned/attachments/20210401/a92bfa1e/attachment.htm>


More information about the webkit-unassigned mailing list