{-# LANGUAGE OverloadedStrings #-}
module GHC.StgToJS.Stack
( resetSlots
, isolateSlots
, setSlots
, getSlots
, addSlots
, dropSlots
, addUnknownSlots
, push
, push'
, adjSpN
, adjSpN'
, adjSp'
, adjSp
, pushNN
, pushNN'
, pushN'
, pushN
, pushOptimized'
, pushOptimized
, pushLneFrame
, popN
, popSkip
, popSkipI
, loadSkip
, updateThunk
, updateThunk'
, bhStats
)
where
import GHC.Prelude
import GHC.JS.Unsat.Syntax
import GHC.JS.Make
import GHC.StgToJS.Types
import GHC.StgToJS.Monad
import GHC.StgToJS.Ids
import GHC.StgToJS.ExprCtx
import GHC.StgToJS.Heap
import GHC.StgToJS.Regs
import GHC.Types.Id
import GHC.Utils.Misc
import GHC.Data.FastString
import qualified Data.Bits as Bits
import qualified Data.List as L
import qualified Control.Monad.Trans.State.Strict as State
import Data.Array
import Data.Monoid
import Control.Monad
resetSlots :: G a -> G a
resetSlots :: forall a. G a -> G a
resetSlots G a
m = do
[StackSlot]
s <- G [StackSlot]
getSlots
Int
d <- G Int
getStackDepth
[StackSlot] -> G ()
setSlots []
a
a <- G a
m
[StackSlot] -> G ()
setSlots [StackSlot]
s
Int -> G ()
setStackDepth Int
d
a -> G a
forall a. a -> StateT GenState IO a
forall (m :: * -> *) a. Monad m => a -> m a
return a
a
isolateSlots :: G a -> G a
isolateSlots :: forall a. G a -> G a
isolateSlots G a
m = do
[StackSlot]
s <- G [StackSlot]
getSlots
Int
d <- G Int
getStackDepth
a
a <- G a
m
[StackSlot] -> G ()
setSlots [StackSlot]
s
Int -> G ()
setStackDepth Int
d
a -> G a
forall a. a -> StateT GenState IO a
forall (f :: * -> *) a. Applicative f => a -> f a
pure a
a
setStackDepth :: Int -> G ()
setStackDepth :: Int -> G ()
setStackDepth Int
d = (GenGroupState -> GenGroupState) -> G ()
modifyGroup (\GenGroupState
s -> GenGroupState
s { ggsStackDepth = d})
getStackDepth :: G Int
getStackDepth :: G Int
getStackDepth = (GenState -> Int) -> G Int
forall (m :: * -> *) s a. Monad m => (s -> a) -> StateT s m a
State.gets (GenGroupState -> Int
ggsStackDepth (GenGroupState -> Int)
-> (GenState -> GenGroupState) -> GenState -> Int
forall b c a. (b -> c) -> (a -> b) -> a -> c
. GenState -> GenGroupState
gsGroup)
modifyStackDepth :: (Int -> Int) -> G ()
modifyStackDepth :: (Int -> Int) -> G ()
modifyStackDepth Int -> Int
f = (GenGroupState -> GenGroupState) -> G ()
modifyGroup (\GenGroupState
s -> GenGroupState
s { ggsStackDepth = f (ggsStackDepth s) })
setSlots :: [StackSlot] -> G ()
setSlots :: [StackSlot] -> G ()
setSlots [StackSlot]
xs = (GenGroupState -> GenGroupState) -> G ()
modifyGroup (\GenGroupState
g -> GenGroupState
g { ggsStack = xs})
getSlots :: G [StackSlot]
getSlots :: G [StackSlot]
getSlots = (GenState -> [StackSlot]) -> G [StackSlot]
forall (m :: * -> *) s a. Monad m => (s -> a) -> StateT s m a
State.gets (GenGroupState -> [StackSlot]
ggsStack (GenGroupState -> [StackSlot])
-> (GenState -> GenGroupState) -> GenState -> [StackSlot]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. GenState -> GenGroupState
gsGroup)
modifySlots :: ([StackSlot] -> [StackSlot]) -> G ()
modifySlots :: ([StackSlot] -> [StackSlot]) -> G ()
modifySlots [StackSlot] -> [StackSlot]
f = (GenGroupState -> GenGroupState) -> G ()
modifyGroup (\GenGroupState
g -> GenGroupState
g { ggsStack = f (ggsStack g)})
addUnknownSlots :: Int -> G ()
addUnknownSlots :: Int -> G ()
addUnknownSlots Int
n = [StackSlot] -> G ()
addSlots (Int -> StackSlot -> [StackSlot]
forall a. Int -> a -> [a]
replicate Int
n StackSlot
SlotUnknown)
addSlots :: [StackSlot] -> G ()
addSlots :: [StackSlot] -> G ()
addSlots [StackSlot]
xs = do
[StackSlot]
s <- G [StackSlot]
getSlots
[StackSlot] -> G ()
setSlots ([StackSlot]
xs [StackSlot] -> [StackSlot] -> [StackSlot]
forall a. [a] -> [a] -> [a]
++ [StackSlot]
s)
dropSlots :: Int -> G ()
dropSlots :: Int -> G ()
dropSlots Int
n = ([StackSlot] -> [StackSlot]) -> G ()
modifySlots (Int -> [StackSlot] -> [StackSlot]
forall a. Int -> [a] -> [a]
drop Int
n)
push :: [JExpr] -> G JStat
push :: [JExpr] -> G JStat
push [JExpr]
xs = do
Int -> G ()
dropSlots ([JExpr] -> Int
forall a. [a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [JExpr]
xs)
(Int -> Int) -> G ()
modifyStackDepth (Int -> Int -> Int
forall a. Num a => a -> a -> a
+ ([JExpr] -> Int
forall a. [a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [JExpr]
xs))
(StgToJSConfig -> [JExpr] -> JStat)
-> [JExpr] -> StgToJSConfig -> JStat
forall a b c. (a -> b -> c) -> b -> a -> c
flip StgToJSConfig -> [JExpr] -> JStat
push' [JExpr]
xs (StgToJSConfig -> JStat)
-> StateT GenState IO StgToJSConfig -> G JStat
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> StateT GenState IO StgToJSConfig
getSettings
push' :: StgToJSConfig -> [JExpr] -> JStat
push' :: StgToJSConfig -> [JExpr] -> JStat
push' StgToJSConfig
_ [] = JStat
forall a. Monoid a => a
mempty
push' StgToJSConfig
cs [JExpr]
xs
| StgToJSConfig -> Bool
csInlinePush StgToJSConfig
cs Bool -> Bool -> Bool
|| Int
l Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
> Int
32 Bool -> Bool -> Bool
|| Int
l Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
< Int
2 = Int -> JStat
adjSp' Int
l JStat -> JStat -> JStat
forall a. Semigroup a => a -> a -> a
<> [JStat] -> JStat
forall a. Monoid a => [a] -> a
mconcat [JStat]
items
| Bool
otherwise = JExpr -> [JExpr] -> JStat
ApplStat (Ident -> JExpr
forall a. ToJExpr a => a -> JExpr
toJExpr (Ident -> JExpr) -> Ident -> JExpr
forall a b. (a -> b) -> a -> b
$ Array Int Ident
pushN Array Int Ident -> Int -> Ident
forall i e. Ix i => Array i e -> i -> e
! Int
l) [JExpr]
xs
where
items :: [JStat]
items = (Int -> JExpr -> JStat) -> [Int] -> [JExpr] -> [JStat]
forall a b c. (a -> b -> c) -> [a] -> [b] -> [c]
zipWith Int -> JExpr -> JStat
f [(Int
1::Int)..] [JExpr]
xs
offset :: Int -> JExpr
offset Int
i | Int
i Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
l = JExpr
sp
| Bool
otherwise = JOp -> JExpr -> JExpr -> JExpr
InfixExpr JOp
SubOp JExpr
sp (Int -> JExpr
forall a. ToJExpr a => a -> JExpr
toJExpr (Int
l Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
i))
l :: Int
l = [JExpr] -> Int
forall a. [a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [JExpr]
xs
f :: Int -> JExpr -> JStat
f Int
i JExpr
e = JExpr -> JExpr -> JStat
AssignStat ((JExpr -> JExpr -> JExpr
IdxExpr JExpr
stack) (JExpr -> JExpr
forall a. ToJExpr a => a -> JExpr
toJExpr (Int -> JExpr
offset Int
i))) (JExpr -> JExpr
forall a. ToJExpr a => a -> JExpr
toJExpr JExpr
e)
adjSp' :: Int -> JStat
adjSp' :: Int -> JStat
adjSp' Int
0 = JStat
forall a. Monoid a => a
mempty
adjSp' Int
n = JExpr
sp JExpr -> JExpr -> JStat
|= JOp -> JExpr -> JExpr -> JExpr
InfixExpr JOp
AddOp JExpr
sp (Int -> JExpr
forall a. ToJExpr a => a -> JExpr
toJExpr Int
n)
adjSpN' :: Int -> JStat
adjSpN' :: Int -> JStat
adjSpN' Int
0 = JStat
forall a. Monoid a => a
mempty
adjSpN' Int
n = JExpr
sp JExpr -> JExpr -> JStat
|= JOp -> JExpr -> JExpr -> JExpr
InfixExpr JOp
SubOp JExpr
sp (Int -> JExpr
forall a. ToJExpr a => a -> JExpr
toJExpr Int
n)
adjSp :: Int -> G JStat
adjSp :: Int -> G JStat
adjSp Int
0 = JStat -> G JStat
forall a. a -> StateT GenState IO a
forall (m :: * -> *) a. Monad m => a -> m a
return JStat
forall a. Monoid a => a
mempty
adjSp Int
n = do
(Int -> Int) -> G ()
modifyStackDepth (Int -> Int -> Int
forall a. Num a => a -> a -> a
+Int
n)
JStat -> G JStat
forall a. a -> StateT GenState IO a
forall (m :: * -> *) a. Monad m => a -> m a
return (Int -> JStat
adjSp' Int
n)
adjSpN :: Int -> G JStat
adjSpN :: Int -> G JStat
adjSpN Int
0 = JStat -> G JStat
forall a. a -> StateT GenState IO a
forall (m :: * -> *) a. Monad m => a -> m a
return JStat
forall a. Monoid a => a
mempty
adjSpN Int
n = do
(Int -> Int) -> G ()
modifyStackDepth (\Int
x -> Int
x Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
n)
JStat -> G JStat
forall a. a -> StateT GenState IO a
forall (m :: * -> *) a. Monad m => a -> m a
return (Int -> JStat
adjSpN' Int
n)
pushN :: Array Int Ident
pushN :: Array Int Ident
pushN = (Int, Int) -> [Ident] -> Array Int Ident
forall i e. Ix i => (i, i) -> [e] -> Array i e
listArray (Int
1,Int
32) ([Ident] -> Array Int Ident) -> [Ident] -> Array Int Ident
forall a b. (a -> b) -> a -> b
$ (Int -> Ident) -> [Int] -> [Ident]
forall a b. (a -> b) -> [a] -> [b]
map (FastString -> Ident
TxtI (FastString -> Ident) -> (Int -> FastString) -> Int -> Ident
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> FastString
mkFastString (String -> FastString) -> (Int -> String) -> Int -> FastString
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (String
"h$p"String -> String -> String
forall a. [a] -> [a] -> [a]
++) (String -> String) -> (Int -> String) -> Int -> String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Int -> String
forall a. Show a => a -> String
show) [(Int
1::Int)..Int
32]
pushN' :: Array Int JExpr
pushN' :: Array Int JExpr
pushN' = (Ident -> JExpr) -> Array Int Ident -> Array Int JExpr
forall a b. (a -> b) -> Array Int a -> Array Int b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (JVal -> JExpr
ValExpr (JVal -> JExpr) -> (Ident -> JVal) -> Ident -> JExpr
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Ident -> JVal
JVar) Array Int Ident
pushN
pushNN :: Array Integer Ident
pushNN :: Array Integer Ident
pushNN = (Integer, Integer) -> [Ident] -> Array Integer Ident
forall i e. Ix i => (i, i) -> [e] -> Array i e
listArray (Integer
1,Integer
255) ([Ident] -> Array Integer Ident) -> [Ident] -> Array Integer Ident
forall a b. (a -> b) -> a -> b
$ (Int -> Ident) -> [Int] -> [Ident]
forall a b. (a -> b) -> [a] -> [b]
map (FastString -> Ident
TxtI (FastString -> Ident) -> (Int -> FastString) -> Int -> Ident
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> FastString
mkFastString (String -> FastString) -> (Int -> String) -> Int -> FastString
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (String
"h$pp"String -> String -> String
forall a. [a] -> [a] -> [a]
++) (String -> String) -> (Int -> String) -> Int -> String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Int -> String
forall a. Show a => a -> String
show) [(Int
1::Int)..Int
255]
pushNN' :: Array Integer JExpr
pushNN' :: Array Integer JExpr
pushNN' = (Ident -> JExpr) -> Array Integer Ident -> Array Integer JExpr
forall a b. (a -> b) -> Array Integer a -> Array Integer b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (JVal -> JExpr
ValExpr (JVal -> JExpr) -> (Ident -> JVal) -> Ident -> JExpr
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Ident -> JVal
JVar) Array Integer Ident
pushNN
pushOptimized' :: [(Id,Int)] -> G JStat
pushOptimized' :: [(Id, Int)] -> G JStat
pushOptimized' [(Id, Int)]
xs = do
[StackSlot]
slots <- G [StackSlot]
getSlots
[(JExpr, Bool)] -> G JStat
pushOptimized ([(JExpr, Bool)] -> G JStat)
-> StateT GenState IO [(JExpr, Bool)] -> G JStat
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< (((Id, Int) -> StackSlot -> StateT GenState IO (JExpr, Bool))
-> [(Id, Int)] -> [StackSlot] -> StateT GenState IO [(JExpr, Bool)]
forall (m :: * -> *) a b c.
Applicative m =>
(a -> b -> m c) -> [a] -> [b] -> m [c]
zipWithM (Id, Int) -> StackSlot -> StateT GenState IO (JExpr, Bool)
f [(Id, Int)]
xs ([StackSlot]
slots[StackSlot] -> [StackSlot] -> [StackSlot]
forall a. [a] -> [a] -> [a]
++StackSlot -> [StackSlot]
forall a. a -> [a]
repeat StackSlot
SlotUnknown))
where
f :: (Id, Int) -> StackSlot -> StateT GenState IO (JExpr, Bool)
f (Id
i1,Int
n1) StackSlot
xs2 = do
[JExpr]
xs <- Id -> G [JExpr]
varsForId Id
i1
let !id_n1 :: JExpr
id_n1 = [JExpr]
xs [JExpr] -> Int -> JExpr
forall a. HasCallStack => [a] -> Int -> a
!! (Int
n1Int -> Int -> Int
forall a. Num a => a -> a -> a
-Int
1)
case StackSlot
xs2 of
SlotId Id
i2 Int
n2 -> (JExpr, Bool) -> StateT GenState IO (JExpr, Bool)
forall a. a -> StateT GenState IO a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (JExpr
id_n1,Id
i1Id -> Id -> Bool
forall a. Eq a => a -> a -> Bool
==Id
i2Bool -> Bool -> Bool
&&Int
n1Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
==Int
n2)
StackSlot
_ -> (JExpr, Bool) -> StateT GenState IO (JExpr, Bool)
forall a. a -> StateT GenState IO a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (JExpr
id_n1,Bool
False)
pushOptimized :: [(JExpr,Bool)]
-> G JStat
pushOptimized :: [(JExpr, Bool)] -> G JStat
pushOptimized [] = JStat -> G JStat
forall a. a -> StateT GenState IO a
forall (m :: * -> *) a. Monad m => a -> m a
return JStat
forall a. Monoid a => a
mempty
pushOptimized [(JExpr, Bool)]
xs = do
Int -> G ()
dropSlots Int
l
(Int -> Int) -> G ()
modifyStackDepth (Int -> Int -> Int
forall a. Num a => a -> a -> a
+ [(JExpr, Bool)] -> Int
forall a. [a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [(JExpr, Bool)]
xs)
Bool -> JStat
go (Bool -> JStat)
-> (StgToJSConfig -> Bool) -> StgToJSConfig -> JStat
forall b c a. (b -> c) -> (a -> b) -> a -> c
. StgToJSConfig -> Bool
csInlinePush (StgToJSConfig -> JStat)
-> StateT GenState IO StgToJSConfig -> G JStat
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> StateT GenState IO StgToJSConfig
getSettings
where
go :: Bool -> JStat
go Bool
True = JStat
inlinePush
go Bool
_
| ((JExpr, Bool) -> Bool) -> [(JExpr, Bool)] -> Bool
forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
all (JExpr, Bool) -> Bool
forall a b. (a, b) -> b
snd [(JExpr, Bool)]
xs = Int -> JStat
adjSp' Int
l
| ((JExpr, Bool) -> Bool) -> [(JExpr, Bool)] -> Bool
forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
all (Bool -> Bool
not(Bool -> Bool) -> ((JExpr, Bool) -> Bool) -> (JExpr, Bool) -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
.(JExpr, Bool) -> Bool
forall a b. (a, b) -> b
snd) [(JExpr, Bool)]
xs Bool -> Bool -> Bool
&& Int
l Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
<= Int
32 =
JExpr -> [JExpr] -> JStat
ApplStat (Array Int JExpr
pushN' Array Int JExpr -> Int -> JExpr
forall i e. Ix i => Array i e -> i -> e
! Int
l) (((JExpr, Bool) -> JExpr) -> [(JExpr, Bool)] -> [JExpr]
forall a b. (a -> b) -> [a] -> [b]
map (JExpr, Bool) -> JExpr
forall a b. (a, b) -> a
fst [(JExpr, Bool)]
xs)
| Int
l Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
<= Int
8 Bool -> Bool -> Bool
&& Bool -> Bool
not ((JExpr, Bool) -> Bool
forall a b. (a, b) -> b
snd ((JExpr, Bool) -> Bool) -> (JExpr, Bool) -> Bool
forall a b. (a -> b) -> a -> b
$ [(JExpr, Bool)] -> (JExpr, Bool)
forall a. HasCallStack => [a] -> a
last [(JExpr, Bool)]
xs) =
JExpr -> [JExpr] -> JStat
ApplStat (Array Integer JExpr
pushNN' Array Integer JExpr -> Integer -> JExpr
forall i e. Ix i => Array i e -> i -> e
! Integer
sig) [ JExpr
e | (JExpr
e,Bool
False) <- [(JExpr, Bool)]
xs ]
| Bool
otherwise = JStat
inlinePush
l :: Int
l = [(JExpr, Bool)] -> Int
forall a. [a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [(JExpr, Bool)]
xs
sig :: Integer
sig :: Integer
sig = (Integer -> Integer -> Integer) -> [Integer] -> Integer
forall a. HasCallStack => (a -> a -> a) -> [a] -> a
L.foldl1' Integer -> Integer -> Integer
forall a. Bits a => a -> a -> a
(Bits..|.) ([Integer] -> Integer) -> [Integer] -> Integer
forall a b. (a -> b) -> a -> b
$ ((JExpr, Bool) -> Int -> Integer)
-> [(JExpr, Bool)] -> [Int] -> [Integer]
forall a b c. (a -> b -> c) -> [a] -> [b] -> [c]
zipWith (\(JExpr
_e,Bool
b) Int
i -> if Bool -> Bool
not Bool
b then Int -> Integer
forall a. Bits a => Int -> a
Bits.bit Int
i else Integer
0) [(JExpr, Bool)]
xs [Int
0..]
inlinePush :: JStat
inlinePush = Int -> JStat
adjSp' Int
l JStat -> JStat -> JStat
forall a. Semigroup a => a -> a -> a
<> [JStat] -> JStat
forall a. Monoid a => [a] -> a
mconcat ((Int -> (JExpr, Bool) -> JStat)
-> [Int] -> [(JExpr, Bool)] -> [JStat]
forall a b c. (a -> b -> c) -> [a] -> [b] -> [c]
zipWith Int -> (JExpr, Bool) -> JStat
pushSlot [Int
1..] [(JExpr, Bool)]
xs)
pushSlot :: Int -> (JExpr, Bool) -> JStat
pushSlot Int
i (JExpr
ex, Bool
False) = JExpr -> JExpr -> JExpr
IdxExpr JExpr
stack (Int -> JExpr
offset Int
i) JExpr -> JExpr -> JStat
|= JExpr
ex
pushSlot Int
_ (JExpr, Bool)
_ = JStat
forall a. Monoid a => a
mempty
offset :: Int -> JExpr
offset Int
i | Int
i Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
l = JExpr
sp
| Bool
otherwise = JOp -> JExpr -> JExpr -> JExpr
InfixExpr JOp
SubOp JExpr
sp (Int -> JExpr
forall a. ToJExpr a => a -> JExpr
toJExpr (Int
l Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
i))
pushLneFrame :: HasDebugCallStack => Int -> ExprCtx -> G JStat
pushLneFrame :: HasDebugCallStack => Int -> ExprCtx -> G JStat
pushLneFrame Int
size ExprCtx
ctx =
let ctx' :: ExprCtx
ctx' = ExprCtx -> Int -> ExprCtx
ctxLneShrinkStack ExprCtx
ctx Int
size
in [(Id, Int)] -> G JStat
pushOptimized' (ExprCtx -> [(Id, Int)]
ctxLneFrameVars ExprCtx
ctx')
popSkip :: Int
-> [JExpr]
-> JStat
popSkip :: Int -> [JExpr] -> JStat
popSkip Int
0 [] = JStat
forall a. Monoid a => a
mempty
popSkip Int
n [] = Int -> JStat
adjSpN' Int
n
popSkip Int
n [JExpr]
tgt = Int -> [JExpr] -> JStat
loadSkip Int
n [JExpr]
tgt JStat -> JStat -> JStat
forall a. Semigroup a => a -> a -> a
<> Int -> JStat
adjSpN' ([JExpr] -> Int
forall a. [a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [JExpr]
tgt Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
n)
loadSkip :: Int -> [JExpr] -> JStat
loadSkip :: Int -> [JExpr] -> JStat
loadSkip = JExpr -> Int -> [JExpr] -> JStat
loadSkipFrom JExpr
sp
where
loadSkipFrom :: JExpr -> Int -> [JExpr] -> JStat
loadSkipFrom :: JExpr -> Int -> [JExpr] -> JStat
loadSkipFrom JExpr
fr Int
n [JExpr]
xs = [JStat] -> JStat
forall a. Monoid a => [a] -> a
mconcat [JStat]
items
where
items :: [JStat]
items = [JStat] -> [JStat]
forall a. [a] -> [a]
reverse ([JStat] -> [JStat]) -> [JStat] -> [JStat]
forall a b. (a -> b) -> a -> b
$ (Int -> JExpr -> JStat) -> [Int] -> [JExpr] -> [JStat]
forall a b c. (a -> b -> c) -> [a] -> [b] -> [c]
zipWith Int -> JExpr -> JStat
f [(Int
0::Int)..] ([JExpr] -> [JExpr]
forall a. [a] -> [a]
reverse [JExpr]
xs)
offset :: Int -> JExpr
offset Int
0 = JExpr
fr
offset Int
n = JOp -> JExpr -> JExpr -> JExpr
InfixExpr JOp
SubOp JExpr
fr (Int -> JExpr
forall a. ToJExpr a => a -> JExpr
toJExpr Int
n)
f :: Int -> JExpr -> JStat
f Int
i JExpr
ex = JExpr
ex JExpr -> JExpr -> JStat
|= JExpr -> JExpr -> JExpr
IdxExpr JExpr
stack (JExpr -> JExpr
forall a. ToJExpr a => a -> JExpr
toJExpr (Int -> JExpr
offset (Int
iInt -> Int -> Int
forall a. Num a => a -> a -> a
+Int
n)))
popSkipI :: Int -> [(Ident,StackSlot)] -> G JStat
popSkipI :: Int -> [(Ident, StackSlot)] -> G JStat
popSkipI Int
0 [] = JStat -> G JStat
forall a. a -> StateT GenState IO a
forall (f :: * -> *) a. Applicative f => a -> f a
pure JStat
forall a. Monoid a => a
mempty
popSkipI Int
n [] = Int -> G JStat
popN Int
n
popSkipI Int
n [(Ident, StackSlot)]
xs = do
Int -> G ()
addUnknownSlots Int
n
[StackSlot] -> G ()
addSlots (((Ident, StackSlot) -> StackSlot)
-> [(Ident, StackSlot)] -> [StackSlot]
forall a b. (a -> b) -> [a] -> [b]
map (Ident, StackSlot) -> StackSlot
forall a b. (a, b) -> b
snd [(Ident, StackSlot)]
xs)
JStat
a <- Int -> G JStat
adjSpN ([(Ident, StackSlot)] -> Int
forall a. [a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [(Ident, StackSlot)]
xs Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
n)
JStat -> G JStat
forall a. a -> StateT GenState IO a
forall (m :: * -> *) a. Monad m => a -> m a
return (Int -> [Ident] -> JStat
loadSkipI Int
n (((Ident, StackSlot) -> Ident) -> [(Ident, StackSlot)] -> [Ident]
forall a b. (a -> b) -> [a] -> [b]
map (Ident, StackSlot) -> Ident
forall a b. (a, b) -> a
fst [(Ident, StackSlot)]
xs) JStat -> JStat -> JStat
forall a. Semigroup a => a -> a -> a
<> JStat
a)
loadSkipI :: Int -> [Ident] -> JStat
loadSkipI :: Int -> [Ident] -> JStat
loadSkipI = JExpr -> Int -> [Ident] -> JStat
loadSkipIFrom JExpr
sp
where loadSkipIFrom :: JExpr -> Int -> [Ident] -> JStat
loadSkipIFrom :: JExpr -> Int -> [Ident] -> JStat
loadSkipIFrom JExpr
fr Int
n [Ident]
xs = [JStat] -> JStat
forall a. Monoid a => [a] -> a
mconcat [JStat]
items
where
items :: [JStat]
items = [JStat] -> [JStat]
forall a. [a] -> [a]
reverse ([JStat] -> [JStat]) -> [JStat] -> [JStat]
forall a b. (a -> b) -> a -> b
$ (Int -> Ident -> JStat) -> [Int] -> [Ident] -> [JStat]
forall a b c. (a -> b -> c) -> [a] -> [b] -> [c]
zipWith Int -> Ident -> JStat
f [(Int
0::Int)..] ([Ident] -> [Ident]
forall a. [a] -> [a]
reverse [Ident]
xs)
offset :: Int -> JExpr
offset Int
0 = JExpr
fr
offset Int
n = JOp -> JExpr -> JExpr -> JExpr
InfixExpr JOp
SubOp JExpr
fr (Int -> JExpr
forall a. ToJExpr a => a -> JExpr
toJExpr Int
n)
f :: Int -> Ident -> JStat
f Int
i Ident
ex = Ident
ex Ident -> JExpr -> JStat
||= JExpr -> JExpr -> JExpr
IdxExpr JExpr
stack (JExpr -> JExpr
forall a. ToJExpr a => a -> JExpr
toJExpr (Int -> JExpr
offset (Int
iInt -> Int -> Int
forall a. Num a => a -> a -> a
+Int
n)))
popN :: Int -> G JStat
popN :: Int -> G JStat
popN Int
n = Int -> G ()
addUnknownSlots Int
n G () -> G JStat -> G JStat
forall a b.
StateT GenState IO a
-> StateT GenState IO b -> StateT GenState IO b
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> Int -> G JStat
adjSpN Int
n
bhStats :: StgToJSConfig -> Bool -> JStat
bhStats :: StgToJSConfig -> Bool -> JStat
bhStats StgToJSConfig
s Bool
pushUpd = [JStat] -> JStat
forall a. Monoid a => [a] -> a
mconcat
[ if Bool
pushUpd then StgToJSConfig -> [JExpr] -> JStat
push' StgToJSConfig
s [JExpr
r1, FastString -> JExpr
var FastString
"h$upd_frame"] else JStat
forall a. Monoid a => a
mempty
, StgReg -> JExpr
forall a. ToJExpr a => a -> JExpr
toJExpr StgReg
R1 JExpr -> FastString -> JExpr
.^ FastString
closureEntry_ JExpr -> JExpr -> JStat
|= FastString -> JExpr
var FastString
"h$blackhole"
, StgReg -> JExpr
forall a. ToJExpr a => a -> JExpr
toJExpr StgReg
R1 JExpr -> FastString -> JExpr
.^ FastString
closureField1_ JExpr -> JExpr -> JStat
|= FastString -> JExpr
var FastString
"h$currentThread"
, StgReg -> JExpr
forall a. ToJExpr a => a -> JExpr
toJExpr StgReg
R1 JExpr -> FastString -> JExpr
.^ FastString
closureField2_ JExpr -> JExpr -> JStat
|= JExpr
null_
]
updateThunk :: G JStat
updateThunk :: G JStat
updateThunk = do
StgToJSConfig
settings <- StateT GenState IO StgToJSConfig
getSettings
let adjPushStack :: Int -> G ()
adjPushStack :: Int -> G ()
adjPushStack Int
n = do (Int -> Int) -> G ()
modifyStackDepth (Int -> Int -> Int
forall a. Num a => a -> a -> a
+Int
n)
Int -> G ()
dropSlots Int
n
Int -> G ()
adjPushStack Int
2
JStat -> G JStat
forall a. a -> StateT GenState IO a
forall (m :: * -> *) a. Monad m => a -> m a
return (JStat -> G JStat) -> JStat -> G JStat
forall a b. (a -> b) -> a -> b
$ (StgToJSConfig -> JStat
updateThunk' StgToJSConfig
settings)
updateThunk' :: StgToJSConfig -> JStat
updateThunk' :: StgToJSConfig -> JStat
updateThunk' StgToJSConfig
settings =
if StgToJSConfig -> Bool
csInlineBlackhole StgToJSConfig
settings
then StgToJSConfig -> Bool -> JStat
bhStats StgToJSConfig
settings Bool
True
else JExpr -> [JExpr] -> JStat
ApplStat (FastString -> JExpr
var FastString
"h$bh") []