comparison src/eval.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 465bd3c7d932
children 671b65f2b075
comparison
equal deleted inserted replaced
1291:3d99b5e6c6ec 1292:f3437b56874d
1 /* Evaluator for XEmacs Lisp interpreter. 1 /* Evaluator for XEmacs Lisp interpreter.
2 Copyright (C) 1985-1987, 1992-1994 Free Software Foundation, Inc. 2 Copyright (C) 1985-1987, 1992-1994 Free Software Foundation, Inc.
3 Copyright (C) 1995 Sun Microsystems, Inc. 3 Copyright (C) 1995 Sun Microsystems, Inc.
4 Copyright (C) 2000, 2001, 2002 Ben Wing. 4 Copyright (C) 2000, 2001, 2002, 2003 Ben Wing.
5 5
6 This file is part of XEmacs. 6 This file is part of XEmacs.
7 7
8 XEmacs is free software; you can redistribute it and/or modify it 8 XEmacs is free software; you can redistribute it and/or modify it
9 under the terms of the GNU General Public License as published by the 9 under the terms of the GNU General Public License as published by the
145 #include "console-impl.h" 145 #include "console-impl.h"
146 #include "device.h" 146 #include "device.h"
147 #include "frame.h" 147 #include "frame.h"
148 #include "lstream.h" 148 #include "lstream.h"
149 #include "opaque.h" 149 #include "opaque.h"
150 #include "profile.h"
150 #include "window.h" 151 #include "window.h"
151 152
152 struct backtrace *backtrace_list; 153 struct backtrace *backtrace_list;
153
154 /* Note: you must always fill in all of the fields in a backtrace structure
155 before pushing them on the backtrace_list. The profiling code depends
156 on this. */
157
158 #define PUSH_BACKTRACE(bt) do { \
159 (bt).next = backtrace_list; \
160 backtrace_list = &(bt); \
161 } while (0)
162
163 #define POP_BACKTRACE(bt) do { \
164 backtrace_list = (bt).next; \
165 } while (0)
166 154
167 /* Macros for calling subrs with an argument list whose length is only 155 /* Macros for calling subrs with an argument list whose length is only
168 known at runtime. See EXFUN and DEFUN for similar hackery. */ 156 known at runtime. See EXFUN and DEFUN for similar hackery. */
169 157
170 #define AV_0(av) 158 #define AV_0(av)
290 278
291 /* Maximum size allowed for specpdl allocation */ 279 /* Maximum size allowed for specpdl allocation */
292 Fixnum max_specpdl_size; 280 Fixnum max_specpdl_size;
293 281
294 /* Depth in Lisp evaluations and function calls. */ 282 /* Depth in Lisp evaluations and function calls. */
295 static int lisp_eval_depth; 283 int lisp_eval_depth;
296 284
297 /* Maximum allowed depth in Lisp evaluations and function calls. */ 285 /* Maximum allowed depth in Lisp evaluations and function calls. */
298 Fixnum max_lisp_eval_depth; 286 Fixnum max_lisp_eval_depth;
299 287
300 /* Nonzero means enter debugger before next function call */ 288 /* Nonzero means enter debugger before next function call */
301 static int debug_on_next_call; 289 static int debug_on_next_call;
290
291 int backtrace_with_internal_sections;
302 292
303 /* List of conditions (non-nil atom means all) which cause a backtrace 293 /* List of conditions (non-nil atom means all) which cause a backtrace
304 if an error is handled by the command loop's error handler. */ 294 if an error is handled by the command loop's error handler. */
305 Lisp_Object Vstack_trace_on_error; 295 Lisp_Object Vstack_trace_on_error;
306 296
1593 catchlist = c->next; 1583 catchlist = c->next;
1594 check_catchlist_sanity (); 1584 check_catchlist_sanity ();
1595 #endif /* Former code */ 1585 #endif /* Former code */
1596 1586
1597 UNWIND_GCPRO_TO (c->gcpro); 1587 UNWIND_GCPRO_TO (c->gcpro);
1598 backtrace_list = c->backlist; 1588 if (profiling_active)
1589 {
1590 while (backtrace_list != c->backlist)
1591 {
1592 profile_record_unwind (backtrace_list);
1593 backtrace_list = backtrace_list->next;
1594 }
1595 }
1596 else
1597 backtrace_list = c->backlist;
1599 lisp_eval_depth = c->lisp_eval_depth; 1598 lisp_eval_depth = c->lisp_eval_depth;
1600 1599
1601 #ifdef DEFEND_AGAINST_THROW_RECURSION 1600 #ifdef DEFEND_AGAINST_THROW_RECURSION
1602 throw_level = 0; 1601 throw_level = 0;
1603 #endif 1602 #endif
1704 return unbind_to_1 (speccount, Feval (XCAR (args))); 1703 return unbind_to_1 (speccount, Feval (XCAR (args)));
1705 } 1704 }
1706 1705
1707 1706
1708 /************************************************************************/ 1707 /************************************************************************/
1709 /* Signalling and trapping errors */ 1708 /* Trapping errors */
1710 /************************************************************************/ 1709 /************************************************************************/
1711 1710
1712 static Lisp_Object 1711 static Lisp_Object
1713 condition_bind_unwind (Lisp_Object loser) 1712 condition_bind_unwind (Lisp_Object loser)
1714 { 1713 {
3090 { 3089 {
3091 backtrace.function = &Qcall_interactively; 3090 backtrace.function = &Qcall_interactively;
3092 backtrace.args = &cmd; 3091 backtrace.args = &cmd;
3093 backtrace.nargs = 1; 3092 backtrace.nargs = 1;
3094 backtrace.evalargs = 0; 3093 backtrace.evalargs = 0;
3095 backtrace.pdlcount = specpdl_depth(); 3094 backtrace.pdlcount = specpdl_depth ();
3096 backtrace.debug_on_exit = 0; 3095 backtrace.debug_on_exit = 0;
3096 backtrace.function_being_called = 0;
3097 PUSH_BACKTRACE (backtrace); 3097 PUSH_BACKTRACE (backtrace);
3098 3098
3099 PROFILE_ENTER_FUNCTION ();
3099 final = Fcall_interactively (cmd, record_flag, keys); 3100 final = Fcall_interactively (cmd, record_flag, keys);
3101 PROFILE_EXIT_FUNCTION ();
3100 3102
3101 POP_BACKTRACE (backtrace); 3103 POP_BACKTRACE (backtrace);
3102 return final; 3104 return final;
3103 } 3105 }
3104 else if (STRINGP (final) || VECTORP (final)) 3106 else if (STRINGP (final) || VECTORP (final))
3533 backtrace.function = &original_fun; /* This also protects them from gc */ 3535 backtrace.function = &original_fun; /* This also protects them from gc */
3534 backtrace.args = &original_args; 3536 backtrace.args = &original_args;
3535 backtrace.nargs = UNEVALLED; 3537 backtrace.nargs = UNEVALLED;
3536 backtrace.evalargs = 1; 3538 backtrace.evalargs = 1;
3537 backtrace.debug_on_exit = 0; 3539 backtrace.debug_on_exit = 0;
3540 backtrace.function_being_called = 0;
3538 PUSH_BACKTRACE (backtrace); 3541 PUSH_BACKTRACE (backtrace);
3539 3542
3540 if (debug_on_next_call) 3543 if (debug_on_next_call)
3541 do_debug_on_call (Qt); 3544 do_debug_on_call (Qt);
3542
3543 if (profiling_active)
3544 profile_increase_call_count (original_fun);
3545 3545
3546 /* At this point, only original_fun and original_args 3546 /* At this point, only original_fun and original_args
3547 have values that will be used below. */ 3547 have values that will be used below. */
3548 retry: 3548 retry:
3549 fun = indirect_function (original_fun, 1); 3549 fun = indirect_function (original_fun, 1);
3557 goto wrong_number_of_arguments; 3557 goto wrong_number_of_arguments;
3558 3558
3559 if (max_args == UNEVALLED) /* Optimize for the common case */ 3559 if (max_args == UNEVALLED) /* Optimize for the common case */
3560 { 3560 {
3561 backtrace.evalargs = 0; 3561 backtrace.evalargs = 0;
3562 PROFILE_ENTER_FUNCTION ();
3562 val = (((Lisp_Object (*) (Lisp_Object)) subr_function (subr)) 3563 val = (((Lisp_Object (*) (Lisp_Object)) subr_function (subr))
3563 (original_args)); 3564 (original_args));
3565 PROFILE_EXIT_FUNCTION ();
3564 } 3566 }
3565 else if (nargs <= max_args) 3567 else if (nargs <= max_args)
3566 { 3568 {
3567 struct gcpro gcpro1; 3569 struct gcpro gcpro1;
3568 Lisp_Object args[SUBR_MAX_ARGS]; 3570 Lisp_Object args[SUBR_MAX_ARGS];
3584 *p++ = Qnil; 3586 *p++ = Qnil;
3585 3587
3586 backtrace.args = args; 3588 backtrace.args = args;
3587 backtrace.nargs = nargs; 3589 backtrace.nargs = nargs;
3588 3590
3591 PROFILE_ENTER_FUNCTION ();
3589 FUNCALL_SUBR (val, subr, args, max_args); 3592 FUNCALL_SUBR (val, subr, args, max_args);
3593 PROFILE_EXIT_FUNCTION ();
3590 3594
3591 UNGCPRO; 3595 UNGCPRO;
3592 } 3596 }
3593 else if (max_args == MANY) 3597 else if (max_args == MANY)
3594 { 3598 {
3609 } 3613 }
3610 3614
3611 backtrace.args = args; 3615 backtrace.args = args;
3612 backtrace.nargs = nargs; 3616 backtrace.nargs = nargs;
3613 3617
3618 PROFILE_ENTER_FUNCTION ();
3614 val = (((Lisp_Object (*) (int, Lisp_Object *)) subr_function (subr)) 3619 val = (((Lisp_Object (*) (int, Lisp_Object *)) subr_function (subr))
3615 (nargs, args)); 3620 (nargs, args));
3621 PROFILE_EXIT_FUNCTION ();
3616 3622
3617 UNGCPRO; 3623 UNGCPRO;
3618 } 3624 }
3619 else 3625 else
3620 { 3626 {
3641 3647
3642 backtrace.args = args; 3648 backtrace.args = args;
3643 backtrace.nargs = nargs; 3649 backtrace.nargs = nargs;
3644 backtrace.evalargs = 0; 3650 backtrace.evalargs = 0;
3645 3651
3652 PROFILE_ENTER_FUNCTION ();
3646 val = funcall_compiled_function (fun, nargs, args); 3653 val = funcall_compiled_function (fun, nargs, args);
3654 PROFILE_EXIT_FUNCTION ();
3647 3655
3648 /* Do the debug-on-exit now, while args is still GCPROed. */ 3656 /* Do the debug-on-exit now, while args is still GCPROed. */
3649 if (backtrace.debug_on_exit) 3657 if (backtrace.debug_on_exit)
3650 val = do_debug_on_exit (val); 3658 val = do_debug_on_exit (val);
3651 /* Don't do it again when we return to eval. */ 3659 /* Don't do it again when we return to eval. */
3663 do_autoload (fun, original_fun); 3671 do_autoload (fun, original_fun);
3664 goto retry; 3672 goto retry;
3665 } 3673 }
3666 else if (EQ (funcar, Qmacro)) 3674 else if (EQ (funcar, Qmacro))
3667 { 3675 {
3676 PROFILE_ENTER_FUNCTION ();
3668 val = Feval (apply1 (XCDR (fun), original_args)); 3677 val = Feval (apply1 (XCDR (fun), original_args));
3678 PROFILE_EXIT_FUNCTION ();
3669 } 3679 }
3670 else if (EQ (funcar, Qlambda)) 3680 else if (EQ (funcar, Qlambda))
3671 { 3681 {
3672 struct gcpro gcpro1; 3682 struct gcpro gcpro1;
3673 Lisp_Object *args = alloca_array (Lisp_Object, nargs); 3683 Lisp_Object *args = alloca_array (Lisp_Object, nargs);
3688 3698
3689 backtrace.args = args; /* this also GCPROs `args' */ 3699 backtrace.args = args; /* this also GCPROs `args' */
3690 backtrace.nargs = nargs; 3700 backtrace.nargs = nargs;
3691 backtrace.evalargs = 0; 3701 backtrace.evalargs = 0;
3692 3702
3703 PROFILE_ENTER_FUNCTION ();
3693 val = funcall_lambda (fun, nargs, args); 3704 val = funcall_lambda (fun, nargs, args);
3705 PROFILE_EXIT_FUNCTION ();
3694 3706
3695 /* Do the debug-on-exit now, while args is still GCPROed. */ 3707 /* Do the debug-on-exit now, while args is still GCPROed. */
3696 if (backtrace.debug_on_exit) 3708 if (backtrace.debug_on_exit)
3697 val = do_debug_on_exit (val); 3709 val = do_debug_on_exit (val);
3698 /* Don't do it again when we return to eval. */ 3710 /* Don't do it again when we return to eval. */
3743 Lisp_Object fun; 3755 Lisp_Object fun;
3744 Lisp_Object val; 3756 Lisp_Object val;
3745 struct backtrace backtrace; 3757 struct backtrace backtrace;
3746 int fun_nargs = nargs - 1; 3758 int fun_nargs = nargs - 1;
3747 Lisp_Object *fun_args = args + 1; 3759 Lisp_Object *fun_args = args + 1;
3760 Lisp_Object orig_fun;
3748 3761
3749 QUIT; 3762 QUIT;
3750 3763
3751 if (funcall_allocation_flag) 3764 if (funcall_allocation_flag)
3752 { 3765 {
3779 if (lisp_eval_depth > max_lisp_eval_depth) 3792 if (lisp_eval_depth > max_lisp_eval_depth)
3780 stack_overflow ("Lisp nesting exceeds `max-lisp-eval-depth'", 3793 stack_overflow ("Lisp nesting exceeds `max-lisp-eval-depth'",
3781 Qunbound); 3794 Qunbound);
3782 } 3795 }
3783 3796
3784 backtrace.pdlcount = specpdl_depth(); 3797 backtrace.pdlcount = specpdl_depth ();
3785 backtrace.function = &args[0]; 3798 backtrace.function = &args[0];
3786 backtrace.args = fun_args; 3799 backtrace.args = fun_args;
3787 backtrace.nargs = fun_nargs; 3800 backtrace.nargs = fun_nargs;
3788 backtrace.evalargs = 0; 3801 backtrace.evalargs = 0;
3789 backtrace.debug_on_exit = 0; 3802 backtrace.debug_on_exit = 0;
3803 backtrace.function_being_called = 0;
3790 PUSH_BACKTRACE (backtrace); 3804 PUSH_BACKTRACE (backtrace);
3791 3805
3792 if (debug_on_next_call) 3806 if (debug_on_next_call)
3793 do_debug_on_call (Qlambda); 3807 do_debug_on_call (Qlambda);
3794 3808
3809 orig_fun = args[0];
3810
3795 retry: 3811 retry:
3796 3812
3797 fun = args[0]; 3813 fun = args[0];
3798
3799 /* It might be useful to place this *after* all the checks. */
3800 if (profiling_active)
3801 profile_increase_call_count (fun);
3802 3814
3803 /* We could call indirect_function directly, but profiling shows 3815 /* We could call indirect_function directly, but profiling shows
3804 this is worth optimizing by partially unrolling the loop. */ 3816 this is worth optimizing by partially unrolling the loop. */
3805 if (SYMBOLP (fun)) 3817 if (SYMBOLP (fun))
3806 { 3818 {
3820 Lisp_Object spacious_args[SUBR_MAX_ARGS]; 3832 Lisp_Object spacious_args[SUBR_MAX_ARGS];
3821 3833
3822 if (fun_nargs == max_args) /* Optimize for the common case */ 3834 if (fun_nargs == max_args) /* Optimize for the common case */
3823 { 3835 {
3824 funcall_subr: 3836 funcall_subr:
3837 PROFILE_ENTER_FUNCTION ();
3825 FUNCALL_SUBR (val, subr, fun_args, max_args); 3838 FUNCALL_SUBR (val, subr, fun_args, max_args);
3839 PROFILE_EXIT_FUNCTION ();
3826 } 3840 }
3827 else if (fun_nargs < subr->min_args) 3841 else if (fun_nargs < subr->min_args)
3828 { 3842 {
3829 goto wrong_number_of_arguments; 3843 goto wrong_number_of_arguments;
3830 } 3844 }
3841 fun_args = spacious_args; 3855 fun_args = spacious_args;
3842 goto funcall_subr; 3856 goto funcall_subr;
3843 } 3857 }
3844 else if (max_args == MANY) 3858 else if (max_args == MANY)
3845 { 3859 {
3860 PROFILE_ENTER_FUNCTION ();
3846 val = SUBR_FUNCTION (subr, MANY) (fun_nargs, fun_args); 3861 val = SUBR_FUNCTION (subr, MANY) (fun_nargs, fun_args);
3862 PROFILE_EXIT_FUNCTION ();
3847 } 3863 }
3848 else if (max_args == UNEVALLED) /* Can't funcall a special form */ 3864 else if (max_args == UNEVALLED) /* Can't funcall a special form */
3849 { 3865 {
3850 goto invalid_function; 3866 goto invalid_function;
3851 } 3867 }
3855 val = signal_wrong_number_of_arguments_error (fun, fun_nargs); 3871 val = signal_wrong_number_of_arguments_error (fun, fun_nargs);
3856 } 3872 }
3857 } 3873 }
3858 else if (COMPILED_FUNCTIONP (fun)) 3874 else if (COMPILED_FUNCTIONP (fun))
3859 { 3875 {
3876 PROFILE_ENTER_FUNCTION ();
3860 val = funcall_compiled_function (fun, fun_nargs, fun_args); 3877 val = funcall_compiled_function (fun, fun_nargs, fun_args);
3878 PROFILE_EXIT_FUNCTION ();
3861 } 3879 }
3862 else if (CONSP (fun)) 3880 else if (CONSP (fun))
3863 { 3881 {
3864 Lisp_Object funcar = XCAR (fun); 3882 Lisp_Object funcar = XCAR (fun);
3865 3883
3866 if (EQ (funcar, Qlambda)) 3884 if (EQ (funcar, Qlambda))
3867 { 3885 {
3886 PROFILE_ENTER_FUNCTION ();
3868 val = funcall_lambda (fun, fun_nargs, fun_args); 3887 val = funcall_lambda (fun, fun_nargs, fun_args);
3888 PROFILE_EXIT_FUNCTION ();
3869 } 3889 }
3870 else if (EQ (funcar, Qautoload)) 3890 else if (EQ (funcar, Qautoload))
3871 { 3891 {
3872 /* do_autoload GCPROs both arguments */ 3892 /* do_autoload GCPROs both arguments */
3873 do_autoload (fun, args[0]); 3893 do_autoload (fun, args[0]);
6054 } 6074 }
6055 } 6075 }
6056 if (printing_bindings) write_c_string (stream, ")\n"); 6076 if (printing_bindings) write_c_string (stream, ")\n");
6057 } 6077 }
6058 6078
6079 static Lisp_Object
6080 backtrace_unevalled_args (Lisp_Object *args)
6081 {
6082 if (args)
6083 return *args;
6084 else
6085 return list1 (build_string ("[internal]"));
6086 }
6087
6059 DEFUN ("backtrace", Fbacktrace, 0, 2, "", /* 6088 DEFUN ("backtrace", Fbacktrace, 0, 2, "", /*
6060 Print a trace of Lisp function calls currently active. 6089 Print a trace of Lisp function calls currently active.
6061 Optional arg STREAM specifies the output stream to send the backtrace to, 6090 Optional arg STREAM specifies the output stream to send the backtrace to,
6062 and defaults to the value of `standard-output'. 6091 and defaults to the value of `standard-output'.
6063 Optional second arg DETAILED non-nil means show places where currently 6092 Optional second arg DETAILED non-nil means show places where currently
6133 speccount = backlist->pdlcount; 6162 speccount = backlist->pdlcount;
6134 } 6163 }
6135 write_c_string (stream, backlist->debug_on_exit ? "* " : " "); 6164 write_c_string (stream, backlist->debug_on_exit ? "* " : " ");
6136 if (backlist->nargs == UNEVALLED) 6165 if (backlist->nargs == UNEVALLED)
6137 { 6166 {
6138 Fprin1 (Fcons (*backlist->function, *backlist->args), stream); 6167 Fprin1 (Fcons (*backlist->function,
6168 backtrace_unevalled_args (backlist->args)),
6169 stream);
6139 write_c_string (stream, "\n"); /* from FSFmacs 19.30 */ 6170 write_c_string (stream, "\n"); /* from FSFmacs 19.30 */
6140 } 6171 }
6141 else 6172 else
6142 { 6173 {
6143 Lisp_Object tem = *backlist->function; 6174 Lisp_Object tem = *backlist->function;
6211 backlist = backlist->next; 6242 backlist = backlist->next;
6212 6243
6213 if (!backlist) 6244 if (!backlist)
6214 return Qnil; 6245 return Qnil;
6215 if (backlist->nargs == UNEVALLED) 6246 if (backlist->nargs == UNEVALLED)
6216 return Fcons (Qnil, Fcons (*backlist->function, *backlist->args)); 6247 return Fcons (Qnil, Fcons (*backlist->function,
6248 backtrace_unevalled_args (backlist->args)));
6217 else 6249 else
6218 { 6250 {
6219 if (backlist->nargs == MANY) 6251 if (backlist->nargs == MANY)
6220 tem = *backlist->args; 6252 tem = *backlist->args;
6221 else 6253 else
6512 6544
6513 DEFVAR_BOOL ("debug-on-next-call", &debug_on_next_call /* 6545 DEFVAR_BOOL ("debug-on-next-call", &debug_on_next_call /*
6514 Non-nil means enter debugger before next `eval', `apply' or `funcall'. 6546 Non-nil means enter debugger before next `eval', `apply' or `funcall'.
6515 */ ); 6547 */ );
6516 6548
6549 DEFVAR_BOOL ("backtrace-with-interal-sections",
6550 &backtrace_with_internal_sections /*
6551 Non-nil means backtraces will contain additional information indicating
6552 when particular sections of the C code have been entered, e.g. redisplay(),
6553 byte-char conversion, internal-external conversion, etc. This can be
6554 particularly useful when XEmacs crashes, in helping to pinpoint the problem.
6555 */ );
6556 #ifdef ERROR_CHECK_STRUCTURES
6557 backtrace_with_internal_sections = 1;
6558 #else
6559 backtrace_with_internal_sections = 0;
6560 #endif
6561
6517 DEFVAR_LISP ("debugger", &Vdebugger /* 6562 DEFVAR_LISP ("debugger", &Vdebugger /*
6518 Function to call to invoke debugger. 6563 Function to call to invoke debugger.
6519 If due to frame exit, args are `exit' and the value being returned; 6564 If due to frame exit, args are `exit' and the value being returned;
6520 this function's value will be returned instead of that. 6565 this function's value will be returned instead of that.
6521 If due to error, args are `error' and a list of the args to `signal'. 6566 If due to error, args are `error' and a list of the args to `signal'.