fix(wasm): realloc should handle smaller new size
This commit is contained in:
parent
6c05cdfb0c
commit
e6ad0683ca
2 changed files with 1201 additions and 1154 deletions
|
|
@ -14,6 +14,7 @@ extern void tree_sitter_debug_message(const char *, size_t);
|
|||
|
||||
#define PAGESIZE 0x10000
|
||||
#define MAX_HEAP_SIZE (4 * 1024 * 1024)
|
||||
#define MIN(a, b) ((a) < (b) ? (a) : (b))
|
||||
|
||||
typedef struct {
|
||||
size_t size;
|
||||
|
|
@ -118,18 +119,41 @@ void *realloc(void *ptr, size_t new_size) {
|
|||
return malloc(new_size);
|
||||
}
|
||||
|
||||
// Per the C standard, realloc(ptr, 0) acts like free(ptr) and returns NULL.
|
||||
if (new_size == 0) {
|
||||
free(ptr);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
Region *region = region_for_ptr(ptr);
|
||||
Region *region_end = region_after(region, region->size);
|
||||
|
||||
// When reallocating the last allocated region, return
|
||||
// the same pointer, and skip copying the data.
|
||||
if (region_end == next) {
|
||||
next = region;
|
||||
return malloc(new_size);
|
||||
// grow the heap and update last region's size so we do not need to copy data
|
||||
Region *new_region_end = region_after(region, new_size);
|
||||
if (new_region_end > heap_end) {
|
||||
if ((char *)new_region_end - (char *)heap_start > MAX_HEAP_SIZE) {
|
||||
return NULL;
|
||||
}
|
||||
if (!grow_heap(new_size)) return NULL;
|
||||
heap_end = get_heap_end();
|
||||
}
|
||||
|
||||
region->size = new_size;
|
||||
next = new_region_end;
|
||||
return ptr;
|
||||
}
|
||||
|
||||
void *result = malloc(new_size);
|
||||
memcpy(result, ®ion->data, region->size);
|
||||
if (result == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
size_t copy_size = MIN(region->size, new_size);
|
||||
memcpy(result, ®ion->data, copy_size);
|
||||
free(ptr);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
Loading…
Add table
Add a link
Reference in a new issue