Next: Linking with C object files, Previous: Using pragma foreign_code for C, Up: Interfacing with C [Contents]
Passing pointers to dynamically-allocated memory from Mercury to code written in other languages, or vice versa, is in general implementation-dependent.
The current Mercury implementation supports two different methods of memory management: conservative garbage collection, or no garbage collection. The latter is suitable only for programs with very short running times (less than a second), which makes the former the standard method for almost all Mercury programs.
Conservative garbage collection makes inter-language calls simplest. Mercury uses the Boehm-Demers-Weiser conservative garbage collector, which we also call simply Boehm gc. This has its own set of functions for allocating memory blocks, such as ‘MR_GC_NEW’, which are documented in runtime/mercury_memory.h. Memory blocks allocated by these functions, either in C code generated by the Mercury compiler or in C code hand written by programmers, are automatically reclaimed when they are no longer referred to either from the stack, from global variables, or from other memory blocks allocated by Boehm gc functions. Note that these are the only places where Boehm gc looks for pointers to the blocks it has allocated. If the only pointers to such a block occur in other parts of memory, such as in memory blocks allocated by ‘malloc’, the Boehm collector won’t see them, and may collect the block prematurely. Programmers can avoid this either by not storing pointers to Boehm-allocated memory in malloc-allocated blocks, or by storing them e.g. on the stack as well.
Boehm gc recognizes pointers to the blocks it has allocated only if they point either to the start to the block, or to a byte in the first word of the block; pointers into the middle of a block beyond the first word won’t keep the block alive.
Pointers to Boehm-allocated memory blocks can be passed freely between Mercury and C code provided these restrictions are observed.
Note that the Boehm collector cannot and does not recover memory allocated by other methods, such as ‘malloc’.
When using no garbage collection,
heap storage is reclaimed only on backtracking.
This requires programmers to be careful
not to retain pointers to memory on the Mercury heap
after Mercury has backtracked
to before the point where that memory was allocated.
They must also avoid the use of the macros
MR_list_empty()
and MR_list_cons()
.
(The reason for this is that they may access Mercury’s ‘MR_hp’ register,
which might not be valid in C code.
Using them in the bodies of procedures
defined using ‘pragma foreign_proc’ with
‘will_not_call_mercury’ would probably work,
but we don’t advise it.)
Instead, you can write Mercury functions to perform these actions
and use ‘pragma foreign_export’ to access them from C.
This alternative method also works with conservative garbage collection.
Future Mercury implementations may use non-conservative methods of garbage collection. For such implementations, it will be necessary to explicitly register pointers passed to C with the garbage collector. The mechanism for doing this has not yet been decided on. It would be desirable to provide a single memory management interface for use when interfacing with other languages that can work for all methods of memory management, but more implementation experience is needed before we can formulate such an interface.
Next: Linking with C object files, Previous: Using pragma foreign_code for C, Up: Interfacing with C [Contents]