Alien-Judy

 view release on metacpan or  search on metacpan

src/judy-1.0.5/test/malloc-pre2.8a.c  view on Meta::CPAN

  Because freed chunks may be overwritten with bookkeeping fields, this
  malloc will often die when freed memory is overwritten by user
  programs.  This can be very effective (albeit in an annoying way)
  in helping track down dangling pointers.

  If you compile with -DDEBUG, a number of assertion checks are
  enabled that will catch more memory errors. You probably won't be
  able to make much sense of the actual assertion errors, but they
  should help you locate incorrectly overwritten memory.  The
  checking is fairly extensive, and will slow down execution
  noticeably. Calling malloc_stats or mallinfo with DEBUG set will
  attempt to check every non-mmapped allocated and free chunk in the
  course of computing the summmaries. (By nature, mmapped regions
  cannot be checked very much automatically.)

  Setting DEBUG may also be helpful if you are trying to modify
  this code. The assertions in the check routines spell out in more
  detail the assumptions and invariants underlying the algorithms.

  Setting DEBUG does NOT provide an automated mechanism for checking
  that all accesses to malloced memory stay within their
  bounds. However, there are several add-ons and adaptations of this
  or other mallocs available that do this.
*/

#if DEBUG
#include <assert.h>
/* #define assert(x) if(!(x)) abort() */ 

#else
#define assert(x) ((void)0)
#endif

/*
  The unsigned integer type used for comparing any two chunk sizes.
  This should be at least as wide as size_t, but should not be signed.
*/

#ifndef CHUNK_SIZE_T
#define CHUNK_SIZE_T unsigned long
#endif

#define MAX_CHUNK_SIZE  ((CHUNK_SIZE_T)(-1UL))

/* 
  The unsigned integer type used to hold addresses when they are are
  manipulated as integers. Except that it is not defined on all
  systems, intptr_t would suffice.
*/
#ifndef PTR_UINT
#define PTR_UINT unsigned long
#endif


/*
  INTERNAL_SIZE_T is the word-size used for internal bookkeeping
  of chunk sizes.

  The default version is the same as size_t.

  While not strictly necessary, it is best to define this as an
  unsigned type, even if size_t is a signed type. This may avoid some
  artificial size limitations on some systems.

  On a 64-bit machine, you may be able to reduce malloc overhead by
  defining INTERNAL_SIZE_T to be a 32 bit `unsigned int' at the
  expense of not being able to handle more than 2^32 of malloced
  space. If this limitation is acceptable, you are encouraged to set
  this unless you are on a platform requiring 16byte alignments. In
  this case the alignment requirements turn out to negate any
  potential advantages of decreasing size_t word size.

  Implementors: Beware of the possible combinations of:
     - INTERNAL_SIZE_T might be signed or unsigned, might be 32 or 64 bits,
       and might be the same width as int or as long
     - size_t might have different width and signedness as INTERNAL_SIZE_T
     - int and long might be 32 or 64 bits, and might be the same width
  To deal with this, most comparisons and difference computations
  among INTERNAL_SIZE_Ts should cast them to CHUNK_SIZE_T, being
  aware of the fact that casting an unsigned int to a wider long does
  not sign-extend. (This also makes checking for negative numbers
  awkward.) Some of these casts result in harmless compiler warnings
  on some systems.
*/

#ifndef INTERNAL_SIZE_T
#define INTERNAL_SIZE_T size_t
#endif

/* The corresponding word size */
#define SIZE_SZ                (sizeof(INTERNAL_SIZE_T))



/*
  MALLOC_ALIGNMENT is the minimum alignment for malloc'ed chunks.
  It must be a power of two at least 2 * SIZE_SZ, even on machines
  for which smaller alignments would suffice. It may be defined as
  larger than this though. Note however that code and data structures
  are optimized for the case of 8-byte alignment.
*/


#ifndef MALLOC_ALIGNMENT
#define MALLOC_ALIGNMENT       (2 * SIZE_SZ)
#endif

/* The corresponding bit mask value */
#define MALLOC_ALIGN_MASK      (MALLOC_ALIGNMENT - 1)



/*
  REALLOC_ZERO_BYTES_FREES should be set if a call to
  realloc with zero bytes should be the same as a call to free.
  Some people think it should. Otherwise, since this malloc
  returns a unique pointer for malloc(0), so does realloc(p, 0).
*/

