fix USE_LD to eventually be restorable.
git-svn-id: https://yap.svn.sf.net/svnroot/yap/trunk@1201 b08c6af1-5177-4d33-ba66-4b1c6b8b522a
This commit is contained in:
parent
55c4f87043
commit
f0f6dd9de5
@ -550,16 +550,16 @@ p_get_att(void) {
|
|||||||
|
|
||||||
if (id != attvars_ext) {
|
if (id != attvars_ext) {
|
||||||
Yap_Error(TYPE_ERROR_VARIABLE,inp,"get_att/2");
|
Yap_Error(TYPE_ERROR_VARIABLE,inp,"get_att/2");
|
||||||
return(FALSE);
|
return FALSE;
|
||||||
}
|
}
|
||||||
out = GetAtt(attv,IntegerOfTerm(Deref(ARG2)));
|
out = GetAtt(attv,IntegerOfTerm(Deref(ARG2)));
|
||||||
return(!IsVarTerm(out) && Yap_unify(ARG3,out));
|
return !IsVarTerm(out) && Yap_unify(ARG3,out);
|
||||||
}
|
}
|
||||||
/* Yap_Error(INSTANTIATION_ERROR,inp,"get_att/2");*/
|
/* Yap_Error(INSTANTIATION_ERROR,inp,"get_att/2");*/
|
||||||
return(FALSE);
|
return FALSE;
|
||||||
} else {
|
} else {
|
||||||
Yap_Error(TYPE_ERROR_VARIABLE,inp,"get_att/2");
|
Yap_Error(TYPE_ERROR_VARIABLE,inp,"get_att/2");
|
||||||
return(FALSE);
|
return FALSE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
295
C/dlmalloc.c
295
C/dlmalloc.c
@ -202,227 +202,6 @@ yapsbrk(long size)
|
|||||||
return oldHeapTop;
|
return oldHeapTop;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
---------- Size and alignment checks and conversions ----------
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* conversion from malloc headers to user pointers, and back */
|
|
||||||
|
|
||||||
#define chunk2mem(p) ((Void_t*)((char*)(p) + 2*SIZE_SZ))
|
|
||||||
#define mem2chunk(mem) ((mchunkptr)((char*)(mem) - 2*SIZE_SZ))
|
|
||||||
|
|
||||||
/* The smallest possible chunk */
|
|
||||||
#define MIN_CHUNK_SIZE (sizeof(struct malloc_chunk))
|
|
||||||
|
|
||||||
/* The smallest size we can malloc is an aligned minimal chunk */
|
|
||||||
|
|
||||||
#define MINSIZE \
|
|
||||||
(CHUNK_SIZE_T)(((MIN_CHUNK_SIZE+MALLOC_ALIGN_MASK) & ~MALLOC_ALIGN_MASK))
|
|
||||||
|
|
||||||
/* Check if m has acceptable alignment */
|
|
||||||
|
|
||||||
#define aligned_OK(m) (((PTR_UINT)((m)) & (MALLOC_ALIGN_MASK)) == 0)
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
Check if a request is so large that it would wrap around zero when
|
|
||||||
padded and aligned. To simplify some other code, the bound is made
|
|
||||||
low enough so that adding MINSIZE will also not wrap around sero.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#define REQUEST_OUT_OF_RANGE(req) \
|
|
||||||
((CHUNK_SIZE_T)(req) >= \
|
|
||||||
(CHUNK_SIZE_T)(INTERNAL_SIZE_T)(-2 * MINSIZE))
|
|
||||||
|
|
||||||
/* pad request bytes into a usable size -- internal version */
|
|
||||||
|
|
||||||
#define request2size(req) \
|
|
||||||
(((req) + SIZE_SZ + MALLOC_ALIGN_MASK < MINSIZE) ? \
|
|
||||||
MINSIZE : \
|
|
||||||
((req) + SIZE_SZ + MALLOC_ALIGN_MASK) & ~MALLOC_ALIGN_MASK)
|
|
||||||
|
|
||||||
/* Same, except also perform argument check */
|
|
||||||
|
|
||||||
#define checked_request2size(req, sz) \
|
|
||||||
if (REQUEST_OUT_OF_RANGE(req)) { \
|
|
||||||
MALLOC_FAILURE_ACTION; \
|
|
||||||
return 0; \
|
|
||||||
} \
|
|
||||||
(sz) = request2size(req);
|
|
||||||
|
|
||||||
/*
|
|
||||||
--------------- Physical chunk operations ---------------
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
/* size field is or'ed with PREV_INUSE when previous adjacent chunk in use */
|
|
||||||
#define PREV_INUSE 0x1
|
|
||||||
|
|
||||||
/* extract inuse bit of previous chunk */
|
|
||||||
#define prev_inuse(p) ((p)->size & PREV_INUSE)
|
|
||||||
|
|
||||||
|
|
||||||
/* size field is or'ed with IS_MMAPPED if the chunk was obtained with mmap() */
|
|
||||||
#define IS_MMAPPED 0x2
|
|
||||||
|
|
||||||
/* check for mmap()'ed chunk */
|
|
||||||
#define chunk_is_mmapped(p) ((p)->size & IS_MMAPPED)
|
|
||||||
|
|
||||||
/*
|
|
||||||
Bits to mask off when extracting size
|
|
||||||
|
|
||||||
Note: IS_MMAPPED is intentionally not masked off from size field in
|
|
||||||
macros for which mmapped chunks should never be seen. This should
|
|
||||||
cause helpful core dumps to occur if it is tried by accident by
|
|
||||||
people extending or adapting this malloc.
|
|
||||||
*/
|
|
||||||
#define SIZE_BITS (PREV_INUSE|IS_MMAPPED)
|
|
||||||
|
|
||||||
/* Get size, ignoring use bits */
|
|
||||||
#define chunksize(p) ((p)->size & ~(SIZE_BITS))
|
|
||||||
|
|
||||||
|
|
||||||
/* Ptr to next physical malloc_chunk. */
|
|
||||||
#define next_chunk(p) ((mchunkptr)( ((char*)(p)) + ((p)->size & ~PREV_INUSE) ))
|
|
||||||
|
|
||||||
/* Ptr to previous physical malloc_chunk */
|
|
||||||
#define prev_chunk(p) ((mchunkptr)( ((char*)(p)) - ((p)->prev_size) ))
|
|
||||||
|
|
||||||
/* Treat space at ptr + offset as a chunk */
|
|
||||||
#define chunk_at_offset(p, s) ((mchunkptr)(((char*)(p)) + (s)))
|
|
||||||
|
|
||||||
/* extract p's inuse bit */
|
|
||||||
#define inuse(p)\
|
|
||||||
((((mchunkptr)(((char*)(p))+((p)->size & ~PREV_INUSE)))->size) & PREV_INUSE)
|
|
||||||
|
|
||||||
/* set/clear chunk as being inuse without otherwise disturbing */
|
|
||||||
#define set_inuse(p)\
|
|
||||||
((mchunkptr)(((char*)(p)) + ((p)->size & ~PREV_INUSE)))->size |= PREV_INUSE
|
|
||||||
|
|
||||||
#define clear_inuse(p)\
|
|
||||||
((mchunkptr)(((char*)(p)) + ((p)->size & ~PREV_INUSE)))->size &= ~(PREV_INUSE)
|
|
||||||
|
|
||||||
|
|
||||||
/* check/set/clear inuse bits in known places */
|
|
||||||
#define inuse_bit_at_offset(p, s)\
|
|
||||||
(((mchunkptr)(((char*)(p)) + (s)))->size & PREV_INUSE)
|
|
||||||
|
|
||||||
#define set_inuse_bit_at_offset(p, s)\
|
|
||||||
(((mchunkptr)(((char*)(p)) + (s)))->size |= PREV_INUSE)
|
|
||||||
|
|
||||||
#define clear_inuse_bit_at_offset(p, s)\
|
|
||||||
(((mchunkptr)(((char*)(p)) + (s)))->size &= ~(PREV_INUSE))
|
|
||||||
|
|
||||||
|
|
||||||
/* Set size at head, without disturbing its use bit */
|
|
||||||
#define set_head_size(p, s) ((p)->size = (((p)->size & PREV_INUSE) | (s)))
|
|
||||||
|
|
||||||
/* Set size/use field */
|
|
||||||
#define set_head(p, s) ((p)->size = (s))
|
|
||||||
|
|
||||||
/* Set size at footer (only when chunk is not in use) */
|
|
||||||
#define set_foot(p, s) (((mchunkptr)((char*)(p) + (s)))->prev_size = (s))
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
-------------------- Internal data structures --------------------
|
|
||||||
|
|
||||||
All internal state is held in an instance of malloc_state defined
|
|
||||||
below. There are no other static variables, except in two optional
|
|
||||||
cases:
|
|
||||||
* If USE_MALLOC_LOCK is defined, the mALLOC_MUTEx declared above.
|
|
||||||
* If HAVE_MMAP is true, but mmap doesn't support
|
|
||||||
MAP_ANONYMOUS, a dummy file descriptor for mmap.
|
|
||||||
|
|
||||||
Beware of lots of tricks that minimize the total bookkeeping space
|
|
||||||
requirements. The result is a little over 1K bytes (for 4byte
|
|
||||||
pointers and size_t.)
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
Bins
|
|
||||||
|
|
||||||
An array of bin headers for free chunks. Each bin is doubly
|
|
||||||
linked. The bins are approximately proportionally (log) spaced.
|
|
||||||
There are a lot of these bins (128). This may look excessive, but
|
|
||||||
works very well in practice. Most bins hold sizes that are
|
|
||||||
unusual as malloc request sizes, but are more usual for fragments
|
|
||||||
and consolidated sets of chunks, which is what these bins hold, so
|
|
||||||
they can be found quickly. All procedures maintain the invariant
|
|
||||||
that no consolidated chunk physically borders another one, so each
|
|
||||||
chunk in a list is known to be preceeded and followed by either
|
|
||||||
inuse chunks or the ends of memory.
|
|
||||||
|
|
||||||
Chunks in bins are kept in size order, with ties going to the
|
|
||||||
approximately least recently used chunk. Ordering isn't needed
|
|
||||||
for the small bins, which all contain the same-sized chunks, but
|
|
||||||
facilitates best-fit allocation for larger chunks. These lists
|
|
||||||
are just sequential. Keeping them in order almost never requires
|
|
||||||
enough traversal to warrant using fancier ordered data
|
|
||||||
structures.
|
|
||||||
|
|
||||||
Chunks of the same size are linked with the most
|
|
||||||
recently freed at the front, and allocations are taken from the
|
|
||||||
back. This results in LRU (FIFO) allocation order, which tends
|
|
||||||
to give each chunk an equal opportunity to be consolidated with
|
|
||||||
adjacent freed chunks, resulting in larger free chunks and less
|
|
||||||
fragmentation.
|
|
||||||
|
|
||||||
To simplify use in double-linked lists, each bin header acts
|
|
||||||
as a malloc_chunk. This avoids special-casing for headers.
|
|
||||||
But to conserve space and improve locality, we allocate
|
|
||||||
only the fd/bk pointers of bins, and then use repositioning tricks
|
|
||||||
to treat these as the fields of a malloc_chunk*.
|
|
||||||
*/
|
|
||||||
|
|
||||||
typedef struct malloc_chunk* mbinptr;
|
|
||||||
|
|
||||||
/* addressing -- note that bin_at(0) does not exist */
|
|
||||||
#define bin_at(m, i) ((mbinptr)((char*)&((m)->bins[(i)<<1]) - (SIZE_SZ<<1)))
|
|
||||||
|
|
||||||
/* analog of ++bin */
|
|
||||||
#define next_bin(b) ((mbinptr)((char*)(b) + (sizeof(mchunkptr)<<1)))
|
|
||||||
|
|
||||||
/* Reminders about list directionality within bins */
|
|
||||||
#define first(b) ((b)->fd)
|
|
||||||
#define last(b) ((b)->bk)
|
|
||||||
|
|
||||||
/* Take a chunk off a bin list */
|
|
||||||
#define unlink(P, BK, FD) { \
|
|
||||||
FD = P->fd; \
|
|
||||||
BK = P->bk; \
|
|
||||||
FD->bk = BK; \
|
|
||||||
BK->fd = FD; \
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
Indexing
|
|
||||||
|
|
||||||
Bins for sizes < 512 bytes contain chunks of all the same size, spaced
|
|
||||||
8 bytes apart. Larger bins are approximately logarithmically spaced:
|
|
||||||
|
|
||||||
64 bins of size 8
|
|
||||||
32 bins of size 64
|
|
||||||
16 bins of size 512
|
|
||||||
8 bins of size 4096
|
|
||||||
4 bins of size 32768
|
|
||||||
2 bins of size 262144
|
|
||||||
1 bin of size what's left
|
|
||||||
|
|
||||||
The bins top out around 1MB because we expect to service large
|
|
||||||
requests via mmap.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#define NBINS 96
|
|
||||||
#define NSMALLBINS 32
|
|
||||||
#define SMALLBIN_WIDTH 8
|
|
||||||
#define MIN_LARGE_SIZE 256
|
|
||||||
|
|
||||||
#define in_smallbin_range(sz) \
|
|
||||||
((CHUNK_SIZE_T)(sz) < (CHUNK_SIZE_T)MIN_LARGE_SIZE)
|
|
||||||
|
|
||||||
#define smallbin_index(sz) (((unsigned)(sz)) >> 3)
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Compute index for size. We expect this to be inlined when
|
Compute index for size. We expect this to be inlined when
|
||||||
compiled with optimization, else not, which works out well.
|
compiled with optimization, else not, which works out well.
|
||||||
@ -534,11 +313,6 @@ static int largebin_index(unsigned int sz) {
|
|||||||
when they are noticed to be empty during traversal in malloc.
|
when they are noticed to be empty during traversal in malloc.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* Conservatively use 32 bits per map word, even if on 64bit system */
|
|
||||||
#define BINMAPSHIFT 5
|
|
||||||
#define BITSPERMAP (1U << BINMAPSHIFT)
|
|
||||||
#define BINMAPSIZE (NBINS / BITSPERMAP)
|
|
||||||
|
|
||||||
#define idx2block(i) ((i) >> BINMAPSHIFT)
|
#define idx2block(i) ((i) >> BINMAPSHIFT)
|
||||||
#define idx2bit(i) ((1U << ((i) & ((1U << BINMAPSHIFT)-1))))
|
#define idx2bit(i) ((1U << ((i) & ((1U << BINMAPSHIFT)-1))))
|
||||||
|
|
||||||
@ -563,16 +337,6 @@ static int largebin_index(unsigned int sz) {
|
|||||||
other free chunks.
|
other free chunks.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
typedef struct malloc_chunk* mfastbinptr;
|
|
||||||
|
|
||||||
/* offset 2 to use otherwise unindexable first 2 bins */
|
|
||||||
#define fastbin_index(sz) ((((unsigned int)(sz)) >> 3) - 2)
|
|
||||||
|
|
||||||
/* The maximum fastbin request size we support */
|
|
||||||
#define MAX_FAST_SIZE 80
|
|
||||||
|
|
||||||
#define NFASTBINS (fastbin_index(request2size(MAX_FAST_SIZE))+1)
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
FASTBIN_CONSOLIDATION_THRESHOLD is the size of a chunk in free()
|
FASTBIN_CONSOLIDATION_THRESHOLD is the size of a chunk in free()
|
||||||
that triggers automatic consolidation of possibly-surrounding
|
that triggers automatic consolidation of possibly-surrounding
|
||||||
@ -646,51 +410,6 @@ typedef struct malloc_chunk* mfastbinptr;
|
|||||||
((M)->morecore_properties &= ~MORECORE_CONTIGUOUS_BIT)
|
((M)->morecore_properties &= ~MORECORE_CONTIGUOUS_BIT)
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
----------- Internal state representation and initialization -----------
|
|
||||||
*/
|
|
||||||
|
|
||||||
struct malloc_state {
|
|
||||||
|
|
||||||
/* The maximum chunk size to be eligible for fastbin */
|
|
||||||
INTERNAL_SIZE_T max_fast; /* low 2 bits used as flags */
|
|
||||||
|
|
||||||
/* Fastbins */
|
|
||||||
mfastbinptr fastbins[NFASTBINS];
|
|
||||||
|
|
||||||
/* Base of the topmost chunk -- not otherwise kept in a bin */
|
|
||||||
mchunkptr top;
|
|
||||||
|
|
||||||
/* The remainder from the most recent split of a small request */
|
|
||||||
mchunkptr last_remainder;
|
|
||||||
|
|
||||||
/* Normal bins packed as described above */
|
|
||||||
mchunkptr bins[NBINS * 2];
|
|
||||||
|
|
||||||
/* Bitmap of bins. Trailing zero map handles cases of largest binned size */
|
|
||||||
unsigned int binmap[BINMAPSIZE+1];
|
|
||||||
|
|
||||||
/* Tunable parameters */
|
|
||||||
CHUNK_SIZE_T trim_threshold;
|
|
||||||
INTERNAL_SIZE_T top_pad;
|
|
||||||
INTERNAL_SIZE_T mmap_threshold;
|
|
||||||
|
|
||||||
/* Cache malloc_getpagesize */
|
|
||||||
unsigned int pagesize;
|
|
||||||
|
|
||||||
/* Track properties of MORECORE */
|
|
||||||
unsigned int morecore_properties;
|
|
||||||
|
|
||||||
/* Statistics */
|
|
||||||
INTERNAL_SIZE_T mmapped_mem;
|
|
||||||
INTERNAL_SIZE_T sbrked_mem;
|
|
||||||
INTERNAL_SIZE_T max_sbrked_mem;
|
|
||||||
INTERNAL_SIZE_T max_mmapped_mem;
|
|
||||||
INTERNAL_SIZE_T max_total_mem;
|
|
||||||
};
|
|
||||||
|
|
||||||
typedef struct malloc_state *mstate;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
There is exactly one instance of this struct in this malloc.
|
There is exactly one instance of this struct in this malloc.
|
||||||
If you are adapting this malloc in a way that does NOT use a static
|
If you are adapting this malloc in a way that does NOT use a static
|
||||||
@ -1719,7 +1438,7 @@ Void_t* mALLOc(size_t bytes)
|
|||||||
|
|
||||||
if ((CHUNK_SIZE_T)(size) >= (CHUNK_SIZE_T)(nb)) {
|
if ((CHUNK_SIZE_T)(size) >= (CHUNK_SIZE_T)(nb)) {
|
||||||
remainder_size = size - nb;
|
remainder_size = size - nb;
|
||||||
unlink(victim, bck, fwd);
|
dl_unlink(victim, bck, fwd);
|
||||||
|
|
||||||
/* Exhaust */
|
/* Exhaust */
|
||||||
if (remainder_size < MINSIZE) {
|
if (remainder_size < MINSIZE) {
|
||||||
@ -1795,7 +1514,7 @@ Void_t* mALLOc(size_t bytes)
|
|||||||
|
|
||||||
remainder_size = size - nb;
|
remainder_size = size - nb;
|
||||||
|
|
||||||
/* unlink */
|
/* dl_unlink */
|
||||||
bck = victim->bk;
|
bck = victim->bk;
|
||||||
bin->bk = bck;
|
bin->bk = bck;
|
||||||
bck->fd = bin;
|
bck->fd = bin;
|
||||||
@ -1928,7 +1647,7 @@ void fREe(mem) Void_t* mem;
|
|||||||
prevsize = p->prev_size;
|
prevsize = p->prev_size;
|
||||||
size += prevsize;
|
size += prevsize;
|
||||||
p = chunk_at_offset(p, -((long) prevsize));
|
p = chunk_at_offset(p, -((long) prevsize));
|
||||||
unlink(p, bck, fwd);
|
dl_unlink(p, bck, fwd);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (nextchunk != av->top) {
|
if (nextchunk != av->top) {
|
||||||
@ -1938,7 +1657,7 @@ void fREe(mem) Void_t* mem;
|
|||||||
|
|
||||||
/* consolidate forward */
|
/* consolidate forward */
|
||||||
if (!nextinuse) {
|
if (!nextinuse) {
|
||||||
unlink(nextchunk, bck, fwd);
|
dl_unlink(nextchunk, bck, fwd);
|
||||||
size += nextsize;
|
size += nextsize;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2084,7 +1803,7 @@ static void malloc_consolidate(av) mstate av;
|
|||||||
prevsize = p->prev_size;
|
prevsize = p->prev_size;
|
||||||
size += prevsize;
|
size += prevsize;
|
||||||
p = chunk_at_offset(p, -((long) prevsize));
|
p = chunk_at_offset(p, -((long) prevsize));
|
||||||
unlink(p, bck, fwd);
|
dl_unlink(p, bck, fwd);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (nextchunk != av->top) {
|
if (nextchunk != av->top) {
|
||||||
@ -2093,7 +1812,7 @@ static void malloc_consolidate(av) mstate av;
|
|||||||
|
|
||||||
if (!nextinuse) {
|
if (!nextinuse) {
|
||||||
size += nextsize;
|
size += nextsize;
|
||||||
unlink(nextchunk, bck, fwd);
|
dl_unlink(nextchunk, bck, fwd);
|
||||||
}
|
}
|
||||||
|
|
||||||
first_unsorted = unsorted_bin->fd;
|
first_unsorted = unsorted_bin->fd;
|
||||||
@ -2203,7 +1922,7 @@ Void_t* rEALLOc(oldmem, bytes) Void_t* oldmem; size_t bytes;
|
|||||||
(CHUNK_SIZE_T)(newsize = oldsize + chunksize(next)) >=
|
(CHUNK_SIZE_T)(newsize = oldsize + chunksize(next)) >=
|
||||||
(CHUNK_SIZE_T)(nb)) {
|
(CHUNK_SIZE_T)(nb)) {
|
||||||
newp = oldp;
|
newp = oldp;
|
||||||
unlink(next, bck, fwd);
|
dl_unlink(next, bck, fwd);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* allocate, copy, free */
|
/* allocate, copy, free */
|
||||||
|
@ -3577,7 +3577,7 @@ call_gc(UInt gc_lim, Int predarity, CELL *current_env, yamop *nextop)
|
|||||||
* debug for(save_total=1; save_total<=N; ++save_total)
|
* debug for(save_total=1; save_total<=N; ++save_total)
|
||||||
* plwrite(XREGS[save_total],Yap_DebugPutc,0);
|
* plwrite(XREGS[save_total],Yap_DebugPutc,0);
|
||||||
*/
|
*/
|
||||||
return ( TRUE );
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
|
57
C/save.c
57
C/save.c
@ -23,6 +23,9 @@ static char SccsId[] = "@(#)save.c 1.3 3/15/90";
|
|||||||
#endif
|
#endif
|
||||||
#include "absmi.h"
|
#include "absmi.h"
|
||||||
#include "alloc.h"
|
#include "alloc.h"
|
||||||
|
#if USE_DL_MALLOC
|
||||||
|
#include "dlmalloc.h"
|
||||||
|
#endif
|
||||||
#include "yapio.h"
|
#include "yapio.h"
|
||||||
#include "sshift.h"
|
#include "sshift.h"
|
||||||
#include "Foreign.h"
|
#include "Foreign.h"
|
||||||
@ -1061,10 +1064,61 @@ RestoreIOStructures(void)
|
|||||||
Yap_InitStdStreams();
|
Yap_InitStdStreams();
|
||||||
}
|
}
|
||||||
|
|
||||||
/* restores the list of free space, with its curious structure */
|
#if USE_DL_MALLOC
|
||||||
|
static struct malloc_chunk *
|
||||||
|
RestoreFreeChunk(struct malloc_chunk *ptr)
|
||||||
|
{
|
||||||
|
if (ptr->fd) {
|
||||||
|
ptr->fd = ChunkPtrAdjust(ptr->fd);
|
||||||
|
}
|
||||||
|
if (ptr->bk) {
|
||||||
|
ptr->bk = ChunkPtrAdjust(ptr->bk);
|
||||||
|
}
|
||||||
|
return ptr;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
static void
|
static void
|
||||||
RestoreFreeSpace(void)
|
RestoreFreeSpace(void)
|
||||||
{
|
{
|
||||||
|
#if USE_DL_MALLOC
|
||||||
|
int i;
|
||||||
|
|
||||||
|
Yap_av = (struct malloc_state *)AddrAdjust((ADDR)Yap_av);
|
||||||
|
for (i = 0; i < NFASTBINS; i++) {
|
||||||
|
if (Yap_av->fastbins[i]) {
|
||||||
|
struct malloc_chunk *ptr;
|
||||||
|
|
||||||
|
Yap_av->fastbins[i] = ptr = ChunkPtrAdjust(Yap_av->fastbins[i]);
|
||||||
|
while (ptr) {
|
||||||
|
ptr = RestoreFreeChunk(ptr)->fd;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (Yap_av->top) {
|
||||||
|
Yap_av->top = ChunkPtrAdjust(Yap_av->top);
|
||||||
|
}
|
||||||
|
if (Yap_av->last_remainder) {
|
||||||
|
Yap_av->top = ChunkPtrAdjust(Yap_av->last_remainder);
|
||||||
|
}
|
||||||
|
for (i = 0; i < NBINS; i++) {
|
||||||
|
|
||||||
|
struct malloc_chunk *ptr;
|
||||||
|
|
||||||
|
if (Yap_av->bins[i*2]) {
|
||||||
|
Yap_av->bins[i*2] = ptr = ChunkPtrAdjust(Yap_av->bins[i*2]);
|
||||||
|
} else {
|
||||||
|
ptr = NULL;
|
||||||
|
}
|
||||||
|
if (Yap_av->bins[i*2+1]) {
|
||||||
|
Yap_av->bins[i*2+1] = ChunkPtrAdjust(Yap_av->bins[i*2+1]);
|
||||||
|
}
|
||||||
|
while (ptr && ptr != Yap_av->bins[i*2]) {
|
||||||
|
ptr = RestoreFreeChunk(ptr)->fd;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
/* restores the list of free space, with its curious structure */
|
||||||
register BlockHeader *bpt, *bsz;
|
register BlockHeader *bpt, *bsz;
|
||||||
if (FreeBlocks != NULL)
|
if (FreeBlocks != NULL)
|
||||||
FreeBlocks = BlockAdjust(FreeBlocks);
|
FreeBlocks = BlockAdjust(FreeBlocks);
|
||||||
@ -1089,6 +1143,7 @@ RestoreFreeSpace(void)
|
|||||||
bpt = bpt->b_next_size;
|
bpt = bpt->b_next_size;
|
||||||
}
|
}
|
||||||
*((YAP_SEG_SIZE *) HeapTop) = InUseFlag;
|
*((YAP_SEG_SIZE *) HeapTop) = InUseFlag;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
/* restore the atom entries which are invisible for the user */
|
/* restore the atom entries which are invisible for the user */
|
||||||
|
309
H/dlmalloc.h
309
H/dlmalloc.h
@ -1170,4 +1170,313 @@ nextchunk-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
|||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
---------- Size and alignment checks and conversions ----------
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* conversion from malloc headers to user pointers, and back */
|
||||||
|
|
||||||
|
#define chunk2mem(p) ((Void_t*)((char*)(p) + 2*SIZE_SZ))
|
||||||
|
#define mem2chunk(mem) ((mchunkptr)((char*)(mem) - 2*SIZE_SZ))
|
||||||
|
|
||||||
|
/* The smallest possible chunk */
|
||||||
|
#define MIN_CHUNK_SIZE (sizeof(struct malloc_chunk))
|
||||||
|
|
||||||
|
/* The smallest size we can malloc is an aligned minimal chunk */
|
||||||
|
|
||||||
|
#define MINSIZE \
|
||||||
|
(CHUNK_SIZE_T)(((MIN_CHUNK_SIZE+MALLOC_ALIGN_MASK) & ~MALLOC_ALIGN_MASK))
|
||||||
|
|
||||||
|
/* Check if m has acceptable alignment */
|
||||||
|
|
||||||
|
#define aligned_OK(m) (((PTR_UINT)((m)) & (MALLOC_ALIGN_MASK)) == 0)
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
Check if a request is so large that it would wrap around zero when
|
||||||
|
padded and aligned. To simplify some other code, the bound is made
|
||||||
|
low enough so that adding MINSIZE will also not wrap around sero.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define REQUEST_OUT_OF_RANGE(req) \
|
||||||
|
((CHUNK_SIZE_T)(req) >= \
|
||||||
|
(CHUNK_SIZE_T)(INTERNAL_SIZE_T)(-2 * MINSIZE))
|
||||||
|
|
||||||
|
/* pad request bytes into a usable size -- internal version */
|
||||||
|
|
||||||
|
#define request2size(req) \
|
||||||
|
(((req) + SIZE_SZ + MALLOC_ALIGN_MASK < MINSIZE) ? \
|
||||||
|
MINSIZE : \
|
||||||
|
((req) + SIZE_SZ + MALLOC_ALIGN_MASK) & ~MALLOC_ALIGN_MASK)
|
||||||
|
|
||||||
|
/* Same, except also perform argument check */
|
||||||
|
|
||||||
|
#define checked_request2size(req, sz) \
|
||||||
|
if (REQUEST_OUT_OF_RANGE(req)) { \
|
||||||
|
MALLOC_FAILURE_ACTION; \
|
||||||
|
return 0; \
|
||||||
|
} \
|
||||||
|
(sz) = request2size(req);
|
||||||
|
|
||||||
|
/*
|
||||||
|
--------------- Physical chunk operations ---------------
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
/* size field is or'ed with PREV_INUSE when previous adjacent chunk in use */
|
||||||
|
#define PREV_INUSE 0x1
|
||||||
|
|
||||||
|
/* extract inuse bit of previous chunk */
|
||||||
|
#define prev_inuse(p) ((p)->size & PREV_INUSE)
|
||||||
|
|
||||||
|
|
||||||
|
/* size field is or'ed with IS_MMAPPED if the chunk was obtained with mmap() */
|
||||||
|
#define IS_MMAPPED 0x2
|
||||||
|
|
||||||
|
/* check for mmap()'ed chunk */
|
||||||
|
#define chunk_is_mmapped(p) ((p)->size & IS_MMAPPED)
|
||||||
|
|
||||||
|
/*
|
||||||
|
Bits to mask off when extracting size
|
||||||
|
|
||||||
|
Note: IS_MMAPPED is intentionally not masked off from size field in
|
||||||
|
macros for which mmapped chunks should never be seen. This should
|
||||||
|
cause helpful core dumps to occur if it is tried by accident by
|
||||||
|
people extending or adapting this malloc.
|
||||||
|
*/
|
||||||
|
#define SIZE_BITS (PREV_INUSE|IS_MMAPPED)
|
||||||
|
|
||||||
|
/* Get size, ignoring use bits */
|
||||||
|
#define chunksize(p) ((p)->size & ~(SIZE_BITS))
|
||||||
|
|
||||||
|
|
||||||
|
/* Ptr to next physical malloc_chunk. */
|
||||||
|
#define next_chunk(p) ((mchunkptr)( ((char*)(p)) + ((p)->size & ~PREV_INUSE) ))
|
||||||
|
|
||||||
|
/* Ptr to previous physical malloc_chunk */
|
||||||
|
#define prev_chunk(p) ((mchunkptr)( ((char*)(p)) - ((p)->prev_size) ))
|
||||||
|
|
||||||
|
/* Treat space at ptr + offset as a chunk */
|
||||||
|
#define chunk_at_offset(p, s) ((mchunkptr)(((char*)(p)) + (s)))
|
||||||
|
|
||||||
|
/* extract p's inuse bit */
|
||||||
|
#define inuse(p)\
|
||||||
|
((((mchunkptr)(((char*)(p))+((p)->size & ~PREV_INUSE)))->size) & PREV_INUSE)
|
||||||
|
|
||||||
|
/* set/clear chunk as being inuse without otherwise disturbing */
|
||||||
|
#define set_inuse(p)\
|
||||||
|
((mchunkptr)(((char*)(p)) + ((p)->size & ~PREV_INUSE)))->size |= PREV_INUSE
|
||||||
|
|
||||||
|
#define clear_inuse(p)\
|
||||||
|
((mchunkptr)(((char*)(p)) + ((p)->size & ~PREV_INUSE)))->size &= ~(PREV_INUSE)
|
||||||
|
|
||||||
|
|
||||||
|
/* check/set/clear inuse bits in known places */
|
||||||
|
#define inuse_bit_at_offset(p, s)\
|
||||||
|
(((mchunkptr)(((char*)(p)) + (s)))->size & PREV_INUSE)
|
||||||
|
|
||||||
|
#define set_inuse_bit_at_offset(p, s)\
|
||||||
|
(((mchunkptr)(((char*)(p)) + (s)))->size |= PREV_INUSE)
|
||||||
|
|
||||||
|
#define clear_inuse_bit_at_offset(p, s)\
|
||||||
|
(((mchunkptr)(((char*)(p)) + (s)))->size &= ~(PREV_INUSE))
|
||||||
|
|
||||||
|
|
||||||
|
/* Set size at head, without disturbing its use bit */
|
||||||
|
#define set_head_size(p, s) ((p)->size = (((p)->size & PREV_INUSE) | (s)))
|
||||||
|
|
||||||
|
/* Set size/use field */
|
||||||
|
#define set_head(p, s) ((p)->size = (s))
|
||||||
|
|
||||||
|
/* Set size at footer (only when chunk is not in use) */
|
||||||
|
#define set_foot(p, s) (((mchunkptr)((char*)(p) + (s)))->prev_size = (s))
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
-------------------- Internal data structures --------------------
|
||||||
|
|
||||||
|
All internal state is held in an instance of malloc_state defined
|
||||||
|
below. There are no other static variables, except in two optional
|
||||||
|
cases:
|
||||||
|
* If USE_MALLOC_LOCK is defined, the mALLOC_MUTEx declared above.
|
||||||
|
* If HAVE_MMAP is true, but mmap doesn't support
|
||||||
|
MAP_ANONYMOUS, a dummy file descriptor for mmap.
|
||||||
|
|
||||||
|
Beware of lots of tricks that minimize the total bookkeeping space
|
||||||
|
requirements. The result is a little over 1K bytes (for 4byte
|
||||||
|
pointers and size_t.)
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
Bins
|
||||||
|
|
||||||
|
An array of bin headers for free chunks. Each bin is doubly
|
||||||
|
linked. The bins are approximately proportionally (log) spaced.
|
||||||
|
There are a lot of these bins (128). This may look excessive, but
|
||||||
|
works very well in practice. Most bins hold sizes that are
|
||||||
|
unusual as malloc request sizes, but are more usual for fragments
|
||||||
|
and consolidated sets of chunks, which is what these bins hold, so
|
||||||
|
they can be found quickly. All procedures maintain the invariant
|
||||||
|
that no consolidated chunk physically borders another one, so each
|
||||||
|
chunk in a list is known to be preceeded and followed by either
|
||||||
|
inuse chunks or the ends of memory.
|
||||||
|
|
||||||
|
Chunks in bins are kept in size order, with ties going to the
|
||||||
|
approximately least recently used chunk. Ordering isn't needed
|
||||||
|
for the small bins, which all contain the same-sized chunks, but
|
||||||
|
facilitates best-fit allocation for larger chunks. These lists
|
||||||
|
are just sequential. Keeping them in order almost never requires
|
||||||
|
enough traversal to warrant using fancier ordered data
|
||||||
|
structures.
|
||||||
|
|
||||||
|
Chunks of the same size are linked with the most
|
||||||
|
recently freed at the front, and allocations are taken from the
|
||||||
|
back. This results in LRU (FIFO) allocation order, which tends
|
||||||
|
to give each chunk an equal opportunity to be consolidated with
|
||||||
|
adjacent freed chunks, resulting in larger free chunks and less
|
||||||
|
fragmentation.
|
||||||
|
|
||||||
|
To simplify use in double-linked lists, each bin header acts
|
||||||
|
as a malloc_chunk. This avoids special-casing for headers.
|
||||||
|
But to conserve space and improve locality, we allocate
|
||||||
|
only the fd/bk pointers of bins, and then use repositioning tricks
|
||||||
|
to treat these as the fields of a malloc_chunk*.
|
||||||
|
*/
|
||||||
|
|
||||||
|
typedef struct malloc_chunk* mbinptr;
|
||||||
|
|
||||||
|
/* addressing -- note that bin_at(0) does not exist */
|
||||||
|
#define bin_at(m, i) ((mbinptr)((char*)&((m)->bins[(i)<<1]) - (SIZE_SZ<<1)))
|
||||||
|
|
||||||
|
/* analog of ++bin */
|
||||||
|
#define next_bin(b) ((mbinptr)((char*)(b) + (sizeof(mchunkptr)<<1)))
|
||||||
|
|
||||||
|
/* Reminders about list directionality within bins */
|
||||||
|
#define first(b) ((b)->fd)
|
||||||
|
#define last(b) ((b)->bk)
|
||||||
|
|
||||||
|
/* Take a chunk off a bin list */
|
||||||
|
#define dl_unlink(P, BK, FD) { \
|
||||||
|
FD = P->fd; \
|
||||||
|
BK = P->bk; \
|
||||||
|
FD->bk = BK; \
|
||||||
|
BK->fd = FD; \
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Indexing
|
||||||
|
|
||||||
|
Bins for sizes < 512 bytes contain chunks of all the same size, spaced
|
||||||
|
8 bytes apart. Larger bins are approximately logarithmically spaced:
|
||||||
|
|
||||||
|
64 bins of size 8
|
||||||
|
32 bins of size 64
|
||||||
|
16 bins of size 512
|
||||||
|
8 bins of size 4096
|
||||||
|
4 bins of size 32768
|
||||||
|
2 bins of size 262144
|
||||||
|
1 bin of size what's left
|
||||||
|
|
||||||
|
The bins top out around 1MB because we expect to service large
|
||||||
|
requests via mmap.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define NBINS 96
|
||||||
|
#define NSMALLBINS 32
|
||||||
|
#define SMALLBIN_WIDTH 8
|
||||||
|
#define MIN_LARGE_SIZE 256
|
||||||
|
|
||||||
|
#define in_smallbin_range(sz) \
|
||||||
|
((CHUNK_SIZE_T)(sz) < (CHUNK_SIZE_T)MIN_LARGE_SIZE)
|
||||||
|
|
||||||
|
#define smallbin_index(sz) (((unsigned)(sz)) >> 3)
|
||||||
|
|
||||||
|
/*
|
||||||
|
----------- Internal state representation and initialization -----------
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
Binmap
|
||||||
|
|
||||||
|
To help compensate for the large number of bins, a one-level index
|
||||||
|
structure is used for bin-by-bin searching. `binmap' is a
|
||||||
|
bitvector recording whether bins are definitely empty so they can
|
||||||
|
be skipped over during during traversals. The bits are NOT always
|
||||||
|
cleared as soon as bins are empty, but instead only
|
||||||
|
when they are noticed to be empty during traversal in malloc.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Conservatively use 32 bits per map word, even if on 64bit system */
|
||||||
|
#define BINMAPSHIFT 5
|
||||||
|
#define BITSPERMAP (1U << BINMAPSHIFT)
|
||||||
|
#define BINMAPSIZE (NBINS / BITSPERMAP)
|
||||||
|
|
||||||
|
/*
|
||||||
|
Fastbins
|
||||||
|
|
||||||
|
An array of lists holding recently freed small chunks. Fastbins
|
||||||
|
are not doubly linked. It is faster to single-link them, and
|
||||||
|
since chunks are never removed from the middles of these lists,
|
||||||
|
double linking is not necessary. Also, unlike regular bins, they
|
||||||
|
are not even processed in FIFO order (they use faster LIFO) since
|
||||||
|
ordering doesn't much matter in the transient contexts in which
|
||||||
|
fastbins are normally used.
|
||||||
|
|
||||||
|
Chunks in fastbins keep their inuse bit set, so they cannot
|
||||||
|
be consolidated with other free chunks. malloc_consolidate
|
||||||
|
releases all chunks in fastbins and consolidates them with
|
||||||
|
other free chunks.
|
||||||
|
*/
|
||||||
|
|
||||||
|
typedef struct malloc_chunk* mfastbinptr;
|
||||||
|
|
||||||
|
/* The maximum fastbin request size we support */
|
||||||
|
#define MAX_FAST_SIZE 80
|
||||||
|
|
||||||
|
/* offset 2 to use otherwise unindexable first 2 bins */
|
||||||
|
#define fastbin_index(sz) ((((unsigned int)(sz)) >> 3) - 2)
|
||||||
|
|
||||||
|
#define NFASTBINS (fastbin_index(request2size(MAX_FAST_SIZE))+1)
|
||||||
|
|
||||||
|
struct malloc_state {
|
||||||
|
|
||||||
|
/* The maximum chunk size to be eligible for fastbin */
|
||||||
|
INTERNAL_SIZE_T max_fast; /* low 2 bits used as flags */
|
||||||
|
|
||||||
|
/* Fastbins */
|
||||||
|
mfastbinptr fastbins[NFASTBINS];
|
||||||
|
|
||||||
|
/* Base of the topmost chunk -- not otherwise kept in a bin */
|
||||||
|
mchunkptr top;
|
||||||
|
|
||||||
|
/* The remainder from the most recent split of a small request */
|
||||||
|
mchunkptr last_remainder;
|
||||||
|
|
||||||
|
/* Normal bins packed as described above */
|
||||||
|
mchunkptr bins[NBINS * 2];
|
||||||
|
|
||||||
|
/* Bitmap of bins. Trailing zero map handles cases of largest binned size */
|
||||||
|
unsigned int binmap[BINMAPSIZE+1];
|
||||||
|
|
||||||
|
/* Tunable parameters */
|
||||||
|
CHUNK_SIZE_T trim_threshold;
|
||||||
|
INTERNAL_SIZE_T top_pad;
|
||||||
|
INTERNAL_SIZE_T mmap_threshold;
|
||||||
|
|
||||||
|
/* Cache malloc_getpagesize */
|
||||||
|
unsigned int pagesize;
|
||||||
|
|
||||||
|
/* Track properties of MORECORE */
|
||||||
|
unsigned int morecore_properties;
|
||||||
|
|
||||||
|
/* Statistics */
|
||||||
|
INTERNAL_SIZE_T mmapped_mem;
|
||||||
|
INTERNAL_SIZE_T sbrked_mem;
|
||||||
|
INTERNAL_SIZE_T max_sbrked_mem;
|
||||||
|
INTERNAL_SIZE_T max_mmapped_mem;
|
||||||
|
INTERNAL_SIZE_T max_total_mem;
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef struct malloc_state *mstate;
|
||||||
|
|
||||||
#endif /* USE_DL_MALLOC */
|
#endif /* USE_DL_MALLOC */
|
||||||
|
@ -90,6 +90,9 @@ Inline(PtoPredAdjust, PredEntry *, PredEntry *, ptr, ((PredEntry *)(CharP(ptr) +
|
|||||||
Inline(PtoArrayEAdjust, ArrayEntry *, ArrayEntry *, ptr, ((ArrayEntry *)(CharP(ptr) + HDiff)) )
|
Inline(PtoArrayEAdjust, ArrayEntry *, ArrayEntry *, ptr, ((ArrayEntry *)(CharP(ptr) + HDiff)) )
|
||||||
Inline(PtoLUCAdjust, struct logic_upd_clause *, struct logic_upd_clause *, ptr, ((struct logic_upd_clause *)(CharP(ptr) + HDiff)) )
|
Inline(PtoLUCAdjust, struct logic_upd_clause *, struct logic_upd_clause *, ptr, ((struct logic_upd_clause *)(CharP(ptr) + HDiff)) )
|
||||||
Inline(PtoStCAdjust, struct static_clause *, struct static_clause *, ptr, ((struct static_upd_clause *)(CharP(ptr) + HDiff)) )
|
Inline(PtoStCAdjust, struct static_clause *, struct static_clause *, ptr, ((struct static_upd_clause *)(CharP(ptr) + HDiff)) )
|
||||||
|
#if USE_DL_MALLOC
|
||||||
|
Inline(ChunkPtrAdjust, struct malloc_chunk *, struct malloc_chunk *, ptr, ((struct malloc_chunk *)(CharP(ptr) + HDiff)) )
|
||||||
|
#endif
|
||||||
#if PRECOMPUTE_REGADDRESS
|
#if PRECOMPUTE_REGADDRESS
|
||||||
Inline(XAdjust, wamreg, wamreg, reg, (wamreg)((reg)+XDiff) )
|
Inline(XAdjust, wamreg, wamreg, reg, (wamreg)((reg)+XDiff) )
|
||||||
#else
|
#else
|
||||||
|
Reference in New Issue
Block a user