about summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorKartik K. Agaram <vc@akkartik.com>2016-08-17 12:48:16 -0700
committerKartik K. Agaram <vc@akkartik.com>2016-08-17 12:55:37 -0700
commitccc5eb730e628801e1d021b387c8e6b8428f1ba3 (patch)
tree0bba94bb33d4549cdb385d4cf09626ff3946a3a0
parentfe4bcd7e26927488583b437120ef597f22094f76 (diff)
downloadmu-ccc5eb730e628801e1d021b387c8e6b8428f1ba3.tar.gz
3216
Another hole in refcount management, which I noticed while doing commit
3202, and thinking about which led to the insight of commit 3212.

Now the summary of commit 3197 is modified to this:

  Update refcounts of products after every instruction, EXCEPT:

    a) when instruction is a non-primitive and the callee starts with
    'local-scope' (because it's already not decremented in 'return')

  OR:

    b) when instruction is primitive 'next-ingredient' or
    'next-ingredient-without-typechecking', and its result is saved to a
    variable in the default space (because it's already incremented at
    the time of the call)
-rw-r--r--072scheduler.cc32
1 files changed, 31 insertions, 1 deletions
diff --git a/072scheduler.cc b/072scheduler.cc
index 0b0dd54f..33b75a2a 100644
--- a/072scheduler.cc
+++ b/072scheduler.cc
@@ -260,8 +260,38 @@ increment_any_refcounts(ingredient, ingredients.at(i));
 :(before "End Populate start-running Ingredient")
 increment_any_refcounts(ingredient, ingredients.at(i));
 :(before "End should_update_refcounts_in_write_memory Special-cases For Primitives")
-if (inst.operation == NEXT_INGREDIENT || inst.operation == NEXT_INGREDIENT_WITHOUT_TYPECHECKING)
+if (inst.operation == NEXT_INGREDIENT || inst.operation == NEXT_INGREDIENT_WITHOUT_TYPECHECKING) {
+  if (space_index(inst.products.at(0)) > 0) return true;
+  if (has_property(inst.products.at(0), "raw")) return true;
   return false;
+}
+
+:(scenario next_ingredient_never_leaks_refcounts)
+def create-scope n:address:number -> default-space:address:array:location [
+  default-space <- new location:type, 2
+  load-ingredients
+]
+def use-scope [
+  local-scope
+  0:address:array:location/names:create-scope <- next-ingredient
+  n:address:number/space:1 <- next-ingredient  # should decrement refcount
+  *n/space:1 <- copy 34
+  n2:number <- add *n/space:1, 1
+  reply n2
+]
+def main [
+  local-scope
+  n:address:number <- copy 12000/unsafe  # pretend allocation with a known address
+  *n <- copy 23
+  scope:address:array:location <- create-scope n
+  n2:address:number <- copy 13000/unsafe
+  n3:number <- use-scope scope, n2
+]
++run: {n: ("address" "number"), "space": "1"} <- next-ingredient
++mem: decrementing refcount of 12000: 2 -> 1
++run: {n: ("address" "number"), "space": "1", "lookup": ()} <- copy {34: "literal"}
+
+//: back to testing 'start-running'
 
 :(scenario start_running_returns_routine_id)
 def f1 [