diff options
author | Kartik K. Agaram <vc@akkartik.com> | 2016-05-12 16:38:59 -0700 |
---|---|---|
committer | Kartik K. Agaram <vc@akkartik.com> | 2016-05-12 16:38:59 -0700 |
commit | 8dede22ec64fbbe59ded852592d65efb630151fe (patch) | |
tree | 4ae0272dd59b4733a91b3cd3df085ecda58da005 /036refcount.cc | |
parent | ac8acc7b05774ac5777d5a03311728fb14d3f217 (diff) | |
download | mu-8dede22ec64fbbe59ded852592d65efb630151fe.tar.gz |
2955 - back to more refcount housekeeping
Update refcounts of address elements when copying containers. Still lots to do; see todo list at end of 036refcount.cc.
Diffstat (limited to '036refcount.cc')
-rw-r--r-- | 036refcount.cc | 108 |
1 files changed, 108 insertions, 0 deletions
diff --git a/036refcount.cc b/036refcount.cc index e7d3efc1..9d2f8c99 100644 --- a/036refcount.cc +++ b/036refcount.cc @@ -160,3 +160,111 @@ def main [ :(after "Write Memory in Successful MAYBE_CONVERT") if (is_mu_address(product)) update_refcounts(get_or_insert(Memory, product.value), get_or_insert(Memory, base_address+/*skip tag*/1), payload_size(product)); + +//: manage refcounts in instructions that copy multiple locations at a time + +:(code) +:(scenario refcounts_copy_nested) +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 + 3:foo <- copy *2:address:foo +] ++run: {1: ("address" "number")} <- new {number: "type"} ++mem: incrementing refcount of 1000: 0 -> 1 ++run: {2: ("address" "foo"), "lookup": ()} <- put {2: ("address" "foo"), "lookup": ()}, {x: "offset"}, {1: ("address" "number")} ++mem: incrementing refcount of 1000: 1 -> 2 +# copying a container increments refcounts of any contained addresses ++run: {3: "foo"} <- copy {2: ("address" "foo"), "lookup": ()} ++mem: incrementing refcount of 1000: 2 -> 3 + +:(after "Types") +struct address_element_info { + int offset; // where inside a container type (after flattening nested containers!) the address lies + int payload_size; // size of type it points to + address_element_info(int o, int p) { + offset = o; + payload_size = p; + } +}; +:(before "End container_metadata Fields") +vector<address_element_info> address; // list of offsets containing addresses, and the sizes of their corresponding payloads + +//: populate metadata.address in a separate transform, because it requires +//: already knowing the sizes of all types + +:(after "Transform.push_back(compute_container_sizes)") +Transform.push_back(compute_container_address_offsets); +:(code) +void compute_container_address_offsets(const recipe_ordinal r) { + recipe& caller = get(Recipe, r); +//? cerr << "compute offsets " << caller.name <<'\n'; + for (int i = 0; i < SIZE(caller.steps); ++i) { + instruction& inst = caller.steps.at(i); + for (int i = 0; i < SIZE(inst.ingredients); ++i) + compute_container_address_offsets(inst.ingredients.at(i)); + for (int i = 0; i < SIZE(inst.products); ++i) + compute_container_address_offsets(inst.products.at(i)); + } +} +void compute_container_address_offsets(reagent& r) { + if (is_literal(r) || is_dummy(r)) return; + compute_container_address_offsets(r.type); + if (contains_key(Container_metadata, r.type)) + r.metadata = get(Container_metadata, r.type); +} +void compute_container_address_offsets(type_tree* type) { + if (!type) return; + if (type->left) compute_container_address_offsets(type->left); + if (type->right) compute_container_address_offsets(type->right); + if (!contains_key(Type, type->value)) return; // error raised elsewhere + type_info& info = get(Type, type->value); + if (info.kind == CONTAINER) { +//? cerr << " " << to_string(type) << '\n'; + container_metadata& metadata = get(Container_metadata, type); + if (!metadata.address.empty()) return; + for (int i = 0; i < SIZE(info.elements); ++i) { + reagent/*copy*/ element = info.elements.at(i); + // Compute Container Address Offset(element) + if (is_mu_address(element)) { + metadata.address.push_back(address_element_info(metadata.offset.at(i), payload_size(element))); +//? cerr << info.name << " has address at offset " << metadata.address.back().offset << '\n'; + } + } + } +} + +:(before "End write_memory(x) Special-cases") +if (is_mu_container(x)) { + // Can't recurse here because we have to worry about shape-shifting + // containers. Always go off of x.metadata rather than the global + // Container_metadata. + assert(x.metadata.size); + for (int i = 0; i < SIZE(x.metadata.address); ++i) { + const address_element_info& info = x.metadata.address.at(i); + update_refcounts(get_or_insert(Memory, x.value + info.offset), data.at(info.offset), info.payload_size); + } +} + +:(code) +bool is_mu_container(const reagent& r) { + if (r.type->value == 0) return false; + type_info& info = get(Type, r.type->value); + return info.kind == CONTAINER; +} + +bool is_mu_exclusive_container(const reagent& r) { + if (r.type->value == 0) return false; + type_info& info = get(Type, r.type->value); + return info.kind == EXCLUSIVE_CONTAINER; +} + +// todo: +// container containing container containing address +// exclusive container sometimes containing address +// container containing exclusive container sometimes containing address +// ensure the original unguarded write_memory loop is never run |