{-# LANGUAGE MagicHash #-}
{-# LANGUAGE UnliftedFFITypes #-}
module Unison.Runtime.JIT.Native
(
NativeFn,
Status,
statusOK,
statusError,
enterNative,
FrameRecord (..),
outAp,
outFp,
outSp,
outFrameCount,
outFrames,
configureNative,
ctxLayout,
rtsFacts,
hplimValue,
helperAddresses,
tableAddresses,
murmurCAddress,
ucmpCAddress,
)
where
import Control.Monad (forM)
import Control.Monad.Primitive (PrimState)
import Data.Int (Int64)
import Data.Primitive.Array (MutableArray (..))
import Data.Primitive.ByteArray (MutableByteArray (..), readByteArray)
import Data.Word (Word64)
import Foreign.C.String (CString, peekCString)
import Foreign.Marshal.Alloc (allocaBytes, free)
import Foreign.Ptr (FunPtr, Ptr, WordPtr (..), ptrToWordPtr, wordPtrToPtr)
import Foreign.Storable (peekElemOff)
import GHC.Exts (MutableArray#, MutableByteArray#)
import Unison.Runtime.Stack (Closure)
data NativeFn
type Status = Int
data FrameRecord = FrameRecord {FrameRecord -> Int
frIndex :: !Int, FrameRecord -> Int
frFrameSize :: !Int, FrameRecord -> Int
frPendingArgs :: !Int}
deriving (Int -> FrameRecord -> ShowS
[FrameRecord] -> ShowS
FrameRecord -> String
(Int -> FrameRecord -> ShowS)
-> (FrameRecord -> String)
-> ([FrameRecord] -> ShowS)
-> Show FrameRecord
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> FrameRecord -> ShowS
showsPrec :: Int -> FrameRecord -> ShowS
$cshow :: FrameRecord -> String
show :: FrameRecord -> String
$cshowList :: [FrameRecord] -> ShowS
showList :: [FrameRecord] -> ShowS
Show)
statusOK, statusError :: Status
statusOK :: Int
statusOK = Int
0
statusError :: Int
statusError = -Int
1
outAp, outFp, outSp, outFrameCount :: MutableByteArray (PrimState IO) -> Int -> IO Int
outAp :: MutableByteArray (PrimState IO) -> Int -> IO Int
outAp MutableByteArray (PrimState IO)
ustk Int
size = MutableByteArray (PrimState IO) -> Int -> IO Int
forall a (m :: * -> *).
(Prim a, PrimMonad m) =>
MutableByteArray (PrimState m) -> Int -> m a
readByteArray MutableByteArray (PrimState IO)
ustk Int
size
outFp :: MutableByteArray (PrimState IO) -> Int -> IO Int
outFp MutableByteArray (PrimState IO)
ustk Int
size = MutableByteArray (PrimState IO) -> Int -> IO Int
forall a (m :: * -> *).
(Prim a, PrimMonad m) =>
MutableByteArray (PrimState m) -> Int -> m a
readByteArray MutableByteArray (PrimState IO)
ustk (Int
size Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
1)
outSp :: MutableByteArray (PrimState IO) -> Int -> IO Int
outSp MutableByteArray (PrimState IO)
ustk Int
size = MutableByteArray (PrimState IO) -> Int -> IO Int
forall a (m :: * -> *).
(Prim a, PrimMonad m) =>
MutableByteArray (PrimState m) -> Int -> m a
readByteArray MutableByteArray (PrimState IO)
ustk (Int
size Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
2)
outFrameCount :: MutableByteArray (PrimState IO) -> Int -> IO Int
outFrameCount MutableByteArray (PrimState IO)
ustk Int
size = MutableByteArray (PrimState IO) -> Int -> IO Int
forall a (m :: * -> *).
(Prim a, PrimMonad m) =>
MutableByteArray (PrimState m) -> Int -> m a
readByteArray MutableByteArray (PrimState IO)
ustk (Int
size Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
3)
{-# INLINE outAp #-}
{-# INLINE outFp #-}
{-# INLINE outSp #-}
{-# INLINE outFrameCount #-}
outFrames :: MutableByteArray (PrimState IO) -> Int -> IO [FrameRecord]
outFrames :: MutableByteArray (PrimState IO) -> Int -> IO [FrameRecord]
outFrames = MutableByteArray (PrimState IO) -> Int -> IO [FrameRecord]
frameRecords
foreign import ccall unsafe "unison_jit_enter"
c_enter ::
FunPtr NativeFn ->
MutableByteArray# (PrimState IO) ->
MutableArray# (PrimState IO) Closure ->
MutableArray# (PrimState IO) Closure ->
Int64 ->
Int64 ->
Int64 ->
Int64 ->
IO Int64
enterNative ::
FunPtr NativeFn ->
MutableByteArray (PrimState IO) ->
MutableArray (PrimState IO) Closure ->
MutableArray (PrimState IO) Closure ->
Int ->
Int ->
Int ->
Int ->
IO Status
enterNative :: FunPtr NativeFn
-> MutableByteArray (PrimState IO)
-> MutableArray (PrimState IO) Closure
-> MutableArray (PrimState IO) Closure
-> Int
-> Int
-> Int
-> Int
-> IO Int
enterNative FunPtr NativeFn
fn (MutableByteArray MutableByteArray# (PrimState IO)
ustk) (MutableArray MutableArray# (PrimState IO) Closure
bstk) (MutableArray MutableArray# (PrimState IO) Closure
pool) Int
size Int
ap Int
fp Int
sp = do
Int64
status <- FunPtr NativeFn
-> MutableByteArray# (PrimState IO)
-> MutableArray# (PrimState IO) Closure
-> MutableArray# (PrimState IO) Closure
-> Int64
-> Int64
-> Int64
-> Int64
-> IO Int64
c_enter FunPtr NativeFn
fn MutableByteArray# (PrimState IO)
ustk MutableArray# (PrimState IO) Closure
bstk MutableArray# (PrimState IO) Closure
pool (Int -> Int64
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
size) (Int -> Int64
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
ap) (Int -> Int64
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
fp) (Int -> Int64
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
sp)
Int -> IO Int
forall a. a -> IO a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Int -> IO Int) -> Int -> IO Int
forall a b. (a -> b) -> a -> b
$! Int64 -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int64
status
{-# INLINE enterNative #-}
frameRecords :: MutableByteArray (PrimState IO) -> Int -> IO [FrameRecord]
frameRecords :: MutableByteArray (PrimState IO) -> Int -> IO [FrameRecord]
frameRecords MutableByteArray (PrimState IO)
out Int
size = do
Int
n <- MutableByteArray (PrimState IO) -> Int -> IO Int
forall a (m :: * -> *).
(Prim a, PrimMonad m) =>
MutableByteArray (PrimState m) -> Int -> m a
readByteArray MutableByteArray (PrimState IO)
out (Int
size Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
3) :: IO Int
if Int
n Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
<= Int
inlineFrames
then (Int -> IO FrameRecord) -> [Int] -> IO [FrameRecord]
forall (t :: * -> *) (m :: * -> *) a b.
(Traversable t, Monad m) =>
(a -> m b) -> t a -> m (t b)
forall (m :: * -> *) a b. Monad m => (a -> m b) -> [a] -> m [b]
mapM (\Int
i -> Int -> Int -> Int -> FrameRecord
FrameRecord (Int -> Int -> Int -> FrameRecord)
-> IO Int -> IO (Int -> Int -> FrameRecord)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> MutableByteArray (PrimState IO) -> Int -> IO Int
forall a (m :: * -> *).
(Prim a, PrimMonad m) =>
MutableByteArray (PrimState m) -> Int -> m a
readByteArray MutableByteArray (PrimState IO)
out (Int
size Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
4 Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
3 Int -> Int -> Int
forall a. Num a => a -> a -> a
* Int
i) IO (Int -> Int -> FrameRecord) -> IO Int -> IO (Int -> FrameRecord)
forall a b. IO (a -> b) -> IO a -> IO b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> MutableByteArray (PrimState IO) -> Int -> IO Int
forall a (m :: * -> *).
(Prim a, PrimMonad m) =>
MutableByteArray (PrimState m) -> Int -> m a
readByteArray MutableByteArray (PrimState IO)
out (Int
size Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
5 Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
3 Int -> Int -> Int
forall a. Num a => a -> a -> a
* Int
i) IO (Int -> FrameRecord) -> IO Int -> IO FrameRecord
forall a b. IO (a -> b) -> IO a -> IO b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> MutableByteArray (PrimState IO) -> Int -> IO Int
forall a (m :: * -> *).
(Prim a, PrimMonad m) =>
MutableByteArray (PrimState m) -> Int -> m a
readByteArray MutableByteArray (PrimState IO)
out (Int
size Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
6 Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
3 Int -> Int -> Int
forall a. Num a => a -> a -> a
* Int
i)) [Int
0 .. Int
n Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
1]
else do
Word
addr <- MutableByteArray (PrimState IO) -> Int -> IO Word
forall a (m :: * -> *).
(Prim a, PrimMonad m) =>
MutableByteArray (PrimState m) -> Int -> m a
readByteArray MutableByteArray (PrimState IO)
out (Int
size Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
4) :: IO Word
let buf :: Ptr Int64
buf = WordPtr -> Ptr Int64
forall a. WordPtr -> Ptr a
wordPtrToPtr (Word -> WordPtr
WordPtr Word
addr) :: Ptr Int64
record :: Int -> IO FrameRecord
record Int
i =
Int -> Int -> Int -> FrameRecord
FrameRecord
(Int -> Int -> Int -> FrameRecord)
-> IO Int -> IO (Int -> Int -> FrameRecord)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> (Int64 -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Int64 -> Int) -> IO Int64 -> IO Int
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Ptr Int64 -> Int -> IO Int64
forall a. Storable a => Ptr a -> Int -> IO a
peekElemOff Ptr Int64
buf (Int
3 Int -> Int -> Int
forall a. Num a => a -> a -> a
* Int
i))
IO (Int -> Int -> FrameRecord) -> IO Int -> IO (Int -> FrameRecord)
forall a b. IO (a -> b) -> IO a -> IO b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> (Int64 -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Int64 -> Int) -> IO Int64 -> IO Int
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Ptr Int64 -> Int -> IO Int64
forall a. Storable a => Ptr a -> Int -> IO a
peekElemOff Ptr Int64
buf (Int
3 Int -> Int -> Int
forall a. Num a => a -> a -> a
* Int
i Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
1))
IO (Int -> FrameRecord) -> IO Int -> IO FrameRecord
forall a b. IO (a -> b) -> IO a -> IO b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> (Int64 -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Int64 -> Int) -> IO Int64 -> IO Int
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Ptr Int64 -> Int -> IO Int64
forall a. Storable a => Ptr a -> Int -> IO a
peekElemOff Ptr Int64
buf (Int
3 Int -> Int -> Int
forall a. Num a => a -> a -> a
* Int
i Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
2))
[FrameRecord]
fs <- (Int -> IO FrameRecord) -> [Int] -> IO [FrameRecord]
forall (t :: * -> *) (m :: * -> *) a b.
(Traversable t, Monad m) =>
(a -> m b) -> t a -> m (t b)
forall (m :: * -> *) a b. Monad m => (a -> m b) -> [a] -> m [b]
mapM Int -> IO FrameRecord
record [Int
0 .. Int
n Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
1]
Ptr Int64 -> IO ()
forall a. Ptr a -> IO ()
free Ptr Int64
buf
pure [FrameRecord]
fs
inlineFrames :: Int
inlineFrames :: Int
inlineFrames = Int
8
foreign import ccall unsafe "unison_jit_configure" c_configure :: Int64 -> Int64 -> Int64 -> Int64 -> Int64 -> IO ()
configureNative :: Int -> Int -> Int -> Int -> Bool -> IO ()
configureNative :: Int -> Int -> Int -> Int -> Bool -> IO ()
configureNative Int
pollEvery Int
calleeEvery Int
cstack Int
alloc Bool
tr =
Int64 -> Int64 -> Int64 -> Int64 -> Int64 -> IO ()
c_configure (Int -> Int64
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
pollEvery) (Int -> Int64
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
calleeEvery) (Int -> Int64
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
cstack) (Int -> Int64
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
alloc) (if Bool
tr then Int64
1 else Int64
0)
foreign import ccall unsafe "unison_jit_ctx_layout" c_ctxLayout :: Ptr Int64 -> Int64 -> IO Int64
ctxLayout :: IO ([Int], Int)
ctxLayout :: IO ([Int], Int)
ctxLayout = Int -> (Ptr Int64 -> IO ([Int], Int)) -> IO ([Int], Int)
forall a b. Int -> (Ptr a -> IO b) -> IO b
allocaBytes (Int
8 Int -> Int -> Int
forall a. Num a => a -> a -> a
* Int
32) ((Ptr Int64 -> IO ([Int], Int)) -> IO ([Int], Int))
-> (Ptr Int64 -> IO ([Int], Int)) -> IO ([Int], Int)
forall a b. (a -> b) -> a -> b
$ \Ptr Int64
out -> do
Int64
size <- Ptr Int64 -> Int64 -> IO Int64
c_ctxLayout Ptr Int64
out Int64
32
[Int64]
offs <- (Int -> IO Int64) -> [Int] -> IO [Int64]
forall (t :: * -> *) (m :: * -> *) a b.
(Traversable t, Monad m) =>
(a -> m b) -> t a -> m (t b)
forall (m :: * -> *) a b. Monad m => (a -> m b) -> [a] -> m [b]
mapM (Ptr Int64 -> Int -> IO Int64
forall a. Storable a => Ptr a -> Int -> IO a
peekElemOff Ptr Int64
out) [Int
0 .. Int
22]
pure ((Int64 -> Int) -> [Int64] -> [Int]
forall a b. (a -> b) -> [a] -> [b]
map Int64 -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral [Int64]
offs, Int64 -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int64
size)
foreign import ccall unsafe "unison_jit_rts_facts" c_rtsFacts :: Ptr Int64 -> Int64 -> IO Int64
rtsFacts :: IO [Int]
rtsFacts :: IO [Int]
rtsFacts = Int -> (Ptr Int64 -> IO [Int]) -> IO [Int]
forall a b. Int -> (Ptr a -> IO b) -> IO b
allocaBytes (Int
8 Int -> Int -> Int
forall a. Num a => a -> a -> a
* Int
16) ((Ptr Int64 -> IO [Int]) -> IO [Int])
-> (Ptr Int64 -> IO [Int]) -> IO [Int]
forall a b. (a -> b) -> a -> b
$ \Ptr Int64
out -> do
Int64
n <- Ptr Int64 -> Int64 -> IO Int64
c_rtsFacts Ptr Int64
out Int64
16
(Int64 -> Int) -> [Int64] -> [Int]
forall a b. (a -> b) -> [a] -> [b]
map Int64 -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral ([Int64] -> [Int]) -> IO [Int64] -> IO [Int]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> (Int -> IO Int64) -> [Int] -> IO [Int64]
forall (t :: * -> *) (m :: * -> *) a b.
(Traversable t, Monad m) =>
(a -> m b) -> t a -> m (t b)
forall (m :: * -> *) a b. Monad m => (a -> m b) -> [a] -> m [b]
mapM (Ptr Int64 -> Int -> IO Int64
forall a. Storable a => Ptr a -> Int -> IO a
peekElemOff Ptr Int64
out) [Int
0 .. Int64 -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int64
n Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
1]
foreign import ccall unsafe "unison_jit_hplim_value" c_hplimValue :: IO Int64
hplimValue :: IO Int
hplimValue :: IO Int
hplimValue = Int64 -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Int64 -> Int) -> IO Int64 -> IO Int
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> IO Int64
c_hplimValue
foreign import ccall unsafe "unison_jit_helper_addresses" c_helperAddresses :: Ptr CString -> Ptr (Ptr ()) -> Int64 -> IO Int64
helperAddresses :: IO [(String, Word64)]
helperAddresses :: IO [(String, Word64)]
helperAddresses = Int
-> (Ptr CString -> Ptr (Ptr ()) -> Int64 -> IO Int64)
-> IO [(String, Word64)]
namedAddresses Int
256 Ptr CString -> Ptr (Ptr ()) -> Int64 -> IO Int64
c_helperAddresses
foreign import ccall unsafe "unison_jit_table_addresses" c_tableAddresses :: Ptr CString -> Ptr (Ptr ()) -> Int64 -> IO Int64
tableAddresses :: IO [(String, Word64)]
tableAddresses :: IO [(String, Word64)]
tableAddresses = Int
-> (Ptr CString -> Ptr (Ptr ()) -> Int64 -> IO Int64)
-> IO [(String, Word64)]
namedAddresses Int
16 Ptr CString -> Ptr (Ptr ()) -> Int64 -> IO Int64
c_tableAddresses
namedAddresses :: Int -> (Ptr CString -> Ptr (Ptr ()) -> Int64 -> IO Int64) -> IO [(String, Word64)]
namedAddresses :: Int
-> (Ptr CString -> Ptr (Ptr ()) -> Int64 -> IO Int64)
-> IO [(String, Word64)]
namedAddresses Int
most Ptr CString -> Ptr (Ptr ()) -> Int64 -> IO Int64
fill = Int
-> (Ptr CString -> IO [(String, Word64)]) -> IO [(String, Word64)]
forall a b. Int -> (Ptr a -> IO b) -> IO b
allocaBytes (Int
8 Int -> Int -> Int
forall a. Num a => a -> a -> a
* Int
most) ((Ptr CString -> IO [(String, Word64)]) -> IO [(String, Word64)])
-> (Ptr CString -> IO [(String, Word64)]) -> IO [(String, Word64)]
forall a b. (a -> b) -> a -> b
$ \Ptr CString
names -> Int
-> (Ptr (Ptr ()) -> IO [(String, Word64)]) -> IO [(String, Word64)]
forall a b. Int -> (Ptr a -> IO b) -> IO b
allocaBytes (Int
8 Int -> Int -> Int
forall a. Num a => a -> a -> a
* Int
most) ((Ptr (Ptr ()) -> IO [(String, Word64)]) -> IO [(String, Word64)])
-> (Ptr (Ptr ()) -> IO [(String, Word64)]) -> IO [(String, Word64)]
forall a b. (a -> b) -> a -> b
$ \Ptr (Ptr ())
addrs -> do
Int64
n <- Ptr CString -> Ptr (Ptr ()) -> Int64 -> IO Int64
fill Ptr CString
names Ptr (Ptr ())
addrs (Int -> Int64
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
most)
[Int] -> (Int -> IO (String, Word64)) -> IO [(String, Word64)]
forall (t :: * -> *) (m :: * -> *) a b.
(Traversable t, Monad m) =>
t a -> (a -> m b) -> m (t b)
forM [Int
0 .. Int64 -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int64
n Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
1] ((Int -> IO (String, Word64)) -> IO [(String, Word64)])
-> (Int -> IO (String, Word64)) -> IO [(String, Word64)]
forall a b. (a -> b) -> a -> b
$ \Int
i -> do
String
name <- Ptr CString -> Int -> IO CString
forall a. Storable a => Ptr a -> Int -> IO a
peekElemOff Ptr CString
names Int
i IO CString -> (CString -> IO String) -> IO String
forall a b. IO a -> (a -> IO b) -> IO b
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= CString -> IO String
peekCString
Ptr ()
addr <- Ptr (Ptr ()) -> Int -> IO (Ptr ())
forall a. Storable a => Ptr a -> Int -> IO a
peekElemOff Ptr (Ptr ())
addrs Int
i
pure (String
name, WordPtr -> Word64
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Ptr () -> WordPtr
forall a. Ptr a -> WordPtr
ptrToWordPtr Ptr ()
addr))
foreign import ccall "&unison_jit_murmur" c_murmurAddr :: FunPtr (Int64 -> Ptr () -> IO ())
foreign import ccall "&unison_jit_ucmp" c_ucmpAddr :: FunPtr (Int64 -> Ptr () -> Int64 -> Ptr () -> Int64 -> IO ())
murmurCAddress :: FunPtr (Int64 -> Ptr () -> IO ())
murmurCAddress :: FunPtr (Int64 -> Ptr () -> IO ())
murmurCAddress = FunPtr (Int64 -> Ptr () -> IO ())
c_murmurAddr
ucmpCAddress :: FunPtr (Int64 -> Ptr () -> Int64 -> Ptr () -> Int64 -> IO ())
ucmpCAddress :: FunPtr (Int64 -> Ptr () -> Int64 -> Ptr () -> Int64 -> IO ())
ucmpCAddress = FunPtr (Int64 -> Ptr () -> Int64 -> Ptr () -> Int64 -> IO ())
c_ucmpAddr