about summary refs log tree commit diff stats
path: root/035refcount.cc
diff options
context:
space:
mode:
authorKartik K. Agaram <vc@akkartik.com>2016-05-03 10:15:17 -0700
committerKartik K. Agaram <vc@akkartik.com>2016-05-03 10:15:17 -0700
commitdc9afcbd7d7f1dcfae7b9ae659ccea4944b95a29 (patch)
tree90141172495d4f607d2ac03da912b98556b6686f /035refcount.cc
parent02909fecf6fba87604ff73fe3067e43e0ad068ee (diff)
downloadmu-dc9afcbd7d7f1dcfae7b9ae659ccea4944b95a29.tar.gz
2894
Reorganize the 'address' layer and split it up before we start greatly
expanding them to manage refcounts in nested objects.
Diffstat (limited to '035refcount.cc')
-rw-r--r--035refcount.cc74
1 files changed, 74 insertions, 0 deletions
diff --git a/035refcount.cc b/035refcount.cc
new file mode 100644
index 00000000..c0256c61
--- /dev/null
+++ b/035refcount.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_4)
+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_5)
+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