-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathallocator.wat
83 lines (83 loc) · 2.64 KB
/
allocator.wat
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
(module
(memory $memory (export "memory") 1)
(global $last (mut i32) (i32.const 8))
(func $realloc (export "realloc")
(param $old_ptr i32)
(param $old_size i32)
(param $align i32)
(param $new_size i32)
(result i32)
(local $ret i32)
;; Test if the old pointer is non-null
local.get $old_ptr
if
;; If the old size is bigger than the new size then
;; this is a shrink and transparently allow it
local.get $old_size
local.get $new_size
i32.gt_u
if
local.get $old_ptr
return
end
;; otherwise fall through to allocate a new chunk which will later
;; copy data over
end
;; align up `$last`
(global.set $last
(i32.and
(i32.add
(global.get $last)
(i32.add
(local.get $align)
(i32.const -1)))
(i32.xor
(i32.add
(local.get $align)
(i32.const -1))
(i32.const -1))))
;; save the current value of `$last` as the return value
global.get $last
local.set $ret
;; bump our pointer
(global.set $last
(i32.add
(global.get $last)
(local.get $new_size)))
;; while `memory.size` is less than `$last`, grow memory
;; by one page
(loop $loop
(if
(i32.lt_u
(i32.mul (memory.size) (i32.const 65536))
(global.get $last))
(then
i32.const 1
memory.grow
;; test to make sure growth succeeded
i32.const -1
i32.eq
if unreachable end
br $loop)))
;; ensure anything necessary is set to valid data by spraying a bit
;; pattern that is invalid
local.get $ret
i32.const 0xde
local.get $new_size
memory.fill
;; If the old pointer is present then that means this was a reallocation
;; of an existing chunk which means the existing data must be copied.
local.get $old_ptr
if
local.get $ret ;; destination
local.get $old_ptr ;; source
local.get $old_size ;; size
memory.copy
end
local.get $ret
)
(func $clear (export "clear")
i32.const 8
global.set $last
)
)