mirror of
https://github.com/vlang/v.git
synced 2023-08-10 21:13:21 +03:00
builtin: use dlmalloc for -freestanding
(#13054)
This commit is contained in:
@ -21,22 +21,8 @@ pub const (
|
||||
n_tree_bins = 32
|
||||
small_bin_shift = 3
|
||||
tree_bin_shift = 8
|
||||
default_granularity = 64 * 1024
|
||||
default_trim_threshold = 2 * 1024 * 1024
|
||||
|
||||
max_release_check_rate = 4095
|
||||
malloc_alignment = sizeof(usize) * 2
|
||||
chunk_overhead = sizeof(usize)
|
||||
mmap_chnk_overhead = 2 * sizeof(usize)
|
||||
min_large_size = 1 << tree_bin_shift
|
||||
max_small_size = min_large_size - 1
|
||||
max_small_request = max_small_size - (malloc_alignment - 1) - chunk_overhead
|
||||
min_chunk_size = align_up(sizeof(Chunk), malloc_alignment)
|
||||
chunk_mem_offset = 2 * sizeof(usize)
|
||||
min_request = min_chunk_size - chunk_overhead - 1
|
||||
top_foot_size = align_offset_usize(chunk_mem_offset) + pad_request(sizeof(Segment)) +
|
||||
min_chunk_size
|
||||
max_request = calc_max_request()
|
||||
mmap_foot_pad = 4 * sizeof(usize)
|
||||
)
|
||||
|
||||
fn usize_leading_zeros(x usize) usize {
|
||||
@ -47,14 +33,85 @@ fn usize_leading_zeros(x usize) usize {
|
||||
}
|
||||
}
|
||||
|
||||
[inline]
|
||||
fn default_granularity() usize {
|
||||
return 64 * 1024
|
||||
}
|
||||
|
||||
[inline]
|
||||
fn default_trim_threshold() usize {
|
||||
return 2 * 1024 * 1024
|
||||
}
|
||||
|
||||
[inline]
|
||||
fn malloc_alignment() usize {
|
||||
return sizeof(usize) * 2
|
||||
}
|
||||
|
||||
[inline]
|
||||
fn chunk_overhead() usize {
|
||||
return sizeof(usize)
|
||||
}
|
||||
|
||||
[inline]
|
||||
fn min_large_size() usize {
|
||||
return 1 << dlmalloc.tree_bin_shift
|
||||
}
|
||||
|
||||
[inline]
|
||||
fn mmap_chunk_overhead() usize {
|
||||
return 2 * sizeof(usize)
|
||||
}
|
||||
|
||||
[inline]
|
||||
fn max_small_size() usize {
|
||||
return min_large_size() - 1
|
||||
}
|
||||
|
||||
[inline]
|
||||
fn max_small_request() usize {
|
||||
return max_small_size() - (malloc_alignment() - 1) - chunk_overhead()
|
||||
}
|
||||
|
||||
[inline]
|
||||
fn min_chunk_size() usize {
|
||||
return align_up(sizeof(Chunk), malloc_alignment())
|
||||
}
|
||||
|
||||
[inline]
|
||||
fn chunk_mem_offset() usize {
|
||||
return 2 * sizeof(usize)
|
||||
}
|
||||
|
||||
[inline]
|
||||
fn min_request() usize {
|
||||
return min_chunk_size() - chunk_overhead() - 1
|
||||
}
|
||||
|
||||
[inline]
|
||||
fn top_foot_size() usize {
|
||||
return align_offset_usize(chunk_mem_offset()) + pad_request(sizeof(Segment)) + min_chunk_size()
|
||||
}
|
||||
|
||||
[inline]
|
||||
fn max_request() usize {
|
||||
return calc_max_request()
|
||||
}
|
||||
|
||||
[inline]
|
||||
fn mmap_foot_pad() usize {
|
||||
return 4 * sizeof(usize)
|
||||
}
|
||||
|
||||
fn min_sys_alloc_space() usize {
|
||||
return ((~0 - (dlmalloc.default_granularity + dlmalloc.top_foot_size +
|
||||
dlmalloc.malloc_alignment) + 1) & ~dlmalloc.malloc_alignment) - dlmalloc.chunk_overhead + 1
|
||||
return ((~0 - (default_granularity() + top_foot_size() + malloc_alignment()) +
|
||||
1) & ~malloc_alignment()) - chunk_overhead() + 1
|
||||
}
|
||||
|
||||
fn calc_max_request() usize {
|
||||
x := min_sys_alloc_space()
|
||||
y := (~dlmalloc.min_chunk_size + 1) << 2
|
||||
y := (~min_chunk_size() + 1) << 2
|
||||
|
||||
if x < y {
|
||||
return x
|
||||
} else {
|
||||
@ -63,15 +120,15 @@ fn calc_max_request() usize {
|
||||
}
|
||||
|
||||
fn pad_request(amt usize) usize {
|
||||
return align_up(amt + dlmalloc.chunk_overhead, dlmalloc.malloc_alignment)
|
||||
return align_up(amt + chunk_overhead(), malloc_alignment())
|
||||
}
|
||||
|
||||
fn align_offset_usize(addr usize) usize {
|
||||
return align_up(addr, dlmalloc.malloc_alignment) - addr
|
||||
return align_up(addr, malloc_alignment()) - addr
|
||||
}
|
||||
|
||||
fn is_aligned(a usize) bool {
|
||||
return a & (dlmalloc.malloc_alignment - 1) == 0
|
||||
return a & (malloc_alignment() - 1) == 0
|
||||
}
|
||||
|
||||
fn is_small(s usize) bool {
|
||||
@ -110,13 +167,13 @@ fn leftshift_for_tree_index(x u32) u32 {
|
||||
[unsafe]
|
||||
fn align_as_chunk(ptr_ voidptr) &Chunk {
|
||||
ptr := usize(ptr_)
|
||||
chunk := ptr + dlmalloc.chunk_mem_offset
|
||||
chunk := ptr + chunk_mem_offset()
|
||||
return &Chunk(ptr + align_offset_usize(chunk))
|
||||
}
|
||||
|
||||
fn request_2_size(req usize) usize {
|
||||
if req < dlmalloc.min_request {
|
||||
return dlmalloc.min_chunk_size
|
||||
if req < min_request() {
|
||||
return min_chunk_size()
|
||||
} else {
|
||||
return pad_request(req)
|
||||
}
|
||||
@ -124,9 +181,9 @@ fn request_2_size(req usize) usize {
|
||||
|
||||
fn overhead_for(c &Chunk) usize {
|
||||
if c.mmapped() {
|
||||
return dlmalloc.mmap_chnk_overhead
|
||||
return mmap_chunk_overhead()
|
||||
} else {
|
||||
return dlmalloc.chunk_overhead
|
||||
return chunk_overhead()
|
||||
}
|
||||
}
|
||||
|
||||
@ -148,6 +205,7 @@ pub struct Allocator {
|
||||
|
||||
pub struct Dlmalloc {
|
||||
system_allocator Allocator
|
||||
max_request usize = 4294901657
|
||||
mut:
|
||||
// bin maps
|
||||
smallmap u32 // bin map for small bins
|
||||
@ -157,8 +215,8 @@ mut:
|
||||
treebins [n_tree_bins]&TreeChunk
|
||||
dvsize usize
|
||||
topsize usize
|
||||
dv &Chunk
|
||||
top &Chunk
|
||||
dv &Chunk = voidptr(0)
|
||||
top &Chunk = voidptr(0)
|
||||
footprint usize
|
||||
max_footprint usize
|
||||
seg Segment
|
||||
@ -184,6 +242,7 @@ pub fn new(system_allocator Allocator) Dlmalloc {
|
||||
least_addr: voidptr(0)
|
||||
release_checks: 0
|
||||
system_allocator: system_allocator
|
||||
max_request: 4294901657
|
||||
}
|
||||
}
|
||||
|
||||
@ -215,14 +274,17 @@ mut:
|
||||
}
|
||||
|
||||
const (
|
||||
pinuse = 1 << 0
|
||||
cinuse = 1 << 1
|
||||
flag4 = 1 << 2
|
||||
inuse = pinuse | cinuse
|
||||
flag_bits = pinuse | cinuse | flag4
|
||||
fencepost_head = inuse | sizeof(usize)
|
||||
pinuse = 1 << 0
|
||||
cinuse = 1 << 1
|
||||
flag4 = 1 << 2
|
||||
inuse = pinuse | cinuse
|
||||
flag_bits = pinuse | cinuse | flag4
|
||||
)
|
||||
|
||||
fn fencepost_head() usize {
|
||||
return dlmalloc.inuse | sizeof(usize)
|
||||
}
|
||||
|
||||
fn (c &Chunk) size() usize {
|
||||
return c.head & ~dlmalloc.flag_bits
|
||||
}
|
||||
@ -300,12 +362,12 @@ fn (c &Chunk) minus_offset(offset usize) &Chunk {
|
||||
}
|
||||
|
||||
fn (c &Chunk) to_mem() voidptr {
|
||||
return voidptr(usize(c) + dlmalloc.chunk_mem_offset)
|
||||
return voidptr(usize(c) + chunk_mem_offset())
|
||||
}
|
||||
|
||||
fn chunk_from_mem(mem_ voidptr) &Chunk {
|
||||
mem := usize(mem_)
|
||||
return &Chunk((mem - dlmalloc.chunk_mem_offset))
|
||||
return &Chunk((mem - chunk_mem_offset()))
|
||||
}
|
||||
|
||||
fn (tree &TreeChunk) leftmost_child() &TreeChunk {
|
||||
@ -485,6 +547,7 @@ fn (mut dl Dlmalloc) unlink_large_chunk(chunk_ &TreeChunk) {
|
||||
fn (mut dl Dlmalloc) unlink_first_small_chunk(head_ &Chunk, next_ &Chunk, idx u32) {
|
||||
mut next := next_
|
||||
mut head := head_
|
||||
|
||||
mut ptr := next.prev
|
||||
if head == ptr {
|
||||
unsafe { dl.clear_smallmap(idx) }
|
||||
@ -512,12 +575,15 @@ pub fn (mut dl Dlmalloc) calloc(size usize) voidptr {
|
||||
pub fn (mut dl Dlmalloc) free_(mem voidptr) {
|
||||
unsafe {
|
||||
mut p := chunk_from_mem(mem)
|
||||
|
||||
mut psize := p.size()
|
||||
next := p.plus_offset(psize)
|
||||
|
||||
if !p.pinuse() {
|
||||
prevsize := p.prev_foot
|
||||
|
||||
if p.mmapped() {
|
||||
psize += prevsize + dlmalloc.mmap_foot_pad
|
||||
psize += prevsize + mmap_foot_pad()
|
||||
if dl.system_allocator.free_(dl.system_allocator.data, voidptr(usize(p) - prevsize),
|
||||
psize)
|
||||
{
|
||||
@ -531,7 +597,7 @@ pub fn (mut dl Dlmalloc) free_(mem voidptr) {
|
||||
p = prev
|
||||
if voidptr(p) != voidptr(dl.dv) {
|
||||
dl.unlink_chunk(p, prevsize)
|
||||
} else if next.head & dlmalloc.inuse == dlmalloc.inuse {
|
||||
} else if (next.head & dlmalloc.inuse) == dlmalloc.inuse {
|
||||
dl.dvsize = psize
|
||||
p.set_free_with_pinuse(psize, next)
|
||||
return
|
||||
@ -596,10 +662,10 @@ fn (mut dl Dlmalloc) sys_trim(pad_ usize) bool {
|
||||
unsafe {
|
||||
mut pad := pad_
|
||||
mut released := usize(0)
|
||||
if pad < dlmalloc.max_request && !isnil(dl.top) {
|
||||
pad += dlmalloc.top_foot_size
|
||||
if pad < dl.max_request && !isnil(dl.top) {
|
||||
pad += top_foot_size()
|
||||
if dl.topsize > pad {
|
||||
unit := usize(dlmalloc.default_granularity)
|
||||
unit := usize(default_granularity)
|
||||
extra := ((dl.topsize - pad + unit - 1) / unit - 1) * unit
|
||||
mut sp := dl.segment_holding(dl.top)
|
||||
|
||||
@ -653,7 +719,7 @@ fn (mut dl Dlmalloc) release_unused_segments() usize {
|
||||
mut p := align_as_chunk(base)
|
||||
psize := p.size()
|
||||
chunk_top := voidptr(usize(p) + psize)
|
||||
top := voidptr(usize(base) + (size - dlmalloc.top_foot_size))
|
||||
top := voidptr(usize(base) + (size - top_foot_size()))
|
||||
if !p.inuse() && chunk_top >= top {
|
||||
mut tp := &TreeChunk(p)
|
||||
if voidptr(p) == voidptr(dl.dv) {
|
||||
@ -734,6 +800,9 @@ fn (mut dl Dlmalloc) insert_small_chunk(chunk_ &Chunk, size usize) {
|
||||
} else {
|
||||
f = head.prev
|
||||
}
|
||||
|
||||
assert !isnil(f)
|
||||
assert !isnil(head)
|
||||
head.prev = chunk
|
||||
f.next = chunk
|
||||
chunk.prev = f
|
||||
@ -757,6 +826,7 @@ fn (mut dl Dlmalloc) insert_large_chunk(chunk_ &TreeChunk, size usize) {
|
||||
dl.mark_treemap(idx)
|
||||
*h = chunk
|
||||
chunk.parent = voidptr(h)
|
||||
assert !isnil(chunkc)
|
||||
chunkc.prev = chunkc
|
||||
chunkc.next = chunkc
|
||||
} else {
|
||||
@ -780,6 +850,7 @@ fn (mut dl Dlmalloc) insert_large_chunk(chunk_ &TreeChunk, size usize) {
|
||||
tc := t.chunk()
|
||||
f := tc.prev
|
||||
f.next = chunkc
|
||||
assert !isnil(chunkc)
|
||||
tc.prev = chunkc
|
||||
chunkc.prev = f
|
||||
chunkc.next = tc
|
||||
@ -825,8 +896,9 @@ fn (mut dl Dlmalloc) treemap_is_marked(idx u32) bool {
|
||||
[unsafe]
|
||||
pub fn (mut dl Dlmalloc) malloc(size usize) voidptr {
|
||||
mut nb := usize(0)
|
||||
|
||||
unsafe {
|
||||
if size <= dlmalloc.max_small_request {
|
||||
if size <= max_small_request() {
|
||||
nb = request_2_size(size)
|
||||
mut idx := small_index(nb)
|
||||
smallbits := dl.smallmap >> idx
|
||||
@ -854,7 +926,7 @@ pub fn (mut dl Dlmalloc) malloc(size usize) voidptr {
|
||||
dl.unlink_first_small_chunk(b, p, i)
|
||||
smallsize := small_index2size(i)
|
||||
rsize := smallsize - nb
|
||||
if sizeof(usize) != 4 && rsize < dlmalloc.min_chunk_size {
|
||||
if sizeof(usize) != 4 && rsize < min_chunk_size() {
|
||||
p.set_inuse_and_pinuse(smallsize)
|
||||
} else {
|
||||
p.set_size_and_pinuse_of_inuse_chunk(nb)
|
||||
@ -871,7 +943,7 @@ pub fn (mut dl Dlmalloc) malloc(size usize) voidptr {
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if size >= dlmalloc.max_request {
|
||||
} else if size >= dl.max_request {
|
||||
return voidptr(0)
|
||||
} else {
|
||||
nb = pad_request(size)
|
||||
@ -882,12 +954,13 @@ pub fn (mut dl Dlmalloc) malloc(size usize) voidptr {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// use the `dv` node if we can, splitting it if necessary or otherwise
|
||||
// exhausting the entire chunk
|
||||
if nb <= dl.dvsize {
|
||||
rsize := dl.dvsize - nb
|
||||
mut p := dl.dv
|
||||
if rsize >= dlmalloc.min_chunk_size {
|
||||
if rsize >= min_chunk_size() {
|
||||
dl.dv = p.plus_offset(nb)
|
||||
dl.dvsize = rsize
|
||||
mut r := dl.dv
|
||||
@ -899,6 +972,7 @@ pub fn (mut dl Dlmalloc) malloc(size usize) voidptr {
|
||||
dl.dv = voidptr(0)
|
||||
p.set_inuse_and_pinuse(dvs)
|
||||
}
|
||||
|
||||
return p.to_mem()
|
||||
}
|
||||
// Split the top node if we can
|
||||
@ -910,8 +984,10 @@ pub fn (mut dl Dlmalloc) malloc(size usize) voidptr {
|
||||
mut r := dl.top
|
||||
r.head = rsize | dlmalloc.pinuse
|
||||
p.set_size_and_pinuse_of_inuse_chunk(nb)
|
||||
|
||||
return p.to_mem()
|
||||
}
|
||||
|
||||
return dl.sys_alloc(nb)
|
||||
}
|
||||
}
|
||||
@ -937,19 +1013,20 @@ fn (mut dl Dlmalloc) init_top(ptr &Chunk, size_ usize) {
|
||||
dl.topsize = size
|
||||
p.head = size | dlmalloc.pinuse
|
||||
|
||||
p.plus_offset(size).head = dlmalloc.top_foot_size
|
||||
dl.trim_check = dlmalloc.default_trim_threshold
|
||||
p.plus_offset(size).head = top_foot_size()
|
||||
dl.trim_check = u32(default_trim_threshold())
|
||||
}
|
||||
|
||||
[unsafe]
|
||||
fn (mut dl Dlmalloc) sys_alloc(size usize) voidptr {
|
||||
asize := align_up(size + dlmalloc.top_foot_size + dlmalloc.malloc_alignment, dlmalloc.default_granularity)
|
||||
asize := align_up(size + top_foot_size() + malloc_alignment(), default_granularity())
|
||||
unsafe {
|
||||
tbase, mut tsize, flags := dl.system_allocator.alloc(dl.system_allocator.data,
|
||||
asize)
|
||||
if isnil(tbase) {
|
||||
return tbase
|
||||
}
|
||||
|
||||
dl.footprint += tsize
|
||||
dl.max_footprint = if dl.max_footprint > dl.footprint {
|
||||
dl.max_footprint
|
||||
@ -965,7 +1042,7 @@ fn (mut dl Dlmalloc) sys_alloc(size usize) voidptr {
|
||||
dl.seg.flags = flags
|
||||
dl.release_checks = dlmalloc.max_release_check_rate
|
||||
dl.init_bins()
|
||||
tsize_ := tsize - dlmalloc.top_foot_size
|
||||
tsize_ := tsize - top_foot_size()
|
||||
dl.init_top(&Chunk(tbase), tsize_)
|
||||
} else {
|
||||
mut sp := &dl.seg
|
||||
@ -1037,7 +1114,7 @@ fn (mut dl Dlmalloc) tmalloc_small(size usize) voidptr {
|
||||
|
||||
mut vc := v.chunk()
|
||||
r := &TreeChunk(vc.plus_offset(size))
|
||||
if rsize < dlmalloc.min_chunk_size {
|
||||
if rsize < min_chunk_size() {
|
||||
vc.set_inuse_and_pinuse(rsize + size)
|
||||
} else {
|
||||
mut rc := r.chunk()
|
||||
@ -1107,7 +1184,7 @@ fn (mut dl Dlmalloc) tmalloc_large(size usize) voidptr {
|
||||
mut vc := v.chunk()
|
||||
mut r := vc.plus_offset(size)
|
||||
dl.unlink_large_chunk(v)
|
||||
if rsize < dlmalloc.min_chunk_size {
|
||||
if rsize < min_chunk_size() {
|
||||
vc.set_inuse_and_pinuse(rsize + size)
|
||||
} else {
|
||||
vc.set_size_and_pinuse_of_inuse_chunk(size)
|
||||
@ -1163,18 +1240,18 @@ fn (mut dl Dlmalloc) add_segment(tbase voidptr, tsize usize, flags u32) {
|
||||
mut oldsp := dl.segment_holding(old_top)
|
||||
old_end := oldsp.top()
|
||||
ssize := pad_request(sizeof(Segment))
|
||||
mut offset := ssize + sizeof(usize) * 4 + dlmalloc.malloc_alignment - 1
|
||||
mut offset := ssize + sizeof(usize) * 4 + malloc_alignment() - 1
|
||||
rawsp := voidptr(usize(old_end) - offset)
|
||||
offset = align_offset_usize((&Chunk(rawsp)).to_mem())
|
||||
asp := voidptr(usize(rawsp) + offset)
|
||||
csp := if asp < voidptr(usize(old_top) + dlmalloc.min_chunk_size) { old_top } else { asp }
|
||||
csp := if asp < voidptr(usize(old_top) + min_chunk_size()) { old_top } else { asp }
|
||||
mut sp := &Chunk(csp)
|
||||
mut ss := &Segment(sp.to_mem())
|
||||
mut tnext := sp.plus_offset(ssize)
|
||||
mut p := tnext
|
||||
mut nfences := 0
|
||||
|
||||
size := tsize - dlmalloc.top_foot_size
|
||||
size := tsize - top_foot_size()
|
||||
dl.init_top(&Chunk(tbase), size)
|
||||
|
||||
sp.set_size_and_pinuse_of_inuse_chunk(ssize)
|
||||
@ -1186,7 +1263,7 @@ fn (mut dl Dlmalloc) add_segment(tbase voidptr, tsize usize, flags u32) {
|
||||
|
||||
for {
|
||||
nextp := p.plus_offset(sizeof(usize))
|
||||
p.head = dlmalloc.fencepost_head
|
||||
p.head = fencepost_head()
|
||||
nfences += 1
|
||||
if nextp.head < old_end {
|
||||
p = nextp
|
||||
@ -1222,7 +1299,7 @@ fn (mut dl Dlmalloc) segment_holding(ptr voidptr) &Segment {
|
||||
// realloc behaves as libc realloc, but operates within the given space
|
||||
[unsafe]
|
||||
pub fn (mut dl Dlmalloc) realloc(oldmem voidptr, bytes usize) voidptr {
|
||||
if bytes >= dlmalloc.max_request {
|
||||
if bytes >= dl.max_request {
|
||||
return voidptr(0)
|
||||
}
|
||||
unsafe {
|
||||
@ -1249,16 +1326,16 @@ pub fn (mut dl Dlmalloc) realloc(oldmem voidptr, bytes usize) voidptr {
|
||||
[unsafe]
|
||||
pub fn (mut dl Dlmalloc) memalign(alignment_ usize, bytes usize) voidptr {
|
||||
mut alignment := alignment_
|
||||
if alignment < dlmalloc.min_chunk_size {
|
||||
alignment = dlmalloc.min_chunk_size
|
||||
if alignment < min_chunk_size() {
|
||||
alignment = min_chunk_size()
|
||||
}
|
||||
|
||||
if bytes >= dlmalloc.max_request - alignment {
|
||||
if bytes >= max_request() - alignment {
|
||||
return voidptr(0)
|
||||
}
|
||||
unsafe {
|
||||
nb := request_2_size(bytes)
|
||||
req := nb + alignment + dlmalloc.min_chunk_size - dlmalloc.chunk_overhead
|
||||
req := nb + alignment + min_chunk_size() - chunk_overhead()
|
||||
mem := dl.malloc(req)
|
||||
if isnil(mem) {
|
||||
return mem
|
||||
@ -1274,7 +1351,7 @@ pub fn (mut dl Dlmalloc) memalign(alignment_ usize, bytes usize) voidptr {
|
||||
br_ := (usize(mem) + alignment - 1) & (~alignment + 1)
|
||||
br := chunk_from_mem(voidptr(br_))
|
||||
mut pos := voidptr(0)
|
||||
if usize(br) - usize(p) > dlmalloc.min_chunk_size {
|
||||
if usize(br) - usize(p) > min_chunk_size() {
|
||||
pos = voidptr(br)
|
||||
} else {
|
||||
pos = voidptr(usize(br) + alignment)
|
||||
@ -1297,7 +1374,7 @@ pub fn (mut dl Dlmalloc) memalign(alignment_ usize, bytes usize) voidptr {
|
||||
|
||||
if !p.mmapped() {
|
||||
size := p.size()
|
||||
if size > nb + dlmalloc.min_chunk_size {
|
||||
if size > nb + min_chunk_size() {
|
||||
remainder_size := size - nb
|
||||
mut remainder := p.plus_offset(nb)
|
||||
p.set_inuse(nb)
|
||||
@ -1319,7 +1396,7 @@ fn (mut dl Dlmalloc) try_realloc_chunk(p_ &Chunk, nb usize, can_move bool) &Chun
|
||||
return dl.mmap_resize(p, nb, can_move)
|
||||
} else if oldsize >= nb {
|
||||
rsize := oldsize - nb
|
||||
if rsize >= dlmalloc.min_chunk_size {
|
||||
if rsize >= min_chunk_size() {
|
||||
mut r := p.plus_offset(nb)
|
||||
p.set_inuse(nb)
|
||||
r.set_inuse(rsize)
|
||||
@ -1346,7 +1423,7 @@ fn (mut dl Dlmalloc) try_realloc_chunk(p_ &Chunk, nb usize, can_move bool) &Chun
|
||||
}
|
||||
|
||||
dsize := oldsize + dvs - nb
|
||||
if dsize >= dlmalloc.min_chunk_size {
|
||||
if dsize >= min_chunk_size() {
|
||||
mut r := p.plus_offset(nb)
|
||||
mut n := r.plus_offset(dsize)
|
||||
p.set_inuse(nb)
|
||||
@ -1368,7 +1445,7 @@ fn (mut dl Dlmalloc) try_realloc_chunk(p_ &Chunk, nb usize, can_move bool) &Chun
|
||||
}
|
||||
rsize := oldsize + nextsize - nb
|
||||
dl.unlink_chunk(next, nextsize)
|
||||
if rsize < dlmalloc.min_chunk_size {
|
||||
if rsize < min_chunk_size() {
|
||||
newsize := oldsize + nextsize
|
||||
p.set_inuse(newsize)
|
||||
} else {
|
||||
@ -1392,13 +1469,13 @@ fn (mut dl Dlmalloc) mmap_resize(oldp_ &Chunk, nb usize, can_move bool) &Chunk {
|
||||
return voidptr(0)
|
||||
}
|
||||
// Keep the old chunk if it's big enough but not too big
|
||||
if oldsize >= nb + sizeof(usize) && (oldsize - nb) <= (dlmalloc.default_granularity << 1) {
|
||||
if oldsize >= nb + sizeof(usize) && (oldsize - nb) <= (default_granularity() << 1) {
|
||||
return oldp
|
||||
}
|
||||
|
||||
offset := oldp.prev_foot
|
||||
oldmmsize := oldsize + offset + dlmalloc.mmap_foot_pad
|
||||
newmmsize := dl.mmap_align(nb + 6 * sizeof(usize) + dlmalloc.malloc_alignment - 1)
|
||||
oldmmsize := oldsize + offset + mmap_foot_pad()
|
||||
newmmsize := dl.mmap_align(nb + 6 * sizeof(usize) + malloc_alignment() - 1)
|
||||
|
||||
ptr := dl.system_allocator.remap(dl.system_allocator.data, voidptr(usize(oldp) - offset),
|
||||
oldmmsize, newmmsize, can_move)
|
||||
@ -1407,9 +1484,9 @@ fn (mut dl Dlmalloc) mmap_resize(oldp_ &Chunk, nb usize, can_move bool) &Chunk {
|
||||
}
|
||||
|
||||
mut newp := &Chunk(voidptr(usize(ptr) + offset))
|
||||
psize := newmmsize - offset - dlmalloc.mmap_foot_pad
|
||||
psize := newmmsize - offset - mmap_foot_pad()
|
||||
newp.head = psize
|
||||
newp.plus_offset(psize).head = dlmalloc.fencepost_head
|
||||
newp.plus_offset(psize).head = fencepost_head()
|
||||
newp.plus_offset(psize + sizeof(usize)).head = 0
|
||||
if ptr < dl.least_addr {
|
||||
dl.least_addr = ptr
|
||||
@ -1434,7 +1511,7 @@ fn (mut dl Dlmalloc) dispose_chunk(p_ &Chunk, psize_ usize) {
|
||||
if !p.pinuse() {
|
||||
prevsize := p.prev_foot
|
||||
if p.mmapped() {
|
||||
psize += prevsize + dlmalloc.mmap_foot_pad
|
||||
psize += prevsize + mmap_foot_pad()
|
||||
|
||||
if dl.system_allocator.free_(dl.system_allocator.data, voidptr(usize(p) - prevsize),
|
||||
psize)
|
||||
|
@ -1,8 +1,9 @@
|
||||
module dlmalloc
|
||||
|
||||
#include <sys/mman.h>
|
||||
#include <unistd.h>
|
||||
|
||||
$if !freestanding {
|
||||
#include <sys/mman.h>
|
||||
#include <unistd.h>
|
||||
}
|
||||
fn C.munmap(ptr voidptr, size usize) int
|
||||
fn C.mremap(ptr voidptr, old usize, new usize, flags usize) voidptr
|
||||
fn C.mmap(base voidptr, len usize, prot int, flags int, fd int, offset i64) voidptr
|
||||
@ -50,17 +51,22 @@ enum MapFlags {
|
||||
}
|
||||
|
||||
fn system_alloc(_ voidptr, size usize) (voidptr, usize, u32) {
|
||||
unsafe {
|
||||
mem_prot := MemProt(int(MemProt.prot_read) | int(MemProt.prot_write))
|
||||
map_flags := MapFlags(int(MapFlags.map_private) | int(MapFlags.map_anonymous))
|
||||
addr := C.mmap(voidptr(0), size, int(mem_prot), int(map_flags), -1, 0)
|
||||
$if !freestanding {
|
||||
unsafe {
|
||||
mem_prot := MemProt(int(MemProt.prot_read) | int(MemProt.prot_write))
|
||||
map_flags := MapFlags(int(MapFlags.map_private) | int(MapFlags.map_anonymous))
|
||||
addr := C.mmap(voidptr(0), size, int(mem_prot), int(map_flags), -1, 0)
|
||||
|
||||
if addr == voidptr(-1) {
|
||||
return voidptr(0), 0, 0
|
||||
} else {
|
||||
return addr, size, 0
|
||||
if addr == voidptr(-1) {
|
||||
return voidptr(0), 0, 0
|
||||
} else {
|
||||
return addr, size, 0
|
||||
}
|
||||
}
|
||||
} $else {
|
||||
return voidptr(0), 0, 0
|
||||
}
|
||||
return voidptr(0), 0, 0
|
||||
}
|
||||
|
||||
fn system_remap(_ voidptr, ptr voidptr, oldsize usize, newsize usize, can_move bool) voidptr {
|
||||
@ -68,7 +74,7 @@ fn system_remap(_ voidptr, ptr voidptr, oldsize usize, newsize usize, can_move b
|
||||
}
|
||||
|
||||
fn system_free_part(_ voidptr, ptr voidptr, oldsize usize, newsize usize) bool {
|
||||
$if linux {
|
||||
$if linux && !freestanding {
|
||||
unsafe {
|
||||
rc := C.mremap(ptr, oldsize, newsize, 0)
|
||||
if rc != voidptr(-1) {
|
||||
@ -76,7 +82,7 @@ fn system_free_part(_ voidptr, ptr voidptr, oldsize usize, newsize usize) bool {
|
||||
}
|
||||
return C.munmap(voidptr(usize(ptr) + newsize), oldsize - newsize) == 0
|
||||
}
|
||||
} $else $if macos {
|
||||
} $else $if macos && !freestanding {
|
||||
unsafe {
|
||||
return C.munmap(voidptr(usize(ptr) + newsize), oldsize - newsize) == 0
|
||||
}
|
||||
@ -85,8 +91,12 @@ fn system_free_part(_ voidptr, ptr voidptr, oldsize usize, newsize usize) bool {
|
||||
}
|
||||
|
||||
fn system_free(_ voidptr, ptr voidptr, size usize) bool {
|
||||
unsafe {
|
||||
return C.munmap(ptr, size) == 0
|
||||
$if !freestanding {
|
||||
unsafe {
|
||||
return C.munmap(ptr, size) == 0
|
||||
}
|
||||
} $else {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -54,7 +54,7 @@ pub fn realloc(ptr voidptr, oldsize usize, newsize usize) voidptr {
|
||||
[unsafe]
|
||||
pub fn memalign(size usize, align usize) voidptr {
|
||||
unsafe {
|
||||
if align <= malloc_alignment {
|
||||
if align <= malloc_alignment() {
|
||||
return global.malloc(size)
|
||||
} else {
|
||||
return global.memalign(align, size)
|
||||
|
Reference in New Issue
Block a user