-
Notifications
You must be signed in to change notification settings - Fork 1k
Description
Consider the following code:
(import (scheme))
(define (f1)
(with-continuation-mark 'key 'outer
(f2)))
(define (f2)
(car
(list
(call/cc
(lambda (c)
(continuation-marks->list (continuation-next-marks c) 'key))))))
(define (g1 x)
(with-continuation-mark 'key 'outer
(g2 x)))
(define kar car)
(define (g2 x)
(kar
(list
(fx+ x x))))
(pretty-print (f1))
(guard (c ((implementation-restriction-violation? c)
(pretty-print (continuation-marks->list (continuation-next-marks (condition-continuation c)) 'key))))
(pretty-print (g1 (greatest-fixnum))))
If it is run as a script (so that the optimiser cannot do interprocedural optimisations), it first prints (outer) and then (). The expected console output is (outer) twice.
The reason that it doesn't work as advertised in the manual (condition-continuation "indicates the current continuation at the point where the exception described by the condition occurred") is that the compiler basically turns the call to the error handler for fx+ into a tail call. This is the generated assembly on my machine:
g2:
entry.71:
0: subi (imm 1), $trap
5: beq lt.68(123)
ej.72:
7: cmpi (imm 1), %ac0
11: bne lf.67(105)
dcl.73:
13: mov %r8, %rcx
16: or %r8, %rcx
19: testib (imm 7), %rcx
22: bne Llib.66(79)
lt.74:
24: mov %r8, %rcx
27: add %r8, %rcx
30: bvs Llib.66(71)
ej.75:
32: lea (disp -7 %ap), %xp
36: addi (imm 16), %ap
40: cmp %ap, $eap
44: bcs Lget-room.65(42)
ej.64:
46: mov %xp, %r8
49: mov %rcx, (disp 7 %r8)
53: movi (imm 38), (disp 15 %r8)
61: movi (literal 0 (object kar.*top*:kar)), %xp
71: mov (disp 5 %xp), %cp
76: movi (imm 1), %ac0
83: jmp (disp 13 %xp)
Lget-room.65:
88: movi (imm 4294967295), %xp
98: call %xp
101: relocation: (x86_64-call 65 (library-code #(libspec get-room 178)))
101: bra ej.64(-57)
Llib.66:
103: mov %r8, %rdi
106: movi (imm 4294967295), %ts
116: jmp %ts
118: relocation: (x86_64-jump 65 (library-code #(libspec fx+ 51256)))
lf.67:
118: movi (imm 4294967295), %ts
128: jmp %ts
130: relocation: (x86_64-jump 65 (library-code #(libspec doargerr 176)))
lt.68:
130: movi (imm 4294967295), %ts
140: jmp %ts
142: relocation: (x86_64-jump 65 (library-code #(libspec event-detour 180)))
142: <end g2>
To fix it, the compiler must not treat calls to library error procedures as tail calls if they do not happen in tail position (but this will blow up the code size). Alternatively, the specification of (condition-continuation) must be weakened, making it less reliable. I haven't tested how much Racket is affected by this inaccuracy.