/*   #define REALLOC_ZERO_BYTES_FREES */

src/judy-1.0.5/test/malloc-pre2.8a.c  view on Meta::CPAN


#ifdef LACKS_UNISTD_H
#if !defined(__FreeBSD__) && !defined(__OpenBSD__) && !defined(__NetBSD__)
extern Void_t*     sbrk(ptrdiff_t);
#endif
#endif

/*
  MORECORE is the name of the routine to call to obtain more memory
  from the system.  See below for general guidance on writing
  alternative MORECORE functions, as well as a version for WIN32 and a
  sample version for pre-OSX macos.
*/

#ifndef MORECORE
#define MORECORE sbrk
#endif

/*
  MORECORE_FAILURE is the value returned upon failure of MORECORE
  as well as mmap. Since it cannot be an otherwise valid memory address,
  and must reflect values of standard sys calls, you probably ought not
  try to redefine it.
*/

#ifndef MORECORE_FAILURE
#define MORECORE_FAILURE (-1)
#endif

/*
  If MORECORE_CONTIGUOUS is true, take advantage of fact that
  consecutive calls to MORECORE with positive arguments always return
  contiguous increasing addresses.  This is true of unix sbrk.  Even
  if not defined, when regions happen to be contiguous, malloc will
  permit allocations spanning regions obtained from different
  calls. But defining this when applicable enables some stronger
  consistency checks and space efficiencies. 
*/

#ifndef MORECORE_CONTIGUOUS
#define MORECORE_CONTIGUOUS 1
#endif

/*
  Define MORECORE_CANNOT_TRIM if your version of MORECORE
  cannot release space back to the system when given negative
  arguments. This is generally necessary only if you are using
  a hand-crafted MORECORE function that cannot handle negative arguments.
*/

/* #define MORECORE_CANNOT_TRIM */


/*
  Define HAVE_MMAP as true to optionally make malloc() use mmap() to
  allocate very large blocks.  These will be returned to the
  operating system immediately after a free(). Also, if mmap
  is available, it is used as a backup strategy in cases where
  MORECORE fails to provide space from system.

  This malloc is best tuned to work with mmap for large requests.
  If you do not have mmap, operations involving very large chunks (1MB
  or so) may be slower than you'd like.
*/

#define HAVE_MMAP 0

#ifndef HAVE_MMAP
#define HAVE_MMAP 1
#endif

#if HAVE_MMAP
/* 
   Standard unix mmap using /dev/zero clears memory so calloc doesn't
   need to.
*/

#ifndef MMAP_CLEARS
#define MMAP_CLEARS 1
#endif

#else /* no mmap */
#ifndef MMAP_CLEARS
#define MMAP_CLEARS 0
#endif
#endif


/* 
   MMAP_AS_MORECORE_SIZE is the minimum mmap size argument to use if
   sbrk fails, and mmap is used as a backup (which is done only if
   HAVE_MMAP).  The value must be a multiple of page size.  This
   backup strategy generally applies only when systems have "holes" in
   address space, so sbrk cannot perform contiguous expansion, but
   there is still space available on system.  On systems for which
   this is known to be useful (i.e. most linux kernels), this occurs
   only when programs allocate huge amounts of memory.  Between this,
   and the fact that mmap regions tend to be limited, the size should
   be large, to avoid too many mmap calls and thus avoid running out
   of kernel resources.
*/

#ifndef MMAP_AS_MORECORE_SIZE
#define MMAP_AS_MORECORE_SIZE (1024 * 1024)
#endif

/*
  Define HAVE_MREMAP to make realloc() use mremap() to re-allocate
  large blocks.  This is currently only possible on Linux with
  kernel versions newer than 1.3.77.
*/

#ifndef HAVE_MREMAP
#ifdef linux
#define HAVE_MREMAP 1
#else
#define HAVE_MREMAP 0
#endif

#endif /* HAVE_MMAP */

src/judy-1.0.5/test/malloc-pre2.8a.c  view on Meta::CPAN

  malloc_usable_size(Void_t* p);

  Returns the number of bytes you can actually use in
  an allocated chunk, which may be more than you requested (although
  often not) due to alignment and minimum size constraints.
  You can use this many bytes without worrying about
  overwriting other allocated objects. This is not a particularly great
  programming practice. malloc_usable_size can be more useful in
  debugging and assertions, for example:

  p = malloc(n);
  assert(malloc_usable_size(p) >= 256);

