caml-list - the Caml user's mailing list
 help / color / mirror / Atom feed
* [Caml-list] How is the frametable handled when throwing exceptions?
@ 2017-02-11 14:02 Christoph Höger
  2017-02-11 14:10 ` Nicolás Ojeda Bär
  2017-02-13 15:13 ` Stephen Dolan
  0 siblings, 2 replies; 5+ messages in thread
From: Christoph Höger @ 2017-02-11 14:02 UTC (permalink / raw)
  To: OCaml Mailing List

[-- Attachment #1: Type: text/plain, Size: 857 bytes --]

Dear all,

while studying camls native code generation and garbage collection
strategy, I came upon Connor Benner's bachelor thesis from 2012, where he
implemented a llvm backend for ocamlopt. One intriguing remark mentioned
OCamls exception mechanism as basically consisting a pointer to the stack
frame of the last exception handler in a special register (r14, when I
recall correctly). Throwing an exception that becomes a mov/pop/ret
operation. This however, seems to interfere with garbage collection: From
the C-API, it seems that all local roots are stored in the frametable via
some special macros (e.g. CAMLParam, CAMLlocal).

When control just returns from a stack frame, how are the entries removed
from the frametable?

I would be glad, if someone could answer this or point me to the relevant
documentation (if any exists).

thanks,

Christoph

[-- Attachment #2: Type: text/html, Size: 974 bytes --]

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [Caml-list] How is the frametable handled when throwing exceptions?
  2017-02-11 14:02 [Caml-list] How is the frametable handled when throwing exceptions? Christoph Höger
@ 2017-02-11 14:10 ` Nicolás Ojeda Bär
  2017-02-12 13:25   ` Christoph Höger
  2017-02-13 15:13 ` Stephen Dolan
  1 sibling, 1 reply; 5+ messages in thread
From: Nicolás Ojeda Bär @ 2017-02-11 14:10 UTC (permalink / raw)
  To: Christoph Höger; +Cc: OCaml Mailing List

[-- Attachment #1: Type: text/plain, Size: 1409 bytes --]

Hi Christoph,

Someone who knows more will be able to get a better answer, but I don't
think there is much of an issue here:
when using the C API to register local roots (CAMLparam, CAMLlocal, etc),
these roots are in effect
stored in the C stack.  When raising an exception the stack is _cut down_
and all those roots
are promptly forgotten (as they should be).

Cheers,
Nicolas


On Sat, Feb 11, 2017 at 3:02 PM, Christoph Höger <
christoph.hoeger@celeraone.com> wrote:

> Dear all,
>
> while studying camls native code generation and garbage collection
> strategy, I came upon Connor Benner's bachelor thesis from 2012, where he
> implemented a llvm backend for ocamlopt. One intriguing remark mentioned
> OCamls exception mechanism as basically consisting a pointer to the stack
> frame of the last exception handler in a special register (r14, when I
> recall correctly). Throwing an exception that becomes a mov/pop/ret
> operation. This however, seems to interfere with garbage collection: From
> the C-API, it seems that all local roots are stored in the frametable via
> some special macros (e.g. CAMLParam, CAMLlocal).
>
> When control just returns from a stack frame, how are the entries removed
> from the frametable?
>
> I would be glad, if someone could answer this or point me to the relevant
> documentation (if any exists).
>
> thanks,
>
> Christoph
>

[-- Attachment #2: Type: text/html, Size: 1859 bytes --]

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [Caml-list] How is the frametable handled when throwing exceptions?
  2017-02-11 14:10 ` Nicolás Ojeda Bär
@ 2017-02-12 13:25   ` Christoph Höger
  2017-02-12 14:55     ` Nicolás Ojeda Bär
  0 siblings, 1 reply; 5+ messages in thread
From: Christoph Höger @ 2017-02-12 13:25 UTC (permalink / raw)
  To: Nicolás Ojeda Bär; +Cc: OCaml Mailing List

[-- Attachment #1: Type: text/plain, Size: 1946 bytes --]

Nicolás,

that is my understanding, too. But what I am missing is the
_de_-registration of the roots. AFAIK, the frametable is a static, global
object and when the stack is cut down, it then contains stale pointers. So
either the frametable is useless (as a global object), because the GC
traverses the call stack or there is some kind of deregstration going on
somewhere.

On Sat, Feb 11, 2017 at 3:10 PM, Nicolás Ojeda Bär <
nicolas.ojeda.bar@lexifi.com> wrote:

> Hi Christoph,
>
> Someone who knows more will be able to get a better answer, but I don't
> think there is much of an issue here:
> when using the C API to register local roots (CAMLparam, CAMLlocal, etc),
> these roots are in effect
> stored in the C stack.  When raising an exception the stack is _cut down_
> and all those roots
> are promptly forgotten (as they should be).
>
> Cheers,
> Nicolas
>
>
> On Sat, Feb 11, 2017 at 3:02 PM, Christoph Höger <
> christoph.hoeger@celeraone.com> wrote:
>
>> Dear all,
>>
>> while studying camls native code generation and garbage collection
>> strategy, I came upon Connor Benner's bachelor thesis from 2012, where he
>> implemented a llvm backend for ocamlopt. One intriguing remark mentioned
>> OCamls exception mechanism as basically consisting a pointer to the stack
>> frame of the last exception handler in a special register (r14, when I
>> recall correctly). Throwing an exception that becomes a mov/pop/ret
>> operation. This however, seems to interfere with garbage collection: From
>> the C-API, it seems that all local roots are stored in the frametable via
>> some special macros (e.g. CAMLParam, CAMLlocal).
>>
>> When control just returns from a stack frame, how are the entries removed
>> from the frametable?
>>
>> I would be glad, if someone could answer this or point me to the relevant
>> documentation (if any exists).
>>
>> thanks,
>>
>> Christoph
>>
>
>

[-- Attachment #2: Type: text/html, Size: 2715 bytes --]

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [Caml-list] How is the frametable handled when throwing exceptions?
  2017-02-12 13:25   ` Christoph Höger
@ 2017-02-12 14:55     ` Nicolás Ojeda Bär
  0 siblings, 0 replies; 5+ messages in thread
From: Nicolás Ojeda Bär @ 2017-02-12 14:55 UTC (permalink / raw)
  To: Christoph Höger; +Cc: OCaml Mailing List

[-- Attachment #1: Type: text/plain, Size: 3320 bytes --]

Hi Christoph,

No, the "frametable" is not a single static, global object (it would be
hard to make this work with separate compilation, etc).
Rather each function (both ML and C) is associated to a "frame descriptor"
detailing where to find live values (for ML functions, the frame descriptor
is associated to its function using the return address as a key).  When the
GC is triggered it traverses the stack (both ML and C) and collects the
full list of GC roots.  Of course there is also a list of "global" roots
which *are* registered in a single, global table.  For these roots indeed
one must deregister them explicitly (see caml_{register,remove}_global_root
and its "generational" friends).

Some pointers:

You can read the stack-walking code in

  https://github.com/ocaml/ocaml/blob/trunk/asmrun/roots.c#L438

When the GC is invoked when running ML code, this code depends on some
global pointers which are set up in the asm
glue, e.g.

  https://github.com/ocaml/ocaml/blob/trunk/asmrun/amd64.S

Finally frame descriptors are emitted in the native-code backends, e.g.:

  https://github.com/ocaml/ocaml/blob/trunk/asmcomp/amd64/emit.mlp#L241

Hope this helps,
Nicolas


On Sun, Feb 12, 2017 at 2:25 PM, Christoph Höger <
christoph.hoeger@celeraone.com> wrote:

> Nicolás,
>
> that is my understanding, too. But what I am missing is the
> _de_-registration of the roots. AFAIK, the frametable is a static, global
> object and when the stack is cut down, it then contains stale pointers. So
> either the frametable is useless (as a global object), because the GC
> traverses the call stack or there is some kind of deregstration going on
> somewhere.
>
> On Sat, Feb 11, 2017 at 3:10 PM, Nicolás Ojeda Bär <
> nicolas.ojeda.bar@lexifi.com> wrote:
>
>> Hi Christoph,
>>
>> Someone who knows more will be able to get a better answer, but I don't
>> think there is much of an issue here:
>> when using the C API to register local roots (CAMLparam, CAMLlocal, etc),
>> these roots are in effect
>> stored in the C stack.  When raising an exception the stack is _cut down_
>> and all those roots
>> are promptly forgotten (as they should be).
>>
>> Cheers,
>> Nicolas
>>
>>
>> On Sat, Feb 11, 2017 at 3:02 PM, Christoph Höger <
>> christoph.hoeger@celeraone.com> wrote:
>>
>>> Dear all,
>>>
>>> while studying camls native code generation and garbage collection
>>> strategy, I came upon Connor Benner's bachelor thesis from 2012, where he
>>> implemented a llvm backend for ocamlopt. One intriguing remark mentioned
>>> OCamls exception mechanism as basically consisting a pointer to the stack
>>> frame of the last exception handler in a special register (r14, when I
>>> recall correctly). Throwing an exception that becomes a mov/pop/ret
>>> operation. This however, seems to interfere with garbage collection: From
>>> the C-API, it seems that all local roots are stored in the frametable via
>>> some special macros (e.g. CAMLParam, CAMLlocal).
>>>
>>> When control just returns from a stack frame, how are the entries
>>> removed from the frametable?
>>>
>>> I would be glad, if someone could answer this or point me to the
>>> relevant documentation (if any exists).
>>>
>>> thanks,
>>>
>>> Christoph
>>>
>>
>>
>

[-- Attachment #2: Type: text/html, Size: 5005 bytes --]

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [Caml-list] How is the frametable handled when throwing exceptions?
  2017-02-11 14:02 [Caml-list] How is the frametable handled when throwing exceptions? Christoph Höger
  2017-02-11 14:10 ` Nicolás Ojeda Bär
@ 2017-02-13 15:13 ` Stephen Dolan
  1 sibling, 0 replies; 5+ messages in thread
From: Stephen Dolan @ 2017-02-13 15:13 UTC (permalink / raw)
  To: Christoph Höger; +Cc: OCaml Mailing List

[-- Attachment #1: Type: text/plain, Size: 2202 bytes --]

On 11 February 2017 at 14:02, Christoph Höger <
christoph.hoeger@celeraone.com> wrote:

> Dear all,
>
> while studying camls native code generation and garbage collection
> strategy, I came upon Connor Benner's bachelor thesis from 2012, where he
> implemented a llvm backend for ocamlopt. One intriguing remark mentioned
> OCamls exception mechanism as basically consisting a pointer to the stack
> frame of the last exception handler in a special register (r14, when I
> recall correctly). Throwing an exception that becomes a mov/pop/ret
> operation. This however, seems to interfere with garbage collection: From
> the C-API, it seems that all local roots are stored in the frametable via
> some special macros (e.g. CAMLParam, CAMLlocal).
>
> When control just returns from a stack frame, how are the entries removed
> from the frametable?
>

The frametable is a static data structure, which is a hashtable mapping
return addresses in OCaml functions to sets of stack offsets. When the GC
wants to traverse the stack, it walks the stack, picking out the return
address for each stack frame and looking them up in the frametable to find
out which stack slots are live. When OCaml code raises an exception, it
simply discards the stack up to the exception handler.

Code using the C API registers local roots in a different data structure
(caml_local_roots) using the CAMLlocal/param macros. When C code raises an
exception using caml_raise (see asmrun/fail.c), local roots are popped off
caml_local_roots one by one before raising the exception.

The tricky case is when OCaml code raises an exception, but there are C
frames between the top of the stack and the exception handler. To handle
this case, the implementation of caml_callback (calling OCaml from C)
unconditionally adds an exception handler. Should this exception handler
catch anything, it's rethrown with caml_raise.

The effect of this is that if an exception is thrown and the stack has a
mixture of OCaml and C frames before the exception handler, then the
exception will propagate by alternately cutting off OCaml segments of the
stack, and unwinding C segments of the stack.

Stephen

[-- Attachment #2: Type: text/html, Size: 2650 bytes --]

^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2017-02-13 15:13 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-02-11 14:02 [Caml-list] How is the frametable handled when throwing exceptions? Christoph Höger
2017-02-11 14:10 ` Nicolás Ojeda Bär
2017-02-12 13:25   ` Christoph Höger
2017-02-12 14:55     ` Nicolás Ojeda Bär
2017-02-13 15:13 ` Stephen Dolan

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).