An unusual case, but without it:
(a) we had an assertion failure
(b) we can overwrite the caller's infotable, which might cause
the garbage collector to collect live data.
Better to keep the update frame live at all call sites,
not just at returns.
-- Don't forget to keep the outgoing parameters in the CallArea live,
-- as well as the update frame.
-- Don't forget to keep the outgoing parameters in the CallArea live,
-- as well as the update frame.
+-- Note: We have to keep the update frame live at a call because of the
+-- case where the function doesn't return -- in that case, there won't
+-- be a return to keep the update frame live. We'd still better keep the
+-- info pointer in the update frame live at any call site;
+-- otherwise we could screw up the garbage collector.
liveLastOut :: (BlockId -> SubAreaSet) -> Last -> SubAreaSet
liveLastOut env l =
case l of
liveLastOut :: (BlockId -> SubAreaSet) -> Last -> SubAreaSet
liveLastOut env l =
case l of
- LastCall _ Nothing n _ ->
+ LastCall _ Nothing n _ ->
add_area (CallArea Old) n out -- add outgoing args (includes upd frame)
add_area (CallArea Old) n out -- add outgoing args (includes upd frame)
- LastCall _ (Just k) n _ -> add_area (CallArea (Young k)) n out
+ LastCall _ (Just k) n (Just upd_n) ->
+ add_area (CallArea Old) n (add_area (CallArea (Young k)) n out)
+ LastCall _ (Just k) n Nothing ->
+ add_area (CallArea (Young k)) n out
_ -> out
where out = joinOuts slotLattice env l
add_area _ n live | n == 0 = live
_ -> out
where out = joinOuts slotLattice env l
add_area _ n live | n == 0 = live
cml_target :: CmmExpr, -- never a CmmPrim to a CallishMachOp!
cml_cont :: Maybe BlockId,
-- BlockId of continuation (Nothing for return or tail call)
cml_target :: CmmExpr, -- never a CmmPrim to a CallishMachOp!
cml_cont :: Maybe BlockId,
-- BlockId of continuation (Nothing for return or tail call)
- cml_args :: ByteOff, -- bytes offset for youngest outgoing arg
+ cml_args :: ByteOff, -- byte offset for youngest outgoing arg
+ -- (includes update frame, which must be younger)
cml_ret_off :: Maybe UpdFrameOffset}
-- stack offset for return (update frames);
-- The return offset should be Nothing only if we have to create
cml_ret_off :: Maybe UpdFrameOffset}
-- stack offset for return (update frames);
-- The return offset should be Nothing only if we have to create