gpt4 book ai didi

ruby - Ruby如何通过值和指针区分VALUE?

转载 作者:数据小太阳 更新时间:2023-10-29 07:43:07 25 4
gpt4 key购买 nike

对于truenil或小整数等值,ruby进行优化。它不使用VALUE指针作为指针,而是直接使用VALUE来存储数据。
我想知道ruby是如何区别这些用途的:

def foo(x)
...

x相关联的。从低级的角度来说,它们只是一个数字。如何判断某个数字是否是指向某个对象的指针?我想到的只是限制指针将msb设置为0,并将msb的直接值设置为1。但这只是我的猜测。怎么用ruby做的?

最佳答案

ruby有很多不同的实现。Ruby语言规范没有为对象指定任何特定的内部表示——为什么要这样做?毕竟,这是一个内部代表!
例如,JRube根本不把对象表示为C指针,而是将它们表示为Java对象。IronRuby将它们表示为.NET对象。opal将它们表示为ecmascript对象。maglev将它们表示为smalltalk对象。
然而,确实有一些实现使用了您描述的策略。现在被废弃的核磁共振成像仪就是这样做的,亚尔夫和鲁宾纽斯也这样做。
这实际上是一个非常古老的技巧,至少可以追溯到20世纪60年代。它被称为标记指针表示法,正如其名称所示,您需要用一些额外的元数据标记指针,以便知道它是否实际是指向某个对象的指针或其他对象的编码数据类型。
有些CPU有专门用于此目的的特殊标记位。(例如,在AS/400上,CPU甚至没有指针,它有128位对象引用,尽管原来的CPU只有48位宽,而新的基于电源的CPU只有64位;额外的位用于编码各种元数据,如类型、所有者、访问限制,等)一些CPU具有用于其他目的的标记位,可为此目的“滥用”。然而,大多数现代主流CPU没有标记位。
但是,你可以用一个诡计!在许多现代CPU上,未对齐的内存访问(访问一个不以单词边界开头的地址)非常慢(在某些CPU上,甚至根本不可能),这意味着在32位CPU上,所有实际使用的指针,以两个00位结束,在64位CPU上以三个000位结束。可以将这些位用作标记位:以00结尾的指针实际上是指针,以011011结尾的指针是某些其他数据类型的编码。
在磁共振成像中,以1结尾的指针用于编码31/63位Fixnums。在yarv中,指针用于编码31/63位Fixnums,即根据公式2n+1(n << 1) | 1编码为实际机器整数的整数。在64位平台上,yarv还使用以10结尾的指针,使用类似的方案对62位flonum进行编码。(如果你想知道为什么yarv中aobject_idFixnum是2n+1,现在你知道:yarv使用对象id的内存地址,而2n+1是n的“内存地址”)。
那么,nilfalsetrue呢?好吧,在我们目前的计划中,他们没有空间。然而,非常低的内存地址通常是为操作系统内核保留的,这意味着像024这样的指针在程序中不可能实际出现。yarv使用这个空间来编码nilfalsetruefalse被编码为0(这很方便,因为这也是c中false的编码),nil被编码为0b1000true被编码为0b10100(在flonums引入之前,在较旧的版本中它曾经是00b100b100)。
从理论上讲,这里也有很多空间来编码其他对象,但yarv没有做到这一点。例如,一些smalltalk或lisp vm在那里编码ascii或bmp unicode字符对象,或者一些常用的对象,例如空列表、空数组或空字符串。
不过,仍然有一些部分丢失了:没有对象头,只有裸位模式,虚拟机如何访问类、方法、实例变量等?嗯,不可能。这些必须是特殊的大小写,并硬编码到虚拟机中。vm只需知道以1结尾的指针是一个编码的Fixnum,并且必须知道类是Fixnum,并且可以在那里找到方法。比如变量?好吧,你可以把它们和对象分开存放在旁边的字典里。或者你走ruby路线,完全不允许他们。

关于ruby - Ruby如何通过值和指针区分VALUE?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33843393/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com