*/
size_t   public_mUSABLe(Void_t*);

/*
  malloc_stats();
  Prints on stderr the amount of space obtained from the system (both
  via sbrk and mmap), the maximum amount (which may be more than
  current if malloc_trim and/or munmap got called), and the current
  number of bytes allocated via malloc (or realloc, etc) but not yet
  freed. Note that this is the number of bytes allocated, not the
  number requested. It will be larger than the number requested
  because of alignment and bookkeeping overhead. Because it includes
  alignment wastage as being in use, this figure may be greater than
  zero even when no user-level chunks are allocated.

  The reported current and maximum system memory can be inaccurate if
  a program makes other calls to system memory allocation functions
  (normally sbrk) outside of malloc.

  malloc_stats prints only the most commonly interesting statistics.
  More information can be obtained by calling mallinfo.

*/
void     public_mSTATs();

/* mallopt tuning options */

/*
  M_MXFAST is the maximum request size used for "fastbins", special bins
  that hold returned chunks without consolidating their spaces. This
  enables future requests for chunks of the same size to be handled
  very quickly, but can increase fragmentation, and thus increase the
  overall memory footprint of a program.

  This malloc manages fastbins very conservatively yet still
  efficiently, so fragmentation is rarely a problem for values less
  than or equal to the default.  The maximum supported value of MXFAST
  is 64 (also the default). You wouldn't want it any higher than this
  anyway.  Fastbins are designed especially for use with many small
  structs, objects or strings -- the default handles
  structs/objects/arrays with sizes up to 16 4byte fields, or small
  strings representing words, tokens, etc. Using fastbins for larger
  objects normally worsens fragmentation without improving speed.

  M_MXFAST is set in REQUEST size units. It is internally used in
  chunksize units, which adds padding and alignment.  You can reduce
  M_MXFAST to 0 to disable all use of fastbins.  This causes the malloc
  algorithm to be a closer approximation of fifo-best-fit in all cases,
  not just for larger requests, but will generally cause it to be
  slower.
*/


/* M_MXFAST is a standard SVID/XPG tuning option, usually listed in malloc.h */
#ifndef M_MXFAST
#define M_MXFAST            1    
#endif

#ifndef DEFAULT_MXFAST
#define DEFAULT_MXFAST     64
#endif


