diff options
author | Kartik Agaram <vc@akkartik.com> | 2018-06-15 22:16:09 -0700 |
---|---|---|
committer | Kartik Agaram <vc@akkartik.com> | 2018-06-15 22:16:09 -0700 |
commit | ce9b2b0515eaf92a9c68c8608fd9bf392c941d50 (patch) | |
tree | eb1899f86308c712e54ef94a1c85243c26621c45 /034address.cc | |
parent | 0edd9b9fc60440213e4df926ea511419ee291f1e (diff) | |
download | mu-ce9b2b0515eaf92a9c68c8608fd9bf392c941d50.tar.gz |
4258 - undo 4257
Diffstat (limited to '034address.cc')
-rw-r--r-- | 034address.cc | 85 |
1 files changed, 21 insertions, 64 deletions
diff --git a/034address.cc b/034address.cc index 94c930bd..bce51b2e 100644 --- a/034address.cc +++ b/034address.cc @@ -18,37 +18,6 @@ //: write to the payload of an ingredient rather than its value, simply add //: the /lookup property to it. Modern computers provide efficient support for //: addresses and lookups, making this a realistic feature. -//: -//: To create addresses and allocate memory exclusively for their use, use -//: 'new'. Memory is a finite resource so if the computer can't satisfy your -//: request, 'new' may return a 0 (null) address. -//: -//: Computers these days have lots of memory so in practice we can often -//: assume we'll never run out. If you start running out however, say in a -//: long-running program, you'll need to switch mental gears and start -//: husbanding our memory more carefully. The most important tool to avoid -//: wasting memory is to 'abandon' an address when you don't need it anymore. -//: That frees up the memory allocated to it to be reused in future calls to -//: 'new'. - -//: Since memory can be reused multiple times, it can happen that you have a -//: stale copy to an address that has since been abandoned and reused. Using -//: the stale address is almost never safe, but it can be very hard to track -//: down such copies because any errors caused by them may occur even millions -//: of instructions after the copy or abandon instruction. To help track down -//: such issues, Mu tracks an 'alloc id' for each allocation it makes. The -//: first call to 'new' has an alloc id of 1, the second gets 2, and so on. -//: The alloc id is never reused. -:(before "End Globals") -long long Next_alloc_id = 0; -:(before "End Reset") -Next_alloc_id = 0; - -//: The 'new' instruction records alloc ids both in the memory being allocated -//: and *also* in the address. The 'abandon' instruction clears alloc ids in -//: both places as well. Tracking alloc ids in this manner allows us to raise -//: errors about stale addresses much earlier: 'lookup' operations always -//: compare alloc ids between the address and its payload. //: todo: give 'new' a custodian ingredient. Following malloc/free is a temporary hack. @@ -57,30 +26,28 @@ Next_alloc_id = 0; # should get back different results def main [ 1:address:num/raw <- new number:type - 3:address:num/raw <- new number:type - 5:bool/raw <- equal 1:address:num/raw, 3:address:num/raw + 2:address:num/raw <- new number:type + 3:bool/raw <- equal 1:address:num/raw, 2:address:num/raw ] -+mem: storing 1000 in location 2 +mem: storing 0 in location 3 :(scenario new_array) # call 'new' with a second ingredient to allocate an array of some type rather than a single copy def main [ 1:address:array:num/raw <- new number:type, 5 - 3:address:num/raw <- new number:type - 5:num/raw <- subtract 3:address:num/raw, 1:address:array:num/raw + 2:address:num/raw <- new number:type + 3:num/raw <- subtract 2:address:num/raw, 1:address:array:num/raw ] +run: {1: ("address" "array" "number"), "raw": ()} <- new {number: "type"}, {5: "literal"} +mem: array length is 5 -+mem: storing 1000 in location 2 # don't forget the extra location for array length -+mem: storing 7 in location 5 ++mem: storing 6 in location 3 :(scenario dilated_reagent_with_new) def main [ 1:address:address:num <- new {(address number): type} ] -+new: size of '(address number)' is 2 ++new: size of '(address number)' is 1 //: 'new' takes a weird 'type' as its first ingredient; don't error on it :(before "End Mu Types Initialization") @@ -184,13 +151,6 @@ def main [ ] $error: 0 -:(scenario equal_result_of_new_with_null) -def main [ - 1:&:num <- new num:type - 10:bool <- equal 1:&:num, 0 -] -+mem: storing 0 in location 10 - //: To implement 'new', a Mu transform turns all 'new' instructions into //: 'allocate' instructions that precompute the amount of memory they want to //: allocate. @@ -261,18 +221,15 @@ case ALLOCATE: { int result = allocate(size); if (SIZE(current_instruction().ingredients) > 1) { // initialize array length - trace("mem") << "storing array length " << ingredients.at(1).at(0) << " in location " << result+/*skip alloc id*/1 << end(); - put(Memory, result+/*skip alloc id*/1, ingredients.at(1).at(0)); + trace("mem") << "storing " << ingredients.at(1).at(0) << " in location " << result << end(); + put(Memory, result, ingredients.at(1).at(0)); } products.resize(1); - products.at(0).push_back(0); products.at(0).push_back(result); break; } :(code) int allocate(int size) { - // include space for alloc id - ++size; trace("mem") << "allocating size " << size << end(); //? Total_alloc += size; //? ++Num_alloc; @@ -333,41 +290,41 @@ def main [ :(scenario new_size) def main [ 11:address:num/raw <- new number:type - 13:address:num/raw <- new number:type - 15:num/raw <- subtract 13:address:num/raw, 11:address:num/raw + 12:address:num/raw <- new number:type + 13:num/raw <- subtract 12:address:num/raw, 11:address:num/raw ] -# size of number + alloc id -+mem: storing 2 in location 15 +# size of number ++mem: storing 1 in location 13 :(scenario new_array_size) def main [ 1:address:array:num/raw <- new number:type, 5 - 3:address:num/raw <- new number:type - 5:num/raw <- subtract 3:address:num/raw, 1:address:array:num/raw + 2:address:num/raw <- new number:type + 3:num/raw <- subtract 2:address:num/raw, 1:address:array:num/raw ] # 5 locations for array contents + array length -+mem: storing 7 in location 5 ++mem: storing 6 in location 3 :(scenario new_empty_array) def main [ 1:address:array:num/raw <- new number:type, 0 - 3:address:num/raw <- new number:type - 5:num/raw <- subtract 3:address:num/raw, 1:address:array:num/raw + 2:address:num/raw <- new number:type + 3:num/raw <- subtract 2:address:num/raw, 1:address:array:num/raw ] +run: {1: ("address" "array" "number"), "raw": ()} <- new {number: "type"}, {0: "literal"} +mem: array length is 0 # one location for array length -+mem: storing 2 in location 5 ++mem: storing 1 in location 3 //: If a routine runs out of its initial allocation, it should allocate more. :(scenario new_overflow) -% Initial_memory_per_routine = 3; // barely enough room for point allocation below +% Initial_memory_per_routine = 2; // barely enough room for point allocation below def main [ 1:address:num/raw <- new number:type 2:address:point/raw <- new point:type # not enough room in initial page ] -+new: routine allocated memory from 1000 to 1003 -+new: routine allocated memory from 1003 to 1006 ++new: routine allocated memory from 1000 to 1002 ++new: routine allocated memory from 1002 to 1004 :(scenario new_without_ingredient) % Hide_errors = true; |