Fixed leaks in Array.reverse and Array.swap.

This commit is contained in:
Erik Svedäng 2018-03-12 14:37:53 +01:00
parent f4d84c80fc
commit b5ab5cebca
4 changed files with 80 additions and 26 deletions

View File

@ -124,22 +124,22 @@
(defn repeat [n f]
(let-do [a (allocate n)]
(for [i 0 n] (aset! &a i (f)))
(for [i 0 n] (aset-uninitialized! &a i (f)))
a))
(defn repeat-indexed [n f]
(let-do [a (allocate n)]
(for [i 0 n] (aset! &a i (f i)))
(for [i 0 n] (aset-uninitialized! &a i (f i)))
a))
(defn replicate [n e]
(let-do [a (allocate n)]
(for [i 0 n] (aset! &a i @e))
(for [i 0 n] (aset-uninitialized! &a i @e))
a))
(defn copy-map [f a]
(let-do [na (allocate (count a))]
(for [i 0 (count a)]
(aset! &na i (f (nth a i))))
(aset-uninitialized! &na i (f (nth a i))))
na))
)

View File

@ -170,23 +170,56 @@ templateRaw = defineTemplate
(\(FuncTy [arrayType] _) -> [])
templateAset :: (String, Binder)
templateAset = defineTemplate
(SymPath ["Array"] "aset")
(FuncTy [StructTy "Array" [VarTy "t"], IntTy, VarTy "t"] (StructTy "Array" [VarTy "t"]))
(toTemplate "Array $NAME (Array a, int n, $t newValue)")
(toTemplate $ unlines ["$DECL {"
," #ifndef OPTIMIZE"
," assert(n >= 0);"
," assert(n < a.len);"
," #endif"
," (($t*)a.data)[n] = newValue;"
," return a;"
,"}"])
(\(FuncTy [arrayType, _, _] _) -> [])
templateAset = defineTypeParameterizedTemplate templateCreator path t
where path = SymPath ["Array"] "aset"
t = (FuncTy [StructTy "Array" [VarTy "t"], IntTy, VarTy "t"] (StructTy "Array" [VarTy "t"]))
templateCreator = TemplateCreator $
\typeEnv env ->
Template
t
(\_ -> toTemplate $ "Array $NAME (Array a, int n, $t newValue)")
(\(FuncTy [_, _, insideTy] _) ->
let deleter = insideArrayDeletion typeEnv env insideTy
in toTemplate $ unlines ["$DECL {"
," #ifndef OPTIMIZE"
," assert(n >= 0);"
," assert(n < a.len);"
," #endif"
, deleter "n"
," (($t*)a.data)[n] = newValue;"
," return a;"
,"}"])
(\(FuncTy [_, _, insideTy] _) ->
depsForDeleteFunc typeEnv env insideTy)
templateAsetBang :: (String, Binder)
templateAsetBang = defineTypeParameterizedTemplate templateCreator path t
where path = (SymPath ["Array"] "aset!")
t = (FuncTy [RefTy (StructTy "Array" [VarTy "t"]), IntTy, VarTy "t"] UnitTy)
templateCreator = TemplateCreator $
\typeEnv env ->
Template
t
(const (toTemplate "void $NAME (Array *aRef, int n, $t newValue)"))
(\(FuncTy [_, _, insideTy] _) ->
let deleter = insideArrayDeletion typeEnv env insideTy
in (toTemplate $ unlines ["$DECL {"
," Array a = *aRef;"
," #ifndef OPTIMIZE"
," assert(n >= 0);"
," assert(n < a.len);"
," #endif"
, deleter "n"
," (($t*)a.data)[n] = newValue;"
,"}"]))
(\(FuncTy [(RefTy arrayType), _, _] _) ->
depsForDeleteFunc typeEnv env arrayType)
-- | This function can set uninitialized memory in an array (used together with 'allocate').
-- | It will NOT try to free the value that is alredy at location 'n'.
templateAsetUninitializedBang :: (String, Binder)
templateAsetUninitializedBang = defineTypeParameterizedTemplate templateCreator path t
where path = (SymPath ["Array"] "aset-uninitialized!")
t = (FuncTy [RefTy (StructTy "Array" [VarTy "t"]), IntTy, VarTy "t"] UnitTy)
templateCreator = TemplateCreator $
\typeEnv env ->
@ -201,8 +234,7 @@ templateAsetBang = defineTypeParameterizedTemplate templateCreator path t
," #endif"
," (($t*)a.data)[n] = newValue;"
,"}"]))
(\(FuncTy [(RefTy arrayType), _, _] _) ->
depsForDeleteFunc typeEnv env arrayType)
(const [])
templateCount :: (String, Binder)
templateCount = defineTypeParameterizedTemplate templateCreator path t

