Skip to content

Commit

Permalink
Intern strings locally, not globally
Browse files Browse the repository at this point in the history
  • Loading branch information
ryantrinkle committed Jan 10, 2021
1 parent 241752d commit 0adb998
Show file tree
Hide file tree
Showing 16 changed files with 58 additions and 33 deletions.
4 changes: 1 addition & 3 deletions hnix.cabal
Original file line number Diff line number Diff line change
Expand Up @@ -417,7 +417,6 @@ library
, http-client >= 0.5.14 && < 0.6 || >= 0.6.4 && < 0.7
, http-client-tls >= 0.3.5 && < 0.4
, http-types >= 0.12.2 && < 0.13
, intern
, lens-family >= 1.2.2 && < 2.2
, lens-family-core >= 1.2.2 && < 2.2
, lens-family-th >= 0.5.0 && < 0.6
Expand Down Expand Up @@ -449,6 +448,7 @@ library
, unordered-containers >= 0.2.9 && < 0.3
, vector >= 0.12.0 && < 0.13
, xml >= 1.3.14 && < 1.4
, ghc-prim
if flag(optimize)
ghc-options: -fexpose-all-unfoldings -fspecialise-aggressively -O2
if !impl(ghcjs)
Expand Down Expand Up @@ -485,7 +485,6 @@ executable hnix
, free
, haskeline >= 0.8.0.0 && < 0.9
, hnix
, intern
, mtl
, optparse-applicative
, pretty-show
Expand Down Expand Up @@ -537,7 +536,6 @@ test-suite hnix-tests
, filepath
, hedgehog
, hnix
, intern
, megaparsec
, mtl
, neat-interpolation
Expand Down
1 change: 0 additions & 1 deletion main/Main.hs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@ import Control.Monad.Catch
import Control.Monad.Free
import Control.Monad.IO.Class
import qualified Data.HashMap.Lazy as M
import Data.Interned ( unintern )
import qualified Data.Map as Map
import Data.List ( sortOn )
import Data.Maybe ( fromJust )
Expand Down
1 change: 0 additions & 1 deletion main/Repl.hs
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,6 @@ import Nix.Value.Monad (demand)
import qualified Data.List
import qualified Data.Maybe
import qualified Data.HashMap.Lazy
import Data.Interned
import Data.Text (Text)
import qualified Data.Text
import qualified Data.Text.IO
Expand Down
1 change: 0 additions & 1 deletion src/Nix.hs
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,6 @@ import Control.Arrow ( first, second )
import Control.Monad.Reader
import Data.Fix
import qualified Data.HashMap.Lazy as M
import Data.Interned
import qualified Data.Text as Text
import qualified Data.Text.Read as Text
import Nix.Builtins
Expand Down
3 changes: 1 addition & 2 deletions src/Nix/Builtins.hs
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,6 @@ import Data.Char ( isDigit )
import Data.Fix ( foldFix )
import Data.Foldable ( foldrM )
import qualified Data.HashMap.Lazy as M
import Data.Interned
import Data.List
import Data.Maybe
import Data.Scientific
Expand Down Expand Up @@ -1308,7 +1307,7 @@ readDir_ p = demand p $ \path' -> do
| isDirectory s -> FileTypeDirectory
| isSymbolicLink s -> FileTypeSymlink
| otherwise -> FileTypeUnknown
pure (intern @VarName $ Text.pack item, t)
pure (intern $ Text.pack item, t)
getDeeper <$> toValue (M.fromList itemsWithTypes)

