/
callstack-overflow.factor
80 lines (65 loc) · 2.84 KB
/
callstack-overflow.factor
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
USING: accessors classes.struct continuations kernel kernel.private literals
math memory sequences system threads.private tools.dispatch.private
tools.test ;
QUALIFIED: vm
IN: compiler.tests.callstack-overflow
! This test file is for all callstack overflow-related problems.
: pre ( -- )
nano-count 0 = [ ] [ ] if ;
: post ( -- ) ;
: do-overflow ( -- )
pre do-overflow post ;
: recurse ( -- ? )
[ do-overflow f ] [ ] recover second ERROR-CALLSTACK-OVERFLOW = ;
: overflow-c ( -- ) overflow-c overflow-c ;
: overflow/w-primitive ( -- )
reset-dispatch-stats overflow/w-primitive post ;
: get-context ( -- ctx ) context vm:context memory>struct ;
: remaining-stack ( -- n )
get-context [ callstack-top>> ] [ callstack-seg>> start>> ] bi - ;
: overflow/w-compact-gc ( -- )
remaining-stack dup 500 < [
drop compact-gc
] [ drop overflow/w-compact-gc ] if post ;
! The VM cannot recover from callstack overflow on Windows, because no
! facility exists to run memory protection fault handlers on an
! alternate callstack. So we punt on the whole test-suite.
os windows? [
! This tries to verify that enough bytes are cut off from the
! callstack to run the error handler. It appears that the previous
! limit of 1024 bytes didn't give the gc enough stack space to
! work with, so we bumped that limit to 16384.
{ t } [
10 [ recurse ] replicate [ ] all?
] unit-test
! ! See how well callstack overflow is handled
! [ clear drop ] must-fail
!
! : callstack-overflow callstack-overflow f ;
! [ callstack-overflow ] must-fail
[ overflow-c ] [
2 head ${ KERNEL-ERROR ERROR-CALLSTACK-OVERFLOW } =
] must-fail-with
! The way this is problematic is because a primitive is
! involved. reset-dispatch-stats is called, decreasing RSP by cell
! bytes and then there is < 0x20 bytes stack left. Then SUB RSP,
! 0x18 is called to setup the call frame. Then the context is
! saved and ctx->callstack_top is set to RSP - 8 which is below
! the stack limit. Then dereferencing ctx->callstack_top segfaults
! so we need to handle the case specially in
! dispatch_non_resumable_signal().
[ overflow/w-primitive ] [
2 head ${ KERNEL-ERROR ERROR-CALLSTACK-OVERFLOW } =
] must-fail-with
! This test crashes with a Memory protection fault on OS X 64-bit
! for some reason. See #1478
cpu x86.64? os macosx? and [
! Load up the stack until there is < 500 bytes of it left. Then
! run a big gc cycle. 500 bytes isn't enough, so a callstack
! overflow would occur during the gc which we can't handle. The
! solution is to for the duration of the gc unlock the segment's
! lower guard page which gives it pagesize (4096) more bytes to
! play with.
{ } [ overflow/w-compact-gc ] unit-test
] unless
] unless