View File

@ -41,6 +41,7 @@ arrayModule = Env { envBindings = bindings, envParent = Nothing, envModuleName =
, templateRaw
, templateAset
, templateAsetBang
, templateAsetUninitializedBang
, templateCount
, templatePushBack
, templatePopBack

View File

@ -116,6 +116,14 @@
(do (set! r &t) ;; Here the set variable is a ref.
())))
(defn set-me [s]
(do (for [i 0 10]
(set! s @"other"))
s))
(defn setting-5 []
(let [s @""]
(assert (= @"other" (set-me s)))))
(def g1 @"Hello")
@ -174,6 +182,11 @@
(branch-in-let false))
(defn array-aset []
(let [xs [@"a" @"b" @"c"]]
(do (aset! &xs 0 @"q")
(assert (= &[@"q" @"b" @"c"] &xs)))))
(defn append-ref [a b]
(String.append @a @b))
@ -218,11 +231,16 @@
(let [xs [@"a" @"b" @"c" @"d" @"e"]]
(assert (= &[@"c" @"d"] &(Array.subarray &xs 2 4)))))
(defn array-reverse []
(defn array-reverse-1 []
(let [xs [@"a" @"b" @"c" @"d" @"e"]]
(assert (= &[@"e" @"d" @"c" @"b" @"a"]
&(Array.reverse xs)))))
(defn array-reverse-2 []
(let [xs [@"a" @"b" @"c" @"d" @"e" @"f" @"g" @"h" @"i" @"j"]]
(assert (= &[@"j" @"i" @"h" @"g" @"f" @"e" @"d" @"c" @"b" @"a"]
&(Array.reverse xs)))))
(defn array-index-of []
(let [xs [@"a" @"b" @"c" @"d" @"e"]]
(assert (= 2 (Array.index-of &xs @"c")))))
@ -320,6 +338,7 @@
(assert-no-leak test setting-2 "setting-2 does not leak")
(assert-no-leak test setting-3 "setting-3 does not leak")
(assert-no-leak test setting-4 "setting-4 does not leak")
(assert-no-leak test setting-5 "setting-5 does not leak")
(assert-no-leak test global-1 "global-1 does not leak")
(assert-no-leak test global-2 "global-2 does not leak")
(assert-no-leak test if-1 "if-1 does not leak")
@ -328,6 +347,7 @@
(assert-no-leak test if-4 "if-4 does not leak")
(assert-no-leak test if-5 "if-5 does not leak")
(assert-no-leak test if-6 "if-6 does not leak")
(assert-no-leak test array-aset "array-aset does not leak")
(assert-no-leak test array-reduce "array-reduce does not leak")
(assert-no-leak test array-first "array-first does not leak")
(assert-no-leak test array-last "array-last does not leak")
@ -337,15 +357,16 @@
(assert-no-leak test array-minimum "array-minimum does not leak")
(assert-no-leak test array-sum "array-sum does not leak")
(assert-no-leak test array-subarray "array-subarray does not leak")
;; LEAKS! (assert-no-leak test array-reverse "array-reverse does not leak")
(assert-no-leak test array-reverse-1 "array-reverse-2 does not leak")
(assert-no-leak test array-reverse-2 "array-reverse-2 does not leak")
(assert-no-leak test array-index-of "array-index-of does not leak")
(assert-no-leak test array-element-count "array-element-count does not leak")
;; LEAKS! (assert-no-leak test array-aupdate "array-aupdate does not leak")
;; LEAKS! (assert-no-leak test array-aupdate! "array-aupdate! does not leak")
;; LEAKS! (assert-no-leak test array-swap "array-swap does not leak")
;; LEAKS! (assert-no-leak test array-swap! "array-swap! does not leak")
;; (assert-no-leak test array-aupdate "array-aupdate does not leak")
;; (assert-no-leak test array-aupdate! "array-aupdate! does not leak")
(assert-no-leak test array-swap "array-swap does not leak")
(assert-no-leak test array-swap! "array-swap! does not leak")
(assert-no-leak test array-range "array-range does not leak")
;; (assert-no-leak test array-sort-1 "array-sort-1 does not leak")
;; PROBLEMATIC (assert-no-leak test array-sort-1 "array-sort-1 does not leak")
(assert-no-leak test array-sort-2 "array-sort-2 does not leak")
(assert-no-leak test array-repeat "array-repeat does not leak")
(assert-no-leak test array-replicate "array-replicate does not leak")