SpiderMonkey compartments

A compartment is a new concept with SpiderMonkey 1.8.5. Compartments are used to create multiple JavaScript memory heaps, which avoids having one heap for all JavaScript objects. Each compartment is a separate JavaScript heap.

In previous versions of SpiderMonkey, the garbage collector would walk the entire heap of all JavaScript objects when garbage collection was needed. With compartments, garbage collection can run per compartment. This can result in significant performance improvements in some applications.

An object in one compartment cannot touch an object in another compartment, except through a cross-compartment wrapper.

Compartment Example

The Firefox browser embeds SpiderMonkey. In Firefox 4 and above, compartments are used and all JavaScript objects that belong to a certain origin (such as "http://mail.google.com/" or "http://www.bank.com/") are placed in a separate compartment. This has some important implications:

  • All objects created by a website reside in the same compartment and hence are located in the same memory region. This improves cache utilization by reducing false sharing of cache lines. False sharing occurs when we are trying to operate on an object and we have to read an entire cache line of data into the CPU cache. In the old model, JavaScript objects could be co-located with arbitrary other JavaScript objects from other origins. Such cross-origin objects are used together very infrequently, which reduces the number of cache hits we get. In the new model most objects touched by a website are tightly packed next to each other in memory, with no cross-origin objects in between.
  • JavaScript objects (including JavaScript functions, which are objects also) are only allowed to touch objects in the same compartment. This invariant is very useful for security purposes. The JavaScript engine enforces this requirement at a very low level. It means that a "google.com" object can never accidentally leak into an untrusted website such as "evil.com". Only a special object type can cross the compartment boundaries. We call these objects cross-compartment wrappers. SpiderMonkey tracks the creation of these cross-compartment wrappers and thus it knows at all times what objects from a compartment are kept alive by outside references (through cross-compartment wrappers). This allows the garbage collecting of individual compartments, in addition to global collection. SpiderMonkey simply assumes that all objects referenced from outside the compartment are live, and then walks the object graph inside the compartment. Objects that are found to be disconnected from the graph are discarded. With this new per-compartment garbage collection we shortcut having to walk unrelated heap areas of a window or tab that triggered a garbage collection.

​See also