about summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorKartik K. Agaram <vc@akkartik.com>2016-06-29 10:54:18 -0700
committerKartik K. Agaram <vc@akkartik.com>2016-06-29 10:54:18 -0700
commit3be3006c78ef5ddb1bd30c01d472542a99175545 (patch)
tree0274c1760626981c7c55979974d0c0eb0a226d9c
parentd9630e06d8b520614bc263b7f0256a3baf7a6ef9 (diff)
downloadmu-3be3006c78ef5ddb1bd30c01d472542a99175545.tar.gz
3075
Back to slow progress on deep-copy.
-rw-r--r--073deep_copy.cc63
1 files changed, 56 insertions, 7 deletions
diff --git a/073deep_copy.cc b/073deep_copy.cc
index 3f4edbb5..24577f9a 100644
--- a/073deep_copy.cc
+++ b/073deep_copy.cc
@@ -31,6 +31,25 @@ def main [
 # containers are identical as long as they don't contain addresses
 +mem: storing 1 in location 10
 
+:(scenario deep_copy_address)
+def main [
+  local-scope
+  x:address:number <- new number:type
+  *x <- copy 34
+  y:address:number <- deep-copy x
+  10:boolean/raw <- equal x, y
+  11:boolean/raw <- equal *x, *y
+  y <- copy 0
+]
+# the result of deep-copy is a new address
++mem: storing 0 in location 10
+# however, the contents are identical
++mem: storing 1 in location 11
+# the result of deep-copy gets a refcount of 1
++run: {y: ("address" "number")} <- copy {0: "literal"}
++mem: decrementing refcount of 1009: 1 -> 0
++abandon: saving 1009 in free-list of size 2
+
 :(before "End Primitive Recipe Declarations")
 DEEP_COPY,
 :(before "End Primitive Recipe Numbers")
@@ -46,17 +65,23 @@ case DEEP_COPY: {
 :(before "End Primitive Recipe Implementations")
 case DEEP_COPY: {
   const reagent& input = current_instruction().ingredients.at(0);
-  products.push_back(deep_copy(input));
+  // allocate a tiny bit of temporary space for deep_copy()
+  reagent tmp("tmp:address:number");
+  tmp.value = allocate(1);
+  products.push_back(deep_copy(input, tmp));
+  // reclaim Mu memory allocated for tmp
+  abandon(tmp.value, tmp.type->right, payload_size(tmp));
+  // reclaim host memory allocated for tmp.type when tmp goes out of scope
   break;
 }
 
 :(code)
-vector<double> deep_copy(reagent/*copy*/ in) {
+vector<double> deep_copy(reagent/*copy*/ in, reagent& tmp) {
   canonize(in);
   vector<double> result;
   map<int, int> addresses_copied;
   if (is_mu_address(in))
-    result.push_back(deep_copy_address(in.value, addresses_copied));
+    result.push_back(deep_copy_address(in, addresses_copied, tmp));
   // TODO: handle arrays
   else
     deep_copy(in, addresses_copied, result);
@@ -64,11 +89,35 @@ vector<double> deep_copy(reagent/*copy*/ in) {
 }
 
 // deep-copy an address and return a new address
-int deep_copy_address(int in_address, map<int, int>& addresses_copied) {
+int deep_copy_address(reagent/*copy*/ canonized_in, map<int, int>& addresses_copied, reagent& tmp) {
+  int in_address = canonized_in.value;
   if (in_address == 0) return 0;
-  if (contains_key(addresses_copied, in_address)) return get(addresses_copied, in_address);
-  int out = 0;
-  // HERE
+  if (contains_key(addresses_copied, in_address))
+    return get(addresses_copied, in_address);
+  // TODO: what about address:address:___? Should deep-copy be doing multiple
+  // lookups? If the goal is to eliminate all common addresses, yes.
+  reagent/*copy*/ payload = canonized_in;
+  payload.properties.push_back(pair<string, string_tree*>("lookup", NULL));
+  canonize(payload);
+  int out = allocate(size_of(payload));
+  const type_info& info = get(Type, payload.type->value);
+  switch (info.kind) {
+    case PRIMITIVE: {
+      canonized_in.properties.push_back(pair<string, string_tree*>("lookup", NULL));
+      vector<double> data = read_memory(canonized_in);
+      reagent/*copy*/ out_payload = canonized_in;
+      // HACK: write_memory interface isn't ideal for this situation; we need
+      // a temporary location to help copy the payload.
+      put(Memory, tmp.value, out);
+      out_payload.value = tmp.value;
+      write_memory(out_payload, data, -1);
+      break;
+    }
+    case CONTAINER:
+      break;
+    case EXCLUSIVE_CONTAINER:
+      break;
+  }
   put(addresses_copied, in_address, out);
   return out;
 }