From 9cb52cf1af9c9c77b461ed5af97baf1cf56981e2 Mon Sep 17 00:00:00 2001 From: Simon Tatham Date: Tue, 16 Jul 2019 21:10:02 +0100 Subject: [PATCH] vala: avoid half-constructed vectors being garbage-collected. The clause in eval_ast() which evaluates each element of an input vector into an output vector was holding the intermediate results in an ordinary GLib.List, and putting them all into a vector at the end of the evaluation. But that meant that nothing was preventing all those values from being garbage-collected half way through. Now we make an output Mal.Vector at the start of the process, and point a GC.Root at it to ensure it stays around until we've finished putting items in it. This fixes the vala part of #418, I think. --- vala/step2_eval.vala | 11 ++++++----- vala/step3_env.vala | 11 ++++++----- vala/step4_if_fn_do.vala | 11 ++++++----- vala/step5_tco.vala | 11 ++++++----- vala/step6_file.vala | 11 ++++++----- vala/step7_quote.vala | 11 ++++++----- vala/step8_macros.vala | 11 ++++++----- vala/step9_try.vala | 11 ++++++----- vala/stepA_mal.vala | 11 ++++++----- 9 files changed, 54 insertions(+), 45 deletions(-) diff --git a/vala/step2_eval.vala b/vala/step2_eval.vala index fec151503a..f62e8806a2 100644 --- a/vala/step2_eval.vala +++ b/vala/step2_eval.vala @@ -101,11 +101,12 @@ class Mal.Main : GLib.Object { return result; } if (ast is Mal.Vector) { - var results = new GLib.List(); - for (var iter = (ast as Mal.Vector).iter(); - iter.nonempty(); iter.step()) - results.append(EVAL(iter.deref(), env)); - return new Mal.Vector.from_list(results); + var vec = ast as Mal.Vector; + var result = new Mal.Vector.with_size(vec.length); + var root = new GC.Root(result); (void)root; + for (var i = 0; i < vec.length; i++) + result[i] = EVAL(vec[i], env); + return result; } if (ast is Mal.Hashmap) { var result = new Mal.Hashmap(); diff --git a/vala/step3_env.vala b/vala/step3_env.vala index bfced742ba..429b5b17db 100644 --- a/vala/step3_env.vala +++ b/vala/step3_env.vala @@ -83,11 +83,12 @@ class Mal.Main : GLib.Object { return result; } if (ast is Mal.Vector) { - var results = new GLib.List(); - for (var iter = (ast as Mal.Vector).iter(); - iter.nonempty(); iter.step()) - results.append(EVAL(iter.deref(), env)); - return new Mal.Vector.from_list(results); + var vec = ast as Mal.Vector; + var result = new Mal.Vector.with_size(vec.length); + var root = new GC.Root(result); (void)root; + for (var i = 0; i < vec.length; i++) + result[i] = EVAL(vec[i], env); + return result; } if (ast is Mal.Hashmap) { var result = new Mal.Hashmap(); diff --git a/vala/step4_if_fn_do.vala b/vala/step4_if_fn_do.vala index 13ab98aa2a..93d09c3f58 100644 --- a/vala/step4_if_fn_do.vala +++ b/vala/step4_if_fn_do.vala @@ -38,11 +38,12 @@ class Mal.Main: GLib.Object { return result; } if (ast is Mal.Vector) { - var results = new GLib.List(); - for (var iter = (ast as Mal.Vector).iter(); - iter.nonempty(); iter.step()) - results.append(EVAL(iter.deref(), env)); - return new Mal.Vector.from_list(results); + var vec = ast as Mal.Vector; + var result = new Mal.Vector.with_size(vec.length); + var root = new GC.Root(result); (void)root; + for (var i = 0; i < vec.length; i++) + result[i] = EVAL(vec[i], env); + return result; } if (ast is Mal.Hashmap) { var result = new Mal.Hashmap(); diff --git a/vala/step5_tco.vala b/vala/step5_tco.vala index d944f4ab25..c29a31fd6d 100644 --- a/vala/step5_tco.vala +++ b/vala/step5_tco.vala @@ -38,11 +38,12 @@ class Mal.Main : GLib.Object { return result; } if (ast is Mal.Vector) { - var results = new GLib.List(); - for (var iter = (ast as Mal.Vector).iter(); - iter.nonempty(); iter.step()) - results.append(EVAL(iter.deref(), env)); - return new Mal.Vector.from_list(results); + var vec = ast as Mal.Vector; + var result = new Mal.Vector.with_size(vec.length); + var root = new GC.Root(result); (void)root; + for (var i = 0; i < vec.length; i++) + result[i] = EVAL(vec[i], env); + return result; } if (ast is Mal.Hashmap) { var result = new Mal.Hashmap(); diff --git a/vala/step6_file.vala b/vala/step6_file.vala index 23979477fd..3bdd83c96e 100644 --- a/vala/step6_file.vala +++ b/vala/step6_file.vala @@ -52,11 +52,12 @@ class Mal.Main : GLib.Object { return result; } if (ast is Mal.Vector) { - var results = new GLib.List(); - for (var iter = (ast as Mal.Vector).iter(); - iter.nonempty(); iter.step()) - results.append(EVAL(iter.deref(), env)); - return new Mal.Vector.from_list(results); + var vec = ast as Mal.Vector; + var result = new Mal.Vector.with_size(vec.length); + var root = new GC.Root(result); (void)root; + for (var i = 0; i < vec.length; i++) + result[i] = EVAL(vec[i], env); + return result; } if (ast is Mal.Hashmap) { var result = new Mal.Hashmap(); diff --git a/vala/step7_quote.vala b/vala/step7_quote.vala index 57739e1f02..4fc745f914 100644 --- a/vala/step7_quote.vala +++ b/vala/step7_quote.vala @@ -52,11 +52,12 @@ class Mal.Main : GLib.Object { return result; } if (ast is Mal.Vector) { - var results = new GLib.List(); - for (var iter = (ast as Mal.Vector).iter(); - iter.nonempty(); iter.step()) - results.append(EVAL(iter.deref(), env)); - return new Mal.Vector.from_list(results); + var vec = ast as Mal.Vector; + var result = new Mal.Vector.with_size(vec.length); + var root = new GC.Root(result); (void)root; + for (var i = 0; i < vec.length; i++) + result[i] = EVAL(vec[i], env); + return result; } if (ast is Mal.Hashmap) { var result = new Mal.Hashmap(); diff --git a/vala/step8_macros.vala b/vala/step8_macros.vala index 099562e544..8c0088cb6c 100644 --- a/vala/step8_macros.vala +++ b/vala/step8_macros.vala @@ -52,11 +52,12 @@ class Mal.Main : GLib.Object { return result; } if (ast is Mal.Vector) { - var results = new GLib.List(); - for (var iter = (ast as Mal.Vector).iter(); - iter.nonempty(); iter.step()) - results.append(EVAL(iter.deref(), env)); - return new Mal.Vector.from_list(results); + var vec = ast as Mal.Vector; + var result = new Mal.Vector.with_size(vec.length); + var root = new GC.Root(result); (void)root; + for (var i = 0; i < vec.length; i++) + result[i] = EVAL(vec[i], env); + return result; } if (ast is Mal.Hashmap) { var result = new Mal.Hashmap(); diff --git a/vala/step9_try.vala b/vala/step9_try.vala index 155690caee..f6d5222d58 100644 --- a/vala/step9_try.vala +++ b/vala/step9_try.vala @@ -53,11 +53,12 @@ class Mal.Main : GLib.Object { return result; } if (ast is Mal.Vector) { - var results = new GLib.List(); - for (var iter = (ast as Mal.Vector).iter(); - iter.nonempty(); iter.step()) - results.append(EVAL(iter.deref(), env)); - return new Mal.Vector.from_list(results); + var vec = ast as Mal.Vector; + var result = new Mal.Vector.with_size(vec.length); + var root = new GC.Root(result); (void)root; + for (var i = 0; i < vec.length; i++) + result[i] = EVAL(vec[i], env); + return result; } if (ast is Mal.Hashmap) { var result = new Mal.Hashmap(); diff --git a/vala/stepA_mal.vala b/vala/stepA_mal.vala index 46eab4d266..349c607840 100644 --- a/vala/stepA_mal.vala +++ b/vala/stepA_mal.vala @@ -53,11 +53,12 @@ class Mal.Main : GLib.Object { return result; } if (ast is Mal.Vector) { - var results = new GLib.List(); - for (var iter = (ast as Mal.Vector).iter(); - iter.nonempty(); iter.step()) - results.append(EVAL(iter.deref(), env)); - return new Mal.Vector.from_list(results); + var vec = ast as Mal.Vector; + var result = new Mal.Vector.with_size(vec.length); + var root = new GC.Root(result); (void)root; + for (var i = 0; i < vec.length; i++) + result[i] = EVAL(vec[i], env); + return result; } if (ast is Mal.Hashmap) { var result = new Mal.Hashmap();