about summary refs log tree commit diff stats
path: root/020run.cc
diff options
context:
space:
mode:
authorKartik K. Agaram <vc@akkartik.com>2017-10-22 23:14:19 -0700
committerKartik K. Agaram <vc@akkartik.com>2017-10-22 23:48:03 -0700
commit514f0e34aa25317e069d9a154fe76826829a8d88 (patch)
tree08dc4112cbac8556e8aaab59ea56181b7178a6fa /020run.cc
parentf8a6721df2a5080fe3e17c83e46678c1a4f9d006 (diff)
downloadmu-514f0e34aa25317e069d9a154fe76826829a8d88.tar.gz
4089
Clean up how we reclaim local scopes.

It used to work like this (commit 3216):

  1. 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)

  2. If a function starts with 'local-scope', force it to be reclaimed
  before each return. However, since locals may be returned, *very
  carefully* don't reclaim those. (See the logic in the old `escaping`
  and `should_update_refcount` functions.)

However, this approach had issues. We needed two separate commands for
'local-scope' (reclaim locals on exit) and 'new-default-space'
(programmer takes charge of reclaiming locals). The hard-coded
reclamation duplicated refcounting logic. In addition to adding
complexity, this implementation failed to work if a function overwrites
default-space after setting up a local-scope (the old default-space is
leaked). It also fails in the presence of continuations. Calling a
continuation more than once was guaranteed to corrupt memory (commit
3986).

After this commit, reclaiming local scopes now works like this:

  Update refcounts of products for every PRIMITIVE instruction.
  For non-primitive instructions, all the work happens in the `return`
  instruction:
    increment refcount of ingredients to `return`
      (unless -- one last bit of ugliness -- they aren't saved in the
      caller)
    decrement the refcount of the default-space
      use existing infrastructure for reclaiming as necessary
      if reclaiming default-space, first decrement refcount of each
      local
        again, use existing infrastructure for reclaiming as necessary

This commit (finally!) completes the bulk[1] of step 2 of the plan in
commit 3991. It was very hard until I gave up trying to tweak the
existing implementation and just test-drove layer 43 from scratch.

[1] There's still potential for memory corruption if we abuse
`default-space`. I should probably try to add warnings about that at
some point (todo in layer 45).
Diffstat (limited to '020run.cc')
-rw-r--r--020run.cc8
1 files changed, 3 insertions, 5 deletions
diff --git a/020run.cc b/020run.cc
index c4df88bd..d1bc77f4 100644
--- a/020run.cc
+++ b/020run.cc
@@ -95,15 +95,15 @@ void run_current_routine() {
     }
     //: used by a later layer
     if (write_products) {
-      Writing_products_of_instruction = true;
       if (SIZE(products) < SIZE(current_instruction().products)) {
         raise << SIZE(products) << " vs " << SIZE(current_instruction().products) << ": failed to write to all products in '" << to_original_string(current_instruction()) << "'\n" << end();
       }
       else {
-        for (int i = 0;  i < SIZE(current_instruction().products);  ++i)
+        for (int i = 0;  i < SIZE(current_instruction().products);  ++i) {
+          // Writing Instruction Product(i)
           write_memory(current_instruction().products.at(i), products.at(i));
+        }
       }
-      Writing_products_of_instruction = false;
     }
     // End Running One Instruction
     if (fall_through_to_next_instruction)
@@ -111,8 +111,6 @@ void run_current_routine() {
   }
   stop_running_current_routine:;
 }
-:(before "End Globals")
-bool Writing_products_of_instruction = false;
 
 :(code)
 //: hook replaced in a later layer