about summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorKartik K. Agaram <vc@akkartik.com>2016-06-11 10:13:40 -0700
committerKartik K. Agaram <vc@akkartik.com>2016-06-11 10:13:40 -0700
commit8eec27b624535698646fbcd2a20403c17cc79cc7 (patch)
tree3538ec149885c4dea0cb8bcd71b20552fb3e5327
parentf07659fd5eb24ad9e49fdded4dc5b85df9e43f4b (diff)
downloadmu-8eec27b624535698646fbcd2a20403c17cc79cc7.tar.gz
3047 - fix another hole in refcount management
This wouldn't have failed silently; I have that fig leaf. If someone had
tried to copy an exclusive container containing an exclusive container
containing an address Mu would have crashed on them.
-rw-r--r--036refcount.cc82
1 files changed, 56 insertions, 26 deletions
diff --git a/036refcount.cc b/036refcount.cc
index 34a59f6d..73ad8928 100644
--- a/036refcount.cc
+++ b/036refcount.cc
@@ -320,34 +320,42 @@ void append_addresses(int base_offset, const type_tree* type, map<set<tag_condit
     get_or_insert(out, key).insert(address_element_info(base_offset, new type_tree(*type->right)));
     return;
   }
-  if (info.kind == PRIMITIVE) return;
-  for (int curr_index = 0, curr_offset = base_offset; curr_index < SIZE(info.elements); ++curr_index) {
-    trace(9993, "transform") << "checking container " << type->name << ", element " << curr_index << end();
-    reagent/*copy*/ element = element_type(type, curr_index);
-    // Compute Container Address Offset(element)
-    if (is_mu_address(element)) {
-      trace(9993, "transform") << "address at offset " << curr_offset << end();
-      get_or_insert(out, key).insert(address_element_info(curr_offset, new type_tree(*element.type->right)));
-      ++curr_offset;
-    }
-    else if (is_mu_container(element)) {
-      append_addresses(curr_offset, element.type, out, key);
-      curr_offset += size_of(element);
-    }
-    else if (is_mu_exclusive_container(element)) {
-      const type_info& element_info = get(Type, element.type->value);
-      for (int tag = 0; tag < SIZE(element_info.elements); ++tag) {
-        set<tag_condition_info> new_key = key;
-        new_key.insert(tag_condition_info(curr_offset, tag));
-        set<address_element_info>& tmp = get_or_insert(out, new_key);
-        if (tmp.empty())
-          append_addresses(curr_offset+/*skip tag*/1, variant_type(element.type, tag).type, out, new_key);
+  if (info.kind == CONTAINER) {
+    for (int curr_index = 0, curr_offset = base_offset; curr_index < SIZE(info.elements); ++curr_index) {
+      trace(9993, "transform") << "checking container " << type->name << ", element " << curr_index << end();
+      reagent/*copy*/ element = element_type(type, curr_index);
+      // Compute Container Address Offset(element)
+      if (is_mu_address(element)) {
+        trace(9993, "transform") << "address at offset " << curr_offset << end();
+        get_or_insert(out, key).insert(address_element_info(curr_offset, new type_tree(*element.type->right)));
+        ++curr_offset;
+      }
+      else if (is_mu_container(element)) {
+        append_addresses(curr_offset, element.type, out, key);
+        curr_offset += size_of(element);
+      }
+      else if (is_mu_exclusive_container(element)) {
+        const type_info& element_info = get(Type, element.type->value);
+        for (int tag = 0; tag < SIZE(element_info.elements); ++tag) {
+          set<tag_condition_info> new_key = key;
+          new_key.insert(tag_condition_info(curr_offset, tag));
+          if (!contains_key(out, new_key))
+            append_addresses(curr_offset+/*skip tag*/1, variant_type(element.type, tag).type, out, new_key);
+        }
+        curr_offset += size_of(element);
+      }
+      else {
+        // non-address primitive
+        ++curr_offset;
       }
-      curr_offset += size_of(element);
     }
-    else {
-      // non-address primitive
-      ++curr_offset;
+  }
+  else if (info.kind == EXCLUSIVE_CONTAINER) {
+    for (int tag = 0; tag < SIZE(info.elements); ++tag) {
+      set<tag_condition_info> new_key = key;
+      new_key.insert(tag_condition_info(base_offset, tag));
+      if (!contains_key(out, new_key))
+        append_addresses(base_offset+/*skip tag*/1, variant_type(type, tag).type, out, new_key);
     }
   }
 }
@@ -553,6 +561,28 @@ def main [
 +run: {17: "foo"} <- copy {13: "foo"}
 +mem: incrementing refcount of 1000: 3 -> 4
 
+:(scenario refcounts_copy_exclusive_container_within_exclusive_container)
+exclusive-container foo [
+  a:number
+  b:bar
+]
+exclusive-container bar [
+  x:number
+  y:address:number
+]
+def main [
+  1:address:number <- new number:type
+  10:foo <- merge 1/b, 1/y, 1:address:number
+  20:foo <- copy 10:foo
+]
++run: {1: ("address" "number")} <- new {number: "type"}
++mem: incrementing refcount of 1000: 0 -> 1
+# no change while merging items of other types
++run: {10: "foo"} <- merge {1: "literal", "b": ()}, {1: "literal", "y": ()}, {1: ("address" "number")}
++mem: incrementing refcount of 1000: 1 -> 2
++run: {20: "foo"} <- copy {10: "foo"}
++mem: incrementing refcount of 1000: 2 -> 3
+
 :(code)
 bool is_mu_container(const reagent& r) {
   return is_mu_container(r.type);