summaryrefslogtreecommitdiff
path: root/src/alloc.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/alloc.c')
-rw-r--r--src/alloc.c120
1 files changed, 106 insertions, 14 deletions
diff --git a/src/alloc.c b/src/alloc.c
index b86ed4ed262..4ea337ddbaa 100644
--- a/src/alloc.c
+++ b/src/alloc.c
@@ -3152,6 +3152,26 @@ cleanup_vector (struct Lisp_Vector *vector)
module_finalize_function (function);
}
#endif
+ else if (NATIVE_COMP_FLAG
+ && PSEUDOVECTOR_TYPEP (&vector->header, PVEC_NATIVE_COMP_UNIT))
+ {
+ struct Lisp_Native_Comp_Unit *cu =
+ PSEUDOVEC_STRUCT (vector, Lisp_Native_Comp_Unit);
+ unload_comp_unit (cu);
+ }
+ else if (NATIVE_COMP_FLAG
+ && PSEUDOVECTOR_TYPEP (&vector->header, PVEC_SUBR))
+ {
+ struct Lisp_Subr *subr =
+ PSEUDOVEC_STRUCT (vector, Lisp_Subr);
+ if (!NILP (subr->native_comp_u[0]))
+ {
+ /* FIXME Alternative and non invasive solution to this
+ cast? */
+ xfree ((char *)subr->symbol_name);
+ xfree (subr->native_c_name[0]);
+ }
+ }
}
/* Reclaim space used by unmarked vectors. */
@@ -3498,6 +3518,38 @@ usage: (make-byte-code ARGLIST BYTE-CODE CONSTANTS DEPTH &optional DOCSTRING INT
return val;
}
+DEFUN ("make-closure", Fmake_closure, Smake_closure, 1, MANY, 0,
+ doc: /* Create a byte-code closure from PROTOTYPE and CLOSURE-VARS.
+Return a copy of PROTOTYPE, a byte-code object, with CLOSURE-VARS
+replacing the elements in the beginning of the constant-vector.
+usage: (make-closure PROTOTYPE &rest CLOSURE-VARS) */)
+ (ptrdiff_t nargs, Lisp_Object *args)
+{
+ Lisp_Object protofun = args[0];
+ CHECK_TYPE (COMPILEDP (protofun), Qbyte_code_function_p, protofun);
+
+ /* Create a copy of the constant vector, filling it with the closure
+ variables in the beginning. (The overwritten part should just
+ contain placeholder values.) */
+ Lisp_Object proto_constvec = AREF (protofun, COMPILED_CONSTANTS);
+ ptrdiff_t constsize = ASIZE (proto_constvec);
+ ptrdiff_t nvars = nargs - 1;
+ if (nvars > constsize)
+ error ("Closure vars do not fit in constvec");
+ Lisp_Object constvec = make_uninit_vector (constsize);
+ memcpy (XVECTOR (constvec)->contents, args + 1, nvars * word_size);
+ memcpy (XVECTOR (constvec)->contents + nvars,
+ XVECTOR (proto_constvec)->contents + nvars,
+ (constsize - nvars) * word_size);
+
+ /* Return a copy of the prototype function with the new constant vector. */
+ ptrdiff_t protosize = PVSIZE (protofun);
+ struct Lisp_Vector *v = allocate_vectorlike (protosize, false);
+ v->header = XVECTOR (protofun)->header;
+ memcpy (v->contents, XVECTOR (protofun)->contents, protosize * word_size);
+ v->contents[COMPILED_CONSTANTS] = constvec;
+ return make_lisp_ptr (v, Lisp_Vectorlike);
+}
/***********************************************************************
@@ -4688,7 +4740,7 @@ live_small_vector_p (struct mem_node *m, void *p)
marked. */
static void
-mark_maybe_pointer (void *p)
+mark_maybe_pointer (void *p, bool symbol_only)
{
struct mem_node *m;
@@ -4703,14 +4755,32 @@ mark_maybe_pointer (void *p)
definitely _don't_ have an object. */
if (pdumper_object_p (p))
{
+ /* FIXME: This code assumes that every reachable pdumper object
+ is addressed either by a pointer to the object start, or by
+ the same pointer with an LSB-style tag. This assumption
+ fails if a pdumper object is reachable only via machine
+ addresses of non-initial object components. Although such
+ addressing is rare in machine code generated by C compilers
+ from Emacs source code, it can occur in some cases. To fix
+ this problem, the pdumper code should grok non-initial
+ addresses, as the non-pdumper code does. */
+ uintptr_t mask = VALMASK & UINTPTR_MAX;
+ uintptr_t masked_p = (uintptr_t) p & mask;
+ void *po = (void *) masked_p;
+ char *cp = p;
+ char *cpo = po;
/* Don't use pdumper_object_p_precise here! It doesn't check the
tag bits. OBJ here might be complete garbage, so we need to
verify both the pointer and the tag. */
- int type = pdumper_find_object_type (p);
- if (pdumper_valid_object_type_p (type))
- mark_object (type == Lisp_Symbol
- ? make_lisp_symbol (p)
- : make_lisp_ptr (p, type));
+ int type = pdumper_find_object_type (po);
+ if (pdumper_valid_object_type_p (type)
+ && (!USE_LSB_TAG || p == po || cp - cpo == type))
+ {
+ if (type == Lisp_Symbol)
+ mark_object (make_lisp_symbol (po));
+ else if (!symbol_only)
+ mark_object (make_lisp_ptr (po, type));
+ }
return;
}
@@ -4728,6 +4798,8 @@ mark_maybe_pointer (void *p)
case MEM_TYPE_CONS:
{
+ if (symbol_only)
+ return;
struct Lisp_Cons *h = live_cons_holding (m, p);
if (!h)
return;
@@ -4737,6 +4809,8 @@ mark_maybe_pointer (void *p)
case MEM_TYPE_STRING:
{
+ if (symbol_only)
+ return;
struct Lisp_String *h = live_string_holding (m, p);
if (!h)
return;
@@ -4755,6 +4829,8 @@ mark_maybe_pointer (void *p)
case MEM_TYPE_FLOAT:
{
+ if (symbol_only)
+ return;
struct Lisp_Float *h = live_float_holding (m, p);
if (!h)
return;
@@ -4764,6 +4840,8 @@ mark_maybe_pointer (void *p)
case MEM_TYPE_VECTORLIKE:
{
+ if (symbol_only)
+ return;
struct Lisp_Vector *h = live_large_vector_holding (m, p);
if (!h)
return;
@@ -4773,6 +4851,8 @@ mark_maybe_pointer (void *p)
case MEM_TYPE_VECTOR_BLOCK:
{
+ if (symbol_only)
+ return;
struct Lisp_Vector *h = live_small_vector_holding (m, p);
if (!h)
return;
@@ -4834,7 +4914,7 @@ mark_memory (void const *start, void const *end)
for (pp = start; (void const *) pp < end; pp += GC_POINTER_ALIGNMENT)
{
void *p = *(void *const *) pp;
- mark_maybe_pointer (p);
+ mark_maybe_pointer (p, false);
/* Unmask any struct Lisp_Symbol pointer that make_lisp_symbol
previously disguised by adding the address of 'lispsym'.
@@ -4843,7 +4923,7 @@ mark_memory (void const *start, void const *end)
non-adjacent words and P might be the low-order word's value. */
intptr_t ip;
INT_ADD_WRAPV ((intptr_t) p, (intptr_t) lispsym, &ip);
- mark_maybe_pointer ((void *) ip);
+ mark_maybe_pointer ((void *) ip, true);
}
}
@@ -6216,7 +6296,7 @@ For further details, see Info node `(elisp)Garbage Collection'. */)
}
DEFUN ("garbage-collect-maybe", Fgarbage_collect_maybe,
-Sgarbage_collect_maybe, 1, 1, "",
+Sgarbage_collect_maybe, 1, 1, 0,
doc: /* Call `garbage-collect' if enough allocation happened.
FACTOR determines what "enough" means here:
If FACTOR is a positive number N, it means to run GC if more than
@@ -6693,6 +6773,15 @@ mark_object (Lisp_Object arg)
break;
case PVEC_SUBR:
+ if (SUBR_NATIVE_COMPILEDP (obj))
+ {
+ set_vector_marked (ptr);
+ struct Lisp_Subr *subr = XSUBR (obj);
+ mark_object (subr->native_intspec);
+ mark_object (subr->native_comp_u[0]);
+ mark_object (subr->lambda_list[0]);
+ mark_object (subr->type[0]);
+ }
break;
case PVEC_FREE:
@@ -6837,7 +6926,9 @@ survives_gc_p (Lisp_Object obj)
break;
case Lisp_Vectorlike:
- survives_p = SUBRP (obj) || vector_marked_p (XVECTOR (obj));
+ survives_p =
+ (SUBRP (obj) && !SUBR_NATIVE_COMPILEDP (obj)) ||
+ vector_marked_p (XVECTOR (obj));
break;
case Lisp_Cons:
@@ -7227,7 +7318,7 @@ Frames, windows, buffers, and subprocesses count as vectors
make_int (strings_consed));
}
-#ifdef GNU_LINUX
+#if defined GNU_LINUX && defined __GLIBC__
DEFUN ("malloc-info", Fmalloc_info, Smalloc_info, 0, 0, "",
doc: /* Report malloc information to stderr.
This function outputs to stderr an XML-formatted
@@ -7573,6 +7664,7 @@ N should be nonnegative. */);
defsubr (&Srecord);
defsubr (&Sbool_vector);
defsubr (&Smake_byte_code);
+ defsubr (&Smake_closure);
defsubr (&Smake_list);
defsubr (&Smake_vector);
defsubr (&Smake_record);
@@ -7586,7 +7678,7 @@ N should be nonnegative. */);
defsubr (&Sgarbage_collect_maybe);
defsubr (&Smemory_info);
defsubr (&Smemory_use_counts);
-#ifdef GNU_LINUX
+#if defined GNU_LINUX && defined __GLIBC__
defsubr (&Smalloc_info);
#endif
defsubr (&Ssuspicious_object);
@@ -7596,14 +7688,14 @@ N should be nonnegative. */);
static union Aligned_Lisp_Subr Swatch_gc_cons_threshold =
{{{ PSEUDOVECTOR_FLAG | (PVEC_SUBR << PSEUDOVECTOR_AREA_BITS) },
{ .a4 = watch_gc_cons_threshold },
- 4, 4, "watch_gc_cons_threshold", 0, 0}};
+ 4, 4, "watch_gc_cons_threshold", {0}, 0}};
XSETSUBR (watcher, &Swatch_gc_cons_threshold.s);
Fadd_variable_watcher (Qgc_cons_threshold, watcher);
static union Aligned_Lisp_Subr Swatch_gc_cons_percentage =
{{{ PSEUDOVECTOR_FLAG | (PVEC_SUBR << PSEUDOVECTOR_AREA_BITS) },
{ .a4 = watch_gc_cons_percentage },
- 4, 4, "watch_gc_cons_percentage", 0, 0}};
+ 4, 4, "watch_gc_cons_percentage", {0}, 0}};
XSETSUBR (watcher, &Swatch_gc_cons_percentage.s);
Fadd_variable_watcher (Qgc_cons_percentage, watcher);
}