Skip to content

SpiderMonkey infodump

Josh Matthews edited this page Mar 9, 2018 · 5 revisions

Nursery & barriers

Some JS objects (objects, strings, ids, etc.) are allocated in the nursery. Barriers are needed to ensure that these non-nursery pointers to these nursery values are tracked at all times. Heap<T> ensures that these barriers occur when storing pointers to nursery objects in arbitrary heap locations. Stack roots like Rooted<T> and the CustomAutoRooter API also track pointers to nursery values correctly. Nursery GCs only collect objects from the nursery and check the known set of pointers to nursery values, so they do not invoke arbitrary tracing callbacks (unlike full GCs). This means that any pointers to nursery objects that have not been reported via barriers or stack roots will not be considered and are at risk of becoming dangling.

Storage

  • SM value: *mut JSObject, jsid, *mut JSString
  • Rooted<T>: stack root for an SM value; the value will be considered rooted for the duration of the container's lifetime
  • Heap<T>: heap pointer to SM value; the value will not be GCed iff the container is traced by a trace hook that executes during a GC. It does not root the value merely by existing.

Dangerous stuff

Heap<T> values must not be moved after being initialized to a non-default value

This includes moving a structure that transitively contains an inline Heap<T> (eg. a struct containing a struct that contains a Heap<T>). Doing so will invalidate the pointers that were stored in SM's innards during barrier operations for that Heap<T> value, which will lead to dangling pointers if the contents of the Heap<T> are GCed. To avoid this problem, either:

  • store Box<Heap<T>>
  • box the struct that contains the Heap<T>
  • pin the struct that contains the Heap<T> so it cannot be moved
Clone this wiki locally