aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorAndrea Corallo2020-07-26 09:40:02 +0200
committerAndrea Corallo2020-07-26 09:40:02 +0200
commit7a161dc688f0eeee64e307a55efbc7d11bab3627 (patch)
tree127cd6d6257e8e484a7021b12790610d308f7594 /src
parent79ed90380547128b9919d407901a886fed0306b7 (diff)
parent9f01ce6327af886f26399924a9aadf16cdd4fd9f (diff)
downloademacs-7a161dc688f0eeee64e307a55efbc7d11bab3627.tar.gz
emacs-7a161dc688f0eeee64e307a55efbc7d11bab3627.zip
Merge remote-tracking branch 'savahnna/master' into HEAD
Diffstat (limited to 'src')
-rw-r--r--src/emacs-module.c108
-rw-r--r--src/emacs.c2
-rw-r--r--src/w32proc.c10
3 files changed, 86 insertions, 34 deletions
diff --git a/src/emacs-module.c b/src/emacs-module.c
index 3d1827c7dad..e4e7da088d7 100644
--- a/src/emacs-module.c
+++ b/src/emacs-module.c
@@ -78,6 +78,7 @@ To add a new module function, proceed as follows:
78#include "emacs-module.h" 78#include "emacs-module.h"
79 79
80#include <stdarg.h> 80#include <stdarg.h>
81#include <stdbool.h>
81#include <stddef.h> 82#include <stddef.h>
82#include <stdint.h> 83#include <stdint.h>
83#include <stdlib.h> 84#include <stdlib.h>
@@ -154,11 +155,11 @@ struct emacs_value_frame
154/* A structure that holds an initial frame (so that the first local 155/* A structure that holds an initial frame (so that the first local
155 values require no dynamic allocation) and keeps track of the 156 values require no dynamic allocation) and keeps track of the
156 current frame. */ 157 current frame. */
157static struct emacs_value_storage 158struct emacs_value_storage
158{ 159{
159 struct emacs_value_frame initial; 160 struct emacs_value_frame initial;
160 struct emacs_value_frame *current; 161 struct emacs_value_frame *current;
161} global_storage; 162};
162 163
163 164
164/* Private runtime and environment members. */ 165/* Private runtime and environment members. */
@@ -371,10 +372,57 @@ module_get_environment (struct emacs_runtime *runtime)
371} 372}
372 373
373/* To make global refs (GC-protected global values) keep a hash that 374/* To make global refs (GC-protected global values) keep a hash that
374 maps global Lisp objects to reference counts. */ 375 maps global Lisp objects to 'struct module_global_reference'
376 objects. We store the 'emacs_value' in the hash table so that it
377 is automatically garbage-collected (Bug#42482). */
375 378
376static Lisp_Object Vmodule_refs_hash; 379static Lisp_Object Vmodule_refs_hash;
377 380
381/* Pseudovector type for global references. The pseudovector tag is
382 PVEC_OTHER since these values are never printed and don't need to
383 be special-cased for garbage collection. */
384
385struct module_global_reference {
386 /* Pseudovector header, must come first. */
387 union vectorlike_header header;
388
389 /* Holds the emacs_value for the object. The Lisp_Object stored
390 therein must be the same as the hash key. */
391 struct emacs_value_tag value;
392
393 /* Reference count, always positive. */
394 ptrdiff_t refcount;
395};
396
397static struct module_global_reference *
398XMODULE_GLOBAL_REFERENCE (Lisp_Object o)
399{
400 eassert (PSEUDOVECTORP (o, PVEC_OTHER));
401 return XUNTAG (o, Lisp_Vectorlike, struct module_global_reference);
402}
403
404/* Returns whether V is a global reference. Only used to check module
405 assertions. If V is not a global reference, increment *N by the
406 number of global references (for debugging output). */
407
408static bool
409module_global_reference_p (emacs_value v, ptrdiff_t *n)
410{
411 struct Lisp_Hash_Table *h = XHASH_TABLE (Vmodule_refs_hash);
412 /* Note that we can't use `hash_lookup' because V might be a local
413 reference that's identical to some global reference. */
414 for (ptrdiff_t i = 0; i < HASH_TABLE_SIZE (h); ++i)
415 {
416 if (!EQ (HASH_KEY (h, i), Qunbound)
417 && &XMODULE_GLOBAL_REFERENCE (HASH_VALUE (h, i))->value == v)
418 return true;
419 }
420 /* Only used for debugging, so we don't care about overflow, just
421 make sure the operation is defined. */
422 INT_ADD_WRAPV (*n, h->count, n);
423 return false;
424}
425
378static emacs_value 426static emacs_value
379module_make_global_ref (emacs_env *env, emacs_value value) 427module_make_global_ref (emacs_env *env, emacs_value value)
380{ 428{
@@ -383,21 +431,30 @@ module_make_global_ref (emacs_env *env, emacs_value value)
383 Lisp_Object new_obj = value_to_lisp (value), hashcode; 431 Lisp_Object new_obj = value_to_lisp (value), hashcode;
384 ptrdiff_t i = hash_lookup (h, new_obj, &hashcode); 432 ptrdiff_t i = hash_lookup (h, new_obj, &hashcode);
385 433
434 /* Note: This approach requires the garbage collector to never move
435 objects. */
436
386 if (i >= 0) 437 if (i >= 0)
387 { 438 {
388 Lisp_Object value = HASH_VALUE (h, i); 439 Lisp_Object value = HASH_VALUE (h, i);
389 EMACS_INT refcount = XFIXNAT (value) + 1; 440 struct module_global_reference *ref = XMODULE_GLOBAL_REFERENCE (value);
390 if (MOST_POSITIVE_FIXNUM < refcount) 441 bool overflow = INT_ADD_WRAPV (ref->refcount, 1, &ref->refcount);
442 if (overflow)
391 overflow_error (); 443 overflow_error ();
392 value = make_fixed_natnum (refcount); 444 return &ref->value;
393 set_hash_value_slot (h, i, value);
394 } 445 }
395 else 446 else
396 { 447 {
397 hash_put (h, new_obj, make_fixed_natnum (1), hashcode); 448 struct module_global_reference *ref
449 = ALLOCATE_PLAIN_PSEUDOVECTOR (struct module_global_reference,
450 PVEC_OTHER);
451 ref->value.v = new_obj;
452 ref->refcount = 1;
453 Lisp_Object value;
454 XSETPSEUDOVECTOR (value, ref, PVEC_OTHER);
455 hash_put (h, new_obj, value, hashcode);
456 return &ref->value;
398 } 457 }
399
400 return allocate_emacs_value (env, &global_storage, new_obj);
401} 458}
402 459
403static void 460static void
@@ -411,25 +468,21 @@ module_free_global_ref (emacs_env *env, emacs_value global_value)
411 Lisp_Object obj = value_to_lisp (global_value); 468 Lisp_Object obj = value_to_lisp (global_value);
412 ptrdiff_t i = hash_lookup (h, obj, NULL); 469 ptrdiff_t i = hash_lookup (h, obj, NULL);
413 470
414 if (i >= 0) 471 if (module_assertions)
415 { 472 {
416 EMACS_INT refcount = XFIXNAT (HASH_VALUE (h, i)) - 1; 473 ptrdiff_t n = 0;
417 if (refcount > 0) 474 if (! module_global_reference_p (global_value, &n))
418 set_hash_value_slot (h, i, make_fixed_natnum (refcount)); 475 module_abort ("Global value was not found in list of %"pD"d globals",
419 else 476 n);
420 {
421 eassert (refcount == 0);
422 hash_remove_from_table (h, obj);
423 }
424 } 477 }
425 478
426 if (module_assertions) 479 if (i >= 0)
427 { 480 {
428 ptrdiff_t count = 0; 481 Lisp_Object value = HASH_VALUE (h, i);
429 if (value_storage_contains_p (&global_storage, global_value, &count)) 482 struct module_global_reference *ref = XMODULE_GLOBAL_REFERENCE (value);
430 return; 483 eassert (0 < ref->refcount);
431 module_abort ("Global value was not found in list of %"pD"d globals", 484 if (--ref->refcount == 0)
432 count); 485 hash_remove_from_table (h, obj);
433 } 486 }
434} 487}
435 488
@@ -1250,7 +1303,7 @@ value_to_lisp (emacs_value v)
1250 ++num_environments; 1303 ++num_environments;
1251 } 1304 }
1252 /* Also check global values. */ 1305 /* Also check global values. */
1253 if (value_storage_contains_p (&global_storage, v, &num_values)) 1306 if (module_global_reference_p (v, &num_values))
1254 goto ok; 1307 goto ok;
1255 module_abort (("Emacs value not found in %"pD"d values " 1308 module_abort (("Emacs value not found in %"pD"d values "
1256 "of %"pD"d environments"), 1309 "of %"pD"d environments"),
@@ -1467,10 +1520,7 @@ module_handle_nonlocal_exit (emacs_env *env, enum nonlocal_exit type,
1467void 1520void
1468init_module_assertions (bool enable) 1521init_module_assertions (bool enable)
1469{ 1522{
1470 /* If enabling module assertions, use a hidden environment for
1471 storing the globals. This environment is never freed. */
1472 module_assertions = enable; 1523 module_assertions = enable;
1473 initialize_storage (&global_storage);
1474} 1524}
1475 1525
1476/* Return whether STORAGE contains VALUE. Used to check module 1526/* Return whether STORAGE contains VALUE. Used to check module
diff --git a/src/emacs.c b/src/emacs.c
index 228ac293370..34717cdae2f 100644
--- a/src/emacs.c
+++ b/src/emacs.c
@@ -2356,6 +2356,8 @@ DEFUN ("kill-emacs", Fkill_emacs, Skill_emacs, 0, 1, "P",
2356 doc: /* Exit the Emacs job and kill it. 2356 doc: /* Exit the Emacs job and kill it.
2357If ARG is an integer, return ARG as the exit program code. 2357If ARG is an integer, return ARG as the exit program code.
2358If ARG is a string, stuff it as keyboard input. 2358If ARG is a string, stuff it as keyboard input.
2359Any other value of ARG, or ARG omitted, means return an
2360exit code that indicates successful program termination.
2359 2361
2360This function is called upon receipt of the signals SIGTERM 2362This function is called upon receipt of the signals SIGTERM
2361or SIGHUP, and upon SIGINT in batch mode. 2363or SIGHUP, and upon SIGINT in batch mode.
diff --git a/src/w32proc.c b/src/w32proc.c
index 16e32e4c58d..c50f246a454 100644
--- a/src/w32proc.c
+++ b/src/w32proc.c
@@ -2790,11 +2790,11 @@ sys_kill (pid_t pid, int sig)
2790 /* Set the foreground window to the child. */ 2790 /* Set the foreground window to the child. */
2791 if (SetForegroundWindow (cp->hwnd)) 2791 if (SetForegroundWindow (cp->hwnd))
2792 { 2792 {
2793 /* Record the state of the Ctrl key: the user could 2793 /* Record the state of the left Ctrl key: the user
2794 have it depressed while we are simulating Ctrl-C, 2794 could have it depressed while we are simulating
2795 in which case we will have to leave the state of 2795 Ctrl-C, in which case we will have to leave the
2796 Ctrl depressed when we are done. */ 2796 state of that Ctrl depressed when we are done. */
2797 short ctrl_state = GetKeyState (VK_CONTROL) & 0x8000; 2797 short ctrl_state = GetKeyState (VK_LCONTROL) & 0x8000;
2798 2798
2799 /* Generate keystrokes as if user had typed Ctrl-Break or 2799 /* Generate keystrokes as if user had typed Ctrl-Break or
2800 Ctrl-C. */ 2800 Ctrl-C. */