diff options
author | Kartik Agaram <vc@akkartik.com> | 2018-06-24 10:23:27 -0700 |
---|---|---|
committer | Kartik Agaram <vc@akkartik.com> | 2018-06-24 10:23:27 -0700 |
commit | 3ecee22a8a440b5f299729cbe49aede7e270c67c (patch) | |
tree | 2a756da343d10cc5e533cea3aa64d7574fa036d8 | |
parent | d82c16098e4f7454b79ee4cad6393949d6f32b18 (diff) | |
download | mu-3ecee22a8a440b5f299729cbe49aede7e270c67c.tar.gz |
4269 - start validating alloc-ids on lookup
Seems incredible that this is all it took. Needs more testing. I also need to rethink how we organize our layers about addresses. Alloc-id stuff is scattered everywhere. The space for alloc-ids is perhaps unavoidably scattered. Just assume the layout from the start. But it seems bad that the scenario testing the lookup-time validation is in the 'abandon' layer when the code is in the 'lookup' layer.
-rw-r--r-- | 034address.cc | 24 | ||||
-rw-r--r-- | 035lookup.cc | 1 | ||||
-rw-r--r-- | 037abandon.cc | 38 |
3 files changed, 58 insertions, 5 deletions
diff --git a/034address.cc b/034address.cc index 6c4bdda4..a71f5194 100644 --- a/034address.cc +++ b/034address.cc @@ -255,19 +255,24 @@ put(Recipe_ordinal, "allocate", ALLOCATE); case ALLOCATE: { // compute the space we need int size = ingredients.at(0).at(0); + int alloc_id = Next_alloc_id; + Next_alloc_id++; if (SIZE(ingredients) > 1) { // array allocation trace("mem") << "array length is " << ingredients.at(1).at(0) << end(); size = /*space for length*/1 + size*ingredients.at(1).at(0); } int result = allocate(size); + // initialize alloc-id in payload + trace("mem") << "storing alloc-id " << alloc_id << " in location " << result << end(); + put(Memory, result, alloc_id); 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)); } products.resize(1); - products.at(0).push_back(/*alloc id*/0); + products.at(0).push_back(alloc_id); products.at(0).push_back(result); break; } @@ -331,6 +336,23 @@ def main [ 1:&:num <- new num:type ] +mem: storing 0 in location 10 ++mem: storing 0 in location 11 ++mem: storing 10 in location 2 + +:(scenario new_initializes_alloc_id) +% Memory_allocated_until = 10; +% put(Memory, Memory_allocated_until, 1); +% Next_alloc_id = 23; +def main [ + 1:&:num <- new num:type +] +# initialize memory ++mem: storing 0 in location 10 ++mem: storing 0 in location 11 +# alloc-id in payload ++mem: storing alloc-id 23 in location 10 +# alloc-id in address ++mem: storing 23 in location 1 :(scenario new_size) def main [ diff --git a/035lookup.cc b/035lookup.cc index 3b9ae6a2..02c2ab3f 100644 --- a/035lookup.cc +++ b/035lookup.cc @@ -102,6 +102,7 @@ void lookup_memory_core(reagent& x, bool check_for_null) { // validate alloc-id double alloc_id_in_address = get_or_insert(Memory, x.value); double alloc_id_in_payload = get_or_insert(Memory, new_value); +//? cerr << x.value << ": " << alloc_id_in_address << " vs " << new_value << ": " << alloc_id_in_payload << '\n'; if (alloc_id_in_address != alloc_id_in_payload) { raise << maybe(current_recipe_name()) << "address is already abandoned in '" << to_original_string(current_instruction()) << "'\n" << end(); dump_callstack(); diff --git a/037abandon.cc b/037abandon.cc index ca7c242c..c2b9125e 100644 --- a/037abandon.cc +++ b/037abandon.cc @@ -14,6 +14,18 @@ def main [ //: When abandoning addresses we'll save them to a 'free list', segregated by size. +//: Before, suppose variable V contains address A which points to payload P: +//: location V contains an alloc-id N +//: location V+1 contains A +//: location A contains alloc-id N +//: location A+1 onwards contains P +//: Additionally, suppose the head of the free list is initially F. +//: After abandoning: +//: location V contains invalid alloc-id -1 +//: location V+1 contains 0 +//: location A contains invalid alloc-id N +//: location A+1 contains the previous head of free-list F + :(before "End routine Fields") map<int, int> free_list; @@ -40,18 +52,23 @@ case ABANDON: { reagent/*copy*/ ingredient = current_instruction().ingredients.at(i); canonize(ingredient); abandon(get_or_insert(Memory, ingredient.value+/*skip alloc id*/1), payload_size(ingredient)); +//? cerr << "clear after abandon: " << ingredient.value << '\n'; + put(Memory, /*alloc id*/ingredient.value, /*invalid*/-1); + put(Memory, /*address*/ingredient.value+1, 0); } break; } :(code) void abandon(int address, int payload_size) { - // clear memory - for (int curr = address; curr < address+payload_size; ++curr) + put(Memory, address, /*invalid alloc-id*/-1); +//? cerr << "abandon: " << address << '\n'; + // clear rest of payload + for (int curr = address+1; curr < address+payload_size; ++curr) put(Memory, curr, 0); // append existing free list to address trace("abandon") << "saving " << address << " in free-list of size " << payload_size << end(); - put(Memory, address, get_or_insert(Current_routine->free_list, payload_size)); + put(Memory, address+/*skip invalid alloc-id*/1, get_or_insert(Current_routine->free_list, payload_size)); put(Current_routine->free_list, payload_size, address); } @@ -66,8 +83,11 @@ if (get_or_insert(Current_routine->free_list, size)) { trace("abandon") << "picking up space from free-list of size " << size << end(); int result = get_or_insert(Current_routine->free_list, size); trace("mem") << "new alloc from free list: " << result << end(); - put(Current_routine->free_list, size, get_or_insert(Memory, result)); + put(Current_routine->free_list, size, get_or_insert(Memory, result+/*skip alloc id*/1)); + // clear 'deleted' tag put(Memory, result, 0); + // clear next pointer + put(Memory, result+/*skip alloc id*/1, 0); for (int curr = result; curr < result+size; ++curr) { if (get_or_insert(Memory, curr) != 0) { raise << maybe(current_recipe_name()) << "memory in free list was not zeroed out: " << curr << '/' << result << "; somebody wrote to us after free!!!\n" << end(); @@ -100,3 +120,13 @@ def main [ ] # both calls to new returned identical addresses +mem: storing 1 in location 50 + +:(scenario lookup_of_abandoned_address_raises_error) +% Hide_errors = true; +def main [ + 1:&:num <- new num:type + 3:&:num <- copy 1:&:num + abandon 1:&:num + 5:num/raw <- copy *3:&:num +] ++error: main: address is already abandoned in '5:num/raw <- copy *3:&:num' |