Marge Bot pushed to branch master at Glasgow Haskell Compiler / GHC

Commits:

6 changed files:

Changes:

  • compiler/GHC/StgToJS/Apply.hs
    ... ... @@ -185,7 +185,7 @@ genApp ctx i args
    185 185
           as'      <- concatMapM genArg args
    
    186 186
           ei       <- varForEntryId i
    
    187 187
           let ra = mconcat . reverse $
    
    188
    -                 zipWith (\r a -> toJExpr r |= a) [R1 ..] as'
    
    188
    +                 zipWith (\r a -> toJExpr r |= a) regsFromR1 as'
    
    189 189
           p <- pushLneFrame n ctx
    
    190 190
           a <- adjSp 1 -- for the header (which will only be written when the thread is suspended)
    
    191 191
           return (ra <> p <> a <> returnS ei, ExprCont)
    
    ... ... @@ -464,42 +464,31 @@ specTag spec = Bits.shiftL (specVars spec) 8 Bits..|. specArgs spec
    464 464
     specTagExpr :: ApplySpec -> JStgExpr
    
    465 465
     specTagExpr = toJExpr . specTag
    
    466 466
     
    
    467
    --- | Build arrays to quickly lookup apply functions
    
    467
    +-- | Build functions to quickly lookup apply functions
    
    468 468
     --
    
    469
    ---  h$apply[r << 8 | n] = function application for r regs, n args
    
    470
    ---  h$paps[r]           = partial application for r registers (number of args is in the object)
    
    469
    +--  h$apply(r << 8 | n) = function application for r regs, n args
    
    470
    +--  h$paps(r)           = partial application for r registers (number of args is in the object)
    
    471 471
     mkApplyArr :: JSM JStgStat
    
    472 472
     mkApplyArr =
    
    473
    -  do mk_ap_gens  <- jFor (|= zero_) (.<. Int 65536) preIncrS
    
    474
    -                    \j -> hdApply .! j |= hdApGen
    
    475
    -     mk_pap_gens <- jFor (|= zero_) (.<. Int 128) preIncrS
    
    476
    -                    \j -> hdPaps .! j |=  hdPapGen
    
    473
    +  do paps_fun <- jFunction (name hdPapsStr) \(MkSolo i) -> pure $ SwitchStat i (map case_pap specPap) (returnS hdPapGen)
    
    474
    +     apply_fun <- jFunction (name hdApplyStr) \(MkSolo i) -> pure $ SwitchStat i (mapMaybe' case_apply applySpec) (returnS hdApGen)
    
    477 475
          return $ mconcat
    
    478
    -       [ name hdApplyStr ||= toJExpr (JList [])
    
    479
    -       , name hdPapsStr  ||= toJExpr (JList [])
    
    480
    -       , ApplStat (hdInitStatic .^ "push")
    
    481
    -         [ jLam' $
    
    482
    -           mconcat
    
    483
    -           [ mk_ap_gens
    
    484
    -           , mk_pap_gens
    
    485
    -           , mconcat (map assignSpec applySpec)
    
    486
    -           , mconcat (map assignPap specPap)
    
    487
    -           ]
    
    488
    -         ]
    
    476
    +       [ paps_fun
    
    477
    +       , apply_fun
    
    489 478
            ]
    
    490 479
       where
    
    491
    -    assignSpec :: ApplySpec -> JStgStat
    
    492
    -    assignSpec spec = case specConv spec of
    
    480
    +    case_apply :: ApplySpec -> Maybe (JStgExpr,JStgStat)
    
    481
    +    case_apply spec = case specConv spec of
    
    493 482
           -- both fast/slow (regs/stack) specialized apply functions have the same
    
    494 483
           -- tags. We store the stack ones in the array because they are used as
    
    495 484
           -- continuation stack frames.
    
    496
    -      StackConv -> hdApply .! specTagExpr spec |= specApplyExpr spec
    
    497
    -      RegsConv  -> mempty
    
    485
    +      StackConv -> Just (specTagExpr spec, returnS (specApplyExpr spec))
    
    486
    +      RegsConv  -> Nothing
    
    498 487
     
    
    499 488
         hdPap_ = unpackFS hdPapStr_
    
    500 489
     
    
    501
    -    assignPap :: Int -> JStgStat
    
    502
    -    assignPap p = hdPaps .! toJExpr p |= global (mkFastString (hdPap_ ++ show p))
    
    490
    +    case_pap :: Int -> (JStgExpr, JStgStat)
    
    491
    +    case_pap p = (toJExpr p,  returnS $ global (mkFastString (hdPap_ ++ show p)))
    
    503 492
     
    
    504 493
     -- | Push a continuation on the stack
    
    505 494
     --
    
    ... ... @@ -619,7 +608,7 @@ genericStackApply cfg = closure info body
    619 608
                              -- compute new tag with consumed register values and args removed
    
    620 609
                              , newTag |= ((given_regs-needed_regs).<<.8) .|. (given_args - needed_args)
    
    621 610
                              -- find application function for the remaining regs/args
    
    622
    -                         , newAp |= hdApply .! newTag
    
    611
    +                         , newAp |= ApplExpr hdApply [newTag]
    
    623 612
                              , traceRts cfg (jString "h$ap_gen: next: " + (newAp .^ "n"))
    
    624 613
     
    
    625 614
                              -- Drop used registers from the stack.
    
    ... ... @@ -643,7 +632,7 @@ genericStackApply cfg = closure info body
    643 632
                              -----------------------------
    
    644 633
                              [ traceRts cfg (jString "h$ap_gen: undersat")
    
    645 634
                              -- find PAP entry function corresponding to given_regs count
    
    646
    -                         , p      |= hdPaps .! given_regs
    
    635
    +                         , p      |= ApplExpr hdPaps [given_regs]
    
    647 636
     
    
    648 637
                              -- build PAP payload: R1 + tag + given register values
    
    649 638
                              , newTag |= ((needed_regs-given_regs) .<<. 8) .|. (needed_args-given_args)
    
    ... ... @@ -716,7 +705,7 @@ genericFastApply s =
    716 705
                  do push_all_regs <- pushAllRegs tag
    
    717 706
                     return $ mconcat $
    
    718 707
                       [ push_all_regs
    
    719
    -                  , ap |= hdApply .! tag
    
    708
    +                  , ap |= ApplExpr hdApply [tag]
    
    720 709
                       , ifS (ap .===. hdApGen)
    
    721 710
                         ((sp |= sp + 2) <> (stack .! (sp-1) |= tag))
    
    722 711
                         (sp |= sp + 1)
    
    ... ... @@ -750,7 +739,7 @@ genericFastApply s =
    750 739
                     , traceRts s (jString "h$ap_gen_fast: oversat " + sp)
    
    751 740
                     , push_args
    
    752 741
                     , newTag |= ((myRegs-( arity.>>.8)).<<.8).|.myAr-ar
    
    753
    -                , newAp |= hdApply .! newTag
    
    742
    +                , newAp |= ApplExpr hdApply [newTag]
    
    754 743
                     , ifS (newAp .===. hdApGen)
    
    755 744
                       ((sp |= sp + 2) <> (stack .! (sp - 1) |= newTag))
    
    756 745
                       (sp |= sp + 1)
    
    ... ... @@ -761,7 +750,7 @@ genericFastApply s =
    761 750
                    -- else
    
    762 751
                     [traceRts s (jString "h$ap_gen_fast: undersat: " + myRegs + jString " " + tag)
    
    763 752
                     , jwhenS (tag .!=. 0) $ mconcat
    
    764
    -                  [ p |= hdPaps .! myRegs
    
    753
    +                  [ p |= ApplExpr hdPaps [myRegs]
    
    765 754
                       , dat |= toJExpr [r1, ((arity .>>. 8)-myRegs)*256+ar-myAr]
    
    766 755
                       , get_regs
    
    767 756
                       , r1 |= initClosure s p dat jCurrentCCS
    
    ... ... @@ -773,14 +762,24 @@ genericFastApply s =
    773 762
         pushAllRegs :: JStgExpr -> JSM JStgStat
    
    774 763
         pushAllRegs tag =
    
    775 764
           jVar \regs ->
    
    776
    -             return $ mconcat $
    
    777
    -             [ regs |= tag .>>. 8
    
    778
    -             , sp |= sp + regs
    
    779
    -             , SwitchStat regs (map pushReg [65,64..2]) mempty
    
    780
    -             ]
    
    781
    -      where
    
    782
    -        pushReg :: Int -> (JStgExpr, JStgStat)
    
    783
    -        pushReg r = (toJExpr (r-1),  stack .! (sp - toJExpr (r - 2)) |= jsReg r)
    
    765
    +             let max_low_reg = regNumber maxLowReg
    
    766
    +                 low_regs = [max_low_reg, max_low_reg-1..2] -- R1 isn't used for arguments
    
    767
    +                 pushReg :: Int -> (JStgExpr, JStgStat)
    
    768
    +                 pushReg r = (toJExpr r,  stack .! (sp - toJExpr (r - 2)) |= jsReg r)
    
    769
    +             in return $ mconcat $
    
    770
    +                  [ regs |= tag .>>. 8
    
    771
    +                  , sp |= sp + regs
    
    772
    +                    -- increment the number of regs by 1, so that it matches register
    
    773
    +                    -- numbers (R1 is not used for args)
    
    774
    +                  , postIncrS regs
    
    775
    +                    -- copy high registers with a loop
    
    776
    +                  , WhileStat False (regs .>. toJExpr max_low_reg) $ mconcat
    
    777
    +                      -- rN stored in stack[sp - N - 2] so that r2 is stored in stack[sp], etc.
    
    778
    +                      [ stack .! (sp - regs - 2) |= highReg_expr regs
    
    779
    +                      , postDecrS regs
    
    780
    +                      ]
    
    781
    +                  , SwitchStat regs (map pushReg low_regs) mempty
    
    782
    +                  ]
    
    784 783
     
    
    785 784
         pushArgs :: JStgExpr -> JStgExpr -> JSM JStgStat
    
    786 785
         pushArgs start end =
    
    ... ... @@ -906,7 +905,7 @@ stackApply s fun_name nargs nvars =
    906 905
                  [ rs |= (arity .>>. 8)
    
    907 906
                  , loadRegs rs
    
    908 907
                  , sp |= sp - rs
    
    909
    -             , newAp |= (hdApply .! ((toJExpr nargs-arity0).|.((toJExpr nvars-rs).<<.8)))
    
    908
    +             , newAp |= ApplExpr hdApply [(toJExpr nargs-arity0).|.((toJExpr nvars-rs).<<.8)]
    
    910 909
                  , stack .! sp |= newAp
    
    911 910
                  , profStat s pushRestoreCCS
    
    912 911
                  , traceRts s (toJExpr (fun_name <> ": new stack frame: ") + (newAp .^ "n"))
    
    ... ... @@ -989,7 +988,7 @@ fastApply s fun_name nargs nvars = if nargs == 0 && nvars == 0
    989 988
                                   + rsRemain)
    
    990 989
                     , saveRegs rs
    
    991 990
                     , sp |= sp + rsRemain + 1
    
    992
    -                , stack .! sp |= hdApply .! ((rsRemain.<<.8).|. (toJExpr nargs - mask8 arity))
    
    991
    +                , stack .! sp |= ApplExpr hdApply [(rsRemain.<<.8).|. (toJExpr nargs - mask8 arity)]
    
    993 992
                     , profStat s pushRestoreCCS
    
    994 993
                     , returnS c
    
    995 994
                     ]
    
    ... ... @@ -1238,14 +1237,30 @@ pap s r = closure (ClosureInfo
    1238 1237
                  , profStat s (enterCostCentreFun currentCCS)
    
    1239 1238
                  , extra |= (funOrPapArity c (Just f) .>>. 8) - toJExpr r
    
    1240 1239
                  , traceRts s (toJExpr (funcName <> ": pap extra args moving: ") + extra)
    
    1241
    -             , moveBy extra
    
    1240
    +             , case r of
    
    1241
    +                0 -> mempty -- in pap_0 we don't shift any register
    
    1242
    +                _ -> moveBy extra
    
    1242 1243
                  , loadOwnArgs d
    
    1243 1244
                  , r1 |= c
    
    1244 1245
                  , returnS f
    
    1245 1246
                  ]
    
    1246
    -    moveBy extra = SwitchStat extra
    
    1247
    -                   (reverse $ map moveCase [1..maxReg-r-1]) mempty
    
    1248
    -    moveCase m = (toJExpr m, jsReg (m+r+1) |= jsReg (m+1))
    
    1247
    +    moveBy extra =
    
    1248
    +      let max_low_reg = regNumber maxLowReg
    
    1249
    +          low_regs = [max_low_reg, max_low_reg-1..2] -- R1 isn't used for arguments
    
    1250
    +          move_case m = (toJExpr m, jsReg (m+r) |= jsReg m)
    
    1251
    +      in mconcat
    
    1252
    +          [ -- increment the number of args by 1, so that it matches register
    
    1253
    +            -- numbers (R1 is not used for args)
    
    1254
    +            postIncrS extra
    
    1255
    +            -- copy high registers with a loop
    
    1256
    +          ,  WhileStat False (extra .>. toJExpr max_low_reg) $ mconcat
    
    1257
    +              [ highReg_expr (extra + toJExpr r) |= highReg_expr extra
    
    1258
    +              , postDecrS extra
    
    1259
    +              ]
    
    1260
    +            -- then copy low registers with a case
    
    1261
    +          , SwitchStat extra (map move_case low_regs) mempty
    
    1262
    +          ]
    
    1263
    +
    
    1249 1264
         loadOwnArgs d = mconcat $ map (\r ->
    
    1250 1265
             jsReg (r+1) |= dField d (r+2)) [1..r]
    
    1251 1266
         dField d n = SelExpr d (name . mkFastString $ ('d':show (n-1)))
    
    ... ... @@ -1274,7 +1289,9 @@ papGen cfg =
    1274 1289
                     (jString "h$pap_gen: expected function or pap")
    
    1275 1290
                   , profStat cfg (enterCostCentreFun currentCCS)
    
    1276 1291
                   , traceRts cfg (jString "h$pap_gen: generic pap extra args moving: " + or)
    
    1292
    +                -- shift newly applied arguments into appropriate registers
    
    1277 1293
                   , appS hdMoveRegs2 [or, r]
    
    1294
    +                -- load stored arguments into lowest argument registers (i.e. starting from R2)
    
    1278 1295
                   , loadOwnArgs d r
    
    1279 1296
                   , r1 |= c
    
    1280 1297
                   , returnS f
    
    ... ... @@ -1285,9 +1302,22 @@ papGen cfg =
    1285 1302
         funcIdent = name funcName
    
    1286 1303
         funcName = hdPapGenStr
    
    1287 1304
         loadOwnArgs d r =
    
    1288
    -      let prop n = d .^ ("d" <> mkFastString (show $ n+1))
    
    1289
    -          loadOwnArg n = (toJExpr n, jsReg (n+1) |= prop n)
    
    1290
    -      in  SwitchStat r (map loadOwnArg [127,126..1]) mempty
    
    1305
    +      let prop n = d .^ (mkFastString ("d" ++ show n))
    
    1306
    +          loadOwnArg n = (toJExpr n, jsReg n |= prop n)
    
    1307
    +          max_low_reg = regNumber maxLowReg
    
    1308
    +          low_regs = [max_low_reg, max_low_reg-1..2] -- R1 isn't used for arguments
    
    1309
    +      in  mconcat
    
    1310
    +            [ -- increment the number of args by 1, so that it matches register
    
    1311
    +              -- numbers (R1 is not used for args) and PAP fields (starting from d2)
    
    1312
    +              postIncrS r
    
    1313
    +              -- copy high registers with a loop
    
    1314
    +            ,  WhileStat False (r .>. toJExpr max_low_reg) $ mconcat
    
    1315
    +                [ highReg_expr r |= (d .! (jString (fsLit "d") + r))
    
    1316
    +                , postDecrS r
    
    1317
    +                ]
    
    1318
    +              -- then copy low registers with a case.
    
    1319
    +            , SwitchStat r (map loadOwnArg low_regs) mempty
    
    1320
    +            ]
    
    1291 1321
     
    
    1292 1322
     -- general utilities
    
    1293 1323
     -- move the first n registers, starting at R2, m places up (do not use with negative m)
    
    ... ... @@ -1301,7 +1331,7 @@ moveRegs2 = jFunction (name hdMoveRegs2) moveSwitch
    1301 1331
         switchCase n m = (toJExpr $
    
    1302 1332
                           (n `Bits.shiftL` 8) Bits..|. m
    
    1303 1333
                          , mconcat (map (`moveRegFast` m) [n+1,n..2])
    
    1304
    -                       <> BreakStat Nothing {-[j| break; |]-})
    
    1334
    +                       <> BreakStat Nothing)
    
    1305 1335
         moveRegFast n m = jsReg (n+m) |= jsReg n
    
    1306 1336
         -- fallback
    
    1307 1337
         defaultCase n m =
    

  • compiler/GHC/StgToJS/Expr.hs
    ... ... @@ -312,7 +312,7 @@ genBody ctx startReg args e typ = do
    312 312
       -- load arguments into local variables
    
    313 313
       la <- do
    
    314 314
         args' <- concatMapM genIdArgI args
    
    315
    -    return (declAssignAll args' (fmap toJExpr [startReg..]))
    
    315
    +    return (declAssignAll args' (jsRegsFrom startReg))
    
    316 316
     
    
    317 317
       -- assert that arguments have valid runtime reps
    
    318 318
       lav <- verifyRuntimeReps args
    
    ... ... @@ -665,7 +665,7 @@ genCase ctx bnd e at alts l
    665 665
       | otherwise = do
    
    666 666
           rj       <- genRet ctx bnd at alts l
    
    667 667
           let ctx' = ctxSetTop bnd
    
    668
    -                  $ ctxSetTarget (assocIdExprs bnd (map toJExpr [R1 ..]))
    
    668
    +                  $ ctxSetTarget (assocIdExprs bnd jsRegsFromR1)
    
    669 669
                       $ ctx
    
    670 670
           (ej, _r) <- genExpr ctx' e
    
    671 671
           return (rj <> ej, ExprCont)
    
    ... ... @@ -730,7 +730,7 @@ genRet ctx e at as l = freshIdent >>= f
    730 730
     
    
    731 731
         fun free = resetSlots $ do
    
    732 732
           decs          <- declVarsForId e
    
    733
    -      load          <- flip assignAll (map toJExpr [R1 ..]) . map toJExpr <$> identsForId e
    
    733
    +      load          <- flip assignAll jsRegsFromR1 . map toJExpr <$> identsForId e
    
    734 734
           loadv         <- verifyRuntimeReps [e]
    
    735 735
           ras           <- loadRetArgs free
    
    736 736
           rasv          <- verifyRuntimeReps (map (\(x,_,_)->x) free)
    

  • compiler/GHC/StgToJS/Regs.hs
    1 1
     {-# LANGUAGE OverloadedStrings #-}
    
    2
    +{-# LANGUAGE PatternSynonyms #-}
    
    2 3
     
    
    3 4
     module GHC.StgToJS.Regs
    
    4 5
       ( StgReg (..)
    
    ... ... @@ -6,17 +7,25 @@ module GHC.StgToJS.Regs
    6 7
       , sp
    
    7 8
       , stack
    
    8 9
       , r1, r2, r3, r4
    
    10
    +  , pattern R1, pattern R2, pattern R3, pattern R4
    
    9 11
       , regsFromR1
    
    10 12
       , regsFromR2
    
    13
    +  , regsFromTo
    
    14
    +  , jsRegsFrom
    
    11 15
       , jsRegsFromR1
    
    12 16
       , jsRegsFromR2
    
    13 17
       , StgRet (..)
    
    14
    -  , jsRegToInt
    
    15
    -  , intToJSReg
    
    18
    +  , regNumber
    
    16 19
       , jsReg
    
    20
    +  , highReg
    
    21
    +  , highReg_expr
    
    17 22
       , maxReg
    
    23
    +  , maxLowReg
    
    18 24
       , minReg
    
    25
    +  , minHighReg
    
    19 26
       , lowRegs
    
    27
    +  , lowRegsCount
    
    28
    +  , lowRegsIdents
    
    20 29
       , retRegs
    
    21 30
       , register
    
    22 31
       , foreignRegister
    
    ... ... @@ -32,6 +41,7 @@ import GHC.JS.Make
    32 41
     import GHC.StgToJS.Symbols
    
    33 42
     
    
    34 43
     import GHC.Data.FastString
    
    44
    +import GHC.Utils.Panic.Plain
    
    35 45
     
    
    36 46
     import Data.Array
    
    37 47
     import qualified Data.ByteString.Char8 as BSC
    
    ... ... @@ -39,26 +49,15 @@ import Data.Char
    39 49
     import Data.Semigroup ((<>))
    
    40 50
     
    
    41 51
     -- | General purpose "registers"
    
    42
    ---
    
    43
    --- The JS backend arbitrarily supports 128 registers
    
    44
    -data StgReg
    
    45
    -  = R1  | R2  | R3  | R4  | R5  | R6  | R7  | R8
    
    46
    -  | R9  | R10 | R11 | R12 | R13 | R14 | R15 | R16
    
    47
    -  | R17 | R18 | R19 | R20 | R21 | R22 | R23 | R24
    
    48
    -  | R25 | R26 | R27 | R28 | R29 | R30 | R31 | R32
    
    49
    -  | R33 | R34 | R35 | R36 | R37 | R38 | R39 | R40
    
    50
    -  | R41 | R42 | R43 | R44 | R45 | R46 | R47 | R48
    
    51
    -  | R49 | R50 | R51 | R52 | R53 | R54 | R55 | R56
    
    52
    -  | R57 | R58 | R59 | R60 | R61 | R62 | R63 | R64
    
    53
    -  | R65 | R66 | R67 | R68 | R69 | R70 | R71 | R72
    
    54
    -  | R73 | R74 | R75 | R76 | R77 | R78 | R79 | R80
    
    55
    -  | R81 | R82 | R83 | R84 | R85 | R86 | R87 | R88
    
    56
    -  | R89 | R90 | R91 | R92 | R93 | R94 | R95 | R96
    
    57
    -  | R97  | R98  | R99  | R100 | R101 | R102 | R103 | R104
    
    58
    -  | R105 | R106 | R107 | R108 | R109 | R110 | R111 | R112
    
    59
    -  | R113 | R114 | R115 | R116 | R117 | R118 | R119 | R120
    
    60
    -  | R121 | R122 | R123 | R124 | R125 | R126 | R127 | R128
    
    61
    -  deriving (Eq, Ord, Show, Enum, Bounded, Ix)
    
    52
    +newtype StgReg
    
    53
    +  = StgReg Int
    
    54
    +  deriving (Eq,Ord,Ix)
    
    55
    +
    
    56
    +pattern R1, R2, R3, R4 :: StgReg
    
    57
    +pattern R1 = StgReg 0
    
    58
    +pattern R2 = StgReg 1
    
    59
    +pattern R3 = StgReg 2
    
    60
    +pattern R4 = StgReg 3
    
    62 61
     
    
    63 62
     -- | Stack registers
    
    64 63
     data Special
    
    ... ... @@ -78,7 +77,7 @@ instance ToJExpr Special where
    78 77
       toJExpr Sp     = hdStackPtr
    
    79 78
     
    
    80 79
     instance ToJExpr StgReg where
    
    81
    -  toJExpr r = registers ! r
    
    80
    +  toJExpr r = register r
    
    82 81
     
    
    83 82
     instance ToJExpr StgRet where
    
    84 83
       toJExpr r = rets ! r
    
    ... ... @@ -99,25 +98,42 @@ r2 = toJExpr R2
    99 98
     r3 = toJExpr R3
    
    100 99
     r4 = toJExpr R4
    
    101 100
     
    
    101
    +-- | 1-indexed register number (R1 has index 1)
    
    102
    +regNumber :: StgReg -> Int
    
    103
    +regNumber (StgReg r) = r+1
    
    102 104
     
    
    103
    -jsRegToInt :: StgReg -> Int
    
    104
    -jsRegToInt = (+1) . fromEnum
    
    105
    +-- | StgReg from 1-indexed number
    
    106
    +regFromNumber :: Int -> StgReg
    
    107
    +regFromNumber r = assert (r >= 1) $ StgReg (r-1)
    
    105 108
     
    
    106
    -intToJSReg :: Int -> StgReg
    
    107
    -intToJSReg r = toEnum (r - 1)
    
    109
    +regsFromTo :: StgReg -> StgReg -> [StgReg]
    
    110
    +regsFromTo (StgReg x) (StgReg y) = map StgReg [x .. y]
    
    108 111
     
    
    112
    +-- | Register expression from its 1-indexed index
    
    109 113
     jsReg :: Int -> JStgExpr
    
    110
    -jsReg r = toJExpr (intToJSReg r)
    
    114
    +jsReg r = toJExpr (regFromNumber r)
    
    115
    +
    
    116
    +minReg :: StgReg
    
    117
    +minReg = R1
    
    111 118
     
    
    112
    -maxReg :: Int
    
    113
    -maxReg = jsRegToInt maxBound
    
    119
    +maxReg :: StgReg
    
    120
    +maxReg = regFromNumber maxBound
    
    114 121
     
    
    115
    -minReg :: Int
    
    116
    -minReg = jsRegToInt minBound
    
    122
    +lowRegsCount :: Int
    
    123
    +lowRegsCount = 31
    
    124
    +
    
    125
    +maxLowReg :: StgReg
    
    126
    +maxLowReg = regFromNumber lowRegsCount
    
    127
    +
    
    128
    +-- | First register stored in h$regs array instead of having its own top-level
    
    129
    +-- variable
    
    130
    +minHighReg :: StgReg
    
    131
    +minHighReg = case maxLowReg of
    
    132
    +  StgReg r -> StgReg (r+1)
    
    117 133
     
    
    118 134
     -- | List of registers, starting from R1
    
    119 135
     regsFromR1 :: [StgReg]
    
    120
    -regsFromR1 = enumFrom R1
    
    136
    +regsFromR1 = regsFromTo R1 maxReg ++ repeat (panic "StgToJS: code requires too many registers")
    
    121 137
     
    
    122 138
     -- | List of registers, starting from R2
    
    123 139
     regsFromR2 :: [StgReg]
    
    ... ... @@ -131,35 +147,59 @@ jsRegsFromR1 = fmap toJExpr regsFromR1
    131 147
     jsRegsFromR2 :: [JStgExpr]
    
    132 148
     jsRegsFromR2 = tail jsRegsFromR1
    
    133 149
     
    
    150
    +-- | List of registers, starting from given reg as JExpr
    
    151
    +jsRegsFrom :: StgReg -> [JStgExpr]
    
    152
    +jsRegsFrom (StgReg n) = drop n jsRegsFromR1
    
    153
    +
    
    154
    +-- | High register
    
    155
    +highReg :: Int -> JStgExpr
    
    156
    +highReg r = assert (r >= regNumber minHighReg) $ IdxExpr hdRegs (toJExpr (r - regNumber minHighReg))
    
    157
    +
    
    158
    +-- | High register indexing with a JS expression
    
    159
    +highReg_expr :: JStgExpr -> JStgExpr
    
    160
    +highReg_expr r = IdxExpr hdRegs (r - toJExpr (regNumber minHighReg))
    
    161
    +
    
    162
    +
    
    134 163
     ---------------------------------------------------
    
    135 164
     -- caches
    
    136 165
     ---------------------------------------------------
    
    137 166
     
    
    138
    -lowRegs :: [Ident]
    
    139
    -lowRegs = map reg_to_ident [R1 .. R31]
    
    140
    -  where reg_to_ident = name . mkFastString . (unpackFS hdStr ++) . map toLower . show
    
    167
    +lowRegs :: [StgReg]
    
    168
    +lowRegs = regsFromTo minReg maxLowReg
    
    169
    +
    
    170
    +lowRegsIdents :: [Ident]
    
    171
    +lowRegsIdents = map reg_to_ident lowRegs
    
    172
    +  where
    
    173
    +    -- low regs are named h$r1, h$r2, etc.
    
    174
    +    reg_to_ident r = name (mkFastString (unpackFS hdStr ++ "r" ++ show (regNumber r)))
    
    141 175
     
    
    142 176
     retRegs :: [Ident]
    
    143 177
     retRegs = [name . mkFastStringByteString
    
    144 178
                $ hdB <> BSC.pack (map toLower $ show n) | n <- enumFrom Ret1]
    
    145 179
     
    
    146
    --- cache JExpr representing StgReg
    
    147
    -registers :: Array StgReg JStgExpr
    
    148
    -registers = listArray (minBound, maxBound) (map (global . identFS) lowRegs ++ map regN [R32 .. R128])
    
    149
    -  where
    
    150
    -    regN :: StgReg -> JStgExpr
    
    151
    -    regN r = IdxExpr hdRegs (toJExpr (fromEnum r - 32))
    
    152
    -
    
    153 180
     -- cache JExpr representing StgRet
    
    154 181
     rets :: Array StgRet JStgExpr
    
    155 182
     rets = listArray (minBound, maxBound) (map retN (enumFrom Ret1))
    
    156 183
       where
    
    157 184
         retN = global . mkFastString . (unpackFS hdStr ++) . map toLower . show
    
    158 185
     
    
    159
    --- | Given a register, return the JS syntax object representing that register
    
    160
    -register :: StgReg -> JStgExpr
    
    161
    -register i = registers ! i
    
    162
    -
    
    163 186
     -- | Given a register, return the JS syntax object representing that register
    
    164 187
     foreignRegister :: StgRet -> JStgExpr
    
    165 188
     foreignRegister i = rets ! i
    
    189
    +
    
    190
    +-- | Given a register, return the JS syntax object representing that register
    
    191
    +register :: StgReg -> JStgExpr
    
    192
    +register i
    
    193
    +  | i <= maxCachedReg = register_cache ! i -- Expressions of common registers are cached.
    
    194
    +  | otherwise         = make_high_reg i    -- Expression of higher registers are made on the fly
    
    195
    +
    
    196
    +maxCachedReg :: StgReg
    
    197
    +maxCachedReg = regFromNumber 128
    
    198
    +
    
    199
    +-- cache JExpr representing StgReg
    
    200
    +register_cache :: Array StgReg JStgExpr
    
    201
    +register_cache = listArray (minReg, maxCachedReg) (map (global . identFS) lowRegsIdents ++ map make_high_reg (regsFromTo minHighReg maxCachedReg))
    
    202
    +
    
    203
    +-- | Make h$regs[XXX] expression for the register
    
    204
    +make_high_reg :: StgReg -> JStgExpr
    
    205
    +make_high_reg r = highReg (regNumber r)

  • compiler/GHC/StgToJS/Rts/Rts.hs
    ... ... @@ -54,7 +54,12 @@ import qualified Data.Bits as Bits
    54 54
     -- | The garbageCollector resets registers and result variables.
    
    55 55
     garbageCollector :: JSM JStgStat
    
    56 56
     garbageCollector = jBlock
    
    57
    -    [ jFunction' hdResetRegisters  (return $ mconcat $ map resetRegister [minBound..maxBound])
    
    57
    +    [ jFunction' hdResetRegisters  $ return $ mconcat
    
    58
    +        [ -- reset low registers explicitly
    
    59
    +          mconcat (map resetRegister lowRegs)
    
    60
    +          -- reset the whole h$regs array with h$regs.fill(null)
    
    61
    +        , toStat $ ApplExpr (hdRegs .^ "fill") [null_]
    
    62
    +        ]
    
    58 63
         , jFunction' hdResetResultVars (return $ mconcat $ map resetResultVar [minBound..maxBound])
    
    59 64
         ]
    
    60 65
     
    
    ... ... @@ -249,7 +254,7 @@ declRegs = do
    249 254
         loaders         <- loadRegs
    
    250 255
         return $
    
    251 256
           mconcat [ hdRegsStr ||= toJExpr (JList [])
    
    252
    -              , mconcat (map declReg lowRegs)
    
    257
    +              , mconcat (map declReg lowRegsIdents)
    
    253 258
                   , getters_setters
    
    254 259
                   , loaders
    
    255 260
                   ]
    
    ... ... @@ -259,15 +264,15 @@ declRegs = do
    259 264
     -- | JS payload to define getters and setters on the registers.
    
    260 265
     regGettersSetters :: JSM JStgStat
    
    261 266
     regGettersSetters =
    
    262
    -  do setters <- jFunction (name hdGetRegStr) (\(MkSolo n) -> return $ SwitchStat n getRegCases mempty)
    
    263
    -     getters <- jFunction (name hdSetRegStr) (\(n,v)      -> return $ SwitchStat n (setRegCases v) mempty)
    
    267
    +  do getters <- jFunction (name hdGetRegStr) (\(MkSolo n) -> return $ SwitchStat n getRegCases (defaultGetRegCase n))
    
    268
    +     setters <- jFunction (name hdSetRegStr) (\(n,v)      -> return $ SwitchStat n (setRegCases v) (defaultSetRegCase n v))
    
    264 269
          return $ setters <> getters
    
    265 270
       where
    
    266
    -    getRegCases =
    
    267
    -      map (\r -> (toJExpr (jsRegToInt r) , returnS (toJExpr r))) regsFromR1
    
    268
    -    setRegCases :: JStgExpr -> [(JStgExpr,JStgStat)]
    
    269
    -    setRegCases v =
    
    270
    -      map (\r -> (toJExpr (jsRegToInt r), (toJExpr r |= toJExpr v) <> returnS undefined_)) regsFromR1
    
    271
    +    getRegCases         = map (\r -> (toJExpr (regNumber r) , returnS (toJExpr r))) lowRegs
    
    272
    +    defaultGetRegCase n = returnS (highReg_expr n)
    
    273
    +
    
    274
    +    setRegCases v         = map (\r -> (toJExpr (regNumber r), (toJExpr r |= v) <> BreakStat Nothing)) lowRegs
    
    275
    +    defaultSetRegCase n v = highReg_expr n |= v
    
    271 276
     
    
    272 277
     -- | JS payload that defines the functions to load each register
    
    273 278
     loadRegs :: JSM JStgStat
    

  • compiler/GHC/StgToJS/Rts/Types.hs
    ... ... @@ -69,12 +69,3 @@ stackFrameSize tgt f =
    69 69
                     (tgt |= mask8 tag + 1)       -- else set to mask'd tag + 1
    
    70 70
                   ]
    
    71 71
               ))
    72
    -
    
    73
    -  --------------------------------------------------------------------------------
    
    74
    --- Register utilities
    
    75
    ---------------------------------------------------------------------------------
    
    76
    -
    
    77
    --- | Perform the computation 'f', on the range of registers bounded by 'start'
    
    78
    --- and 'end'.
    
    79
    -withRegs :: StgReg -> StgReg -> (StgReg -> JStgStat) -> JStgStat
    
    80
    -withRegs start end f = mconcat $ fmap f [start..end]

  • testsuite/tests/codeGen/should_run/all.T
    ... ... @@ -256,4 +256,4 @@ test('T24893', normal, compile_and_run, ['-O'])
    256 256
     test('CCallConv', [req_c], compile_and_run, ['CCallConv_c.c'])
    
    257 257
     test('T25364', normal, compile_and_run, [''])
    
    258 258
     test('T26061', normal, compile_and_run, [''])
    
    259
    -test('T26537', js_broken(26558), compile_and_run, ['-O2 -fregs-graph'])
    259
    +test('T26537', normal, compile_and_run, ['-O2 -fregs-graph'])