|
3 | 3 | use super::REALLOC_AND_FREE; |
4 | 4 | use wasmtime::Result; |
5 | 5 | use wasmtime::component::{Component, Linker}; |
6 | | -use wasmtime::{Engine, Store, StoreContextMut, Trap}; |
| 6 | +use wasmtime::{Config, Engine, PoolingAllocationConfig, Store, StoreContextMut, Trap}; |
7 | 7 |
|
8 | 8 | const UTF16_TAG: u32 = 1 << 31; |
9 | 9 |
|
@@ -576,3 +576,73 @@ fn test_raw_when_encoded( |
576 | 576 | Err(e) => Ok(Some(e)), |
577 | 577 | } |
578 | 578 | } |
| 579 | + |
| 580 | +#[test] |
| 581 | +fn pass_string_on_component_boundary() -> Result<()> { |
| 582 | + // Configure an engine such that linear memories are allocated right next |
| 583 | + // to each other and are 1 wasm page large. This'll ensure that the string |
| 584 | + // at the beginning of the second memory is at the end of the first memory. |
| 585 | + let mut pooling_config = PoolingAllocationConfig::new(); |
| 586 | + pooling_config.total_component_instances(3); |
| 587 | + pooling_config.total_memories(2); |
| 588 | + pooling_config.total_tables(0); |
| 589 | + pooling_config.total_stacks(0); |
| 590 | + pooling_config.max_memory_size(65536); |
| 591 | + let mut config = Config::new(); |
| 592 | + config.memory_guard_size(0); |
| 593 | + config.memory_reservation(65536); |
| 594 | + config.allocation_strategy(pooling_config); |
| 595 | + let engine = Engine::new(&config)?; |
| 596 | + |
| 597 | + let component = r#" |
| 598 | +(component |
| 599 | + ;; This component is instantiated first so its allocation function returns a |
| 600 | + ;; pointer at the end of memory which will be right up against the next |
| 601 | + ;; linear memory. |
| 602 | + (component $c |
| 603 | + (core module $m |
| 604 | + (func (export "") (param i32 i32)) |
| 605 | + (func (export "realloc") (param i32 i32 i32 i32) (result i32) i32.const 65520) |
| 606 | + (memory (export "memory") 1) |
| 607 | + ) |
| 608 | + (core instance $m (instantiate $m)) |
| 609 | + (func (export "a") (param "a" string) |
| 610 | + (canon lift (core func $m "") (realloc (func $m "realloc")) (memory $m "memory")) |
| 611 | + ) |
| 612 | + ) |
| 613 | +
|
| 614 | + ;; This component is instantiated second meaning its memory is after the |
| 615 | + ;; one above, so the string is placed first thing in linear memory. |
| 616 | + (component $c2 |
| 617 | + (import "a" (func $f (param "a" string))) |
| 618 | + (core module $libc |
| 619 | + (memory (export "memory") 1) |
| 620 | + (data (memory 0) (i32.const 0) "0123456789abcdef") |
| 621 | + ) |
| 622 | + (core instance $libc (instantiate $libc)) |
| 623 | + (core func $f (canon lower (func $f) (memory $libc "memory"))) |
| 624 | + (core module $m |
| 625 | + (import "" "" (func $f (param i32 i32))) |
| 626 | + (func (export "f") |
| 627 | + (call $f |
| 628 | + (i32.const 0) ;; ptr |
| 629 | + (i32.const 16)) ;; len |
| 630 | + ) |
| 631 | + ) |
| 632 | + (core instance $m (instantiate $m (with "" (instance (export "" (func $f)))))) |
| 633 | + (func (export "f") (canon lift (core func $m "f"))) |
| 634 | + ) |
| 635 | +
|
| 636 | + (instance $c (instantiate $c)) |
| 637 | + (instance $c2 (instantiate $c2 (with "a" (func $c "a")))) |
| 638 | + (export "f" (func $c2 "f")) |
| 639 | +) |
| 640 | +"#; |
| 641 | + |
| 642 | + let component = Component::new(&engine, &component)?; |
| 643 | + let mut store = Store::new(&engine, ()); |
| 644 | + let instance = Linker::new(&engine).instantiate(&mut store, &component)?; |
| 645 | + let func = instance.get_typed_func::<(), ()>(&mut store, "f")?; |
| 646 | + func.call(&mut store, ())?; |
| 647 | + Ok(()) |
| 648 | +} |
0 commit comments