<primitive: xyz> 语句在方法声明中的作用是什么?

What does the <primitive: xyz> statement do in a method declaration?

这是 Character class 的 asciiValue 方法:

asciiValue
   <primitive: 171>
   ^ self primitiveFailed

asciiValue 发送给一个字符对象,例如$A,returns它的ascii码。有人可以解释一下 asciiValue 方法是如何工作的吗? <primitive: 171> 是从哪里来的,它的目的是什么?

之所以这是原始方法而不是常规的 Smalltalk 方法,是因为 Pharo 中的 Charactersimmediate objects.

当在内存中看到时,objects 是具有 header 和一些附加字段的数据结构,每个实例变量一个。这些插槽包含指向当前绑定到 ivar 的 object 的指针。

然而,在 SmallIntegers 的情况下,此结构传统上被简化为具有 SmallInteger 的 ivar 的 object 不指向小整数 object,它有 SmallInteger。这就是为什么 SmallIntegers 被称为立即 objects 的原因:你不指向它们,你有它们。

当然,要实现立即值,您需要一种在内存中区分它们的方法。 SmallIntegers 是整数,但在内存中指针也是整数。建立区别的技巧是观察所有 object 都分配在 4(32 位)或 8(64 位)的倍数的地址中。这意味着指针的两个低位总是等于 0。因此,您可以使用这些备用位来 tag 立即数 objects 并将立即数存储在剩余的较高位中位。

在 Pharo 和其他方言的情况下,Characters 其代码点适合一个字节,可以很容易地标记,因此它们变得直接。这就是 Characters(和 SmallIntegers)没有 ivars 的原因:它们是它们代表的值,加上虚拟机的一些标签来区分。

因此,Smalltalk 映像无法访问 ASCII Character 的数值,需要让 VM 读取它。这就是 Pharo 需要一个原语来回答 #asciiValue 消息的原因。

有关 Smalltalk 原语的更多信息,请查看 Smalltalk: How primitives are implemented?