代码之家  ›  专栏  ›  技术社区  ›  typesanitizer

Haskell运行时如何区分指针和未装箱的字大小值?

  •  4
  • typesanitizer  · 技术社区  · 6 年前

    在64位平台上,OCAML int 由于指针标记,类型为63位。这使得ints可以取消绑定,并且在运行时仍然可以与指针区分开来,从而实现精确的gc。IIRC,ghc-rts中的gc也是精确的,但是ghc的ints是64位的,可以取消绑定。如果是这样,那么运行时系统如何区分int和pointer?在区分其他未绑定的单词大小值和指针时,似乎也会出现同样的问题。

    2 回复  |  直到 6 年前
        1
  •  1
  •   chi    6 年前

    基本上,这在GHC中描述 RTS documentation 当它详细描述堆对象的格式时,包含一个头和一个有效负载。

    头描述负载的哪些字是指针,以便垃圾收集可以工作。

    这意味着,对于任何堆对象,大致都有一个单词的开销。

        2
  •  6
  •   zenhack    6 年前

    简短的版本是:将所有指针和所有非指针组合在一起分配值,并包含一点元数据,这样GC就知道接下来要做什么。

    注意haskell报告实际上允许 Int 为31或63位,使OCAML策略有效——但这不是GHC所做的。

    稍长一点的版本是说“元数据”实际上是垃圾收集器使用的两个函数。要给出一个粗略的草图,您可以将haskell中的值视为在运行时用方法表示为OO样式的对象:

    class Fn:
        # By far the most used; this evaluates the value:
        enter(...) -> ...
        # Used by the garbage collector:
        scavenge(...) -> ...
        evacuate(...) -> ...
    

    其结果是,值对自己的了解足以进行簿记,并且对于一些常见的布局,GHC定义了这些函数的专门版本;垃圾收集器主要不知道清道夫和清道夫是如何工作的。指针和非指针的分离是为了能够为常见情况创建和共享通用实现。

    请注意,即使对于不是“函数”的haskell值也存在“enter”函数,因为延迟意味着即使类型为int,计算仍可能涉及计算。

    如果你想要很长的版本,我建议你阅读:

    https://www.microsoft.com/en-us/research/publication/implementing-lazy-functional-languages-on-stock-hardware-the-spineless-tagless-g-machine/

    关于Haskell是如何映射到硬件的,这涉及到很多细节。这是一本引人入胜的书,里面有很多整洁的东西,与大多数(严格的)功能语言的实现方式有很大的不同。这篇论文很旧,但仍然相关。