summaryrefslogtreecommitdiff
path: root/compiler/codeGen/StgCmmClosure.hs
diff options
context:
space:
mode:
authorSimon Marlow <marlowsd@gmail.com>2014-02-27 09:41:19 +0000
committerSimon Marlow <marlowsd@gmail.com>2014-02-27 09:41:19 +0000
commitb1ddec1e6d4695d71d38b59db26829d71ad784e1 (patch)
treea6ea9e1d800de9a92ff3368c96bf2cc1adcd0bb9 /compiler/codeGen/StgCmmClosure.hs
parentb1ee32edbe9be7b695cce7975450782e0a290c47 (diff)
downloadhaskell-b1ddec1e6d4695d71d38b59db26829d71ad784e1.tar.gz
Fix a bug in codegen for non-updatable selector thunks (#8817)
To evaluate most non-updatable thunks, we can jump directly to the entry code if we know what it is. But not for a selector thunk: these might be updated by the garbage collector, so we have to enter the closure with an indirect jump through its info pointer.
Diffstat (limited to 'compiler/codeGen/StgCmmClosure.hs')
-rw-r--r--compiler/codeGen/StgCmmClosure.hs58
1 files changed, 35 insertions, 23 deletions
diff --git a/compiler/codeGen/StgCmmClosure.hs b/compiler/codeGen/StgCmmClosure.hs
index af9c7b8e07..c9302f21a1 100644
--- a/compiler/codeGen/StgCmmClosure.hs
+++ b/compiler/codeGen/StgCmmClosure.hs
@@ -450,25 +450,27 @@ in TcGenDeriv.) -}
whether or not it has free variables, and whether we're running
sequentially or in parallel.
-Closure Node Argument Enter
-Characteristics Par Req'd Passing Via
--------------------------------------------------------------------------------
-Unknown & no & yes & stack & node
-Known fun (>1 arg), no fvs & no & no & registers & fast entry (enough args)
- & slow entry (otherwise)
-Known fun (>1 arg), fvs & no & yes & registers & fast entry (enough args)
-0 arg, no fvs \r,\s & no & no & n/a & direct entry
-0 arg, no fvs \u & no & yes & n/a & node
-0 arg, fvs \r,\s & no & yes & n/a & direct entry
-0 arg, fvs \u & no & yes & n/a & node
-Unknown & yes & yes & stack & node
-Known fun (>1 arg), no fvs & yes & no & registers & fast entry (enough args)
- & slow entry (otherwise)
-Known fun (>1 arg), fvs & yes & yes & registers & node
-0 arg, no fvs \r,\s & yes & no & n/a & direct entry
-0 arg, no fvs \u & yes & yes & n/a & node
-0 arg, fvs \r,\s & yes & yes & n/a & node
-0 arg, fvs \u & yes & yes & n/a & node
+Closure Node Argument Enter
+Characteristics Par Req'd Passing Via
+---------------------------------------------------------------------------
+Unknown & no & yes & stack & node
+Known fun (>1 arg), no fvs & no & no & registers & fast entry (enough args)
+ & slow entry (otherwise)
+Known fun (>1 arg), fvs & no & yes & registers & fast entry (enough args)
+0 arg, no fvs \r,\s & no & no & n/a & direct entry
+0 arg, no fvs \u & no & yes & n/a & node
+0 arg, fvs \r,\s,selector & no & yes & n/a & node
+0 arg, fvs \r,\s & no & yes & n/a & direct entry
+0 arg, fvs \u & no & yes & n/a & node
+Unknown & yes & yes & stack & node
+Known fun (>1 arg), no fvs & yes & no & registers & fast entry (enough args)
+ & slow entry (otherwise)
+Known fun (>1 arg), fvs & yes & yes & registers & node
+0 arg, fvs \r,\s,selector & yes & yes & n/a & node
+0 arg, no fvs \r,\s & yes & no & n/a & direct entry
+0 arg, no fvs \u & yes & yes & n/a & node
+0 arg, fvs \r,\s & yes & yes & n/a & node
+0 arg, fvs \u & yes & yes & n/a & node
When black-holing, single-entry closures could also be entered via node
(rather than directly) to catch double-entry. -}
@@ -519,7 +521,8 @@ getCallMethod dflags _name _ lf_info _n_args _cg_loc _self_loop_info
-- fetched since we allocated it.
EnterIt
-getCallMethod dflags name id (LFReEntrant _ arity _ _) n_args _cg_loc _self_loop_info
+getCallMethod dflags name id (LFReEntrant _ arity _ _) n_args _cg_loc
+ _self_loop_info
| n_args == 0 = ASSERT( arity /= 0 )
ReturnIt -- No args at all
| n_args < arity = SlowCall -- Not enough args
@@ -531,7 +534,8 @@ getCallMethod _ _name _ LFUnLifted n_args _cg_loc _self_loop_info
getCallMethod _ _name _ (LFCon _) n_args _cg_loc _self_loop_info
= ASSERT( n_args == 0 ) ReturnIt
-getCallMethod dflags name id (LFThunk _ _ updatable std_form_info is_fun) n_args _cg_loc _self_loop_info
+getCallMethod dflags name id (LFThunk _ _ updatable std_form_info is_fun)
+ n_args _cg_loc _self_loop_info
| is_fun -- it *might* be a function, so we must "call" it (which is always safe)
= SlowCall -- We cannot just enter it [in eval/apply, the entry code
-- is the fast-entry code]
@@ -544,6 +548,12 @@ getCallMethod dflags name id (LFThunk _ _ updatable std_form_info is_fun) n_args
of jumping directly to the entry code is still valid. --SDM
-}
= EnterIt
+
+ -- even a non-updatable selector thunk can be updated by the garbage
+ -- collector, so we must enter it. (#8817)
+ | SelectorThunk{} <- std_form_info
+ = EnterIt
+
-- We used to have ASSERT( n_args == 0 ), but actually it is
-- possible for the optimiser to generate
-- let bot :: Int = error Int "urk"
@@ -553,7 +563,8 @@ getCallMethod dflags name id (LFThunk _ _ updatable std_form_info is_fun) n_args
| otherwise -- Jump direct to code for single-entry thunks
= ASSERT( n_args == 0 )
- DirectEntry (thunkEntryLabel dflags name (idCafInfo id) std_form_info updatable) 0
+ DirectEntry (thunkEntryLabel dflags name (idCafInfo id) std_form_info
+ updatable) 0
getCallMethod _ _name _ (LFUnknown True) _n_arg _cg_locs _self_loop_info
= SlowCall -- might be a function
@@ -562,7 +573,8 @@ getCallMethod _ name _ (LFUnknown False) n_args _cg_loc _self_loop_info
= ASSERT2( n_args == 0, ppr name <+> ppr n_args )
EnterIt -- Not a function
-getCallMethod _ _name _ LFLetNoEscape _n_args (LneLoc blk_id lne_regs) _self_loop_info
+getCallMethod _ _name _ LFLetNoEscape _n_args (LneLoc blk_id lne_regs)
+ _self_loop_info
= JumpToIt blk_id lne_regs
getCallMethod _ _ _ _ _ _ _ = panic "Unknown call method"