about summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorKartik K. Agaram <vc@akkartik.com>2015-07-13 22:15:34 -0700
committerKartik K. Agaram <vc@akkartik.com>2015-07-13 22:15:34 -0700
commit84e4ed1ab58d5b34cf92919aedbb15736a7349d9 (patch)
tree2ee77491ea1bdf7e1a529d0dc4b897674ae817f8
parent83fcebf3210b638d9f8248e0007e9f0c9804980a (diff)
downloadmu-84e4ed1ab58d5b34cf92919aedbb15736a7349d9.tar.gz
1779
Now we can reclaim allocated space. But the API's suspect. I still want
to provide some sort of tree of allocations. For now we'll use this only
to reclaim default-spaces. That's next.
-rw-r--r--043new.cc86
1 files changed, 86 insertions, 0 deletions
diff --git a/043new.cc b/043new.cc
index 5600f443..d75d4bd0 100644
--- a/043new.cc
+++ b/043new.cc
@@ -170,6 +170,92 @@ recipe main [
 +new: routine allocated memory from 1000 to 1002
 +new: routine allocated memory from 1002 to 1004
 
+//: We also provide a way to return memory, and to reuse reclaimed memory.
+//: todo: custodians, etc. Following malloc/free is a temporary hack.
+
+:(scenario new_reclaim)
+recipe main [
+  1:address:number <- new number:type
+  abandon 1:address:number
+  2:address:number <- new number:type  # must be same size as abandoned memory to reuse
+  3:boolean <- equal 1:address:number, 2:address:number
+]
+# both allocations should have returned the same address
++mem: storing 1 in location 3
+
+:(before "End Globals")
+map<long long int, long long int> Free_list;
+:(before "End Setup")
+Free_list.clear();
+
+:(before "End Primitive Recipe Declarations")
+ABANDON,
+:(before "End Primitive Recipe Numbers")
+Recipe_ordinal["abandon"] = ABANDON;
+:(before "End Primitive Recipe Implementations")
+case ABANDON: {
+  if (!scalar(ingredients.at(0))) {
+    raise << "abandon's ingredient should be scalar\n";
+    break;
+  }
+  long long int address = ingredients.at(0).at(0);
+  reagent types = canonize(current_instruction().ingredients.at(0));
+  if (types.types.at(0) != Type_ordinal["address"]) {
+    raise << "abandon's ingredient should be an address\n";
+    break;
+  }
+  reagent target_type = deref(types);
+  abandon(address, size_of(target_type));
+  break;
+}
+
+:(code)
+void abandon(long long int address, long long int size) {
+//?   cerr << "abandon: " << size << '\n'; //? 1
+  // clear memory
+  for (long long int curr = address; curr < address+size; ++curr)
+    Memory[curr] = 0;
+  // append existing free list to address
+  Memory[address] = Free_list[size];
+  Free_list[size] = address;
+}
+
+:(before "ensure_space(size)" following "case NEW")
+if (Free_list[size]) {
+  long long int result = Free_list[size];
+  Free_list[size] = Memory[result];
+  for (long long int curr = result+1; curr < result+size; ++curr)
+    if (Memory[curr] != 0)
+      raise << "memory in free list was not zeroed out; somebody wrote to us after free!!!\n" << die();
+  if (SIZE(current_instruction().ingredients) > 1)
+    Memory[result] = array_length;
+  else
+    Memory[result] = 0;
+  products.resize(1);
+  products.at(0).push_back(result);
+  break;
+}
+
+:(scenario new_differing_size_no_reclaim)
+recipe main [
+  1:address:number <- new number:type
+  abandon 1:address:number
+  2:address:number <- new number:type, 2:literal  # different size
+  3:boolean <- equal 1:address:number, 2:address:number
+]
+# no reuse
++mem: storing 0 in location 3
+
+:(scenario new_reclaim_array)
+recipe main [
+  1:address:array:number <- new number:type, 2:literal
+  abandon 1:address:array:number
+  2:address:array:number <- new number:type, 2:literal
+  3:boolean <- equal 1:address:array:number, 2:address:array:number
+]
+# reuse
++mem: storing 1 in location 3
+
 //:: Next, extend 'new' to handle a unicode string literal argument.
 
 :(scenario new_string)