@@ -78,10 +78,6 @@ pub async fn initialize_staged(
7878 // - No runtime table operations
7979 // - No reference type globals
8080 // - Each module instantiated at most once
81- // - If a module exports a memory, a single module must export a mutable `__stack_pointer` global of type I32
82- //
83- // Note that we use `__stack_pointer` to allocate 8 bytes to store the canonical `list<u8>` representation of
84- // memory.
8581
8682 let copy_component_section = |section, component : & [ u8 ] , result : & mut Component | {
8783 if let Some ( ( id, range) ) = section {
@@ -374,7 +370,6 @@ pub async fn initialize_staged(
374370 let mut lifts = CanonicalFunctionSection :: new ( ) ;
375371 let mut component_types = ComponentTypeSection :: new ( ) ;
376372 let mut component_exports = ComponentExportSection :: new ( ) ;
377- let mut stack_pointers = Vec :: new ( ) ;
378373 for ( module_index, globals_to_export) in & globals_to_export {
379374 for ( global_index, ( name, ty) ) in globals_to_export {
380375 let ty = Encode . val_type ( * ty) ?;
@@ -390,9 +385,6 @@ pub async fn initialize_staged(
390385 shared : false ,
391386 } ,
392387 ) ;
393- if name == "__stack_pointer" {
394- stack_pointers. push ( ( offset, ty) ) ;
395- }
396388 functions. function ( offset) ;
397389 let mut function = Function :: new ( [ ] ) ;
398390 function. instruction ( & Ins :: GlobalGet ( offset) ) ;
@@ -432,14 +424,6 @@ pub async fn initialize_staged(
432424 }
433425
434426 if let Some ( ( module_index, name, ty) ) = memory_info {
435- let stack_pointer = match stack_pointers. as_slice ( ) {
436- [ ( offset, ValType :: I32 ) ] => * offset,
437-
438- _ => bail ! (
439- "component with memory must contain exactly one module which \
440- exports a mutable `__stack_pointer` global of type I32"
441- ) ,
442- } ;
443427 let offset = types. len ( ) ;
444428 types. ty ( ) . function ( [ ] , [ wasm_encoder:: ValType :: I32 ] ) ;
445429 imports. import (
@@ -450,19 +434,41 @@ pub async fn initialize_staged(
450434 functions. function ( offset) ;
451435
452436 let mut function = Function :: new ( [ ( 1 , wasm_encoder:: ValType :: I32 ) ] ) ;
453- function. instruction ( & Ins :: GlobalGet ( stack_pointer) ) ;
454- function. instruction ( & Ins :: I32Const ( 8 ) ) ;
455- function. instruction ( & Ins :: I32Sub ) ;
437+ function. instruction ( & Ins :: MemorySize ( 0 ) ) ;
438+ // stack[0] = current memory, in pages
439+
440+ function. instruction ( & Ins :: I32Const ( PAGE_SIZE_BYTES ) ) ;
441+ function. instruction ( & Ins :: I32Mul ) ;
456442 function. instruction ( & Ins :: LocalTee ( 0 ) ) ;
443+ // stack[0] = local[0] = current memory, in bytes
444+
445+ function. instruction ( & Ins :: I32Const ( 1 ) ) ;
446+ function. instruction ( & Ins :: MemoryGrow ( 0 ) ) ;
447+ // stack[1] = old memory, in bytes
448+ // stack[0] = grown memory, in pages, or -1 if failed
457449 function. instruction ( & Ins :: I32Const ( 0 ) ) ;
458- function. instruction ( & Ins :: I32Store ( mem_arg ( 0 , 2 ) ) ) ;
459- function. instruction ( & Ins :: LocalGet ( 0 ) ) ;
450+ function. instruction ( & Ins :: I32LtS ) ;
451+ function. instruction ( & Ins :: If ( wasm_encoder:: BlockType :: Empty ) ) ;
452+ // Trap if memory grow failed
453+ function. instruction ( & Ins :: Unreachable ) ;
454+ function. instruction ( & Ins :: Else ) ;
455+ function. instruction ( & Ins :: End ) ;
456+
457+ // stack[0] = old memory, in bytes
460458 function. instruction ( & Ins :: I32Const ( 0 ) ) ;
461- function. instruction ( & Ins :: MemoryGrow ( 0 ) ) ;
462- function. instruction ( & Ins :: I32Const ( PAGE_SIZE_BYTES ) ) ;
463- function. instruction ( & Ins :: I32Mul ) ;
464- function. instruction ( & Ins :: I32Store ( mem_arg ( 4 , 2 ) ) ) ;
459+ // stack[1] = old memory in bytes
460+ // stack[0] = 0 (start of memory)
461+ function. instruction ( & Ins :: I32Store ( mem_arg ( 0 , 1 ) ) ) ;
462+ // 0 stored at end of old memory
463+ function. instruction ( & Ins :: LocalGet ( 0 ) ) ;
464+ function. instruction ( & Ins :: LocalGet ( 0 ) ) ;
465+ // stack[1] = old memory in bytes
466+ // stack[0] = old memory in bytes
467+ function. instruction ( & Ins :: I32Store ( mem_arg ( 4 , 1 ) ) ) ;
468+ // old memory size, stored at old memory + 4
469+
465470 function. instruction ( & Ins :: LocalGet ( 0 ) ) ;
471+ // stack[0] = old memory in bytes
466472 function. instruction ( & Ins :: End ) ;
467473 code. function ( & function) ;
468474
@@ -524,6 +530,7 @@ pub async fn initialize_staged(
524530
525531 let instrumented_component = instrumented_component. finish ( ) ;
526532
533+ std:: fs:: write ( "instrumented.wasm" , & instrumented_component) ?;
527534 Validator :: new ( ) . validate_all ( & instrumented_component) ?;
528535
529536 let mut invoker = initialize ( instrumented_component) . await ?;
@@ -541,26 +548,26 @@ pub async fn initialize_staged(
541548 invoker
542549 . call_s32 ( name)
543550 . await
544- . with_context ( || name . to_owned ( ) ) ?,
551+ . with_context ( || format ! ( "retrieving global value {name}" ) ) ?,
545552 ) ,
546553 wasmparser:: ValType :: I64 => ConstExpr :: i64_const (
547554 invoker
548555 . call_s64 ( name)
549556 . await
550- . with_context ( || name . to_owned ( ) ) ?,
557+ . with_context ( || format ! ( "retrieving global value {name}" ) ) ?,
551558 ) ,
552559 wasmparser:: ValType :: F32 => ConstExpr :: f32_const (
553560 invoker
554561 . call_f32 ( name)
555562 . await
556- . with_context ( || name . to_owned ( ) ) ?
563+ . with_context ( || format ! ( "retrieving global value {name}" ) ) ?
557564 . into ( ) ,
558565 ) ,
559566 wasmparser:: ValType :: F64 => ConstExpr :: f64_const (
560567 invoker
561568 . call_f64 ( name)
562569 . await
563- . with_context ( || name . to_owned ( ) ) ?
570+ . with_context ( || format ! ( "retrieving global value {name}" ) ) ?
564571 . into ( ) ,
565572 ) ,
566573 wasmparser:: ValType :: V128 => bail ! ( "V128 not yet supported" ) ,
@@ -573,7 +580,12 @@ pub async fn initialize_staged(
573580
574581 let memory_value = if memory_info. is_some ( ) {
575582 let name = "component-init-get-memory" ;
576- Some ( invoker. call_list_u8 ( name) . await . context ( name) ?)
583+ Some (
584+ invoker
585+ . call_list_u8 ( name)
586+ . await
587+ . with_context ( || format ! ( "retrieving memory with {name}" ) ) ?,
588+ )
577589 } else {
578590 None
579591 } ;
0 commit comments