aboutsummaryrefslogtreecommitdiffstats
path: root/src/alloc.c
diff options
context:
space:
mode:
authorMattias EngdegÄrd2021-12-31 17:24:31 +0100
committerMattias EngdegÄrd2022-01-24 11:41:46 +0100
commit65caf5b205d22f76bb4ec85cfe597b621a83afb3 (patch)
tree8a4b71295d56f76ad0fee6c4471aa036c6e7e226 /src/alloc.c
parentce1de3a8d9723305f48fd4527fbceaff3cec50ba (diff)
downloademacs-65caf5b205d22f76bb4ec85cfe597b621a83afb3.tar.gz
emacs-65caf5b205d22f76bb4ec85cfe597b621a83afb3.zip
Pin bytecode strings to avoid copy at call time
Avoid making a copy (in the interpreter C stack frame) of the bytecode string by making sure it won't be moved by the GC. This is done by reallocating it to the heap normally only used for large strings, which isn't compacted. This requires that we retain an explicit reference to the bytecode string object (`bytestr`) lest it be GCed away should all other references vanish during execution. We allocate an extra stack slot for that, as we already do for the constant vector object. * src/alloc.c (allocate_string_data): Add `immovable` argument. (resize_string_data, make_clear_multibyte_string): Use it. (pin_string): New. * src/pdumper.c (dump_string): Fix incorrect comment. Update hash for Lisp_String (only comments changed, not contents). * src/lread.c (read1): * src/alloc.c (Fmake_byte_code, purecopy): * src/bytecode.c (Fbyte_code): Pin bytecode on object creation. (exec_byte_code): Don't copy bytecode. Retain `bytestr` explicitly. * src/lisp.h (Lisp_String): Explain special size_byte values. (string_immovable_p): New.
Diffstat (limited to 'src/alloc.c')
-rw-r--r--src/alloc.c38
1 files changed, 34 insertions, 4 deletions
diff --git a/src/alloc.c b/src/alloc.c
index e0b2c220231..e01ea36e642 100644
--- a/src/alloc.c
+++ b/src/alloc.c
@@ -1853,7 +1853,8 @@ allocate_string (void)
1853 1853
1854static void 1854static void
1855allocate_string_data (struct Lisp_String *s, 1855allocate_string_data (struct Lisp_String *s,
1856 EMACS_INT nchars, EMACS_INT nbytes, bool clearit) 1856 EMACS_INT nchars, EMACS_INT nbytes, bool clearit,
1857 bool immovable)
1857{ 1858{
1858 sdata *data; 1859 sdata *data;
1859 struct sblock *b; 1860 struct sblock *b;
@@ -1867,7 +1868,7 @@ allocate_string_data (struct Lisp_String *s,
1867 1868
1868 MALLOC_BLOCK_INPUT; 1869 MALLOC_BLOCK_INPUT;
1869 1870
1870 if (nbytes > LARGE_STRING_BYTES) 1871 if (nbytes > LARGE_STRING_BYTES || immovable)
1871 { 1872 {
1872 size_t size = FLEXSIZEOF (struct sblock, data, needed); 1873 size_t size = FLEXSIZEOF (struct sblock, data, needed);
1873 1874
@@ -1967,7 +1968,7 @@ resize_string_data (Lisp_Object string, ptrdiff_t cidx_byte,
1967 } 1968 }
1968 else 1969 else
1969 { 1970 {
1970 allocate_string_data (XSTRING (string), nchars, new_nbytes, false); 1971 allocate_string_data (XSTRING (string), nchars, new_nbytes, false, false);
1971 unsigned char *new_data = SDATA (string); 1972 unsigned char *new_data = SDATA (string);
1972 new_charaddr = new_data + cidx_byte; 1973 new_charaddr = new_data + cidx_byte;
1973 memcpy (new_charaddr + new_clen, data + cidx_byte + clen, 1974 memcpy (new_charaddr + new_clen, data + cidx_byte + clen,
@@ -2483,7 +2484,7 @@ make_clear_multibyte_string (EMACS_INT nchars, EMACS_INT nbytes, bool clearit)
2483 2484
2484 s = allocate_string (); 2485 s = allocate_string ();
2485 s->u.s.intervals = NULL; 2486 s->u.s.intervals = NULL;
2486 allocate_string_data (s, nchars, nbytes, clearit); 2487 allocate_string_data (s, nchars, nbytes, clearit, false);
2487 XSETSTRING (string, s); 2488 XSETSTRING (string, s);
2488 string_chars_consed += nbytes; 2489 string_chars_consed += nbytes;
2489 return string; 2490 return string;
@@ -2513,6 +2514,29 @@ make_formatted_string (char *buf, const char *format, ...)
2513 return make_string (buf, length); 2514 return make_string (buf, length);
2514} 2515}
2515 2516
2517/* Pin a unibyte string in place so that it won't move during GC. */
2518void
2519pin_string (Lisp_Object string)
2520{
2521 eassert (STRINGP (string) && !STRING_MULTIBYTE (string));
2522 struct Lisp_String *s = XSTRING (string);
2523 ptrdiff_t size = STRING_BYTES (s);
2524 unsigned char *data = s->u.s.data;
2525
2526 if (!(size > LARGE_STRING_BYTES
2527 || PURE_P (data) || pdumper_object_p (data)
2528 || s->u.s.size_byte == -3))
2529 {
2530 eassert (s->u.s.size_byte == -1);
2531 sdata *old_sdata = SDATA_OF_STRING (s);
2532 allocate_string_data (s, size, size, false, true);
2533 memcpy (s->u.s.data, data, size);
2534 old_sdata->string = NULL;
2535 SDATA_NBYTES (old_sdata) = size;
2536 }
2537 s->u.s.size_byte = -3;
2538}
2539
2516 2540
2517/*********************************************************************** 2541/***********************************************************************
2518 Float Allocation 2542 Float Allocation
@@ -3515,6 +3539,8 @@ usage: (make-byte-code ARGLIST BYTE-CODE CONSTANTS DEPTH &optional DOCSTRING INT
3515 && FIXNATP (args[COMPILED_STACK_DEPTH]))) 3539 && FIXNATP (args[COMPILED_STACK_DEPTH])))
3516 error ("Invalid byte-code object"); 3540 error ("Invalid byte-code object");
3517 3541
3542 pin_string (args[COMPILED_BYTECODE]); // Bytecode must be immovable.
3543
3518 /* We used to purecopy everything here, if purify-flag was set. This worked 3544 /* We used to purecopy everything here, if purify-flag was set. This worked
3519 OK for Emacs-23, but with Emacs-24's lexical binding code, it can be 3545 OK for Emacs-23, but with Emacs-24's lexical binding code, it can be
3520 dangerous, since make-byte-code is used during execution to build 3546 dangerous, since make-byte-code is used during execution to build
@@ -5653,6 +5679,10 @@ purecopy (Lisp_Object obj)
5653 memcpy (vec, objp, nbytes); 5679 memcpy (vec, objp, nbytes);
5654 for (i = 0; i < size; i++) 5680 for (i = 0; i < size; i++)
5655 vec->contents[i] = purecopy (vec->contents[i]); 5681 vec->contents[i] = purecopy (vec->contents[i]);
5682 // Byte code strings must be pinned.
5683 if (COMPILEDP (obj) && size >= 2 && STRINGP (vec->contents[1])
5684 && !STRING_MULTIBYTE (vec->contents[1]))
5685 pin_string (vec->contents[1]);
5656 XSETVECTOR (obj, vec); 5686 XSETVECTOR (obj, vec);
5657 } 5687 }
5658 else if (BARE_SYMBOL_P (obj)) 5688 else if (BARE_SYMBOL_P (obj))