/*
  M_TRIM_THRESHOLD is the maximum amount of unused top-most memory
  to keep before releasing via malloc_trim in free().

  Automatic trimming is mainly useful in long-lived programs.
  Because trimming via sbrk can be slow on some systems, and can
  sometimes be wasteful (in cases where programs immediately
  afterward allocate more large chunks) the value should be high
  enough so that your overall system performance would improve by
  releasing this much memory.

  The trim threshold and the mmap control parameters (see below)
  can be traded off with one another. Trimming and mmapping are
  two different ways of releasing unused memory back to the
  system. Between these two, it is often possible to keep
  system-level demands of a long-lived program down to a bare
  minimum. For example, in one test suite of sessions measuring
  the XF86 X server on Linux, using a trim threshold of 128K and a
  mmap threshold of 192K led to near-minimal long term resource
  consumption.

  If you are using this malloc in a long-lived program, it should
  pay to experiment with these values.  As a rough guide, you
  might set to a value close to the average size of a process
  (program) running on your system.  Releasing this much memory
  would allow such a process to run in memory.  Generally, it's
  worth it to tune for trimming rather tham memory mapping when a
  program undergoes phases where several large chunks are
  allocated and released in ways that can reuse each other's
  storage, perhaps mixed with phases where there are no such
  chunks at all.  And in well-behaved long-lived programs,
  controlling release of large blocks via trimming versus mapping
  is usually faster.

  However, in most programs, these parameters serve mainly as
  protection against the system-level effects of carrying around
  massive amounts of unneeded memory. Since frequent calls to
  sbrk, mmap, and munmap otherwise degrade performance, the default
  parameters are set to relatively high values that serve only as
  safeguards.

  The trim value must be greater than page size to have any useful
  effect.  To disable trimming completely, you can set to 
  (unsigned long)(-1)

src/judy-1.0.5/test/malloc-pre2.8a.c  view on Meta::CPAN

  mark_smallbin(av, idx);
  p->fd = fwd;
  p->bk = bck;
  fwd->bk = bck->fd = p;

  assert(in_smallbin_range(nb));
}

static void insert_chunk(mstate av, mchunkptr p, CHUNK_SIZE_T nb) { 
  if (in_smallbin_range(nb)) 
    insert_small_chunk(av, p, nb);
  else 
    insert_treenode(av, (tchunkptr)p, nb);
}


static mchunkptr take_from_smallbin(mstate av, mchunkptr bin, bitmap_t bit) {
  mchunkptr p = bin->bk;
  mchunkptr bck = p->bk;
  assert(p != bin);
  bin->bk = bck;
  bck->fd = bin;
  if (bck == bin)
    av->smallbits &= ~bit; 
  return p;
}

static void unlink_chunk(mstate av, mchunkptr q, CHUNK_SIZE_T size) {
  mchunkptr fwd = q->fd;
  mchunkptr bck = q->bk;
  fwd->bk = bck;
  bck->fd = fwd;
  if (fwd == bck && in_smallbin_range(size)) {
    clear_smallbin(av, smallbin_index(size));
  }
  else if (!in_smallbin_range(size)) {
    tchunkptr t = (tchunkptr)q;
    tchunkptr c = (tchunkptr)fwd;
    if (c == t) {
      if (t->child[0] == t->child[1]) {
        unlink_leaf_node(av, t);
        return;
      }
      else {
        c = find_replacement(t);
      }
    }
    else {
      if (t->parent == 0) {
        return;
      }
    }

    transfer_tree_links(t, c);
    check_tree(c);
  }
}

static Void_t* use_treechunk(mstate av, 
                             CHUNK_SIZE_T nb,
                             tchunkptr bestchunk,
                             CHUNK_SIZE_T bestsize, 
                             tchunkptr leaf) {

  CHUNK_SIZE_T rsize;

  if (bestchunk->bk != bestchunk)
    unlink_chained_node(bestchunk);
  else {
    unlink_leaf_node(av, leaf);
    if (leaf != bestchunk) 
      transfer_tree_links(bestchunk, leaf);
  }
  
  rsize = bestsize - nb;
  if (rsize >= MINSIZE) {
    mchunkptr rem = chunk_at_offset(bestchunk, nb);
    set_head(bestchunk, nb | PREV_INUSE);
    set_head(rem, rsize | PREV_INUSE);
    set_foot(rem, rsize);
    insert_chunk(av, rem, rsize);
  }
  else {
    set_inuse_bit_at_offset(bestchunk, bestsize);
  }
  check_malloced_chunk((mchunkptr)(bestchunk), nb);
  return chunk2mem(bestchunk);
}


/*
  ------------------------------ malloc ------------------------------
*/

