From 76d633b05a0a11a4fd97dbe3d3c04610a450514f Mon Sep 17 00:00:00 2001 From: Chris Penner Date: Wed, 11 Sep 2024 14:30:06 -0700 Subject: [PATCH 01/40] Add closures as a GComb constructor --- unison-runtime/src/Unison/Runtime/MCode.hs | 63 ++++++++++++---------- 1 file changed, 35 insertions(+), 28 deletions(-) diff --git a/unison-runtime/src/Unison/Runtime/MCode.hs b/unison-runtime/src/Unison/Runtime/MCode.hs index 03f8547cd3..996737446b 100644 --- a/unison-runtime/src/Unison/Runtime/MCode.hs +++ b/unison-runtime/src/Unison/Runtime/MCode.hs @@ -61,6 +61,7 @@ import Data.List (partition) import Data.Map.Strict qualified as M import Data.Primitive.ByteArray import Data.Primitive.PrimArray +import Data.Void (Void) import Data.Word (Word16, Word64) import GHC.Stack (HasCallStack) import Unison.ABT.Normalized (pattern TAbss) @@ -456,7 +457,7 @@ data MLit type Instr = GInstr CombIx -type RInstr = GInstr RComb +type RInstr clos = GInstr (RComb clos) -- Instructions for manipulating the data stack in the main portion of -- a block @@ -529,7 +530,7 @@ data GInstr comb type Section = GSection CombIx -type RSection = GSection RComb +type RSection clos = GSection (RComb clos) data GSection comb = -- Apply a function to arguments. This is the 'slow path', and @@ -599,7 +600,7 @@ data CombIx combRef :: CombIx -> Reference combRef (CIx r _ _) = r -rCombRef :: RComb -> Reference +rCombRef :: RComb clos -> Reference rCombRef (RComb cix _) = combRef cix data RefNums = RN @@ -612,62 +613,64 @@ emptyRNs = RN mt mt where mt _ = internalBug "RefNums: empty" -type Comb = GComb CombIx +type Comb = GComb Void CombIx -data GComb comb +data GComb clos comb = Lam !Int -- Number of unboxed arguments !Int -- Number of boxed arguments !Int -- Maximum needed unboxed frame size !Int -- Maximum needed boxed frame size !(GSection comb) -- Entry + | -- A pre-evaluated comb, typically a pure top-level const + Cached clos deriving stock (Show, Eq, Ord, Functor, Foldable, Traversable) -type Combs = GCombs CombIx +type Combs clos = GCombs clos CombIx -type RCombs = GCombs RComb +type RCombs clos = GCombs clos (RComb clos) -- | Extract the CombIx from an RComb. -pattern RCombIx :: CombIx -> RComb +pattern RCombIx :: CombIx -> RComb clos pattern RCombIx r <- (rCombIx -> r) {-# COMPLETE RCombIx #-} -- | Extract the Reference from an RComb. -pattern RCombRef :: Reference -> RComb +pattern RCombRef :: Reference -> RComb clos pattern RCombRef r <- (combRef . rCombIx -> r) {-# COMPLETE RCombRef #-} -- | The fixed point of a GComb where all references to a Comb are themselves Combs. -data RComb = RComb +data RComb clos = RComb { rCombIx :: !CombIx, - unRComb :: (GComb RComb {- Possibly recursive comb, keep it lazy or risk blowing up -}) + unRComb :: (GComb clos (RComb clos {- Possibly recursive comb, keep it lazy or risk blowing up -})) } -- Eq and Ord instances on the CombIx to avoid infinite recursion when -- comparing self-recursive functions. -instance Eq RComb where +instance Eq (RComb clos) where RComb r1 _ == RComb r2 _ = r1 == r2 -instance Ord RComb where +instance Ord (RComb clos) where compare (RComb r1 _) (RComb r2 _) = compare r1 r2 -- | Convert an RComb to a Comb by forgetting the sections and keeping only the CombIx. -rCombToComb :: RComb -> Comb +rCombToComb :: RComb Void -> Comb rCombToComb (RComb _ix c) = rCombIx <$> c -- | RCombs can be infinitely recursive so we show the CombIx instead. -instance Show RComb where +instance Show (RComb clos) where show (RComb ix _) = show ix -- | Map of combinators, parameterized by comb reference type -type GCombs comb = EnumMap Word64 (GComb comb) +type GCombs clos comb = EnumMap Word64 (GComb clos comb) -- | A reference to a combinator, parameterized by comb type Ref = GRef CombIx -type RRef = GRef RComb +type RRef clos = GRef (RComb clos) data GRef comb = Stk !Int -- stack reference to a closure @@ -677,7 +680,7 @@ data GRef comb type Branch = GBranch CombIx -type RBranch = GBranch RComb +type RBranch clos = GBranch (RComb clos) data GBranch comb = -- if tag == n then t else f @@ -805,10 +808,10 @@ emitCombs rns grpr grpn (Rec grp ent) = resolveCombs :: -- Existing in-scope combs that might be referenced -- TODO: Do we ever actually need to pass this? - Maybe (EnumMap Word64 RCombs) -> + Maybe (EnumMap Word64 (RCombs clos)) -> -- Combinators which need their knots tied. - EnumMap Word64 Combs -> - EnumMap Word64 RCombs + EnumMap Word64 (Combs clos) -> + EnumMap Word64 (RCombs clos) resolveCombs mayExisting combs = -- Fixed point lookup; -- We make sure not to force resolved Combs or we'll loop forever. @@ -1557,9 +1560,11 @@ demuxArgs as0 = combDeps :: Comb -> [Word64] combDeps (Lam _ _ _ _ s) = sectionDeps s +combDeps (Cached {}) = [] combTypes :: Comb -> [Word64] combTypes (Lam _ _ _ _ s) = sectionTypes s +combTypes (Cached {}) = [] sectionDeps :: Section -> [Word64] sectionDeps (App _ (Env (CIx _ w _)) _) = [w] @@ -1624,13 +1629,15 @@ prettyCombs w es = (mapToList es) prettyComb :: Word64 -> Word64 -> Comb -> ShowS -prettyComb w i (Lam ua ba _ _ s) = - shows w - . showString ":" - . shows i - . shows [ua, ba] - . showString ":\n" - . prettySection 2 s +prettyComb w i = \case + (Lam ua ba _ _ s) -> + shows w + . showString ":" + . shows i + . shows [ua, ba] + . showString ":\n" + . prettySection 2 s + (Cached {}) -> showString "" prettySection :: Int -> Section -> ShowS prettySection ind sec = From 706e785c527dff4ae1293cb973a146fbf0c6fe98 Mon Sep 17 00:00:00 2001 From: Chris Penner Date: Wed, 11 Sep 2024 14:30:06 -0700 Subject: [PATCH 02/40] Handle cached closures in the Machine --- unison-runtime/src/Unison/Runtime/Builtin.hs | 10 +- .../src/Unison/Runtime/Decompile.hs | 58 +++---- .../src/Unison/Runtime/Foreign/Function.hs | 24 +-- .../src/Unison/Runtime/Interface.hs | 20 ++- unison-runtime/src/Unison/Runtime/MCode.hs | 8 +- .../src/Unison/Runtime/MCode/Serialize.hs | 26 ++- unison-runtime/src/Unison/Runtime/Machine.hs | 129 ++++++++------ unison-runtime/src/Unison/Runtime/Stack.hs | 163 +++++++++++------- 8 files changed, 268 insertions(+), 170 deletions(-) diff --git a/unison-runtime/src/Unison/Runtime/Builtin.hs b/unison-runtime/src/Unison/Runtime/Builtin.hs index 070bdd8118..893f64a233 100644 --- a/unison-runtime/src/Unison/Runtime/Builtin.hs +++ b/unison-runtime/src/Unison/Runtime/Builtin.hs @@ -2304,7 +2304,7 @@ unitValue :: Closure unitValue = Closure.Enum Ty.unitRef 0 natValue :: Word64 -> Closure -natValue w = Closure.DataU1 Ty.natRef 0 (fromIntegral w) +natValue w = Closure.DataU1 Ty.natRef 0 (fromIntegral w) mkForeignTls :: forall a r. @@ -3156,9 +3156,9 @@ declareForeigns = do $ Right <$> PA.freezeByteArray src (fromIntegral off) (fromIntegral len) declareForeign Untracked "MutableArray.freeze" boxNatNatToExnBox . mkForeign $ - \(src :: PA.MutableArray PA.RealWorld Closure.RClosure, off, len) -> + \(src :: PA.MutableArray PA.RealWorld Closure, off, len) -> if len == 0 - then fmap Right . PA.unsafeFreezeArray =<< PA.newArray 0 Closure.BlackHole + then fmap Right . PA.unsafeFreezeArray =<< PA.newArray 0 ( Closure.BlackHole) else checkBounds "MutableArray.freeze" @@ -3173,7 +3173,7 @@ declareForeigns = do pure . PA.sizeofByteArray declareForeign Tracked "IO.array" natToBox . mkForeign $ - \n -> PA.newArray n (Closure.BlackHole :: Closure.RClosure) + \n -> PA.newArray n (Closure.BlackHole :: Closure) declareForeign Tracked "IO.arrayOf" boxNatToBox . mkForeign $ \(v :: Closure, n) -> PA.newArray n v declareForeign Tracked "IO.bytearray" natToBox . mkForeign $ PA.newByteArray @@ -3185,7 +3185,7 @@ declareForeigns = do pure arr declareForeign Untracked "Scope.array" natToBox . mkForeign $ - \n -> PA.newArray n (Closure.BlackHole :: Closure.RClosure) + \n -> PA.newArray n (Closure.BlackHole :: Closure) declareForeign Untracked "Scope.arrayOf" boxNatToBox . mkForeign $ \(v :: Closure, n) -> PA.newArray n v declareForeign Untracked "Scope.bytearray" natToBox . mkForeign $ PA.newByteArray diff --git a/unison-runtime/src/Unison/Runtime/Decompile.hs b/unison-runtime/src/Unison/Runtime/Decompile.hs index 13084ea1dc..346385e7cd 100644 --- a/unison-runtime/src/Unison/Runtime/Decompile.hs +++ b/unison-runtime/src/Unison/Runtime/Decompile.hs @@ -34,8 +34,7 @@ import Unison.Runtime.Foreign import Unison.Runtime.IOSource (iarrayFromListRef, ibarrayFromBytesRef) import Unison.Runtime.MCode (CombIx (..), pattern RCombIx, pattern RCombRef) import Unison.Runtime.Stack - ( Closure, - GClosure (..), + ( Closure (..), pattern DataC, pattern PApV, ) @@ -153,33 +152,34 @@ decompile :: (Word64 -> Word64 -> Maybe (Term v ())) -> Closure -> DecompResult v -decompile _ _ (DataC rf (maskTags -> ct) [] []) - | rf == booleanRef = tag2bool ct -decompile _ _ (DataC rf (maskTags -> ct) [i] []) = - decompileUnboxed rf ct i -decompile backref topTerms (DataC rf _ [] [b]) - | rf == anyRef = - app () (builtin () "Any.Any") <$> decompile backref topTerms b -decompile backref topTerms (DataC rf (maskTags -> ct) [] bs) = - apps' (con rf ct) <$> traverse (decompile backref topTerms) bs -decompile backref topTerms (PApV (RCombIx (CIx rf rt k)) [] bs) - | rf == Builtin "jumpCont" = err Cont $ bug "" - | Builtin nm <- rf = - apps' (builtin () nm) <$> traverse (decompile backref topTerms) bs - | Just t <- topTerms rt k = - Term.etaReduceEtaVars . substitute t - <$> traverse (decompile backref topTerms) bs - | k > 0, - Just _ <- topTerms rt 0 = - err (UnkLocal rf k) $ bug "" - | otherwise = err (UnkComb rf) $ ref () rf -decompile _ _ (PAp (RCombRef rf) _ _) = - err (BadPAp rf) $ bug "" -decompile _ _ (DataC rf _ _ _) = err (BadData rf) $ bug "" -decompile _ _ BlackHole = err Exn $ bug "" -decompile _ _ (Captured {}) = err Cont $ bug "" -decompile backref topTerms (Foreign f) = - decompileForeign backref topTerms f +decompile backref topTerms = \case + DataC rf (maskTags -> ct) [] [] + | rf == booleanRef -> tag2bool ct + DataC rf (maskTags -> ct) [i] [] -> + decompileUnboxed rf ct i + (DataC rf _ [] [b]) + | rf == anyRef -> + app () (builtin () "Any.Any") <$> decompile backref topTerms b + (DataC rf (maskTags -> ct) [] bs) -> + apps' (con rf ct) <$> traverse (decompile backref topTerms) bs + (PApV (RCombIx (CIx rf rt k)) [] bs) + | rf == Builtin "jumpCont" -> err Cont $ bug "" + | Builtin nm <- rf -> + apps' (builtin () nm) <$> traverse (decompile backref topTerms) bs + | Just t <- topTerms rt k -> + Term.etaReduceEtaVars . substitute t + <$> traverse (decompile backref topTerms) bs + | k > 0, + Just _ <- topTerms rt 0 -> + err (UnkLocal rf k) $ bug "" + | otherwise -> err (UnkComb rf) $ ref () rf + (PAp (RCombRef rf) _ _) -> + err (BadPAp rf) $ bug "" + (DataC rf _ _ _) -> err (BadData rf) $ bug "" + BlackHole -> err Exn $ bug "" + (Captured {}) -> err Cont $ bug "" + (Foreign f) -> + decompileForeign backref topTerms f tag2bool :: (Var v) => Word64 -> DecompResult v tag2bool 0 = pure (boolean () False) diff --git a/unison-runtime/src/Unison/Runtime/Foreign/Function.hs b/unison-runtime/src/Unison/Runtime/Foreign/Function.hs index de73cc7331..ed9d890088 100644 --- a/unison-runtime/src/Unison/Runtime/Foreign/Function.hs +++ b/unison-runtime/src/Unison/Runtime/Foreign/Function.hs @@ -124,7 +124,7 @@ instance ForeignConvention Char where -- In reality this fixes the type to be 'RClosure', but allows us to defer -- the typechecker a bit and avoid a bunch of annoying type annotations. -instance (GClosure comb ~ Elem 'BX) => ForeignConvention (GClosure comb) where +instance ForeignConvention Closure where readForeign us (i : bs) _ bstk = (us,bs,) <$> peekOff bstk i readForeign _ [] _ _ = foreignCCError "Closure" writeForeign ustk bstk c = do @@ -441,7 +441,7 @@ instance ForeignConvention BufferMode where -- In reality this fixes the type to be 'RClosure', but allows us to defer -- the typechecker a bit and avoid a bunch of annoying type annotations. -instance (GClosure comb ~ Elem 'BX) => ForeignConvention [GClosure comb] where +instance ForeignConvention [Closure] where readForeign us (i : bs) _ bstk = (us,bs,) . toList <$> peekOffS bstk i readForeign _ _ _ _ = foreignCCError "[Closure]" @@ -453,23 +453,23 @@ instance ForeignConvention [Foreign] where readForeign = readForeignAs (fmap marshalToForeign) writeForeign = writeForeignAs (fmap Foreign) -instance ForeignConvention (MVar RClosure) where +instance ForeignConvention (MVar Closure) where readForeign = readForeignAs (unwrapForeign . marshalToForeign) writeForeign = writeForeignAs (Foreign . Wrap mvarRef) -instance ForeignConvention (TVar RClosure) where +instance ForeignConvention (TVar Closure) where readForeign = readForeignAs (unwrapForeign . marshalToForeign) writeForeign = writeForeignAs (Foreign . Wrap tvarRef) -instance ForeignConvention (IORef RClosure) where +instance ForeignConvention (IORef Closure) where readForeign = readForeignAs (unwrapForeign . marshalToForeign) writeForeign = writeForeignAs (Foreign . Wrap refRef) -instance ForeignConvention (Ticket RClosure) where +instance ForeignConvention (Ticket Closure) where readForeign = readForeignAs (unwrapForeign . marshalToForeign) writeForeign = writeForeignAs (Foreign . Wrap ticketRef) -instance ForeignConvention (Promise RClosure) where +instance ForeignConvention (Promise Closure) where readForeign = readForeignAs (unwrapForeign . marshalToForeign) writeForeign = writeForeignAs (Foreign . Wrap promiseRef) @@ -485,7 +485,7 @@ instance ForeignConvention Foreign where readForeign = readForeignAs marshalToForeign writeForeign = writeForeignAs Foreign -instance ForeignConvention (PA.MutableArray s RClosure) where +instance ForeignConvention (PA.MutableArray s Closure) where readForeign = readForeignAs (unwrapForeign . marshalToForeign) writeForeign = writeForeignAs (Foreign . Wrap marrayRef) @@ -493,7 +493,7 @@ instance ForeignConvention (PA.MutableByteArray s) where readForeign = readForeignAs (unwrapForeign . marshalToForeign) writeForeign = writeForeignAs (Foreign . Wrap mbytearrayRef) -instance ForeignConvention (PA.Array RClosure) where +instance ForeignConvention (PA.Array Closure) where readForeign = readForeignAs (unwrapForeign . marshalToForeign) writeForeign = writeForeignAs (Foreign . Wrap iarrayRef) @@ -505,13 +505,13 @@ instance {-# OVERLAPPABLE #-} (BuiltinForeign b) => ForeignConvention b where readForeign = readForeignBuiltin writeForeign = writeForeignBuiltin -fromUnisonPair :: RClosure -> (a, b) +fromUnisonPair :: Closure -> (a, b) fromUnisonPair (DataC _ _ [] [x, DataC _ _ [] [y, _]]) = (unwrapForeignClosure x, unwrapForeignClosure y) fromUnisonPair _ = error "fromUnisonPair: invalid closure" toUnisonPair :: - (BuiltinForeign a, BuiltinForeign b) => (a, b) -> RClosure + (BuiltinForeign a, BuiltinForeign b) => (a, b) -> Closure toUnisonPair (x, y) = DataC Ty.pairRef @@ -522,7 +522,7 @@ toUnisonPair (x, y) = un = DataC Ty.unitRef 0 [] [] wr z = Foreign $ wrapBuiltin z -unwrapForeignClosure :: RClosure -> a +unwrapForeignClosure :: Closure -> a unwrapForeignClosure = unwrapForeign . marshalToForeign instance {-# OVERLAPPABLE #-} (BuiltinForeign a, BuiltinForeign b) => ForeignConvention [(a, b)] where diff --git a/unison-runtime/src/Unison/Runtime/Interface.hs b/unison-runtime/src/Unison/Runtime/Interface.hs index 103242c8d4..8c0075ee7a 100644 --- a/unison-runtime/src/Unison/Runtime/Interface.hs +++ b/unison-runtime/src/Unison/Runtime/Interface.hs @@ -48,6 +48,7 @@ import Data.Set as Set ) import Data.Set qualified as Set import Data.Text as Text (isPrefixOf, pack, unpack) +import Data.Void (absurd) import GHC.IO.Exception (IOErrorType (NoSuchThing, OtherError, PermissionDenied), IOException (ioe_description, ioe_type)) import GHC.Stack (callStack) import Network.Simple.TCP (Socket, acceptFork, listen, recv, send) @@ -117,6 +118,7 @@ import Unison.Runtime.MCode.Serialize import Unison.Runtime.Machine ( ActiveThreads, CCache (..), + MCombs, Tracer (..), apply0, baseCCache, @@ -1205,7 +1207,7 @@ runStandalone sc init = -- standalone bytecode. data StoredCache = SCache - (EnumMap Word64 Combs) + (EnumMap Word64 (Combs Void)) (EnumMap Word64 Reference) (EnumMap Word64 Reference) Word64 @@ -1218,7 +1220,7 @@ data StoredCache putStoredCache :: (MonadPut m) => StoredCache -> m () putStoredCache (SCache cs crs trs ftm fty int rtm rty sbs) = do - putEnumMap putNat (putEnumMap putNat (putComb putCombIx)) cs + putEnumMap putNat (putEnumMap putNat (putComb absurd putCombIx)) cs putEnumMap putNat putReference crs putEnumMap putNat putReference trs putNat ftm @@ -1231,7 +1233,7 @@ putStoredCache (SCache cs crs trs ftm fty int rtm rty sbs) = do getStoredCache :: (MonadGet m) => m StoredCache getStoredCache = SCache - <$> getEnumMap getNat (getEnumMap getNat (getComb getCombIx)) + <$> getEnumMap getNat (getEnumMap getNat (getComb getClos getCombIx)) <*> getEnumMap getNat getReference <*> getEnumMap getNat getReference <*> getNat @@ -1240,6 +1242,8 @@ getStoredCache = <*> getMap getReference getNat <*> getMap getReference getNat <*> getMap getReference (fromList <$> getList getReference) + where + getClos = fail "getStoredCache: found unexpected serialized CachedClosure in StoredCache" debugTextFormat :: Bool -> Pretty ColorText -> String debugTextFormat fancy = @@ -1286,7 +1290,7 @@ restoreCache (SCache cs crs trs ftm fty int rtm rty sbs) = (debugTextFormat fancy $ pretty PPE.empty dv) rns = emptyRNs {dnum = refLookup "ty" builtinTypeNumbering} rf k = builtinTermBackref ! k - combs :: EnumMap Word64 RCombs + combs :: EnumMap Word64 MCombs combs = let builtinCombs = mapWithKey (\k v -> emitComb @Symbol rns (rf k) k mempty (0, v)) numberedTermLookup in builtinCombs <> cs @@ -1294,8 +1298,8 @@ restoreCache (SCache cs crs trs ftm fty int rtm rty sbs) = traceNeeded :: Word64 -> - EnumMap Word64 RCombs -> - IO (EnumMap Word64 RCombs) + EnumMap Word64 MCombs -> + IO (EnumMap Word64 MCombs) traceNeeded init src = fmap (`withoutKeys` ks) $ go mempty init where ks = keysSet numberedTermLookup @@ -1306,7 +1310,7 @@ traceNeeded init src = fmap (`withoutKeys` ks) $ go mempty init | otherwise = die $ "traceNeeded: unknown combinator: " ++ show w buildSCache :: - EnumMap Word64 Combs -> + EnumMap Word64 (Combs Void) -> EnumMap Word64 Reference -> EnumMap Word64 Reference -> Word64 -> @@ -1356,5 +1360,5 @@ standalone cc init = <*> readTVarIO (refTy cc) <*> readTVarIO (sandbox cc) where - unTieRCombs :: EnumMap Word64 RCombs -> EnumMap Word64 Combs + unTieRCombs :: EnumMap Word64 MCombs -> EnumMap Word64 (Combs Void) unTieRCombs = fmap . fmap . fmap $ rCombIx diff --git a/unison-runtime/src/Unison/Runtime/MCode.hs b/unison-runtime/src/Unison/Runtime/MCode.hs index 996737446b..98559f8fab 100644 --- a/unison-runtime/src/Unison/Runtime/MCode.hs +++ b/unison-runtime/src/Unison/Runtime/MCode.hs @@ -623,7 +623,7 @@ data GComb clos comb !Int -- Maximum needed boxed frame size !(GSection comb) -- Entry | -- A pre-evaluated comb, typically a pure top-level const - Cached clos + CachedClosure clos deriving stock (Show, Eq, Ord, Functor, Foldable, Traversable) type Combs clos = GCombs clos CombIx @@ -1560,11 +1560,11 @@ demuxArgs as0 = combDeps :: Comb -> [Word64] combDeps (Lam _ _ _ _ s) = sectionDeps s -combDeps (Cached {}) = [] +combDeps (CachedClosure {}) = [] combTypes :: Comb -> [Word64] combTypes (Lam _ _ _ _ s) = sectionTypes s -combTypes (Cached {}) = [] +combTypes (CachedClosure {}) = [] sectionDeps :: Section -> [Word64] sectionDeps (App _ (Env (CIx _ w _)) _) = [w] @@ -1637,7 +1637,7 @@ prettyComb w i = \case . shows [ua, ba] . showString ":\n" . prettySection 2 s - (Cached {}) -> showString "" + (CachedClosure {}) -> showString "" prettySection :: Int -> Section -> ShowS prettySection ind sec = diff --git a/unison-runtime/src/Unison/Runtime/MCode/Serialize.hs b/unison-runtime/src/Unison/Runtime/MCode/Serialize.hs index d64b52065a..a3592f4a4e 100644 --- a/unison-runtime/src/Unison/Runtime/MCode/Serialize.hs +++ b/unison-runtime/src/Unison/Runtime/MCode/Serialize.hs @@ -21,12 +21,28 @@ import Unison.Runtime.MCode hiding (MatchT) import Unison.Runtime.Serialize import Unison.Util.Text qualified as Util.Text -putComb :: (MonadPut m) => (cix -> m ()) -> GComb cix -> m () -putComb putCix (Lam ua ba uf bf body) = - pInt ua *> pInt ba *> pInt uf *> pInt bf *> putSection putCix body +data CombT = LamT | CachedClosureT -getComb :: (MonadGet m) => m cix -> m (GComb cix) -getComb gCix = Lam <$> gInt <*> gInt <*> gInt <*> gInt <*> (getSection gCix) +instance Tag CombT where + tag2word LamT = 0 + tag2word CachedClosureT = 1 + + word2tag 0 = pure LamT + word2tag 1 = pure CachedClosureT + word2tag n = unknownTag "CombT" n + +putComb :: (MonadPut m) => (clos -> m ()) -> (cix -> m ()) -> GComb clos cix -> m () +putComb putClos putCix = \case + (Lam ua ba uf bf body) -> + putTag LamT *> pInt ua *> pInt ba *> pInt uf *> pInt bf *> putSection putCix body + (CachedClosure clos) -> + putTag CachedClosureT *> putClos clos + +getComb :: (MonadGet m) => m clos -> m cix -> m (GComb clos cix) +getComb gClos gCix = + getTag >>= \case + LamT -> Lam <$> gInt <*> gInt <*> gInt <*> gInt <*> getSection gCix + CachedClosureT -> CachedClosure <$> gClos data SectionT = AppT diff --git a/unison-runtime/src/Unison/Runtime/Machine.hs b/unison-runtime/src/Unison/Runtime/Machine.hs index 11e7941b41..581b74f8d9 100644 --- a/unison-runtime/src/Unison/Runtime/Machine.hs +++ b/unison-runtime/src/Unison/Runtime/Machine.hs @@ -64,9 +64,11 @@ import UnliftIO.Concurrent qualified as UnliftIO -- | A ref storing every currently active thread. -- This is helpful for cleaning up orphaned threads when the main process --- completes. We track threads when running in a host process like UCM, --- otherwise we don't bother since forked threads are cleaned up automatically on --- termination. +-- completes. +-- +-- We track threads when running in a host process like UCM, +-- otherwise, in one-off environments 'Nothing' is used and we don't bother tracking forked threads since they'll be +-- cleaned up automatically on process termination. type ActiveThreads = Maybe (IORef (Set ThreadId)) type Tag = Word64 @@ -74,6 +76,18 @@ type Tag = Word64 -- dynamic environment type DEnv = EnumMap Word64 Closure +type MCombs = RCombs Closure + +type MSection = RSection Closure + +type MBranch = RBranch Closure + +type MInstr = RInstr Closure + +type MComb = RComb Closure + +type MRef = RRef Closure + data Tracer = NoTrace | MsgTrace String String String @@ -84,7 +98,7 @@ data CCache = CCache { foreignFuncs :: EnumMap Word64 ForeignFunc, sandboxed :: Bool, tracer :: Bool -> Closure -> Tracer, - combs :: TVar (EnumMap Word64 RCombs), + combs :: TVar (EnumMap Word64 MCombs), combRefs :: TVar (EnumMap Word64 Reference), tagRefs :: TVar (EnumMap Word64 Reference), freshTm :: TVar Word64, @@ -136,7 +150,7 @@ baseCCache sandboxed = do rns = emptyRNs {dnum = refLookup "ty" builtinTypeNumbering} - combs :: EnumMap Word64 RCombs + combs :: EnumMap Word64 MCombs combs = ( mapWithKey (\k v -> let r = builtinTermBackref ! k in emitComb @Symbol rns r k mempty (0, v)) @@ -158,7 +172,7 @@ stk'info s@(BS _ _ sp _) = do prn sp -- Entry point for evaluating a section -eval0 :: CCache -> ActiveThreads -> RSection -> IO () +eval0 :: CCache -> ActiveThreads -> MSection -> IO () eval0 !env !activeThreads !co = do ustk <- alloc bstk <- alloc @@ -168,7 +182,7 @@ eval0 !env !activeThreads !co = do eval env denv activeThreads ustk bstk (k KE) dummyRef co topDEnv :: - EnumMap Word64 RCombs -> + EnumMap Word64 MCombs -> M.Map Reference Word64 -> M.Map Reference Word64 -> (DEnv, K -> K) @@ -270,7 +284,7 @@ exec :: Stack 'BX -> K -> Reference -> - RInstr -> + MInstr -> IO (DEnv, Stack 'UN, Stack 'BX, K) exec !_ !denv !_activeThreads !ustk !bstk !k _ (Info tx) = do info tx ustk @@ -596,7 +610,7 @@ eval :: Stack 'BX -> K -> Reference -> - RSection -> + MSection -> IO () eval !env !denv !activeThreads !ustk !bstk !k r (Match i (TestT df cs)) = do t <- peekOffBi bstk i @@ -694,7 +708,7 @@ enter :: K -> Bool -> Args -> - RComb -> + MComb -> IO () enter !env !denv !activeThreads !ustk !bstk !k !ck !args !rcomb = do ustk <- if ck then ensure ustk uf else pure ustk @@ -732,38 +746,42 @@ apply :: Args -> Closure -> IO () -apply !env !denv !activeThreads !ustk !bstk !k !ck !args (PAp comb useg bseg) = - case unRComb comb of - Lam ua ba uf bf entry - | ck || ua <= uac && ba <= bac -> do - ustk <- ensure ustk uf - bstk <- ensure bstk bf - (ustk, bstk) <- moveArgs ustk bstk args - ustk <- dumpSeg ustk useg A - bstk <- dumpSeg bstk bseg A - ustk <- acceptArgs ustk ua - bstk <- acceptArgs bstk ba - eval env denv activeThreads ustk bstk k (rCombRef comb) entry - | otherwise -> do - (useg, bseg) <- closeArgs C ustk bstk useg bseg args - ustk <- discardFrame =<< frameArgs ustk - bstk <- discardFrame =<< frameArgs bstk +apply !env !denv !activeThreads !ustk !bstk !k !ck !args = \case + (PAp comb useg bseg) -> + case unRComb comb of + CachedClosure clos -> zeroArgClosure clos + Lam ua ba uf bf entry + | ck || ua <= uac && ba <= bac -> do + ustk <- ensure ustk uf + bstk <- ensure bstk bf + (ustk, bstk) <- moveArgs ustk bstk args + ustk <- dumpSeg ustk useg A + bstk <- dumpSeg bstk bseg A + ustk <- acceptArgs ustk ua + bstk <- acceptArgs bstk ba + eval env denv activeThreads ustk bstk k (rCombRef comb) entry + | otherwise -> do + (useg, bseg) <- closeArgs C ustk bstk useg bseg args + ustk <- discardFrame =<< frameArgs ustk + bstk <- discardFrame =<< frameArgs bstk + bstk <- bump bstk + poke bstk $ PAp comb useg bseg + yield env denv activeThreads ustk bstk k + where + uac = asize ustk + ucount args + uscount useg + bac = asize bstk + bcount args + bscount bseg + clo -> zeroArgClosure clo + where + zeroArgClosure clo + | ZArgs <- args, + asize ustk == 0, + asize bstk == 0 = do + ustk <- discardFrame ustk + bstk <- discardFrame bstk bstk <- bump bstk - poke bstk $ PAp comb useg bseg + poke bstk clo yield env denv activeThreads ustk bstk k - where - uac = asize ustk + ucount args + uscount useg - bac = asize bstk + bcount args + bscount bseg -apply !env !denv !activeThreads !ustk !bstk !k !_ !args clo - | ZArgs <- args, - asize ustk == 0, - asize bstk == 0 = do - ustk <- discardFrame ustk - bstk <- discardFrame bstk - bstk <- bump bstk - poke bstk clo - yield env denv activeThreads ustk bstk k - | otherwise = die $ "applying non-function: " ++ show clo + | otherwise = die $ "applying non-function: " ++ show clo {-# INLINE apply #-} jump :: @@ -1845,11 +1863,11 @@ yield !env !denv !activeThreads !ustk !bstk !k = leap denv k {-# INLINE yield #-} selectTextBranch :: - Util.Text.Text -> RSection -> M.Map Util.Text.Text RSection -> RSection + Util.Text.Text -> MSection -> M.Map Util.Text.Text MSection -> MSection selectTextBranch t df cs = M.findWithDefault df t cs {-# INLINE selectTextBranch #-} -selectBranch :: Tag -> RBranch -> RSection +selectBranch :: Tag -> MBranch -> MSection selectBranch t (Test1 u y n) | t == u = y | otherwise = n @@ -1918,7 +1936,7 @@ discardCont denv ustk bstk k p = <&> \(_, denv, ustk, bstk, k) -> (denv, ustk, bstk, k) {-# INLINE discardCont #-} -resolve :: CCache -> DEnv -> Stack 'BX -> RRef -> IO Closure +resolve :: CCache -> DEnv -> Stack 'BX -> MRef -> IO Closure resolve _ _ _ (Env rComb) = pure $ PAp rComb unull bnull resolve _ _ bstk (Stk i) = peekOff bstk i resolve env denv _ (Dyn i) = case EC.lookup i denv of @@ -1933,7 +1951,7 @@ unhandledErr fname env i = where bomb sh = die $ fname ++ ": unhandled ability request: " ++ sh -rCombSection :: EnumMap Word64 RCombs -> CombIx -> RComb +rCombSection :: EnumMap Word64 MCombs -> CombIx -> MComb rCombSection combs cix@(CIx r n i) = case EC.lookup n combs of Just cmbs -> case EC.lookup i cmbs of @@ -1941,7 +1959,7 @@ rCombSection combs cix@(CIx r n i) = Nothing -> error $ "unknown section `" ++ show i ++ "` of combinator `" ++ show n ++ "`. Reference: " ++ show r Nothing -> error $ "unknown combinator `" ++ show n ++ "`. Reference: " ++ show r -resolveSection :: CCache -> Section -> IO RSection +resolveSection :: CCache -> Section -> IO MSection resolveSection cc section = do rcombs <- readTVarIO (combs cc) pure $ rCombSection rcombs <$> section @@ -2118,10 +2136,25 @@ cacheAdd0 ntys0 tml sands cc = atomically $ do let newCombs = resolveCombs (Just oldCombs) . mapFromList $ zipWith combinate [ntm ..] rgs in newCombs <> oldCombs nsn <- updateMap (M.fromList sands) (sandbox cc) + -- Now that the code cache is primed with everything we need, + -- we can pre-evaluate the top-level constants. + preEvalTopLevelConstants cc pure $ int `seq` rtm `seq` nrs `seq` ncs `seq` nsn `seq` () where toAdd = M.fromList tml +preEvalTopLevelConstants :: CCache -> IO () +preEvalTopLevelConstants cc = do + activeThreads <- Just <$> UnliftIO.newIORef mempty + cmbs <- readTVarIO (combs cc) + for (EC.keys cmbs) \w -> do + let hook _ustk bstk = do + clos <- peek bstk + atomically $ do + modifyTVar (combs cc) $ EC.mapInsert w (Cached clos) + apply0 (Just hook) cc activeThreads w + pure () + expandSandbox :: Map Reference (Set Reference) -> [(Reference, SuperGroup Symbol)] -> @@ -2227,7 +2260,7 @@ reflectValue rty = goV | t == floatTag = pure $ ANF.Float (intToDouble v) | otherwise = die . err $ "unboxed data: " <> show (t, v) -reifyValue :: CCache -> ANF.Value -> IO (Either [Reference] RClosure) +reifyValue :: CCache -> ANF.Value -> IO (Either [Reference] Closure) reifyValue cc val = do erc <- atomically $ do @@ -2245,7 +2278,7 @@ reifyValue cc val = do (tyLinks, tmLinks) = valueLinks f val reifyValue0 :: - (EnumMap Word64 RCombs, M.Map Reference Word64, M.Map Reference Word64) -> + (EnumMap Word64 MCombs, M.Map Reference Word64, M.Map Reference Word64) -> ANF.Value -> IO Closure reifyValue0 (combs, rty, rtm) = goV @@ -2257,7 +2290,7 @@ reifyValue0 (combs, rty, rtm) = goV refTm r | Just w <- M.lookup r rtm = pure w | otherwise = die . err $ "unknown term reference: " ++ show r - goIx :: ANF.GroupRef -> IO RComb + goIx :: ANF.GroupRef -> IO MComb goIx (ANF.GR r i) = refTm r <&> \n -> rCombSection combs (CIx r n i) diff --git a/unison-runtime/src/Unison/Runtime/Stack.hs b/unison-runtime/src/Unison/Runtime/Stack.hs index b85707b1b3..e497662f38 100644 --- a/unison-runtime/src/Unison/Runtime/Stack.hs +++ b/unison-runtime/src/Unison/Runtime/Stack.hs @@ -8,9 +8,24 @@ module Unison.Runtime.Stack ( K (..), - GClosure (.., DataC, PApV, CapV), - Closure, - RClosure, + GClosure (..), + Closure + ( .., + DataC, + PApV, + CapV, + PAp, + Enum, + DataU1, + DataU2, + DataB1, + DataB2, + DataUB, + DataG, + Captured, + Foreign, + BlackHole + ), IxClosure, Callback (..), Augment (..), @@ -80,7 +95,7 @@ data K !Int -- pending unboxed args !Int -- pending boxed args !(EnumSet Word64) - !(EnumMap Word64 RClosure) + !(EnumMap Word64 Closure) !K | -- save information about a frame for later resumption Push @@ -88,35 +103,63 @@ data K !Int -- boxed frame size !Int -- pending unboxed args !Int -- pending boxed args - !RComb -- local continuation reference + !(RComb Closure) -- local continuation reference !K deriving (Eq, Ord) -type RClosure = GClosure RComb +newtype Closure + = Closure {unClosure :: (GClosure (RComb Closure))} + deriving stock (Show, Eq, Ord) type IxClosure = GClosure CombIx -type Closure = GClosure RComb - data GClosure comb - = PAp + = GPAp !comb {-# UNPACK #-} !(Seg 'UN) -- unboxed args {- unpack -} !(Seg 'BX) -- boxed args - | Enum !Reference !Word64 - | DataU1 !Reference !Word64 !Int - | DataU2 !Reference !Word64 !Int !Int - | DataB1 !Reference !Word64 !(GClosure comb) - | DataB2 !Reference !Word64 !(GClosure comb) !(GClosure comb) - | DataUB !Reference !Word64 !Int !(GClosure comb) - | DataG !Reference !Word64 !(Seg 'UN) !(Seg 'BX) + | GEnum !Reference !Word64 + | GDataU1 !Reference !Word64 !Int + | GDataU2 !Reference !Word64 !Int !Int + | GDataB1 !Reference !Word64 !(GClosure comb) + | GDataB2 !Reference !Word64 !(GClosure comb) !(GClosure comb) + | GDataUB !Reference !Word64 !Int !(GClosure comb) + | GDataG !Reference !Word64 !(Seg 'UN) !(Seg 'BX) | -- code cont, u/b arg size, u/b data stacks - Captured !K !Int !Int {-# UNPACK #-} !(Seg 'UN) !(Seg 'BX) - | Foreign !Foreign - | BlackHole + GCaptured !K !Int !Int {-# UNPACK #-} !(Seg 'UN) !(Seg 'BX) + | GForeign !Foreign + | GBlackHole deriving stock (Show, Eq, Ord, Functor, Foldable, Traversable) +pattern PAp comb segUn segBx = Closure (GPAp comb segUn segBx) + +pattern Enum r t = Closure (GEnum r t) + +pattern DataU1 r t i = Closure (GDataU1 r t i) + +pattern DataU2 r t i j = Closure (GDataU2 r t i j) + +pattern DataB1 r t x <- Closure (GDataB1 r t (Closure -> x)) + where + DataB1 r t x = Closure (GDataB1 r t (unClosure x)) + +pattern DataB2 r t x y <- Closure (GDataB2 r t (Closure -> x) (Closure -> y)) + where + DataB2 r t x y = Closure (GDataB2 r t (unClosure x) (unClosure y)) + +pattern DataUB r t i y <- Closure (GDataUB r t i (Closure -> y)) + where + DataUB r t i y = Closure (GDataUB r t i (unClosure y)) + +pattern DataG r t us bs = Closure (GDataG r t us bs) + +pattern Captured k ua ba us bs = Closure (GCaptured k ua ba us bs) + +pattern Foreign x = Closure (GForeign x) + +pattern BlackHole = Closure GBlackHole + traceK :: Reference -> K -> [(Reference, Int)] traceK begin = dedup (begin, 1) where @@ -126,15 +169,16 @@ traceK begin = dedup (begin, 1) | otherwise = p : dedup (r, 1) k dedup p _ = [p] -splitData :: RClosure -> Maybe (Reference, Word64, [Int], [RClosure]) -splitData (Enum r t) = Just (r, t, [], []) -splitData (DataU1 r t i) = Just (r, t, [i], []) -splitData (DataU2 r t i j) = Just (r, t, [i, j], []) -splitData (DataB1 r t x) = Just (r, t, [], [x]) -splitData (DataB2 r t x y) = Just (r, t, [], [x, y]) -splitData (DataUB r t i y) = Just (r, t, [i], [y]) -splitData (DataG r t us bs) = Just (r, t, ints us, bsegToList bs) -splitData _ = Nothing +splitData :: Closure -> Maybe (Reference, Word64, [Int], [Closure]) +splitData = \case + (Enum r t) -> Just (r, t, [], []) + (DataU1 r t i) -> Just (r, t, [i], []) + (DataU2 r t i j) -> Just (r, t, [i, j], []) + (DataB1 r t x) -> Just (r, t, [], [x]) + (DataB2 r t x y) -> Just (r, t, [], [x, y]) + (DataUB r t i y) -> Just (r, t, [i], [y]) + (DataG r t us bs) -> Just (r, t, ints us, bsegToList bs) + _ -> Nothing -- | Converts an unboxed segment to a list of integers for a more interchangeable -- representation. The segments are stored in backwards order, so this reverses @@ -153,15 +197,15 @@ useg ws = case L.fromList $ reverse ws of -- | Converts a boxed segment to a list of closures. The segments are stored -- backwards, so this reverses the contents. -bsegToList :: Seg 'BX -> [RClosure] +bsegToList :: Seg 'BX -> [Closure] bsegToList = reverse . L.toList -- | Converts a list of closures back to a boxed segment. Segments are stored -- backwards, so this reverses the contents. -bseg :: [RClosure] -> Seg 'BX +bseg :: [Closure] -> Seg 'BX bseg = L.fromList . reverse -formData :: Reference -> Word64 -> [Int] -> [RClosure] -> RClosure +formData :: Reference -> Word64 -> [Int] -> [Closure] -> Closure formData r t [] [] = Enum r t formData r t [i] [] = DataU1 r t i formData r t [i, j] [] = DataU2 r t i j @@ -178,19 +222,19 @@ frameDataSize = go 0 0 go usz bsz (Mark ua ba _ _ k) = go (usz + ua) (bsz + ba) k go usz bsz (Push uf bf ua ba _ k) = go (usz + uf + ua) (bsz + bf + ba) k -pattern DataC :: Reference -> Word64 -> [Int] -> [RClosure] -> RClosure +pattern DataC :: Reference -> Word64 -> [Int] -> [Closure] -> Closure pattern DataC rf ct us bs <- (splitData -> Just (rf, ct, us, bs)) where DataC rf ct us bs = formData rf ct us bs -pattern PApV :: RComb -> [Int] -> [RClosure] -> RClosure +pattern PApV :: RComb Closure -> [Int] -> [Closure] -> Closure pattern PApV ic us bs <- PAp ic (ints -> us) (bsegToList -> bs) where PApV ic us bs = PAp ic (useg us) (bseg bs) -pattern CapV :: K -> Int -> Int -> [Int] -> [RClosure] -> RClosure +pattern CapV :: K -> Int -> Int -> [Int] -> [Closure] -> Closure pattern CapV k ua ba us bs <- Captured k ua ba (ints -> us) (bsegToList -> bs) where @@ -202,7 +246,7 @@ pattern CapV k ua ba us bs <- {-# COMPLETE DataC, PApV, CapV, Foreign, BlackHole #-} -marshalToForeign :: (HasCallStack) => RClosure -> Foreign +marshalToForeign :: (HasCallStack) => Closure -> Foreign marshalToForeign (Foreign x) = x marshalToForeign c = error $ "marshalToForeign: unhandled closure: " ++ show c @@ -215,7 +259,7 @@ type FP = Int type UA = MutableByteArray (PrimState IO) -type BA = MutableArray (PrimState IO) RClosure +type BA = MutableArray (PrimState IO) Closure words :: Int -> Int words n = n `div` 8 @@ -283,7 +327,7 @@ bargOnto stk sp cop cp0 (Arg2 i j) = do bargOnto stk sp cop cp0 (ArgN v) = do buf <- if overwrite - then newArray sz BlackHole + then newArray sz $ BlackHole else pure cop let loop i | i < 0 = return () @@ -348,8 +392,8 @@ class MEM (b :: Mem) where asize :: Stack b -> SZ instance MEM 'UN where - data Stack 'UN = - -- Note: uap <= ufp <= usp + data Stack 'UN + = -- Note: uap <= ufp <= usp US { uap :: !Int, -- arg pointer ufp :: !Int, -- frame pointer @@ -527,16 +571,16 @@ peekOffBi :: (BuiltinForeign b) => Stack 'BX -> Int -> IO b peekOffBi bstk i = unwrapForeign . marshalToForeign <$> peekOff bstk i {-# INLINE peekOffBi #-} -peekOffS :: Stack 'BX -> Int -> IO (Seq RClosure) +peekOffS :: Stack 'BX -> Int -> IO (Seq Closure) peekOffS bstk i = unwrapForeign . marshalToForeign <$> peekOff bstk i {-# INLINE peekOffS #-} -pokeS :: Stack 'BX -> Seq RClosure -> IO () +pokeS :: Stack 'BX -> Seq Closure -> IO () pokeS bstk s = poke bstk (Foreign $ Wrap Ty.listRef s) {-# INLINE pokeS #-} -pokeOffS :: Stack 'BX -> Int -> Seq RClosure -> IO () +pokeOffS :: Stack 'BX -> Int -> Seq Closure -> IO () pokeOffS bstk i s = pokeOff bstk i (Foreign $ Wrap Ty.listRef s) {-# INLINE pokeOffS #-} @@ -569,10 +613,10 @@ instance MEM 'BX where { bap :: !Int, bfp :: !Int, bsp :: !Int, - bstk :: {-# UNPACK #-} !(MutableArray (PrimState IO) RClosure) + bstk :: {-# UNPACK #-} !(MutableArray (PrimState IO) Closure) } - type Elem 'BX = RClosure - type Seg 'BX = Array RClosure + type Elem 'BX = Closure + type Seg 'BX = Array Closure alloc = BS (-1) (-1) (-1) <$> newArray 512 BlackHole {-# INLINE alloc #-} @@ -711,20 +755,21 @@ uscount seg = words $ sizeofByteArray seg bscount :: Seg 'BX -> Int bscount seg = sizeofArray seg -closureTermRefs :: (Monoid m) => (Reference -> m) -> (RClosure -> m) -closureTermRefs f (PAp (RComb (CIx r _ _) _) _ cs) = - f r <> foldMap (closureTermRefs f) cs -closureTermRefs f (DataB1 _ _ c) = closureTermRefs f c -closureTermRefs f (DataB2 _ _ c1 c2) = - closureTermRefs f c1 <> closureTermRefs f c2 -closureTermRefs f (DataUB _ _ _ c) = - closureTermRefs f c -closureTermRefs f (Captured k _ _ _ cs) = - contTermRefs f k <> foldMap (closureTermRefs f) cs -closureTermRefs f (Foreign fo) - | Just (cs :: Seq RClosure) <- maybeUnwrapForeign Ty.listRef fo = - foldMap (closureTermRefs f) cs -closureTermRefs _ _ = mempty +closureTermRefs :: (Monoid m) => (Reference -> m) -> (Closure -> m) +closureTermRefs f = \case + PAp (RComb (CIx r _ _) _) _ cs -> + f r <> foldMap (closureTermRefs f) cs + (DataB1 _ _ c) -> closureTermRefs f c + (DataB2 _ _ c1 c2) -> + closureTermRefs f c1 <> closureTermRefs f c2 + (DataUB _ _ _ c) -> + closureTermRefs f c + (Captured k _ _ _ cs) -> + contTermRefs f k <> foldMap (closureTermRefs f) cs + (Foreign fo) + | Just (cs :: Seq Closure) <- maybeUnwrapForeign Ty.listRef fo -> + foldMap (closureTermRefs f) cs + _ -> mempty contTermRefs :: (Monoid m) => (Reference -> m) -> K -> m contTermRefs f (Mark _ _ _ m k) = From 2c115215d82a33ab112a9d23425dd8ee32cab195 Mon Sep 17 00:00:00 2001 From: Chris Penner Date: Thu, 12 Sep 2024 14:44:48 -0700 Subject: [PATCH 03/40] Compiling, but still need to actually inline closures --- .../src/Unison/Runtime/Interface.hs | 24 ++++---- unison-runtime/src/Unison/Runtime/MCode.hs | 31 ++++++++--- .../src/Unison/Runtime/MCode/Serialize.hs | 6 +- unison-runtime/src/Unison/Runtime/Machine.hs | 55 +++++++++++-------- .../src/Unison/Runtime/Stack/Serialize.hs | 11 ++++ unison-runtime/unison-runtime.cabal | 1 + 6 files changed, 81 insertions(+), 47 deletions(-) create mode 100644 unison-runtime/src/Unison/Runtime/Stack/Serialize.hs diff --git a/unison-runtime/src/Unison/Runtime/Interface.hs b/unison-runtime/src/Unison/Runtime/Interface.hs index 8c0075ee7a..852b522b8c 100644 --- a/unison-runtime/src/Unison/Runtime/Interface.hs +++ b/unison-runtime/src/Unison/Runtime/Interface.hs @@ -48,7 +48,6 @@ import Data.Set as Set ) import Data.Set qualified as Set import Data.Text as Text (isPrefixOf, pack, unpack) -import Data.Void (absurd) import GHC.IO.Exception (IOErrorType (NoSuchThing, OtherError, PermissionDenied), IOException (ioe_description, ioe_type)) import GHC.Stack (callStack) import Network.Simple.TCP (Socket, acceptFork, listen, recv, send) @@ -102,11 +101,11 @@ import Unison.Runtime.Exception import Unison.Runtime.MCode ( Args (..), CombIx (..), - Combs, + GCombs, GInstr (..), GSection (..), - RCombs, RefNums (..), + absurdCombs, combDeps, combTypes, emitComb, @@ -136,6 +135,7 @@ import Unison.Runtime.Machine import Unison.Runtime.Pattern import Unison.Runtime.Serialize as SER import Unison.Runtime.Stack +import Unison.Runtime.Stack.Serialize (getClosure, putClosure) import Unison.Symbol (Symbol) import Unison.Syntax.HashQualified qualified as HQ (toText) import Unison.Syntax.NamePrinter (prettyHashQualified) @@ -1207,7 +1207,7 @@ runStandalone sc init = -- standalone bytecode. data StoredCache = SCache - (EnumMap Word64 (Combs Void)) + (EnumMap Word64 (GCombs Closure CombIx)) (EnumMap Word64 Reference) (EnumMap Word64 Reference) Word64 @@ -1220,7 +1220,7 @@ data StoredCache putStoredCache :: (MonadPut m) => StoredCache -> m () putStoredCache (SCache cs crs trs ftm fty int rtm rty sbs) = do - putEnumMap putNat (putEnumMap putNat (putComb absurd putCombIx)) cs + putEnumMap putNat (putEnumMap putNat (putComb putClosure putCombIx)) cs putEnumMap putNat putReference crs putEnumMap putNat putReference trs putNat ftm @@ -1233,7 +1233,7 @@ putStoredCache (SCache cs crs trs ftm fty int rtm rty sbs) = do getStoredCache :: (MonadGet m) => m StoredCache getStoredCache = SCache - <$> getEnumMap getNat (getEnumMap getNat (getComb getClos getCombIx)) + <$> getEnumMap getNat (getEnumMap getNat (getComb getClosure getCombIx)) <*> getEnumMap getNat getReference <*> getEnumMap getNat getReference <*> getNat @@ -1242,8 +1242,6 @@ getStoredCache = <*> getMap getReference getNat <*> getMap getReference getNat <*> getMap getReference (fromList <$> getList getReference) - where - getClos = fail "getStoredCache: found unexpected serialized CachedClosure in StoredCache" debugTextFormat :: Bool -> Pretty ColorText -> String debugTextFormat fancy = @@ -1293,7 +1291,7 @@ restoreCache (SCache cs crs trs ftm fty int rtm rty sbs) = combs :: EnumMap Word64 MCombs combs = let builtinCombs = mapWithKey (\k v -> emitComb @Symbol rns (rf k) k mempty (0, v)) numberedTermLookup - in builtinCombs <> cs + in absurdCombs builtinCombs <> cs & resolveCombs Nothing traceNeeded :: @@ -1310,7 +1308,7 @@ traceNeeded init src = fmap (`withoutKeys` ks) $ go mempty init | otherwise = die $ "traceNeeded: unknown combinator: " ++ show w buildSCache :: - EnumMap Word64 (Combs Void) -> + EnumMap Word64 (GCombs Closure CombIx) -> EnumMap Word64 Reference -> EnumMap Word64 Reference -> Word64 -> @@ -1360,5 +1358,7 @@ standalone cc init = <*> readTVarIO (refTy cc) <*> readTVarIO (sandbox cc) where - unTieRCombs :: EnumMap Word64 MCombs -> EnumMap Word64 (Combs Void) - unTieRCombs = fmap . fmap . fmap $ rCombIx + unTieRCombs :: EnumMap Word64 MCombs -> EnumMap Word64 (GCombs Closure CombIx) + unTieRCombs m = + m + & (fmap . fmap . fmap) rCombIx diff --git a/unison-runtime/src/Unison/Runtime/MCode.hs b/unison-runtime/src/Unison/Runtime/MCode.hs index 98559f8fab..1682f2b12a 100644 --- a/unison-runtime/src/Unison/Runtime/MCode.hs +++ b/unison-runtime/src/Unison/Runtime/MCode.hs @@ -42,6 +42,7 @@ module Unison.Runtime.MCode emitCombs, emitComb, resolveCombs, + absurdCombs, emptyRNs, argsToLists, combRef, @@ -53,7 +54,9 @@ module Unison.Runtime.MCode ) where -import Data.Bifunctor (bimap, first) +import Data.Bifoldable (Bifoldable (..)) +import Data.Bifunctor (Bifunctor, bimap, first) +import Data.Bitraversable (Bitraversable (..), bifoldMapDefault, bimapDefault) import Data.Bits (shiftL, shiftR, (.|.)) import Data.Coerce import Data.Functor ((<&>)) @@ -61,7 +64,7 @@ import Data.List (partition) import Data.Map.Strict qualified as M import Data.Primitive.ByteArray import Data.Primitive.PrimArray -import Data.Void (Void) +import Data.Void (Void, absurd) import Data.Word (Word16, Word64) import GHC.Stack (HasCallStack) import Unison.ABT.Normalized (pattern TAbss) @@ -623,10 +626,20 @@ data GComb clos comb !Int -- Maximum needed boxed frame size !(GSection comb) -- Entry | -- A pre-evaluated comb, typically a pure top-level const - CachedClosure clos + CachedClosure !Word64 {- top level comb ix -} !clos deriving stock (Show, Eq, Ord, Functor, Foldable, Traversable) -type Combs clos = GCombs clos CombIx +instance Bifunctor GComb where + bimap = bimapDefault + +instance Bifoldable GComb where + bifoldMap = bifoldMapDefault + +instance Bitraversable GComb where + bitraverse f _ (CachedClosure cix c) = CachedClosure cix <$> f c + bitraverse _ f (Lam u b uf bf s) = Lam u b uf bf <$> traverse f s + +type Combs = GCombs Void CombIx type RCombs clos = GCombs clos (RComb clos) @@ -810,7 +823,7 @@ resolveCombs :: -- TODO: Do we ever actually need to pass this? Maybe (EnumMap Word64 (RCombs clos)) -> -- Combinators which need their knots tied. - EnumMap Word64 (Combs clos) -> + EnumMap Word64 (GCombs clos CombIx) -> EnumMap Word64 (RCombs clos) resolveCombs mayExisting combs = -- Fixed point lookup; @@ -835,6 +848,9 @@ resolveCombs mayExisting combs = ++ "`." in resolved +absurdCombs :: EnumMap Word64 (EnumMap Word64 (GComb Void cix)) -> EnumMap Word64 (GCombs any cix) +absurdCombs = fmap . fmap . first $ absurd + -- Type for aggregating the necessary stack frame size. First field is -- unboxed size, second is boxed. The Applicative instance takes the -- point-wise maximum, so that combining values from different branches @@ -1558,11 +1574,11 @@ demuxArgs as0 = -- TODO: handle ranges (us, bs) -> DArgN (primArrayFromList us) (primArrayFromList bs) -combDeps :: Comb -> [Word64] +combDeps :: GComb any CombIx -> [Word64] combDeps (Lam _ _ _ _ s) = sectionDeps s combDeps (CachedClosure {}) = [] -combTypes :: Comb -> [Word64] +combTypes :: GComb any CombIx -> [Word64] combTypes (Lam _ _ _ _ s) = sectionTypes s combTypes (CachedClosure {}) = [] @@ -1637,7 +1653,6 @@ prettyComb w i = \case . shows [ua, ba] . showString ":\n" . prettySection 2 s - (CachedClosure {}) -> showString "" prettySection :: Int -> Section -> ShowS prettySection ind sec = diff --git a/unison-runtime/src/Unison/Runtime/MCode/Serialize.hs b/unison-runtime/src/Unison/Runtime/MCode/Serialize.hs index a3592f4a4e..5d8e34cc4c 100644 --- a/unison-runtime/src/Unison/Runtime/MCode/Serialize.hs +++ b/unison-runtime/src/Unison/Runtime/MCode/Serialize.hs @@ -35,14 +35,14 @@ putComb :: (MonadPut m) => (clos -> m ()) -> (cix -> m ()) -> GComb clos cix -> putComb putClos putCix = \case (Lam ua ba uf bf body) -> putTag LamT *> pInt ua *> pInt ba *> pInt uf *> pInt bf *> putSection putCix body - (CachedClosure clos) -> - putTag CachedClosureT *> putClos clos + (CachedClosure w clos) -> + putTag CachedClosureT *> pWord w *> putClos clos getComb :: (MonadGet m) => m clos -> m cix -> m (GComb clos cix) getComb gClos gCix = getTag >>= \case LamT -> Lam <$> gInt <*> gInt <*> gInt <*> gInt <*> getSection gCix - CachedClosureT -> CachedClosure <$> gClos + CachedClosureT -> CachedClosure <$> gWord <*> gClos data SectionT = AppT diff --git a/unison-runtime/src/Unison/Runtime/Machine.hs b/unison-runtime/src/Unison/Runtime/Machine.hs index 581b74f8d9..965eccfb85 100644 --- a/unison-runtime/src/Unison/Runtime/Machine.hs +++ b/unison-runtime/src/Unison/Runtime/Machine.hs @@ -22,6 +22,7 @@ import Data.Set qualified as Set import Data.Text qualified as DTx import Data.Text.IO qualified as Tx import Data.Traversable +import Data.Void (absurd) import GHC.Conc as STM (unsafeIOToSTM) import Unison.Builtin.Decls (exceptionRef, ioFailureRef) import Unison.Builtin.Decls qualified as Rf @@ -156,6 +157,7 @@ baseCCache sandboxed = do (\k v -> let r = builtinTermBackref ! k in emitComb @Symbol rns r k mempty (0, v)) numberedTermLookup ) + & absurdCombs & resolveCombs Nothing info :: (Show a) => String -> a -> IO () @@ -749,7 +751,7 @@ apply :: apply !env !denv !activeThreads !ustk !bstk !k !ck !args = \case (PAp comb useg bseg) -> case unRComb comb of - CachedClosure clos -> zeroArgClosure clos + CachedClosure _cix clos -> zeroArgClosure clos Lam ua ba uf bf entry | ck || ua <= uac && ba <= bac -> do ustk <- ensure ustk uf @@ -2117,30 +2119,34 @@ cacheAdd0 :: [(Reference, Set Reference)] -> CCache -> IO () -cacheAdd0 ntys0 tml sands cc = atomically $ do - have <- readTVar (intermed cc) - let new = M.difference toAdd have - sz = fromIntegral $ M.size new - rgs = M.toList new - rs = fst <$> rgs - int <- writeTVar (intermed cc) (have <> new) - rty <- addRefs (freshTy cc) (refTy cc) (tagRefs cc) ntys0 - ntm <- stateTVar (freshTm cc) $ \i -> (i, i + sz) - rtm <- updateMap (M.fromList $ zip rs [ntm ..]) (refTm cc) - -- check for missing references - let rns = RN (refLookup "ty" rty) (refLookup "tm" rtm) - combinate :: Word64 -> (Reference, SuperGroup Symbol) -> (Word64, EnumMap Word64 Comb) - combinate n (r, g) = (n, emitCombs rns r n g) - nrs <- updateMap (mapFromList $ zip [ntm ..] rs) (combRefs cc) - ncs <- modifyMap (combs cc) \oldCombs -> - let newCombs = resolveCombs (Just oldCombs) . mapFromList $ zipWith combinate [ntm ..] rgs - in newCombs <> oldCombs - nsn <- updateMap (M.fromList sands) (sandbox cc) - -- Now that the code cache is primed with everything we need, - -- we can pre-evaluate the top-level constants. +cacheAdd0 ntys0 tml sands cc = do + atomically $ do + have <- readTVar (intermed cc) + let new = M.difference toAdd have + sz = fromIntegral $ M.size new + rgs = M.toList new + rs = fst <$> rgs + int <- writeTVar (intermed cc) (have <> new) + rty <- addRefs (freshTy cc) (refTy cc) (tagRefs cc) ntys0 + ntm <- stateTVar (freshTm cc) $ \i -> (i, i + sz) + rtm <- updateMap (M.fromList $ zip rs [ntm ..]) (refTm cc) + -- check for missing references + let rns = RN (refLookup "ty" rty) (refLookup "tm" rtm) + combinate :: Word64 -> (Reference, SuperGroup Symbol) -> (Word64, EnumMap Word64 Comb) + combinate n (r, g) = (n, emitCombs rns r n g) + nrs <- updateMap (mapFromList $ zip [ntm ..] rs) (combRefs cc) + ncs <- modifyMap (combs cc) \oldCombs -> + let newCombs :: EnumMap Word64 MCombs + newCombs = resolveCombs (Just oldCombs) . absurdCombs . mapFromList $ zipWith combinate [ntm ..] rgs + in newCombs <> oldCombs + nsn <- updateMap (M.fromList sands) (sandbox cc) + -- Now that the code cache is primed with everything we need, + -- we can pre-evaluate the top-level constants. + pure $ int `seq` rtm `seq` nrs `seq` ncs `seq` nsn `seq` () preEvalTopLevelConstants cc - pure $ int `seq` rtm `seq` nrs `seq` ncs `seq` nsn `seq` () where + absurdCombs :: EnumMap Word64 (EnumMap Word64 (GComb Void cix)) -> EnumMap Word64 (GCombs Closure cix) + absurdCombs = fmap . fmap . first $ absurd toAdd = M.fromList tml preEvalTopLevelConstants :: CCache -> IO () @@ -2151,7 +2157,8 @@ preEvalTopLevelConstants cc = do let hook _ustk bstk = do clos <- peek bstk atomically $ do - modifyTVar (combs cc) $ EC.mapInsert w (Cached clos) + -- TODO: Check that it's right to just insert the closure at comb position 0 + modifyTVar (combs cc) $ EC.mapInsert w (EC.mapSingleton 0 $ CachedClosure w clos) apply0 (Just hook) cc activeThreads w pure () diff --git a/unison-runtime/src/Unison/Runtime/Stack/Serialize.hs b/unison-runtime/src/Unison/Runtime/Stack/Serialize.hs new file mode 100644 index 0000000000..cdf6ce78a5 --- /dev/null +++ b/unison-runtime/src/Unison/Runtime/Stack/Serialize.hs @@ -0,0 +1,11 @@ +module Unison.Runtime.Stack.Serialize (putClosure, getClosure) where + +import Data.Bytes.Get +import Data.Bytes.Put +import Unison.Runtime.Stack (Closure) + +putClosure :: (MonadPut m) => Closure -> m () +putClosure = error "putClosure not implemented" + +getClosure :: (MonadGet m) => m Closure +getClosure = error "getClosure not implemented" diff --git a/unison-runtime/unison-runtime.cabal b/unison-runtime/unison-runtime.cabal index ea54c20b6a..ed7b8688db 100644 --- a/unison-runtime/unison-runtime.cabal +++ b/unison-runtime/unison-runtime.cabal @@ -49,6 +49,7 @@ library Unison.Runtime.Serialize Unison.Runtime.SparseVector Unison.Runtime.Stack + Unison.Runtime.Stack.Serialize Unison.Runtime.Vector hs-source-dirs: src From 42405173a6fec503aa25431695b59b07f34af608 Mon Sep 17 00:00:00 2001 From: Chris Penner Date: Thu, 12 Sep 2024 15:10:00 -0700 Subject: [PATCH 04/40] Attempt to pre-eval --- .../src/Unison/Runtime/Interface.hs | 6 +--- unison-runtime/src/Unison/Runtime/MCode.hs | 5 ++- unison-runtime/src/Unison/Runtime/Machine.hs | 31 ++++++++++++++----- 3 files changed, 28 insertions(+), 14 deletions(-) diff --git a/unison-runtime/src/Unison/Runtime/Interface.hs b/unison-runtime/src/Unison/Runtime/Interface.hs index 852b522b8c..454a9576c2 100644 --- a/unison-runtime/src/Unison/Runtime/Interface.hs +++ b/unison-runtime/src/Unison/Runtime/Interface.hs @@ -112,6 +112,7 @@ import Unison.Runtime.MCode emptyRNs, rCombIx, resolveCombs, + unTieRCombs, ) import Unison.Runtime.MCode.Serialize import Unison.Runtime.Machine @@ -1357,8 +1358,3 @@ standalone cc init = <*> readTVarIO (refTm cc) <*> readTVarIO (refTy cc) <*> readTVarIO (sandbox cc) - where - unTieRCombs :: EnumMap Word64 MCombs -> EnumMap Word64 (GCombs Closure CombIx) - unTieRCombs m = - m - & (fmap . fmap . fmap) rCombIx diff --git a/unison-runtime/src/Unison/Runtime/MCode.hs b/unison-runtime/src/Unison/Runtime/MCode.hs index 1682f2b12a..563ed6a538 100644 --- a/unison-runtime/src/Unison/Runtime/MCode.hs +++ b/unison-runtime/src/Unison/Runtime/MCode.hs @@ -42,6 +42,7 @@ module Unison.Runtime.MCode emitCombs, emitComb, resolveCombs, + unTieRCombs, absurdCombs, emptyRNs, argsToLists, @@ -820,7 +821,6 @@ emitCombs rns grpr grpn (Rec grp ent) = -- tying the knot recursively when necessary. resolveCombs :: -- Existing in-scope combs that might be referenced - -- TODO: Do we ever actually need to pass this? Maybe (EnumMap Word64 (RCombs clos)) -> -- Combinators which need their knots tied. EnumMap Word64 (GCombs clos CombIx) -> @@ -848,6 +848,9 @@ resolveCombs mayExisting combs = ++ "`." in resolved +unTieRCombs :: EnumMap Word64 (RCombs clos) -> EnumMap Word64 (GCombs clos CombIx) +unTieRCombs = (fmap . fmap . fmap) rCombIx + absurdCombs :: EnumMap Word64 (EnumMap Word64 (GComb Void cix)) -> EnumMap Word64 (GCombs any cix) absurdCombs = fmap . fmap . first $ absurd diff --git a/unison-runtime/src/Unison/Runtime/Machine.hs b/unison-runtime/src/Unison/Runtime/Machine.hs index 965eccfb85..0a88693390 100644 --- a/unison-runtime/src/Unison/Runtime/Machine.hs +++ b/unison-runtime/src/Unison/Runtime/Machine.hs @@ -22,7 +22,6 @@ import Data.Set qualified as Set import Data.Text qualified as DTx import Data.Text.IO qualified as Tx import Data.Traversable -import Data.Void (absurd) import GHC.Conc as STM (unsafeIOToSTM) import Unison.Builtin.Decls (exceptionRef, ioFailureRef) import Unison.Builtin.Decls qualified as Rf @@ -2143,24 +2142,40 @@ cacheAdd0 ntys0 tml sands cc = do -- Now that the code cache is primed with everything we need, -- we can pre-evaluate the top-level constants. pure $ int `seq` rtm `seq` nrs `seq` ncs `seq` nsn `seq` () - preEvalTopLevelConstants cc + preEvalTopLevelConstants cacheableRefs cc where - absurdCombs :: EnumMap Word64 (EnumMap Word64 (GComb Void cix)) -> EnumMap Word64 (GCombs Closure cix) - absurdCombs = fmap . fmap . first $ absurd toAdd = M.fromList tml -preEvalTopLevelConstants :: CCache -> IO () -preEvalTopLevelConstants cc = do +preEvalTopLevelConstants :: Set Reference -> CCache -> IO () +preEvalTopLevelConstants cacheableRefs cc = do activeThreads <- Just <$> UnliftIO.newIORef mempty cmbs <- readTVarIO (combs cc) - for (EC.keys cmbs) \w -> do + for_ (EC.keys cmbs) \w -> do let hook _ustk bstk = do clos <- peek bstk atomically $ do -- TODO: Check that it's right to just insert the closure at comb position 0 modifyTVar (combs cc) $ EC.mapInsert w (EC.mapSingleton 0 $ CachedClosure w clos) apply0 (Just hook) cc activeThreads w - pure () + atomically $ modifyTVar (combs cc) reTieCombs + where + reTieCombs :: EnumMap Word64 (RCombs Closure) -> EnumMap Word64 (RCombs Closure) + reTieCombs combs = + combs + & (fmap . fmap . fmap) \case + -- For each combinator ref in all the source code, if it's in the set of pre-evaluated refs, + -- replace the combinator in the source with the pre-evaluated closure rather than the cyclic RComb. + rComb@(RComb cix@(CIx ref w i) _) + | Set.member ref cacheableRefs, + Just cachedClos <- + ( EC.lookup w combs + >>= EC.lookup i + ) -> do RComb cix cachedClos + | otherwise -> rComb + +-- unTieRCombs combs +-- & (fmap . fmap) _ +-- & resolveCombs Nothing expandSandbox :: Map Reference (Set Reference) -> From eefff5b04e20385badd9232a885bf651a469fb45 Mon Sep 17 00:00:00 2001 From: Chris Penner Date: Thu, 12 Sep 2024 15:42:21 -0700 Subject: [PATCH 05/40] Edit CodeLookup --- .../src/Unison/Codebase/CodeLookup.hs | 15 +++++++--- .../src/Unison/Runtime/Interface.hs | 7 +++-- unison-runtime/src/Unison/Runtime/Machine.hs | 28 +++++++++++++++---- 3 files changed, 39 insertions(+), 11 deletions(-) diff --git a/parser-typechecker/src/Unison/Codebase/CodeLookup.hs b/parser-typechecker/src/Unison/Codebase/CodeLookup.hs index aad2794519..ba03109760 100644 --- a/parser-typechecker/src/Unison/Codebase/CodeLookup.hs +++ b/parser-typechecker/src/Unison/Codebase/CodeLookup.hs @@ -1,5 +1,6 @@ module Unison.Codebase.CodeLookup where +import Control.Arrow ((***)) import Control.Monad.Morph (MFunctor (..)) import Data.Set qualified as Set import Unison.DataDeclaration (Decl) @@ -8,38 +9,44 @@ import Unison.Prelude import Unison.Reference qualified as Reference import Unison.Term (Term) import Unison.Term qualified as Term +import Unison.Type (Type) import Unison.Util.Defns (Defns (..)) import Unison.Util.Set qualified as Set import Unison.Var (Var) data CodeLookup v m a = CodeLookup { getTerm :: Reference.Id -> m (Maybe (Term v a)), + getTermAndType :: Reference.Id -> m (Maybe (Term v a, Type v a)), getTypeDeclaration :: Reference.Id -> m (Maybe (Decl v a)) } instance MFunctor (CodeLookup v) where - hoist f (CodeLookup tm tp) = CodeLookup (f . tm) (f . tp) + hoist f (CodeLookup tm tmTyp tp) = CodeLookup (f . tm) (f . tmTyp) (f . tp) instance (Ord v, Functor m) => Functor (CodeLookup v m) where - fmap f cl = CodeLookup tm ty + fmap f cl = CodeLookup tm tmTyp ty where tm id = fmap (Term.amap f) <$> getTerm cl id ty id = fmap md <$> getTypeDeclaration cl id + tmTyp id = fmap (Term.amap f *** fmap f) <$> getTermAndType cl id md (Left e) = Left (f <$> e) md (Right d) = Right (f <$> d) instance (Monad m) => Semigroup (CodeLookup v m a) where - c1 <> c2 = CodeLookup tm ty + c1 <> c2 = CodeLookup tm tmTyp ty where tm id = do o <- getTerm c1 id case o of Nothing -> getTerm c2 id; Just _ -> pure o + tmTyp id = do + o <- getTermAndType c1 id + case o of Nothing -> getTermAndType c2 id; Just _ -> pure o ty id = do o <- getTypeDeclaration c1 id case o of Nothing -> getTypeDeclaration c2 id; Just _ -> pure o instance (Monad m) => Monoid (CodeLookup v m a) where - mempty = CodeLookup (const $ pure Nothing) (const $ pure Nothing) + mempty = CodeLookup (const $ pure Nothing) (const $ pure Nothing) (const $ pure Nothing) -- todo: can this be implemented in terms of TransitiveClosure.transitiveClosure? -- todo: add some tests on this guy? diff --git a/unison-runtime/src/Unison/Runtime/Interface.hs b/unison-runtime/src/Unison/Runtime/Interface.hs index 454a9576c2..fcfe8bbc44 100644 --- a/unison-runtime/src/Unison/Runtime/Interface.hs +++ b/unison-runtime/src/Unison/Runtime/Interface.hs @@ -118,6 +118,7 @@ import Unison.Runtime.MCode.Serialize import Unison.Runtime.Machine ( ActiveThreads, CCache (..), + Cacheability, MCombs, Tracer (..), apply0, @@ -400,7 +401,7 @@ loadCode :: PrettyPrintEnv -> EvalCtx -> [Reference] -> - IO (EvalCtx, [(Reference, SuperGroup Symbol)]) + IO (EvalCtx, [(Reference, SuperGroup Symbol, Cacheability)]) loadCode cl ppe ctx tmrs = do igs <- readTVarIO (intermed $ ccache ctx) q <- @@ -446,7 +447,8 @@ loadDeps cl ppe ctx tyrs tmrs = do ctx <- foldM (uncurry . allocType) ctx $ Prelude.filter p tyrs let tyAdd = Set.fromList $ fst <$> tyrs out@(_, rgrp) <- loadCode cl ppe ctx tmrs - out <$ cacheAdd0 tyAdd rgrp (expandSandbox sand rgrp) cc + let superGroups = rgrp <&> \(r, sg, _) -> (r, sg) + out <$ cacheAdd0 tyAdd rgrp (expandSandbox sand superGroups) cc compileValue :: Reference -> [(Reference, SuperGroup Symbol)] -> Value compileValue base = @@ -786,6 +788,7 @@ prepareEvaluation :: EvalCtx -> IO (EvalCtx, [(Reference, SuperGroup Symbol)], Reference) prepareEvaluation ppe tm ctx = do + -- TODO: Check whether we need to set cacheability here, I think probably not? missing <- cacheAdd rgrp (ccache ctx') when (not . null $ missing) . fail $ reportBug "E029347" $ diff --git a/unison-runtime/src/Unison/Runtime/Machine.hs b/unison-runtime/src/Unison/Runtime/Machine.hs index 0a88693390..caa1b251aa 100644 --- a/unison-runtime/src/Unison/Runtime/Machine.hs +++ b/unison-runtime/src/Unison/Runtime/Machine.hs @@ -12,6 +12,7 @@ module Unison.Runtime.Machine where import Control.Concurrent (ThreadId) import Control.Concurrent.STM as STM import Control.Exception +import Control.Lens import Data.Bits import Data.Map.Strict qualified as M import Data.Ord (comparing) @@ -88,6 +89,11 @@ type MComb = RComb Closure type MRef = RRef Closure +-- | Whether the evaluation of a given definition is cacheable or not. +-- i.e. it's a top-level pure value. +data Cacheability = Cacheable | Uncacheable + deriving stock (Eq, Show) + data Tracer = NoTrace | MsgTrace String String String @@ -2114,11 +2120,21 @@ evaluateSTM x = unsafeIOToSTM (evaluate x) cacheAdd0 :: S.Set Reference -> - [(Reference, SuperGroup Symbol)] -> + [(Reference, SuperGroup Symbol, Cacheability)] -> [(Reference, Set Reference)] -> CCache -> IO () -cacheAdd0 ntys0 tml sands cc = do +cacheAdd0 ntys0 termSuperGroups sands cc = do + let cacheableRefs = + termSuperGroups + & mapMaybe + ( \case + (ref, _gr, Cacheable) -> Just ref + (_ref, _gr, Uncacheable) -> Nothing + ) + & Set.fromList + let toAdd = M.fromList (termSuperGroups <&> \(r, g, _) -> (r, g)) + atomically $ do have <- readTVar (intermed cc) let new = M.difference toAdd have @@ -2143,8 +2159,6 @@ cacheAdd0 ntys0 tml sands cc = do -- we can pre-evaluate the top-level constants. pure $ int `seq` rtm `seq` nrs `seq` ncs `seq` nsn `seq` () preEvalTopLevelConstants cacheableRefs cc - where - toAdd = M.fromList tml preEvalTopLevelConstants :: Set Reference -> CCache -> IO () preEvalTopLevelConstants cacheableRefs cc = do @@ -2212,8 +2226,12 @@ cacheAdd l cc = do | otherwise = Const (mempty, mempty) (missing, tys) = getConst $ (foldMap . foldMap) (foldGroupLinks f) l l' = filter (\(r, _) -> M.notMember r rtm) l + -- Terms added via cacheAdd will have already been eval'd and cached if possible when + -- they were originally loaded, so we + -- don't need to re-check for cacheability here as part of a dynamic cache add. + l'' = l' <&> (\(r, g) -> (r, g, Uncacheable)) if S.null missing - then [] <$ cacheAdd0 tys l' (expandSandbox sand l') cc + then [] <$ cacheAdd0 tys l'' (expandSandbox sand l') cc else pure $ S.toList missing reflectValue :: EnumMap Word64 Reference -> Closure -> IO ANF.Value From 4b2c49086aa3039cad74e04db3a4aeba53cf3d44 Mon Sep 17 00:00:00 2001 From: Chris Penner Date: Fri, 13 Sep 2024 11:13:12 -0700 Subject: [PATCH 06/40] Compiling somehow --- parser-typechecker/src/Unison/Builtin.hs | 2 +- .../src/Unison/Codebase/CodeLookup.hs | 9 +++-- .../src/Unison/Codebase/CodeLookup/Util.hs | 11 +++--- unison-runtime/src/Unison/Codebase/Execute.hs | 6 +++- .../src/Unison/Runtime/Interface.hs | 36 ++++++++++++++++--- 5 files changed, 49 insertions(+), 15 deletions(-) diff --git a/parser-typechecker/src/Unison/Builtin.hs b/parser-typechecker/src/Unison/Builtin.hs index 1a9477fa63..15934d4895 100644 --- a/parser-typechecker/src/Unison/Builtin.hs +++ b/parser-typechecker/src/Unison/Builtin.hs @@ -103,7 +103,7 @@ builtinEffectDecls :: [(Symbol, (R.Id, EffectDeclaration))] builtinEffectDecls = [(v, (r, Intrinsic <$ d)) | (v, r, d) <- DD.builtinEffectDecls] codeLookup :: (Applicative m) => CodeLookup Symbol m Ann -codeLookup = CodeLookup (const $ pure Nothing) $ \r -> +codeLookup = CodeLookup (const $ pure Nothing) (const $ pure Nothing) $ \r -> pure $ lookup r [(r, Right x) | (r, x) <- snd <$> builtinDataDecls] <|> lookup r [(r, Left x) | (r, x) <- snd <$> builtinEffectDecls] diff --git a/parser-typechecker/src/Unison/Codebase/CodeLookup.hs b/parser-typechecker/src/Unison/Codebase/CodeLookup.hs index ba03109760..b27a2e7948 100644 --- a/parser-typechecker/src/Unison/Codebase/CodeLookup.hs +++ b/parser-typechecker/src/Unison/Codebase/CodeLookup.hs @@ -1,6 +1,5 @@ module Unison.Codebase.CodeLookup where -import Control.Arrow ((***)) import Control.Monad.Morph (MFunctor (..)) import Data.Set qualified as Set import Unison.DataDeclaration (Decl) @@ -16,7 +15,7 @@ import Unison.Var (Var) data CodeLookup v m a = CodeLookup { getTerm :: Reference.Id -> m (Maybe (Term v a)), - getTermAndType :: Reference.Id -> m (Maybe (Term v a, Type v a)), + getTypeOfTerm :: Reference.Id -> m (Maybe (Type v a)), getTypeDeclaration :: Reference.Id -> m (Maybe (Decl v a)) } @@ -28,7 +27,7 @@ instance (Ord v, Functor m) => Functor (CodeLookup v m) where where tm id = fmap (Term.amap f) <$> getTerm cl id ty id = fmap md <$> getTypeDeclaration cl id - tmTyp id = fmap (Term.amap f *** fmap f) <$> getTermAndType cl id + tmTyp id = (fmap . fmap) f <$> getTypeOfTerm cl id md (Left e) = Left (f <$> e) md (Right d) = Right (f <$> d) @@ -39,8 +38,8 @@ instance (Monad m) => Semigroup (CodeLookup v m a) where o <- getTerm c1 id case o of Nothing -> getTerm c2 id; Just _ -> pure o tmTyp id = do - o <- getTermAndType c1 id - case o of Nothing -> getTermAndType c2 id; Just _ -> pure o + o <- getTypeOfTerm c1 id + case o of Nothing -> getTypeOfTerm c2 id; Just _ -> pure o ty id = do o <- getTypeDeclaration c1 id case o of Nothing -> getTypeDeclaration c2 id; Just _ -> pure o diff --git a/parser-typechecker/src/Unison/Codebase/CodeLookup/Util.hs b/parser-typechecker/src/Unison/Codebase/CodeLookup/Util.hs index 82c323fe78..708891159e 100644 --- a/parser-typechecker/src/Unison/Codebase/CodeLookup/Util.hs +++ b/parser-typechecker/src/Unison/Codebase/CodeLookup/Util.hs @@ -8,15 +8,18 @@ import Unison.DataDeclaration qualified as DataDeclaration import Unison.Prelude import Unison.Reference qualified as Reference import Unison.Term qualified as Term +import Unison.Type qualified as Type import Unison.UnisonFile qualified as UF import Unison.UnisonFile.Type (TypecheckedUnisonFile) import Unison.Var (Var) fromTypecheckedUnisonFile :: forall m v a. (Var v, Monad m) => TypecheckedUnisonFile v a -> CodeLookup v m a -fromTypecheckedUnisonFile tuf = CodeLookup tm ty +fromTypecheckedUnisonFile tuf = CodeLookup tm tmTyp ty where tm :: Reference.Id -> m (Maybe (Term.Term v a)) - tm id = pure $ Map.lookup id termMap + tm id = pure . fmap fst $ Map.lookup id termMap + tmTyp :: Reference.Id -> m (Maybe (Type.Type v a)) + tmTyp id = pure . fmap snd $ Map.lookup id termMap ty :: Reference.Id -> m (Maybe (DataDeclaration.Decl v a)) ty id = pure $ Map.lookup id dataDeclMap <|> Map.lookup id effectDeclMap dataDeclMap = @@ -31,5 +34,5 @@ fromTypecheckedUnisonFile tuf = CodeLookup tm ty | (_, (Reference.DerivedId id, ad)) <- Map.toList (UF.effectDeclarations' tuf) ] - termMap :: Map Reference.Id (Term.Term v a) - termMap = Map.fromList [(id, tm) | (_a, id, _wk, tm, _tp) <- toList $ UF.hashTermsId tuf] + termMap :: Map Reference.Id (Term.Term v a, Type.Type v a) + termMap = Map.fromList [(id, (tm, typ)) | (_a, id, _wk, tm, typ) <- toList $ UF.hashTermsId tuf] diff --git a/unison-runtime/src/Unison/Codebase/Execute.hs b/unison-runtime/src/Unison/Codebase/Execute.hs index 71f345220c..22b54c6f7d 100644 --- a/unison-runtime/src/Unison/Codebase/Execute.hs +++ b/unison-runtime/src/Unison/Codebase/Execute.hs @@ -68,6 +68,10 @@ execute codebase runtime mainPath = codebaseToCodeLookup :: (MonadIO m) => Codebase m Symbol Parser.Ann -> CL.CodeLookup Symbol m Parser.Ann codebaseToCodeLookup c = - CL.CodeLookup (Codebase.runTransaction c . getTerm c) (Codebase.runTransaction c . getTypeDeclaration c) + CL.CodeLookup goGetTerm goGetTypeOfTerm goGetTypeDecl <> Builtin.codeLookup <> IOSource.codeLookupM + where + goGetTerm = (Codebase.runTransaction c . getTerm c) + goGetTypeOfTerm = (Codebase.runTransaction c . getTypeOfTermImpl c) + goGetTypeDecl = (Codebase.runTransaction c . getTypeDeclaration c) diff --git a/unison-runtime/src/Unison/Runtime/Interface.hs b/unison-runtime/src/Unison/Runtime/Interface.hs index fcfe8bbc44..ef896fbde5 100644 --- a/unison-runtime/src/Unison/Runtime/Interface.hs +++ b/unison-runtime/src/Unison/Runtime/Interface.hs @@ -71,6 +71,7 @@ import System.Process waitForProcess, withCreateProcess, ) +import Unison.ABT qualified as ABT import Unison.Builtin.Decls qualified as RF import Unison.Codebase.CodeLookup (CodeLookup (..)) import Unison.Codebase.MainTerm (builtinIOTestTypes, builtinMain) @@ -118,7 +119,7 @@ import Unison.Runtime.MCode.Serialize import Unison.Runtime.Machine ( ActiveThreads, CCache (..), - Cacheability, + Cacheability (..), MCombs, Tracer (..), apply0, @@ -143,6 +144,7 @@ import Unison.Syntax.HashQualified qualified as HQ (toText) import Unison.Syntax.NamePrinter (prettyHashQualified) import Unison.Syntax.TermPrinter import Unison.Term qualified as Tm +import Unison.Type qualified as Type import Unison.Util.EnumContainers as EC import Unison.Util.Monoid (foldMapM) import Unison.Util.Pretty as P @@ -151,6 +153,8 @@ import UnliftIO.Concurrent qualified as UnliftIO type Term v = Tm.Term v () +type Type v = Type.Type v () + data Remapping = Remap { remap :: Map.Map Reference Reference, backmap :: Map.Map Reference Reference @@ -196,6 +200,17 @@ resolveTermRef cl r@(RF.DerivedId i) = Nothing -> die $ "Unknown term reference: " ++ show r Just tm -> pure tm +resolveTermRefType :: + CodeLookup Symbol IO () -> + RF.Reference -> + IO (Type Symbol) +resolveTermRefType _ b@(RF.Builtin _) = + die $ "Unknown builtin term reference: " ++ show b +resolveTermRefType cl r@(RF.DerivedId i) = + getTypeOfTerm cl i >>= \case + Nothing -> die $ "Unknown term reference: " ++ show r + Just typ -> pure typ + allocType :: EvalCtx -> RF.Reference -> @@ -401,7 +416,7 @@ loadCode :: PrettyPrintEnv -> EvalCtx -> [Reference] -> - IO (EvalCtx, [(Reference, SuperGroup Symbol, Cacheability)]) + IO (EvalCtx, [(Reference, SuperGroup Symbol)]) loadCode cl ppe ctx tmrs = do igs <- readTVarIO (intermed $ ccache ctx) q <- @@ -447,8 +462,21 @@ loadDeps cl ppe ctx tyrs tmrs = do ctx <- foldM (uncurry . allocType) ctx $ Prelude.filter p tyrs let tyAdd = Set.fromList $ fst <$> tyrs out@(_, rgrp) <- loadCode cl ppe ctx tmrs - let superGroups = rgrp <&> \(r, sg, _) -> (r, sg) - out <$ cacheAdd0 tyAdd rgrp (expandSandbox sand superGroups) cc + crgrp <- traverse checkCacheability rgrp + out <$ cacheAdd0 tyAdd crgrp (expandSandbox sand rgrp) cc + where + checkCacheability :: (Reference, sprgrp) -> IO (Reference, sprgrp, Cacheability) + checkCacheability (r, sg) = do + typ <- resolveTermRefType cl r + if ABT.cata hasArrows typ + then pure (r, sg, Uncacheable) + else pure (r, sg, Cacheable) + hasArrows :: a -> ABT.ABT Type.F v Bool -> Bool + hasArrows _ = \case + ABT.Tm f -> case f of + Type.Arrow _ _ -> True + other -> or other + t -> or t compileValue :: Reference -> [(Reference, SuperGroup Symbol)] -> Value compileValue base = From d5a802ba975e61629127caae4f25854f7d2adf61 Mon Sep 17 00:00:00 2001 From: Chris Penner Date: Fri, 13 Sep 2024 13:22:19 -0700 Subject: [PATCH 07/40] Check types of refs right before passing to CCache --- stack.yaml | 2 +- unison-runtime/src/Unison/Runtime/ANF.hs | 35 +++++++++------- .../src/Unison/Runtime/ANF/Serialize.hs | 16 +++++++- .../src/Unison/Runtime/Interface.hs | 40 +++++++++---------- unison-runtime/src/Unison/Runtime/MCode.hs | 2 +- unison-runtime/src/Unison/Runtime/Machine.hs | 15 +++---- 6 files changed, 61 insertions(+), 49 deletions(-) diff --git a/stack.yaml b/stack.yaml index 6a31222d65..c75e0c1638 100644 --- a/stack.yaml +++ b/stack.yaml @@ -73,7 +73,7 @@ allow-newer-deps: ghc-options: # All packages - "$locals": -Wall -Werror -Wno-name-shadowing -Wno-missing-pattern-synonym-signatures -fprint-expanded-synonyms -fwrite-ide-info -Wunused-packages #-freverse-errors + "$locals": -Wall -Werror -Wno-name-shadowing -Wno-missing-pattern-synonym-signatures -fprint-expanded-synonyms -fwrite-ide-info -Wunused-packages -debug #-freverse-errors # See https://github.com/haskell/haskell-language-server/issues/208 "$everything": -haddock diff --git a/unison-runtime/src/Unison/Runtime/ANF.hs b/unison-runtime/src/Unison/Runtime/ANF.hs index 0c2fa20ff8..6d219a6c25 100644 --- a/unison-runtime/src/Unison/Runtime/ANF.hs +++ b/unison-runtime/src/Unison/Runtime/ANF.hs @@ -36,6 +36,7 @@ module Unison.Runtime.ANF Direction (..), SuperNormal (..), SuperGroup (..), + Cacheability (..), POp (..), FOp, close, @@ -80,7 +81,7 @@ module Unison.Runtime.ANF where import Control.Exception (throw) -import Control.Lens (snoc, unsnoc) +import Control.Lens (over, snoc, traversed, unsnoc, _2) import Control.Monad.Reader (ReaderT (..), ask, local) import Control.Monad.State (MonadState (..), State, gets, modify, runState) import Data.Bifoldable (Bifoldable (..)) @@ -402,7 +403,7 @@ freshFloat avoid (Var.freshIn avoid -> v0) = groupFloater :: (Var v, Monoid a) => (Term v a -> FloatM v a (Term v a)) -> - [(v, Term v a)] -> + [(v, Term v a, Cacheability)] -> FloatM v a (Map v v) groupFloater rec vbs = do cvs <- gets (\(vs, _, _) -> vs) @@ -556,8 +557,8 @@ floatGroup :: (Var v) => (Monoid a) => Map v Reference -> - [(v, Term v a)] -> - ([(v, Id)], [(Reference, Term v a)], [(Reference, Term v a)]) + [(v, Term v a, Cacheability)] -> + ([(v, Id)], [(Reference, Term v a, Cacheability)], [(Reference, Term v a)]) floatGroup orig grp = case runState go0 (Set.empty, [], []) of (_, st) -> case postFloat orig st of (_, subvs, tops, dcmp) -> (subvs, tops, dcmp) @@ -601,9 +602,9 @@ lamLiftGroup :: (Var v) => (Monoid a) => Map v Reference -> - [(v, Term v a)] -> - ([(v, Id)], [(Reference, Term v a)], [(Reference, Term v a)]) -lamLiftGroup orig gr = floatGroup orig . (fmap . fmap) (close keep) $ gr + [(v, Term v a, Cacheability)] -> + ([(v, Id)], [(Reference, Term v a, Cacheability)], [(Reference, Term v a)]) +lamLiftGroup orig gr = floatGroup orig . (over (traversed . _2)) (close keep) $ gr where keep = Set.fromList $ map fst gr @@ -1470,9 +1471,15 @@ type DNormal v = Directed () (ANormal v) data SuperNormal v = Lambda {conventions :: [Mem], bound :: ANormal v} deriving (Show, Eq) +-- | Whether the evaluation of a given definition is cacheable or not. +-- i.e. it's a top-level pure value. +data Cacheability = Cacheable | Uncacheable + deriving stock (Eq, Show) + data SuperGroup v = Rec { group :: [(v, SuperNormal v)], - entry :: SuperNormal v + entry :: SuperNormal v, + cacheable :: Cacheability } deriving (Show) @@ -1496,7 +1503,7 @@ equivocate :: SuperGroup v -> SuperGroup v -> Either (SGEqv v) () -equivocate g0@(Rec bs0 e0) g1@(Rec bs1 e1) +equivocate g0@(Rec bs0 e0 _c0) g1@(Rec bs1 e1 _c1) | length bs0 == length bs1 = traverse_ eqvSN (zip ns0 ns1) *> eqvSN (e0, e1) | otherwise = Left $ NumDefns g0 g1 @@ -1586,8 +1593,8 @@ bindDirection = traverse (const binder) record :: (Var v) => (v, SuperNormal v) -> ANFM v () record p = modify $ \(fr, bnd, to) -> (fr, bnd, p : to) -superNormalize :: (Var v) => Term v a -> SuperGroup v -superNormalize tm = Rec l c +superNormalize :: (Var v) => Cacheability -> Term v a -> SuperGroup v +superNormalize cacheable tm = Rec l c cacheable where (bs, e) | LetRecNamed' bs e <- tm = (bs, e) @@ -2004,8 +2011,8 @@ traverseGroupLinks :: (Bool -> Reference -> f Reference) -> SuperGroup v -> f (SuperGroup v) -traverseGroupLinks f (Rec bs e) = - Rec <$> (traverse . traverse) (normalLinks f) bs <*> normalLinks f e +traverseGroupLinks f (Rec bs e cacheable) = + Rec <$> (traverse . traverse) (normalLinks f) bs <*> normalLinks f e <*> pure cacheable foldGroupLinks :: (Monoid r, Var v) => @@ -2149,7 +2156,7 @@ indent :: Int -> ShowS indent ind = showString (replicate (ind * 2) ' ') prettyGroup :: (Var v) => String -> SuperGroup v -> ShowS -prettyGroup s (Rec grp ent) = +prettyGroup s (Rec grp ent _c) = showString ("let rec[" ++ s ++ "]\n") . foldr f id grp . showString "entry" diff --git a/unison-runtime/src/Unison/Runtime/ANF/Serialize.hs b/unison-runtime/src/Unison/Runtime/ANF/Serialize.hs index 995856e1b4..551df30469 100644 --- a/unison-runtime/src/Unison/Runtime/ANF/Serialize.hs +++ b/unison-runtime/src/Unison/Runtime/ANF/Serialize.hs @@ -312,10 +312,11 @@ putGroup :: EC.EnumMap FOp Text -> SuperGroup v -> m () -putGroup refrep fops (Rec bs e) = +putGroup refrep fops (Rec bs e cacheable) = putLength n *> traverse_ (putComb refrep fops ctx) cs *> putComb refrep fops ctx e + *> putCacheability cacheable where n = length us (us, cs) = unzip bs @@ -328,7 +329,18 @@ getGroup = do vs = getFresh <$> take l [0 ..] ctx = pushCtx vs [] cs <- replicateM l (getComb ctx n) - Rec (zip vs cs) <$> getComb ctx n + Rec (zip vs cs) <$> getComb ctx n <*> getCacheability + +putCacheability :: (MonadPut m) => Cacheability -> m () +putCacheability c = putBool $ case c of + Cacheable -> True + Uncacheable -> False + +getCacheability :: (MonadGet m) => m Cacheability +getCacheability = + getBool <&> \case + True -> Cacheable + False -> Uncacheable putComb :: (MonadPut m) => diff --git a/unison-runtime/src/Unison/Runtime/Interface.hs b/unison-runtime/src/Unison/Runtime/Interface.hs index ef896fbde5..dcc7278c45 100644 --- a/unison-runtime/src/Unison/Runtime/Interface.hs +++ b/unison-runtime/src/Unison/Runtime/Interface.hs @@ -79,6 +79,7 @@ import Unison.Codebase.Runtime (CompileOpts (..), Error, Runtime (..)) import Unison.ConstructorReference (ConstructorReference, GConstructorReference (..)) import Unison.ConstructorReference qualified as RF import Unison.DataDeclaration (Decl, declFields, declTypeDependencies) +import Unison.Debug qualified as Debug import Unison.Hashing.V2.Convert qualified as Hashing import Unison.LabeledDependency qualified as RF import Unison.Parser.Ann (Ann (External)) @@ -119,7 +120,6 @@ import Unison.Runtime.MCode.Serialize import Unison.Runtime.Machine ( ActiveThreads, CCache (..), - Cacheability (..), MCombs, Tracer (..), apply0, @@ -200,17 +200,6 @@ resolveTermRef cl r@(RF.DerivedId i) = Nothing -> die $ "Unknown term reference: " ++ show r Just tm -> pure tm -resolveTermRefType :: - CodeLookup Symbol IO () -> - RF.Reference -> - IO (Type Symbol) -resolveTermRefType _ b@(RF.Builtin _) = - die $ "Unknown builtin term reference: " ++ show b -resolveTermRefType cl r@(RF.DerivedId i) = - getTypeOfTerm cl i >>= \case - Nothing -> die $ "Unknown term reference: " ++ show r - Just typ -> pure typ - allocType :: EvalCtx -> RF.Reference -> @@ -467,10 +456,20 @@ loadDeps cl ppe ctx tyrs tmrs = do where checkCacheability :: (Reference, sprgrp) -> IO (Reference, sprgrp, Cacheability) checkCacheability (r, sg) = do - typ <- resolveTermRefType cl r - if ABT.cata hasArrows typ - then pure (r, sg, Uncacheable) - else pure (r, sg, Cacheable) + getTermType r >>= \case + Just typ | not (ABT.cata hasArrows typ) -> pure (r, sg, Cacheable) + _ -> pure (r, sg, Uncacheable) + getTermType :: Reference -> IO (Maybe (Type Symbol)) + getTermType = \case + ref@(RF.DerivedId i) -> + getTypeOfTerm cl i >>= \case + Just t -> do + Debug.debugM Debug.Temp "Found type for: " ref + pure $ Just t + Nothing -> do + Debug.debugM Debug.Temp "NO type for: " ref + pure Nothing + RF.Builtin {} -> pure $ Nothing hasArrows :: a -> ABT.ABT Type.F v Bool -> Bool hasArrows _ = \case ABT.Tm f -> case f of @@ -720,7 +719,7 @@ intermediateTerms :: (HasCallStack) => PrettyPrintEnv -> EvalCtx -> - Map RF.Id (Symbol, Term Symbol) -> + Map RF.Id (Symbol, Term Symbol, Cacheability) -> ( Map.Map Symbol Reference, Map.Map Reference (SuperGroup Symbol), Map.Map Reference (Map.Map Word64 (Term Symbol)) @@ -731,7 +730,7 @@ intermediateTerms ppe ctx rtms = (subvs, Map.mapWithKey f cmbs, Map.map (Map.singleton 0) dcmp) where f ref = - superNormalize + superNormalize _cacheable . splitPatterns (dspec ctx) . addDefaultCases tmName where @@ -771,9 +770,9 @@ normalizeTerm ctx tm = normalizeGroup :: EvalCtx -> Map Symbol Reference -> - [(Symbol, Term Symbol)] -> + [(Symbol, Term Symbol, Cacheability)] -> ( Map Symbol Reference, - Map Reference (Term Symbol), + Map Reference (Term Symbol, Cacheability), Map Reference (Term Symbol) ) normalizeGroup ctx orig gr0 = case lamLiftGroup orig gr of @@ -816,7 +815,6 @@ prepareEvaluation :: EvalCtx -> IO (EvalCtx, [(Reference, SuperGroup Symbol)], Reference) prepareEvaluation ppe tm ctx = do - -- TODO: Check whether we need to set cacheability here, I think probably not? missing <- cacheAdd rgrp (ccache ctx') when (not . null $ missing) . fail $ reportBug "E029347" $ diff --git a/unison-runtime/src/Unison/Runtime/MCode.hs b/unison-runtime/src/Unison/Runtime/MCode.hs index 563ed6a538..89875fcaf9 100644 --- a/unison-runtime/src/Unison/Runtime/MCode.hs +++ b/unison-runtime/src/Unison/Runtime/MCode.hs @@ -809,7 +809,7 @@ emitCombs :: Word64 -> SuperGroup v -> EnumMap Word64 Comb -emitCombs rns grpr grpn (Rec grp ent) = +emitCombs rns grpr grpn (Rec grp ent _cacheable) = emitComb rns grpr grpn rec (0, ent) <> aux where (rvs, cmbs) = unzip grp diff --git a/unison-runtime/src/Unison/Runtime/Machine.hs b/unison-runtime/src/Unison/Runtime/Machine.hs index caa1b251aa..39877371cb 100644 --- a/unison-runtime/src/Unison/Runtime/Machine.hs +++ b/unison-runtime/src/Unison/Runtime/Machine.hs @@ -89,11 +89,6 @@ type MComb = RComb Closure type MRef = RRef Closure --- | Whether the evaluation of a given definition is cacheable or not. --- i.e. it's a top-level pure value. -data Cacheability = Cacheable | Uncacheable - deriving stock (Eq, Show) - data Tracer = NoTrace | MsgTrace String String String @@ -366,7 +361,7 @@ exec !env !denv !_activeThreads !ustk !bstk !k _ (BPrim1 LKUP i) Just sn <- EC.lookup w numberedTermLookup -> do poke ustk 1 bstk <- bump bstk - bstk <$ pokeBi bstk (ANF.Rec [] sn) + bstk <$ pokeBi bstk (ANF.Rec [] sn ANF.Uncacheable) | otherwise -> bstk <$ poke ustk 0 Just sg -> do poke ustk 1 @@ -2120,7 +2115,7 @@ evaluateSTM x = unsafeIOToSTM (evaluate x) cacheAdd0 :: S.Set Reference -> - [(Reference, SuperGroup Symbol, Cacheability)] -> + [(Reference, SuperGroup Symbol, ANF.Cacheability)] -> [(Reference, Set Reference)] -> CCache -> IO () @@ -2129,8 +2124,8 @@ cacheAdd0 ntys0 termSuperGroups sands cc = do termSuperGroups & mapMaybe ( \case - (ref, _gr, Cacheable) -> Just ref - (_ref, _gr, Uncacheable) -> Nothing + (ref, _gr, ANF.Cacheable) -> Just ref + (_ref, _gr, ANF.Uncacheable) -> Nothing ) & Set.fromList let toAdd = M.fromList (termSuperGroups <&> \(r, g, _) -> (r, g)) @@ -2229,7 +2224,7 @@ cacheAdd l cc = do -- Terms added via cacheAdd will have already been eval'd and cached if possible when -- they were originally loaded, so we -- don't need to re-check for cacheability here as part of a dynamic cache add. - l'' = l' <&> (\(r, g) -> (r, g, Uncacheable)) + l'' = l' <&> (\(r, g) -> (r, g, ANF.Uncacheable)) if S.null missing then [] <$ cacheAdd0 tys l'' (expandSandbox sand l') cc else pure $ S.toList missing From 5ea32f089fed14e7756822e0857e47924259becf Mon Sep 17 00:00:00 2001 From: Chris Penner Date: Tue, 24 Sep 2024 10:14:53 -0700 Subject: [PATCH 08/40] Don't thread cacheability through floating --- unison-runtime/src/Unison/Runtime/ANF.hs | 27 +++++++++---------- .../src/Unison/Runtime/ANF/Serialize.hs | 5 ++-- .../src/Unison/Runtime/Interface.hs | 8 +++--- unison-runtime/src/Unison/Runtime/MCode.hs | 2 +- 4 files changed, 20 insertions(+), 22 deletions(-) diff --git a/unison-runtime/src/Unison/Runtime/ANF.hs b/unison-runtime/src/Unison/Runtime/ANF.hs index 6d219a6c25..13ba7b038a 100644 --- a/unison-runtime/src/Unison/Runtime/ANF.hs +++ b/unison-runtime/src/Unison/Runtime/ANF.hs @@ -81,7 +81,7 @@ module Unison.Runtime.ANF where import Control.Exception (throw) -import Control.Lens (over, snoc, traversed, unsnoc, _2) +import Control.Lens (snoc, traversed, unsnoc, _2) import Control.Monad.Reader (ReaderT (..), ask, local) import Control.Monad.State (MonadState (..), State, gets, modify, runState) import Data.Bifoldable (Bifoldable (..)) @@ -403,7 +403,7 @@ freshFloat avoid (Var.freshIn avoid -> v0) = groupFloater :: (Var v, Monoid a) => (Term v a -> FloatM v a (Term v a)) -> - [(v, Term v a, Cacheability)] -> + [(v, Term v a)] -> FloatM v a (Map v v) groupFloater rec vbs = do cvs <- gets (\(vs, _, _) -> vs) @@ -557,8 +557,8 @@ floatGroup :: (Var v) => (Monoid a) => Map v Reference -> - [(v, Term v a, Cacheability)] -> - ([(v, Id)], [(Reference, Term v a, Cacheability)], [(Reference, Term v a)]) + [(v, Term v a)] -> + ([(v, Id)], [(Reference, Term v a)], [(Reference, Term v a)]) floatGroup orig grp = case runState go0 (Set.empty, [], []) of (_, st) -> case postFloat orig st of (_, subvs, tops, dcmp) -> (subvs, tops, dcmp) @@ -602,8 +602,8 @@ lamLiftGroup :: (Var v) => (Monoid a) => Map v Reference -> - [(v, Term v a, Cacheability)] -> - ([(v, Id)], [(Reference, Term v a, Cacheability)], [(Reference, Term v a)]) + [(v, Term v a)] -> + ([(v, Id)], [(Reference, Term v a)], [(Reference, Term v a)]) lamLiftGroup orig gr = floatGroup orig . (over (traversed . _2)) (close keep) $ gr where keep = Set.fromList $ map fst gr @@ -1478,8 +1478,7 @@ data Cacheability = Cacheable | Uncacheable data SuperGroup v = Rec { group :: [(v, SuperNormal v)], - entry :: SuperNormal v, - cacheable :: Cacheability + entry :: SuperNormal v } deriving (Show) @@ -1503,7 +1502,7 @@ equivocate :: SuperGroup v -> SuperGroup v -> Either (SGEqv v) () -equivocate g0@(Rec bs0 e0 _c0) g1@(Rec bs1 e1 _c1) +equivocate g0@(Rec bs0 e0) g1@(Rec bs1 e1) | length bs0 == length bs1 = traverse_ eqvSN (zip ns0 ns1) *> eqvSN (e0, e1) | otherwise = Left $ NumDefns g0 g1 @@ -1593,8 +1592,8 @@ bindDirection = traverse (const binder) record :: (Var v) => (v, SuperNormal v) -> ANFM v () record p = modify $ \(fr, bnd, to) -> (fr, bnd, p : to) -superNormalize :: (Var v) => Cacheability -> Term v a -> SuperGroup v -superNormalize cacheable tm = Rec l c cacheable +superNormalize :: (Var v) => Term v a -> SuperGroup v +superNormalize tm = Rec l c where (bs, e) | LetRecNamed' bs e <- tm = (bs, e) @@ -2011,8 +2010,8 @@ traverseGroupLinks :: (Bool -> Reference -> f Reference) -> SuperGroup v -> f (SuperGroup v) -traverseGroupLinks f (Rec bs e cacheable) = - Rec <$> (traverse . traverse) (normalLinks f) bs <*> normalLinks f e <*> pure cacheable +traverseGroupLinks f (Rec bs e) = + Rec <$> (traverse . traverse) (normalLinks f) bs <*> normalLinks f e foldGroupLinks :: (Monoid r, Var v) => @@ -2156,7 +2155,7 @@ indent :: Int -> ShowS indent ind = showString (replicate (ind * 2) ' ') prettyGroup :: (Var v) => String -> SuperGroup v -> ShowS -prettyGroup s (Rec grp ent _c) = +prettyGroup s (Rec grp ent) = showString ("let rec[" ++ s ++ "]\n") . foldr f id grp . showString "entry" diff --git a/unison-runtime/src/Unison/Runtime/ANF/Serialize.hs b/unison-runtime/src/Unison/Runtime/ANF/Serialize.hs index 551df30469..2c24007262 100644 --- a/unison-runtime/src/Unison/Runtime/ANF/Serialize.hs +++ b/unison-runtime/src/Unison/Runtime/ANF/Serialize.hs @@ -312,11 +312,10 @@ putGroup :: EC.EnumMap FOp Text -> SuperGroup v -> m () -putGroup refrep fops (Rec bs e cacheable) = +putGroup refrep fops (Rec bs e) = putLength n *> traverse_ (putComb refrep fops ctx) cs *> putComb refrep fops ctx e - *> putCacheability cacheable where n = length us (us, cs) = unzip bs @@ -329,7 +328,7 @@ getGroup = do vs = getFresh <$> take l [0 ..] ctx = pushCtx vs [] cs <- replicateM l (getComb ctx n) - Rec (zip vs cs) <$> getComb ctx n <*> getCacheability + Rec (zip vs cs) <$> getComb ctx n putCacheability :: (MonadPut m) => Cacheability -> m () putCacheability c = putBool $ case c of diff --git a/unison-runtime/src/Unison/Runtime/Interface.hs b/unison-runtime/src/Unison/Runtime/Interface.hs index dcc7278c45..05ad12c8e9 100644 --- a/unison-runtime/src/Unison/Runtime/Interface.hs +++ b/unison-runtime/src/Unison/Runtime/Interface.hs @@ -719,7 +719,7 @@ intermediateTerms :: (HasCallStack) => PrettyPrintEnv -> EvalCtx -> - Map RF.Id (Symbol, Term Symbol, Cacheability) -> + Map RF.Id (Symbol, Term Symbol) -> ( Map.Map Symbol Reference, Map.Map Reference (SuperGroup Symbol), Map.Map Reference (Map.Map Word64 (Term Symbol)) @@ -730,7 +730,7 @@ intermediateTerms ppe ctx rtms = (subvs, Map.mapWithKey f cmbs, Map.map (Map.singleton 0) dcmp) where f ref = - superNormalize _cacheable + superNormalize . splitPatterns (dspec ctx) . addDefaultCases tmName where @@ -770,9 +770,9 @@ normalizeTerm ctx tm = normalizeGroup :: EvalCtx -> Map Symbol Reference -> - [(Symbol, Term Symbol, Cacheability)] -> + [(Symbol, Term Symbol)] -> ( Map Symbol Reference, - Map Reference (Term Symbol, Cacheability), + Map Reference (Term Symbol), Map Reference (Term Symbol) ) normalizeGroup ctx orig gr0 = case lamLiftGroup orig gr of diff --git a/unison-runtime/src/Unison/Runtime/MCode.hs b/unison-runtime/src/Unison/Runtime/MCode.hs index 89875fcaf9..563ed6a538 100644 --- a/unison-runtime/src/Unison/Runtime/MCode.hs +++ b/unison-runtime/src/Unison/Runtime/MCode.hs @@ -809,7 +809,7 @@ emitCombs :: Word64 -> SuperGroup v -> EnumMap Word64 Comb -emitCombs rns grpr grpn (Rec grp ent _cacheable) = +emitCombs rns grpr grpn (Rec grp ent) = emitComb rns grpr grpn rec (0, ent) <> aux where (rvs, cmbs) = unzip grp From df9571264c60dccf1f6a4325a6c71c3888c2f757 Mon Sep 17 00:00:00 2001 From: Chris Penner Date: Tue, 24 Sep 2024 10:25:38 -0700 Subject: [PATCH 09/40] Add type aliases for refs --- .../src/Unison/Runtime/Interface.hs | 44 ++++++++++++------- 1 file changed, 28 insertions(+), 16 deletions(-) diff --git a/unison-runtime/src/Unison/Runtime/Interface.hs b/unison-runtime/src/Unison/Runtime/Interface.hs index 05ad12c8e9..9cdedff6cb 100644 --- a/unison-runtime/src/Unison/Runtime/Interface.hs +++ b/unison-runtime/src/Unison/Runtime/Interface.hs @@ -155,21 +155,33 @@ type Term v = Tm.Term v () type Type v = Type.Type v () -data Remapping = Remap - { remap :: Map.Map Reference Reference, - backmap :: Map.Map Reference Reference +-- Note that these annotations are suggestions at best, since in many places codebase refs, intermediate refs, and +-- floated refs are all intermingled. +type CodebaseReference = Reference + +-- Note that these annotations are suggestions at best, since in many places codebase refs, intermediate refs, and +-- floated refs are all intermingled. +type IntermediateReference = Reference + +-- Note that these annotations are suggestions at best, since in many places codebase refs, intermediate refs, and +-- floated refs are all intermingled. +type FloatedReference = Reference + +data Remapping from to = Remap + { remap :: Map.Map from to, + backmap :: Map.Map to from } -instance Semigroup Remapping where +instance (Ord from, Ord to) => Semigroup (Remapping from to) where Remap r1 b1 <> Remap r2 b2 = Remap (r1 <> r2) (b1 <> b2) -instance Monoid Remapping where +instance (Ord from, Ord to) => Monoid (Remapping from to) where mempty = Remap mempty mempty data EvalCtx = ECtx { dspec :: DataSpec, - floatRemap :: Remapping, - intermedRemap :: Remapping, + floatRemap :: Remapping CodebaseReference FloatedReference, + intermedRemap :: Remapping FloatedReference IntermediateReference, decompTm :: Map.Map Reference (Map.Map Word64 (Term Symbol)), ccache :: CCache } @@ -334,7 +346,7 @@ backrefAdd :: backrefAdd m ctx@ECtx {decompTm} = ctx {decompTm = m <> decompTm} -remapAdd :: Map.Map Reference Reference -> Remapping -> Remapping +remapAdd :: (Ord from, Ord to) => Map.Map from to -> Remapping from to -> Remapping from to remapAdd m Remap {remap, backmap} = Remap {remap = m <> remap, backmap = tm <> backmap} where @@ -348,31 +360,31 @@ intermedRemapAdd :: Map.Map Reference Reference -> EvalCtx -> EvalCtx intermedRemapAdd m ctx@ECtx {intermedRemap} = ctx {intermedRemap = remapAdd m intermedRemap} -baseToIntermed :: EvalCtx -> Reference -> Maybe Reference +baseToIntermed :: EvalCtx -> CodebaseReference -> Maybe IntermediateReference baseToIntermed ctx r = do r <- Map.lookup r . remap $ floatRemap ctx Map.lookup r . remap $ intermedRemap ctx -- Runs references through the forward maps to get intermediate -- references. Works on both base and floated references. -toIntermed :: EvalCtx -> Reference -> Reference +toIntermed :: EvalCtx -> Reference -> IntermediateReference toIntermed ctx r | r <- Map.findWithDefault r r . remap $ floatRemap ctx, Just r <- Map.lookup r . remap $ intermedRemap ctx = r toIntermed _ r = r -floatToIntermed :: EvalCtx -> Reference -> Maybe Reference +floatToIntermed :: EvalCtx -> FloatedReference -> Maybe IntermediateReference floatToIntermed ctx r = Map.lookup r . remap $ intermedRemap ctx -intermedToBase :: EvalCtx -> Reference -> Maybe Reference +intermedToBase :: EvalCtx -> IntermediateReference -> Maybe CodebaseReference intermedToBase ctx r = do r <- Map.lookup r . backmap $ intermedRemap ctx Map.lookup r . backmap $ floatRemap ctx -- Runs references through the backmaps with defaults at all steps. -backmapRef :: EvalCtx -> Reference -> Reference +backmapRef :: EvalCtx -> Reference -> CodebaseReference backmapRef ctx r0 = r2 where r1 = Map.findWithDefault r0 r0 . backmap $ intermedRemap ctx @@ -838,9 +850,9 @@ watchHook r _ bstk = peek bstk >>= writeIORef r backReferenceTm :: EnumMap Word64 Reference -> - Remapping -> - Remapping -> - Map.Map Reference (Map.Map Word64 (Term Symbol)) -> + Remapping IntermediateReference CodebaseReference -> + Remapping FloatedReference IntermediateReference -> + Map.Map CodebaseReference (Map.Map Word64 (Term Symbol)) -> Word64 -> Word64 -> Maybe (Term Symbol) From 151f345c82466de7a78013b6d8afc41a80be9f51 Mon Sep 17 00:00:00 2001 From: Chris Penner Date: Tue, 24 Sep 2024 10:25:38 -0700 Subject: [PATCH 10/40] Use backmap to look up types of codebase refs of top level defs --- .../src/Unison/Runtime/Interface.hs | 26 +++++++++---------- unison-runtime/src/Unison/Runtime/Machine.hs | 2 +- 2 files changed, 13 insertions(+), 15 deletions(-) diff --git a/unison-runtime/src/Unison/Runtime/Interface.hs b/unison-runtime/src/Unison/Runtime/Interface.hs index 9cdedff6cb..a2c06f1f4e 100644 --- a/unison-runtime/src/Unison/Runtime/Interface.hs +++ b/unison-runtime/src/Unison/Runtime/Interface.hs @@ -79,7 +79,6 @@ import Unison.Codebase.Runtime (CompileOpts (..), Error, Runtime (..)) import Unison.ConstructorReference (ConstructorReference, GConstructorReference (..)) import Unison.ConstructorReference qualified as RF import Unison.DataDeclaration (Decl, declFields, declTypeDependencies) -import Unison.Debug qualified as Debug import Unison.Hashing.V2.Convert qualified as Hashing import Unison.LabeledDependency qualified as RF import Unison.Parser.Ann (Ann (External)) @@ -462,25 +461,24 @@ loadDeps cl ppe ctx tyrs tmrs = do _ -> False ctx <- foldM (uncurry . allocType) ctx $ Prelude.filter p tyrs let tyAdd = Set.fromList $ fst <$> tyrs - out@(_, rgrp) <- loadCode cl ppe ctx tmrs - crgrp <- traverse checkCacheability rgrp + out@(ctx', rgrp) <- loadCode cl ppe ctx tmrs + crgrp <- traverse (checkCacheability ctx') rgrp out <$ cacheAdd0 tyAdd crgrp (expandSandbox sand rgrp) cc where - checkCacheability :: (Reference, sprgrp) -> IO (Reference, sprgrp, Cacheability) - checkCacheability (r, sg) = do - getTermType r >>= \case + checkCacheability :: EvalCtx -> (IntermediateReference, sprgrp) -> IO (IntermediateReference, sprgrp, Cacheability) + checkCacheability ctx (r, sg) = do + let codebaseRef = backmapRef ctx r + getTermType codebaseRef >>= \case + -- A term's result is cacheable iff it has no arrows in its type, + -- this is sufficient since top-level definitions can't have effects without a delay. Just typ | not (ABT.cata hasArrows typ) -> pure (r, sg, Cacheable) _ -> pure (r, sg, Uncacheable) - getTermType :: Reference -> IO (Maybe (Type Symbol)) + getTermType :: CodebaseReference -> IO (Maybe (Type Symbol)) getTermType = \case - ref@(RF.DerivedId i) -> + (RF.DerivedId i) -> getTypeOfTerm cl i >>= \case - Just t -> do - Debug.debugM Debug.Temp "Found type for: " ref - pure $ Just t - Nothing -> do - Debug.debugM Debug.Temp "NO type for: " ref - pure Nothing + Just t -> pure $ Just t + Nothing -> pure Nothing RF.Builtin {} -> pure $ Nothing hasArrows :: a -> ABT.ABT Type.F v Bool -> Bool hasArrows _ = \case diff --git a/unison-runtime/src/Unison/Runtime/Machine.hs b/unison-runtime/src/Unison/Runtime/Machine.hs index 39877371cb..df3955483d 100644 --- a/unison-runtime/src/Unison/Runtime/Machine.hs +++ b/unison-runtime/src/Unison/Runtime/Machine.hs @@ -361,7 +361,7 @@ exec !env !denv !_activeThreads !ustk !bstk !k _ (BPrim1 LKUP i) Just sn <- EC.lookup w numberedTermLookup -> do poke ustk 1 bstk <- bump bstk - bstk <$ pokeBi bstk (ANF.Rec [] sn ANF.Uncacheable) + bstk <$ pokeBi bstk (ANF.Rec [] sn) | otherwise -> bstk <$ poke ustk 0 Just sg -> do poke ustk 1 From f367824de27d20d07dbf634a1286a3482055c8e9 Mon Sep 17 00:00:00 2001 From: Chris Penner Date: Tue, 24 Sep 2024 10:51:52 -0700 Subject: [PATCH 11/40] Cleanup --- stack.yaml | 2 +- unison-runtime/src/Unison/Runtime/ANF.hs | 10 ++-------- unison-runtime/src/Unison/Runtime/ANF/Serialize.hs | 11 ----------- unison-runtime/src/Unison/Runtime/Interface.hs | 1 + unison-runtime/src/Unison/Runtime/Machine.hs | 13 +++++++++---- 5 files changed, 13 insertions(+), 24 deletions(-) diff --git a/stack.yaml b/stack.yaml index c75e0c1638..6a31222d65 100644 --- a/stack.yaml +++ b/stack.yaml @@ -73,7 +73,7 @@ allow-newer-deps: ghc-options: # All packages - "$locals": -Wall -Werror -Wno-name-shadowing -Wno-missing-pattern-synonym-signatures -fprint-expanded-synonyms -fwrite-ide-info -Wunused-packages -debug #-freverse-errors + "$locals": -Wall -Werror -Wno-name-shadowing -Wno-missing-pattern-synonym-signatures -fprint-expanded-synonyms -fwrite-ide-info -Wunused-packages #-freverse-errors # See https://github.com/haskell/haskell-language-server/issues/208 "$everything": -haddock diff --git a/unison-runtime/src/Unison/Runtime/ANF.hs b/unison-runtime/src/Unison/Runtime/ANF.hs index 13ba7b038a..0c2fa20ff8 100644 --- a/unison-runtime/src/Unison/Runtime/ANF.hs +++ b/unison-runtime/src/Unison/Runtime/ANF.hs @@ -36,7 +36,6 @@ module Unison.Runtime.ANF Direction (..), SuperNormal (..), SuperGroup (..), - Cacheability (..), POp (..), FOp, close, @@ -81,7 +80,7 @@ module Unison.Runtime.ANF where import Control.Exception (throw) -import Control.Lens (snoc, traversed, unsnoc, _2) +import Control.Lens (snoc, unsnoc) import Control.Monad.Reader (ReaderT (..), ask, local) import Control.Monad.State (MonadState (..), State, gets, modify, runState) import Data.Bifoldable (Bifoldable (..)) @@ -604,7 +603,7 @@ lamLiftGroup :: Map v Reference -> [(v, Term v a)] -> ([(v, Id)], [(Reference, Term v a)], [(Reference, Term v a)]) -lamLiftGroup orig gr = floatGroup orig . (over (traversed . _2)) (close keep) $ gr +lamLiftGroup orig gr = floatGroup orig . (fmap . fmap) (close keep) $ gr where keep = Set.fromList $ map fst gr @@ -1471,11 +1470,6 @@ type DNormal v = Directed () (ANormal v) data SuperNormal v = Lambda {conventions :: [Mem], bound :: ANormal v} deriving (Show, Eq) --- | Whether the evaluation of a given definition is cacheable or not. --- i.e. it's a top-level pure value. -data Cacheability = Cacheable | Uncacheable - deriving stock (Eq, Show) - data SuperGroup v = Rec { group :: [(v, SuperNormal v)], entry :: SuperNormal v diff --git a/unison-runtime/src/Unison/Runtime/ANF/Serialize.hs b/unison-runtime/src/Unison/Runtime/ANF/Serialize.hs index 2c24007262..995856e1b4 100644 --- a/unison-runtime/src/Unison/Runtime/ANF/Serialize.hs +++ b/unison-runtime/src/Unison/Runtime/ANF/Serialize.hs @@ -330,17 +330,6 @@ getGroup = do cs <- replicateM l (getComb ctx n) Rec (zip vs cs) <$> getComb ctx n -putCacheability :: (MonadPut m) => Cacheability -> m () -putCacheability c = putBool $ case c of - Cacheable -> True - Uncacheable -> False - -getCacheability :: (MonadGet m) => m Cacheability -getCacheability = - getBool <&> \case - True -> Cacheable - False -> Uncacheable - putComb :: (MonadPut m) => (Var v) => diff --git a/unison-runtime/src/Unison/Runtime/Interface.hs b/unison-runtime/src/Unison/Runtime/Interface.hs index a2c06f1f4e..e8a04b3f89 100644 --- a/unison-runtime/src/Unison/Runtime/Interface.hs +++ b/unison-runtime/src/Unison/Runtime/Interface.hs @@ -119,6 +119,7 @@ import Unison.Runtime.MCode.Serialize import Unison.Runtime.Machine ( ActiveThreads, CCache (..), + Cacheability (..), MCombs, Tracer (..), apply0, diff --git a/unison-runtime/src/Unison/Runtime/Machine.hs b/unison-runtime/src/Unison/Runtime/Machine.hs index df3955483d..4db7fbb2ce 100644 --- a/unison-runtime/src/Unison/Runtime/Machine.hs +++ b/unison-runtime/src/Unison/Runtime/Machine.hs @@ -94,6 +94,11 @@ data Tracer | MsgTrace String String String | SimpleTrace String +-- | Whether the evaluation of a given definition is cacheable or not. +-- i.e. it's a top-level pure value. +data Cacheability = Cacheable | Uncacheable + deriving stock (Eq, Show) + -- code caching environment data CCache = CCache { foreignFuncs :: EnumMap Word64 ForeignFunc, @@ -2115,7 +2120,7 @@ evaluateSTM x = unsafeIOToSTM (evaluate x) cacheAdd0 :: S.Set Reference -> - [(Reference, SuperGroup Symbol, ANF.Cacheability)] -> + [(Reference, SuperGroup Symbol, Cacheability)] -> [(Reference, Set Reference)] -> CCache -> IO () @@ -2124,8 +2129,8 @@ cacheAdd0 ntys0 termSuperGroups sands cc = do termSuperGroups & mapMaybe ( \case - (ref, _gr, ANF.Cacheable) -> Just ref - (_ref, _gr, ANF.Uncacheable) -> Nothing + (ref, _gr, Cacheable) -> Just ref + (_ref, _gr, Uncacheable) -> Nothing ) & Set.fromList let toAdd = M.fromList (termSuperGroups <&> \(r, g, _) -> (r, g)) @@ -2224,7 +2229,7 @@ cacheAdd l cc = do -- Terms added via cacheAdd will have already been eval'd and cached if possible when -- they were originally loaded, so we -- don't need to re-check for cacheability here as part of a dynamic cache add. - l'' = l' <&> (\(r, g) -> (r, g, ANF.Uncacheable)) + l'' = l' <&> (\(r, g) -> (r, g, Uncacheable)) if S.null missing then [] <$ cacheAdd0 tys l'' (expandSandbox sand l') cc else pure $ S.toList missing From da9a5880910b540e54ac164ff409f5c7beff1f53 Mon Sep 17 00:00:00 2001 From: Chris Penner Date: Tue, 24 Sep 2024 10:51:52 -0700 Subject: [PATCH 12/40] Working pre-evaluated closures. --- unison-runtime/src/Unison/Runtime/Machine.hs | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/unison-runtime/src/Unison/Runtime/Machine.hs b/unison-runtime/src/Unison/Runtime/Machine.hs index 4db7fbb2ce..ced1a9d276 100644 --- a/unison-runtime/src/Unison/Runtime/Machine.hs +++ b/unison-runtime/src/Unison/Runtime/Machine.hs @@ -756,7 +756,8 @@ apply :: apply !env !denv !activeThreads !ustk !bstk !k !ck !args = \case (PAp comb useg bseg) -> case unRComb comb of - CachedClosure _cix clos -> zeroArgClosure clos + CachedClosure _cix clos -> do + zeroArgClosure clos Lam ua ba uf bf entry | ck || ua <= uac && ba <= bac -> do ustk <- ensure ustk uf @@ -2163,8 +2164,11 @@ cacheAdd0 ntys0 termSuperGroups sands cc = do preEvalTopLevelConstants :: Set Reference -> CCache -> IO () preEvalTopLevelConstants cacheableRefs cc = do activeThreads <- Just <$> UnliftIO.newIORef mempty - cmbs <- readTVarIO (combs cc) - for_ (EC.keys cmbs) \w -> do + cmbRefs <- readTVarIO (combRefs cc) + let cacheableCombs = + EC.mapToList cmbRefs + & mapMaybe (\(w, ref) -> if ref `Set.member` cacheableRefs then Just w else Nothing) + for_ cacheableCombs \w -> do let hook _ustk bstk = do clos <- peek bstk atomically $ do @@ -2187,10 +2191,6 @@ preEvalTopLevelConstants cacheableRefs cc = do ) -> do RComb cix cachedClos | otherwise -> rComb --- unTieRCombs combs --- & (fmap . fmap) _ --- & resolveCombs Nothing - expandSandbox :: Map Reference (Set Reference) -> [(Reference, SuperGroup Symbol)] -> From 1940a4aba7f163967c05682407197c895e7c110d Mon Sep 17 00:00:00 2001 From: Chris Penner Date: Tue, 24 Sep 2024 10:51:52 -0700 Subject: [PATCH 13/40] Debugging info --- unison-runtime/src/Unison/Runtime/Machine.hs | 24 ++++++++------------ 1 file changed, 9 insertions(+), 15 deletions(-) diff --git a/unison-runtime/src/Unison/Runtime/Machine.hs b/unison-runtime/src/Unison/Runtime/Machine.hs index ced1a9d276..b252615772 100644 --- a/unison-runtime/src/Unison/Runtime/Machine.hs +++ b/unison-runtime/src/Unison/Runtime/Machine.hs @@ -27,6 +27,7 @@ import GHC.Conc as STM (unsafeIOToSTM) import Unison.Builtin.Decls (exceptionRef, ioFailureRef) import Unison.Builtin.Decls qualified as Rf import Unison.ConstructorReference qualified as CR +import Unison.Debug qualified as Debug import Unison.Prelude hiding (Text) import Unison.Reference ( Reference, @@ -2168,28 +2169,21 @@ preEvalTopLevelConstants cacheableRefs cc = do let cacheableCombs = EC.mapToList cmbRefs & mapMaybe (\(w, ref) -> if ref `Set.member` cacheableRefs then Just w else Nothing) + & Set.fromList for_ cacheableCombs \w -> do + Debug.debugM Debug.Temp "Evaluating " w let hook _ustk bstk = do clos <- peek bstk + Debug.debugM Debug.Temp "Evaluated" ("Evaluated " ++ show w ++ " to " ++ show clos) atomically $ do -- TODO: Check that it's right to just insert the closure at comb position 0 modifyTVar (combs cc) $ EC.mapInsert w (EC.mapSingleton 0 $ CachedClosure w clos) apply0 (Just hook) cc activeThreads w - atomically $ modifyTVar (combs cc) reTieCombs - where - reTieCombs :: EnumMap Word64 (RCombs Closure) -> EnumMap Word64 (RCombs Closure) - reTieCombs combs = - combs - & (fmap . fmap . fmap) \case - -- For each combinator ref in all the source code, if it's in the set of pre-evaluated refs, - -- replace the combinator in the source with the pre-evaluated closure rather than the cyclic RComb. - rComb@(RComb cix@(CIx ref w i) _) - | Set.member ref cacheableRefs, - Just cachedClos <- - ( EC.lookup w combs - >>= EC.lookup i - ) -> do RComb cix cachedClos - | otherwise -> rComb + + Debug.debugLogM Debug.Temp "Done pre-caching" + -- Rewrite all the inlined combinator references to point to the + -- new cached versions. + atomically $ modifyTVar (combs cc) (resolveCombs Nothing . unTieRCombs) expandSandbox :: Map Reference (Set Reference) -> From d0a95e9954493ac437a3db356fa83c5596aff25a Mon Sep 17 00:00:00 2001 From: Chris Penner Date: Tue, 24 Sep 2024 17:06:24 -0700 Subject: [PATCH 14/40] Fix missing pattern matches on Clos's --- unison-runtime/src/Unison/Runtime/Machine.hs | 52 ++++++++++++-------- 1 file changed, 31 insertions(+), 21 deletions(-) diff --git a/unison-runtime/src/Unison/Runtime/Machine.hs b/unison-runtime/src/Unison/Runtime/Machine.hs index b252615772..1b43a745b9 100644 --- a/unison-runtime/src/Unison/Runtime/Machine.hs +++ b/unison-runtime/src/Unison/Runtime/Machine.hs @@ -4,8 +4,6 @@ {-# LANGUAGE PatternSynonyms #-} {-# LANGUAGE RankNTypes #-} {-# LANGUAGE ViewPatterns #-} --- TODO: Fix up all the uni-patterns -{-# OPTIONS_GHC -Wno-incomplete-uni-patterns #-} module Unison.Runtime.Machine where @@ -320,7 +318,9 @@ exec !env !denv !_activeThreads !ustk !bstk !k _ (BPrim1 MISS i) | sandboxed env = die "attempted to use sandboxed operation: isMissing" | otherwise = do clink <- peekOff bstk i - let Ref link = unwrapForeign $ marshalToForeign clink + let link = case unwrapForeign $ marshalToForeign clink of + Ref r -> r + _ -> error "exec:BPrim1:MISS: Expected Ref" m <- readTVarIO (intermed env) ustk <- bump ustk if (link `M.member` m) then poke ustk 1 else poke ustk 0 @@ -358,7 +358,9 @@ exec !env !denv !_activeThreads !ustk !bstk !k _ (BPrim1 LKUP i) | sandboxed env = die "attempted to use sandboxed operation: lookup" | otherwise = do clink <- peekOff bstk i - let Ref link = unwrapForeign $ marshalToForeign clink + let link = case unwrapForeign $ marshalToForeign clink of + Ref r -> r + _ -> error "exec:BPrim1:LKUP: Expected Ref" m <- readTVarIO (intermed env) ustk <- bump ustk bstk <- case M.lookup link m of @@ -718,17 +720,22 @@ enter :: Args -> MComb -> IO () -enter !env !denv !activeThreads !ustk !bstk !k !ck !args !rcomb = do - ustk <- if ck then ensure ustk uf else pure ustk - bstk <- if ck then ensure bstk bf else pure bstk - (ustk, bstk) <- moveArgs ustk bstk args - ustk <- acceptArgs ustk ua - bstk <- acceptArgs bstk ba - -- TODO: start putting references in `Call` if we ever start - -- detecting saturated calls. - eval env denv activeThreads ustk bstk k dummyRef entry - where - (RComb _ (Lam ua ba uf bf entry)) = rcomb +enter !env !denv !activeThreads !ustk !bstk !k !ck !args = \case + (RComb _ (Lam ua ba uf bf entry)) -> do + ustk <- if ck then ensure ustk uf else pure ustk + bstk <- if ck then ensure bstk bf else pure bstk + (ustk, bstk) <- moveArgs ustk bstk args + ustk <- acceptArgs ustk ua + bstk <- acceptArgs bstk ba + -- TODO: start putting references in `Call` if we ever start + -- detecting saturated calls. + eval env denv activeThreads ustk bstk k dummyRef entry + (RComb _ (CachedClosure _cix clos)) -> do + ustk <- discardFrame ustk + bstk <- discardFrame bstk + bstk <- bump bstk + poke bstk clos + yield env denv activeThreads ustk bstk k {-# INLINE enter #-} -- fast path by-name delaying @@ -1861,12 +1868,15 @@ yield !env !denv !activeThreads !ustk !bstk !k = leap denv k bstk <- adjustArgs bstk ba apply env denv activeThreads ustk bstk k False (BArg1 0) clo leap !denv (Push ufsz bfsz uasz basz rComb k) = do - let Lam _ _ uf bf nx = unRComb rComb - ustk <- restoreFrame ustk ufsz uasz - bstk <- restoreFrame bstk bfsz basz - ustk <- ensure ustk uf - bstk <- ensure bstk bf - eval env denv activeThreads ustk bstk k (rCombRef rComb) nx + case unRComb rComb of + Lam _ _ uf bf nx -> do + ustk <- restoreFrame ustk ufsz uasz + bstk <- restoreFrame bstk bfsz basz + ustk <- ensure ustk uf + bstk <- ensure bstk bf + eval env denv activeThreads ustk bstk k (rCombRef rComb) nx + CachedClosure _w clo -> do + _ leap _ (CB (Hook f)) = f ustk bstk leap _ KE = pure () {-# INLINE yield #-} From e0bacf1a5a70bf018d505606335cc5b2946707eb Mon Sep 17 00:00:00 2001 From: Chris Penner Date: Tue, 24 Sep 2024 17:32:56 -0700 Subject: [PATCH 15/40] Store srcCombs in SCache --- .../src/Unison/Runtime/Interface.hs | 50 +++++++++++-------- .../src/Unison/Runtime/MCode/Serialize.hs | 15 +++--- unison-runtime/src/Unison/Runtime/Machine.hs | 17 +++++-- 3 files changed, 49 insertions(+), 33 deletions(-) diff --git a/unison-runtime/src/Unison/Runtime/Interface.hs b/unison-runtime/src/Unison/Runtime/Interface.hs index e8a04b3f89..9e57e774e3 100644 --- a/unison-runtime/src/Unison/Runtime/Interface.hs +++ b/unison-runtime/src/Unison/Runtime/Interface.hs @@ -102,25 +102,23 @@ import Unison.Runtime.Exception import Unison.Runtime.MCode ( Args (..), CombIx (..), + Combs, GCombs, GInstr (..), GSection (..), + RCombs, RefNums (..), - absurdCombs, combDeps, combTypes, emitComb, emptyRNs, - rCombIx, resolveCombs, - unTieRCombs, ) import Unison.Runtime.MCode.Serialize import Unison.Runtime.Machine ( ActiveThreads, CCache (..), Cacheability (..), - MCombs, Tracer (..), apply0, baseCCache, @@ -138,7 +136,6 @@ import Unison.Runtime.Machine import Unison.Runtime.Pattern import Unison.Runtime.Serialize as SER import Unison.Runtime.Stack -import Unison.Runtime.Stack.Serialize (getClosure, putClosure) import Unison.Symbol (Symbol) import Unison.Syntax.HashQualified qualified as HQ (toText) import Unison.Syntax.NamePrinter (prettyHashQualified) @@ -1248,8 +1245,9 @@ runStandalone sc init = -- standalone bytecode. data StoredCache = SCache - (EnumMap Word64 (GCombs Closure CombIx)) + (EnumMap Word64 Combs) (EnumMap Word64 Reference) + (EnumSet Word64) (EnumMap Word64 Reference) Word64 Word64 @@ -1260,9 +1258,10 @@ data StoredCache deriving (Show) putStoredCache :: (MonadPut m) => StoredCache -> m () -putStoredCache (SCache cs crs trs ftm fty int rtm rty sbs) = do - putEnumMap putNat (putEnumMap putNat (putComb putClosure putCombIx)) cs +putStoredCache (SCache cs crs cacheableCombs trs ftm fty int rtm rty sbs) = do + putEnumMap putNat (putEnumMap putNat (putComb putCombIx)) cs putEnumMap putNat putReference crs + putEnumSet putNat cacheableCombs putEnumMap putNat putReference trs putNat ftm putNat fty @@ -1274,8 +1273,9 @@ putStoredCache (SCache cs crs trs ftm fty int rtm rty sbs) = do getStoredCache :: (MonadGet m) => m StoredCache getStoredCache = SCache - <$> getEnumMap getNat (getEnumMap getNat (getComb getClosure getCombIx)) + <$> getEnumMap getNat (getEnumMap getNat (getComb getCombIx)) <*> getEnumMap getNat getReference + <*> getEnumSet getNat <*> getEnumMap getNat getReference <*> getNat <*> getNat @@ -1302,10 +1302,12 @@ tabulateErrors errs = : (listErrors errs) restoreCache :: StoredCache -> IO CCache -restoreCache (SCache cs crs trs ftm fty int rtm rty sbs) = +restoreCache (SCache cs crs cacheableCombs trs ftm fty int rtm rty sbs) = CCache builtinForeigns False debugText - <$> newTVarIO combs + <$> newTVarIO srcCombs + <*> newTVarIO combs <*> newTVarIO (crs <> builtinTermBackref) + <*> newTVarIO cacheableCombs <*> newTVarIO (trs <> builtinTypeBackref) <*> newTVarIO ftm <*> newTVarIO fty @@ -1329,28 +1331,32 @@ restoreCache (SCache cs crs trs ftm fty int rtm rty sbs) = (debugTextFormat fancy $ pretty PPE.empty dv) rns = emptyRNs {dnum = refLookup "ty" builtinTypeNumbering} rf k = builtinTermBackref ! k - combs :: EnumMap Word64 MCombs - combs = + srcCombs :: EnumMap Word64 Combs + srcCombs = let builtinCombs = mapWithKey (\k v -> emitComb @Symbol rns (rf k) k mempty (0, v)) numberedTermLookup - in absurdCombs builtinCombs <> cs - & resolveCombs Nothing + in builtinCombs <> cs + combs :: EnumMap Word64 (RCombs Closure) + combs = + srcCombs + & resolveCombs Nothing traceNeeded :: Word64 -> - EnumMap Word64 MCombs -> - IO (EnumMap Word64 MCombs) + EnumMap Word64 Combs -> + IO (EnumMap Word64 Combs) traceNeeded init src = fmap (`withoutKeys` ks) $ go mempty init where ks = keysSet numberedTermLookup go acc w | hasKey w acc = pure acc | Just co <- EC.lookup w src = - foldlM go (mapInsert w co acc) (foldMap (combDeps . fmap rCombIx) co) + foldlM go (mapInsert w co acc) (foldMap combDeps co) | otherwise = die $ "traceNeeded: unknown combinator: " ++ show w buildSCache :: - EnumMap Word64 (GCombs Closure CombIx) -> + EnumMap Word64 (GCombs Void CombIx) -> EnumMap Word64 Reference -> + EnumSet Word64 -> EnumMap Word64 Reference -> Word64 -> Word64 -> @@ -1359,10 +1365,11 @@ buildSCache :: Map Reference Word64 -> Map Reference (Set Reference) -> StoredCache -buildSCache cs crsrc trsrc ftm fty intsrc rtmsrc rtysrc sndbx = +buildSCache cs crsrc cacheableCombs trsrc ftm fty intsrc rtmsrc rtysrc sndbx = SCache cs crs + cacheableCombs trs ftm fty @@ -1389,8 +1396,9 @@ buildSCache cs crsrc trsrc ftm fty intsrc rtmsrc rtysrc sndbx = standalone :: CCache -> Word64 -> IO StoredCache standalone cc init = buildSCache - <$> (readTVarIO (combs cc) >>= traceNeeded init >>= pure . unTieRCombs) + <$> (readTVarIO (srcCombs cc) >>= traceNeeded init) <*> readTVarIO (combRefs cc) + <*> readTVarIO (cacheableCombs cc) <*> readTVarIO (tagRefs cc) <*> readTVarIO (freshTm cc) <*> readTVarIO (freshTy cc) diff --git a/unison-runtime/src/Unison/Runtime/MCode/Serialize.hs b/unison-runtime/src/Unison/Runtime/MCode/Serialize.hs index 5d8e34cc4c..895a6d0216 100644 --- a/unison-runtime/src/Unison/Runtime/MCode/Serialize.hs +++ b/unison-runtime/src/Unison/Runtime/MCode/Serialize.hs @@ -15,6 +15,7 @@ import Data.Bytes.Put import Data.Bytes.Serial import Data.Bytes.VarInt import Data.Primitive.PrimArray +import Data.Void (Void) import Data.Word (Word64) import GHC.Exts (IsList (..)) import Unison.Runtime.MCode hiding (MatchT) @@ -31,18 +32,14 @@ instance Tag CombT where word2tag 1 = pure CachedClosureT word2tag n = unknownTag "CombT" n -putComb :: (MonadPut m) => (clos -> m ()) -> (cix -> m ()) -> GComb clos cix -> m () -putComb putClos putCix = \case +putComb :: (MonadPut m) => (cix -> m ()) -> GComb Void cix -> m () +putComb putCix = \case (Lam ua ba uf bf body) -> putTag LamT *> pInt ua *> pInt ba *> pInt uf *> pInt bf *> putSection putCix body - (CachedClosure w clos) -> - putTag CachedClosureT *> pWord w *> putClos clos -getComb :: (MonadGet m) => m clos -> m cix -> m (GComb clos cix) -getComb gClos gCix = - getTag >>= \case - LamT -> Lam <$> gInt <*> gInt <*> gInt <*> gInt <*> getSection gCix - CachedClosureT -> CachedClosure <$> gWord <*> gClos +getComb :: (MonadGet m) => m cix -> m (GComb clos cix) +getComb gCix = + Lam <$> gInt <*> gInt <*> gInt <*> gInt <*> getSection gCix data SectionT = AppT diff --git a/unison-runtime/src/Unison/Runtime/Machine.hs b/unison-runtime/src/Unison/Runtime/Machine.hs index 1b43a745b9..0e7073a44d 100644 --- a/unison-runtime/src/Unison/Runtime/Machine.hs +++ b/unison-runtime/src/Unison/Runtime/Machine.hs @@ -103,8 +103,13 @@ data CCache = CCache { foreignFuncs :: EnumMap Word64 ForeignFunc, sandboxed :: Bool, tracer :: Bool -> Closure -> Tracer, + -- The Combs from the original MCode before any optimizations. + -- These are used when we convert down to an SCache + srcCombs :: TVar (EnumMap Word64 Combs), combs :: TVar (EnumMap Word64 MCombs), combRefs :: TVar (EnumMap Word64 Reference), + -- Combs which we're allowed to cache after evaluating + cacheableCombs :: TVar (EnumSet Word64), tagRefs :: TVar (EnumMap Word64 Reference), freshTm :: TVar Word64, freshTy :: TVar Word64, @@ -138,8 +143,10 @@ refNumTy' cc r = M.lookup r <$> refNumsTy cc baseCCache :: Bool -> IO CCache baseCCache sandboxed = do CCache ffuncs sandboxed noTrace - <$> newTVarIO combs + <$> newTVarIO srcCombs + <*> newTVarIO combs <*> newTVarIO builtinTermBackref + <*> newTVarIO cacheableCombs <*> newTVarIO builtinTypeBackref <*> newTVarIO ftm <*> newTVarIO fty @@ -148,6 +155,7 @@ baseCCache sandboxed = do <*> newTVarIO builtinTypeNumbering <*> newTVarIO baseSandboxInfo where + cacheableCombs = mempty ffuncs | sandboxed = sandboxedForeigns | otherwise = builtinForeigns noTrace _ _ = NoTrace ftm = 1 + maximum builtinTermNumbering @@ -155,12 +163,15 @@ baseCCache sandboxed = do rns = emptyRNs {dnum = refLookup "ty" builtinTypeNumbering} - combs :: EnumMap Word64 MCombs - combs = + srcCombs :: EnumMap Word64 Combs + srcCombs = ( mapWithKey (\k v -> let r = builtinTermBackref ! k in emitComb @Symbol rns r k mempty (0, v)) numberedTermLookup ) + combs :: EnumMap Word64 MCombs + combs = + srcCombs & absurdCombs & resolveCombs Nothing From 47fd299a2946c105f85cec2b72668da7ced898d9 Mon Sep 17 00:00:00 2001 From: Chris Penner Date: Wed, 25 Sep 2024 09:54:24 -0700 Subject: [PATCH 16/40] Pre-eval constants when loading from .uc files --- .../src/Unison/Runtime/Interface.hs | 32 +++++++----- unison-runtime/src/Unison/Runtime/Machine.hs | 49 +++++++++---------- 2 files changed, 42 insertions(+), 39 deletions(-) diff --git a/unison-runtime/src/Unison/Runtime/Interface.hs b/unison-runtime/src/Unison/Runtime/Interface.hs index 9e57e774e3..dd182b61cb 100644 --- a/unison-runtime/src/Unison/Runtime/Interface.hs +++ b/unison-runtime/src/Unison/Runtime/Interface.hs @@ -108,6 +108,7 @@ import Unison.Runtime.MCode GSection (..), RCombs, RefNums (..), + absurdCombs, combDeps, combTypes, emitComb, @@ -126,6 +127,7 @@ import Unison.Runtime.Machine cacheAdd0, eval0, expandSandbox, + preEvalTopLevelConstants, refLookup, refNumTm, refNumsTm, @@ -1302,19 +1304,22 @@ tabulateErrors errs = : (listErrors errs) restoreCache :: StoredCache -> IO CCache -restoreCache (SCache cs crs cacheableCombs trs ftm fty int rtm rty sbs) = - CCache builtinForeigns False debugText - <$> newTVarIO srcCombs - <*> newTVarIO combs - <*> newTVarIO (crs <> builtinTermBackref) - <*> newTVarIO cacheableCombs - <*> newTVarIO (trs <> builtinTypeBackref) - <*> newTVarIO ftm - <*> newTVarIO fty - <*> newTVarIO int - <*> newTVarIO (rtm <> builtinTermNumbering) - <*> newTVarIO (rty <> builtinTypeNumbering) - <*> newTVarIO (sbs <> baseSandboxInfo) +restoreCache (SCache cs crs cacheableCombs trs ftm fty int rtm rty sbs) = do + cc <- + CCache builtinForeigns False debugText + <$> newTVarIO srcCombs + <*> newTVarIO combs + <*> newTVarIO (crs <> builtinTermBackref) + <*> newTVarIO cacheableCombs + <*> newTVarIO (trs <> builtinTypeBackref) + <*> newTVarIO ftm + <*> newTVarIO fty + <*> newTVarIO int + <*> newTVarIO (rtm <> builtinTermNumbering) + <*> newTVarIO (rty <> builtinTypeNumbering) + <*> newTVarIO (sbs <> baseSandboxInfo) + preEvalTopLevelConstants cacheableCombs cc + pure cc where decom = decompile @@ -1338,6 +1343,7 @@ restoreCache (SCache cs crs cacheableCombs trs ftm fty int rtm rty sbs) = combs :: EnumMap Word64 (RCombs Closure) combs = srcCombs + & absurdCombs & resolveCombs Nothing traceNeeded :: diff --git a/unison-runtime/src/Unison/Runtime/Machine.hs b/unison-runtime/src/Unison/Runtime/Machine.hs index 0e7073a44d..f8191860ff 100644 --- a/unison-runtime/src/Unison/Runtime/Machine.hs +++ b/unison-runtime/src/Unison/Runtime/Machine.hs @@ -1886,8 +1886,8 @@ yield !env !denv !activeThreads !ustk !bstk !k = leap denv k ustk <- ensure ustk uf bstk <- ensure bstk bf eval env denv activeThreads ustk bstk k (rCombRef rComb) nx - CachedClosure _w clo -> do - _ + CachedClosure _w _clo -> do + error "TODO: Get help from Dan" leap _ (CB (Hook f)) = f ustk bstk leap _ KE = pure () {-# INLINE yield #-} @@ -2148,22 +2148,13 @@ cacheAdd0 :: CCache -> IO () cacheAdd0 ntys0 termSuperGroups sands cc = do - let cacheableRefs = - termSuperGroups - & mapMaybe - ( \case - (ref, _gr, Cacheable) -> Just ref - (_ref, _gr, Uncacheable) -> Nothing - ) - & Set.fromList let toAdd = M.fromList (termSuperGroups <&> \(r, g, _) -> (r, g)) - - atomically $ do + newCacheableCombs <- atomically $ do have <- readTVar (intermed cc) let new = M.difference toAdd have - sz = fromIntegral $ M.size new - rgs = M.toList new - rs = fst <$> rgs + let sz = fromIntegral $ M.size new + let rgs = M.toList new + let rs = fst <$> rgs int <- writeTVar (intermed cc) (have <> new) rty <- addRefs (freshTy cc) (refTy cc) (tagRefs cc) ntys0 ntm <- stateTVar (freshTm cc) $ \i -> (i, i + sz) @@ -2172,26 +2163,32 @@ cacheAdd0 ntys0 termSuperGroups sands cc = do let rns = RN (refLookup "ty" rty) (refLookup "tm" rtm) combinate :: Word64 -> (Reference, SuperGroup Symbol) -> (Word64, EnumMap Word64 Comb) combinate n (r, g) = (n, emitCombs rns r n g) - nrs <- updateMap (mapFromList $ zip [ntm ..] rs) (combRefs cc) + let combRefUpdates = (mapFromList $ zip [ntm ..] rs) + let combIdFromRefMap = (M.fromList $ zip rs [ntm ..]) + let newCacheableCombs = + termSuperGroups + & mapMaybe + ( \case + (ref, _, Cacheable) -> M.lookup ref combIdFromRefMap + _ -> Nothing + ) + & EC.setFromList + newCombRefs <- updateMap combRefUpdates (combRefs cc) ncs <- modifyMap (combs cc) \oldCombs -> let newCombs :: EnumMap Word64 MCombs newCombs = resolveCombs (Just oldCombs) . absurdCombs . mapFromList $ zipWith combinate [ntm ..] rgs in newCombs <> oldCombs nsn <- updateMap (M.fromList sands) (sandbox cc) + ncc <- updateMap (newCacheableCombs) (cacheableCombs cc) -- Now that the code cache is primed with everything we need, -- we can pre-evaluate the top-level constants. - pure $ int `seq` rtm `seq` nrs `seq` ncs `seq` nsn `seq` () - preEvalTopLevelConstants cacheableRefs cc + pure $ int `seq` rtm `seq` newCombRefs `seq` ncs `seq` nsn `seq` ncc `seq` newCacheableCombs + preEvalTopLevelConstants newCacheableCombs cc -preEvalTopLevelConstants :: Set Reference -> CCache -> IO () -preEvalTopLevelConstants cacheableRefs cc = do +preEvalTopLevelConstants :: EnumSet Word64 -> CCache -> IO () +preEvalTopLevelConstants cacheableCombs cc = do activeThreads <- Just <$> UnliftIO.newIORef mempty - cmbRefs <- readTVarIO (combRefs cc) - let cacheableCombs = - EC.mapToList cmbRefs - & mapMaybe (\(w, ref) -> if ref `Set.member` cacheableRefs then Just w else Nothing) - & Set.fromList - for_ cacheableCombs \w -> do + for_ (EC.setToList cacheableCombs) \w -> do Debug.debugM Debug.Temp "Evaluating " w let hook _ustk bstk = do clos <- peek bstk From e7ca2f535676d2fdb614f6079d582aefe01798e2 Mon Sep 17 00:00:00 2001 From: Chris Penner Date: Wed, 25 Sep 2024 17:47:40 -0700 Subject: [PATCH 17/40] Start on serializing closures --- .../src/Unison/Runtime/Interface.hs | 12 ++-- .../src/Unison/Runtime/MCode/Serialize.hs | 17 +++-- .../src/Unison/Runtime/Serialize.hs | 6 ++ .../src/Unison/Runtime/Stack/Serialize.hs | 65 +++++++++++++++++-- 4 files changed, 84 insertions(+), 16 deletions(-) diff --git a/unison-runtime/src/Unison/Runtime/Interface.hs b/unison-runtime/src/Unison/Runtime/Interface.hs index dd182b61cb..e3f90f4a1f 100644 --- a/unison-runtime/src/Unison/Runtime/Interface.hs +++ b/unison-runtime/src/Unison/Runtime/Interface.hs @@ -138,6 +138,7 @@ import Unison.Runtime.Machine import Unison.Runtime.Pattern import Unison.Runtime.Serialize as SER import Unison.Runtime.Stack +import Unison.Runtime.Stack.Serialize (getClosure, putClosure) import Unison.Symbol (Symbol) import Unison.Syntax.HashQualified qualified as HQ (toText) import Unison.Syntax.NamePrinter (prettyHashQualified) @@ -1243,11 +1244,14 @@ runStandalone :: StoredCache -> CombIx -> IO (Either (Pretty ColorText) ()) runStandalone sc init = restoreCache sc >>= executeMainComb init +-- Storable closure +type SClosure = GClosure CombIx + -- | A version of the Code Cache designed to be serialized to disk as -- standalone bytecode. data StoredCache = SCache - (EnumMap Word64 Combs) + (EnumMap Word64 (GCombs SClosure CombIx)) (EnumMap Word64 Reference) (EnumSet Word64) (EnumMap Word64 Reference) @@ -1261,7 +1265,7 @@ data StoredCache putStoredCache :: (MonadPut m) => StoredCache -> m () putStoredCache (SCache cs crs cacheableCombs trs ftm fty int rtm rty sbs) = do - putEnumMap putNat (putEnumMap putNat (putComb putCombIx)) cs + putEnumMap putNat (putEnumMap putNat (putComb putClosure putCombIx)) cs putEnumMap putNat putReference crs putEnumSet putNat cacheableCombs putEnumMap putNat putReference trs @@ -1275,7 +1279,7 @@ putStoredCache (SCache cs crs cacheableCombs trs ftm fty int rtm rty sbs) = do getStoredCache :: (MonadGet m) => m StoredCache getStoredCache = SCache - <$> getEnumMap getNat (getEnumMap getNat (getComb getCombIx)) + <$> getEnumMap getNat (getEnumMap getNat (getComb getClosure getCombIx)) <*> getEnumMap getNat getReference <*> getEnumSet getNat <*> getEnumMap getNat getReference @@ -1360,7 +1364,7 @@ traceNeeded init src = fmap (`withoutKeys` ks) $ go mempty init | otherwise = die $ "traceNeeded: unknown combinator: " ++ show w buildSCache :: - EnumMap Word64 (GCombs Void CombIx) -> + EnumMap Word64 (GCombs Closure CombIx) -> EnumMap Word64 Reference -> EnumSet Word64 -> EnumMap Word64 Reference -> diff --git a/unison-runtime/src/Unison/Runtime/MCode/Serialize.hs b/unison-runtime/src/Unison/Runtime/MCode/Serialize.hs index 895a6d0216..aecf846ed1 100644 --- a/unison-runtime/src/Unison/Runtime/MCode/Serialize.hs +++ b/unison-runtime/src/Unison/Runtime/MCode/Serialize.hs @@ -15,7 +15,6 @@ import Data.Bytes.Put import Data.Bytes.Serial import Data.Bytes.VarInt import Data.Primitive.PrimArray -import Data.Void (Void) import Data.Word (Word64) import GHC.Exts (IsList (..)) import Unison.Runtime.MCode hiding (MatchT) @@ -32,14 +31,20 @@ instance Tag CombT where word2tag 1 = pure CachedClosureT word2tag n = unknownTag "CombT" n -putComb :: (MonadPut m) => (cix -> m ()) -> GComb Void cix -> m () -putComb putCix = \case +putComb :: (MonadPut m) => (clos -> m ()) -> (cix -> m ()) -> GComb clos cix -> m () +putComb putClos putCix = \case (Lam ua ba uf bf body) -> putTag LamT *> pInt ua *> pInt ba *> pInt uf *> pInt bf *> putSection putCix body + (CachedClosure w c) -> + putTag CachedClosureT *> putNat w *> putClos c -getComb :: (MonadGet m) => m cix -> m (GComb clos cix) -getComb gCix = - Lam <$> gInt <*> gInt <*> gInt <*> gInt <*> getSection gCix +getComb :: (MonadGet m) => m clos -> m cix -> m (GComb clos cix) +getComb gClos gCix = + getTag >>= \case + LamT -> + Lam <$> gInt <*> gInt <*> gInt <*> gInt <*> getSection gCix + CachedClosureT -> + CachedClosure <$> getNat <*> gClos data SectionT = AppT diff --git a/unison-runtime/src/Unison/Runtime/Serialize.hs b/unison-runtime/src/Unison/Runtime/Serialize.hs index 064200cd55..394b846a0b 100644 --- a/unison-runtime/src/Unison/Runtime/Serialize.hs +++ b/unison-runtime/src/Unison/Runtime/Serialize.hs @@ -201,6 +201,12 @@ getByteArray = PA.byteArrayFromList <$> getList getWord8 putByteArray :: (MonadPut m) => PA.ByteArray -> m () putByteArray a = putFoldable putWord8 (IL.toList a) +getArray :: (MonadGet m) => m a -> m (PA.Array a) +getArray getThing = PA.arrayFromList <$> getList getThing + +putArray :: (MonadPut m) => (a -> m ()) -> PA.Array a -> m () +putArray putThing a = putFoldable putThing (IL.toList a) + getBlock :: (MonadGet m) => m Bytes.Chunk getBlock = getLength >>= fmap Bytes.byteStringToChunk . getByteString diff --git a/unison-runtime/src/Unison/Runtime/Stack/Serialize.hs b/unison-runtime/src/Unison/Runtime/Stack/Serialize.hs index cdf6ce78a5..6c6553ad14 100644 --- a/unison-runtime/src/Unison/Runtime/Stack/Serialize.hs +++ b/unison-runtime/src/Unison/Runtime/Stack/Serialize.hs @@ -1,11 +1,64 @@ -module Unison.Runtime.Stack.Serialize (putClosure, getClosure) where +module Unison.Runtime.Stack.Serialize (putGClosure, getGClosure) where import Data.Bytes.Get import Data.Bytes.Put -import Unison.Runtime.Stack (Closure) +import Unison.Runtime.Serialize +import Unison.Runtime.Stack (Closure (..), GClosure (..)) -putClosure :: (MonadPut m) => Closure -> m () -putClosure = error "putClosure not implemented" +data GClosureT + = GPApT + | GEnumT + | GDataU1T + | GDataU2T + | GDataB1T + | GDataB2T + | GDataUBT + | GDataGT + | GCapturedT + | GForeignT + | GBlackHoleT -getClosure :: (MonadGet m) => m Closure -getClosure = error "getClosure not implemented" +instance Tag GClosureT where + tag2word = \case + GPApT -> 0 + GEnumT -> 1 + GDataU1T -> 2 + GDataU2T -> 3 + GDataB1T -> 4 + GDataB2T -> 5 + GDataUBT -> 6 + GDataGT -> 7 + GCapturedT -> 8 + GForeignT -> 9 + GBlackHoleT -> 10 + word2tag = \case + 0 -> pure GPApT + 1 -> pure GEnumT + 2 -> pure GDataU1T + 3 -> pure GDataU2T + 4 -> pure GDataB1T + 5 -> pure GDataB2T + 6 -> pure GDataUBT + 7 -> pure GDataGT + 8 -> pure GCapturedT + 9 -> pure GForeignT + 10 -> pure GBlackHoleT + n -> unknownTag "GClosureT" n + +putGClosure :: (MonadPut m) => (comb -> m ()) -> GClosure comb -> m () +putGClosure putComb = \case + GPAp comb uargs bargs -> + putTag GPApT *> putComb comb *> putByteArray uargs *> putArray (putGClosure putComb) bargs + GEnum r i -> _ + GDataU1 r w i -> _ + GDataU2 r w i j -> _ + GDataB1 r w c -> _ + GDataB2 r w c1 c2 -> _ + GDataUB r w i c -> _ + GDataG r w s1 s2 -> _ + GCaptured k i j s1 s2 -> _ + GForeign f -> _ + GBlackHole -> _ + +getGClosure :: (MonadGet m) => m Closure +getGClosure = error "getClosure not implemented" From e7d01c0f41a7b125b5fb3e3e37d423055d274c29 Mon Sep 17 00:00:00 2001 From: Chris Penner Date: Thu, 26 Sep 2024 16:32:56 -0700 Subject: [PATCH 18/40] Split CombIx out of RComb --- unison-runtime/src/Unison/Runtime/MCode.hs | 60 +++++++++---------- .../src/Unison/Runtime/MCode/Serialize.hs | 60 +++++++++---------- unison-runtime/src/Unison/Runtime/Stack.hs | 6 +- 3 files changed, 61 insertions(+), 65 deletions(-) diff --git a/unison-runtime/src/Unison/Runtime/MCode.hs b/unison-runtime/src/Unison/Runtime/MCode.hs index 03f8547cd3..7c2aae62b5 100644 --- a/unison-runtime/src/Unison/Runtime/MCode.hs +++ b/unison-runtime/src/Unison/Runtime/MCode.hs @@ -22,7 +22,6 @@ module Unison.Runtime.MCode RComb (..), pattern RCombIx, pattern RCombRef, - rCombToComb, GCombs, Combs, RCombs, @@ -454,7 +453,7 @@ data MLit | MY !Reference deriving (Show, Eq, Ord) -type Instr = GInstr CombIx +type Instr = GInstr () type RInstr = GInstr RComb @@ -527,7 +526,7 @@ data GInstr comb TryForce !Int deriving stock (Show, Eq, Ord, Functor, Foldable, Traversable) -type Section = GSection CombIx +type Section = GSection () type RSection = GSection RComb @@ -547,7 +546,8 @@ data GSection comb -- sufficient for where we're jumping to. Call !Bool -- skip stack check - !comb -- global function reference + !CombIx + {- Lazy! Might be cyclic -} comb !Args -- arguments | -- Jump to a captured continuation value. Jump @@ -564,7 +564,7 @@ data GSection comb | -- Sequence two sections. The second is pushed as a return -- point for the results of the first. Stack modifications in -- the first are lost on return to the second. - Let !(GSection comb) !comb + Let !(GSection comb) !CombIx {- Lazy! Might be cyclic -} comb | -- Throw an exception with the given message Die String | -- Immediately stop a thread of interpretation. This is more of @@ -612,7 +612,7 @@ emptyRNs = RN mt mt where mt _ = internalBug "RefNums: empty" -type Comb = GComb CombIx +type Comb = GComb () data GComb comb = Lam @@ -653,10 +653,6 @@ instance Eq RComb where instance Ord RComb where compare (RComb r1 _) (RComb r2 _) = compare r1 r2 --- | Convert an RComb to a Comb by forgetting the sections and keeping only the CombIx. -rCombToComb :: RComb -> Comb -rCombToComb (RComb _ix c) = rCombIx <$> c - -- | RCombs can be infinitely recursive so we show the CombIx instead. instance Show RComb where show (RComb ix _) = show ix @@ -665,17 +661,17 @@ instance Show RComb where type GCombs comb = EnumMap Word64 (GComb comb) -- | A reference to a combinator, parameterized by comb -type Ref = GRef CombIx +type Ref = GRef () type RRef = GRef RComb data GRef comb = Stk !Int -- stack reference to a closure - | Env !comb -- direct reference to comb, usually embedded as an RComb + | Env !CombIx {- Lazy! Might be cyclic -} comb | Dyn !Word64 -- dynamic scope reference to a closure deriving (Show, Eq, Ord, Functor, Foldable, Traversable) -type Branch = GBranch CombIx +type Branch = GBranch () type RBranch = GBranch RComb @@ -922,7 +918,7 @@ emitSection rns grpr grpn rec ctx (TLets d us ms bu bo) = ectx = pushCtx (zip us ms) ctx emitSection rns grpr grpn rec ctx (TName u (Left f) args bo) = emitClosures grpr grpn rec ctx args $ \ctx as -> - Ins (Name (Env (CIx f (cnum rns f) 0)) as) + Ins (Name (Env (CIx f (cnum rns f) 0) ()) as) <$> emitSection rns grpr grpn rec (Var u BX ctx) bo emitSection rns grpr grpn rec ctx (TName u (Right v) args bo) | Just (i, BX) <- ctxResolve ctx v = @@ -931,14 +927,14 @@ emitSection rns grpr grpn rec ctx (TName u (Right v) args bo) <$> emitSection rns grpr grpn rec (Var u BX ctx) bo | Just n <- rctxResolve rec v = emitClosures grpr grpn rec ctx args $ \ctx as -> - Ins (Name (Env (CIx grpr grpn n)) as) + Ins (Name (Env (CIx grpr grpn n) ()) as) <$> emitSection rns grpr grpn rec (Var u BX ctx) bo | otherwise = emitSectionVErr v emitSection _ grpr grpn rec ctx (TVar v) | Just (i, BX) <- ctxResolve ctx v = countCtx ctx . Yield $ BArg1 i | Just (i, UN) <- ctxResolve ctx v = countCtx ctx . Yield $ UArg1 i | Just j <- rctxResolve rec v = - countCtx ctx $ App False (Env (CIx grpr grpn j)) ZArgs + countCtx ctx $ App False (Env (CIx grpr grpn j) ()) ZArgs | otherwise = emitSectionVErr v emitSection _ _ grpn _ ctx (TPrm p args) = -- 3 is a conservative estimate of how many extra stack slots @@ -1066,12 +1062,12 @@ emitFunction _ grpr grpn rec ctx (FVar v) as | Just (i, BX) <- ctxResolve ctx v = App False (Stk i) as | Just j <- rctxResolve rec v = - App False (Env (CIx grpr grpn j)) as + App False (Env (CIx grpr grpn j) ()) as | otherwise = emitSectionVErr v emitFunction rns _grpr _ _ _ (FComb r) as | otherwise -- slow path = - App False (Env (CIx r n 0)) as + App False (Env (CIx r n 0) ()) as where n = cnum rns r emitFunction rns _grpr _ _ _ (FCon r t) as = @@ -1174,7 +1170,7 @@ emitLet rns grpr grpn rec d vcs ctx bnd <$> emitSection rns grpr grpn rec (Block ctx) bnd <*> record (pushCtx vcs ctx) w esect where - f s w = Let s (CIx grpr grpn w) + f s w = Let s (CIx grpr grpn w) () -- Translate from ANF prim ops to machine code operations. The -- machine code operations are divided with respect to more detailed @@ -1524,7 +1520,7 @@ emitClosures grpr grpn rec ctx args k = allocate ctx (a : as) k | Just _ <- ctxResolve ctx a = allocate ctx as k | Just n <- rctxResolve rec a = - Ins (Name (Env (CIx grpr grpn n)) ZArgs) <$> allocate (Var a BX ctx) as k + Ins (Name (Env (CIx grpr grpn n) ()) ZArgs) <$> allocate (Var a BX ctx) as k | otherwise = internalBug $ "emitClosures: unknown reference: " ++ show a @@ -1561,23 +1557,23 @@ combDeps (Lam _ _ _ _ s) = sectionDeps s combTypes :: Comb -> [Word64] combTypes (Lam _ _ _ _ s) = sectionTypes s -sectionDeps :: Section -> [Word64] -sectionDeps (App _ (Env (CIx _ w _)) _) = [w] -sectionDeps (Call _ (CIx _ w _) _) = [w] +sectionDeps :: GSection comb -> [Word64] +sectionDeps (App _ (Env (CIx _ w _) _) _) = [w] +sectionDeps (Call _ (CIx _ w _) _ _) = [w] sectionDeps (Match _ br) = branchDeps br sectionDeps (DMatch _ _ br) = branchDeps br sectionDeps (RMatch _ pu br) = sectionDeps pu ++ foldMap branchDeps br sectionDeps (NMatch _ _ br) = branchDeps br sectionDeps (Ins i s) - | Name (Env (CIx _ w _)) _ <- i = w : sectionDeps s + | Name (Env (CIx _ w _) _) _ <- i = w : sectionDeps s | otherwise = sectionDeps s -sectionDeps (Let s (CIx _ w _)) = w : sectionDeps s +sectionDeps (Let s (CIx _ w _) _) = w : sectionDeps s sectionDeps _ = [] sectionTypes :: Section -> [Word64] sectionTypes (Ins i s) = instrTypes i ++ sectionTypes s -sectionTypes (Let s _) = sectionTypes s +sectionTypes (Let s _ _) = sectionTypes s sectionTypes (Match _ br) = branchTypes br sectionTypes (DMatch _ _ br) = branchTypes br sectionTypes (NMatch _ _ br) = branchTypes br @@ -1592,7 +1588,7 @@ instrTypes (Capture w) = [w] instrTypes (SetDyn w _) = [w] instrTypes _ = [] -branchDeps :: Branch -> [Word64] +branchDeps :: GBranch comb -> [Word64] branchDeps (Test1 _ s1 d) = sectionDeps s1 ++ sectionDeps d branchDeps (Test2 _ s1 _ s2 d) = sectionDeps s1 ++ sectionDeps s2 ++ sectionDeps d @@ -1632,7 +1628,7 @@ prettyComb w i (Lam ua ba _ _ s) = . showString ":\n" . prettySection 2 s -prettySection :: Int -> Section -> ShowS +prettySection :: (Show comb) => Int -> GSection comb -> ShowS prettySection ind sec = indent ind . case sec of App _ r as -> @@ -1640,7 +1636,7 @@ prettySection ind sec = . showsPrec 12 r . showString " " . prettyArgs as - Call _ i as -> + Call _ i _ as -> showString "Call " . shows i . showString " " . prettyArgs as Jump i as -> showString "Jump " . shows i . showString " " . prettyArgs as @@ -1652,7 +1648,7 @@ prettySection ind sec = Yield as -> showString "Yield " . prettyArgs as Ins i nx -> prettyIns i . showString "\n" . prettySection ind nx - Let s n -> + Let s n _ -> showString "Let\n" . prettySection (ind + 2) s . showString "\n" @@ -1691,7 +1687,7 @@ prettyIx (CIx _ c s) = . shows s . showString "]" -prettyBranches :: Int -> Branch -> ShowS +prettyBranches :: (Show comb) => Int -> GBranch comb -> ShowS prettyBranches ind bs = case bs of Test1 i e df -> pdf df . picase i e @@ -1721,7 +1717,7 @@ un = ('U' :) bx :: ShowS bx = ('B' :) -prettyIns :: Instr -> ShowS +prettyIns :: (Show comb) => GInstr comb -> ShowS prettyIns (Pack r i as) = showString "Pack " . showsPrec 10 r diff --git a/unison-runtime/src/Unison/Runtime/MCode/Serialize.hs b/unison-runtime/src/Unison/Runtime/MCode/Serialize.hs index d64b52065a..5d7e6339fd 100644 --- a/unison-runtime/src/Unison/Runtime/MCode/Serialize.hs +++ b/unison-runtime/src/Unison/Runtime/MCode/Serialize.hs @@ -25,8 +25,8 @@ putComb :: (MonadPut m) => (cix -> m ()) -> GComb cix -> m () putComb putCix (Lam ua ba uf bf body) = pInt ua *> pInt ba *> pInt uf *> pInt bf *> putSection putCix body -getComb :: (MonadGet m) => m cix -> m (GComb cix) -getComb gCix = Lam <$> gInt <*> gInt <*> gInt <*> gInt <*> (getSection gCix) +getComb :: (MonadGet m) => m Comb +getComb = Lam <$> gInt <*> gInt <*> gInt <*> gInt <*> getSection data SectionT = AppT @@ -72,13 +72,13 @@ instance Tag SectionT where putSection :: (MonadPut m) => (cix -> m ()) -> GSection cix -> m () putSection pCix = \case - App b r a -> putTag AppT *> serialize b *> putRef pCix r *> putArgs a - Call b cix a -> putTag CallT *> serialize b *> pCix cix *> putArgs a + App b r a -> putTag AppT *> serialize b *> putRef r *> putArgs a + Call b cix _comb a -> putTag CallT *> serialize b *> putCombIx cix *> putArgs a Jump i a -> putTag JumpT *> pInt i *> putArgs a Match i b -> putTag MatchT *> pInt i *> putBranch pCix b Yield a -> putTag YieldT *> putArgs a Ins i s -> putTag InsT *> putInstr pCix i *> putSection pCix s - Let s ci -> putTag LetT *> putSection pCix s *> pCix ci + Let s ci _comb -> putTag LetT *> putSection pCix s *> putCombIx ci Die s -> putTag DieT *> serialize s Exit -> putTag ExitT DMatch mr i b -> putTag DMatchT *> putMaybe mr putReference *> pInt i *> putBranch pCix b @@ -89,15 +89,15 @@ putSection pCix = \case *> putSection pCix pu *> putEnumMap pWord (putBranch pCix) bs -getSection :: (MonadGet m) => m cix -> m (GSection cix) -getSection gCix = +getSection :: (MonadGet m) => m Section +getSection = getTag >>= \case - AppT -> App <$> deserialize <*> getRef gCix <*> getArgs - CallT -> Call <$> deserialize <*> gCix <*> getArgs + AppT -> App <$> deserialize <*> getRef <*> getArgs + CallT -> Call <$> deserialize <*> getCombIx <*> pure () <*> getArgs JumpT -> Jump <$> gInt <*> getArgs - MatchT -> Match <$> gInt <*> getBranch gCix + MatchT -> Match <$> gInt <*> getBranch YieldT -> Yield <$> getArgs - InsT -> Ins <$> getInstr gCix <*> getSection gCix + InsT -> Ins <$> getInstr <*> getSection LetT -> Let <$> getSection gCix <*> gCix DieT -> Die <$> deserialize ExitT -> pure Exit @@ -178,7 +178,7 @@ putInstr pCix = \case (ForeignCall b w a) -> putTag ForeignCallT *> serialize b *> pWord w *> putArgs a (SetDyn w i) -> putTag SetDynT *> pWord w *> pInt i (Capture w) -> putTag CaptureT *> pWord w - (Name r a) -> putTag NameT *> putRef pCix r *> putArgs a + (Name r a) -> putTag NameT *> putRef r *> putArgs a (Info s) -> putTag InfoT *> serialize s (Pack r w a) -> putTag PackT *> putReference r *> pWord w *> putArgs a (Unpack mr i) -> putTag UnpackT *> putMaybe mr putReference *> pInt i @@ -191,8 +191,8 @@ putInstr pCix = \case (Seq a) -> putTag SeqT *> putArgs a (TryForce i) -> putTag TryForceT *> pInt i -getInstr :: (MonadGet m) => m cix -> m (GInstr cix) -getInstr gCix = +getInstr :: (MonadGet m) => m Instr +getInstr = getTag >>= \case UPrim1T -> UPrim1 <$> getTag <*> gInt UPrim2T -> UPrim2 <$> getTag <*> gInt <*> gInt @@ -201,7 +201,7 @@ getInstr gCix = ForeignCallT -> ForeignCall <$> deserialize <*> gWord <*> getArgs SetDynT -> SetDyn <$> gWord <*> gInt CaptureT -> Capture <$> gWord - NameT -> Name <$> getRef gCix <*> getArgs + NameT -> Name <$> getRef <*> getArgs InfoT -> Info <$> deserialize PackT -> Pack <$> getReference <*> gWord <*> getArgs UnpackT -> Unpack <$> getMaybe getReference <*> gInt @@ -305,16 +305,16 @@ instance Tag RefT where word2tag 2 = pure DynT word2tag n = unknownTag "RefT" n -putRef :: (MonadPut m) => (cix -> m ()) -> GRef cix -> m () -putRef _pCix (Stk i) = putTag StkT *> pInt i -putRef pCix (Env cix) = putTag EnvT *> pCix cix -putRef _pCix (Dyn i) = putTag DynT *> pWord i +putRef :: (MonadPut m) => GRef cix -> m () +putRef (Stk i) = putTag StkT *> pInt i +putRef (Env cix _) = putTag EnvT *> putCombIx cix +putRef (Dyn i) = putTag DynT *> pWord i -getRef :: (MonadGet m) => m cix -> m (GRef cix) -getRef gCix = +getRef :: (MonadGet m) => m Ref +getRef = getTag >>= \case StkT -> Stk <$> gInt - EnvT -> Env <$> gCix + EnvT -> Env <$> getCombIx <*> pure () DynT -> Dyn <$> gWord putCombIx :: (MonadPut m) => CombIx -> m () @@ -384,19 +384,19 @@ putBranch pCix (TestW d m) = putBranch pCix (TestT d m) = putTag TestTT *> putSection pCix d *> putMap (putText . Util.Text.toText) (putSection pCix) m -getBranch :: (MonadGet m) => m cix -> m (GBranch cix) -getBranch gCix = +getBranch :: (MonadGet m) => m Branch +getBranch = getTag >>= \case - Test1T -> Test1 <$> gWord <*> getSection gCix <*> getSection gCix + Test1T -> Test1 <$> gWord <*> getSection <*> getSection Test2T -> Test2 <$> gWord - <*> getSection gCix + <*> getSection <*> gWord - <*> getSection gCix - <*> getSection gCix - TestWT -> TestW <$> getSection gCix <*> getEnumMap gWord (getSection gCix) - TestTT -> TestT <$> getSection gCix <*> getMap (Util.Text.fromText <$> getText) (getSection gCix) + <*> getSection + <*> getSection + TestWT -> TestW <$> getSection <*> getEnumMap gWord getSection + TestTT -> TestT <$> getSection <*> getMap (Util.Text.fromText <$> getText) getSection gInt :: (MonadGet m) => m Int gInt = unVarInt <$> deserialize diff --git a/unison-runtime/src/Unison/Runtime/Stack.hs b/unison-runtime/src/Unison/Runtime/Stack.hs index b85707b1b3..db69b75826 100644 --- a/unison-runtime/src/Unison/Runtime/Stack.hs +++ b/unison-runtime/src/Unison/Runtime/Stack.hs @@ -100,7 +100,7 @@ type Closure = GClosure RComb data GClosure comb = PAp - !comb + {- Lazy! Might be cyclic -} comb {-# UNPACK #-} !(Seg 'UN) -- unboxed args {- unpack -} !(Seg 'BX) -- boxed args @@ -348,8 +348,8 @@ class MEM (b :: Mem) where asize :: Stack b -> SZ instance MEM 'UN where - data Stack 'UN = - -- Note: uap <= ufp <= usp + data Stack 'UN + = -- Note: uap <= ufp <= usp US { uap :: !Int, -- arg pointer ufp :: !Int, -- frame pointer From 699a23d2908aa4ad26c046f918bae7afa282a948 Mon Sep 17 00:00:00 2001 From: Chris Penner Date: Thu, 26 Sep 2024 17:14:13 -0700 Subject: [PATCH 19/40] Successfully split of CombIx --- .../src/Unison/Runtime/Interface.hs | 6 +- unison-runtime/src/Unison/Runtime/MCode.hs | 36 ++++++---- .../src/Unison/Runtime/MCode/Serialize.hs | 71 +++++++++++-------- unison-runtime/src/Unison/Runtime/Machine.hs | 8 +-- 4 files changed, 69 insertions(+), 52 deletions(-) diff --git a/unison-runtime/src/Unison/Runtime/Interface.hs b/unison-runtime/src/Unison/Runtime/Interface.hs index 103242c8d4..7c9c17aea8 100644 --- a/unison-runtime/src/Unison/Runtime/Interface.hs +++ b/unison-runtime/src/Unison/Runtime/Interface.hs @@ -1006,7 +1006,7 @@ executeMainComb :: CCache -> IO (Either (Pretty ColorText) ()) executeMainComb init cc = do - rSection <- resolveSection cc $ Ins (Pack RF.unitRef 0 ZArgs) $ Call True init (BArg1 0) + rSection <- resolveSection cc $ Ins (Pack RF.unitRef 0 ZArgs) $ Call True init init (BArg1 0) result <- UnliftIO.try . eval0 cc Nothing $ rSection case result of @@ -1218,7 +1218,7 @@ data StoredCache putStoredCache :: (MonadPut m) => StoredCache -> m () putStoredCache (SCache cs crs trs ftm fty int rtm rty sbs) = do - putEnumMap putNat (putEnumMap putNat (putComb putCombIx)) cs + putEnumMap putNat (putEnumMap putNat putComb) cs putEnumMap putNat putReference crs putEnumMap putNat putReference trs putNat ftm @@ -1231,7 +1231,7 @@ putStoredCache (SCache cs crs trs ftm fty int rtm rty sbs) = do getStoredCache :: (MonadGet m) => m StoredCache getStoredCache = SCache - <$> getEnumMap getNat (getEnumMap getNat (getComb getCombIx)) + <$> getEnumMap getNat (getEnumMap getNat getComb) <*> getEnumMap getNat getReference <*> getEnumMap getNat getReference <*> getNat diff --git a/unison-runtime/src/Unison/Runtime/MCode.hs b/unison-runtime/src/Unison/Runtime/MCode.hs index 7c2aae62b5..37f1a9ae7a 100644 --- a/unison-runtime/src/Unison/Runtime/MCode.hs +++ b/unison-runtime/src/Unison/Runtime/MCode.hs @@ -453,7 +453,7 @@ data MLit | MY !Reference deriving (Show, Eq, Ord) -type Instr = GInstr () +type Instr = GInstr CombIx type RInstr = GInstr RComb @@ -526,7 +526,7 @@ data GInstr comb TryForce !Int deriving stock (Show, Eq, Ord, Functor, Foldable, Traversable) -type Section = GSection () +type Section = GSection CombIx type RSection = GSection RComb @@ -612,7 +612,7 @@ emptyRNs = RN mt mt where mt _ = internalBug "RefNums: empty" -type Comb = GComb () +type Comb = GComb CombIx data GComb comb = Lam @@ -661,7 +661,7 @@ instance Show RComb where type GCombs comb = EnumMap Word64 (GComb comb) -- | A reference to a combinator, parameterized by comb -type Ref = GRef () +type Ref = GRef CombIx type RRef = GRef RComb @@ -671,7 +671,7 @@ data GRef comb | Dyn !Word64 -- dynamic scope reference to a closure deriving (Show, Eq, Ord, Functor, Foldable, Traversable) -type Branch = GBranch () +type Branch = GBranch CombIx type RBranch = GBranch RComb @@ -918,8 +918,9 @@ emitSection rns grpr grpn rec ctx (TLets d us ms bu bo) = ectx = pushCtx (zip us ms) ctx emitSection rns grpr grpn rec ctx (TName u (Left f) args bo) = emitClosures grpr grpn rec ctx args $ \ctx as -> - Ins (Name (Env (CIx f (cnum rns f) 0) ()) as) - <$> emitSection rns grpr grpn rec (Var u BX ctx) bo + let cix = (CIx f (cnum rns f) 0) + in Ins (Name (Env cix cix) as) + <$> emitSection rns grpr grpn rec (Var u BX ctx) bo emitSection rns grpr grpn rec ctx (TName u (Right v) args bo) | Just (i, BX) <- ctxResolve ctx v = emitClosures grpr grpn rec ctx args $ \ctx as -> @@ -927,14 +928,16 @@ emitSection rns grpr grpn rec ctx (TName u (Right v) args bo) <$> emitSection rns grpr grpn rec (Var u BX ctx) bo | Just n <- rctxResolve rec v = emitClosures grpr grpn rec ctx args $ \ctx as -> - Ins (Name (Env (CIx grpr grpn n) ()) as) - <$> emitSection rns grpr grpn rec (Var u BX ctx) bo + let cix = (CIx grpr grpn n) + in Ins (Name (Env cix cix) as) + <$> emitSection rns grpr grpn rec (Var u BX ctx) bo | otherwise = emitSectionVErr v emitSection _ grpr grpn rec ctx (TVar v) | Just (i, BX) <- ctxResolve ctx v = countCtx ctx . Yield $ BArg1 i | Just (i, UN) <- ctxResolve ctx v = countCtx ctx . Yield $ UArg1 i | Just j <- rctxResolve rec v = - countCtx ctx $ App False (Env (CIx grpr grpn j) ()) ZArgs + let cix = (CIx grpr grpn j) + in countCtx ctx $ App False (Env cix cix) ZArgs | otherwise = emitSectionVErr v emitSection _ _ grpn _ ctx (TPrm p args) = -- 3 is a conservative estimate of how many extra stack slots @@ -1062,12 +1065,14 @@ emitFunction _ grpr grpn rec ctx (FVar v) as | Just (i, BX) <- ctxResolve ctx v = App False (Stk i) as | Just j <- rctxResolve rec v = - App False (Env (CIx grpr grpn j) ()) as + let cix = CIx grpr grpn j + in App False (Env cix cix) as | otherwise = emitSectionVErr v emitFunction rns _grpr _ _ _ (FComb r) as | otherwise -- slow path = - App False (Env (CIx r n 0) ()) as + let cix = CIx r n 0 + in App False (Env cix cix) as where n = cnum rns r emitFunction rns _grpr _ _ _ (FCon r t) as = @@ -1170,7 +1175,9 @@ emitLet rns grpr grpn rec d vcs ctx bnd <$> emitSection rns grpr grpn rec (Block ctx) bnd <*> record (pushCtx vcs ctx) w esect where - f s w = Let s (CIx grpr grpn w) () + f s w = + let cix = (CIx grpr grpn w) + in Let s cix cix -- Translate from ANF prim ops to machine code operations. The -- machine code operations are divided with respect to more detailed @@ -1520,7 +1527,8 @@ emitClosures grpr grpn rec ctx args k = allocate ctx (a : as) k | Just _ <- ctxResolve ctx a = allocate ctx as k | Just n <- rctxResolve rec a = - Ins (Name (Env (CIx grpr grpn n) ()) ZArgs) <$> allocate (Var a BX ctx) as k + let cix = (CIx grpr grpn n) + in Ins (Name (Env cix cix) ZArgs) <$> allocate (Var a BX ctx) as k | otherwise = internalBug $ "emitClosures: unknown reference: " ++ show a diff --git a/unison-runtime/src/Unison/Runtime/MCode/Serialize.hs b/unison-runtime/src/Unison/Runtime/MCode/Serialize.hs index 5d7e6339fd..36a587c067 100644 --- a/unison-runtime/src/Unison/Runtime/MCode/Serialize.hs +++ b/unison-runtime/src/Unison/Runtime/MCode/Serialize.hs @@ -21,9 +21,9 @@ import Unison.Runtime.MCode hiding (MatchT) import Unison.Runtime.Serialize import Unison.Util.Text qualified as Util.Text -putComb :: (MonadPut m) => (cix -> m ()) -> GComb cix -> m () -putComb putCix (Lam ua ba uf bf body) = - pInt ua *> pInt ba *> pInt uf *> pInt bf *> putSection putCix body +putComb :: (MonadPut m) => GComb cix -> m () +putComb (Lam ua ba uf bf body) = + pInt ua *> pInt ba *> pInt uf *> pInt bf *> putSection body getComb :: (MonadGet m) => m Comb getComb = Lam <$> gInt <*> gInt <*> gInt <*> gInt <*> getSection @@ -70,41 +70,48 @@ instance Tag SectionT where word2tag 11 = pure RMatchT word2tag i = unknownTag "SectionT" i -putSection :: (MonadPut m) => (cix -> m ()) -> GSection cix -> m () -putSection pCix = \case +putSection :: (MonadPut m) => GSection cix -> m () +putSection = \case App b r a -> putTag AppT *> serialize b *> putRef r *> putArgs a Call b cix _comb a -> putTag CallT *> serialize b *> putCombIx cix *> putArgs a Jump i a -> putTag JumpT *> pInt i *> putArgs a - Match i b -> putTag MatchT *> pInt i *> putBranch pCix b + Match i b -> putTag MatchT *> pInt i *> putBranch b Yield a -> putTag YieldT *> putArgs a - Ins i s -> putTag InsT *> putInstr pCix i *> putSection pCix s - Let s ci _comb -> putTag LetT *> putSection pCix s *> putCombIx ci + Ins i s -> putTag InsT *> putInstr i *> putSection s + Let s ci _comb -> putTag LetT *> putSection s *> putCombIx ci Die s -> putTag DieT *> serialize s Exit -> putTag ExitT - DMatch mr i b -> putTag DMatchT *> putMaybe mr putReference *> pInt i *> putBranch pCix b - NMatch mr i b -> putTag NMatchT *> putMaybe mr putReference *> pInt i *> putBranch pCix b + DMatch mr i b -> putTag DMatchT *> putMaybe mr putReference *> pInt i *> putBranch b + NMatch mr i b -> putTag NMatchT *> putMaybe mr putReference *> pInt i *> putBranch b RMatch i pu bs -> putTag RMatchT *> pInt i - *> putSection pCix pu - *> putEnumMap pWord (putBranch pCix) bs + *> putSection pu + *> putEnumMap pWord putBranch bs getSection :: (MonadGet m) => m Section getSection = getTag >>= \case AppT -> App <$> deserialize <*> getRef <*> getArgs - CallT -> Call <$> deserialize <*> getCombIx <*> pure () <*> getArgs + CallT -> do + skipCheck <- deserialize + cix <- getCombIx + args <- getArgs + pure $ Call skipCheck cix cix args JumpT -> Jump <$> gInt <*> getArgs MatchT -> Match <$> gInt <*> getBranch YieldT -> Yield <$> getArgs InsT -> Ins <$> getInstr <*> getSection - LetT -> Let <$> getSection gCix <*> gCix + LetT -> do + s <- getSection + cix <- getCombIx + pure $ Let s cix cix DieT -> Die <$> deserialize ExitT -> pure Exit - DMatchT -> DMatch <$> getMaybe getReference <*> gInt <*> getBranch gCix - NMatchT -> NMatch <$> getMaybe getReference <*> gInt <*> getBranch gCix + DMatchT -> DMatch <$> getMaybe getReference <*> gInt <*> getBranch + NMatchT -> NMatch <$> getMaybe getReference <*> gInt <*> getBranch RMatchT -> - RMatch <$> gInt <*> getSection gCix <*> getEnumMap gWord (getBranch gCix) + RMatch <$> gInt <*> getSection <*> getEnumMap gWord getBranch data InstrT = UPrim1T @@ -169,8 +176,8 @@ instance Tag InstrT where word2tag 18 = pure BLitT word2tag n = unknownTag "InstrT" n -putInstr :: (MonadPut m) => (cix -> m ()) -> GInstr cix -> m () -putInstr pCix = \case +putInstr :: (MonadPut m) => GInstr cix -> m () +putInstr = \case (UPrim1 up i) -> putTag UPrim1T *> putTag up *> pInt i (UPrim2 up i j) -> putTag UPrim2T *> putTag up *> pInt i *> pInt j (BPrim1 bp i) -> putTag BPrim1T *> putTag bp *> pInt i @@ -314,7 +321,9 @@ getRef :: (MonadGet m) => m Ref getRef = getTag >>= \case StkT -> Stk <$> gInt - EnvT -> Env <$> getCombIx <*> pure () + EnvT -> do + cix <- getCombIx + pure $ Env cix cix DynT -> Dyn <$> gWord putCombIx :: (MonadPut m) => CombIx -> m () @@ -369,20 +378,20 @@ instance Tag BranchT where word2tag 3 = pure TestTT word2tag n = unknownTag "BranchT" n -putBranch :: (MonadPut m) => (cix -> m ()) -> GBranch cix -> m () -putBranch pCix (Test1 w s d) = - putTag Test1T *> pWord w *> putSection pCix s *> putSection pCix d -putBranch pCix (Test2 a sa b sb d) = +putBranch :: (MonadPut m) => GBranch cix -> m () +putBranch (Test1 w s d) = + putTag Test1T *> pWord w *> putSection s *> putSection d +putBranch (Test2 a sa b sb d) = putTag Test2T *> pWord a - *> putSection pCix sa + *> putSection sa *> pWord b - *> putSection pCix sb - *> putSection pCix d -putBranch pCix (TestW d m) = - putTag TestWT *> putSection pCix d *> putEnumMap pWord (putSection pCix) m -putBranch pCix (TestT d m) = - putTag TestTT *> putSection pCix d *> putMap (putText . Util.Text.toText) (putSection pCix) m + *> putSection sb + *> putSection d +putBranch (TestW d m) = + putTag TestWT *> putSection d *> putEnumMap pWord putSection m +putBranch (TestT d m) = + putTag TestTT *> putSection d *> putMap (putText . Util.Text.toText) putSection m getBranch :: (MonadGet m) => m Branch getBranch = diff --git a/unison-runtime/src/Unison/Runtime/Machine.hs b/unison-runtime/src/Unison/Runtime/Machine.hs index 11e7941b41..6f5e017157 100644 --- a/unison-runtime/src/Unison/Runtime/Machine.hs +++ b/unison-runtime/src/Unison/Runtime/Machine.hs @@ -632,14 +632,14 @@ eval !env !denv !activeThreads !ustk !bstk !k _ (Yield args) eval !env !denv !activeThreads !ustk !bstk !k _ (App ck r args) = resolve env denv bstk r >>= apply env denv activeThreads ustk bstk k ck args -eval !env !denv !activeThreads !ustk !bstk !k _ (Call ck rcomb args) = +eval !env !denv !activeThreads !ustk !bstk !k _ (Call ck _combIx rcomb args) = enter env denv activeThreads ustk bstk k ck args rcomb eval !env !denv !activeThreads !ustk !bstk !k _ (Jump i args) = peekOff bstk i >>= jump env denv activeThreads ustk bstk k args -eval !env !denv !activeThreads !ustk !bstk !k r (Let nw cix) = do +eval !env !denv !activeThreads !ustk !bstk !k r (Let nw _combIx comb) = do (ustk, ufsz, uasz) <- saveFrame ustk (bstk, bfsz, basz) <- saveFrame bstk - eval env denv activeThreads ustk bstk (Push ufsz bfsz uasz basz cix k) r nw + eval env denv activeThreads ustk bstk (Push ufsz bfsz uasz basz comb k) r nw eval !env !denv !activeThreads !ustk !bstk !k r (Ins i nx) = do (denv, ustk, bstk, k) <- exec env denv activeThreads ustk bstk k r i eval env denv activeThreads ustk bstk k r nx @@ -1919,7 +1919,7 @@ discardCont denv ustk bstk k p = {-# INLINE discardCont #-} resolve :: CCache -> DEnv -> Stack 'BX -> RRef -> IO Closure -resolve _ _ _ (Env rComb) = pure $ PAp rComb unull bnull +resolve _ _ _ (Env _cix rComb) = pure $ PAp rComb unull bnull resolve _ _ bstk (Stk i) = peekOff bstk i resolve env denv _ (Dyn i) = case EC.lookup i denv of Just clo -> pure clo From 2fb33a2c69dbcec0c6175fb08ff4f4c6a9841ec4 Mon Sep 17 00:00:00 2001 From: Chris Penner Date: Thu, 26 Sep 2024 17:45:42 -0700 Subject: [PATCH 20/40] Handle serializing/deserializing split up combs --- .../src/Unison/Runtime/Decompile.hs | 6 +- .../src/Unison/Runtime/Interface.hs | 28 +++---- unison-runtime/src/Unison/Runtime/MCode.hs | 48 +++-------- unison-runtime/src/Unison/Runtime/Machine.hs | 82 ++++++++++--------- unison-runtime/src/Unison/Runtime/Stack.hs | 56 ++++++++++--- 5 files changed, 114 insertions(+), 106 deletions(-) diff --git a/unison-runtime/src/Unison/Runtime/Decompile.hs b/unison-runtime/src/Unison/Runtime/Decompile.hs index 13084ea1dc..1dc7f3f5d0 100644 --- a/unison-runtime/src/Unison/Runtime/Decompile.hs +++ b/unison-runtime/src/Unison/Runtime/Decompile.hs @@ -32,7 +32,7 @@ import Unison.Runtime.Foreign maybeUnwrapForeign, ) import Unison.Runtime.IOSource (iarrayFromListRef, ibarrayFromBytesRef) -import Unison.Runtime.MCode (CombIx (..), pattern RCombIx, pattern RCombRef) +import Unison.Runtime.MCode (CombIx (..)) import Unison.Runtime.Stack ( Closure, GClosure (..), @@ -162,7 +162,7 @@ decompile backref topTerms (DataC rf _ [] [b]) app () (builtin () "Any.Any") <$> decompile backref topTerms b decompile backref topTerms (DataC rf (maskTags -> ct) [] bs) = apps' (con rf ct) <$> traverse (decompile backref topTerms) bs -decompile backref topTerms (PApV (RCombIx (CIx rf rt k)) [] bs) +decompile backref topTerms (PApV (CIx rf rt k) _ [] bs) | rf == Builtin "jumpCont" = err Cont $ bug "" | Builtin nm <- rf = apps' (builtin () nm) <$> traverse (decompile backref topTerms) bs @@ -173,7 +173,7 @@ decompile backref topTerms (PApV (RCombIx (CIx rf rt k)) [] bs) Just _ <- topTerms rt 0 = err (UnkLocal rf k) $ bug "" | otherwise = err (UnkComb rf) $ ref () rf -decompile _ _ (PAp (RCombRef rf) _ _) = +decompile _ _ (PAp (CIx rf _ _) _ _ _) = err (BadPAp rf) $ bug "" decompile _ _ (DataC rf _ _ _) = err (BadData rf) $ bug "" decompile _ _ BlackHole = err Exn $ bug "" diff --git a/unison-runtime/src/Unison/Runtime/Interface.hs b/unison-runtime/src/Unison/Runtime/Interface.hs index 7c9c17aea8..062a286167 100644 --- a/unison-runtime/src/Unison/Runtime/Interface.hs +++ b/unison-runtime/src/Unison/Runtime/Interface.hs @@ -101,7 +101,7 @@ import Unison.Runtime.Exception import Unison.Runtime.MCode ( Args (..), CombIx (..), - Combs, + GCombs, GInstr (..), GSection (..), RCombs, @@ -110,7 +110,6 @@ import Unison.Runtime.MCode combTypes, emitComb, emptyRNs, - rCombIx, resolveCombs, ) import Unison.Runtime.MCode.Serialize @@ -1130,7 +1129,7 @@ catchInternalErrors sub = sub `UnliftIO.catch` hCE `UnliftIO.catch` hRE decodeStandalone :: BL.ByteString -> - Either String (Text, Text, CombIx, StoredCache) + Either String (Text, Text, CombIx, StoredCache CombIx) decodeStandalone b = bimap thd thd $ runGetOrFail g b where thd (_, _, x) = x @@ -1197,15 +1196,15 @@ tryM = hRE (PE _ e) = pure $ Just e hRE (BU _ _ _) = pure $ Just "impossible" -runStandalone :: StoredCache -> CombIx -> IO (Either (Pretty ColorText) ()) +runStandalone :: StoredCache CombIx -> CombIx -> IO (Either (Pretty ColorText) ()) runStandalone sc init = restoreCache sc >>= executeMainComb init -- | A version of the Code Cache designed to be serialized to disk as -- standalone bytecode. -data StoredCache +data StoredCache comb = SCache - (EnumMap Word64 Combs) + (EnumMap Word64 (GCombs comb)) (EnumMap Word64 Reference) (EnumMap Word64 Reference) Word64 @@ -1216,7 +1215,7 @@ data StoredCache (Map Reference (Set Reference)) deriving (Show) -putStoredCache :: (MonadPut m) => StoredCache -> m () +putStoredCache :: (MonadPut m) => StoredCache comb -> m () putStoredCache (SCache cs crs trs ftm fty int rtm rty sbs) = do putEnumMap putNat (putEnumMap putNat putComb) cs putEnumMap putNat putReference crs @@ -1228,7 +1227,7 @@ putStoredCache (SCache cs crs trs ftm fty int rtm rty sbs) = do putMap putReference putNat rty putMap putReference (putFoldable putReference) sbs -getStoredCache :: (MonadGet m) => m StoredCache +getStoredCache :: (MonadGet m) => m (StoredCache CombIx) getStoredCache = SCache <$> getEnumMap getNat (getEnumMap getNat getComb) @@ -1258,7 +1257,7 @@ tabulateErrors errs = : P.wrap "The following errors occured while decompiling:" : (listErrors errs) -restoreCache :: StoredCache -> IO CCache +restoreCache :: StoredCache CombIx -> IO CCache restoreCache (SCache cs crs trs ftm fty int rtm rty sbs) = CCache builtinForeigns False debugText <$> newTVarIO combs @@ -1302,11 +1301,11 @@ traceNeeded init src = fmap (`withoutKeys` ks) $ go mempty init go acc w | hasKey w acc = pure acc | Just co <- EC.lookup w src = - foldlM go (mapInsert w co acc) (foldMap (combDeps . fmap rCombIx) co) + foldlM go (mapInsert w co acc) (foldMap combDeps co) | otherwise = die $ "traceNeeded: unknown combinator: " ++ show w buildSCache :: - EnumMap Word64 Combs -> + EnumMap Word64 (GCombs ()) -> EnumMap Word64 Reference -> EnumMap Word64 Reference -> Word64 -> @@ -1315,7 +1314,7 @@ buildSCache :: Map Reference Word64 -> Map Reference Word64 -> Map Reference (Set Reference) -> - StoredCache + StoredCache () buildSCache cs crsrc trsrc ftm fty intsrc rtmsrc rtysrc sndbx = SCache cs @@ -1343,7 +1342,7 @@ buildSCache cs crsrc trsrc ftm fty intsrc rtmsrc rtysrc sndbx = restrictTyW m = restrictKeys m typeKeys restrictTyR m = Map.restrictKeys m typeRefs -standalone :: CCache -> Word64 -> IO StoredCache +standalone :: CCache -> Word64 -> IO (StoredCache ()) standalone cc init = buildSCache <$> (readTVarIO (combs cc) >>= traceNeeded init >>= pure . unTieRCombs) @@ -1356,5 +1355,4 @@ standalone cc init = <*> readTVarIO (refTy cc) <*> readTVarIO (sandbox cc) where - unTieRCombs :: EnumMap Word64 RCombs -> EnumMap Word64 Combs - unTieRCombs = fmap . fmap . fmap $ rCombIx + unTieRCombs = fmap . fmap . fmap $ const () diff --git a/unison-runtime/src/Unison/Runtime/MCode.hs b/unison-runtime/src/Unison/Runtime/MCode.hs index 37f1a9ae7a..47dce5ce01 100644 --- a/unison-runtime/src/Unison/Runtime/MCode.hs +++ b/unison-runtime/src/Unison/Runtime/MCode.hs @@ -20,8 +20,6 @@ module Unison.Runtime.MCode GComb (..), Comb, RComb (..), - pattern RCombIx, - pattern RCombRef, GCombs, Combs, RCombs, @@ -44,7 +42,6 @@ module Unison.Runtime.MCode emptyRNs, argsToLists, combRef, - rCombRef, combDeps, combTypes, prettyCombs, @@ -599,9 +596,6 @@ data CombIx combRef :: CombIx -> Reference combRef (CIx r _ _) = r -rCombRef :: RComb -> Reference -rCombRef (RComb cix _) = combRef cix - data RefNums = RN { dnum :: Reference -> Word64, cnum :: Reference -> Word64 @@ -627,35 +621,13 @@ type Combs = GCombs CombIx type RCombs = GCombs RComb --- | Extract the CombIx from an RComb. -pattern RCombIx :: CombIx -> RComb -pattern RCombIx r <- (rCombIx -> r) - -{-# COMPLETE RCombIx #-} - --- | Extract the Reference from an RComb. -pattern RCombRef :: Reference -> RComb -pattern RCombRef r <- (combRef . rCombIx -> r) - -{-# COMPLETE RCombRef #-} - -- | The fixed point of a GComb where all references to a Comb are themselves Combs. -data RComb = RComb - { rCombIx :: !CombIx, - unRComb :: (GComb RComb {- Possibly recursive comb, keep it lazy or risk blowing up -}) +newtype RComb = RComb + { unRComb :: (GComb RComb {- Possibly recursive comb, keep it lazy or risk blowing up -}) } --- Eq and Ord instances on the CombIx to avoid infinite recursion when --- comparing self-recursive functions. -instance Eq RComb where - RComb r1 _ == RComb r2 _ = r1 == r2 - -instance Ord RComb where - compare (RComb r1 _) (RComb r2 _) = compare r1 r2 - --- | RCombs can be infinitely recursive so we show the CombIx instead. instance Show RComb where - show (RComb ix _) = show ix + show _ = "" -- | Map of combinators, parameterized by comb reference type type GCombs comb = EnumMap Word64 (GComb comb) @@ -810,7 +782,7 @@ resolveCombs mayExisting combs = -- We make sure not to force resolved Combs or we'll loop forever. let ~resolved = combs - <&> (fmap . fmap) \(cix@(CIx _ n i)) -> + <&> (fmap . fmap) \(CIx _ n i) -> let cmbs = case mayExisting >>= EC.lookup n of Just cmbs -> cmbs Nothing -> @@ -818,7 +790,7 @@ resolveCombs mayExisting combs = Just cmbs -> cmbs Nothing -> error $ "unknown combinator `" ++ show n ++ "`." in case EC.lookup i cmbs of - Just cmb -> RComb cix cmb + Just cmb -> RComb cmb Nothing -> error $ "unknown section `" @@ -1559,10 +1531,10 @@ demuxArgs as0 = -- TODO: handle ranges (us, bs) -> DArgN (primArrayFromList us) (primArrayFromList bs) -combDeps :: Comb -> [Word64] +combDeps :: GComb any -> [Word64] combDeps (Lam _ _ _ _ s) = sectionDeps s -combTypes :: Comb -> [Word64] +combTypes :: GComb comb -> [Word64] combTypes (Lam _ _ _ _ s) = sectionTypes s sectionDeps :: GSection comb -> [Word64] @@ -1579,7 +1551,7 @@ sectionDeps (Ins i s) sectionDeps (Let s (CIx _ w _) _) = w : sectionDeps s sectionDeps _ = [] -sectionTypes :: Section -> [Word64] +sectionTypes :: GSection comb -> [Word64] sectionTypes (Ins i s) = instrTypes i ++ sectionTypes s sectionTypes (Let s _ _) = sectionTypes s sectionTypes (Match _ br) = branchTypes br @@ -1589,7 +1561,7 @@ sectionTypes (RMatch _ pu br) = sectionTypes pu ++ foldMap branchTypes br sectionTypes _ = [] -instrTypes :: Instr -> [Word64] +instrTypes :: GInstr comb -> [Word64] instrTypes (Pack _ w _) = [w `shiftR` 16] instrTypes (Reset ws) = setToList ws instrTypes (Capture w) = [w] @@ -1605,7 +1577,7 @@ branchDeps (TestW d m) = branchDeps (TestT d m) = sectionDeps d ++ foldMap sectionDeps m -branchTypes :: Branch -> [Word64] +branchTypes :: GBranch comb -> [Word64] branchTypes (Test1 _ s1 d) = sectionTypes s1 ++ sectionTypes d branchTypes (Test2 _ s1 _ s2 d) = sectionTypes s1 ++ sectionTypes s2 ++ sectionTypes d diff --git a/unison-runtime/src/Unison/Runtime/Machine.hs b/unison-runtime/src/Unison/Runtime/Machine.hs index 6f5e017157..05a59c7e70 100644 --- a/unison-runtime/src/Unison/Runtime/Machine.hs +++ b/unison-runtime/src/Unison/Runtime/Machine.hs @@ -179,7 +179,7 @@ topDEnv combs rfTy rfTm Just j <- M.lookup rcrf rfTm = let cix = (CIx rcrf j 0) comb = rCombSection combs cix - in ( EC.mapSingleton n (PAp comb unull bnull), + in ( EC.mapSingleton n (PAp cix comb unull bnull), Mark 0 0 (EC.setSingleton n) mempty ) topDEnv _ _ _ = (mempty, id) @@ -205,9 +205,10 @@ apply0 !callback !env !threadTracker !i = do r <- case EC.lookup i cmbrs of Just r -> pure r Nothing -> die "apply0: missing reference to entry point" - let entryComb = rCombSection cmbs (CIx r i 0) + let entryCix = (CIx r i 0) + let entryComb = rCombSection cmbs entryCix apply env denv threadTracker ustk bstk (kf k0) True ZArgs $ - PAp entryComb unull bnull + PAp entryCix entryComb unull bnull where k0 = maybe KE (CB . Hook) callback @@ -636,10 +637,10 @@ eval !env !denv !activeThreads !ustk !bstk !k _ (Call ck _combIx rcomb args) = enter env denv activeThreads ustk bstk k ck args rcomb eval !env !denv !activeThreads !ustk !bstk !k _ (Jump i args) = peekOff bstk i >>= jump env denv activeThreads ustk bstk k args -eval !env !denv !activeThreads !ustk !bstk !k r (Let nw _combIx comb) = do +eval !env !denv !activeThreads !ustk !bstk !k r (Let nw cix comb) = do (ustk, ufsz, uasz) <- saveFrame ustk (bstk, bfsz, basz) <- saveFrame bstk - eval env denv activeThreads ustk bstk (Push ufsz bfsz uasz basz comb k) r nw + eval env denv activeThreads ustk bstk (Push ufsz bfsz uasz basz cix comb k) r nw eval !env !denv !activeThreads !ustk !bstk !k r (Ins i nx) = do (denv, ustk, bstk, k) <- exec env denv activeThreads ustk bstk k r i eval env denv activeThreads ustk bstk k r nx @@ -706,16 +707,16 @@ enter !env !denv !activeThreads !ustk !bstk !k !ck !args !rcomb = do -- detecting saturated calls. eval env denv activeThreads ustk bstk k dummyRef entry where - (RComb _ (Lam ua ba uf bf entry)) = rcomb + (RComb (Lam ua ba uf bf entry)) = rcomb {-# INLINE enter #-} -- fast path by-name delaying name :: Stack 'UN -> Stack 'BX -> Args -> Closure -> IO (Stack 'BX) name !ustk !bstk !args clo = case clo of - PAp comb useg bseg -> do + PAp cix comb useg bseg -> do (useg, bseg) <- closeArgs I ustk bstk useg bseg args bstk <- bump bstk - poke bstk $ PAp comb useg bseg + poke bstk $ PAp cix comb useg bseg pure bstk _ -> die $ "naming non-function: " ++ show clo {-# INLINE name #-} @@ -732,7 +733,7 @@ apply :: Args -> Closure -> IO () -apply !env !denv !activeThreads !ustk !bstk !k !ck !args (PAp comb useg bseg) = +apply !env !denv !activeThreads !ustk !bstk !k !ck !args (PAp cix@(CIx combRef _ _) comb useg bseg) = case unRComb comb of Lam ua ba uf bf entry | ck || ua <= uac && ba <= bac -> do @@ -743,13 +744,13 @@ apply !env !denv !activeThreads !ustk !bstk !k !ck !args (PAp comb useg bseg) = bstk <- dumpSeg bstk bseg A ustk <- acceptArgs ustk ua bstk <- acceptArgs bstk ba - eval env denv activeThreads ustk bstk k (rCombRef comb) entry + eval env denv activeThreads ustk bstk k combRef entry | otherwise -> do (useg, bseg) <- closeArgs C ustk bstk useg bseg args ustk <- discardFrame =<< frameArgs ustk bstk <- discardFrame =<< frameArgs bstk bstk <- bump bstk - poke bstk $ PAp comb useg bseg + poke bstk $ PAp cix comb useg bseg yield env denv activeThreads ustk bstk k where uac = asize ustk + ucount args + uscount useg @@ -797,8 +798,8 @@ jump !env !denv !activeThreads !ustk !bstk !k !args clo = case clo of -- pending, and the result stacks need to be adjusted. Hence the 3 results. adjust (Mark ua ba rs denv k) = (0, 0, Mark (ua + asize ustk) (ba + asize bstk) rs denv k) - adjust (Push un bn ua ba cix k) = - (0, 0, Push un bn (ua + asize ustk) (ba + asize bstk) cix k) + adjust (Push un bn ua ba cix rcomb k) = + (0, 0, Push un bn (ua + asize ustk) (ba + asize bstk) cix rcomb k) adjust k = (asize ustk, asize bstk, k) {-# INLINE jump #-} @@ -818,8 +819,8 @@ repush !env !activeThreads !ustk !bstk = go where denv' = cs <> EC.withoutKeys denv ps cs' = EC.restrictKeys denv ps - go !denv (Push un bn ua ba nx sk) !k = - go denv sk $ Push un bn ua ba nx k + go !denv (Push un bn ua ba cix rcomb sk) !k = + go denv sk $ Push un bn ua ba cix rcomb k go !_ (CB _) !_ = die "repush: impossible" {-# INLINE repush #-} @@ -1833,13 +1834,13 @@ yield !env !denv !activeThreads !ustk !bstk !k = leap denv k ustk <- adjustArgs ustk ua bstk <- adjustArgs bstk ba apply env denv activeThreads ustk bstk k False (BArg1 0) clo - leap !denv (Push ufsz bfsz uasz basz rComb k) = do + leap !denv (Push ufsz bfsz uasz basz (CIx ref _ _) rComb k) = do let Lam _ _ uf bf nx = unRComb rComb ustk <- restoreFrame ustk ufsz uasz bstk <- restoreFrame bstk bfsz basz ustk <- ensure ustk uf bstk <- ensure bstk bf - eval env denv activeThreads ustk bstk k (rCombRef rComb) nx + eval env denv activeThreads ustk bstk k ref nx leap _ (CB (Hook f)) = f ustk bstk leap _ KE = pure () {-# INLINE yield #-} @@ -1895,8 +1896,8 @@ splitCont !denv !ustk !bstk !k !p = where denv' = cs <> EC.withoutKeys denv ps cs' = EC.restrictKeys denv ps - walk !denv !usz !bsz !ck (Push un bn ua ba br k) = - walk denv (usz + un + ua) (bsz + bn + ba) (Push un bn ua ba br ck) k + walk !denv !usz !bsz !ck (Push un bn ua ba br brComb k) = + walk denv (usz + un + ua) (bsz + bn + ba) (Push un bn ua ba br brComb ck) k finish !denv !usz !bsz !ua !ba !ck !k = do (useg, ustk) <- grab ustk usz @@ -1919,7 +1920,7 @@ discardCont denv ustk bstk k p = {-# INLINE discardCont #-} resolve :: CCache -> DEnv -> Stack 'BX -> RRef -> IO Closure -resolve _ _ _ (Env _cix rComb) = pure $ PAp rComb unull bnull +resolve _ _ _ (Env cix rComb) = pure $ PAp cix rComb unull bnull resolve _ _ bstk (Stk i) = peekOff bstk i resolve env denv _ (Dyn i) = case EC.lookup i denv of Just clo -> pure clo @@ -1934,10 +1935,10 @@ unhandledErr fname env i = bomb sh = die $ fname ++ ": unhandled ability request: " ++ sh rCombSection :: EnumMap Word64 RCombs -> CombIx -> RComb -rCombSection combs cix@(CIx r n i) = +rCombSection combs (CIx r n i) = case EC.lookup n combs of Just cmbs -> case EC.lookup i cmbs of - Just cmb -> RComb cix cmb + Just cmb -> RComb cmb Nothing -> error $ "unknown section `" ++ show i ++ "` of combinator `" ++ show n ++ "`. Reference: " ++ show r Nothing -> error $ "unknown combinator `" ++ show n ++ "`. Reference: " ++ show r @@ -2172,8 +2173,8 @@ reflectValue rty = goV goIx (CIx r _ i) = ANF.GR r i - goV (PApV rComb ua ba) = - ANF.Partial (goIx $ rCombIx rComb) (fromIntegral <$> ua) <$> traverse goV ba + goV (PApV cix _rComb ua ba) = + ANF.Partial (goIx cix) (fromIntegral <$> ua) <$> traverse goV ba goV (DataC _ t [w] []) = ANF.BLit <$> reflectUData t w goV (DataC r t us bs) = ANF.Data r (maskTags t) (fromIntegral <$> us) <$> traverse goV bs @@ -2188,13 +2189,13 @@ reflectValue rty = goV ps <- traverse refTy (EC.setToList ps) de <- traverse (\(k, v) -> (,) <$> refTy k <*> goV v) (mapToList de) ANF.Mark (fromIntegral ua) (fromIntegral ba) ps (M.fromList de) <$> goK k - goK (Push uf bf ua ba rComb k) = + goK (Push uf bf ua ba cix _rComb k) = ANF.Push (fromIntegral uf) (fromIntegral bf) (fromIntegral ua) (fromIntegral ba) - (goIx $ rCombIx rComb) + (goIx cix) <$> goK k goF f @@ -2257,15 +2258,18 @@ reifyValue0 (combs, rty, rtm) = goV refTm r | Just w <- M.lookup r rtm = pure w | otherwise = die . err $ "unknown term reference: " ++ show r - goIx :: ANF.GroupRef -> IO RComb + goIx :: ANF.GroupRef -> IO (CombIx, RComb) goIx (ANF.GR r i) = refTm r <&> \n -> - rCombSection combs (CIx r n i) + let cix = (CIx r n i) + in (cix, rCombSection combs cix) - goV (ANF.Partial gr ua ba) = - pap <$> (goIx gr) <*> traverse goV ba + goV (ANF.Partial gr ua ba) = do + (cix, rcomb) <- goIx gr + clos <- traverse goV ba + pure $ pap cix rcomb clos where - pap i = PApV i (fromIntegral <$> ua) + pap cix i = PApV cix i (fromIntegral <$> ua) goV (ANF.Data r t0 us bs) = do t <- flip packTags (fromIntegral t0) . fromIntegral <$> refTy r DataC r t (fromIntegral <$> us) <$> traverse goV bs @@ -2287,14 +2291,16 @@ reifyValue0 (combs, rty, rtm) = goV where mrk ps de k = Mark (fromIntegral ua) (fromIntegral ba) (setFromList ps) (mapFromList de) k - goK (ANF.Push uf bf ua ba gr k) = + goK (ANF.Push uf bf ua ba gr k) = do + (cix, rcomb) <- goIx gr Push (fromIntegral uf) (fromIntegral bf) (fromIntegral ua) (fromIntegral ba) - <$> (goIx gr) - <*> goK k + cix + rcomb + <$> goK k goL (ANF.Text t) = pure . Foreign $ Wrap Rf.textRef t goL (ANF.List l) = Foreign . Wrap Rf.listRef <$> traverse goV l @@ -2342,8 +2348,8 @@ universalEq frn = eqc ct1 == ct2 && eql (==) us1 us2 && eql eqc bs1 bs2 - eqc (PApV i1 us1 bs1) (PApV i2 us2 bs2) = - i1 == i2 + eqc (PApV cix1 _ us1 bs1) (PApV cix2 _ us2 bs2) = + cix1 == cix2 && eql (==) us1 us2 && eql eqc bs1 bs2 eqc (CapV k1 ua1 ba1 us1 bs1) (CapV k2 ua2 ba2 us2 bs2) = @@ -2481,8 +2487,8 @@ universalCompare frn = cmpc False -- when comparing corresponding `Any` values, which have -- existentials inside check that type references match <> cmpl (cmpc $ tyEq || rf1 == Rf.anyRef) bs1 bs2 - cmpc tyEq (PApV i1 us1 bs1) (PApV i2 us2 bs2) = - compare i1 i2 + cmpc tyEq (PApV cix1 _ us1 bs1) (PApV cix2 _ us2 bs2) = + compare cix1 cix2 <> cmpl compare us1 us2 <> cmpl (cmpc tyEq) bs1 bs2 cmpc _ (CapV k1 ua1 ba1 us1 bs1) (CapV k2 ua2 ba2 us2 bs2) = diff --git a/unison-runtime/src/Unison/Runtime/Stack.hs b/unison-runtime/src/Unison/Runtime/Stack.hs index db69b75826..95639a90a3 100644 --- a/unison-runtime/src/Unison/Runtime/Stack.hs +++ b/unison-runtime/src/Unison/Runtime/Stack.hs @@ -50,6 +50,7 @@ where import Control.Monad (when) import Control.Monad.Primitive import Data.Foldable as F (for_) +import Data.Functor (($>)) import Data.Kind qualified as Kind import Data.Sequence (Seq) import Data.Word @@ -88,9 +89,32 @@ data K !Int -- boxed frame size !Int -- pending unboxed args !Int -- pending boxed args - !RComb -- local continuation reference + !CombIx + RComb -- local continuation reference !K - deriving (Eq, Ord) + +instance Eq K where + KE == KE = True + (CB cb) == (CB cb') = cb == cb' + (Mark ua ba ps m k) == (Mark ua' ba' ps' m' k') = + ua == ua' && ba == ba' && ps == ps' && m == m' && k == k' + (Push uf bf ua ba ci _comb k) == (Push uf' bf' ua' ba' ci' _comb' k') = + uf == uf' && bf == bf' && ua == ua' && ba == ba' && ci == ci' && k == k' + _ == _ = False + +instance Ord K where + compare KE KE = EQ + compare (CB cb) (CB cb') = compare cb cb' + compare (Mark ua ba ps m k) (Mark ua' ba' ps' m' k') = + compare (ua, ba, ps, m, k) (ua', ba', ps', m', k') + compare (Push uf bf ua ba ci _comb k) (Push uf' bf' ua' ba' ci' _comb' k') = + compare (uf, bf, ua, ba, ci, k) (uf', bf', ua', ba', ci', k') + compare KE _ = LT + compare _ KE = GT + compare (CB _) _ = LT + compare _ (CB _) = GT + compare (Mark _ _ _ _ _) _ = LT + compare _ (Mark _ _ _ _ _) = GT type RClosure = GClosure RComb @@ -100,6 +124,7 @@ type Closure = GClosure RComb data GClosure comb = PAp + !CombIx {- Lazy! Might be cyclic -} comb {-# UNPACK #-} !(Seg 'UN) -- unboxed args {- unpack -} @@ -115,13 +140,20 @@ data GClosure comb Captured !K !Int !Int {-# UNPACK #-} !(Seg 'UN) !(Seg 'BX) | Foreign !Foreign | BlackHole - deriving stock (Show, Eq, Ord, Functor, Foldable, Traversable) + deriving stock (Show, Functor, Foldable, Traversable) + +instance Eq (GClosure comb) where + -- This is safe because the embedded CombIx will break disputes + a == b = (a $> ()) == (b $> ()) + +instance Ord (GClosure comb) where + compare a b = compare (a $> ()) (b $> ()) traceK :: Reference -> K -> [(Reference, Int)] traceK begin = dedup (begin, 1) where dedup p (Mark _ _ _ _ k) = dedup p k - dedup p@(cur, n) (Push _ _ _ _ (RComb (CIx r _ _) _) k) + dedup p@(cur, n) (Push _ _ _ _ (CIx r _ _) _ k) | cur == r = dedup (cur, 1 + n) k | otherwise = p : dedup (r, 1) k dedup p _ = [p] @@ -176,7 +208,7 @@ frameDataSize = go 0 0 go usz bsz KE = (usz, bsz) go usz bsz (CB _) = (usz, bsz) go usz bsz (Mark ua ba _ _ k) = go (usz + ua) (bsz + ba) k - go usz bsz (Push uf bf ua ba _ k) = go (usz + uf + ua) (bsz + bf + ba) k + go usz bsz (Push uf bf ua ba _ _ k) = go (usz + uf + ua) (bsz + bf + ba) k pattern DataC :: Reference -> Word64 -> [Int] -> [RClosure] -> RClosure pattern DataC rf ct us bs <- @@ -184,11 +216,11 @@ pattern DataC rf ct us bs <- where DataC rf ct us bs = formData rf ct us bs -pattern PApV :: RComb -> [Int] -> [RClosure] -> RClosure -pattern PApV ic us bs <- - PAp ic (ints -> us) (bsegToList -> bs) +pattern PApV :: CombIx -> RComb -> [Int] -> [RClosure] -> RClosure +pattern PApV cix rcomb us bs <- + PAp cix rcomb (ints -> us) (bsegToList -> bs) where - PApV ic us bs = PAp ic (useg us) (bseg bs) + PApV cix rcomb us bs = PAp cix rcomb (useg us) (bseg bs) pattern CapV :: K -> Int -> Int -> [Int] -> [RClosure] -> RClosure pattern CapV k ua ba us bs <- @@ -559,7 +591,7 @@ instance Show K where where go _ KE = "]" go _ (CB _) = "]" - go com (Push uf bf ua ba ci k) = + go com (Push uf bf ua ba ci _rcomb k) = com ++ show (uf, bf, ua, ba, ci) ++ go "," k go com (Mark ua ba ps _ k) = com ++ "M " ++ show ua ++ " " ++ show ba ++ " " ++ show ps ++ go "," k @@ -712,7 +744,7 @@ bscount :: Seg 'BX -> Int bscount seg = sizeofArray seg closureTermRefs :: (Monoid m) => (Reference -> m) -> (RClosure -> m) -closureTermRefs f (PAp (RComb (CIx r _ _) _) _ cs) = +closureTermRefs f (PAp (CIx r _ _) _ _ cs) = f r <> foldMap (closureTermRefs f) cs closureTermRefs f (DataB1 _ _ c) = closureTermRefs f c closureTermRefs f (DataB2 _ _ c1 c2) = @@ -729,6 +761,6 @@ closureTermRefs _ _ = mempty contTermRefs :: (Monoid m) => (Reference -> m) -> K -> m contTermRefs f (Mark _ _ _ m k) = foldMap (closureTermRefs f) m <> contTermRefs f k -contTermRefs f (Push _ _ _ _ (RComb (CIx r _ _) _) k) = +contTermRefs f (Push _ _ _ _ (CIx r _ _) _ k) = f r <> contTermRefs f k contTermRefs _ _ = mempty From c662bfca7c763914842529a9f15675eeda207e5b Mon Sep 17 00:00:00 2001 From: Chris Penner Date: Thu, 26 Sep 2024 15:56:46 -0700 Subject: [PATCH 21/40] Serialization WIP --- .../src/Unison/Runtime/Stack/Serialize.hs | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/unison-runtime/src/Unison/Runtime/Stack/Serialize.hs b/unison-runtime/src/Unison/Runtime/Stack/Serialize.hs index 6c6553ad14..bcf1b00dc4 100644 --- a/unison-runtime/src/Unison/Runtime/Stack/Serialize.hs +++ b/unison-runtime/src/Unison/Runtime/Stack/Serialize.hs @@ -49,16 +49,18 @@ putGClosure :: (MonadPut m) => (comb -> m ()) -> GClosure comb -> m () putGClosure putComb = \case GPAp comb uargs bargs -> putTag GPApT *> putComb comb *> putByteArray uargs *> putArray (putGClosure putComb) bargs - GEnum r i -> _ - GDataU1 r w i -> _ - GDataU2 r w i j -> _ - GDataB1 r w c -> _ - GDataB2 r w c1 c2 -> _ - GDataUB r w i c -> _ - GDataG r w s1 s2 -> _ - GCaptured k i j s1 s2 -> _ + GEnum r w -> putTag GEnumT *> putReference r *> putNat w + GDataU1 r w i -> putTag GDataU1T *> putReference r *> putNat w *> putI i + GDataU2 r w i j -> putTag GDataU2T *> putReference r *> putNat w *> putI i *> putInt j + GDataB1 r w clos -> putTag GDataB1T *> putReference r *> putNat w *> putGClosure putComb clos + GDataB2 r w c1 c2 -> putTag GDataB2T *> putReference r *> putNat w *> putGClosure putComb c1 *> putGClosure putComb c2 + GDataUB r w i c -> putTag GDataUBT *> putReference r *> putNat w *> putI i *> putGClosure putComb c + GDataG r w usegs bsegs -> putTag GDataGT *> putReference r *> putNat w *> putByteArray usegs *> putArray (putGClosure putComb) bsegs + GCaptured k i j s1 s2 -> putTag GCapturedT *> putInt k *> putInt i *> putInt j *> putGCaptured putComb s1 *> putGCaptured putComb s2 GForeign f -> _ GBlackHole -> _ + where + putI = putInt . fromIntegral getGClosure :: (MonadGet m) => m Closure getGClosure = error "getClosure not implemented" From 336c1a49ac6c411a96188ea97905958dcd6c2ac5 Mon Sep 17 00:00:00 2001 From: Chris Penner Date: Fri, 27 Sep 2024 11:16:04 -0700 Subject: [PATCH 22/40] Rewrite pre-evaluation --- .../src/Unison/Runtime/Interface.hs | 2 -- unison-runtime/src/Unison/Runtime/Machine.hs | 36 ++++++++++--------- 2 files changed, 20 insertions(+), 18 deletions(-) diff --git a/unison-runtime/src/Unison/Runtime/Interface.hs b/unison-runtime/src/Unison/Runtime/Interface.hs index bd838a9cf3..f76821334f 100644 --- a/unison-runtime/src/Unison/Runtime/Interface.hs +++ b/unison-runtime/src/Unison/Runtime/Interface.hs @@ -126,7 +126,6 @@ import Unison.Runtime.Machine cacheAdd0, eval0, expandSandbox, - preEvalTopLevelConstants, refLookup, refNumTm, refNumsTm, @@ -1317,7 +1316,6 @@ restoreCache (SCache cs crs cacheableCombs trs ftm fty int rtm rty sbs) = do <*> newTVarIO (rtm <> builtinTermNumbering) <*> newTVarIO (rty <> builtinTypeNumbering) <*> newTVarIO (sbs <> baseSandboxInfo) - preEvalTopLevelConstants cacheableCombs cc pure cc where decom = diff --git a/unison-runtime/src/Unison/Runtime/Machine.hs b/unison-runtime/src/Unison/Runtime/Machine.hs index 876b18d03d..d14df2cc1f 100644 --- a/unison-runtime/src/Unison/Runtime/Machine.hs +++ b/unison-runtime/src/Unison/Runtime/Machine.hs @@ -1999,9 +1999,6 @@ updateMap new0 r = do stateTVar r $ \old -> let total = new <> old in (total, total) -modifyMap :: TVar s -> (s -> s) -> STM s -modifyMap r f = stateTVar r $ \old -> let new = f old in (new, new) - refLookup :: String -> M.Map Reference Word64 -> Reference -> Word64 refLookup s m r | Just w <- M.lookup r m = w @@ -2142,7 +2139,7 @@ cacheAdd0 :: IO () cacheAdd0 ntys0 termSuperGroups sands cc = do let toAdd = M.fromList (termSuperGroups <&> \(r, g, _) -> (r, g)) - newCacheableCombs <- atomically $ do + (unresolvedCacheableCombs, unresolvedNonCacheableCombs) <- atomically $ do have <- readTVar (intermed cc) let new = M.difference toAdd have let sz = fromIntegral $ M.size new @@ -2167,34 +2164,41 @@ cacheAdd0 ntys0 termSuperGroups sands cc = do ) & EC.setFromList newCombRefs <- updateMap combRefUpdates (combRefs cc) - ncs <- modifyMap (combs cc) \oldCombs -> - let newCombs :: EnumMap Word64 MCombs - newCombs = resolveCombs (Just oldCombs) . absurdCombs . mapFromList $ zipWith combinate [ntm ..] rgs - in newCombs <> oldCombs + (unresolvedCacheableCombs, unresolvedNonCacheableCombs, updatedCombs) <- stateTVar (combs cc) \oldCombs -> + let unresolvedNewCombs :: EnumMap Word64 (GCombs any CombIx) + unresolvedNewCombs = absurdCombs . mapFromList $ zipWith combinate [ntm ..] rgs + (unresolvedCacheableCombs, unresolvedNonCacheableCombs) = + EC.mapToList unresolvedNewCombs & foldMap \(w, gcombs) -> + if EC.member w newCacheableCombs + then (EC.mapSingleton w gcombs, mempty) + else (mempty, EC.mapSingleton w gcombs) + newCombs :: EnumMap Word64 MCombs + newCombs = resolveCombs (Just oldCombs) $ unresolvedNewCombs + updatedCombs = newCombs <> oldCombs + in ((unresolvedCacheableCombs, unresolvedNonCacheableCombs, updatedCombs), updatedCombs) nsn <- updateMap (M.fromList sands) (sandbox cc) - ncc <- updateMap (newCacheableCombs) (cacheableCombs cc) + ncc <- updateMap newCacheableCombs (cacheableCombs cc) -- Now that the code cache is primed with everything we need, -- we can pre-evaluate the top-level constants. - pure $ int `seq` rtm `seq` newCombRefs `seq` ncs `seq` nsn `seq` ncc `seq` newCacheableCombs - preEvalTopLevelConstants newCacheableCombs cc + pure $ int `seq` rtm `seq` newCombRefs `seq` updatedCombs `seq` nsn `seq` ncc `seq` (unresolvedCacheableCombs, unresolvedNonCacheableCombs) + preEvalTopLevelConstants unresolvedCacheableCombs unresolvedNonCacheableCombs cc -preEvalTopLevelConstants :: EnumSet Word64 -> CCache -> IO () -preEvalTopLevelConstants cacheableCombs cc = do +preEvalTopLevelConstants :: (EnumMap Word64 (GCombs Closure CombIx)) -> (EnumMap Word64 (GCombs Closure CombIx)) -> CCache -> IO () +preEvalTopLevelConstants cacheableCombs newCombs cc = do activeThreads <- Just <$> UnliftIO.newIORef mempty - for_ (EC.setToList cacheableCombs) \w -> do + for_ (EC.mapToList cacheableCombs) \(w, _) -> do Debug.debugM Debug.Temp "Evaluating " w let hook _ustk bstk = do clos <- peek bstk Debug.debugM Debug.Temp "Evaluated" ("Evaluated " ++ show w ++ " to " ++ show clos) atomically $ do - -- TODO: Check that it's right to just insert the closure at comb position 0 modifyTVar (combs cc) $ EC.mapInsert w (EC.mapSingleton 0 $ CachedClosure w clos) apply0 (Just hook) cc activeThreads w Debug.debugLogM Debug.Temp "Done pre-caching" -- Rewrite all the inlined combinator references to point to the -- new cached versions. - atomically $ modifyTVar (combs cc) (resolveCombs Nothing . _) + atomically $ modifyTVar (combs cc) (\existingCombs -> (resolveCombs (Just existingCombs) (cacheableCombs <> newCombs))) expandSandbox :: Map Reference (Set Reference) -> From 5a946f8dca054f5eecedf061f1128ac0f8081690 Mon Sep 17 00:00:00 2001 From: Chris Penner Date: Fri, 27 Sep 2024 11:29:30 -0700 Subject: [PATCH 23/40] Fixed closure embedding --- parser-typechecker/src/Unison/Util/EnumContainers.hs | 4 ++++ unison-runtime/src/Unison/Runtime/Machine.hs | 7 +++++-- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/parser-typechecker/src/Unison/Util/EnumContainers.hs b/parser-typechecker/src/Unison/Util/EnumContainers.hs index ec61f3f8cc..0a84aa4dd2 100644 --- a/parser-typechecker/src/Unison/Util/EnumContainers.hs +++ b/parser-typechecker/src/Unison/Util/EnumContainers.hs @@ -15,6 +15,7 @@ module Unison.Util.EnumContainers keysSet, restrictKeys, withoutKeys, + mapDifference, member, lookup, lookupWithDefault, @@ -118,6 +119,9 @@ restrictKeys (EM m) (ES s) = EM $ IM.restrictKeys m s withoutKeys :: (EnumKey k) => EnumMap k a -> EnumSet k -> EnumMap k a withoutKeys (EM m) (ES s) = EM $ IM.withoutKeys m s +mapDifference :: (EnumKey k) => EnumMap k a -> EnumMap k b -> EnumMap k a +mapDifference (EM l) (EM r) = EM $ IM.difference l r + member :: (EnumKey k) => k -> EnumSet k -> Bool member e (ES s) = IS.member (keyToInt e) s diff --git a/unison-runtime/src/Unison/Runtime/Machine.hs b/unison-runtime/src/Unison/Runtime/Machine.hs index d14df2cc1f..2c6ee42349 100644 --- a/unison-runtime/src/Unison/Runtime/Machine.hs +++ b/unison-runtime/src/Unison/Runtime/Machine.hs @@ -2186,19 +2186,22 @@ cacheAdd0 ntys0 termSuperGroups sands cc = do preEvalTopLevelConstants :: (EnumMap Word64 (GCombs Closure CombIx)) -> (EnumMap Word64 (GCombs Closure CombIx)) -> CCache -> IO () preEvalTopLevelConstants cacheableCombs newCombs cc = do activeThreads <- Just <$> UnliftIO.newIORef mempty + evaluatedCacheableCombsVar <- newTVarIO mempty for_ (EC.mapToList cacheableCombs) \(w, _) -> do Debug.debugM Debug.Temp "Evaluating " w let hook _ustk bstk = do clos <- peek bstk Debug.debugM Debug.Temp "Evaluated" ("Evaluated " ++ show w ++ " to " ++ show clos) atomically $ do - modifyTVar (combs cc) $ EC.mapInsert w (EC.mapSingleton 0 $ CachedClosure w clos) + modifyTVar evaluatedCacheableCombsVar $ EC.mapInsert w (EC.mapSingleton 0 $ CachedClosure w clos) apply0 (Just hook) cc activeThreads w + evaluatedCacheableCombs <- readTVarIO evaluatedCacheableCombsVar Debug.debugLogM Debug.Temp "Done pre-caching" + let allNew = evaluatedCacheableCombs <> newCombs -- Rewrite all the inlined combinator references to point to the -- new cached versions. - atomically $ modifyTVar (combs cc) (\existingCombs -> (resolveCombs (Just existingCombs) (cacheableCombs <> newCombs))) + atomically $ modifyTVar (combs cc) (\existingCombs -> (resolveCombs (Just $ EC.mapDifference existingCombs allNew) allNew) <> existingCombs) expandSandbox :: Map Reference (Set Reference) -> From 6ea04b807534d51a197bcf96ae949483138eda29 Mon Sep 17 00:00:00 2001 From: Chris Penner Date: Fri, 27 Sep 2024 12:56:00 -0700 Subject: [PATCH 24/40] Don't serialize Closures --- .../src/Unison/Runtime/Interface.hs | 42 +++++++++---------- .../src/Unison/Runtime/MCode/Serialize.hs | 8 ++-- unison-runtime/src/Unison/Runtime/Machine.hs | 14 +++++-- 3 files changed, 36 insertions(+), 28 deletions(-) diff --git a/unison-runtime/src/Unison/Runtime/Interface.hs b/unison-runtime/src/Unison/Runtime/Interface.hs index f76821334f..7870ca13ae 100644 --- a/unison-runtime/src/Unison/Runtime/Interface.hs +++ b/unison-runtime/src/Unison/Runtime/Interface.hs @@ -48,6 +48,7 @@ import Data.Set as Set ) import Data.Set qualified as Set import Data.Text as Text (isPrefixOf, pack, unpack) +import Data.Void (absurd) import GHC.IO.Exception (IOErrorType (NoSuchThing, OtherError, PermissionDenied), IOException (ioe_description, ioe_type)) import GHC.Stack (callStack) import Network.Simple.TCP (Socket, acceptFork, listen, recv, send) @@ -119,6 +120,7 @@ import Unison.Runtime.Machine ( ActiveThreads, CCache (..), Cacheability (..), + Combs, Tracer (..), apply0, baseCCache, @@ -136,7 +138,6 @@ import Unison.Runtime.Machine import Unison.Runtime.Pattern import Unison.Runtime.Serialize as SER import Unison.Runtime.Stack -import Unison.Runtime.Stack.Serialize (getClosure, putClosure) import Unison.Symbol (Symbol) import Unison.Syntax.HashQualified qualified as HQ (toText) import Unison.Syntax.NamePrinter (prettyHashQualified) @@ -1171,7 +1172,7 @@ catchInternalErrors sub = sub `UnliftIO.catch` hCE `UnliftIO.catch` hRE decodeStandalone :: BL.ByteString -> - Either String (Text, Text, CombIx, StoredCache CombIx) + Either String (Text, Text, CombIx, StoredCache) decodeStandalone b = bimap thd thd $ runGetOrFail g b where thd (_, _, x) = x @@ -1238,15 +1239,15 @@ tryM = hRE (PE _ e) = pure $ Just e hRE (BU _ _ _) = pure $ Just "impossible" -runStandalone :: StoredCache CombIx -> CombIx -> IO (Either (Pretty ColorText) ()) +runStandalone :: StoredCache -> CombIx -> IO (Either (Pretty ColorText) ()) runStandalone sc init = restoreCache sc >>= executeMainComb init -- | A version of the Code Cache designed to be serialized to disk as -- standalone bytecode. -data StoredCache comb +data StoredCache = SCache - (EnumMap Word64 (GCombs Closure comb)) + (EnumMap Word64 Combs) (EnumMap Word64 Reference) (EnumSet Word64) (EnumMap Word64 Reference) @@ -1258,9 +1259,9 @@ data StoredCache comb (Map Reference (Set Reference)) deriving (Show) -putStoredCache :: (MonadPut m) => StoredCache comb -> m () +putStoredCache :: (MonadPut m) => StoredCache -> m () putStoredCache (SCache cs crs cacheableCombs trs ftm fty int rtm rty sbs) = do - putEnumMap putNat (putEnumMap putNat (putComb putClosure)) cs + putEnumMap putNat (putEnumMap putNat (putComb absurd)) cs putEnumMap putNat putReference crs putEnumSet putNat cacheableCombs putEnumMap putNat putReference trs @@ -1271,10 +1272,10 @@ putStoredCache (SCache cs crs cacheableCombs trs ftm fty int rtm rty sbs) = do putMap putReference putNat rty putMap putReference (putFoldable putReference) sbs -getStoredCache :: (MonadGet m) => m (StoredCache CombIx) +getStoredCache :: (MonadGet m) => m StoredCache getStoredCache = SCache - <$> getEnumMap getNat (getEnumMap getNat (getComb getClosure)) + <$> getEnumMap getNat (getEnumMap getNat getComb) <*> getEnumMap getNat getReference <*> getEnumSet getNat <*> getEnumMap getNat getReference @@ -1302,11 +1303,12 @@ tabulateErrors errs = : P.wrap "The following errors occured while decompiling:" : (listErrors errs) -restoreCache :: StoredCache CombIx -> IO CCache +restoreCache :: StoredCache -> IO CCache restoreCache (SCache cs crs cacheableCombs trs ftm fty int rtm rty sbs) = do cc <- CCache builtinForeigns False debugText - <$> newTVarIO combs + <$> newTVarIO srcCombs + <*> newTVarIO combs <*> newTVarIO (crs <> builtinTermBackref) <*> newTVarIO cacheableCombs <*> newTVarIO (trs <> builtinTypeBackref) @@ -1333,13 +1335,14 @@ restoreCache (SCache cs crs cacheableCombs trs ftm fty int rtm rty sbs) = do (debugTextFormat fancy $ pretty PPE.empty dv) rns = emptyRNs {dnum = refLookup "ty" builtinTypeNumbering} rf k = builtinTermBackref ! k - srcCombs :: EnumMap Word64 (GCombs Closure CombIx) + srcCombs :: EnumMap Word64 Combs srcCombs = let builtinCombs = mapWithKey (\k v -> emitComb @Symbol rns (rf k) k mempty (0, v)) numberedTermLookup - in absurdCombs builtinCombs <> cs + in builtinCombs <> cs combs :: EnumMap Word64 (RCombs Closure) combs = srcCombs + & absurdCombs & resolveCombs Nothing traceNeeded :: @@ -1356,7 +1359,7 @@ traceNeeded init src = fmap (`withoutKeys` ks) $ go mempty init | otherwise = die $ "traceNeeded: unknown combinator: " ++ show w buildSCache :: - EnumMap Word64 (GCombs Closure cix) -> + EnumMap Word64 Combs -> EnumMap Word64 Reference -> EnumSet Word64 -> EnumMap Word64 Reference -> @@ -1366,10 +1369,10 @@ buildSCache :: Map Reference Word64 -> Map Reference Word64 -> Map Reference (Set Reference) -> - StoredCache () + StoredCache buildSCache cs crsrc cacheableCombs trsrc ftm fty intsrc rtmsrc rtysrc sndbx = SCache - (forgetCombIx cs) + cs crs cacheableCombs trs @@ -1395,13 +1398,10 @@ buildSCache cs crsrc cacheableCombs trsrc ftm fty intsrc rtmsrc rtysrc sndbx = restrictTyW m = restrictKeys m typeKeys restrictTyR m = Map.restrictKeys m typeRefs - forgetCombIx :: EnumMap Word64 (GCombs Closure cix) -> EnumMap Word64 (GCombs Closure ()) - forgetCombIx = (fmap . fmap . fmap) (const ()) - -standalone :: CCache -> Word64 -> IO (StoredCache ()) +standalone :: CCache -> Word64 -> IO StoredCache standalone cc init = buildSCache - <$> (readTVarIO (combs cc) >>= traceNeeded init) + <$> (readTVarIO (srcCombs cc) >>= traceNeeded init) <*> readTVarIO (combRefs cc) <*> readTVarIO (cacheableCombs cc) <*> readTVarIO (tagRefs cc) diff --git a/unison-runtime/src/Unison/Runtime/MCode/Serialize.hs b/unison-runtime/src/Unison/Runtime/MCode/Serialize.hs index 6ed194e722..5817517352 100644 --- a/unison-runtime/src/Unison/Runtime/MCode/Serialize.hs +++ b/unison-runtime/src/Unison/Runtime/MCode/Serialize.hs @@ -15,6 +15,7 @@ import Data.Bytes.Put import Data.Bytes.Serial import Data.Bytes.VarInt import Data.Primitive.PrimArray +import Data.Void (Void) import Data.Word (Word64) import GHC.Exts (IsList (..)) import Unison.Runtime.MCode hiding (MatchT) @@ -38,13 +39,12 @@ putComb pClos = \case (CachedClosure w c) -> putTag CachedClosureT *> putNat w *> pClos c -getComb :: (MonadGet m) => m clos -> m (GComb clos CombIx) -getComb gClos = +getComb :: (MonadGet m) => m (GComb Void CombIx) +getComb = getTag >>= \case LamT -> Lam <$> gInt <*> gInt <*> gInt <*> gInt <*> getSection - CachedClosureT -> - CachedClosure <$> getNat <*> gClos + CachedClosureT -> error "getComb: Unexpected serialized Cached Closure" data SectionT = AppT diff --git a/unison-runtime/src/Unison/Runtime/Machine.hs b/unison-runtime/src/Unison/Runtime/Machine.hs index 2c6ee42349..5b0ed74c0f 100644 --- a/unison-runtime/src/Unison/Runtime/Machine.hs +++ b/unison-runtime/src/Unison/Runtime/Machine.hs @@ -78,6 +78,8 @@ type DEnv = EnumMap Word64 Closure type MCombs = RCombs Closure +type Combs = GCombs Void CombIx + type MSection = RSection Closure type MBranch = RBranch Closure @@ -103,6 +105,8 @@ data CCache = CCache { foreignFuncs :: EnumMap Word64 ForeignFunc, sandboxed :: Bool, tracer :: Bool -> Closure -> Tracer, + -- Combinators in their original form, where they're easier to serialize into SCache + srcCombs :: TVar (EnumMap Word64 Combs), combs :: TVar (EnumMap Word64 MCombs), combRefs :: TVar (EnumMap Word64 Reference), -- Combs which we're allowed to cache after evaluating @@ -140,7 +144,8 @@ refNumTy' cc r = M.lookup r <$> refNumsTy cc baseCCache :: Bool -> IO CCache baseCCache sandboxed = do CCache ffuncs sandboxed noTrace - <$> newTVarIO combs + <$> newTVarIO srcCombs + <*> newTVarIO combs <*> newTVarIO builtinTermBackref <*> newTVarIO cacheableCombs <*> newTVarIO builtinTypeBackref @@ -159,11 +164,14 @@ baseCCache sandboxed = do rns = emptyRNs {dnum = refLookup "ty" builtinTypeNumbering} - combs :: EnumMap Word64 MCombs - combs = + srcCombs :: EnumMap Word64 Combs + srcCombs = numberedTermLookup & mapWithKey (\k v -> let r = builtinTermBackref ! k in emitComb @Symbol rns r k mempty (0, v)) + combs :: EnumMap Word64 MCombs + combs = + srcCombs & absurdCombs & resolveCombs Nothing From 44d2f829e8829280a8091c837e38152b9c19f2f8 Mon Sep 17 00:00:00 2001 From: Chris Penner Date: Sat, 28 Sep 2024 10:12:43 -0700 Subject: [PATCH 25/40] Serialize cacheable combs and re-eval on load --- unison-runtime/src/Unison/Runtime/Interface.hs | 12 ++++++++++++ unison-runtime/src/Unison/Runtime/Machine.hs | 7 ++++--- 2 files changed, 16 insertions(+), 3 deletions(-) diff --git a/unison-runtime/src/Unison/Runtime/Interface.hs b/unison-runtime/src/Unison/Runtime/Interface.hs index 7870ca13ae..763482d84d 100644 --- a/unison-runtime/src/Unison/Runtime/Interface.hs +++ b/unison-runtime/src/Unison/Runtime/Interface.hs @@ -128,6 +128,7 @@ import Unison.Runtime.Machine cacheAdd0, eval0, expandSandbox, + preEvalTopLevelConstants, refLookup, refNumTm, refNumsTm, @@ -1318,6 +1319,17 @@ restoreCache (SCache cs crs cacheableCombs trs ftm fty int rtm rty sbs) = do <*> newTVarIO (rtm <> builtinTermNumbering) <*> newTVarIO (rty <> builtinTypeNumbering) <*> newTVarIO (sbs <> baseSandboxInfo) + let (unresolvedCacheableCombs, unresolvedNonCacheableCombs) = + srcCombs + & absurdCombs + & EC.mapToList + & foldMap + ( \(k, v) -> + if k `member` cacheableCombs + then (EC.mapSingleton k v, mempty) + else (mempty, EC.mapSingleton k v) + ) + preEvalTopLevelConstants unresolvedCacheableCombs unresolvedNonCacheableCombs cc pure cc where decom = diff --git a/unison-runtime/src/Unison/Runtime/Machine.hs b/unison-runtime/src/Unison/Runtime/Machine.hs index 5b0ed74c0f..4567031b44 100644 --- a/unison-runtime/src/Unison/Runtime/Machine.hs +++ b/unison-runtime/src/Unison/Runtime/Machine.hs @@ -2172,7 +2172,7 @@ cacheAdd0 ntys0 termSuperGroups sands cc = do ) & EC.setFromList newCombRefs <- updateMap combRefUpdates (combRefs cc) - (unresolvedCacheableCombs, unresolvedNonCacheableCombs, updatedCombs) <- stateTVar (combs cc) \oldCombs -> + (unresolvedNewCombs, unresolvedCacheableCombs, unresolvedNonCacheableCombs, updatedCombs) <- stateTVar (combs cc) \oldCombs -> let unresolvedNewCombs :: EnumMap Word64 (GCombs any CombIx) unresolvedNewCombs = absurdCombs . mapFromList $ zipWith combinate [ntm ..] rgs (unresolvedCacheableCombs, unresolvedNonCacheableCombs) = @@ -2183,12 +2183,13 @@ cacheAdd0 ntys0 termSuperGroups sands cc = do newCombs :: EnumMap Word64 MCombs newCombs = resolveCombs (Just oldCombs) $ unresolvedNewCombs updatedCombs = newCombs <> oldCombs - in ((unresolvedCacheableCombs, unresolvedNonCacheableCombs, updatedCombs), updatedCombs) + in ((unresolvedNewCombs, unresolvedCacheableCombs, unresolvedNonCacheableCombs, updatedCombs), updatedCombs) + nsc <- updateMap unresolvedNewCombs (srcCombs cc) nsn <- updateMap (M.fromList sands) (sandbox cc) ncc <- updateMap newCacheableCombs (cacheableCombs cc) -- Now that the code cache is primed with everything we need, -- we can pre-evaluate the top-level constants. - pure $ int `seq` rtm `seq` newCombRefs `seq` updatedCombs `seq` nsn `seq` ncc `seq` (unresolvedCacheableCombs, unresolvedNonCacheableCombs) + pure $ int `seq` rtm `seq` newCombRefs `seq` updatedCombs `seq` nsn `seq` ncc `seq` nsc `seq` (unresolvedCacheableCombs, unresolvedNonCacheableCombs) preEvalTopLevelConstants unresolvedCacheableCombs unresolvedNonCacheableCombs cc preEvalTopLevelConstants :: (EnumMap Word64 (GCombs Closure CombIx)) -> (EnumMap Word64 (GCombs Closure CombIx)) -> CCache -> IO () From cd60a76c7b0b082c5210d8d27909ed015975c31b Mon Sep 17 00:00:00 2001 From: ChrisPenner Date: Mon, 30 Sep 2024 02:27:23 +0000 Subject: [PATCH 26/40] automatically run ormolu --- unison-runtime/src/Unison/Runtime/Stack.hs | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/unison-runtime/src/Unison/Runtime/Stack.hs b/unison-runtime/src/Unison/Runtime/Stack.hs index 2a9947f9c9..90139cea78 100644 --- a/unison-runtime/src/Unison/Runtime/Stack.hs +++ b/unison-runtime/src/Unison/Runtime/Stack.hs @@ -131,8 +131,7 @@ instance Ord K where compare (Mark _ _ _ _ _) _ = LT compare _ (Mark _ _ _ _ _) = GT -newtype Closure - = Closure {unClosure :: (GClosure (RComb Closure))} +newtype Closure = Closure {unClosure :: (GClosure (RComb Closure))} deriving stock (Show, Eq, Ord) type IxClosure = GClosure CombIx @@ -424,8 +423,8 @@ class MEM (b :: Mem) where asize :: Stack b -> SZ instance MEM 'UN where - data Stack 'UN - = -- Note: uap <= ufp <= usp + data Stack 'UN = + -- Note: uap <= ufp <= usp US { uap :: !Int, -- arg pointer ufp :: !Int, -- frame pointer From 493daeb0447ed8e63524e1c47d431a6b7a26dd9b Mon Sep 17 00:00:00 2001 From: Chris Penner Date: Sun, 29 Sep 2024 19:31:21 -0700 Subject: [PATCH 27/40] PR Cleanup --- unison-runtime/src/Unison/Runtime/MCode.hs | 4 - .../src/Unison/Runtime/Stack/Serialize.hs | 109 ------------------ unison-runtime/unison-runtime.cabal | 1 - 3 files changed, 114 deletions(-) delete mode 100644 unison-runtime/src/Unison/Runtime/Stack/Serialize.hs diff --git a/unison-runtime/src/Unison/Runtime/MCode.hs b/unison-runtime/src/Unison/Runtime/MCode.hs index b1634a4d46..8ccaeb47e4 100644 --- a/unison-runtime/src/Unison/Runtime/MCode.hs +++ b/unison-runtime/src/Unison/Runtime/MCode.hs @@ -38,7 +38,6 @@ module Unison.Runtime.MCode emitCombs, emitComb, resolveCombs, - unTieRCombs, absurdCombs, emptyRNs, argsToLists, @@ -813,9 +812,6 @@ resolveCombs mayExisting combs = ++ "`." in resolved -unTieRCombs :: EnumMap Word64 (RCombs clos) -> EnumMap Word64 (GCombs clos ()) -unTieRCombs = (fmap . fmap . fmap) (const ()) - absurdCombs :: EnumMap Word64 (EnumMap Word64 (GComb Void cix)) -> EnumMap Word64 (GCombs any cix) absurdCombs = fmap . fmap . first $ absurd diff --git a/unison-runtime/src/Unison/Runtime/Stack/Serialize.hs b/unison-runtime/src/Unison/Runtime/Stack/Serialize.hs deleted file mode 100644 index dd7b088f20..0000000000 --- a/unison-runtime/src/Unison/Runtime/Stack/Serialize.hs +++ /dev/null @@ -1,109 +0,0 @@ -module Unison.Runtime.Stack.Serialize (putClosure, getClosure) where - -import Data.Bytes.Get -import Data.Bytes.Put -import Unison.Runtime.Foreign (Foreign (..)) -import Unison.Runtime.MCode.Serialize (putCombIx) -import Unison.Runtime.Serialize -import Unison.Runtime.Stack (Closure (..), GClosure (..), K (..)) - -data GClosureT - = GPApT - | GEnumT - | GDataU1T - | GDataU2T - | GDataB1T - | GDataB2T - | GDataUBT - | GDataGT - | GCapturedT - | GForeignT - | GBlackHoleT - -instance Tag GClosureT where - tag2word = \case - GPApT -> 0 - GEnumT -> 1 - GDataU1T -> 2 - GDataU2T -> 3 - GDataB1T -> 4 - GDataB2T -> 5 - GDataUBT -> 6 - GDataGT -> 7 - GCapturedT -> 8 - GForeignT -> 9 - GBlackHoleT -> 10 - word2tag = \case - 0 -> pure GPApT - 1 -> pure GEnumT - 2 -> pure GDataU1T - 3 -> pure GDataU2T - 4 -> pure GDataB1T - 5 -> pure GDataB2T - 6 -> pure GDataUBT - 7 -> pure GDataGT - 8 -> pure GCapturedT - 9 -> pure GForeignT - 10 -> pure GBlackHoleT - n -> unknownTag "GClosureT" n - -putClosure :: (MonadPut m) => Closure -> m () -putClosure (Closure gclos) = case gclos of - GPAp cix _comb uargs bargs -> - putTag GPApT *> putCombIx cix *> putByteArray uargs *> putArray putClosure bargs - GEnum r w -> putTag GEnumT *> putReference r *> putNat w - GDataU1 r w i -> putTag GDataU1T *> putReference r *> putNat w *> putI i - GDataU2 r w i j -> putTag GDataU2T *> putReference r *> putNat w *> putI i *> putI j - GDataB1 r w clos -> putTag GDataB1T *> putReference r *> putNat w *> putClosure (Closure clos) - GDataB2 r w c1 c2 -> putTag GDataB2T *> putReference r *> putNat w *> putClosure (Closure c1) *> putClosure (Closure c2) - GDataUB r w i c -> putTag GDataUBT *> putReference r *> putNat w *> putI i *> putClosure (Closure c) - GDataG r w usegs bsegs -> putTag GDataGT *> putReference r *> putNat w *> putByteArray usegs *> putArray putClosure bsegs - GCaptured k i j s1 s2 -> putTag GCapturedT *> putK k *> putI i *> putI j *> putByteArray s1 *> putArray putClosure s2 - GForeign (Wrap ref _) -> error $ "putClosure: Cannot serialize foreign, ref: " <> show ref - GBlackHole -> putTag GBlackHoleT - where - putI = putInt . fromIntegral - -getClosure :: (MonadGet m) => m Closure -getClosure = error "getClosure not implemented" - -data KTag - = KET - | CBT - | MarkT - | PushT - -instance Tag KTag where - tag2word = \case - KET -> 0 - CBT -> 1 - MarkT -> 2 - PushT -> 3 - word2tag = \case - 0 -> pure KET - 1 -> pure CBT - 2 -> pure MarkT - 3 -> pure PushT - n -> unknownTag "KTag" n - -putK :: (MonadPut m) => K -> m () -putK = \case - KE {} -> putTag KET - CB {} -> error "putK: Cannot serialize Callback" - Mark puarg pbarg ws cs k -> - putTag MarkT - *> putI puarg - *> putI pbarg - *> putEnumSet putNat ws - *> putEnumMap putNat putClosure cs - *> putK k - Push ufsz bfsz puarg pbarg cix _comb k -> - putTag PushT - *> putI ufsz - *> putI bfsz - *> putI puarg - *> putI pbarg - *> putCombIx cix - *> putK k - where - putI = putInt . fromIntegral diff --git a/unison-runtime/unison-runtime.cabal b/unison-runtime/unison-runtime.cabal index ed7b8688db..ea54c20b6a 100644 --- a/unison-runtime/unison-runtime.cabal +++ b/unison-runtime/unison-runtime.cabal @@ -49,7 +49,6 @@ library Unison.Runtime.Serialize Unison.Runtime.SparseVector Unison.Runtime.Stack - Unison.Runtime.Stack.Serialize Unison.Runtime.Vector hs-source-dirs: src From ad3225fce87922431753ad834c4029dbfd302abc Mon Sep 17 00:00:00 2001 From: Dan Doel Date: Mon, 30 Sep 2024 17:15:39 -0400 Subject: [PATCH 28/40] Tweak MCode Let representation This introduces a minor change to the structure of MCode Let bindings. Before various refactoring, a Let would use a CombIx to indicate where execution should resume once the binding is evaluated. Now the code is resolved ahead of time and referred to directly. However, logically this code is just a further Section; the rest of the actual function that contained the Let. The purpose of using a Comb was to store stack protection information, so that the stack check can be performed upon reentry. This is necessary if the continuation has been captured and we are resuming in a context that was not the original entry point of the resumption. Now, though, a top level 'comb' can be either code or a memoized value, but a resumption will never be the latter. So Let has been changed to store the relevant information, instead of delegating to Comb. --- unison-runtime/src/Unison/Runtime/MCode.hs | 24 ++++--- .../src/Unison/Runtime/MCode/Serialize.hs | 14 +++-- unison-runtime/src/Unison/Runtime/Machine.hs | 63 ++++++++++--------- unison-runtime/src/Unison/Runtime/Stack.hs | 19 +++--- 4 files changed, 69 insertions(+), 51 deletions(-) diff --git a/unison-runtime/src/Unison/Runtime/MCode.hs b/unison-runtime/src/Unison/Runtime/MCode.hs index 8ccaeb47e4..1a5612aa2e 100644 --- a/unison-runtime/src/Unison/Runtime/MCode.hs +++ b/unison-runtime/src/Unison/Runtime/MCode.hs @@ -564,7 +564,11 @@ data GSection comb | -- Sequence two sections. The second is pushed as a return -- point for the results of the first. Stack modifications in -- the first are lost on return to the second. - Let !(GSection comb) !CombIx {- Lazy! Might be cyclic -} comb + Let !(GSection comb) -- binding + !CombIx -- body section refrence + !Int -- unboxed stack safety + !Int -- boxed stack safety + !(GSection comb) -- body code | -- Throw an exception with the given message Die String | -- Immediately stop a thread of interpretation. This is more of @@ -846,12 +850,13 @@ onCount f (EM e) = EM $ fmap f <$> e letIndex :: Word16 -> Word64 -> Word64 letIndex l c = c .|. fromIntegral l -record :: Ctx v -> Word16 -> Emit Section -> Emit Word64 +record :: Ctx v -> Word16 -> Emit Section -> Emit (Word64, Comb) record ctx l (EM es) = EM $ \c -> let (m, C u b s) = es c (au, ab) = countCtx0 0 0 ctx n = letIndex l c - in (EC.mapInsert n (Lam au ab u b s) m, C u b n) + comb = Lam au ab u b s + in (EC.mapInsert n comb m, C u b (n, comb)) recordTop :: [v] -> Word16 -> Emit Section -> Emit () recordTop vs l (EM e) = EM $ \c -> @@ -1162,9 +1167,9 @@ emitLet rns grpr grpn rec d vcs ctx bnd <$> emitSection rns grpr grpn rec (Block ctx) bnd <*> record (pushCtx vcs ctx) w esect where - f s w = + f s (w , Lam _ _ un bx bd) = let cix = (CIx grpr grpn w) - in Let s cix cix + in Let s cix un bx bd -- Translate from ANF prim ops to machine code operations. The -- machine code operations are divided with respect to more detailed @@ -1565,12 +1570,13 @@ sectionDeps (NMatch _ _ br) = branchDeps br sectionDeps (Ins i s) | Name (Env (CIx _ w _) _) _ <- i = w : sectionDeps s | otherwise = sectionDeps s -sectionDeps (Let s (CIx _ w _) _) = w : sectionDeps s +sectionDeps (Let s (CIx _ w _) _ _ b) = + w : sectionDeps s ++ sectionDeps b sectionDeps _ = [] sectionTypes :: GSection comb -> [Word64] sectionTypes (Ins i s) = instrTypes i ++ sectionTypes s -sectionTypes (Let s _ _) = sectionTypes s +sectionTypes (Let s _ _ _ b) = sectionTypes s ++ sectionTypes b sectionTypes (Match _ br) = branchTypes br sectionTypes (DMatch _ _ br) = branchTypes br sectionTypes (NMatch _ _ br) = branchTypes br @@ -1646,12 +1652,12 @@ prettySection ind sec = Yield as -> showString "Yield " . prettyArgs as Ins i nx -> prettyIns i . showString "\n" . prettySection ind nx - Let s n _ -> + Let s _ _ _ b -> showString "Let\n" . prettySection (ind + 2) s . showString "\n" . indent ind - . prettyIx n + . prettySection ind b Die s -> showString $ "Die " ++ s Exit -> showString "Exit" DMatch _ i bs -> diff --git a/unison-runtime/src/Unison/Runtime/MCode/Serialize.hs b/unison-runtime/src/Unison/Runtime/MCode/Serialize.hs index 5817517352..39a430c81b 100644 --- a/unison-runtime/src/Unison/Runtime/MCode/Serialize.hs +++ b/unison-runtime/src/Unison/Runtime/MCode/Serialize.hs @@ -96,7 +96,13 @@ putSection = \case Match i b -> putTag MatchT *> pInt i *> putBranch b Yield a -> putTag YieldT *> putArgs a Ins i s -> putTag InsT *> putInstr i *> putSection s - Let s ci _comb -> putTag LetT *> putSection s *> putCombIx ci + Let s ci uf bf bd -> + putTag LetT + *> putSection s + *> putCombIx ci + *> pInt uf + *> pInt bf + *> putSection bd Die s -> putTag DieT *> serialize s Exit -> putTag ExitT DMatch mr i b -> putTag DMatchT *> putMaybe mr putReference *> pInt i *> putBranch b @@ -120,10 +126,8 @@ getSection = MatchT -> Match <$> gInt <*> getBranch YieldT -> Yield <$> getArgs InsT -> Ins <$> getInstr <*> getSection - LetT -> do - s <- getSection - cix <- getCombIx - pure $ Let s cix cix + LetT -> + Let <$> getSection <*> getCombIx <*> gInt <*> gInt <*> getSection DieT -> Die <$> deserialize ExitT -> pure Exit DMatchT -> DMatch <$> getMaybe getReference <*> gInt <*> getBranch diff --git a/unison-runtime/src/Unison/Runtime/Machine.hs b/unison-runtime/src/Unison/Runtime/Machine.hs index 4567031b44..cffb6236b6 100644 --- a/unison-runtime/src/Unison/Runtime/Machine.hs +++ b/unison-runtime/src/Unison/Runtime/Machine.hs @@ -672,10 +672,12 @@ eval !env !denv !activeThreads !ustk !bstk !k _ (Call ck _combIx rcomb args) = enter env denv activeThreads ustk bstk k ck args rcomb eval !env !denv !activeThreads !ustk !bstk !k _ (Jump i args) = peekOff bstk i >>= jump env denv activeThreads ustk bstk k args -eval !env !denv !activeThreads !ustk !bstk !k r (Let nw cix comb) = do +eval !env !denv !activeThreads !ustk !bstk !k r (Let nw cix uf bf sect) = do (ustk, ufsz, uasz) <- saveFrame ustk (bstk, bfsz, basz) <- saveFrame bstk - eval env denv activeThreads ustk bstk (Push ufsz bfsz uasz basz cix comb k) r nw + eval env denv activeThreads ustk bstk + (Push ufsz bfsz uasz basz cix uf bf sect k) + r nw eval !env !denv !activeThreads !ustk !bstk !k r (Ins i nx) = do (denv, ustk, bstk, k) <- exec env denv activeThreads ustk bstk k r i eval env denv activeThreads ustk bstk k r nx @@ -843,8 +845,8 @@ jump !env !denv !activeThreads !ustk !bstk !k !args clo = case clo of -- pending, and the result stacks need to be adjusted. Hence the 3 results. adjust (Mark ua ba rs denv k) = (0, 0, Mark (ua + asize ustk) (ba + asize bstk) rs denv k) - adjust (Push un bn ua ba cix rcomb k) = - (0, 0, Push un bn (ua + asize ustk) (ba + asize bstk) cix rcomb k) + adjust (Push un bn ua ba cix uf bf rsect k) = + (0, 0, Push un bn (ua + asize ustk) (ba + asize bstk) cix uf bf rsect k) adjust k = (asize ustk, asize bstk, k) {-# INLINE jump #-} @@ -864,8 +866,8 @@ repush !env !activeThreads !ustk !bstk = go where denv' = cs <> EC.withoutKeys denv ps cs' = EC.restrictKeys denv ps - go !denv (Push un bn ua ba cix rcomb sk) !k = - go denv sk $ Push un bn ua ba cix rcomb k + go !denv (Push un bn ua ba cix uf bf rsect sk) !k = + go denv sk $ Push un bn ua ba cix uf bf rsect k go !_ (CB _) !_ = die "repush: impossible" {-# INLINE repush #-} @@ -1879,16 +1881,12 @@ yield !env !denv !activeThreads !ustk !bstk !k = leap denv k ustk <- adjustArgs ustk ua bstk <- adjustArgs bstk ba apply env denv activeThreads ustk bstk k False (BArg1 0) clo - leap !denv (Push ufsz bfsz uasz basz (CIx ref _ _) rComb k) = do - case unRComb rComb of - Lam _ _ uf bf nx -> do - ustk <- restoreFrame ustk ufsz uasz - bstk <- restoreFrame bstk bfsz basz - ustk <- ensure ustk uf - bstk <- ensure bstk bf - eval env denv activeThreads ustk bstk k ref nx - CachedClosure _w _clo -> do - error "TODO: Get help from Dan" + leap !denv (Push ufsz bfsz uasz basz (CIx ref _ _) uf bf nx k) = do + ustk <- restoreFrame ustk ufsz uasz + bstk <- restoreFrame bstk bfsz basz + ustk <- ensure ustk uf + bstk <- ensure bstk bf + eval env denv activeThreads ustk bstk k ref nx leap _ (CB (Hook f)) = f ustk bstk leap _ KE = pure () {-# INLINE yield #-} @@ -1944,8 +1942,9 @@ splitCont !denv !ustk !bstk !k !p = where denv' = cs <> EC.withoutKeys denv ps cs' = EC.restrictKeys denv ps - walk !denv !usz !bsz !ck (Push un bn ua ba br brComb k) = - walk denv (usz + un + ua) (bsz + bn + ba) (Push un bn ua ba br brComb ck) k + walk !denv !usz !bsz !ck (Push un bn ua ba br up bp brSect k) = + walk denv (usz + un + ua) (bsz + bn + ba) + (Push un bn ua ba br up bp brSect ck) k finish !denv !usz !bsz !ua !ba !ck !k = do (useg, ustk) <- grab ustk usz @@ -2282,7 +2281,7 @@ reflectValue rty = goV ps <- traverse refTy (EC.setToList ps) de <- traverse (\(k, v) -> (,) <$> refTy k <*> goV v) (mapToList de) ANF.Mark (fromIntegral ua) (fromIntegral ba) ps (M.fromList de) <$> goK k - goK (Push uf bf ua ba cix _rComb k) = + goK (Push uf bf ua ba cix _ _ _rsect k) = ANF.Push (fromIntegral uf) (fromIntegral bf) @@ -2384,16 +2383,22 @@ reifyValue0 (combs, rty, rtm) = goV where mrk ps de k = Mark (fromIntegral ua) (fromIntegral ba) (setFromList ps) (mapFromList de) k - goK (ANF.Push uf bf ua ba gr k) = do - (cix, rcomb) <- goIx gr - Push - (fromIntegral uf) - (fromIntegral bf) - (fromIntegral ua) - (fromIntegral ba) - cix - rcomb - <$> goK k + goK (ANF.Push uf bf ua ba gr k) = goIx gr >>= \case + (cix, RComb (Lam _ _ un bx sect)) -> + Push + (fromIntegral uf) + (fromIntegral bf) + (fromIntegral ua) + (fromIntegral ba) + cix + un + bx + sect + <$> goK k + (CIx r _ _ , _) -> + die . err $ + "tried to reify a continuation with a cached value resumption" + ++ show r goL (ANF.Text t) = pure . Foreign $ Wrap Rf.textRef t goL (ANF.List l) = Foreign . Wrap Rf.listRef <$> traverse goV l diff --git a/unison-runtime/src/Unison/Runtime/Stack.hs b/unison-runtime/src/Unison/Runtime/Stack.hs index 90139cea78..cf632a66a6 100644 --- a/unison-runtime/src/Unison/Runtime/Stack.hs +++ b/unison-runtime/src/Unison/Runtime/Stack.hs @@ -104,8 +104,10 @@ data K !Int -- boxed frame size !Int -- pending unboxed args !Int -- pending boxed args - !CombIx - (RComb Closure) -- local continuation reference + !CombIx -- resumption section reference + !Int -- unboxed stack guard + !Int -- boxed stack guard + !(RSection Closure) -- resumption section !K instance Eq K where @@ -113,7 +115,7 @@ instance Eq K where (CB cb) == (CB cb') = cb == cb' (Mark ua ba ps m k) == (Mark ua' ba' ps' m' k') = ua == ua' && ba == ba' && ps == ps' && m == m' && k == k' - (Push uf bf ua ba ci _comb k) == (Push uf' bf' ua' ba' ci' _comb' k') = + (Push uf bf ua ba ci _ _ _sect k) == (Push uf' bf' ua' ba' ci' _ _ _sect' k') = uf == uf' && bf == bf' && ua == ua' && ba == ba' && ci == ci' && k == k' _ == _ = False @@ -122,7 +124,7 @@ instance Ord K where compare (CB cb) (CB cb') = compare cb cb' compare (Mark ua ba ps m k) (Mark ua' ba' ps' m' k') = compare (ua, ba, ps, m, k) (ua', ba', ps', m', k') - compare (Push uf bf ua ba ci _comb k) (Push uf' bf' ua' ba' ci' _comb' k') = + compare (Push uf bf ua ba ci _ _ _sect k) (Push uf' bf' ua' ba' ci' _ _ _sect' k') = compare (uf, bf, ua, ba, ci, k) (uf', bf', ua', ba', ci', k') compare KE _ = LT compare _ KE = GT @@ -195,7 +197,7 @@ traceK :: Reference -> K -> [(Reference, Int)] traceK begin = dedup (begin, 1) where dedup p (Mark _ _ _ _ k) = dedup p k - dedup p@(cur, n) (Push _ _ _ _ (CIx r _ _) _ k) + dedup p@(cur, n) (Push _ _ _ _ (CIx r _ _) _ _ _ k) | cur == r = dedup (cur, 1 + n) k | otherwise = p : dedup (r, 1) k dedup p _ = [p] @@ -251,7 +253,8 @@ frameDataSize = go 0 0 go usz bsz KE = (usz, bsz) go usz bsz (CB _) = (usz, bsz) go usz bsz (Mark ua ba _ _ k) = go (usz + ua) (bsz + ba) k - go usz bsz (Push uf bf ua ba _ _ k) = go (usz + uf + ua) (bsz + bf + ba) k + go usz bsz (Push uf bf ua ba _ _ _ _ k) = + go (usz + uf + ua) (bsz + bf + ba) k pattern DataC :: Reference -> Word64 -> [Int] -> [Closure] -> Closure pattern DataC rf ct us bs <- @@ -634,7 +637,7 @@ instance Show K where where go _ KE = "]" go _ (CB _) = "]" - go com (Push uf bf ua ba ci _rcomb k) = + go com (Push uf bf ua ba ci _un _bx _rsect k) = com ++ show (uf, bf, ua, ba, ci) ++ go "," k go com (Mark ua ba ps _ k) = com ++ "M " ++ show ua ++ " " ++ show ba ++ " " ++ show ps ++ go "," k @@ -805,6 +808,6 @@ closureTermRefs f = \case contTermRefs :: (Monoid m) => (Reference -> m) -> K -> m contTermRefs f (Mark _ _ _ m k) = foldMap (closureTermRefs f) m <> contTermRefs f k -contTermRefs f (Push _ _ _ _ (CIx r _ _) _ k) = +contTermRefs f (Push _ _ _ _ (CIx r _ _) _ _ b k) = f r <> contTermRefs f k contTermRefs _ _ = mempty From 4ff96efa962b6622f67e42e5c31a8a98e8195234 Mon Sep 17 00:00:00 2001 From: Dan Doel Date: Mon, 30 Sep 2024 17:27:12 -0400 Subject: [PATCH 29/40] Add some documentation about the new MCode Let --- unison-runtime/src/Unison/Runtime/MCode.hs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/unison-runtime/src/Unison/Runtime/MCode.hs b/unison-runtime/src/Unison/Runtime/MCode.hs index 1a5612aa2e..3cafc8e11e 100644 --- a/unison-runtime/src/Unison/Runtime/MCode.hs +++ b/unison-runtime/src/Unison/Runtime/MCode.hs @@ -564,6 +564,12 @@ data GSection comb | -- Sequence two sections. The second is pushed as a return -- point for the results of the first. Stack modifications in -- the first are lost on return to the second. + -- + -- The stored CombIx is a combinator that contains the second + -- section, which can be used to reconstruct structures that + -- throw away the section, like serializable continuation values. + -- Code generation will emit the section as its own combinator, + -- but also include it directly here. Let !(GSection comb) -- binding !CombIx -- body section refrence !Int -- unboxed stack safety From 3164f82ae463eaf3b5a267c50848bee4a12f8077 Mon Sep 17 00:00:00 2001 From: Dan Doel Date: Mon, 30 Sep 2024 17:34:32 -0400 Subject: [PATCH 30/40] Remove now unnecessary prettyIx --- unison-runtime/src/Unison/Runtime/MCode.hs | 8 -------- 1 file changed, 8 deletions(-) diff --git a/unison-runtime/src/Unison/Runtime/MCode.hs b/unison-runtime/src/Unison/Runtime/MCode.hs index 3cafc8e11e..284f577837 100644 --- a/unison-runtime/src/Unison/Runtime/MCode.hs +++ b/unison-runtime/src/Unison/Runtime/MCode.hs @@ -1689,14 +1689,6 @@ prettySection ind sec = . showString " ->\n" . prettyBranches (ind + 1) e -prettyIx :: CombIx -> ShowS -prettyIx (CIx _ c s) = - showString "Resume[" - . shows c - . showString "," - . shows s - . showString "]" - prettyBranches :: (Show comb) => Int -> GBranch comb -> ShowS prettyBranches ind bs = case bs of From 42f6d76ee6ea1643da918dc13caefa350b368a90 Mon Sep 17 00:00:00 2001 From: dolio Date: Mon, 30 Sep 2024 21:35:30 +0000 Subject: [PATCH 31/40] automatically run ormolu --- unison-runtime/src/Unison/Runtime/MCode.hs | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/unison-runtime/src/Unison/Runtime/MCode.hs b/unison-runtime/src/Unison/Runtime/MCode.hs index 284f577837..33a6528189 100644 --- a/unison-runtime/src/Unison/Runtime/MCode.hs +++ b/unison-runtime/src/Unison/Runtime/MCode.hs @@ -570,11 +570,12 @@ data GSection comb -- throw away the section, like serializable continuation values. -- Code generation will emit the section as its own combinator, -- but also include it directly here. - Let !(GSection comb) -- binding - !CombIx -- body section refrence - !Int -- unboxed stack safety - !Int -- boxed stack safety - !(GSection comb) -- body code + Let + !(GSection comb) -- binding + !CombIx -- body section refrence + !Int -- unboxed stack safety + !Int -- boxed stack safety + !(GSection comb) -- body code | -- Throw an exception with the given message Die String | -- Immediately stop a thread of interpretation. This is more of @@ -1173,7 +1174,7 @@ emitLet rns grpr grpn rec d vcs ctx bnd <$> emitSection rns grpr grpn rec (Block ctx) bnd <*> record (pushCtx vcs ctx) w esect where - f s (w , Lam _ _ un bx bd) = + f s (w, Lam _ _ un bx bd) = let cix = (CIx grpr grpn w) in Let s cix un bx bd From 0ea57fc234239e0436dccf722e37bbac48503746 Mon Sep 17 00:00:00 2001 From: Dan Doel Date: Mon, 30 Sep 2024 17:51:09 -0400 Subject: [PATCH 32/40] Fix unused binding warning --- unison-runtime/src/Unison/Runtime/Stack.hs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/unison-runtime/src/Unison/Runtime/Stack.hs b/unison-runtime/src/Unison/Runtime/Stack.hs index cf632a66a6..2c76cd4a7c 100644 --- a/unison-runtime/src/Unison/Runtime/Stack.hs +++ b/unison-runtime/src/Unison/Runtime/Stack.hs @@ -808,6 +808,6 @@ closureTermRefs f = \case contTermRefs :: (Monoid m) => (Reference -> m) -> K -> m contTermRefs f (Mark _ _ _ m k) = foldMap (closureTermRefs f) m <> contTermRefs f k -contTermRefs f (Push _ _ _ _ (CIx r _ _) _ _ b k) = +contTermRefs f (Push _ _ _ _ (CIx r _ _) _ _ _ k) = f r <> contTermRefs f k contTermRefs _ _ = mempty From eeadb6d92048ae210f48280aeba2c2c0541d6dbc Mon Sep 17 00:00:00 2001 From: Dan Doel Date: Fri, 4 Oct 2024 01:05:06 -0400 Subject: [PATCH 33/40] Factor GComb a bit, and make PAp more correct A PAp should only contain an actual combinator, not a cached value. So, the combinator case has been factored out of and unpacked into GComb. This way a PAp can refer to the factored-out part. --- unison-runtime/src/Unison/Runtime/MCode.hs | 26 +++++++--- unison-runtime/src/Unison/Runtime/Machine.hs | 50 ++++++++++++-------- unison-runtime/src/Unison/Runtime/Stack.hs | 5 +- 3 files changed, 52 insertions(+), 29 deletions(-) diff --git a/unison-runtime/src/Unison/Runtime/MCode.hs b/unison-runtime/src/Unison/Runtime/MCode.hs index 33a6528189..d3c683fa43 100644 --- a/unison-runtime/src/Unison/Runtime/MCode.hs +++ b/unison-runtime/src/Unison/Runtime/MCode.hs @@ -17,9 +17,11 @@ module Unison.Runtime.MCode GSection (.., MatchT, MatchW), RSection, Section, - GComb (..), + GComb (.., Lam), + GCombInfo (..), Comb, RComb (..), + RCombInfo, GCombs, RCombs, CombIx (..), @@ -622,17 +624,29 @@ emptyRNs = RN mt mt type Comb = GComb Void CombIx -data GComb clos comb - = Lam +-- Actual information for a proper combinator. The GComb type is no +-- longer strictly a 'combinator.' +data GCombInfo comb + = LamI !Int -- Number of unboxed arguments !Int -- Number of boxed arguments !Int -- Maximum needed unboxed frame size !Int -- Maximum needed boxed frame size !(GSection comb) -- Entry + deriving stock (Show, Eq, Ord, Functor, Foldable, Traversable) + +data GComb clos comb + = Comb {-# unpack #-} !(GCombInfo comb) | -- A pre-evaluated comb, typically a pure top-level const CachedClosure !Word64 {- top level comb ix -} !clos deriving stock (Show, Eq, Ord, Functor, Foldable, Traversable) +pattern Lam + :: Int -> Int -> Int -> Int -> GSection comb -> GComb clos comb +pattern Lam ua ba uf bf sect = Comb (LamI ua ba uf bf sect) +-- it seems GHC can't figure this out itself +{-# complete CachedClosure, Lam #-} + instance Bifunctor GComb where bimap = bimapDefault @@ -646,9 +660,9 @@ instance Bitraversable GComb where type RCombs clos = GCombs clos (RComb clos) -- | The fixed point of a GComb where all references to a Comb are themselves Combs. -newtype RComb clos = RComb - { unRComb :: (GComb clos (RComb clos {- Possibly recursive comb, keep it lazy or risk blowing up -})) - } +newtype RComb clos = RComb { unRComb :: GComb clos (RComb clos) } + +type RCombInfo clos = GCombInfo (RComb clos) instance Show (RComb clos) where show _ = "" diff --git a/unison-runtime/src/Unison/Runtime/Machine.hs b/unison-runtime/src/Unison/Runtime/Machine.hs index cffb6236b6..69281e42f4 100644 --- a/unison-runtime/src/Unison/Runtime/Machine.hs +++ b/unison-runtime/src/Unison/Runtime/Machine.hs @@ -198,6 +198,11 @@ eval0 !env !activeThreads !co = do topDEnv cmbs <$> readTVarIO (refTy env) <*> readTVarIO (refTm env) eval env denv activeThreads ustk bstk (k KE) dummyRef co +mCombClosure :: CombIx -> MComb -> Closure +mCombClosure cix (RComb (Comb comb)) = + PAp cix comb unull bnull +mCombClosure _ (RComb (CachedClosure _ clo)) = clo + topDEnv :: EnumMap Word64 MCombs -> M.Map Reference Word64 -> @@ -205,14 +210,13 @@ topDEnv :: (DEnv, K -> K) topDEnv combs rfTy rfTm | Just n <- M.lookup exceptionRef rfTy, - -- TODO: Should I special-case this raise ref and pass it down from the top rather than always looking it up? rcrf <- Builtin (DTx.pack "raise"), - Just j <- M.lookup rcrf rfTm = - let cix = (CIx rcrf j 0) - comb = rCombSection combs cix - in ( EC.mapSingleton n (PAp cix comb unull bnull), - Mark 0 0 (EC.setSingleton n) mempty - ) + Just j <- M.lookup rcrf rfTm, + cix <- CIx rcrf j 0, + clo <- mCombClosure cix $ rCombSection combs cix = + ( EC.mapSingleton n clo, + Mark 0 0 (EC.setSingleton n) mempty + ) topDEnv _ _ _ = (mempty, id) -- Entry point for evaluating a numbered combinator. @@ -237,9 +241,12 @@ apply0 !callback !env !threadTracker !i = do Just r -> pure r Nothing -> die "apply0: missing reference to entry point" let entryCix = (CIx r i 0) - let entryComb = rCombSection cmbs entryCix - apply env denv threadTracker ustk bstk (kf k0) True ZArgs $ - PAp entryCix entryComb unull bnull + case unRComb $ rCombSection cmbs entryCix of + Comb entryComb -> + apply env denv threadTracker ustk bstk (kf k0) True ZArgs $ + PAp entryCix entryComb unull bnull + -- if it's cached, we can just finish + CachedClosure _ clo -> bump bstk >>= \bstk -> poke bstk clo where k0 = maybe KE (CB . Hook) callback @@ -777,10 +784,8 @@ apply :: IO () apply !env !denv !activeThreads !ustk !bstk !k !ck !args = \case (PAp cix@(CIx combRef _ _) comb useg bseg) -> - case unRComb comb of - CachedClosure _cix clos -> do - zeroArgClosure clos - Lam ua ba uf bf entry + case comb of + LamI ua ba uf bf entry | ck || ua <= uac && ba <= bac -> do ustk <- ensure ustk uf bstk <- ensure bstk bf @@ -1967,7 +1972,7 @@ discardCont denv ustk bstk k p = {-# INLINE discardCont #-} resolve :: CCache -> DEnv -> Stack 'BX -> MRef -> IO Closure -resolve _ _ _ (Env cix rComb) = pure $ PAp cix rComb unull bnull +resolve _ _ _ (Env cix mcomb) = pure $ mCombClosure cix mcomb resolve _ _ bstk (Stk i) = peekOff bstk i resolve env denv _ (Dyn i) = case EC.lookup i denv of Just clo -> pure clo @@ -2356,12 +2361,15 @@ reifyValue0 (combs, rty, rtm) = goV let cix = (CIx r n i) in (cix, rCombSection combs cix) - goV (ANF.Partial gr ua ba) = do - (cix, rcomb) <- goIx gr - clos <- traverse goV ba - pure $ pap cix rcomb clos - where - pap cix i = PApV cix i (fromIntegral <$> ua) + goV (ANF.Partial gr ua ba) = goIx gr >>= \case + (cix, RComb (Comb rcomb)) -> pap cix rcomb <$> traverse goV ba + where + pap cix i = PApV cix i (fromIntegral <$> ua) + (_, RComb (CachedClosure _ clo)) + | [] <- ua, [] <- ba -> pure clo + | otherwise -> die . err $ msg + where + msg = "reifyValue0: non-trivial partial application to cached value" goV (ANF.Data r t0 us bs) = do t <- flip packTags (fromIntegral t0) . fromIntegral <$> refTy r DataC r t (fromIntegral <$> us) <$> traverse goV bs diff --git a/unison-runtime/src/Unison/Runtime/Stack.hs b/unison-runtime/src/Unison/Runtime/Stack.hs index 2c76cd4a7c..a0528c1d3b 100644 --- a/unison-runtime/src/Unison/Runtime/Stack.hs +++ b/unison-runtime/src/Unison/Runtime/Stack.hs @@ -141,7 +141,7 @@ type IxClosure = GClosure CombIx data GClosure comb = GPAp !CombIx - {- Lazy! Might be cyclic -} comb + {-# UNPACK #-} !(GCombInfo comb) {-# UNPACK #-} !(Seg 'UN) -- unboxed args {- unpack -} !(Seg 'BX) -- boxed args @@ -262,7 +262,8 @@ pattern DataC rf ct us bs <- where DataC rf ct us bs = formData rf ct us bs -pattern PApV :: CombIx -> RComb Closure -> [Int] -> [Closure] -> Closure +pattern PApV + :: CombIx -> RCombInfo Closure -> [Int] -> [Closure] -> Closure pattern PApV cix rcomb us bs <- PAp cix rcomb (ints -> us) (bsegToList -> bs) where From 3c7078751f8594b68da10421eb32baf3ccb38e77 Mon Sep 17 00:00:00 2001 From: dolio Date: Fri, 4 Oct 2024 13:38:59 +0000 Subject: [PATCH 34/40] automatically run ormolu --- unison-runtime/src/Unison/Runtime/Stack.hs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/unison-runtime/src/Unison/Runtime/Stack.hs b/unison-runtime/src/Unison/Runtime/Stack.hs index a0528c1d3b..f916a12166 100644 --- a/unison-runtime/src/Unison/Runtime/Stack.hs +++ b/unison-runtime/src/Unison/Runtime/Stack.hs @@ -262,8 +262,8 @@ pattern DataC rf ct us bs <- where DataC rf ct us bs = formData rf ct us bs -pattern PApV - :: CombIx -> RCombInfo Closure -> [Int] -> [Closure] -> Closure +pattern PApV :: + CombIx -> RCombInfo Closure -> [Int] -> [Closure] -> Closure pattern PApV cix rcomb us bs <- PAp cix rcomb (ints -> us) (bsegToList -> bs) where From 2982c5e19256b5e7146205af954ca4404d84eb04 Mon Sep 17 00:00:00 2001 From: Dan Doel Date: Fri, 4 Oct 2024 16:32:59 -0400 Subject: [PATCH 35/40] Include cacheability information in Code values This allows code sent between machines to pre-evaluate things if applicable. Naturally, this requires serialization version changes. Some tweaks have been made to avoid changing hashes as much as possible between versions. Old serialized values and code can still be loaded, but obviously they will be treated as completely uncacheable. --- unison-runtime/src/Unison/Runtime/ANF.hs | 38 +++++++++- .../src/Unison/Runtime/ANF/Rehash.hs | 28 +++---- .../src/Unison/Runtime/ANF/Serialize.hs | 57 ++++++++++---- unison-runtime/src/Unison/Runtime/Builtin.hs | 19 ++--- unison-runtime/src/Unison/Runtime/Foreign.hs | 11 +-- .../src/Unison/Runtime/Foreign/Function.hs | 5 +- .../src/Unison/Runtime/Interface.hs | 76 ++++++++++--------- unison-runtime/src/Unison/Runtime/Machine.hs | 45 ++++++----- .../transcripts-using-base/random-deserial.md | 23 ++++-- .../random-deserial.output.md | 23 ++++-- .../transcripts-using-base/serial-test-00.md | 2 +- .../serial-test-00.output.md | 2 +- .../transcripts-using-base/serial-test-01.md | 2 +- .../serial-test-01.output.md | 2 +- .../transcripts-using-base/serial-test-02.md | 2 +- .../serial-test-02.output.md | 2 +- .../transcripts-using-base/serial-test-03.md | 2 +- .../serial-test-03.output.md | 2 +- .../transcripts-using-base/serial-test-04.md | 2 +- .../serial-test-04.output.md | 2 +- .../serialized-cases/case-00.v5.hash | 1 + .../serialized-cases/case-00.v5.ser | 1 + .../serialized-cases/case-01.v5.hash | 1 + .../serialized-cases/case-01.v5.ser | 1 + .../serialized-cases/case-02.v5.hash | 1 + .../serialized-cases/case-02.v5.ser | 1 + .../serialized-cases/case-03.v5.hash | 1 + .../serialized-cases/case-03.v5.ser | 1 + .../serialized-cases/case-04.v5.hash | 1 + .../serialized-cases/case-04.v5.ser | 1 + 30 files changed, 223 insertions(+), 132 deletions(-) create mode 100644 unison-src/transcripts-using-base/serialized-cases/case-00.v5.hash create mode 100644 unison-src/transcripts-using-base/serialized-cases/case-00.v5.ser create mode 100644 unison-src/transcripts-using-base/serialized-cases/case-01.v5.hash create mode 100644 unison-src/transcripts-using-base/serialized-cases/case-01.v5.ser create mode 100644 unison-src/transcripts-using-base/serialized-cases/case-02.v5.hash create mode 100644 unison-src/transcripts-using-base/serialized-cases/case-02.v5.ser create mode 100644 unison-src/transcripts-using-base/serialized-cases/case-03.v5.hash create mode 100644 unison-src/transcripts-using-base/serialized-cases/case-03.v5.ser create mode 100644 unison-src/transcripts-using-base/serialized-cases/case-04.v5.hash create mode 100644 unison-src/transcripts-using-base/serialized-cases/case-04.v5.ser diff --git a/unison-runtime/src/Unison/Runtime/ANF.hs b/unison-runtime/src/Unison/Runtime/ANF.hs index 0c2fa20ff8..c4e1ef15e6 100644 --- a/unison-runtime/src/Unison/Runtime/ANF.hs +++ b/unison-runtime/src/Unison/Runtime/ANF.hs @@ -33,6 +33,7 @@ module Unison.Runtime.ANF internalBug, Mem (..), Lit (..), + Cacheability (..), Direction (..), SuperNormal (..), SuperGroup (..), @@ -53,6 +54,7 @@ module Unison.Runtime.ANF CTag, Tag (..), GroupRef (..), + Code (..), Value (..), Cont (..), BLit (..), @@ -66,11 +68,15 @@ module Unison.Runtime.ANF equivocate, superNormalize, anfTerm, + codeGroup, valueTermLinks, valueLinks, groupTermLinks, + foldGroup, foldGroupLinks, + overGroup, overGroupLinks, + traverseGroup, traverseGroupLinks, normalLinks, prettyGroup, @@ -1476,6 +1482,11 @@ data SuperGroup v = Rec } deriving (Show) +-- | Whether the evaluation of a given definition is cacheable or not. +-- i.e. it's a top-level pure value. +data Cacheability = Cacheable | Uncacheable + deriving stock (Eq, Show) + instance (Var v) => Eq (SuperGroup v) where g0 == g1 | Left _ <- equivocate g0 g1 = False | otherwise = True @@ -1529,6 +1540,31 @@ data Value | BLit BLit deriving (Show) +-- Since we can now track cacheability of supergroups, this type +-- pairs the two together. This is the type that should be used +-- as the representation of unison Code values rather than the +-- previous `SuperGroup Symbol`. +data Code = CodeRep (SuperGroup Symbol) Cacheability + deriving (Show) + +codeGroup :: Code -> SuperGroup Symbol +codeGroup (CodeRep sg _) = sg + +instance Eq Code where + CodeRep sg1 _ == CodeRep sg2 _ = sg1 == sg2 + +overGroup :: (SuperGroup Symbol -> SuperGroup Symbol) -> Code -> Code +overGroup f (CodeRep sg ch) = CodeRep (f sg) ch + +foldGroup :: Monoid m => (SuperGroup Symbol -> m) -> Code -> m +foldGroup f (CodeRep sg _) = f sg + +traverseGroup :: + Applicative f => + (SuperGroup Symbol -> f (SuperGroup Symbol)) -> + Code -> f Code +traverseGroup f (CodeRep sg ch) = flip CodeRep ch <$> f sg + data Cont = KE | Mark Word64 Word64 [Reference] (Map Reference Value) Cont @@ -1542,7 +1578,7 @@ data BLit | TyLink Reference | Bytes Bytes | Quote Value - | Code (SuperGroup Symbol) + | Code Code | BArr PA.ByteArray | Pos Word64 | Neg Word64 diff --git a/unison-runtime/src/Unison/Runtime/ANF/Rehash.hs b/unison-runtime/src/Unison/Runtime/ANF/Rehash.hs index 4bd3c2434f..a6a50722d8 100644 --- a/unison-runtime/src/Unison/Runtime/ANF/Rehash.hs +++ b/unison-runtime/src/Unison/Runtime/ANF/Rehash.hs @@ -1,7 +1,7 @@ module Unison.Runtime.ANF.Rehash where import Crypto.Hash -import Data.Bifunctor (bimap, first, second) +import Data.Bifunctor (bimap, second) import Data.ByteArray (convert) import Data.ByteString (cons) import Data.ByteString.Lazy (toChunks) @@ -16,25 +16,23 @@ import Unison.Reference as Reference import Unison.Referent as Referent import Unison.Runtime.ANF as ANF import Unison.Runtime.ANF.Serialize as ANF -import Unison.Var (Var) +import Unison.Symbol (Symbol) checkGroupHashes :: - (Var v) => - [(Referent, SuperGroup v)] -> + [(Referent, Code)] -> Either (Text, [Referent]) (Either [Referent] [Referent]) checkGroupHashes rgs = case checkMissing rgs of Left err -> Left err Right [] -> - case rehashGroups . Map.fromList $ first toReference <$> rgs of + case rehashGroups . Map.fromList $ bimap toReference codeGroup <$> rgs of Left err -> Left err Right (rrs, _) -> Right . Right . fmap (Ref . fst) . filter (uncurry (/=)) $ Map.toList rrs Right ms -> Right (Left $ Ref <$> ms) rehashGroups :: - (Var v) => - Map.Map Reference (SuperGroup v) -> - Either (Text, [Referent]) (Map.Map Reference Reference, Map.Map Reference (SuperGroup v)) + Map.Map Reference (SuperGroup Symbol) -> + Either (Text, [Referent]) (Map.Map Reference Reference, Map.Map Reference (SuperGroup Symbol)) rehashGroups m | badsccs <- filter (not . checkSCC) sccs, not $ null badsccs = @@ -56,12 +54,11 @@ rehashGroups m (rm, sgs) = rehashSCC scc checkMissing :: - (Var v) => - [(Referent, SuperGroup v)] -> + [(Referent, Code)] -> Either (Text, [Referent]) [Reference] -checkMissing (unzip -> (rs, gs)) = do +checkMissing (unzip -> (rs, cs)) = do is <- fmap Set.fromList . traverse f $ rs - pure . nub . foldMap (filter (p is) . groupTermLinks) $ gs + pure . nub . foldMap (filter (p is) . groupTermLinks . codeGroup) $ cs where f (Ref (DerivedId i)) = pure i f r@Ref {} = @@ -74,9 +71,8 @@ checkMissing (unzip -> (rs, gs)) = do p _ _ = False rehashSCC :: - (Var v) => - SCC (Reference, SuperGroup v) -> - (Map.Map Reference Reference, Map.Map Reference (SuperGroup v)) + SCC (Reference, SuperGroup Symbol) -> + (Map.Map Reference Reference, Map.Map Reference (SuperGroup Symbol)) rehashSCC scc | checkSCC scc = (refreps, newSGs) where @@ -103,7 +99,7 @@ rehashSCC scc refreps = Map.fromList $ fmap (\(r, _) -> (r, replace r)) ps rehashSCC scc = error $ "unexpected SCC:\n" ++ show scc -checkSCC :: SCC (Reference, SuperGroup v) -> Bool +checkSCC :: SCC (Reference, a) -> Bool checkSCC AcyclicSCC {} = True checkSCC (CyclicSCC []) = True checkSCC (CyclicSCC (p : ps)) = all (same p) ps diff --git a/unison-runtime/src/Unison/Runtime/ANF/Serialize.hs b/unison-runtime/src/Unison/Runtime/ANF/Serialize.hs index 995856e1b4..ba97dfa080 100644 --- a/unison-runtime/src/Unison/Runtime/ANF/Serialize.hs +++ b/unison-runtime/src/Unison/Runtime/ANF/Serialize.hs @@ -330,6 +330,25 @@ getGroup = do cs <- replicateM l (getComb ctx n) Rec (zip vs cs) <$> getComb ctx n +putCode :: MonadPut m => EC.EnumMap FOp Text -> Code -> m () +putCode fops (CodeRep g c) = putGroup mempty fops g *> putCacheability c + +getCode :: MonadGet m => Word32 -> m Code +getCode v = CodeRep <$> getGroup <*> getCache + where + getCache | v == 3 = getCacheability + | otherwise = pure Uncacheable + +putCacheability :: MonadPut m => Cacheability -> m () +putCacheability Uncacheable = putWord8 0 +putCacheability Cacheable = putWord8 1 + +getCacheability :: MonadGet m => m Cacheability +getCacheability = getWord8 >>= \case + 0 -> pure Uncacheable + 1 -> pure Cacheable + n -> exn $ "getBLit: unrecognized cacheability byte: " ++ show n + putComb :: (MonadPut m) => (Var v) => @@ -659,7 +678,7 @@ putBLit (TmLink r) = putTag TmLinkT *> putReferent r putBLit (TyLink r) = putTag TyLinkT *> putReference r putBLit (Bytes b) = putTag BytesT *> putBytes b putBLit (Quote v) = putTag QuoteT *> putValue v -putBLit (Code g) = putTag CodeT *> putGroup mempty mempty g +putBLit (Code co) = putTag CodeT *> putCode mempty co putBLit (BArr a) = putTag BArrT *> putByteArray a putBLit (Pos n) = putTag PosT *> putPositive n putBLit (Neg n) = putTag NegT *> putPositive n @@ -676,7 +695,9 @@ getBLit v = TyLinkT -> TyLink <$> getReference BytesT -> Bytes <$> getBytes QuoteT -> Quote <$> getValue v - CodeT -> Code <$> getGroup + CodeT -> Code <$> getCode cv + where + cv | v == 5 = 3 | otherwise = 2 BArrT -> BArr <$> getByteArray PosT -> Pos <$> getPositive NegT -> Neg <$> getPositive @@ -913,18 +934,16 @@ getCont v = <*> getGroupRef <*> getCont v -deserializeGroup :: (Var v) => ByteString -> Either String (SuperGroup v) -deserializeGroup bs = runGetS (getVersion *> getGroup) bs +deserializeCode :: ByteString -> Either String Code +deserializeCode bs = runGetS (getVersion >>= getCode) bs where getVersion = getWord32be >>= \case - 1 -> pure () - 2 -> pure () + n | 1 <= n && n <= 3 -> pure n n -> fail $ "deserializeGroup: unknown version: " ++ show n -serializeGroup :: - (Var v) => EC.EnumMap FOp Text -> SuperGroup v -> ByteString -serializeGroup fops sg = runPutS (putVersion *> putGroup mempty fops sg) +serializeCode :: EC.EnumMap FOp Text -> Code -> ByteString +serializeCode fops co = runPutS (putVersion *> putCode fops co) where putVersion = putWord32be codeVersion @@ -970,7 +989,7 @@ getVersionedValue = getVersion >>= getValue n | n < 1 -> fail $ "deserializeValue: unknown version: " ++ show n | n < 3 -> fail $ "deserializeValue: unsupported version: " ++ show n - | n <= 4 -> pure n + | n <= 5 -> pure n | otherwise -> fail $ "deserializeValue: unknown version: " ++ show n deserializeValue :: ByteString -> Either String Value @@ -981,13 +1000,21 @@ serializeValue v = runPutS (putVersion *> putValue v) where putVersion = putWord32be valueVersion -serializeValueLazy :: Value -> L.ByteString -serializeValueLazy v = runPutLazy (putVersion *> putValue v) +-- This serializer is used exclusively for hashing unison values. +-- For this reason, it doesn't prefix the string with the current +-- version, so that only genuine changes in the way things are +-- serialized will change hashes. +-- +-- The 4 prefix is used because we were previously including the +-- version in the hash, so to maintain the same hashes, we need to +-- include the extra bytes that were previously there. +serializeValueForHash :: Value -> L.ByteString +serializeValueForHash v = runPutLazy (putPrefix *> putValue v) where - putVersion = putWord32be valueVersion + putPrefix = putWord32be 4 valueVersion :: Word32 -valueVersion = 4 +valueVersion = 5 codeVersion :: Word32 -codeVersion = 2 +codeVersion = 3 diff --git a/unison-runtime/src/Unison/Runtime/Builtin.hs b/unison-runtime/src/Unison/Runtime/Builtin.hs index 893f64a233..0a31bdce41 100644 --- a/unison-runtime/src/Unison/Runtime/Builtin.hs +++ b/unison-runtime/src/Unison/Runtime/Builtin.hs @@ -2860,23 +2860,24 @@ declareForeigns = do declareForeign Untracked "Code.validateLinks" boxToExnEBoxBox . mkForeign - $ \(lsgs0 :: [(Referent, SuperGroup Symbol)]) -> do + $ \(lsgs0 :: [(Referent, Code)]) -> do let f (msg, rs) = Failure Ty.miscFailureRef (Util.Text.fromText msg) rs pure . first f $ checkGroupHashes lsgs0 declareForeign Untracked "Code.dependencies" boxDirect . mkForeign - $ \(sg :: SuperGroup Symbol) -> + $ \(CodeRep sg _) -> pure $ Wrap Ty.termLinkRef . Ref <$> groupTermLinks sg declareForeign Untracked "Code.serialize" boxDirect . mkForeign - $ \(sg :: SuperGroup Symbol) -> - pure . Bytes.fromArray $ serializeGroup builtinForeignNames sg + $ \(co :: Code) -> + pure . Bytes.fromArray $ serializeCode builtinForeignNames co declareForeign Untracked "Code.deserialize" boxToEBoxBox . mkForeign - $ pure . deserializeGroup @Symbol . Bytes.toArray + $ pure . deserializeCode . Bytes.toArray declareForeign Untracked "Code.display" boxBoxDirect . mkForeign $ - \(nm, sg) -> pure $ prettyGroup @Symbol (Util.Text.unpack nm) sg "" + \(nm, (CodeRep sg _)) -> + pure $ prettyGroup @Symbol (Util.Text.unpack nm) sg "" declareForeign Untracked "Value.dependencies" boxDirect . mkForeign $ pure . fmap (Wrap Ty.termLinkRef . Ref) . valueTermLinks @@ -2924,7 +2925,7 @@ declareForeigns = do L.ByteString -> Hash.Digest a hashlazy _ l = Hash.hashlazy l - in pure . Bytes.fromArray . hashlazy alg $ serializeValueLazy x + in pure . Bytes.fromArray . hashlazy alg $ serializeValueForHash x declareForeign Untracked "crypto.hmac" crypto'hmac . mkForeign $ \(HashAlgorithm _ alg, key, x) -> @@ -2935,7 +2936,7 @@ declareForeigns = do . HMAC.updates (HMAC.initialize $ Bytes.toArray @BA.Bytes key) $ L.toChunks s - in pure . Bytes.fromArray . hmac alg $ serializeValueLazy x + in pure . Bytes.fromArray . hmac alg $ serializeValueForHash x declareForeign Untracked "crypto.Ed25519.sign.impl" boxBoxBoxToEFBox . mkForeign @@ -2961,7 +2962,7 @@ declareForeigns = do Right a -> Right a declareForeign Untracked "Universal.murmurHash" murmur'hash . mkForeign $ - pure . asWord64 . hash64 . serializeValueLazy + pure . asWord64 . hash64 . serializeValueForHash declareForeign Tracked "IO.randomBytes" natToBox . mkForeign $ \n -> Bytes.fromArray <$> getRandomBytes @IO @ByteString n diff --git a/unison-runtime/src/Unison/Runtime/Foreign.hs b/unison-runtime/src/Unison/Runtime/Foreign.hs index c9cd12fafb..5559ce9b6c 100644 --- a/unison-runtime/src/Unison/Runtime/Foreign.hs +++ b/unison-runtime/src/Unison/Runtime/Foreign.hs @@ -34,8 +34,7 @@ import System.IO (Handle) import System.Process (ProcessHandle) import Unison.Reference (Reference) import Unison.Referent (Referent) -import Unison.Runtime.ANF (SuperGroup, Value) -import Unison.Symbol (Symbol) +import Unison.Runtime.ANF (Code, Value) import Unison.Type qualified as Ty import Unison.Util.Bytes (Bytes) import Unison.Util.Text (Text) @@ -130,8 +129,8 @@ charClassCmp :: CharPattern -> CharPattern -> Ordering charClassCmp = compare {-# NOINLINE charClassCmp #-} -codeEq :: SuperGroup Symbol -> SuperGroup Symbol -> Bool -codeEq sg1 sg2 = sg1 == sg2 +codeEq :: Code -> Code -> Bool +codeEq co1 co2 = co1 == co2 {-# NOINLINE codeEq #-} tylEq :: Reference -> Reference -> Bool @@ -256,9 +255,7 @@ instance BuiltinForeign FilePath where foreignRef = Tagged Ty.filePathRef instance BuiltinForeign TLS.Context where foreignRef = Tagged Ty.tlsRef -instance BuiltinForeign (SuperGroup Symbol) where - foreignRef = Tagged Ty.codeRef - +instance BuiltinForeign Code where foreignRef = Tagged Ty.codeRef instance BuiltinForeign Value where foreignRef = Tagged Ty.valueRef instance BuiltinForeign TimeSpec where foreignRef = Tagged Ty.timeSpecRef diff --git a/unison-runtime/src/Unison/Runtime/Foreign/Function.hs b/unison-runtime/src/Unison/Runtime/Foreign/Function.hs index ed9d890088..e793d93508 100644 --- a/unison-runtime/src/Unison/Runtime/Foreign/Function.hs +++ b/unison-runtime/src/Unison/Runtime/Foreign/Function.hs @@ -31,12 +31,11 @@ import Network.UDP (UDPSocket) import System.IO (BufferMode (..), Handle, IOMode, SeekMode) import Unison.Builtin.Decls qualified as Ty import Unison.Reference (Reference) -import Unison.Runtime.ANF (Mem (..), SuperGroup, Value, internalBug) +import Unison.Runtime.ANF (Mem (..), Code, Value, internalBug) import Unison.Runtime.Exception import Unison.Runtime.Foreign import Unison.Runtime.MCode import Unison.Runtime.Stack -import Unison.Symbol (Symbol) import Unison.Type ( iarrayRef, ibytearrayRef, @@ -473,7 +472,7 @@ instance ForeignConvention (Promise Closure) where readForeign = readForeignAs (unwrapForeign . marshalToForeign) writeForeign = writeForeignAs (Foreign . Wrap promiseRef) -instance ForeignConvention (SuperGroup Symbol) where +instance ForeignConvention Code where readForeign = readForeignBuiltin writeForeign = writeForeignBuiltin diff --git a/unison-runtime/src/Unison/Runtime/Interface.hs b/unison-runtime/src/Unison/Runtime/Interface.hs index 42f3ab10a9..78a9665a00 100644 --- a/unison-runtime/src/Unison/Runtime/Interface.hs +++ b/unison-runtime/src/Unison/Runtime/Interface.hs @@ -117,7 +117,6 @@ import Unison.Runtime.MCode.Serialize import Unison.Runtime.Machine ( ActiveThreads, CCache (..), - Cacheability (..), Combs, Tracer (..), apply0, @@ -449,7 +448,7 @@ loadDeps :: EvalCtx -> [(Reference, Either [Int] [Int])] -> [Reference] -> - IO (EvalCtx, [(Reference, SuperGroup Symbol)]) + IO (EvalCtx, [(Reference, Code)]) loadDeps cl ppe ctx tyrs tmrs = do let cc = ccache ctx sand <- readTVarIO (sandbox cc) @@ -461,33 +460,40 @@ loadDeps cl ppe ctx tyrs tmrs = do _ -> False ctx <- foldM (uncurry . allocType) ctx $ Prelude.filter p tyrs let tyAdd = Set.fromList $ fst <$> tyrs - out@(ctx', rgrp) <- loadCode cl ppe ctx tmrs - crgrp <- traverse (checkCacheability ctx') rgrp - out <$ cacheAdd0 tyAdd crgrp (expandSandbox sand rgrp) cc + (ctx', rgrp) <- loadCode cl ppe ctx tmrs + crgrp <- traverse (checkCacheability cl ctx') rgrp + (ctx', crgrp) <$ cacheAdd0 tyAdd crgrp (expandSandbox sand rgrp) cc + +checkCacheability :: + CodeLookup Symbol IO () -> + EvalCtx -> + (IntermediateReference, SuperGroup Symbol) -> + IO (IntermediateReference, Code) +checkCacheability cl ctx (r, sg) = + getTermType codebaseRef >>= \case + -- A term's result is cacheable iff it has no arrows in its type, + -- this is sufficient since top-level definitions can't have effects without a delay. + Just typ | not (Rec.cata hasArrows typ) -> + pure (r, CodeRep sg Cacheable) + _ -> pure (r, CodeRep sg Uncacheable) where - checkCacheability :: EvalCtx -> (IntermediateReference, sprgrp) -> IO (IntermediateReference, sprgrp, Cacheability) - checkCacheability ctx (r, sg) = do - let codebaseRef = backmapRef ctx r - getTermType codebaseRef >>= \case - -- A term's result is cacheable iff it has no arrows in its type, - -- this is sufficient since top-level definitions can't have effects without a delay. - Just typ | not (Rec.cata hasArrows typ) -> pure (r, sg, Cacheable) - _ -> pure (r, sg, Uncacheable) - getTermType :: CodebaseReference -> IO (Maybe (Type Symbol)) - getTermType = \case - (RF.DerivedId i) -> - getTypeOfTerm cl i >>= \case - Just t -> pure $ Just t - Nothing -> pure Nothing - RF.Builtin {} -> pure $ Nothing - hasArrows :: Type.TypeF v a Bool -> Bool - hasArrows abt = case ABT.out' abt of - (ABT.Tm f) -> case f of - Type.Arrow _ _ -> True - other -> or other - t -> or t - -compileValue :: Reference -> [(Reference, SuperGroup Symbol)] -> Value + codebaseRef = backmapRef ctx r + getTermType :: CodebaseReference -> IO (Maybe (Type Symbol)) + getTermType = \case + (RF.DerivedId i) -> + getTypeOfTerm cl i >>= \case + Just t -> pure $ Just t + Nothing -> pure Nothing + RF.Builtin {} -> pure $ Nothing + hasArrows :: Type.TypeF v a Bool -> Bool + hasArrows abt = case ABT.out' abt of + (ABT.Tm f) -> case f of + Type.Arrow _ _ -> True + other -> or other + t -> or t + + +compileValue :: Reference -> [(Reference, Code)] -> Value compileValue base = flip pair (rf base) . ANF.BLit . List . Seq.fromList . fmap cpair where @@ -823,22 +829,24 @@ prepareEvaluation :: PrettyPrintEnv -> Term Symbol -> EvalCtx -> - IO (EvalCtx, [(Reference, SuperGroup Symbol)], Reference) + IO (EvalCtx, [(Reference, Code)], Reference) prepareEvaluation ppe tm ctx = do - missing <- cacheAdd rgrp (ccache ctx') + missing <- cacheAdd rcode (ccache ctx') when (not . null $ missing) . fail $ reportBug "E029347" $ "Error in prepareEvaluation, cache is missing: " <> show missing - pure (backrefAdd rbkr ctx', rgrp, rmn) + pure (backrefAdd rbkr ctx', rcode, rmn) where + uncacheable g = CodeRep g Uncacheable (rmn0, frem, rgrp0, rbkr) = intermediateTerm ppe ctx tm int b r | b || Map.member r rgrp0 = r | otherwise = toIntermed ctx r (ctx', rrefs, rgrp) = performRehash - ((fmap . overGroupLinks) int rgrp0) + ((fmap . overGroupLinks) int $ rgrp0) (floatRemapAdd frem ctx) + rcode = second uncacheable <$> rgrp rmn = case Map.lookup rmn0 rrefs of Just r -> r Nothing -> error "prepareEvaluation: could not remap main ref" @@ -921,7 +929,7 @@ nativeEvalInContext :: EvalCtx -> Socket -> PortNumber -> - [(Reference, SuperGroup Symbol)] -> + [(Reference, Code)] -> Reference -> IO (Either Error ([Error], Term Symbol)) nativeEvalInContext executable ppe ctx serv port codes base = do @@ -973,7 +981,7 @@ nativeEvalInContext executable ppe ctx serv port codes base = do nativeCompileCodes :: CompileOpts -> FilePath -> - [(Reference, SuperGroup Symbol)] -> + [(Reference, Code)] -> Reference -> FilePath -> IO () diff --git a/unison-runtime/src/Unison/Runtime/Machine.hs b/unison-runtime/src/Unison/Runtime/Machine.hs index 69281e42f4..e3b56a535a 100644 --- a/unison-runtime/src/Unison/Runtime/Machine.hs +++ b/unison-runtime/src/Unison/Runtime/Machine.hs @@ -35,9 +35,13 @@ import Unison.Reference ) import Unison.Referent (Referent, pattern Con, pattern Ref) import Unison.Runtime.ANF as ANF - ( CompileExn (..), + ( Cacheability (..), + CompileExn (..), Mem (..), + Code (..), SuperGroup, + codeGroup, + foldGroup, foldGroupLinks, maskTags, packTags, @@ -95,11 +99,6 @@ data Tracer | MsgTrace String String String | SimpleTrace String --- | Whether the evaluation of a given definition is cacheable or not. --- i.e. it's a top-level pure value. -data Cacheability = Cacheable | Uncacheable - deriving stock (Eq, Show) - -- code caching environment data CCache = CCache { foreignFuncs :: EnumMap Word64 ForeignFunc, @@ -360,7 +359,7 @@ exec !env !denv !_activeThreads !ustk !bstk !k _ (BPrim1 CVLD i) | otherwise = do arg <- peekOffS bstk i news <- decodeCacheArgument arg - codeValidate news env >>= \case + codeValidate (second codeGroup <$> news) env >>= \case Nothing -> do ustk <- bump ustk poke ustk 0 @@ -381,6 +380,8 @@ exec !env !denv !_activeThreads !ustk !bstk !k _ (BPrim1 LKUP i) Ref r -> r _ -> error "exec:BPrim1:LKUP: Expected Ref" m <- readTVarIO (intermed env) + rfn <- readTVarIO (refTm env) + cach <- readTVarIO (cacheableCombs env) ustk <- bump ustk bstk <- case M.lookup link m of Nothing @@ -388,12 +389,15 @@ exec !env !denv !_activeThreads !ustk !bstk !k _ (BPrim1 LKUP i) Just sn <- EC.lookup w numberedTermLookup -> do poke ustk 1 bstk <- bump bstk - bstk <$ pokeBi bstk (ANF.Rec [] sn) + bstk <$ pokeBi bstk (CodeRep (ANF.Rec [] sn) Uncacheable) | otherwise -> bstk <$ poke ustk 0 Just sg -> do poke ustk 1 bstk <- bump bstk - bstk <$ pokeBi bstk sg + let ch | Just n <- M.lookup link rfn + , EC.member n cach = Cacheable + | otherwise = Uncacheable + bstk <$ pokeBi bstk (CodeRep sg ch) pure (denv, ustk, bstk, k) exec !_ !denv !_activeThreads !ustk !bstk !k _ (BPrim1 TLTT i) = do clink <- peekOff bstk i @@ -2018,7 +2022,7 @@ refLookup s m r error $ "refLookup:" ++ s ++ ": unknown reference: " ++ show r decodeCacheArgument :: - Sq.Seq Closure -> IO [(Reference, SuperGroup Symbol)] + Sq.Seq Closure -> IO [(Reference, Code)] decodeCacheArgument s = for (toList s) $ \case DataB2 _ _ (Foreign x) (DataB2 _ _ (Foreign y) _) -> case unwrapForeign x of @@ -2145,12 +2149,12 @@ evaluateSTM x = unsafeIOToSTM (evaluate x) cacheAdd0 :: S.Set Reference -> - [(Reference, SuperGroup Symbol, Cacheability)] -> + [(Reference, Code)] -> [(Reference, Set Reference)] -> CCache -> IO () cacheAdd0 ntys0 termSuperGroups sands cc = do - let toAdd = M.fromList (termSuperGroups <&> \(r, g, _) -> (r, g)) + let toAdd = M.fromList (termSuperGroups <&> second codeGroup) (unresolvedCacheableCombs, unresolvedNonCacheableCombs) <- atomically $ do have <- readTVar (intermed cc) let new = M.difference toAdd have @@ -2171,7 +2175,8 @@ cacheAdd0 ntys0 termSuperGroups sands cc = do termSuperGroups & mapMaybe ( \case - (ref, _, Cacheable) -> M.lookup ref combIdFromRefMap + (ref, CodeRep _ Cacheable) -> + M.lookup ref combIdFromRefMap _ -> Nothing ) & EC.setFromList @@ -2237,24 +2242,22 @@ expandSandbox sand0 groups = fixed mempty extra' = M.fromList new cacheAdd :: - [(Reference, SuperGroup Symbol)] -> + [(Reference, Code)] -> CCache -> IO [Reference] cacheAdd l cc = do rtm <- readTVarIO (refTm cc) rty <- readTVarIO (refTy cc) sand <- readTVarIO (sandbox cc) - let known = M.keysSet rtm <> S.fromList (fst <$> l) + let known = M.keysSet rtm <> S.fromList (view _1 <$> l) f b r | not b, S.notMember r known = Const (S.singleton r, mempty) | b, M.notMember r rty = Const (mempty, S.singleton r) | otherwise = Const (mempty, mempty) - (missing, tys) = getConst $ (foldMap . foldMap) (foldGroupLinks f) l - l' = filter (\(r, _) -> M.notMember r rtm) l - -- Terms added via cacheAdd will have already been eval'd and cached if possible when - -- they were originally loaded, so we - -- don't need to re-check for cacheability here as part of a dynamic cache add. - l'' = l' <&> (\(r, g) -> (r, g, Uncacheable)) + (missing, tys) = + getConst $ (foldMap . foldMap . foldGroup) (foldGroupLinks f) l + l'' = filter (\(r, _) -> M.notMember r rtm) l + l' = map (second codeGroup) l'' if S.null missing then [] <$ cacheAdd0 tys l'' (expandSandbox sand l') cc else pure $ S.toList missing diff --git a/unison-src/transcripts-using-base/random-deserial.md b/unison-src/transcripts-using-base/random-deserial.md index 2c6ff77de5..5ceb2900d4 100644 --- a/unison-src/transcripts-using-base/random-deserial.md +++ b/unison-src/transcripts-using-base/random-deserial.md @@ -25,15 +25,20 @@ shuffle = runTestCase : Text ->{Exception,IO} (Text, Test.Result) runTestCase name = - sfile = directory ++ name ++ ".v4.ser" - lsfile = directory ++ name ++ ".v3.ser" + sfile = directory ++ name ++ ".v5.ser" + ls3file = directory ++ name ++ ".v3.ser" + ls4file = directory ++ name ++ ".v4.ser" ofile = directory ++ name ++ ".out" - hfile = directory ++ name ++ ".v4.hash" + hfile = directory ++ name ++ ".v5.hash" p@(f, i) = loadSelfContained sfile - pl@(fl, il) = - if fileExists lsfile - then loadSelfContained lsfile + pl3@(fl3, il3) = + if fileExists ls3file + then loadSelfContained ls3file + else p + pl4@(fl4, il4) = + if fileExists ls4file + then loadSelfContained ls4file else p o = fromUtf8 (readFile ofile) h = readFile hfile @@ -43,8 +48,10 @@ runTestCase name = then Fail (name ++ " output mismatch") else if not (toBase32 (crypto.hash Sha3_512 p) == h) then Fail (name ++ " hash mismatch") - else if not (fl il == f i) - then Fail (name ++ " legacy mismatch") + else if not (fl3 il3 == f i) + then Fail (name ++ " legacy v3 mismatch") + else if not (fl4 il4 == f i) + then Fail (name ++ " legacy v4 mismatch") else Ok name (name, result) diff --git a/unison-src/transcripts-using-base/random-deserial.output.md b/unison-src/transcripts-using-base/random-deserial.output.md index 6c68e978ec..316132ed4d 100644 --- a/unison-src/transcripts-using-base/random-deserial.output.md +++ b/unison-src/transcripts-using-base/random-deserial.output.md @@ -25,15 +25,20 @@ shuffle = runTestCase : Text ->{Exception,IO} (Text, Test.Result) runTestCase name = - sfile = directory ++ name ++ ".v4.ser" - lsfile = directory ++ name ++ ".v3.ser" + sfile = directory ++ name ++ ".v5.ser" + ls3file = directory ++ name ++ ".v3.ser" + ls4file = directory ++ name ++ ".v4.ser" ofile = directory ++ name ++ ".out" - hfile = directory ++ name ++ ".v4.hash" + hfile = directory ++ name ++ ".v5.hash" p@(f, i) = loadSelfContained sfile - pl@(fl, il) = - if fileExists lsfile - then loadSelfContained lsfile + pl3@(fl3, il3) = + if fileExists ls3file + then loadSelfContained ls3file + else p + pl4@(fl4, il4) = + if fileExists ls4file + then loadSelfContained ls4file else p o = fromUtf8 (readFile ofile) h = readFile hfile @@ -43,8 +48,10 @@ runTestCase name = then Fail (name ++ " output mismatch") else if not (toBase32 (crypto.hash Sha3_512 p) == h) then Fail (name ++ " hash mismatch") - else if not (fl il == f i) - then Fail (name ++ " legacy mismatch") + else if not (fl3 il3 == f i) + then Fail (name ++ " legacy v3 mismatch") + else if not (fl4 il4 == f i) + then Fail (name ++ " legacy v4 mismatch") else Ok name (name, result) diff --git a/unison-src/transcripts-using-base/serial-test-00.md b/unison-src/transcripts-using-base/serial-test-00.md index 21860243e3..d1a0b8e282 100644 --- a/unison-src/transcripts-using-base/serial-test-00.md +++ b/unison-src/transcripts-using-base/serial-test-00.md @@ -64,7 +64,7 @@ mkTestCase = do f = evaluate balancedSum catenate tup = (tree0, tree1, tree2, tree3) - saveTestCase "case-00" "v4" f tup + saveTestCase "case-00" "v5" f tup ``` ```ucm diff --git a/unison-src/transcripts-using-base/serial-test-00.output.md b/unison-src/transcripts-using-base/serial-test-00.output.md index ce996f93ba..4483682980 100644 --- a/unison-src/transcripts-using-base/serial-test-00.output.md +++ b/unison-src/transcripts-using-base/serial-test-00.output.md @@ -64,7 +64,7 @@ mkTestCase = do f = evaluate balancedSum catenate tup = (tree0, tree1, tree2, tree3) - saveTestCase "case-00" "v4" f tup + saveTestCase "case-00" "v5" f tup ``` ``` ucm diff --git a/unison-src/transcripts-using-base/serial-test-01.md b/unison-src/transcripts-using-base/serial-test-01.md index bc5f84af0d..7d5f1ffa07 100644 --- a/unison-src/transcripts-using-base/serial-test-01.md +++ b/unison-src/transcripts-using-base/serial-test-01.md @@ -12,7 +12,7 @@ combines = cases "(" ++ toText rx ++ ", " ++ toText ry ++ ", \"" ++ rz ++ "\")" mkTestCase = do - saveTestCase "case-01" "v4" combines (l1, l2, l3) + saveTestCase "case-01" "v5" combines (l1, l2, l3) ``` ```ucm diff --git a/unison-src/transcripts-using-base/serial-test-01.output.md b/unison-src/transcripts-using-base/serial-test-01.output.md index a6654a2547..f2734eb118 100644 --- a/unison-src/transcripts-using-base/serial-test-01.output.md +++ b/unison-src/transcripts-using-base/serial-test-01.output.md @@ -12,7 +12,7 @@ combines = cases "(" ++ toText rx ++ ", " ++ toText ry ++ ", \"" ++ rz ++ "\")" mkTestCase = do - saveTestCase "case-01" "v4" combines (l1, l2, l3) + saveTestCase "case-01" "v5" combines (l1, l2, l3) ``` ``` ucm diff --git a/unison-src/transcripts-using-base/serial-test-02.md b/unison-src/transcripts-using-base/serial-test-02.md index 15518165a0..06a6d255f1 100644 --- a/unison-src/transcripts-using-base/serial-test-02.md +++ b/unison-src/transcripts-using-base/serial-test-02.md @@ -25,7 +25,7 @@ products = cases (x, y, z) -> "(" ++ toText px ++ ", " ++ toText py ++ ", \"" ++ toText pz ++ "\")" mkTestCase = do - saveTestCase "case-02" "v4" products (l1, l2, l3) + saveTestCase "case-02" "v5" products (l1, l2, l3) ``` diff --git a/unison-src/transcripts-using-base/serial-test-02.output.md b/unison-src/transcripts-using-base/serial-test-02.output.md index 102fea092b..08339ffd0f 100644 --- a/unison-src/transcripts-using-base/serial-test-02.output.md +++ b/unison-src/transcripts-using-base/serial-test-02.output.md @@ -25,7 +25,7 @@ products = cases (x, y, z) -> "(" ++ toText px ++ ", " ++ toText py ++ ", \"" ++ toText pz ++ "\")" mkTestCase = do - saveTestCase "case-02" "v4" products (l1, l2, l3) + saveTestCase "case-02" "v5" products (l1, l2, l3) ``` diff --git a/unison-src/transcripts-using-base/serial-test-03.md b/unison-src/transcripts-using-base/serial-test-03.md index 2e66f687d9..c7b514de72 100644 --- a/unison-src/transcripts-using-base/serial-test-03.md +++ b/unison-src/transcripts-using-base/serial-test-03.md @@ -40,7 +40,7 @@ finish = cases (x, y, z) -> mkTestCase = do trip = (suspSum l1, suspSum l2, suspSum l3) - saveTestCase "case-03" "v4" finish trip + saveTestCase "case-03" "v5" finish trip ``` ```ucm diff --git a/unison-src/transcripts-using-base/serial-test-03.output.md b/unison-src/transcripts-using-base/serial-test-03.output.md index a20eafe7f6..824cab1a39 100644 --- a/unison-src/transcripts-using-base/serial-test-03.output.md +++ b/unison-src/transcripts-using-base/serial-test-03.output.md @@ -40,7 +40,7 @@ finish = cases (x, y, z) -> mkTestCase = do trip = (suspSum l1, suspSum l2, suspSum l3) - saveTestCase "case-03" "v4" finish trip + saveTestCase "case-03" "v5" finish trip ``` ``` ucm diff --git a/unison-src/transcripts-using-base/serial-test-04.md b/unison-src/transcripts-using-base/serial-test-04.md index 212b59c9e0..210b42796a 100644 --- a/unison-src/transcripts-using-base/serial-test-04.md +++ b/unison-src/transcripts-using-base/serial-test-04.md @@ -10,7 +10,7 @@ mutual1 n = mutual0 n mkTestCase = do - saveTestCase "case-04" "v4" mutual1 5 + saveTestCase "case-04" "v5" mutual1 5 ``` ```ucm diff --git a/unison-src/transcripts-using-base/serial-test-04.output.md b/unison-src/transcripts-using-base/serial-test-04.output.md index 990ce14799..7d8eef05e2 100644 --- a/unison-src/transcripts-using-base/serial-test-04.output.md +++ b/unison-src/transcripts-using-base/serial-test-04.output.md @@ -9,7 +9,7 @@ mutual1 n = mutual0 n mkTestCase = do - saveTestCase "case-04" "v4" mutual1 5 + saveTestCase "case-04" "v5" mutual1 5 ``` ``` ucm diff --git a/unison-src/transcripts-using-base/serialized-cases/case-00.v5.hash b/unison-src/transcripts-using-base/serialized-cases/case-00.v5.hash new file mode 100644 index 0000000000..181c564dc3 --- /dev/null +++ b/unison-src/transcripts-using-base/serialized-cases/case-00.v5.hash @@ -0,0 +1 @@ +Z6EW6IDZJXHDMNGTVSKYLMZVG47ORYF4O6JDQXQGQFJP476SLM75FXFOYI27OJHMIX5OIHKQ6LXWLYQ5LDGEYWEXK6GQPP6JKH6SVMI= \ No newline at end of file diff --git a/unison-src/transcripts-using-base/serialized-cases/case-00.v5.ser b/unison-src/transcripts-using-base/serialized-cases/case-00.v5.ser new file mode 100644 index 0000000000..afdd5055e3 --- /dev/null +++ b/unison-src/transcripts-using-base/serialized-cases/case-00.v5.ser @@ -0,0 +1 @@ +AAAAABIBAFABKYCFITJNTOQRE3BRWTYOOLZIFGNVKRU5GVLMBALLTNRPXH2ZPF4XNLZYXJVJEXKJWKPQNL7E3K7B2E3V4XY2ROGIXGCG4I3T5ZYZ6UAAAAAAAAAAAAAAAIBQCAYBAFABKYCFITJNTOQRE3BRWTYOOLZIFGNVKRU5GVLMBALLTNRPXH2ZPF4XNLZYXJVJEXKJWKPQNL7E3K7B2E3V4XY2ROGIXGCG4I3T5ZYZ6UAAAAAAAAAAAAAAAIBQEAABEEACITAXWMOCQYHP2S67NQK5TVVWHTWRHFIEUOIEFN74DGYKE2OBEPAAAEAUAFLAIVCNFWN2CETMGG2PBZZPFAUZWVKGTU2VNQEBNONWF647LF4XS5VPHC5GVES5JGZJ6BVP4TNL4HITOXS7DKFYZC4YI3RDOPXHDH2QAAAAAAAAAAAAAABAGBQAAQAQCAIBAYAAIAKAVNVYCKXZSHU43Z7M4UVJXJC34TQNL7UBPR4WVYGEY5MHXUFY4VSGME4Q4YGZISBZLWLHHH4C4YVGRWWO756FKRLIORSNPQSF346AB7AAAIAAAAIBAEBQCAIBBMAACAIBAMAQCIIAERGBPMY4FBQO7VF563AV3HLLMPHNCOKQJI4QIK37YGNQUJU4CI6AABAGAUCAECYAAIAQCAYAA4AQECYAAMAQCAYBAEQQAJCMC6ZRYKDA57KL35WBLWOWWY6O2E4VASRZAQVX7QM3BITJYER4AACAQBYGAIFQABABAEBQACACAEAAGAAJAIBQAAAAAEAUAABP6FJQWQ7SCDU3JWOKBXLTS6QCY2USLMHUBPFRDGDT7LHPHKJWHDVXD7SD5OFSIBT3BJDDZO4PDQZQ2SBWHU3L5YTB5F7CPGHUZUBAAAAAAAAAAAAAAAAACAKACVQEKRGS3G5BCJWDDNHQ44XSQKM3KVDJ2NKWYCAWXG3C7OPVS6LZO2XTROTKSJOUTMU7A2X6JWV6DUJXLZPRVC4MROMENYRXH3TRT5IAAAAAAAAAAAAAAAQDAIAACIIAHDXRRIMB4F6FH4J44EBLP3BIFABO6BS5DLJQ4I7Z27OHFVQB5AUQAAIBIAKWARKE2LM3UEJGYMNU6DTS6KBJTNKUNHJVK3AIC243ML5Z6WLZPF3K6OF2NKJF2SNST4DK7ZG2XYORG5PF6GULRSFZQRXCG47OOGPVAAAAAAAAAAAAAAACAMDAAAIBAEAAAAIBIAAC74KTBNB7EEHJWTM4UDOXHF5AFRVJEWYPIC6LCGMHH6WO6OUTMOHLOH7EH24LEQDHWCSGHS5Y6HBTBVEDMPJWX3RGD2L6E6MPJTICAAAAAAAAAAAAAAAAAEAUAFLAIVCNFWN2CETMGG2PBZZPFAUZWVKGTU2VNQEBNONWF647LF4XS5VPHC5GVES5JGZJ6BVP4TNL4HITOXS7DKFYZC4YI3RDOPXHDH2QAAAAAAAAAAAAAABAGAQAAEQQBCLQUZTNWT6XVBNC7BA7RZ2HQDESXNE6HF6TC7W2SFPNUPVZUMHAAAAQCQAVMBCUJUWZXIISNQY3J4HHF4UCTG2VI2OTKVWAQFVZWYX3T5MXS6LWV44LU2USLVE3FHYGV7SNVPQ5CN26L4NIXDELTBDOENZ644M7KAAAAAAAAAAAAAAAEAYGAABQCAIBAYAAIAKACVQEKRGS3G5BCJWDDNHQ44XSQKM3KVDJ2NKWYCAWXG3C7OPVS6LZO2XTROTKSJOUTMU7A2X6JWV6DUJXLZPRVC4MROMENYRXH3TRT5IAAEAAEAIBAYAAIAKACVQEKRGS3G5BCJWDDNHQ44XSQKM3KVDJ2NKWYCAWXG3C7OPVS6LZO2XTROTKSJOUTMU7A2X6JWV6DUJXLZPRVC4MROMENYRXH3TRT5IAAEAAEAIBAYAAIAKACVQEKRGS3G5BCJWDDNHQ44XSQKM3KVDJ2NKWYCAWXG3C7OPVS6LZO2XTROTKSJOUTMU7A2X6JWV6DUJXLZPRVC4MROMENYRXH3TRT5IAAEAAEAIBAYAAIAKACVQEKRGS3G5BCJWDDNHQ44XSQKM3KVDJ2NKWYCAWXG3C7OPVS6LZO2XTROTKSJOUTMU7A2X6JWV6DUJXLZPRVC4MROMENYRXH3TRT5IAAEAAEAIBAYAAIAKAAAX7CUYLIPZBB2NU3HFA3VZZPIBMNKJFWD2AXSYRTBZ7VTXTVE3DR23R7ZB6XCZEAZ5QURR4XOHRYMYNJA3D2NV64JQ6S7RHTD2M2AQAAEAAACYABYAQCAYABIAQOCYABUAQCAYABMAQMCYABQAQCAYABQAQKCYABMAQCAYABQAQICQBAEDQGAJIBMAACAIBAMAQACSOMF2C45DPKRSXQ5ABAQFQAAQBAEBQCAAHKRSXQ5BOFMVQEAIABIAQCBYDAIWCACYAAMAQCAYBAADVIZLYOQXCWKYCAEAAWAAEAEAQGAIABJHGC5BOORXVIZLYOQAQOCYAAUAQCAYBAADVIZLYOQXCWKYCAEAAUAIBA4BQELBABMAAMAIBAMAQAB2UMV4HILRLFMBACAALAADQCAIDAEAAUTTBOQXHI32UMV4HIAIKBMAAQAIBAMAQAB2UMV4HILRLFMBACAAKAEAQOAYCFQQAWAAJAEAQGAIAA5KGK6DUFYVSWAQBAAFQACQBAEBQCAAHKRSXQ5BOFMVQEAANBIAQCBYDAEUQGAIAA5KGK6DUFYVSWAQBAAAAAAAAAAAACAKAAAX7CUYLIPZBB2NU3HFA3VZZPIBMNKJFWD2AXSYRTBZ7VTXTVE3DR23R7ZB6XCZEAZ5QURR4XOHRYMYNJA3D2NV64JQ6S7RHTD2M2AQAAAAAAAAAAAAAAAABAFABKYCFITJNTOQRE3BRWTYOOLZIFGNVKRU5GVLMBALLTNRPXH2ZPF4XNLZYXJVJEXKJWKPQNL7E3K7B2E3V4XY2ROGIXGCG4I3T5ZYZ6UAAAAAAAAAAAAAAAIBQKAIBIAKWARKE2LM3UEJGYMNU6DTS6KBJTNKUNHJVK3AIC243ML5Z6WLZPF3K6OF2NKJF2SNST4DK7ZG2XYORG5PF6GULRSFZQRXCG47OOGPVAAAAAAAAAAAAAAACAAASCAEJOCTGNW2P26UFUL4ED6HHI6AMSK5UTY4X2ML63KIV5WR6XGRQ4AAAAAAAAAAAAAAAAIAACIIAERGBPMY4FBQO7VF563AV3HLLMPHNCOKQJI4QIK37YGNQUJU4CI6AAAAAAAAAAAAAAABQAAJBAA4O6GFBQHQXYU7RHTQQFN7MFAUAF3YGLUNNGDRD7HL5Y4WWAHUCSAAAAAAAAAAAAAAAAAAAAVHGC5BOFMAAAAAAAAAAAAAAAMEAAAABEEACITAXWMOCQYHP2S67NQK5TVVWHTWRHFIEUOIEFN74DGYKE2OBEPAAAAAAAAAAAAAAAAYAAEQQAOHPDCQYDYL4KPYTZYICW7WCQKAC54DF2GWTBYR7TV64OLLAD2BJAAAAAAAAAAAAAAAAAAAAOVDFPB2C4KZLAAAAAAAAAAAAAAADAAAACAKACVQEKRGS3G5BCJWDDNHQ44XSQKM3KVDJ2NKWYCAWXG3C7OPVS6LZO2XTROTKSJOUTMU7A2X6JWV6DUJXLZPRVC4MROMENYRXH3TRT5IAAAAAAAAAAAAAAAQBAFABKYCFITJNTOQRE3BRWTYOOLZIFGNVKRU5GVLMBALLTNRPXH2ZPF4XNLZYXJVJEXKJWKPQNL7E3K7B2E3V4XY2ROGIXGCG4I3T5ZYZ6UAAAAAAAAAAAAAAAIAQCQFLNOASV6MR5HG6P3HFFKN2IW7E4DK75AL4PFVOBRGHLB55BOHFMRTBHEHGBWKEQOK5SZZZ7AXGFJUNVTX7PRKUK2DUMTL4ERO7HQAPYAAAAAAAAAAAAAAQGAIBICVWXAJK7GI6TTPH5TSSVG5ELPSOBVP6QF6HS2XAYTDVQ66QXDSWIZQTSDTA3FCIHFOZM447QLTCU2G2Z37XYVKFNB2GJV6CIXPTYAH4AAAAAAAAAAAAAAIDAEAUBK3LQEVPTEPJZXT6ZZJKTOSFXZHA2X7IC7DZNLQMJR2YPPILRZLEMYJZBZQNSREDSXMWOOPYFZRKNDNM5734KVCWQ5DE27BELXZ4AD6AAAAAAAAAAAAAAAAAGCACAEAUBK3LQEVPTEPJZXT6ZZJKTOSFXZHA2X7IC7DZNLQMJR2YPPILRZLEMYJZBZQNSREDSXMWOOPYFZRKNDNM5734KVCWQ5DE27BELXZ4AD6AAAAAAAAAAAAAAAAAGCABAEAUBK3LQEVPTEPJZXT6ZZJKTOSFXZHA2X7IC7DZNLQMJR2YPPILRZLEMYJZBZQNSREDSXMWOOPYFZRKNDNM5734KVCWQ5DE27BELXZ4AD6AAAAAAAAAAAAAAEBQCAKAVNVYCKXZSHU43Z7M4UVJXJC34TQNL7UBPR4WVYGEY5MHXUFY4VSGME4Q4YGZISBZLWLHHH4C4YVGRWWO756FKRLIORSNPQSF346AB7AAAAAAAAAAAAAAAAADBABQCAKAVNVYCKXZSHU43Z7M4UVJXJC34TQNL7UBPR4WVYGEY5MHXUFY4VSGME4Q4YGZISBZLWLHHH4C4YVGRWWO756FKRLIORSNPQSF346AB7AAAAAAAAAAAAAACAYBAFAKW24BFL4ZD2ON47WOKKU3URN6JYGV72AXY6LK4DCMOWD32C4OKZDGCOIOMDMUJA4V3FTTT6BOMKTI3LHP67CVIVUHIZGXYJC56PAA7QAAAAAAAAAAAAAAAABQQBABAFAKW24BFL4ZD2ON47WOKKU3URN6JYGV72AXY6LK4DCMOWD32C4OKZDGCOIOMDMUJA4V3FTTT6BOMKTI3LHP67CVIVUHIZGXYJC56PAA7QAAAAAAAAAAAAAAAAAQCQAVMBCUJUWZXIISNQY3J4HHF4UCTG2VI2OTKVWAQFVZWYX3T5MXS6LWV44LU2USLVE3FHYGV7SNVPQ5CN26L4NIXDELTBDOENZ644M7KAAAAAAAAAAAAAAAEAIBICVWXAJK7GI6TTPH5TSSVG5ELPSOBVP6QF6HS2XAYTDVQ66QXDSWIZQTSDTA3FCIHFOZM447QLTCU2G2Z37XYVKFNB2GJV6CIXPTYAH4AAAAAAAAAAAAAAIDAEAUBK3LQEVPTEPJZXT6ZZJKTOSFXZHA2X7IC7DZNLQMJR2YPPILRZLEMYJZBZQNSREDSXMWOOPYFZRKNDNM5734KVCWQ5DE27BELXZ4AD6AAAAAAAAAAAAAAEBQCAKAVNVYCKXZSHU43Z7M4UVJXJC34TQNL7UBPR4WVYGEY5MHXUFY4VSGME4Q4YGZISBZLWLHHH4C4YVGRWWO756FKRLIORSNPQSF346AB7AAAAAAAAAAAAAACAYBAFAKW24BFL4ZD2ON47WOKKU3URN6JYGV72AXY6LK4DCMOWD32C4OKZDGCOIOMDMUJA4V3FTTT6BOMKTI3LHP67CVIVUHIZGXYJC56PAA7QAAAAAAAAAAAAAAAABQQAQBAFAKW24BFL4ZD2ON47WOKKU3URN6JYGV72AXY6LK4DCMOWD32C4OKZDGCOIOMDMUJA4V3FTTT6BOMKTI3LHP67CVIVUHIZGXYJC56PAA7QAAAAAAAAAAAAAAAABQQAIBAFAKW24BFL4ZD2ON47WOKKU3URN6JYGV72AXY6LK4DCMOWD32C4OKZDGCOIOMDMUJA4V3FTTT6BOMKTI3LHP67CVIVUHIZGXYJC56PAA7QAAAAAAAAAAAAABAMAQCQFLNOASV6MR5HG6P3HFFKN2IW7E4DK75AL4PFVOBRGHLB55BOHFMRTBHEHGBWKEQOK5SZZZ7AXGFJUNVTX7PRKUK2DUMTL4ERO7HQAPYAAAAAAAAAAAAAAAAAYIAMAQCQFLNOASV6MR5HG6P3HFFKN2IW7E4DK75AL4PFVOBRGHLB55BOHFMRTBHEHGBWKEQOK5SZZZ7AXGFJUNVTX7PRKUK2DUMTL4ERO7HQAPYAAAAAAAAAAAAAAQGAIBICVWXAJK7GI6TTPH5TSSVG5ELPSOBVP6QF6HS2XAYTDVQ66QXDSWIZQTSDTA3FCIHFOZM447QLTCU2G2Z37XYVKFNB2GJV6CIXPTYAH4AAAAAAAAAAAAAAAAAMEAIAIBICVWXAJK7GI6TTPH5TSSVG5ELPSOBVP6QF6HS2XAYTDVQ66QXDSWIZQTSDTA3FCIHFOZM447QLTCU2G2Z37XYVKFNB2GJV6CIXPTYAH4AAAAAAAAAAAAAAAAAMEAAAIBICVWXAJK7GI6TTPH5TSSVG5ELPSOBVP6QF6HS2XAYTDVQ66QXDSWIZQTSDTA3FCIHFOZM447QLTCU2G2Z37XYVKFNB2GJV6CIXPTYAH4AAAAAAAAAAAAAAIDAEAUBK3LQEVPTEPJZXT6ZZJKTOSFXZHA2X7IC7DZNLQMJR2YPPILRZLEMYJZBZQNSREDSXMWOOPYFZRKNDNM5734KVCWQ5DE27BELXZ4AD6AAAAAAAAAAAAAAEBQCAKAVNVYCKXZSHU43Z7M4UVJXJC34TQNL7UBPR4WVYGEY5MHXUFY4VSGME4Q4YGZISBZLWLHHH4C4YVGRWWO756FKRLIORSNPQSF346AB7AAAAAAAAAAAAAACAYBAFAKW24BFL4ZD2ON47WOKKU3URN6JYGV72AXY6LK4DCMOWD32C4OKZDGCOIOMDMUJA4V3FTTT6BOMKTI3LHP67CVIVUHIZGXYJC56PAA7QAAAAAAAAAAAAAAAABQQBYBAFAKW24BFL4ZD2ON47WOKKU3URN6JYGV72AXY6LK4DCMOWD32C4OKZDGCOIOMDMUJA4V3FTTT6BOMKTI3LHP67CVIVUHIZGXYJC56PAA7QAAAAAAAAAAAAAAAABQQBQBAFAKW24BFL4ZD2ON47WOKKU3URN6JYGV72AXY6LK4DCMOWD32C4OKZDGCOIOMDMUJA4V3FTTT6BOMKTI3LHP67CVIVUHIZGXYJC56PAA7QAAAAAAAAAAAAABAMAQCQFLNOASV6MR5HG6P3HFFKN2IW7E4DK75AL4PFVOBRGHLB55BOHFMRTBHEHGBWKEQOK5SZZZ7AXGFJUNVTX7PRKUK2DUMTL4ERO7HQAPYAAAAAAAAAAAAAAAAAYIBAAQCQFLNOASV6MR5HG6P3HFFKN2IW7E4DK75AL4PFVOBRGHLB55BOHFMRTBHEHGBWKEQOK5SZZZ7AXGFJUNVTX7PRKUK2DUMTL4ERO7HQAPYAAAAAAAAAAAAAAQGAIBICVWXAJK7GI6TTPH5TSSVG5ELPSOBVP6QF6HS2XAYTDVQ66QXDSWIZQTSDTA3FCIHFOZM447QLTCU2G2Z37XYVKFNB2GJV6CIXPTYAH4AAAAAAAAAAAAAAAAAMEASAIBICVWXAJK7GI6TTPH5TSSVG5ELPSOBVP6QF6HS2XAYTDVQ66QXDSWIZQTSDTA3FCIHFOZM447QLTCU2G2Z37XYVKFNB2GJV6CIXPTYAH4AAAAAAAAAAAAAAAAAMEAKAIBICVWXAJK7GI6TTPH5TSSVG5ELPSOBVP6QF6HS2XAYTDVQ66QXDSWIZQTSDTA3FCIHFOZM447QLTCU2G2Z37XYVKFNB2GJV6CIXPTYAH4AAAAAAAAAAAAAAAAAEAUAFLAIVCNFWN2CETMGG2PBZZPFAUZWVKGTU2VNQEBNONWF647LF4XS5VPHC5GVES5JGZJ6BVP4TNL4HITOXS7DKFYZC4YI3RDOPXHDH2QAAAAAAAAAAAAAABACAKAVNVYCKXZSHU43Z7M4UVJXJC34TQNL7UBPR4WVYGEY5MHXUFY4VSGME4Q4YGZISBZLWLHHH4C4YVGRWWO756FKRLIORSNPQSF346AB7AAAAAAAAAAAAAACAYBAFAKW24BFL4ZD2ON47WOKKU3URN6JYGV72AXY6LK4DCMOWD32C4OKZDGCOIOMDMUJA4V3FTTT6BOMKTI3LHP67CVIVUHIZGXYJC56PAA7QAAAAAAAAAAAAABAMAQCQFLNOASV6MR5HG6P3HFFKN2IW7E4DK75AL4PFVOBRGHLB55BOHFMRTBHEHGBWKEQOK5SZZZ7AXGFJUNVTX7PRKUK2DUMTL4ERO7HQAPYAAAAAAAAAAAAAAQGAIBICVWXAJK7GI6TTPH5TSSVG5ELPSOBVP6QF6HS2XAYTDVQ66QXDSWIZQTSDTA3FCIHFOZM447QLTCU2G2Z37XYVKFNB2GJV6CIXPTYAH4AAAAAAAAAAAAAAAAAMEAEAIBICVWXAJK7GI6TTPH5TSSVG5ELPSOBVP6QF6HS2XAYTDVQ66QXDSWIZQTSDTA3FCIHFOZM447QLTCU2G2Z37XYVKFNB2GJV6CIXPTYAH4AAAAAAAAAAAAAAAAAMEACAIBICVWXAJK7GI6TTPH5TSSVG5ELPSOBVP6QF6HS2XAYTDVQ66QXDSWIZQTSDTA3FCIHFOZM447QLTCU2G2Z37XYVKFNB2GJV6CIXPTYAH4AAAAAAAAAAAAAAIDAEAUBK3LQEVPTEPJZXT6ZZJKTOSFXZHA2X7IC7DZNLQMJR2YPPILRZLEMYJZBZQNSREDSXMWOOPYFZRKNDNM5734KVCWQ5DE27BELXZ4AD6AAAAAAAAAAAAAAAAAGCADAEAUBK3LQEVPTEPJZXT6ZZJKTOSFXZHA2X7IC7DZNLQMJR2YPPILRZLEMYJZBZQNSREDSXMWOOPYFZRKNDNM5734KVCWQ5DE27BELXZ4AD6AAAAAAAAAAAAAAEBQCAKAVNVYCKXZSHU43Z7M4UVJXJC34TQNL7UBPR4WVYGEY5MHXUFY4VSGME4Q4YGZISBZLWLHHH4C4YVGRWWO756FKRLIORSNPQSF346AB7AAAAAAAAAAAAAAAAADBACACAKAVNVYCKXZSHU43Z7M4UVJXJC34TQNL7UBPR4WVYGEY5MHXUFY4VSGME4Q4YGZISBZLWLHHH4C4YVGRWWO756FKRLIORSNPQSF346AB7AAAAAAAAAAAAAAAAADBAFACAKAVNVYCKXZSHU43Z7M4UVJXJC34TQNL7UBPR4WVYGEY5MHXUFY4VSGME4Q4YGZISBZLWLHHH4C4YVGRWWO756FKRLIORSNPQSF346AB7AAAAAAAAAAAAAACAYBAFAKW24BFL4ZD2ON47WOKKU3URN6JYGV72AXY6LK4DCMOWD32C4OKZDGCOIOMDMUJA4V3FTTT6BOMKTI3LHP67CVIVUHIZGXYJC56PAA7QAAAAAAAAAAAAABAMAQCQFLNOASV6MR5HG6P3HFFKN2IW7E4DK75AL4PFVOBRGHLB55BOHFMRTBHEHGBWKEQOK5SZZZ7AXGFJUNVTX7PRKUK2DUMTL4ERO7HQAPYAAAAAAAAAAAAAAQGAIBICVWXAJK7GI6TTPH5TSSVG5ELPSOBVP6QF6HS2XAYTDVQ66QXDSWIZQTSDTA3FCIHFOZM447QLTCU2G2Z37XYVKFNB2GJV6CIXPTYAH4AAAAAAAAAAAAAAAAAMEAEAIBICVWXAJK7GI6TTPH5TSSVG5ELPSOBVP6QF6HS2XAYTDVQ66QXDSWIZQTSDTA3FCIHFOZM447QLTCU2G2Z37XYVKFNB2GJV6CIXPTYAH4AAAAAAAAAAAAAAAAAMEACAIBICVWXAJK7GI6TTPH5TSSVG5ELPSOBVP6QF6HS2XAYTDVQ66QXDSWIZQTSDTA3FCIHFOZM447QLTCU2G2Z37XYVKFNB2GJV6CIXPTYAH4AAAAAAAAAAAAAAIDAEAUBK3LQEVPTEPJZXT6ZZJKTOSFXZHA2X7IC7DZNLQMJR2YPPILRZLEMYJZBZQNSREDSXMWOOPYFZRKNDNM5734KVCWQ5DE27BELXZ4AD6AAAAAAAAAAAAAAAAAGCADAEAUBK3LQEVPTEPJZXT6ZZJKTOSFXZHA2X7IC7DZNLQMJR2YPPILRZLEMYJZBZQNSREDSXMWOOPYFZRKNDNM5734KVCWQ5DE27BELXZ4AD6AAAAAAAAAAAAAAEBQCAKAVNVYCKXZSHU43Z7M4UVJXJC34TQNL7UBPR4WVYGEY5MHXUFY4VSGME4Q4YGZISBZLWLHHH4C4YVGRWWO756FKRLIORSNPQSF346AB7AAAAAAAAAAAAAAAAADBACACAKAVNVYCKXZSHU43Z7M4UVJXJC34TQNL7UBPR4WVYGEY5MHXUFY4VSGME4Q4YGZISBZLWLHHH4C4YVGRWWO756FKRLIORSNPQSF346AB7AAAAAAAAAAAAAAAAADBAAACAKAVNVYCKXZSHU43Z7M4UVJXJC34TQNL7UBPR4WVYGEY5MHXUFY4VSGME4Q4YGZISBZLWLHHH4C4YVGRWWO756FKRLIORSNPQSF346AB7AAAAAAAAAAAAAACAYBAFAKW24BFL4ZD2ON47WOKKU3URN6JYGV72AXY6LK4DCMOWD32C4OKZDGCOIOMDMUJA4V3FTTT6BOMKTI3LHP67CVIVUHIZGXYJC56PAA7QAAAAAAAAAAAAABAMAQCQFLNOASV6MR5HG6P3HFFKN2IW7E4DK75AL4PFVOBRGHLB55BOHFMRTBHEHGBWKEQOK5SZZZ7AXGFJUNVTX7PRKUK2DUMTL4ERO7HQAPYAAAAAAAAAAAAAAQGAIBICVWXAJK7GI6TTPH5TSSVG5ELPSOBVP6QF6HS2XAYTDVQ66QXDSWIZQTSDTA3FCIHFOZM447QLTCU2G2Z37XYVKFNB2GJV6CIXPTYAH4AAAAAAAAAAAAAAAAAMEAOAIBICVWXAJK7GI6TTPH5TSSVG5ELPSOBVP6QF6HS2XAYTDVQ66QXDSWIZQTSDTA3FCIHFOZM447QLTCU2G2Z37XYVKFNB2GJV6CIXPTYAH4AAAAAAAAAAAAAAAAAMEAMAIBICVWXAJK7GI6TTPH5TSSVG5ELPSOBVP6QF6HS2XAYTDVQ66QXDSWIZQTSDTA3FCIHFOZM447QLTCU2G2Z37XYVKFNB2GJV6CIXPTYAH4AAAAAAAAAAAAAAIDAEAUBK3LQEVPTEPJZXT6ZZJKTOSFXZHA2X7IC7DZNLQMJR2YPPILRZLEMYJZBZQNSREDSXMWOOPYFZRKNDNM5734KVCWQ5DE27BELXZ4AD6AAAAAAAAAAAAAAAAAGCAIAEAUBK3LQEVPTEPJZXT6ZZJKTOSFXZHA2X7IC7DZNLQMJR2YPPILRZLEMYJZBZQNSREDSXMWOOPYFZRKNDNM5734KVCWQ5DE27BELXZ4AD6AAAAAAAAAAAAAAEBQCAKAVNVYCKXZSHU43Z7M4UVJXJC34TQNL7UBPR4WVYGEY5MHXUFY4VSGME4Q4YGZISBZLWLHHH4C4YVGRWWO756FKRLIORSNPQSF346AB7AAAAAAAAAAAAAAAAADBAEQCAKAVNVYCKXZSHU43Z7M4UVJXJC34TQNL7UBPR4WVYGEY5MHXUFY4VSGME4Q4YGZISBZLWLHHH4C4YVGRWWO756FKRLIORSNPQSF346AB7AAAAAAAAAAAAAAAAADBACQCAKAVNVYCKXZSHU43Z7M4UVJXJC34TQNL7UBPR4WVYGEY5MHXUFY4VSGME4Q4YGZISBZLWLHHH4C4YVGRWWO756FKRLIORSNPQSF346AB7AAAAAAAAAAAAAAAAABAFABKYCFITJNTOQRE3BRWTYOOLZIFGNVKRU5GVLMBALLTNRPXH2ZPF4XNLZYXJVJEXKJWKPQNL7E3K7B2E3V4XY2ROGIXGCG4I3T5ZYZ6UAAAAAAAAAAAAAAAIAQCQFLNOASV6MR5HG6P3HFFKN2IW7E4DK75AL4PFVOBRGHLB55BOHFMRTBHEHGBWKEQOK5SZZZ7AXGFJUNVTX7PRKUK2DUMTL4ERO7HQAPYAAAAAAAAAAAAAAQGAIBICVWXAJK7GI6TTPH5TSSVG5ELPSOBVP6QF6HS2XAYTDVQ66QXDSWIZQTSDTA3FCIHFOZM447QLTCU2G2Z37XYVKFNB2GJV6CIXPTYAH4AAAAAAAAAAAAAAIDAEAUBK3LQEVPTEPJZXT6ZZJKTOSFXZHA2X7IC7DZNLQMJR2YPPILRZLEMYJZBZQNSREDSXMWOOPYFZRKNDNM5734KVCWQ5DE27BELXZ4AD6AAAAAAAAAAAAAAAAAGAAFNBSWY3DPAEAUBK3LQEVPTEPJZXT6ZZJKTOSFXZHA2X7IC7DZNLQMJR2YPPILRZLEMYJZBZQNSREDSXMWOOPYFZRKNDNM5734KVCWQ5DE27BELXZ4AD6AAAAAAAAAAAAAAAAAGAABEAAQCQFLNOASV6MR5HG6P3HFFKN2IW7E4DK75AL4PFVOBRGHLB55BOHFMRTBHEHGBWKEQOK5SZZZ7AXGFJUNVTX7PRKUK2DUMTL4ERO7HQAPYAAAAAAAAAAAAAAQGAIBICVWXAJK7GI6TTPH5TSSVG5ELPSOBVP6QF6HS2XAYTDVQ66QXDSWIZQTSDTA3FCIHFOZM447QLTCU2G2Z37XYVKFNB2GJV6CIXPTYAH4AAAAAAAAAAAAAAIDAEAUBK3LQEVPTEPJZXT6ZZJKTOSFXZHA2X7IC7DZNLQMJR2YPPILRZLEMYJZBZQNSREDSXMWOOPYFZRKNDNM5734KVCWQ5DE27BELXZ4AD6AAAAAAAAAAAAAAAAAGAAEM5XW6ZABAFAKW24BFL4ZD2ON47WOKKU3URN6JYGV72AXY6LK4DCMOWD32C4OKZDGCOIOMDMUJA4V3FTTT6BOMKTI3LHP67CVIVUHIZGXYJC56PAA7QAAAAAAAAAAAAAAAABQAA3CPFSQCAKAVNVYCKXZSHU43Z7M4UVJXJC34TQNL7UBPR4WVYGEY5MHXUFY4VSGME4Q4YGZISBZLWLHHH4C4YVGRWWO756FKRLIORSNPQSF346AB7AAAAAAAAAAAAAAAAABAFAAAL7RKMFUH4QQ5G2NTSQN244XUAWGVES3B5ALZMIZQ472Z3Z2SNRY5NY74Q7LRMSAM6YKIY6LXDY4GMGUQNR5G27OEYPJPYTZR5GNAIAAAAAAAAAAAAAAAAAQCQAAF7YVGC2D6IIOTNGZZIG5OOL2ALDKSJNQ6QF4WEMYOP5M545JGY4OW4P6IPVYWJAGPMFEMPF3R4ODGDKIGY6TNPXCMHUX4J4Y6TGQEAAAAAAAAAAAAAAAAAIBIAAC74KTBNB7EEHJWTM4UDOXHF5AFRVJEWYPIC6LCGMHH6WO6OUTMOHLOH7EH24LEQDHWCSGHS5Y6HBTBVEDMPJWX3RGD2L6E6MPJTICAAAAAAAAAAAAAAAA \ No newline at end of file diff --git a/unison-src/transcripts-using-base/serialized-cases/case-01.v5.hash b/unison-src/transcripts-using-base/serialized-cases/case-01.v5.hash new file mode 100644 index 0000000000..d576afd225 --- /dev/null +++ b/unison-src/transcripts-using-base/serialized-cases/case-01.v5.hash @@ -0,0 +1 @@ +F5QWFLMAWQDYCMOPDCCTYLWJ2HOBGUG2G5YLWHSAFGDXSHGYQIWDSN6PVWC2RJXIGB7ZBSZVIJ6OENKGWAEZIV3CLQ2AWL3WKITPDXA= \ No newline at end of file diff --git a/unison-src/transcripts-using-base/serialized-cases/case-01.v5.ser b/unison-src/transcripts-using-base/serialized-cases/case-01.v5.ser new file mode 100644 index 0000000000..071ca615cb --- /dev/null +++ b/unison-src/transcripts-using-base/serialized-cases/case-01.v5.ser @@ -0,0 +1 @@ +AAAAABIBAFABKYCFITJNTOQRE3BRWTYOOLZIFGNVKRU5GVLMBALLTNRPXH2ZPF4XNLZYXJVJEXKJWKPQNL7E3K7B2E3V4XY2ROGIXGCG4I3T5ZYZ6UAAAAAAAAAAAAAAAIBQCBABAFABKYCFITJNTOQRE3BRWTYOOLZIFGNVKRU5GVLMBALLTNRPXH2ZPF4XNLZYXJVJEXKJWKPQNL7E3K7B2E3V4XY2ROGIXGCG4I3T5ZYZ6UAAAAAAAAAAAAAAAIBQEAABEEAFG5MMPCUOP3IIQXASYKKG2MIJ2XJ3B7MGFL6E44DZUAQUNLQVKHIAAEAUAFLAIVCNFWN2CETMGG2PBZZPFAUZWVKGTU2VNQEBNONWF647LF4XS5VPHC5GVES5JGZJ6BVP4TNL4HITOXS7DKFYZC4YI3RDOPXHDH2QAAAAAAAAAAAAAABAGBQAAMAQCAIKAEAQYAIAAAAAAAAAAAAAGAIBEEAO7KOJ7HCZGJXDGV7GZE7OLVCVEIO5QE4Y6TLY67FZSQS6DUK2SVYAAQAQGAQAAAAQCQAAF7YVGC2D6IIOTNGZZIG5OOL2ALDKSJNQ6QF4WEMYOP5M545JGY4OW4P6IPVYWJAGPMFEMPF3R4ODGDKIGY6TNPXCMHUX4J4Y6TGQEAAAAAAAAAAAAAAAAAIBIAKWARKE2LM3UEJGYMNU6DTS6KBJTNKUNHJVK3AIC243ML5Z6WLZPF3K6OF2NKJF2SNST4DK7ZG2XYORG5PF6GULRSFZQRXCG47OOGPVAAAAAAAAAAAAAAACAMBAAAJBACAVWVMCTIBA5P5JFQIRMCJBBMWMLBPXDOTQRHHF76XEAPI46LZWWAABAFABKYCFITJNTOQRE3BRWTYOOLZIFGNVKRU5GVLMBALLTNRPXH2ZPF4XNLZYXJVJEXKJWKPQNL7E3K7B2E3V4XY2ROGIXGCG4I3T5ZYZ6UAAAAAAAAAAAAAAAIBQMAABAEDAABABIAKWARKE2LM3UEJGYMNU6DTS6KBJTNKUNHJVK3AIC243ML5Z6WLZPF3K6OF2NKJF2SNST4DK7ZG2XYORG5PF6GULRSFZQRXCG47OOGPVAAAQAAQBAEDAABABIAKWARKE2LM3UEJGYMNU6DTS6KBJTNKUNHJVK3AIC243ML5Z6WLZPF3K6OF2NKJF2SNST4DK7ZG2XYORG5PF6GULRSFZQRXCG47OOGPVAAAQAAQBAEDAABABIAKWARKE2LM3UEJGYMNU6DTS6KBJTNKUNHJVK3AIC243ML5Z6WLZPF3K6OF2NKJF2SNST4DK7ZG2XYORG5PF6GULRSFZQRXCG47OOGPVAAAQAAQBAEDAABABIAAC74KTBNB7EEHJWTM4UDOXHF5AFRVJEWYPIC6LCGMHH6WO6OUTMOHLOH7EH24LEQDHWCSGHS5Y6HBTBVEDMPJWX3RGD2L6E6MPJTICAAAQAAALAAAQCAIDAEAAORTMN5QXILRLAAFACAIMAIAAAAAAAAAAAAALAAGQCAIDAEASCACTOWGHRKHH5UEILQJMFFDNGEE5LU5Q7WDCV7COOB42AIKGVYKVDUAAGAIAA4FQAAQBAEBQCAAFJFXHILRLAAFACAIMAAAAAAAAAAAAAAALAAGACAIDAEASCACTOWGHRKHH5UEILQJMFFDNGEE5LU5Q7WDCV7COOB42AIKGVYKVDUAAGAIABAFQAAYBAEBQCAJBACKBUK5CBIZUMPZQELVRT4XZEUX7KCXBOZMJE7YZOIMHLEHMX4UEEAAABIAQCBYDAAFQACYBAEBQCAJBABJXLDDYVDT62CEFYEWCSRWTCCOV2OYP3BRK7RHHA6NAEFDK4FKR2AADAEAASCQBAEDQGAJIBMAAIAIBAMAQADCGNRXWC5BOORXVIZLYOQAQOCYAAUAQCAYBAADVIZLYOQXCWKYCAEAAUAIBA4BQELBABMAAMAIBAMAQAB2UMV4HILRLFMBACAALAADQCAIDAEAAUSLOOQXHI32UMV4HIAIIBMAAQAIBAMAQAB2UMV4HILRLFMBACAAKAEAQOAYDFQQCECYABEAQCAYBAADVIZLYOQXCWKYCAEAAWAAKAEAQGAIAA5KGK6DUFYVSWAQABEFACAIHAMBCEKIDAEAAOVDFPB2C4KZLAIAQAAAAAAAAAAIBIAAC74KTBNB7EEHJWTM4UDOXHF5AFRVJEWYPIC6LCGMHH6WO6OUTMOHLOH7EH24LEQDHWCSGHS5Y6HBTBVEDMPJWX3RGD2L6E6MPJTICAAAAAAAAAAAAAAAAAEAUAFLAIVCNFWN2CETMGG2PBZZPFAUZWVKGTU2VNQEBNONWF647LF4XS5VPHC5GVES5JGZJ6BVP4TNL4HITOXS7DKFYZC4YI3RDOPXHDH2QAAAAAAAAAAAAAABAGAQAAEQQBFA2FORAUM2GH4YCF2YZ6L4SKL7VBLQXMWESP4MXEGDVSDWL6KCCAAAQCQAVMBCUJUWZXIISNQY3J4HHF4UCTG2VI2OTKVWAQFVZWYX3T5MXS6LWV44LU2USLVE3FHYGV7SNVPQ5CN26L4NIXDELTBDOENZ644M7KAAAAAAAAAAAAAAAEAYGAABACAILAAAQCAIDAEAAWQ3IMFZC45DPKRSXQ5ABAABQCAAHKRSXQ5BOFMVQEAQAAAAQCQAAF7YVGC2D6IIOTNGZZIG5OOL2ALDKSJNQ6QF4WEMYOP5M545JGY4OW4P6IPVYWJAGPMFEMPF3R4ODGDKIGY6TNPXCMHUX4J4Y6TGQEAAAAAAAAAAAAAAAAAIBIAKWARKE2LM3UEJGYMNU6DTS6KBJTNKUNHJVK3AIC243ML5Z6WLZPF3K6OF2NKJF2SNST4DK7ZG2XYORG5PF6GULRSFZQRXCG47OOGPVAAAAAAAAAAAAAAACAMBAAAJBADX2TSPZYWJSNYZVPZWJH3S5IVJCDXMBHGHU26HXZOMUEXQ5CWUVOAABAFABKYCFITJNTOQRE3BRWTYOOLZIFGNVKRU5GVLMBALLTNRPXH2ZPF4XNLZYXJVJEXKJWKPQNL7E3K7B2E3V4XY2ROGIXGCG4I3T5ZYZ6UAAAAAAAAAAAAAAAIBQMAAEAEAQCAILAABQCAIDAEAAOTDJON2C4YLUAIAAGBQAAQAUBPFXSLRYBUMTQI4D4TSH2NNNUNKNR3L447EHJZMO3DMA3FE3H7JJBKRQSX7O7KXGBYVP5635Y6GI6DVXFPYHJ2YVBLSZV6TR5NYFZLZAAAQAAEAQWAABAEAQGAAEAIBQACQBAEGACAAAAAAAAAAAAEFQAAQBAEBQCAAFJZQXILRLAICAAAYBAEQQB35JZH44LEZG4M2X43ET5ZOUKURB3WATTD2NPD34XGKCLYORLKKXAACAQBYCAAAQAAICAAAACAKAAAX7CUYLIPZBB2NU3HFA3VZZPIBMNKJFWD2AXSYRTBZ7VTXTVE3DR23R7ZB6XCZEAZ5QURR4XOHRYMYNJA3D2NV64JQ6S7RHTD2M2AQAAAAAAAAAAAAAAAABAFABKYCFITJNTOQRE3BRWTYOOLZIFGNVKRU5GVLMBALLTNRPXH2ZPF4XNLZYXJVJEXKJWKPQNL7E3K7B2E3V4XY2ROGIXGCG4I3T5ZYZ6UAAAAAAAAAAAAAAAIBQKAIBIAKWARKE2LM3UEJGYMNU6DTS6KBJTNKUNHJVK3AIC243ML5Z6WLZPF3K6OF2NKJF2SNST4DK7ZG2XYORG5PF6GULRSFZQRXCG47OOGPVAAAAAAAAAAAAAAACAAASCAEBLNKYFGQCB272SLARCYESCCZMYWC7OG5HBCOOL75OIA6RZ4XTNMAAAAAAAAAAAAAAAAAQCQAVMBCUJUWZXIISNQY3J4HHF4UCTG2VI2OTKVWAQFVZWYX3T5MXS6LWV44LU2USLVE3FHYGV7SNVPQ5CN26L4NIXDELTBDOENZ644M7KAAAAAAAAAAAAAAAEAIBIAKWARKE2LM3UEJGYMNU6DTS6KBJTNKUNHJVK3AIC243ML5Z6WLZPF3K6OF2NKJF2SNST4DK7ZG2XYORG5PF6GULRSFZQRXCG47OOGPVAAAAAAAAAAAAAAACAMAQGAYLH7YAAAAAAAAAAAYLIAAAAAAAAAAAAAYLIAEAAAAAAAAAAAIBIAKWARKE2LM3UEJGYMNU6DTS6KBJTNKUNHJVK3AIC243ML5Z6WLZPF3K6OF2NKJF2SNST4DK7ZG2XYORG5PF6GULRSFZQRXCG47OOGPVAAAAAAAAAAAAAAACAMAQGAYIAEBQQAQDBABQCAKACVQEKRGS3G5BCJWDDNHQ44XSQKM3KVDJ2NKWYCAWXG3C7OPVS6LZO2XTROTKSJOUTMU7A2X6JWV6DUJXLZPRVC4MROMENYRXH3TRT5IAAAAAAAAAAAAAAAQDAEBQGCTBAMFGEAYKMMAQCQAAF7YVGC2D6IIOTNGZZIG5OOL2ALDKSJNQ6QF4WEMYOP5M545JGY4OW4P6IPVYWJAGPMFEMPF3R4ODGDKIGY6TNPXCMHUX4J4Y6TGQEAAAAAAAAAAAAAAAAAIBIAAC74KTBNB7EEHJWTM4UDOXHF5AFRVJEWYPIC6LCGMHH6WO6OUTMOHLOH7EH24LEQDHWCSGHS5Y6HBTBVEDMPJWX3RGD2L6E6MPJTICAAAAAAAAAAAAAAAAAEAUAABP6FJQWQ7SCDU3JWOKBXLTS6QCY2USLMHUBPFRDGDT7LHPHKJWHDVXD7SD5OFSIBT3BJDDZO4PDQZQ2SBWHU3L5YTB5F7CPGHUZUBAAAAAAAAAAAAAAAAA==== \ No newline at end of file diff --git a/unison-src/transcripts-using-base/serialized-cases/case-02.v5.hash b/unison-src/transcripts-using-base/serialized-cases/case-02.v5.hash new file mode 100644 index 0000000000..f7f6926bc2 --- /dev/null +++ b/unison-src/transcripts-using-base/serialized-cases/case-02.v5.hash @@ -0,0 +1 @@ +OKXJPQQY4QXSCGDHM2LSUTSIKWE7W5PS6CSYCKBOEOBTRKHOKWTH6QZP7HEVWPEJC5CWGWB54ZPI7YB36F37MXN7ISPCP5JGX26NRBQ= \ No newline at end of file diff --git a/unison-src/transcripts-using-base/serialized-cases/case-02.v5.ser b/unison-src/transcripts-using-base/serialized-cases/case-02.v5.ser new file mode 100644 index 0000000000..0257e72254 --- /dev/null +++ b/unison-src/transcripts-using-base/serialized-cases/case-02.v5.ser @@ -0,0 +1 @@ +AAAAABIBAFABKYCFITJNTOQRE3BRWTYOOLZIFGNVKRU5GVLMBALLTNRPXH2ZPF4XNLZYXJVJEXKJWKPQNL7E3K7B2E3V4XY2ROGIXGCG4I3T5ZYZ6UAAAAAAAAAAAAAAAIBQCBIBAFABKYCFITJNTOQRE3BRWTYOOLZIFGNVKRU5GVLMBALLTNRPXH2ZPF4XNLZYXJVJEXKJWKPQNL7E3K7B2E3V4XY2ROGIXGCG4I3T5ZYZ6UAAAAAAAAAAAAAAAIBQEAABEEAAYIUEFZ4JEHYKKJOYXA3U4QEFR2C7BDWZX43W26BCDHYJLM2O2UYAAEAUAFLAIVCNFWN2CETMGG2PBZZPFAUZWVKGTU2VNQEBNONWF647LF4XS5VPHC5GVES5JGZJ6BVP4TNL4HITOXS7DKFYZC4YI3RDOPXHDH2QAAAAAAAAAAAAAABAGBQAAIAQCCYAAIAQCAYBAAFEY2LTOQXHM2LFO5WACAAGAACACQBXUUCXAJCWUDKCCPAAZUOSPHG5OAQWM7RAIACNQG5HLXLG25SJ6V4VM43AO7YPRRQOZDZQ6GRWPWODX4EPCCQUPWP5K4RWURF7N2IYQAACAABACAIGAEDAAA2OMF2ACAAAAAAAAAAAAAFACAIMAEAAAAAAAAAAAAADAQAUAMY65NCSULNIGUIJ26OXZM426I623Z65KBOZEJNZZYM7LU57JG7EVXPBXX6OFMJZQKWUPCI3PXACLDTU7NZUWCBSXG2XRNZ7IM23NWTQAAABAAAQWAABAEAQGAIAAVHGC5BOFIBAIAIDAEASCAAMEKCC46ESD4FFEXMLQN2OICCY5BPQR3M36N3NPARBT4EVWNHNKMAAEAABAEAACAQAAAAQCQAAF7YVGC2D6IIOTNGZZIG5OOL2ALDKSJNQ6QF4WEMYOP5M545JGY4OW4P6IPVYWJAGPMFEMPF3R4ODGDKIGY6TNPXCMHUX4J4Y6TGQEAAAAAAAAAAAAAAAAAIBIAKWARKE2LM3UEJGYMNU6DTS6KBJTNKUNHJVK3AIC243ML5Z6WLZPF3K6OF2NKJF2SNST4DK7ZG2XYORG5PF6GULRSFZQRXCG47OOGPVAAAAAAAAAAAAAAACAMBAAAJBAAQQUM3BJ2CBV2DRYDFJVT73O4QXWQ2FFGAQ65UETP5ZKJGMQUOPIAABAFABKYCFITJNTOQRE3BRWTYOOLZIFGNVKRU5GVLMBALLTNRPXH2ZPF4XNLZYXJVJEXKJWKPQNL7E3K7B2E3V4XY2ROGIXGCG4I3T5ZYZ6UAAAAAAAAAAAAAAAIBQMAABAEDAABABIAKWARKE2LM3UEJGYMNU6DTS6KBJTNKUNHJVK3AIC243ML5Z6WLZPF3K6OF2NKJF2SNST4DK7ZG2XYORG5PF6GULRSFZQRXCG47OOGPVAAAQAAQBAEDAABABIAKWARKE2LM3UEJGYMNU6DTS6KBJTNKUNHJVK3AIC243ML5Z6WLZPF3K6OF2NKJF2SNST4DK7ZG2XYORG5PF6GULRSFZQRXCG47OOGPVAAAQAAQBAEDAABABIAKWARKE2LM3UEJGYMNU6DTS6KBJTNKUNHJVK3AIC243ML5Z6WLZPF3K6OF2NKJF2SNST4DK7ZG2XYORG5PF6GULRSFZQRXCG47OOGPVAAAQAAQBAEDAABABIAAC74KTBNB7EEHJWTM4UDOXHF5AFRVJEWYPIC6LCGMHH6WO6OUTMOHLOH7EH24LEQDHWCSGHS5Y6HBTBVEDMPJWX3RGD2L6E6MPJTICAAAQAAALAAFQCAIDAEASCAHMBCFOX4WLK3FQIFDLLBB3ZZQPJHUEKONSUX2NJGCJJSHMAWVAHQAACBILAAFACAIDAEASCAHMBCFOX4WLK3FQIFDLLBB3ZZQPJHUEKONSUX2NJGCJJSHMAWVAHQAACBALAAEQCAIDAEASCAHMBCFOX4WLK3FQIFDLLBB3ZZQPJHUEKONSUX2NJGCJJSHMAWVAHQAACAYKAEAQOAYBFAFQAAIBAEBQCAAKJZQXILTUN5KGK6DUAEBQWAACAEAQGAIAA5KGK6DUFYVSWAQBAAFACAIHAMBCYIALAABQCAIDAEAAOVDFPB2C4KZLAIAQACYAAQAQCAYBAAFE4YLUFZ2G6VDFPB2ACBQLAACQCAIDAEAAOVDFPB2C4KZLAIAQACQBAEDQGAZMEARAWAAGAEAQGAIAA5KGK6DUFYVSWAQBAAFQABYBAEBQCAAKJZQXILTUN5KGK6DUAEEQWAAIAEAQGAIAA5KGK6DUFYVSWAQBAAFACAIHAMBCEKIDAEAAOVDFPB2C4KZLAIAQAAAAAAAAAAIBIAAC74KTBNB7EEHJWTM4UDOXHF5AFRVJEWYPIC6LCGMHH6WO6OUTMOHLOH7EH24LEQDHWCSGHS5Y6HBTBVEDMPJWX3RGD2L6E6MPJTICAAAAAAAAAAAAAAAAAEAUAFLAIVCNFWN2CETMGG2PBZZPFAUZWVKGTU2VNQEBNONWF647LF4XS5VPHC5GVES5JGZJ6BVP4TNL4HITOXS7DKFYZC4YI3RDOPXHDH2QAAAAAAAAAAAAAABAGAQAAEQQAZBETA2YKUQSP2CMAM3N7CPNDHRXDY2J6ZCJ4PQFN3I32GWQGMJTAAAQCQAVMBCUJUWZXIISNQY3J4HHF4UCTG2VI2OTKVWAQFVZWYX3T5MXS6LWV44LU2USLVE3FHYGV7SNVPQ5CN26L4NIXDELTBDOENZ644M7KAAAAAAAAAAAAAAAEAYGAEAQCBQAAIAQCQBTD3VUKKRNVA2RBHLZ27FTTLZD3LPH3VIF3ERFXHHBT5OTX5E34SW54G67ZYVRHGBK2R4JDN64AJMOOT5XGSYIGK43K6FXH5BTLNW2OAABAAAQCBIBIAZR522FFIW2QNIQTV45PSZZV4R5VXT52UC5SIS3TTQZ6XJ36SN6JLO6DPP44KYTTAVNI6ERW7OAEWHHJ63TJMEDFONVPC3T6QZVW3NHAAEAACDKOVWXAQ3PNZ2ACAABAIAQAAIBBEAQABABAFADGHXLIUVC3KBVCCOXTV6LHGXSHWW6PXKQLWJCLOOODH25HP2JXZFN3YN57TRLCOMCVVDYSG35YASY45H3ONFQQMVZWV4LOP2DGW3NU4AAAAQBAAAQCQAAF7YVGC2D6IIOTNGZZIG5OOL2ALDKSJNQ6QF4WEMYOP5M545JGY4OW4P6IPVYWJAGPMFEMPF3R4ODGDKIGY6TNPXCMHUX4J4Y6TGQEAAAAAAAAAAAAAAAAAIBIAKWARKE2LM3UEJGYMNU6DTS6KBJTNKUNHJVK3AIC243ML5Z6WLZPF3K6OF2NKJF2SNST4DK7ZG2XYORG5PF6GULRSFZQRXCG47OOGPVAAAAAAAAAAAAAAACAMBAAAJBABTRHHJSOELTLHBAUQWOZQU2H5SUAC5SDOJNUSQDJ2NEYRSZ4RBDQAABAFABKYCFITJNTOQRE3BRWTYOOLZIFGNVKRU5GVLMBALLTNRPXH2ZPF4XNLZYXJVJEXKJWKPQNL7E3K7B2E3V4XY2ROGIXGCG4I3T5ZYZ6UAAAAAAAAAAAAAAAIBQMAABAEFACAIMAEAAAAAAAAAAAAADAEASCAAMEKCC46ESD4FFEXMLQN2OICCY5BPQR3M36N3NPARBT4EVWNHNKMAAEAABAAAQCQAAF7YVGC2D6IIOTNGZZIG5OOL2ALDKSJNQ6QF4WEMYOP5M545JGY4OW4P6IPVYWJAGPMFEMPF3R4ODGDKIGY6TNPXCMHUX4J4Y6TGQEAAAAAAAAAAAAAAAAAIBIAKWARKE2LM3UEJGYMNU6DTS6KBJTNKUNHJVK3AIC243ML5Z6WLZPF3K6OF2NKJF2SNST4DK7ZG2XYORG5PF6GULRSFZQRXCG47OOGPVAAAAAAAAAAAAAAACAMBAAAJBADWARCXL6LFVNSYECRVVQQ544YHUT2CFHGZKL5GUTBEUZDWALKQDYAABAFABKYCFITJNTOQRE3BRWTYOOLZIFGNVKRU5GVLMBALLTNRPXH2ZPF4XNLZYXJVJEXKJWKPQNL7E3K7B2E3V4XY2ROGIXGCG4I3T5ZYZ6UAAAAAAAAAAAAAAAIBQMAABAEFQAAIBAEBQCAJBABSCJGBVQVJBE7UEYAZW36E62GPDOHRUT5SETY7AK3WRXUNNAMYTGAAABAASCADHCOOTE4IXGWOCBJBM5TBJUP3FIAF3EG4S3JFAGTU2JRDFTZCCHAAACAIDAAAQCAAAAEAUAABP6FJQWQ7SCDU3JWOKBXLTS6QCY2USLMHUBPFRDGDT7LHPHKJWHDVXD7SD5OFSIBT3BJDDZO4PDQZQ2SBWHU3L5YTB5F7CPGHUZUBAAAAAAAAAAAAAAAAACAKACVQEKRGS3G5BCJWDDNHQ44XSQKM3KVDJ2NKWYCAWXG3C7OPVS6LZO2XTROTKSJOUTMU7A2X6JWV6DUJXLZPRVC4MROMENYRXH3TRT5IAAAAAAAAAAAAAAAQDAUAQCQAVMBCUJUWZXIISNQY3J4HHF4UCTG2VI2OTKVWAQFVZWYX3T5MXS6LWV44LU2USLVE3FHYGV7SNVPQ5CN26L4NIXDELTBDOENZ644M7KAAAAAAAAAAAAAAAEAABEEACCCRTMFHIIGXIOHAMVGWP7N3SC62DIUUYCD3WQSN7XFJEZSCRZ5AAAAAAAAAAAAAAAAABAFABKYCFITJNTOQRE3BRWTYOOLZIFGNVKRU5GVLMBALLTNRPXH2ZPF4XNLZYXJVJEXKJWKPQNL7E3K7B2E3V4XY2ROGIXGCG4I3T5ZYZ6UAAAAAAAAAAAAAAAIAQCQAVMBCUJUWZXIISNQY3J4HHF4UCTG2VI2OTKVWAQFVZWYX3T5MXS6LWV44LU2USLVE3FHYGV7SNVPQ5CN26L4NIXDELTBDOENZ644M7KAAAAAAAAAAAAAAAEAYBAUBQQAIDBABQGCAFAMEAOAYIBEAQCQAVMBCUJUWZXIISNQY3J4HHF4UCTG2VI2OTKVWAQFVZWYX3T5MXS6LWV44LU2USLVE3FHYGV7SNVPQ5CN26L4NIXDELTBDOENZ644M7KAAAAAAAAAAAAAAAEAYBBEBQQAIDBABAGCAAAMEAGAYIAQBQQBIDBADAGCAHAMEAQAIBIAKWARKE2LM3UEJGYMNU6DTS6KBJTNKUNHJVK3AIC243ML5Z6WLZPF3K6OF2NKJF2SNST4DK7ZG2XYORG5PF6GULRSFZQRXCG47OOGPVAAAAAAAAAAAAAAACAMAQQAYIAEBQQAQDBACAGCAIAMEBAAYIAMBQQBIDBADACAKAAAX7CUYLIPZBB2NU3HFA3VZZPIBMNKJFWD2AXSYRTBZ7VTXTVE3DR23R7ZB6XCZEAZ5QURR4XOHRYMYNJA3D2NV64JQ6S7RHTD2M2AQAAAAAAAAAAAAAAAABAFAAAL7RKMFUH4QQ5G2NTSQN244XUAWGVES3B5ALZMIZQ472Z3Z2SNRY5NY74Q7LRMSAM6YKIY6LXDY4GMGUQNR5G27OEYPJPYTZR5GNAIAAAAAAAAAAAAAAAAAQCQAAF7YVGC2D6IIOTNGZZIG5OOL2ALDKSJNQ6QF4WEMYOP5M545JGY4OW4P6IPVYWJAGPMFEMPF3R4ODGDKIGY6TNPXCMHUX4J4Y6TGQEAAAAAAAAAAAAAAAA=== \ No newline at end of file diff --git a/unison-src/transcripts-using-base/serialized-cases/case-03.v5.hash b/unison-src/transcripts-using-base/serialized-cases/case-03.v5.hash new file mode 100644 index 0000000000..3b39c4aee9 --- /dev/null +++ b/unison-src/transcripts-using-base/serialized-cases/case-03.v5.hash @@ -0,0 +1 @@ +DLSO2TFPG5363MWC7FDSUW55VYA7P7CI4DBRFLWGPSUTF6YR45QPIPBSJPANZH44MGVYRSSMTPXODLDUFCO6JF43V3IPU4DRDU7JKII= \ No newline at end of file diff --git a/unison-src/transcripts-using-base/serialized-cases/case-03.v5.ser b/unison-src/transcripts-using-base/serialized-cases/case-03.v5.ser new file mode 100644 index 0000000000..f0188e6737 --- /dev/null +++ b/unison-src/transcripts-using-base/serialized-cases/case-03.v5.ser @@ -0,0 +1 @@ +AAAAABIBAFABKYCFITJNTOQRE3BRWTYOOLZIFGNVKRU5GVLMBALLTNRPXH2ZPF4XNLZYXJVJEXKJWKPQNL7E3K7B2E3V4XY2ROGIXGCG4I3T5ZYZ6UAAAAAAAAAAAAAAAIBQCCIBAFABKYCFITJNTOQRE3BRWTYOOLZIFGNVKRU5GVLMBALLTNRPXH2ZPF4XNLZYXJVJEXKJWKPQNL7E3K7B2E3V4XY2ROGIXGCG4I3T5ZYZ6UAAAAAAAAAAAAAAAIBQEAABEEAAOT2MXCZHSMGAQPMEZKCLBK4QHW54TGGJGIN2ZSOFWF4ATCCIDMQAAEAUAFLAIVCNFWN2CETMGG2PBZZPFAUZWVKGTU2VNQEBNONWF647LF4XS5VPHC5GVES5JGZJ6BVP4TNL4HITOXS7DKFYZC4YI3RDOPXHDH2QAAAAAAAAAAAAAABAGBQBAEAQMAACAEAUAN3GIMROJ5IWBPMSHX64WVGJX6EVR6NCKICJCW2N4SPLQXPT6PXCXZDZJLMCA6CDITYETZT5R2CPBEKIKXQMMHVEFHUWQ6BSLO5APT5AAAIAAEAQKAKAG5TEGIXE6ULAXWJD37OLKTE37CKY7GRFEBERLNG6JHVYLXZ7H3RL4R4UVWBAPBBUJ4CJ4Z6Y5BHQSFEFLYGGD2SCT2LIPAZFXOQHZ6QABAAAQ2TVNVYEG33OOQAQACYAAEAQCAYBAEQQAB2PJS4LE6JQYCB5QTFIJMFLSA63XSMYZEZBXLGJYWYXQCMIJANSAEAQAAYAAMAQAAIAAEAQSAIAAQAQCQBXMZBSFZHVCYF5SI673S2UZG7YSWHZUJJAJEK3JXSJ5OC56PZ64K7EPFFNQIDYINCPASPGPWHIJ4ERJBK6BRQ6UQU6S2DYGJN3UB6PUAAAAIAQAAIBIAAC74KTBNB7EEHJWTM4UDOXHF5AFRVJEWYPIC6LCGMHH6WO6OUTMOHLOH7EH24LEQDHWCSGHS5Y6HBTBVEDMPJWX3RGD2L6E6MPJTICAAAAAAAAAAAAAAAAAEAUAFLAIVCNFWN2CETMGG2PBZZPFAUZWVKGTU2VNQEBNONWF647LF4XS5VPHC5GVES5JGZJ6BVP4TNL4HITOXS7DKFYZC4YI3RDOPXHDH2QAAAAAAAAAAAAAABAGAQAAEQQAB2PJS4LE6JQYCB5QTFIJMFLSA63XSMYZEZBXLGJYWYXQCMIJANSAEAQCQAVMBCUJUWZXIISNQY3J4HHF4UCTG2VI2OTKVWAQFVZWYX3T5MXS6LWV44LU2USLVE3FHYGV7SNVPQ5CN26L4NIXDELTBDOENZ644M7KAAAAAAAAAAAAAAAEAYGAABACAILAAAQCAIDAEASCAAHJ5GLRMTZGDAIHWCMVBFQVOID3O6JTDETEG5MZHC3C6AJRBEBWIAAACABEEANR5YMZ4O453FLTU6EFVRUUPWHXYW6TUZGJMG5CJVPJJYYAJA5VZIAAIBACAYAAEAQAAABAFAAAL7RKMFUH4QQ5G2NTSQN244XUAWGVES3B5ALZMIZQ472Z3Z2SNRY5NY74Q7LRMSAM6YKIY6LXDY4GMGUQNR5G27OEYPJPYTZR5GNAIAAAAAAAAAAAAAAAAAQCQAVMBCUJUWZXIISNQY3J4HHF4UCTG2VI2OTKVWAQFVZWYX3T5MXS6LWV44LU2USLVE3FHYGV7SNVPQ5CN26L4NIXDELTBDOENZ644M7KAAAAAAAAAAAAAAAEAYCAAASCABD4J3OKKBTZLPQBBAFHIQYPQADAQXNC3RHA5YKBV72ZGYDNKNQSIAACAKACVQEKRGS3G5BCJWDDNHQ44XSQKM3KVDJ2NKWYCAWXG3C7OPVS6LZO2XTROTKSJOUTMU7A2X6JWV6DUJXLZPRVC4MROMENYRXH3TRT5IAAAAAAAAAAAAAAAQDAYAAEAIBBMAAKAIBAMAQACSMNFZXILTWNFSXO3ABAADAABABIA32KBLQERLKBVBBHQAM2HJHTTOXAILGPYQEABGYDOTV3VTNOZE7K6KWONQHP4HYYYHMR4YPDI3H3HB36CHRBIKH3H6VOI3KIS7W5EMIAABAAAQBAEFACAIMAEAAAAAAAAAAAAALAACACAIDAEAAYVLONF3GK4TTMFWC4PJ5AIBAABQAAQAAOQTPN5WGKYLOAEAAACYAAEAQCAYBAACU4YLUFYVQEBQDAMAQCIIAEPRHNZJIGPFN6AEEAU5CDB6AAMCC5ULOE4DXBIGX7LE3ANVJWCJAAAQAAMAQWAACAEAQGAIBEEAC2JSHAGH3K5IHP2I4HDLNULFR2E4EAVMRCBBNP4YWVWQTSB7RT7IAAEDAWAADAEAQGBABIA3WMQZC4T2RMC6ZEPP5ZNKMTP4JLD42EUQESFNU3ZE6XBO7H47OFPSHSSWYEB4EGRHQJHTH3DUE6CIUQVPAYYPKIKPJNB4DEW52A7H2AAAACAADAEASCABD4J3OKKBTZLPQBBAFHIQYPQADAQXNC3RHA5YKBV72ZGYDNKNQSIAAEAAEAEAACAQAAAAQCQAAF7YVGC2D6IIOTNGZZIG5OOL2ALDKSJNQ6QF4WEMYOP5M545JGY4OW4P6IPVYWJAGPMFEMPF3R4ODGDKIGY6TNPXCMHUX4J4Y6TGQEAAAAAAAAAAAAAAAAAIBIAKWARKE2LM3UEJGYMNU6DTS6KBJTNKUNHJVK3AIC243ML5Z6WLZPF3K6OF2NKJF2SNST4DK7ZG2XYORG5PF6GULRSFZQRXCG47OOGPVAAAAAAAAAAAAAAACAMBAAAJBAAWSMRYBR62XKB36SHBY23NCZMORHBAFLEIQILL7GFVNUE4QP4M72AABAFABKYCFITJNTOQRE3BRWTYOOLZIFGNVKRU5GVLMBALLTNRPXH2ZPF4XNLZYXJVJEXKJWKPQNL7E3K7B2E3V4XY2ROGIXGCG4I3T5ZYZ6UAAAAAAAAAAAAAAAIBQMAACAEAQWAABAEAQGAIBEEALXH4JMVTQID2LYZDNY3BE27ZGPCN3RF5B7BBRYHCBOA6XAK6MCPAAAIAQAAYDAFAELKAEKPNPXNQI6W6YSDGGZGXWUNYSTAHMSM6JVRCZOWLR4AATVNPYCLZDPEOQXITARNPEUEFDJ3J63DOWUMUEQ22II25H2OTZMS7VLYAACAIAAAAQCQAAF7YVGC2D6IIOTNGZZIG5OOL2ALDKSJNQ6QF4WEMYOP5M545JGY4OW4P6IPVYWJAGPMFEMPF3R4ODGDKIGY6TNPXCMHUX4J4Y6TGQEAAAAAAAAAAAAAAAAAIBIAKWARKE2LM3UEJGYMNU6DTS6KBJTNKUNHJVK3AIC243ML5Z6WLZPF3K6OF2NKJF2SNST4DK7ZG2XYORG5PF6GULRSFZQRXCG47OOGPVAAAAAAAAAAAAAAACAMBAAAJBAA253RUJNETZ3VLBDFSP6O3WXO2GIFWYC5R4RFOHVEID6ZKI2ZOCIAABAFABKYCFITJNTOQRE3BRWTYOOLZIFGNVKRU5GVLMBALLTNRPXH2ZPF4XNLZYXJVJEXKJWKPQNL7E3K7B2E3V4XY2ROGIXGCG4I3T5ZYZ6UAAAAAAAAAAAAAAAIBQMAACAEAQMAAEAFAELKAEKPNPXNQI6W6YSDGGZGXWUNYSTAHMSM6JVRCZOWLR4AATVNPYCLZDPEOQXITARNPEUEFDJ3J63DOWUMUEQ22II25H2OTZMS7VLYAAEAABAEAQAAIBAEFQAAIBAEBQAAABAIBQCAJBAA253RUJNETZ3VLBDFSP6O3WXO2GIFWYC5R4RFOHVEID6ZKI2ZOCIAACAMAAAAABAFAAAL7RKMFUH4QQ5G2NTSQN244XUAWGVES3B5ALZMIZQ472Z3Z2SNRY5NY74Q7LRMSAM6YKIY6LXDY4GMGUQNR5G27OEYPJPYTZR5GNAIAAAAAAAAAAAAAAAAAQCQAVMBCUJUWZXIISNQY3J4HHF4UCTG2VI2OTKVWAQFVZWYX3T5MXS6LWV44LU2USLVE3FHYGV7SNVPQ5CN26L4NIXDELTBDOENZ644M7KAAAAAAAAAAAAAAAEAYCAAASCAC23KGP4O2QVLBIVRGK3KNMAXLIWJNNACUZJTSDXUCUCGLJWAODNUAACAKACVQEKRGS3G5BCJWDDNHQ44XSQKM3KVDJ2NKWYCAWXG3C7OPVS6LZO2XTROTKSJOUTMU7A2X6JWV6DUJXLZPRVC4MROMENYRXH3TRT5IAAAAAAAAAAAAAAAQDAYAACAIGAACACQAVMBCUJUWZXIISNQY3J4HHF4UCTG2VI2OTKVWAQFVZWYX3T5MXS6LWV44LU2USLVE3FHYGV7SNVPQ5CN26L4NIXDELTBDOENZ644M7KAABAABACAIGAACACQAVMBCUJUWZXIISNQY3J4HHF4UCTG2VI2OTKVWAQFVZWYX3T5MXS6LWV44LU2USLVE3FHYGV7SNVPQ5CN26L4NIXDELTBDOENZ644M7KAABAABACAIGAACACQAVMBCUJUWZXIISNQY3J4HHF4UCTG2VI2OTKVWAQFVZWYX3T5MXS6LWV44LU2USLVE3FHYGV7SNVPQ5CN26L4NIXDELTBDOENZ644M7KAABAABACAIGAACACQAAF7YVGC2D6IIOTNGZZIG5OOL2ALDKSJNQ6QF4WEMYOP5M545JGY4OW4P6IPVYWJAGPMFEMPF3R4ODGDKIGY6TNPXCMHUX4J4Y6TGQEAABAAAAUAIBBQAQAAAAAAAAAAACBMAAWAIBAMAQCIIAGXO4NCLJE6O5KYIZMT7TW5V3WRSBNWAXMPEJLR5JCA7WKSGWLQSAAAQAAYFACAIMAEAAAAAAAAAAAAQLAAFACAIDAEASCABV3XDIS2JHTXKWCGLE745XNO5UMQLNQF3DZCK4PKIQH5SURVS4EQAAEAAGBIAQCDABAAAAAAAAAAAAECYABEAQCAYBAEQQANO5Y2EWSJ452VQRSZH7HN3LXNDEC3MBOY6ISXD2SEB7MVENMXBEAABAABQKAEAQOAYBFAFQAAIBAEBQCAAKJZQXILTUN5KGK6DUAECQWAACAEAQGAIAA5KGK6DUFYVSWAQBAAFACAIHAMBCYIALAABQCAIDAEAAOVDFPB2C4KZLAIAQACYAAQAQCAYBAAFE4YLUFZ2G6VDFPB2ACBYLAACQCAIDAEAAOVDFPB2C4KZLAIAQACQBAEDQGAZMEARAWAAGAEAQGAIAA5KGK6DUFYVSWAQBAAFQABYBAEBQCAAKJZQXILTUN5KGK6DUAEEQWAAIAEAQGAIAA5KGK6DUFYVSWAQBAAFACAIHAMBCEKIDAEAAOVDFPB2C4KZLAIAQAAAAAAAAAAIBIAAC74KTBNB7EEHJWTM4UDOXHF5AFRVJEWYPIC6LCGMHH6WO6OUTMOHLOH7EH24LEQDHWCSGHS5Y6HBTBVEDMPJWX3RGD2L6E6MPJTICAAAAAAAAAAAAAAAAAEAUAFLAIVCNFWN2CETMGG2PBZZPFAUZWVKGTU2VNQEBNONWF647LF4XS5VPHC5GVES5JGZJ6BVP4TNL4HITOXS7DKFYZC4YI3RDOPXHDH2QAAAAAAAAAAAAAABAGAQAAEQQBO47RFSWOBAPJPDENXDMETL7EZ4JXOEXUH4EGHA4IFYD24BLZQJ4AAAQCQAVMBCUJUWZXIISNQY3J4HHF4UCTG2VI2OTKVWAQFVZWYX3T5MXS6LWV44LU2USLVE3FHYGV7SNVPQ5CN26L4NIXDELTBDOENZ644M7KAAAAAAAAAAAAAAAEAYGAABQCAIBBMAACAIBAMAQABKOMF2C4KYCAIAAGAACAEAAAAIBIAAC74KTBNB7EEHJWTM4UDOXHF5AFRVJEWYPIC6LCGMHH6WO6OUTMOHLOH7EH24LEQDHWCSGHS5Y6HBTBVEDMPJWX3RGD2L6E6MPJTICAAAAAAAAAAAAAAAAAEAUAFLAIVCNFWN2CETMGG2PBZZPFAUZWVKGTU2VNQEBNONWF647LF4XS5VPHC5GVES5JGZJ6BVP4TNL4HITOXS7DKFYZC4YI3RDOPXHDH2QAAAAAAAAAAAAAABAGAQAAEQQBWHXBTHR3TXMVOOTYQWWGSR6Y67C32OTEZFQ3UJGV5FHDABEDWXFAAAQCQAVMBCUJUWZXIISNQY3J4HHF4UCTG2VI2OTKVWAQFVZWYX3T5MXS6LWV44LU2USLVE3FHYGV7SNVPQ5CN26L4NIXDELTBDOENZ644M7KAAAAAAAAAAAAAAAEAYGAABACAIDAAAQCAAAAEAUAABP6FJQWQ7SCDU3JWOKBXLTS6QCY2USLMHUBPFRDGDT7LHPHKJWHDVXD7SD5OFSIBT3BJDDZO4PDQZQ2SBWHU3L5YTB5F7CPGHUZUBAAAAAAAAAAAAAAAAACAKACVQEKRGS3G5BCJWDDNHQ44XSQKM3KVDJ2NKWYCAWXG3C7OPVS6LZO2XTROTKSJOUTMU7A2X6JWV6DUJXLZPRVC4MROMENYRXH3TRT5IAAAAAAAAAAAAAAAQDAIAACIIA56Y5WAMUIZRITDKODUPJXHBCZSTKHCBX3KEPA7VOBOBEFIG6PEJQAAIBIAKWARKE2LM3UEJGYMNU6DTS6KBJTNKUNHJVK3AIC243ML5Z6WLZPF3K6OF2NKJF2SNST4DK7ZG2XYORG5PF6GULRSFZQRXCG47OOGPVAAAAAAAAAAAAAAACAMDAAAQBAEFACAIMAEAAAAAAAAAAAAALAAAQCAIDAEASCABD4J3OKKBTZLPQBBAFHIQYPQADAQXNC3RHA5YKBV72ZGYDNKNQSIAAEAACAMBQCQCFVACFHWX3WYEPLPMJBTDMTL3KG4JJQDWJGPE2YRMXLFY6AAJ2WX4BF4RXSHILUJQIWXSKCCRU5U7NRXLKGKCINNEENOT5HJ4WJP2V4AAAAEAAAAIBIAAC74KTBNB7EEHJWTM4UDOXHF5AFRVJEWYPIC6LCGMHH6WO6OUTMOHLOH7EH24LEQDHWCSGHS5Y6HBTBVEDMPJWX3RGD2L6E6MPJTICAAAAAAAAAAAAAAAAAEAUAFLAIVCNFWN2CETMGG2PBZZPFAUZWVKGTU2VNQEBNONWF647LF4XS5VPHC5GVES5JGZJ6BVP4TNL4HITOXS7DKFYZC4YI3RDOPXHDH2QAAAAAAAAAAAAAABAGBIBAFABKYCFITJNTOQRE3BRWTYOOLZIFGNVKRU5GVLMBALLTNRPXH2ZPF4XNLZYXJVJEXKJWKPQNL7E3K7B2E3V4XY2ROGIXGCG4I3T5ZYZ6UAAAAAAAAAAAAAAAIAACIIALLNIZ7R3KCVMFCWEZLNJVQC5NCZFVUAKTFGOIO6QKQIZNGYBYNWQAAAAAAAAAAAAAAAACAKACVQEKRGS3G5BCJWDDNHQ44XSQKM3KVDJ2NKWYCAWXG3C7OPVS6LZO2XTROTKSJOUTMU7A2X6JWV6DUJXLZPRVC4MROMENYRXH3TRT5IAAAAAAAAAAAAAAAQBAFABKYCFITJNTOQRE3BRWTYOOLZIFGNVKRU5GVLMBALLTNRPXH2ZPF4XNLZYXJVJEXKJWKPQNL7E3K7B2E3V4XY2ROGIXGCG4I3T5ZYZ6UAAAAAAAAAAAAAAAIAQCQCFVACFHWX3WYEPLPMJBTDMTL3KG4JJQDWJGPE2YRMXLFY6AAJ2WX4BF4RXSHILUJQIWXSKCCRU5U7NRXLKGKCINNEENOT5HJ4WJP2V4AAAAAAAAAAAAAAQCAABEEALXH4JMVTQID2LYZDNY3BE27ZGPCN3RF5B7BBRYHCBOA6XAK6MCPAAAAAAAAAAAAAAAAQDBABQAAJBAADU6TFYWJ4TBQED3BGKQSYKXEB5XPEZRSJSDOWMTRNRPAEYQSA3EAIAAAAAAAAAAAAACAAABBVHK3LQINXW45AAAAAAAAAAAAAACAQLAAASCABNEZDQDD5VOUDX5EODRVW2FSY5COCAKWIRAQWX6MLK3IJZA7YZ7UAAAAAAAAAAAAAAAEBQQAYBAADUE33PNRSWC3QAAAAAAAAAAAAQAAYIAABQQAADAEEAGCADAMEAIAYIAABQQBIDBADAGCAAAMEAOAYIBAAQCQBXUUCXAJCWUDKCCPAAZUOSPHG5OAQWM7RAIACNQG5HLXLG25SJ6V4VM43AO7YPRRQOZDZQ6GRWPWODX4EPCCQUPWP5K4RWURF7N2IYQAAAAAAAAAAAAAAAEAYIAABQCCADBABQGCAEAMEAAAYIAUBQQBQDBAAAGCAHAMEAQAYIAMBQCCIDBAAAGCADAMEAIAYIAABQQBIDBADAGCAAAMEAOAYIBABQQAADAEFQGCABAMEAEAYIAABQQAYDBACAGCAAAMEAKAYIAYBQQAADBADQGCAIAEAUAABP6FJQWQ7SCDU3JWOKBXLTS6QCY2USLMHUBPFRDGDT7LHPHKJWHDVXD7SD5OFSIBT3BJDDZO4PDQZQ2SBWHU3L5YTB5F7CPGHUZUBAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAMAAAAAAAAAAAAABEEAO7MO3AGKEMYUJRVHB2HU3TQRMZJVDRA35VCHQP2XAXASCUDPHSEYAAAAAAAAAAAAACAQAAAAAAAAAAAEAAAAAAAAAAAAAAEQQAI7CO3SSQM6K34AIIBJ2EGD4AAYEF3IW4JYHOCQNP6WJWA3KTMESAAAAAAAAAAAAAAYAAEAUAFLAIVCNFWN2CETMGG2PBZZPFAUZWVKGTU2VNQEBNONWF647LF4XS5VPHC5GVES5JGZJ6BVP4TNL4HITOXS7DKFYZC4YI3RDOPXHDH2QAAAAAAAAAAAAAABACAKAIWUAIU627O3AR5N5REGMNSNPNI3RFGAOZEZ4TLCFS5MXDYABHK27QEXSG6I5BORGBC26JIIKGTWT5WG5NIZIJBVUQRV2PU5HSZF7KXQAAAAAAAAAAAAACAIAAEQQBO47RFSWOBAPJPDENXDMETL7EZ4JXOEXUH4EGHA4IFYD24BLZQJ4AAAAAAAAAAAAAAACAMEAEAABEEAAOT2MXCZHSMGAQPMEZKCLBK4QHW54TGGJGIN2ZSOFWF4ATCCIDMQBAAAAAAAAAAAAAAIAAAEGU5LNOBBW63TUAAAAAAAAAAAAAAICBMAACIIAFUTEOAMPWV2QO7URYOGW3IWLDUJYIBKZCECC27ZRNLNBHED7DH6QAAAAAAAAAAAAAAAQGCACAEAAOQTPN5WGKYLOAAAAAAAAAAAACAADBAAAGCAAAMAQSAYIAMBQQAADBAAQGCAAAMEAKAYIAABQQBADBAAAGCAGAEAUAN5FAVYCIVVA2QQTYAGNDUTZZXLQEFTH4ICAATMBXJ252ZWXMSPVPFLHGYDX6D4MMDWI6MHRUNT5TQ57BDYQUFD5T7KXENVEJP3OSGEAAAAAAAAAAAAAAABAGCAAAMAQSAYIAMBQQAADBAAQGCAAAMEAKAYIAABQQBADBAAAGCAGAMEAEAYBBIBQQAADBABQGCAAAMEACAYIAABQQBIDBAAAGCAEAMEAAAYIAYBQQAADAEFQGCACAMEAAAYIAMBQQAADBAAQGCAAAMEAKAYIAABQQBADBAAAGCAGAEAUAABP6FJQWQ7SCDU3JWOKBXLTS6QCY2USLMHUBPFRDGDT7LHPHKJWHDVXD7SD5OFSIBT3BJDDZO4PDQZQ2SBWHU3L5YTB5F7CPGHUZUBAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAMAAAAAAAAAAAAABEEAO7MO3AGKEMYUJRVHB2HU3TQRMZJVDRA35VCHQP2XAXASCUDPHSEYAAAAAAAAAAAAACAQAAAAAAAAAAAEAAAAAAAAAAAAAAEQQAI7CO3SSQM6K34AIIBJ2EGD4AAYEF3IW4JYHOCQNP6WJWA3KTMESAAAAAAAAAAAAAAYAAEAUAFLAIVCNFWN2CETMGG2PBZZPFAUZWVKGTU2VNQEBNONWF647LF4XS5VPHC5GVES5JGZJ6BVP4TNL4HITOXS7DKFYZC4YI3RDOPXHDH2QAAAAAAAAAAAAAABACAKAIWUAIU627O3AR5N5REGMNSNPNI3RFGAOZEZ4TLCFS5MXDYABHK27QEXSG6I5BORGBC26JIIKGTWT5WG5NIZIJBVUQRV2PU5HSZF7KXQAAAAAAAAAAAAAAAIDBAWQCAKAAAX7CUYLIPZBB2NU3HFA3VZZPIBMNKJFWD2AXSYRTBZ7VTXTVE3DR23R7ZB6XCZEAZ5QURR4XOHRYMYNJA3D2NV64JQ6S7RHTD2M2AQAAAAAAAAAAAAAAAABAFAAAL7RKMFUH4QQ5G2NTSQN244XUAWGVES3B5ALZMIZQ472Z3Z2SNRY5NY74Q7LRMSAM6YKIY6LXDY4GMGUQNR5G27OEYPJPYTZR5GNAIAAAAAAAAAAAAAAAAAQCQAAF7YVGC2D6IIOTNGZZIG5OOL2ALDKSJNQ6QF4WEMYOP5M545JGY4OW4P6IPVYWJAGPMFEMPF3R4ODGDKIGY6TNPXCMHUX4J4Y6TGQEAAAAAAAAAAAAAAAA=== \ No newline at end of file diff --git a/unison-src/transcripts-using-base/serialized-cases/case-04.v5.hash b/unison-src/transcripts-using-base/serialized-cases/case-04.v5.hash new file mode 100644 index 0000000000..acb9258d45 --- /dev/null +++ b/unison-src/transcripts-using-base/serialized-cases/case-04.v5.hash @@ -0,0 +1 @@ +EXAQLMU6IKGAY7DNOHND5VUQQAQPIJN3IVCF5DISOOEVLRQZ3Q2CZOYEVDMY7MYQX2CG6CJFH2HQD6XOMKHQNK5JUZB3G7RZQNREQRQ= \ No newline at end of file diff --git a/unison-src/transcripts-using-base/serialized-cases/case-04.v5.ser b/unison-src/transcripts-using-base/serialized-cases/case-04.v5.ser new file mode 100644 index 0000000000..bcced67760 --- /dev/null +++ b/unison-src/transcripts-using-base/serialized-cases/case-04.v5.ser @@ -0,0 +1 @@ +AAAAABIBAFABKYCFITJNTOQRE3BRWTYOOLZIFGNVKRU5GVLMBALLTNRPXH2ZPF4XNLZYXJVJEXKJWKPQNL7E3K7B2E3V4XY2ROGIXGCG4I3T5ZYZ6UAAAAAAAAAAAAAAAIBQCBIBAFABKYCFITJNTOQRE3BRWTYOOLZIFGNVKRU5GVLMBALLTNRPXH2ZPF4XNLZYXJVJEXKJWKPQNL7E3K7B2E3V4XY2ROGIXGCG4I3T5ZYZ6UAAAAAAAAAAAAAAAIBQEAABEEADVNOCW62AVOZXJ6CMCXMWMTBLF4FFUTLGYPNRXF3BZCNXIDIOZNIAAEAUAFLAIVCNFWN2CETMGG2PBZZPFAUZWVKGTU2VNQEBNONWF647LF4XS5VPHC5GVES5JGZJ6BVP4TNL4HITOXS7DKFYZC4YI3RDOPXHDH2QAAAAAAAAAAAAAABAGBQAAEAQMAAGAABU4YLUAEAAAAAAAAAAAAAHAMCG623BPEAQWAACAEAQGAIBEEAG57PICSIFU224UOLFTG2BAWCL4E7NVW2SJJUAWDIJO7R3YJCNHYQAAAFACAIMAEAAAAAAAAAAAAILAAAQCAIDAEAAQTTBOQXGI4TPOABAEAADAEASCAB2WXBLPNAKXM3U7BGBLWLGJQVS6CS2JVTMHWY3S5Q4RG3UBUHMWUAQCAAAAEAUAABP6FJQWQ7SCDU3JWOKBXLTS6QCY2USLMHUBPFRDGDT7LHPHKJWHDVXD7SD5OFSIBT3BJDDZO4PDQZQ2SBWHU3L5YTB5F7CPGHUZUBAAAAAAAAAAAAAAAAACAKACVQEKRGS3G5BCJWDDNHQ44XSQKM3KVDJ2NKWYCAWXG3C7OPVS6LZO2XTROTKSJOUTMU7A2X6JWV6DUJXLZPRVC4MROMENYRXH3TRT5IAAAAAAAAAAAAAAAQDAIAACIIAHK24FN5UBK5TOT4EYFOZMZGCWLYKLJGWNQ63DOLWDSE3OQGQ5S2QCAIBIAKWARKE2LM3UEJGYMNU6DTS6KBJTNKUNHJVK3AIC243ML5Z6WLZPF3K6OF2NKJF2SNST4DK7ZG2XYORG5PF6GULRSFZQRXCG47OOGPVAAAAAAAAAAAAAAACAMDAAAIBAMAQCIIAHK24FN5UBK5TOT4EYFOZMZGCWLYKLJGWNQ63DOLWDSE3OQGQ5S2QAAIAAAAQCQAAF7YVGC2D6IIOTNGZZIG5OOL2ALDKSJNQ6QF4WEMYOP5M545JGY4OW4P6IPVYWJAGPMFEMPF3R4ODGDKIGY6TNPXCMHUX4J4Y6TGQEAAAAAAAAAAAAAAAAAIBIAKWARKE2LM3UEJGYMNU6DTS6KBJTNKUNHJVK3AIC243ML5Z6WLZPF3K6OF2NKJF2SNST4DK7ZG2XYORG5PF6GULRSFZQRXCG47OOGPVAAAAAAAAAAAAAAACAMBAAAJBABXP32AUSBNGWXFDSZMZWQIFQS7BH3NNWUSKNAFQ2CLX4O6CITJ6EAABAFABKYCFITJNTOQRE3BRWTYOOLZIFGNVKRU5GVLMBALLTNRPXH2ZPF4XNLZYXJVJEXKJWKPQNL7E3K7B2E3V4XY2ROGIXGCG4I3T5ZYZ6UAAAAAAAAAAAAAAAIBQMAAABMAACAIBAMAQCIIA74Z3E7TZQYDVD277KYVK5NAJDGFSKNDJXTUKC63K45WJSDPTGK4QAAALAABACAIDAEABGSKPFZXXAZLOIZUWYZJONFWXA3BOOYZQAAYBAEQQB3YGQKCYHD3UZXVHZGINUEURDHPZAHALBT23ILWELMAMPRQ2D7NPAABACAAAAEAUAABP6FJQWQ7SCDU3JWOKBXLTS6QCY2USLMHUBPFRDGDT7LHPHKJWHDVXD7SD5OFSIBT3BJDDZO4PDQZQ2SBWHU3L5YTB5F7CPGHUZUBAAAAAAAAAAAAAAAAACAKACVQEKRGS3G5BCJWDDNHQ44XSQKM3KVDJ2NKWYCAWXG3C7OPVS6LZO2XTROTKSJOUTMU7A2X6JWV6DUJXLZPRVC4MROMENYRXH3TRT5IAAAAAAAAAAAAAAAQDAIAACIIA54DIFBMDR52M32T4TEG2CKIRTX4QDQFQZ5NUF3CFWAGHYYNB7WXQAAIBIAKWARKE2LM3UEJGYMNU6DTS6KBJTNKUNHJVK3AIC243ML5Z6WLZPF3K6OF2NKJF2SNST4DK7ZG2XYORG5PF6GULRSFZQRXCG47OOGPVAAAAAAAAAAAAAAACAMDAABABAEAQCCYAAEAQCAYAAIBACAADAACACAAAAEAUAABP6FJQWQ7SCDU3JWOKBXLTS6QCY2USLMHUBPFRDGDT7LHPHKJWHDVXD7SD5OFSIBT3BJDDZO4PDQZQ2SBWHU3L5YTB5F7CPGHUZUBAAAAAAAAAAAAAAAAACAKACVQEKRGS3G5BCJWDDNHQ44XSQKM3KVDJ2NKWYCAWXG3C7OPVS6LZO2XTROTKSJOUTMU7A2X6JWV6DUJXLZPRVC4MROMENYRXH3TRT5IAAAAAAAAAAAAAAAQDAIAACIIA74Z3E7TZQYDVD277KYVK5NAJDGFSKNDJXTUKC63K45WJSDPTGK4QAAIBIAKWARKE2LM3UEJGYMNU6DTS6KBJTNKUNHJVK3AIC243ML5Z6WLZPF3K6OF2NKJF2SNST4DK7ZG2XYORG5PF6GULRSFZQRXCG47OOGPVAAAAAAAAAAAAAAACAMDAAAIBAYAAIAKAAYHWPACBPYWKJKM2NKSLWVRBTSNVST2AI6PHPF4OJ5445524FEGZP6XTZUG4DBW2Y2I4CYBXK5ONOIRUUGROEFVJFPSLQVSNSU5EE7IAAIAACAIBAAAQCAIDAQAUAJOA7BYABDTZGHSVVPMSW7MJOX2SYXXFOHDKQRESSFMT3HFUDFIO5UOEVZ4JCZAQQL53EGN2XPGLX432KM4VDDP52DPQXQ7AQNTICXPAAAABAAAAAAIBIAAC74KTBNB7EEHJWTM4UDOXHF5AFRVJEWYPIC6LCGMHH6WO6OUTMOHLOH7EH24LEQDHWCSGHS5Y6HBTBVEDMPJWX3RGD2L6E6MPJTICAAAAAAAAAAAAAAAAAEAUAFLAIVCNFWN2CETMGG2PBZZPFAUZWVKGTU2VNQEBNONWF647LF4XS5VPHC5GVES5JGZJ6BVP4TNL4HITOXS7DKFYZC4YI3RDOPXHDH2QAAAAAAAAAAAAAABAGBIBAFABKYCFITJNTOQRE3BRWTYOOLZIFGNVKRU5GVLMBALLTNRPXH2ZPF4XNLZYXJVJEXKJWKPQNL7E3K7B2E3V4XY2ROGIXGCG4I3T5ZYZ6UAAAAAAAAAAAAAAAIAACIIAHK24FN5UBK5TOT4EYFOZMZGCWLYKLJGWNQ63DOLWDSE3OQGQ5S2QCAAAAAAAAAAAAAAACAKACVQEKRGS3G5BCJWDDNHQ44XSQKM3KVDJ2NKWYCAWXG3C7OPVS6LZO2XTROTKSJOUTMU7A2X6JWV6DUJXLZPRVC4MROMENYRXH3TRT5IAAAAAAAAAAAAAAAQDBACQCAKAAAX7CUYLIPZBB2NU3HFA3VZZPIBMNKJFWD2AXSYRTBZ7VTXTVE3DR23R7ZB6XCZEAZ5QURR4XOHRYMYNJA3D2NV64JQ6S7RHTD2M2AQAAAAAAAAAAAAAAAABAFAAAL7RKMFUH4QQ5G2NTSQN244XUAWGVES3B5ALZMIZQ472Z3Z2SNRY5NY74Q7LRMSAM6YKIY6LXDY4GMGUQNR5G27OEYPJPYTZR5GNAIAAAAAAAAAAAAAAAA====== \ No newline at end of file From 4b45eead2135511b9e17f6cc95f06a9a39fbc30c Mon Sep 17 00:00:00 2001 From: dolio Date: Fri, 4 Oct 2024 20:37:19 +0000 Subject: [PATCH 36/40] automatically run ormolu --- unison-runtime/src/Unison/Runtime/Machine.hs | 80 ++++++++++++-------- 1 file changed, 47 insertions(+), 33 deletions(-) diff --git a/unison-runtime/src/Unison/Runtime/Machine.hs b/unison-runtime/src/Unison/Runtime/Machine.hs index e3b56a535a..94df3f7c40 100644 --- a/unison-runtime/src/Unison/Runtime/Machine.hs +++ b/unison-runtime/src/Unison/Runtime/Machine.hs @@ -36,9 +36,9 @@ import Unison.Reference import Unison.Referent (Referent, pattern Con, pattern Ref) import Unison.Runtime.ANF as ANF ( Cacheability (..), + Code (..), CompileExn (..), Mem (..), - Code (..), SuperGroup, codeGroup, foldGroup, @@ -394,9 +394,11 @@ exec !env !denv !_activeThreads !ustk !bstk !k _ (BPrim1 LKUP i) Just sg -> do poke ustk 1 bstk <- bump bstk - let ch | Just n <- M.lookup link rfn - , EC.member n cach = Cacheable - | otherwise = Uncacheable + let ch + | Just n <- M.lookup link rfn, + EC.member n cach = + Cacheable + | otherwise = Uncacheable bstk <$ pokeBi bstk (CodeRep sg ch) pure (denv, ustk, bstk, k) exec !_ !denv !_activeThreads !ustk !bstk !k _ (BPrim1 TLTT i) = do @@ -686,9 +688,15 @@ eval !env !denv !activeThreads !ustk !bstk !k _ (Jump i args) = eval !env !denv !activeThreads !ustk !bstk !k r (Let nw cix uf bf sect) = do (ustk, ufsz, uasz) <- saveFrame ustk (bstk, bfsz, basz) <- saveFrame bstk - eval env denv activeThreads ustk bstk + eval + env + denv + activeThreads + ustk + bstk (Push ufsz bfsz uasz basz cix uf bf sect k) - r nw + r + nw eval !env !denv !activeThreads !ustk !bstk !k r (Ins i nx) = do (denv, ustk, bstk, k) <- exec env denv activeThreads ustk bstk k r i eval env denv activeThreads ustk bstk k r nx @@ -1952,8 +1960,12 @@ splitCont !denv !ustk !bstk !k !p = denv' = cs <> EC.withoutKeys denv ps cs' = EC.restrictKeys denv ps walk !denv !usz !bsz !ck (Push un bn ua ba br up bp brSect k) = - walk denv (usz + un + ua) (bsz + bn + ba) - (Push un bn ua ba br up bp brSect ck) k + walk + denv + (usz + un + ua) + (bsz + bn + ba) + (Push un bn ua ba br up bp brSect ck) + k finish !denv !usz !bsz !ua !ba !ck !k = do (useg, ustk) <- grab ustk usz @@ -2364,15 +2376,16 @@ reifyValue0 (combs, rty, rtm) = goV let cix = (CIx r n i) in (cix, rCombSection combs cix) - goV (ANF.Partial gr ua ba) = goIx gr >>= \case - (cix, RComb (Comb rcomb)) -> pap cix rcomb <$> traverse goV ba - where - pap cix i = PApV cix i (fromIntegral <$> ua) - (_, RComb (CachedClosure _ clo)) - | [] <- ua, [] <- ba -> pure clo - | otherwise -> die . err $ msg - where - msg = "reifyValue0: non-trivial partial application to cached value" + goV (ANF.Partial gr ua ba) = + goIx gr >>= \case + (cix, RComb (Comb rcomb)) -> pap cix rcomb <$> traverse goV ba + where + pap cix i = PApV cix i (fromIntegral <$> ua) + (_, RComb (CachedClosure _ clo)) + | [] <- ua, [] <- ba -> pure clo + | otherwise -> die . err $ msg + where + msg = "reifyValue0: non-trivial partial application to cached value" goV (ANF.Data r t0 us bs) = do t <- flip packTags (fromIntegral t0) . fromIntegral <$> refTy r DataC r t (fromIntegral <$> us) <$> traverse goV bs @@ -2394,22 +2407,23 @@ reifyValue0 (combs, rty, rtm) = goV where mrk ps de k = Mark (fromIntegral ua) (fromIntegral ba) (setFromList ps) (mapFromList de) k - goK (ANF.Push uf bf ua ba gr k) = goIx gr >>= \case - (cix, RComb (Lam _ _ un bx sect)) -> - Push - (fromIntegral uf) - (fromIntegral bf) - (fromIntegral ua) - (fromIntegral ba) - cix - un - bx - sect - <$> goK k - (CIx r _ _ , _) -> - die . err $ - "tried to reify a continuation with a cached value resumption" - ++ show r + goK (ANF.Push uf bf ua ba gr k) = + goIx gr >>= \case + (cix, RComb (Lam _ _ un bx sect)) -> + Push + (fromIntegral uf) + (fromIntegral bf) + (fromIntegral ua) + (fromIntegral ba) + cix + un + bx + sect + <$> goK k + (CIx r _ _, _) -> + die . err $ + "tried to reify a continuation with a cached value resumption" + ++ show r goL (ANF.Text t) = pure . Foreign $ Wrap Rf.textRef t goL (ANF.List l) = Foreign . Wrap Rf.listRef <$> traverse goV l From 545f5eaeb11c8e310cd64aeed31fa344915f7593 Mon Sep 17 00:00:00 2001 From: Dan Doel Date: Fri, 4 Oct 2024 16:50:43 -0400 Subject: [PATCH 37/40] Fix MCode tests --- unison-runtime/tests/Unison/Test/Runtime/MCode.hs | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/unison-runtime/tests/Unison/Test/Runtime/MCode.hs b/unison-runtime/tests/Unison/Test/Runtime/MCode.hs index e277e60a02..e5676444cd 100644 --- a/unison-runtime/tests/Unison/Test/Runtime/MCode.hs +++ b/unison-runtime/tests/Unison/Test/Runtime/MCode.hs @@ -10,7 +10,9 @@ import Data.Map.Strict qualified as Map import EasyTest import Unison.Reference (Reference, Reference' (Builtin)) import Unison.Runtime.ANF - ( SuperGroup (..), + ( Cacheability (..), + Code (..), + SuperGroup (..), lamLift, superNormalize, ) @@ -45,11 +47,12 @@ testEval0 :: [(Reference, SuperGroup Symbol)] -> SuperGroup Symbol -> Test () testEval0 env main = ok << io do cc <- baseCCache False - _ <- cacheAdd ((mainRef, main) : env) cc + _ <- cacheAdd ((fmap . fmap) uncacheable $ (mainRef, main) : env) cc rtm <- readTVarIO (refTm cc) apply0 Nothing cc Nothing (rtm Map.! mainRef) where (<<) = flip (>>) + uncacheable sg = CodeRep sg Uncacheable asrt :: Section asrt = From d8d2f69807370529197716abe7c3297968e148cf Mon Sep 17 00:00:00 2001 From: Dan Doel Date: Mon, 7 Oct 2024 21:48:40 -0400 Subject: [PATCH 38/40] Fix a guard in unison-runtime It was meant to be a test in a `match` expression, but was missing a #:when --- scheme-libs/racket/unison-runtime.rkt | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/scheme-libs/racket/unison-runtime.rkt b/scheme-libs/racket/unison-runtime.rkt index da1ddb5ed0..ad8afbe06a 100644 --- a/scheme-libs/racket/unison-runtime.rkt +++ b/scheme-libs/racket/unison-runtime.rkt @@ -68,12 +68,12 @@ (let ([bs (grab-bytes port)]) (match (builtin-Value.deserialize (bytes->chunked-bytes bs)) [(unison-data _ t (list q)) - (= t ref-either-right:tag) + #:when (= t ref-either-right:tag) (apply values (unison-tuple->list (reify-value (unison-quote-val q))))] - [else - (raise "unexpected input")]))) + [val + (raise (format "unexpected input: ~a " (describe-value val)))]))) (define (natural->bytes/variable n) (let rec ([i n] [acc '()]) From 1660ea4b1505d5dc8be7ae6d43e7ea0cbcd31a51 Mon Sep 17 00:00:00 2001 From: Dan Doel Date: Mon, 7 Oct 2024 22:17:42 -0400 Subject: [PATCH 39/40] Bump @unison/internal version to fix jit compatibility for serialization --- .github/workflows/ci.yaml | 2 +- unison-src/transcripts-manual/gen-racket-libs.md | 2 +- unison-src/transcripts-manual/gen-racket-libs.output.md | 8 ++++---- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 1d826551e8..f8326ce9b1 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -14,7 +14,7 @@ on: env: ## Some version numbers that are used during CI ormolu_version: 0.7.2.0 - jit_version: "@unison/internal/releases/0.0.20" + jit_version: "@unison/internal/releases/0.0.21" runtime_tests_version: "@unison/runtime-tests/main" ## Some cached directories diff --git a/unison-src/transcripts-manual/gen-racket-libs.md b/unison-src/transcripts-manual/gen-racket-libs.md index d1e3818a26..b3137a636d 100644 --- a/unison-src/transcripts-manual/gen-racket-libs.md +++ b/unison-src/transcripts-manual/gen-racket-libs.md @@ -4,7 +4,7 @@ When we start out, `./scheme-libs/racket` contains a bunch of library files that Next, we'll download the jit project and generate a few Racket files from it. ```ucm -jit-setup/main> lib.install @unison/internal/releases/0.0.20 +jit-setup/main> lib.install @unison/internal/releases/0.0.21 ``` ```unison diff --git a/unison-src/transcripts-manual/gen-racket-libs.output.md b/unison-src/transcripts-manual/gen-racket-libs.output.md index 3def8b4636..9586cc8d72 100644 --- a/unison-src/transcripts-manual/gen-racket-libs.output.md +++ b/unison-src/transcripts-manual/gen-racket-libs.output.md @@ -3,12 +3,12 @@ When we start out, `./scheme-libs/racket` contains a bunch of library files that Next, we'll download the jit project and generate a few Racket files from it. ``` ucm -jit-setup/main> lib.install @unison/internal/releases/0.0.20 +jit-setup/main> lib.install @unison/internal/releases/0.0.21 - Downloaded 14935 entities. + Downloaded 14985 entities. - I installed @unison/internal/releases/0.0.20 as - unison_internal_0_0_20. + I installed @unison/internal/releases/0.0.21 as + unison_internal_0_0_21. ``` ``` unison From b3d9d63f36d1ba3479aea6264b8fd0756f6a1e60 Mon Sep 17 00:00:00 2001 From: Dan Doel Date: Mon, 7 Oct 2024 22:28:48 -0400 Subject: [PATCH 40/40] Bump runtime-tests version for new serialization format --- .github/workflows/ci-test-jit.yaml | 2 +- .github/workflows/ci.yaml | 2 +- unison-src/builtin-tests/interpreter-tests.sh | 2 +- unison-src/builtin-tests/jit-tests.sh | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/ci-test-jit.yaml b/.github/workflows/ci-test-jit.yaml index 1d062a5ca2..0ab3c291d6 100644 --- a/.github/workflows/ci-test-jit.yaml +++ b/.github/workflows/ci-test-jit.yaml @@ -4,7 +4,7 @@ on: workflow_call: env: - runtime_tests_version: "@unison/runtime-tests/releases/0.0.1" + runtime_tests_version: "@unison/runtime-tests/releases/0.0.2" # for best results, this should match the path in ci.yaml too; but GH doesn't make it easy to share them. runtime_tests_codebase: "~/.cache/unisonlanguage/runtime-tests.unison" diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 51059d3778..23e9b8aeaa 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -15,7 +15,7 @@ env: ## Some version numbers that are used during CI ormolu_version: 0.7.2.0 jit_version: "@unison/internal/releases/0.0.21" - runtime_tests_version: "@unison/runtime-tests/releases/0.0.1" + runtime_tests_version: "@unison/runtime-tests/releases/0.0.2" ## Some cached directories # a temp path for caching a built `ucm` diff --git a/unison-src/builtin-tests/interpreter-tests.sh b/unison-src/builtin-tests/interpreter-tests.sh index e1f3e5c05e..94c0aeea4b 100755 --- a/unison-src/builtin-tests/interpreter-tests.sh +++ b/unison-src/builtin-tests/interpreter-tests.sh @@ -4,7 +4,7 @@ set -ex ucm=$(stack exec -- which unison) echo "$ucm" -runtime_tests_version="@unison/runtime-tests/releases/0.0.1" +runtime_tests_version="@unison/runtime-tests/releases/0.0.2" echo $runtime_tests_version codebase=${XDG_CACHE_HOME:-"$HOME/.cache"}/unisonlanguage/runtime-tests.unison diff --git a/unison-src/builtin-tests/jit-tests.sh b/unison-src/builtin-tests/jit-tests.sh index 1cba258c06..bd3464b4ab 100755 --- a/unison-src/builtin-tests/jit-tests.sh +++ b/unison-src/builtin-tests/jit-tests.sh @@ -8,7 +8,7 @@ if [ -z "$1" ]; then exit 1 fi -runtime_tests_version="@unison/runtime-tests/releases/0.0.1" +runtime_tests_version="@unison/runtime-tests/releases/0.0.2" echo $runtime_tests_version codebase=${XDG_CACHE_HOME:-"$HOME/.cache"}/unisonlanguage/runtime-tests.unison