diff options
author | Sven Tennie <sven.tennie@gmail.com> | 2020-10-31 13:28:54 -0400 |
---|---|---|
committer | Marge Bot <ben+marge-bot@smart-cactus.org> | 2021-09-23 15:59:38 -0400 |
commit | 6f7f59901c047882ba8c9ae8812264f86b12483a (patch) | |
tree | dbff896e8fb871d947b20c3b58736b82469be89a /compiler/GHC | |
parent | 022d9717d06542c2345e27ef018390a9d034a1f1 (diff) | |
download | haskell-6f7f59901c047882ba8c9ae8812264f86b12483a.tar.gz |
Introduce stack snapshotting / cloning (#18741)
Add `StackSnapshot#` primitive type that represents a cloned stack (StgStack).
The cloning interface consists of two functions, that clone either the treads
own stack (cloneMyStack) or another threads stack (cloneThreadStack).
The stack snapshot is offline/cold, i.e. it isn't evaluated any further. This is
useful for analyses as it prevents concurrent modifications.
For technical details, please see Note [Stack Cloning].
Co-authored-by: Ben Gamari <bgamari.foss@gmail.com>
Co-authored-by: Matthew Pickering <matthewtpickering@gmail.com>
Diffstat (limited to 'compiler/GHC')
-rw-r--r-- | compiler/GHC/Builtin/Names.hs | 3 | ||||
-rw-r--r-- | compiler/GHC/Builtin/Types/Prim.hs | 20 | ||||
-rw-r--r-- | compiler/GHC/Builtin/primops.txt.pp | 33 | ||||
-rw-r--r-- | compiler/GHC/StgToCmm/Prim.hs | 1 |
4 files changed, 46 insertions, 11 deletions
diff --git a/compiler/GHC/Builtin/Names.hs b/compiler/GHC/Builtin/Names.hs index d5da296cb6..b7f54060b9 100644 --- a/compiler/GHC/Builtin/Names.hs +++ b/compiler/GHC/Builtin/Names.hs @@ -1885,7 +1885,7 @@ statePrimTyConKey, stableNamePrimTyConKey, stableNameTyConKey, typeConKey, threadIdPrimTyConKey, bcoPrimTyConKey, ptrTyConKey, funPtrTyConKey, tVarPrimTyConKey, eqPrimTyConKey, eqReprPrimTyConKey, eqPhantPrimTyConKey, - compactPrimTyConKey :: Unique + compactPrimTyConKey, stackSnapshotPrimTyConKey :: Unique statePrimTyConKey = mkPreludeTyConUnique 50 stableNamePrimTyConKey = mkPreludeTyConUnique 51 stableNameTyConKey = mkPreludeTyConUnique 52 @@ -1913,6 +1913,7 @@ ptrTyConKey = mkPreludeTyConUnique 77 funPtrTyConKey = mkPreludeTyConUnique 78 tVarPrimTyConKey = mkPreludeTyConUnique 79 compactPrimTyConKey = mkPreludeTyConUnique 80 +stackSnapshotPrimTyConKey = mkPreludeTyConUnique 81 eitherTyConKey :: Unique eitherTyConKey = mkPreludeTyConUnique 84 diff --git a/compiler/GHC/Builtin/Types/Prim.hs b/compiler/GHC/Builtin/Types/Prim.hs index ce4f1e5dc0..9ba6d87927 100644 --- a/compiler/GHC/Builtin/Types/Prim.hs +++ b/compiler/GHC/Builtin/Types/Prim.hs @@ -83,6 +83,7 @@ module GHC.Builtin.Types.Prim( bcoPrimTyCon, bcoPrimTy, weakPrimTyCon, mkWeakPrimTy, threadIdPrimTyCon, threadIdPrimTy, + stackSnapshotPrimTyCon, stackSnapshotPrimTy, int8PrimTyCon, int8PrimTy, int8PrimTyConName, word8PrimTyCon, word8PrimTy, word8PrimTyConName, @@ -203,6 +204,7 @@ exposedPrimTyCons , word16PrimTyCon , word32PrimTyCon , word64PrimTyCon + , stackSnapshotPrimTyCon , tYPETyCon , funTyCon @@ -225,7 +227,7 @@ mkBuiltInPrimTc fs unique tycon BuiltInSyntax -charPrimTyConName, intPrimTyConName, int8PrimTyConName, int16PrimTyConName, int32PrimTyConName, int64PrimTyConName, wordPrimTyConName, word32PrimTyConName, word8PrimTyConName, word16PrimTyConName, word64PrimTyConName, addrPrimTyConName, floatPrimTyConName, doublePrimTyConName, statePrimTyConName, proxyPrimTyConName, realWorldTyConName, arrayPrimTyConName, arrayArrayPrimTyConName, smallArrayPrimTyConName, byteArrayPrimTyConName, mutableArrayPrimTyConName, mutableByteArrayPrimTyConName, mutableArrayArrayPrimTyConName, smallMutableArrayPrimTyConName, mutVarPrimTyConName, mVarPrimTyConName, ioPortPrimTyConName, tVarPrimTyConName, stablePtrPrimTyConName, stableNamePrimTyConName, compactPrimTyConName, bcoPrimTyConName, weakPrimTyConName, threadIdPrimTyConName, eqPrimTyConName, eqReprPrimTyConName, eqPhantPrimTyConName :: Name +charPrimTyConName, intPrimTyConName, int8PrimTyConName, int16PrimTyConName, int32PrimTyConName, int64PrimTyConName, wordPrimTyConName, word32PrimTyConName, word8PrimTyConName, word16PrimTyConName, word64PrimTyConName, addrPrimTyConName, floatPrimTyConName, doublePrimTyConName, statePrimTyConName, proxyPrimTyConName, realWorldTyConName, arrayPrimTyConName, arrayArrayPrimTyConName, smallArrayPrimTyConName, byteArrayPrimTyConName, mutableArrayPrimTyConName, mutableByteArrayPrimTyConName, mutableArrayArrayPrimTyConName, smallMutableArrayPrimTyConName, mutVarPrimTyConName, mVarPrimTyConName, ioPortPrimTyConName, tVarPrimTyConName, stablePtrPrimTyConName, stableNamePrimTyConName, compactPrimTyConName, bcoPrimTyConName, weakPrimTyConName, threadIdPrimTyConName, eqPrimTyConName, eqReprPrimTyConName, eqPhantPrimTyConName, stackSnapshotPrimTyConName :: Name charPrimTyConName = mkPrimTc (fsLit "Char#") charPrimTyConKey charPrimTyCon intPrimTyConName = mkPrimTc (fsLit "Int#") intPrimTyConKey intPrimTyCon int8PrimTyConName = mkPrimTc (fsLit "Int8#") int8PrimTyConKey int8PrimTyCon @@ -261,6 +263,7 @@ tVarPrimTyConName = mkPrimTc (fsLit "TVar#") tVarPrimTyConKey tVarPr stablePtrPrimTyConName = mkPrimTc (fsLit "StablePtr#") stablePtrPrimTyConKey stablePtrPrimTyCon stableNamePrimTyConName = mkPrimTc (fsLit "StableName#") stableNamePrimTyConKey stableNamePrimTyCon compactPrimTyConName = mkPrimTc (fsLit "Compact#") compactPrimTyConKey compactPrimTyCon +stackSnapshotPrimTyConName = mkPrimTc (fsLit "StackSnapshot#") stackSnapshotPrimTyConKey stackSnapshotPrimTyCon bcoPrimTyConName = mkPrimTc (fsLit "BCO") bcoPrimTyConKey bcoPrimTyCon weakPrimTyConName = mkPrimTc (fsLit "Weak#") weakPrimTyConKey weakPrimTyCon threadIdPrimTyConName = mkPrimTc (fsLit "ThreadId#") threadIdPrimTyConKey threadIdPrimTyCon @@ -1159,6 +1162,21 @@ compactPrimTy = mkTyConTy compactPrimTyCon {- ************************************************************************ * * + The @StackSnapshot#@ type +* * +************************************************************************ +-} + +stackSnapshotPrimTyCon :: TyCon +stackSnapshotPrimTyCon = pcPrimTyCon0 stackSnapshotPrimTyConName UnliftedRep + +stackSnapshotPrimTy :: Type +stackSnapshotPrimTy = mkTyConTy stackSnapshotPrimTyCon + + +{- +************************************************************************ +* * The ``bytecode object'' type * * ************************************************************************ diff --git a/compiler/GHC/Builtin/primops.txt.pp b/compiler/GHC/Builtin/primops.txt.pp index bf3b879449..58d4ec91f3 100644 --- a/compiler/GHC/Builtin/primops.txt.pp +++ b/compiler/GHC/Builtin/primops.txt.pp @@ -190,9 +190,9 @@ defaults -- Note [Levity and representation polymorphic primops] -- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -- In the types of primops in this module, --- +-- -- * The names `a,b,c,s` stand for type variables of kind Type --- +-- -- * The names `v` and `w` stand for levity-polymorphic -- type variables. -- For example: @@ -207,7 +207,7 @@ defaults -- - `v` and `w` end up written as `a` and `b` (respectively) in types, -- which means that one shouldn't write a primop type involving both -- `a` and `v`, nor `b` and `w`. --- +-- -- * The names `o` and `p` stand for representation-polymorphic -- type variables, similarly to `v` and `w` above. For example: -- op :: o -> p -> Int @@ -3259,29 +3259,29 @@ primop ReallyUnsafePtrEqualityOp "reallyUnsafePtrEquality#" GenPrimOp -- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -- The primop `reallyUnsafePtrEquality#` does a direct pointer -- equality between two (boxed) values. Several things to note: --- +-- -- * It is levity-polymorphic. It works for TYPE (BoxedRep Lifted) and -- TYPE (BoxedRep Unlifted). But not TYPE IntRep, for example. -- This levity-polymorphism comes from the use of the type variables -- "v" and "w". See Note [Levity and representation polymorphic primops] --- +-- -- * It does not evaluate its arguments. The user of the primop is responsible -- for doing so. --- +-- -- * It is hetero-typed; you can compare pointers of different types. -- This is used in various packages such as containers & unordered-containers. --- +-- -- * It is obviously very dangerous, because -- let x = f y in reallyUnsafePtrEquality# x x -- will probably return True, whereas -- reallyUnsafePtrEquality# (f y) (f y) -- will probably return False. ("probably", because it's affected -- by CSE and inlining). --- +-- -- * reallyUnsafePtrEquality# can't fail, but it is marked as such -- to prevent it from floating out. -- See Note [reallyUnsafePtrEquality# can_fail] --- +-- -- The library GHC.Exts provides several less Wild-West functions -- for use in specific cases, namely: -- @@ -3647,6 +3647,21 @@ primop SetThreadAllocationCounter "setThreadAllocationCounter#" GenPrimOp has_side_effects = True out_of_line = True +primtype StackSnapshot# + +primop CloneMyStack "cloneMyStack#" GenPrimOp + State# RealWorld -> (# State# RealWorld, StackSnapshot# #) + { Clones the stack of the current (active) Haskell thread. A cloned stack is + represented by {\tt StackSnapshot# } and is not evaluated any further + (i.e. it's "cold"). This is useful for stack decoding (backtraces) and + analyses because there are no concurrent mutations on a cloned stack. + The module {\tt GHC.Stack.CloneStack } contains related funcions. + Please see Note [Stack Cloning] for technical details. } + with + has_side_effects = True + out_of_line = True + + ------------------------------------------------------------------------ section "Safe coercions" ------------------------------------------------------------------------ diff --git a/compiler/GHC/StgToCmm/Prim.hs b/compiler/GHC/StgToCmm/Prim.hs index dff86341b1..0f5943bf48 100644 --- a/compiler/GHC/StgToCmm/Prim.hs +++ b/compiler/GHC/StgToCmm/Prim.hs @@ -1669,6 +1669,7 @@ emitPrimOp dflags primop = case primop of TraceEventBinaryOp -> alwaysExternal TraceMarkerOp -> alwaysExternal SetThreadAllocationCounter -> alwaysExternal + CloneMyStack -> alwaysExternal -- See Note [keepAlive# magic] in GHC.CoreToStg.Prep. KeepAliveOp -> panic "keepAlive# should have been eliminated in CorePrep" |