Void_t* mALLOc(size_t bytes) {
  mstate av = get_malloc_state();
  CHUNK_SIZE_T nb;

  checked_request2size(bytes, nb);

  if (nb <= (CHUNK_SIZE_T)(av->max_fast)) { 
    mfastbinptr*  fb = &(av->fastbins[(fastbin_index(nb))]);
    mchunkptr fp = *fb;
    if (fp != 0) {
      *fb = fp->fd;
      check_remalloced_chunk(fp, nb);
      return chunk2mem(fp);
    }
  }
    

  for (;;) {
    if (in_smallbin_range(nb)) {
      bin_index_t sidx = smallbin_index(nb);
      bitmap_t sbit = idx2bit(sidx);
      
      if (sbit <= av->smallbits) {
        mchunkptr p;
        if ((sbit & av->smallbits) != 0) {
          p = take_from_smallbin(av, bin_at(av,sidx), sbit);
          set_inuse_bit_at_offset(p, nb);
        }
        else {
          bitmap_t nbit = least_bit(left_bits(sbit) & av->smallbits);
          bin_index_t nidx = bit2idx(nbit);
          CHUNK_SIZE_T psize = size_for_smallindex(nidx);
          CHUNK_SIZE_T qsize = psize - nb;
          p = take_from_smallbin(av, bin_at(av, nidx), nbit);
          if (qsize < MINSIZE) {
            set_inuse_bit_at_offset(p, psize);
          }
          else {
            mchunkptr q = chunk_at_offset(p, nb);
            set_head(p, nb | PREV_INUSE);
            set_head(q, qsize | PREV_INUSE);
            set_foot(q, qsize);
            insert_small_chunk(av, q, qsize);
          }
        }
        check_malloced_chunk(p, nb);
        return chunk2mem(p);
      }
      
      if (av->treebits != 0) {
        bitmap_t vbit = least_bit(av->treebits);
        bin_index_t vidx = bit2idx(vbit);
        tbinptr* vbin = tbin_at(av, vidx);
        tchunkptr bestchunk = *vbin;
        tchunkptr c = leftmost_child(bestchunk);
        CHUNK_SIZE_T bestsize = chunksize(bestchunk);
        tchunkptr leaf;
        CHUNK_SIZE_T rsize;

        /*  Fast path if remainder will replace bestchunk */
        if (c == 0) {
          rsize = bestsize - nb;
          leaf = bestchunk;

          if (rsize >= minsize_for_treeindex(vidx) &&
              bestchunk->bk == bestchunk) {
            tchunkptr r = (tchunkptr)(chunk_at_offset(bestchunk, nb));

            set_head(bestchunk, nb | PREV_INUSE);
            set_head(r, rsize | PREV_INUSE);
            set_foot(r, rsize);
            *vbin = r;
            r->fd = r;
            r->bk = r;
            r->child[0] = 0;
            r->child[1] = 0;
            r->parent = (tchunkptr)vbin;
            r->index = vidx;
            check_malloced_chunk((mchunkptr)bestchunk, nb);
            return chunk2mem(bestchunk);
          }
        }
        else {
          do {
            CHUNK_SIZE_T csize = chunksize(c);
            if (csize < bestsize) {
              bestchunk = c;
              bestsize = csize;
            }
            leaf = c;
            c = leftmost_child(c);
          } while (c != 0);
        }
        return use_treechunk(av, nb, bestchunk, bestsize, leaf);
      }
    }
    else {
      bin_index_t tidx = treebin_index(nb);
      bitmap_t tbit = idx2bit(tidx);
      
      if (tbit <= av->treebits) {
        tchunkptr bestchunk = 0;
        CHUNK_SIZE_T bestsize = MAX_CHUNK_SIZE;
        tchunkptr leaf;
        bitmap_t vbit;
        
        for (;;) {
          if ((tbit & av->treebits) != 0) {
            tchunkptr t = *tbin_at(av, tidx);
            bin_index_t shift = bitshift_for_index(tidx);
            for (;;) {
              int dir;
              CHUNK_SIZE_T tsize = chunksize(t);
              leaf = t;
              if (tsize >= nb && tsize < bestsize) {
                bestchunk = t;
                bestsize = tsize;
                if (tsize == nb && t->bk != t)
                  break;
              }
              
              dir = (shift == 0)? 0 : (nb >> shift--) & 1;
              t = leaf->child[dir];
              if (t == 0) {
                shift = 0; /* if forced right, go leftmost from now on */
                t = leaf->child[1-dir];
                if (t == 0)
                  break;
              }
            } 
            if (bestchunk != 0)
              return use_treechunk(av, nb, bestchunk, bestsize, leaf);
          }
          if (have_fastchunks(av))
            malloc_consolidate(av);
          else
            break;
        }
        
        vbit = least_bit(left_bits(tbit) & av->treebits);
        if (vbit != 0) {
          bin_index_t vidx = bit2idx(vbit);
          tbinptr* vbin = tbin_at(av, vidx);
          tchunkptr c = *vbin;
          do {
            CHUNK_SIZE_T csize = chunksize(c);
            leaf = c;
            if (csize < bestsize) {
              bestchunk = c;
              bestsize = csize;
            }
            c = leftmost_child(c);
          } while (c != 0);
          return use_treechunk(av, nb, bestchunk, bestsize, leaf);
        }
      }
    }
    
    /*
      If large enough, split off the chunk bordering the end of memory
      (held in av->top). This is called in accord with the best-fit
      search rule.  In effect, av->top is treated as larger (and thus
      less well fitting) than any other available chunk since it can
      be extended to be as large as necessary (up to system
      limitations).
      
      We require that av->top always exists (i.e., has size >=
      MINSIZE) after initialization, so if it would otherwise be
      exhuasted by current request, it is replenished. (The main
      reason for ensuring it exists is that we may need MINSIZE space
      to put in fenceposts in sysmalloc.)
    */
    
    if (av->top != 0) {
      mchunkptr topchunk = av->top;
      CHUNK_SIZE_T topsize = chunksize(topchunk);
      
      if (topsize >= nb + MINSIZE) {
        CHUNK_SIZE_T remainder_size = topsize - nb;
        mchunkptr remainder = chunk_at_offset(topchunk, nb);
        
        av->top = remainder;
        set_head(topchunk, nb | PREV_INUSE);
        set_head(remainder, remainder_size | PREV_INUSE);
        
        check_malloced_chunk(topchunk, nb);
        return chunk2mem(topchunk);
      }
      else if (have_fastchunks(av)) {
        malloc_consolidate(av);
      }
      else
        break;
    }  
    else
      break;
  }
  return sysmalloc(av, nb);
}

