comparison src/alloc.c @ 1292:f3437b56874d

[xemacs-hg @ 2003-02-13 09:57:04 by ben] profile updates profile.c: Major reworking. Keep track of new information -- total function timing (includes descendants), GC usage, total GC usage (includes descendants). New functions to be called appropriately from eval.c, alloc.c to keep track of this information. Keep track of when we're actually in a function vs. in its profile, for more accurate timing counts. Track profile overhead separately. Create new mechanism for specifying "internal sections" that are tracked just like regular Lisp functions and even appear in the backtrace if `backtrace-with-internal-sections' is non-nil (t by default for error-checking builds). Add some KKCC information for the straight (non-Elisp) hash table used by profile, which contains Lisp objects in its keys -- but not used yet. Remove old ad-hoc methods for tracking garbage collection, redisplay (which was incorrect anyway when Lisp was called within these sections). Don't record any tick info when blocking under MS Windows, since the timer there is in real time rather than in process time. Make `start-profiling', `stop-profiling' interactive. Be consistent wrt. recursive functions and functions currently on the stack when starting or stopping -- together these make implementing the `total' values extremely difficult. When we start profiling, we act as if we just entered all the functions currently on the stack. Likewise when exiting. Create vars in_profile for tracking time spent inside of profiling, and profiling_lock for setting exclusive access to the main hash table when reading from it or modifying it. (protects against getting screwed up by the signal handle going off at the same time. profile.h: New file. Create macros for declaring internal profiling sections. lisp.h: Move profile-related stuff to profile.h. alloc.c: Keep track of total consing, for profile. Tell profile when we are consing. Use new profile-section method for noting garbage-collection. alloc.c: Abort if we attempt to call the allocator reentrantly. backtrace.h, eval.c: Add info for use by profile in the backtrace frame and transfer PUSH_BACKTRACE/POP_BACKTRACE from eval.c, for use with profile. elhash.c: Author comment. eval.c, lisp.h: New Lisp var `backtrace-with-internal-sections'. Set to t when error-checking is on. eval.c: When unwinding, eval.c: Report to profile when we are about-to-call and just-called wrt. a function. alloc.c, eval.c: Allow for "fake" backtrace frames, for internal sections (used by profile and `backtrace-with-internal-sections'. event-Xt.c, event-gtk.c, event-msw.c, event-tty.c: Record when we are actually blocking on an event, for profile's sake. event-stream.c: Record internal profiling sections for getting, dispatching events. extents.c: Record internal profiling sections for map_extents. hash.c, hash.h: Add pregrow_hash_table_if_necessary(). (Used in profile code since the signal handler is the main grower but can't allow a realloc(). We make sure, at critical points, that the table is large enough.) lread.c: Create internal profiling sections for `load' (which may be triggered internally by autoload, etc.). redisplay.c: Remove old profile_redisplay_flag. Use new macros to declare internal profiling section for redisplay. text.c: Use new macros to declare internal profiling sections for char-byte conversion and internal-external conversion. SEMI-UNRELATED CHANGES: ----------------------- text.c: Update the long comments.
author ben
date Thu, 13 Feb 2003 09:57:08 +0000
parents beb703ae34fd
children 70921960b980
comparison
equal deleted inserted replaced
1291:3d99b5e6c6ec 1292:f3437b56874d
54 #include "frame-impl.h" 54 #include "frame-impl.h"
55 #include "glyphs.h" 55 #include "glyphs.h"
56 #include "opaque.h" 56 #include "opaque.h"
57 #include "lstream.h" 57 #include "lstream.h"
58 #include "process.h" 58 #include "process.h"
59 #include "profile.h"
59 #include "redisplay.h" 60 #include "redisplay.h"
60 #include "specifier.h" 61 #include "specifier.h"
61 #include "sysfile.h" 62 #include "sysfile.h"
62 #include "sysdep.h" 63 #include "sysdep.h"
63 #include "window.h" 64 #include "window.h"
90 static Fixnum debug_allocation_backtrace_length; 91 static Fixnum debug_allocation_backtrace_length;
91 #endif 92 #endif
92 93
93 /* Number of bytes of consing done since the last gc */ 94 /* Number of bytes of consing done since the last gc */
94 static EMACS_INT consing_since_gc; 95 static EMACS_INT consing_since_gc;
96 EMACS_UINT total_consing;
97
95 int need_to_garbage_collect; 98 int need_to_garbage_collect;
96 int need_to_check_c_alloca; 99 int need_to_check_c_alloca;
97 int need_to_signal_post_gc; 100 int need_to_signal_post_gc;
98 int funcall_allocation_flag; 101 int funcall_allocation_flag;
99 Bytecount __temp_alloca_size__; 102 Bytecount __temp_alloca_size__;
103 Ffuncall() faster */ 106 Ffuncall() faster */
104 #define INCREMENT_CONS_COUNTER_1(size) \ 107 #define INCREMENT_CONS_COUNTER_1(size) \
105 do \ 108 do \
106 { \ 109 { \
107 consing_since_gc += (size); \ 110 consing_since_gc += (size); \
111 total_consing += (size); \
112 if (profiling_active) \
113 profile_record_consing (size); \
108 recompute_need_to_garbage_collect (); \ 114 recompute_need_to_garbage_collect (); \
109 } while (0) 115 } while (0)
110 116
111 #define debug_allocation_backtrace() \ 117 #define debug_allocation_backtrace() \
112 do { \ 118 do { \
141 INCREMENT_CONS_COUNTER_1 (size) 147 INCREMENT_CONS_COUNTER_1 (size)
142 #endif 148 #endif
143 149
144 #define DECREMENT_CONS_COUNTER(size) do { \ 150 #define DECREMENT_CONS_COUNTER(size) do { \
145 consing_since_gc -= (size); \ 151 consing_since_gc -= (size); \
152 total_consing -= (size); \
153 if (profiling_active) \
154 profile_record_unconsing (size); \
146 if (consing_since_gc < 0) \ 155 if (consing_since_gc < 0) \
147 consing_since_gc = 0; \ 156 consing_since_gc = 0; \
148 recompute_need_to_garbage_collect (); \ 157 recompute_need_to_garbage_collect (); \
149 } while (0) 158 } while (0)
150 159
187 /* "Garbage collecting" */ 196 /* "Garbage collecting" */
188 Lisp_Object Vgc_message; 197 Lisp_Object Vgc_message;
189 Lisp_Object Vgc_pointer_glyph; 198 Lisp_Object Vgc_pointer_glyph;
190 static const Char_ASCII gc_default_message[] = "Garbage collecting"; 199 static const Char_ASCII gc_default_message[] = "Garbage collecting";
191 Lisp_Object Qgarbage_collecting; 200 Lisp_Object Qgarbage_collecting;
201
202 static Lisp_Object QSin_garbage_collection;
192 203
193 /* Non-zero means we're in the process of doing the dump */ 204 /* Non-zero means we're in the process of doing the dump */
194 int purify_flag; 205 int purify_flag;
195 206
196 /* Non-zero means we're pdumping out or in */ 207 /* Non-zero means we're pdumping out or in */
300 minimum_address_seen = (char *) val; 311 minimum_address_seen = (char *) val;
301 } 312 }
302 313
303 /* like malloc and realloc but check for no memory left. */ 314 /* like malloc and realloc but check for no memory left. */
304 315
316 static int in_malloc;
317
305 #undef xmalloc 318 #undef xmalloc
306 void * 319 void *
307 xmalloc (Bytecount size) 320 xmalloc (Bytecount size)
308 { 321 {
309 void *val = malloc (size); 322 void *val;
323 #ifdef ERROR_CHECK_MALLOC
324 assert (!in_malloc);
325 in_malloc = 1;
326 #endif
327 val = malloc (size);
328 #ifdef ERROR_CHECK_MALLOC
329 in_malloc = 0;
330 #endif
310 if (!val && (size != 0)) memory_full (); 331 if (!val && (size != 0)) memory_full ();
311 set_alloc_mins_and_maxes (val, size); 332 set_alloc_mins_and_maxes (val, size);
312 return val; 333 return val;
313 } 334 }
314 335
315 #undef xcalloc 336 #undef xcalloc
316 static void * 337 static void *
317 xcalloc (Elemcount nelem, Bytecount elsize) 338 xcalloc (Elemcount nelem, Bytecount elsize)
318 { 339 {
319 void *val = calloc (nelem, elsize); 340 void *val;
341 #ifdef ERROR_CHECK_MALLOC
342 assert (!in_malloc);
343 in_malloc = 1;
344 #endif
345 val= calloc (nelem, elsize);
346 #ifdef ERROR_CHECK_MALLOC
347 in_malloc = 0;
348 #endif
320 349
321 if (!val && (nelem != 0)) memory_full (); 350 if (!val && (nelem != 0)) memory_full ();
322 set_alloc_mins_and_maxes (val, nelem * elsize); 351 set_alloc_mins_and_maxes (val, nelem * elsize);
323 return val; 352 return val;
324 } 353 }
331 360
332 #undef xrealloc 361 #undef xrealloc
333 void * 362 void *
334 xrealloc (void *block, Bytecount size) 363 xrealloc (void *block, Bytecount size)
335 { 364 {
365 #ifdef ERROR_CHECK_MALLOC
366 assert (!in_malloc);
367 in_malloc = 1;
368 #endif
336 block = realloc (block, size); 369 block = realloc (block, size);
370 #ifdef ERROR_CHECK_MALLOC
371 in_malloc = 0;
372 #endif
337 373
338 if (!block && (size != 0)) memory_full (); 374 if (!block && (size != 0)) memory_full ();
339 set_alloc_mins_and_maxes (block, size); 375 set_alloc_mins_and_maxes (block, size);
340 return block; 376 return block;
341 } 377 }
351 /* Unbelievably, calling free() on 0xDEADBEEF doesn't cause an 387 /* Unbelievably, calling free() on 0xDEADBEEF doesn't cause an
352 error until much later on for many system mallocs, such as 388 error until much later on for many system mallocs, such as
353 the one that comes with Solaris 2.3. FMH!! */ 389 the one that comes with Solaris 2.3. FMH!! */
354 assert (block != (void *) 0xDEADBEEF); 390 assert (block != (void *) 0xDEADBEEF);
355 assert (block); 391 assert (block);
392 assert (!in_malloc);
393 in_malloc = 1;
356 #endif /* ERROR_CHECK_MALLOC */ 394 #endif /* ERROR_CHECK_MALLOC */
357 free (block); 395 free (block);
396 #ifdef ERROR_CHECK_MALLOC
397 in_malloc = 0;
398 #endif
358 } 399 }
359 400
360 #ifdef ERROR_CHECK_GC 401 #ifdef ERROR_CHECK_GC
361 402
362 static void 403 static void
4361 struct frame *f; 4402 struct frame *f;
4362 int speccount; 4403 int speccount;
4363 int cursor_changed; 4404 int cursor_changed;
4364 Lisp_Object pre_gc_cursor; 4405 Lisp_Object pre_gc_cursor;
4365 struct gcpro gcpro1; 4406 struct gcpro gcpro1;
4407 PROFILE_DECLARE ();
4366 4408
4367 assert (!in_display || gc_currently_forbidden); 4409 assert (!in_display || gc_currently_forbidden);
4368 4410
4369 if (gc_in_progress 4411 if (gc_in_progress
4370 || gc_currently_forbidden 4412 || gc_currently_forbidden
4371 || in_display 4413 || in_display
4372 || preparing_for_armageddon) 4414 || preparing_for_armageddon)
4373 return; 4415 return;
4416
4417 PROFILE_RECORD_ENTERING_SECTION (QSin_garbage_collection);
4374 4418
4375 /* We used to call selected_frame() here. 4419 /* We used to call selected_frame() here.
4376 4420
4377 The following functions cannot be called inside GC 4421 The following functions cannot be called inside GC
4378 so we move to after the above tests. */ 4422 so we move to after the above tests. */
4528 { 4572 {
4529 int nargs = backlist->nargs; 4573 int nargs = backlist->nargs;
4530 int i; 4574 int i;
4531 4575
4532 mark_object (*backlist->function); 4576 mark_object (*backlist->function);
4533 if (nargs < 0 /* nargs == UNEVALLED || nargs == MANY */) 4577 if (nargs < 0 /* nargs == UNEVALLED || nargs == MANY */
4578 /* might be fake (internal profiling entry) */
4579 && backlist->args)
4534 mark_object (backlist->args[0]); 4580 mark_object (backlist->args[0]);
4535 else 4581 else
4536 for (i = 0; i < nargs; i++) 4582 for (i = 0; i < nargs; i++)
4537 mark_object (backlist->args[i]); 4583 mark_object (backlist->args[i]);
4538 } 4584 }
4618 UNGCPRO; 4664 UNGCPRO;
4619 4665
4620 need_to_signal_post_gc = 1; 4666 need_to_signal_post_gc = 1;
4621 funcall_allocation_flag = 1; 4667 funcall_allocation_flag = 1;
4622 4668
4669 PROFILE_RECORD_EXITING_SECTION (QSin_garbage_collection);
4670
4623 return; 4671 return;
4624 } 4672 }
4625 4673
4626 /* Debugging aids. */ 4674 /* Debugging aids. */
4627 4675
5146 } 5194 }
5147 5195
5148 void 5196 void
5149 vars_of_alloc (void) 5197 vars_of_alloc (void)
5150 { 5198 {
5199 QSin_garbage_collection = build_msg_string ("(in garbage collection)");
5200 staticpro (&QSin_garbage_collection);
5201
5151 DEFVAR_INT ("gc-cons-threshold", &gc_cons_threshold /* 5202 DEFVAR_INT ("gc-cons-threshold", &gc_cons_threshold /*
5152 *Number of bytes of consing between garbage collections. 5203 *Number of bytes of consing between garbage collections.
5153 \"Consing\" is a misnomer in that this actually counts allocation 5204 \"Consing\" is a misnomer in that this actually counts allocation
5154 of all different kinds of objects, not just conses. 5205 of all different kinds of objects, not just conses.
5155 Garbage collection can happen automatically once this many bytes have been 5206 Garbage collection can happen automatically once this many bytes have been