@@ -3,9 +3,12 @@ use crate::emitter_x64::*;
3
3
use crate :: x64_decl:: { new_machine_state, X64Register } ;
4
4
use smallvec:: smallvec;
5
5
use smallvec:: SmallVec ;
6
+ use std:: cmp;
6
7
use std:: collections:: HashSet ;
7
8
use wasmer_compiler:: wasmparser:: Type as WpType ;
8
9
10
+ const NATIVE_PAGE_SIZE : usize = 4096 ;
11
+
9
12
struct MachineStackOffset ( usize ) ;
10
13
11
14
pub struct Machine {
@@ -447,18 +450,48 @@ impl Machine {
447
450
}
448
451
}
449
452
450
- // Initialize all normal locals to zero.
451
- for i in n_params..n {
452
- a. emit_mov ( Size :: S64 , Location :: Imm32 ( 0 ) , locations[ i] ) ;
453
- }
454
-
455
453
// Load vmctx into R15.
456
454
a. emit_mov (
457
455
Size :: S64 ,
458
456
Self :: get_param_location ( 0 ) ,
459
457
Location :: GPR ( GPR :: R15 ) ,
460
458
) ;
461
459
460
+ // Stack probe.
461
+ //
462
+ // `rep stosq` writes data from low address to high address and may skip the stack guard page.
463
+ // so here we probe it explicitly when needed.
464
+ for i in ( n_params..n) . step_by ( NATIVE_PAGE_SIZE / 8 ) . skip ( 1 ) {
465
+ a. emit_mov ( Size :: S64 , Location :: Imm32 ( 0 ) , locations[ i] ) ;
466
+ }
467
+
468
+ //Initialize all normal locals to zero.
469
+ let mut init_stack_loc_cnt = 0 ;
470
+ let mut last_stack_loc = Location :: Memory ( GPR :: RBP , i32:: MAX ) ;
471
+ for i in n_params..n {
472
+ match locations[ i] {
473
+ Location :: Memory ( _, _) => {
474
+ init_stack_loc_cnt += 1 ;
475
+ last_stack_loc = cmp:: min ( last_stack_loc, locations[ i] ) ;
476
+ }
477
+ Location :: GPR ( _) => {
478
+ a. emit_mov ( Size :: S64 , Location :: Imm32 ( 0 ) , locations[ i] ) ;
479
+ }
480
+ _ => unreachable ! ( ) ,
481
+ }
482
+ }
483
+ if init_stack_loc_cnt > 0 {
484
+ // Since this assemblies takes up 24 bytes, If initialize more than 2 slots, These assemblies are smallar.
485
+ a. emit_mov (
486
+ Size :: S64 ,
487
+ Location :: Imm64 ( init_stack_loc_cnt as u64 ) ,
488
+ Location :: GPR ( GPR :: RCX ) ,
489
+ ) ;
490
+ a. emit_xor ( Size :: S64 , Location :: GPR ( GPR :: RAX ) , Location :: GPR ( GPR :: RAX ) ) ;
491
+ a. emit_lea ( Size :: S64 , last_stack_loc, Location :: GPR ( GPR :: RDI ) ) ;
492
+ a. emit_rep_stosq ( ) ;
493
+ }
494
+
462
495
// Add the size of all locals allocated to stack.
463
496
self . stack_offset . 0 += static_area_size - callee_saved_regs_size;
464
497
0 commit comments