-/* Storage allocation and gc for GNU Emacs Lisp interpreter.
-
-Copyright (C) 1985-1986, 1988, 1993-1995, 1997-2014 Free Software
-Foundation, Inc.
-
-This file is part of GNU Emacs.
-
-GNU Emacs is free software: you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation, either version 3 of the License, or
-(at your option) any later version.
-
-GNU Emacs is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
-
-#include <config.h>
-
-#include <stdio.h>
-#include <limits.h> /* For CHAR_BIT. */
-
-#ifdef ENABLE_CHECKING
-#include <signal.h> /* For SIGABRT. */
-#endif
-
-#ifdef HAVE_PTHREAD
-#include <pthread.h>
-#endif
-
-#include "lisp.h"
-#include "process.h"
-#include "intervals.h"
-#include "puresize.h"
-#include "character.h"
-#include "buffer.h"
-#include "window.h"
-#include "keyboard.h"
-#include "frame.h"
-#include "blockinput.h"
-#include "termhooks.h" /* For struct terminal. */
-#ifdef HAVE_WINDOW_SYSTEM
-#include TERM_HEADER
-#endif /* HAVE_WINDOW_SYSTEM */
-
-#include <verify.h>
-#include <execinfo.h> /* For backtrace. */
-
-#if (defined ENABLE_CHECKING \
- && defined HAVE_VALGRIND_VALGRIND_H \
- && !defined USE_VALGRIND)
-# define USE_VALGRIND 1
-#endif
-
-#if USE_VALGRIND
-#include <valgrind/valgrind.h>
-#include <valgrind/memcheck.h>
-static bool valgrind_p;
-#endif
-
-/* GC_CHECK_MARKED_OBJECTS means do sanity checks on allocated objects.
- Doable only if GC_MARK_STACK. */
-#if ! GC_MARK_STACK
-# undef GC_CHECK_MARKED_OBJECTS
-#endif
-
-/* GC_MALLOC_CHECK defined means perform validity checks of malloc'd
- memory. Can do this only if using gmalloc.c and if not checking
- marked objects. */
-
-#if (defined SYSTEM_MALLOC || defined DOUG_LEA_MALLOC \
- || defined GC_CHECK_MARKED_OBJECTS)
-#undef GC_MALLOC_CHECK
-#endif
-
-#include <unistd.h>
-#include <fcntl.h>
-
-#ifdef USE_GTK
-# include "gtkutil.h"
-#endif
-#ifdef WINDOWSNT
-#include "w32.h"
-#include "w32heap.h" /* for sbrk */
-#endif
-
-#ifdef DOUG_LEA_MALLOC
-
-#include <malloc.h>
-
-/* Specify maximum number of areas to mmap. It would be nice to use a
- value that explicitly means "no limit". */
-
-#define MMAP_MAX_AREAS 100000000
-
-#endif /* not DOUG_LEA_MALLOC */
-
-/* Mark, unmark, query mark bit of a Lisp string. S must be a pointer
- to a struct Lisp_String. */
-
-#define MARK_STRING(S) ((S)->size |= ARRAY_MARK_FLAG)
-#define UNMARK_STRING(S) ((S)->size &= ~ARRAY_MARK_FLAG)
-#define STRING_MARKED_P(S) (((S)->size & ARRAY_MARK_FLAG) != 0)
-
-#define VECTOR_MARK(V) ((V)->header.size |= ARRAY_MARK_FLAG)
-#define VECTOR_UNMARK(V) ((V)->header.size &= ~ARRAY_MARK_FLAG)
-#define VECTOR_MARKED_P(V) (((V)->header.size & ARRAY_MARK_FLAG) != 0)
-
-/* Default value of gc_cons_threshold (see below). */
-
-#define GC_DEFAULT_THRESHOLD (100000 * word_size)
-
-/* Global variables. */
-struct emacs_globals globals;
-
-/* Number of bytes of consing done since the last gc. */
-
-EMACS_INT consing_since_gc;
-
-/* Similar minimum, computed from Vgc_cons_percentage. */
-
-EMACS_INT gc_relative_threshold;
-
-/* Minimum number of bytes of consing since GC before next GC,
- when memory is full. */
-
-EMACS_INT memory_full_cons_threshold;
-
-/* True during GC. */
-
-bool gc_in_progress;
-
-/* True means abort if try to GC.
- This is for code which is written on the assumption that
- no GC will happen, so as to verify that assumption. */
-
-bool abort_on_gc;
-
-/* Number of live and free conses etc. */
-
-static EMACS_INT total_conses, total_markers, total_symbols, total_buffers;
-static EMACS_INT total_free_conses, total_free_markers, total_free_symbols;
-static EMACS_INT total_free_floats, total_floats;
-
-/* Points to memory space allocated as "spare", to be freed if we run
- out of memory. We keep one large block, four cons-blocks, and
- two string blocks. */
-
-static char *spare_memory[7];
-
-/* Amount of spare memory to keep in large reserve block, or to see
- whether this much is available when malloc fails on a larger request. */
-
-#define SPARE_MEMORY (1 << 14)
-
-/* Initialize it to a nonzero value to force it into data space
- (rather than bss space). That way unexec will remap it into text
- space (pure), on some systems. We have not implemented the
- remapping on more recent systems because this is less important
- nowadays than in the days of small memories and timesharing. */
-
-EMACS_INT pure[(PURESIZE + sizeof (EMACS_INT) - 1) / sizeof (EMACS_INT)] = {1,};
-#define PUREBEG (char *) pure
-
-/* Pointer to the pure area, and its size. */
-
-static char *purebeg;
-static ptrdiff_t pure_size;
-
-/* Number of bytes of pure storage used before pure storage overflowed.
- If this is non-zero, this implies that an overflow occurred. */
-
-static ptrdiff_t pure_bytes_used_before_overflow;
-
-/* True if P points into pure space. */
-
-#define PURE_POINTER_P(P) \
- ((uintptr_t) (P) - (uintptr_t) purebeg <= pure_size)
-
-/* Index in pure at which next pure Lisp object will be allocated.. */
-
-static ptrdiff_t pure_bytes_used_lisp;
-
-/* Number of bytes allocated for non-Lisp objects in pure storage. */
-
-static ptrdiff_t pure_bytes_used_non_lisp;
-
-/* If nonzero, this is a warning delivered by malloc and not yet
- displayed. */
-
-const char *pending_malloc_warning;
-
-#if 0 /* Normally, pointer sanity only on request... */
-#ifdef ENABLE_CHECKING
-#define SUSPICIOUS_OBJECT_CHECKING 1
-#endif
-#endif
-
-/* ... but unconditionally use SUSPICIOUS_OBJECT_CHECKING while the GC
- bug is unresolved. */
-#define SUSPICIOUS_OBJECT_CHECKING 1
-
-#ifdef SUSPICIOUS_OBJECT_CHECKING
-struct suspicious_free_record
-{
- void *suspicious_object;
- void *backtrace[128];
-};
-static void *suspicious_objects[32];
-static int suspicious_object_index;
-struct suspicious_free_record suspicious_free_history[64] EXTERNALLY_VISIBLE;
-static int suspicious_free_history_index;
-/* Find the first currently-monitored suspicious pointer in range
- [begin,end) or NULL if no such pointer exists. */
-static void *find_suspicious_object_in_range (void *begin, void *end);
-static void detect_suspicious_free (void *ptr);
-#else
-# define find_suspicious_object_in_range(begin, end) NULL
-# define detect_suspicious_free(ptr) (void)
-#endif
-
-/* Maximum amount of C stack to save when a GC happens. */
-
-#ifndef MAX_SAVE_STACK
-#define MAX_SAVE_STACK 16000
-#endif
-
-/* Buffer in which we save a copy of the C stack at each GC. */
-
-#if MAX_SAVE_STACK > 0
-static char *stack_copy;
-static ptrdiff_t stack_copy_size;
-
-/* Copy to DEST a block of memory from SRC of size SIZE bytes,
- avoiding any address sanitization. */
-
-static void * ATTRIBUTE_NO_SANITIZE_ADDRESS
-no_sanitize_memcpy (void *dest, void const *src, size_t size)
-{
- if (! ADDRESS_SANITIZER)
- return memcpy (dest, src, size);
- else
- {
- size_t i;
- char *d = dest;
- char const *s = src;
- for (i = 0; i < size; i++)
- d[i] = s[i];
- return dest;
- }
-}
-
-#endif /* MAX_SAVE_STACK > 0 */
-
-static Lisp_Object Qconses;
-static Lisp_Object Qsymbols;
-static Lisp_Object Qmiscs;
-static Lisp_Object Qstrings;
-static Lisp_Object Qvectors;
-static Lisp_Object Qfloats;
-static Lisp_Object Qintervals;
-static Lisp_Object Qbuffers;
-static Lisp_Object Qstring_bytes, Qvector_slots, Qheap;
-static Lisp_Object Qgc_cons_threshold;
-Lisp_Object Qautomatic_gc;
-Lisp_Object Qchar_table_extra_slots;
-
-/* Hook run after GC has finished. */
-
-static Lisp_Object Qpost_gc_hook;
-
-static void mark_terminals (void);
-static void gc_sweep (void);
-static Lisp_Object make_pure_vector (ptrdiff_t);
-static void mark_buffer (struct buffer *);
-
-#if !defined REL_ALLOC || defined SYSTEM_MALLOC
-static void refill_memory_reserve (void);
-#endif
-static void compact_small_strings (void);
-static void free_large_strings (void);
-extern Lisp_Object which_symbols (Lisp_Object, EMACS_INT) EXTERNALLY_VISIBLE;
-
-/* When scanning the C stack for live Lisp objects, Emacs keeps track of
- what memory allocated via lisp_malloc and lisp_align_malloc is intended
- for what purpose. This enumeration specifies the type of memory. */
-
-enum mem_type
-{
- MEM_TYPE_NON_LISP,
- MEM_TYPE_BUFFER,
- MEM_TYPE_CONS,
- MEM_TYPE_STRING,
- MEM_TYPE_MISC,
- MEM_TYPE_SYMBOL,
- MEM_TYPE_FLOAT,
- /* Since all non-bool pseudovectors are small enough to be
- allocated from vector blocks, this memory type denotes
- large regular vectors and large bool pseudovectors. */
- MEM_TYPE_VECTORLIKE,
- /* Special type to denote vector blocks. */
- MEM_TYPE_VECTOR_BLOCK,
- /* Special type to denote reserved memory. */
- MEM_TYPE_SPARE
-};
-
-#if GC_MARK_STACK || defined GC_MALLOC_CHECK
-
-/* A unique object in pure space used to make some Lisp objects
- on free lists recognizable in O(1). */
-
-static Lisp_Object Vdead;
-#define DEADP(x) EQ (x, Vdead)
-
-#ifdef GC_MALLOC_CHECK
-
-enum mem_type allocated_mem_type;
-
-#endif /* GC_MALLOC_CHECK */
-
-/* A node in the red-black tree describing allocated memory containing
- Lisp data. Each such block is recorded with its start and end
- address when it is allocated, and removed from the tree when it
- is freed.
-
- A red-black tree is a balanced binary tree with the following
- properties:
-
- 1. Every node is either red or black.
- 2. Every leaf is black.
- 3. If a node is red, then both of its children are black.
- 4. Every simple path from a node to a descendant leaf contains
- the same number of black nodes.
- 5. The root is always black.
-
- When nodes are inserted into the tree, or deleted from the tree,
- the tree is "fixed" so that these properties are always true.
-
- A red-black tree with N internal nodes has height at most 2
- log(N+1). Searches, insertions and deletions are done in O(log N).
- Please see a text book about data structures for a detailed
- description of red-black trees. Any book worth its salt should
- describe them. */
-
-struct mem_node
-{
- /* Children of this node. These pointers are never NULL. When there
- is no child, the value is MEM_NIL, which points to a dummy node. */
- struct mem_node *left, *right;
-
- /* The parent of this node. In the root node, this is NULL. */
- struct mem_node *parent;
-
- /* Start and end of allocated region. */
- void *start, *end;
-
- /* Node color. */
- enum {MEM_BLACK, MEM_RED} color;
-
- /* Memory type. */
- enum mem_type type;
-};
-
-/* Base address of stack. Set in main. */
-
-Lisp_Object *stack_base;
-
-/* Root of the tree describing allocated Lisp memory. */
-
-static struct mem_node *mem_root;
-
-/* Lowest and highest known address in the heap. */
-
-static void *min_heap_address, *max_heap_address;
-
-/* Sentinel node of the tree. */
-
-static struct mem_node mem_z;
-#define MEM_NIL &mem_z
-
-static struct mem_node *mem_insert (void *, void *, enum mem_type);
-static void mem_insert_fixup (struct mem_node *);
-static void mem_rotate_left (struct mem_node *);
-static void mem_rotate_right (struct mem_node *);
-static void mem_delete (struct mem_node *);
-static void mem_delete_fixup (struct mem_node *);
-static struct mem_node *mem_find (void *);
-
-#endif /* GC_MARK_STACK || GC_MALLOC_CHECK */
-
-#ifndef DEADP
-# define DEADP(x) 0
-#endif
-
-/* Recording what needs to be marked for gc. */
-
-struct gcpro *gcprolist;
-
-/* Addresses of staticpro'd variables. Initialize it to a nonzero
- value; otherwise some compilers put it into BSS. */
-
-enum { NSTATICS = 2048 };
-static Lisp_Object *staticvec[NSTATICS] = {&Vpurify_flag};
-
-/* Index of next unused slot in staticvec. */
-
-static int staticidx;
-
-static void *pure_alloc (size_t, int);
-
-/* Return X rounded to the next multiple of Y. Arguments should not
- have side effects, as they are evaluated more than once. Assume X
- + Y - 1 does not overflow. Tune for Y being a power of 2. */
-
-#define ROUNDUP(x, y) ((y) & ((y) - 1) \
- ? ((x) + (y) - 1) - ((x) + (y) - 1) % (y) \
- : ((x) + (y) - 1) & ~ ((y) - 1))
-
-/* Return PTR rounded up to the next multiple of ALIGNMENT. */
-
-static void *
-ALIGN (void *ptr, int alignment)
-{
- return (void *) ROUNDUP ((uintptr_t) ptr, alignment);
-}
-
-static void
-XFLOAT_INIT (Lisp_Object f, double n)
-{
- XFLOAT (f)->u.data = n;
-}
-
-static bool
-pointers_fit_in_lispobj_p (void)
-{
- return (UINTPTR_MAX <= VAL_MAX) || USE_LSB_TAG;
-}
-
-static bool
-mmap_lisp_allowed_p (void)
-{
- /* If we can't store all memory addresses in our lisp objects, it's
- risky to let the heap use mmap and give us addresses from all
- over our address space. We also can't use mmap for lisp objects
- if we might dump: unexec doesn't preserve the contents of mmaped
- regions. */
- return pointers_fit_in_lispobj_p () && !might_dump;
-}
-
-\f
-/************************************************************************
- Malloc
- ************************************************************************/
-
-/* Function malloc calls this if it finds we are near exhausting storage. */
-
-void
-malloc_warning (const char *str)
-{
- pending_malloc_warning = str;
-}
-
-
-/* Display an already-pending malloc warning. */
-
-void
-display_malloc_warning (void)
-{
- call3 (intern ("display-warning"),
- intern ("alloc"),
- build_string (pending_malloc_warning),
- intern ("emergency"));
- pending_malloc_warning = 0;
-}
-\f
-/* Called if we can't allocate relocatable space for a buffer. */
-
-void
-buffer_memory_full (ptrdiff_t nbytes)
-{
- /* If buffers use the relocating allocator, no need to free
- spare_memory, because we may have plenty of malloc space left
- that we could get, and if we don't, the malloc that fails will
- itself cause spare_memory to be freed. If buffers don't use the
- relocating allocator, treat this like any other failing
- malloc. */
-
-#ifndef REL_ALLOC
- memory_full (nbytes);
-#else
- /* This used to call error, but if we've run out of memory, we could
- get infinite recursion trying to build the string. */
- xsignal (Qnil, Vmemory_signal_data);
-#endif
-}
-
-/* A common multiple of the positive integers A and B. Ideally this
- would be the least common multiple, but there's no way to do that
- as a constant expression in C, so do the best that we can easily do. */
-#define COMMON_MULTIPLE(a, b) \
- ((a) % (b) == 0 ? (a) : (b) % (a) == 0 ? (b) : (a) * (b))
-
-#ifndef XMALLOC_OVERRUN_CHECK
-#define XMALLOC_OVERRUN_CHECK_OVERHEAD 0
-#else
-
-/* Check for overrun in malloc'ed buffers by wrapping a header and trailer
- around each block.
-
- The header consists of XMALLOC_OVERRUN_CHECK_SIZE fixed bytes
- followed by XMALLOC_OVERRUN_SIZE_SIZE bytes containing the original
- block size in little-endian order. The trailer consists of
- XMALLOC_OVERRUN_CHECK_SIZE fixed bytes.
-
- The header is used to detect whether this block has been allocated
- through these functions, as some low-level libc functions may
- bypass the malloc hooks. */
-
-#define XMALLOC_OVERRUN_CHECK_SIZE 16
-#define XMALLOC_OVERRUN_CHECK_OVERHEAD \
- (2 * XMALLOC_OVERRUN_CHECK_SIZE + XMALLOC_OVERRUN_SIZE_SIZE)
-
-/* Define XMALLOC_OVERRUN_SIZE_SIZE so that (1) it's large enough to
- hold a size_t value and (2) the header size is a multiple of the
- alignment that Emacs needs for C types and for USE_LSB_TAG. */
-#define XMALLOC_BASE_ALIGNMENT \
- alignof (union { long double d; intmax_t i; void *p; })
-
-#if USE_LSB_TAG
-# define XMALLOC_HEADER_ALIGNMENT \
- COMMON_MULTIPLE (GCALIGNMENT, XMALLOC_BASE_ALIGNMENT)
-#else
-# define XMALLOC_HEADER_ALIGNMENT XMALLOC_BASE_ALIGNMENT
-#endif
-#define XMALLOC_OVERRUN_SIZE_SIZE \
- (((XMALLOC_OVERRUN_CHECK_SIZE + sizeof (size_t) \
- + XMALLOC_HEADER_ALIGNMENT - 1) \
- / XMALLOC_HEADER_ALIGNMENT * XMALLOC_HEADER_ALIGNMENT) \
- - XMALLOC_OVERRUN_CHECK_SIZE)
-
-static char const xmalloc_overrun_check_header[XMALLOC_OVERRUN_CHECK_SIZE] =
- { '\x9a', '\x9b', '\xae', '\xaf',
- '\xbf', '\xbe', '\xce', '\xcf',
- '\xea', '\xeb', '\xec', '\xed',
- '\xdf', '\xde', '\x9c', '\x9d' };
-
-static char const xmalloc_overrun_check_trailer[XMALLOC_OVERRUN_CHECK_SIZE] =
- { '\xaa', '\xab', '\xac', '\xad',
- '\xba', '\xbb', '\xbc', '\xbd',
- '\xca', '\xcb', '\xcc', '\xcd',
- '\xda', '\xdb', '\xdc', '\xdd' };
-
-/* Insert and extract the block size in the header. */
-
-static void
-xmalloc_put_size (unsigned char *ptr, size_t size)
-{
- int i;
- for (i = 0; i < XMALLOC_OVERRUN_SIZE_SIZE; i++)
- {
- *--ptr = size & ((1 << CHAR_BIT) - 1);
- size >>= CHAR_BIT;
- }
-}
-
-static size_t
-xmalloc_get_size (unsigned char *ptr)
-{
- size_t size = 0;
- int i;
- ptr -= XMALLOC_OVERRUN_SIZE_SIZE;
- for (i = 0; i < XMALLOC_OVERRUN_SIZE_SIZE; i++)
- {
- size <<= CHAR_BIT;
- size += *ptr++;
- }
- return size;
-}
-
-
-/* Like malloc, but wraps allocated block with header and trailer. */
-
-static void *
-overrun_check_malloc (size_t size)
-{
- register unsigned char *val;
- if (SIZE_MAX - XMALLOC_OVERRUN_CHECK_OVERHEAD < size)
- emacs_abort ();
-
- val = malloc (size + XMALLOC_OVERRUN_CHECK_OVERHEAD);
- if (val)
- {
- memcpy (val, xmalloc_overrun_check_header, XMALLOC_OVERRUN_CHECK_SIZE);
- val += XMALLOC_OVERRUN_CHECK_SIZE + XMALLOC_OVERRUN_SIZE_SIZE;
- xmalloc_put_size (val, size);
- memcpy (val + size, xmalloc_overrun_check_trailer,
- XMALLOC_OVERRUN_CHECK_SIZE);
- }
- return val;
-}
-
-
-/* Like realloc, but checks old block for overrun, and wraps new block
- with header and trailer. */
-
-static void *
-overrun_check_realloc (void *block, size_t size)
-{
- register unsigned char *val = (unsigned char *) block;
- if (SIZE_MAX - XMALLOC_OVERRUN_CHECK_OVERHEAD < size)
- emacs_abort ();
-
- if (val
- && memcmp (xmalloc_overrun_check_header,
- val - XMALLOC_OVERRUN_CHECK_SIZE - XMALLOC_OVERRUN_SIZE_SIZE,
- XMALLOC_OVERRUN_CHECK_SIZE) == 0)
- {
- size_t osize = xmalloc_get_size (val);
- if (memcmp (xmalloc_overrun_check_trailer, val + osize,
- XMALLOC_OVERRUN_CHECK_SIZE))
- emacs_abort ();
- memset (val + osize, 0, XMALLOC_OVERRUN_CHECK_SIZE);
- val -= XMALLOC_OVERRUN_CHECK_SIZE + XMALLOC_OVERRUN_SIZE_SIZE;
- memset (val, 0, XMALLOC_OVERRUN_CHECK_SIZE + XMALLOC_OVERRUN_SIZE_SIZE);
- }
-
- val = realloc (val, size + XMALLOC_OVERRUN_CHECK_OVERHEAD);
-
- if (val)
- {
- memcpy (val, xmalloc_overrun_check_header, XMALLOC_OVERRUN_CHECK_SIZE);
- val += XMALLOC_OVERRUN_CHECK_SIZE + XMALLOC_OVERRUN_SIZE_SIZE;
- xmalloc_put_size (val, size);
- memcpy (val + size, xmalloc_overrun_check_trailer,
- XMALLOC_OVERRUN_CHECK_SIZE);
- }
- return val;
-}
-
-/* Like free, but checks block for overrun. */
-
-static void
-overrun_check_free (void *block)
-{
- unsigned char *val = (unsigned char *) block;
-
- if (val
- && memcmp (xmalloc_overrun_check_header,
- val - XMALLOC_OVERRUN_CHECK_SIZE - XMALLOC_OVERRUN_SIZE_SIZE,
- XMALLOC_OVERRUN_CHECK_SIZE) == 0)
- {
- size_t osize = xmalloc_get_size (val);
- if (memcmp (xmalloc_overrun_check_trailer, val + osize,
- XMALLOC_OVERRUN_CHECK_SIZE))
- emacs_abort ();
-#ifdef XMALLOC_CLEAR_FREE_MEMORY
- val -= XMALLOC_OVERRUN_CHECK_SIZE + XMALLOC_OVERRUN_SIZE_SIZE;
- memset (val, 0xff, osize + XMALLOC_OVERRUN_CHECK_OVERHEAD);
-#else
- memset (val + osize, 0, XMALLOC_OVERRUN_CHECK_SIZE);
- val -= XMALLOC_OVERRUN_CHECK_SIZE + XMALLOC_OVERRUN_SIZE_SIZE;
- memset (val, 0, XMALLOC_OVERRUN_CHECK_SIZE + XMALLOC_OVERRUN_SIZE_SIZE);
-#endif
- }
-
- free (val);
-}
-
-#undef malloc
-#undef realloc
-#undef free
-#define malloc overrun_check_malloc
-#define realloc overrun_check_realloc
-#define free overrun_check_free
-#endif
-
-/* If compiled with XMALLOC_BLOCK_INPUT_CHECK, define a symbol
- BLOCK_INPUT_IN_MEMORY_ALLOCATORS that is visible to the debugger.
- If that variable is set, block input while in one of Emacs's memory
- allocation functions. There should be no need for this debugging
- option, since signal handlers do not allocate memory, but Emacs
- formerly allocated memory in signal handlers and this compile-time
- option remains as a way to help debug the issue should it rear its
- ugly head again. */
-#ifdef XMALLOC_BLOCK_INPUT_CHECK
-bool block_input_in_memory_allocators EXTERNALLY_VISIBLE;
-static void
-malloc_block_input (void)
-{
- if (block_input_in_memory_allocators)
- block_input ();
-}
-static void
-malloc_unblock_input (void)
-{
- if (block_input_in_memory_allocators)
- unblock_input ();
-}
-# define MALLOC_BLOCK_INPUT malloc_block_input ()
-# define MALLOC_UNBLOCK_INPUT malloc_unblock_input ()
-#else
-# define MALLOC_BLOCK_INPUT ((void) 0)
-# define MALLOC_UNBLOCK_INPUT ((void) 0)
-#endif
-
-#define MALLOC_PROBE(size) \
- do { \
- if (profiler_memory_running) \
- malloc_probe (size); \
- } while (0)
-
-
-/* Like malloc but check for no memory and block interrupt input.. */
-
-void *
-xmalloc (size_t size)
-{
- void *val;
-
- MALLOC_BLOCK_INPUT;
- val = malloc (size);
- MALLOC_UNBLOCK_INPUT;
-
- if (!val && size)
- memory_full (size);
- MALLOC_PROBE (size);
- return val;
-}
-
-/* Like the above, but zeroes out the memory just allocated. */
-
-void *
-xzalloc (size_t size)
-{
- void *val;
-
- MALLOC_BLOCK_INPUT;
- val = malloc (size);
- MALLOC_UNBLOCK_INPUT;
-
- if (!val && size)
- memory_full (size);
- memset (val, 0, size);
- MALLOC_PROBE (size);
- return val;
-}
-
-/* Like realloc but check for no memory and block interrupt input.. */
-
-void *
-xrealloc (void *block, size_t size)
-{
- void *val;
-
- MALLOC_BLOCK_INPUT;
- /* We must call malloc explicitly when BLOCK is 0, since some
- reallocs don't do this. */
- if (! block)
- val = malloc (size);
- else
- val = realloc (block, size);
- MALLOC_UNBLOCK_INPUT;
-
- if (!val && size)
- memory_full (size);
- MALLOC_PROBE (size);
- return val;
-}
-
-
-/* Like free but block interrupt input. */
-
-void
-xfree (void *block)
-{
- if (!block)
- return;
- MALLOC_BLOCK_INPUT;
- free (block);
- MALLOC_UNBLOCK_INPUT;
- /* We don't call refill_memory_reserve here
- because in practice the call in r_alloc_free seems to suffice. */
-}
-
-
-/* Other parts of Emacs pass large int values to allocator functions
- expecting ptrdiff_t. This is portable in practice, but check it to
- be safe. */
-verify (INT_MAX <= PTRDIFF_MAX);
-
-
-/* Allocate an array of NITEMS items, each of size ITEM_SIZE.
- Signal an error on memory exhaustion, and block interrupt input. */
-
-void *
-xnmalloc (ptrdiff_t nitems, ptrdiff_t item_size)
-{
- eassert (0 <= nitems && 0 < item_size);
- if (min (PTRDIFF_MAX, SIZE_MAX) / item_size < nitems)
- memory_full (SIZE_MAX);
- return xmalloc (nitems * item_size);
-}
-
-
-/* Reallocate an array PA to make it of NITEMS items, each of size ITEM_SIZE.
- Signal an error on memory exhaustion, and block interrupt input. */
-
-void *
-xnrealloc (void *pa, ptrdiff_t nitems, ptrdiff_t item_size)
-{
- eassert (0 <= nitems && 0 < item_size);
- if (min (PTRDIFF_MAX, SIZE_MAX) / item_size < nitems)
- memory_full (SIZE_MAX);
- return xrealloc (pa, nitems * item_size);
-}
-
-
-/* Grow PA, which points to an array of *NITEMS items, and return the
- location of the reallocated array, updating *NITEMS to reflect its
- new size. The new array will contain at least NITEMS_INCR_MIN more
- items, but will not contain more than NITEMS_MAX items total.
- ITEM_SIZE is the size of each item, in bytes.
-
- ITEM_SIZE and NITEMS_INCR_MIN must be positive. *NITEMS must be
- nonnegative. If NITEMS_MAX is -1, it is treated as if it were
- infinity.
-
- If PA is null, then allocate a new array instead of reallocating
- the old one.
-
- Block interrupt input as needed. If memory exhaustion occurs, set
- *NITEMS to zero if PA is null, and signal an error (i.e., do not
- return).
-
- Thus, to grow an array A without saving its old contents, do
- { xfree (A); A = NULL; A = xpalloc (NULL, &AITEMS, ...); }.
- The A = NULL avoids a dangling pointer if xpalloc exhausts memory
- and signals an error, and later this code is reexecuted and
- attempts to free A. */
-
-void *
-xpalloc (void *pa, ptrdiff_t *nitems, ptrdiff_t nitems_incr_min,
- ptrdiff_t nitems_max, ptrdiff_t item_size)
-{
- /* The approximate size to use for initial small allocation
- requests. This is the largest "small" request for the GNU C
- library malloc. */
- enum { DEFAULT_MXFAST = 64 * sizeof (size_t) / 4 };
-
- /* If the array is tiny, grow it to about (but no greater than)
- DEFAULT_MXFAST bytes. Otherwise, grow it by about 50%. */
- ptrdiff_t n = *nitems;
- ptrdiff_t tiny_max = DEFAULT_MXFAST / item_size - n;
- ptrdiff_t half_again = n >> 1;
- ptrdiff_t incr_estimate = max (tiny_max, half_again);
-
- /* Adjust the increment according to three constraints: NITEMS_INCR_MIN,
- NITEMS_MAX, and what the C language can represent safely. */
- ptrdiff_t C_language_max = min (PTRDIFF_MAX, SIZE_MAX) / item_size;
- ptrdiff_t n_max = (0 <= nitems_max && nitems_max < C_language_max
- ? nitems_max : C_language_max);
- ptrdiff_t nitems_incr_max = n_max - n;
- ptrdiff_t incr = max (nitems_incr_min, min (incr_estimate, nitems_incr_max));
-
- eassert (0 < item_size && 0 < nitems_incr_min && 0 <= n && -1 <= nitems_max);
- if (! pa)
- *nitems = 0;
- if (nitems_incr_max < incr)
- memory_full (SIZE_MAX);
- n += incr;
- pa = xrealloc (pa, n * item_size);
- *nitems = n;
- return pa;
-}
-
-
-/* Like strdup, but uses xmalloc. */
-
-char *
-xstrdup (const char *s)
-{
- ptrdiff_t size;
- eassert (s);
- size = strlen (s) + 1;
- return memcpy (xmalloc (size), s, size);
-}
-
-/* Like above, but duplicates Lisp string to C string. */
-
-char *
-xlispstrdup (Lisp_Object string)
-{
- ptrdiff_t size = SBYTES (string) + 1;
- return memcpy (xmalloc (size), SSDATA (string), size);
-}
-
-/* Assign to *PTR a copy of STRING, freeing any storage *PTR formerly
- pointed to. If STRING is null, assign it without copying anything.
- Allocate before freeing, to avoid a dangling pointer if allocation
- fails. */
-
-void
-dupstring (char **ptr, char const *string)
-{
- char *old = *ptr;
- *ptr = string ? xstrdup (string) : 0;
- xfree (old);
-}
-
-
-/* Like putenv, but (1) use the equivalent of xmalloc and (2) the
- argument is a const pointer. */
-
-void
-xputenv (char const *string)
-{
- if (putenv ((char *) string) != 0)
- memory_full (0);
-}
-
-/* Return a newly allocated memory block of SIZE bytes, remembering
- to free it when unwinding. */
-void *
-record_xmalloc (size_t size)
-{
- void *p = xmalloc (size);
- record_unwind_protect_ptr (xfree, p);
- return p;
-}
-
-
-/* Like malloc but used for allocating Lisp data. NBYTES is the
- number of bytes to allocate, TYPE describes the intended use of the
- allocated memory block (for strings, for conses, ...). */
-
-#if ! USE_LSB_TAG
-void *lisp_malloc_loser EXTERNALLY_VISIBLE;
-#endif
-
-static void *
-lisp_malloc (size_t nbytes, enum mem_type type)
-{
- register void *val;
-
- MALLOC_BLOCK_INPUT;
-
-#ifdef GC_MALLOC_CHECK
- allocated_mem_type = type;
-#endif
-
- val = malloc (nbytes);
-
-#if ! USE_LSB_TAG
- /* If the memory just allocated cannot be addressed thru a Lisp
- object's pointer, and it needs to be,
- that's equivalent to running out of memory. */
- if (val && type != MEM_TYPE_NON_LISP)
- {
- Lisp_Object tem;
- XSETCONS (tem, (char *) val + nbytes - 1);
- if ((char *) XCONS (tem) != (char *) val + nbytes - 1)
- {
- lisp_malloc_loser = val;
- free (val);
- val = 0;
- }
- }
-#endif
-
-#if GC_MARK_STACK && !defined GC_MALLOC_CHECK
- if (val && type != MEM_TYPE_NON_LISP)
- mem_insert (val, (char *) val + nbytes, type);
-#endif
-
- MALLOC_UNBLOCK_INPUT;
- if (!val && nbytes)
- memory_full (nbytes);
- MALLOC_PROBE (nbytes);
- return val;
-}
-
-/* Free BLOCK. This must be called to free memory allocated with a
- call to lisp_malloc. */
-
-static void
-lisp_free (void *block)
-{
- MALLOC_BLOCK_INPUT;
- free (block);
-#if GC_MARK_STACK && !defined GC_MALLOC_CHECK
- mem_delete (mem_find (block));
-#endif
- MALLOC_UNBLOCK_INPUT;
-}
-
-/***** Allocation of aligned blocks of memory to store Lisp data. *****/
-
-/* The entry point is lisp_align_malloc which returns blocks of at most
- BLOCK_BYTES and guarantees they are aligned on a BLOCK_ALIGN boundary. */
-
-/* Use aligned_alloc if it or a simple substitute is available.
- Address sanitization breaks aligned allocation, as of gcc 4.8.2 and
- clang 3.3 anyway. */
-
-#if ! ADDRESS_SANITIZER
-# if !defined SYSTEM_MALLOC && !defined DOUG_LEA_MALLOC
-# define USE_ALIGNED_ALLOC 1
-/* Defined in gmalloc.c. */
-void *aligned_alloc (size_t, size_t);
-# elif defined HAVE_ALIGNED_ALLOC
-# define USE_ALIGNED_ALLOC 1
-# elif defined HAVE_POSIX_MEMALIGN
-# define USE_ALIGNED_ALLOC 1
-static void *
-aligned_alloc (size_t alignment, size_t size)
-{
- void *p;
- return posix_memalign (&p, alignment, size) == 0 ? p : 0;
-}
-# endif
-#endif
-
-/* BLOCK_ALIGN has to be a power of 2. */
-#define BLOCK_ALIGN (1 << 10)
-
-/* Padding to leave at the end of a malloc'd block. This is to give
- malloc a chance to minimize the amount of memory wasted to alignment.
- It should be tuned to the particular malloc library used.
- On glibc-2.3.2, malloc never tries to align, so a padding of 0 is best.
- aligned_alloc on the other hand would ideally prefer a value of 4
- because otherwise, there's 1020 bytes wasted between each ablocks.
- In Emacs, testing shows that those 1020 can most of the time be
- efficiently used by malloc to place other objects, so a value of 0 can
- still preferable unless you have a lot of aligned blocks and virtually
- nothing else. */
-#define BLOCK_PADDING 0
-#define BLOCK_BYTES \
- (BLOCK_ALIGN - sizeof (struct ablocks *) - BLOCK_PADDING)
-
-/* Internal data structures and constants. */
-
-#define ABLOCKS_SIZE 16
-
-/* An aligned block of memory. */
-struct ablock
-{
- union
- {
- char payload[BLOCK_BYTES];
- struct ablock *next_free;
- } x;
- /* `abase' is the aligned base of the ablocks. */
- /* It is overloaded to hold the virtual `busy' field that counts
- the number of used ablock in the parent ablocks.
- The first ablock has the `busy' field, the others have the `abase'
- field. To tell the difference, we assume that pointers will have
- integer values larger than 2 * ABLOCKS_SIZE. The lowest bit of `busy'
- is used to tell whether the real base of the parent ablocks is `abase'
- (if not, the word before the first ablock holds a pointer to the
- real base). */
- struct ablocks *abase;
- /* The padding of all but the last ablock is unused. The padding of
- the last ablock in an ablocks is not allocated. */
-#if BLOCK_PADDING
- char padding[BLOCK_PADDING];
-#endif
-};
-
-/* A bunch of consecutive aligned blocks. */
-struct ablocks
-{
- struct ablock blocks[ABLOCKS_SIZE];
-};
-
-/* Size of the block requested from malloc or aligned_alloc. */
-#define ABLOCKS_BYTES (sizeof (struct ablocks) - BLOCK_PADDING)
-
-#define ABLOCK_ABASE(block) \
- (((uintptr_t) (block)->abase) <= (1 + 2 * ABLOCKS_SIZE) \
- ? (struct ablocks *)(block) \
- : (block)->abase)
-
-/* Virtual `busy' field. */
-#define ABLOCKS_BUSY(abase) ((abase)->blocks[0].abase)
-
-/* Pointer to the (not necessarily aligned) malloc block. */
-#ifdef USE_ALIGNED_ALLOC
-#define ABLOCKS_BASE(abase) (abase)
-#else
-#define ABLOCKS_BASE(abase) \
- (1 & (intptr_t) ABLOCKS_BUSY (abase) ? abase : ((void **)abase)[-1])
-#endif
-
-/* The list of free ablock. */
-static struct ablock *free_ablock;
-
-/* Allocate an aligned block of nbytes.
- Alignment is on a multiple of BLOCK_ALIGN and `nbytes' has to be
- smaller or equal to BLOCK_BYTES. */
-static void *
-lisp_align_malloc (size_t nbytes, enum mem_type type)
-{
- void *base, *val;
- struct ablocks *abase;
-
- eassert (nbytes <= BLOCK_BYTES);
-
- MALLOC_BLOCK_INPUT;
-
-#ifdef GC_MALLOC_CHECK
- allocated_mem_type = type;
-#endif
-
- if (!free_ablock)
- {
- int i;
- intptr_t aligned; /* int gets warning casting to 64-bit pointer. */
-
-#ifdef DOUG_LEA_MALLOC
- if (!mmap_lisp_allowed_p ())
- mallopt (M_MMAP_MAX, 0);
-#endif
-
-#ifdef USE_ALIGNED_ALLOC
- abase = base = aligned_alloc (BLOCK_ALIGN, ABLOCKS_BYTES);
-#else
- base = malloc (ABLOCKS_BYTES);
- abase = ALIGN (base, BLOCK_ALIGN);
-#endif
-
- if (base == 0)
- {
- MALLOC_UNBLOCK_INPUT;
- memory_full (ABLOCKS_BYTES);
- }
-
- aligned = (base == abase);
- if (!aligned)
- ((void **) abase)[-1] = base;
-
-#ifdef DOUG_LEA_MALLOC
- if (!mmap_lisp_allowed_p ())
- mallopt (M_MMAP_MAX, MMAP_MAX_AREAS);
-#endif
-
-#if ! USE_LSB_TAG
- /* If the memory just allocated cannot be addressed thru a Lisp
- object's pointer, and it needs to be, that's equivalent to
- running out of memory. */
- if (type != MEM_TYPE_NON_LISP)
- {
- Lisp_Object tem;
- char *end = (char *) base + ABLOCKS_BYTES - 1;
- XSETCONS (tem, end);
- if ((char *) XCONS (tem) != end)
- {
- lisp_malloc_loser = base;
- free (base);
- MALLOC_UNBLOCK_INPUT;
- memory_full (SIZE_MAX);
- }
- }
-#endif
-
- /* Initialize the blocks and put them on the free list.
- If `base' was not properly aligned, we can't use the last block. */
- for (i = 0; i < (aligned ? ABLOCKS_SIZE : ABLOCKS_SIZE - 1); i++)
- {
- abase->blocks[i].abase = abase;
- abase->blocks[i].x.next_free = free_ablock;
- free_ablock = &abase->blocks[i];
- }
- ABLOCKS_BUSY (abase) = (struct ablocks *) aligned;
-
- eassert (0 == ((uintptr_t) abase) % BLOCK_ALIGN);
- eassert (ABLOCK_ABASE (&abase->blocks[3]) == abase); /* 3 is arbitrary */
- eassert (ABLOCK_ABASE (&abase->blocks[0]) == abase);
- eassert (ABLOCKS_BASE (abase) == base);
- eassert (aligned == (intptr_t) ABLOCKS_BUSY (abase));
- }
-
- abase = ABLOCK_ABASE (free_ablock);
- ABLOCKS_BUSY (abase)
- = (struct ablocks *) (2 + (intptr_t) ABLOCKS_BUSY (abase));
- val = free_ablock;
- free_ablock = free_ablock->x.next_free;
-
-#if GC_MARK_STACK && !defined GC_MALLOC_CHECK
- if (type != MEM_TYPE_NON_LISP)
- mem_insert (val, (char *) val + nbytes, type);
-#endif
-
- MALLOC_UNBLOCK_INPUT;
-
- MALLOC_PROBE (nbytes);
-
- eassert (0 == ((uintptr_t) val) % BLOCK_ALIGN);
- return val;
-}
-
-static void
-lisp_align_free (void *block)
-{
- struct ablock *ablock = block;
- struct ablocks *abase = ABLOCK_ABASE (ablock);
-
- MALLOC_BLOCK_INPUT;
-#if GC_MARK_STACK && !defined GC_MALLOC_CHECK
- mem_delete (mem_find (block));
-#endif
- /* Put on free list. */
- ablock->x.next_free = free_ablock;
- free_ablock = ablock;
- /* Update busy count. */
- ABLOCKS_BUSY (abase)
- = (struct ablocks *) (-2 + (intptr_t) ABLOCKS_BUSY (abase));
-
- if (2 > (intptr_t) ABLOCKS_BUSY (abase))
- { /* All the blocks are free. */
- int i = 0, aligned = (intptr_t) ABLOCKS_BUSY (abase);
- struct ablock **tem = &free_ablock;
- struct ablock *atop = &abase->blocks[aligned ? ABLOCKS_SIZE : ABLOCKS_SIZE - 1];
-
- while (*tem)
- {
- if (*tem >= (struct ablock *) abase && *tem < atop)
- {
- i++;
- *tem = (*tem)->x.next_free;
- }
- else
- tem = &(*tem)->x.next_free;
- }
- eassert ((aligned & 1) == aligned);
- eassert (i == (aligned ? ABLOCKS_SIZE : ABLOCKS_SIZE - 1));
-#ifdef USE_POSIX_MEMALIGN
- eassert ((uintptr_t) ABLOCKS_BASE (abase) % BLOCK_ALIGN == 0);
-#endif
- free (ABLOCKS_BASE (abase));
- }
- MALLOC_UNBLOCK_INPUT;
-}
-
-\f
-/***********************************************************************
- Interval Allocation
- ***********************************************************************/
-
-/* Number of intervals allocated in an interval_block structure.
- The 1020 is 1024 minus malloc overhead. */
-
-#define INTERVAL_BLOCK_SIZE \
- ((1020 - sizeof (struct interval_block *)) / sizeof (struct interval))
-
-/* Intervals are allocated in chunks in the form of an interval_block
- structure. */
-
-struct interval_block
-{
- /* Place `intervals' first, to preserve alignment. */
- struct interval intervals[INTERVAL_BLOCK_SIZE];
- struct interval_block *next;
-};
-
-/* Current interval block. Its `next' pointer points to older
- blocks. */
-
-static struct interval_block *interval_block;
-
-/* Index in interval_block above of the next unused interval
- structure. */
-
-static int interval_block_index = INTERVAL_BLOCK_SIZE;
-
-/* Number of free and live intervals. */
-
-static EMACS_INT total_free_intervals, total_intervals;
-
-/* List of free intervals. */
-
-static INTERVAL interval_free_list;
-
-/* Return a new interval. */
-
-INTERVAL
-make_interval (void)
-{
- INTERVAL val;
-
- MALLOC_BLOCK_INPUT;
-
- if (interval_free_list)
- {
- val = interval_free_list;
- interval_free_list = INTERVAL_PARENT (interval_free_list);
- }
- else
- {
- if (interval_block_index == INTERVAL_BLOCK_SIZE)
- {
- struct interval_block *newi
- = lisp_malloc (sizeof *newi, MEM_TYPE_NON_LISP);
-
- newi->next = interval_block;
- interval_block = newi;
- interval_block_index = 0;
- total_free_intervals += INTERVAL_BLOCK_SIZE;
- }
- val = &interval_block->intervals[interval_block_index++];
- }
-
- MALLOC_UNBLOCK_INPUT;
-
- consing_since_gc += sizeof (struct interval);
- intervals_consed++;
- total_free_intervals--;
- RESET_INTERVAL (val);
- val->gcmarkbit = 0;
- return val;
-}
-
-
-/* Mark Lisp objects in interval I. */
-
-static void
-mark_interval (register INTERVAL i, Lisp_Object dummy)
-{
- /* Intervals should never be shared. So, if extra internal checking is
- enabled, GC aborts if it seems to have visited an interval twice. */
- eassert (!i->gcmarkbit);
- i->gcmarkbit = 1;
- mark_object (i->plist);
-}
-
-/* Mark the interval tree rooted in I. */
-
-#define MARK_INTERVAL_TREE(i) \
- do { \
- if (i && !i->gcmarkbit) \
- traverse_intervals_noorder (i, mark_interval, Qnil); \
- } while (0)
-
-/***********************************************************************
- String Allocation
- ***********************************************************************/
-
-/* Lisp_Strings are allocated in string_block structures. When a new
- string_block is allocated, all the Lisp_Strings it contains are
- added to a free-list string_free_list. When a new Lisp_String is
- needed, it is taken from that list. During the sweep phase of GC,
- string_blocks that are entirely free are freed, except two which
- we keep.
-
- String data is allocated from sblock structures. Strings larger
- than LARGE_STRING_BYTES, get their own sblock, data for smaller
- strings is sub-allocated out of sblocks of size SBLOCK_SIZE.
-
- Sblocks consist internally of sdata structures, one for each
- Lisp_String. The sdata structure points to the Lisp_String it
- belongs to. The Lisp_String points back to the `u.data' member of
- its sdata structure.
-
- When a Lisp_String is freed during GC, it is put back on
- string_free_list, and its `data' member and its sdata's `string'
- pointer is set to null. The size of the string is recorded in the
- `n.nbytes' member of the sdata. So, sdata structures that are no
- longer used, can be easily recognized, and it's easy to compact the
- sblocks of small strings which we do in compact_small_strings. */
-
-/* Size in bytes of an sblock structure used for small strings. This
- is 8192 minus malloc overhead. */
-
-#define SBLOCK_SIZE 8188
-
-/* Strings larger than this are considered large strings. String data
- for large strings is allocated from individual sblocks. */
-
-#define LARGE_STRING_BYTES 1024
-
-/* The SDATA typedef is a struct or union describing string memory
- sub-allocated from an sblock. This is where the contents of Lisp
- strings are stored. */
-
-struct sdata
-{
- /* Back-pointer to the string this sdata belongs to. If null, this
- structure is free, and NBYTES (in this structure or in the union below)
- contains the string's byte size (the same value that STRING_BYTES
- would return if STRING were non-null). If non-null, STRING_BYTES
- (STRING) is the size of the data, and DATA contains the string's
- contents. */
- struct Lisp_String *string;
-
-#ifdef GC_CHECK_STRING_BYTES
- ptrdiff_t nbytes;
-#endif
-
- unsigned char data[FLEXIBLE_ARRAY_MEMBER];
-};
-
-#ifdef GC_CHECK_STRING_BYTES
-
-typedef struct sdata sdata;
-#define SDATA_NBYTES(S) (S)->nbytes
-#define SDATA_DATA(S) (S)->data
-
-#else
-
-typedef union
-{
- struct Lisp_String *string;
-
- /* When STRING is nonnull, this union is actually of type 'struct sdata',
- which has a flexible array member. However, if implemented by
- giving this union a member of type 'struct sdata', the union
- could not be the last (flexible) member of 'struct sblock',
- because C99 prohibits a flexible array member from having a type
- that is itself a flexible array. So, comment this member out here,
- but remember that the option's there when using this union. */
-#if 0
- struct sdata u;
-#endif
-
- /* When STRING is null. */
- struct
- {
- struct Lisp_String *string;
- ptrdiff_t nbytes;
- } n;
-} sdata;
-
-#define SDATA_NBYTES(S) (S)->n.nbytes
-#define SDATA_DATA(S) ((struct sdata *) (S))->data
-
-#endif /* not GC_CHECK_STRING_BYTES */
-
-enum { SDATA_DATA_OFFSET = offsetof (struct sdata, data) };
-
-/* Structure describing a block of memory which is sub-allocated to
- obtain string data memory for strings. Blocks for small strings
- are of fixed size SBLOCK_SIZE. Blocks for large strings are made
- as large as needed. */
-
-struct sblock
-{
- /* Next in list. */
- struct sblock *next;
-
- /* Pointer to the next free sdata block. This points past the end
- of the sblock if there isn't any space left in this block. */
- sdata *next_free;
-
- /* String data. */
- sdata data[FLEXIBLE_ARRAY_MEMBER];
-};
-
-/* Number of Lisp strings in a string_block structure. The 1020 is
- 1024 minus malloc overhead. */
-
-#define STRING_BLOCK_SIZE \
- ((1020 - sizeof (struct string_block *)) / sizeof (struct Lisp_String))
-
-/* Structure describing a block from which Lisp_String structures
- are allocated. */
-
-struct string_block
-{
- /* Place `strings' first, to preserve alignment. */
- struct Lisp_String strings[STRING_BLOCK_SIZE];
- struct string_block *next;
-};
-
-/* Head and tail of the list of sblock structures holding Lisp string
- data. We always allocate from current_sblock. The NEXT pointers
- in the sblock structures go from oldest_sblock to current_sblock. */
-
-static struct sblock *oldest_sblock, *current_sblock;
-
-/* List of sblocks for large strings. */
-
-static struct sblock *large_sblocks;
-
-/* List of string_block structures. */
-
-static struct string_block *string_blocks;
-
-/* Free-list of Lisp_Strings. */
-
-static struct Lisp_String *string_free_list;
-
-/* Number of live and free Lisp_Strings. */
-
-static EMACS_INT total_strings, total_free_strings;
-
-/* Number of bytes used by live strings. */
-
-static EMACS_INT total_string_bytes;
-
-/* Given a pointer to a Lisp_String S which is on the free-list
- string_free_list, return a pointer to its successor in the
- free-list. */
-
-#define NEXT_FREE_LISP_STRING(S) (*(struct Lisp_String **) (S))
-
-/* Return a pointer to the sdata structure belonging to Lisp string S.
- S must be live, i.e. S->data must not be null. S->data is actually
- a pointer to the `u.data' member of its sdata structure; the
- structure starts at a constant offset in front of that. */
-
-#define SDATA_OF_STRING(S) ((sdata *) ((S)->data - SDATA_DATA_OFFSET))
-
-
-#ifdef GC_CHECK_STRING_OVERRUN
-
-/* We check for overrun in string data blocks by appending a small
- "cookie" after each allocated string data block, and check for the
- presence of this cookie during GC. */
-
-#define GC_STRING_OVERRUN_COOKIE_SIZE 4
-static char const string_overrun_cookie[GC_STRING_OVERRUN_COOKIE_SIZE] =
- { '\xde', '\xad', '\xbe', '\xef' };
-
-#else
-#define GC_STRING_OVERRUN_COOKIE_SIZE 0
-#endif
-
-/* Value is the size of an sdata structure large enough to hold NBYTES
- bytes of string data. The value returned includes a terminating
- NUL byte, the size of the sdata structure, and padding. */
-
-#ifdef GC_CHECK_STRING_BYTES
-
-#define SDATA_SIZE(NBYTES) \
- ((SDATA_DATA_OFFSET \
- + (NBYTES) + 1 \
- + sizeof (ptrdiff_t) - 1) \
- & ~(sizeof (ptrdiff_t) - 1))
-
-#else /* not GC_CHECK_STRING_BYTES */
-
-/* The 'max' reserves space for the nbytes union member even when NBYTES + 1 is
- less than the size of that member. The 'max' is not needed when
- SDATA_DATA_OFFSET is a multiple of sizeof (ptrdiff_t), because then the
- alignment code reserves enough space. */
-
-#define SDATA_SIZE(NBYTES) \
- ((SDATA_DATA_OFFSET \
- + (SDATA_DATA_OFFSET % sizeof (ptrdiff_t) == 0 \
- ? NBYTES \
- : max (NBYTES, sizeof (ptrdiff_t) - 1)) \
- + 1 \
- + sizeof (ptrdiff_t) - 1) \
- & ~(sizeof (ptrdiff_t) - 1))
-
-#endif /* not GC_CHECK_STRING_BYTES */
-
-/* Extra bytes to allocate for each string. */
-
-#define GC_STRING_EXTRA (GC_STRING_OVERRUN_COOKIE_SIZE)
-
-/* Exact bound on the number of bytes in a string, not counting the
- terminating null. A string cannot contain more bytes than
- STRING_BYTES_BOUND, nor can it be so long that the size_t
- arithmetic in allocate_string_data would overflow while it is
- calculating a value to be passed to malloc. */
-static ptrdiff_t const STRING_BYTES_MAX =
- min (STRING_BYTES_BOUND,
- ((SIZE_MAX - XMALLOC_OVERRUN_CHECK_OVERHEAD
- - GC_STRING_EXTRA
- - offsetof (struct sblock, data)
- - SDATA_DATA_OFFSET)
- & ~(sizeof (EMACS_INT) - 1)));
-
-/* Initialize string allocation. Called from init_alloc_once. */
-
-static void
-init_strings (void)
-{
- empty_unibyte_string = make_pure_string ("", 0, 0, 0);
- empty_multibyte_string = make_pure_string ("", 0, 0, 1);
-}
-
-
-#ifdef GC_CHECK_STRING_BYTES
-
-static int check_string_bytes_count;
-
-/* Like STRING_BYTES, but with debugging check. Can be
- called during GC, so pay attention to the mark bit. */
-
-ptrdiff_t
-string_bytes (struct Lisp_String *s)
-{
- ptrdiff_t nbytes =
- (s->size_byte < 0 ? s->size & ~ARRAY_MARK_FLAG : s->size_byte);
-
- if (!PURE_POINTER_P (s)
- && s->data
- && nbytes != SDATA_NBYTES (SDATA_OF_STRING (s)))
- emacs_abort ();
- return nbytes;
-}
-
-/* Check validity of Lisp strings' string_bytes member in B. */
-
-static void
-check_sblock (struct sblock *b)
-{
- sdata *from, *end, *from_end;
-
- end = b->next_free;
-
- for (from = b->data; from < end; from = from_end)
- {
- /* Compute the next FROM here because copying below may
- overwrite data we need to compute it. */
- ptrdiff_t nbytes;
-
- /* Check that the string size recorded in the string is the
- same as the one recorded in the sdata structure. */
- nbytes = SDATA_SIZE (from->string ? string_bytes (from->string)
- : SDATA_NBYTES (from));
- from_end = (sdata *) ((char *) from + nbytes + GC_STRING_EXTRA);
- }
-}
-
-
-/* Check validity of Lisp strings' string_bytes member. ALL_P
- means check all strings, otherwise check only most
- recently allocated strings. Used for hunting a bug. */
-
-static void
-check_string_bytes (bool all_p)
-{
- if (all_p)
- {
- struct sblock *b;
-
- for (b = large_sblocks; b; b = b->next)
- {
- struct Lisp_String *s = b->data[0].string;
- if (s)
- string_bytes (s);
- }
-
- for (b = oldest_sblock; b; b = b->next)
- check_sblock (b);
- }
- else if (current_sblock)
- check_sblock (current_sblock);
-}
-
-#else /* not GC_CHECK_STRING_BYTES */
-
-#define check_string_bytes(all) ((void) 0)
-
-#endif /* GC_CHECK_STRING_BYTES */
-
-#ifdef GC_CHECK_STRING_FREE_LIST
-
-/* Walk through the string free list looking for bogus next pointers.
- This may catch buffer overrun from a previous string. */
-
-static void
-check_string_free_list (void)
-{
- struct Lisp_String *s;
-
- /* Pop a Lisp_String off the free-list. */
- s = string_free_list;
- while (s != NULL)
- {
- if ((uintptr_t) s < 1024)
- emacs_abort ();
- s = NEXT_FREE_LISP_STRING (s);
- }
-}
-#else
-#define check_string_free_list()
-#endif
-
-/* Return a new Lisp_String. */
-
-static struct Lisp_String *
-allocate_string (void)
-{
- struct Lisp_String *s;
-
- MALLOC_BLOCK_INPUT;
-
- /* If the free-list is empty, allocate a new string_block, and
- add all the Lisp_Strings in it to the free-list. */
- if (string_free_list == NULL)
- {
- struct string_block *b = lisp_malloc (sizeof *b, MEM_TYPE_STRING);
- int i;
-
- b->next = string_blocks;
- string_blocks = b;
-
- for (i = STRING_BLOCK_SIZE - 1; i >= 0; --i)
- {
- s = b->strings + i;
- /* Every string on a free list should have NULL data pointer. */
- s->data = NULL;
- NEXT_FREE_LISP_STRING (s) = string_free_list;
- string_free_list = s;
- }
-
- total_free_strings += STRING_BLOCK_SIZE;
- }
-
- check_string_free_list ();
-
- /* Pop a Lisp_String off the free-list. */
- s = string_free_list;
- string_free_list = NEXT_FREE_LISP_STRING (s);
-
- MALLOC_UNBLOCK_INPUT;
-
- --total_free_strings;
- ++total_strings;
- ++strings_consed;
- consing_since_gc += sizeof *s;
-
-#ifdef GC_CHECK_STRING_BYTES
- if (!noninteractive)
- {
- if (++check_string_bytes_count == 200)
- {
- check_string_bytes_count = 0;
- check_string_bytes (1);
- }
- else
- check_string_bytes (0);
- }
-#endif /* GC_CHECK_STRING_BYTES */
-
- return s;
-}
-
-
-/* Set up Lisp_String S for holding NCHARS characters, NBYTES bytes,
- plus a NUL byte at the end. Allocate an sdata structure for S, and
- set S->data to its `u.data' member. Store a NUL byte at the end of
- S->data. Set S->size to NCHARS and S->size_byte to NBYTES. Free
- S->data if it was initially non-null. */
-
-void
-allocate_string_data (struct Lisp_String *s,
- EMACS_INT nchars, EMACS_INT nbytes)
-{
- sdata *data, *old_data;
- struct sblock *b;
- ptrdiff_t needed, old_nbytes;
-
- if (STRING_BYTES_MAX < nbytes)
- string_overflow ();
-
- /* Determine the number of bytes needed to store NBYTES bytes
- of string data. */
- needed = SDATA_SIZE (nbytes);
- if (s->data)
- {
- old_data = SDATA_OF_STRING (s);
- old_nbytes = STRING_BYTES (s);
- }
- else
- old_data = NULL;
-
- MALLOC_BLOCK_INPUT;
-
- if (nbytes > LARGE_STRING_BYTES)
- {
- size_t size = offsetof (struct sblock, data) + needed;
-
-#ifdef DOUG_LEA_MALLOC
- if (!mmap_lisp_allowed_p ())
- mallopt (M_MMAP_MAX, 0);
-#endif
-
- b = lisp_malloc (size + GC_STRING_EXTRA, MEM_TYPE_NON_LISP);
-
-#ifdef DOUG_LEA_MALLOC
- if (!mmap_lisp_allowed_p ())
- mallopt (M_MMAP_MAX, MMAP_MAX_AREAS);
-#endif
-
- b->next_free = b->data;
- b->data[0].string = NULL;
- b->next = large_sblocks;
- large_sblocks = b;
- }
- else if (current_sblock == NULL
- || (((char *) current_sblock + SBLOCK_SIZE
- - (char *) current_sblock->next_free)
- < (needed + GC_STRING_EXTRA)))
- {
- /* Not enough room in the current sblock. */
- b = lisp_malloc (SBLOCK_SIZE, MEM_TYPE_NON_LISP);
- b->next_free = b->data;
- b->data[0].string = NULL;
- b->next = NULL;
-
- if (current_sblock)
- current_sblock->next = b;
- else
- oldest_sblock = b;
- current_sblock = b;
- }
- else
- b = current_sblock;
-
- data = b->next_free;
- b->next_free = (sdata *) ((char *) data + needed + GC_STRING_EXTRA);
-
- MALLOC_UNBLOCK_INPUT;
-
- data->string = s;
- s->data = SDATA_DATA (data);
-#ifdef GC_CHECK_STRING_BYTES
- SDATA_NBYTES (data) = nbytes;
-#endif
- s->size = nchars;
- s->size_byte = nbytes;
- s->data[nbytes] = '\0';
-#ifdef GC_CHECK_STRING_OVERRUN
- memcpy ((char *) data + needed, string_overrun_cookie,
- GC_STRING_OVERRUN_COOKIE_SIZE);
-#endif
-
- /* Note that Faset may call to this function when S has already data
- assigned. In this case, mark data as free by setting it's string
- back-pointer to null, and record the size of the data in it. */
- if (old_data)
- {
- SDATA_NBYTES (old_data) = old_nbytes;
- old_data->string = NULL;
- }
-
- consing_since_gc += needed;
-}
-
-
-/* Sweep and compact strings. */
-
-NO_INLINE /* For better stack traces */
-static void
-sweep_strings (void)
-{
- struct string_block *b, *next;
- struct string_block *live_blocks = NULL;
-
- string_free_list = NULL;
- total_strings = total_free_strings = 0;
- total_string_bytes = 0;
-
- /* Scan strings_blocks, free Lisp_Strings that aren't marked. */
- for (b = string_blocks; b; b = next)
- {
- int i, nfree = 0;
- struct Lisp_String *free_list_before = string_free_list;
-
- next = b->next;
-
- for (i = 0; i < STRING_BLOCK_SIZE; ++i)
- {
- struct Lisp_String *s = b->strings + i;
-
- if (s->data)
- {
- /* String was not on free-list before. */
- if (STRING_MARKED_P (s))
- {
- /* String is live; unmark it and its intervals. */
- UNMARK_STRING (s);
-
- /* Do not use string_(set|get)_intervals here. */
- s->intervals = balance_intervals (s->intervals);
-
- ++total_strings;
- total_string_bytes += STRING_BYTES (s);
- }
- else
- {
- /* String is dead. Put it on the free-list. */
- sdata *data = SDATA_OF_STRING (s);
-
- /* Save the size of S in its sdata so that we know
- how large that is. Reset the sdata's string
- back-pointer so that we know it's free. */
-#ifdef GC_CHECK_STRING_BYTES
- if (string_bytes (s) != SDATA_NBYTES (data))
- emacs_abort ();
-#else
- data->n.nbytes = STRING_BYTES (s);
-#endif
- data->string = NULL;
-
- /* Reset the strings's `data' member so that we
- know it's free. */
- s->data = NULL;
-
- /* Put the string on the free-list. */
- NEXT_FREE_LISP_STRING (s) = string_free_list;
- string_free_list = s;
- ++nfree;
- }
- }
- else
- {
- /* S was on the free-list before. Put it there again. */
- NEXT_FREE_LISP_STRING (s) = string_free_list;
- string_free_list = s;
- ++nfree;
- }
- }
-
- /* Free blocks that contain free Lisp_Strings only, except
- the first two of them. */
- if (nfree == STRING_BLOCK_SIZE
- && total_free_strings > STRING_BLOCK_SIZE)
- {
- lisp_free (b);
- string_free_list = free_list_before;
- }
- else
- {
- total_free_strings += nfree;
- b->next = live_blocks;
- live_blocks = b;
- }
- }
-
- check_string_free_list ();
-
- string_blocks = live_blocks;
- free_large_strings ();
- compact_small_strings ();
-
- check_string_free_list ();
-}
-
-
-/* Free dead large strings. */
-
-static void
-free_large_strings (void)
-{
- struct sblock *b, *next;
- struct sblock *live_blocks = NULL;
-
- for (b = large_sblocks; b; b = next)
- {
- next = b->next;
-
- if (b->data[0].string == NULL)
- lisp_free (b);
- else
- {
- b->next = live_blocks;
- live_blocks = b;
- }
- }
-
- large_sblocks = live_blocks;
-}
-
-
-/* Compact data of small strings. Free sblocks that don't contain
- data of live strings after compaction. */
-
-static void
-compact_small_strings (void)
-{
- struct sblock *b, *tb, *next;
- sdata *from, *to, *end, *tb_end;
- sdata *to_end, *from_end;
-
- /* TB is the sblock we copy to, TO is the sdata within TB we copy
- to, and TB_END is the end of TB. */
- tb = oldest_sblock;
- tb_end = (sdata *) ((char *) tb + SBLOCK_SIZE);
- to = tb->data;
-
- /* Step through the blocks from the oldest to the youngest. We
- expect that old blocks will stabilize over time, so that less
- copying will happen this way. */
- for (b = oldest_sblock; b; b = b->next)
- {
- end = b->next_free;
- eassert ((char *) end <= (char *) b + SBLOCK_SIZE);
-
- for (from = b->data; from < end; from = from_end)
- {
- /* Compute the next FROM here because copying below may
- overwrite data we need to compute it. */
- ptrdiff_t nbytes;
- struct Lisp_String *s = from->string;
-
-#ifdef GC_CHECK_STRING_BYTES
- /* Check that the string size recorded in the string is the
- same as the one recorded in the sdata structure. */
- if (s && string_bytes (s) != SDATA_NBYTES (from))
- emacs_abort ();
-#endif /* GC_CHECK_STRING_BYTES */
-
- nbytes = s ? STRING_BYTES (s) : SDATA_NBYTES (from);
- eassert (nbytes <= LARGE_STRING_BYTES);
-
- nbytes = SDATA_SIZE (nbytes);
- from_end = (sdata *) ((char *) from + nbytes + GC_STRING_EXTRA);
-
-#ifdef GC_CHECK_STRING_OVERRUN
- if (memcmp (string_overrun_cookie,
- (char *) from_end - GC_STRING_OVERRUN_COOKIE_SIZE,
- GC_STRING_OVERRUN_COOKIE_SIZE))
- emacs_abort ();
-#endif
-
- /* Non-NULL S means it's alive. Copy its data. */
- if (s)
- {
- /* If TB is full, proceed with the next sblock. */
- to_end = (sdata *) ((char *) to + nbytes + GC_STRING_EXTRA);
- if (to_end > tb_end)
- {
- tb->next_free = to;
- tb = tb->next;
- tb_end = (sdata *) ((char *) tb + SBLOCK_SIZE);
- to = tb->data;
- to_end = (sdata *) ((char *) to + nbytes + GC_STRING_EXTRA);
- }
-
- /* Copy, and update the string's `data' pointer. */
- if (from != to)
- {
- eassert (tb != b || to < from);
- memmove (to, from, nbytes + GC_STRING_EXTRA);
- to->string->data = SDATA_DATA (to);
- }
-
- /* Advance past the sdata we copied to. */
- to = to_end;
- }
- }
- }
-
- /* The rest of the sblocks following TB don't contain live data, so
- we can free them. */
- for (b = tb->next; b; b = next)
- {
- next = b->next;
- lisp_free (b);
- }
-
- tb->next_free = to;
- tb->next = NULL;
- current_sblock = tb;
-}
-
-void
-string_overflow (void)
-{
- error ("Maximum string size exceeded");
-}
-
-DEFUN ("make-string", Fmake_string, Smake_string, 2, 2, 0,
- doc: /* Return a newly created string of length LENGTH, with INIT in each element.
-LENGTH must be an integer.
-INIT must be an integer that represents a character. */)
- (Lisp_Object length, Lisp_Object init)
-{
- register Lisp_Object val;
- int c;
- EMACS_INT nbytes;
-
- CHECK_NATNUM (length);
- CHECK_CHARACTER (init);
-
- c = XFASTINT (init);
- if (ASCII_CHAR_P (c))
- {
- nbytes = XINT (length);
- val = make_uninit_string (nbytes);
- memset (SDATA (val), c, nbytes);
- SDATA (val)[nbytes] = 0;
- }
- else
- {
- unsigned char str[MAX_MULTIBYTE_LENGTH];
- ptrdiff_t len = CHAR_STRING (c, str);
- EMACS_INT string_len = XINT (length);
- unsigned char *p, *beg, *end;
-
- if (string_len > STRING_BYTES_MAX / len)
- string_overflow ();
- nbytes = len * string_len;
- val = make_uninit_multibyte_string (string_len, nbytes);
- for (beg = SDATA (val), p = beg, end = beg + nbytes; p < end; p += len)
- {
- /* First time we just copy `str' to the data of `val'. */
- if (p == beg)
- memcpy (p, str, len);
- else
- {
- /* Next time we copy largest possible chunk from
- initialized to uninitialized part of `val'. */
- len = min (p - beg, end - p);
- memcpy (p, beg, len);
- }
- }
- *p = 0;
- }
-
- return val;
-}
-
-/* Fill A with 1 bits if INIT is non-nil, and with 0 bits otherwise.
- Return A. */
-
-Lisp_Object
-bool_vector_fill (Lisp_Object a, Lisp_Object init)
-{
- EMACS_INT nbits = bool_vector_size (a);
- if (0 < nbits)
- {
- unsigned char *data = bool_vector_uchar_data (a);
- int pattern = NILP (init) ? 0 : (1 << BOOL_VECTOR_BITS_PER_CHAR) - 1;
- ptrdiff_t nbytes = bool_vector_bytes (nbits);
- int last_mask = ~ (~0 << ((nbits - 1) % BOOL_VECTOR_BITS_PER_CHAR + 1));
- memset (data, pattern, nbytes - 1);
- data[nbytes - 1] = pattern & last_mask;
- }
- return a;
-}
-
-/* Return a newly allocated, uninitialized bool vector of size NBITS. */
-
-Lisp_Object
-make_uninit_bool_vector (EMACS_INT nbits)
-{
- Lisp_Object val;
- EMACS_INT words = bool_vector_words (nbits);
- EMACS_INT word_bytes = words * sizeof (bits_word);
- EMACS_INT needed_elements = ((bool_header_size - header_size + word_bytes
- + word_size - 1)
- / word_size);
- struct Lisp_Bool_Vector *p
- = (struct Lisp_Bool_Vector *) allocate_vector (needed_elements);
- XSETVECTOR (val, p);
- XSETPVECTYPESIZE (XVECTOR (val), PVEC_BOOL_VECTOR, 0, 0);
- p->size = nbits;
-
- /* Clear padding at the end. */
- if (words)
- p->data[words - 1] = 0;
-
- return val;
-}
-
-DEFUN ("make-bool-vector", Fmake_bool_vector, Smake_bool_vector, 2, 2, 0,
- doc: /* Return a new bool-vector of length LENGTH, using INIT for each element.
-LENGTH must be a number. INIT matters only in whether it is t or nil. */)
- (Lisp_Object length, Lisp_Object init)
-{
- Lisp_Object val;
-
- CHECK_NATNUM (length);
- val = make_uninit_bool_vector (XFASTINT (length));
- return bool_vector_fill (val, init);
-}
-
-
-/* Make a string from NBYTES bytes at CONTENTS, and compute the number
- of characters from the contents. This string may be unibyte or
- multibyte, depending on the contents. */
-
-Lisp_Object
-make_string (const char *contents, ptrdiff_t nbytes)
-{
- register Lisp_Object val;
- ptrdiff_t nchars, multibyte_nbytes;
-
- parse_str_as_multibyte ((const unsigned char *) contents, nbytes,
- &nchars, &multibyte_nbytes);
- if (nbytes == nchars || nbytes != multibyte_nbytes)
- /* CONTENTS contains no multibyte sequences or contains an invalid
- multibyte sequence. We must make unibyte string. */
- val = make_unibyte_string (contents, nbytes);
- else
- val = make_multibyte_string (contents, nchars, nbytes);
- return val;
-}
-
-
-/* Make an unibyte string from LENGTH bytes at CONTENTS. */
-
-Lisp_Object
-make_unibyte_string (const char *contents, ptrdiff_t length)
-{
- register Lisp_Object val;
- val = make_uninit_string (length);
- memcpy (SDATA (val), contents, length);
- return val;
-}
-
-
-/* Make a multibyte string from NCHARS characters occupying NBYTES
- bytes at CONTENTS. */
-
-Lisp_Object
-make_multibyte_string (const char *contents,
- ptrdiff_t nchars, ptrdiff_t nbytes)
-{
- register Lisp_Object val;
- val = make_uninit_multibyte_string (nchars, nbytes);
- memcpy (SDATA (val), contents, nbytes);
- return val;
-}
-
-
-/* Make a string from NCHARS characters occupying NBYTES bytes at
- CONTENTS. It is a multibyte string if NBYTES != NCHARS. */
-
-Lisp_Object
-make_string_from_bytes (const char *contents,
- ptrdiff_t nchars, ptrdiff_t nbytes)
-{
- register Lisp_Object val;
- val = make_uninit_multibyte_string (nchars, nbytes);
- memcpy (SDATA (val), contents, nbytes);
- if (SBYTES (val) == SCHARS (val))
- STRING_SET_UNIBYTE (val);
- return val;
-}
-
-
-/* Make a string from NCHARS characters occupying NBYTES bytes at
- CONTENTS. The argument MULTIBYTE controls whether to label the
- string as multibyte. If NCHARS is negative, it counts the number of
- characters by itself. */
-
-Lisp_Object
-make_specified_string (const char *contents,
- ptrdiff_t nchars, ptrdiff_t nbytes, bool multibyte)
-{
- Lisp_Object val;
-
- if (nchars < 0)
- {
- if (multibyte)
- nchars = multibyte_chars_in_text ((const unsigned char *) contents,
- nbytes);
- else
- nchars = nbytes;
- }
- val = make_uninit_multibyte_string (nchars, nbytes);
- memcpy (SDATA (val), contents, nbytes);
- if (!multibyte)
- STRING_SET_UNIBYTE (val);
- return val;
-}
-
-
-/* Return an unibyte Lisp_String set up to hold LENGTH characters
- occupying LENGTH bytes. */
-
-Lisp_Object
-make_uninit_string (EMACS_INT length)
-{
- Lisp_Object val;
-
- if (!length)
- return empty_unibyte_string;
- val = make_uninit_multibyte_string (length, length);
- STRING_SET_UNIBYTE (val);
- return val;
-}
-
-
-/* Return a multibyte Lisp_String set up to hold NCHARS characters
- which occupy NBYTES bytes. */
-
-Lisp_Object
-make_uninit_multibyte_string (EMACS_INT nchars, EMACS_INT nbytes)
-{
- Lisp_Object string;
- struct Lisp_String *s;
-
- if (nchars < 0)
- emacs_abort ();
- if (!nbytes)
- return empty_multibyte_string;
-
- s = allocate_string ();
- s->intervals = NULL;
- allocate_string_data (s, nchars, nbytes);
- XSETSTRING (string, s);
- string_chars_consed += nbytes;
- return string;
-}
-
-/* Print arguments to BUF according to a FORMAT, then return
- a Lisp_String initialized with the data from BUF. */
-
-Lisp_Object
-make_formatted_string (char *buf, const char *format, ...)
-{
- va_list ap;
- int length;
-
- va_start (ap, format);
- length = vsprintf (buf, format, ap);
- va_end (ap);
- return make_string (buf, length);
-}
-
-\f
-/***********************************************************************
- Float Allocation
- ***********************************************************************/
-
-/* We store float cells inside of float_blocks, allocating a new
- float_block with malloc whenever necessary. Float cells reclaimed
- by GC are put on a free list to be reallocated before allocating
- any new float cells from the latest float_block. */
-
-#define FLOAT_BLOCK_SIZE \
- (((BLOCK_BYTES - sizeof (struct float_block *) \
- /* The compiler might add padding at the end. */ \
- - (sizeof (struct Lisp_Float) - sizeof (int))) * CHAR_BIT) \
- / (sizeof (struct Lisp_Float) * CHAR_BIT + 1))
-
-#define GETMARKBIT(block,n) \
- (((block)->gcmarkbits[(n) / (sizeof (int) * CHAR_BIT)] \
- >> ((n) % (sizeof (int) * CHAR_BIT))) \
- & 1)
-
-#define SETMARKBIT(block,n) \
- (block)->gcmarkbits[(n) / (sizeof (int) * CHAR_BIT)] \
- |= 1 << ((n) % (sizeof (int) * CHAR_BIT))
-
-#define UNSETMARKBIT(block,n) \
- (block)->gcmarkbits[(n) / (sizeof (int) * CHAR_BIT)] \
- &= ~(1 << ((n) % (sizeof (int) * CHAR_BIT)))
-
-#define FLOAT_BLOCK(fptr) \
- ((struct float_block *) (((uintptr_t) (fptr)) & ~(BLOCK_ALIGN - 1)))
-
-#define FLOAT_INDEX(fptr) \
- ((((uintptr_t) (fptr)) & (BLOCK_ALIGN - 1)) / sizeof (struct Lisp_Float))
-
-struct float_block
-{
- /* Place `floats' at the beginning, to ease up FLOAT_INDEX's job. */
- struct Lisp_Float floats[FLOAT_BLOCK_SIZE];
- int gcmarkbits[1 + FLOAT_BLOCK_SIZE / (sizeof (int) * CHAR_BIT)];
- struct float_block *next;
-};
-
-#define FLOAT_MARKED_P(fptr) \
- GETMARKBIT (FLOAT_BLOCK (fptr), FLOAT_INDEX ((fptr)))
-
-#define FLOAT_MARK(fptr) \
- SETMARKBIT (FLOAT_BLOCK (fptr), FLOAT_INDEX ((fptr)))
-
-#define FLOAT_UNMARK(fptr) \
- UNSETMARKBIT (FLOAT_BLOCK (fptr), FLOAT_INDEX ((fptr)))
-
-/* Current float_block. */
-
-static struct float_block *float_block;
-
-/* Index of first unused Lisp_Float in the current float_block. */
-
-static int float_block_index = FLOAT_BLOCK_SIZE;
-
-/* Free-list of Lisp_Floats. */
-
-static struct Lisp_Float *float_free_list;
-
-/* Return a new float object with value FLOAT_VALUE. */
-
-Lisp_Object
-make_float (double float_value)
-{
- register Lisp_Object val;
-
- MALLOC_BLOCK_INPUT;
-
- if (float_free_list)
- {
- /* We use the data field for chaining the free list
- so that we won't use the same field that has the mark bit. */
- XSETFLOAT (val, float_free_list);
- float_free_list = float_free_list->u.chain;
- }
- else
- {
- if (float_block_index == FLOAT_BLOCK_SIZE)
- {
- struct float_block *new
- = lisp_align_malloc (sizeof *new, MEM_TYPE_FLOAT);
- new->next = float_block;
- memset (new->gcmarkbits, 0, sizeof new->gcmarkbits);
- float_block = new;
- float_block_index = 0;
- total_free_floats += FLOAT_BLOCK_SIZE;
- }
- XSETFLOAT (val, &float_block->floats[float_block_index]);
- float_block_index++;
- }
-
- MALLOC_UNBLOCK_INPUT;
-
- XFLOAT_INIT (val, float_value);
- eassert (!FLOAT_MARKED_P (XFLOAT (val)));
- consing_since_gc += sizeof (struct Lisp_Float);
- floats_consed++;
- total_free_floats--;
- return val;
-}
-
-
-\f
-/***********************************************************************
- Cons Allocation
- ***********************************************************************/
-
-/* We store cons cells inside of cons_blocks, allocating a new
- cons_block with malloc whenever necessary. Cons cells reclaimed by
- GC are put on a free list to be reallocated before allocating
- any new cons cells from the latest cons_block. */
-
-#define CONS_BLOCK_SIZE \
- (((BLOCK_BYTES - sizeof (struct cons_block *) \
- /* The compiler might add padding at the end. */ \
- - (sizeof (struct Lisp_Cons) - sizeof (int))) * CHAR_BIT) \
- / (sizeof (struct Lisp_Cons) * CHAR_BIT + 1))
-
-#define CONS_BLOCK(fptr) \
- ((struct cons_block *) ((uintptr_t) (fptr) & ~(BLOCK_ALIGN - 1)))
-
-#define CONS_INDEX(fptr) \
- (((uintptr_t) (fptr) & (BLOCK_ALIGN - 1)) / sizeof (struct Lisp_Cons))
-
-struct cons_block
-{
- /* Place `conses' at the beginning, to ease up CONS_INDEX's job. */
- struct Lisp_Cons conses[CONS_BLOCK_SIZE];
- int gcmarkbits[1 + CONS_BLOCK_SIZE / (sizeof (int) * CHAR_BIT)];
- struct cons_block *next;
-};
-
-#define CONS_MARKED_P(fptr) \
- GETMARKBIT (CONS_BLOCK (fptr), CONS_INDEX ((fptr)))
-
-#define CONS_MARK(fptr) \
- SETMARKBIT (CONS_BLOCK (fptr), CONS_INDEX ((fptr)))
-
-#define CONS_UNMARK(fptr) \
- UNSETMARKBIT (CONS_BLOCK (fptr), CONS_INDEX ((fptr)))
-
-/* Current cons_block. */
-
-static struct cons_block *cons_block;
-
-/* Index of first unused Lisp_Cons in the current block. */
-
-static int cons_block_index = CONS_BLOCK_SIZE;
-
-/* Free-list of Lisp_Cons structures. */
-
-static struct Lisp_Cons *cons_free_list;
-
-/* Explicitly free a cons cell by putting it on the free-list. */
-
-void
-free_cons (struct Lisp_Cons *ptr)
-{
- ptr->u.chain = cons_free_list;
-#if GC_MARK_STACK
- ptr->car = Vdead;
-#endif
- cons_free_list = ptr;
- consing_since_gc -= sizeof *ptr;
- total_free_conses++;
-}
-
-DEFUN ("cons", Fcons, Scons, 2, 2, 0,
- doc: /* Create a new cons, give it CAR and CDR as components, and return it. */)
- (Lisp_Object car, Lisp_Object cdr)
-{
- register Lisp_Object val;
-
- MALLOC_BLOCK_INPUT;
-
- if (cons_free_list)
- {
- /* We use the cdr for chaining the free list
- so that we won't use the same field that has the mark bit. */
- XSETCONS (val, cons_free_list);
- cons_free_list = cons_free_list->u.chain;
- }
- else
- {
- if (cons_block_index == CONS_BLOCK_SIZE)
- {
- struct cons_block *new
- = lisp_align_malloc (sizeof *new, MEM_TYPE_CONS);
- memset (new->gcmarkbits, 0, sizeof new->gcmarkbits);
- new->next = cons_block;
- cons_block = new;
- cons_block_index = 0;
- total_free_conses += CONS_BLOCK_SIZE;
- }
- XSETCONS (val, &cons_block->conses[cons_block_index]);
- cons_block_index++;
- }
-
- MALLOC_UNBLOCK_INPUT;
-
- XSETCAR (val, car);
- XSETCDR (val, cdr);
- eassert (!CONS_MARKED_P (XCONS (val)));
- consing_since_gc += sizeof (struct Lisp_Cons);
- total_free_conses--;
- cons_cells_consed++;
- return val;
-}
-
-#ifdef GC_CHECK_CONS_LIST
-/* Get an error now if there's any junk in the cons free list. */
-void
-check_cons_list (void)
-{
- struct Lisp_Cons *tail = cons_free_list;
-
- while (tail)
- tail = tail->u.chain;
-}
-#endif
-
-/* Make a list of 1, 2, 3, 4 or 5 specified objects. */
-
-Lisp_Object
-list1 (Lisp_Object arg1)
-{
- return Fcons (arg1, Qnil);
-}
-
-Lisp_Object
-list2 (Lisp_Object arg1, Lisp_Object arg2)
-{
- return Fcons (arg1, Fcons (arg2, Qnil));
-}
-
-
-Lisp_Object
-list3 (Lisp_Object arg1, Lisp_Object arg2, Lisp_Object arg3)
-{
- return Fcons (arg1, Fcons (arg2, Fcons (arg3, Qnil)));
-}
-
-
-Lisp_Object
-list4 (Lisp_Object arg1, Lisp_Object arg2, Lisp_Object arg3, Lisp_Object arg4)
-{
- return Fcons (arg1, Fcons (arg2, Fcons (arg3, Fcons (arg4, Qnil))));
-}
-
-
-Lisp_Object
-list5 (Lisp_Object arg1, Lisp_Object arg2, Lisp_Object arg3, Lisp_Object arg4, Lisp_Object arg5)
-{
- return Fcons (arg1, Fcons (arg2, Fcons (arg3, Fcons (arg4,
- Fcons (arg5, Qnil)))));
-}
-
-/* Make a list of COUNT Lisp_Objects, where ARG is the
- first one. Allocate conses from pure space if TYPE
- is CONSTYPE_PURE, or allocate as usual if type is CONSTYPE_HEAP. */
-
-Lisp_Object
-listn (enum constype type, ptrdiff_t count, Lisp_Object arg, ...)
-{
- va_list ap;
- ptrdiff_t i;
- Lisp_Object val, *objp;
-
- /* Change to SAFE_ALLOCA if you hit this eassert. */
- eassert (count <= MAX_ALLOCA / word_size);
-
- objp = alloca (count * word_size);
- objp[0] = arg;
- va_start (ap, arg);
- for (i = 1; i < count; i++)
- objp[i] = va_arg (ap, Lisp_Object);
- va_end (ap);
-
- for (val = Qnil, i = count - 1; i >= 0; i--)
- {
- if (type == CONSTYPE_PURE)
- val = pure_cons (objp[i], val);
- else if (type == CONSTYPE_HEAP)
- val = Fcons (objp[i], val);
- else
- emacs_abort ();
- }
- return val;
-}
-
-DEFUN ("list", Flist, Slist, 0, MANY, 0,
- doc: /* Return a newly created list with specified arguments as elements.
-Any number of arguments, even zero arguments, are allowed.
-usage: (list &rest OBJECTS) */)
- (ptrdiff_t nargs, Lisp_Object *args)
-{
- register Lisp_Object val;
- val = Qnil;
-
- while (nargs > 0)
- {
- nargs--;
- val = Fcons (args[nargs], val);
- }
- return val;
-}
-
-
-DEFUN ("make-list", Fmake_list, Smake_list, 2, 2, 0,
- doc: /* Return a newly created list of length LENGTH, with each element being INIT. */)
- (register Lisp_Object length, Lisp_Object init)
-{
- register Lisp_Object val;
- register EMACS_INT size;
-
- CHECK_NATNUM (length);
- size = XFASTINT (length);
-
- val = Qnil;
- while (size > 0)
- {
- val = Fcons (init, val);
- --size;
-
- if (size > 0)
- {
- val = Fcons (init, val);
- --size;
-
- if (size > 0)
- {
- val = Fcons (init, val);
- --size;
-
- if (size > 0)
- {
- val = Fcons (init, val);
- --size;
-
- if (size > 0)
- {
- val = Fcons (init, val);
- --size;
- }
- }
- }
- }
-
- QUIT;
- }
-
- return val;
-}
-
-
-\f
-/***********************************************************************
- Vector Allocation
- ***********************************************************************/
-
-/* Sometimes a vector's contents are merely a pointer internally used
- in vector allocation code. Usually you don't want to touch this. */
-
-static struct Lisp_Vector *
-next_vector (struct Lisp_Vector *v)
-{
- return XUNTAG (v->contents[0], 0);
-}
-
-static void
-set_next_vector (struct Lisp_Vector *v, struct Lisp_Vector *p)
-{
- v->contents[0] = make_lisp_ptr (p, 0);
-}
-
-/* This value is balanced well enough to avoid too much internal overhead
- for the most common cases; it's not required to be a power of two, but
- it's expected to be a mult-of-ROUNDUP_SIZE (see below). */
-
-#define VECTOR_BLOCK_SIZE 4096
-
-enum
- {
- /* Alignment of struct Lisp_Vector objects. */
- vector_alignment = COMMON_MULTIPLE (ALIGNOF_STRUCT_LISP_VECTOR,
- USE_LSB_TAG ? GCALIGNMENT : 1),
-
- /* Vector size requests are a multiple of this. */
- roundup_size = COMMON_MULTIPLE (vector_alignment, word_size)
- };
-
-/* Verify assumptions described above. */
-verify ((VECTOR_BLOCK_SIZE % roundup_size) == 0);
-verify (VECTOR_BLOCK_SIZE <= (1 << PSEUDOVECTOR_SIZE_BITS));
-
-/* Round up X to nearest mult-of-ROUNDUP_SIZE --- use at compile time. */
-#define vroundup_ct(x) ROUNDUP (x, roundup_size)
-/* Round up X to nearest mult-of-ROUNDUP_SIZE --- use at runtime. */
-#define vroundup(x) (eassume ((x) >= 0), vroundup_ct (x))
-
-/* Rounding helps to maintain alignment constraints if USE_LSB_TAG. */
-
-#define VECTOR_BLOCK_BYTES (VECTOR_BLOCK_SIZE - vroundup_ct (sizeof (void *)))
-
-/* Size of the minimal vector allocated from block. */
-
-#define VBLOCK_BYTES_MIN vroundup_ct (header_size + sizeof (Lisp_Object))
-
-/* Size of the largest vector allocated from block. */
-
-#define VBLOCK_BYTES_MAX \
- vroundup ((VECTOR_BLOCK_BYTES / 2) - word_size)
-
-/* We maintain one free list for each possible block-allocated
- vector size, and this is the number of free lists we have. */
-
-#define VECTOR_MAX_FREE_LIST_INDEX \
- ((VECTOR_BLOCK_BYTES - VBLOCK_BYTES_MIN) / roundup_size + 1)
-
-/* Common shortcut to advance vector pointer over a block data. */
-
-#define ADVANCE(v, nbytes) ((struct Lisp_Vector *) ((char *) (v) + (nbytes)))
-
-/* Common shortcut to calculate NBYTES-vector index in VECTOR_FREE_LISTS. */
-
-#define VINDEX(nbytes) (((nbytes) - VBLOCK_BYTES_MIN) / roundup_size)
-
-/* Common shortcut to setup vector on a free list. */
-
-#define SETUP_ON_FREE_LIST(v, nbytes, tmp) \
- do { \
- (tmp) = ((nbytes - header_size) / word_size); \
- XSETPVECTYPESIZE (v, PVEC_FREE, 0, (tmp)); \
- eassert ((nbytes) % roundup_size == 0); \
- (tmp) = VINDEX (nbytes); \
- eassert ((tmp) < VECTOR_MAX_FREE_LIST_INDEX); \
- set_next_vector (v, vector_free_lists[tmp]); \
- vector_free_lists[tmp] = (v); \
- total_free_vector_slots += (nbytes) / word_size; \
- } while (0)
-
-/* This internal type is used to maintain the list of large vectors
- which are allocated at their own, e.g. outside of vector blocks.
-
- struct large_vector itself cannot contain a struct Lisp_Vector, as
- the latter contains a flexible array member and C99 does not allow
- such structs to be nested. Instead, each struct large_vector
- object LV is followed by a struct Lisp_Vector, which is at offset
- large_vector_offset from LV, and whose address is therefore
- large_vector_vec (&LV). */
-
-struct large_vector
-{
- struct large_vector *next;
-};
-
-enum
-{
- large_vector_offset = ROUNDUP (sizeof (struct large_vector), vector_alignment)
-};
-
-static struct Lisp_Vector *
-large_vector_vec (struct large_vector *p)
-{
- return (struct Lisp_Vector *) ((char *) p + large_vector_offset);
-}
-
-/* This internal type is used to maintain an underlying storage
- for small vectors. */
-
-struct vector_block
-{
- char data[VECTOR_BLOCK_BYTES];
- struct vector_block *next;
-};
-
-/* Chain of vector blocks. */
-
-static struct vector_block *vector_blocks;
-
-/* Vector free lists, where NTH item points to a chain of free
- vectors of the same NBYTES size, so NTH == VINDEX (NBYTES). */
-
-static struct Lisp_Vector *vector_free_lists[VECTOR_MAX_FREE_LIST_INDEX];
-
-/* Singly-linked list of large vectors. */
-
-static struct large_vector *large_vectors;
-
-/* The only vector with 0 slots, allocated from pure space. */
-
-Lisp_Object zero_vector;
-
-/* Number of live vectors. */
-
-static EMACS_INT total_vectors;
-
-/* Total size of live and free vectors, in Lisp_Object units. */
-
-static EMACS_INT total_vector_slots, total_free_vector_slots;
-
-/* Get a new vector block. */
-
-static struct vector_block *
-allocate_vector_block (void)
-{
- struct vector_block *block = xmalloc (sizeof *block);
-
-#if GC_MARK_STACK && !defined GC_MALLOC_CHECK
- mem_insert (block->data, block->data + VECTOR_BLOCK_BYTES,
- MEM_TYPE_VECTOR_BLOCK);
-#endif
-
- block->next = vector_blocks;
- vector_blocks = block;
- return block;
-}
-
-/* Called once to initialize vector allocation. */
-
-static void
-init_vectors (void)
-{
- zero_vector = make_pure_vector (0);
-}
-
-/* Allocate vector from a vector block. */
-
-static struct Lisp_Vector *
-allocate_vector_from_block (size_t nbytes)
-{
- struct Lisp_Vector *vector;
- struct vector_block *block;
- size_t index, restbytes;
-
- eassert (VBLOCK_BYTES_MIN <= nbytes && nbytes <= VBLOCK_BYTES_MAX);
- eassert (nbytes % roundup_size == 0);
-
- /* First, try to allocate from a free list
- containing vectors of the requested size. */
- index = VINDEX (nbytes);
- if (vector_free_lists[index])
- {
- vector = vector_free_lists[index];
- vector_free_lists[index] = next_vector (vector);
- total_free_vector_slots -= nbytes / word_size;
- return vector;
- }
-
- /* Next, check free lists containing larger vectors. Since
- we will split the result, we should have remaining space
- large enough to use for one-slot vector at least. */
- for (index = VINDEX (nbytes + VBLOCK_BYTES_MIN);
- index < VECTOR_MAX_FREE_LIST_INDEX; index++)
- if (vector_free_lists[index])
- {
- /* This vector is larger than requested. */
- vector = vector_free_lists[index];
- vector_free_lists[index] = next_vector (vector);
- total_free_vector_slots -= nbytes / word_size;
-
- /* Excess bytes are used for the smaller vector,
- which should be set on an appropriate free list. */
- restbytes = index * roundup_size + VBLOCK_BYTES_MIN - nbytes;
- eassert (restbytes % roundup_size == 0);
- SETUP_ON_FREE_LIST (ADVANCE (vector, nbytes), restbytes, index);
- return vector;
- }
-
- /* Finally, need a new vector block. */
- block = allocate_vector_block ();
-
- /* New vector will be at the beginning of this block. */
- vector = (struct Lisp_Vector *) block->data;
-
- /* If the rest of space from this block is large enough
- for one-slot vector at least, set up it on a free list. */
- restbytes = VECTOR_BLOCK_BYTES - nbytes;
- if (restbytes >= VBLOCK_BYTES_MIN)
- {
- eassert (restbytes % roundup_size == 0);
- SETUP_ON_FREE_LIST (ADVANCE (vector, nbytes), restbytes, index);
- }
- return vector;
-}
-
-/* Nonzero if VECTOR pointer is valid pointer inside BLOCK. */
-
-#define VECTOR_IN_BLOCK(vector, block) \
- ((char *) (vector) <= (block)->data \
- + VECTOR_BLOCK_BYTES - VBLOCK_BYTES_MIN)
-
-/* Return the memory footprint of V in bytes. */
-
-static ptrdiff_t
-vector_nbytes (struct Lisp_Vector *v)
-{
- ptrdiff_t size = v->header.size & ~ARRAY_MARK_FLAG;
- ptrdiff_t nwords;
-
- if (size & PSEUDOVECTOR_FLAG)
- {
- if (PSEUDOVECTOR_TYPEP (&v->header, PVEC_BOOL_VECTOR))
- {
- struct Lisp_Bool_Vector *bv = (struct Lisp_Bool_Vector *) v;
- ptrdiff_t word_bytes = (bool_vector_words (bv->size)
- * sizeof (bits_word));
- ptrdiff_t boolvec_bytes = bool_header_size + word_bytes;
- verify (header_size <= bool_header_size);
- nwords = (boolvec_bytes - header_size + word_size - 1) / word_size;
- }
- else
- nwords = ((size & PSEUDOVECTOR_SIZE_MASK)
- + ((size & PSEUDOVECTOR_REST_MASK)
- >> PSEUDOVECTOR_SIZE_BITS));
- }
- else
- nwords = size;
- return vroundup (header_size + word_size * nwords);
-}
-
-/* Release extra resources still in use by VECTOR, which may be any
- vector-like object. For now, this is used just to free data in
- font objects. */
-
-static void
-cleanup_vector (struct Lisp_Vector *vector)
-{
- detect_suspicious_free (vector);
- if (PSEUDOVECTOR_TYPEP (&vector->header, PVEC_FONT)
- && ((vector->header.size & PSEUDOVECTOR_SIZE_MASK)
- == FONT_OBJECT_MAX))
- {
- /* Attempt to catch subtle bugs like Bug#16140. */
- eassert (valid_font_driver (((struct font *) vector)->driver));
- ((struct font *) vector)->driver->close ((struct font *) vector);
- }
-}
-
-/* Reclaim space used by unmarked vectors. */
-
-NO_INLINE /* For better stack traces */
-static void
-sweep_vectors (void)
-{
- struct vector_block *block, **bprev = &vector_blocks;
- struct large_vector *lv, **lvprev = &large_vectors;
- struct Lisp_Vector *vector, *next;
-
- total_vectors = total_vector_slots = total_free_vector_slots = 0;
- memset (vector_free_lists, 0, sizeof (vector_free_lists));
-
- /* Looking through vector blocks. */
-
- for (block = vector_blocks; block; block = *bprev)
- {
- bool free_this_block = 0;
- ptrdiff_t nbytes;
-
- for (vector = (struct Lisp_Vector *) block->data;
- VECTOR_IN_BLOCK (vector, block); vector = next)
- {
- if (VECTOR_MARKED_P (vector))
- {
- VECTOR_UNMARK (vector);
- total_vectors++;
- nbytes = vector_nbytes (vector);
- total_vector_slots += nbytes / word_size;
- next = ADVANCE (vector, nbytes);
- }
- else
- {
- ptrdiff_t total_bytes;
-
- cleanup_vector (vector);
- nbytes = vector_nbytes (vector);
- total_bytes = nbytes;
- next = ADVANCE (vector, nbytes);
-
- /* While NEXT is not marked, try to coalesce with VECTOR,
- thus making VECTOR of the largest possible size. */
-
- while (VECTOR_IN_BLOCK (next, block))
- {
- if (VECTOR_MARKED_P (next))
- break;
- cleanup_vector (next);
- nbytes = vector_nbytes (next);
- total_bytes += nbytes;
- next = ADVANCE (next, nbytes);
- }
-
- eassert (total_bytes % roundup_size == 0);
-
- if (vector == (struct Lisp_Vector *) block->data
- && !VECTOR_IN_BLOCK (next, block))
- /* This block should be freed because all of its
- space was coalesced into the only free vector. */
- free_this_block = 1;
- else
- {
- size_t tmp;
- SETUP_ON_FREE_LIST (vector, total_bytes, tmp);
- }
- }
- }
-
- if (free_this_block)
- {
- *bprev = block->next;
-#if GC_MARK_STACK && !defined GC_MALLOC_CHECK
- mem_delete (mem_find (block->data));
-#endif
- xfree (block);
- }
- else
- bprev = &block->next;
- }
-
- /* Sweep large vectors. */
-
- for (lv = large_vectors; lv; lv = *lvprev)
- {
- vector = large_vector_vec (lv);
- if (VECTOR_MARKED_P (vector))
- {
- VECTOR_UNMARK (vector);
- total_vectors++;
- if (vector->header.size & PSEUDOVECTOR_FLAG)
- {
- /* All non-bool pseudovectors are small enough to be allocated
- from vector blocks. This code should be redesigned if some
- pseudovector type grows beyond VBLOCK_BYTES_MAX. */
- eassert (PSEUDOVECTOR_TYPEP (&vector->header, PVEC_BOOL_VECTOR));
- total_vector_slots += vector_nbytes (vector) / word_size;
- }
- else
- total_vector_slots
- += header_size / word_size + vector->header.size;
- lvprev = &lv->next;
- }
- else
- {
- *lvprev = lv->next;
- lisp_free (lv);
- }
- }
-}
-
-/* Value is a pointer to a newly allocated Lisp_Vector structure
- with room for LEN Lisp_Objects. */
-
-static struct Lisp_Vector *
-allocate_vectorlike (ptrdiff_t len)
-{
- struct Lisp_Vector *p;
-
- MALLOC_BLOCK_INPUT;
-
- if (len == 0)
- p = XVECTOR (zero_vector);
- else
- {
- size_t nbytes = header_size + len * word_size;
-
-#ifdef DOUG_LEA_MALLOC
- if (!mmap_lisp_allowed_p ())
- mallopt (M_MMAP_MAX, 0);
-#endif
-
- if (nbytes <= VBLOCK_BYTES_MAX)
- p = allocate_vector_from_block (vroundup (nbytes));
- else
- {
- struct large_vector *lv
- = lisp_malloc ((large_vector_offset + header_size
- + len * word_size),
- MEM_TYPE_VECTORLIKE);
- lv->next = large_vectors;
- large_vectors = lv;
- p = large_vector_vec (lv);
- }
-
-#ifdef DOUG_LEA_MALLOC
- if (!mmap_lisp_allowed_p ())
- mallopt (M_MMAP_MAX, MMAP_MAX_AREAS);
-#endif
-
- if (find_suspicious_object_in_range (p, (char *) p + nbytes))
- emacs_abort ();
-
- consing_since_gc += nbytes;
- vector_cells_consed += len;
- }
-
- MALLOC_UNBLOCK_INPUT;
-
- return p;
-}
-
-
-/* Allocate a vector with LEN slots. */
-
-struct Lisp_Vector *
-allocate_vector (EMACS_INT len)
-{
- struct Lisp_Vector *v;
- ptrdiff_t nbytes_max = min (PTRDIFF_MAX, SIZE_MAX);
-
- if (min ((nbytes_max - header_size) / word_size, MOST_POSITIVE_FIXNUM) < len)
- memory_full (SIZE_MAX);
- v = allocate_vectorlike (len);
- v->header.size = len;
- return v;
-}
-
-
-/* Allocate other vector-like structures. */
-
-struct Lisp_Vector *
-allocate_pseudovector (int memlen, int lisplen, enum pvec_type tag)
-{
- struct Lisp_Vector *v = allocate_vectorlike (memlen);
- int i;
-
- /* Catch bogus values. */
- eassert (tag <= PVEC_FONT);
- eassert (memlen - lisplen <= (1 << PSEUDOVECTOR_REST_BITS) - 1);
- eassert (lisplen <= (1 << PSEUDOVECTOR_SIZE_BITS) - 1);
-
- /* Only the first lisplen slots will be traced normally by the GC. */
- for (i = 0; i < lisplen; ++i)
- v->contents[i] = Qnil;
-
- XSETPVECTYPESIZE (v, tag, lisplen, memlen - lisplen);
- return v;
-}
-
-struct buffer *
-allocate_buffer (void)
-{
- struct buffer *b = lisp_malloc (sizeof *b, MEM_TYPE_BUFFER);
-
- BUFFER_PVEC_INIT (b);
- /* Put B on the chain of all buffers including killed ones. */
- b->next = all_buffers;
- all_buffers = b;
- /* Note that the rest fields of B are not initialized. */
- return b;
-}
-
-struct Lisp_Hash_Table *
-allocate_hash_table (void)
-{
- return ALLOCATE_PSEUDOVECTOR (struct Lisp_Hash_Table, count, PVEC_HASH_TABLE);
-}
-
-struct window *
-allocate_window (void)
-{
- struct window *w;
-
- w = ALLOCATE_PSEUDOVECTOR (struct window, current_matrix, PVEC_WINDOW);
- /* Users assumes that non-Lisp data is zeroed. */
- memset (&w->current_matrix, 0,
- sizeof (*w) - offsetof (struct window, current_matrix));
- return w;
-}
-
-struct terminal *
-allocate_terminal (void)
-{
- struct terminal *t;
-
- t = ALLOCATE_PSEUDOVECTOR (struct terminal, next_terminal, PVEC_TERMINAL);
- /* Users assumes that non-Lisp data is zeroed. */
- memset (&t->next_terminal, 0,
- sizeof (*t) - offsetof (struct terminal, next_terminal));
- return t;
-}
-
-struct frame *
-allocate_frame (void)
-{
- struct frame *f;
-
- f = ALLOCATE_PSEUDOVECTOR (struct frame, face_cache, PVEC_FRAME);
- /* Users assumes that non-Lisp data is zeroed. */
- memset (&f->face_cache, 0,
- sizeof (*f) - offsetof (struct frame, face_cache));
- return f;
-}
-
-struct Lisp_Process *
-allocate_process (void)
-{
- struct Lisp_Process *p;
-
- p = ALLOCATE_PSEUDOVECTOR (struct Lisp_Process, pid, PVEC_PROCESS);
- /* Users assumes that non-Lisp data is zeroed. */
- memset (&p->pid, 0,
- sizeof (*p) - offsetof (struct Lisp_Process, pid));
- return p;
-}
-
-DEFUN ("make-vector", Fmake_vector, Smake_vector, 2, 2, 0,
- doc: /* Return a newly created vector of length LENGTH, with each element being INIT.
-See also the function `vector'. */)
- (register Lisp_Object length, Lisp_Object init)
-{
- Lisp_Object vector;
- register ptrdiff_t sizei;
- register ptrdiff_t i;
- register struct Lisp_Vector *p;
-
- CHECK_NATNUM (length);
-
- p = allocate_vector (XFASTINT (length));
- sizei = XFASTINT (length);
- for (i = 0; i < sizei; i++)
- p->contents[i] = init;
-
- XSETVECTOR (vector, p);
- return vector;
-}
-
-
-DEFUN ("vector", Fvector, Svector, 0, MANY, 0,
- doc: /* Return a newly created vector with specified arguments as elements.
-Any number of arguments, even zero arguments, are allowed.
-usage: (vector &rest OBJECTS) */)
- (ptrdiff_t nargs, Lisp_Object *args)
-{
- ptrdiff_t i;
- register Lisp_Object val = make_uninit_vector (nargs);
- register struct Lisp_Vector *p = XVECTOR (val);
-
- for (i = 0; i < nargs; i++)
- p->contents[i] = args[i];
- return val;
-}
-
-void
-make_byte_code (struct Lisp_Vector *v)
-{
- /* Don't allow the global zero_vector to become a byte code object. */
- eassert (0 < v->header.size);
-
- if (v->header.size > 1 && STRINGP (v->contents[1])
- && STRING_MULTIBYTE (v->contents[1]))
- /* BYTECODE-STRING must have been produced by Emacs 20.2 or the
- earlier because they produced a raw 8-bit string for byte-code
- and now such a byte-code string is loaded as multibyte while
- raw 8-bit characters converted to multibyte form. Thus, now we
- must convert them back to the original unibyte form. */
- v->contents[1] = Fstring_as_unibyte (v->contents[1]);
- XSETPVECTYPE (v, PVEC_COMPILED);
-}
-
-DEFUN ("make-byte-code", Fmake_byte_code, Smake_byte_code, 4, MANY, 0,
- doc: /* Create a byte-code object with specified arguments as elements.
-The arguments should be the ARGLIST, bytecode-string BYTE-CODE, constant
-vector CONSTANTS, maximum stack size DEPTH, (optional) DOCSTRING,
-and (optional) INTERACTIVE-SPEC.
-The first four arguments are required; at most six have any
-significance.
-The ARGLIST can be either like the one of `lambda', in which case the arguments
-will be dynamically bound before executing the byte code, or it can be an
-integer of the form NNNNNNNRMMMMMMM where the 7bit MMMMMMM specifies the
-minimum number of arguments, the 7-bit NNNNNNN specifies the maximum number
-of arguments (ignoring &rest) and the R bit specifies whether there is a &rest
-argument to catch the left-over arguments. If such an integer is used, the
-arguments will not be dynamically bound but will be instead pushed on the
-stack before executing the byte-code.
-usage: (make-byte-code ARGLIST BYTE-CODE CONSTANTS DEPTH &optional DOCSTRING INTERACTIVE-SPEC &rest ELEMENTS) */)
- (ptrdiff_t nargs, Lisp_Object *args)
-{
- ptrdiff_t i;
- register Lisp_Object val = make_uninit_vector (nargs);
- register struct Lisp_Vector *p = XVECTOR (val);
-
- /* We used to purecopy everything here, if purify-flag was set. This worked
- OK for Emacs-23, but with Emacs-24's lexical binding code, it can be
- dangerous, since make-byte-code is used during execution to build
- closures, so any closure built during the preload phase would end up
- copied into pure space, including its free variables, which is sometimes
- just wasteful and other times plainly wrong (e.g. those free vars may want
- to be setcar'd). */
-
- for (i = 0; i < nargs; i++)
- p->contents[i] = args[i];
- make_byte_code (p);
- XSETCOMPILED (val, p);
- return val;
-}
-
-
-\f
-/***********************************************************************
- Symbol Allocation
- ***********************************************************************/
-
-/* Like struct Lisp_Symbol, but padded so that the size is a multiple
- of the required alignment if LSB tags are used. */
-
-union aligned_Lisp_Symbol
-{
- struct Lisp_Symbol s;
-#if USE_LSB_TAG
- unsigned char c[(sizeof (struct Lisp_Symbol) + GCALIGNMENT - 1)
- & -GCALIGNMENT];
-#endif
-};
-
-/* Each symbol_block is just under 1020 bytes long, since malloc
- really allocates in units of powers of two and uses 4 bytes for its
- own overhead. */
-
-#define SYMBOL_BLOCK_SIZE \
- ((1020 - sizeof (struct symbol_block *)) / sizeof (union aligned_Lisp_Symbol))
-
-struct symbol_block
-{
- /* Place `symbols' first, to preserve alignment. */
- union aligned_Lisp_Symbol symbols[SYMBOL_BLOCK_SIZE];
- struct symbol_block *next;
-};
-
-/* Current symbol block and index of first unused Lisp_Symbol
- structure in it. */
-
-static struct symbol_block *symbol_block;
-static int symbol_block_index = SYMBOL_BLOCK_SIZE;
-
-/* List of free symbols. */
-
-static struct Lisp_Symbol *symbol_free_list;
-
-static void
-set_symbol_name (Lisp_Object sym, Lisp_Object name)
-{
- XSYMBOL (sym)->name = name;
-}
-
-DEFUN ("make-symbol", Fmake_symbol, Smake_symbol, 1, 1, 0,
- doc: /* Return a newly allocated uninterned symbol whose name is NAME.
-Its value is void, and its function definition and property list are nil. */)
- (Lisp_Object name)
-{
- register Lisp_Object val;
- register struct Lisp_Symbol *p;
-
- CHECK_STRING (name);
-
- MALLOC_BLOCK_INPUT;
-
- if (symbol_free_list)
- {
- XSETSYMBOL (val, symbol_free_list);
- symbol_free_list = symbol_free_list->next;
- }
- else
- {
- if (symbol_block_index == SYMBOL_BLOCK_SIZE)
- {
- struct symbol_block *new
- = lisp_malloc (sizeof *new, MEM_TYPE_SYMBOL);
- new->next = symbol_block;
- symbol_block = new;
- symbol_block_index = 0;
- total_free_symbols += SYMBOL_BLOCK_SIZE;
- }
- XSETSYMBOL (val, &symbol_block->symbols[symbol_block_index].s);
- symbol_block_index++;
- }
-
- MALLOC_UNBLOCK_INPUT;
-
- p = XSYMBOL (val);
- set_symbol_name (val, name);
- set_symbol_plist (val, Qnil);
- p->redirect = SYMBOL_PLAINVAL;
- SET_SYMBOL_VAL (p, Qunbound);
- set_symbol_function (val, Qnil);
- set_symbol_next (val, NULL);
- p->gcmarkbit = 0;
- p->interned = SYMBOL_UNINTERNED;
- p->constant = 0;
- p->declared_special = 0;
- consing_since_gc += sizeof (struct Lisp_Symbol);
- symbols_consed++;
- total_free_symbols--;
- return val;
-}
-
-
-\f
-/***********************************************************************
- Marker (Misc) Allocation
- ***********************************************************************/
-
-/* Like union Lisp_Misc, but padded so that its size is a multiple of
- the required alignment when LSB tags are used. */
-
-union aligned_Lisp_Misc
-{
- union Lisp_Misc m;
-#if USE_LSB_TAG
- unsigned char c[(sizeof (union Lisp_Misc) + GCALIGNMENT - 1)
- & -GCALIGNMENT];
-#endif
-};
-
-/* Allocation of markers and other objects that share that structure.
- Works like allocation of conses. */
-
-#define MARKER_BLOCK_SIZE \
- ((1020 - sizeof (struct marker_block *)) / sizeof (union aligned_Lisp_Misc))
-
-struct marker_block
-{
- /* Place `markers' first, to preserve alignment. */
- union aligned_Lisp_Misc markers[MARKER_BLOCK_SIZE];
- struct marker_block *next;
-};
-
-static struct marker_block *marker_block;
-static int marker_block_index = MARKER_BLOCK_SIZE;
-
-static union Lisp_Misc *marker_free_list;
-
-/* Return a newly allocated Lisp_Misc object of specified TYPE. */
-
-static Lisp_Object
-allocate_misc (enum Lisp_Misc_Type type)
-{
- Lisp_Object val;
-
- MALLOC_BLOCK_INPUT;
-
- if (marker_free_list)
- {
- XSETMISC (val, marker_free_list);
- marker_free_list = marker_free_list->u_free.chain;
- }
- else
- {
- if (marker_block_index == MARKER_BLOCK_SIZE)
- {
- struct marker_block *new = lisp_malloc (sizeof *new, MEM_TYPE_MISC);
- new->next = marker_block;
- marker_block = new;
- marker_block_index = 0;
- total_free_markers += MARKER_BLOCK_SIZE;
- }
- XSETMISC (val, &marker_block->markers[marker_block_index].m);
- marker_block_index++;
- }
-
- MALLOC_UNBLOCK_INPUT;
-
- --total_free_markers;
- consing_since_gc += sizeof (union Lisp_Misc);
- misc_objects_consed++;
- XMISCANY (val)->type = type;
- XMISCANY (val)->gcmarkbit = 0;
- return val;
-}
-
-/* Free a Lisp_Misc object. */
-
-void
-free_misc (Lisp_Object misc)
-{
- XMISCANY (misc)->type = Lisp_Misc_Free;
- XMISC (misc)->u_free.chain = marker_free_list;
- marker_free_list = XMISC (misc);
- consing_since_gc -= sizeof (union Lisp_Misc);
- total_free_markers++;
-}
-
-/* Verify properties of Lisp_Save_Value's representation
- that are assumed here and elsewhere. */
-
-verify (SAVE_UNUSED == 0);
-verify (((SAVE_INTEGER | SAVE_POINTER | SAVE_FUNCPOINTER | SAVE_OBJECT)
- >> SAVE_SLOT_BITS)
- == 0);
-
-/* Return Lisp_Save_Value objects for the various combinations
- that callers need. */
-
-Lisp_Object
-make_save_int_int_int (ptrdiff_t a, ptrdiff_t b, ptrdiff_t c)
-{
- Lisp_Object val = allocate_misc (Lisp_Misc_Save_Value);
- struct Lisp_Save_Value *p = XSAVE_VALUE (val);
- p->save_type = SAVE_TYPE_INT_INT_INT;
- p->data[0].integer = a;
- p->data[1].integer = b;
- p->data[2].integer = c;
- return val;
-}
-
-Lisp_Object
-make_save_obj_obj_obj_obj (Lisp_Object a, Lisp_Object b, Lisp_Object c,
- Lisp_Object d)
-{
- Lisp_Object val = allocate_misc (Lisp_Misc_Save_Value);
- struct Lisp_Save_Value *p = XSAVE_VALUE (val);
- p->save_type = SAVE_TYPE_OBJ_OBJ_OBJ_OBJ;
- p->data[0].object = a;
- p->data[1].object = b;
- p->data[2].object = c;
- p->data[3].object = d;
- return val;
-}
-
-Lisp_Object
-make_save_ptr (void *a)
-{
- Lisp_Object val = allocate_misc (Lisp_Misc_Save_Value);
- struct Lisp_Save_Value *p = XSAVE_VALUE (val);
- p->save_type = SAVE_POINTER;
- p->data[0].pointer = a;
- return val;
-}
-
-Lisp_Object
-make_save_ptr_int (void *a, ptrdiff_t b)
-{
- Lisp_Object val = allocate_misc (Lisp_Misc_Save_Value);
- struct Lisp_Save_Value *p = XSAVE_VALUE (val);
- p->save_type = SAVE_TYPE_PTR_INT;
- p->data[0].pointer = a;
- p->data[1].integer = b;
- return val;
-}
-
-#if ! (defined USE_X_TOOLKIT || defined USE_GTK)
-Lisp_Object
-make_save_ptr_ptr (void *a, void *b)
-{
- Lisp_Object val = allocate_misc (Lisp_Misc_Save_Value);
- struct Lisp_Save_Value *p = XSAVE_VALUE (val);
- p->save_type = SAVE_TYPE_PTR_PTR;
- p->data[0].pointer = a;
- p->data[1].pointer = b;
- return val;
-}
-#endif
-
-Lisp_Object
-make_save_funcptr_ptr_obj (void (*a) (void), void *b, Lisp_Object c)
-{
- Lisp_Object val = allocate_misc (Lisp_Misc_Save_Value);
- struct Lisp_Save_Value *p = XSAVE_VALUE (val);
- p->save_type = SAVE_TYPE_FUNCPTR_PTR_OBJ;
- p->data[0].funcpointer = a;
- p->data[1].pointer = b;
- p->data[2].object = c;
- return val;
-}
-
-/* Return a Lisp_Save_Value object that represents an array A
- of N Lisp objects. */
-
-Lisp_Object
-make_save_memory (Lisp_Object *a, ptrdiff_t n)
-{
- Lisp_Object val = allocate_misc (Lisp_Misc_Save_Value);
- struct Lisp_Save_Value *p = XSAVE_VALUE (val);
- p->save_type = SAVE_TYPE_MEMORY;
- p->data[0].pointer = a;
- p->data[1].integer = n;
- return val;
-}
-
-/* Free a Lisp_Save_Value object. Do not use this function
- if SAVE contains pointer other than returned by xmalloc. */
-
-void
-free_save_value (Lisp_Object save)
-{
- xfree (XSAVE_POINTER (save, 0));
- free_misc (save);
-}
-
-/* Return a Lisp_Misc_Overlay object with specified START, END and PLIST. */
-
-Lisp_Object
-build_overlay (Lisp_Object start, Lisp_Object end, Lisp_Object plist)
-{
- register Lisp_Object overlay;
-
- overlay = allocate_misc (Lisp_Misc_Overlay);
- OVERLAY_START (overlay) = start;
- OVERLAY_END (overlay) = end;
- set_overlay_plist (overlay, plist);
- XOVERLAY (overlay)->next = NULL;
- return overlay;
-}
-
-DEFUN ("make-marker", Fmake_marker, Smake_marker, 0, 0, 0,
- doc: /* Return a newly allocated marker which does not point at any place. */)
- (void)
-{
- register Lisp_Object val;
- register struct Lisp_Marker *p;
-
- val = allocate_misc (Lisp_Misc_Marker);
- p = XMARKER (val);
- p->buffer = 0;
- p->bytepos = 0;
- p->charpos = 0;
- p->next = NULL;
- p->insertion_type = 0;
- p->need_adjustment = 0;
- return val;
-}
-
-/* Return a newly allocated marker which points into BUF
- at character position CHARPOS and byte position BYTEPOS. */
-
-Lisp_Object
-build_marker (struct buffer *buf, ptrdiff_t charpos, ptrdiff_t bytepos)
-{
- Lisp_Object obj;
- struct Lisp_Marker *m;
-
- /* No dead buffers here. */
- eassert (BUFFER_LIVE_P (buf));
-
- /* Every character is at least one byte. */
- eassert (charpos <= bytepos);
-
- obj = allocate_misc (Lisp_Misc_Marker);
- m = XMARKER (obj);
- m->buffer = buf;
- m->charpos = charpos;
- m->bytepos = bytepos;
- m->insertion_type = 0;
- m->need_adjustment = 0;
- m->next = BUF_MARKERS (buf);
- BUF_MARKERS (buf) = m;
- return obj;
-}
-
-/* Put MARKER back on the free list after using it temporarily. */
-
-void
-free_marker (Lisp_Object marker)
-{
- unchain_marker (XMARKER (marker));
- free_misc (marker);
-}
-
-\f
-/* Return a newly created vector or string with specified arguments as
- elements. If all the arguments are characters that can fit
- in a string of events, make a string; otherwise, make a vector.
-
- Any number of arguments, even zero arguments, are allowed. */
-
-Lisp_Object
-make_event_array (ptrdiff_t nargs, Lisp_Object *args)
-{
- ptrdiff_t i;
-
- for (i = 0; i < nargs; i++)
- /* The things that fit in a string
- are characters that are in 0...127,
- after discarding the meta bit and all the bits above it. */
- if (!INTEGERP (args[i])
- || (XINT (args[i]) & ~(-CHAR_META)) >= 0200)
- return Fvector (nargs, args);
-
- /* Since the loop exited, we know that all the things in it are
- characters, so we can make a string. */
- {
- Lisp_Object result;
-
- result = Fmake_string (make_number (nargs), make_number (0));
- for (i = 0; i < nargs; i++)
- {
- SSET (result, i, XINT (args[i]));
- /* Move the meta bit to the right place for a string char. */
- if (XINT (args[i]) & CHAR_META)
- SSET (result, i, SREF (result, i) | 0x80);
- }
-
- return result;
- }
-}
-
-
-\f
-/************************************************************************
- Memory Full Handling
- ************************************************************************/
-
-
-/* Called if malloc (NBYTES) returns zero. If NBYTES == SIZE_MAX,
- there may have been size_t overflow so that malloc was never
- called, or perhaps malloc was invoked successfully but the
- resulting pointer had problems fitting into a tagged EMACS_INT. In
- either case this counts as memory being full even though malloc did
- not fail. */
-
-void
-memory_full (size_t nbytes)
-{
- /* Do not go into hysterics merely because a large request failed. */
- bool enough_free_memory = 0;
- if (SPARE_MEMORY < nbytes)
- {
- void *p;
-
- MALLOC_BLOCK_INPUT;
- p = malloc (SPARE_MEMORY);
- if (p)
- {
- free (p);
- enough_free_memory = 1;
- }
- MALLOC_UNBLOCK_INPUT;
- }
-
- if (! enough_free_memory)
- {
- int i;
-
- Vmemory_full = Qt;
-
- memory_full_cons_threshold = sizeof (struct cons_block);
-
- /* The first time we get here, free the spare memory. */
- for (i = 0; i < ARRAYELTS (spare_memory); i++)
- if (spare_memory[i])
- {
- if (i == 0)
- free (spare_memory[i]);
- else if (i >= 1 && i <= 4)
- lisp_align_free (spare_memory[i]);
- else
- lisp_free (spare_memory[i]);
- spare_memory[i] = 0;
- }
- }
-
- /* This used to call error, but if we've run out of memory, we could
- get infinite recursion trying to build the string. */
- xsignal (Qnil, Vmemory_signal_data);
-}
-
-/* If we released our reserve (due to running out of memory),
- and we have a fair amount free once again,
- try to set aside another reserve in case we run out once more.
-
- This is called when a relocatable block is freed in ralloc.c,
- and also directly from this file, in case we're not using ralloc.c. */
-
-void
-refill_memory_reserve (void)
-{
-#ifndef SYSTEM_MALLOC
- if (spare_memory[0] == 0)
- spare_memory[0] = malloc (SPARE_MEMORY);
- if (spare_memory[1] == 0)
- spare_memory[1] = lisp_align_malloc (sizeof (struct cons_block),
- MEM_TYPE_SPARE);
- if (spare_memory[2] == 0)
- spare_memory[2] = lisp_align_malloc (sizeof (struct cons_block),
- MEM_TYPE_SPARE);
- if (spare_memory[3] == 0)
- spare_memory[3] = lisp_align_malloc (sizeof (struct cons_block),
- MEM_TYPE_SPARE);
- if (spare_memory[4] == 0)
- spare_memory[4] = lisp_align_malloc (sizeof (struct cons_block),
- MEM_TYPE_SPARE);
- if (spare_memory[5] == 0)
- spare_memory[5] = lisp_malloc (sizeof (struct string_block),
- MEM_TYPE_SPARE);
- if (spare_memory[6] == 0)
- spare_memory[6] = lisp_malloc (sizeof (struct string_block),
- MEM_TYPE_SPARE);
- if (spare_memory[0] && spare_memory[1] && spare_memory[5])
- Vmemory_full = Qnil;
-#endif
-}
-\f
-/************************************************************************
- C Stack Marking
- ************************************************************************/
-
-#if GC_MARK_STACK || defined GC_MALLOC_CHECK
-
-/* Conservative C stack marking requires a method to identify possibly
- live Lisp objects given a pointer value. We do this by keeping
- track of blocks of Lisp data that are allocated in a red-black tree
- (see also the comment of mem_node which is the type of nodes in
- that tree). Function lisp_malloc adds information for an allocated
- block to the red-black tree with calls to mem_insert, and function
- lisp_free removes it with mem_delete. Functions live_string_p etc
- call mem_find to lookup information about a given pointer in the
- tree, and use that to determine if the pointer points to a Lisp
- object or not. */
-
-/* Initialize this part of alloc.c. */
-
-static void
-mem_init (void)
-{
- mem_z.left = mem_z.right = MEM_NIL;
- mem_z.parent = NULL;
- mem_z.color = MEM_BLACK;
- mem_z.start = mem_z.end = NULL;
- mem_root = MEM_NIL;
-}
-
-
-/* Value is a pointer to the mem_node containing START. Value is
- MEM_NIL if there is no node in the tree containing START. */
-
-static struct mem_node *
-mem_find (void *start)
-{
- struct mem_node *p;
-
- if (start < min_heap_address || start > max_heap_address)
- return MEM_NIL;
-
- /* Make the search always successful to speed up the loop below. */
- mem_z.start = start;
- mem_z.end = (char *) start + 1;
-
- p = mem_root;
- while (start < p->start || start >= p->end)
- p = start < p->start ? p->left : p->right;
- return p;
-}
-
-
-/* Insert a new node into the tree for a block of memory with start
- address START, end address END, and type TYPE. Value is a
- pointer to the node that was inserted. */
-
-static struct mem_node *
-mem_insert (void *start, void *end, enum mem_type type)
-{
- struct mem_node *c, *parent, *x;
-
- if (min_heap_address == NULL || start < min_heap_address)
- min_heap_address = start;
- if (max_heap_address == NULL || end > max_heap_address)
- max_heap_address = end;
-
- /* See where in the tree a node for START belongs. In this
- particular application, it shouldn't happen that a node is already
- present. For debugging purposes, let's check that. */
- c = mem_root;
- parent = NULL;
-
-#if GC_MARK_STACK != GC_MAKE_GCPROS_NOOPS
-
- while (c != MEM_NIL)
- {
- if (start >= c->start && start < c->end)
- emacs_abort ();
- parent = c;
- c = start < c->start ? c->left : c->right;
- }
-
-#else /* GC_MARK_STACK == GC_MARK_STACK_CHECK_GCPROS */
-
- while (c != MEM_NIL)
- {
- parent = c;
- c = start < c->start ? c->left : c->right;
- }
-
-#endif /* GC_MARK_STACK == GC_MARK_STACK_CHECK_GCPROS */
-
- /* Create a new node. */
-#ifdef GC_MALLOC_CHECK
- x = malloc (sizeof *x);
- if (x == NULL)
- emacs_abort ();
-#else
- x = xmalloc (sizeof *x);
-#endif
- x->start = start;
- x->end = end;
- x->type = type;
- x->parent = parent;
- x->left = x->right = MEM_NIL;
- x->color = MEM_RED;
-
- /* Insert it as child of PARENT or install it as root. */
- if (parent)
- {
- if (start < parent->start)
- parent->left = x;
- else
- parent->right = x;
- }
- else
- mem_root = x;
-
- /* Re-establish red-black tree properties. */
- mem_insert_fixup (x);
-
- return x;
-}
-
-
-/* Re-establish the red-black properties of the tree, and thereby
- balance the tree, after node X has been inserted; X is always red. */
-
-static void
-mem_insert_fixup (struct mem_node *x)
-{
- while (x != mem_root && x->parent->color == MEM_RED)
- {
- /* X is red and its parent is red. This is a violation of
- red-black tree property #3. */
-
- if (x->parent == x->parent->parent->left)
- {
- /* We're on the left side of our grandparent, and Y is our
- "uncle". */
- struct mem_node *y = x->parent->parent->right;
-
- if (y->color == MEM_RED)
- {
- /* Uncle and parent are red but should be black because
- X is red. Change the colors accordingly and proceed
- with the grandparent. */
- x->parent->color = MEM_BLACK;
- y->color = MEM_BLACK;
- x->parent->parent->color = MEM_RED;
- x = x->parent->parent;
- }
- else
- {
- /* Parent and uncle have different colors; parent is
- red, uncle is black. */
- if (x == x->parent->right)
- {
- x = x->parent;
- mem_rotate_left (x);
- }
-
- x->parent->color = MEM_BLACK;
- x->parent->parent->color = MEM_RED;
- mem_rotate_right (x->parent->parent);
- }
- }
- else
- {
- /* This is the symmetrical case of above. */
- struct mem_node *y = x->parent->parent->left;
-
- if (y->color == MEM_RED)
- {
- x->parent->color = MEM_BLACK;
- y->color = MEM_BLACK;
- x->parent->parent->color = MEM_RED;
- x = x->parent->parent;
- }
- else
- {
- if (x == x->parent->left)
- {
- x = x->parent;
- mem_rotate_right (x);
- }
-
- x->parent->color = MEM_BLACK;
- x->parent->parent->color = MEM_RED;
- mem_rotate_left (x->parent->parent);
- }
- }
- }
-
- /* The root may have been changed to red due to the algorithm. Set
- it to black so that property #5 is satisfied. */
- mem_root->color = MEM_BLACK;
-}
-
-
-/* (x) (y)
- / \ / \
- a (y) ===> (x) c
- / \ / \
- b c a b */
-
-static void
-mem_rotate_left (struct mem_node *x)
-{
- struct mem_node *y;
-
- /* Turn y's left sub-tree into x's right sub-tree. */
- y = x->right;
- x->right = y->left;
- if (y->left != MEM_NIL)
- y->left->parent = x;
-
- /* Y's parent was x's parent. */
- if (y != MEM_NIL)
- y->parent = x->parent;
-
- /* Get the parent to point to y instead of x. */
- if (x->parent)
- {
- if (x == x->parent->left)
- x->parent->left = y;
- else
- x->parent->right = y;
- }
- else
- mem_root = y;
-
- /* Put x on y's left. */
- y->left = x;
- if (x != MEM_NIL)
- x->parent = y;
-}
-
-
-/* (x) (Y)
- / \ / \
- (y) c ===> a (x)
- / \ / \
- a b b c */
-
-static void
-mem_rotate_right (struct mem_node *x)
-{
- struct mem_node *y = x->left;
-
- x->left = y->right;
- if (y->right != MEM_NIL)
- y->right->parent = x;
-
- if (y != MEM_NIL)
- y->parent = x->parent;
- if (x->parent)
- {
- if (x == x->parent->right)
- x->parent->right = y;
- else
- x->parent->left = y;
- }
- else
- mem_root = y;
-
- y->right = x;
- if (x != MEM_NIL)
- x->parent = y;
-}
-
-
-/* Delete node Z from the tree. If Z is null or MEM_NIL, do nothing. */
-
-static void
-mem_delete (struct mem_node *z)
-{
- struct mem_node *x, *y;
-
- if (!z || z == MEM_NIL)
- return;
-
- if (z->left == MEM_NIL || z->right == MEM_NIL)
- y = z;
- else
- {
- y = z->right;
- while (y->left != MEM_NIL)
- y = y->left;
- }
-
- if (y->left != MEM_NIL)
- x = y->left;
- else
- x = y->right;
-
- x->parent = y->parent;
- if (y->parent)
- {
- if (y == y->parent->left)
- y->parent->left = x;
- else
- y->parent->right = x;
- }
- else
- mem_root = x;
-
- if (y != z)
- {
- z->start = y->start;
- z->end = y->end;
- z->type = y->type;
- }
-
- if (y->color == MEM_BLACK)
- mem_delete_fixup (x);
-
-#ifdef GC_MALLOC_CHECK
- free (y);
-#else
- xfree (y);
-#endif
-}
-
-
-/* Re-establish the red-black properties of the tree, after a
- deletion. */
-
-static void
-mem_delete_fixup (struct mem_node *x)
-{
- while (x != mem_root && x->color == MEM_BLACK)
- {
- if (x == x->parent->left)
- {
- struct mem_node *w = x->parent->right;
-
- if (w->color == MEM_RED)
- {
- w->color = MEM_BLACK;
- x->parent->color = MEM_RED;
- mem_rotate_left (x->parent);
- w = x->parent->right;
- }
-
- if (w->left->color == MEM_BLACK && w->right->color == MEM_BLACK)
- {
- w->color = MEM_RED;
- x = x->parent;
- }
- else
- {
- if (w->right->color == MEM_BLACK)
- {
- w->left->color = MEM_BLACK;
- w->color = MEM_RED;
- mem_rotate_right (w);
- w = x->parent->right;
- }
- w->color = x->parent->color;
- x->parent->color = MEM_BLACK;
- w->right->color = MEM_BLACK;
- mem_rotate_left (x->parent);
- x = mem_root;
- }
- }
- else
- {
- struct mem_node *w = x->parent->left;
-
- if (w->color == MEM_RED)
- {
- w->color = MEM_BLACK;
- x->parent->color = MEM_RED;
- mem_rotate_right (x->parent);
- w = x->parent->left;
- }
-
- if (w->right->color == MEM_BLACK && w->left->color == MEM_BLACK)
- {
- w->color = MEM_RED;
- x = x->parent;
- }
- else
- {
- if (w->left->color == MEM_BLACK)
- {
- w->right->color = MEM_BLACK;
- w->color = MEM_RED;
- mem_rotate_left (w);
- w = x->parent->left;
- }
-
- w->color = x->parent->color;
- x->parent->color = MEM_BLACK;
- w->left->color = MEM_BLACK;
- mem_rotate_right (x->parent);
- x = mem_root;
- }
- }
- }
-
- x->color = MEM_BLACK;
-}
-
-
-/* Value is non-zero if P is a pointer to a live Lisp string on
- the heap. M is a pointer to the mem_block for P. */
-
-static bool
-live_string_p (struct mem_node *m, void *p)
-{
- if (m->type == MEM_TYPE_STRING)
- {
- struct string_block *b = m->start;
- ptrdiff_t offset = (char *) p - (char *) &b->strings[0];
-
- /* P must point to the start of a Lisp_String structure, and it
- must not be on the free-list. */
- return (offset >= 0
- && offset % sizeof b->strings[0] == 0
- && offset < (STRING_BLOCK_SIZE * sizeof b->strings[0])
- && ((struct Lisp_String *) p)->data != NULL);
- }
- else
- return 0;
-}
-
-
-/* Value is non-zero if P is a pointer to a live Lisp cons on
- the heap. M is a pointer to the mem_block for P. */
-
-static bool
-live_cons_p (struct mem_node *m, void *p)
-{
- if (m->type == MEM_TYPE_CONS)
- {
- struct cons_block *b = m->start;
- ptrdiff_t offset = (char *) p - (char *) &b->conses[0];
-
- /* P must point to the start of a Lisp_Cons, not be
- one of the unused cells in the current cons block,
- and not be on the free-list. */
- return (offset >= 0
- && offset % sizeof b->conses[0] == 0
- && offset < (CONS_BLOCK_SIZE * sizeof b->conses[0])
- && (b != cons_block
- || offset / sizeof b->conses[0] < cons_block_index)
- && !EQ (((struct Lisp_Cons *) p)->car, Vdead));
- }
- else
- return 0;
-}
-
-
-/* Value is non-zero if P is a pointer to a live Lisp symbol on
- the heap. M is a pointer to the mem_block for P. */
-
-static bool
-live_symbol_p (struct mem_node *m, void *p)
-{
- if (m->type == MEM_TYPE_SYMBOL)
- {
- struct symbol_block *b = m->start;
- ptrdiff_t offset = (char *) p - (char *) &b->symbols[0];
-
- /* P must point to the start of a Lisp_Symbol, not be
- one of the unused cells in the current symbol block,
- and not be on the free-list. */
- return (offset >= 0
- && offset % sizeof b->symbols[0] == 0
- && offset < (SYMBOL_BLOCK_SIZE * sizeof b->symbols[0])
- && (b != symbol_block
- || offset / sizeof b->symbols[0] < symbol_block_index)
- && !EQ (((struct Lisp_Symbol *)p)->function, Vdead));
- }
- else
- return 0;
-}
-
-
-/* Value is non-zero if P is a pointer to a live Lisp float on
- the heap. M is a pointer to the mem_block for P. */
-
-static bool
-live_float_p (struct mem_node *m, void *p)
-{
- if (m->type == MEM_TYPE_FLOAT)
- {
- struct float_block *b = m->start;
- ptrdiff_t offset = (char *) p - (char *) &b->floats[0];
-
- /* P must point to the start of a Lisp_Float and not be
- one of the unused cells in the current float block. */
- return (offset >= 0
- && offset % sizeof b->floats[0] == 0
- && offset < (FLOAT_BLOCK_SIZE * sizeof b->floats[0])
- && (b != float_block
- || offset / sizeof b->floats[0] < float_block_index));
- }
- else
- return 0;
-}
-
-
-/* Value is non-zero if P is a pointer to a live Lisp Misc on
- the heap. M is a pointer to the mem_block for P. */
-
-static bool
-live_misc_p (struct mem_node *m, void *p)
-{
- if (m->type == MEM_TYPE_MISC)
- {
- struct marker_block *b = m->start;
- ptrdiff_t offset = (char *) p - (char *) &b->markers[0];
-
- /* P must point to the start of a Lisp_Misc, not be
- one of the unused cells in the current misc block,
- and not be on the free-list. */
- return (offset >= 0
- && offset % sizeof b->markers[0] == 0
- && offset < (MARKER_BLOCK_SIZE * sizeof b->markers[0])
- && (b != marker_block
- || offset / sizeof b->markers[0] < marker_block_index)
- && ((union Lisp_Misc *) p)->u_any.type != Lisp_Misc_Free);
- }
- else
- return 0;
-}
-
-
-/* Value is non-zero if P is a pointer to a live vector-like object.
- M is a pointer to the mem_block for P. */
-
-static bool
-live_vector_p (struct mem_node *m, void *p)
-{
- if (m->type == MEM_TYPE_VECTOR_BLOCK)
- {
- /* This memory node corresponds to a vector block. */
- struct vector_block *block = m->start;
- struct Lisp_Vector *vector = (struct Lisp_Vector *) block->data;
-
- /* P is in the block's allocation range. Scan the block
- up to P and see whether P points to the start of some
- vector which is not on a free list. FIXME: check whether
- some allocation patterns (probably a lot of short vectors)
- may cause a substantial overhead of this loop. */
- while (VECTOR_IN_BLOCK (vector, block)
- && vector <= (struct Lisp_Vector *) p)
- {
- if (!PSEUDOVECTOR_TYPEP (&vector->header, PVEC_FREE) && vector == p)
- return 1;
- else
- vector = ADVANCE (vector, vector_nbytes (vector));
- }
- }
- else if (m->type == MEM_TYPE_VECTORLIKE && p == large_vector_vec (m->start))
- /* This memory node corresponds to a large vector. */
- return 1;
- return 0;
-}
-
-
-/* Value is non-zero if P is a pointer to a live buffer. M is a
- pointer to the mem_block for P. */
-
-static bool
-live_buffer_p (struct mem_node *m, void *p)
-{
- /* P must point to the start of the block, and the buffer
- must not have been killed. */
- return (m->type == MEM_TYPE_BUFFER
- && p == m->start
- && !NILP (((struct buffer *) p)->INTERNAL_FIELD (name)));
-}
-
-#endif /* GC_MARK_STACK || defined GC_MALLOC_CHECK */
-
-#if GC_MARK_STACK
-
-#if GC_MARK_STACK == GC_USE_GCPROS_CHECK_ZOMBIES
-
-/* Currently not used, but may be called from gdb. */
-
-void dump_zombies (void) EXTERNALLY_VISIBLE;
-
-/* Array of objects that are kept alive because the C stack contains
- a pattern that looks like a reference to them. */
-
-#define MAX_ZOMBIES 10
-static Lisp_Object zombies[MAX_ZOMBIES];
-
-/* Number of zombie objects. */
-
-static EMACS_INT nzombies;
-
-/* Number of garbage collections. */
-
-static EMACS_INT ngcs;
-
-/* Average percentage of zombies per collection. */
-
-static double avg_zombies;
-
-/* Max. number of live and zombie objects. */
-
-static EMACS_INT max_live, max_zombies;
-
-/* Average number of live objects per GC. */
-
-static double avg_live;
-
-DEFUN ("gc-status", Fgc_status, Sgc_status, 0, 0, "",
- doc: /* Show information about live and zombie objects. */)
- (void)
-{
- Lisp_Object args[8], zombie_list = Qnil;
- EMACS_INT i;
- for (i = 0; i < min (MAX_ZOMBIES, nzombies); i++)
- zombie_list = Fcons (zombies[i], zombie_list);
- args[0] = build_string ("%d GCs, avg live/zombies = %.2f/%.2f (%f%%), max %d/%d\nzombies: %S");
- args[1] = make_number (ngcs);
- args[2] = make_float (avg_live);
- args[3] = make_float (avg_zombies);
- args[4] = make_float (avg_zombies / avg_live / 100);
- args[5] = make_number (max_live);
- args[6] = make_number (max_zombies);
- args[7] = zombie_list;
- return Fmessage (8, args);
-}
-
-#endif /* GC_MARK_STACK == GC_USE_GCPROS_CHECK_ZOMBIES */
-
-
-/* Mark OBJ if we can prove it's a Lisp_Object. */
-
-static void
-mark_maybe_object (Lisp_Object obj)
-{
- void *po;
- struct mem_node *m;
-
-#if USE_VALGRIND
- if (valgrind_p)
- VALGRIND_MAKE_MEM_DEFINED (&obj, sizeof (obj));
-#endif
-
- if (INTEGERP (obj))
- return;
-
- po = (void *) XPNTR (obj);
- m = mem_find (po);
-
- if (m != MEM_NIL)
- {
- bool mark_p = 0;
-
- switch (XTYPE (obj))
- {
- case Lisp_String:
- mark_p = (live_string_p (m, po)
- && !STRING_MARKED_P ((struct Lisp_String *) po));
- break;
-
- case Lisp_Cons:
- mark_p = (live_cons_p (m, po) && !CONS_MARKED_P (XCONS (obj)));
- break;
-
- case Lisp_Symbol:
- mark_p = (live_symbol_p (m, po) && !XSYMBOL (obj)->gcmarkbit);
- break;
-
- case Lisp_Float:
- mark_p = (live_float_p (m, po) && !FLOAT_MARKED_P (XFLOAT (obj)));
- break;
-
- case Lisp_Vectorlike:
- /* Note: can't check BUFFERP before we know it's a
- buffer because checking that dereferences the pointer
- PO which might point anywhere. */
- if (live_vector_p (m, po))
- mark_p = !SUBRP (obj) && !VECTOR_MARKED_P (XVECTOR (obj));
- else if (live_buffer_p (m, po))
- mark_p = BUFFERP (obj) && !VECTOR_MARKED_P (XBUFFER (obj));
- break;
-
- case Lisp_Misc:
- mark_p = (live_misc_p (m, po) && !XMISCANY (obj)->gcmarkbit);
- break;
-
- default:
- break;
- }
-
- if (mark_p)
- {
-#if GC_MARK_STACK == GC_USE_GCPROS_CHECK_ZOMBIES
- if (nzombies < MAX_ZOMBIES)
- zombies[nzombies] = obj;
- ++nzombies;
-#endif
- mark_object (obj);
- }
- }
-}
-
-
-/* If P points to Lisp data, mark that as live if it isn't already
- marked. */
-
-static void
-mark_maybe_pointer (void *p)
-{
- struct mem_node *m;
-
-#if USE_VALGRIND
- if (valgrind_p)
- VALGRIND_MAKE_MEM_DEFINED (&p, sizeof (p));
-#endif
-
- /* Quickly rule out some values which can't point to Lisp data.
- USE_LSB_TAG needs Lisp data to be aligned on multiples of GCALIGNMENT.
- Otherwise, assume that Lisp data is aligned on even addresses. */
- if ((intptr_t) p % (USE_LSB_TAG ? GCALIGNMENT : 2))
- return;
-
- m = mem_find (p);
- if (m != MEM_NIL)
- {
- Lisp_Object obj = Qnil;
-
- switch (m->type)
- {
- case MEM_TYPE_NON_LISP:
- case MEM_TYPE_SPARE:
- /* Nothing to do; not a pointer to Lisp memory. */
- break;
-
- case MEM_TYPE_BUFFER:
- if (live_buffer_p (m, p) && !VECTOR_MARKED_P ((struct buffer *)p))
- XSETVECTOR (obj, p);
- break;
-
- case MEM_TYPE_CONS:
- if (live_cons_p (m, p) && !CONS_MARKED_P ((struct Lisp_Cons *) p))
- XSETCONS (obj, p);
- break;
-
- case MEM_TYPE_STRING:
- if (live_string_p (m, p)
- && !STRING_MARKED_P ((struct Lisp_String *) p))
- XSETSTRING (obj, p);
- break;
-
- case MEM_TYPE_MISC:
- if (live_misc_p (m, p) && !((struct Lisp_Free *) p)->gcmarkbit)
- XSETMISC (obj, p);
- break;
-
- case MEM_TYPE_SYMBOL:
- if (live_symbol_p (m, p) && !((struct Lisp_Symbol *) p)->gcmarkbit)
- XSETSYMBOL (obj, p);
- break;
-
- case MEM_TYPE_FLOAT:
- if (live_float_p (m, p) && !FLOAT_MARKED_P (p))
- XSETFLOAT (obj, p);
- break;
-
- case MEM_TYPE_VECTORLIKE:
- case MEM_TYPE_VECTOR_BLOCK:
- if (live_vector_p (m, p))
- {
- Lisp_Object tem;
- XSETVECTOR (tem, p);
- if (!SUBRP (tem) && !VECTOR_MARKED_P (XVECTOR (tem)))
- obj = tem;
- }
- break;
-
- default:
- emacs_abort ();
- }
-
- if (!NILP (obj))
- mark_object (obj);
- }
-}
-
-
-/* Alignment of pointer values. Use alignof, as it sometimes returns
- a smaller alignment than GCC's __alignof__ and mark_memory might
- miss objects if __alignof__ were used. */
-#define GC_POINTER_ALIGNMENT alignof (void *)
-
-/* Define POINTERS_MIGHT_HIDE_IN_OBJECTS to 1 if marking via C pointers does
- not suffice, which is the typical case. A host where a Lisp_Object is
- wider than a pointer might allocate a Lisp_Object in non-adjacent halves.
- If USE_LSB_TAG, the bottom half is not a valid pointer, but it should
- suffice to widen it to to a Lisp_Object and check it that way. */
-#if USE_LSB_TAG || VAL_MAX < UINTPTR_MAX
-# if !USE_LSB_TAG && VAL_MAX < UINTPTR_MAX >> GCTYPEBITS
- /* If tag bits straddle pointer-word boundaries, neither mark_maybe_pointer
- nor mark_maybe_object can follow the pointers. This should not occur on
- any practical porting target. */
-# error "MSB type bits straddle pointer-word boundaries"
-# endif
- /* Marking via C pointers does not suffice, because Lisp_Objects contain
- pointer words that hold pointers ORed with type bits. */
-# define POINTERS_MIGHT_HIDE_IN_OBJECTS 1
-#else
- /* Marking via C pointers suffices, because Lisp_Objects contain pointer
- words that hold unmodified pointers. */
-# define POINTERS_MIGHT_HIDE_IN_OBJECTS 0
-#endif
-
-/* Mark Lisp objects referenced from the address range START+OFFSET..END
- or END+OFFSET..START. */
-
-static void ATTRIBUTE_NO_SANITIZE_ADDRESS
-mark_memory (void *start, void *end)
-{
- void **pp;
- int i;
-
-#if GC_MARK_STACK == GC_USE_GCPROS_CHECK_ZOMBIES
- nzombies = 0;
-#endif
-
- /* Make START the pointer to the start of the memory region,
- if it isn't already. */
- if (end < start)
- {
- void *tem = start;
- start = end;
- end = tem;
- }
-
- /* Mark Lisp data pointed to. This is necessary because, in some
- situations, the C compiler optimizes Lisp objects away, so that
- only a pointer to them remains. Example:
-
- DEFUN ("testme", Ftestme, Stestme, 0, 0, 0, "")
- ()
- {
- Lisp_Object obj = build_string ("test");
- struct Lisp_String *s = XSTRING (obj);
- Fgarbage_collect ();
- fprintf (stderr, "test `%s'\n", s->data);
- return Qnil;
- }
-
- Here, `obj' isn't really used, and the compiler optimizes it
- away. The only reference to the life string is through the
- pointer `s'. */
-
- for (pp = start; (void *) pp < end; pp++)
- for (i = 0; i < sizeof *pp; i += GC_POINTER_ALIGNMENT)
- {
- void *p = *(void **) ((char *) pp + i);
- mark_maybe_pointer (p);
- if (POINTERS_MIGHT_HIDE_IN_OBJECTS)
- mark_maybe_object (XIL ((intptr_t) p));
- }
-}
-
-#if !defined GC_SAVE_REGISTERS_ON_STACK && !defined GC_SETJMP_WORKS
-
-static bool setjmp_tested_p;
-static int longjmps_done;
-
-#define SETJMP_WILL_LIKELY_WORK "\
-\n\
-Emacs garbage collector has been changed to use conservative stack\n\
-marking. Emacs has determined that the method it uses to do the\n\
-marking will likely work on your system, but this isn't sure.\n\
-\n\
-If you are a system-programmer, or can get the help of a local wizard\n\
-who is, please take a look at the function mark_stack in alloc.c, and\n\
-verify that the methods used are appropriate for your system.\n\
-\n\
-Please mail the result to <emacs-devel@gnu.org>.\n\
-"
-
-#define SETJMP_WILL_NOT_WORK "\
-\n\
-Emacs garbage collector has been changed to use conservative stack\n\
-marking. Emacs has determined that the default method it uses to do the\n\
-marking will not work on your system. We will need a system-dependent\n\
-solution for your system.\n\
-\n\
-Please take a look at the function mark_stack in alloc.c, and\n\
-try to find a way to make it work on your system.\n\
-\n\
-Note that you may get false negatives, depending on the compiler.\n\
-In particular, you need to use -O with GCC for this test.\n\
-\n\
-Please mail the result to <emacs-devel@gnu.org>.\n\
-"
-
-
-/* Perform a quick check if it looks like setjmp saves registers in a
- jmp_buf. Print a message to stderr saying so. When this test
- succeeds, this is _not_ a proof that setjmp is sufficient for
- conservative stack marking. Only the sources or a disassembly
- can prove that. */
-
-static void
-test_setjmp (void)
-{
- char buf[10];
- register int x;
- sys_jmp_buf jbuf;
-
- /* Arrange for X to be put in a register. */
- sprintf (buf, "1");
- x = strlen (buf);
- x = 2 * x - 1;
-
- sys_setjmp (jbuf);
- if (longjmps_done == 1)
- {
- /* Came here after the longjmp at the end of the function.
-
- If x == 1, the longjmp has restored the register to its
- value before the setjmp, and we can hope that setjmp
- saves all such registers in the jmp_buf, although that
- isn't sure.
-
- For other values of X, either something really strange is
- taking place, or the setjmp just didn't save the register. */
-
- if (x == 1)
- fprintf (stderr, SETJMP_WILL_LIKELY_WORK);
- else
- {
- fprintf (stderr, SETJMP_WILL_NOT_WORK);
- exit (1);
- }
- }
-
- ++longjmps_done;
- x = 2;
- if (longjmps_done == 1)
- sys_longjmp (jbuf, 1);
-}
-
-#endif /* not GC_SAVE_REGISTERS_ON_STACK && not GC_SETJMP_WORKS */
-
-
-#if GC_MARK_STACK == GC_MARK_STACK_CHECK_GCPROS
-
-/* Abort if anything GCPRO'd doesn't survive the GC. */
-
-static void
-check_gcpros (void)
-{
- struct gcpro *p;
- ptrdiff_t i;
-
- for (p = gcprolist; p; p = p->next)
- for (i = 0; i < p->nvars; ++i)
- if (!survives_gc_p (p->var[i]))
- /* FIXME: It's not necessarily a bug. It might just be that the
- GCPRO is unnecessary or should release the object sooner. */
- emacs_abort ();
-}
-
-#elif GC_MARK_STACK == GC_USE_GCPROS_CHECK_ZOMBIES
-
-void
-dump_zombies (void)
-{
- int i;
-
- fprintf (stderr, "\nZombies kept alive = %"pI"d:\n", nzombies);
- for (i = 0; i < min (MAX_ZOMBIES, nzombies); ++i)
- {
- fprintf (stderr, " %d = ", i);
- debug_print (zombies[i]);
- }
-}
-
-#endif /* GC_MARK_STACK == GC_USE_GCPROS_CHECK_ZOMBIES */
-
-
-/* Mark live Lisp objects on the C stack.
-
- There are several system-dependent problems to consider when
- porting this to new architectures:
-
- Processor Registers
-
- We have to mark Lisp objects in CPU registers that can hold local
- variables or are used to pass parameters.
-
- If GC_SAVE_REGISTERS_ON_STACK is defined, it should expand to
- something that either saves relevant registers on the stack, or
- calls mark_maybe_object passing it each register's contents.
-
- If GC_SAVE_REGISTERS_ON_STACK is not defined, the current
- implementation assumes that calling setjmp saves registers we need
- to see in a jmp_buf which itself lies on the stack. This doesn't
- have to be true! It must be verified for each system, possibly
- by taking a look at the source code of setjmp.
-
- If __builtin_unwind_init is available (defined by GCC >= 2.8) we
- can use it as a machine independent method to store all registers
- to the stack. In this case the macros described in the previous
- two paragraphs are not used.
-
- Stack Layout
-
- Architectures differ in the way their processor stack is organized.
- For example, the stack might look like this
-
- +----------------+
- | Lisp_Object | size = 4
- +----------------+
- | something else | size = 2
- +----------------+
- | Lisp_Object | size = 4
- +----------------+
- | ... |
-
- In such a case, not every Lisp_Object will be aligned equally. To
- find all Lisp_Object on the stack it won't be sufficient to walk
- the stack in steps of 4 bytes. Instead, two passes will be
- necessary, one starting at the start of the stack, and a second
- pass starting at the start of the stack + 2. Likewise, if the
- minimal alignment of Lisp_Objects on the stack is 1, four passes
- would be necessary, each one starting with one byte more offset
- from the stack start. */
-
-static void
-mark_stack (void)
-{
- void *end;
-
-#ifdef HAVE___BUILTIN_UNWIND_INIT
- /* Force callee-saved registers and register windows onto the stack.
- This is the preferred method if available, obviating the need for
- machine dependent methods. */
- __builtin_unwind_init ();
- end = &end;
-#else /* not HAVE___BUILTIN_UNWIND_INIT */
-#ifndef GC_SAVE_REGISTERS_ON_STACK
- /* jmp_buf may not be aligned enough on darwin-ppc64 */
- union aligned_jmpbuf {
- Lisp_Object o;
- sys_jmp_buf j;
- } j;
- volatile bool stack_grows_down_p = (char *) &j > (char *) stack_base;
-#endif
- /* This trick flushes the register windows so that all the state of
- the process is contained in the stack. */
- /* Fixme: Code in the Boehm GC suggests flushing (with `flushrs') is
- needed on ia64 too. See mach_dep.c, where it also says inline
- assembler doesn't work with relevant proprietary compilers. */
-#ifdef __sparc__
-#if defined (__sparc64__) && defined (__FreeBSD__)
- /* FreeBSD does not have a ta 3 handler. */
- asm ("flushw");
-#else
- asm ("ta 3");
-#endif
-#endif
-
- /* Save registers that we need to see on the stack. We need to see
- registers used to hold register variables and registers used to
- pass parameters. */
-#ifdef GC_SAVE_REGISTERS_ON_STACK
- GC_SAVE_REGISTERS_ON_STACK (end);
-#else /* not GC_SAVE_REGISTERS_ON_STACK */
-
-#ifndef GC_SETJMP_WORKS /* If it hasn't been checked yet that
- setjmp will definitely work, test it
- and print a message with the result
- of the test. */
- if (!setjmp_tested_p)
- {
- setjmp_tested_p = 1;
- test_setjmp ();
- }
-#endif /* GC_SETJMP_WORKS */
-
- sys_setjmp (j.j);
- end = stack_grows_down_p ? (char *) &j + sizeof j : (char *) &j;
-#endif /* not GC_SAVE_REGISTERS_ON_STACK */
-#endif /* not HAVE___BUILTIN_UNWIND_INIT */
-
- /* This assumes that the stack is a contiguous region in memory. If
- that's not the case, something has to be done here to iterate
- over the stack segments. */
- mark_memory (stack_base, end);
-
- /* Allow for marking a secondary stack, like the register stack on the
- ia64. */
-#ifdef GC_MARK_SECONDARY_STACK
- GC_MARK_SECONDARY_STACK ();
-#endif
-
-#if GC_MARK_STACK == GC_MARK_STACK_CHECK_GCPROS
- check_gcpros ();
-#endif
-}
-
-#else /* GC_MARK_STACK == 0 */
-
-#define mark_maybe_object(obj) emacs_abort ()
-
-#endif /* GC_MARK_STACK != 0 */
-
-
-/* Determine whether it is safe to access memory at address P. */
-static int
-valid_pointer_p (void *p)
-{
-#ifdef WINDOWSNT
- return w32_valid_pointer_p (p, 16);
-#else
- int fd[2];
-
- /* Obviously, we cannot just access it (we would SEGV trying), so we
- trick the o/s to tell us whether p is a valid pointer.
- Unfortunately, we cannot use NULL_DEVICE here, as emacs_write may
- not validate p in that case. */
-
- if (emacs_pipe (fd) == 0)
- {
- bool valid = emacs_write (fd[1], p, 16) == 16;
- emacs_close (fd[1]);
- emacs_close (fd[0]);
- return valid;
- }
-
- return -1;
-#endif
-}
-
-/* Return 2 if OBJ is a killed or special buffer object, 1 if OBJ is a
- valid lisp object, 0 if OBJ is NOT a valid lisp object, or -1 if we
- cannot validate OBJ. This function can be quite slow, so its primary
- use is the manual debugging. The only exception is print_object, where
- we use it to check whether the memory referenced by the pointer of
- Lisp_Save_Value object contains valid objects. */
-
-int
-valid_lisp_object_p (Lisp_Object obj)
-{
- void *p;
-#if GC_MARK_STACK
- struct mem_node *m;
-#endif
-
- if (INTEGERP (obj))
- return 1;
-
- p = (void *) XPNTR (obj);
- if (PURE_POINTER_P (p))
- return 1;
-
- if (p == &buffer_defaults || p == &buffer_local_symbols)
- return 2;
-
-#if !GC_MARK_STACK
- return valid_pointer_p (p);
-#else
-
- m = mem_find (p);
-
- if (m == MEM_NIL)
- {
- int valid = valid_pointer_p (p);
- if (valid <= 0)
- return valid;
-
- if (SUBRP (obj))
- return 1;
-
- return 0;
- }
-
- switch (m->type)
- {
- case MEM_TYPE_NON_LISP:
- case MEM_TYPE_SPARE:
- return 0;
-
- case MEM_TYPE_BUFFER:
- return live_buffer_p (m, p) ? 1 : 2;
-
- case MEM_TYPE_CONS:
- return live_cons_p (m, p);
-
- case MEM_TYPE_STRING:
- return live_string_p (m, p);
-
- case MEM_TYPE_MISC:
- return live_misc_p (m, p);
-
- case MEM_TYPE_SYMBOL:
- return live_symbol_p (m, p);
-
- case MEM_TYPE_FLOAT:
- return live_float_p (m, p);
-
- case MEM_TYPE_VECTORLIKE:
- case MEM_TYPE_VECTOR_BLOCK:
- return live_vector_p (m, p);
-
- default:
- break;
- }
-
- return 0;
-#endif
-}
-
-
-
-\f
-/***********************************************************************
- Pure Storage Management
- ***********************************************************************/
-
-/* Allocate room for SIZE bytes from pure Lisp storage and return a
- pointer to it. TYPE is the Lisp type for which the memory is
- allocated. TYPE < 0 means it's not used for a Lisp object. */
-
-static void *
-pure_alloc (size_t size, int type)
-{
- void *result;
-#if USE_LSB_TAG
- size_t alignment = GCALIGNMENT;
-#else
- size_t alignment = alignof (EMACS_INT);
-
- /* Give Lisp_Floats an extra alignment. */
- if (type == Lisp_Float)
- alignment = alignof (struct Lisp_Float);
-#endif
-
- again:
- if (type >= 0)
- {
- /* Allocate space for a Lisp object from the beginning of the free
- space with taking account of alignment. */
- result = ALIGN (purebeg + pure_bytes_used_lisp, alignment);
- pure_bytes_used_lisp = ((char *)result - (char *)purebeg) + size;
- }
- else
- {
- /* Allocate space for a non-Lisp object from the end of the free
- space. */
- pure_bytes_used_non_lisp += size;
- result = purebeg + pure_size - pure_bytes_used_non_lisp;
- }
- pure_bytes_used = pure_bytes_used_lisp + pure_bytes_used_non_lisp;
-
- if (pure_bytes_used <= pure_size)
- return result;
-
- /* Don't allocate a large amount here,
- because it might get mmap'd and then its address
- might not be usable. */
- purebeg = xmalloc (10000);
- pure_size = 10000;
- pure_bytes_used_before_overflow += pure_bytes_used - size;
- pure_bytes_used = 0;
- pure_bytes_used_lisp = pure_bytes_used_non_lisp = 0;
- goto again;
-}
-
-
-/* Print a warning if PURESIZE is too small. */
-
-void
-check_pure_size (void)
-{
- if (pure_bytes_used_before_overflow)
- message (("emacs:0:Pure Lisp storage overflow (approx. %"pI"d"
- " bytes needed)"),
- pure_bytes_used + pure_bytes_used_before_overflow);
-}
-
-
-/* Find the byte sequence {DATA[0], ..., DATA[NBYTES-1], '\0'} from
- the non-Lisp data pool of the pure storage, and return its start
- address. Return NULL if not found. */
-
-static char *
-find_string_data_in_pure (const char *data, ptrdiff_t nbytes)
-{
- int i;
- ptrdiff_t skip, bm_skip[256], last_char_skip, infinity, start, start_max;
- const unsigned char *p;
- char *non_lisp_beg;
-
- if (pure_bytes_used_non_lisp <= nbytes)
- return NULL;
-
- /* Set up the Boyer-Moore table. */
- skip = nbytes + 1;
- for (i = 0; i < 256; i++)
- bm_skip[i] = skip;
-
- p = (const unsigned char *) data;
- while (--skip > 0)
- bm_skip[*p++] = skip;
-
- last_char_skip = bm_skip['\0'];
-
- non_lisp_beg = purebeg + pure_size - pure_bytes_used_non_lisp;
- start_max = pure_bytes_used_non_lisp - (nbytes + 1);
-
- /* See the comments in the function `boyer_moore' (search.c) for the
- use of `infinity'. */
- infinity = pure_bytes_used_non_lisp + 1;
- bm_skip['\0'] = infinity;
-
- p = (const unsigned char *) non_lisp_beg + nbytes;
- start = 0;
- do
- {
- /* Check the last character (== '\0'). */
- do
- {
- start += bm_skip[*(p + start)];
- }
- while (start <= start_max);
-
- if (start < infinity)
- /* Couldn't find the last character. */
- return NULL;
-
- /* No less than `infinity' means we could find the last
- character at `p[start - infinity]'. */
- start -= infinity;
-
- /* Check the remaining characters. */
- if (memcmp (data, non_lisp_beg + start, nbytes) == 0)
- /* Found. */
- return non_lisp_beg + start;
-
- start += last_char_skip;
- }
- while (start <= start_max);
-
- return NULL;
-}
-
-
-/* Return a string allocated in pure space. DATA is a buffer holding
- NCHARS characters, and NBYTES bytes of string data. MULTIBYTE
- means make the result string multibyte.
-
- Must get an error if pure storage is full, since if it cannot hold
- a large string it may be able to hold conses that point to that
- string; then the string is not protected from gc. */
-
-Lisp_Object
-make_pure_string (const char *data,
- ptrdiff_t nchars, ptrdiff_t nbytes, bool multibyte)
-{
- Lisp_Object string;
- struct Lisp_String *s = pure_alloc (sizeof *s, Lisp_String);
- s->data = (unsigned char *) find_string_data_in_pure (data, nbytes);
- if (s->data == NULL)
- {
- s->data = pure_alloc (nbytes + 1, -1);
- memcpy (s->data, data, nbytes);
- s->data[nbytes] = '\0';
- }
- s->size = nchars;
- s->size_byte = multibyte ? nbytes : -1;
- s->intervals = NULL;
- XSETSTRING (string, s);
- return string;
-}
-
-/* Return a string allocated in pure space. Do not
- allocate the string data, just point to DATA. */
-
-Lisp_Object
-make_pure_c_string (const char *data, ptrdiff_t nchars)
-{
- Lisp_Object string;
- struct Lisp_String *s = pure_alloc (sizeof *s, Lisp_String);
- s->size = nchars;
- s->size_byte = -1;
- s->data = (unsigned char *) data;
- s->intervals = NULL;
- XSETSTRING (string, s);
- return string;
-}
-
-/* Return a cons allocated from pure space. Give it pure copies
- of CAR as car and CDR as cdr. */
-
-Lisp_Object
-pure_cons (Lisp_Object car, Lisp_Object cdr)
-{
- Lisp_Object new;
- struct Lisp_Cons *p = pure_alloc (sizeof *p, Lisp_Cons);
- XSETCONS (new, p);
- XSETCAR (new, Fpurecopy (car));
- XSETCDR (new, Fpurecopy (cdr));
- return new;
-}
-
-
-/* Value is a float object with value NUM allocated from pure space. */
-
-static Lisp_Object
-make_pure_float (double num)
-{
- Lisp_Object new;
- struct Lisp_Float *p = pure_alloc (sizeof *p, Lisp_Float);
- XSETFLOAT (new, p);
- XFLOAT_INIT (new, num);
- return new;
-}
-
-
-/* Return a vector with room for LEN Lisp_Objects allocated from
- pure space. */
-
-static Lisp_Object
-make_pure_vector (ptrdiff_t len)
-{
- Lisp_Object new;
- size_t size = header_size + len * word_size;
- struct Lisp_Vector *p = pure_alloc (size, Lisp_Vectorlike);
- XSETVECTOR (new, p);
- XVECTOR (new)->header.size = len;
- return new;
-}
-
-
-DEFUN ("purecopy", Fpurecopy, Spurecopy, 1, 1, 0,
- doc: /* Make a copy of object OBJ in pure storage.
-Recursively copies contents of vectors and cons cells.
-Does not copy symbols. Copies strings without text properties. */)
- (register Lisp_Object obj)
-{
- if (NILP (Vpurify_flag))
- return obj;
-
- if (PURE_POINTER_P (XPNTR (obj)))
- return obj;
-
- if (HASH_TABLE_P (Vpurify_flag)) /* Hash consing. */
- {
- Lisp_Object tmp = Fgethash (obj, Vpurify_flag, Qnil);
- if (!NILP (tmp))
- return tmp;
- }
-
- if (CONSP (obj))
- obj = pure_cons (XCAR (obj), XCDR (obj));
- else if (FLOATP (obj))
- obj = make_pure_float (XFLOAT_DATA (obj));
- else if (STRINGP (obj))
- obj = make_pure_string (SSDATA (obj), SCHARS (obj),
- SBYTES (obj),
- STRING_MULTIBYTE (obj));
- else if (COMPILEDP (obj) || VECTORP (obj))
- {
- register struct Lisp_Vector *vec;
- register ptrdiff_t i;
- ptrdiff_t size;
-
- size = ASIZE (obj);
- if (size & PSEUDOVECTOR_FLAG)
- size &= PSEUDOVECTOR_SIZE_MASK;
- vec = XVECTOR (make_pure_vector (size));
- for (i = 0; i < size; i++)
- vec->contents[i] = Fpurecopy (AREF (obj, i));
- if (COMPILEDP (obj))
- {
- XSETPVECTYPE (vec, PVEC_COMPILED);
- XSETCOMPILED (obj, vec);
- }
- else
- XSETVECTOR (obj, vec);
- }
- else if (MARKERP (obj))
- error ("Attempt to copy a marker to pure storage");
- else
- /* Not purified, don't hash-cons. */
- return obj;
-
- if (HASH_TABLE_P (Vpurify_flag)) /* Hash consing. */
- Fputhash (obj, obj, Vpurify_flag);
-
- return obj;
-}
-
-
-\f
-/***********************************************************************
- Protection from GC
- ***********************************************************************/
-
-/* Put an entry in staticvec, pointing at the variable with address
- VARADDRESS. */
-
-void
-staticpro (Lisp_Object *varaddress)
-{
- if (staticidx >= NSTATICS)
- fatal ("NSTATICS too small; try increasing and recompiling Emacs.");
- staticvec[staticidx++] = varaddress;
-}
-
-\f
-/***********************************************************************
- Protection from GC
- ***********************************************************************/
-
-/* Temporarily prevent garbage collection. */
-
-ptrdiff_t
-inhibit_garbage_collection (void)
-{
- ptrdiff_t count = SPECPDL_INDEX ();
-
- specbind (Qgc_cons_threshold, make_number (MOST_POSITIVE_FIXNUM));
- return count;
-}
-
-/* Used to avoid possible overflows when
- converting from C to Lisp integers. */
-
-static Lisp_Object
-bounded_number (EMACS_INT number)
-{
- return make_number (min (MOST_POSITIVE_FIXNUM, number));
-}
-
-/* Calculate total bytes of live objects. */
-
-static size_t
-total_bytes_of_live_objects (void)
-{
- size_t tot = 0;
- tot += total_conses * sizeof (struct Lisp_Cons);
- tot += total_symbols * sizeof (struct Lisp_Symbol);
- tot += total_markers * sizeof (union Lisp_Misc);
- tot += total_string_bytes;
- tot += total_vector_slots * word_size;
- tot += total_floats * sizeof (struct Lisp_Float);
- tot += total_intervals * sizeof (struct interval);
- tot += total_strings * sizeof (struct Lisp_String);
- return tot;
-}
-
-#ifdef HAVE_WINDOW_SYSTEM
-
-/* This code has a few issues on MS-Windows, see Bug#15876 and Bug#16140. */
-
-#if !defined (HAVE_NTGUI)
-
-/* Remove unmarked font-spec and font-entity objects from ENTRY, which is
- (DRIVER-TYPE NUM-FRAMES FONT-CACHE-DATA ...), and return changed entry. */
-
-static Lisp_Object
-compact_font_cache_entry (Lisp_Object entry)
-{
- Lisp_Object tail, *prev = &entry;
-
- for (tail = entry; CONSP (tail); tail = XCDR (tail))
- {
- bool drop = 0;
- Lisp_Object obj = XCAR (tail);
-
- /* Consider OBJ if it is (font-spec . [font-entity font-entity ...]). */
- if (CONSP (obj) && FONT_SPEC_P (XCAR (obj))
- && !VECTOR_MARKED_P (XFONT_SPEC (XCAR (obj)))
- && VECTORP (XCDR (obj)))
- {
- ptrdiff_t i, size = ASIZE (XCDR (obj)) & ~ARRAY_MARK_FLAG;
-
- /* If font-spec is not marked, most likely all font-entities
- are not marked too. But we must be sure that nothing is
- marked within OBJ before we really drop it. */
- for (i = 0; i < size; i++)
- if (VECTOR_MARKED_P (XFONT_ENTITY (AREF (XCDR (obj), i))))
- break;
-
- if (i == size)
- drop = 1;
- }
- if (drop)
- *prev = XCDR (tail);
- else
- prev = xcdr_addr (tail);
- }
- return entry;
-}
-
-#endif /* not HAVE_NTGUI */
-
-/* Compact font caches on all terminals and mark
- everything which is still here after compaction. */
-
-static void
-compact_font_caches (void)
-{
- struct terminal *t;
-
- for (t = terminal_list; t; t = t->next_terminal)
- {
- Lisp_Object cache = TERMINAL_FONT_CACHE (t);
-#if !defined (HAVE_NTGUI)
- if (CONSP (cache))
- {
- Lisp_Object entry;
-
- for (entry = XCDR (cache); CONSP (entry); entry = XCDR (entry))
- XSETCAR (entry, compact_font_cache_entry (XCAR (entry)));
- }
-#endif /* not HAVE_NTGUI */
- mark_object (cache);
- }
-}
-
-#else /* not HAVE_WINDOW_SYSTEM */
-
-#define compact_font_caches() (void)(0)
-
-#endif /* HAVE_WINDOW_SYSTEM */
-
-/* Remove (MARKER . DATA) entries with unmarked MARKER
- from buffer undo LIST and return changed list. */
-
-static Lisp_Object
-compact_undo_list (Lisp_Object list)
-{
- Lisp_Object tail, *prev = &list;
-
- for (tail = list; CONSP (tail); tail = XCDR (tail))
- {
- if (CONSP (XCAR (tail))
- && MARKERP (XCAR (XCAR (tail)))
- && !XMARKER (XCAR (XCAR (tail)))->gcmarkbit)
- *prev = XCDR (tail);
- else
- prev = xcdr_addr (tail);
- }
- return list;
-}
-
-DEFUN ("garbage-collect", Fgarbage_collect, Sgarbage_collect, 0, 0, "",
- doc: /* Reclaim storage for Lisp objects no longer needed.
-Garbage collection happens automatically if you cons more than
-`gc-cons-threshold' bytes of Lisp data since previous garbage collection.
-`garbage-collect' normally returns a list with info on amount of space in use,
-where each entry has the form (NAME SIZE USED FREE), where:
-- NAME is a symbol describing the kind of objects this entry represents,
-- SIZE is the number of bytes used by each one,
-- USED is the number of those objects that were found live in the heap,
-- FREE is the number of those objects that are not live but that Emacs
- keeps around for future allocations (maybe because it does not know how
- to return them to the OS).
-However, if there was overflow in pure space, `garbage-collect'
-returns nil, because real GC can't be done.
-See Info node `(elisp)Garbage Collection'. */)
- (void)
-{
- struct buffer *nextb;
- char stack_top_variable;
- ptrdiff_t i;
- bool message_p;
- ptrdiff_t count = SPECPDL_INDEX ();
- struct timespec start;
- Lisp_Object retval = Qnil;
- size_t tot_before = 0;
-
- if (abort_on_gc)
- emacs_abort ();
-
- /* Can't GC if pure storage overflowed because we can't determine
- if something is a pure object or not. */
- if (pure_bytes_used_before_overflow)
- return Qnil;
-
- /* Record this function, so it appears on the profiler's backtraces. */
- record_in_backtrace (Qautomatic_gc, &Qnil, 0);
-
- check_cons_list ();
-
- /* Don't keep undo information around forever.
- Do this early on, so it is no problem if the user quits. */
- FOR_EACH_BUFFER (nextb)
- compact_buffer (nextb);
-
- if (profiler_memory_running)
- tot_before = total_bytes_of_live_objects ();
-
- start = current_timespec ();
-
- /* In case user calls debug_print during GC,
- don't let that cause a recursive GC. */
- consing_since_gc = 0;
-
- /* Save what's currently displayed in the echo area. */
- message_p = push_message ();
- record_unwind_protect_void (pop_message_unwind);
-
- /* Save a copy of the contents of the stack, for debugging. */
-#if MAX_SAVE_STACK > 0
- if (NILP (Vpurify_flag))
- {
- char *stack;
- ptrdiff_t stack_size;
- if (&stack_top_variable < stack_bottom)
- {
- stack = &stack_top_variable;
- stack_size = stack_bottom - &stack_top_variable;
- }
- else
- {
- stack = stack_bottom;
- stack_size = &stack_top_variable - stack_bottom;
- }
- if (stack_size <= MAX_SAVE_STACK)
- {
- if (stack_copy_size < stack_size)
- {
- stack_copy = xrealloc (stack_copy, stack_size);
- stack_copy_size = stack_size;
- }
- no_sanitize_memcpy (stack_copy, stack, stack_size);
- }
- }
-#endif /* MAX_SAVE_STACK > 0 */
-
- if (garbage_collection_messages)
- message1_nolog ("Garbage collecting...");
-
- block_input ();
-
- shrink_regexp_cache ();
-
- gc_in_progress = 1;
-
- /* Mark all the special slots that serve as the roots of accessibility. */
-
- mark_buffer (&buffer_defaults);
- mark_buffer (&buffer_local_symbols);
-
- for (i = 0; i < staticidx; i++)
- mark_object (*staticvec[i]);
-
- mark_specpdl ();
- mark_terminals ();
- mark_kboards ();
-
-#ifdef USE_GTK
- xg_mark_data ();
-#endif
-
-#if (GC_MARK_STACK == GC_MAKE_GCPROS_NOOPS \
- || GC_MARK_STACK == GC_MARK_STACK_CHECK_GCPROS)
- mark_stack ();
-#else
- {
- register struct gcpro *tail;
- for (tail = gcprolist; tail; tail = tail->next)
- for (i = 0; i < tail->nvars; i++)
- mark_object (tail->var[i]);
- }
- mark_byte_stack ();
-#endif
- {
- struct handler *handler;
- for (handler = handlerlist; handler; handler = handler->next)
- {
- mark_object (handler->tag_or_ch);
- mark_object (handler->val);
- }
- }
-#ifdef HAVE_WINDOW_SYSTEM
- mark_fringe_data ();
-#endif
-
-#if GC_MARK_STACK == GC_USE_GCPROS_CHECK_ZOMBIES
- mark_stack ();
-#endif
-
- /* Everything is now marked, except for the data in font caches
- and undo lists. They're compacted by removing an items which
- aren't reachable otherwise. */
-
- compact_font_caches ();
-
- FOR_EACH_BUFFER (nextb)
- {
- if (!EQ (BVAR (nextb, undo_list), Qt))
- bset_undo_list (nextb, compact_undo_list (BVAR (nextb, undo_list)));
- /* Now that we have stripped the elements that need not be
- in the undo_list any more, we can finally mark the list. */
- mark_object (BVAR (nextb, undo_list));
- }
-
- gc_sweep ();
-
- /* Clear the mark bits that we set in certain root slots. */
-
- unmark_byte_stack ();
- VECTOR_UNMARK (&buffer_defaults);
- VECTOR_UNMARK (&buffer_local_symbols);
-
-#if GC_MARK_STACK == GC_USE_GCPROS_CHECK_ZOMBIES && 0
- dump_zombies ();
-#endif
-
- check_cons_list ();
-
- gc_in_progress = 0;
-
- unblock_input ();
-
- consing_since_gc = 0;
- if (gc_cons_threshold < GC_DEFAULT_THRESHOLD / 10)
- gc_cons_threshold = GC_DEFAULT_THRESHOLD / 10;
-
- gc_relative_threshold = 0;
- if (FLOATP (Vgc_cons_percentage))
- { /* Set gc_cons_combined_threshold. */
- double tot = total_bytes_of_live_objects ();
-
- tot *= XFLOAT_DATA (Vgc_cons_percentage);
- if (0 < tot)
- {
- if (tot < TYPE_MAXIMUM (EMACS_INT))
- gc_relative_threshold = tot;
- else
- gc_relative_threshold = TYPE_MAXIMUM (EMACS_INT);
- }
- }
-
- if (garbage_collection_messages)
- {
- if (message_p || minibuf_level > 0)
- restore_message ();
- else
- message1_nolog ("Garbage collecting...done");
- }
-
- unbind_to (count, Qnil);
- {
- Lisp_Object total[11];
- int total_size = 10;
-
- total[0] = list4 (Qconses, make_number (sizeof (struct Lisp_Cons)),
- bounded_number (total_conses),
- bounded_number (total_free_conses));
-
- total[1] = list4 (Qsymbols, make_number (sizeof (struct Lisp_Symbol)),
- bounded_number (total_symbols),
- bounded_number (total_free_symbols));
-
- total[2] = list4 (Qmiscs, make_number (sizeof (union Lisp_Misc)),
- bounded_number (total_markers),
- bounded_number (total_free_markers));
-
- total[3] = list4 (Qstrings, make_number (sizeof (struct Lisp_String)),
- bounded_number (total_strings),
- bounded_number (total_free_strings));
-
- total[4] = list3 (Qstring_bytes, make_number (1),
- bounded_number (total_string_bytes));
-
- total[5] = list3 (Qvectors,
- make_number (header_size + sizeof (Lisp_Object)),
- bounded_number (total_vectors));
-
- total[6] = list4 (Qvector_slots, make_number (word_size),
- bounded_number (total_vector_slots),
- bounded_number (total_free_vector_slots));
-
- total[7] = list4 (Qfloats, make_number (sizeof (struct Lisp_Float)),
- bounded_number (total_floats),
- bounded_number (total_free_floats));
-
- total[8] = list4 (Qintervals, make_number (sizeof (struct interval)),
- bounded_number (total_intervals),
- bounded_number (total_free_intervals));
-
- total[9] = list3 (Qbuffers, make_number (sizeof (struct buffer)),
- bounded_number (total_buffers));
-
-#ifdef DOUG_LEA_MALLOC
- total_size++;
- total[10] = list4 (Qheap, make_number (1024),
- bounded_number ((mallinfo ().uordblks + 1023) >> 10),
- bounded_number ((mallinfo ().fordblks + 1023) >> 10));
-#endif
- retval = Flist (total_size, total);
- }
-
-#if GC_MARK_STACK == GC_USE_GCPROS_CHECK_ZOMBIES
- {
- /* Compute average percentage of zombies. */
- double nlive
- = (total_conses + total_symbols + total_markers + total_strings
- + total_vectors + total_floats + total_intervals + total_buffers);
-
- avg_live = (avg_live * ngcs + nlive) / (ngcs + 1);
- max_live = max (nlive, max_live);
- avg_zombies = (avg_zombies * ngcs + nzombies) / (ngcs + 1);
- max_zombies = max (nzombies, max_zombies);
- ++ngcs;
- }
-#endif
-
- if (!NILP (Vpost_gc_hook))
- {
- ptrdiff_t gc_count = inhibit_garbage_collection ();
- safe_run_hooks (Qpost_gc_hook);
- unbind_to (gc_count, Qnil);
- }
-
- /* Accumulate statistics. */
- if (FLOATP (Vgc_elapsed))
- {
- struct timespec since_start = timespec_sub (current_timespec (), start);
- Vgc_elapsed = make_float (XFLOAT_DATA (Vgc_elapsed)
- + timespectod (since_start));
- }
-
- gcs_done++;
-
- /* Collect profiling data. */
- if (profiler_memory_running)
- {
- size_t swept = 0;
- size_t tot_after = total_bytes_of_live_objects ();
- if (tot_before > tot_after)
- swept = tot_before - tot_after;
- malloc_probe (swept);
- }
-
- return retval;
-}
-
-
-/* Mark Lisp objects in glyph matrix MATRIX. Currently the
- only interesting objects referenced from glyphs are strings. */
-
-static void
-mark_glyph_matrix (struct glyph_matrix *matrix)
-{
- struct glyph_row *row = matrix->rows;
- struct glyph_row *end = row + matrix->nrows;
-
- for (; row < end; ++row)
- if (row->enabled_p)
- {
- int area;
- for (area = LEFT_MARGIN_AREA; area < LAST_AREA; ++area)
- {
- struct glyph *glyph = row->glyphs[area];
- struct glyph *end_glyph = glyph + row->used[area];
-
- for (; glyph < end_glyph; ++glyph)
- if (STRINGP (glyph->object)
- && !STRING_MARKED_P (XSTRING (glyph->object)))
- mark_object (glyph->object);
- }
- }
-}
-
-/* Mark reference to a Lisp_Object.
- If the object referred to has not been seen yet, recursively mark
- all the references contained in it. */
-
-#define LAST_MARKED_SIZE 500
-static Lisp_Object last_marked[LAST_MARKED_SIZE];
-static int last_marked_index;
-
-/* For debugging--call abort when we cdr down this many
- links of a list, in mark_object. In debugging,
- the call to abort will hit a breakpoint.
- Normally this is zero and the check never goes off. */
-ptrdiff_t mark_object_loop_halt EXTERNALLY_VISIBLE;
-
-static void
-mark_vectorlike (struct Lisp_Vector *ptr)
-{
- ptrdiff_t size = ptr->header.size;
- ptrdiff_t i;
-
- eassert (!VECTOR_MARKED_P (ptr));
- VECTOR_MARK (ptr); /* Else mark it. */
- if (size & PSEUDOVECTOR_FLAG)
- size &= PSEUDOVECTOR_SIZE_MASK;
-
- /* Note that this size is not the memory-footprint size, but only
- the number of Lisp_Object fields that we should trace.
- The distinction is used e.g. by Lisp_Process which places extra
- non-Lisp_Object fields at the end of the structure... */
- for (i = 0; i < size; i++) /* ...and then mark its elements. */
- mark_object (ptr->contents[i]);
-}
-
-/* Like mark_vectorlike but optimized for char-tables (and
- sub-char-tables) assuming that the contents are mostly integers or
- symbols. */
-
-static void
-mark_char_table (struct Lisp_Vector *ptr)
-{
- int size = ptr->header.size & PSEUDOVECTOR_SIZE_MASK;
- int i;
-
- eassert (!VECTOR_MARKED_P (ptr));
- VECTOR_MARK (ptr);
- for (i = 0; i < size; i++)
- {
- Lisp_Object val = ptr->contents[i];
-
- if (INTEGERP (val) || (SYMBOLP (val) && XSYMBOL (val)->gcmarkbit))
- continue;
- if (SUB_CHAR_TABLE_P (val))
- {
- if (! VECTOR_MARKED_P (XVECTOR (val)))
- mark_char_table (XVECTOR (val));
- }
- else
- mark_object (val);
- }
-}
-
-/* Mark the chain of overlays starting at PTR. */
-
-static void
-mark_overlay (struct Lisp_Overlay *ptr)
-{
- for (; ptr && !ptr->gcmarkbit; ptr = ptr->next)
- {
- ptr->gcmarkbit = 1;
- mark_object (ptr->start);
- mark_object (ptr->end);
- mark_object (ptr->plist);
- }
-}
-
-/* Mark Lisp_Objects and special pointers in BUFFER. */
-
-static void
-mark_buffer (struct buffer *buffer)
-{
- /* This is handled much like other pseudovectors... */
- mark_vectorlike ((struct Lisp_Vector *) buffer);
-
- /* ...but there are some buffer-specific things. */
-
- MARK_INTERVAL_TREE (buffer_intervals (buffer));
-
- /* For now, we just don't mark the undo_list. It's done later in
- a special way just before the sweep phase, and after stripping
- some of its elements that are not needed any more. */
-
- mark_overlay (buffer->overlays_before);
- mark_overlay (buffer->overlays_after);
-
- /* If this is an indirect buffer, mark its base buffer. */
- if (buffer->base_buffer && !VECTOR_MARKED_P (buffer->base_buffer))
- mark_buffer (buffer->base_buffer);
-}
-
-/* Mark Lisp faces in the face cache C. */
-
-static void
-mark_face_cache (struct face_cache *c)
-{
- if (c)
- {
- int i, j;
- for (i = 0; i < c->used; ++i)
- {
- struct face *face = FACE_FROM_ID (c->f, i);
-
- if (face)
- {
- if (face->font && !VECTOR_MARKED_P (face->font))
- mark_vectorlike ((struct Lisp_Vector *) face->font);
-
- for (j = 0; j < LFACE_VECTOR_SIZE; ++j)
- mark_object (face->lface[j]);
- }
- }
- }
-}
-
-/* Remove killed buffers or items whose car is a killed buffer from
- LIST, and mark other items. Return changed LIST, which is marked. */
-
-static Lisp_Object
-mark_discard_killed_buffers (Lisp_Object list)
-{
- Lisp_Object tail, *prev = &list;
-
- for (tail = list; CONSP (tail) && !CONS_MARKED_P (XCONS (tail));
- tail = XCDR (tail))
- {
- Lisp_Object tem = XCAR (tail);
- if (CONSP (tem))
- tem = XCAR (tem);
- if (BUFFERP (tem) && !BUFFER_LIVE_P (XBUFFER (tem)))
- *prev = XCDR (tail);
- else
- {
- CONS_MARK (XCONS (tail));
- mark_object (XCAR (tail));
- prev = xcdr_addr (tail);
- }
- }
- mark_object (tail);
- return list;
-}
-
-/* Determine type of generic Lisp_Object and mark it accordingly. */
-
-void
-mark_object (Lisp_Object arg)
-{
- register Lisp_Object obj = arg;
-#ifdef GC_CHECK_MARKED_OBJECTS
- void *po;
- struct mem_node *m;
-#endif
- ptrdiff_t cdr_count = 0;
-
- loop:
-
- if (PURE_POINTER_P (XPNTR (obj)))
- return;
-
- last_marked[last_marked_index++] = obj;
- if (last_marked_index == LAST_MARKED_SIZE)
- last_marked_index = 0;
-
- /* Perform some sanity checks on the objects marked here. Abort if
- we encounter an object we know is bogus. This increases GC time
- by ~80%, and requires compilation with GC_MARK_STACK != 0. */
-#ifdef GC_CHECK_MARKED_OBJECTS
-
- po = (void *) XPNTR (obj);
-
- /* Check that the object pointed to by PO is known to be a Lisp
- structure allocated from the heap. */
-#define CHECK_ALLOCATED() \
- do { \
- m = mem_find (po); \
- if (m == MEM_NIL) \
- emacs_abort (); \
- } while (0)
-
- /* Check that the object pointed to by PO is live, using predicate
- function LIVEP. */
-#define CHECK_LIVE(LIVEP) \
- do { \
- if (!LIVEP (m, po)) \
- emacs_abort (); \
- } while (0)
-
- /* Check both of the above conditions. */
-#define CHECK_ALLOCATED_AND_LIVE(LIVEP) \
- do { \
- CHECK_ALLOCATED (); \
- CHECK_LIVE (LIVEP); \
- } while (0) \
-
-#else /* not GC_CHECK_MARKED_OBJECTS */
-
-#define CHECK_LIVE(LIVEP) (void) 0
-#define CHECK_ALLOCATED_AND_LIVE(LIVEP) (void) 0
-
-#endif /* not GC_CHECK_MARKED_OBJECTS */
-
- switch (XTYPE (obj))
- {
- case Lisp_String:
- {
- register struct Lisp_String *ptr = XSTRING (obj);
- if (STRING_MARKED_P (ptr))
- break;
- CHECK_ALLOCATED_AND_LIVE (live_string_p);
- MARK_STRING (ptr);
- MARK_INTERVAL_TREE (ptr->intervals);
-#ifdef GC_CHECK_STRING_BYTES
- /* Check that the string size recorded in the string is the
- same as the one recorded in the sdata structure. */
- string_bytes (ptr);
-#endif /* GC_CHECK_STRING_BYTES */
- }
- break;
-
- case Lisp_Vectorlike:
- {
- register struct Lisp_Vector *ptr = XVECTOR (obj);
- register ptrdiff_t pvectype;
-
- if (VECTOR_MARKED_P (ptr))
- break;
-
-#ifdef GC_CHECK_MARKED_OBJECTS
- m = mem_find (po);
- if (m == MEM_NIL && !SUBRP (obj))
- emacs_abort ();
-#endif /* GC_CHECK_MARKED_OBJECTS */
-
- if (ptr->header.size & PSEUDOVECTOR_FLAG)
- pvectype = ((ptr->header.size & PVEC_TYPE_MASK)
- >> PSEUDOVECTOR_AREA_BITS);
- else
- pvectype = PVEC_NORMAL_VECTOR;
-
- if (pvectype != PVEC_SUBR && pvectype != PVEC_BUFFER)
- CHECK_LIVE (live_vector_p);
-
- switch (pvectype)
- {
- case PVEC_BUFFER:
-#ifdef GC_CHECK_MARKED_OBJECTS
- {
- struct buffer *b;
- FOR_EACH_BUFFER (b)
- if (b == po)
- break;
- if (b == NULL)
- emacs_abort ();
- }
-#endif /* GC_CHECK_MARKED_OBJECTS */
- mark_buffer ((struct buffer *) ptr);
- break;
-
- case PVEC_COMPILED:
- { /* We could treat this just like a vector, but it is better
- to save the COMPILED_CONSTANTS element for last and avoid
- recursion there. */
- int size = ptr->header.size & PSEUDOVECTOR_SIZE_MASK;
- int i;
-
- VECTOR_MARK (ptr);
- for (i = 0; i < size; i++)
- if (i != COMPILED_CONSTANTS)
- mark_object (ptr->contents[i]);
- if (size > COMPILED_CONSTANTS)
- {
- obj = ptr->contents[COMPILED_CONSTANTS];
- goto loop;
- }
- }
- break;
-
- case PVEC_FRAME:
- {
- struct frame *f = (struct frame *) ptr;
-
- mark_vectorlike (ptr);
- mark_face_cache (f->face_cache);
-#ifdef HAVE_WINDOW_SYSTEM
- if (FRAME_WINDOW_P (f) && FRAME_X_OUTPUT (f))
- {
- struct font *font = FRAME_FONT (f);
-
- if (font && !VECTOR_MARKED_P (font))
- mark_vectorlike ((struct Lisp_Vector *) font);
- }
-#endif
- }
- break;
-
- case PVEC_WINDOW:
- {
- struct window *w = (struct window *) ptr;
-
- mark_vectorlike (ptr);
-
- /* Mark glyph matrices, if any. Marking window
- matrices is sufficient because frame matrices
- use the same glyph memory. */
- if (w->current_matrix)
- {
- mark_glyph_matrix (w->current_matrix);
- mark_glyph_matrix (w->desired_matrix);
- }
-
- /* Filter out killed buffers from both buffer lists
- in attempt to help GC to reclaim killed buffers faster.
- We can do it elsewhere for live windows, but this is the
- best place to do it for dead windows. */
- wset_prev_buffers
- (w, mark_discard_killed_buffers (w->prev_buffers));
- wset_next_buffers
- (w, mark_discard_killed_buffers (w->next_buffers));
- }
- break;
-
- case PVEC_HASH_TABLE:
- {
- struct Lisp_Hash_Table *h = (struct Lisp_Hash_Table *) ptr;
-
- mark_vectorlike (ptr);
- mark_object (h->test.name);
- mark_object (h->test.user_hash_function);
- mark_object (h->test.user_cmp_function);
- /* If hash table is not weak, mark all keys and values.
- For weak tables, mark only the vector. */
- if (NILP (h->weak))
- mark_object (h->key_and_value);
- else
- VECTOR_MARK (XVECTOR (h->key_and_value));
- }
- break;
-
- case PVEC_CHAR_TABLE:
- mark_char_table (ptr);
- break;
-
- case PVEC_BOOL_VECTOR:
- /* No Lisp_Objects to mark in a bool vector. */
- VECTOR_MARK (ptr);
- break;
-
- case PVEC_SUBR:
- break;
-
- case PVEC_FREE:
- emacs_abort ();
-
- default:
- mark_vectorlike (ptr);
- }
- }
- break;
-
- case Lisp_Symbol:
- {
- register struct Lisp_Symbol *ptr = XSYMBOL (obj);
- struct Lisp_Symbol *ptrx;
-
- if (ptr->gcmarkbit)
- break;
- CHECK_ALLOCATED_AND_LIVE (live_symbol_p);
- ptr->gcmarkbit = 1;
- mark_object (ptr->function);
- mark_object (ptr->plist);
- switch (ptr->redirect)
- {
- case SYMBOL_PLAINVAL: mark_object (SYMBOL_VAL (ptr)); break;
- case SYMBOL_VARALIAS:
- {
- Lisp_Object tem;
- XSETSYMBOL (tem, SYMBOL_ALIAS (ptr));
- mark_object (tem);
- break;
- }
- case SYMBOL_LOCALIZED:
- {
- struct Lisp_Buffer_Local_Value *blv = SYMBOL_BLV (ptr);
- Lisp_Object where = blv->where;
- /* If the value is set up for a killed buffer or deleted
- frame, restore it's global binding. If the value is
- forwarded to a C variable, either it's not a Lisp_Object
- var, or it's staticpro'd already. */
- if ((BUFFERP (where) && !BUFFER_LIVE_P (XBUFFER (where)))
- || (FRAMEP (where) && !FRAME_LIVE_P (XFRAME (where))))
- swap_in_global_binding (ptr);
- mark_object (blv->where);
- mark_object (blv->valcell);
- mark_object (blv->defcell);
- break;
- }
- case SYMBOL_FORWARDED:
- /* If the value is forwarded to a buffer or keyboard field,
- these are marked when we see the corresponding object.
- And if it's forwarded to a C variable, either it's not
- a Lisp_Object var, or it's staticpro'd already. */
- break;
- default: emacs_abort ();
- }
- if (!PURE_POINTER_P (XSTRING (ptr->name)))
- MARK_STRING (XSTRING (ptr->name));
- MARK_INTERVAL_TREE (string_intervals (ptr->name));
-
- ptr = ptr->next;
- if (ptr)
- {
- ptrx = ptr; /* Use of ptrx avoids compiler bug on Sun. */
- XSETSYMBOL (obj, ptrx);
- goto loop;
- }
- }
- break;
-
- case Lisp_Misc:
- CHECK_ALLOCATED_AND_LIVE (live_misc_p);
-
- if (XMISCANY (obj)->gcmarkbit)
- break;
-
- switch (XMISCTYPE (obj))
- {
- case Lisp_Misc_Marker:
- /* DO NOT mark thru the marker's chain.
- The buffer's markers chain does not preserve markers from gc;
- instead, markers are removed from the chain when freed by gc. */
- XMISCANY (obj)->gcmarkbit = 1;
- break;
-
- case Lisp_Misc_Save_Value:
- XMISCANY (obj)->gcmarkbit = 1;
- {
- struct Lisp_Save_Value *ptr = XSAVE_VALUE (obj);
- /* If `save_type' is zero, `data[0].pointer' is the address
- of a memory area containing `data[1].integer' potential
- Lisp_Objects. */
- if (GC_MARK_STACK && ptr->save_type == SAVE_TYPE_MEMORY)
- {
- Lisp_Object *p = ptr->data[0].pointer;
- ptrdiff_t nelt;
- for (nelt = ptr->data[1].integer; nelt > 0; nelt--, p++)
- mark_maybe_object (*p);
- }
- else
- {
- /* Find Lisp_Objects in `data[N]' slots and mark them. */
- int i;
- for (i = 0; i < SAVE_VALUE_SLOTS; i++)
- if (save_type (ptr, i) == SAVE_OBJECT)
- mark_object (ptr->data[i].object);
- }
- }
- break;
-
- case Lisp_Misc_Overlay:
- mark_overlay (XOVERLAY (obj));
- break;
-
- default:
- emacs_abort ();
- }
- break;
-
- case Lisp_Cons:
- {
- register struct Lisp_Cons *ptr = XCONS (obj);
- if (CONS_MARKED_P (ptr))
- break;
- CHECK_ALLOCATED_AND_LIVE (live_cons_p);
- CONS_MARK (ptr);
- /* If the cdr is nil, avoid recursion for the car. */
- if (EQ (ptr->u.cdr, Qnil))
- {
- obj = ptr->car;
- cdr_count = 0;
- goto loop;
- }
- mark_object (ptr->car);
- obj = ptr->u.cdr;
- cdr_count++;
- if (cdr_count == mark_object_loop_halt)
- emacs_abort ();
- goto loop;
- }
-
- case Lisp_Float:
- CHECK_ALLOCATED_AND_LIVE (live_float_p);
- FLOAT_MARK (XFLOAT (obj));
- break;
-
- case_Lisp_Int:
- break;
-
- default:
- emacs_abort ();
- }
-
-#undef CHECK_LIVE
-#undef CHECK_ALLOCATED
-#undef CHECK_ALLOCATED_AND_LIVE
-}
-/* Mark the Lisp pointers in the terminal objects.
- Called by Fgarbage_collect. */
-
-static void
-mark_terminals (void)
-{
- struct terminal *t;
- for (t = terminal_list; t; t = t->next_terminal)
- {
- eassert (t->name != NULL);
-#ifdef HAVE_WINDOW_SYSTEM
- /* If a terminal object is reachable from a stacpro'ed object,
- it might have been marked already. Make sure the image cache
- gets marked. */
- mark_image_cache (t->image_cache);
-#endif /* HAVE_WINDOW_SYSTEM */
- if (!VECTOR_MARKED_P (t))
- mark_vectorlike ((struct Lisp_Vector *)t);
- }
-}
-
-
-
-/* Value is non-zero if OBJ will survive the current GC because it's
- either marked or does not need to be marked to survive. */
-
-bool
-survives_gc_p (Lisp_Object obj)
-{
- bool survives_p;
-
- switch (XTYPE (obj))
- {
- case_Lisp_Int:
- survives_p = 1;
- break;
-
- case Lisp_Symbol:
- survives_p = XSYMBOL (obj)->gcmarkbit;
- break;
-
- case Lisp_Misc:
- survives_p = XMISCANY (obj)->gcmarkbit;
- break;
-
- case Lisp_String:
- survives_p = STRING_MARKED_P (XSTRING (obj));
- break;
-
- case Lisp_Vectorlike:
- survives_p = SUBRP (obj) || VECTOR_MARKED_P (XVECTOR (obj));
- break;
-
- case Lisp_Cons:
- survives_p = CONS_MARKED_P (XCONS (obj));
- break;
-
- case Lisp_Float:
- survives_p = FLOAT_MARKED_P (XFLOAT (obj));
- break;
-
- default:
- emacs_abort ();
- }
-
- return survives_p || PURE_POINTER_P ((void *) XPNTR (obj));
-}
-
-
-\f
-
-NO_INLINE /* For better stack traces */
-static void
-sweep_conses (void)
-{
- register struct cons_block *cblk;
- struct cons_block **cprev = &cons_block;
- register int lim = cons_block_index;
- EMACS_INT num_free = 0, num_used = 0;
-
- cons_free_list = 0;
-
- for (cblk = cons_block; cblk; cblk = *cprev)
- {
- register int i = 0;
- int this_free = 0;
- int ilim = (lim + BITS_PER_INT - 1) / BITS_PER_INT;
-
- /* Scan the mark bits an int at a time. */
- for (i = 0; i < ilim; i++)
- {
- if (cblk->gcmarkbits[i] == -1)
- {
- /* Fast path - all cons cells for this int are marked. */
- cblk->gcmarkbits[i] = 0;
- num_used += BITS_PER_INT;
- }
- else
- {
- /* Some cons cells for this int are not marked.
- Find which ones, and free them. */
- int start, pos, stop;
-
- start = i * BITS_PER_INT;
- stop = lim - start;
- if (stop > BITS_PER_INT)
- stop = BITS_PER_INT;
- stop += start;
-
- for (pos = start; pos < stop; pos++)
- {
- if (!CONS_MARKED_P (&cblk->conses[pos]))
- {
- this_free++;
- cblk->conses[pos].u.chain = cons_free_list;
- cons_free_list = &cblk->conses[pos];
-#if GC_MARK_STACK
- cons_free_list->car = Vdead;
-#endif
- }
- else
- {
- num_used++;
- CONS_UNMARK (&cblk->conses[pos]);
- }
- }
- }
- }
-
- lim = CONS_BLOCK_SIZE;
- /* If this block contains only free conses and we have already
- seen more than two blocks worth of free conses then deallocate
- this block. */
- if (this_free == CONS_BLOCK_SIZE && num_free > CONS_BLOCK_SIZE)
- {
- *cprev = cblk->next;
- /* Unhook from the free list. */
- cons_free_list = cblk->conses[0].u.chain;
- lisp_align_free (cblk);
- }
- else
- {
- num_free += this_free;
- cprev = &cblk->next;
- }
- }
- total_conses = num_used;
- total_free_conses = num_free;
-}
-
-NO_INLINE /* For better stack traces */
-static void
-sweep_floats (void)
-{
- register struct float_block *fblk;
- struct float_block **fprev = &float_block;
- register int lim = float_block_index;
- EMACS_INT num_free = 0, num_used = 0;
-
- float_free_list = 0;
-
- for (fblk = float_block; fblk; fblk = *fprev)
- {
- register int i;
- int this_free = 0;
- for (i = 0; i < lim; i++)
- if (!FLOAT_MARKED_P (&fblk->floats[i]))
- {
- this_free++;
- fblk->floats[i].u.chain = float_free_list;
- float_free_list = &fblk->floats[i];
- }
- else
- {
- num_used++;
- FLOAT_UNMARK (&fblk->floats[i]);
- }
- lim = FLOAT_BLOCK_SIZE;
- /* If this block contains only free floats and we have already
- seen more than two blocks worth of free floats then deallocate
- this block. */
- if (this_free == FLOAT_BLOCK_SIZE && num_free > FLOAT_BLOCK_SIZE)
- {
- *fprev = fblk->next;
- /* Unhook from the free list. */
- float_free_list = fblk->floats[0].u.chain;
- lisp_align_free (fblk);
- }
- else
- {
- num_free += this_free;
- fprev = &fblk->next;
- }
- }
- total_floats = num_used;
- total_free_floats = num_free;
-}
-
-NO_INLINE /* For better stack traces */
-static void
-sweep_intervals (void)
-{
- register struct interval_block *iblk;
- struct interval_block **iprev = &interval_block;
- register int lim = interval_block_index;
- EMACS_INT num_free = 0, num_used = 0;
-
- interval_free_list = 0;
-
- for (iblk = interval_block; iblk; iblk = *iprev)
- {
- register int i;
- int this_free = 0;
-
- for (i = 0; i < lim; i++)
- {
- if (!iblk->intervals[i].gcmarkbit)
- {
- set_interval_parent (&iblk->intervals[i], interval_free_list);
- interval_free_list = &iblk->intervals[i];
- this_free++;
- }
- else
- {
- num_used++;
- iblk->intervals[i].gcmarkbit = 0;
- }
- }
- lim = INTERVAL_BLOCK_SIZE;
- /* If this block contains only free intervals and we have already
- seen more than two blocks worth of free intervals then
- deallocate this block. */
- if (this_free == INTERVAL_BLOCK_SIZE && num_free > INTERVAL_BLOCK_SIZE)
- {
- *iprev = iblk->next;
- /* Unhook from the free list. */
- interval_free_list = INTERVAL_PARENT (&iblk->intervals[0]);
- lisp_free (iblk);
- }
- else
- {
- num_free += this_free;
- iprev = &iblk->next;
- }
- }
- total_intervals = num_used;
- total_free_intervals = num_free;
-}
-
-NO_INLINE /* For better stack traces */
-static void
-sweep_symbols (void)
-{
- register struct symbol_block *sblk;
- struct symbol_block **sprev = &symbol_block;
- register int lim = symbol_block_index;
- EMACS_INT num_free = 0, num_used = 0;
-
- symbol_free_list = NULL;
-
- for (sblk = symbol_block; sblk; sblk = *sprev)
- {
- int this_free = 0;
- union aligned_Lisp_Symbol *sym = sblk->symbols;
- union aligned_Lisp_Symbol *end = sym + lim;
-
- for (; sym < end; ++sym)
- {
- /* Check if the symbol was created during loadup. In such a case
- it might be pointed to by pure bytecode which we don't trace,
- so we conservatively assume that it is live. */
- bool pure_p = PURE_POINTER_P (XSTRING (sym->s.name));
-
- if (!sym->s.gcmarkbit && !pure_p)
- {
- if (sym->s.redirect == SYMBOL_LOCALIZED)
- xfree (SYMBOL_BLV (&sym->s));
- sym->s.next = symbol_free_list;
- symbol_free_list = &sym->s;
-#if GC_MARK_STACK
- symbol_free_list->function = Vdead;
-#endif
- ++this_free;
- }
- else
- {
- ++num_used;
- if (!pure_p)
- eassert (!STRING_MARKED_P (XSTRING (sym->s.name)));
- sym->s.gcmarkbit = 0;
- }
- }
-
- lim = SYMBOL_BLOCK_SIZE;
- /* If this block contains only free symbols and we have already
- seen more than two blocks worth of free symbols then deallocate
- this block. */
- if (this_free == SYMBOL_BLOCK_SIZE && num_free > SYMBOL_BLOCK_SIZE)
- {
- *sprev = sblk->next;
- /* Unhook from the free list. */
- symbol_free_list = sblk->symbols[0].s.next;
- lisp_free (sblk);
- }
- else
- {
- num_free += this_free;
- sprev = &sblk->next;
- }
- }
- total_symbols = num_used;
- total_free_symbols = num_free;
-}
-
-NO_INLINE /* For better stack traces */
-static void
-sweep_misc (void)
-{
- register struct marker_block *mblk;
- struct marker_block **mprev = &marker_block;
- register int lim = marker_block_index;
- EMACS_INT num_free = 0, num_used = 0;
-
- /* Put all unmarked misc's on free list. For a marker, first
- unchain it from the buffer it points into. */
-
- marker_free_list = 0;
-
- for (mblk = marker_block; mblk; mblk = *mprev)
- {
- register int i;
- int this_free = 0;
-
- for (i = 0; i < lim; i++)
- {
- if (!mblk->markers[i].m.u_any.gcmarkbit)
- {
- if (mblk->markers[i].m.u_any.type == Lisp_Misc_Marker)
- unchain_marker (&mblk->markers[i].m.u_marker);
- /* Set the type of the freed object to Lisp_Misc_Free.
- We could leave the type alone, since nobody checks it,
- but this might catch bugs faster. */
- mblk->markers[i].m.u_marker.type = Lisp_Misc_Free;
- mblk->markers[i].m.u_free.chain = marker_free_list;
- marker_free_list = &mblk->markers[i].m;
- this_free++;
- }
- else
- {
- num_used++;
- mblk->markers[i].m.u_any.gcmarkbit = 0;
- }
- }
- lim = MARKER_BLOCK_SIZE;
- /* If this block contains only free markers and we have already
- seen more than two blocks worth of free markers then deallocate
- this block. */
- if (this_free == MARKER_BLOCK_SIZE && num_free > MARKER_BLOCK_SIZE)
- {
- *mprev = mblk->next;
- /* Unhook from the free list. */
- marker_free_list = mblk->markers[0].m.u_free.chain;
- lisp_free (mblk);
- }
- else
- {
- num_free += this_free;
- mprev = &mblk->next;
- }
- }
-
- total_markers = num_used;
- total_free_markers = num_free;
-}
-
-NO_INLINE /* For better stack traces */
-static void
-sweep_buffers (void)
-{
- register struct buffer *buffer, **bprev = &all_buffers;
-
- total_buffers = 0;
- for (buffer = all_buffers; buffer; buffer = *bprev)
- if (!VECTOR_MARKED_P (buffer))
- {
- *bprev = buffer->next;
- lisp_free (buffer);
- }
- else
- {
- VECTOR_UNMARK (buffer);
- /* Do not use buffer_(set|get)_intervals here. */
- buffer->text->intervals = balance_intervals (buffer->text->intervals);
- total_buffers++;
- bprev = &buffer->next;
- }
-}
-
-/* Sweep: find all structures not marked, and free them. */
-static void
-gc_sweep (void)
-{
- /* Remove or mark entries in weak hash tables.
- This must be done before any object is unmarked. */
- sweep_weak_hash_tables ();
-
- sweep_strings ();
- check_string_bytes (!noninteractive);
- sweep_conses ();
- sweep_floats ();
- sweep_intervals ();
- sweep_symbols ();
- sweep_misc ();
- sweep_buffers ();
- sweep_vectors ();
- check_string_bytes (!noninteractive);
-}
-
-\f
-/* Debugging aids. */
-
-DEFUN ("memory-limit", Fmemory_limit, Smemory_limit, 0, 0, 0,
- doc: /* Return the address of the last byte Emacs has allocated, divided by 1024.
-This may be helpful in debugging Emacs's memory usage.
-We divide the value by 1024 to make sure it fits in a Lisp integer. */)
- (void)
-{
- Lisp_Object end;
-
-#ifdef HAVE_NS
- /* Avoid warning. sbrk has no relation to memory allocated anyway. */
- XSETINT (end, 0);
-#else
- XSETINT (end, (intptr_t) (char *) sbrk (0) / 1024);
-#endif
-
- return end;
-}
-
-DEFUN ("memory-use-counts", Fmemory_use_counts, Smemory_use_counts, 0, 0, 0,
- doc: /* Return a list of counters that measure how much consing there has been.
-Each of these counters increments for a certain kind of object.
-The counters wrap around from the largest positive integer to zero.
-Garbage collection does not decrease them.
-The elements of the value are as follows:
- (CONSES FLOATS VECTOR-CELLS SYMBOLS STRING-CHARS MISCS INTERVALS STRINGS)
-All are in units of 1 = one object consed
-except for VECTOR-CELLS and STRING-CHARS, which count the total length of
-objects consed.
-MISCS include overlays, markers, and some internal types.
-Frames, windows, buffers, and subprocesses count as vectors
- (but the contents of a buffer's text do not count here). */)
- (void)
-{
- return listn (CONSTYPE_HEAP, 8,
- bounded_number (cons_cells_consed),
- bounded_number (floats_consed),
- bounded_number (vector_cells_consed),
- bounded_number (symbols_consed),
- bounded_number (string_chars_consed),
- bounded_number (misc_objects_consed),
- bounded_number (intervals_consed),
- bounded_number (strings_consed));
-}
-
-/* Find at most FIND_MAX symbols which have OBJ as their value or
- function. This is used in gdbinit's `xwhichsymbols' command. */
-
-Lisp_Object
-which_symbols (Lisp_Object obj, EMACS_INT find_max)
-{
- struct symbol_block *sblk;
- ptrdiff_t gc_count = inhibit_garbage_collection ();
- Lisp_Object found = Qnil;
-
- if (! DEADP (obj))
- {
- for (sblk = symbol_block; sblk; sblk = sblk->next)
- {
- union aligned_Lisp_Symbol *aligned_sym = sblk->symbols;
- int bn;
-
- for (bn = 0; bn < SYMBOL_BLOCK_SIZE; bn++, aligned_sym++)
- {
- struct Lisp_Symbol *sym = &aligned_sym->s;
- Lisp_Object val;
- Lisp_Object tem;
-
- if (sblk == symbol_block && bn >= symbol_block_index)
- break;
-
- XSETSYMBOL (tem, sym);
- val = find_symbol_value (tem);
- if (EQ (val, obj)
- || EQ (sym->function, obj)
- || (!NILP (sym->function)
- && COMPILEDP (sym->function)
- && EQ (AREF (sym->function, COMPILED_BYTECODE), obj))
- || (!NILP (val)
- && COMPILEDP (val)
- && EQ (AREF (val, COMPILED_BYTECODE), obj)))
- {
- found = Fcons (tem, found);
- if (--find_max == 0)
- goto out;
- }
- }
- }
- }
-
- out:
- unbind_to (gc_count, Qnil);
- return found;
-}
-
-#ifdef SUSPICIOUS_OBJECT_CHECKING
-
-static void *
-find_suspicious_object_in_range (void *begin, void *end)
-{
- char *begin_a = begin;
- char *end_a = end;
- int i;
-
- for (i = 0; i < ARRAYELTS (suspicious_objects); ++i)
- {
- char *suspicious_object = suspicious_objects[i];
- if (begin_a <= suspicious_object && suspicious_object < end_a)
- return suspicious_object;
- }
-
- return NULL;
-}
-
-static void
-detect_suspicious_free (void *ptr)
-{
- int i;
-
- eassert (ptr != NULL);
-
- for (i = 0; i < ARRAYELTS (suspicious_objects); ++i)
- if (suspicious_objects[i] == ptr)
- {
- struct suspicious_free_record *rec
- = &suspicious_free_history[suspicious_free_history_index++];
- if (suspicious_free_history_index ==
- ARRAYELTS (suspicious_free_history))
- {
- suspicious_free_history_index = 0;
- }
-
- memset (rec, 0, sizeof (*rec));
- rec->suspicious_object = ptr;
- backtrace (rec->backtrace, ARRAYELTS (rec->backtrace));
- suspicious_objects[i] = NULL;
- }
-}
-
-#endif /* SUSPICIOUS_OBJECT_CHECKING */
-
-DEFUN ("suspicious-object", Fsuspicious_object, Ssuspicious_object, 1, 1, 0,
- doc: /* Return OBJ, maybe marking it for extra scrutiny.
-If Emacs is compiled with suspicous object checking, capture
-a stack trace when OBJ is freed in order to help track down
-garbage collection bugs. Otherwise, do nothing and return OBJ. */)
- (Lisp_Object obj)
-{
-#ifdef SUSPICIOUS_OBJECT_CHECKING
- /* Right now, we care only about vectors. */
- if (VECTORLIKEP (obj))
- {
- suspicious_objects[suspicious_object_index++] = XVECTOR (obj);
- if (suspicious_object_index == ARRAYELTS (suspicious_objects))
- suspicious_object_index = 0;
- }
-#endif
- return obj;
-}
-
-#ifdef ENABLE_CHECKING
-
-bool suppress_checking;
-
-void
-die (const char *msg, const char *file, int line)
-{
- fprintf (stderr, "\r\n%s:%d: Emacs fatal error: assertion failed: %s\r\n",
- file, line, msg);
- terminate_due_to_signal (SIGABRT, INT_MAX);
-}
-#endif
-\f
-/* Initialization. */
-
-void
-init_alloc_once (void)
-{
- /* Used to do Vpurify_flag = Qt here, but Qt isn't set up yet! */
- purebeg = PUREBEG;
- pure_size = PURESIZE;
-
-#if GC_MARK_STACK || defined GC_MALLOC_CHECK
- mem_init ();
- Vdead = make_pure_string ("DEAD", 4, 4, 0);
-#endif
-
-#ifdef DOUG_LEA_MALLOC
- mallopt (M_TRIM_THRESHOLD, 128 * 1024); /* Trim threshold. */
- mallopt (M_MMAP_THRESHOLD, 64 * 1024); /* Mmap threshold. */
- mallopt (M_MMAP_MAX, MMAP_MAX_AREAS); /* Max. number of mmap'ed areas. */
-#endif
- init_strings ();
- init_vectors ();
-
- refill_memory_reserve ();
- gc_cons_threshold = GC_DEFAULT_THRESHOLD;
-}
-
-void
-init_alloc (void)
-{
- gcprolist = 0;
- byte_stack_list = 0;
-#if GC_MARK_STACK
-#if !defined GC_SAVE_REGISTERS_ON_STACK && !defined GC_SETJMP_WORKS
- setjmp_tested_p = longjmps_done = 0;
-#endif
-#endif
- Vgc_elapsed = make_float (0.0);
- gcs_done = 0;
-
-#if USE_VALGRIND
- valgrind_p = RUNNING_ON_VALGRIND != 0;
-#endif
-}
-
-void
-syms_of_alloc (void)
-{
- DEFVAR_INT ("gc-cons-threshold", gc_cons_threshold,
- doc: /* Number of bytes of consing between garbage collections.
-Garbage collection can happen automatically once this many bytes have been
-allocated since the last garbage collection. All data types count.
-
-Garbage collection happens automatically only when `eval' is called.
-
-By binding this temporarily to a large number, you can effectively
-prevent garbage collection during a part of the program.
-See also `gc-cons-percentage'. */);
-
- DEFVAR_LISP ("gc-cons-percentage", Vgc_cons_percentage,
- doc: /* Portion of the heap used for allocation.
-Garbage collection can happen automatically once this portion of the heap
-has been allocated since the last garbage collection.
-If this portion is smaller than `gc-cons-threshold', this is ignored. */);
- Vgc_cons_percentage = make_float (0.1);
-
- DEFVAR_INT ("pure-bytes-used", pure_bytes_used,
- doc: /* Number of bytes of shareable Lisp data allocated so far. */);
-
- DEFVAR_INT ("cons-cells-consed", cons_cells_consed,
- doc: /* Number of cons cells that have been consed so far. */);
-
- DEFVAR_INT ("floats-consed", floats_consed,
- doc: /* Number of floats that have been consed so far. */);
-
- DEFVAR_INT ("vector-cells-consed", vector_cells_consed,
- doc: /* Number of vector cells that have been consed so far. */);
-
- DEFVAR_INT ("symbols-consed", symbols_consed,
- doc: /* Number of symbols that have been consed so far. */);
-
- DEFVAR_INT ("string-chars-consed", string_chars_consed,
- doc: /* Number of string characters that have been consed so far. */);
-
- DEFVAR_INT ("misc-objects-consed", misc_objects_consed,
- doc: /* Number of miscellaneous objects that have been consed so far.
-These include markers and overlays, plus certain objects not visible
-to users. */);
-
- DEFVAR_INT ("intervals-consed", intervals_consed,
- doc: /* Number of intervals that have been consed so far. */);
-
- DEFVAR_INT ("strings-consed", strings_consed,
- doc: /* Number of strings that have been consed so far. */);
-
- DEFVAR_LISP ("purify-flag", Vpurify_flag,
- doc: /* Non-nil means loading Lisp code in order to dump an executable.
-This means that certain objects should be allocated in shared (pure) space.
-It can also be set to a hash-table, in which case this table is used to
-do hash-consing of the objects allocated to pure space. */);
-
- DEFVAR_BOOL ("garbage-collection-messages", garbage_collection_messages,
- doc: /* Non-nil means display messages at start and end of garbage collection. */);
- garbage_collection_messages = 0;
-
- DEFVAR_LISP ("post-gc-hook", Vpost_gc_hook,
- doc: /* Hook run after garbage collection has finished. */);
- Vpost_gc_hook = Qnil;
- DEFSYM (Qpost_gc_hook, "post-gc-hook");
-
- DEFVAR_LISP ("memory-signal-data", Vmemory_signal_data,
- doc: /* Precomputed `signal' argument for memory-full error. */);
- /* We build this in advance because if we wait until we need it, we might
- not be able to allocate the memory to hold it. */
- Vmemory_signal_data
- = listn (CONSTYPE_PURE, 2, Qerror,
- build_pure_c_string ("Memory exhausted--use M-x save-some-buffers then exit and restart Emacs"));
-
- DEFVAR_LISP ("memory-full", Vmemory_full,
- doc: /* Non-nil means Emacs cannot get much more Lisp memory. */);
- Vmemory_full = Qnil;
-
- DEFSYM (Qconses, "conses");
- DEFSYM (Qsymbols, "symbols");
- DEFSYM (Qmiscs, "miscs");
- DEFSYM (Qstrings, "strings");
- DEFSYM (Qvectors, "vectors");
- DEFSYM (Qfloats, "floats");
- DEFSYM (Qintervals, "intervals");
- DEFSYM (Qbuffers, "buffers");
- DEFSYM (Qstring_bytes, "string-bytes");
- DEFSYM (Qvector_slots, "vector-slots");
- DEFSYM (Qheap, "heap");
- DEFSYM (Qautomatic_gc, "Automatic GC");
-
- DEFSYM (Qgc_cons_threshold, "gc-cons-threshold");
- DEFSYM (Qchar_table_extra_slots, "char-table-extra-slots");
-
- DEFVAR_LISP ("gc-elapsed", Vgc_elapsed,
- doc: /* Accumulated time elapsed in garbage collections.
-The time is in seconds as a floating point value. */);
- DEFVAR_INT ("gcs-done", gcs_done,
- doc: /* Accumulated number of garbage collections done. */);
-
- defsubr (&Scons);
- defsubr (&Slist);
- defsubr (&Svector);
- defsubr (&Smake_byte_code);
- defsubr (&Smake_list);
- defsubr (&Smake_vector);
- defsubr (&Smake_string);
- defsubr (&Smake_bool_vector);
- defsubr (&Smake_symbol);
- defsubr (&Smake_marker);
- defsubr (&Spurecopy);
- defsubr (&Sgarbage_collect);
- defsubr (&Smemory_limit);
- defsubr (&Smemory_use_counts);
- defsubr (&Ssuspicious_object);
-
-#if GC_MARK_STACK == GC_USE_GCPROS_CHECK_ZOMBIES
- defsubr (&Sgc_status);
-#endif
-}
-
-/* When compiled with GCC, GDB might say "No enum type named
- pvec_type" if we don't have at least one symbol with that type, and
- then xbacktrace could fail. Similarly for the other enums and
- their values. Some non-GCC compilers don't like these constructs. */
-#ifdef __GNUC__
-union
-{
- enum CHARTAB_SIZE_BITS CHARTAB_SIZE_BITS;
- enum CHAR_TABLE_STANDARD_SLOTS CHAR_TABLE_STANDARD_SLOTS;
- enum char_bits char_bits;
- enum CHECK_LISP_OBJECT_TYPE CHECK_LISP_OBJECT_TYPE;
- enum DEFAULT_HASH_SIZE DEFAULT_HASH_SIZE;
- enum enum_USE_LSB_TAG enum_USE_LSB_TAG;
- enum FLOAT_TO_STRING_BUFSIZE FLOAT_TO_STRING_BUFSIZE;
- enum Lisp_Bits Lisp_Bits;
- enum Lisp_Compiled Lisp_Compiled;
- enum maxargs maxargs;
- enum MAX_ALLOCA MAX_ALLOCA;
- enum More_Lisp_Bits More_Lisp_Bits;
- enum pvec_type pvec_type;
-} const EXTERNALLY_VISIBLE gdb_make_enums_visible = {0};
-#endif /* __GNUC__ */
+/* Storage allocation and gc for GNU Emacs Lisp interpreter.
+
+Copyright (C) 1985-1986, 1988, 1993-1995, 1997-2014 Free Software
+Foundation, Inc.
+
+This file is part of GNU Emacs.
+
+GNU Emacs is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+GNU Emacs is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
+
+#include <config.h>
+
+#include <stdio.h>
+
+#ifdef ENABLE_CHECKING
+#include <signal.h> /* For SIGABRT. */
+#endif
+
+#ifdef HAVE_PTHREAD
+#include <pthread.h>
+#endif
+
+#include <gc.h>
+
+#include "lisp.h"
+#include "process.h"
+#include "intervals.h"
+#include "character.h"
+#include "buffer.h"
+#include "window.h"
+#include "keyboard.h"
+#include "frame.h"
+#include "termhooks.h" /* For struct terminal. */
+#ifdef HAVE_WINDOW_SYSTEM
+#include TERM_HEADER
+#endif /* HAVE_WINDOW_SYSTEM */
+
+#include <verify.h>
+#include <execinfo.h> /* For backtrace. */
+
+#if (defined ENABLE_CHECKING \
+ && defined HAVE_VALGRIND_VALGRIND_H \
+ && !defined USE_VALGRIND)
+# define USE_VALGRIND 1
+#endif
+
+#if USE_VALGRIND
+#include <valgrind/valgrind.h>
+#include <valgrind/memcheck.h>
+static bool valgrind_p;
+#endif
+
+#include <unistd.h>
+#include <fcntl.h>
+
+#ifdef USE_GTK
+# include "gtkutil.h"
+#endif
+#ifdef WINDOWSNT
+#include "w32.h"
+#include "w32heap.h" /* for sbrk */
+#endif
+
+/* Default value of gc_cons_threshold (see below). */
+
+#define GC_DEFAULT_THRESHOLD (100000 * word_size)
+
+/* Global variables. */
+struct emacs_globals globals;
+
+/* Number of bytes of consing done since the last gc. */
+
+EMACS_INT consing_since_gc;
+
+/* Similar minimum, computed from Vgc_cons_percentage. */
+
+EMACS_INT gc_relative_threshold;
+
+/* Minimum number of bytes of consing since GC before next GC,
+ when memory is full. */
+
+EMACS_INT memory_full_cons_threshold = 1 << 10;
+
+/* True during GC. */
+
+bool gc_in_progress;
+
+/* True means abort if try to GC.
+ This is for code which is written on the assumption that
+ no GC will happen, so as to verify that assumption. */
+
+bool abort_on_gc;
+
+/* Number of live and free conses etc. */
+
+static EMACS_INT total_conses, total_markers, total_symbols, total_buffers;
+static EMACS_INT total_free_conses, total_free_markers, total_free_symbols;
+static EMACS_INT total_free_floats, total_floats;
+
+/* Points to memory space allocated as "spare", to be freed if we run
+ out of memory. */
+
+static void *spare_memory;
+
+/* Amount of spare memory to keep in large reserve block, or to see
+ whether this much is available when malloc fails on a larger request. */
+
+#define SPARE_MEMORY (1 << 15)
+
+/* If nonzero, this is a warning delivered by malloc and not yet
+ displayed. */
+
+const char *pending_malloc_warning;
+
+static Lisp_Object Qgc_cons_threshold;
+Lisp_Object Qchar_table_extra_slots;
+
+/* Hook run after GC has finished. */
+
+static Lisp_Object Qpost_gc_hook;
+
+#if !defined REL_ALLOC || defined SYSTEM_MALLOC
+static void refill_memory_reserve (void);
+#endif
+static Lisp_Object make_empty_string (int);
+extern Lisp_Object which_symbols (Lisp_Object, EMACS_INT) EXTERNALLY_VISIBLE;
+
+#ifndef DEADP
+# define DEADP(x) 0
+#endif
+
+/* Recording what needs to be marked for gc. */
+
+struct gcpro *gcprolist;
+\f
+/************************************************************************
+ Malloc
+ ************************************************************************/
+
+/* Function malloc calls this if it finds we are near exhausting storage. */
+
+void
+malloc_warning (const char *str)
+{
+ pending_malloc_warning = str;
+}
+
+
+/* Display an already-pending malloc warning. */
+
+void
+display_malloc_warning (void)
+{
+ call3 (intern ("display-warning"),
+ intern ("alloc"),
+ build_string (pending_malloc_warning),
+ intern ("emergency"));
+ pending_malloc_warning = 0;
+}
+\f
+/* Called if we can't allocate relocatable space for a buffer. */
+
+void
+buffer_memory_full (ptrdiff_t nbytes)
+{
+ /* If buffers use the relocating allocator, no need to free
+ spare_memory, because we may have plenty of malloc space left
+ that we could get, and if we don't, the malloc that fails will
+ itself cause spare_memory to be freed. If buffers don't use the
+ relocating allocator, treat this like any other failing
+ malloc. */
+
+#ifndef REL_ALLOC
+ memory_full (nbytes);
+#else
+ /* This used to call error, but if we've run out of memory, we could
+ get infinite recursion trying to build the string. */
+ xsignal (Qnil, Vmemory_signal_data);
+#endif
+}
+
+/* Like GC_MALLOC but check for no memory. */
+
+void *
+xmalloc (size_t size)
+{
+ void *val = GC_MALLOC (size);
+ if (!val && size)
+ memory_full (size);
+ return val;
+}
+
+/* Like the above, but zeroes out the memory just allocated. */
+
+void *
+xzalloc (size_t size)
+{
+ return xmalloc (size);
+}
+
+/* Like GC_REALLOC but check for no memory. */
+
+void *
+xrealloc (void *block, size_t size)
+{
+ void *val = GC_REALLOC (block, size);
+ if (!val && size)
+ memory_full (size);
+ return val;
+}
+
+void
+xfree (void *block)
+{
+ return;
+}
+
+/* Allocate pointerless memory. */
+
+void *
+xmalloc_atomic (size_t size)
+{
+ void *val = GC_MALLOC_ATOMIC (size);
+ if (! val && size)
+ memory_full (size);
+ return val;
+}
+
+void *
+xzalloc_atomic (size_t size)
+{
+ return xmalloc_atomic (size);
+}
+
+/* Allocate uncollectable memory. */
+
+void *
+xmalloc_uncollectable (size_t size)
+{
+ void *val = GC_MALLOC_UNCOLLECTABLE (size);
+ if (! val && size)
+ memory_full (size);
+ return val;
+}
+
+/* Allocate memory, but if memory is exhausted, return NULL instead of
+ signalling an error. */
+
+void *
+xmalloc_unsafe (size_t size)
+{
+ return GC_MALLOC (size);
+}
+
+/* Allocate pointerless memory, but if memory is exhausted, return
+ NULL instead of signalling an error. */
+
+void *
+xmalloc_atomic_unsafe (size_t size)
+{
+ return GC_MALLOC_ATOMIC (size);
+}
+
+/* Other parts of Emacs pass large int values to allocator functions
+ expecting ptrdiff_t. This is portable in practice, but check it to
+ be safe. */
+verify (INT_MAX <= PTRDIFF_MAX);
+
+
+/* Allocate an array of NITEMS items, each of size ITEM_SIZE.
+ Signal an error on memory exhaustion. */
+
+void *
+xnmalloc (ptrdiff_t nitems, ptrdiff_t item_size)
+{
+ eassert (0 <= nitems && 0 < item_size);
+ if (min (PTRDIFF_MAX, SIZE_MAX) / item_size < nitems)
+ memory_full (SIZE_MAX);
+ return xmalloc (nitems * item_size);
+}
+
+/* Like xnmalloc for pointerless objects. */
+
+void *
+xnmalloc_atomic (ptrdiff_t nitems, ptrdiff_t item_size)
+{
+ eassert (0 <= nitems && 0 < item_size);
+ if (min (PTRDIFF_MAX, SIZE_MAX) / item_size < nitems)
+ memory_full (SIZE_MAX);
+ return xmalloc_atomic (nitems * item_size);
+}
+
+/* Reallocate an array PA to make it of NITEMS items, each of size ITEM_SIZE.
+ Signal an error on memory exhaustion. */
+
+void *
+xnrealloc (void *pa, ptrdiff_t nitems, ptrdiff_t item_size)
+{
+ eassert (0 <= nitems && 0 < item_size);
+ if (min (PTRDIFF_MAX, SIZE_MAX) / item_size < nitems)
+ memory_full (SIZE_MAX);
+ return xrealloc (pa, nitems * item_size);
+}
+
+
+/* Grow PA, which points to an array of *NITEMS items, and return the
+ location of the reallocated array, updating *NITEMS to reflect its
+ new size. The new array will contain at least NITEMS_INCR_MIN more
+ items, but will not contain more than NITEMS_MAX items total.
+ ITEM_SIZE is the size of each item, in bytes.
+
+ ITEM_SIZE and NITEMS_INCR_MIN must be positive. *NITEMS must be
+ nonnegative. If NITEMS_MAX is -1, it is treated as if it were
+ infinity.
+
+ If PA is null, then allocate a new array instead of reallocating
+ the old one.
+
+ If memory exhaustion occurs, set *NITEMS to zero if PA is null, and
+ signal an error (i.e., do not return).
+
+ Thus, to grow an array A without saving its old contents, do
+ { xfree (A); A = NULL; A = xpalloc (NULL, &AITEMS, ...); }.
+ The A = NULL avoids a dangling pointer if xpalloc exhausts memory
+ and signals an error, and later this code is reexecuted and
+ attempts to free A. */
+
+void *
+xpalloc (void *pa, ptrdiff_t *nitems, ptrdiff_t nitems_incr_min,
+ ptrdiff_t nitems_max, ptrdiff_t item_size)
+{
+ /* The approximate size to use for initial small allocation
+ requests. This is the largest "small" request for the GNU C
+ library malloc. */
+ enum { DEFAULT_MXFAST = 64 * sizeof (size_t) / 4 };
+
+ /* If the array is tiny, grow it to about (but no greater than)
+ DEFAULT_MXFAST bytes. Otherwise, grow it by about 50%. */
+ ptrdiff_t n = *nitems;
+ ptrdiff_t tiny_max = DEFAULT_MXFAST / item_size - n;
+ ptrdiff_t half_again = n >> 1;
+ ptrdiff_t incr_estimate = max (tiny_max, half_again);
+
+ /* Adjust the increment according to three constraints: NITEMS_INCR_MIN,
+ NITEMS_MAX, and what the C language can represent safely. */
+ ptrdiff_t C_language_max = min (PTRDIFF_MAX, SIZE_MAX) / item_size;
+ ptrdiff_t n_max = (0 <= nitems_max && nitems_max < C_language_max
+ ? nitems_max : C_language_max);
+ ptrdiff_t nitems_incr_max = n_max - n;
+ ptrdiff_t incr = max (nitems_incr_min, min (incr_estimate, nitems_incr_max));
+
+ eassert (0 < item_size && 0 < nitems_incr_min && 0 <= n && -1 <= nitems_max);
+ if (! pa)
+ *nitems = 0;
+ if (nitems_incr_max < incr)
+ memory_full (SIZE_MAX);
+ n += incr;
+ pa = xrealloc (pa, n * item_size);
+ *nitems = n;
+ return pa;
+}
+
+
+/* Like strdup, but uses xmalloc. */
+
+char *
+xstrdup (const char *s)
+{
+ ptrdiff_t size;
+ eassert (s);
+ size = strlen (s) + 1;
+ return memcpy (xmalloc_atomic (size), s, size);
+}
+
+/* Like above, but duplicates Lisp string to C string. */
+
+char *
+xlispstrdup (Lisp_Object string)
+{
+ ptrdiff_t size = SBYTES (string) + 1;
+ return memcpy (xmalloc_atomic (size), SSDATA (string), size);
+}
+
+/* Assign to *PTR a copy of STRING, freeing any storage *PTR formerly
+ pointed to. If STRING is null, assign it without copying anything.
+ Allocate before freeing, to avoid a dangling pointer if allocation
+ fails. */
+
+void
+dupstring (char **ptr, char const *string)
+{
+ char *old = *ptr;
+ *ptr = string ? xstrdup (string) : 0;
+ xfree (old);
+}
+
+
+/* Like putenv, but (1) use the equivalent of xmalloc and (2) the
+ argument is a const pointer. */
+
+void
+xputenv (char const *string)
+{
+ if (putenv ((char *) string) != 0)
+ memory_full (0);
+}
+\f
+/***********************************************************************
+ Interval Allocation
+ ***********************************************************************/
+
+/* Return a new interval. */
+
+INTERVAL
+make_interval (void)
+{
+ INTERVAL val = xmalloc (sizeof (struct interval));
+ RESET_INTERVAL (val);
+ return val;
+}
+
+/***********************************************************************
+ String Allocation
+ ***********************************************************************/
+
+/* Initialize string allocation. Called from init_alloc_once. */
+
+static void
+init_strings (void)
+{
+ empty_unibyte_string = make_empty_string (0);
+ empty_multibyte_string = make_empty_string (1);
+}
+
+/* Return a new Lisp_String. */
+
+static Lisp_Object
+allocate_string (void)
+{
+ return scm_make_smob (lisp_string_tag);
+}
+
+
+/* Set up Lisp_String S for holding NCHARS characters, NBYTES bytes,
+ plus a NUL byte at the end. Allocate an sdata structure for S, and
+ set S->data to its `u.data' member. Store a NUL byte at the end of
+ S->data. Set S->size to NCHARS and S->size_byte to NBYTES. Free
+ S->data if it was initially non-null. */
+
+void
+allocate_string_data (Lisp_Object string,
+ EMACS_INT nchars, EMACS_INT nbytes)
+{
+ struct Lisp_String *s = (void *) SCM_SMOB_DATA (string);
+ unsigned char *data;
+
+ if (STRING_BYTES_BOUND < nbytes)
+ string_overflow ();
+
+ data = GC_MALLOC_ATOMIC (nbytes + 1);
+ s->data = data;
+ s->size = nchars;
+ s->size_byte = nbytes;
+ s->data[nbytes] = '\0';
+}
+
+void
+string_overflow (void)
+{
+ error ("Maximum string size exceeded");
+}
+
+static Lisp_Object
+make_empty_string (int multibyte)
+{
+ Lisp_Object string;
+
+ string = allocate_string ();
+ allocate_string_data (string, 0, 0);
+ if (! multibyte)
+ STRING_SET_UNIBYTE (string);
+
+ return string;
+}
+
+DEFUN ("make-string", Fmake_string, Smake_string, 2, 2, 0,
+ doc: /* Return a newly created string of length LENGTH, with INIT in each element.
+LENGTH must be an integer.
+INIT must be an integer that represents a character. */)
+ (Lisp_Object length, Lisp_Object init)
+{
+ register Lisp_Object val;
+ int c;
+ EMACS_INT nbytes;
+
+ CHECK_NATNUM (length);
+ CHECK_CHARACTER (init);
+
+ c = XFASTINT (init);
+ if (ASCII_CHAR_P (c))
+ {
+ nbytes = XINT (length);
+ val = make_uninit_string (nbytes);
+ memset (SDATA (val), c, nbytes);
+ SDATA (val)[nbytes] = 0;
+ }
+ else
+ {
+ unsigned char str[MAX_MULTIBYTE_LENGTH];
+ ptrdiff_t len = CHAR_STRING (c, str);
+ EMACS_INT string_len = XINT (length);
+ unsigned char *p, *beg, *end;
+
+ if (string_len > STRING_BYTES_BOUND / len)
+ string_overflow ();
+ nbytes = len * string_len;
+ val = make_uninit_multibyte_string (string_len, nbytes);
+ for (beg = SDATA (val), p = beg, end = beg + nbytes; p < end; p += len)
+ {
+ /* First time we just copy `str' to the data of `val'. */
+ if (p == beg)
+ memcpy (p, str, len);
+ else
+ {
+ /* Next time we copy largest possible chunk from
+ initialized to uninitialized part of `val'. */
+ len = min (p - beg, end - p);
+ memcpy (p, beg, len);
+ }
+ }
+ *p = 0;
+ }
+
+ return val;
+}
+
+/* Fill A with 1 bits if INIT is non-nil, and with 0 bits otherwise.
+ Return A. */
+
+Lisp_Object
+bool_vector_fill (Lisp_Object a, Lisp_Object init)
+{
+ EMACS_INT nbits = bool_vector_size (a);
+ if (0 < nbits)
+ {
+ unsigned char *data = bool_vector_uchar_data (a);
+ int pattern = NILP (init) ? 0 : (1 << BOOL_VECTOR_BITS_PER_CHAR) - 1;
+ ptrdiff_t nbytes = bool_vector_bytes (nbits);
+ int last_mask = ~ (~0u << ((nbits - 1) % BOOL_VECTOR_BITS_PER_CHAR + 1));
+ memset (data, pattern, nbytes - 1);
+ data[nbytes - 1] = pattern & last_mask;
+ }
+ return a;
+}
+
+/* Return a newly allocated, uninitialized bool vector of size NBITS. */
+
+Lisp_Object
+make_uninit_bool_vector (EMACS_INT nbits)
+{
+ Lisp_Object val;
+ EMACS_INT words = bool_vector_words (nbits);
+ EMACS_INT word_bytes = words * sizeof (bits_word);
+ EMACS_INT needed_elements = ((bool_header_size - header_size + word_bytes
+ + word_size - 1)
+ / word_size);
+ struct Lisp_Bool_Vector *p
+ = (struct Lisp_Bool_Vector *) allocate_vector (needed_elements);
+ XSETVECTOR (val, p);
+ XSETPVECTYPESIZE (XVECTOR (val), PVEC_BOOL_VECTOR, 0, 0);
+ p->size = nbits;
+
+ /* Clear padding at the end. */
+ if (words)
+ p->data[words - 1] = 0;
+
+ return val;
+}
+
+DEFUN ("make-bool-vector", Fmake_bool_vector, Smake_bool_vector, 2, 2, 0,
+ doc: /* Return a new bool-vector of length LENGTH, using INIT for each element.
+LENGTH must be a number. INIT matters only in whether it is t or nil. */)
+ (Lisp_Object length, Lisp_Object init)
+{
+ Lisp_Object val;
+
+ CHECK_NATNUM (length);
+ val = make_uninit_bool_vector (XFASTINT (length));
+ return bool_vector_fill (val, init);
+}
+
+DEFUN ("bool-vector", Fbool_vector, Sbool_vector, 0, MANY, 0,
+ doc: /* Return a new bool-vector with specified arguments as elements.
+Any number of arguments, even zero arguments, are allowed.
+usage: (bool-vector &rest OBJECTS) */)
+ (ptrdiff_t nargs, Lisp_Object *args)
+{
+ ptrdiff_t i;
+ Lisp_Object vector;
+
+ vector = make_uninit_bool_vector (nargs);
+ for (i = 0; i < nargs; i++)
+ bool_vector_set (vector, i, !NILP (args[i]));
+
+ return vector;
+}
+
+/* Make a string from NBYTES bytes at CONTENTS, and compute the number
+ of characters from the contents. This string may be unibyte or
+ multibyte, depending on the contents. */
+
+Lisp_Object
+make_string (const char *contents, ptrdiff_t nbytes)
+{
+ register Lisp_Object val;
+ ptrdiff_t nchars, multibyte_nbytes;
+
+ parse_str_as_multibyte ((const unsigned char *) contents, nbytes,
+ &nchars, &multibyte_nbytes);
+ if (nbytes == nchars || nbytes != multibyte_nbytes)
+ /* CONTENTS contains no multibyte sequences or contains an invalid
+ multibyte sequence. We must make unibyte string. */
+ val = make_unibyte_string (contents, nbytes);
+ else
+ val = make_multibyte_string (contents, nchars, nbytes);
+ return val;
+}
+
+
+/* Make an unibyte string from LENGTH bytes at CONTENTS. */
+
+Lisp_Object
+make_unibyte_string (const char *contents, ptrdiff_t length)
+{
+ register Lisp_Object val;
+ val = make_uninit_string (length);
+ memcpy (SDATA (val), contents, length);
+ return val;
+}
+
+
+/* Make a multibyte string from NCHARS characters occupying NBYTES
+ bytes at CONTENTS. */
+
+Lisp_Object
+make_multibyte_string (const char *contents,
+ ptrdiff_t nchars, ptrdiff_t nbytes)
+{
+ register Lisp_Object val;
+ val = make_uninit_multibyte_string (nchars, nbytes);
+ memcpy (SDATA (val), contents, nbytes);
+ return val;
+}
+
+
+/* Make a string from NCHARS characters occupying NBYTES bytes at
+ CONTENTS. It is a multibyte string if NBYTES != NCHARS. */
+
+Lisp_Object
+make_string_from_bytes (const char *contents,
+ ptrdiff_t nchars, ptrdiff_t nbytes)
+{
+ register Lisp_Object val;
+ val = make_uninit_multibyte_string (nchars, nbytes);
+ memcpy (SDATA (val), contents, nbytes);
+ if (SBYTES (val) == SCHARS (val))
+ STRING_SET_UNIBYTE (val);
+ return val;
+}
+
+
+/* Make a string from NCHARS characters occupying NBYTES bytes at
+ CONTENTS. The argument MULTIBYTE controls whether to label the
+ string as multibyte. If NCHARS is negative, it counts the number of
+ characters by itself. */
+
+Lisp_Object
+make_specified_string (const char *contents,
+ ptrdiff_t nchars, ptrdiff_t nbytes, bool multibyte)
+{
+ Lisp_Object val;
+
+ if (nchars < 0)
+ {
+ if (multibyte)
+ nchars = multibyte_chars_in_text ((const unsigned char *) contents,
+ nbytes);
+ else
+ nchars = nbytes;
+ }
+ val = make_uninit_multibyte_string (nchars, nbytes);
+ memcpy (SDATA (val), contents, nbytes);
+ if (!multibyte)
+ STRING_SET_UNIBYTE (val);
+ return val;
+}
+
+
+/* Return an unibyte Lisp_String set up to hold LENGTH characters
+ occupying LENGTH bytes. */
+
+Lisp_Object
+make_uninit_string (EMACS_INT length)
+{
+ Lisp_Object val;
+
+ if (!length)
+ return empty_unibyte_string;
+ val = make_uninit_multibyte_string (length, length);
+ STRING_SET_UNIBYTE (val);
+ return val;
+}
+
+
+/* Return a multibyte Lisp_String set up to hold NCHARS characters
+ which occupy NBYTES bytes. */
+
+Lisp_Object
+make_uninit_multibyte_string (EMACS_INT nchars, EMACS_INT nbytes)
+{
+ Lisp_Object string;
+
+ if (nchars < 0)
+ emacs_abort ();
+ if (!nbytes)
+ return empty_multibyte_string;
+
+ string = allocate_string ();
+ ((struct Lisp_String *) SCM_SMOB_DATA (string))->intervals = NULL;
+ allocate_string_data (string, nchars, nbytes);
+ return string;
+}
+
+/* Print arguments to BUF according to a FORMAT, then return
+ a Lisp_String initialized with the data from BUF. */
+
+Lisp_Object
+make_formatted_string (char *buf, const char *format, ...)
+{
+ va_list ap;
+ int length;
+
+ va_start (ap, format);
+ length = vsprintf (buf, format, ap);
+ va_end (ap);
+ return make_string (buf, length);
+}
+
+\f
+/***********************************************************************
+ Float Allocation
+ ***********************************************************************/
+
+/* Return a new float object with value FLOAT_VALUE. */
+
+Lisp_Object
+make_float (double float_value)
+{
+ return scm_from_double (float_value);
+}
+
+\f
+/***********************************************************************
+ Cons Allocation
+ ***********************************************************************/
+
+DEFUN ("cons", Fcons, Scons, 2, 2, 0,
+ doc: /* Create a new cons, give it CAR and CDR as components, and return it. */)
+ (Lisp_Object car, Lisp_Object cdr)
+{
+ return scm_cons (car, cdr);
+}
+
+/* Make a list of 1, 2, 3, 4 or 5 specified objects. */
+
+Lisp_Object
+list1 (Lisp_Object arg1)
+{
+ return Fcons (arg1, Qnil);
+}
+
+Lisp_Object
+list2 (Lisp_Object arg1, Lisp_Object arg2)
+{
+ return Fcons (arg1, Fcons (arg2, Qnil));
+}
+
+
+Lisp_Object
+list3 (Lisp_Object arg1, Lisp_Object arg2, Lisp_Object arg3)
+{
+ return Fcons (arg1, Fcons (arg2, Fcons (arg3, Qnil)));
+}
+
+
+Lisp_Object
+list4 (Lisp_Object arg1, Lisp_Object arg2, Lisp_Object arg3, Lisp_Object arg4)
+{
+ return Fcons (arg1, Fcons (arg2, Fcons (arg3, Fcons (arg4, Qnil))));
+}
+
+
+Lisp_Object
+list5 (Lisp_Object arg1, Lisp_Object arg2, Lisp_Object arg3, Lisp_Object arg4, Lisp_Object arg5)
+{
+ return Fcons (arg1, Fcons (arg2, Fcons (arg3, Fcons (arg4,
+ Fcons (arg5, Qnil)))));
+}
+
+/* Make a list of COUNT Lisp_Objects, where ARG is the
+ first one. Allocate conses from pure space if TYPE
+ is CONSTYPE_PURE, or allocate as usual if type is CONSTYPE_HEAP. */
+
+Lisp_Object
+listn (enum constype type, ptrdiff_t count, Lisp_Object arg, ...)
+{
+ va_list ap;
+ ptrdiff_t i;
+ Lisp_Object val, *objp;
+
+ /* Change to SAFE_ALLOCA if you hit this eassert. */
+ eassert (count <= MAX_ALLOCA / word_size);
+
+ objp = alloca (count * word_size);
+ objp[0] = arg;
+ va_start (ap, arg);
+ for (i = 1; i < count; i++)
+ objp[i] = va_arg (ap, Lisp_Object);
+ va_end (ap);
+
+ for (val = Qnil, i = count - 1; i >= 0; i--)
+ {
+ if (type == CONSTYPE_PURE)
+ val = pure_cons (objp[i], val);
+ else if (type == CONSTYPE_HEAP)
+ val = Fcons (objp[i], val);
+ else
+ emacs_abort ();
+ }
+ return val;
+}
+
+DEFUN ("list", Flist, Slist, 0, MANY, 0,
+ doc: /* Return a newly created list with specified arguments as elements.
+Any number of arguments, even zero arguments, are allowed.
+usage: (list &rest OBJECTS) */)
+ (ptrdiff_t nargs, Lisp_Object *args)
+{
+ register Lisp_Object val;
+ val = Qnil;
+
+ while (nargs > 0)
+ {
+ nargs--;
+ val = Fcons (args[nargs], val);
+ }
+ return val;
+}
+
+
+DEFUN ("make-list", Fmake_list, Smake_list, 2, 2, 0,
+ doc: /* Return a newly created list of length LENGTH, with each element being INIT. */)
+ (register Lisp_Object length, Lisp_Object init)
+{
+ register Lisp_Object val;
+ register EMACS_INT size;
+
+ CHECK_NATNUM (length);
+ size = XFASTINT (length);
+
+ val = Qnil;
+ while (size > 0)
+ {
+ val = Fcons (init, val);
+ --size;
+
+ if (size > 0)
+ {
+ val = Fcons (init, val);
+ --size;
+
+ if (size > 0)
+ {
+ val = Fcons (init, val);
+ --size;
+
+ if (size > 0)
+ {
+ val = Fcons (init, val);
+ --size;
+
+ if (size > 0)
+ {
+ val = Fcons (init, val);
+ --size;
+ }
+ }
+ }
+ }
+
+ QUIT;
+ }
+
+ return val;
+}
+
+
+\f
+/***********************************************************************
+ Vector Allocation
+ ***********************************************************************/
+
+/* The only vector with 0 slots, allocated from pure space. */
+
+Lisp_Object zero_vector;
+
+/* Called once to initialize vector allocation. */
+
+static void
+init_vectors (void)
+{
+ struct Lisp_Vector *p = xmalloc (header_size);
+
+ SCM_NEWSMOB (p->header.self, lisp_vectorlike_tag, p);
+ p->header.size = 0;
+ XSETVECTOR (zero_vector, p);
+}
+
+/* Value is a pointer to a newly allocated Lisp_Vector structure
+ with room for LEN Lisp_Objects. */
+
+static struct Lisp_Vector *
+allocate_vectorlike (ptrdiff_t len)
+{
+ struct Lisp_Vector *p;
+
+ if (len == 0)
+ p = XVECTOR (zero_vector);
+ else
+ {
+ p = xmalloc (header_size + len * word_size);
+ SCM_NEWSMOB (p->header.self, lisp_vectorlike_tag, p);
+ }
+
+ return p;
+}
+
+
+/* Allocate a vector with LEN slots. */
+
+struct Lisp_Vector *
+allocate_vector (EMACS_INT len)
+{
+ struct Lisp_Vector *v;
+ ptrdiff_t nbytes_max = min (PTRDIFF_MAX, SIZE_MAX);
+
+ if (min ((nbytes_max - header_size) / word_size, MOST_POSITIVE_FIXNUM) < len)
+ memory_full (SIZE_MAX);
+ v = allocate_vectorlike (len);
+ v->header.size = len;
+ return v;
+}
+
+
+/* Allocate other vector-like structures. */
+
+struct Lisp_Vector *
+allocate_pseudovector (int memlen, int lisplen, enum pvec_type tag)
+{
+ struct Lisp_Vector *v = allocate_vectorlike (memlen);
+ int i;
+
+ /* Catch bogus values. */
+ eassert (tag <= PVEC_FONT);
+ eassert (memlen - lisplen <= (1 << PSEUDOVECTOR_REST_BITS) - 1);
+ eassert (lisplen <= (1 << PSEUDOVECTOR_SIZE_BITS) - 1);
+
+ /* Only the first lisplen slots will be traced normally by the GC. */
+ for (i = 0; i < lisplen; ++i)
+ v->contents[i] = Qnil;
+
+ XSETPVECTYPESIZE (v, tag, lisplen, memlen - lisplen);
+ return v;
+}
+
+struct buffer *
+allocate_buffer (void)
+{
+ struct buffer *b = xmalloc (sizeof *b);
+
+ SCM_NEWSMOB (b->header.self, lisp_vectorlike_tag, b);
+ BUFFER_PVEC_INIT (b);
+ /* Put B on the chain of all buffers including killed ones. */
+ b->next = all_buffers;
+ all_buffers = b;
+ /* Note that the rest fields of B are not initialized. */
+ return b;
+}
+
+struct Lisp_Hash_Table *
+allocate_hash_table (void)
+{
+ return ALLOCATE_PSEUDOVECTOR (struct Lisp_Hash_Table, count, PVEC_HASH_TABLE);
+}
+
+struct window *
+allocate_window (void)
+{
+ struct window *w;
+
+ w = ALLOCATE_PSEUDOVECTOR (struct window, current_matrix, PVEC_WINDOW);
+ /* Users assumes that non-Lisp data is zeroed. */
+ memset (&w->current_matrix, 0,
+ sizeof (*w) - offsetof (struct window, current_matrix));
+ return w;
+}
+
+struct terminal *
+allocate_terminal (void)
+{
+ struct terminal *t;
+
+ t = ALLOCATE_PSEUDOVECTOR (struct terminal, next_terminal, PVEC_TERMINAL);
+ /* Users assumes that non-Lisp data is zeroed. */
+ memset (&t->next_terminal, 0,
+ sizeof (*t) - offsetof (struct terminal, next_terminal));
+ return t;
+}
+
+struct frame *
+allocate_frame (void)
+{
+ struct frame *f;
+
+ f = ALLOCATE_PSEUDOVECTOR (struct frame, face_cache, PVEC_FRAME);
+ /* Users assumes that non-Lisp data is zeroed. */
+ memset (&f->face_cache, 0,
+ sizeof (*f) - offsetof (struct frame, face_cache));
+ return f;
+}
+
+struct Lisp_Process *
+allocate_process (void)
+{
+ struct Lisp_Process *p;
+
+ p = ALLOCATE_PSEUDOVECTOR (struct Lisp_Process, pid, PVEC_PROCESS);
+ /* Users assumes that non-Lisp data is zeroed. */
+ memset (&p->pid, 0,
+ sizeof (*p) - offsetof (struct Lisp_Process, pid));
+ return p;
+}
+
+DEFUN ("make-vector", Fmake_vector, Smake_vector, 2, 2, 0,
+ doc: /* Return a newly created vector of length LENGTH, with each element being INIT.
+See also the function `vector'. */)
+ (register Lisp_Object length, Lisp_Object init)
+{
+ Lisp_Object vector;
+ register ptrdiff_t sizei;
+ register ptrdiff_t i;
+ register struct Lisp_Vector *p;
+
+ CHECK_NATNUM (length);
+
+ p = allocate_vector (XFASTINT (length));
+ sizei = XFASTINT (length);
+ for (i = 0; i < sizei; i++)
+ p->contents[i] = init;
+
+ XSETVECTOR (vector, p);
+ return vector;
+}
+
+
+DEFUN ("vector", Fvector, Svector, 0, MANY, 0,
+ doc: /* Return a newly created vector with specified arguments as elements.
+Any number of arguments, even zero arguments, are allowed.
+usage: (vector &rest OBJECTS) */)
+ (ptrdiff_t nargs, Lisp_Object *args)
+{
+ ptrdiff_t i;
+ register Lisp_Object val = make_uninit_vector (nargs);
+ register struct Lisp_Vector *p = XVECTOR (val);
+
+ for (i = 0; i < nargs; i++)
+ p->contents[i] = args[i];
+ return val;
+}
+
+void
+make_byte_code (struct Lisp_Vector *v)
+{
+ /* Don't allow the global zero_vector to become a byte code object. */
+ eassert (0 < v->header.size);
+
+ if (v->header.size > 1 && STRINGP (v->contents[1])
+ && STRING_MULTIBYTE (v->contents[1]))
+ /* BYTECODE-STRING must have been produced by Emacs 20.2 or the
+ earlier because they produced a raw 8-bit string for byte-code
+ and now such a byte-code string is loaded as multibyte while
+ raw 8-bit characters converted to multibyte form. Thus, now we
+ must convert them back to the original unibyte form. */
+ v->contents[1] = Fstring_as_unibyte (v->contents[1]);
+ XSETPVECTYPE (v, PVEC_COMPILED);
+}
+
+DEFUN ("make-byte-code", Fmake_byte_code, Smake_byte_code, 4, MANY, 0,
+ doc: /* Create a byte-code object with specified arguments as elements.
+The arguments should be the ARGLIST, bytecode-string BYTE-CODE, constant
+vector CONSTANTS, maximum stack size DEPTH, (optional) DOCSTRING,
+and (optional) INTERACTIVE-SPEC.
+The first four arguments are required; at most six have any
+significance.
+The ARGLIST can be either like the one of `lambda', in which case the arguments
+will be dynamically bound before executing the byte code, or it can be an
+integer of the form NNNNNNNRMMMMMMM where the 7bit MMMMMMM specifies the
+minimum number of arguments, the 7-bit NNNNNNN specifies the maximum number
+of arguments (ignoring &rest) and the R bit specifies whether there is a &rest
+argument to catch the left-over arguments. If such an integer is used, the
+arguments will not be dynamically bound but will be instead pushed on the
+stack before executing the byte-code.
+usage: (make-byte-code ARGLIST BYTE-CODE CONSTANTS DEPTH &optional DOCSTRING INTERACTIVE-SPEC &rest ELEMENTS) */)
+ (ptrdiff_t nargs, Lisp_Object *args)
+{
+ ptrdiff_t i;
+ register Lisp_Object val = make_uninit_vector (nargs);
+ register struct Lisp_Vector *p = XVECTOR (val);
+
+ /* We used to purecopy everything here, if purify-flag was set. This worked
+ OK for Emacs-23, but with Emacs-24's lexical binding code, it can be
+ dangerous, since make-byte-code is used during execution to build
+ closures, so any closure built during the preload phase would end up
+ copied into pure space, including its free variables, which is sometimes
+ just wasteful and other times plainly wrong (e.g. those free vars may want
+ to be setcar'd). */
+
+ for (i = 0; i < nargs; i++)
+ p->contents[i] = args[i];
+ make_byte_code (p);
+ XSETCOMPILED (val, p);
+ return val;
+}
+
+
+\f
+/***********************************************************************
+ Symbol Allocation
+ ***********************************************************************/
+
+DEFUN ("make-symbol", Fmake_symbol, Smake_symbol, 1, 1, 0,
+ doc: /* Return a newly allocated uninterned symbol whose name is NAME.
+Its value is void, and its function definition and property list are nil. */)
+ (Lisp_Object name)
+{
+ register Lisp_Object val;
+
+ CHECK_STRING (name);
+
+ val = scm_make_symbol (scm_from_utf8_stringn (SSDATA (name),
+ SBYTES (name)));
+ return val;
+}
+
+
+\f
+/***********************************************************************
+ Marker (Misc) Allocation
+ ***********************************************************************/
+
+/* Return a newly allocated Lisp_Misc object of specified TYPE. */
+
+static Lisp_Object
+allocate_misc (enum Lisp_Misc_Type type)
+{
+ Lisp_Object val;
+ union Lisp_Misc *p;
+
+ p = xmalloc (sizeof *p);
+ SCM_NEWSMOB (p->u_any.self, lisp_misc_tag, p);
+ XSETMISC (val, p);
+ XMISCANY (val)->type = type;
+ return val;
+}
+
+/* Free a Lisp_Misc object. */
+
+void
+free_misc (Lisp_Object misc)
+{
+ return;
+}
+
+/* Verify properties of Lisp_Save_Value's representation
+ that are assumed here and elsewhere. */
+
+verify (SAVE_UNUSED == 0);
+verify (((SAVE_INTEGER | SAVE_POINTER | SAVE_FUNCPOINTER | SAVE_OBJECT)
+ >> SAVE_SLOT_BITS)
+ == 0);
+
+/* Return Lisp_Save_Value objects for the various combinations
+ that callers need. */
+
+Lisp_Object
+make_save_int_int_int (ptrdiff_t a, ptrdiff_t b, ptrdiff_t c)
+{
+ Lisp_Object val = allocate_misc (Lisp_Misc_Save_Value);
+ struct Lisp_Save_Value *p = XSAVE_VALUE (val);
+ p->save_type = SAVE_TYPE_INT_INT_INT;
+ p->data[0].integer = a;
+ p->data[1].integer = b;
+ p->data[2].integer = c;
+ return val;
+}
+
+Lisp_Object
+make_save_obj_obj_obj_obj (Lisp_Object a, Lisp_Object b, Lisp_Object c,
+ Lisp_Object d)
+{
+ Lisp_Object val = allocate_misc (Lisp_Misc_Save_Value);
+ struct Lisp_Save_Value *p = XSAVE_VALUE (val);
+ p->save_type = SAVE_TYPE_OBJ_OBJ_OBJ_OBJ;
+ p->data[0].object = a;
+ p->data[1].object = b;
+ p->data[2].object = c;
+ p->data[3].object = d;
+ return val;
+}
+
+Lisp_Object
+make_save_ptr (void *a)
+{
+ Lisp_Object val = allocate_misc (Lisp_Misc_Save_Value);
+ struct Lisp_Save_Value *p = XSAVE_VALUE (val);
+ p->save_type = SAVE_POINTER;
+ p->data[0].pointer = a;
+ return val;
+}
+
+Lisp_Object
+make_save_ptr_int (void *a, ptrdiff_t b)
+{
+ Lisp_Object val = allocate_misc (Lisp_Misc_Save_Value);
+ struct Lisp_Save_Value *p = XSAVE_VALUE (val);
+ p->save_type = SAVE_TYPE_PTR_INT;
+ p->data[0].pointer = a;
+ p->data[1].integer = b;
+ return val;
+}
+
+#if ! (defined USE_X_TOOLKIT || defined USE_GTK)
+Lisp_Object
+make_save_ptr_ptr (void *a, void *b)
+{
+ Lisp_Object val = allocate_misc (Lisp_Misc_Save_Value);
+ struct Lisp_Save_Value *p = XSAVE_VALUE (val);
+ p->save_type = SAVE_TYPE_PTR_PTR;
+ p->data[0].pointer = a;
+ p->data[1].pointer = b;
+ return val;
+}
+#endif
+
+Lisp_Object
+make_save_funcptr_ptr_obj (void (*a) (void), void *b, Lisp_Object c)
+{
+ Lisp_Object val = allocate_misc (Lisp_Misc_Save_Value);
+ struct Lisp_Save_Value *p = XSAVE_VALUE (val);
+ p->save_type = SAVE_TYPE_FUNCPTR_PTR_OBJ;
+ p->data[0].funcpointer = a;
+ p->data[1].pointer = b;
+ p->data[2].object = c;
+ return val;
+}
+
+/* Return a Lisp_Save_Value object that represents an array A
+ of N Lisp objects. */
+
+Lisp_Object
+make_save_memory (Lisp_Object *a, ptrdiff_t n)
+{
+ Lisp_Object val = allocate_misc (Lisp_Misc_Save_Value);
+ struct Lisp_Save_Value *p = XSAVE_VALUE (val);
+ p->save_type = SAVE_TYPE_MEMORY;
+ p->data[0].pointer = a;
+ p->data[1].integer = n;
+ return val;
+}
+
+/* Free a Lisp_Save_Value object. Do not use this function
+ if SAVE contains pointer other than returned by xmalloc. */
+
+void
+free_save_value (Lisp_Object save)
+{
+ xfree (XSAVE_POINTER (save, 0));
+ free_misc (save);
+}
+
+/* Return a Lisp_Misc_Overlay object with specified START, END and PLIST. */
+
+Lisp_Object
+build_overlay (Lisp_Object start, Lisp_Object end, Lisp_Object plist)
+{
+ register Lisp_Object overlay;
+
+ overlay = allocate_misc (Lisp_Misc_Overlay);
+ OVERLAY_START (overlay) = start;
+ OVERLAY_END (overlay) = end;
+ set_overlay_plist (overlay, plist);
+ XOVERLAY (overlay)->next = NULL;
+ return overlay;
+}
+
+DEFUN ("make-marker", Fmake_marker, Smake_marker, 0, 0, 0,
+ doc: /* Return a newly allocated marker which does not point at any place. */)
+ (void)
+{
+ register Lisp_Object val;
+ register struct Lisp_Marker *p;
+
+ val = allocate_misc (Lisp_Misc_Marker);
+ p = XMARKER (val);
+ p->buffer = 0;
+ p->bytepos = 0;
+ p->charpos = 0;
+ p->next = NULL;
+ p->insertion_type = 0;
+ p->need_adjustment = 0;
+ return val;
+}
+
+/* Return a newly allocated marker which points into BUF
+ at character position CHARPOS and byte position BYTEPOS. */
+
+Lisp_Object
+build_marker (struct buffer *buf, ptrdiff_t charpos, ptrdiff_t bytepos)
+{
+ Lisp_Object obj;
+ struct Lisp_Marker *m;
+
+ /* No dead buffers here. */
+ eassert (BUFFER_LIVE_P (buf));
+
+ /* Every character is at least one byte. */
+ eassert (charpos <= bytepos);
+
+ obj = allocate_misc (Lisp_Misc_Marker);
+ m = XMARKER (obj);
+ m->buffer = buf;
+ m->charpos = charpos;
+ m->bytepos = bytepos;
+ m->insertion_type = 0;
+ m->need_adjustment = 0;
+ m->next = BUF_MARKERS (buf);
+ BUF_MARKERS (buf) = m;
+ return obj;
+}
+\f
+/* Return a newly created vector or string with specified arguments as
+ elements. If all the arguments are characters that can fit
+ in a string of events, make a string; otherwise, make a vector.
+
+ Any number of arguments, even zero arguments, are allowed. */
+
+Lisp_Object
+make_event_array (ptrdiff_t nargs, Lisp_Object *args)
+{
+ ptrdiff_t i;
+
+ for (i = 0; i < nargs; i++)
+ /* The things that fit in a string
+ are characters that are in 0...127,
+ after discarding the meta bit and all the bits above it. */
+ if (!INTEGERP (args[i])
+ || (XINT (args[i]) & ~(-CHAR_META)) >= 0200)
+ return Fvector (nargs, args);
+
+ /* Since the loop exited, we know that all the things in it are
+ characters, so we can make a string. */
+ {
+ Lisp_Object result;
+
+ result = Fmake_string (make_number (nargs), make_number (0));
+ for (i = 0; i < nargs; i++)
+ {
+ SSET (result, i, XINT (args[i]));
+ /* Move the meta bit to the right place for a string char. */
+ if (XINT (args[i]) & CHAR_META)
+ SSET (result, i, SREF (result, i) | 0x80);
+ }
+
+ return result;
+ }
+}
+
+
+\f
+/************************************************************************
+ Memory Full Handling
+ ************************************************************************/
+
+
+/* Called if xmalloc (NBYTES) returns zero. If NBYTES == SIZE_MAX,
+ there may have been size_t overflow so that xmalloc was never
+ called, or perhaps xmalloc was invoked successfully but the
+ resulting pointer had problems fitting into a tagged EMACS_INT. In
+ either case this counts as memory being full even though xmalloc
+ did not fail. */
+
+void
+memory_full (size_t nbytes)
+{
+ /* Do not go into hysterics merely because a large request failed. */
+ bool enough_free_memory = 0;
+ if (SPARE_MEMORY < nbytes)
+ {
+ void *p = xmalloc_atomic_unsafe (SPARE_MEMORY);
+ if (p)
+ {
+ xfree (p);
+ enough_free_memory = 1;
+ }
+ }
+
+ if (! enough_free_memory)
+ {
+ Vmemory_full = Qt;
+
+ /* The first time we get here, free the spare memory. */
+ if (spare_memory)
+ {
+ xfree (spare_memory);
+ spare_memory = NULL;
+ }
+ }
+
+ /* This used to call error, but if we've run out of memory, we could
+ get infinite recursion trying to build the string. */
+ xsignal (Qnil, Vmemory_signal_data);
+}
+
+/* If we released our reserve (due to running out of memory),
+ and we have a fair amount free once again,
+ try to set aside another reserve in case we run out once more.
+
+ This is called when a relocatable block is freed in ralloc.c,
+ and also directly from this file, in case we're not using ralloc.c. */
+
+void
+refill_memory_reserve (void)
+{
+ if (spare_memory == NULL)
+ spare_memory = xmalloc_atomic_unsafe (SPARE_MEMORY);
+
+ if (spare_memory)
+ Vmemory_full = Qnil;
+}
+\f
+/* Determine whether it is safe to access memory at address P. */
+static int
+valid_pointer_p (void *p)
+{
+#ifdef WINDOWSNT
+ return w32_valid_pointer_p (p, 16);
+#else
+ int fd[2];
+
+ /* Obviously, we cannot just access it (we would SEGV trying), so we
+ trick the o/s to tell us whether p is a valid pointer.
+ Unfortunately, we cannot use NULL_DEVICE here, as emacs_write may
+ not validate p in that case. */
+
+ if (emacs_pipe (fd) == 0)
+ {
+ bool valid = emacs_write (fd[1], p, 16) == 16;
+ emacs_close (fd[1]);
+ emacs_close (fd[0]);
+ return valid;
+ }
+
+ return -1;
+#endif
+}
+
+/* Return 2 if OBJ is a killed or special buffer object, 1 if OBJ is a
+ valid lisp object, 0 if OBJ is NOT a valid lisp object, or -1 if we
+ cannot validate OBJ. This function can be quite slow, so its primary
+ use is the manual debugging. The only exception is print_object, where
+ we use it to check whether the memory referenced by the pointer of
+ Lisp_Save_Value object contains valid objects. */
+
+int
+valid_lisp_object_p (Lisp_Object obj)
+{
+ void *p;
+
+ if (SCM_IMP (obj))
+ return 1;
+
+ p = (void *) SCM2PTR (obj);
+
+ if (p == &buffer_defaults || p == &buffer_local_symbols)
+ return 2;
+
+ return valid_pointer_p (p);
+}
+
+/* If GC_MARK_STACK, return 1 if STR is a relocatable data of Lisp_String
+ (i.e. there is a non-pure Lisp_Object X so that SDATA (X) == STR) and 0
+ if not. Otherwise we can't rely on valid_lisp_object_p and return -1.
+ This function is slow and should be used for debugging purposes. */
+
+int
+relocatable_string_data_p (const char *str)
+{
+ return -1;
+}
+
+/***********************************************************************
+ Pure Storage Compatibility Functions
+ ***********************************************************************/
+
+void
+check_pure_size (void)
+{
+ return;
+}
+
+Lisp_Object
+make_pure_string (const char *data,
+ ptrdiff_t nchars, ptrdiff_t nbytes, bool multibyte)
+{
+ return make_specified_string (data, nchars, nbytes, multibyte);
+}
+
+Lisp_Object
+make_pure_c_string (const char *data, ptrdiff_t nchars)
+{
+ return build_string (data);
+}
+
+Lisp_Object
+pure_cons (Lisp_Object car, Lisp_Object cdr)
+{
+ return Fcons (car, cdr);
+}
+
+DEFUN ("purecopy", Fpurecopy, Spurecopy, 1, 1, 0,
+ doc: /* Return OBJ. */)
+ (register Lisp_Object obj)
+{
+ return obj;
+}
+\f
+/***********************************************************************
+ Protection from GC
+ ***********************************************************************/
+
+void
+staticpro (Lisp_Object *varaddress)
+{
+ return;
+}
+\f
+DEFUN ("garbage-collect", Fgarbage_collect, Sgarbage_collect, 0, 0, "",
+ doc: /* Reclaim storage for Lisp objects no longer needed.
+Garbage collection happens automatically if you cons more than
+`gc-cons-threshold' bytes of Lisp data since previous garbage collection.
+`garbage-collect' normally returns a list with info on amount of space in use,
+where each entry has the form (NAME SIZE USED FREE), where:
+- NAME is a symbol describing the kind of objects this entry represents,
+- SIZE is the number of bytes used by each one,
+- USED is the number of those objects that were found live in the heap,
+- FREE is the number of those objects that are not live but that Emacs
+ keeps around for future allocations (maybe because it does not know how
+ to return them to the OS).
+However, if there was overflow in pure space, `garbage-collect'
+returns nil, because real GC can't be done.
+See Info node `(elisp)Garbage Collection'. */)
+ (void)
+{
+ GC_gcollect ();
+ return Qt;
+}
+\f
+#ifdef ENABLE_CHECKING
+
+bool suppress_checking;
+
+void
+die (const char *msg, const char *file, int line)
+{
+ fprintf (stderr, "\r\n%s:%d: Emacs fatal error: assertion failed: %s\r\n",
+ file, line, msg);
+ terminate_due_to_signal (SIGABRT, INT_MAX);
+}
+#endif
+\f
+/* Initialization. */
+
+static int
+print_lisp_string (SCM obj, SCM port, scm_print_state *pstate)
+{
+ scm_c_write (port, "#<elisp-string \"", 16);
+ scm_c_write (port, XSTRING (obj)->data, STRING_BYTES (XSTRING (obj)));
+ scm_c_write (port, "\">", 2);
+ return 0;
+}
+
+void
+init_alloc_once (void)
+{
+ lisp_misc_tag = scm_make_smob_type ("elisp-misc", 0);
+ lisp_string_tag = scm_make_smob_type ("elisp-string",
+ sizeof (struct Lisp_String));
+ scm_set_smob_print (lisp_string_tag, print_lisp_string);
+ lisp_vectorlike_tag = scm_make_smob_type ("elisp-vectorlike", 0);
+
+ /* Used to do Vpurify_flag = Qt here, but Qt isn't set up yet! */
+
+ init_strings ();
+ init_vectors ();
+
+ refill_memory_reserve ();
+ gc_cons_threshold = GC_DEFAULT_THRESHOLD;
+}
+
+void
+init_alloc (void)
+{
+ gcprolist = 0;
+ Vgc_elapsed = make_float (0.0);
+ gcs_done = 0;
+
+#if USE_VALGRIND
+ valgrind_p = RUNNING_ON_VALGRIND != 0;
+#endif
+}
+
+void
+syms_of_alloc (void)
+{
+#include "alloc.x"
+
+ DEFVAR_INT ("gc-cons-threshold", gc_cons_threshold,
+ doc: /* Number of bytes of consing between garbage collections.
+Garbage collection can happen automatically once this many bytes have been
+allocated since the last garbage collection. All data types count.
+
+Garbage collection happens automatically only when `eval' is called.
+
+By binding this temporarily to a large number, you can effectively
+prevent garbage collection during a part of the program.
+See also `gc-cons-percentage'. */);
+
+ DEFVAR_LISP ("gc-cons-percentage", Vgc_cons_percentage,
+ doc: /* Portion of the heap used for allocation.
+Garbage collection can happen automatically once this portion of the heap
+has been allocated since the last garbage collection.
+If this portion is smaller than `gc-cons-threshold', this is ignored. */);
+ Vgc_cons_percentage = make_float (0.1);
+
+ DEFVAR_INT ("pure-bytes-used", pure_bytes_used,
+ doc: /* Number of bytes of shareable Lisp data allocated so far. */);
+
+ DEFVAR_LISP ("purify-flag", Vpurify_flag,
+ doc: /* Non-nil means loading Lisp code in order to dump an executable.
+This means that certain objects should be allocated in shared (pure) space.
+It can also be set to a hash-table, in which case this table is used to
+do hash-consing of the objects allocated to pure space. */);
+
+ DEFVAR_BOOL ("garbage-collection-messages", garbage_collection_messages,
+ doc: /* Non-nil means display messages at start and end of garbage collection. */);
+ garbage_collection_messages = 0;
+
+ DEFVAR_LISP ("post-gc-hook", Vpost_gc_hook,
+ doc: /* Hook run after garbage collection has finished. */);
+ Vpost_gc_hook = Qnil;
+ DEFSYM (Qpost_gc_hook, "post-gc-hook");
+
+ DEFVAR_LISP ("memory-signal-data", Vmemory_signal_data,
+ doc: /* Precomputed `signal' argument for memory-full error. */);
+ /* We build this in advance because if we wait until we need it, we might
+ not be able to allocate the memory to hold it. */
+ Vmemory_signal_data
+ = listn (CONSTYPE_PURE, 2, Qerror,
+ build_pure_c_string ("Memory exhausted--use M-x save-some-buffers then exit and restart Emacs"));
+
+ DEFVAR_LISP ("memory-full", Vmemory_full,
+ doc: /* Non-nil means Emacs cannot get much more Lisp memory. */);
+ Vmemory_full = Qnil;
+
+ DEFSYM (Qgc_cons_threshold, "gc-cons-threshold");
+ DEFSYM (Qchar_table_extra_slots, "char-table-extra-slots");
+
+ DEFVAR_LISP ("gc-elapsed", Vgc_elapsed,
+ doc: /* Accumulated time elapsed in garbage collections.
+The time is in seconds as a floating point value. */);
+ DEFVAR_INT ("gcs-done", gcs_done,
+ doc: /* Accumulated number of garbage collections done. */);
+}
+
+/* When compiled with GCC, GDB might say "No enum type named
+ pvec_type" if we don't have at least one symbol with that type, and
+ then xbacktrace could fail. Similarly for the other enums and
+ their values. Some non-GCC compilers don't like these constructs. */
+#ifdef __GNUC__
+union
+{
+ enum CHARTAB_SIZE_BITS CHARTAB_SIZE_BITS;
+ enum CHAR_TABLE_STANDARD_SLOTS CHAR_TABLE_STANDARD_SLOTS;
+ enum char_bits char_bits;
+ enum DEFAULT_HASH_SIZE DEFAULT_HASH_SIZE;
+ enum Lisp_Bits Lisp_Bits;
+ enum Lisp_Compiled Lisp_Compiled;
+ enum maxargs maxargs;
+ enum MAX_ALLOCA MAX_ALLOCA;
+ enum More_Lisp_Bits More_Lisp_Bits;
+ enum pvec_type pvec_type;
+} const EXTERNALLY_VISIBLE gdb_make_enums_visible = {0};
+#endif /* __GNUC__ */