JavaScript:SpiderMonkey:GC Futures: Difference between revisions

Line 148: Line 148:
Each context has a ''current compartment'', initially the default compartment, and normally the compartment of JS_GetScopeChain(cx). So, for example, <code>js_Atomize(cx, name, strlen(name), 0)</code> allocates the new string from <code>cx->currentCompartment()</code>.
Each context has a ''current compartment'', initially the default compartment, and normally the compartment of JS_GetScopeChain(cx). So, for example, <code>js_Atomize(cx, name, strlen(name), 0)</code> allocates the new string from <code>cx->currentCompartment()</code>.


A tricky consequence of this is that the API function <code>JS_SetProperty(cx, obj, name, vp)</code> must put cx into obj's compartment before calling <code>js_Atomize</code>. Otherwise obj might end up with property ids in other compartments, a bad scene.
A tricky consequence of this is that in an API call <code>JS_SetProperty(cx, obj, name, vp)</code>, obj must be in <code>cx->currentCompartment()</code>, because <code>JS_SetProperty</code> calls <code>js_Atomize</code> to create the property id. Otherwise obj could end up with property ids that reside in <code>cx->currentCompartment()</code> rather than its own compartment: a violation of the rules that will lead to a crash in GC.


When does a context's current compartment change? At API entry points and when a function is called across compartment boundaries (which always happens via a wrapper). So it will be rare and we can fall off trace when it happens.
When does a context's current compartment need to change? Only when setting up a new compartment and when calling across compartment boundaries. The latter always happens in wrapper code. So this will be rare and we can require an API call and fall off trace when it happens.
 
It might be better to require the application to change the current compartment explicitly:


  JSCompartment *
  JSCompartment *
Line 163: Line 161:
  JS_SetCurrentCompartment(cx, compartment);
  JS_SetCurrentCompartment(cx, compartment);


The only code that would need to do so is (a) code setting up new compartments; (b) wrappers. All other APIs could just assert that cx->currentCompartment() agrees with all the arguments that happen to be gc-things.
All existing APIs could just assert that cx->currentCompartment() agrees with all the arguments that happen to be gc-things. The precise rule is: each gc-thing passed in must either be in <code>cx->currentCompartment()</code> or be a string or double in <code>cx->runtime->defaultCompartment</code>.
 
The precise agreement rule is: each gc-thing must either be in <code>cx->currentCompartment()</code> or be a string or double in <code>cx->runtime->defaultCompartment</code> (such strings and doubles may be referenced from anywhere).
638

edits