Mercurial > hg > xemacs-beta
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 |