Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Memory relocation #36

Draft
wants to merge 152 commits into
base: main
Choose a base branch
from
Draft

Memory relocation #36

wants to merge 152 commits into from

Conversation

gabrielbosio
Copy link
Member

@gabrielbosio gabrielbosio commented Jul 27, 2023

NOTE: To merge this, #26 has to be merged.

Start with nested for loops that iterate over segments and cells.
Copy link
Member

@Oppen Oppen left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Besides the individual comments, I left a few other missing NULL checks in the output parameters of hash table and array accesses without comment, as it's generalized and I was spamming too much already.

Comment on lines +93 to +117
void runner_get_segment_sizes(cairo_runner *runner, CC_Array *segment_sizes) {
int num_segments = runner->vm.memory.num_segments;
unsigned int *zero;
for (int i = 0; i < num_segments; i++) {
zero = malloc(sizeof(unsigned int));
*zero = 0;
cc_array_add(segment_sizes, zero);
}

unsigned int *new_size;
CC_HashTableIter memory_iter;
cc_hashtable_iter_init(&memory_iter, runner->vm.memory.data);
TableEntry *entry;
while (cc_hashtable_iter_next(&memory_iter, &entry) != CC_ITER_END) {
relocatable *ptr = entry->key;
unsigned int *segment_size;
assert(cc_array_get_at(segment_sizes, ptr->segment_index, (void **)&segment_size) == CC_OK);

if (*segment_size < ptr->offset + 1) {
new_size = malloc(sizeof(unsigned int));
*new_size = ptr->offset + 1;
cc_array_replace_at(segment_sizes, new_size, ptr->segment_index, NULL);
}
}
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There are a few issues and suggestions with this function.

  1. Suggestion: store values instead of pointer, as it simplifies memory management and avoids any chance of leaks. The array doesn't dereference the pointers and the value fits in the pointer size, so you can convert the values to uintptr_t and then void *. Document it appropriately.
  2. Issue: the call to cc_array_replace_at is leaking the old value. With suggestion 1 this automatically gets fixed.
  3. Suggestion: cc_array_get_at already gives you the pointer to the value and doesn't remove it, so if you choose to keep the heap allocated values you can overwrite the value pointer by it instead, also fixing the leaks.
  4. Issue: you're not checking for NULL for segment_size before dereferencing it. If it's the first inserted value then you hit undefined behavior. You should check for NULL and store unconditionally in that case, since it's the first value you see for that segment.

Comment on lines +119 to +138
// Fills relocation table with the first relocated address of each memory segment
// Warning: Can fail if runner_initialize_main_entrypoint is not called before
void runner_fill_relocation_table(cairo_runner *runner, CC_Array *segment_sizes) {
int *first_addr = malloc(sizeof(int));
*first_addr = 1;
cc_array_add(runner->relocation_table, first_addr);
int *last_segment_size_added;
assert(cc_array_get_at(runner->relocation_table, 0, (void **)&last_segment_size_added) == CC_OK);

int relocation_table_size = runner->vm.memory.num_segments + 1;
for (int i = 1; i < relocation_table_size; i++) {
int segment_idx = i - 1;
int *segment_size;
assert(cc_array_get_at(segment_sizes, segment_idx, (void **)&segment_size) == CC_OK);
int *address = malloc(sizeof(int));
*address = *last_segment_size_added + *segment_size;
cc_array_add(runner->relocation_table, address);
assert(cc_array_get_at(runner->relocation_table, i, (void **)&last_segment_size_added) == CC_OK);
}
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Another batch of suggestions:

  1. Suggestion: rather than warn about possible errors in a comment, it may be a good idea to return an error instead.
  2. Suggestion: use values instead of heap pointers, as mentioned in the other comment.
  3. Issue: not checking segment_size for NULL.
  4. Suggestion: no need to check insertion with cc_array_get_at, you can check the output of cc_array_add instead.

int runner_get_relocated_address(cairo_runner *runner, relocatable *relocatable) {
int *address;
assert(cc_array_get_at(runner->relocation_table, relocatable->segment_index, (void **)&address) == CC_OK);
return *address + relocatable->offset;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Issue: not checking address for NULL.

return *address + relocatable->offset;
}

void runner_get_relocated_value(cairo_runner *runner, maybe_relocatable *value, felt_t out) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If we're modifying out, shouldn't it be a pointer so the caller sees the changes? Ignore this if felt_t is already defined to be a pointer.


for (int i = 0; i < num_segment_sizes; i++) {
int *segment_size;
assert(cc_array_get_at(segment_sizes, i, (void **)&segment_size) == CC_OK);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Issue: not checking segment_size for NULL.

for (int j = 0; j < *segment_size; j++) {
relocatable ptr = {i, j};
maybe_relocatable *cell;
if (cc_hashtable_get(runner->vm.memory.data, &ptr, (void **)&cell) == CC_OK) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same for cell.

src/memory.c Outdated
if (cell->is_some) {
ResultMemory ok = {.is_error = false, .value = {.memory_value = cell->memory_value.value}};
maybe_relocatable *value = NULL;
if (cc_hashtable_get(mem->data, &ptr, (void *)&value) == CC_OK) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

value could be NULL.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants