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.
This commit is contained in:
Kartik Agaram 2018-06-24 10:23:27 -07:00
parent d82c16098e
commit 3ecee22a8a
3 changed files with 58 additions and 5 deletions

View File

@ -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 [

View File

@ -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();

View File

@ -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'