Marge Bot pushed to branch master at Glasgow Haskell Compiler / GHC
Commits:
-
e2d57026
by Luite Stegeman at 2026-09-15T20:13:54-04:00
6 changed files:
- + changelog.d/T27788-js-selector
- compiler/GHC/StgToJS/Apply.hs
- compiler/GHC/StgToJS/Symbols.hs
- + testsuite/tests/javascript/T27788.hs
- + testsuite/tests/javascript/T27788.stdout
- testsuite/tests/javascript/all.T
Changes:
| 1 | +section: js-backend
|
|
| 2 | +synopsis: Fix a bug in the JavaScript backend: Entering a selector thunk whose selected field was an unevaluated thunk could duplicate work or crash the program with a type error.
|
|
| 3 | +issues: #27788
|
|
| 4 | +mrs: !16681 |
| ... | ... | @@ -1036,7 +1036,12 @@ updates s = do |
| 1036 | 1036 | [ si' |= ss' .! i
|
| 1037 | 1037 | , sir' |= (closureField2 si') `ApplExpr` [r1]
|
| 1038 | 1038 | , ifS (app "typeof" [sir'] .===. jTyObject)
|
| 1039 | - (copyClosure DontCopyCC si' sir')
|
|
| 1039 | + (ifS (isThunk sir' .||. isBlackhole sir')
|
|
| 1040 | + (mconcat [ closureInfo si' |= hdUpdThunkEntry
|
|
| 1041 | + , closureField1 si' |= sir'
|
|
| 1042 | + , closureField2 si' |= null_
|
|
| 1043 | + ])
|
|
| 1044 | + (copyClosure DontCopyCC si' sir'))
|
|
| 1040 | 1045 | (assignClosure si' $ unbox_closure sir')
|
| 1041 | 1046 | , postIncrS i
|
| 1042 | 1047 | ]
|
| ... | ... | @@ -1066,7 +1071,8 @@ updates s = do |
| 1066 | 1071 | , -- update selectors
|
| 1067 | 1072 | jwhenS ((app typeof [closureMeta updatee] .===. jTyObject) .&&. (closureMeta updatee .^ "sel"))
|
| 1068 | 1073 | ((ss |= closureMeta updatee .^ "sel")
|
| 1069 | - <> upd_loop)
|
|
| 1074 | + <> upd_loop
|
|
| 1075 | + <> (closureMeta updatee .^ "sel" |= null_))
|
|
| 1070 | 1076 | , -- overwrite the object
|
| 1071 | 1077 | ifS (app typeof [r1] .===. jTyObject)
|
| 1072 | 1078 | (mconcat [ traceRts s (jString "$upd_frame: boxed: " + ((closureInfo r1) .^ "n"))
|
| ... | ... | @@ -375,6 +375,9 @@ hdCAFsResetStr = name "h$CAFsReset" |
| 375 | 375 | hdUpdThunkEntryStr :: Ident
|
| 376 | 376 | hdUpdThunkEntryStr = name "h$upd_thunk_e"
|
| 377 | 377 | |
| 378 | +hdUpdThunkEntry :: JStgExpr
|
|
| 379 | +hdUpdThunkEntry = global (identFS hdUpdThunkEntryStr)
|
|
| 380 | + |
|
| 378 | 381 | hdAp3EntryStr :: Ident
|
| 379 | 382 | hdAp3EntryStr = name "h$ap3_e"
|
| 380 | 383 |
| 1 | +module Main where
|
|
| 2 | + |
|
| 3 | +import Control.Exception (evaluate)
|
|
| 4 | +import System.Environment (getArgs)
|
|
| 5 | + |
|
| 6 | +{-# NOINLINE mkInner #-}
|
|
| 7 | +mkInner :: Int -> (Int, Int)
|
|
| 8 | +mkInner n = (n + 1, n + 2)
|
|
| 9 | + |
|
| 10 | +{-# NOINLINE mkOuter #-}
|
|
| 11 | +mkOuter :: (Int, Int) -> Int -> ((Int, Int), Int)
|
|
| 12 | +mkOuter a n = (a, n)
|
|
| 13 | + |
|
| 14 | +main :: IO ()
|
|
| 15 | +main = do
|
|
| 16 | + n <- length <$> getArgs
|
|
| 17 | + let inner = mkInner n
|
|
| 18 | + outer = mkOuter inner n
|
|
| 19 | + (inner', _) = outer
|
|
| 20 | + (p, _) = inner
|
|
| 21 | + _ <- evaluate inner'
|
|
| 22 | + print (fst inner')
|
|
| 23 | + print (fst inner)
|
|
| 24 | + print p
|
|
| 25 | + print (snd outer) |
| 1 | +1
|
|
| 2 | +1
|
|
| 3 | +1
|
|
| 4 | +0 |
| ... | ... | @@ -28,3 +28,5 @@ test('T24744', normal, makefile_test, ['T24744']) |
| 28 | 28 | |
| 29 | 29 | test('T25633', normal, compile_and_run, [''])
|
| 30 | 30 | test('T24886', normal, compile, [''])
|
| 31 | + |
|
| 32 | +test('T27788', normal, compile_and_run, ['-O0']) |