From 8eec27b624535698646fbcd2a20403c17cc79cc7 Mon Sep 17 00:00:00 2001 From: "Kartik K. Agaram" Date: Sat, 11 Jun 2016 10:13:40 -0700 Subject: 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. --- 036refcount.cc | 82 +++++++++++++++++++++++++++++++++++++++------------------- 1 file 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, mapright))); 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 new_key = key; - new_key.insert(tag_condition_info(curr_offset, tag)); - set& 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 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 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); -- cgit 1.4.1-2-gfad0