summaryrefslogtreecommitdiff
path: root/compiler/prelude/TysWiredIn.hs
diff options
context:
space:
mode:
authorBartosz Nitka <niteria@gmail.com>2018-01-05 15:20:05 +0000
committerBartosz Nitka <niteria@gmail.com>2018-01-10 13:50:56 +0000
commitdbdf77d92c9cd0bbb269137de0bf8754573cdc1e (patch)
tree17bbe7fb388308615ba009e4f887c719c9e58107 /compiler/prelude/TysWiredIn.hs
parent1577908f2a9db0fcf6f749d40dd75481015f5497 (diff)
downloadhaskell-dbdf77d92c9cd0bbb269137de0bf8754573cdc1e.tar.gz
Lift constructor tag allocation out of a loop
Before this change, for each constructor that we want to allocate a tag for we would traverse a list of all the constructors in a datatype to determine which tag a constructor should get. This is obviously quadratic and for datatypes with 10k constructors it actually makes a big difference. This change implements the plan outlined by @simonpj in https://mail.haskell.org/pipermail/ghc-devs/2017-October/014974.html which is basically about using a map and constructing it outside the loop. One place where things got a bit awkward was TysWiredIn.hs, it would have been possible to just assign the tags by hand, but that seemed error-prone to me, so I decided to go through a map there as well. Test Plan: ./validate On a file with 10k constructors Before: 8,130,522,344 bytes allocated in the heap Total time 3.682s ( 3.920s elapsed) After: 4,133,478,744 bytes allocated in the heap Total time 2.509s ( 2.750s elapsed) Reviewers: simonpj, bgamari Reviewed By: simonpj Subscribers: goldfire, rwbarton, thomie, simonmar, carter, simonpj GHC Trac Issues: #14657 Differential Revision: https://phabricator.haskell.org/D4289
Diffstat (limited to 'compiler/prelude/TysWiredIn.hs')
-rw-r--r--compiler/prelude/TysWiredIn.hs10
1 files changed, 9 insertions, 1 deletions
diff --git a/compiler/prelude/TysWiredIn.hs b/compiler/prelude/TysWiredIn.hs
index fda6b221f3..72c24edc3c 100644
--- a/compiler/prelude/TysWiredIn.hs
+++ b/compiler/prelude/TysWiredIn.hs
@@ -150,7 +150,7 @@ import TyCon
import Class ( Class, mkClass )
import RdrName
import Name
-import NameEnv ( NameEnv, mkNameEnv, lookupNameEnv )
+import NameEnv ( NameEnv, mkNameEnv, lookupNameEnv, lookupNameEnv_NF )
import NameSet ( NameSet, mkNameSet, elemNameSet )
import BasicTypes ( Arity, Boxity(..), TupleSort(..), ConTagZ,
SourceText(..) )
@@ -517,6 +517,13 @@ pcDataConWithFixity' declared_infix dc_name wrk_key rri
tyvars ex_tyvars user_tyvars arg_tys tycon
= data_con
where
+ tag_map = mkTyConTagMap tycon
+ -- This constructs the constructor Name to ConTag map once per
+ -- constructor, which is quadratic. It's OK here, because it's
+ -- only called for wired in data types that don't have a lot of
+ -- constructors. It's also likely that GHC will lift tag_map, since
+ -- we call pcDataConWithFixity' with static TyCons in the same module.
+ -- See Note [Constructor tag allocation] and #14657
data_con = mkDataCon dc_name declared_infix prom_info
(map (const no_bang) arg_tys)
[] -- No labelled fields
@@ -527,6 +534,7 @@ pcDataConWithFixity' declared_infix dc_name wrk_key rri
arg_tys (mkTyConApp tycon (mkTyVarTys tyvars))
rri
tycon
+ (lookupNameEnv_NF tag_map dc_name)
[] -- No stupid theta
(mkDataConWorkId wrk_name data_con)
NoDataConRep -- Wired-in types are too simple to need wrappers