> I can't figure out exactly what you mean here. Temporary pins on the stack should be fine, and I don't see why anything else would be necessary.
The browser has a whole native heap (i.e. C++ objects, in current impls) that participates in the JS GC heap as follows:
- If the C++ object is referenced from C++ or from JS, it must be kept alive.
- If the C++ object references a JS object, then the JS object must be kept alive, so long as the C++ object would have been alive per the previous rule.
- It's possible for an object reference chain like JSobject->C++object->C++object->JSobject, and let's assume there are no other pointers to the C++ objects, in which case the last JS object should kept alive by GC only if the first JS object is alive.
- It's possible for dead reference cycles to exist like JSobject<->C++object, in which case both should die.
This requires that C++ has the ability to place references to JS objects in C++ fields.
This is where pinning comes in. It would be quite simple (and memory safe) but also totally incorrect (i.e. massive memory leak) to say that if a C++ field points to a JS object, then the GC just sees that field as a root. This is what I mean by pinning. (Note that "pinning" has many meanings in GC jargon; I'm using the Hermes version of the jargon. I guess I could have said "strong root" or something, but that's weirder to say.) This would be wrong, since it would not allow us to collect the dead cycle at all. Dead cycles are a common case in the browser. It would also cause other subtle breakage.
So, what the browser does instead is to have the C++ heap participate in GC: every C++ object that could possibly store a reference to JS objects anywhere can respond to GC callbacks asking it to account for all of those references. And, every C++ object needs to have a story for being referenced exclusively from JS, exclusively from C++, or a combo of the two. And the C++ code needs to be able to participate in whatever barrier discipline is necessary to get generations or incrementality or concurrency that the JS heap wants.
There are different ways to do this. Blink's Oilpan is probably the most principled, and that's basically a whole GC-for-C++ framework - very complex stuff. So, tons of inherently not-memory-safe code on the browser side just so it can do business with the JS heap.