about summary refs log tree commit diff stats
path: root/036refcount.cc
diff options
context:
space:
mode:
authorKartik K. Agaram <vc@akkartik.com>2016-05-03 17:38:33 -0700
committerKartik K. Agaram <vc@akkartik.com>2016-05-03 17:38:33 -0700
commit6e793202e3dd9a89b88ab291cebbcb788337c592 (patch)
tree964576ac4bca556076c5fe09c4f0323f6e78f774 /036refcount.cc
parent191e9bb224cad7c3ea62d986a89a9aa6301c1966 (diff)
downloadmu-6e793202e3dd9a89b88ab291cebbcb788337c592.tar.gz
2898 - start filling in missing refcounts
This commit covers instructions 'put', 'put-index' and 'maybe-convert'.
Next up are the harder ones: 'copy' and 'merge'. In these cases there's
a non-scalar being copied, and we need to figure out which locations
within it need to update their refcount.
Diffstat (limited to '036refcount.cc')
-rw-r--r--036refcount.cc97
1 files changed, 91 insertions, 6 deletions
diff --git a/036refcount.cc b/036refcount.cc
index a3ea72f9..939490ac 100644
--- a/036refcount.cc
+++ b/036refcount.cc
@@ -18,11 +18,17 @@ def main [
 +mem: decrementing refcount of 1000: 1 -> 0
 
 :(before "End write_memory(reagent x) Special-cases")
-if (x.type->value == get(Type_ordinal, "address")) {
+if (is_mu_address(x)) {
   // compute old address of x, as well as new address we want to write in
-  int old_address = get_or_insert(Memory, x.value);
   assert(scalar(data));
-  int new_address = data.at(0);
+  write_memory_updating_refcounts(x, data.at(0));
+  return;
+}
+:(code)
+// variant of write_memory for addresses
+void write_memory_updating_refcounts(const reagent& canonized_loc, int new_address) {
+  assert(is_mu_address(canonized_loc));
+  int old_address = get_or_insert(Memory, canonized_loc.value);
   // decrement refcount of old address
   if (old_address) {
     int old_refcount = get_or_insert(Memory, old_address);
@@ -30,8 +36,13 @@ if (x.type->value == get(Type_ordinal, "address")) {
     put(Memory, old_address, old_refcount-1);
   }
   // perform the write
-  trace(9999, "mem") << "storing " << no_scientific(data.at(0)) << " in location " << x.value << end();
-  put(Memory, x.value, new_address);
+  trace(9999, "mem") << "storing " << no_scientific(new_address) << " in location " << canonized_loc.value << end();
+  if (!canonized_loc.value) {
+    tb_shutdown();
+    DUMP("");
+    exit(0);
+  }
+  put(Memory, canonized_loc.value, new_address);
   // increment refcount of new address
   if (new_address) {
     int new_refcount = get_or_insert(Memory, new_address);
@@ -40,7 +51,6 @@ if (x.type->value == get(Type_ordinal, "address")) {
     put(Memory, new_address, new_refcount+1);
   }
   // End Update Reference Count
-  return;
 }
 
 :(scenario refcounts_reflexive)
@@ -72,3 +82,78 @@ def foo [
 +mem: incrementing refcount of 1000: 1 -> 2
 +run: {1: ("address" "number")} <- new {number: "type"}
 +mem: decrementing refcount of 1000: 2 -> 1
+
+//: fix up any instructions that don't follow the usual flow of read_memory
+//: before the RUN switch, and write_memory after
+
+:(scenario refcounts_put)
+container foo [
+  x:address:number
+]
+def main [
+  1:address:number <- new number:type
+  2:address:foo <- new foo:type
+  *2:address:foo <- put *2:address:foo, x:offset, 1:address:number
+]
++run: {1: ("address" "number")} <- new {number: "type"}
++mem: incrementing refcount of 1000: 0 -> 1
++run: {2: ("address" "foo")} <- new {foo: "type"}
++mem: incrementing refcount of 1002: 0 -> 1
++run: {2: ("address" "foo"), "lookup": ()} <- put {2: ("address" "foo"), "lookup": ()}, {x: "offset"}, {1: ("address" "number")}
+# put increments refcount
++mem: incrementing refcount of 1000: 1 -> 2
+
+:(after "Write Memory in PUT in Run")
+reagent element = element_type(base.type, offset);
+assert(!has_property(element, "lookup"));
+element.value = address;
+if (is_mu_address(element)) {
+  write_memory_updating_refcounts(element, ingredients.at(2).at(0));
+  goto finish_instruction;
+}
+
+:(scenario refcounts_put_index)
+def main [
+  1:address:number <- new number:type
+  # fake array because we can't yet create an array of addresses (wait for the
+  # support for dilated reagents and parsing more complex type trees)
+  1003:number/raw <- copy 3  # skip refcount at 1002
+  2:address:array:address:number <- copy 1002/unsafe
+  *2:address:array:address:number <- put-index *2:address:array:address:number, 0, 1:address:number
+]
++run: {1: ("address" "number")} <- new {number: "type"}
++mem: incrementing refcount of 1000: 0 -> 1
++run: {2: ("address" "array" "address" "number")} <- copy {1002: "literal", "unsafe": ()}
++mem: incrementing refcount of 1002: 0 -> 1
++run: {2: ("address" "array" "address" "number"), "lookup": ()} <- put-index {2: ("address" "array" "address" "number"), "lookup": ()}, {0: "literal"}, {1: ("address" "number")}
+# put-index increments refcount
++mem: incrementing refcount of 1000: 1 -> 2
+
+:(after "Write Memory in PUT_INDEX in Run")
+if (is_mu_address(element)) {
+  write_memory_updating_refcounts(element, value.at(0));
+  goto finish_instruction;
+}
+
+:(scenario refcounts_maybe_convert)
+exclusive-container foo [
+  x:number
+  p:address:number
+]
+def main [
+  1:address:number <- new number:type
+  2:foo <- merge 1/p, 1:address:number
+  4:address:number, 5:boolean <- maybe-convert 2:foo, p:variant
+]
++run: {1: ("address" "number")} <- new {number: "type"}
++mem: incrementing refcount of 1000: 0 -> 1
++run: {2: "foo"} <- merge {1: "literal", "p": ()}, {1: ("address" "number")}
++run: {4: ("address" "number")}, {5: "boolean"} <- maybe-convert {2: "foo"}, {p: "variant"}
+# maybe-convert increments refcount on success
++mem: incrementing refcount of 1000: 1 -> 2
+
+:(after "Write Memory in Successful MAYBE_CONVERT")
+if (is_mu_address(product)) {
+  write_memory_updating_refcounts(product, get_or_insert(Memory, base_address+/*skip tag*/1));
+  goto finish_instruction;
+}