Blackholes can be large objects (#14497)
authorSimon Marlow <marlowsd@gmail.com>
Mon, 18 Dec 2017 16:23:16 +0000 (11:23 -0500)
committerBen Gamari <ben@smart-cactus.org>
Wed, 17 Jan 2018 22:24:18 +0000 (17:24 -0500)
Test Plan: validate

Reviewers: bgamari, niteria, erikd, dfeuer

Reviewed By: dfeuer

Subscribers: Yuras, dfeuer, rwbarton, thomie, carter

GHC Trac Issues: #14497

Differential Revision: https://phabricator.haskell.org/D4254

(cherry picked from commit fb1f0a46983a887057de647eaaae9e83b5ebebd1)

rts/sm/Evac.c
testsuite/tests/rts/T14497.hs [new file with mode: 0644]
testsuite/tests/rts/T14497.stdout [new file with mode: 0644]
testsuite/tests/rts/all.T

index fb1af0f..526f063 100644 (file)
@@ -898,9 +898,16 @@ evacuate_BLACKHOLE(StgClosure **p)
 
     bd = Bdescr((P_)q);
 
-    // blackholes can't be in a compact, or large
-    ASSERT((bd->flags & (BF_COMPACT | BF_LARGE)) == 0);
-
+    // blackholes can't be in a compact
+    ASSERT((bd->flags & BF_COMPACT) == 0);
+
+    // blackholes *can* be in a large object: when raiseAsync() creates an
+    // AP_STACK the payload might be large enough to create a large object.
+    // See #14497.
+    if (bd->flags & BF_LARGE) {
+        evacuate_large((P_)q);
+        return;
+    }
     if (bd->flags & BF_EVACUATED) {
         if (bd->gen_no < gct->evac_gen_no) {
             gct->failed_to_evac = true;
diff --git a/testsuite/tests/rts/T14497.hs b/testsuite/tests/rts/T14497.hs
new file mode 100644 (file)
index 0000000..b6473f7
--- /dev/null
@@ -0,0 +1,13 @@
+module Main (main) where
+
+import System.Timeout
+
+fuc :: Integer -> Integer
+fuc 0 = 1
+fuc n = n * fuc (n - 1)
+
+main :: IO ()
+main = do
+  let x = fuc 30000
+  timeout 1000 (print x)
+  print (x > 0)
diff --git a/testsuite/tests/rts/T14497.stdout b/testsuite/tests/rts/T14497.stdout
new file mode 100644 (file)
index 0000000..0ca9514
--- /dev/null
@@ -0,0 +1 @@
+True
index d5eaa76..7c5b9c7 100644 (file)
@@ -381,3 +381,4 @@ test('T12497', [ unless(opsys('mingw32'), skip)
 test('T12903', [when(opsys('mingw32'), skip)], compile_and_run, [''])
 test('T13832', exit_code(1), compile_and_run, ['-threaded'])
 test('T13894', normal, compile_and_run, [''])
+test('T14497', normal, compile_and_run, ['-O'])