1;;! component_model_async = true 2;;! reference_types = true 3 4;; This test exercises corner cases where extremely large values are sent 5;; between guests and currently require copying out to the host in Wasmtime 6;; which should result in a trap of some form rather than the host spending all 7;; its time allocating and copying memory. 8 9(component definition $A 10 (type $t (list (list (list (list u8))))) 11 (type $s (stream $t)) 12 (type $f (future $t)) 13 (type $functy (func async (result $s))) 14 15 (component $A 16 (core module $libc (memory (export "memory") 1)) 17 (core instance $libc (instantiate $libc)) 18 19 (core module $m 20 (import "libc" "memory" (memory 1)) 21 (import "" "stream.new" (func $stream.new (result i64))) 22 (import "" "stream.write" (func $stream.write (param i32 i32 i32) (result i32))) 23 (import "" "future.new" (func $future.new (result i64))) 24 (import "" "future.write" (func $future.write (param i32 i32) (result i32))) 25 (import "" "task.return future" (func $task.return-future (param i32))) 26 (import "" "task.return stream" (func $task.return-stream (param i32))) 27 28 (func (export "big-stream") (result i32) 29 (local $w i32) 30 (local $r i32) 31 (local $s i64) 32 (local.set $s (call $stream.new)) 33 (local.set $r (i32.wrap_i64 (local.get $s))) 34 (local.set $w (i32.wrap_i64 (i64.shr_u (local.get $s) (i64.const 32)))) 35 36 (call $task.return-stream (local.get $r)) 37 38 local.get $w 39 (call $prepare-list-to-write (i32.const 5) (i32.const 2)) 40 call $stream.write 41 unreachable 42 ) 43 44 (func (export "big-future") (result i32) 45 (local $w i32) 46 (local $r i32) 47 (local $s i64) 48 (local $base i32) 49 (local $len i32) 50 (local.set $s (call $future.new)) 51 (local.set $r (i32.wrap_i64 (local.get $s))) 52 (local.set $w (i32.wrap_i64 (i64.shr_u (local.get $s) (i64.const 32)))) 53 54 (call $task.return-future (local.get $r)) 55 56 (call $prepare-list-to-write (i32.const 4) (i32.const 2)) 57 local.set $len 58 local.set $base 59 60 (i32.store offset=0 (i32.const 100) (local.get $base)) 61 (i32.store offset=4 (i32.const 100) (local.get $len)) 62 63 64 local.get $w 65 i32.const 100 66 call $future.write 67 unreachable 68 ) 69 70 ;; Prepare $depth+1 layers of lists where the leaves point to all of 71 ;; memory and each layer otherwise is a list of the previous layer. 72 ;; 73 ;; Each layer-of-lists is `$pages` large. 74 (func $prepare-list-to-write (param $depth i32) (param $pages i32) (result i32 i32) 75 (local $base i32) 76 (local $len i32) 77 78 (local $c_base i32) 79 (local $c_len i32) 80 (local $i i32) 81 82 local.get $depth 83 if 84 ;; Case of $depth>0 meaning that this is a list-of-lists layer. 85 ;; Allocate some memory to store this list itself then generate the 86 ;; layer down by recursing. 87 (local.set $base (call $grow (local.get $pages))) 88 (local.set $len 89 (i32.div_u 90 (i32.mul (local.get $pages) (i32.const 65536)) 91 (i32.const 8) 92 ) 93 ) 94 95 (call $prepare-list-to-write 96 (i32.sub (local.get $depth) (i32.const 1)) 97 (local.get $pages)) 98 local.set $c_len 99 local.set $c_base 100 101 ;; Initialize this list-of-lists with all copies of the previous 102 ;; layer's list. 103 loop $l 104 (i32.store offset=0 105 (i32.add (local.get $base) (i32.mul (local.get $i) (i32.const 8))) 106 (local.get $c_base)) 107 (i32.store offset=4 108 (i32.add (local.get $base) (i32.mul (local.get $i) (i32.const 8))) 109 (local.get $c_len)) 110 111 (local.set $i (i32.add (local.get $i) (i32.const 1))) 112 (if (i32.lt_u (local.get $i) (local.get $len)) 113 (then (br $l))) 114 end 115 116 else 117 ;; base case: the bottom list is just a byte list of all of memory. 118 (local.set $base (i32.const 0)) 119 (local.set $len (i32.mul (memory.size) (i32.const 65536))) 120 end 121 122 local.get $base 123 local.get $len 124 ) 125 126 (func $grow (param i32) (result i32) 127 (local $r i32) 128 (local.set $r (memory.grow (local.get 0))) 129 local.get $r 130 i32.const -1 131 i32.eq 132 if unreachable end 133 local.get $r 134 i32.const 65536 135 i32.mul 136 ) 137 138 (func (export "cb") (param i32 i32 i32) (result i32) unreachable) 139 ) 140 (core func $future.new (canon future.new $f)) 141 (core func $future.write (canon future.write $f (memory $libc "memory"))) 142 (core func $stream.new (canon stream.new $s)) 143 (core func $stream.write (canon stream.write $s (memory $libc "memory"))) 144 (core func $task.return-future (canon task.return (result $f))) 145 (core func $task.return-stream (canon task.return (result $s))) 146 (core instance $m (instantiate $m 147 (with "libc" (instance $libc)) 148 (with "" (instance 149 (export "future.new" (func $future.new)) 150 (export "future.write" (func $future.write)) 151 (export "stream.new" (func $stream.new)) 152 (export "stream.write" (func $stream.write)) 153 (export "task.return future" (func $task.return-future)) 154 (export "task.return stream" (func $task.return-stream)) 155 )) 156 )) 157 158 (func (export "big-stream") (result $s) 159 (canon lift (core func $m "big-stream") async 160 (callback (func $m "cb")))) 161 (func (export "big-future") (result $f) 162 (canon lift (core func $m "big-future") async 163 (callback (func $m "cb")))) 164 ) 165 166 (component $B 167 (import "a" (instance $a 168 (export "big-future" (func (result $f))) 169 (export "big-stream" (func (result $s))) 170 )) 171 172 (core module $libc 173 (memory (export "memory") 1) 174 (func (export "realloc") (param i32 i32 i32 i32) (result i32) unreachable) 175 ) 176 (core instance $libc (instantiate $libc)) 177 178 (core module $m 179 (import "libc" "memory" (memory 1)) 180 (import "" "big-stream" (func $big-stream (result i32))) 181 (import "" "big-future" (func $big-future (result i32))) 182 (import "" "stream.read" (func $stream.read (param i32 i32 i32) (result i32))) 183 (import "" "future.read" (func $future.read (param i32 i32) (result i32))) 184 185 (func (export "stream") 186 (call $stream.read 187 (call $big-stream) 188 i32.const 0 189 i32.const 100 190 ) 191 unreachable 192 ) 193 (func (export "future") 194 (call $future.read 195 (call $big-future) 196 i32.const 0 197 ) 198 unreachable 199 ) 200 ) 201 (core func $big-stream (canon lower (func $a "big-stream"))) 202 (core func $big-future (canon lower (func $a "big-future"))) 203 (core func $stream.read 204 (canon stream.read $s 205 (memory $libc "memory") 206 (realloc (func $libc "realloc")) 207 ) 208 ) 209 (core func $future.read 210 (canon future.read $f 211 (memory $libc "memory") 212 (realloc (func $libc "realloc")) 213 ) 214 ) 215 (core instance $m (instantiate $m 216 (with "libc" (instance $libc)) 217 (with "" (instance 218 (export "big-stream" (func $big-stream)) 219 (export "big-future" (func $big-future)) 220 (export "future.read" (func $future.read)) 221 (export "stream.read" (func $stream.read)) 222 )) 223 )) 224 225 (func (export "stream") async (canon lift (core func $m "stream"))) 226 (func (export "future") async (canon lift (core func $m "future"))) 227 228 ) 229 230 (instance $a (instantiate $A)) 231 (instance $b (instantiate $B (with "a" (instance $a)))) 232 (export "stream" (func $b "stream")) 233 (export "future" (func $b "future")) 234) 235 236(component instance $A $A) 237(assert_trap (invoke "stream") "fuel allocated for hostcalls has been exhausted") 238(component instance $A $A) 239(assert_trap (invoke "future") "fuel allocated for hostcalls has been exhausted") 240