fromJSON
Expand Down
1 change: 0 additions & 1 deletion src/Nix/Effects/Derivation.hs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@ import Data.Char ( isAscii, isAlphaNum )
import qualified Data.HashMap.Lazy as M
import qualified Data.HashMap.Strict as MS
import qualified Data.HashSet as S
import Data.Interned
import Data.List
import qualified Data.Map.Strict as Map
import Data.Map.Strict ( Map )
Expand Down
1 change: 0 additions & 1 deletion src/Nix/Eval.hs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@ import Data.Either ( isRight )
import Data.Fix ( Fix(Fix) )
import Data.HashMap.Lazy ( HashMap )
import qualified Data.HashMap.Lazy as M
import Data.Interned
import Data.List ( partition )
import Data.List.NonEmpty ( NonEmpty(..) )
import Data.Maybe ( fromMaybe
Expand Down
1 change: 0 additions & 1 deletion src/Nix/Exec.hs
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,6 @@ import Control.Monad.Fix
import Control.Monad.Reader
import Data.Fix
import qualified Data.HashMap.Lazy as M
import Data.Interned
import Data.List
import qualified Data.List.NonEmpty as NE
import Data.Text ( Text )
Expand Down
2 changes: 0 additions & 2 deletions src/Nix/Expr/Types.hs
Original file line number Diff line number Diff line change
Expand Up @@ -44,8 +44,6 @@ import Data.Fix
import Data.Functor.Classes
import Data.Hashable
import Data.Hashable.Lifted
import Data.Interned.Text
import Data.Interned
import Data.List ( inits
, tails
)
Expand Down
1 change: 0 additions & 1 deletion src/Nix/Json.hs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ import Control.Monad.Trans
import qualified Data.Aeson as A
import qualified Data.Aeson.Encoding as A
import qualified Data.HashMap.Lazy as HM
import Data.Interned
import qualified Data.Text as Text
import qualified Data.Text.Lazy as TL
import qualified Data.Text.Lazy.Encoding as TL
Expand Down
1 change: 0 additions & 1 deletion src/Nix/Lint.hs
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,6 @@ import Control.Monad.ST
import Control.Monad.Trans.Reader
import Data.HashMap.Lazy ( HashMap )
import qualified Data.HashMap.Lazy as M
import Data.Interned
import Data.List
import qualified Data.List.NonEmpty as NE
import Data.Text ( Text )
Expand Down
3 changes: 1 addition & 2 deletions src/Nix/Parser.hs
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,6 @@ import Data.Fix ( Fix(..) )
import Data.Functor
import Data.HashSet ( HashSet )
import qualified Data.HashSet as HashSet
import Data.Interned
import Data.List.NonEmpty ( NonEmpty(..) )
import qualified Data.List.NonEmpty as NE
import qualified Data.Map as Map
Expand All @@ -81,7 +80,7 @@ import GHC.Generics hiding ( Prefix )
import Nix.Expr hiding ( ($>) )
import Nix.Expr.Strings
import Nix.Render
import Nix.Utils ( VarName )
import Nix.Utils ( VarName, intern )
import Prettyprinter ( Doc
, pretty
)
Expand Down
3 changes: 1 addition & 2 deletions src/Nix/Pretty.hs
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,6 @@ import qualified Data.HashSet as HashSet
import Data.List ( isPrefixOf
, sort
)
import Data.Interned ( intern, unintern )
import Data.Interned.Text
import Data.List.NonEmpty ( NonEmpty(..) )
import qualified Data.List.NonEmpty as NE
import Data.Maybe ( isJust
Expand All @@ -47,6 +45,7 @@ import Nix.Normal
import Nix.Parser
import Nix.String
import Nix.Thunk
import Nix.Utils
import Nix.Value
import Prettyprinter
import Text.Read ( readMaybe )
Expand Down
3 changes: 1 addition & 2 deletions src/Nix/TH.hs
Original file line number Diff line number Diff line change
Expand Up @@ -16,14 +16,13 @@ import qualified Data.Set as Set
import qualified Data.Text as Text
import Data.List.NonEmpty ( NonEmpty(..) )
import Data.Maybe ( mapMaybe )
import Data.Interned ( unintern )
import Language.Haskell.TH
import Language.Haskell.TH.Syntax ( liftString )
import Language.Haskell.TH.Quote
import Nix.Atoms
import Nix.Expr
import Nix.Parser
import Nix.Utils ( VarName )
import Nix.Utils ( VarName, unintern )

quoteExprExp :: String -> ExpQ
quoteExprExp s = do
Expand Down
63 changes: 52 additions & 11 deletions src/Nix/Utils.hs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
{-# LANGUAGE TemplateHaskell #-}
{-# LANGUAGE TupleSections #-}
{-# LANGUAGE TypeApplications #-}
{-# LANGUAGE MagicHash #-}

{-# OPTIONS_GHC -Wno-missing-signatures #-}

Expand All @@ -29,8 +30,7 @@ import Data.Fix ( Fix(..) )
import Data.Hashable ( Hashable )
import Data.HashMap.Lazy ( HashMap )
import qualified Data.HashMap.Lazy as M
import Data.Interned.Text
import Data.Interned
import Data.IORef
import Data.List ( sortOn )
import Data.Monoid ( Endo )
import Data.Text ( Text )
Expand All @@ -42,6 +42,10 @@ import Lens.Family2.Stock ( _1
, _2
)
import Lens.Family2.TH ( makeLensesBy )
import System.IO.Unsafe
import GHC.Prim
import Data.Hashable
import Data.String

#if ENABLE_TRACING
import Debug.Trace as X
Expand Down Expand Up @@ -182,18 +186,56 @@ alterF f k m = f (M.lookup k m) <&> \case
Nothing -> M.delete k m
Just v -> M.insert k v m


type VarName = InternedText
data VarName = VarName
{ _varName_hash :: {-# UNPACK #-} !Int
, _varName_ref :: {-# UNPACK #-} !(IORef Text)
}

instance Hashable VarName where
hash = _varName_hash
hashWithSalt salt v = hashWithSalt salt $ _varName_hash v

instance Show VarName where
showsPrec n = showsPrec n . unintern
show = show . unintern
showList = showList . fmap unintern

instance Eq VarName where
a == b
| _varName_ref a == _varName_ref b = True
| _varName_hash a /= _varName_hash b = False
| otherwise = unsafeDupablePerformIO $ do
ta <- readIORef $ _varName_ref a
tb <- readIORef $ _varName_ref b
case reallyUnsafePtrEquality# ta tb of
0# -> if ta == tb
then do writeIORef (_varName_ref b) ta
pure True
else pure False
_ -> pure True

instance Ord VarName where
a `compare` b
| a == b = EQ -- Fast path; also necessary to opportunistically dedup if possible
| otherwise = unintern a `compare` unintern b

instance IsString VarName where
fromString = intern . fromString

intern :: Text -> VarName
intern t = VarName (hash t) $ unsafeDupablePerformIO $ newIORef t

unintern :: VarName -> Text
unintern a = unsafeDupablePerformIO $ readIORef $ _varName_ref a

instance Read VarName where
readsPrec i v = (\(t, s) -> (intern t, s)) <$> readsPrec i v


internConstr :: Constr
internConstr = mkConstr internedTextDataType "intern" [] Prefix

internedTextDataType :: DataType
internedTextDataType = mkDataType "Data.Interned" [internConstr]
internedTextDataType = mkDataType "Nix.Utils" [internConstr]

instance Data VarName where
gfoldl f z v = z intern `f` (unintern v)
Expand All @@ -203,17 +245,16 @@ instance Data VarName where
_ -> error "gunfold"
dataTypeOf _ = internedTextDataType

instance NFData InternedText where rnf !_ = ()
instance NFData VarName where rnf !_ = ()

instance Data.Binary.Binary InternedText where
instance Data.Binary.Binary VarName where
put = Data.Binary.put . unintern
get = intern <$> Data.Binary.get

-- instance Generic InternedText where
-- instance Generic VarName where

instance Codec.Serialise.Serialise InternedText where
instance Codec.Serialise.Serialise VarName where
encode = Codec.Serialise.encode . unintern
decode = intern <$> Codec.Serialise.decode @Text


-- derive instance Data VarName
2 changes: 1 addition & 1 deletion src/Nix/XML.hs
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,10 @@ import qualified Data.HashMap.Lazy as M
import Data.List
import Data.Ord
import qualified Data.Text as Text
import Data.Interned
import Nix.Atoms
import Nix.Expr.Types
import Nix.String
import Nix.Utils
import Nix.Value
import Text.XML.Light

Expand Down

0 comments on commit 0adb998

Please sign in to comment.