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 | |
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.
-rw-r--r-- | 030container.cc | 30 | ||||
-rw-r--r-- | 033exclusive_container.cc | 6 | ||||
-rw-r--r-- | 035lookup.cc | 4 | ||||
-rw-r--r-- | 036refcount.cc | 108 | ||||
-rw-r--r-- | 042name.cc | 2 | ||||
-rw-r--r-- | 057shape_shifting_container.cc | 6 | ||||
-rw-r--r-- | 078hash.cc | 12 |
7 files changed, 133 insertions, 35 deletions
diff --git a/030container.cc b/030container.cc index d340e131..91fb6407 100644 --- a/030container.cc +++ b/030container.cc @@ -169,53 +169,53 @@ if (t.kind == CONTAINER) { //: also store a copy in each reagent in each instruction in each recipe :(after "Begin Instruction Modifying Transforms") // needs to happen before transform_names, therefore after "End Type Modifying Transforms" below -Transform.push_back(compute_container_metadata); +Transform.push_back(compute_container_sizes); :(code) -void compute_container_metadata(recipe_ordinal r) { +void compute_container_sizes(recipe_ordinal r) { recipe& caller = get(Recipe, r); 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_metadata(inst.ingredients.at(i)); + compute_container_sizes(inst.ingredients.at(i)); for (int i = 0; i < SIZE(inst.products); ++i) - compute_container_metadata(inst.products.at(i)); + compute_container_sizes(inst.products.at(i)); } } -void compute_container_metadata(reagent& r) { +void compute_container_sizes(reagent& r) { if (is_literal(r) || is_dummy(r)) return; reagent rcopy = r; - // Compute Container Metadata(reagent rcopy) + // Compute Container Size(reagent rcopy) set<type_ordinal> pending_metadata; - compute_container_metadata(rcopy.type, pending_metadata); + compute_container_sizes(rcopy.type, pending_metadata); if (contains_key(Container_metadata, rcopy.type)) r.metadata = get(Container_metadata, rcopy.type); } -void compute_container_metadata(const type_tree* type, set<type_ordinal>& pending_metadata) { +void compute_container_sizes(const type_tree* type, set<type_ordinal>& pending_metadata) { if (!type) return; if (contains_key(pending_metadata, type->value)) return; - pending_metadata.insert(type->value); + if (type->value) pending_metadata.insert(type->value); if (contains_key(Container_metadata, type)) return; - if (type->left) compute_container_metadata(type->left, pending_metadata); - if (type->right) compute_container_metadata(type->right, pending_metadata); + if (type->left) compute_container_sizes(type->left, pending_metadata); + if (type->right) compute_container_sizes(type->right, pending_metadata); if (!contains_key(Type, type->value)) return; // error raised elsewhere type_info& info = get(Type, type->value); if (info.kind == CONTAINER) { container_metadata metadata; for (int i = 0; i < SIZE(info.elements); ++i) { reagent/*copy*/ element = info.elements.at(i); - // Compute Container Metadata(element) - compute_container_metadata(element.type, pending_metadata); + // Compute Container Size(element) + compute_container_sizes(element.type, pending_metadata); metadata.offset.push_back(metadata.size); // save previous size as offset metadata.size += size_of(element.type); } Container_metadata.push_back(pair<type_tree*, container_metadata>(new type_tree(*type), metadata)); } - // End compute_container_metadata Cases + // End compute_container_sizes Cases } -const container_metadata& get(const vector<pair<type_tree*, container_metadata> >& all, const type_tree* key) { +container_metadata& get(vector<pair<type_tree*, container_metadata> >& all, const type_tree* key) { for (int i = 0; i < SIZE(all); ++i) { if (matches(all.at(i).first, key)) return all.at(i).second; diff --git a/033exclusive_container.cc b/033exclusive_container.cc index cf55598e..3811fd03 100644 --- a/033exclusive_container.cc +++ b/033exclusive_container.cc @@ -35,7 +35,7 @@ if (t.kind == EXCLUSIVE_CONTAINER) { // Compute size_of Exclusive Container return get(Container_metadata, type).size; } -:(before "End compute_container_metadata Cases") +:(before "End compute_container_sizes Cases") if (info.kind == EXCLUSIVE_CONTAINER) { container_metadata metadata; // size of an exclusive container is the size of its largest variant @@ -43,8 +43,8 @@ if (info.kind == EXCLUSIVE_CONTAINER) { int size = 0; for (int i = 0; i < SIZE(info.elements); ++i) { reagent/*copy*/ element = info.elements.at(i); - // Compute Exclusive Container Metadata(element) - compute_container_metadata(element); + // Compute Exclusive Container Size(element) + compute_container_sizes(element.type, pending_metadata); int variant_size = size_of(element); if (variant_size > size) size = variant_size; } diff --git a/035lookup.cc b/035lookup.cc index 505b4ab7..cc83c9c9 100644 --- a/035lookup.cc +++ b/035lookup.cc @@ -143,10 +143,10 @@ canonize_type(product); canonize_type(lhs); canonize_type(rhs); -:(before "Compute Container Metadata(reagent rcopy)") +:(before "Compute Container Size(reagent rcopy)") if (!canonize_type(rcopy)) return; -:(before "Compute Container Metadata(element)") +:(before "Compute Container Size(element)") assert(!has_property(element, "lookup")); :(code) 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 diff --git a/042name.cc b/042name.cc index 583cd1dc..4857a3c5 100644 --- a/042name.cc +++ b/042name.cc @@ -18,7 +18,7 @@ def main [ +error: main: use before set: y # todo: detect conditional defines -:(after "Transform.push_back(compute_container_metadata)") // we need sizes for all types +:(after "Transform.push_back(compute_container_sizes)") Transform.push_back(transform_names); // idempotent :(before "End Globals") diff --git a/057shape_shifting_container.cc b/057shape_shifting_container.cc index 183ec36b..07848600 100644 --- a/057shape_shifting_container.cc +++ b/057shape_shifting_container.cc @@ -247,9 +247,11 @@ def main [ :(before "End element_type Special-cases") replace_type_ingredients(element, type, info); -:(before "Compute Container Metadata(element)") +:(before "Compute Container Size(element)") replace_type_ingredients(element, type, info); -:(before "Compute Exclusive Container Metadata(element)") +:(before "Compute Exclusive Container Size(element)") +replace_type_ingredients(element, type, info); +:(before "Compute Container Address Offset(element)") replace_type_ingredients(element, type, info); :(code) void replace_type_ingredients(reagent& element, const type_tree* caller_type, const type_info& info) { diff --git a/078hash.cc b/078hash.cc index 6577373d..ce63a87d 100644 --- a/078hash.cc +++ b/078hash.cc @@ -88,12 +88,6 @@ size_t hash_mu_array(size_t h, const reagent& r) { return h; } -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; -} - size_t hash_mu_container(size_t h, const reagent& r) { assert(r.type->value); type_info& info = get(Type, r.type->value); @@ -110,12 +104,6 @@ size_t hash_mu_container(size_t h, const reagent& r) { return h; } -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; -} - size_t hash_mu_exclusive_container(size_t h, const reagent& r) { assert(r.type->value); int tag = get(Memory, r.value); |