diff options
author | Kartik K. Agaram <vc@akkartik.com> | 2016-03-12 20:41:35 -0800 |
---|---|---|
committer | Kartik K. Agaram <vc@akkartik.com> | 2016-03-12 20:41:35 -0800 |
commit | d8f2d0b130afd96a4f4f3965686877aa0ad8c11a (patch) | |
tree | 991e34e707ae5aca2de631842d68326dd34e7b59 | |
parent | 194c4ed71d9f0843cddb61ee7235d8cba05e8855 (diff) | |
download | mu-d8f2d0b130afd96a4f4f3965686877aa0ad8c11a.tar.gz |
2767 - reclaim refcounts for local variables
This uncovered a second bug (besides 2766) -- I was manually doing the work of 'new-fake-console' inside 'assume-console' but forgetting to increment a refcount.
-rw-r--r-- | 043space.cc | 34 | ||||
-rw-r--r-- | 085scenario_console.cc | 2 |
2 files changed, 36 insertions, 0 deletions
diff --git a/043space.cc b/043space.cc index 9ccb287c..cd91bd8d 100644 --- a/043space.cc +++ b/043space.cc @@ -211,6 +211,14 @@ def foo [ # both calls to foo should have received the same default-space +mem: storing 1 in location 3 +:(scenario local_scope_frees_up_allocations) +def main [ + local-scope + x:address:shared:array:character <- new [abc] +] ++mem: clearing x:address:shared:array:character + +//: todo: do this in a transform, rather than magically in the reply instruction :(after "Falling Through End Of Recipe") try_reclaim_locals(); :(after "Starting Reply") @@ -231,10 +239,36 @@ void try_reclaim_locals() { if (exiting_recipe.steps.empty()) return; const instruction& inst = exiting_recipe.steps.at(0); if (inst.old_name != "local-scope") return; + // reclaim any local variables unless they're being returned + vector<double> zero; + zero.push_back(0); + for (long long int i = /*leave default space for last*/1; i < SIZE(exiting_recipe.steps); ++i) { + const instruction& inst = exiting_recipe.steps.at(i); + for (long long int i = 0; i < SIZE(inst.products); ++i) { + if (!is_mu_address(inst.products.at(i))) continue; + // local variables only + if (has_property(inst.products.at(i), "space")) continue; + if (has_property(inst.products.at(i), "lookup")) continue; + if (escaping(inst.products.at(i))) continue; + trace(9999, "mem") << "clearing " << inst.products.at(i).original_string << end(); + write_memory(inst.products.at(i), zero); + } + } abandon(current_call().default_space, /*refcount*/1 + /*array length*/1 + /*number-of-locals*/Name[r][""]); } +// is this reagent one of the values returned by the current (reply) instruction? +bool escaping(const reagent& r) { + // nothing escapes when you fall through past end of recipe + if (current_step_index() >= SIZE(Current_routine->steps())) return false; + for (long long i = 0; i < SIZE(current_instruction().ingredients); ++i) { + if (r == current_instruction().ingredients.at(i)) + return true; + } + return false; +} + void rewrite_default_space_instruction(instruction& curr) { if (!curr.ingredients.empty()) raise << to_string(curr) << " can't take any ingredients\n" << end(); diff --git a/085scenario_console.cc b/085scenario_console.cc index 5054753b..bba0769e 100644 --- a/085scenario_console.cc +++ b/085scenario_console.cc @@ -119,6 +119,8 @@ case ASSUME_CONSOLE: { long long int console_address = get_or_insert(Memory, CONSOLE); trace(9999, "mem") << "storing console data in " << console_address+2 << end(); put(Memory, console_address+/*skip refcount*/1+/*offset of 'data' in container 'events'*/1, event_data_address); + // increment refcount for event data + put(Memory, event_data_address, 1); break; } |