Skip to content

Commit 9578ef5

Browse files
committed
fix(memory): refs to globals are not inside-function ref sources
1 parent 0d354aa commit 9578ef5

2 files changed

Lines changed: 34 additions & 1 deletion

File tree

src/Memory.hs

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -715,7 +715,7 @@ addToLifetimesMappingsIfRef internal xobj =
715715
pure ()
716716
where
717717
makeLifetimeMode =
718-
if internal
718+
if internal && not refTargetIsGlobal
719719
then
720720
LifetimeInsideFunction $
721721
Set.fromList
@@ -724,6 +724,13 @@ addToLifetimesMappingsIfRef internal xobj =
724724
_ -> varOfXObj xobj
725725
]
726726
else LifetimeOutsideFunction
727+
refTargetIsGlobal =
728+
case xobj of
729+
XObj (Lst [XObj Ref _ _, target]) _ _ ->
730+
isGlobalFunc target || isGlobalVariable target
731+
_ -> False
732+
isGlobalVariable (XObj (Sym _ (LookupGlobal _ _)) _ _) = True
733+
isGlobalVariable _ = False
727734
mergeLifetimeMode LifetimeOutsideFunction LifetimeOutsideFunction = LifetimeOutsideFunction
728735
mergeLifetimeMode (LifetimeInsideFunction a) (LifetimeInsideFunction b) = LifetimeInsideFunction (Set.union a b)
729736
mergeLifetimeMode (LifetimeInsideFunction a) LifetimeOutsideFunction = LifetimeMixed a
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
(load "Test.carp")
2+
(use Test)
3+
4+
; Regression test: a reference to a global function (e.g. `&str` passed to
5+
; copy-map) inside a while/for body used to fail the memory checker's second
6+
; pass over the loop with "reference isn't alive".
7+
8+
(deftype T (A [Long]) (B []))
9+
(defmodule T
10+
(defn str [t]
11+
(match @t
12+
(T.A i) (Long.str i)
13+
(T.B) @"b"))
14+
(implements str T.str))
15+
16+
(defn join-in-loop []
17+
(let-do [acc []]
18+
(for [i 0 2]
19+
(set! acc (Array.push-back acc (Array.join ", " &(Array.copy-map &str &[(T.A 1l) (T.B)])))))
20+
(Array.join "; " &acc)))
21+
22+
(deftest test
23+
(assert-equal test
24+
"1, b; 1, b"
25+
&(join-in-loop)
26+
"refs to global functions inside loops stay alive"))

0 commit comments

Comments
 (0)