diff options
| author | Jan D | 2015-04-03 12:32:13 +0200 |
|---|---|---|
| committer | Jan D | 2015-04-03 12:32:13 +0200 |
| commit | 75c8741afba2321add3ad52c5143b4fdb1d63e18 (patch) | |
| tree | 3a125791aba92eb58bee81163a93c3246f275a54 /src/alloc.c | |
| parent | 734900695acbe17bc7c52c85133918b8949fd2d3 (diff) | |
| parent | 0b914bada39e4577cd9e9209a15c44cc1f83294d (diff) | |
| download | emacs-75c8741afba2321add3ad52c5143b4fdb1d63e18.tar.gz emacs-75c8741afba2321add3ad52c5143b4fdb1d63e18.zip | |
Merge branch 'master' into cairo
Diffstat (limited to 'src/alloc.c')
| -rw-r--r-- | src/alloc.c | 213 |
1 files changed, 186 insertions, 27 deletions
diff --git a/src/alloc.c b/src/alloc.c index 9aa94b8a559..1f4b1a4694e 100644 --- a/src/alloc.c +++ b/src/alloc.c | |||
| @@ -441,6 +441,15 @@ mmap_lisp_allowed_p (void) | |||
| 441 | return pointers_fit_in_lispobj_p () && !might_dump; | 441 | return pointers_fit_in_lispobj_p () && !might_dump; |
| 442 | } | 442 | } |
| 443 | 443 | ||
| 444 | /* Head of a circularly-linked list of extant finalizers. */ | ||
| 445 | static struct Lisp_Finalizer finalizers; | ||
| 446 | |||
| 447 | /* Head of a circularly-linked list of finalizers that must be invoked | ||
| 448 | because we deemed them unreachable. This list must be global, and | ||
| 449 | not a local inside garbage_collect_1, in case we GC again while | ||
| 450 | running finalizers. */ | ||
| 451 | static struct Lisp_Finalizer doomed_finalizers; | ||
| 452 | |||
| 444 | 453 | ||
| 445 | /************************************************************************ | 454 | /************************************************************************ |
| 446 | Malloc | 455 | Malloc |
| @@ -3414,7 +3423,7 @@ union aligned_Lisp_Misc | |||
| 3414 | }; | 3423 | }; |
| 3415 | 3424 | ||
| 3416 | /* Allocation of markers and other objects that share that structure. | 3425 | /* Allocation of markers and other objects that share that structure. |
| 3417 | Works like allocation of conses. */ | 3426 | Works like allocation of conses. */ |
| 3418 | 3427 | ||
| 3419 | #define MARKER_BLOCK_SIZE \ | 3428 | #define MARKER_BLOCK_SIZE \ |
| 3420 | ((1020 - sizeof (struct marker_block *)) / sizeof (union aligned_Lisp_Misc)) | 3429 | ((1020 - sizeof (struct marker_block *)) / sizeof (union aligned_Lisp_Misc)) |
| @@ -3695,6 +3704,128 @@ make_event_array (ptrdiff_t nargs, Lisp_Object *args) | |||
| 3695 | } | 3704 | } |
| 3696 | } | 3705 | } |
| 3697 | 3706 | ||
| 3707 | static void | ||
| 3708 | init_finalizer_list (struct Lisp_Finalizer *head) | ||
| 3709 | { | ||
| 3710 | head->prev = head->next = head; | ||
| 3711 | } | ||
| 3712 | |||
| 3713 | /* Insert FINALIZER before ELEMENT. */ | ||
| 3714 | |||
| 3715 | static void | ||
| 3716 | finalizer_insert (struct Lisp_Finalizer *element, | ||
| 3717 | struct Lisp_Finalizer *finalizer) | ||
| 3718 | { | ||
| 3719 | eassert (finalizer->prev == NULL); | ||
| 3720 | eassert (finalizer->next == NULL); | ||
| 3721 | finalizer->next = element; | ||
| 3722 | finalizer->prev = element->prev; | ||
| 3723 | finalizer->prev->next = finalizer; | ||
| 3724 | element->prev = finalizer; | ||
| 3725 | } | ||
| 3726 | |||
| 3727 | static void | ||
| 3728 | unchain_finalizer (struct Lisp_Finalizer *finalizer) | ||
| 3729 | { | ||
| 3730 | if (finalizer->prev != NULL) | ||
| 3731 | { | ||
| 3732 | eassert (finalizer->next != NULL); | ||
| 3733 | finalizer->prev->next = finalizer->next; | ||
| 3734 | finalizer->next->prev = finalizer->prev; | ||
| 3735 | finalizer->prev = finalizer->next = NULL; | ||
| 3736 | } | ||
| 3737 | } | ||
| 3738 | |||
| 3739 | static void | ||
| 3740 | mark_finalizer_list (struct Lisp_Finalizer *head) | ||
| 3741 | { | ||
| 3742 | for (struct Lisp_Finalizer *finalizer = head->next; | ||
| 3743 | finalizer != head; | ||
| 3744 | finalizer = finalizer->next) | ||
| 3745 | { | ||
| 3746 | finalizer->base.gcmarkbit = true; | ||
| 3747 | mark_object (finalizer->function); | ||
| 3748 | } | ||
| 3749 | } | ||
| 3750 | |||
| 3751 | /* Move doomed finalizers to list DEST from list SRC. A doomed | ||
| 3752 | finalizer is one that is not GC-reachable and whose | ||
| 3753 | finalizer->function is non-nil. */ | ||
| 3754 | |||
| 3755 | static void | ||
| 3756 | queue_doomed_finalizers (struct Lisp_Finalizer *dest, | ||
| 3757 | struct Lisp_Finalizer *src) | ||
| 3758 | { | ||
| 3759 | struct Lisp_Finalizer *finalizer = src->next; | ||
| 3760 | while (finalizer != src) | ||
| 3761 | { | ||
| 3762 | struct Lisp_Finalizer *next = finalizer->next; | ||
| 3763 | if (!finalizer->base.gcmarkbit && !NILP (finalizer->function)) | ||
| 3764 | { | ||
| 3765 | unchain_finalizer (finalizer); | ||
| 3766 | finalizer_insert (dest, finalizer); | ||
| 3767 | } | ||
| 3768 | |||
| 3769 | finalizer = next; | ||
| 3770 | } | ||
| 3771 | } | ||
| 3772 | |||
| 3773 | static Lisp_Object | ||
| 3774 | run_finalizer_handler (Lisp_Object args) | ||
| 3775 | { | ||
| 3776 | add_to_log ("finalizer failed: %S", args, Qnil); | ||
| 3777 | return Qnil; | ||
| 3778 | } | ||
| 3779 | |||
| 3780 | static void | ||
| 3781 | run_finalizer_function (Lisp_Object function) | ||
| 3782 | { | ||
| 3783 | struct gcpro gcpro1; | ||
| 3784 | ptrdiff_t count = SPECPDL_INDEX (); | ||
| 3785 | |||
| 3786 | GCPRO1 (function); | ||
| 3787 | specbind (Qinhibit_quit, Qt); | ||
| 3788 | internal_condition_case_1 (call0, function, Qt, run_finalizer_handler); | ||
| 3789 | unbind_to (count, Qnil); | ||
| 3790 | UNGCPRO; | ||
| 3791 | } | ||
| 3792 | |||
| 3793 | static void | ||
| 3794 | run_finalizers (struct Lisp_Finalizer *finalizers) | ||
| 3795 | { | ||
| 3796 | struct Lisp_Finalizer *finalizer; | ||
| 3797 | Lisp_Object function; | ||
| 3798 | |||
| 3799 | while (finalizers->next != finalizers) | ||
| 3800 | { | ||
| 3801 | finalizer = finalizers->next; | ||
| 3802 | eassert (finalizer->base.type == Lisp_Misc_Finalizer); | ||
| 3803 | unchain_finalizer (finalizer); | ||
| 3804 | function = finalizer->function; | ||
| 3805 | if (!NILP (function)) | ||
| 3806 | { | ||
| 3807 | finalizer->function = Qnil; | ||
| 3808 | run_finalizer_function (function); | ||
| 3809 | } | ||
| 3810 | } | ||
| 3811 | } | ||
| 3812 | |||
| 3813 | DEFUN ("make-finalizer", Fmake_finalizer, Smake_finalizer, 1, 1, 0, | ||
| 3814 | doc: /* Make a finalizer that will run FUNCTION. | ||
| 3815 | FUNCTION will be called after garbage collection when the returned | ||
| 3816 | finalizer object becomes unreachable. If the finalizer object is | ||
| 3817 | reachable only through references from finalizer objects, it does not | ||
| 3818 | count as reachable for the purpose of deciding whether to run | ||
| 3819 | FUNCTION. FUNCTION will be run once per finalizer object. */) | ||
| 3820 | (Lisp_Object function) | ||
| 3821 | { | ||
| 3822 | Lisp_Object val = allocate_misc (Lisp_Misc_Finalizer); | ||
| 3823 | struct Lisp_Finalizer *finalizer = XFINALIZER (val); | ||
| 3824 | finalizer->function = function; | ||
| 3825 | finalizer->prev = finalizer->next = NULL; | ||
| 3826 | finalizer_insert (&finalizers, finalizer); | ||
| 3827 | return val; | ||
| 3828 | } | ||
| 3698 | 3829 | ||
| 3699 | 3830 | ||
| 3700 | /************************************************************************ | 3831 | /************************************************************************ |
| @@ -4613,7 +4744,7 @@ mark_maybe_pointer (void *p) | |||
| 4613 | #endif | 4744 | #endif |
| 4614 | 4745 | ||
| 4615 | /* Mark Lisp objects referenced from the address range START+OFFSET..END | 4746 | /* Mark Lisp objects referenced from the address range START+OFFSET..END |
| 4616 | or END+OFFSET..START. */ | 4747 | or END+OFFSET..START. */ |
| 4617 | 4748 | ||
| 4618 | static void ATTRIBUTE_NO_SANITIZE_ADDRESS | 4749 | static void ATTRIBUTE_NO_SANITIZE_ADDRESS |
| 4619 | mark_memory (void *start, void *end) | 4750 | mark_memory (void *start, void *end) |
| @@ -5225,7 +5356,6 @@ make_pure_vector (ptrdiff_t len) | |||
| 5225 | return new; | 5356 | return new; |
| 5226 | } | 5357 | } |
| 5227 | 5358 | ||
| 5228 | |||
| 5229 | DEFUN ("purecopy", Fpurecopy, Spurecopy, 1, 1, 0, | 5359 | DEFUN ("purecopy", Fpurecopy, Spurecopy, 1, 1, 0, |
| 5230 | doc: /* Make a copy of object OBJ in pure storage. | 5360 | doc: /* Make a copy of object OBJ in pure storage. |
| 5231 | Recursively copies contents of vectors and cons cells. | 5361 | Recursively copies contents of vectors and cons cells. |
| @@ -5260,28 +5390,26 @@ purecopy (Lisp_Object obj) | |||
| 5260 | else if (FLOATP (obj)) | 5390 | else if (FLOATP (obj)) |
| 5261 | obj = make_pure_float (XFLOAT_DATA (obj)); | 5391 | obj = make_pure_float (XFLOAT_DATA (obj)); |
| 5262 | else if (STRINGP (obj)) | 5392 | else if (STRINGP (obj)) |
| 5263 | obj = make_pure_string (SSDATA (obj), SCHARS (obj), | ||
| 5264 | SBYTES (obj), | ||
| 5265 | STRING_MULTIBYTE (obj)); | ||
| 5266 | else if (COMPILEDP (obj) || VECTORP (obj)) | ||
| 5267 | { | 5393 | { |
| 5268 | register struct Lisp_Vector *vec; | 5394 | if (XSTRING (obj)->intervals) |
| 5395 | message ("Dropping text-properties when making string pure"); | ||
| 5396 | obj = make_pure_string (SSDATA (obj), SCHARS (obj), | ||
| 5397 | SBYTES (obj), | ||
| 5398 | STRING_MULTIBYTE (obj)); | ||
| 5399 | } | ||
| 5400 | else if (COMPILEDP (obj) || VECTORP (obj) || HASH_TABLE_P (obj)) | ||
| 5401 | { | ||
| 5402 | struct Lisp_Vector *objp = XVECTOR (obj); | ||
| 5403 | ptrdiff_t nbytes = vector_nbytes (objp); | ||
| 5404 | struct Lisp_Vector *vec = pure_alloc (nbytes, Lisp_Vectorlike); | ||
| 5269 | register ptrdiff_t i; | 5405 | register ptrdiff_t i; |
| 5270 | ptrdiff_t size; | 5406 | ptrdiff_t size = ASIZE (obj); |
| 5271 | |||
| 5272 | size = ASIZE (obj); | ||
| 5273 | if (size & PSEUDOVECTOR_FLAG) | 5407 | if (size & PSEUDOVECTOR_FLAG) |
| 5274 | size &= PSEUDOVECTOR_SIZE_MASK; | 5408 | size &= PSEUDOVECTOR_SIZE_MASK; |
| 5275 | vec = XVECTOR (make_pure_vector (size)); | 5409 | memcpy (vec, objp, nbytes); |
| 5276 | for (i = 0; i < size; i++) | 5410 | for (i = 0; i < size; i++) |
| 5277 | vec->contents[i] = purecopy (AREF (obj, i)); | 5411 | vec->contents[i] = purecopy (vec->contents[i]); |
| 5278 | if (COMPILEDP (obj)) | 5412 | XSETVECTOR (obj, vec); |
| 5279 | { | ||
| 5280 | XSETPVECTYPE (vec, PVEC_COMPILED); | ||
| 5281 | XSETCOMPILED (obj, vec); | ||
| 5282 | } | ||
| 5283 | else | ||
| 5284 | XSETVECTOR (obj, vec); | ||
| 5285 | } | 5413 | } |
| 5286 | else if (SYMBOLP (obj)) | 5414 | else if (SYMBOLP (obj)) |
| 5287 | { | 5415 | { |
| @@ -5291,6 +5419,7 @@ purecopy (Lisp_Object obj) | |||
| 5291 | XSYMBOL (obj)->pinned = true; | 5419 | XSYMBOL (obj)->pinned = true; |
| 5292 | symbol_block_pinned = symbol_block; | 5420 | symbol_block_pinned = symbol_block; |
| 5293 | } | 5421 | } |
| 5422 | /* Don't hash-cons it. */ | ||
| 5294 | return obj; | 5423 | return obj; |
| 5295 | } | 5424 | } |
| 5296 | else | 5425 | else |
| @@ -5613,9 +5742,9 @@ garbage_collect_1 (void *end) | |||
| 5613 | mark_stack (end); | 5742 | mark_stack (end); |
| 5614 | #endif | 5743 | #endif |
| 5615 | 5744 | ||
| 5616 | /* Everything is now marked, except for the data in font caches | 5745 | /* Everything is now marked, except for the data in font caches, |
| 5617 | and undo lists. They're compacted by removing an items which | 5746 | undo lists, and finalizers. The first two are compacted by |
| 5618 | aren't reachable otherwise. */ | 5747 | removing an items which aren't reachable otherwise. */ |
| 5619 | 5748 | ||
| 5620 | compact_font_caches (); | 5749 | compact_font_caches (); |
| 5621 | 5750 | ||
| @@ -5628,6 +5757,16 @@ garbage_collect_1 (void *end) | |||
| 5628 | mark_object (BVAR (nextb, undo_list)); | 5757 | mark_object (BVAR (nextb, undo_list)); |
| 5629 | } | 5758 | } |
| 5630 | 5759 | ||
| 5760 | /* Now pre-sweep finalizers. Here, we add any unmarked finalizers | ||
| 5761 | to doomed_finalizers so we can run their associated functions | ||
| 5762 | after GC. It's important to scan finalizers at this stage so | ||
| 5763 | that we can be sure that unmarked finalizers are really | ||
| 5764 | unreachable except for references from their associated functions | ||
| 5765 | and from other finalizers. */ | ||
| 5766 | |||
| 5767 | queue_doomed_finalizers (&doomed_finalizers, &finalizers); | ||
| 5768 | mark_finalizer_list (&doomed_finalizers); | ||
| 5769 | |||
| 5631 | gc_sweep (); | 5770 | gc_sweep (); |
| 5632 | 5771 | ||
| 5633 | /* Clear the mark bits that we set in certain root slots. */ | 5772 | /* Clear the mark bits that we set in certain root slots. */ |
| @@ -5728,6 +5867,9 @@ garbage_collect_1 (void *end) | |||
| 5728 | } | 5867 | } |
| 5729 | #endif | 5868 | #endif |
| 5730 | 5869 | ||
| 5870 | /* GC is complete: now we can run our finalizer callbacks. */ | ||
| 5871 | run_finalizers (&doomed_finalizers); | ||
| 5872 | |||
| 5731 | if (!NILP (Vpost_gc_hook)) | 5873 | if (!NILP (Vpost_gc_hook)) |
| 5732 | { | 5874 | { |
| 5733 | ptrdiff_t gc_count = inhibit_garbage_collection (); | 5875 | ptrdiff_t gc_count = inhibit_garbage_collection (); |
| @@ -6085,13 +6227,14 @@ mark_discard_killed_buffers (Lisp_Object list) | |||
| 6085 | void | 6227 | void |
| 6086 | mark_object (Lisp_Object arg) | 6228 | mark_object (Lisp_Object arg) |
| 6087 | { | 6229 | { |
| 6088 | register Lisp_Object obj = arg; | 6230 | register Lisp_Object obj; |
| 6089 | void *po; | 6231 | void *po; |
| 6090 | #ifdef GC_CHECK_MARKED_OBJECTS | 6232 | #ifdef GC_CHECK_MARKED_OBJECTS |
| 6091 | struct mem_node *m; | 6233 | struct mem_node *m; |
| 6092 | #endif | 6234 | #endif |
| 6093 | ptrdiff_t cdr_count = 0; | 6235 | ptrdiff_t cdr_count = 0; |
| 6094 | 6236 | ||
| 6237 | obj = arg; | ||
| 6095 | loop: | 6238 | loop: |
| 6096 | 6239 | ||
| 6097 | po = XPNTR (obj); | 6240 | po = XPNTR (obj); |
| @@ -6364,7 +6507,12 @@ mark_object (Lisp_Object arg) | |||
| 6364 | 6507 | ||
| 6365 | case Lisp_Misc_Overlay: | 6508 | case Lisp_Misc_Overlay: |
| 6366 | mark_overlay (XOVERLAY (obj)); | 6509 | mark_overlay (XOVERLAY (obj)); |
| 6367 | break; | 6510 | break; |
| 6511 | |||
| 6512 | case Lisp_Misc_Finalizer: | ||
| 6513 | XMISCANY (obj)->gcmarkbit = true; | ||
| 6514 | mark_object (XFINALIZER (obj)->function); | ||
| 6515 | break; | ||
| 6368 | 6516 | ||
| 6369 | default: | 6517 | default: |
| 6370 | emacs_abort (); | 6518 | emacs_abort (); |
| @@ -6721,7 +6869,7 @@ sweep_symbols (void) | |||
| 6721 | total_free_symbols = num_free; | 6869 | total_free_symbols = num_free; |
| 6722 | } | 6870 | } |
| 6723 | 6871 | ||
| 6724 | NO_INLINE /* For better stack traces */ | 6872 | NO_INLINE /* For better stack traces. */ |
| 6725 | static void | 6873 | static void |
| 6726 | sweep_misc (void) | 6874 | sweep_misc (void) |
| 6727 | { | 6875 | { |
| @@ -6746,6 +6894,8 @@ sweep_misc (void) | |||
| 6746 | { | 6894 | { |
| 6747 | if (mblk->markers[i].m.u_any.type == Lisp_Misc_Marker) | 6895 | if (mblk->markers[i].m.u_any.type == Lisp_Misc_Marker) |
| 6748 | unchain_marker (&mblk->markers[i].m.u_marker); | 6896 | unchain_marker (&mblk->markers[i].m.u_marker); |
| 6897 | if (mblk->markers[i].m.u_any.type == Lisp_Misc_Finalizer) | ||
| 6898 | unchain_finalizer (&mblk->markers[i].m.u_finalizer); | ||
| 6749 | /* Set the type of the freed object to Lisp_Misc_Free. | 6899 | /* Set the type of the freed object to Lisp_Misc_Free. |
| 6750 | We could leave the type alone, since nobody checks it, | 6900 | We could leave the type alone, since nobody checks it, |
| 6751 | but this might catch bugs faster. */ | 6901 | but this might catch bugs faster. */ |
| @@ -7115,11 +7265,14 @@ init_alloc_once (void) | |||
| 7115 | { | 7265 | { |
| 7116 | /* Even though Qt's contents are not set up, its address is known. */ | 7266 | /* Even though Qt's contents are not set up, its address is known. */ |
| 7117 | Vpurify_flag = Qt; | 7267 | Vpurify_flag = Qt; |
| 7268 | gc_precise = (GC_MARK_STACK == GC_USE_GCPROS_AS_BEFORE); | ||
| 7118 | 7269 | ||
| 7119 | purebeg = PUREBEG; | 7270 | purebeg = PUREBEG; |
| 7120 | pure_size = PURESIZE; | 7271 | pure_size = PURESIZE; |
| 7121 | 7272 | ||
| 7122 | verify_alloca (); | 7273 | verify_alloca (); |
| 7274 | init_finalizer_list (&finalizers); | ||
| 7275 | init_finalizer_list (&doomed_finalizers); | ||
| 7123 | 7276 | ||
| 7124 | #if GC_MARK_STACK || defined GC_MALLOC_CHECK | 7277 | #if GC_MARK_STACK || defined GC_MALLOC_CHECK |
| 7125 | mem_init (); | 7278 | mem_init (); |
| @@ -7254,7 +7407,12 @@ do hash-consing of the objects allocated to pure space. */); | |||
| 7254 | doc: /* Accumulated time elapsed in garbage collections. | 7407 | doc: /* Accumulated time elapsed in garbage collections. |
| 7255 | The time is in seconds as a floating point value. */); | 7408 | The time is in seconds as a floating point value. */); |
| 7256 | DEFVAR_INT ("gcs-done", gcs_done, | 7409 | DEFVAR_INT ("gcs-done", gcs_done, |
| 7257 | doc: /* Accumulated number of garbage collections done. */); | 7410 | doc: /* Accumulated number of garbage collections done. */); |
| 7411 | |||
| 7412 | DEFVAR_BOOL ("gc-precise", gc_precise, | ||
| 7413 | doc: /* Non-nil means GC stack marking is precise. | ||
| 7414 | Useful mainly for automated GC tests. Build time constant.*/); | ||
| 7415 | XSYMBOL (intern_c_string ("gc-precise"))->constant = 1; | ||
| 7258 | 7416 | ||
| 7259 | defsubr (&Scons); | 7417 | defsubr (&Scons); |
| 7260 | defsubr (&Slist); | 7418 | defsubr (&Slist); |
| @@ -7267,6 +7425,7 @@ The time is in seconds as a floating point value. */); | |||
| 7267 | defsubr (&Smake_bool_vector); | 7425 | defsubr (&Smake_bool_vector); |
| 7268 | defsubr (&Smake_symbol); | 7426 | defsubr (&Smake_symbol); |
| 7269 | defsubr (&Smake_marker); | 7427 | defsubr (&Smake_marker); |
| 7428 | defsubr (&Smake_finalizer); | ||
| 7270 | defsubr (&Spurecopy); | 7429 | defsubr (&Spurecopy); |
| 7271 | defsubr (&Sgarbage_collect); | 7430 | defsubr (&Sgarbage_collect); |
| 7272 | defsubr (&Smemory_limit); | 7431 | defsubr (&Smemory_limit); |