Next: , Previous: SEXPTYPEs, Up: SEXPs



1.1.2 头字段的其它部分

头字段 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_NAMEDNAMED 宏设置和访问。它的值可能是 012。 R 有`值传递'(call by value)的假象,因此类似下面的赋值操作

     b <- a

看上去是拷贝一份 a 然后用 b 去访问。 但是,如果ab 随后都没有改变,则没有必要 把它拷贝一份。实际情况是,新符号 ba 绑定 一样的值,并且 对值对象(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 之前已经被使用,下面会 详细描述(通过源码的细致分析说明)。

这些位变量可以通过 LEVELSSETLEVELS 宏访问或设置。这两个宏的名字 看上去和内部因子和有序因子类型有关,但现在已很少 在代码里面出现了。 gp 字段是对 SEXPTYPE 类型是 串行化的/非串行化的(serialized/unserialized), 而对 NILSXPSYMSXPENVSXP 则不是。

如果我们为从0开始的位分类,gp 的位14和15用于 `特异绑定'(`fancy bindings')。位14用锁定一个绑定或环境, 而位15用于表明一个处于活动状态的绑定。(对于`活动状态的绑定'(`active binding') 的定义见源码文件 src/main/envir.c 的头注释部分。 位15用于表明一个环境是否参与全局 高速缓存(global cache)。

几乎所有其它使用仅仅使用位0和1,尽管 它们科研保留开始的4个位。

ARGUSEDSET_ARGUSED 在匹配事实和 形式函数参数的时候使用。它可能的取值是 0, 1 和 2。

MISSINGSET_MISSING 用于参数的成对列表。 4个位被保留,但只有两个可以使用(具体为什么会这样,现在还没有解释)。 似乎,位0被 matchArgs 用于标记返回参数列表中的 缺失的参数,位1用来标记把默认值拷贝给闭包求值框架的某个参数。

DDVALSET_DDVAL 使用位0。 这表明 SYMSXP 是当 ... 被处理时, 默认创建的 ..n 符号的一种。同时也表明, 该位可能需要在 DOTSXP 查询。

位 0 用于标签 PRSEEN。该标签表明一个允诺(promise) 在允诺求值过程中是否可见(这样可以避免 递归回路(recursive loops))。

在环境框架下TAGPRINTNAME 上面,位 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字符串的时候没有必要知道字符编码)。


Footnotes

[1] 译者注:原句为“ For closures it is set by debug() and unset by undebug(), and indicates that evaluations of the function should be run under the browser.”

[2] 译者注:事实上以函数的形式表示,见《R语言定义》