diff options
| author | Stefan Monnier | 2007-10-02 21:16:53 +0000 |
|---|---|---|
| committer | Stefan Monnier | 2007-10-02 21:16:53 +0000 |
| commit | d2029e5b8196e9d670dcbf96555cd92590a0384c (patch) | |
| tree | 1c8a46e16b98b40bbac9bf2cbee6993629865f04 /src/alloc.c | |
| parent | cf00e751e15a327f5cf3d4953ed658aa6ec670a6 (diff) | |
| download | emacs-d2029e5b8196e9d670dcbf96555cd92590a0384c.tar.gz emacs-d2029e5b8196e9d670dcbf96555cd92590a0384c.zip | |
(allocate_pseudovector): New fun.
(ALLOCATE_PSEUDOVECTOR): New macro.
(allocate_window, allocate_terminal, allocate_frame)
(allocate_process): Use it.
(mark_vectorlike): New function.
(mark_object) <FRAMEP, WINDOWP, BOOL_VECTOR_P, VECTORP>: Use it.
(mark_terminals): Use it.
(Fmake_bool_vector, Fmake_char_table, make_sub_char_table)
(Fmake_byte_code): Use XSETPVECTYPE.
Diffstat (limited to 'src/alloc.c')
| -rw-r--r-- | src/alloc.c | 215 |
1 files changed, 84 insertions, 131 deletions
diff --git a/src/alloc.c b/src/alloc.c index 0d64bf66663..d9652a90e01 100644 --- a/src/alloc.c +++ b/src/alloc.c | |||
| @@ -2338,11 +2338,12 @@ LENGTH must be a number. INIT matters only in whether it is t or nil. */) | |||
| 2338 | /* We must allocate one more elements than LENGTH_IN_ELTS for the | 2338 | /* We must allocate one more elements than LENGTH_IN_ELTS for the |
| 2339 | slot `size' of the struct Lisp_Bool_Vector. */ | 2339 | slot `size' of the struct Lisp_Bool_Vector. */ |
| 2340 | val = Fmake_vector (make_number (length_in_elts + 1), Qnil); | 2340 | val = Fmake_vector (make_number (length_in_elts + 1), Qnil); |
| 2341 | p = XBOOL_VECTOR (val); | ||
| 2342 | 2341 | ||
| 2343 | /* Get rid of any bits that would cause confusion. */ | 2342 | /* Get rid of any bits that would cause confusion. */ |
| 2344 | p->vector_size = 0; | 2343 | XVECTOR (val)->size = 0; /* No Lisp_Object to trace in there. */ |
| 2345 | XSETBOOL_VECTOR (val, p); | 2344 | XSETPVECTYPE (XVECTOR (val), PVEC_BOOL_VECTOR); |
| 2345 | |||
| 2346 | p = XBOOL_VECTOR (val); | ||
| 2346 | p->size = XFASTINT (length); | 2347 | p->size = XFASTINT (length); |
| 2347 | 2348 | ||
| 2348 | real_init = (NILP (init) ? 0 : -1); | 2349 | real_init = (NILP (init) ? 0 : -1); |
| @@ -2351,7 +2352,7 @@ LENGTH must be a number. INIT matters only in whether it is t or nil. */) | |||
| 2351 | 2352 | ||
| 2352 | /* Clear the extraneous bits in the last byte. */ | 2353 | /* Clear the extraneous bits in the last byte. */ |
| 2353 | if (XINT (length) != length_in_chars * BOOL_VECTOR_BITS_PER_CHAR) | 2354 | if (XINT (length) != length_in_chars * BOOL_VECTOR_BITS_PER_CHAR) |
| 2354 | XBOOL_VECTOR (val)->data[length_in_chars - 1] | 2355 | p->data[length_in_chars - 1] |
| 2355 | &= (1 << (XINT (length) % BOOL_VECTOR_BITS_PER_CHAR)) - 1; | 2356 | &= (1 << (XINT (length) % BOOL_VECTOR_BITS_PER_CHAR)) - 1; |
| 2356 | 2357 | ||
| 2357 | return val; | 2358 | return val; |
| @@ -2963,6 +2964,27 @@ allocate_vector (nslots) | |||
| 2963 | 2964 | ||
| 2964 | /* Allocate other vector-like structures. */ | 2965 | /* Allocate other vector-like structures. */ |
| 2965 | 2966 | ||
| 2967 | static struct Lisp_Vector * | ||
| 2968 | allocate_pseudovector (memlen, lisplen, tag) | ||
| 2969 | int memlen, lisplen; | ||
| 2970 | EMACS_INT tag; | ||
| 2971 | { | ||
| 2972 | struct Lisp_Vector *v = allocate_vectorlike (memlen); | ||
| 2973 | EMACS_INT i; | ||
| 2974 | |||
| 2975 | /* Only the first lisplen slots will be traced normally by the GC. */ | ||
| 2976 | v->size = lisplen; | ||
| 2977 | for (i = 0; i < lisplen; ++i) | ||
| 2978 | v->contents[i] = Qnil; | ||
| 2979 | |||
| 2980 | XSETPVECTYPE (v, tag); /* Add the appropriate tag. */ | ||
| 2981 | return v; | ||
| 2982 | } | ||
| 2983 | #define ALLOCATE_PSEUDOVECTOR(typ,field,tag) \ | ||
| 2984 | ((typ*) \ | ||
| 2985 | allocate_pseudovector \ | ||
| 2986 | (VECSIZE (typ), PSEUDOVECSIZE (typ, field), tag)) | ||
| 2987 | |||
| 2966 | struct Lisp_Hash_Table * | 2988 | struct Lisp_Hash_Table * |
| 2967 | allocate_hash_table () | 2989 | allocate_hash_table () |
| 2968 | { | 2990 | { |
| @@ -2976,78 +2998,47 @@ allocate_hash_table () | |||
| 2976 | 2998 | ||
| 2977 | return (struct Lisp_Hash_Table *) v; | 2999 | return (struct Lisp_Hash_Table *) v; |
| 2978 | } | 3000 | } |
| 2979 | 3001 | ||
| 2980 | 3002 | ||
| 2981 | struct window * | 3003 | struct window * |
| 2982 | allocate_window () | 3004 | allocate_window () |
| 2983 | { | 3005 | { |
| 2984 | EMACS_INT len = VECSIZE (struct window); | 3006 | return ALLOCATE_PSEUDOVECTOR(struct window, current_matrix, PVEC_WINDOW); |
| 2985 | struct Lisp_Vector *v = allocate_vectorlike (len); | ||
| 2986 | EMACS_INT i; | ||
| 2987 | |||
| 2988 | for (i = 0; i < len; ++i) | ||
| 2989 | v->contents[i] = Qnil; | ||
| 2990 | v->size = len; | ||
| 2991 | |||
| 2992 | return (struct window *) v; | ||
| 2993 | } | 3007 | } |
| 2994 | 3008 | ||
| 2995 | 3009 | ||
| 2996 | struct terminal * | 3010 | struct terminal * |
| 2997 | allocate_terminal () | 3011 | allocate_terminal () |
| 2998 | { | 3012 | { |
| 2999 | /* Memory-footprint of the object in nb of Lisp_Object fields. */ | 3013 | struct terminal *t = ALLOCATE_PSEUDOVECTOR (struct terminal, |
| 3000 | EMACS_INT memlen = VECSIZE (struct terminal); | 3014 | next_terminal, PVEC_TERMINAL); |
| 3001 | /* Size if we only count the actual Lisp_Object fields (which need to be | 3015 | /* Zero out the non-GC'd fields. FIXME: This should be made unnecessary. */ |
| 3002 | traced by the GC). */ | 3016 | bzero (&(t->next_terminal), |
| 3003 | EMACS_INT lisplen = PSEUDOVECSIZE (struct terminal, next_terminal); | 3017 | ((char*)(t+1)) - ((char*)&(t->next_terminal))); |
| 3004 | struct Lisp_Vector *v = allocate_vectorlike (memlen); | ||
| 3005 | EMACS_INT i; | ||
| 3006 | Lisp_Object tmp, zero = make_number (0); | ||
| 3007 | 3018 | ||
| 3008 | for (i = 0; i < lisplen; ++i) | 3019 | return t; |
| 3009 | v->contents[i] = Qnil; | ||
| 3010 | for (;i < memlen; ++i) | ||
| 3011 | v->contents[i] = zero; | ||
| 3012 | v->size = lisplen; /* Only trace the Lisp fields. */ | ||
| 3013 | XSETTERMINAL (tmp, v); /* Add the appropriate tag. */ | ||
| 3014 | |||
| 3015 | return (struct terminal *) v; | ||
| 3016 | } | 3020 | } |
| 3017 | 3021 | ||
| 3018 | struct frame * | 3022 | struct frame * |
| 3019 | allocate_frame () | 3023 | allocate_frame () |
| 3020 | { | 3024 | { |
| 3021 | EMACS_INT len = VECSIZE (struct frame); | 3025 | struct frame *f = ALLOCATE_PSEUDOVECTOR (struct frame, |
| 3022 | struct Lisp_Vector *v = allocate_vectorlike (len); | 3026 | face_cache, PVEC_FRAME); |
| 3023 | EMACS_INT i; | 3027 | /* Zero out the non-GC'd fields. FIXME: This should be made unnecessary. */ |
| 3024 | 3028 | bzero (&(f->face_cache), | |
| 3025 | for (i = 0; i < len; ++i) | 3029 | ((char*)(f+1)) - ((char*)&(f->face_cache))); |
| 3026 | v->contents[i] = make_number (0); | 3030 | return f; |
| 3027 | v->size = len; | ||
| 3028 | return (struct frame *) v; | ||
| 3029 | } | 3031 | } |
| 3030 | 3032 | ||
| 3031 | 3033 | ||
| 3032 | struct Lisp_Process * | 3034 | struct Lisp_Process * |
| 3033 | allocate_process () | 3035 | allocate_process () |
| 3034 | { | 3036 | { |
| 3035 | /* Memory-footprint of the object in nb of Lisp_Object fields. */ | 3037 | return ALLOCATE_PSEUDOVECTOR (struct Lisp_Process, pid, PVEC_PROCESS); |
| 3036 | EMACS_INT memlen = VECSIZE (struct Lisp_Process); | ||
| 3037 | /* Size if we only count the actual Lisp_Object fields (which need to be | ||
| 3038 | traced by the GC). */ | ||
| 3039 | EMACS_INT lisplen = PSEUDOVECSIZE (struct Lisp_Process, pid); | ||
| 3040 | struct Lisp_Vector *v = allocate_vectorlike (memlen); | ||
| 3041 | EMACS_INT i; | ||
| 3042 | |||
| 3043 | for (i = 0; i < lisplen; ++i) | ||
| 3044 | v->contents[i] = Qnil; | ||
| 3045 | v->size = lisplen; | ||
| 3046 | |||
| 3047 | return (struct Lisp_Process *) v; | ||
| 3048 | } | 3038 | } |
| 3049 | 3039 | ||
| 3050 | 3040 | ||
| 3041 | /* Only used for PVEC_WINDOW_CONFIGURATION. */ | ||
| 3051 | struct Lisp_Vector * | 3042 | struct Lisp_Vector * |
| 3052 | allocate_other_vector (len) | 3043 | allocate_other_vector (len) |
| 3053 | EMACS_INT len; | 3044 | EMACS_INT len; |
| @@ -3104,6 +3095,7 @@ The property's value should be an integer between 0 and 10. */) | |||
| 3104 | /* Add 2 to the size for the defalt and parent slots. */ | 3095 | /* Add 2 to the size for the defalt and parent slots. */ |
| 3105 | vector = Fmake_vector (make_number (CHAR_TABLE_STANDARD_SLOTS + XINT (n)), | 3096 | vector = Fmake_vector (make_number (CHAR_TABLE_STANDARD_SLOTS + XINT (n)), |
| 3106 | init); | 3097 | init); |
| 3098 | XSETPVECTYPE (XVECTOR (vector), PVEC_CHAR_TABLE); | ||
| 3107 | XCHAR_TABLE (vector)->top = Qt; | 3099 | XCHAR_TABLE (vector)->top = Qt; |
| 3108 | XCHAR_TABLE (vector)->parent = Qnil; | 3100 | XCHAR_TABLE (vector)->parent = Qnil; |
| 3109 | XCHAR_TABLE (vector)->purpose = purpose; | 3101 | XCHAR_TABLE (vector)->purpose = purpose; |
| @@ -3122,6 +3114,7 @@ make_sub_char_table (init) | |||
| 3122 | { | 3114 | { |
| 3123 | Lisp_Object vector | 3115 | Lisp_Object vector |
| 3124 | = Fmake_vector (make_number (SUB_CHAR_TABLE_STANDARD_SLOTS), init); | 3116 | = Fmake_vector (make_number (SUB_CHAR_TABLE_STANDARD_SLOTS), init); |
| 3117 | XSETPVECTYPE (XVECTOR (vector), PVEC_CHAR_TABLE); | ||
| 3125 | XCHAR_TABLE (vector)->top = Qnil; | 3118 | XCHAR_TABLE (vector)->top = Qnil; |
| 3126 | XCHAR_TABLE (vector)->defalt = Qnil; | 3119 | XCHAR_TABLE (vector)->defalt = Qnil; |
| 3127 | XSETCHAR_TABLE (vector, XCHAR_TABLE (vector)); | 3120 | XSETCHAR_TABLE (vector, XCHAR_TABLE (vector)); |
| @@ -3186,6 +3179,7 @@ usage: (make-byte-code ARGLIST BYTE-CODE CONSTANTS DEPTH &optional DOCSTRING INT | |||
| 3186 | args[index] = Fpurecopy (args[index]); | 3179 | args[index] = Fpurecopy (args[index]); |
| 3187 | p->contents[index] = args[index]; | 3180 | p->contents[index] = args[index]; |
| 3188 | } | 3181 | } |
| 3182 | XSETPVECTYPE (p, PVEC_COMPILED); | ||
| 3189 | XSETCOMPILED (val, p); | 3183 | XSETCOMPILED (val, p); |
| 3190 | return val; | 3184 | return val; |
| 3191 | } | 3185 | } |
| @@ -5442,6 +5436,29 @@ int last_marked_index; | |||
| 5442 | Normally this is zero and the check never goes off. */ | 5436 | Normally this is zero and the check never goes off. */ |
| 5443 | int mark_object_loop_halt; | 5437 | int mark_object_loop_halt; |
| 5444 | 5438 | ||
| 5439 | /* Return non-zero if the object was not yet marked. */ | ||
| 5440 | static int | ||
| 5441 | mark_vectorlike (ptr) | ||
| 5442 | struct Lisp_Vector *ptr; | ||
| 5443 | { | ||
| 5444 | register EMACS_INT size = ptr->size; | ||
| 5445 | register int i; | ||
| 5446 | |||
| 5447 | if (VECTOR_MARKED_P (ptr)) | ||
| 5448 | return 0; /* Already marked */ | ||
| 5449 | VECTOR_MARK (ptr); /* Else mark it */ | ||
| 5450 | if (size & PSEUDOVECTOR_FLAG) | ||
| 5451 | size &= PSEUDOVECTOR_SIZE_MASK; | ||
| 5452 | |||
| 5453 | /* Note that this size is not the memory-footprint size, but only | ||
| 5454 | the number of Lisp_Object fields that we should trace. | ||
| 5455 | The distinction is used e.g. by Lisp_Process which places extra | ||
| 5456 | non-Lisp_Object fields at the end of the structure. */ | ||
| 5457 | for (i = 0; i < size; i++) /* and then mark its elements */ | ||
| 5458 | mark_object (ptr->contents[i]); | ||
| 5459 | return 1; | ||
| 5460 | } | ||
| 5461 | |||
| 5445 | void | 5462 | void |
| 5446 | mark_object (arg) | 5463 | mark_object (arg) |
| 5447 | Lisp_Object arg; | 5464 | Lisp_Object arg; |
| @@ -5571,74 +5588,28 @@ mark_object (arg) | |||
| 5571 | else if (GC_FRAMEP (obj)) | 5588 | else if (GC_FRAMEP (obj)) |
| 5572 | { | 5589 | { |
| 5573 | register struct frame *ptr = XFRAME (obj); | 5590 | register struct frame *ptr = XFRAME (obj); |
| 5574 | 5591 | if (mark_vectorlike (XVECTOR (obj))) | |
| 5575 | if (VECTOR_MARKED_P (ptr)) break; /* Already marked */ | 5592 | { |
| 5576 | VECTOR_MARK (ptr); /* Else mark it */ | ||
| 5577 | |||
| 5578 | CHECK_LIVE (live_vector_p); | ||
| 5579 | mark_object (ptr->name); | ||
| 5580 | mark_object (ptr->icon_name); | ||
| 5581 | mark_object (ptr->title); | ||
| 5582 | mark_object (ptr->focus_frame); | ||
| 5583 | mark_object (ptr->selected_window); | ||
| 5584 | mark_object (ptr->minibuffer_window); | ||
| 5585 | mark_object (ptr->param_alist); | ||
| 5586 | mark_object (ptr->scroll_bars); | ||
| 5587 | mark_object (ptr->condemned_scroll_bars); | ||
| 5588 | mark_object (ptr->menu_bar_items); | ||
| 5589 | mark_object (ptr->face_alist); | ||
| 5590 | mark_object (ptr->menu_bar_vector); | ||
| 5591 | mark_object (ptr->buffer_predicate); | ||
| 5592 | mark_object (ptr->buffer_list); | ||
| 5593 | mark_object (ptr->buried_buffer_list); | ||
| 5594 | mark_object (ptr->menu_bar_window); | ||
| 5595 | mark_object (ptr->tool_bar_window); | ||
| 5596 | mark_face_cache (ptr->face_cache); | 5593 | mark_face_cache (ptr->face_cache); |
| 5597 | #ifdef HAVE_WINDOW_SYSTEM | 5594 | #ifdef HAVE_WINDOW_SYSTEM |
| 5598 | mark_image_cache (ptr); | 5595 | mark_image_cache (ptr); |
| 5599 | mark_object (ptr->tool_bar_items); | ||
| 5600 | mark_object (ptr->desired_tool_bar_string); | ||
| 5601 | mark_object (ptr->current_tool_bar_string); | ||
| 5602 | #endif /* HAVE_WINDOW_SYSTEM */ | 5596 | #endif /* HAVE_WINDOW_SYSTEM */ |
| 5603 | } | 5597 | } |
| 5604 | else if (GC_BOOL_VECTOR_P (obj)) | ||
| 5605 | { | ||
| 5606 | register struct Lisp_Vector *ptr = XVECTOR (obj); | ||
| 5607 | |||
| 5608 | if (VECTOR_MARKED_P (ptr)) | ||
| 5609 | break; /* Already marked */ | ||
| 5610 | CHECK_LIVE (live_vector_p); | ||
| 5611 | VECTOR_MARK (ptr); /* Else mark it */ | ||
| 5612 | } | 5598 | } |
| 5613 | else if (GC_WINDOWP (obj)) | 5599 | else if (GC_WINDOWP (obj)) |
| 5614 | { | 5600 | { |
| 5615 | register struct Lisp_Vector *ptr = XVECTOR (obj); | 5601 | register struct Lisp_Vector *ptr = XVECTOR (obj); |
| 5616 | struct window *w = XWINDOW (obj); | 5602 | struct window *w = XWINDOW (obj); |
| 5617 | register int i; | 5603 | if (mark_vectorlike (ptr)) |
| 5618 | 5604 | { | |
| 5619 | /* Stop if already marked. */ | ||
| 5620 | if (VECTOR_MARKED_P (ptr)) | ||
| 5621 | break; | ||
| 5622 | |||
| 5623 | /* Mark it. */ | ||
| 5624 | CHECK_LIVE (live_vector_p); | ||
| 5625 | VECTOR_MARK (ptr); | ||
| 5626 | |||
| 5627 | /* There is no Lisp data above The member CURRENT_MATRIX in | ||
| 5628 | struct WINDOW. Stop marking when that slot is reached. */ | ||
| 5629 | for (i = 0; | ||
| 5630 | (char *) &ptr->contents[i] < (char *) &w->current_matrix; | ||
| 5631 | i++) | ||
| 5632 | mark_object (ptr->contents[i]); | ||
| 5633 | |||
| 5634 | /* Mark glyphs for leaf windows. Marking window matrices is | 5605 | /* Mark glyphs for leaf windows. Marking window matrices is |
| 5635 | sufficient because frame matrices use the same glyph | 5606 | sufficient because frame matrices use the same glyph |
| 5636 | memory. */ | 5607 | memory. */ |
| 5637 | if (NILP (w->hchild) | 5608 | if (NILP (w->hchild) |
| 5638 | && NILP (w->vchild) | 5609 | && NILP (w->vchild) |
| 5639 | && w->current_matrix) | 5610 | && w->current_matrix) |
| 5640 | { | 5611 | { |
| 5641 | mark_glyph_matrix (w->current_matrix); | 5612 | mark_glyph_matrix (w->current_matrix); |
| 5642 | mark_glyph_matrix (w->desired_matrix); | 5613 | mark_glyph_matrix (w->desired_matrix); |
| 5643 | } | 5614 | } |
| 5644 | } | 5615 | } |
| @@ -5672,29 +5643,13 @@ mark_object (arg) | |||
| 5672 | /* If hash table is not weak, mark all keys and values. | 5643 | /* If hash table is not weak, mark all keys and values. |
| 5673 | For weak tables, mark only the vector. */ | 5644 | For weak tables, mark only the vector. */ |
| 5674 | if (GC_NILP (h->weak)) | 5645 | if (GC_NILP (h->weak)) |
| 5675 | mark_object (h->key_and_value); | 5646 | mark_object (h->key_and_value); |
| 5676 | else | 5647 | else |
| 5677 | VECTOR_MARK (XVECTOR (h->key_and_value)); | 5648 | VECTOR_MARK (XVECTOR (h->key_and_value)); |
| 5649 | } | ||
| 5678 | } | 5650 | } |
| 5679 | else | 5651 | else |
| 5680 | { | 5652 | mark_vectorlike (XVECTOR (obj)); |
| 5681 | register struct Lisp_Vector *ptr = XVECTOR (obj); | ||
| 5682 | register EMACS_INT size = ptr->size; | ||
| 5683 | register int i; | ||
| 5684 | |||
| 5685 | if (VECTOR_MARKED_P (ptr)) break; /* Already marked */ | ||
| 5686 | CHECK_LIVE (live_vector_p); | ||
| 5687 | VECTOR_MARK (ptr); /* Else mark it */ | ||
| 5688 | if (size & PSEUDOVECTOR_FLAG) | ||
| 5689 | size &= PSEUDOVECTOR_SIZE_MASK; | ||
| 5690 | |||
| 5691 | /* Note that this size is not the memory-footprint size, but only | ||
| 5692 | the number of Lisp_Object fields that we should trace. | ||
| 5693 | The distinction is used e.g. by Lisp_Process which places extra | ||
| 5694 | non-Lisp_Object fields at the end of the structure. */ | ||
| 5695 | for (i = 0; i < size; i++) /* and then mark its elements */ | ||
| 5696 | mark_object (ptr->contents[i]); | ||
| 5697 | } | ||
| 5698 | break; | 5653 | break; |
| 5699 | 5654 | ||
| 5700 | case Lisp_Symbol: | 5655 | case Lisp_Symbol: |
| @@ -5892,12 +5847,10 @@ static void | |||
| 5892 | mark_terminals (void) | 5847 | mark_terminals (void) |
| 5893 | { | 5848 | { |
| 5894 | struct terminal *t; | 5849 | struct terminal *t; |
| 5895 | Lisp_Object tmp; | ||
| 5896 | for (t = terminal_list; t; t = t->next_terminal) | 5850 | for (t = terminal_list; t; t = t->next_terminal) |
| 5897 | { | 5851 | { |
| 5898 | eassert (t->name != NULL); | 5852 | eassert (t->name != NULL); |
| 5899 | XSETVECTOR (tmp, t); | 5853 | mark_vectorlike ((struct Lisp_Vector *)tmp); |
| 5900 | mark_object (tmp); | ||
| 5901 | } | 5854 | } |
| 5902 | } | 5855 | } |
| 5903 | 5856 | ||