/*
  ------------------------------ free ------------------------------
*/


void fREe(Void_t* mem) {
  mstate av = get_malloc_state();

  mchunkptr p = mem2chunk(mem);

  if (mem != 0) {
    INTERNAL_SIZE_T rawsize = p->size;
    CHUNK_SIZE_T size = chunksize(p);
    check_inuse_chunk(p);

    /*
      If eligible, place chunk on a fastbin so it can be found
      and used quickly in malloc.
    */

    if ((CHUNK_SIZE_T)(size) <= (CHUNK_SIZE_T)(av->max_fast)

src/judy-1.0.5/test/malloc-pre2.8a.c  view on Meta::CPAN

      * Default trim and mmap thresholds now 256K.

    V2.7.0 Sun Mar 11 14:14:06 2001  Doug Lea  (dl at gee)
      * Introduce independent_comalloc and independent_calloc.
        Thanks to Michael Pachos for motivation and help.
      * Make optional .h file available
      * Allow > 2GB requests on 32bit systems.
      * new WIN32 sbrk, mmap, munmap, lock code from <Walter@GeNeSys-e.de>.
        Thanks also to Andreas Mueller <a.mueller at paradatec.de>,
        and Anonymous.
      * Allow override of MALLOC_ALIGNMENT (Thanks to Ruud Waij for 
        helping test this.)
      * memalign: check alignment arg
      * realloc: don't try to shift chunks backwards, since this
        leads to  more fragmentation in some programs and doesn't
        seem to help in any others.
      * Collect all cases in malloc requiring system memory into sysmalloc
      * Use mmap as backup to sbrk
      * Place all internal state in malloc_state
      * Introduce fastbins (although similar to 2.5.1)
      * Many minor tunings and cosmetic improvements
      * Introduce USE_PUBLIC_MALLOC_WRAPPERS, USE_MALLOC_LOCK 
      * Introduce MALLOC_FAILURE_ACTION, MORECORE_CONTIGUOUS
        Thanks to Tony E. Bennett <tbennett@nvidia.com> and others.
      * Include errno.h to support default failure action.

    V2.6.6 Sun Dec  5 07:42:19 1999  Doug Lea  (dl at gee)
      * return null for negative arguments
      * Added Several WIN32 cleanups from Martin C. Fong <mcfong at yahoo.com>
         * Add 'LACKS_SYS_PARAM_H' for those systems without 'sys/param.h'
          (e.g. WIN32 platforms)
         * Cleanup header file inclusion for WIN32 platforms
         * Cleanup code to avoid Microsoft Visual C++ compiler complaints
         * Add 'USE_DL_PREFIX' to quickly allow co-existence with existing
           memory allocation routines
         * Set 'malloc_getpagesize' for WIN32 platforms (needs more work)
         * Use 'assert' rather than 'ASSERT' in WIN32 code to conform to
           usage of 'assert' in non-WIN32 code
         * Improve WIN32 'sbrk()' emulation's 'findRegion()' routine to
           avoid infinite loop
      * Always call 'fREe()' rather than 'free()'

    V2.6.5 Wed Jun 17 15:57:31 1998  Doug Lea  (dl at gee)
      * Fixed ordering problem with boundary-stamping

    V2.6.3 Sun May 19 08:17:58 1996  Doug Lea  (dl at gee)
      * Added pvalloc, as recommended by H.J. Liu
      * Added 64bit pointer support mainly from Wolfram Gloger
      * Added anonymously donated WIN32 sbrk emulation
      * Malloc, calloc, getpagesize: add optimizations from Raymond Nijssen
      * malloc_extend_top: fix mask error that caused wastage after
        foreign sbrks
      * Add linux mremap support code from HJ Liu

    V2.6.2 Tue Dec  5 06:52:55 1995  Doug Lea  (dl at gee)
      * Integrated most documentation with the code.
      * Add support for mmap, with help from
        Wolfram Gloger (Gloger@lrz.uni-muenchen.de).
      * Use last_remainder in more cases.
      * Pack bins using idea from  colin@nyx10.cs.du.edu
      * Use ordered bins instead of best-fit threshhold
      * Eliminate block-local decls to simplify tracing and debugging.
      * Support another case of realloc via move into top
      * Fix error occuring when initial sbrk_base not word-aligned.
      * Rely on page size for units instead of SBRK_UNIT to
        avoid surprises about sbrk alignment conventions.
      * Add mallinfo, mallopt. Thanks to Raymond Nijssen
        (raymond@es.ele.tue.nl) for the suggestion.
      * Add `pad' argument to malloc_trim and top_pad mallopt parameter.
      * More precautions for cases where other routines call sbrk,
        courtesy of Wolfram Gloger (Gloger@lrz.uni-muenchen.de).
      * Added macros etc., allowing use in linux libc from
        H.J. Lu (hjl@gnu.ai.mit.edu)
      * Inverted this history list

    V2.6.1 Sat Dec  2 14:10:57 1995  Doug Lea  (dl at gee)
      * Re-tuned and fixed to behave more nicely with V2.6.0 changes.
      * Removed all preallocation code since under current scheme
        the work required to undo bad preallocations exceeds
        the work saved in good cases for most test programs.
      * No longer use return list or unconsolidated bins since
        no scheme using them consistently outperforms those that don't
        given above changes.
      * Use best fit for very large chunks to prevent some worst-cases.
      * Added some support for debugging

    V2.6.0 Sat Nov  4 07:05:23 1995  Doug Lea  (dl at gee)
      * Removed footers when chunks are in use. Thanks to
        Paul Wilson (wilson@cs.texas.edu) for the suggestion.

    V2.5.4 Wed Nov  1 07:54:51 1995  Doug Lea  (dl at gee)
      * Added malloc_trim, with help from Wolfram Gloger
        (wmglo@Dent.MED.Uni-Muenchen.DE).

    V2.5.3 Tue Apr 26 10:16:01 1994  Doug Lea  (dl at g)

    V2.5.2 Tue Apr  5 16:20:40 1994  Doug Lea  (dl at g)
      * realloc: try to expand in both directions
      * malloc: swap order of clean-bin strategy;
      * realloc: only conditionally expand backwards
      * Try not to scavenge used bins
      * Use bin counts as a guide to preallocation
      * Occasionally bin return list chunks in first scan
      * Add a few optimizations from colin@nyx10.cs.du.edu

    V2.5.1 Sat Aug 14 15:40:43 1993  Doug Lea  (dl at g)
      * faster bin computation & slightly different binning
      * merged all consolidations to one part of malloc proper
         (eliminating old malloc_find_space & malloc_clean_bin)
      * Scan 2 returns chunks (not just 1)
      * Propagate failure in realloc if malloc returns 0
      * Add stuff to allow compilation on non-ANSI compilers
          from kpv@research.att.com

    V2.5 Sat Aug  7 07:41:59 1993  Doug Lea  (dl at g.oswego.edu)
      * removed potential for odd address access in prev_chunk
      * removed dependency on getpagesize.h
      * misc cosmetics and a bit more internal documentation
      * anticosmetics: mangled names in macros to evade debugger strangeness
      * tested on sparc, hp-700, dec-mips, rs6000
          with gcc & native cc (hp, dec only) allowing
          Detlefs & Zorn comparison study (in SIGPLAN Notices.)

    Trial version Fri Aug 28 13:14:29 1992  Doug Lea  (dl at g.oswego.edu)
      * Based loosely on libg++-1.2X malloc. (It retains some of the overall
         structure of old version,  but most details differ.)

*/




( run in 2.101 seconds using v1.01-cache-2.11-cpan-df04353d9ac )