cranelift: Add inline stack probing for x64 (#4747)
* cranelift: Add inline stack probe for x64 * cranelift: Cleanups comments Thanks @jameysharp!
This commit is contained in:
@@ -0,0 +1,67 @@
|
||||
test compile precise-output
|
||||
set enable_probestack=true
|
||||
; Test with the larger size of 64k
|
||||
set probestack_size_log2=16
|
||||
set probestack_strategy=inline
|
||||
target x86_64
|
||||
|
||||
|
||||
|
||||
; If the stack size is just one page, we can avoid the stack probe entirely
|
||||
function %single_page() -> i64 system_v {
|
||||
ss0 = explicit_slot 8192
|
||||
|
||||
block0:
|
||||
v1 = stack_addr.i64 ss0
|
||||
return v1
|
||||
}
|
||||
|
||||
; pushq %rbp
|
||||
; movq %rsp, %rbp
|
||||
; subq %rsp, $8192, %rsp
|
||||
; block0:
|
||||
; lea rsp(0 + virtual offset), %rax
|
||||
; addq %rsp, $8192, %rsp
|
||||
; movq %rbp, %rsp
|
||||
; popq %rbp
|
||||
; ret
|
||||
|
||||
function %unrolled() -> i64 system_v {
|
||||
ss0 = explicit_slot 196608
|
||||
|
||||
block0:
|
||||
v1 = stack_addr.i64 ss0
|
||||
return v1
|
||||
}
|
||||
|
||||
; pushq %rbp
|
||||
; movq %rsp, %rbp
|
||||
; movl %esp, -65536(%rsp)
|
||||
; movl %esp, -131072(%rsp)
|
||||
; movl %esp, -196608(%rsp)
|
||||
; subq %rsp, $196608, %rsp
|
||||
; block0:
|
||||
; lea rsp(0 + virtual offset), %rax
|
||||
; addq %rsp, $196608, %rsp
|
||||
; movq %rbp, %rsp
|
||||
; popq %rbp
|
||||
; ret
|
||||
|
||||
function %large() -> i64 system_v {
|
||||
ss0 = explicit_slot 2097152
|
||||
|
||||
block0:
|
||||
v1 = stack_addr.i64 ss0
|
||||
return v1
|
||||
}
|
||||
|
||||
; pushq %rbp
|
||||
; movq %rsp, %rbp
|
||||
; stack_probe_loop %r11, frame_size=2097152, guard_size=65536
|
||||
; subq %rsp, $2097152, %rsp
|
||||
; block0:
|
||||
; lea rsp(0 + virtual offset), %rax
|
||||
; addq %rsp, $2097152, %rsp
|
||||
; movq %rbp, %rsp
|
||||
; popq %rbp
|
||||
; ret
|
||||
66
cranelift/filetests/filetests/isa/x64/inline-probestack.clif
Normal file
66
cranelift/filetests/filetests/isa/x64/inline-probestack.clif
Normal file
@@ -0,0 +1,66 @@
|
||||
test compile precise-output
|
||||
set enable_probestack=true
|
||||
set probestack_strategy=inline
|
||||
; This is the default and is equivalent to a page size of 4096
|
||||
set probestack_size_log2=12
|
||||
target x86_64
|
||||
|
||||
|
||||
; If the stack size is just one page, we can avoid the stack probe entirely
|
||||
function %single_page() -> i64 system_v {
|
||||
ss0 = explicit_slot 2048
|
||||
|
||||
block0:
|
||||
v1 = stack_addr.i64 ss0
|
||||
return v1
|
||||
}
|
||||
|
||||
; pushq %rbp
|
||||
; movq %rsp, %rbp
|
||||
; subq %rsp, $2048, %rsp
|
||||
; block0:
|
||||
; lea rsp(0 + virtual offset), %rax
|
||||
; addq %rsp, $2048, %rsp
|
||||
; movq %rbp, %rsp
|
||||
; popq %rbp
|
||||
; ret
|
||||
|
||||
function %unrolled() -> i64 system_v {
|
||||
ss0 = explicit_slot 12288
|
||||
|
||||
block0:
|
||||
v1 = stack_addr.i64 ss0
|
||||
return v1
|
||||
}
|
||||
|
||||
; pushq %rbp
|
||||
; movq %rsp, %rbp
|
||||
; movl %esp, -4096(%rsp)
|
||||
; movl %esp, -8192(%rsp)
|
||||
; movl %esp, -12288(%rsp)
|
||||
; subq %rsp, $12288, %rsp
|
||||
; block0:
|
||||
; lea rsp(0 + virtual offset), %rax
|
||||
; addq %rsp, $12288, %rsp
|
||||
; movq %rbp, %rsp
|
||||
; popq %rbp
|
||||
; ret
|
||||
|
||||
function %large() -> i64 system_v {
|
||||
ss0 = explicit_slot 100000
|
||||
|
||||
block0:
|
||||
v1 = stack_addr.i64 ss0
|
||||
return v1
|
||||
}
|
||||
|
||||
; pushq %rbp
|
||||
; movq %rsp, %rbp
|
||||
; stack_probe_loop %r11, frame_size=100000, guard_size=4096
|
||||
; subq %rsp, $100000, %rsp
|
||||
; block0:
|
||||
; lea rsp(0 + virtual offset), %rax
|
||||
; addq %rsp, $100000, %rsp
|
||||
; movq %rbp, %rsp
|
||||
; popq %rbp
|
||||
; ret
|
||||
@@ -1,5 +1,7 @@
|
||||
test run
|
||||
set enable_llvm_abi_extensions=true
|
||||
; Disable stack probes since these tests don't require them
|
||||
set enable_probestack=false
|
||||
target x86_64
|
||||
target aarch64
|
||||
target s390x
|
||||
|
||||
@@ -0,0 +1,37 @@
|
||||
test interpret
|
||||
test run
|
||||
set enable_probestack=true
|
||||
set probestack_strategy=inline
|
||||
|
||||
; This is the default and is equivalent to a page size of 4096
|
||||
set probestack_size_log2=12
|
||||
target x86_64
|
||||
; Test also with 64k pages
|
||||
set probestack_size_log2=16
|
||||
target x86_64
|
||||
|
||||
; Create a huge stack slot (1MB), way larger than PAGE_SIZE and touch the end of it.
|
||||
; This guarantees that we bypass the guard page, cause a page fault the OS isn't expecting
|
||||
; which turns into a segfault if we haven't correctly implemented stack probing.
|
||||
|
||||
function %probe_loop(i64) -> i64 {
|
||||
ss0 = explicit_slot 1048576
|
||||
|
||||
block0(v0: i64):
|
||||
stack_store.i64 v0, ss0
|
||||
v1 = stack_load.i64 ss0
|
||||
return v1
|
||||
}
|
||||
; run: %probe_loop(1) == 1
|
||||
|
||||
|
||||
; Tests the unrolled version of the stackprobe
|
||||
function %probe_unroll(i64) -> i64 {
|
||||
ss0 = explicit_slot 9000
|
||||
|
||||
block0(v0: i64):
|
||||
stack_store.i64 v0, ss0
|
||||
v1 = stack_load.i64 ss0
|
||||
return v1
|
||||
}
|
||||
; run: %probe_unroll(1) == 1
|
||||
@@ -1,5 +1,7 @@
|
||||
test interpret
|
||||
test run
|
||||
; Disable stack probes since these tests don't require them
|
||||
set enable_probestack=false
|
||||
target x86_64
|
||||
target s390x
|
||||
target aarch64
|
||||
|
||||
@@ -43,19 +43,6 @@ fn build_host_isa(
|
||||
builder.set(value.name, &value.value_string()).unwrap();
|
||||
}
|
||||
|
||||
// We need to force disable stack probing, since we don't support it yet.
|
||||
let flags = {
|
||||
let mut flags_builder = settings::builder();
|
||||
|
||||
// Copy all flags
|
||||
for flag in flags.iter() {
|
||||
flags_builder.set(flag.name, &flag.value_string()).unwrap();
|
||||
}
|
||||
|
||||
flags_builder.set("enable_probestack", "false").unwrap();
|
||||
settings::Flags::new(flags_builder)
|
||||
};
|
||||
|
||||
builder.finish(flags).unwrap()
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user