Files
mercury/runtime/mercury_memory.h
Mark Brown d465fa53cb Update the COPYING.LIB file and references to it.
Discussion of these changes can be found on the Mercury developers
mailing list archives from June 2018.

COPYING.LIB:
    Add a special linking exception to the LGPL.

*:
    Update references to COPYING.LIB.

    Clean up some minor errors that have accumulated in copyright
    messages.
2018-06-09 17:43:12 +10:00

389 lines
16 KiB
C

// vim: ts=4 sw=4 expandtab ft=c
// Copyright (C) 1994-2000,2002, 2004, 2006, 2008 The University of Melbourne.
// Copyright (C) 2014-2016, 2018 The Mercury Team.
// This file is distributed under the terms specified in COPYING.LIB.
// mercury_memory.h:
// general memory-allocation related stuff for the Mercury runtime.
//
// This defines the different memory areas used by the Mercury runtime,
// including the det & nondet stacks, the heap (and solutions heap),
// and the fake_reg array for holding Mercury virtual registers.
// It also provides interfaces for constructing new memory zones,
// and for allocating (possibly shared) memory.
#ifndef MERCURY_MEMORY_H
#define MERCURY_MEMORY_H
#include "mercury_memory_zones.h"
#include <stddef.h> // for size_t
#include "mercury_types.h" // for MR_Word
#include "mercury_std.h" // for MR_bool
#include "mercury_conf.h" // for MR_CONSERVATIVE_GC, etc.
#if defined(MR_CONSERVATIVE_GC)
#if defined(MR_BOEHM_GC)
#define GC_I_HIDE_POINTERS
#include "gc.h" // for GC_FREE
#endif
#endif
// MR_round_up(amount, align) returns `amount' rounded up to the nearest
// alignment boundary. `align' must be a power of 2.
#define MR_round_up(amount, align) ((((amount) - 1) | ((align) - 1)) + 1)
// MR_kilobytes_to_bytes_and_round_up(var) takes an original value in var
// which represents an memory size measured in kilobytes, and converts it to
// a memory size measured in bytes, and then rounds it up to be the next
// multiple of MR_unit.
#define MR_kilobytes_to_bytes_and_round_up(var) \
do { \
var = MR_round_up(var * 1024, MR_unit); \
} while (0)
// For these functions, see the comments in mercury_memory.c and
// mercury_engine.c
extern void MR_init_memory(void);
extern void MR_init_heap(void);
#ifdef MR_CONSERVATIVE_GC
extern void MR_init_conservative_GC(void);
#endif
////////////////////////////////////////////////////////////////////////////
// MR_malloc() and MR_realloc() are like the standard C malloc() and realloc()
// functions, except that the return values are checked.
//
// Structures allocated with MR_malloc() and MR_realloc() must NOT contain
// pointers into GC'ed memory, because those pointers will never be traced
// by the conservative GC. Use MR_GC_malloc() or MR_GC_malloc_uncollectable()
// for that.
//
// MR_NEW(type):
// Allocates space for an object of the specified type.
//
// MR_NEW_ARRAY(type, num):
// Allocates space for an array of objects of the specified type.
//
// MR_RESIZE_ARRAY(ptr, type, num):
// Resizes the array, as with realloc().
//
// MR_malloc(bytes):
// Allocates the given number of bytes.
//
// MR_realloc(old, bytes):
// Allocates the given number of bytes, copies over the old contents of
// the previously allocated block pointed to by old, and then frees that
// old block.
//
// MR_ensure_big_enough_buffer(buffer_ptr, buffer_size_ptr, needed_size):
// Given a character buffer pointed to by buffer_ptr whose is given by
// *buffer_size_ptr, ensure that the buffer is big enough to hold
// needed_size characters. If it needs to make the block bigger,
// this function will update both *buffer_ptr and *buffer_size_ptr.
//
// MR_free(ptr):
// Deallocates the memory.
extern void *MR_malloc(size_t n);
extern void *MR_realloc(void *old, size_t n);
extern void MR_ensure_big_enough_buffer(char **buffer_ptr,
int *buffer_size_ptr, int needed_size);
#define MR_free(ptr) free(ptr)
#define MR_free_func free
#define MR_NEW(type) \
((type *) MR_malloc(sizeof(type)))
#define MR_NEW_ARRAY(type, num) \
((type *) MR_malloc((num) * sizeof(type)))
#define MR_RESIZE_ARRAY(ptr, type, num) \
((type *) MR_realloc((ptr), (num) * sizeof(type)))
// These routines all allocate memory that will be traced by the
// conservative garbage collector, if conservative GC is enabled.
// (For the native GC, you need to call MR_add_root() to register roots.)
// These routines all check for a null return value themselves,
// so the caller need not check.
//
// MR_GC_NEW(type):
// Allocates space for an object of the specified type.
// If conservative GC is enabled, the object will be garbage collected
// when it is no longer referenced from GC-traced memory.
// Memory allocated with malloc() (or MR_malloc() or MR_NEW())
// is not GC-traced. Nor is thread-local storage.
//
// MR_GC_NEW_UNCOLLECTABLE(type):
// Allocates space for an object of the specified type.
// The object will not be garbage collected even if it is not referenced,
// or only referenced from thread-local storage or storage allocated
// with malloc(). It should be explicitly deallocated with MR_GC_free().
//
// MR_GC_NEW_ARRAY(type, num):
// Allocates space for an array of objects of the specified type.
//
// MR_GC_RESIZE_ARRAY(ptr, type, num):
// Resizes the array, as with realloc().
//
// MR_GC_malloc(bytes):
// Allocates the given number of bytes.
// If conservative GC is enabled, the memory will be garbage collected
// when it is no longer referenced from GC-traced memory (see above).
//
// MR_GC_malloc_uncollectable(bytes):
// Allocates the given number of bytes.
// The memory will not be garbage collected, and so it should be
// explicitly deallocated using MR_GC_free().
//
// MR_GC_malloc_atomic(bytes):
// Allocates the given number of bytes.
// Pointers to GC objects may not be stored in this object. This allows
// the GC to optimize its marking phase.
//
// MR_GC_realloc(ptr, bytes):
// Reallocates the memory block pointed to by ptr.
//
// MR_GC_free(ptr):
// Deallocates the memory.
//
// MR_GC_register_finalizer(ptr, finalize_func, data):
// When ptr is garbage collected invoke (*finalize_func)(ptr, data).
// ptr must have be a pointer to space allocated by the garbage collector.
// data is a pointer to some user-defined data.
// XXX currently this only works with the Boehm collector, i.e. in .gc
// grades, it is a no-op in non .gc grades.
//
// XXX this interface is subject to change.
//
// Note: consider using the _attrib variants below.
//
// MR_new_weak_ptr(ptr, object):
// Create a weak pointer to object and store it in the memory pointed to by
// ptr (a double pointer). object must have been allocated using one of
// the MR_GC methods. Weak pointers only work with the Boehm collector
// (.gc grades). In other grades this is an ordinary pointer.
//
// MR_weak_ptr_read(weak_ptr):
// Dereference a weak pointer. Returns NULL of the pointed to object has
// been deallocated. If weak_ptr is NULL then NULL is returned, so the
// programmer doesn't need to do an extra NULL check in case their pointer
// is deliberately NULL;
extern void *MR_GC_malloc(size_t num_bytes);
extern void *MR_GC_malloc_uncollectable(size_t num_bytes);
extern void *MR_GC_malloc_atomic(size_t num_bytes);
extern void *MR_GC_realloc(void *ptr, size_t num_bytes);
typedef void (*MR_GC_finalizer)(void *ptr, void *data);
#define MR_GC_NEW(type) \
((type *) MR_GC_malloc(sizeof(type)))
#define MR_GC_NEW_UNCOLLECTABLE(type) \
((type *) MR_GC_malloc_uncollectable(sizeof(type)))
#define MR_GC_NEW_ARRAY(type, num) \
((type *) MR_GC_malloc((num) * sizeof(type)))
#define MR_GC_RESIZE_ARRAY(ptr, type, num) \
((type *) MR_GC_realloc((ptr), (num) * sizeof(type)))
#ifdef MR_CONSERVATIVE_GC
#define MR_GC_free(ptr) GC_FREE(ptr)
#else
#define MR_GC_free(ptr) free(ptr)
#endif
#if defined(MR_CONSERVATIVE_GC) && defined(MR_BOEHM_GC)
#define MR_GC_register_finalizer(ptr, finalizer, data) \
GC_REGISTER_FINALIZER((ptr), (finalizer), (data), 0, 0)
#else
#define MR_GC_register_finalizer(ptr, finalizer, data)
#endif
// Don't dereference a weak pointer directly, it won't work as the pointer
// is hidden from the GC by storing its negated bits.
#ifdef MR_BOEHM_GC
#define MR_NULL_WEAK_PTR 0
typedef GC_hidden_pointer MR_weak_ptr;
#else
#define MR_NULL_WEAK_PTR NULL
typedef void* MR_weak_ptr;
#endif
// Create a weak pointer to obj and store the pointer in the memory pointed
// to by weak_ptr, which must be a pointer to an MR_weak_ptr. obj must not
// be an internal pointer and weak_ptr must be located within a heap object
// managed by the GC.
#ifdef MR_BOEHM_GC
#define MR_new_weak_ptr(weak_ptr, obj) \
do { \
int result; \
\
*(weak_ptr) = GC_HIDE_POINTER((obj)); \
/* \
** This call takes a double pointer, so it can clear the \
** user's pointer. Recall that *weak_ptr is a hidden pointer \
** a pointer cast to an int. \
*/ \
\
result = \
GC_general_register_disappearing_link((void**)(weak_ptr), (obj)); \
\
if (GC_DUPLICATE == result) { \
MR_fatal_error( \
"Error registering weak pointer: already registered"); \
} else if (GC_NO_MEMORY == result) { \
MR_fatal_error( \
"Error registering weak pointer: out of memory"); \
} \
} while (0)
#else
#define MR_new_weak_ptr(weak_ptr, obj) \
do { \
*(weak_ptr) = (obj); \
} while (0)
#endif
// Don't call this directly. It must be protected by Boehm's allocation lock,
// see MR_weak_ptr_read below.
#ifdef MR_BOEHM_GC
extern void*
MR_weak_ptr_read_unsafe(void* weak_ptr);
#endif
// Use this before dereferencing a weak pointer. weak_ptr must be a pointer
// to an MR_weak_ptr. This returns the real pointer that the weak pointer
// represents.
#ifdef MR_BOEHM_GC
#define MR_weak_ptr_read(weak_ptr) \
((MR_NULL_WEAK_PTR != *(weak_ptr)) ? \
GC_call_with_alloc_lock(MR_weak_ptr_read_unsafe, (weak_ptr)) : \
NULL)
#else
#define MR_weak_ptr_read(weak_ptr) \
(*(weak_ptr))
#endif
// MR_GC_NEW_ATTRIB(type, attrib):
// MR_GC_NEW_UNCOLLECTABLE_ATTRIB(type, attrib):
// MR_GC_NEW_ARRAY_ATTRIB(type, attrib):
// MR_GC_malloc_attrib(bytes, attrib):
// MR_GC_malloc_uncollectable_attrib(bytes, attrib):
// MR_GC_realloc_attrib(ptr, num_bytes):
// In grades with memory attribution support, these variants will allocate
// an extra word before the object. The value stored `attrib' is stored
// in that extra word.
//
// MR_GC_RESIZE_ARRAY_ATTRIB(ptr, type, num):
// MR_GC_free_attrib(ptr):
// These variants take into account the extra word before ptr.
// You must NOT pass pointers which were returned by non-"attrib"
// functions or macros to these "attrib" variants, and vice versa.
#define MR_GC_NEW_ATTRIB(type, attrib) \
((type *) MR_GC_malloc_attrib(sizeof(type), (attrib)))
#define MR_GC_NEW_UNCOLLECTABLE_ATTRIB(type, attrib) \
((type *) MR_GC_malloc_uncollectable_attrib(sizeof(type), (attrib)))
#define MR_GC_NEW_ARRAY_ATTRIB(type, num, attrib) \
((type *) MR_GC_malloc_attrib((num) * sizeof(type), (attrib)))
#define MR_GC_RESIZE_ARRAY_ATTRIB(ptr, type, num) \
((type *) MR_GC_realloc_attrib((ptr), (num) * sizeof(type)))
extern void *MR_GC_malloc_attrib(size_t num_bytes, void *attrib);
extern void *MR_GC_malloc_uncollectable_attrib(size_t num_bytes,
void *attrib);
extern void *MR_GC_realloc_attrib(void *ptr, size_t num_bytes);
extern void MR_GC_free_attrib(void *ptr);
struct MR_AllocSiteInfo_Struct {
MR_Code *MR_asi_proc;
const char *MR_asi_file_name;
const int MR_asi_line_number;
const char *MR_asi_type;
const int MR_asi_words;
};
// Builtin allocation site ids for use in the runtime and other
// hand-written code when context-specific ids are unavailable.
// MR_ALLOC_SITE_RUNTIME is a catch-all for internal runtime structures;
// these are hidden by default in `mprof -s' output.
#define MR_ALLOC_SITE_NONE ((void *) 0)
#ifdef MR_MPROF_PROFILE_MEMORY_ATTRIBUTION
// These must match the entries in mercury_heap_profile.c.
extern MR_AllocSiteInfo MR_builtin_alloc_sites[9];
#define MR_ALLOC_SITE_RUNTIME ((void *) &MR_builtin_alloc_sites[0])
#define MR_ALLOC_SITE_FLOAT ((void *) &MR_builtin_alloc_sites[1])
#define MR_ALLOC_SITE_STRING ((void *) &MR_builtin_alloc_sites[2])
#define MR_ALLOC_SITE_TYPE_INFO ((void *) &MR_builtin_alloc_sites[3])
#define MR_ALLOC_SITE_FOREIGN ((void *) &MR_builtin_alloc_sites[4])
#define MR_ALLOC_SITE_TABLING ((void *) &MR_builtin_alloc_sites[5])
#define MR_ALLOC_SITE_STM ((void *) &MR_builtin_alloc_sites[6])
#define MR_ALLOC_SITE_INT64 ((void *) &MR_builtin_alloc_sites[7])
#define MR_ALLOC_SITE_UINT64 ((void *) &MR_builtin_alloc_sites[8])
#else
#define MR_ALLOC_ID MR_ALLOC_SITE_NONE
#define MR_ALLOC_SITE_RUNTIME MR_ALLOC_SITE_NONE
#define MR_ALLOC_SITE_FLOAT MR_ALLOC_SITE_NONE
#define MR_ALLOC_SITE_STRING MR_ALLOC_SITE_NONE
#define MR_ALLOC_SITE_TYPE_INFO MR_ALLOC_SITE_NONE
#define MR_ALLOC_SITE_FOREIGN MR_ALLOC_SITE_NONE
#define MR_ALLOC_SITE_TABLING MR_ALLOC_SITE_NONE
#define MR_ALLOC_SITE_STM MR_ALLOC_SITE_NONE
#define MR_ALLOC_SITE_INT64 MR_ALLOC_SITE_NONE
#define MR_ALLOC_SITE_UINT64 MR_ALLOC_SITE_NONE
#endif
extern void *MR_new_object_func(size_t num_bytes,
MR_AllocSiteInfoPtr alloc_id, const char *name);
extern void *MR_new_object_atomic_func(size_t num_bytes,
MR_AllocSiteInfoPtr alloc_id, const char *name);
////////////////////////////////////////////////////////////////////////////
// MR_copy_string makes a copy of the given string,
// using memory allocated with MR_malloc().
extern char *MR_copy_string(const char *s);
////////////////////////////////////////////////////////////////////////////
// `MR_unit' is the size of the minimum unit of memory we allocate (in bytes).
// `MR_page_size' is the size of a single page of memory.
extern size_t MR_unit;
extern size_t MR_page_size;
////////////////////////////////////////////////////////////////////////////
// Users need to call MR_add_root() for any global variable which contains
// pointers to the Mercury heap. This information is only used for agc grades.
#ifdef MR_NATIVE_GC
#define MR_add_root(root_ptr, type_info) \
MR_agc_add_root((root_ptr), (type_info))
#else
#define MR_add_root(root_ptr, type_info) // nothing
#endif
////////////////////////////////////////////////////////////////////////////
#endif // not MERCURY_MEMORY_H