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 14:39:38 -0700
committerKartik K. Agaram <vc@akkartik.com>2016-05-03 14:39:38 -0700
commit191e9bb224cad7c3ea62d986a89a9aa6301c1966 (patch)
treeebc0d0020617f12442981b098100688ed6766c2b /036refcount.cc
parent5331af09d0967d7679ecf37e61ec9347460e0f03 (diff)
downloadmu-191e9bb224cad7c3ea62d986a89a9aa6301c1966.tar.gz
2897
Diffstat (limited to '036refcount.cc')
-rw-r--r--036refcount.cc74
1 files changed, 74 insertions, 0 deletions
diff --git a/036refcount.cc b/036refcount.cc
new file mode 100644
index 00000000..a3ea72f9
--- /dev/null
+++ b/036refcount.cc
@@ -0,0 +1,74 @@
+//: Update refcounts when copying addresses.
+//: The top of layer 34 has more on refcounts.
+
+:(scenario refcounts)
+def main [
+  1:address:number <- copy 1000/unsafe
+  2:address:number <- copy 1:address:number
+  1:address:number <- copy 0
+  2:address:number <- copy 0
+]
++run: {1: ("address" "number")} <- copy {1000: "literal", "unsafe": ()}
++mem: incrementing refcount of 1000: 0 -> 1
++run: {2: ("address" "number")} <- copy {1: ("address" "number")}
++mem: incrementing refcount of 1000: 1 -> 2
++run: {1: ("address" "number")} <- copy {0: "literal"}
++mem: decrementing refcount of 1000: 2 -> 1
++run: {2: ("address" "number")} <- copy {0: "literal"}
++mem: decrementing refcount of 1000: 1 -> 0
+
+:(before "End write_memory(reagent x) Special-cases")
+if (x.type->value == get(Type_ordinal, "address")) {
+  // 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);
+  // decrement refcount of old address
+  if (old_address) {
+    int old_refcount = get_or_insert(Memory, old_address);
+    trace(9999, "mem") << "decrementing refcount of " << old_address << ": " << old_refcount << " -> " << (old_refcount-1) << end();
+    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);
+  // increment refcount of new address
+  if (new_address) {
+    int new_refcount = get_or_insert(Memory, new_address);
+    assert(new_refcount >= 0);  // == 0 only when new_address == old_address
+    trace(9999, "mem") << "incrementing refcount of " << new_address << ": " << new_refcount << " -> " << (new_refcount+1) << end();
+    put(Memory, new_address, new_refcount+1);
+  }
+  // End Update Reference Count
+  return;
+}
+
+:(scenario refcounts_reflexive)
+def main [
+  1:address:number <- new number:type
+  # idempotent copies leave refcount unchanged
+  1:address:number <- copy 1:address:number
+]
++run: {1: ("address" "number")} <- new {number: "type"}
++mem: incrementing refcount of 1000: 0 -> 1
++run: {1: ("address" "number")} <- copy {1: ("address" "number")}
++mem: decrementing refcount of 1000: 1 -> 0
++mem: incrementing refcount of 1000: 0 -> 1
+
+:(scenario refcounts_call)
+def main [
+  1:address:number <- new number:type
+  # passing in addresses to recipes increments refcount
+  foo 1:address:number
+  # return does NOT yet decrement refcount; memory must be explicitly managed
+  1:address:number <- new number:type
+]
+def foo [
+  2:address:number <- next-ingredient
+]
++run: {1: ("address" "number")} <- new {number: "type"}
++mem: incrementing refcount of 1000: 0 -> 1
++run: {2: ("address" "number")} <- next-ingredient
++mem: incrementing refcount of 1000: 1 -> 2
++run: {1: ("address" "number")} <- new {number: "type"}
++mem: decrementing refcount of 1000: 2 -> 1