diff options
author | Edward Z. Yang <ezyang@mit.edu> | 2011-03-23 13:43:30 +0000 |
---|---|---|
committer | Edward Z. Yang <ezyang@mit.edu> | 2011-03-23 13:43:30 +0000 |
commit | cb5260d444da0f74c2e06c7857dff2f163415ebd (patch) | |
tree | c6287cdccd93d1106db537fbd4e22d9d276b603a /compiler/codeGen/StgCmmEnv.hs | |
parent | 6c979675be92983796cf7426d1ffd30d3dc8af02 (diff) | |
download | haskell-cb5260d444da0f74c2e06c7857dff2f163415ebd.tar.gz |
Immediately tag initialization code to prevent untagged spills.
When allocating new objects on the heap, we previously returned
a CmmExpr containing the heap pointer as well as the tag expression,
which would be added to the code graph upon first usage. Unfortunately,
this meant that untagged heap pointers living in registers might
be spilled to the stack, where they interacted poorly with garbage
collection (we saw this bug specifically with the compacting garbage
collector.)
This fix immediately tags the register containing the heap pointer,
so that unless we have extremely unfriendly spill code, the new pointer
will never be spilled to the stack untagged.
An alternate solution might have been to modify allocDynClosure to
tag the pointer upon the initial register allocation, but not all
invocations of allocDynClosure tag the resulting pointer, and
threading the consequent CgIdInfo for the cases that did would have
been annoying.
Diffstat (limited to 'compiler/codeGen/StgCmmEnv.hs')
-rw-r--r-- | compiler/codeGen/StgCmmEnv.hs | 14 |
1 files changed, 11 insertions, 3 deletions
diff --git a/compiler/codeGen/StgCmmEnv.hs b/compiler/codeGen/StgCmmEnv.hs index 469f58d7df..369e1993aa 100644 --- a/compiler/codeGen/StgCmmEnv.hs +++ b/compiler/codeGen/StgCmmEnv.hs @@ -37,6 +37,7 @@ import CLabel import BlockId import CmmExpr import CmmUtils +import MkGraph (CmmAGraph, mkAssign, (<*>)) import FastString import Id import VarEnv @@ -86,9 +87,16 @@ litIdInfo :: Id -> LambdaFormInfo -> CmmLit -> CgIdInfo litIdInfo id lf_info lit = --mkCgIdInfo id lf_info (CmmLit lit) mkCgIdInfo id lf_info (addDynTag (CmmLit lit) (lfDynTag lf_info)) -regIdInfo :: Id -> LambdaFormInfo -> LocalReg -> CgIdInfo -regIdInfo id lf_info reg = - mkCgIdInfo id lf_info (addDynTag (CmmReg (CmmLocal reg)) (lfDynTag lf_info)) +-- Because the register may be spilled to the stack in untagged form, we +-- modify the initialization code 'init' to immediately tag the +-- register, and store a plain register in the CgIdInfo. We allocate +-- a new register in order to keep single-assignment and help out the +-- inliner. -- EZY +regIdInfo :: Id -> LambdaFormInfo -> LocalReg -> CmmAGraph -> FCode (CgIdInfo, CmmAGraph) +regIdInfo id lf_info reg init = do + reg' <- newTemp (localRegType reg) + let init' = init <*> mkAssign (CmmLocal reg') (addDynTag (CmmReg (CmmLocal reg)) (lfDynTag lf_info)) + return (mkCgIdInfo id lf_info (CmmReg (CmmLocal reg')), init') idInfoToAmode :: CgIdInfo -> CmmExpr -- Returns a CmmExpr for the *tagged* pointer |