Mercurial > emacs
comparison src/alloc.c @ 85019:21a145f18ed2
(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.
| author | Stefan Monnier <monnier@iro.umontreal.ca> |
|---|---|
| date | Tue, 02 Oct 2007 21:16:53 +0000 |
| parents | 33b7fe948502 |
| children | db98fea45dfd |
comparison
equal
deleted
inserted
replaced
| 85018:3389713480bb | 85019:21a145f18ed2 |
|---|---|
| 2336 / BOOL_VECTOR_BITS_PER_CHAR); | 2336 / BOOL_VECTOR_BITS_PER_CHAR); |
| 2337 | 2337 |
| 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 | |
| 2342 /* Get rid of any bits that would cause confusion. */ | |
| 2343 XVECTOR (val)->size = 0; /* No Lisp_Object to trace in there. */ | |
| 2344 XSETPVECTYPE (XVECTOR (val), PVEC_BOOL_VECTOR); | |
| 2345 | |
| 2341 p = XBOOL_VECTOR (val); | 2346 p = XBOOL_VECTOR (val); |
| 2342 | |
| 2343 /* Get rid of any bits that would cause confusion. */ | |
| 2344 p->vector_size = 0; | |
| 2345 XSETBOOL_VECTOR (val, p); | |
| 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); |
| 2349 for (i = 0; i < length_in_chars ; i++) | 2350 for (i = 0; i < length_in_chars ; i++) |
| 2350 p->data[i] = real_init; | 2351 p->data[i] = real_init; |
| 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; |
| 2358 } | 2359 } |
| 2359 | 2360 |
| 2961 } | 2962 } |
| 2962 | 2963 |
| 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 { |
| 2969 EMACS_INT len = VECSIZE (struct Lisp_Hash_Table); | 2991 EMACS_INT len = VECSIZE (struct Lisp_Hash_Table); |
| 2970 struct Lisp_Vector *v = allocate_vectorlike (len); | 2992 struct Lisp_Vector *v = allocate_vectorlike (len); |
| 2974 for (i = 0; i < len; ++i) | 2996 for (i = 0; i < len; ++i) |
| 2975 v->contents[i] = Qnil; | 2997 v->contents[i] = Qnil; |
| 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); | 3018 |
| 3005 EMACS_INT i; | 3019 return t; |
| 3006 Lisp_Object tmp, zero = make_number (0); | |
| 3007 | |
| 3008 for (i = 0; i < lisplen; ++i) | |
| 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); | 3038 } |
| 3037 /* Size if we only count the actual Lisp_Object fields (which need to be | 3039 |
| 3038 traced by the GC). */ | 3040 |
| 3039 EMACS_INT lisplen = PSEUDOVECSIZE (struct Lisp_Process, pid); | 3041 /* Only used for PVEC_WINDOW_CONFIGURATION. */ |
| 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 } | |
| 3049 | |
| 3050 | |
| 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; |
| 3054 { | 3045 { |
| 3055 struct Lisp_Vector *v = allocate_vectorlike (len); | 3046 struct Lisp_Vector *v = allocate_vectorlike (len); |
| 3102 if (XINT (n) < 0 || XINT (n) > 10) | 3093 if (XINT (n) < 0 || XINT (n) > 10) |
| 3103 args_out_of_range (n, Qnil); | 3094 args_out_of_range (n, Qnil); |
| 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; |
| 3110 XSETCHAR_TABLE (vector, XCHAR_TABLE (vector)); | 3102 XSETCHAR_TABLE (vector, XCHAR_TABLE (vector)); |
| 3111 return vector; | 3103 return vector; |
| 3120 make_sub_char_table (init) | 3112 make_sub_char_table (init) |
| 3121 Lisp_Object init; | 3113 Lisp_Object 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)); |
| 3128 return vector; | 3121 return vector; |
| 3129 } | 3122 } |
| 3184 { | 3177 { |
| 3185 if (!NILP (Vpurify_flag)) | 3178 if (!NILP (Vpurify_flag)) |
| 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 } |
| 3192 | 3186 |
| 3193 | 3187 |
| 5440 links of a list, in mark_object. In debugging, | 5434 links of a list, in mark_object. In debugging, |
| 5441 the call to abort will hit a breakpoint. | 5435 the call to abort will hit a breakpoint. |
| 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; |
| 5448 { | 5465 { |
| 5449 register Lisp_Object obj = arg; | 5466 register Lisp_Object obj = arg; |
| 5569 goto loop; | 5586 goto loop; |
| 5570 } | 5587 } |
| 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 } |
| 5645 else if (GC_HASH_TABLE_P (obj)) | 5616 else if (GC_HASH_TABLE_P (obj)) |
| 5646 { | 5617 { |
| 5670 mark_object (h->user_cmp_function); | 5641 mark_object (h->user_cmp_function); |
| 5671 | 5642 |
| 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: |
| 5701 { | 5656 { |
| 5702 register struct Lisp_Symbol *ptr = XSYMBOL (obj); | 5657 register struct Lisp_Symbol *ptr = XSYMBOL (obj); |
| 5890 | 5845 |
| 5891 static void | 5846 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 |
| 5904 | 5857 |
| 5905 | 5858 |
