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:
parent
d82c16098e
commit
3ecee22a8a
|
@ -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 [
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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'
|
||||
|
|
Loading…
Reference in New Issue