1ce3c1a72SMangoPeachGrape #pragma once 2*b2c64de1SMangoPeachGrape #include <string_view> 3ce3c1a72SMangoPeachGrape 4*b2c64de1SMangoPeachGrape // From crates/component-util/src/lib.rs 5*b2c64de1SMangoPeachGrape inline constexpr std::string_view REALLOC_AND_FREE = 6*b2c64de1SMangoPeachGrape R"END( 7*b2c64de1SMangoPeachGrape (global $last (mut i32) (i32.const 8)) 8*b2c64de1SMangoPeachGrape (func $realloc (export "realloc") 9*b2c64de1SMangoPeachGrape (param $old_ptr i32) 10*b2c64de1SMangoPeachGrape (param $old_size i32) 11*b2c64de1SMangoPeachGrape (param $align i32) 12*b2c64de1SMangoPeachGrape (param $new_size i32) 13*b2c64de1SMangoPeachGrape (result i32) 14*b2c64de1SMangoPeachGrape 15*b2c64de1SMangoPeachGrape (local $ret i32) 16*b2c64de1SMangoPeachGrape 17*b2c64de1SMangoPeachGrape ;; Test if the old pointer is non-null 18*b2c64de1SMangoPeachGrape local.get $old_ptr 19*b2c64de1SMangoPeachGrape if 20*b2c64de1SMangoPeachGrape ;; If the old size is bigger than the new size then 21*b2c64de1SMangoPeachGrape ;; this is a shrink and transparently allow it 22*b2c64de1SMangoPeachGrape local.get $old_size 23*b2c64de1SMangoPeachGrape local.get $new_size 24*b2c64de1SMangoPeachGrape i32.gt_u 25*b2c64de1SMangoPeachGrape if 26*b2c64de1SMangoPeachGrape local.get $old_ptr 27*b2c64de1SMangoPeachGrape return 28*b2c64de1SMangoPeachGrape end 29*b2c64de1SMangoPeachGrape 30*b2c64de1SMangoPeachGrape ;; otherwise fall through to allocate a new chunk which will later 31*b2c64de1SMangoPeachGrape ;; copy data over 32*b2c64de1SMangoPeachGrape end 33*b2c64de1SMangoPeachGrape 34*b2c64de1SMangoPeachGrape ;; align up `$last` 35*b2c64de1SMangoPeachGrape (global.set $last 36*b2c64de1SMangoPeachGrape (i32.and 37*b2c64de1SMangoPeachGrape (i32.add 38*b2c64de1SMangoPeachGrape (global.get $last) 39*b2c64de1SMangoPeachGrape (i32.add 40*b2c64de1SMangoPeachGrape (local.get $align) 41*b2c64de1SMangoPeachGrape (i32.const -1))) 42*b2c64de1SMangoPeachGrape (i32.xor 43*b2c64de1SMangoPeachGrape (i32.add 44*b2c64de1SMangoPeachGrape (local.get $align) 45*b2c64de1SMangoPeachGrape (i32.const -1)) 46*b2c64de1SMangoPeachGrape (i32.const -1)))) 47*b2c64de1SMangoPeachGrape 48*b2c64de1SMangoPeachGrape ;; save the current value of `$last` as the return value 49*b2c64de1SMangoPeachGrape global.get $last 50*b2c64de1SMangoPeachGrape local.set $ret 51*b2c64de1SMangoPeachGrape 52*b2c64de1SMangoPeachGrape ;; bump our pointer 53*b2c64de1SMangoPeachGrape (global.set $last 54*b2c64de1SMangoPeachGrape (i32.add 55*b2c64de1SMangoPeachGrape (global.get $last) 56*b2c64de1SMangoPeachGrape (local.get $new_size))) 57*b2c64de1SMangoPeachGrape 58*b2c64de1SMangoPeachGrape ;; while `memory.size` is less than `$last`, grow memory 59*b2c64de1SMangoPeachGrape ;; by one page 60*b2c64de1SMangoPeachGrape (loop $loop 61*b2c64de1SMangoPeachGrape (if 62*b2c64de1SMangoPeachGrape (i32.lt_u 63*b2c64de1SMangoPeachGrape (i32.mul (memory.size) (i32.const 65536)) 64*b2c64de1SMangoPeachGrape (global.get $last)) 65*b2c64de1SMangoPeachGrape (then 66*b2c64de1SMangoPeachGrape i32.const 1 67*b2c64de1SMangoPeachGrape memory.grow 68*b2c64de1SMangoPeachGrape ;; test to make sure growth succeeded 69*b2c64de1SMangoPeachGrape i32.const -1 70*b2c64de1SMangoPeachGrape i32.eq 71*b2c64de1SMangoPeachGrape if unreachable end 72*b2c64de1SMangoPeachGrape 73*b2c64de1SMangoPeachGrape br $loop))) 74*b2c64de1SMangoPeachGrape 75*b2c64de1SMangoPeachGrape 76*b2c64de1SMangoPeachGrape ;; ensure anything necessary is set to valid data by spraying a bit 77*b2c64de1SMangoPeachGrape ;; pattern that is invalid 78*b2c64de1SMangoPeachGrape local.get $ret 79*b2c64de1SMangoPeachGrape i32.const 0xde 80*b2c64de1SMangoPeachGrape local.get $new_size 81*b2c64de1SMangoPeachGrape memory.fill 82*b2c64de1SMangoPeachGrape 83*b2c64de1SMangoPeachGrape ;; If the old pointer is present then that means this was a reallocation 84*b2c64de1SMangoPeachGrape ;; of an existing chunk which means the existing data must be copied. 85*b2c64de1SMangoPeachGrape local.get $old_ptr 86*b2c64de1SMangoPeachGrape if 87*b2c64de1SMangoPeachGrape local.get $ret ;; destination 88*b2c64de1SMangoPeachGrape local.get $old_ptr ;; source 89*b2c64de1SMangoPeachGrape local.get $old_size ;; size 90*b2c64de1SMangoPeachGrape memory.copy 91*b2c64de1SMangoPeachGrape end 92*b2c64de1SMangoPeachGrape 93*b2c64de1SMangoPeachGrape local.get $ret 94*b2c64de1SMangoPeachGrape ) 95*b2c64de1SMangoPeachGrape )END"; 96