Next: , Previous: , Up: Allocation of Objects in SXEmacs Lisp   [Contents][Index]


11.3 GCPROing

GCPROing is one of the ugliest and trickiest parts of Emacs internals. The basic idea is that whenever garbage collection occurs, all in-use objects must be reachable somehow or other from one of the roots of accessibility. The roots of accessibility are:

  1. All objects that have been staticpro()d or staticpro_nodump()ed. This is used for any global C variables that hold Lisp objects. A call to staticpro() happens implicitly as a result of any symbols declared with defsymbol() and any variables declared with DEFVAR_FOO(). You need to explicitly call staticpro() (in the vars_of_foo() method of a module) for other global C variables holding Lisp objects. (This typically includes internal lists and such things.). Use staticpro_nodump() only in the rare cases when you do not want the pointed variable to be saved at dump time but rather recompute it at startup.

    Note that obarray is one of the staticpro()d things. Therefore, all functions and variables get marked through this.

  2. Any shadowed bindings that are sitting on the specpdl stack.
  3. Any objects sitting in currently active (Lisp) stack frames, catches, and condition cases.
  4. A couple of special-case places where active objects are located.
  5. Anything currently marked with GCPRO.

Marking with GCPRO is necessary because some C functions (quite a lot, in fact), allocate objects during their operation. Quite frequently, there will be no other pointer to the object while the function is running, and if a garbage collection occurs and the object needs to be referenced again, bad things will happen. The solution is to mark those objects with GCPRO. Unfortunately this is easy to forget, and there is basically no way around this problem. Here are some rules, though:

  1. For every GCPROn, there have to be declarations of struct gcpro gcpro1, gcpro2, etc.
  2. You must UNGCPRO anything that’s GCPROed, and you must not UNGCPRO if you haven’t GCPROed. Getting either of these wrong will lead to crashes, often in completely random places unrelated to where the problem lies.
  3. The way this actually works is that all currently active GCPROs are chained through the struct gcpro local variables, with the variable ‘gcprolist’ pointing to the head of the list and the nth local gcpro variable pointing to the first gcpro variable in the next enclosing stack frame. Each GCPROed thing is an lvalue, and the struct gcpro local variable contains a pointer to this lvalue. This is why things will mess up badly if you don’t pair up the GCPROs and UNGCPROs—you will end up with gcprolists containing pointers to struct gcpros or local Lisp_Object variables in no-longer-active stack frames.
  4. It is actually possible for a single struct gcpro to protect a contiguous array of any number of values, rather than just a single lvalue. To effect this, call GCPROn as usual on the first object in the array and then set gcpron.nvars.
  5. Strings are relocated. What this means in practice is that the pointer obtained using XSTRING_DATA() is liable to change at any time, and you should never keep it around past any function call, or pass it as an argument to any function that might cause a garbage collection. This is why a number of functions accept either a “non-relocatable” char * pointer or a relocatable Lisp string, and only access the Lisp string’s data at the very last minute. In some cases, you may end up having to alloca() some space and copy the string’s data into it.
  6. By convention, if you have to nest GCPRO’s, use NGCPROn (along with struct gcpro ngcpro1, ngcpro2, etc.), NNGCPROn, etc. This avoids compiler warnings about shadowed locals.
  7. It is always better to err on the side of extra GCPROs rather than too few. The extra cycles spent on this are almost never going to make a whit of difference in the speed of anything.
  8. The general rule to follow is that caller, not callee, GCPROs. That is, you should not have to explicitly GCPRO any Lisp objects that are passed in as parameters.

    One exception from this rule is if you ever plan to change the parameter value, and store a new object in it. In that case, you must GCPRO the parameter, because otherwise the new object will not be protected.

    So, if you create any Lisp objects (remember, this happens in all sorts of circumstances, e.g. with Fcons(), etc.), you are responsible for GCPROing them, unless you are absolutely sure that there’s no possibility that a garbage-collection can occur while you need to use the object. Even then, consider GCPROing.

  9. A garbage collection can occur whenever anything calls Feval, or whenever a QUIT can occur where execution can continue past this. (Remember, this is almost anywhere.)
  10. If you have the least smidgeon of doubt about whether you need to GCPRO, you should GCPRO.
  11. Beware of GCPROing something that is uninitialized. If you have any shade of doubt about this, initialize all your variables to Qnil.
  12. Be careful of traps, like calling Fcons() in the argument to another function. By the “caller protects” law, you should be GCPROing the newly-created cons, but you aren’t. A certain number of functions that are commonly called on freshly created stuff (e.g. nconc2(), Fsignal()), break the “caller protects” law and go ahead and GCPRO their arguments so as to simplify things, but make sure and check if it’s OK whenever doing something like this.
  13. Once again, remember to GCPRO! Bugs resulting from insufficient GCPROing are intermittent and extremely difficult to track down, often showing up in crashes inside of garbage-collect or in weirdly corrupted objects or even in incorrect values in a totally different section of code.

If you don’t understand whether to GCPRO in a particular instance, ask on the mailing lists. A general hint is that prog1 is the canonical example.

Given the extremely error-prone nature of the GCPRO scheme, and the difficulties in tracking down, it should be considered a deficiency in the SXEmacs code. A solution to this problem would involve implementing so-called conservative garbage collection for the C stack. That involves looking through all of stack memory and treating anything that looks like a reference to an object as a reference. This will result in a few objects not getting collected when they should, but it obviates the need for GCPROing, and allows garbage collection to happen at any point at all, such as during object allocation.


Next: , Previous: , Up: Allocation of Objects in SXEmacs Lisp   [Contents][Index]