Skip to content
Snippets Groups Projects
Commit d7aed5e6 authored by Simon Marlow's avatar Simon Marlow Committed by Ian Lynagh
Browse files

Add two new primops:

  seq#   :: a -> State# s -> (# State# s, a #)
  spark# :: a -> State# s -> (# State# s, a #)

seq# is a version of seq that can be used in a State#-passing
context.  We will use it to implement Control.Exception.evaluate and
thus fix #5129.  Also we have plans to use it to fix #5262.

spark# is to seq# as par is to pseq.  That is, it creates a spark in a
State#-passing context.  We will use spark# and seq# to implement rpar
and rseq respectively in an improved implementation of the Eval monad.
parent f9129b03
No related branches found
No related tags found
No related merge requests found
...@@ -157,6 +157,25 @@ cgCase (StgApp v []) _live_in_whole_case _live_in_alts bndr ...@@ -157,6 +157,25 @@ cgCase (StgApp v []) _live_in_whole_case _live_in_alts bndr
reps_compatible = idCgRep v == idCgRep bndr reps_compatible = idCgRep v == idCgRep bndr
\end{code} \end{code}
Special case #2.5; seq#
case seq# a s of v
(# s', a' #) -> e
==>
case a of v
(# s', a' #) -> e
(taking advantage of the fact that the return convention for (# State#, a #)
is the same as the return convention for just 'a')
\begin{code}
cgCase (StgOpApp (StgPrimOp SeqOp) [StgVarArg a, _] _)
live_in_whole_case live_in_alts bndr alt_type alts
= cgCase (StgApp a []) live_in_whole_case live_in_alts bndr alt_type alts
\end{code}
Special case #3: inline PrimOps and foreign calls. Special case #3: inline PrimOps and foreign calls.
\begin{code} \begin{code}
......
...@@ -151,6 +151,13 @@ cgExpr (StgOpApp (StgPrimOp TagToEnumOp) [arg] res_ty) ...@@ -151,6 +151,13 @@ cgExpr (StgOpApp (StgPrimOp TagToEnumOp) [arg] res_ty)
tycon = tyConAppTyCon res_ty tycon = tyConAppTyCon res_ty
cgExpr (StgOpApp (StgPrimOp SeqOp) [StgVarArg a, _] _res_ty)
= cgTailCall a []
-- seq# :: a -> State# -> (# State# , a #)
-- but the return convention for (# State#, a #) is exactly the same as
-- for just a, so we can implment seq# by
-- seq# a s ==> a
cgExpr (StgOpApp (StgPrimOp primop) args res_ty) cgExpr (StgOpApp (StgPrimOp primop) args res_ty)
| primOpOutOfLine primop | primOpOutOfLine primop
= tailCallPrimOp primop args = tailCallPrimOp primop args
......
...@@ -126,9 +126,29 @@ emitPrimOp [res] ParOp [arg] live ...@@ -126,9 +126,29 @@ emitPrimOp [res] ParOp [arg] live
(Just vols) (Just vols)
NoC_SRT -- No SRT b/c we do PlayRisky NoC_SRT -- No SRT b/c we do PlayRisky
CmmMayReturn CmmMayReturn
where
newspark = CmmLit (CmmLabel (mkCmmCodeLabel rtsPackageId (fsLit "newSpark")))
emitPrimOp [res] SparkOp [arg] live = do
-- returns the value of arg in res. We're going to therefore
-- refer to arg twice (once to pass to newSpark(), and once to
-- assign to res), so put it in a temporary.
tmp <- newTemp bWord
stmtC (CmmAssign (CmmLocal tmp) arg)
vols <- getVolatileRegs live
emitForeignCall' PlayRisky []
(CmmCallee newspark CCallConv)
[ (CmmHinted (CmmReg (CmmGlobal BaseReg)) AddrHint)
, (CmmHinted arg AddrHint) ]
(Just vols)
NoC_SRT -- No SRT b/c we do PlayRisky
CmmMayReturn
stmtC (CmmAssign (CmmLocal res) (CmmReg (CmmLocal tmp)))
where where
newspark = CmmLit (CmmLabel (mkCmmCodeLabel rtsPackageId (fsLit "newSpark"))) newspark = CmmLit (CmmLabel (mkCmmCodeLabel rtsPackageId (fsLit "newSpark")))
emitPrimOp [res] ReadMutVarOp [mutv] _ emitPrimOp [res] ReadMutVarOp [mutv] _
= stmtC (CmmAssign (CmmLocal res) (cmmLoadIndexW mutv fixedHdrSize gcWord)) = stmtC (CmmAssign (CmmLocal res) (cmmLoadIndexW mutv fixedHdrSize gcWord))
......
...@@ -1650,6 +1650,21 @@ primop ParOp "par#" GenPrimOp ...@@ -1650,6 +1650,21 @@ primop ParOp "par#" GenPrimOp
has_side_effects = True has_side_effects = True
code_size = { primOpCodeSizeForeignCall } code_size = { primOpCodeSizeForeignCall }
primop SparkOp "spark#" GenPrimOp
a -> State# s -> (# State# s, a #)
with has_side_effects = True
code_size = { primOpCodeSizeForeignCall }
primop SeqOp "seq#" GenPrimOp
a -> State# s -> (# State# s, a #)
-- why return the value? So that we can control sharing of seq'd
-- values: in
-- let x = e in x `seq` ... x ...
-- we don't want to inline x, so better to represent it as
-- let x = e in case seq# x RW of (# _, x' #) -> ... x' ...
-- also it matches the type of rseq in the Eval monad.
primop GetSparkOp "getSpark#" GenPrimOp primop GetSparkOp "getSpark#" GenPrimOp
State# s -> (# State# s, Int#, a #) State# s -> (# State# s, Int#, a #)
with with
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment