builtin: fix `-d debug_realloc`, add realloc_data/3
parent
ddbe57e00a
commit
125be84e3d
|
@ -86,7 +86,6 @@ fn new_array_from_c_array_no_alloc(len int, cap int, elm_size int, c_array voidp
|
|||
}
|
||||
|
||||
// Private function. Doubles array capacity if needed.
|
||||
[inline]
|
||||
fn (mut a array) ensure_cap(required int) {
|
||||
if required <= a.cap {
|
||||
return
|
||||
|
@ -98,7 +97,7 @@ fn (mut a array) ensure_cap(required int) {
|
|||
new_size := cap * a.element_size
|
||||
mut new_data := byteptr(0)
|
||||
if a.cap > 0 {
|
||||
new_data = unsafe { v_realloc(a.data, new_size) }
|
||||
new_data = unsafe { realloc_data(a.data, a.cap * a.element_size, new_size) }
|
||||
} else {
|
||||
new_data = vcalloc(new_size)
|
||||
}
|
||||
|
|
|
@ -209,31 +209,55 @@ pub fn v_realloc(b byteptr, n int) byteptr {
|
|||
C.memcpy(new_ptr, b, n)
|
||||
}
|
||||
} $else {
|
||||
$if debug_realloc ? {
|
||||
// NB: this is slower, but helps debugging memory problems.
|
||||
// The main idea is to always force reallocating:
|
||||
// 1) allocate a new memory block
|
||||
// 2) copy the old to the new
|
||||
// 3) fill the old with 0x57 (`W`)
|
||||
// 4) free the old block
|
||||
// => if there is still a pointer to the old block somewhere
|
||||
// it will point to memory that is now filled with 0x57.
|
||||
unsafe {
|
||||
new_ptr = malloc(n)
|
||||
C.memcpy(new_ptr, b, n)
|
||||
C.memset(b, 0x57, n)
|
||||
C.free(b)
|
||||
}
|
||||
} $else {
|
||||
new_ptr = unsafe { C.realloc(b, n) }
|
||||
if new_ptr == 0 {
|
||||
panic('realloc($n) failed')
|
||||
}
|
||||
new_ptr = unsafe { C.realloc(b, n) }
|
||||
if new_ptr == 0 {
|
||||
panic('realloc($n) failed')
|
||||
}
|
||||
}
|
||||
return new_ptr
|
||||
}
|
||||
|
||||
// realloc_data resizes the memory block pointed by `old_data` to `new_size`
|
||||
// bytes. `old_data` must be a pointer to an existing memory block, previously
|
||||
// allocated with `malloc`, `v_calloc` or `vcalloc`, of size `old_data`.
|
||||
// realloc_data returns a pointer to the new location of the block.
|
||||
// NB: if you know the old data size, it is preferable to call `realloc_data`,
|
||||
// instead of `v_realloc`, at least during development, because `realloc_data`
|
||||
// can make debugging easier, when you compile your program with
|
||||
// `-d debug_realloc`.
|
||||
[unsafe]
|
||||
pub fn realloc_data(old_data byteptr, old_size int, new_size int) byteptr {
|
||||
$if prealloc {
|
||||
unsafe {
|
||||
new_ptr := malloc(new_size)
|
||||
C.memcpy(new_ptr, old_data, old_size)
|
||||
return new_ptr
|
||||
}
|
||||
}
|
||||
$if debug_realloc ? {
|
||||
// NB: this is slower, but helps debugging memory problems.
|
||||
// The main idea is to always force reallocating:
|
||||
// 1) allocate a new memory block
|
||||
// 2) copy the old to the new
|
||||
// 3) fill the old with 0x57 (`W`)
|
||||
// 4) free the old block
|
||||
// => if there is still a pointer to the old block somewhere
|
||||
// it will point to memory that is now filled with 0x57.
|
||||
unsafe {
|
||||
new_ptr := malloc(new_size)
|
||||
C.memcpy(new_ptr, old_data, old_size)
|
||||
C.memset(old_data, 0x57, old_size)
|
||||
C.free(old_data)
|
||||
return new_ptr
|
||||
}
|
||||
}
|
||||
nptr := unsafe { C.realloc(old_data, new_size) }
|
||||
if nptr == 0 {
|
||||
panic('realloc_data($new_size) failed')
|
||||
}
|
||||
return nptr
|
||||
}
|
||||
|
||||
// v_calloc dynamically allocates a zeroed `n` bytes block of memory on the heap.
|
||||
// v_calloc returns a `byteptr` pointing to the memory address of the allocated space.
|
||||
pub fn v_calloc(n int) byteptr {
|
||||
|
|
|
@ -142,12 +142,14 @@ fn (d &DenseArray) has_index(i int) bool {
|
|||
// The growth-factor is roughly 1.125 `(x + (x >> 3))`
|
||||
[inline]
|
||||
fn (mut d DenseArray) expand() int {
|
||||
old_cap := d.cap
|
||||
old_size := d.slot_bytes * old_cap
|
||||
if d.cap == d.len {
|
||||
d.cap += d.cap >> 3
|
||||
unsafe {
|
||||
d.data = v_realloc(d.data, d.slot_bytes * d.cap)
|
||||
d.data = realloc_data(d.data, old_size, d.slot_bytes * d.cap)
|
||||
if d.deletes != 0 {
|
||||
d.all_deleted = v_realloc(d.all_deleted, d.cap)
|
||||
d.all_deleted = realloc_data(d.all_deleted, old_cap, d.cap)
|
||||
C.memset(d.all_deleted + d.len, 0, d.cap - d.len)
|
||||
}
|
||||
}
|
||||
|
@ -185,9 +187,10 @@ fn (mut d DenseArray) zeros_to_end() {
|
|||
free(d.all_deleted)
|
||||
}
|
||||
d.len = count
|
||||
old_cap := d.cap
|
||||
d.cap = if count < 8 { 8 } else { count }
|
||||
unsafe {
|
||||
d.data = v_realloc(d.data, d.slot_bytes * d.cap)
|
||||
d.data = realloc_data(d.data, d.slot_bytes * old_cap, d.slot_bytes * d.cap)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -406,10 +409,12 @@ fn (mut m map) meta_greater(_index u32, _metas u32, kvi u32) {
|
|||
[inline]
|
||||
fn (mut m map) ensure_extra_metas(probe_count u32) {
|
||||
if (probe_count << 1) == m.extra_metas {
|
||||
size_of_u32 := sizeof(u32)
|
||||
old_mem_size := (m.even_index + 2 + m.extra_metas)
|
||||
m.extra_metas += extra_metas_inc
|
||||
mem_size := (m.even_index + 2 + m.extra_metas)
|
||||
unsafe {
|
||||
x := v_realloc(byteptr(m.metas), int(sizeof(u32) * mem_size))
|
||||
x := realloc_data(byteptr(m.metas), int(size_of_u32 * old_mem_size), int(size_of_u32 * mem_size))
|
||||
m.metas = &u32(x)
|
||||
C.memset(m.metas + mem_size - extra_metas_inc, 0, int(sizeof(u32) * extra_metas_inc))
|
||||
}
|
||||
|
@ -477,6 +482,7 @@ fn (mut m map) expand() {
|
|||
fn (mut m map) rehash() {
|
||||
meta_bytes := sizeof(u32) * (m.even_index + 2 + m.extra_metas)
|
||||
unsafe {
|
||||
// TODO: use realloc_data here too
|
||||
x := v_realloc(byteptr(m.metas), int(meta_bytes))
|
||||
m.metas = &u32(x)
|
||||
C.memset(m.metas, 0, meta_bytes)
|
||||
|
|
|
@ -445,6 +445,7 @@ pub fn get_raw_stdin() []byte {
|
|||
$if windows {
|
||||
unsafe {
|
||||
block_bytes := 512
|
||||
mut old_size := block_bytes
|
||||
mut buf := malloc(block_bytes)
|
||||
h_input := C.GetStdHandle(C.STD_INPUT_HANDLE)
|
||||
mut bytes_read := 0
|
||||
|
@ -456,7 +457,9 @@ pub fn get_raw_stdin() []byte {
|
|||
if !res {
|
||||
break
|
||||
}
|
||||
buf = v_realloc(buf, offset + block_bytes + (block_bytes - bytes_read))
|
||||
new_size := offset + block_bytes + (block_bytes - bytes_read)
|
||||
buf = realloc_data(buf, old_size, new_size)
|
||||
old_size = new_size
|
||||
}
|
||||
return array{
|
||||
element_size: 1
|
||||
|
|
Loading…
Reference in New Issue