aboutsummaryrefslogtreecommitdiffstats
path: root/src/bytecode.c
diff options
context:
space:
mode:
authorMattias EngdegÄrd2021-12-31 17:24:31 +0100
committerMattias EngdegÄrd2022-01-11 15:22:41 +0100
commit870806d4c453addca794aa0940298425241e13d9 (patch)
tree0b625a185bc4827290b2d72b132ac1fd94573886 /src/bytecode.c
parentb43e4a184ff35c3cc6accb769f04e3d75bcb751b (diff)
downloademacs-870806d4c453addca794aa0940298425241e13d9.tar.gz
emacs-870806d4c453addca794aa0940298425241e13d9.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/bytecode.c')
-rw-r--r--src/bytecode.c23
1 files changed, 16 insertions, 7 deletions
diff --git a/src/bytecode.c b/src/bytecode.c
index 5e7de2725a0..1561bdc149d 100644
--- a/src/bytecode.c
+++ b/src/bytecode.c
@@ -331,6 +331,7 @@ If the third argument is incorrect, Emacs may crash. */)
331 the original unibyte form. */ 331 the original unibyte form. */
332 bytestr = Fstring_as_unibyte (bytestr); 332 bytestr = Fstring_as_unibyte (bytestr);
333 } 333 }
334 pin_string (bytestr); // Bytecode must be immovable.
334 335
335 return exec_byte_code (bytestr, vector, maxdepth, Qnil, 0, NULL); 336 return exec_byte_code (bytestr, vector, maxdepth, Qnil, 0, NULL);
336} 337}
@@ -358,22 +359,28 @@ exec_byte_code (Lisp_Object bytestr, Lisp_Object vector, Lisp_Object maxdepth,
358#endif 359#endif
359 360
360 eassert (!STRING_MULTIBYTE (bytestr)); 361 eassert (!STRING_MULTIBYTE (bytestr));
362 eassert (string_immovable_p (bytestr));
361 363
362 ptrdiff_t const_length = ASIZE (vector); 364 ptrdiff_t const_length = ASIZE (vector);
363 ptrdiff_t bytestr_length = SCHARS (bytestr); 365 ptrdiff_t bytestr_length = SCHARS (bytestr);
364 Lisp_Object *vectorp = XVECTOR (vector)->contents; 366 Lisp_Object *vectorp = XVECTOR (vector)->contents;
365 367
366 unsigned char quitcounter = 1; 368 unsigned char quitcounter = 1;
367 EMACS_INT stack_items = XFIXNAT (maxdepth) + 1; 369 /* Allocate two more slots than required, because... */
370 EMACS_INT stack_items = XFIXNAT (maxdepth) + 2;
368 USE_SAFE_ALLOCA; 371 USE_SAFE_ALLOCA;
369 void *alloc; 372 void *alloc;
370 SAFE_ALLOCA_LISP_EXTRA (alloc, stack_items, bytestr_length); 373 SAFE_ALLOCA_LISP (alloc, stack_items);
371 Lisp_Object *stack_base = alloc; 374 Lisp_Object *stack_base = alloc;
372 Lisp_Object *top = stack_base; 375 /* ... we plonk BYTESTR and VECTOR there to ensure that they survive
373 *top = vector; /* Ensure VECTOR survives GC (Bug#33014). */ 376 GC (bug#33014), since these variables aren't used directly beyond
374 Lisp_Object *stack_lim = stack_base + stack_items; 377 the interpreter prologue and wouldn't be found in the stack frame
375 unsigned char const *bytestr_data = memcpy (stack_lim, 378 otherwise. */
376 SDATA (bytestr), bytestr_length); 379 stack_base[0] = bytestr;
380 stack_base[1] = vector;
381 Lisp_Object *top = stack_base + 1;
382 Lisp_Object *stack_lim = top + stack_items;
383 unsigned char const *bytestr_data = SDATA (bytestr);
377 unsigned char const *pc = bytestr_data; 384 unsigned char const *pc = bytestr_data;
378 ptrdiff_t count = SPECPDL_INDEX (); 385 ptrdiff_t count = SPECPDL_INDEX ();
379 386
@@ -1570,6 +1577,8 @@ exec_byte_code (Lisp_Object bytestr, Lisp_Object vector, Lisp_Object maxdepth,
1570 1577
1571 exit: 1578 exit:
1572 1579
1580 eassert (SDATA (bytestr) == bytestr_data);
1581
1573 /* Binds and unbinds are supposed to be compiled balanced. */ 1582 /* Binds and unbinds are supposed to be compiled balanced. */
1574 if (SPECPDL_INDEX () != count) 1583 if (SPECPDL_INDEX () != count)
1575 { 1584 {