@@ -21,24 +21,49 @@ __global g_memory_block &VMemoryBlock
2121struct VMemoryBlock {
2222mut :
2323 id int
24+ mallocs int
2425 cap isize
25- start & u8 = 0
26- previous & VMemoryBlock = 0
2726 remaining isize
28- current & u8 = 0
29- mallocs int
27+ previous & VMemoryBlock = 0
28+ next & VMemoryBlock = 0
29+ start & u8 = 0
30+ current & u8 = 0
31+ }
32+
33+ fn vmemory_abort_on_nil (p voidptr , bytes isize) {
34+ if unsafe { p == 0 } {
35+ C.fprintf (C.stderr, c 'could not allocate %lld bytes\n ' , bytes)
36+ exit (1 )
37+ }
3038}
3139
3240@[unsafe ]
3341fn vmemory_block_new (prev & VMemoryBlock, at_least isize) & VMemoryBlock {
34- mut v := unsafe { & VMemoryBlock (C.calloc (1 , sizeof (VMemoryBlock))) }
42+ vmem_block_size := sizeof (VMemoryBlock)
43+ mut v := unsafe { & VMemoryBlock (C.calloc (1 , vmem_block_size)) }
44+ vmemory_abort_on_nil (v, vmem_block_size)
3545 if unsafe { prev != 0 } {
3646 v.id = prev.id + 1
3747 }
3848
3949 v.previous = prev
40- block_size := if at_least < prealloc_block_size { prealloc_block_size } else { at_least }
50+ if unsafe { prev != 0 } {
51+ prev.next = v
52+ }
53+ block_size := if at_least < isize (prealloc_block_size) {
54+ isize (prealloc_block_size)
55+ } else {
56+ at_least
57+ }
58+ $if prealloc_trace_malloc ? {
59+ C.fprintf (C.stderr, c 'vmemory_block_new id: %d , block_size: %lld, at_least: %lld\n ' ,
60+ v.id, block_size, at_least)
61+ }
4162 v.start = unsafe { C.malloc (block_size) }
63+ vmemory_abort_on_nil (v.start, block_size)
64+ $if prealloc_memset ? {
65+ unsafe { C.memset (v.start, int ($d ('prealloc_memset_value' , 0 )), block_size) }
66+ }
4267 v.cap = block_size
4368 v.remaining = block_size
4469 v.current = v.start
@@ -47,15 +72,19 @@ fn vmemory_block_new(prev &VMemoryBlock, at_least isize) &VMemoryBlock {
4772
4873@[unsafe ]
4974fn vmemory_block_malloc (n isize) & u8 {
75+ $if prealloc_trace_malloc ? {
76+ C.fprintf (C.stderr, c 'vmemory_block_malloc g_memory_block.id: %d , n: %lld\n ' ,
77+ g_memory_block.id, n)
78+ }
5079 unsafe {
51- if g_memory_block.remaining < n {
80+ if _unlikely_ ( g_memory_block.remaining < n) {
5281 g_memory_block = vmemory_block_new (g_memory_block, n)
5382 }
54- mut res := & u8 (0 )
83+ mut res := & u8 (nil )
5584 res = g_memory_block.current
85+ g_memory_block.current + = n
5686 g_memory_block.remaining - = n
5787 g_memory_block.mallocs++
58- g_memory_block.current + = n
5988 return res
6089 }
6190}
@@ -64,26 +93,79 @@ fn vmemory_block_malloc(n isize) &u8 {
6493
6594@[unsafe ]
6695fn prealloc_vinit () {
96+ $if prealloc_trace_vinit ? {
97+ C.fprintf (C.stderr, c 'prealloc_vinit started\n ' )
98+ }
6799 unsafe {
68- g_memory_block = vmemory_block_new (nil, prealloc_block_size)
100+ g_memory_block = vmemory_block_new (nil, isize ( prealloc_block_size) )
69101 at_exit (prealloc_vcleanup) or {}
70102 }
71103}
72104
73105@[unsafe ]
74106fn prealloc_vcleanup () {
107+ $if prealloc_trace_vcleanup ? {
108+ C.fprintf (C.stderr, c 'prealloc_vcleanup started\n ' )
109+ }
75110 $if prealloc_stats ? {
76111 // Note: we do 2 loops here, because string interpolation
77112 // in the first loop may still use g_memory_block
78113 // The second loop however should *not* allocate at all.
79114 mut nr_mallocs := i64 (0 )
115+ mut total_used := u64 (0 )
80116 mut mb := g_memory_block
81117 for unsafe { mb != 0 } {
82118 nr_mallocs + = mb.mallocs
83- eprintln ('> freeing mb.id: ${mb.id:3} | cap: ${mb.cap:7} | rem: ${mb.remaining:7} | start: ${voidptr(mb.start)} | current: ${voidptr(mb.current)} | diff: ${u64(mb.current) - u64(mb.start):7} bytes | mallocs: ${mb.mallocs} ' )
119+ used := u64 (mb.current) - u64 (mb.start)
120+ total_used + = used
121+ C.fprintf (C.stderr, c '> freeing mb: %16p, mb.id: %3d | cap: %10lld | rem: %10lld | start: %16p | current: %16p | used: %10lld bytes | mallocs: %6d\n ' ,
122+ mb, mb.id, mb.cap, mb.remaining, mb.start, mb.current, used, mb.mallocs)
84123 mb = mb.previous
85124 }
86- eprintln ('> nr_mallocs: ${nr_mallocs} ' )
125+ C.fprintf (C.stderr, c '> nr_mallocs: %lld, total_used: %lld bytes\n ' , nr_mallocs,
126+ total_used)
127+ }
128+ $if prealloc_dump ? {
129+ C.fprintf (C.stderr, c 'prealloc_vcleanup dumping memory contents ...\n ' )
130+ mut start := g_memory_block
131+ unsafe {
132+ for start.previous != 0 {
133+ start = start.previous
134+ }
135+ C.fprintf (C.stderr, c 'prealloc_vcleanup start: %p \n ' , start)
136+ C.fprintf (C.stderr, c 'prealloc_vcleanup start.id: %d \n ' , start.id)
137+ C.fprintf (C.stderr, c 'prealloc_vcleanup start.next: %p \n ' , start.next)
138+
139+ mut total_used := u64 (0 )
140+ path := $d ('memdumpfile' , 'memdump.bin' )
141+ C.fprintf (C.stderr, c 'prealloc_vcleanup dumping process memory to path: %s \n ' ,
142+ path.str)
143+ stream := C.fopen (path.str, 'wb' .str)
144+ mut mb := start
145+ for {
146+ used := u64 (mb.current) - u64 (mb.start)
147+ total_used + = used
148+ C.fprintf (C.stderr, c 'prealloc_vcleanup dumping mb: %p , mb.id: %d , used: %10lld bytes\n ' ,
149+ mb, mb.id, used)
150+
151+ mut ptr := mb.start
152+ mut remaining_bytes := isize (used)
153+ mut x := isize (0 )
154+ for remaining_bytes > 0 {
155+ x = isize (C.fwrite (ptr, 1 , remaining_bytes, stream))
156+ ptr + = x
157+ remaining_bytes - = x
158+ }
159+
160+ if mb.next == 0 {
161+ break
162+ }
163+ mb = mb.next
164+ }
165+ C.fclose (stream)
166+ C.fprintf (C.stderr, c 'prealloc_vcleanup total dump size in bytes: %lld\n ' ,
167+ total_used)
168+ }
87169 }
88170 unsafe {
89171 for g_memory_block != 0 {
0 commit comments