JavaScript backend: GHC.StgToJS.Rts.Rts module requires refactoring improvements
There are several places in the JavaScript backend's GHC.StgToJS.Rts.Rts module, responsible for generating JavaScript RTS functions, where code is repeated unnecessarily.
In some of these cases, there is a potential performance deficit in the form of FastString
s being formed several times from String
s, which are themselves repeated several times. Because these FastString
s are used in generating argument names for generated JavaScript ASTs, to be used in functions with increasing lengths, the argument names are repeated often. So we might have function f1(x1) {...}
, function f2(x1, x2) {...}
, ..., function f24(x1, x2, ..., x24) {...}
.
An example of this is the variables generated by mkClosureCon
. Variables up to x24
are used by h$cN
, meaning x3
is generated 22 times, x4
21 times, and so on:
mkClosureCon :: Int -> JStat
mkClosureCon n = funName ||= toJExpr fun
where
funName = TxtI $ mkFastString ("h$c" ++ show n)
-- args are: f x1 x2 .. xn [cc]
args = TxtI "f" : addCCArg' (map (TxtI . mkFastString . ('x':) . show) [(1::Int)..n])
In other cases, the code repetition is the result of unnecessary special cases for the "base cases" of recursively generated functions. These cases can simply be generalised.
An example of this is the 0, 1, and 2-length cases of mkClosureCon
:
closureConstructors :: StgToJSConfig -> JStat
closureConstructors s = BlockStat
[ declClsConstr "h$c" ["f"] $ Closure
{ clEntry = var "f"
, clField1 = null_
, clField2 = null_
, clMeta = 0
, clCC = ccVal
}
, declClsConstr "h$c0" ["f"] $ Closure
{ clEntry = var "f"
, clField1 = null_
, clField2 = null_
, clMeta = 0
, clCC = ccVal
}
, declClsConstr "h$c1" ["f", "x1"] $ Closure
{ clEntry = var "f"
, clField1 = var "x1"
, clField2 = null_
, clMeta = 0
, clCC = ccVal
}
, declClsConstr "h$c2" ["f", "x1", "x2"] $ Closure
{ clEntry = var "f"
, clField1 = var "x1"
, clField2 = var "x2"
, clMeta = 0
, clCC = ccVal
}
, mconcat (map mkClosureCon [3..24])
, mconcat (map mkDataFill [1..24])
]