头字段 sxpinfo 是以如下的 32 位 C 结构定义
struct sxpinfo_struct {
SEXPTYPE type : 5; /* 上面已经讨论过 */
unsigned int obj : 1; /* 这是一个有类属性的对象吗? */
unsigned int named : 2; /* 用于控制拷贝 */
unsigned int gp : 16; /* 通常目的,见下面的内容 */
unsigned int mark : 1; /* 在GC里面标识 `in use'(在使用) */
unsigned int debug : 1;
unsigned int trace : 1;
unsigned int spare : 1; /* 没有被使用的 */
unsigned int gcgen : 1; /* GC的世代数 */
unsigned int gccls : 3; /* GC的节点的类 */
}; /* Tot: 32 */
debug 位用于闭包(closures)和环境(environments)。对于闭包,
通过 debug() 载入和 undebug() 卸载,并且表明函数的求值
必须在浏览器下运行1。对于环境,它只表明浏览器是否处于单步模式
(single-step mode)。
trace 位用于进行 trace() (代码跟踪测试)的函数,
并且用于副本跟踪测试(见 tracemem)
的其它对象。
named 字段通过 SET_NAMED 和
NAMED 宏设置和访问。它的值可能是 0,1 和 2。
R 有`值传递'(call by value)的假象,因此类似下面的赋值操作
b <- a
看上去是拷贝一份 a 然后用 b 去访问。
但是,如果a 和 b 随后都没有改变,则没有必要
把它拷贝一份。实际情况是,新符号 b 和 a 绑定
一样的值,并且 对值对象(value object)的 named 字段进行
设置(在这种情况下设为 2)。
当一个对象要改变时,要参考 named 字段的值。
该字段是 2 意味着这个对象在改变之前需要
复制一下。(注意,这并没有要求该对象一定要复制一下,
仅仅表示它需要复制一下无论是否真的需要)。字段值是
0 时表示没有其它 SEXP 和这个对象共享
数据,因此对它的修改是安全的。
字段值是 1 用于如下情况
dim(a) <- c(7, 2)
其中,a 在整个计算过程中原则上以两份拷贝
的形式存在,大体上如下所示2
a <- `dim<-`(a, c(7, 2))
但是在这种情况下,这种多拷贝的形式不再是必要的, 如一些原始函数可以通过优化来避免 额外的一份拷贝。
gp 位用`通用目的'(`general purpose')来定义。
从 R 2.4.0 开始,位 4(即,第五位)用于标明 S4 对象。
位 0-3 和 位 14-15 之前已经被使用,下面会
详细描述(通过源码的细致分析说明)。
这些位变量可以通过 LEVELS 和
SETLEVELS 宏访问或设置。这两个宏的名字
看上去和内部因子和有序因子类型有关,但现在已很少
在代码里面出现了。
gp 字段是对 SEXPTYPE 类型是
串行化的/非串行化的(serialized/unserialized),
而对 NILSXP, SYMSXP 和 ENVSXP
则不是。
如果我们为从0开始的位分类,gp 的位14和15用于
`特异绑定'(`fancy bindings')。位14用锁定一个绑定或环境,
而位15用于表明一个处于活动状态的绑定。(对于`活动状态的绑定'(`active binding')
的定义见源码文件 src/main/envir.c 的头注释部分。
位15用于表明一个环境是否参与全局
高速缓存(global cache)。
几乎所有其它使用仅仅使用位0和1,尽管 它们科研保留开始的4个位。
宏 ARGUSED 和 SET_ARGUSED 在匹配事实和
形式函数参数的时候使用。它可能的取值是
0, 1 和 2。
宏 MISSING 和 SET_MISSING 用于参数的成对列表。
4个位被保留,但只有两个可以使用(具体为什么会这样,现在还没有解释)。
似乎,位0被 matchArgs 用于标记返回参数列表中的
缺失的参数,位1用来标记把默认值拷贝给闭包求值框架的某个参数。
宏 DDVAL 和 SET_DDVAL 使用位0。
这表明 SYMSXP 是当 ... 被处理时,
默认创建的 ..n 符号的一种。同时也表明,
该位可能需要在 DOTSXP 查询。
位 0 用于标签 PRSEEN。该标签表明一个允诺(promise)
在允诺求值过程中是否可见(这样可以避免
递归回路(recursive loops))。
在环境框架下TAG 的 PRINTNAME 上面,位 0 用于
HASHASH。
位 0 和 1 用于弱引用(weak references)(用于表明 `准备终结'('ready to finalize'),`退出时终结'('finalize on exit'))。
位 0 用在条件处理系统(condition handling system)(利用VECSXP)时
来表明一个调用处理器(calling handler)。
从 R 2.5.0 开始,CHARSXP的位 2 和 3 分布用于表示
大家熟知的 Latin-1 和 UTF-8 字符编码。
(如果是ASCII,则不需要设置。
因为代码在处理ASCII字符串的时候没有必要知道字符编码)。