From a654e4ecace2d506d1b10f1dde2c287ebe84ef37 Mon Sep 17 00:00:00 2001 From: "Kartik K. Agaram" Date: Sat, 26 Mar 2016 23:59:59 -0700 Subject: 2812 --- html/043space.cc.html | 105 +++++++++++++++++++++++++++++++++++++------------- 1 file changed, 78 insertions(+), 27 deletions(-) (limited to 'html/043space.cc.html') diff --git a/html/043space.cc.html b/html/043space.cc.html index ab2144de..c4783e1e 100644 --- a/html/043space.cc.html +++ b/html/043space.cc.html @@ -3,29 +3,39 @@ Mu - 043space.cc - - + + - + + + + -
+
 //: Spaces help isolate recipes from each other. You can create them at will,
 //: and all addresses in arguments are implicitly based on the 'default-space'
 //: (unless they have the /raw property)
@@ -73,7 +83,7 @@ def main [
 
 //:: now implement space support
 :(before "End call Fields")
-long long int default_space;
+int default_space;
 :(before "End call Constructor")
 default_space = 0;
 
@@ -84,22 +94,22 @@ default_space = 0;
   if (is_raw(x) || is_dummy(x)) return;
   if (x.name == "default-space") return;
   if (!x.initialized) {
-    raise << to_string(current_instruction()) << ": reagent not initialized: " << x.original_string << '\n' << end();
+    raise << to_original_string(current_instruction()) << ": reagent not initialized: " << x.original_string << '\n' << end();
   }
   x.set_value(address(x.value, space_base(x)));
   x.properties.push_back(pair<string, string_tree*>("raw", NULL));
   assert(is_raw(x));
 }
 
-long long int space_base(const reagent& x) {
+int space_base(const reagent& x) {
   // temporary stub; will be replaced in a later layer
   return current_call().default_space ? (current_call().default_space+/*skip refcount*/1) : 0;
 }
 
-long long int address(long long int offset, long long int base) {
+int address(int offset, int base) {
   assert(offset >= 0);
   if (base == 0) return offset;  // raw
-  long long int size = get_or_insert(Memory, base);
+  int size = get_or_insert(Memory, base);
   if (offset >= size) {
     // todo: test
     raise << "location " << offset << " is out of bounds " << size << " at " << base << '\n' << end();
@@ -110,7 +120,7 @@ default_space = 0;
 
 //:: reads and writes to the 'default-space' variable have special behavior
 
-:(after "void write_memory(reagent x, vector<double> data)")
+:(after "void write_memory(reagent x, const vector<double>& data)")
   if (x.name == "default-space") {
     if (!scalar(data)
         || !x.type
@@ -189,8 +199,8 @@ tmp.properties.pus
 :(scenario new_default_space)
 def main [
   new-default-space
-  x:number <- copy 0
-  y:number <- copy 3
+  x:number <- copy 0
+  y:number <- copy 3
 ]
 # allocate space for x and y, as well as the chaining slot at 0
 +mem: array size is 3
@@ -216,7 +226,7 @@ def main [
       raise << "no space allocated for default-space in recipe " << current_recipe_name() << "; are you using names?\n" << end();
     return result;
   }
-:(after "void write_memory(reagent x, vector<double> data)")
+:(after "void write_memory(reagent x, const vector<double>& data)")
   if (x.name == "number-of-locals") {
     raise << maybe(current_recipe_name()) << "can't write to special name 'number-of-locals'\n" << end();
     return;
@@ -233,12 +243,21 @@ def main [
 ]
 def foo [
   local-scope
-  x:number <- copy 34
+  x:number <- copy 34
   return default-space:address:shared:array:location
 ]
 # both calls to foo should have received the same default-space
 +mem: storing 1 in location 3
 
+:(code)  // pending test
+//? :(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")
@@ -255,16 +274,47 @@ try_reclaim_locals();
 void try_reclaim_locals() {
   // only reclaim routines starting with 'local-scope'
   const recipe_ordinal r = get(Recipe_ordinal, current_recipe_name());
-  if (get(Recipe, r).steps.empty()) return;
-  const instruction& inst = get(Recipe, r).steps.at(0);
+  const recipe& exiting_recipe = get(Recipe, r);
+  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
+  // TODO: this isn't working yet. Doesn't handle address:shared stored in
+  // containers created by 'copy' or 'merge'. We'd end up deleting the address
+  // even if some container containing it was returned.
+  // This might doom our whole refcounting-based approach :/
+//?   vector<double> zero;
+//?   zero.push_back(0);
+//?   for (int i = /*leave default space for last*/1; i < SIZE(exiting_recipe.steps); ++i) {
+//?     const instruction& inst = exiting_recipe.steps.at(i);
+//?     for (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();
+    raise << to_original_string(curr) << " can't take any ingredients\n" << end();
   curr.name = "new";
   curr.ingredients.push_back(reagent("location:type"));
   curr.ingredients.push_back(reagent("number-of-locals:literal"));
@@ -305,7 +355,7 @@ Hide_missing_default_space_errors = false:(code)
 bool contains_non_special_name(const recipe_ordinal r) {
-  for (map<string, long long int>::iterator p = Name[r].begin(); p != Name[r].end(); ++p) {
+  for (map<string, int>::iterator p = Name[r].begin(); p != Name[r].end(); ++p) {
     if (p->first.empty()) continue;
     if (p->first.find("stash_") == 0) continue;  // generated by rewrite_stashes_to_text (cross-layer)
     if (!is_special_name(p->first))
@@ -322,7 +372,7 @@ Hide_missing_default_space_errors = false}
 
 bool operator<(const reagent& a, const reagent& b) {
-  long long int aspace = 0, bspace = 0;
+  int aspace = 0, bspace = 0;
   if (has_property(a, "space")) aspace = to_integer(property(a, "space")->value);
   if (has_property(b, "space")) bspace = to_integer(property(b, "space")->value);
   if (aspace != bspace) return aspace < bspace;
@@ -331,3 +381,4 @@ Hide_missing_default_space_errors = false
 
 
+
-- 
cgit 1.4.1-2-gfad0