连接到 GHC 运行时系统
Hook into GHC runtime system
我一直在研究如何在 Haskell 中实现事务内存,但我不确定我是否理解暴露给程序员的 STM 操作如何挂钩到用 C 编写的运行时系统函数中。在 [= git 回购的 13=],我看到以下定义:
-- |A monad supporting atomic memory transactions.
newtype STM a = STM (State# RealWorld -> (# State# RealWorld, a #))
deriving Typeable
-- |Shared memory locations that support atomic memory transactions.
data TVar a = TVar (TVar# RealWorld a)
deriving Typeable
-- |Create a new TVar holding a value supplied
newTVar :: a -> STM (TVar a)
newTVar val = STM $ \s1# ->
case newTVar# val s1# of
(# s2#, tvar# #) -> (# s2#, TVar tvar# #)
然后在ghc/rts/PrimOps.cmm
中,我看到下面的C--定义:
stg_newTVarzh (P_ init){
W_ tv;
ALLOC_PRIM_P (SIZEOF_StgTVar, stg_newTVarzh, init);
tv = Hp - SIZEOF_StgTVar + WDS(1);
SET_HDR (tv, stg_TVAR_DIRTY_info, CCCS);
StgTVar_current_value(tv) = init;
StgTVar_first_watch_queue_entry(tv) = stg_END_STM_WATCH_QUEUE_closure;
StgTVar_num_updates(tv) = 0;
return (tv);
}
我的问题:
- 第一个和最后一个
#
在 (# s2#, TVar tvar# #)
中是什么意思。我之前读过,在变量后面放一个 #
只是一种命名约定,表示某些东西未装箱,但它本身意味着什么?
- 我们如何从
newTVar#
到 stg_newTVarzh
?似乎我错过了这两者之间的另一个定义。编译器是否将 newTVar#
重写为对列出的 C-- 函数的调用?
- C-- 代码中的
P_
和 W_
是什么?
我只能在 ghc/compiler/prelude/primops.txt.pp
中找到另一个 newTVar#
primop NewTVarOp "newTVar#" GenPrimOp
a
-> State# s -> (# State# s, TVar# s a #)
{Create a new {\tt TVar\#} holding a specified initial value.}
with
out_of_line = True
has_side_effects = True
根据 https://ghc.haskell.org/trac/ghc/wiki/Commentary/PrimOps,这是原语的定义方式,以便编译器了解它们。
(# s2#, TVar tvar# #)
是一个 unboxed tuple.
名称 stg_newTVarzh
的构建自:
stg_
前缀,是整个GHC运行时通用的,代表spineless-tagless G-machine,一种评估函数式语言的抽象机器;
newTVar
这是 newTVar#
的第一部分;
最后的zh
,也就是所谓的#
的z-encoding:这种编码生成了一个可供linker/the使用的普通名称所有平台中的 ABI,删除哈希 (#) 等有趣的字符。
我一直在研究如何在 Haskell 中实现事务内存,但我不确定我是否理解暴露给程序员的 STM 操作如何挂钩到用 C 编写的运行时系统函数中。在 [= git 回购的 13=],我看到以下定义:
-- |A monad supporting atomic memory transactions.
newtype STM a = STM (State# RealWorld -> (# State# RealWorld, a #))
deriving Typeable
-- |Shared memory locations that support atomic memory transactions.
data TVar a = TVar (TVar# RealWorld a)
deriving Typeable
-- |Create a new TVar holding a value supplied
newTVar :: a -> STM (TVar a)
newTVar val = STM $ \s1# ->
case newTVar# val s1# of
(# s2#, tvar# #) -> (# s2#, TVar tvar# #)
然后在ghc/rts/PrimOps.cmm
中,我看到下面的C--定义:
stg_newTVarzh (P_ init){
W_ tv;
ALLOC_PRIM_P (SIZEOF_StgTVar, stg_newTVarzh, init);
tv = Hp - SIZEOF_StgTVar + WDS(1);
SET_HDR (tv, stg_TVAR_DIRTY_info, CCCS);
StgTVar_current_value(tv) = init;
StgTVar_first_watch_queue_entry(tv) = stg_END_STM_WATCH_QUEUE_closure;
StgTVar_num_updates(tv) = 0;
return (tv);
}
我的问题:
- 第一个和最后一个
#
在(# s2#, TVar tvar# #)
中是什么意思。我之前读过,在变量后面放一个#
只是一种命名约定,表示某些东西未装箱,但它本身意味着什么? - 我们如何从
newTVar#
到stg_newTVarzh
?似乎我错过了这两者之间的另一个定义。编译器是否将newTVar#
重写为对列出的 C-- 函数的调用? - C-- 代码中的
P_
和W_
是什么?
我只能在 ghc/compiler/prelude/primops.txt.pp
newTVar#
primop NewTVarOp "newTVar#" GenPrimOp
a
-> State# s -> (# State# s, TVar# s a #)
{Create a new {\tt TVar\#} holding a specified initial value.}
with
out_of_line = True
has_side_effects = True
根据 https://ghc.haskell.org/trac/ghc/wiki/Commentary/PrimOps,这是原语的定义方式,以便编译器了解它们。
(# s2#, TVar tvar# #)
是一个 unboxed tuple.
名称 stg_newTVarzh
的构建自:
stg_
前缀,是整个GHC运行时通用的,代表spineless-tagless G-machine,一种评估函数式语言的抽象机器;newTVar
这是newTVar#
的第一部分;最后的
zh
,也就是所谓的#
的z-encoding:这种编码生成了一个可供linker/the使用的普通名称所有平台中的 ABI,删除哈希 (#) 等有趣的字符。