guile-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: The relationship between SCM and scm_t_bits.


From: Dirk Herrmann
Subject: Re: The relationship between SCM and scm_t_bits.
Date: Sat, 15 May 2004 09:31:52 +0200
User-agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.4.2) Gecko/20040220

Marius Vollmer wrote:

Hi,

I just got confused about our two 'fundamental' types, SCM and
scm_t_bits.

The two types were introduced in order to create a level of abstraction between code, that operates on the encoding of scheme types, and code that only requires on API elements to do so. The background was, that SCM formerly was just a typedef to "long". This had the disadvantage that the compiler did not do proper type checking when dealing with SCM types. For example, you could by mistake write "if (some_SCM_value) ..." if instead you had intended to write "if (!SCM_FALSEP (some_SCM_value))". Guile had a number of bugs of this or a similar type at that time. Thus, we wanted to introduce a better type checking, but on the other hand be able to deal with the bit representation in low level code. Thus the separation into SCM and scm_t_bits.

The idea is, to have SCM normally defined to be some performance efficient type, like a pointer to an unknown struct. This will inhibit most errors, like passing an integer where a SCM is expected, or performing arithmetic operations on a SCM value. It does not, however, inhibit the "if (some_SCM_value)" bug, since the compiler will accept a pointer there. Thus, from time to time, just for type-checking purposes, we can have SCM defined as a struct or union, thus inhibiting even those problems. You will find more information about that if you are looking at the use of SCM_DEBUG_TYPING_STRICTNESS in tags.h and the explanation in __scm.h. Unfortunately, compiling with SCM_DEBUG_TYPING_STRICTNESS set to 2 does not compile without errors, due to some tricky problems in some files. Nevertheless it should still be quite helpful for most parts of guile. Using it, I remember to have fixed about 5 to 10 bugs in guile at that time, which would not have been easy to find without thorough code inspection (or, if someone would have run into them).

For example, consider a list that is pointed to by a global variable
and some fairly standard way of dealing with singly-linked lists in C:

 SCM head;

 void
 delete_some ()
 {
   SCM *node_ptr = &head;
   if (should_delete (*node_ptr))
     *node_ptr = SCM_CDR (*node_ptr);
   else
     node_ptr = SCM_CDRLOC (*node_ptr);
 }

Such code should be avoided. Otherwise I think it is difficult to move to generational garbage collection: Generational garbage collection is based on the assumption, that newer objects only can point to older objects. This is true, as long as you don't modifiy existing objects. Therefore, write accesses to existing objects must pass through a write barrier, which is some code that helps the gc to work correctly even in case of references from old to new.

By modifying SCM values through SCM pointers you skip the write barrier. When switching to generational GC, such code would have to be fixed, either to avoid using the pointer access, or to add some operations that perform, what the write barrier would have done. Thus, in order to keep the number of places small which require such fixing later, I try to avoid using SCM_CDRLOC etc.

Best regards,
Dirk Herrmann





reply via email to

[Prev in Thread] Current Thread [Next in Thread]